I am trying to understand different ways linux kernel initialize structures. In this query I wrote a sample usb driver but I do not understand some points, pointed as comments preceding ??
static struct usb_device_id pen_table[] = //?? why pen_table is an array
{
{ USB_DEVICE(0xaaaa , 0x8816) }, //??what type of array initialization is this
{} /* Terminating entry */ //??how this terminates
};
I tried to initialize device id table in this way, but I am getting errors as near initialization
static struct usb_device_id pen_table = {
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor=0xaaaa,
.idProduct = 0x8816,
};
You should have Linux
kernel source at hand to really understand this.
pen_table
is an array?It wil be necessary in MODULE_DEVICE_TABLE
(see Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage) and in defining instance of usb_driver
struct, see http://opensourceforu.efytimes.com/2011/11/usb-drivers-in-linux-2/.
USB_DEVICE
is a macro defined in include/linux/usb.h:
#define USB_DEVICE(vend, prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
.idVendor = (vend), \
.idProduct = (prod)
C standard says:
The initialization shall occur in initializer list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject; all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
and:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
- if it has pointer type, it is initialized to a null pointer;
- if it has arithmetic type, it is initialized to (positive or unsigned) zero;
- if it is an aggregate, every member is initialized (recursively) according to these rules;
- if it is a union, the first named member is initialized (recursively) according to these rules.
Thanks to this, id_table
is defined as a pointer and not as an array inside usb_driver
:
const struct usb_device_id *id_table;
Instead of passing an array size independently a function that uses id_table
will increment pointer to id_table
until one of its elements is NULL. See this short example that represents this technique:
#include <stdio.h>
#include <stdlib.h>
struct small
{
int a;
int b;
};
struct big
{
struct small *s;
};
struct small table[] =
{
{1, 1},
{2, 2},
{3, 3},
{}
};
int main(void)
{
struct big b = {
.s = table
};
const struct small *s;
/* traverse through table using pointer arithmetic */
for (s = b.s; s->a; s++)
{
printf("%d\n", s->a);
printf("%d\n", s->b);
}
exit(0);
}
I don't, are you sure you're not trying to redefine pen_table
? What's an error message?