Page MenuHomeFreeBSD

Add USB support for location based device unit numbers
Needs ReviewPublic

Authored by hselasky on Oct 3 2019, 12:02 PM.

Details

Summary

Add USB support for location based device unit numbers.

Sponsored by: Mellanox Technologies

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Skipped
Unit
Unit Tests Skipped
Build Status
Buildable 26847

Event Timeline

Fix bug in uniq number compuation. Controller number must be last.

Unit numbers are kinda lame. Wouldn't it be better to add aliases?

@imp: We can have both if the TTY layers support it.

Could you implement a tty_makedevalias() function ?

At least with this patch the sysctls are coherent, pointing to only one device.

There is people who expect the first serial device they plug-in to be ttyU0 (me for example) and there are people who would prefer the unit number to stay the same independent of the order the devices are detected (me as well).

I would prefer aliases as well, so we can have both. I didn't check whether it actually is a match to your problem, but how about tty_makealias() in sys/tty.h?

sys/tty.h-int tty_makedevf(struct tty *tp, struct ucred *cred, int flags,
sys/tty.h- const char *fmt, ...) printflike(4, 5);
sys/tty.h-#define TTYMK_CLONING 0x1
sys/tty.h-#define tty_makedev(tp, cred, fmt, ...) \
sys/tty.h- (void )tty_makedevf((tp), (cred), 0, (fmt), __VA_ARGS__) sys/tty.h:#define tty_makealias(tp,fmt,...) \ sys/tty.h- make_dev_alias((tp)->t_dev, fmt,
VA_ARGS__)
sys/tty.h-
sys/tty.h-/* Signalling processes. */
sys/tty.h-void tty_signal_sessleader(struct tty *tp, int signal);
sys/tty.h-void tty_signal_pgrp(struct tty *tp, int signal);

I do remember from way back talks about naming schemes for USB devices in the USB device tree, something like usb-1-3-2 being a device plugged into port 2 of a hub that is plugged into port 3 of a hub plugged into port 1 of the root hub.

There is people who expect the first serial device they plug-in to be ttyU0 (me for example) and there are people who would prefer the unit number to stay the same independent of the order the devices are detected (me as well).

I would prefer aliases as well, so we can have both. I didn't check whether it actually is a match to your problem, but how about tty_makealias() in sys/tty.h?

sys/tty.h-int tty_makedevf(struct tty *tp, struct ucred *cred, int flags,
sys/tty.h- const char *fmt, ...) printflike(4, 5);
sys/tty.h-#define TTYMK_CLONING 0x1
sys/tty.h-#define tty_makedev(tp, cred, fmt, ...) \
sys/tty.h- (void )tty_makedevf((tp), (cred), 0, (fmt), __VA_ARGS__) sys/tty.h:#define tty_makealias(tp,fmt,...) \ sys/tty.h- make_dev_alias((tp)->t_dev, fmt,
VA_ARGS__)
sys/tty.h-
sys/tty.h-/* Signalling processes. */
sys/tty.h-void tty_signal_sessleader(struct tty *tp, int signal);
sys/tty.h-void tty_signal_pgrp(struct tty *tp, int signal);

I do remember from way back talks about naming schemes for USB devices in the USB device tree, something like usb-1-3-2 being a device plugged into port 2 of a hub that is plugged into port 3 of a hub plugged into port 1 of the root hub.

I'd prefer the alias stuff as well. I think we have what we need, but if not I'm happy to fix things that are broken.

There's a number of different ways to have the aliases setup, and at times code in ucom will be the answer, and other times code in devfs and/or devd might be better. The whole device_t vs dev_t stuff will get in the way here, I fear...

Why is this needed at all? What's the motivation?

@avg: It is needed for embedded, where for example tree USB modems control different things and you have apps that should connect to the same modem after boot.

I see.
I think that the problem can be solved quite easily with devd, but maybe it's not good for embedded solutions.
Also, I am not sure how stable the unit numbers are going to be with respect to add-in USB controllers and external USB hubs.

I do not have any objections.

My use case for something like this is a USB-serial console server where I might have 16 different USB-serial adapters attached to various USB hubs; I intended to address it by using the serial number in each device.

@hselasky can you give an example of the unit numbers that would be generated by this patch?

My use case for something like this is a USB-serial console server where I might have 16 different USB-serial adapters attached to various USB hubs; I intended to address it by using the serial number in each device.

Yes, I am doing something like that now.

attach 1001 {
        match "vendor"          "0x12d1";
        match "product"         "0x1506";
        action "ln -sf /dev/cua$ttyname.0 /dev/3g";
};

notify 1001 {
        match "system"          "USB";
        match "subsystem"       "DEVICE";
        match "type"            "DETACH";
        match "vendor"          "0x12d1";
        match "product"         "0x1506";
        action "unlink /dev/3g";
};

