Last time I described how to access the configuration manager from the comfort of kernel space. Today I'll venture out into the uncharted regions of user space and show you how your applications can access this same information. Take my hand and follow my lead.
There's sample code to study; you can find it at
<ftp://ftp.be.com/pub/samples/device_kit/listdev.zip>
. As
with last time, the relevant header file is
<driver/config_manager.h>
.
The /dev/misc/config
device acts as the middleman between
the configuration manager and user code. We've put together
interface code that handles all the messiness for you.
Rather than commit any energy to learning a one-shot
interface, have faith and place your trust in these
routines. Everything you need to know about this glue code
can be divined from <cm_wrapper.h>
.
The bulk of the first article concerned the mechanics of fetching information from the configuration manager. Rather than repeat myself, I'll spend time instead telling you how to make sense of this information.
The resource_descriptor
is the basic unit of configuration
information, describing an IRQ, DMA, I/O port, or memory
used by a device. IRQs and DMAs are described by bitmasks,
while I/O ports and memory are described by ranges. A line
of source is worth a thousand words:
void print_mask(const char *name, resource_descriptor r) { int i; for (i=0;i<32;i++) if (r.d.m.mask == (1 << i)) break; if (i == 32) i = -1; printf("%s: %d\n", name, i); } void print_range(const char *name, resource_descriptor r) { printf("%s: 0x%x - 0x%x\n", name, r.d.r.minbase, r.d.r.minbase + r.d.r.len - 1); } void print_resource_descriptor(resource_descriptor r) { switch (r.type) { case B_IRQ_RESOURCE: print_mask("irq", r); break; case B_DMA_RESOURCE: print_mask("dma", r); break; case B_IO_PORT_RESOURCE: print_range("i/o ports", r); break; case B_MEMORY_RESOURCE: print_range("memory", r); break; default: printf("Unknown resource type (%d)\n", r.type); break; } }
A device_configuration
is an array of resource descriptors
representing the resources assigned to the device. Behold:
void print_device_configuration(struct device_configuration *config) { int i; for (i=0;inum_resources;i++) print_resource_descriptor(config->resources[i]); }
The final structure of interest is
possible_device_configurations
, representing the space of
configurations a device can take. It is an array of
device_configurations
, with each element representing a set
of states the device can assume. Each resource_descriptor
in
a possible_device_configuration
represents a set of possible
values for a resource, rather than a single value, allowing
for a compact description of possible resource
configurations for a device.
Since a device_configuration
is a variable-sized structure,
you can't directly index the possible_device_configurations
to obtain a given device_configuration
. You have to be more
clever, but only just. As you might expect:
void print_possible_device_configurations(struct possible_device_configurations *possible) { #define NEXT_POSSIBLE(c) \ (c) = (struct device_configuration *) \ ((uchar *)(c) + \ sizeof(struct device_configuration) + \ (c)->num_resources * \ sizeof(resource_descriptor)) struct device configuration *config = possible->possible + 0; int i; for (i=0;i<possible->num_possible;i++) { print_device_configuration(config); NEXT_POSSIBLE(config); } }
Each resource_descriptor
in a possible_device_configurations
may represent a set of possible resources, so the lower
level functions will, sadly, need to be changed, leaving us
with only the greasy middlemen, print_device_configuration
and print_resource_descriptor
, unchanged. Some parting words
of advice:
void print_mask(const char *name, resource_descriptor r) { bool first = true; int i; printf("%s: [", name); if (!r.d.m.mask) printf("none"); for (i=0;i<32;i++) if (r.d.m.mask & (1 << i)) { printf("%s%d", first ? "" : ",", i); first = false; } printf("]\n"); } void print_range(const char *name, resource_descriptor r) { printf("%s: min %x max %x step %x length %x\n", name, r.d.r.minbase, r.d.r.maxbase, r.d.r.basealign, r.d.r.len); }
Copyright ©1999 Be, Inc. Be is a registered trademark, and BeOS, BeBox, BeWare, GeekPort, the Be logo and the BeOS logo are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners.