trejan
Posts: 2157
Joined: Tue Jul 02, 2019 2:28 pm

RPi 4 USB-C socket as host

Sat Jul 20, 2019 7:05 pm

This is probably useless for the vast majority of people.

The USB-C socket on the RPi 4 is officially meant to be device only but you can still use it as a host port if you have a USB-A to USB-C adapter. Add "dtoverlay=dwc2,dr_mode=host" to /boot/config.txt to force the internal USB controller to host mode. You'll need to use an alternate method of powering the RPi 4 such as PoE or via the expansion header.

Plugging in an actual USB-C device may not work as the RPi 4 doesn't implement the CC1/CC2 signalling needed. A USB-A to USB-C adapter does work but you need to force it into host mode.

I did it because of some issues with a specific USB device and using any other bulk device at the same time would cause problems with timing. Swapped one of them over to the DWC controller and both work fine together.
Last edited by trejan on Sun Jul 21, 2019 12:13 am, edited 1 time in total.

andrum99
Posts: 1220
Joined: Fri Jul 20, 2012 2:41 pm

Re: RPi 4 USB-C socket as host

Sat Jul 20, 2019 9:51 pm

trejan wrote:
Sat Jul 20, 2019 7:05 pm
The USB-C socket on the RPi 4 is officially meant to be device only
No its not. It officially supports both device mode and host mode, as it is the same USB controller on the BCM283x SoC used on all previous models of Raspberry Pi. The type A USB ports on the Pi use the new VLI controller, which was added in addition to the USB controller built into the SoC.

trejan
Posts: 2157
Joined: Tue Jul 02, 2019 2:28 pm

Re: RPi 4 USB-C socket as host

Sat Jul 20, 2019 10:16 pm

andrum99 wrote:
Sat Jul 20, 2019 9:51 pm
No its not. It officially supports both device mode and host mode, as it is the same USB controller on the BCM283x SoC used on all previous models of Raspberry Pi. The type A USB ports on the Pi use the new VLI controller, which was added in addition to the USB controller built into the SoC.
Yes. It is. I know it has the same DWC controller as before and it does do both hence the dtoverlay line to force it into host mode. However, the documentation specifically says it is meant to be used in the USB device mode only.

https://www.raspberrypi.org/documentati ... erview_pi4
The OTG hardware present on previous models of Pi is still available and it has moved to a single connection on the USB-C port. The OTG hardware is intended to be used in device-only mode on Pi 4.
It doesn't automatically switch between host and device mode so you have to add the dtoverlay line if you want host mode.

drgeoff
Posts: 10765
Joined: Wed Jan 25, 2012 6:39 pm

Re: RPi 4 USB-C socket as host

Sat Jul 20, 2019 11:13 pm

It that is what the documentation is really meant to say it is badly written.

"The OTG hardware is intended to be used in device-only mode on Pi 4." would be "The OTG hardware is intended to be used only in device mode on Pi 4."

But if that was what the documentation should say then the means to operate in host mode (via the dtoverlay) would not be provided.

plugwash
Forum Moderator
Forum Moderator
Posts: 3618
Joined: Wed Dec 28, 2011 11:45 pm

Re: RPi 4 USB-C socket as host

Sat Jul 20, 2019 11:32 pm

As I understand it the issue is that the USB C detection wiring is not set up for dual role, this means two things.

1. You have to force the mode to use the port in host mode because the Pi can't detect that what is plugged in is a device and not a host.
2. You may have problems if you use a C to C cable because the device may think it's connected to another device. Using a C plug to A socket adapter along with an A plug to C plug lead should avoid this.

trejan
Posts: 2157
Joined: Tue Jul 02, 2019 2:28 pm

Re: RPi 4 USB-C socket as host

Sun Jul 21, 2019 12:11 am

What plugwash said.

