USB serial gadget not working on TX1

Has anyone managed to get the USB serial gadget working on a TX1 (i.e. the jetson tx1 is a serial device over USB to some host PC)? I’ve followed the instructions in kernel/Documentation/usb/gadget_serial.txt. I’ve built the kernel with

CONFIG_USB_G_SERIAL=m

which also changed

CONFIG_USB_F_ACM=m
CONFIG_USB_U_SERIAL=m
CONFIG_USB_F_SERIAL=m
CONFIG_USB_F_OBEX=m

after some tries, I also enabled

CONFIG_USB_GADGET_DEBUG=y
CONFIG_USB_GADGET_DEBUG_FILES=y

After booting I use

sudo modprobe g_serial

Things look somewhat OK from the tegra side:

user@jetson9:~$ dmesg | grep otg
[    2.681184] tegra-otg tegra-otg: otg transceiver registered
[    7.136490] port_otg: yes
[    7.373452] otg state changed: SUSPEND --> PERIPHERAL
user@jetson9:~$ dmesg | grep g_serial
[   11.688974] udc tegra-udc.0: registering UDC driver [g_serial]
[   11.702343] g_serial gadget: adding 'acm'/ffffffc0fd0dbc00 to config 'CDC ACM config'/ffffffbffc02c480
[   11.702362] g_serial gadget: acm ttyGS0: dual speed IN/ep1in OUT/ep1out NOTIFY/ep2in
[   11.702376] g_serial gadget: Gadget Serial v2.4
[   11.702382] g_serial gadget: g_serial ready
[   11.702401] tegra-udc: bind to driver g_serial

however the host side doesn’t seem to see the device at all. I don’t see any messages in syslog regarding connection of a new usb device, and I don’t see anything show up with lsusb. There is no device at /dev/ttyUSB0, which is what I was expecting.

Has anyone gotten this to work on the TX1?

The gadget interface is just a stub or framework, you still have to create code which the interface uses in place of an actual device. E.G., there is also support for a mass storage gadget, but it won’t make the system hard drive appear as a USB hard disk if you don’t write or configure code to cause that behavior.

Also, the micro-USB port could have software written to autodetect whether a type A (behave as host) or type B (behave as device) connector is inserted, but this has not been written. The default for that port is host mode. Unless the Jetson is in recovery mode (not what you want for this purpose) or you manually set to device mode, it won’t be a device.

For a typical way to go to or from host or device mode you might use these aliases:

# list mode:
alias otg='egrep '[01]' /sys/devices/platform/tegra-otg/enable_*'
# set host mode:
alias otgdev='echo 0 > /sys/devices/platform/tegra-otg/enable_host ;\
   echo 1 > /sys/devices/platform/tegra-otg/enable_device ;\
   egrep '[01]' /sys/devices/platform/tegra-otg/enable_*'
# set device mode:
alias otghost='echo 0 > /sys/devices/platform/tegra-otg/enable_device ;\
   echo 1 > /sys/devices/platform/tegra-otg/enable_host ;\
   egrep '[01]' /sys/devices/platform/tegra-otg/enable_*'

So a big question is what kind of serial device do you want the Jetson to become in device mode? You’ll have some work to put that in place.

Thanks for the input. While I think that the uvc gadget interface is a stub, the serial gadget module seems to be complete, based on the kernel documentation. There’s also plenty of results for the RasPI, CHIP, and other embedded systems that seem to corroborate that the serial gadget module is fully functional. You might be right, but gadget/serial.c seems to be fully implemented.

Also those “enable_host” and “enable_device” files don’t exist on the tx1 (they did on the tk1). From tegra-otg.c

tegra = tegra_clone;
	if (!tegra->support_usb_id && !tegra->support_pmu_id) {
		err = device_create_file(&pdev->dev, &dev_attr_enable_host);
		if (err) {
			dev_warn(&pdev->dev,
				"Can't register host-sysfs attribute\n");
			goto err;
		}
		err = device_create_file(&pdev->dev, &dev_attr_enable_device);
		if (err) {
			dev_warn(&pdev->dev,
				"Can't register device-sysfs attribute\n");
			device_remove_file(&pdev->dev, &dev_attr_enable_host);
			goto err;
		}
	}

Also note the log messages I posted above, which seems to indicate that the otg driver is changing state to ‘peripheral’ mode on it’s own.

What is the serial data source? How does the gadget know to find this data?

The g_serial module creates /dev/ttyGS0, and it appears that on the “device (tx1)” side you can treat that like any other serial. I tried running getty on that device.

/sbin/getty -a <user> -L 115200 ttyGS0

I also tried simply catting data to it like they did in this tutorial for the amadeus board. Here’salso a (rather opaque) tutorial on running getty through the serial gadget on the RasPI.

I hadn’t noticed that before, but you’re right about the /sys files. dmesg even indicates plugging in a type-B micro-USB cable to an outside host, or a type-A micro-USB cable and correctly switching mode (currently using R24.1, don’t know what differences there may be with R23.2).

Sometimes failures of serial USB are just a permissions issue. What are the permissions of “/dev/ttyGS0”?

Also, I don’t know if ttyGS0 would go away when a micro-B cable is not inserted, but in case ttyGS0’s existence does not depend on inserted cable type, are you sure your cable is type-B? Most of the cables on the market (including the supplied cable for flash) are type-B, so odds are high that the cable is correct, it’s just a case of being thorough.

What is the output of “sudo setserial -a /dev/ttyGS0”?

/dev/ttyGS0 is owned by root. When I ran getty and when I tried to pipe data into/out of the device I did so as root.

When I remove the micro USB cable, the device /dev/ttyGS0 stays present. I do see kernel log output along the lines of “otg state changed: SUSPEND → PERIPHERAL” and “otg state changed: PERIPHERAL → SUSPEND” when plugging and unplugging the usb cable.

I’ve got another kernel build on my test machine right now that doesn’t have the g_serial module but I will reply again with output of “setserial -a /dev/ttyGS0” soon.