Does USB Peripheral Mode work under Debian, Buster-359?

Flashed with Android-99 the DragonBoard 410c appears to behave as I would expect with regards to USB Host and peripheral mode. No connection to the microUSB connector and the USB is configured as a Host and the two hub connectors work with mouse and keyboard. When the micro-usb is connected, the 5V from the host (level shifted) is detected on an IO line on the DragonBoard MPU and the usb controller is reconfigured as a peripheral, which can be enumerated by the host.

When the micro-usb is disconnected, the process reverses, and the mouse and keyboard become active again.

When Debian (Buster, 359) is loaded, either using the SD Development image or the SD Install image, the system appears to be fixed in host mode only. Although Gadget support appears to be configured in the kernel, no UDC is shown in /sys/class/udc, so loading libcomposite and setting up a Gadget using configfs has no effect.

I don’t see any activity in the SysLog when I plug and unplug the Micro USB cable either, which I assume means that there is no module akin to dcw2 monitoring OTG_SENSE (or, in this case, the 5V being present, not the actual sense connection on the connector). But it is not clear to me what that driver should be for this build.

I’m sorry if this is a remedial question, but when I searched this forum and others, most people where just confused that there is a single USB controller, so the connectors are mutually exclusive, but were seeing a switch in their syslogs. There is a similar report to mine from Oct 16 here:

But it doesn’t seem answered/resolved. I was hoping someone could point me in the right direction before I bite the bullet and rebuild the kernel and dive into the driver source.

Thanks in advance!

OTG mode is not supported with last release and snapshots. I’m currently try to upstream a solution, you can find my work at (6 patches on top of qcomlt kernel). Once upstreamed patches will be backported to the QCOMLT kernel and integrated in builds. Meanwhile you can build this kernel yourself. Let me know if it works.

I’ll give it a try over the next few days and let you know the results. Thanks!

Since I posted I installed J15 and spent some time playing with the peripheral blocks more directly (I often find Linux driver stacks a bit confusing, so I tend to start at the HW and work my way up). So it will be interesting to examine your patches.

Thanks again!


I rebuilt the release kernel following the directions here:

The one difference being that I used abootimg instead of mkbootimg (package couldn’t be found). I first took the release fastboot image and broke it apart with abootimg -x, then recreated and tested it to make sure my abootimg params were correct.

I then substituted the file: Image.gz+dtb created in the above instructions for zImage extracted from the release image. That all worked fine.

Next I pulled your “linux” repo and checked out the qcomlt-4.14-usb branch. Everything builds fine, but it hangs when I try to fastboot it on the DragonBoard 410c. So I formatted patches for the last 5 commits, then applied them on debian-qcom-dragonboard410c-18.01, checked out of the release repo above.

That builds and runs, the IO lines and hub reset behavior does toggle with the presence of a microUSB connection, and a udc instance (/sys/class/udc/ci_hdrc.0) is present. No enumeration occurs on the host side, but nothing is yet bound to the udc (as far as I know). I’ll try setting up a gadget when I get another chance to play with this later this week and report the results. Sorry! I thought I had enough time today, but it took me longer to get the kernel building than I expected.

Thanks again!

Great good not know ! a simple test is inserting cdc_ether module (modprobe cdc_ether).

/sbin/modprobe cdc_ether does appear to load the module without error (/sbin/modinfo shows a bunch of aliases and Yes for intree), but no enumeration occurs when the cable is plugged into a host.

I ran make menuconfig on the host and looked at the options. Gadget support is set to yes and ethernet is set to M. So is mass storage, so I made a fat filesystem file and loaded the old g_mass_storage gadget. It also loads without error, but no enumeration.

I looked quickly with our LeCroy USB tracer and it appears that the host sees insertion, but the peripheral controller is not responding. I am traveling for work today and tomorrow, but can dig a little deeper in a few days. It seems that the ChipIdea driver is not switching modes, but that is just a guess.

Just let me know if there is anything else that you want me to try.


Note: I am basing my guess on the syslog. I see a bunch of unhandled ‘unbind’ actions on ci_hdrc.0, and some messages about enumeration when it returns as a host, but no messages suggesting a mode switch.

Actually cdc_ether is the Host driver, you need to modprobe the gadget driver, g_ether. (I did not test g_mass_storage).


I figured that out after I posted when I put a trace at the udc register gadget function. None of the peripheral gadgets work, and cdc_ether working seems like a clue why. If you look at the DragonBoard schematic, page 25:

You will see that J4, the micro-USB connector, doesn’t have pin 4 connected to anything. Pin 4 is the OTG ID/Sense line. OTG cables ground that pin to put the controller in Host Mode. But that line isn’t connected, so it should be floating on the controller. That means the OTG peripheral controller should always be in peripheral mode and any host gadgets should not work.