It can't automatically switch between host and device mode on a RPi 4 because of the USB-C connector. USB OTG determines which end is what role by the ID pin in a micro USB connector but that doesn't exist in a USB-C connector. USB-C Dual Role does the detection with the CC1/CC2 pins and toggles those between pull up and pull down. The RPi 4 doesn't implement any of that.

If you wanted to make the USB-C socket into a dual role port then you'll need to add something like a TI TUSB320 which implements all of the CC signalling internally and generates an ID output for the USB OTG controller. It'll use up valuable PCB space and be an additional cost for a feature that most people will never use.

I'll update my initial post to say this is with a USB-A to USB-C adapter. YMMV for everything else.
drgeoff wrote:
Sat Jul 20, 2019 11:13 pm
But if that was what the documentation should say then the means to operate in host mode (via the dtoverlay) would not be provided.
That overlay was added back in 2016 so it isn't something specific to the RPi 4.

jdb
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2394
Joined: Thu Jul 11, 2013 2:37 pm

Re: RPi 4 USB-C socket as host

Sun Jul 21, 2019 10:30 am

Can someone try the config.txt parameter "otg_mode=1"?

This swaps the DWC controller out for an xhci host-only controller on the USBC USB2.0 pins. No guarantees about which configurations this will work with, though.

drgeoff wrote:
Sat Jul 20, 2019 11:13 pm
It that is what the documentation is really meant to say it is badly written.

"The OTG hardware is intended to be used in device-only mode on Pi 4." would be "The OTG hardware is intended to be used only in device mode on Pi 4."

But if that was what the documentation should say then the means to operate in host mode (via the dtoverlay) would not be provided.
As plugwash said, the OTG ID pin is not connected to anything inside the USBC port so device operation is assumed. There is no hardware mechanism available to say that the port *should* operate in host mode. Cable hacks or forcing via devicetree will work, but is not a generally supported use case.
Rockets are loud.
https://astro-pi.org

trejan
Posts: 2157
Joined: Tue Jul 02, 2019 2:28 pm

Re: RPi 4 USB-C socket as host

Sun Jul 21, 2019 10:57 am

jdb wrote:
Sun Jul 21, 2019 10:30 am
Can someone try the config.txt parameter "otg_mode=1"?

This swaps the DWC controller out for an xhci host-only controller on the USBC USB2.0 pins. No guarantees about which configurations this will work with, though.
Didn't work for me. The XHCI controller does appear but doesn't see my device. dmesg doesn't say anything.

I was wondering how to enable the internal XHCI controller in the devicetree. Changing the status from disabled to okay didn't do anything when I tried it the other day.

hippy
Posts: 7753
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: RPi 4 USB-C socket as host

Sun Jul 21, 2019 1:50 pm

andrum99 wrote:
Sat Jul 20, 2019 9:51 pm
trejan wrote:
Sat Jul 20, 2019 7:05 pm
The USB-C socket on the RPi 4 is officially meant to be device only
No its not. It officially supports both device mode and host mode, as it is the same USB controller on the BCM283x SoC used on all previous models of Raspberry Pi.
The best way to describe the situation is probably "the Pi 4B USB-C socket allows it to be a USB-C device or limited capability USB-C host but the Pi 4B is only officially a USB-C device due to its hardware configuration".

This was a timely topic as I was this morning buying bits to build a USB-C to USB-A socket 'OTG cable' - It answers the questions I had.

andrum99
Posts: 1220
Joined: Fri Jul 20, 2012 2:41 pm

Re: RPi 4 USB-C socket as host

Sun Jul 21, 2019 9:00 pm

trejan wrote:
Sat Jul 20, 2019 10:16 pm
andrum99 wrote:
Sat Jul 20, 2019 9:51 pm
No its not. It officially supports both device mode and host mode, as it is the same USB controller on the BCM283x SoC used on all previous models of Raspberry Pi. The type A USB ports on the Pi use the new VLI controller, which was added in addition to the USB controller built into the SoC.
Yes. It is. I know it has the same DWC controller as before and it does do both hence the dtoverlay line to force it into host mode. However, the documentation specifically says it is meant to be used in the USB device mode only.

