Originally Posted by
yann
thank you, actually i speak Croatian, not English, I understand "writing ssimple kernel driver" document, but i do not in some way...one thing i dont understansd, is in wich order do these commands go...
It must be hard to deal with a language barrier for material like that. I am always surprised more people do not translate stuff like this, voluntarily -- I suppose by the time your english is good enough, maybe you cannot be bothered to help anyone else out? Anyway...
That's all one C program. However, kernel programming does not use the standard C libraries and is specially compiled, so there are some significant differences. For example, there is no main().
This is because a module runs as part of the kernel process, and is not really an independent executable. When the module is loaded* -- ie, the program is started -- it registers a number of callback functions and other information with the kernel. A callback is a function which is called in response to some event, eg, in a user interactive program, you could have a callback for when the mouse is moved. Callbacks in modules are called by the kernel itself when, for example, the kernel detects a USB device plugged into the system. So an individual USB module must first register the ID of the device for which it was written, and some functions to deal with generic USB events (that is, basic events common to all USB devices, such as being plugged and probed by the OS). Those functions are a struct usb_driver, the ID is in a struct usb_device_id. These should be global to the scope of the module, eg, they are not assigned in any function.
Notice there is a pointer in the usb_driver struct to a usb_device_id struct. What does go in an actual function is a call to usb_register(), which takes a pointer to the usb_driver struct which is declared globally (and has a pointer to the device_id struct). That function is the module's initialization function, and it is defined as such at compilation by including this line at the end of the module code:
module_init (my_inititialization_function);
I haven't done this stuff in a while. This is the simple part; USB module programming gets quite complex. Don't feel you have to go through with it at this point, it may be "counter productive" for you until you have more experience with the C language -- there is a lot of need for looping thru arrays of nested structs:
Code:
for (i=0;i<dev->actconfig->desc.bNumInterfaces;i++) {
tmp=dev->actconfig->interface[i];
printk("usbgetinfo: Configuration %d of %d\n",i+1,dev->actconfig->desc.bNumInterfaces);
for (j=0;j<tmp->num_altsetting; j++) {
hinfc=&tmp->altsetting[j];
printk("\tInterface %d of %d\n",j+1,tmp->num_altsetting);
for (k=0; k<hinfc->desc.bNumEndpoints; k++) {
endpoint = &hinfc->endpoint[k];
/* endpoint->desc is a struct usb_endpoint_descriptor */
printk("\t\tEndpoint: %d",endpoint->desc.bEndpointAddress);
if (endpoint->desc.bEndpointAddress & USB_DIR_IN) printk(" (in) ");
if (endpoint->desc.bEndpointAddress & USB_DIR_OUT) printk(" (out) ");
type = endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
switch (type) {
case (USB_ENDPOINT_XFER_BULK): printk("BULK\n"); break;
case (USB_ENDPOINT_XFER_ISOC): printk("ISOCHRONOUS\n"); break;
case (USB_ENDPOINT_XFER_INT): printk("INTERRUPT\n"); break;
default: printk("??\n"); break;
}
}
}
}
Notice the use of printk() instead of printf(), since you cannot use stdio.h in a kernel module. Having fun yet?
Here is an online book you may want to look at:
Linux Device Drivers, 2nd Edition: Online Book
Unfortunately, the kernel changes all the time and there were some significant changes to some of the names of usb functions in the past year or so, meaning some material may contain the old function names. But the general idea remains the same.
* the module can also be placed "in tree" with the other modules and added to a database with the depmod shell command; the kernel can then load the module on the basis of the info in the database (the device ID, etc).