Handling Bluetooth “dropouts” on Chrome OS

A handy script to easily reset the Bluetooth controller on Chromebook devices

I love my Chromebook, a Lenovo X131e.

I also love my Bluetooth mouse.

I do NOT love when the Bluetooth controller becomes inoperable on my Chromebook, preventing the use of my mouse (and any other Bluetooth devices, as well).

It seems that, sometimes, the Bluetooth controller “hard locks”; typically, the only way to recover from this scenario would be a total reboot. A full reboot is quite a pain, especially while working with a lot of open windows/tabs.

Bluetooth: It’s great…when it works

While the convenience offered by Bluetooth is a wonderful thing, it can cause quite the headache when it inexplicably stops working.

The Chrome OS Bluetooth menu

chrome os bluetooth menu
The Bluetooth menu in Chrome OS

This is how it looks while my mouse is working.

Unfortunately, things can look quite similar while things are not working.

One might think: “Perhaps if I turn the Bluetooth off, and then back on, it’ll work again.”

WRONG!

Toggle the Bluetooth state, and it will simply refuse to return to the enabled state.

So what’s going on here?

Bluetooth Hardware

Often, despite being internal to the Chromebook, the Bluetooth hardware is connected to the rest of the system via USB — this may come as a surprise to some. Now, for reasons unbeknownst to me, the Bluetooth USB device enters a state in which it is no longer functional. So, with an ordinary USB device, the first action most would take is to unplug the device and plug it back in; not too easy when the device is embedded within the Chromebook.

usbreset.c — a handy little tool

Enter usbreset.c — a (relatively) unknown snippet of code, which once compiled, can issue a USB reset ioctl; essentially “unplugging and plugging the device back in” via software.

To compile, open a shell, change to the directory in which usbreset.c is located, and execute:

gcc -o usbreset usbreset.c

Optionally, the compiled product can be placed into a directory which is part of the $PATH environment variable, such as /usr/local/sbin, which will make use much easier.

Following compilation, usbreset takes one parameter: the USB device path, such as /dev/bus/usb/${bus}/${dev}

The bus and device numbers can be acquired using lsusb — look for the line describing a Bluetooth controller. On my X131e, I receive the following output:

localhost ~ # lsusb
Bus 002 Device 004: ID 413c:819b Dell Computer Corp.
Bus 002 Device 007: ID 0cf3:3004 Atheros Communications, Inc. AR3012 Bluetooth 4.0
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 5986:0299 Acer, Inc
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Great, now I have the bus (002) and device (007) numbers. I can go ahead and issue the following command:

usbreset /dev/bus/usb/002/007

After a few seconds, Bluetooth should be working again. Awesome!

Unfortunately, the device number tends to change.

Easier Procedure

I wrote a simple shell script to grab the bus and device numbers from the output of lsusb, and to issue the reset.

You can find it, along with the source for usbreset.c, in this bitbucket snippet.

Please note that this was created for use on my X131e; while I have experienced Bluetooth issues on other Chrome OS devices, and have used usbreset (successfully), I have NOT used this script on those devices. Your mileage may vary; the script will likely need to be adjusted for your setup.

Feedback

If you have any questions, comments, feedback, or suggestions for improvement, please let me know in the comments below.

I hope this is useful to someone else!

Author: Gerad Munsch

I'm a laid back guy, with a wonderful wife, two awesome kids, and an obsession with technology. Aside from the obvious hobbies, such as wiring my house with Cat5, automating things with microcontrollers, working with my home lab (Cisco, Hyper-V, ESXi), and taking things apart, I also enjoy spending time with my family, working on my '99 Honda Civic, and exploring the great outdoors.