So, with your patches, either the controller isn’t actually being switched to OTG mode (just left in host mode, but with the D lines routed to an alternate connector) or the sense line isn’t properly mapped via Snapdragon IO routing (routed to something that is polling low, instead of high via a pullup resistor as it should be).

As I mentioned, I’m away from my bench for a few days for work, but will try to dig deeper early next week.


Hi @jfitzpat

The 410 processor chip only has one USB port. When nothing is connected to J4 then the port is in host mode and connected to the onboard USB hub to drive the two Type A connectors (and the USB pins on the HS connector).

The Micro USB connector at J4 was never intended to be a host port, it can only be a device port. It is NOT a USB-OTG port (would every body please stop calling it a OTG port, it creates this confusion), J4 is strictly a device port. When you connect a USB cable to J4 the external device provides +5V into the board at pin 1. When the board detects +5V at pin 1, it flips the MUX at S1 from the hub to J4. GPIO_121 changes state and changes the USB port from host to device mode.

There is no need for J4 to detect host or device mode (since it is always device), hence pin 4 is not connected. You will also notice that since J4 can never be a host, there is no way for the board to provide +5V power to the external device. Hence even if you connect a device to J4 with an OTG cable, and force the 410 USB port into host mode, the device won’t work because there is no power delivered to the device.

Hope this helps

OK, summer is over, time for me to start looking for a job :wink:

Uh, I realize that - see my previous posts. The title of the thread refers to peripheral mode, not OTG. I only referenced OTG_SENSE (ID) in my original question.

However, the current release, Buster 359 does not behave as you describe. Plugging in a cable has no effect because the GPIO lines are driven. Hence my question.

Loic fowarded me his candidate patches, which toggle the line by monitoring the GPIO line strapped to the micro V+, but the controller is still in host mode. You can confirm this with the debugfs mounted and something like:

sudo tail -f /sys/kernel/debug/ci_hdrc.0/role

It will report “host”.

Although Loic toggled the switch routing the D lines, but the driver role is not switched so, the connector works as a FORCED HOST port, not a target - hence non standard conforming (a non standard USB port).

Although I didn’t actually refer to the port this way, I’m not sure why you object to the term OTG. The USB peripheral is a dual-role OTG controller. That is the level that this must be addressed at. Anyone who has a similar question has already tried the release Debian (Buster 359) and, like me, realized that the port does not work as you describe and is likely willing to go deeper to get the port to work.

So, to clarify the Dragonboard can either be a HOST via the USB type-A ports or a PERIPHERAL via the micro USB port. Since the micro USB pin-4 (OTG ID) is floating, we cannot really speak about OTG, but standard peripheral port. The patch role is just to toggle controller peripheral mode when VBUS is detected on micro USB port and route controller pins (D+, D-) to the micro USB.

On my side, the sysfs file /sys/kernel/debug/ci_hdrc.0/role correctly returns ‘gadget’ when I plug my computer to the Dragonboard micro USB.

I believe you. But I think that I’m missing a change from your branch.

When I manipulate and monitor the chipidea driver with your changes everything seems plumbed correctly and the host/peripheral flag from hw_read_otgsc is correct.

Remember, I’m running just your 5 commits on top of the release branch. When I get back I’m going to try to figure out why I couldn’t just build and run your branch directly. I was wondering if I needed to build and replace all the modules as well, but perhaps it is something else?

When you checkout the _usb branch from your repo are there special steps you take to build it for the 410c board?

Thanks again for all your help! It’s been a few years since I wrote any Linux drivers and the USB/OTG docs at are pretty sketchy. :slight_smile:

Hi @jfitzpat

Ah, I see the distinction. I am a HW engineer, so I am looking at the connector J4, it is not USB-OTG. You are a SW engineer and looking at the USB port from the SW and registers out, from that point of view the 410 is a USB-OTG device.

The driver will need to look at GPIO_121 to determine the required role, and then drive PM_GPIO_4 to set the MUX to the right state. As well and changing the controller from host to gadget mode.

Older versions of Debian did do this correctly, I was able to set up an Ethernet Gadget last year on the device port J4. Hence I am confident that the HW is correctly designed. Of course the infrastructure for the driver is constantly is constantly evolving, so what you are seeing is a bug in Build 359.

I hope you and @Loic can get the USB functionality repaired.

My resume is now updated…


Sorry, just got back from a work trip. Instead of just applying your last 5 commits on the release branch, I took your repo/branch and added the commits one at a time from the rebase. It seems my initial crash was related to my not doing an update build of all the modules as well. Now, mode switching works as you describe for the ci driver. I’ll let you know if I run into any more problems, but it seems like everything I need is working.

Sorry I didn’t track the build problem down sooner, it would have stopped me from wasting some of your time.

Thanks again for all your help.


1 Like