https://www.raspberrypi.org/documentati ... erview_pi4
The OTG hardware present on previous models of Pi is still available and it has moved to a single connection on the USB-C port. The OTG hardware is intended to be used in device-only mode on Pi 4.
It doesn't automatically switch between host and device mode so you have to add the dtoverlay line if you want host mode.
I didn't know the documentation said that. I was going on what James Hughes posted on one of the forums.

fury
Posts: 16
Joined: Thu Sep 20, 2012 4:37 pm

Re: RPi 4 USB-C socket as host

Thu Dec 19, 2019 5:13 am

Is it possible to boot up with it set to host by default but have a way to switch into peripheral / gadget mode at runtime? e.g. temporarily enable g_serial or g_ether or something like that for a makeshift debug port without needing SSH or digging into the IO header UART

I'm planning on using it in an automated test system and it would be nice to be able to hit a button on my UI to make the normally host port a gadget port for plugging into my laptop without changing config.txt and rebooting

sjevtic
Posts: 6
Joined: Mon Feb 17, 2020 3:39 pm

Re: RPi 4 USB-C socket as host

Thu Mar 05, 2020 1:57 pm

fury wrote:
Thu Dec 19, 2019 5:13 am
Is it possible to boot up with it set to host by default but have a way to switch into peripheral / gadget mode at runtime? e.g. temporarily enable g_serial or g_ether or something like that for a makeshift debug port without needing SSH or digging into the IO header UART

I'm planning on using it in an automated test system and it would be nice to be able to hit a button on my UI to make the normally host port a gadget port for plugging into my laptop without changing config.txt and rebooting

As long as you are not using it for power input, the USB-C port works wonderfully as both a device and host port. If you want the USB port to boot up in host mode, put this in config.txt:

Code: Select all

dtoverlay=dwc2,dr_mode=host

Regardless of whether or not you have done this, you can switch into device mode in the shell as root:

Code: Select all

modprobe -r dwc2 && dtoverlay dwc2 dr_mode=peripheral && modprobe dwc2

At this point, you can load the gadget of your choice. When you are done, remove, the gadget driver, and you can switch back to host mode:

Code: Select all

modprobe -r dwc2 && dtoverlay dwc2 dr_mode=host && modprobe dwc2

In short, all of this is possible because of the excellent dtoverlay utility provided by Raspberry Pi. It doesn't do anything magical; you could instead yourself manage the installation of the overlay via configfs (i.e., in /sys/kernel/config/device-tree/overlays), but it sure is convenient! Note also the following:

  1. dr_mode is checked only once when dwc2 is loaded so the remove/dtoverlay change/insert pattern is necessary for correct behavior.
  2. modprobe returns success both when asked to remove an unloaded module as well as when asked to load an already loaded module.
  3. When the dwc2 overlay first appears, or appears after having been previously removed, it seems that dwc2 is automatically loaded.
  4. The default value of dr_mode is otg. On rpi4, where the OTG pin isn't connected to anything useful, so this has the effect of being device mode.
The scheme proposed above has the implication of loading the dwc2 overlay once for every role switch. If that is undesirable, for example because you will be doing many role switches, you can always remove the overlay before reinserting it again:

Code: Select all

dtoverlay -r dwc2

Interestingly, every time the overlay is inserted, dmesg shows the following:

Code: Select all

OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/usb@7e980000/compatible
OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/usb@7e980000/dr_mode
OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/usb@7e980000/g-np-tx-fifo-size
OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/usb@7e980000/g-rx-fifo-size
OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/usb@7e980000/g-tx-fifo-size
OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/usb@7e980000/status

I have not done any investigation to evaluate the impact of either repeated installation of the overlay or the remove/insert paradigm. Perhaps a device tree expert can weigh in on the relative merits of these two approaches.

elee
Posts: 1
Joined: Fri Apr 24, 2020 12:43 am

