It's possible to blacklist a single USB device from connecting to Linux, while allowing similar USB devices to connect. In my case, I wanted to disable my laptop's built in Bluetooth host (a USB device installed inside the laptop). However I wanted a second USB Bluetooth host, integrated as part of my new WiFi card, to still work.

I hadn't seen a lot of discussion of this online so I thought I'd post the details.

Short version

Create a udev rule that uses the USB authorisation mechanism in the kernel to de-authorize the device. The bus will put the device into suspend mode, and it'll never become active.

I put my rule into a new file /etc/udev/rules.d/81-bluetooth-hci.rules. It blacklists any USB device with Vendor ID 0a5c and Product ID 217f. Here's the entire contents of the rule file:

 # Lenovo Broadcom based HCI should be disabled
 SUBSYSTEM=="usb", ATTRS{idVendor}=="0a5c", ATTRS{idProduct}=="217f", ATTR{authorized}="0"

(The file is exactly two lines long - a one line comment and then a single line below that with the udev rule. The blog theme renders it as multiple lines.)

More detailed explanation

The most common way to "blacklist" devices from appearing in a generic Linux kernel is to use module blacklisting, so a particular module is never loaded and any devices that rely on that module can't be used.

This doesn't work if you want to blacklist a single device of a particular type (ie my case of wanting one Bluetooth HCI but not the other Bluetooth HCI, they both use the module btusb so I can't blacklist it).

USB device authorisation allows you to do this, at least for USB devices. It was added to the kernel in 2007 when the Wireless USB standard was coming out (remember that?).

Most posts about authorisation take the point of view of locking down your USB subsystem so only trusted devices can connect. This is how it's described in the kernel documentation. However, as we've just seen, you can use the same authorisation mechanism to automatically disable a particular device.

Identifying a device

You can usually identify the USB device you want to blacklist via the USB IDs shown in lsusb output, written into a udev rule as shown above. However if that's not enough there is also the udevadm info feature called "attrwalk". For example, to walk all udev attributes of my Bluetooth hci device:

udevadm info -a -p /sys/class/bluetooth/hci0

Any of the ATTRS printed in the output can be used to identify/match USB devices to be disabled. Note that the output may "walk" past the device and into higher-up devices on the bus, so the earlier blocks of output are the most useful.

Devices which are de-authorised seem to be put into suspend mode, so if they are bus powered then this means they should consume almost neglible current. I can't really tell how much current the USB Bluetooth device built into my laptop uses while suspended, but it's definitely less annoying than having to pass --hci X arguments to all my Bluetooth LE tools.

Thoughts on “Blacklisting a single USB device from Linux