attach 1001 {
        match "vendor"          "0x2341";
        match "product"         "0x0043";
        action "ln -sf /dev/cua$ttyname /dev/arduino";
};

notify 1001 {
        match "system"          "USB";
        match "subsystem"       "DEVICE";
        match "type"            "DETACH";
        match "vendor"          "0x2341";
        match "product"         "0x0043";
        action "unlink /dev/arduino";
};

Requires manual configuration though.
At the same time, it's quite flexible.
Of course, totally identical devices (down to serial numbers) can still cause confusion.

Of course, totally identical devices (down to serial numbers) can still cause confusion.

Indeed; most of the cheap USB-serial adapters (e.g. the ones available on aliexpress.com for about $1 USD) have the same (often empty) serial number. I found that the cp210x devices can be reprogrammed. https://github.com/emaste/cp210x-cfg is my trivial FreeBSD port of a configuration tool I use to give them unique serial numbers.

I took Daniel O'Connor's script from: https://www.mail-archive.com/freebsd-usb@freebsd.org/msg14258.html

and did a minor improvement to support creating a USB path via the hub ports, and have this script now:
https://www.funkthat.com/~jmg/FreeBSD/usbserialsn

It creates symlinks for devices:
freebsd@generic:~ $ ls -l /dev/*.usb.2.* /dev/*370*
lrwxr-xr-x 1 root wheel 5 Jun 6 22:40 /dev/cu.XXX370XXXXXX -> cuaU4
lrwxr-xr-x 1 root wheel 5 Jun 6 22:20 /dev/cu.usb.2.1.1 -> cuaU1
lrwxr-xr-x 1 root wheel 5 Jun 6 22:32 /dev/cu.usb.2.1.3 -> cuaU0
lrwxr-xr-x 1 root wheel 5 Jun 6 22:32 /dev/cu.usb.2.1.4.1.4 -> cuaU2
lrwxr-xr-x 1 root wheel 5 Jun 6 22:40 /dev/tty.XXX370XXXXXX -> ttyU4
lrwxr-xr-x 1 root wheel 5 Jun 6 22:20 /dev/tty.usb.2.1.1 -> ttyU1
lrwxr-xr-x 1 root wheel 5 Jun 6 22:32 /dev/tty.usb.2.1.3 -> ttyU0
lrwxr-xr-x 1 root wheel 5 Jun 6 22:32 /dev/tty.usb.2.1.4.1.4 -> ttyU2

Cool script. It would be better to add the alias with devfs. Then it would disappear w/o devd needing all the info...

In D21886#554614, @imp wrote:

Cool script. It would be better to add the alias with devfs. Then it would disappear w/o devd needing all the info...

How do you propose to do it? It looks like devfs.conf is the only part of devfs that supports link, and that is done via /etc/rc.d/devfs on boot. devfs.rules and devfs do not have the option to specify links.

I've been using this script for about a week, and it does exactly what it says on the tin.
Since devfs.conf only gets read on boot, I think handling this script via devd is the perfect way to handle devices that can disappear and reappear.

Would be fantastic if it could be merged, others can enjoy it. :)

I've been using this script for about a week, and it does exactly what it says on the tin.
Since devfs.conf only gets read on boot, I think handling this script via devd is the perfect way to handle devices that can disappear and reappear.

Would be fantastic if it could be merged, others can enjoy it. :)

Are you using this patch or script?

I've been using this script for about a week, and it does exactly what it says on the tin.
Since devfs.conf only gets read on boot, I think handling this script via devd is the perfect way to handle devices that can disappear and reappear.

Would be fantastic if it could be merged, others can enjoy it. :)

Are you using this patch or script?

Yes, I'm using the script jmg@ modified - it works exactly as I would expect it to:

ls -l /dev/tty.* /dev/cu.*
lrwxr-xr-x  1 root  wheel  5 Jun 12 12:54 /dev/cu.A0AC1F827C641630 -> cuaU2
lrwxr-xr-x  1 root  wheel  5 Jun 12 12:54 /dev/tty.A0AC1F827C641630 -> ttyU2

Hello world :-) +1 and thank you for this unique tty/cua with USBSERIAL in node name :-) Also thank you for the hints for DEVD :-) Highly demanded in complex embedded systems and electronics testing scenarios :-)

FYI, I wasn't aware of this but there was more to do to conner's script; I have a 4-port USB-serial dongle (1 USB, 4 cuaU*)..
I had put it onto the wiki the other day https://wiki.freebsd.org/BjoernZeeb/USBSerialConsole

rpokala added inline comments.
sys/dev/usb/serial/usb_serial.c
306

location isn't a variable in this function; did you mean ssc->sc_unit?