Re: RPi 4 USB-C socket as host

Fri Apr 24, 2020 1:02 am

Hello,

I would also like to switch the direction of the pi 4 OTG port (as part of a test setup).
Ideally in host mode it could read/write a USB drive, and in device mode it would appear as 3 peripherals (usb-uart, usb-drive, usb-ethernet)

The command to switch the OTG port to host mode worked when I connected a keyboard.

Code: Select all

modprobe -r dwc2 && dtoverlay dwc2 dr_mode=host && modprobe dwc2
And when I connected a USB drive I could mount it and see the directories/files.
But reading the files produced mangled contents (non-ascii characters).
I could write a file, but when I tried reading that file on a macbook it was also mangled.

The same USB drive worked fine when plugged into the "regular" usb ports on the rpi4, so I guessing some driver is not getting loaded, or some configuration is missing?

Any hints/suggestions would be welcome.

Regards,
Eric

kevinthefixer
Posts: 94
Joined: Sun Jun 02, 2013 10:36 pm

Re: RPi 4 USB-C socket as host

Sun May 03, 2020 2:38 am

Hi guys, I confess I'm over my head here in this thread. But I think it would be worth your while to look here:
viewtopic.php?f=28&t=267331
While you're getting mangled files, we are getting "spurious spikes" on our oscilloscopes. I can't help but think the two are related. I have another puzzling point to add: my Hantek 6022BL 'scope does not show this behavior, it has a perfectly clean trace with only the expected RFI noise, and very little of that. It's also connected through the usb-c port as described in the other thread. If anyone can shed a bit of light on this I'd appreciate it! PM me if you need me to experiment or???

Thanks, Kevin

jj_0
Posts: 113
Joined: Wed Jul 11, 2012 7:07 am

Re: RPi 4 USB-C socket as host

Sat Jun 13, 2020 2:51 pm

elee wrote:
Fri Apr 24, 2020 1:02 am
Hello,

I would also like to switch the direction of the pi 4 OTG port (as part of a test setup).
Ideally in host mode it could read/write a USB drive, and in device mode it would appear as 3 peripherals (usb-uart, usb-drive, usb-ethernet)

The command to switch the OTG port to host mode worked when I connected a keyboard.

Code: Select all

modprobe -r dwc2 && dtoverlay dwc2 dr_mode=host && modprobe dwc2
And when I connected a USB drive I could mount it and see the directories/files.
But reading the files produced mangled contents (non-ascii characters).
I could write a file, but when I tried reading that file on a macbook it was also mangled.

The same USB drive worked fine when plugged into the "regular" usb ports on the rpi4, so I guessing some driver is not getting loaded, or some configuration is missing?

Any hints/suggestions would be welcome.

Regards,
Eric
I tested this with a USB-drive as well and have the same experience, even with a powered USB hub (or actually a powered USB power meter). So it does not seem to be power-related.

I put some test files on the USB-drive and tested from the normal USB2 port:

Code: Select all

root@rpi4b-4:/home/pi# ls -lisa /mnt
total 4664
 2    4 drwx------  2 pi   pi      4096 Jun 13 15:10 .
 2    4 drwxr-xr-x 22 root root    4096 Jun 13 14:36 ..
12  188 -rw-r--r--  1 root root  191442 Jun 13 14:23 test-file-from-laptop.txt
16   28 -rw-r--r--  1 root root   27576 Jun 13 14:54 test-file-from-rpi4.txt
15 4440 -rw-r--r--  1 root root 4543636 Jun 13 15:04 THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
Then checksummed them:

Code: Select all

root@rpi4b-4:/home/pi# md5sum /mnt/*
dd504035434432c1094ae84385f008c1  /mnt/test-file-from-laptop.txt
aa95bbcdafaa668968519520b29f5a0e  /mnt/test-file-from-rpi4.txt
08c2766c98e6006c47b7937f0569755c  /mnt/THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
And checked which blocks one of them occupied:

