|
From: Peter S. <stu...@cd...> - 2004-09-12 05:31:49
|
(Sorry about the duplicate if you're subscribed to the list, Eric.) Whew, long thread. It seems there's some confusion going on.. Let's see if I can straighten it out. :) There seems to be a bit of a misunderstanding due to varying perceptions of libusb. My perception of the scope of libusb is as follows: libusb is a way to abstract the USB API of several operating systems into one easy-to-use library API that primarily adheres to the USB communication model. (Which consists of devices, configurations, interfaces and endpoints.) libusb is not a general utility library for use with any USB device. Perhaps it should be? IMHO it shouldn't. I would prefer a libusbutil for such things instead, possibly linked with libusb. Applications that can make use of libusb are applications that need to speak with USB devices whose (application) interface doesn't map well to an existing kernel subsystem. Applications that communicate with USB devices through some other, existing kernel interface probably wont have much use for libusb. Examples: alsamixer doesn't need libusb to control a USB soundcard since the ALSA USB audio driver in the kernel makes it look like any other soundcard in the system. OpenCT, which is a smart card reader library, uses libusb to access USB crypto tokens and smart card readers because card readers have no existing interface in the kernel and while there is an USB class specification for chip cards available now, (CCID) many older readers and tokens do not adhere to it, instead they each implement their own proprietary command set. I'm sorry if this was already completely clear. The rest of this mail pretty much just falls back on, and sometimes rewrites, the above. On Fri, Sep 10, 2004 at 09:59:37AM -0400, Eric S. Raymond wrote: > What we would like to do is this: > > 1) If the user specified a GPS path, open it. (This will handle > serial ports.) > > 2) If the user didn't specify s GPS path, scan the USB bus at > device-open time for an eligible device. If one is found, open it. > > 3) If all else fails, fall back on opening /dev/gps. > > 4) Set the opened fd to 4800/N/1 and go. > > The libusb code makes step 2 relatively easy, but doesn't give us > what we need for step 4. [..] > We can't use a udev handle because that would snarl us up in a lot > of ugly device-dependent code, especially in step 4 where the libusb > magic for setting line parameters is driver-dependent. We know it > dosn't have to be this way, because termios(2) calls work when > applied to a USB-device file descriptor obtained through open(2) on > a pathname. What kind of pathname, exactly? I am quite sure that you will not get the intended results (if any) from termios() calls on files anywhere in /proc/bus/usb. If you can find the correct /dev/ttyUSB* pathname in step 2 (how, though?) it could of course also be used in step 4. But I think all you can find with libusb is the /proc/bus/usb filename (in Linux). That fd will only accept USBFS ioctl()s however, and is not usable as a write()/read() communications channel to the device. > >Another way of doing this could involve parsing some information given > >by procfs, sysfs, etc to resolve the appropriate node path and obtain > >a file descriptor. > > > >procfs provides /proc/tty/driver/usbserial, which contains > >Vendor/Product IDs and most importantly the minor number listing for > >each device which can be used to form the node path to try and open. For all devices handled by usb-serial, this is the exact method that should be used, IMHO. It is quite specific to Linux, however. As is of course the usb-serial driver, so that may not be an issue. > >An algorithm to formulate a device node path based on the parsed > >vid/pid and minor could be used. This sounds like the best way, as > >both kernels 2.4 - 2.6 have this... I agree. > >I think, and could be used within the bus scanning code via libusb. > >For the Earthmate, it could break to the libusb handler since a > >driver is not available in the mainline kernels (yet). As I'm sure you've already realized this kind of thing falls outside the (current) scope of libusb. > >sysfs, which I'm sure you know is something new to 2.6, provides > >/sys/bus/usb-serial/drivers, which contains folders labeled by > >driver with the actual name of the node path the device has been > >assigned to inside, although that does not guarantee the path > >exists. > > While these methods are theoretically possible, they are not anything > that belongs in application code. I agree. Abstracting that part of OS differences into a library would be handy. But I'm not sure it should go into libusb. libusbutil could probably use some of the code in libusb though, or perhaps the other way around? One library provides nothing but OS abstraction of USB metainformation and the other provides applications with an API for communicating with devices per the standardized communications model. Or maybe they should be merged? I really like the very small footprint of libusb though, and I'd still want the option of not including all that device-specific code in (the hypothetic) libusbutil for times when I know I won't need it. Or maybe just use textutils on procfs? > And we are not the last project that is going to run into this > problem. Indeed, but.. > Any code that wants to handle USB devices as ttys will > hit it -- an almost identical use case occurs, for example, in > coping with UPSes (which, like GPSes can also be serial or USB). (This is the actual problem!) ..there is no uniform way to handle a USB device as a TTY. It's not standardized. :( > The underlying design issue here is that the usefulness of libusb > is sharply limited by the fact that its I/O objects don't live in > the same namespace as the rest of Unix. This needs to be fixed. IMHO, no. Again, libusb is meant to provide applications with easy access to the various parts of a USB device such as interfaces and ultimately endpoints. All USB devices can not be adequately represented by a single fd. I can imaginge a directory tree with one fd per endpoint, but abstracting that in a library instead of inside the kernel is a good thing, plus it can be made to work literally anywhere, even on systems lacking a directory/file concept. > We therefore request a feature from libusb: a new entry point > > int usb_file_descriptor(struct usb_device *dev) > > that returns a Unix file descriptor connected the specified > USB device. It would be most useful if the descriptor survived > unplug/replug of the device, but for gpsd's purposes it would > suffice if read/write returned -1 with EBADF after unplug. For your purposes this call would do something like the following: * open() the /proc/bus/usb fd corresponding to the device. * ioctl() it to pass the request on to the kernel. * Kernel usbfs code checks which serial device was registered by the usb-serial driver for the device. * The kernel simulates an open() call on the /dev/ttyUSB* device and returns a new open file descriptor as a result of the ioctl(). This new kernel usbfs ioctl() needs to know about each USB driver in the kernel providing a /dev interface to (part of) a device. I don't think this approach would be accepted by the kernel people. And what about all the other OSes, where there simply is no information available about this mapping? Be it due to closed source, lack of interest in cooperation or just bad OS design. On Fri, Sep 10, 2004 at 02:09:01PM -0400, Eric S. Raymond wrote: > > I think that it is always going to be a collection of > > application specific hacks, best placed in an application. > > "Application-specific hacks" are exactly what service libraries like > this are supposed to prevent. You have just defined libusb as being > effectively useless. See libusb scope stuff above. :) > Let me put that a slightly different way. Speaking as a developer > with real problems to solve involving talking to USB GPS and UPS > devices -- if libusb doesn't supply something equivalent to this, > there is no point in my carrying it around. The "application- > specific hacks" (like stepping through /dev/ttyUSB* by hand) will > drive it out entirely. Again, if you can communicate with your USB device through the kernel, you're already outside the scope of libusb. :) On Fri, Sep 10, 2004 at 03:17:16PM -0400, Eric S. Raymond wrote: > If the function were application-specific, I would agree. But if > the function were application-specific, I would not have brought it > up here. It's going to show up in *any* application area that is > in transition between RS232 and USB. There are lots of those, and > there are going to be more. On Fri, Sep 10, 2004 at 03:54:48PM -0700, Michael Bender wrote: > Eric, > I think that it was a bone-headed move on the part of the USB > standards body to not create a serial class, so that we have this > proliferation of vendor-specific serial USB devices and drivers. Right. There is no standardized way to represent a RS232 interface via USB. The usb-serial kernel driver supports many of these vendor-specific implementations. There is a USB Communications Class, but it standardizes the actual modem or terminal adapter rather than the legacy port. The USB approach to your problem is to create a UPS class and a GPS class. powerd and gpsd would then use libusb to communicate with the devices. (Some HID UPS stuff exists already, as mentioned by someone else.) On Fri, Sep 10, 2004 at 07:44:29PM -0400, Eric S. Raymond wrote: > Having two code paths in this circumstance, one that goes through > termios and one that goes through device-dependent USB stuff, is > just silly. I agree completely. Any USB code path should only be class-depenent. But for vendor classes the code path will be vendor- and vendor class-dependent, effectively making it almost device-dependent. > More generally, one of the design achievements of Unix is to > unify all streamlike interfaces around the file descriptor and > all devices into a unified file name space. Yup. USB doesn't fit very well into that model, though. > If libusb doesn't support this (at least up to the level of > supporting the normal Unixlike stream operations on > devices for which they make sense) then I can only conclude that > libusb is broken as designed. If the kernel provides the (/dev) interface, libusb is useless. > > If so, I think first off it's a bug in the Linux implementation > > that an fd associated with a USB device responds to termios > > ioctls - are you absolutely sure that the fd that's floating > > around in the guts of the Linux implementation of libusb is the > > fd that you want to use to issue termios ioctls to? > > In the case of a serial-to-USB device, is there anything else > it could reasonably be? There's no way to know that a device is serial-to-USB if it isn't supported by usb-serial. :( > Your group is free to dismiss these issues as red herrings, but if you > do that I'm equally free to dismiss your group as a bunch of wankers > and libusb as an essentially pointless exercise in API proliferation. > We might both be right, or might both be wrong, Selah. > > Take my problem seriously and I'll take you seriously. Or not. > Your choice. I hope you feel that I have taken your problem seriously, and that this longish mail provided some insight in spite of the many repetitive comments. Please also note that I am in no way especially authoritative for the libusb project. I'm just a happy user making some observations. //Peter |