Re: Forcing a USB device to "ugen"
> Date: Tue, 26 Mar 2024 17:41:52 -0400 > From: Thor Lancelot Simon > > On Tue, Mar 26, 2024 at 12:25:07AM +, Taylor R Campbell wrote: > > > > We should really expose a /dev/ugen* instance for _every_ USB device; > > those that have kernel drivers attached have only limited access via > > /dev/ugen* (no reads, writes, transfer ioctls, &c.), until you do > > ioctl(USB_KICK_OUT_KERNEL_DRIVER) or whatever, at which point the > > kernel driver will detach and the user program can take over instead > > and use the full ugen(4) API. > > I don't think this can be safely allowed at security level > 0, unless, > perhaps, it's restricted from working on devices that would match disk > drivers. ioctl(USB_KICK_OUT_KERNEL_DRIVER) would attempt to detach the driver without DETACH_FORCE, so disk devices with file systems mounted would simply decline and the ioctl would fail.
Re: Forcing a USB device to "ugen"
> On Mar 26, 2024, at 2:41 PM, Thor Lancelot Simon wrote: > > I don't think this can be safely allowed at security level > 0, unless, > perhaps, it's restricted from working on devices that would match disk > drivers. The driver being asked to detach could certainly refuse to do so based on why it’s being asked. -- thorpej
Re: Forcing a USB device to "ugen"
On Tue, Mar 26, 2024 at 12:25:07AM +, Taylor R Campbell wrote: > > We should really expose a /dev/ugen* instance for _every_ USB device; > those that have kernel drivers attached have only limited access via > /dev/ugen* (no reads, writes, transfer ioctls, &c.), until you do > ioctl(USB_KICK_OUT_KERNEL_DRIVER) or whatever, at which point the > kernel driver will detach and the user program can take over instead > and use the full ugen(4) API. I don't think this can be safely allowed at security level > 0, unless, perhaps, it's restricted from working on devices that would match disk drivers.
Re: Forcing a USB device to "ugen"
> On Mar 26, 2024, at 10:18 AM, Jason Thorpe wrote: > > Like I said in a previous message on this thread, I think the better model is > for ugen to always exist for every USB device / interface, and for the kernel > driver to attach there. Then it’s easy to just say “detach whatever kernel > driver is here [assuming it’s not busy providing some other service] so that > user-space can take over”, and “re-attach any kernel driver that might match > this device now that I’m done”. I guess I should explicitly state the other part of this, which is “and anything other than totally benign control pipe transfers without having CLAIM’d the device/interface must return EBUSY”. It’s the act of CLAIM’ing the device/interface that detaches the kernel driver and the act of RELEASE’ing it that causes the kernel to attempt to re-attach one. -- thorpej
Re: Forcing a USB device to "ugen"
> On Mar 26, 2024, at 9:31 AM, Brian Buhrow wrote: > > Isn't it possible to do most of what Jason proposes by using the drvctl > interface to > detach a driver from a specific USB device? Then, some glue could be added > to the ugen driver > to allow it to be attached to arbitrary devices using the same drvctl > interface? That seems a > lot easier to me than building a registry of devices and device IDs, which > will be woefully > out of date before it gets published. It also has the advantage of allowing > the user to do > creative stuff that the developers didn't think of. Am I missing something > obvious? It’s absolutely not easier, because there’s not really an easy way, once the kernel driver is detached, to say “attach ugen where that other thing was, AND ONLY THERE”. Like I said in a previous message on this thread, I think the better model is for ugen to always exist for every USB device / interface, and for the kernel driver to attach there. Then it’s easy to just say “detach whatever kernel driver is here [assuming it’s not busy providing some other service] so that user-space can take over”, and “re-attach any kernel driver that might match this device now that I’m done”. -- thorpej
Re: Forcing a USB device to "ugen"
Brian Buhrow writes: > Isn't it possible to do most of what Jason proposes by using the drvctl > interface to > detach a driver from a specific USB device? Then, some glue could be added > to the ugen driver > to allow it to be attached to arbitrary devices using the same drvctl > interface? That seems a > lot easier to me than building a registry of devices and device IDs, which > will be woefully > out of date before it gets published. It also has the advantage of allowing > the user to do > creative stuff that the developers didn't think of. Am I missing something > obvious? > > -thanks > -Brian I don't think that the detach part is a problem, but the second part is murky. The only thing I know of that can do the second part is a rescan call against the USB bus. Unless the ugen driver is allowed to have a higher priority than the specific device driver, the specific wins during the rescan of the USB bus. The use of ugenif was mentioned, and this is a way to do the "make ugen have a higher priority" game, but ugenif requires a custom kernel. See the ugen man page for the hint on how to use ugenif. There is the concept of tags that can be passed in a rescan, but to use those effectively for this problem is messy. You may end up having to put the "detect that ugen has a high priority" in every driver or at the very least the [uoevx]hci drivers and even then, it isn't tied to a specific device really, just the concept of "on this rescan, have ugen take priority" and ANY device found would get ugen. Jason's notion of using ugen as a bus instead of a leaf has merit and may be the better approach. The devil will be in the details, however. -- Brad Spencer - b...@anduin.eldar.org - KC8VKS - http://anduin.eldar.org
Re: Forcing a USB device to "ugen"
Jason Thorpe writes: [snip] >> What would be wrong with attaching an ugen to interface 1 instead of >> an ucom in the ftdi driver itself? > > ugen can’t currently attach to things other than uhub. I think attaching > ugen as the leaf is the wrong model, though; ugen should be what the kernel > drivers themselves attach to, IMO. This would probably make it very possible to have a USBIP server. For that, you need to more or less be able to do ugen against any physically present USB device, without the specific device drivers getting in the way. Even if you had to detach the specific driver, to get ugen exposed that would be ok, even better if you didn't have to do that, of course... According to the man page for ugen there is a way to compile a kernel such that ugen takes priority over the specific driver, but that is more than a little clunky in the USBIP server case. This is the ugenif case that was mentioned before. > -- thorpej -- Brad Spencer - b...@anduin.eldar.org - KC8VKS - http://anduin.eldar.org
Re: Forcing a USB device to "ugen"
Isn't it possible to do most of what Jason proposes by using the drvctl interface to detach a driver from a specific USB device? Then, some glue could be added to the ugen driver to allow it to be attached to arbitrary devices using the same drvctl interface? That seems a lot easier to me than building a registry of devices and device IDs, which will be woefully out of date before it gets published. It also has the advantage of allowing the user to do creative stuff that the developers didn't think of. Am I missing something obvious? -thanks -Brian
Re: Forcing a USB device to "ugen"
> On Mar 26, 2024, at 5:37 AM, Robert Swindells wrote: > > I thought that all FTDI devices provided JTAG etc. functionality, just > that the pins are not connected to anything in some devices. I guess it depends on how your individual FTDI board is wired up. Also, for chips without the MPSSE, you need something else. OpenOCD supports JTAG over the FT232R, for example, by bit-banging with the various RS232 signals (RXD, TXD, RTS, CTS, DTR, DCD). Anyway, as I noted in my original email, my particular board has one of the 2232 interfaces intended for use as a UART (and connected to a header that labels it for that purpose), and the second interface brought out two 4 different headers labeled for JTAG, SWD, SPI, and I2C. > What would be wrong with attaching an ugen to interface 1 instead of > an ucom in the ftdi driver itself? ugen can’t currently attach to things other than uhub. I think attaching ugen as the leaf is the wrong model, though; ugen should be what the kernel drivers themselves attach to, IMO. -- thorpej
Re: Forcing a USB device to "ugen"
> On Mar 26, 2024, at 2:49 AM, Martin Husemann wrote: > It is also not *that* intrusive as it may sound at first look: > basically we need a central registry that collects all the > identification data (vid,pid,strings and what have you) plus the parent > and the device pointer, and a flag if this is a device claimed by some > driver or one of the currently visible ugen* things. I was thinking about this while sipping my first cup of coffee this morning.. I think the right model is for a “ugen” or what-have-you attach to uhub, and then for the kernel drivers to attach to ugen (either claim the whole device or attach to individual interfaces). -- thorpej
Re: Forcing a USB device to "ugen"
Robert Swindells writes: > Jason Thorpe wrote: >> I have a device based on the FTDI FT2232C: >> >> [ 3285.311079] uftdi1 at uhub1 port 2 configuration 1 interface 0 >> [ 3285.311079] uftdi1: SecuringHardware.com (0x0403) Tigard V1.1 >> (0x6010), rev 2.00/7.00, addr 3 >> [ 3285.311079] ucom1 at uftdi1 portno 1 >> [ 3285.311079] uftdi2 at uhub1 port 2 configuration 1 interface 1 >> [ 3285.311079] uftdi2: SecuringHardware.com (0x0403) Tigard V1.1 >> (0x6010), rev 2.00/7.00, addr 3 >> [ 3285.311079] ucom2 at uftdi2 portno 2 >> >> It's a combo device that, in addition to a standard TTL-level UART, >> has a bunch of break-out headers for doing things like SPI, SWD, and >> JTAG (in my case, I need to use JTAG for programming some Atmel >> CPLDs). I should be able to do this with OpenOCD >> (pkgsrc/devel/openocd), but libfdti1 fails to find the device because >> libusb1 only deals in "ugen". > > I thought that all FTDI devices provided JTAG etc. functionality, just > that the pins are not connected to anything in some devices. I believe that only the ones with the more advanced engine design can do JTAG (I think that uses the BITBANG mode, which is yet another mode along side UART and MPSSE, but I don't exactly remember). FTDI makes a lot of chip types, and some of them are only UART. > What would be wrong with attaching an ugen to interface 1 instead of > an ucom in the ftdi driver itself? In the FT4232 chip, for example, there are two MPSSE engines attached to two of the four ports and 4 distinct ports total (the FT2232 has two MPSSE engines and two ports total, and the FT232H has one MPSSE engine and two ports, but they are 16 bits and not the usual 8 bits that the others have). On the FT4232, the two MPSSE engines can program their respective ports to be I2C, SPI, GPIO and etc.. and support a BITBANG mode that can also be used for GPIO and etc... They also support the usual UART mode on a port. The two ports that don't have the MPSSE engine can do the UART and BITBANG mode. In general, the chip is more complicated then simply setting a specific interface to something or other. There probably should be a userland utility or a plist file somewhere that tells uftdi what you want a particular interface / port to be. It is entirely reasonable to want to change the personality without a reboot from userland. A detach / reattach is acceptable. -- Brad Spencer - b...@anduin.eldar.org - KC8VKS - http://anduin.eldar.org
Re: Forcing a USB device to "ugen"
Jason Thorpe wrote: > I have a device based on the FTDI FT2232C: > > [ 3285.311079] uftdi1 at uhub1 port 2 configuration 1 interface 0 > [ 3285.311079] uftdi1: SecuringHardware.com (0x0403) Tigard V1.1 > (0x6010), rev 2.00/7.00, addr 3 > [ 3285.311079] ucom1 at uftdi1 portno 1 > [ 3285.311079] uftdi2 at uhub1 port 2 configuration 1 interface 1 > [ 3285.311079] uftdi2: SecuringHardware.com (0x0403) Tigard V1.1 > (0x6010), rev 2.00/7.00, addr 3 > [ 3285.311079] ucom2 at uftdi2 portno 2 > > It's a combo device that, in addition to a standard TTL-level UART, > has a bunch of break-out headers for doing things like SPI, SWD, and > JTAG (in my case, I need to use JTAG for programming some Atmel > CPLDs). I should be able to do this with OpenOCD > (pkgsrc/devel/openocd), but libfdti1 fails to find the device because > libusb1 only deals in "ugen". I thought that all FTDI devices provided JTAG etc. functionality, just that the pins are not connected to anything in some devices. What would be wrong with attaching an ugen to interface 1 instead of an ucom in the ftdi driver itself?
Re: Forcing a USB device to "ugen"
Jason Thorpe writes: > I have a device based on the FTDI FT2232C: > > [ 3285.311079] uftdi1 at uhub1 port 2 configuration 1 interface 0 > [ 3285.311079] uftdi1: SecuringHardware.com (0x0403) Tigard V1.1 > (0x6010), rev 2.00/7.00, addr 3 > [ 3285.311079] ucom1 at uftdi1 portno 1 > [ 3285.311079] uftdi2 at uhub1 port 2 configuration 1 interface 1 > [ 3285.311079] uftdi2: SecuringHardware.com (0x0403) Tigard V1.1 > (0x6010), rev 2.00/7.00, addr 3 > [ 3285.311079] ucom2 at uftdi2 portno 2 > > It's a combo device that, in addition to a standard TTL-level UART, has a > bunch of break-out headers for doing things like SPI, SWD, and JTAG (in my > case, I need to use JTAG for programming some Atmel CPLDs). I should be able > to do this with OpenOCD (pkgsrc/devel/openocd), but libfdti1 fails to find > the device because libusb1 only deals in "ugen". > > "ugenif" might have been a possible solution here, except for the fact that > 0x0403,0x6010 is the standard VID,PID for the FTDI FT2232C, and I don't want > "interface 1" of ALL FT2232C devices to get the "ugen" treatment. The desire > to use "ugen" on "interface 1" is not a property of 0x0403,0x6010, it's > really a property of "SecuringHardware.com","Tigard V1.1". Unfortunately, > there's isn't a way to express that in the kernel config syntax. > > I think my only short-term option here is to, in uftdi_match(), specifically > reject based on this criteria: > > - VID == 0x0403 > - PID == 0x6010 > - interface number == 1 > - vendor string == "SecuringHardware.com" > - product string == "Tigard V1.1" > > (It's never useful, on this particular board, to use the second port as a > UART.) > > -- thorpej [going a little off topic, but maybe this fills in some blanks about that chip] The FT2232 and its buddies the FT4232 and FT232H are nice chips. They are also polymorphic in that there is at least one or more engines in the chip called the MPSSE that can program the pins to support any number of different sorts of things such as I2C, SPI, and simple GPIO (and others) in addition to a mode that is the usual FTDI UART (at the very least, some of the chips support other UART modes). The chip always identifies itself as a FTwhatever, however, and you can't use that as the basis for what you want the pins to do and in some cases you can have a usual FTDI UART plus a I2C bus (for example) at the same time because there is more than one MPSSE engine present. I have samples of all of the chips, and some interest in supporting the polymorphic behavior, but no particular time to do the work. My personal main goal would be to allow any system with a USB port the ability to have I2C, probably SPI and simple GPIO. -- Brad Spencer - b...@anduin.eldar.org - KC8VKS - http://anduin.eldar.org
Re: Forcing a USB device to "ugen"
On Tue, Mar 26, 2024 at 09:09:57AM +0100, Manuel Bouyer wrote: > On Tue, Mar 26, 2024 at 12:25:07AM +, Taylor R Campbell wrote: > > This is how it works in other systems like Linux with > > USBDEVFS_CLAIMINTERFACE, and that's the model that libusb is built > > around. It's a nontrivial change to our USB stack requiring some care > > to get right, but this is far and away the biggest shortcoming of our > > USB stack and we should unquestionably do it. > > Strongly seconded. Yes! It is also not *that* intrusive as it may sound at first look: basically we need a central registry that collects all the identification data (vid,pid,strings and what have you) plus the parent and the device pointer, and a flag if this is a device claimed by some driver or one of the currently visible ugen* things. Due to this being USB we already have detach support everywhere, and only need a bit of additional glue. Martin
Re: Forcing a USB device to "ugen"
On Tue, Mar 26, 2024 at 12:25:07AM +, Taylor R Campbell wrote: > > Date: Mon, 25 Mar 2024 19:47:31 -0400 > > From: Greg Troxel > > > > Jason Thorpe writes: > > > > > I should be able to do this with OpenOCD (pkgsrc/devel/openocd), but > > > libfdti1 fails to find the device because libusb1 only deals in > > > "ugen". > > > > Is that fundamental, in that ugen has ioctls that are ugen-ish that > > uftdi does not? I am guessing you thought about fixing libusb1. > > It is possible that we could kludge some horrible hacks into ucom(4) > to pass /dev/ttyU* ioctls through to uftdi(4), but not all USB drivers > even have a /dev node that could be hacked up in that way. Really, > there is a general fundamental limitation with NetBSD's USB stack: > user programs have no way to take over USB devices from kernel > drivers. > > We should really expose a /dev/ugen* instance for _every_ USB device; > those that have kernel drivers attached have only limited access via > /dev/ugen* (no reads, writes, transfer ioctls, &c.), until you do > ioctl(USB_KICK_OUT_KERNEL_DRIVER) or whatever, at which point the > kernel driver will detach and the user program can take over instead > and use the full ugen(4) API. > > This is how it works in other systems like Linux with > USBDEVFS_CLAIMINTERFACE, and that's the model that libusb is built > around. It's a nontrivial change to our USB stack requiring some care > to get right, but this is far and away the biggest shortcoming of our > USB stack and we should unquestionably do it. Strongly seconded. -- Manuel Bouyer NetBSD: 26 ans d'experience feront toujours la difference --
Re: Forcing a USB device to "ugen"
> Date: Mon, 25 Mar 2024 19:47:31 -0400 > From: Greg Troxel > > Jason Thorpe writes: > > > I should be able to do this with OpenOCD (pkgsrc/devel/openocd), but > > libfdti1 fails to find the device because libusb1 only deals in > > "ugen". > > Is that fundamental, in that ugen has ioctls that are ugen-ish that > uftdi does not? I am guessing you thought about fixing libusb1. It is possible that we could kludge some horrible hacks into ucom(4) to pass /dev/ttyU* ioctls through to uftdi(4), but not all USB drivers even have a /dev node that could be hacked up in that way. Really, there is a general fundamental limitation with NetBSD's USB stack: user programs have no way to take over USB devices from kernel drivers. We should really expose a /dev/ugen* instance for _every_ USB device; those that have kernel drivers attached have only limited access via /dev/ugen* (no reads, writes, transfer ioctls, &c.), until you do ioctl(USB_KICK_OUT_KERNEL_DRIVER) or whatever, at which point the kernel driver will detach and the user program can take over instead and use the full ugen(4) API. This is how it works in other systems like Linux with USBDEVFS_CLAIMINTERFACE, and that's the model that libusb is built around. It's a nontrivial change to our USB stack requiring some care to get right, but this is far and away the biggest shortcoming of our USB stack and we should unquestionably do it.
Re: Forcing a USB device to "ugen"
Jason Thorpe writes: > I should be able to do this with OpenOCD (pkgsrc/devel/openocd), but > libfdti1 fails to find the device because libusb1 only deals in > "ugen". Is that fundamental, in that ugen has ioctls that are ugen-ish that uftdi does not? I am guessing you thought about fixing libusb1. > The desire to use "ugen" on "interface 1" is not a property of > 0x0403,0x6010, it's really a property of > "SecuringHardware.com","Tigard V1.1". Unfortunately, there's isn't a > way to express that in the kernel config syntax. > > I think my only short-term option here is to, in uftdi_match(), specifically > reject based on this criteria: > > - VID == 0x0403 > - PID == 0x6010 > - interface number == 1 > - vendor string == "SecuringHardware.com" > - product string == "Tigard V1.1" > > (It's never useful, on this particular board, to use the second port as a > UART.) That seems reasonable to me. It seems pretty unlikely to break other things.
Forcing a USB device to "ugen"
I have a device based on the FTDI FT2232C: [ 3285.311079] uftdi1 at uhub1 port 2 configuration 1 interface 0 [ 3285.311079] uftdi1: SecuringHardware.com (0x0403) Tigard V1.1 (0x6010), rev 2.00/7.00, addr 3 [ 3285.311079] ucom1 at uftdi1 portno 1 [ 3285.311079] uftdi2 at uhub1 port 2 configuration 1 interface 1 [ 3285.311079] uftdi2: SecuringHardware.com (0x0403) Tigard V1.1 (0x6010), rev 2.00/7.00, addr 3 [ 3285.311079] ucom2 at uftdi2 portno 2 It's a combo device that, in addition to a standard TTL-level UART, has a bunch of break-out headers for doing things like SPI, SWD, and JTAG (in my case, I need to use JTAG for programming some Atmel CPLDs). I should be able to do this with OpenOCD (pkgsrc/devel/openocd), but libfdti1 fails to find the device because libusb1 only deals in "ugen". "ugenif" might have been a possible solution here, except for the fact that 0x0403,0x6010 is the standard VID,PID for the FTDI FT2232C, and I don't want "interface 1" of ALL FT2232C devices to get the "ugen" treatment. The desire to use "ugen" on "interface 1" is not a property of 0x0403,0x6010, it's really a property of "SecuringHardware.com","Tigard V1.1". Unfortunately, there's isn't a way to express that in the kernel config syntax. I think my only short-term option here is to, in uftdi_match(), specifically reject based on this criteria: - VID == 0x0403 - PID == 0x6010 - interface number == 1 - vendor string == "SecuringHardware.com" - product string == "Tigard V1.1" (It's never useful, on this particular board, to use the second port as a UART.) -- thorpej