Re: Forcing a USB device to "ugen"

2024-03-26 Thread Manuel Bouyer
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"

2024-03-26 Thread Martin Husemann
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"

2024-03-26 Thread Brad Spencer
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"

2024-03-26 Thread Robert Swindells


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"

2024-03-26 Thread Brad Spencer
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"

2024-03-26 Thread Jason Thorpe


> 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"

2024-03-26 Thread Jason Thorpe


> 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"

2024-03-26 Thread Brian Buhrow
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"

2024-03-26 Thread Brad Spencer
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"

2024-03-26 Thread Brad Spencer
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"

2024-03-26 Thread Jason Thorpe


> 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"

2024-03-26 Thread Jason Thorpe


> 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"

2024-03-26 Thread 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.



Re: Forcing a USB device to "ugen"

2024-03-26 Thread Jason Thorpe


> 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"

2024-03-26 Thread Taylor R Campbell
> 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.