USB device 'hotplug' not passed to the container

Hello
Only recently I plug in my test phone to push/pull files via adb, I found out that the usb device doesn’t hotplug onto the container that have the usb device registered onto.

  usb:18d1:4ee7:
    gid: "46"
    mode: "0660"
    productid: 4ee7
    type: usb
    vendorid: 18d1

Last known to work on lxd version 5.19, before I migrated it to incus version 0.6 without testing the usb device functionality.

Currently running on incus client 6.3, server version 6.3 and lxcfs 6.0.1
Posting here to check if anyone have the same issue or I misconfigured something.

Hi!

Make sure to run sudo adb kill-server on the host before you start the container with the Incus USB device. Because if you do not do so, Incus may not be able to push the USB device into the container.

adb wasn’t installed on the host.
The thing is back in lxd 5.19, whenever I plug in the usb device, in this case an android device, it lxd daemon will automatically push the device to the container.

Now, I have to first delete the usb device and re-add them to the container.

I tried earlier with a phone and I noticed that the device was not pushed into the container if the adb server is running on the host. When I made sure that there was no adb server running on the host, then Incus would automatically push the device into the container.

Considering that this feature worked at least for me (with one caveat though), it means that it generally works. You would need to look into the logs to figure out what’s going on in your specific case.

I would check

  1. the output of sudo dmesg.
  2. incus monitor --pretty (keep this running in a terminal and it shows in realtime the log messages).
  3. any non-standard udev rules that may exist.

Also, your device name usb:18d1:4ee7 looks peculiar with those colons. Perhaps you found a bug in the device name? Can you name the device without colons?

  1. The container that has the usb device configured is already started and running.
  2. Check no adb process running on the host
  3. Rename the device name to usb-18d1-4ee7 or usb-18d1-4ee0 (for fastboot)
  4. Switched on the android device in fastboot mode or with adb debugging option enabled.
  5. Check container, doesn’t apply the usb device over the container.
  6. However, if I restart the container or remove and reapply the usb device through incus config device {add|remove} <container_name>, it works.

dmesg output when the USB device is plugged in:

[61561.329593] usb 1-1: new high-speed USB device number 9 using xhci_hcd
[61561.482338] usb 1-1: New USB device found, idVendor=18d1, idProduct=4ee0, bcdDevice= 1.00
[61561.482360] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[61561.482371] usb 1-1: Product: Android
[61561.482378] usb 1-1: Manufacturer: HTC
[61561.482384] usb 1-1: SerialNumber: XXXX

incus monitor, when I manually add the device using incus config device {add|remove} after removing the same usb device entry:

