Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usb device id table understanding

Tags:

c

linux

usb

drivers

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,
};
like image 260
nikhil chaubey Avatar asked Jun 30 '26 00:06

nikhil chaubey


1 Answers

You should have Linux kernel source at hand to really understand this.

  • Why 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/.

  • what type of array initialization is this?

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)
  • how this terminates?

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 tried to initialize device id table in this way, but I am getting errors as near initialization

I don't, are you sure you're not trying to redefine pen_table? What's an error message?

like image 180
Arkadiusz Drabczyk Avatar answered Jul 02 '26 12:07

Arkadiusz Drabczyk