Code: Select all

root@rpi4b-4:/home/pi# debugfs -R "stat <15>" /dev/sda1 >which-blocks.txt
debugfs 1.44.5 (15-Dec-2018)
root@rpi4b-4:/home/pi# cat which-blocks.txt 
Inode: 15   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 552302989    Version: 0x00000000:00000001
User:     0   Group:     0   Project:     0   Size: 4543636
File ACL: 0
Links: 1   Blockcount: 8880
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x5ee4ceda:6fa04480 -- Sat Jun 13 15:04:26 2020
 atime: 0x5ee4cfa0:a7ef5e44 -- Sat Jun 13 15:07:44 2020
 mtime: 0x5ee4ceda:6fa04480 -- Sat Jun 13 15:04:26 2020
crtime: 0x5ee4ceda:6bcfb16c -- Sat Jun 13 15:04:26 2020
Size of extra inode fields: 32
Inode checksum: 0x3c5f49a5
EXTENTS:
(0-1109):33288-34397
root@rpi4b-4:/home/pi# 
Then unmounted, put the USB-drive in the USB-C port mounted and did the above again:

Code: Select all

root@rpi4b-4:/home/pi# ls -lisa /mnt
total 4664
 2    4 drwx------  2 pi   pi      4096 Jun 13 15:10 .
 2    4 drwxr-xr-x 22 root root    4096 Jun 13 14:36 ..
12  188 -rw-r--r--  1 root root  191442 Jun 13 14:23 test-file-from-laptop.txt
16   28 -rw-r--r--  1 root root   27576 Jun 13 14:54 test-file-from-rpi4.txt
15 4440 -rw-r--r--  1 root root 4543636 Jun 13 15:04 THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
root@rpi4b-4:/home/pi# md5sum /mnt/*
7d38b23ddb73d1e28dff2cc95ce1a561  /mnt/test-file-from-laptop.txt
7a4e01a582596539e1919856b64d2ea5  /mnt/test-file-from-rpi4.txt
1838f326c5608aab214dff845a851d63  /mnt/THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
root@rpi4b-4:/home/pi# debugfs -R "stat <15>" /dev/sda1 >which-blocks.txt
debugfs 1.44.5 (15-Dec-2018)
root@rpi4b-4:/home/pi# cat which-blocks.txt
Inode: 15   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 552302989    Version: 0x00000000:00000001
User:     0   Group:     0   Project:     0   Size: 4543636
File ACL: 0
Links: 1   Blockcount: 8880
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x5ee4ceda:6fa04480 -- Sat Jun 13 15:04:26 2020
 atime: 0x5ee4cfa0:a7ef5e44 -- Sat Jun 13 15:07:44 2020
 mtime: 0x5ee4ceda:6fa04480 -- Sat Jun 13 15:04:26 2020
crtime: 0x5ee4ceda:6bcfb16c -- Sat Jun 13 15:04:26 2020
Size of extra inode fields: 32
Inode checksum: 0x3c5f49a5
EXTENTS:
(0-1109):33288-34397
So interestingly enough the directory entries are still intact, the md5sum is different but the test file still occupies the correct blocks. So something is going wrong in reading (some) blocks.

Also, if you do a loop mount of the physical device everything seems fine:

Code: Select all

root@rpi4b-4:/home/pi# losetup -fP --show /dev/sda
/dev/loop0
root@rpi4b-4:/home/pi# mount /dev/loop0p1 /mnt
root@rpi4b-4:/home/pi# ls -lisa /mnt
total 4664
 2    4 drwx------  2 pi   pi      4096 Jun 13 15:10 .
 2    4 drwxr-xr-x 22 root root    4096 Jun 13 14:36 ..
