My name is Shawn Campbell and I am creating a linux device driver for a previously unsupported device. The device is a magtek swipe reader that has a single endpoint that uses the usb "interrupt in" transfer method. I can get data from my read method, but the driver crashes my system. I am stuck in a "change cascade" where I keep changing things around trying to determine the problem. Another pair of eyes would be great. I am new to kernel development and I could use some help. I will include my source as an attachment. The source is based on the usb-skeleton driver from the 2.4.18 kernel source. I will be using the device driver on a 2.4.x kernel once in production use. Any suggestions or observations about why the code would hangup my system would be appreciated. Am I using spinlocks or semaphores incorrectly? What about my use of wait_queues? Am I forgetting to protect a data structure with a spinlock or semaphore at a key point? Am I kfree()ing a data structure too early? Is the location and usage of usb_submit_urb and usb_unlink_urb ok? I read somewhere that the probe/disconnect routines should have most of the code of the open/release routines. Is that true?
Here is what I have attempted so far: I have been reading the Linux Device Drivers 2nd Edition, the USB and HID pdfs, linux/Documentation, posting to kernel newbies, can anyone recommend any other books or information sources for a beginner? Oh, add this list to that list of sources, though this is my first post. :) My device is an HID device. My first attempt was the hid driver. The swipe reader reports itself as neither a keyboard or mouse, just an hid device. The hiddev driver was my next attempt. It did claim my device and I could interact with it in a limited way. I talked to Paul Stewart and we emailed back and forth for a while. My issue with the hiddev device was that while I could get the data from the input report via ioctl calls, if same card was swiped twice, the second time I would get no notification from the device that anything had happened. I used read() to determine when a card was swiped and an ioctl() call to get to the report. I really needed the input report to be returned via the read(). The read() call as it is now only returns the differences between reports which isn't useful for my situation. The hiddev driver was written to talk to ups(s), which only need to report changes in state. Paul told me about a enhancement to the hiddev driver in the 2.5.x kernel, some new ioctl calls would allow the driver to be switched into a mode that would return the full report. Paul backported the patch to the 2.4.x kernel. I applied the patch, but it froze my system. I tried several smaller patches he sent me via email. I didn't have any success. I really appreciated all the effort and time Paul took into to helping me. While I was working with Paul, I started developing my own device driver from scratch using the Linux Device Drivers book as a guide just in case hiddev didn't pan out. Then I happened to see a mention of kernel newbies somewhere, perhaps in the kernel device driver book. I jumped on irc and started talking to Greg Kroah. He suggested that I adapt the omninet driver (usb-serial) to my needs and that it what I attempted. I chatted back and forth about how to get to work with my device. I made the changes and I could get a read() to return all but the first 8 bytes. I was loosing the first packet. I talked to Greg about it, and he thought that it would probably be easier to mail him what I had done. I sent him the code. He also suggested looking at usb-skeleton. So I took my from scratch driver, usb-skeleton, and my linux device driver book and constructed a new driver. To my surprise, it actually worked. I could read a full report from my device. But the driver wasn't being quite right. I unplugged the driver in the middle of cat /dev/test0 and sometimes it would segmentation fault, and when it didn't, it wouldn't kill the process and return an error as it did when I have cat(ed) other character devices. I emailed Greg my current code for the device driver I had crafted from usb-skeleton. Greg is going to be away for about a week though. I asked him if he could recommend a mailing list. He told me about linux-usb-devel. So I am posting this extremely long message here. I wanted to include all the information about my entire experience so that anyone offering assistance would know what I have attempted so far. My code is attached to this document. It is a module for 2.4.x. Any help would be appreciated. Shawn p.s. Thanks to Greg and Paul for patiently helping me. I have learned a lot.
magtek.c
Description: Binary data