DEBUG  [2024-08-18T07:40:29+0] Removing device                               device=usb-18d1-4ee0 instance=<container_name> instanceType=container project=default type=usb
DEBUG  [2024-08-18T07:40:29+0] UpdateInstanceBackupFile started              driver=dir instance=<container_name> pool=default project=default
DEBUG  [2024-08-18T07:40:29+0] Skipping unmount as in use                    driver=dir pool=default refCount=1 volName=<container_name>
DEBUG  [2024-08-18T07:40:29+0] Instance operation lock finished              action=update err="<nil>" instance=<container_name> project=default reusable=false
INFO   [2024-08-18T07:40:29+0] Action: instance-updated, Source: /1.0/instances/<container_name>, Requestor: unix/<username> (@)
DEBUG  [2024-08-18T07:40:29+0] Success for operation                         class=task description="Updating instance" operation=<UUID> project=default
INFO   [2024-08-18T07:40:29+0] ID: <UUID>, Class: task, Description: Updating instance  CreatedAt="2024-08-18 07:40:29.105268005 +0 +00" Err= Location=none MayCancel=false Metadata="map[]" Resources="map[instances:[/1.0/instances/<contai
ner_name>]]" Status=Success StatusCode=Success UpdatedAt="2024-08-18 07:40:29.105268005 +0 +00"
DEBUG  [2024-08-18T07:40:29+0] UpdateInstanceBackupFile finished             driver=dir instance=<container_name> pool=default project=default
DEBUG  [2024-08-18T07:40:29+0] Event listener server handler stopped         listener=<UUID> local=/var/lib/incus/unix.socket remote=@
DEBUG  [2024-08-18T07:40:48+0] Handling API request                          ip=@ method=GET protocol=unix url=/1.0 username=<username>
DEBUG  [2024-08-18T07:40:48+0] Handling API request                          ip=@ method=GET protocol=unix url=/1.0/instances/<container_name> username=<username>
DEBUG  [2024-08-18T07:40:48+0] Handling API request                          ip=@ method=GET protocol=unix url=/1.0/events username=<username>
DEBUG  [2024-08-18T07:40:48+0] Event listener server handler started         id=<UUID> local=/var/lib/incus/unix.socket remote=@
DEBUG  [2024-08-18T07:40:48+0] Handling API request                          ip=@ method=PUT protocol=unix url=/1.0/instances/<container_name> username=<username>
DEBUG  [2024-08-18T07:40:48+0] Lock acquired for instance                    instance=<container_name> project=default
DEBUG  [2024-08-18T07:40:48+0] Acquiring lock for instance                   instance=<container_name> project=default
DEBUG  [2024-08-18T07:40:48+0] Started operation                             class=task description="Updating instance" operation=<UUID> project=default
DEBUG  [2024-08-18T07:40:48+0] New operation                                 class=task description="Updating instance" operation=<UUID> project=default
DEBUG  [2024-08-18T07:40:48+0] Instance operation lock created               action=update instance=<container_name> project=default reusable=false
INFO   [2024-08-18T07:40:48+0] ID: d0861fbd-xxxx, Class: task, Description: Updating instance  CreatedAt="2024-08-18 07:40:48.840899263 +0 +00" Err= Location=none MayCancel=false Metadata="map[]" Resources="map[instances:[/1.0/instances/<container_name>]]" Status=Running StatusCode=Running UpdatedAt="2024-08-18 07:40:48.840899263 +0 +00"
INFO   [2024-08-18T07:40:48+0] ID: <UUID>, Class: task, Description: Updating instance  CreatedAt="2024-08-18 07:40:48.840899263 +0 +00" Err= Location=none MayCancel=false Metadata="map[]" Resources="map[instances:[/1.0/instances/<container_name>]]" Status=Pending StatusCode=Pending UpdatedAt="2024-08-18 07:40:48.840899263 +0 +00"
DEBUG  [2024-08-18T07:40:48+0] Handling API request                          ip=@ method=GET protocol=unix url=/1.0/operations/<UUID> username=<username>
DEBUG  [2024-08-18T07:40:48+0] Starting device                               device=usb-18d1-4ee0 instance=<container_name> instanceType=container project=default type=usb
DEBUG  [2024-08-18T07:40:48+0] Adding device                                 device=usb-18d1-4ee0 instance=<container_name> instanceType=container project=default type=usb

After wards if I plugged it out and plug it back in, the device, incus monitor did not show anything

I tried again and I got cases that the USB device was not pushed into the container although it should. But when it worked, I had incus monitor --pretty and it did not show up something relevant. Nor at /var/log/incus/mycontainer.

There was a case that

  1. the device was working in the container
  2. I run adb devices on the host and the device was gone from the container.
  3. I run on the host adb kill-server and the device magically reappeared in the container. I did not even restart the container.

I think what we are missing is an in-depth understanding of what’s happening when a USB device is attached to a container. If there’s a way to get such low-level logs.

Can you file an issue on the project

  1. start off with a new container, show all relevant commands.
  2. mention your host OS.
  3. add the above debugging information.

The Incus handling is very simple and pretty error proof.

What we do with unix-hotplug is listen for uevents which are triggered as new character devices in /dev are created following a device being inserted, we then parse the uevent and try to tie the uevent to a particular USB device and check if the product and vendor fields line up, if they do, the device gets added to the container (same as a unix-char device would do manually).

Now this is mostly relevant for devices where you get a char device to show up following a hotplug event, things like serial consoles and other similar devices.