12  188 -rw-r--r--  1 root root  191442 Jun 13 14:23 test-file-from-laptop.txt
16   28 -rw-r--r--  1 root root   27576 Jun 13 14:54 test-file-from-rpi4.txt
15 4440 -rw-r--r--  1 root root 4543636 Jun 13 15:04 THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
root@rpi4b-4:/home/pi# md5sum /mnt/*
dd504035434432c1094ae84385f008c1  /mnt/test-file-from-laptop.txt
aa95bbcdafaa668968519520b29f5a0e  /mnt/test-file-from-rpi4.txt
08c2766c98e6006c47b7937f0569755c  /mnt/THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
root@rpi4b-4:/home/pi# debugfs -R "stat <15>" /dev/sda1 >which-blocks.txt
debugfs 1.44.5 (15-Dec-2018)
root@rpi4b-4:/home/pi# cat which-blocks.txt 
Inode: 15   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 552302989    Version: 0x00000000:00000001
User:     0   Group:     0   Project:     0   Size: 4543636
File ACL: 0
Links: 1   Blockcount: 8880
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x5ee4ceda:6fa04480 -- Sat Jun 13 15:04:26 2020
 atime: 0x5ee4cfa0:a7ef5e44 -- Sat Jun 13 15:07:44 2020
 mtime: 0x5ee4ceda:6fa04480 -- Sat Jun 13 15:04:26 2020
crtime: 0x5ee4ceda:6bcfb16c -- Sat Jun 13 15:04:26 2020
Size of extra inode fields: 32
Inode checksum: 0x3c5f49a5
EXTENTS:
(0-1109):33288-34397
root@rpi4b-4:/home/pi# 
'debugfs -R "cat <12>" /dev/sda1' and 'dd-ing' /dev/sda1 also seems to to work fine:

Code: Select all

# On the USB C port:
root@rpi4b-4:/home/pi# debugfs -R "cat <12>" /dev/sda1 | md5sum
debugfs 1.44.5 (15-Dec-2018)
dd504035434432c1094ae84385f008c1  -
root@rpi4b-4:/home/pi# dd if=/dev/sde1 of=sde1-dd.img bs=512M
3+1 records in
3+1 records out
2048917504 bytes (2.0 GB, 1.9 GiB) copied, 251.721 s, 8.1 MB/s
root@rpi4b-4:/home/pi# mount sde1-dd.img /mnt
root@rpi4b-4:/home/pi# ls -lisa /mnt
total 4664
 2    4 drwx------  2 pi   pi      4096 Jun 13 15:10 .
 2    4 drwxr-xr-x 22 root root    4096 Jun 13 14:36 ..
12  188 -rw-r--r--  1 root root  191442 Jun 13 14:23 test-file-from-laptop.txt
16   28 -rw-r--r--  1 root root   27576 Jun 13 14:54 test-file-from-rpi4.txt
15 4440 -rw-r--r--  1 root root 4543636 Jun 13 15:04 THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
root@rpi4b-4:/home/pi# md5sum /mnt/*
dd504035434432c1094ae84385f008c1  /mnt/test-file-from-laptop.txt
aa95bbcdafaa668968519520b29f5a0e  /mnt/test-file-from-rpi4.txt
08c2766c98e6006c47b7937f0569755c  /mnt/THEC64-Full-size-User-Manual-Dec-2019-EN.pdf
So the problem doesn't appear when using 'direct access' but does appear when going via the USB Mass Storage os SCSI driver?

UPDATE: All of the above was on Linux rpi4b-4 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l GNU/Linux

After an 'rpi-update' to 'Linux rpi4b-4 5.4.45-v7l+ #1321 SMP Wed Jun 10 17:39:20 BST 2020 armv7l GNU/Linux' however it seems to work fine:

Code: Select all

root@rpi4b-4:md5sum /mnt/*
dd504035434432c1094ae84385f008c1  test-file-from-laptop.txt
aa95bbcdafaa668968519520b29f5a0e  test-file-from-rpi4.txt
08c2766c98e6006c47b7937f0569755c  THEC64-Full-size-User-Manual-Dec-2019-EN.pdf

Return to “Advanced users”