From: Peter H. <ph...@gm...> - 2015-08-24 20:52:01
|
Hi, I see that LIBUSB_REQUEST_TYPE_VENDOR is not supported on windows (but it is well supported on linux). This is well visible on line 4115 of windows_usb.c (function hid_submit_control_transfer). I'm playing with a keyboard firmware and the keyboard is supposed to be configurable using an application running on a PC. The application should be portable to both linux and windows. It may look like vendor specific extensions over a control endpoint would be a good choice. Well, at least I do not need one more endpoint on the device (since the control endpoint is already there). And this works fine on linux. But the support is missing on windows. Now my two questions: 1) Why is the support on windows missing? Is it because the windows API does not allow to use vendor extensions on the control endpoint? Or is it only because nobody needed this yet and therefore it was not implemented? 2) As a workaround, I'm considering to add one more endpoint to the keyboard: a Virtual COM Port. Would both linux and windows ports of libusb support sending and receiving data over the COM Port endpoint? Thanks, Peter. |
From: Xiaofan C. <xia...@gm...> - 2015-08-25 02:27:34
|
On Tue, Aug 25, 2015 at 4:34 AM, Peter Hercek <ph...@gm...> wrote: > Hi, > > I see that LIBUSB_REQUEST_TYPE_VENDOR is not supported on windows (but > it is well supported on linux). This is well visible on line 4115 of > windows_usb.c (function hid_submit_control_transfer). That is the limitation of the HID backend. The WinUSB backend will not have this limitation. In reality, the HID backend is not for keyboard and mouse, it is rather more for generic HID device. https://github.com/libusb/libusb/wiki/Windows#Known_Restrictions HID keyboards and mice cannot be accessed using the native HID driver as Windows reserves exclusive access to them. Are your device a standard USB HID keyboard? > I'm playing with a keyboard firmware and the keyboard is supposed to be > configurable using an application running on a PC. The application > should be portable to both linux and windows. I think libusb is the wrong choice here. > It may look like vendor specific extensions over a control endpoint > would be a good choice. Well, at least I do not need one more endpoint > on the device (since the control endpoint is already there). And this > works fine on linux. But the support is missing on windows. > > Now my two questions: > > 1) Why is the support on windows missing? Is it because the windows API > does not allow to use vendor extensions on the control endpoint? Or is > it only because nobody needed this yet and therefore it was not implemented? As mentioned before, it is a limitation of the HID backend. > 2) As a workaround, I'm considering to add one more endpoint to the > keyboard: a Virtual COM Port. Would both linux and windows ports of > libusb support sending and receiving data over the COM Port endpoint? > Again, you are using the wrong library. Under Windows, I believe the keyboard vendors use a filter driver or things like that. I am not an expert though. -- Xiaofan |
From: Xiaofan C. <xia...@gm...> - 2015-08-25 05:13:34
|
On Tue, Aug 25, 2015 at 10:27 AM, Xiaofan Chen <xia...@gm...> wrote: > On Tue, Aug 25, 2015 at 4:34 AM, Peter Hercek <ph...@gm...> wrote: >> 2) As a workaround, I'm considering to add one more endpoint to the >> keyboard: a Virtual COM Port. Would both linux and windows ports of >> libusb support sending and receiving data over the COM Port endpoint? >> > > Again, you are using the wrong library. Under Windows, I believe > the keyboard vendors use a filter driver or things like that. I am > not an expert though. > But if you really want to keep the keyboard function and also use libusb Windows, you can make your device a USB Composite Device, no extra endpoint needed, just adding another interface (maybe you want to make it Interface 0, the keyboard will be interface 1) with just the control endpoint. Use WinUSB for Interface 0 and you can use libusb for it. Just remember, you need to have a supported driver (WinUSB is the preferred) to use libusb under Windows. HID backend has many limitations and is really meant for generic HID device. -- Xiaofan |
From: Peter H. <ph...@gm...> - 2015-08-25 09:43:24
|
On 08/25/2015 04:27 AM, Xiaofan Chen wrote: > On Tue, Aug 25, 2015 at 4:34 AM, Peter Hercek <ph...@gm...> wrote: >> I see that LIBUSB_REQUEST_TYPE_VENDOR is not supported on windows (but >> it is well supported on linux). This is well visible on line 4115 of >> windows_usb.c (function hid_submit_control_transfer). > That is the limitation of the HID backend. The WinUSB backend will > not have this limitation. > > In reality, the HID backend is not for keyboard and mouse, it is > rather more for generic HID device. > > https://github.com/libusb/libusb/wiki/Windows#Known_Restrictions > HID keyboards and mice cannot be accessed using the > native HID driver as Windows reserves exclusive access to them. > > Are your device a standard USB HID keyboard? Yes, the device has 3 endpoints now: * control endpoint * keyboard endpoint * mouse endpoint It should stay to be a standard keyboard and mouse so that it works even when no specific drivers are installed on both linux and windows. The idea is that the configuration PC application should be only optional. The basic keyboard/mouse functionality must work without it (and without special drivers). But user can install an application/drivers to control more advanced settings of the keyboard/mouse in a more comfortable way. And it should be possible to navigate the PC application with the keyboard/mouse which is being configured. Ok, so the HID driver used by HID backend does not support vendor specific control requests. Therefore my options are (beside writing my own driver for windows which I definitely do not intend to): 1) Assign WinUSB driver to the device. Would that driver also support the keyboard/mouse functionality? 2) Add second interface to some of the endpoints. But this means that I would need to switch to the interface and during that time either keyboard, or mouse, or both would not be available. Is that true? 3) Use a Virtual COM Port on one more additional endpoint. In this case, I would probably need libusb only to find which of all the available COM ports is the one on the keyboard/mouse device. I would probably use QT for the communication itself (standard COM port classes). Would libusb allow me to identify the right COM port using the same code path on both linux and windows? I know I can identify the right COM port if I write specific code for linux and windows. The reason why I'm trying to use libusb is that it was used before. So it is easy to continue using it. I'm just modifying an open firmware https://github.com/hercek/keyboard-firmware/tree/katy. I would also like to use the same code path for both linux and windows. I would like all OS specific stuff to be in 3rd party libraries. Thanks. |
From: Xiaofan C. <xia...@gm...> - 2015-08-25 10:13:30
|
On Tue, Aug 25, 2015 at 5:43 PM, Peter Hercek <ph...@gm...> wrote: > On 08/25/2015 04:27 AM, Xiaofan Chen wrote: >> On Tue, Aug 25, 2015 at 4:34 AM, Peter Hercek <ph...@gm...> wrote: >> Are your device a standard USB HID keyboard? > Yes, the device has 3 endpoints now: > * control endpoint > * keyboard endpoint > * mouse endpoint > > It should stay to be a standard keyboard and mouse so that it works even > when no specific drivers are installed on both linux and windows. The > idea is that the configuration PC application should be only optional. > The basic keyboard/mouse functionality must work without it (and without > special drivers). How do you design your basic keyboard/mouse function? Using a USB composite device or an HID top level collection? > But user can install an application/drivers to control > more advanced settings of the keyboard/mouse in a more comfortable way. > And it should be possible to navigate the PC application with the > keyboard/mouse which is being configured. What kind of configuration? > Ok, so the HID driver used by HID backend does not support vendor > specific control requests. > Therefore my options are (beside writing my own driver for windows which > I definitely do not intend to): > > 1) Assign WinUSB driver to the device. Would that driver also support > the keyboard/mouse functionality? No. That is not an option. You will lose the keyboard/mouse function. > 2) Add second interface to some of the endpoints. But this means that I > would need to switch to the interface and during that time either > keyboard, or mouse, or both would not be available. Is that true? No. It will appear as three device under Windows. You only assign WinUSB to that custom interface. > 3) Use a Virtual COM Port on one more additional endpoint. In this case, > I would probably need libusb only to find which of all the available COM > ports is the one on the keyboard/mouse device. I would probably use QT > for the communication itself (standard COM port classes). Would libusb > allow me to identify the right COM port using the same code path on both > linux and windows? I know I can identify the right COM port if I write > specific code for linux and windows. Forget about the COM port, that is another complication. libusb is not the right library to talk to a USB Com ports. > The reason why I'm trying to use libusb is that it was used before. So > it is easy to continue using it. I'm just modifying an open firmware > https://github.com/hercek/keyboard-firmware/tree/katy. I would also like > to use the same code path for both linux and windows. I would like all > OS specific stuff to be in 3rd party libraries. > -- Xiaofan |
From: Peter H. <ph...@gm...> - 2015-08-25 14:21:15
|
On 08/25/2015 12:13 PM, Xiaofan Chen wrote: > How do you design your basic keyboard/mouse function? Using > a USB composite device or an HID top level collection? It is an USB composite device. >> But user can install an application/drivers to control >> more advanced settings of the keyboard/mouse in a more comfortable way. >> And it should be possible to navigate the PC application with the >> keyboard/mouse which is being configured. > What kind of configuration? I meant configuration for the meaning of the keyboard switches. E.g. what usb ussageId is sent when the first key in the top row is pressed. So it is about what is the meaning of physical switches and whether some chords should emit a macro etc. I did not mean USB HID device configurations. > >> 2) Add second interface to some of the endpoints. But this means that I >> would need to switch to the interface and during that time either >> keyboard, or mouse, or both would not be available. Is that true? > No. It will appear as three device under Windows. You only assign > WinUSB to that custom interface. Ok, but that means that I would not use switching of USB Configurations or setting alternate settings of an interface. That means one more endpoint (which would be handled by WinUSB). So the keyboard would have 4 bidirectional endpoints: subControl, hidKeybaord, hidMouse, winUsbControl (this last one is my custom substitute for missing LIBUSB_REQUEST_TYPE_VENDOR). >> 3) Use a Virtual COM Port on one more additional endpoint. In this case, >> I would probably need libusb only to find which of all the available COM >> ports is the one on the keyboard/mouse device. I would probably use QT >> for the communication itself (standard COM port classes). Would libusb >> allow me to identify the right COM port using the same code path on both >> linux and windows? I know I can identify the right COM port if I write >> specific code for linux and windows. > Forget about the COM port, that is another complication. libusb > is not the right library to talk to a USB Com ports. I did not intend to use it for talking to COM ports only as an OS independent way to identify the right COM port (the com port which is part of the keyboard device). Thanks. |
From: Tim R. <ti...@pr...> - 2015-08-25 17:03:34
|
Peter Hercek wrote: >>> 2) Add second interface to some of the endpoints. But this means that I >>> would need to switch to the interface and during that time either >>> keyboard, or mouse, or both would not be available. Is that true? >> No. It will appear as three device under Windows. You only assign >> WinUSB to that custom interface. > Ok, but that means that I would not use switching of USB Configurations > or setting alternate settings of an interface. That means one more > endpoint (which would be handled by WinUSB). Switching configurations is very problematic in Windows. You generally want to avoid that. Alternate settings don't help in your case. Those change the endpoint array in an interface, but the interface will already have been assigned to a driver. To do what you want, you need a new interface. > So the keyboard would have 4 bidirectional endpoints: subControl, > hidKeybaord, hidMouse, winUsbControl (this last one is my custom > substitute for missing LIBUSB_REQUEST_TYPE_VENDOR). Control endpoints are bidirectional. All other endpoints are unidirectional. In this case, however, what you're trying to do is gain access from an application. That means you need a driver, and drivers are assigned by interface, not by endpoint. Indeed, if the functionality you want is all available through the control endpoint, then you could simply add another interface with no endpoints at all. So, you have interface 0 defining a keyboard device with your keyboard interrupt endpoint. You have interface 1 defining a mouse device with your mouse interrupt endpoint. You have interface 2 defining a custom device with no endpoints. (Or do you have your mouse and keyboard as two top-level collections in a single interface?) > I did not intend to use it for talking to COM ports only as an OS > independent way to identify the right COM port ... Ah, if only there were such a thing... -- Tim Roberts, ti...@pr... Providenza & Boekelheide, Inc. |
From: Peter H. <ph...@gm...> - 2015-08-26 01:24:22
|
On 08/25/2015 07:03 PM, Tim Roberts wrote: > Control endpoints are bidirectional. All other endpoints are > unidirectional. In this case, however, what you're trying to do is gain > access from an application. That means you need a driver, and drivers > are assigned by interface, not by endpoint. Indeed, if the > functionality you want is all available through the control endpoint, > then you could simply add another interface with no endpoints at all. > > So, you have interface 0 defining a keyboard device with your keyboard > interrupt endpoint. You have interface 1 defining a mouse device with > your mouse interrupt endpoint. You have interface 2 defining a custom > device with no endpoints. > > (Or do you have your mouse and keyboard as two top-level collections in > a single interface?) No, keyboard and mouse have separate interfaces. Thanks for pointing all my mistakes. I think I understand now. I should be sending vendor requests to my new interface (instead of the device). The new interface will have only the control endpoint. And the interface will have WinUsb driver instead of the HID driver. The vendor requests should work with winusb backend. What happens when one sends vendor request to a device which has more interfaces and the interfaces use different drivers (and therefore backends). Which backend would process requests to the device? |
From: Tim R. <ti...@pr...> - 2015-08-26 19:27:51
|
Peter Hercek wrote: > Thanks for pointing all my mistakes. I think I understand now. I should > be sending vendor requests to my new interface (instead of the device). Are you talking about the bmRequest field? That isn't related to what we're talking about here. The device neither knows nor cares what the driver configuration is like. It just gets requests. What you need to know is how to get that request. To do that, you need to open a driver. To get a driver you can open, you need an interface, which doesn't need any endpoints. > The new interface will have only the control endpoint. This is a picky point, but there is only one control endpoint 0, and it doesn't belong to any interfaces. It is always available. > And the interface > will have WinUsb driver instead of the HID driver. The vendor requests > should work with winusb backend. Yes. > What happens when one sends vendor request to a device which has more > interfaces and the interfaces use different drivers (and therefore > backends). Which backend would process requests to the device? I don't understand the question. Interfaces are merely used to collect endpoints together and trigger driver loading. The traffic on the wire is concerned only with endpoints. The only time an interface number goes across the wire is when you enable an interface or change an alternate setting. The device just sees traffic for endpoint 0 or endpoint 0x81, etc. -- Tim Roberts, ti...@pr... Providenza & Boekelheide, Inc. |
From: Alan S. <st...@ro...> - 2015-08-26 19:42:31
|
On Wed, 26 Aug 2015, Tim Roberts wrote: > Peter Hercek wrote: ... > > What happens when one sends vendor request to a device which has more > > interfaces and the interfaces use different drivers (and therefore > > backends). Which backend would process requests to the device? > > I don't understand the question. Interfaces are merely used to collect > endpoints together and trigger driver loading. The traffic on the wire > is concerned only with endpoints. The only time an interface number > goes across the wire is when you enable an interface or change an > alternate setting. The device just sees traffic for endpoint 0 or > endpoint 0x81, etc. I think Peter was asking what would happen if a control request was sent with the Recipient bitmask set to either INTERFACE or ENDPOINT (and the type set to VENDOR, although this shouldn't matter). Which driver would process the request? Presumably the driver associated with the interface or endpoint specified in the request's wIndex field. But Tim knows more about this than I do. Didn't the policy change not too long ago, starting with Windows 8? Alan Stern |
From: Tim R. <ti...@pr...> - 2015-08-27 18:06:57
|
Alan Stern wrote: > I think Peter was asking what would happen if a control request was > sent with the Recipient bitmask set to either INTERFACE or ENDPOINT > (and the type set to VENDOR, although this shouldn't matter). Which > driver would process the request? But, that question is meaningless, right? Drivers don't process requests. Drivers SUBMIT requests. > Presumably the driver associated with the interface or endpoint > specified in the request's wIndex field. But Tim knows more about this > than I do. Didn't the policy change not too long ago, starting with > Windows 8? Yes. Years ago, Windows didn't care about the interface and endpoint fields in wIndex, but Linux would reject the request unless the driver had claimed the corresponding interface. When I whined about that, you convinced me that the Linux way was correct, and in Windows 8 Microsoft adopted the same restriction. However, that's not related to the question here. -- Tim Roberts, ti...@pr... Providenza & Boekelheide, Inc. |
From: Alan S. <st...@ro...> - 2015-08-27 18:53:48
|
On Thu, 27 Aug 2015, Tim Roberts wrote: > Alan Stern wrote: > > I think Peter was asking what would happen if a control request was > > sent with the Recipient bitmask set to either INTERFACE or ENDPOINT > > (and the type set to VENDOR, although this shouldn't matter). Which > > driver would process the request? > > But, that question is meaningless, right? Drivers don't process > requests. Drivers SUBMIT requests. No, libusb submits requests. Drivers like WinUSB take the submissions and massage them into a form that core OS will accept. At least, that's my understanding -- otherwise why would libusb need any particular driver to be associated with a device? (Or if you want to put it another way, libusb asks a driver to submit a request on its behalf. They amount to the same thing.) So if you had a composite device, with WinUSB bound to one interface, libusbK bound to another, and some other driver bound to a third, what would happen when libusb submits a control request like the one described above? Alan Stern |
From: Tim R. <ti...@pr...> - 2015-08-28 16:43:32
|
Alan Stern wrote: > On Thu, 27 Aug 2015, Tim Roberts wrote: >> >> But, that question is meaningless, right? Drivers don't process >> requests. Drivers SUBMIT requests. > No, libusb submits requests. Drivers like WinUSB take the submissions > and massage them into a form that core OS will accept. At least, > that's my understanding -- otherwise why would libusb need any > particular driver to be associated with a device? Because libusb is just an application. It doesn't really participate in the kernel USB subsystems. It can't, because user-mode applications aren't allowed to do that. When I said "requests", I meant "URBs". Only drivers can submit URBs. The libusb/driver interface is merely a private convention between a kernel driver and its user-mode client. It happens to have the same information one would find in a URB, but that's just a convenient accident. It's not part of the USB core on any of the operating systems.. > (Or if you want to put it another way, libusb asks a driver to submit a > request on its behalf. They amount to the same thing.) I would argue that it is NOT the same thing. It is merely an accident of the design of the WinUSB API. Libusb is just one of a plethora of clients that feed to myriad private kernel driver interfaces that get translated into URBs, where the USB stack really begins. However, this is just unimportant semantic nitpicking, something I enjoy more than most rational people. > So if you had a composite device, with WinUSB bound to one interface, > libusbK bound to another, and some other driver bound to a third, what > would happen when libusb submits a control request like the one > described above? There can't possibly be any automatic routing, if that's what you're asking. In a composite device, on Windows at least, it isn't until you get down to the generic composite parent driver (usbccgp) that any of the components are even aware that there ARE multiple interfaces. Usbccgp rewrites the descriptors that it hands upwards, so that the individual interface drivers are fooled into thinking they are a single-interface device. All of the interface drivers have access to the control endpoint, and a driver can certainly create a control transfer URB with a different interface number than the one it was assigned. In earlier systems, Windows would allow this. Starting in Windows 8, such a request fails with an "incorrect parameter" error, just as Linux has always done. HOWEVER, with WinUSB in particular, there is an additional twist to this. When you call WinUsb_ControlTransfer with a "to interface" or "from interface" request, WinUSB will automatically fill in the wIndex field with the interface that you own. Thus, it is impossible to submit a cross-interface request through WinUSB. -- Tim Roberts, ti...@pr... Providenza & Boekelheide, Inc. |
From: Peter H. <ph...@gm...> - 2015-08-27 09:49:33
|
Notice all my knowledge about USB is only from reading a few tutorials (like USB in a NutShell) and the experience I got modifying the keyboard firmware and the associated QT client PC application. I did not even write the original source code there. My goal si so that the PC application works well for both Linux and Windows and preferably using the same code path (without ifdefs). Sometimes I may be quite wrong in my thinking how it works. Thanks for patience. On 08/26/2015 09:27 PM, Tim Roberts wrote: > Peter Hercek wrote: >> Thanks for pointing all my mistakes. I think I understand now. I should >> be sending vendor requests to my new interface (instead of the device). > Are you talking about the bmRequest field? That isn't related to what > we're talking about here. The device neither knows nor cares what the > driver configuration is like. It just gets requests. What you need to > know is how to get that request. To do that, you need to open a > driver. To get a driver you can open, you need an interface, which > doesn't need any endpoints. Yes, I meant bmRequestType. I'm not sure what you mean by device here. Is it a windows abstraction of a physical device (like a keyboard) in the corresponding driver or do you mean the firmware in the physical device (e.g. keyboard firmware). Looks like you mean the physical device. And yes the keyboard firmware in my case does not have any clue about drivers on the PC side. >> What happens when one sends vendor request to a device which has more >> interfaces and the interfaces use different drivers (and therefore >> backends). Which backend would process requests to the device? > I don't understand the question. Interfaces are merely used to collect > endpoints together and trigger driver loading. The traffic on the wire > is concerned only with endpoints. The only time an interface number > goes across the wire is when you enable an interface or change an > alternate setting. The device just sees traffic for endpoint 0 or > endpoint 0x81, etc. > I'm talking about mbRequestType here. As far as I know the QT application just: * enumerates the usb devices (libusb_get_device_list); * selects the descriptor it knows (using checks on result of libusb_get_device_descriptor); * gets handle for the descriptor (libusb_open) * sends vendor requests to the keyboard (libusb_control_transfer) The vendor requests are targeted as: LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_{IN,OUT} By sending a request to the device I mean LIBUSB_RECIPIENT_DEVICE. By sending to an interface I mean LIBUSB_RECIPIENT_INTERFACE (and the interface id being in wIndex). I assumed that libusb does dispatching to the proper backend (driver) based on the selected interface. If that would be so, then of course there is a question how requests targeted as LIBUSB_RECIPIENT_DEVICE or LIBUSB_RECIPIENT_ENDPOINT (for the shared endpoint 0) would be dispatched. Which backend would be selected if there are more backends/drivers associated with the device? From your response it feels like I must select the backend explicitly somehow. What linux driver would correspond to WinUSB driver in Windows? Lets assume I want to extend the keyboard device by adding a logging interface and an input interrupt endpoint with it. I.e. the added interface would not use only endpoint 0 but also its own *endpoint**N*. What would be a good driver on linux (I assume it is WinUSB on windows) to read the raw data from *endpoint**N*? |
From: Alan S. <st...@ro...> - 2015-08-27 14:10:40
|
On Thu, 27 Aug 2015, Peter Hercek wrote: > What linux driver would correspond to WinUSB driver in Windows? Lets > assume I want to extend the keyboard device by adding a logging > interface and an input interrupt endpoint with it. I.e. the added > interface would not use only endpoint 0 but also its own *endpoint**N*. > What would be a good driver on linux (I assume it is WinUSB on windows) > to read the raw data from *endpoint**N*? Linux has only one driver for libusb (or other direct userspace access to USB devices): usbfs. There's no choice involved. Alan Stern |