For an Android phone with ADB, from what I recall, this is just a basic libusb device, that is, it doesn’t have any custom device outside of the base /dev/bus/usb/XYZ thing.

For those, the usb device type is usually a better fit.

Android device are a libusb device, so definitely usb device is the best fit.
However, I still couldn’t identify what causes it unable to hotplug into an incus container.

Last known to work is on lxd 5.19, thereafter I didn’t do any much Android work so didn’t test it on incus 0.6 (migrated from lxd 5.19) until incus 6.3. Currently on incus 6.4.

What use to work now doesn’t

any updates on this topic? I too am trying to pass my android device to a container so I can use as a camara for recording. I can install adb on the host and see the device there, but in the container never get the device. I took note of what Simos mentions about not running adb host on the host so I just uninstalled altogether.

Am I understanding correctly. Most usb devices would get automatically passed to the container?

It used to be that way, once the usb device is connected, as long as the container has the existing usb device setup (with the correct vendor id, vendor id + product id) it will be automatically setup

Am asking here to see if others have face similar issues.

@stgraber Is this a bug that’s present in incus, should I raise any issue on incus github?

I was able to make mines work by using type usb by the way.

This looks like a case where we would need to perform some background digging.

It works for some if not most users, so it’s not such a bug in Incus where it does not work at all.

If ADB server is running on the host, then the phone is not visible in the container. But if I kill the ADB server on the host, then the phone appears automagically in the container. Is that an Incus issue or could it be an Android issue that only one process at a time can do ADB?

When you connect your phone to the PC, your computer starts charging it. The default it to charge the phone. Some Android systems may prompt you to switch to a data connection which means to make the phone appear as a disk device so you can take your photos, etc. Is that required for ADB?

The thread topic mentions hotplug which alludes to unix-hotplug. I do not use that and never did for ADB. Is anyone trying to make this work with unix-hotplug? I use usb instead.

Ok, I posted about this. Please check, verify and leave feedback. In my case the setup is working fine. Report back any corner cases.

Thanks, works for me just fine.

1 Like

I think I found something, I went through Simo`s Tutorial. How to use your Android phone with ADB in an Incus container – Mi blog lah! So to authorize the device one must reconnect. But once you reconnect, the device number will change on the host. and then will change on the instance. But the folder /dev/bus/usb/… will not update so device will no longer be found. I did try setting devnum to the instance config the problem is the device num actually changes on the host and when in the instance /dev/bus disappears. I take it because the device id is no longer valid.

On the host:
squeige@Ragnarok:~$ lsusb
Bus 001 Device 056: ID 04e8:6864 Samsung Electronics Co., Ltd GT-I9070 (network tethering, USB debugging enabled)

on the instance:

devices:
adb:
productid: “6864”
type: usb
vendorid: “04e8”

root@adb:~# lsusb
Bus 001 Device 056: ID 04e8:6864 Samsung Electronics Co., Ltd GT-I9070 (network tethering, USB debugging enabled)

root@adb:~# adb start-server

  • daemon not running; starting now at tcp:5037
  • daemon started successfully
    root@adb:~# adb devices
    List of devices attached
    R58R22N6WWF unauthorized

– disconnect to authorize
root@adb:~# lsusb
Bus 001 Device 059: ID 04e8:6864 Samsung Electronics Co., Ltd GT-I9070 (network tethering, USB debugging enabled)

root@adb:~# ls -la /dev/bus/usb/001/056
crw-rw---- 1 root root 189, 55 Sep 25 06:16 /dev/bus/usb/001/056
root@adb:~# ls -la /dev/bus/usb/001/
total 0
drwxr-xr-x 2 root root 60 Sep 25 06:14 .
drwxr-xr-x 3 root root 60 Sep 25 06:14 …
crw-rw---- 1 root root 189, 55 Sep 25 06:16 056

I also tried installing adb on the host, authorizing and doing the kill-server. But that did not work, inside the instance I am getting unathoized. But if I disconnect I will have the issue I am describing.

So the question becomes does /dev/bus/dev/… update automatically?