Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm trying to write a kernel driver for a USB device. I've done a LibUSB version. But now I'm confused. What's the difference between them when I make use of them?
* LibUSB (userspace driver): I used reverse engineering to write these drivers, then I'm so afraid that if I use LibUSB, I'll have to write a lot of code for every action. LibUSB is a kind of library, API... When I need to communicate with the device, I write a C/C++ app and use this API/lib to send/receive data for example.
* Kernel driver: I'll write the driver once, install and make it reside in kernel, it'll be as a system file (character driver, my intent). I suppose that this module will automatically do the background tasks for me, and I only have to do a few thing with it.
Could you tell me if it's right? I don't know how to do next...
To answer your question, consider the difference between "a USB keyboard" and "a USB hard disk drive."
A "USB keyboard" is a single input/output device that a particular application will simply need to "find, recognize, and talk to." From the operating-system's perspective, this is just a serial device. It's got a particular recognition-signature (so you can tell that it's a keyboard), but the operating system really doesn't need to do special things with it.
A music-application would like to be able to handle "USB keyboards" fairly generically. A user-space library is a good way to do that. In this way, each app doesn't have to repeat a bunch of code: they simply use the library.
On the other hand, "a USB hard disk drive" needs to present itself as a hard-disk storage device. Clients who wish to avail themselves of its services want to consider only that "they are talking to a mounted hard-disk." They don't care that it's USB-attached. Therefore, the operating systemmust contain the driver ... must contain all of the code that talks to the USB-device. (In fact, the operating system must prevent user-space applications from attempting to open such a device themselves.)
Based on what you have described in your post, I believe that the user-space library that you have already created is the correct approach to use in your case.
Thank you so much. Your explanation has made me understand the concept. That's what I need. Thank you, thank you!
Just one more point. Now I have many these USB boards attached to my computer. I need to handle all of them. After some Google search result, I see Libusb can do that. But do you think if a kernel driver may be better?
Quote:
Originally Posted by sundialsvcs
To answer your question, consider the difference between "a USB keyboard" and "a USB hard disk drive."
A "USB keyboard" is a single input/output device that a particular application will simply need to "find, recognize, and talk to." From the operating-system's perspective, this is just a serial device. It's got a particular recognition-signature (so you can tell that it's a keyboard), but the operating system really doesn't need to do special things with it.
A music-application would like to be able to handle "USB keyboards" fairly generically. A user-space library is a good way to do that. In this way, each app doesn't have to repeat a bunch of code: they simply use the library.
On the other hand, "a USB hard disk drive" needs to present itself as a hard-disk storage device. Clients who wish to avail themselves of its services want to consider only that "they are talking to a mounted hard-disk." They don't care that it's USB-attached. Therefore, the operating systemmust contain the driver ... must contain all of the code that talks to the USB-device. (In fact, the operating system must prevent user-space applications from attempting to open such a device themselves.)
Based on what you have described in your post, I believe that the user-space library that you have already created is the correct approach to use in your case.
The kernel simply presents all the devices to you... as character-device "files" in /dev. What more do you need than this, for your application? (Answer: nothing.)
The kernel is already providing you with the ability to open the devices (as "files"), and to read from them and write to them (asynchronously or synchronously) and to control them. That's all you need in this case.
The user-land library simply "hides the messy details" from application programs. It keeps device-specific details from wandering into the applications themselves.
For instance, that (musical) keyboard... It's a USB keyboard, but it could have been a MIDI keyboard. In both cases, an ordinary user-land program can do the job because all you're doing with the device in both cases is sending and receiving a stream of bytes. The user-land "device driver" library might provide the very-useful service of allowing applications to abstract the notion of "a keyboard instrument." It might handle both MIDI and USB interfaces in such a way that the application would not need to care (but might only need to specify...) exactly how this keyboard is attached to the computer.
There already is a family of "USB device" drivers in the kernel. In this case, we're just using the "serial, vanilla" driver ... which lets us open, close, read, write, and control the device. We have no need for the kernel to (in this case, for this type of device) observe the stream of data that is being read or written, nor to produce it. For a USB-attached disk drive or network-adapter, say, it would be quite different.
The kernel is already providing you with the ability to open the devices (as "files"), and to read from them and write to them (asynchronously or synchronously) and to control them. That's all you need in this case.
By the way, if I use this "file", the main operation is read/write. But a device may need more than that: read/write command, read/write data (bulk), ... How can I control these kind of transfer types?
Quote:
The user-land library simply "hides the messy details" from application programs. It keeps device-specific details from wandering into the applications themselves.
Yeah, the US "driver" makes the work easier to programmers. One of it's advantages is the "transparence" as you said.
But it also has some drawbacks: root/privileged user right, slow... As the previous question, I have to handle multiple device (same kind). If I use kernel driver, it'll automatically create that quantity of system files in /dev/. But with LibUSB, I don't know how it treats. I'm investigating...
I've solved the LibUSB problem. For every attached device, I'll open each, and assign a handle. That's so.
Could you can tell me more about these system files, if I use kernel driver? The main operation is read/write. But a device may need more than that: read/write command, read/write data (bulk), ... How can I control so many kind of data transfer?
Basically, what the kernel is doing for you is simply to present the USB devices as serial-devices in /dev. (Each USB device presents an identity which determines how the system attempts to use the device...) The so-called udev subsystem manages this feat.
So, what your library would do is to search-for and open the appropriate USB device, as a file, and then manage all the read/write/fcntl activity on behalf of the application program. In so doing, it would insulate said program from awareness or concerns about exactly how the device works.
Basically, what the kernel is doing for you is simply to present the USB devices as serial-devices in /dev. (Each USB device presents an identity which determines how the system attempts to use the device...) The so-called udev subsystem manages this feat.
So, what your library would do is to search-for and open the appropriate USB device, as a file, and then manage all the read/write/fcntl activity on behalf of the application program. In so doing, it would insulate said program from awareness or concerns about exactly how the device works.
Thank you for your explanation. But it's not very clear for me. I had created a simple driver for my USB device. It was represented as a file as you said. Then I "echo 1" to this file. In the driver, write_function, correlative with ".write" file_operation, I pass this parameter "1" and then turn on a LED. It was OK. But I know the file_operations are just read, write, flush... It means that I can only communicate with the device via these functions. Suppose that I need to send a command and a data to the device, in the write_function, I'll need to use some "switch/case" to call the appropriate usb-function to handle each type of transfer, for example, usb_control_msg (for command msg) and usb_bulk_msg (for data msg). Could you tell me if it's true? I don't know how a device can work with many action just with limited functions like that.
I really appreciate your patience, and your help. I feel good to meet you here. Thank you a lot!
Devices vary. The USB protocol (as reflected in "libusb") contains a fairly-sophisticated range of "commands" that you can send to a device. Anyhow, your driver-software will continue to employ "libusb" for that, its intended purpose.
What your library will|does do is to manage all those calls to "libusb," sending the right commands and otherwise making the right calls to "cause whatever your app wants to happen ... to happen."
You won't be doing the calls directly: that's what "libusb" is for.
Devices vary. The USB protocol (as reflected in "libusb") contains a fairly-sophisticated range of "commands" that you can send to a device. Anyhow, your driver-software will continue to employ "libusb" for that, its intended purpose.
What your library will|does do is to manage all those calls to "libusb," sending the right commands and otherwise making the right calls to "cause whatever your app wants to happen ... to happen."
You won't be doing the calls directly: that's what "libusb" is for.
Yeah, I know, but I'm asking how the kernel driver works. My question may be unclear. My LibUSB-based version is updating, and it seems to work. I'm just thinking about the kernel version, at least I can learn something about it (kernel driver). Can I raise the previous question again?
Thank you for your explanation so far. But there's something I don't understand about kernel driver. Can I ask you about it for more?
I had created a simple driver for my USB device. You know, it was represented as a file, not a file on a disk, which is represented by a structure named inode. Then I "echo 1" to this file. In my driver, write_function, correlative with ".write=" file_operation, I pass this parameter "1" and then turn on a LED. It was OK.
But let me ask a *stupid* question. It's the only thing unresolving in my mind. The probe function does it job in initializing (detect a device). After that, the device waits for user interaction. The way we communicate to device is through the file above. If we fwrite data to file, it means the device will receive that data later.
I know that the file_operations are just read, write, flush... Suppose that I need to send a control command and a data buffer to the device, in the write_function, I'll need to use some "switch/case" to call the appropriate usb-function to handle each type of transfer, for example, usb_control_msg (for command msg) and usb_bulk_msg (for data msg). It's my reason. Could you tell me if it's true? I don't know how can a device work with many actions just with limited functions like that.
Thanks for your kind help.
Last edited by rockballad; 08-27-2008 at 02:01 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.