Programmatically removing all bluetooth devices on the Linux command line - linux

I am able to scan for all available bluetooth devices with hcitool or with my C program.
I can pair the device using it's address with a simple-agent python script.
I would like to know if I can also remove the paired device using either hcitool, hciconfig or some kind of bluetooth command.
I know the information of detected devices for the hci0 controller is stored in /var/lib/bluetooth/XX:XX:XX:XX:XX:XX, where XX:XX:XX:XX:XX is the address of the hci controller.
This would be useful for testing pairing, connecting and disconnecting devices.

For those using Ubuntu 20.04, here is the same command using the bluetoothctl command
#!/bin/bash
for device in $(bluetoothctl devices | grep -o "[[:xdigit:]:]\{8,17\}"); do
echo "removing bluetooth device: $device | $(bluetoothctl remove $device)"
done

bluez-test-device remove XX:XX:XX:XX:XX:XX

If you install the bluez-tools package, run this to unpair a bluetooth device :
bt-device -r xx:xx:xx:xx:xx:xx
where xx:xx:xx:xx:xx:xx is the address of the paired device.

As it is mentioned above on ashish's answer, you can us bluez-test-device to remove the device which that you already know its mac address. So the problem is to parse the mac address of the added devices.
With python or c or whatever you use,
1) list the devices with;
bluez-test-device list
and parse the output and get all the MAC addresses of the devices, add them to a list.
2) disconnect and remove the devices;
bluez-test-device disconnect <MAC ADDRESS>
bluez-test-device remove <MAC ADDRESS>

Command using bluetoothctl binary: for device in $(bluetoothctl devices | grep -vEi '(o que mais vc quer deixar aqui|samsung|jbl|wireless)' | awk '{print $2}'); do bluetoothctl remove $device; done

All these answers don't answer the headline "removing all Bluetooth devices"
I wrote this little bash script to remove all the Bluetooth devices that are listed in the bt-device -l
#!/bin/bash
for device in $(bt-device -l | grep -o "[[:xdigit:]:]\{11,17\}"); do
echo "removing bluetooth device: $device | $(bt-device -r $device)"
done
How to run?
Make a new file like <fileName>.sh and paste the code above.
Run chmod +x <fileName> to make the script executable
Run ./<fileName>.sh
Celebrate! All Bluetooth devices are removed now :)

Related

bluez: scan and connect in parallel

what I want to achieve in a test setup is:
running:
hcitool -i hci0 lescan --duplicates --passive
on one shell
and in parallel connect on another via
hcitool -i hci0 lecc <BTADDR>
The moment I issue the connect command the scan process exits.
Why is that? I thought choosing to scan --passive will allow a scan output while managing a connection?
Best,
If you are on kernel 3.2 and above use gatttool or bluetoothctl for LE connections. hcitool is deprecated and you should not be using them anymore. Compile and install latest bluez and use gatttool for LE connections. If your LE device is in the vicinity, you should be able to connect, read and write using gatttool directly:
say, your local BT adapter is hci0 and the remote device BD_ADDR is 12:22:33:44:55:66 then:
gatttool -i hci0 -b 12:22:33:44:55:66 -I
[12:22:33:44:55:66][LE]>connect
Attempting to connect to 12:22:33:44:55:66
Connection successful
[12:22:33:44:55:66][LE]>characteristics
Read manual and help to know more about gattool.

Read raw USB data for port being used by VirtualBox

I have software for communicating with a serial device that only runs on Windows 7. My host machine is running Ubuntu 16.04, with Windows 7 in virtual box.
I've managed to set it up using USB device filters in VirtualBox settings so that Windows sees and can communicate with the device.
However I'd like to capture what's being sent to and from the device. I thought something as simple as cat /dev/ttyUSB0 would work but unfortunately when I start VirtualBox I get this in dmesg:
[31199.465270] vboxdrv: ffffffffc0df4020 VMMR0.r0
[31199.653494] vboxdrv: ffffffffc0ef7020 VBoxDDR0.r0
[31199.710573] VBoxNetFlt: attached to 'wlp1s0' / 98:54:1b:04:13:48
[31199.863579] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[31199.863674] ftdi_sio 1-3:1.0: device disconnected
So I don't know which file to monitor in /dev anymore. I suppose I might be able to try listen for the communication from Windows, but if I can I'd like to know if it's possible to monitor it from my host machine.
Edit:
This answer helped me for a start. I now get some cool looking stream on the terminal, next step is deciphering it, or if anyone has a better way I'm interested - it looks like the person who answered that question still has deciphering it as a TODO :-)
The fact that it was communicating with software in VirtualBox didn't really matter. This answer got me most of the way just by (as root):
modprobe usbmon
cat /sys/kernel/debug/usb/devices|less and search for device
cat /sys/kernel/debug/usb/usbmon/7u where 7 is the number from "Bus=" in the device table from step 2
From there is was just filtering the output.
A basic way could be just
cat /sys/kernel/debug/usb/usbmon/1u |cut -d\ -f9- | grep ^\n
But the device I was working with was constantly sending lines with just 4 characters, to filter out those I got the address word from the output line, and grepped for that. In my case I only wanted to capture "C" or callback output. I was also filtering for lines that contained more than just the default "0160" that the device was constantly outputting. To try understand the hex output I put a xxd -r -p at the end which gave me:
cat /sys/kernel/debug/usb/usbmon/1u | grep -e 'C Bi:1:005:1\s0\s\w*\s=\s0160\w' | cut -d\ -f8- | xxd -r
Where the grep is
grep -e 'C <address> <someotherstuff> = <always-output-string><anycharacter>
This still gave me this indecipherable junk below, but I don't know the format so I'm stuck here. Maybe the steps to read and filter will be useful for someone
>
O�UDQN��RG_JAMS142E DEFAULT0XXXXXXX�lSTz:�RSDU�vy��������������������������z�fff=�����{6zC"z�u6zC�z�H
;�����C��Af[���RSC�b ISD�EGIN
�CG_IEW0321:0407JUN12S��Z-�$''$'''C'''

Raspberry Pi & Blend Micro : can't connect with Bluetooth

Recently got a Blend Micro for a project and I need a raspberry pi to initiate a bluetooth connection with it.
For that I installed BlueZ 5.2 on raspberry and i used this command to detect the Blend Micro :
sudo hcitool -i hci0 lescan
I correctly detect the Blend micro then i use the gatttool command :
sudo gatttool -i hcitool hci0 -b XX:XX:XX:XX:XX:XX -I
(where the XX corresponds to the Blend MAC address)
But when I initiate the connection by typing connect it says "Host is down" :
$ sudo gatttool -i hci0 -b XX:XX:XX:XX:XX:XX -I
[ ][XX:XX:XX:XX:XX:XX][LE]> connect
Connecting... connect error: Host is down (112)
[ ][XX:XX:XX:XX:XX:XX][LE]>
Do you have any idea on how to fix that ? Tried many things without any results though...
Regards, RaZZeR
When you are connecting, you need to add "-t random" to your command line.

How to initialize Bluetooth in a startup script with Yocto Poky Linux

I have a script that initializes my bluetooth setup on an Intel Edison. It allows pairing and connecting to this headless machine running Yocto Poky Linux. It was suggested that I put the startup script in /etc/init.d and run update-rc.d myscript.sh defaults. The script ran but it didn't work (generated boot errors saying bluetooth device not found) because Bluetooth had not started yet. I did some reasearch and after removing my links I did update-rc.d myscript.sh defaults 99 which was claimed to run the script last but it did't make any differrence -- it still ran in the same place in the boot sequence. I verified that the links had S99 on them so it seemed like they were set up correctly. There is another post on SO asking a similar question but that was a Ubuntu system where mine is Poky Linux. That solution suggested putting the startup script in a directory that does not exist on my system. There were other suggestions, putting it in rc.local, which I did and got the same result, it runs before Bluetooth is initialized.
Here is my script. My program is called nmea_thread and is run last. Everything else is initializing Bluetooth.
#!/bin/sh
/usr/sbin/rfkill unblock bluetooth
/usr/bin/hciconfig hci0 up
/usr/bin/hciconfig hci0 piscan
/usr/bin/hciconfig hic0 sspmode 0
/home/root/simpleAgent/simple-agent &
/home/root/nmea_thread
Often bluetooth is initialized asynchronously, so you can't be sure that your script will be run after hci0 is added. Good solution is to wait for BT initialization in background:
#!/bin/bash
if [ "$1" != "background" ]; then
$0 background &
else
#Wait until BT is initialized
for ((i = 0; i <= 100; i++)) do
hciconfig hci0 && break
usleep 100000
done
/usr/sbin/rfkill unblock bluetooth
/usr/bin/hciconfig hci0 up
/usr/bin/hciconfig hci0 piscan
/usr/bin/hciconfig hic0 sspmode 0
/home/root/simpleAgent/simple-agent &
/home/root/nmea_thread
fi
hciattach is the correct way.
syntax
hciattach /dev/ttyAMA0 bcm43xx 3000000
you need to flash the driver first before initializing it. Currently i don't remember how, but thats how i made it with raspberry pi and yocto.
Note if you use systemV, you can do call it from a script and it will work
Using SystemD, you need to make it in a service and wait. Falshing should be done in the two cases.

How to I detect whether a tty belonging to a gsm/3g-modem is a data or control port?

I'm currently writing a small tool for a linux router that sets up a wwan (gsm/3g) connection when I plug an appropriate modem into its USB port. When the device is plugged in several ttys are registered and I currently maintain a list of manufacturers and devices and which of their registered ttys is the control / data port.
If possible I want to get rid of this list and find a way to somehow probe the registered ttys directly to check if they are a control port or a data port.
I examined the sourcecode of wvdial and modem-manager to see how these tools detect the right port but was unable to find suitable information. I also tried to look for information in sysfs to distinguish the ports but this wasn't successful either.
You cannot detect this via external means. The common practise is either to setup udev rules for specific modem manufacturer and model. Or you can sequentially connect to each tty and verify via AT command what type of port it is.
In the case of udev rules you can follow this process:
1) Detect modem vid and pid
2) Based on vid/pid create symlinks in /dev/serial/by-id
For example a Sierra Wireless MC8795V modem with vid = 1199 and pid 683c. I know that port 3 is always the AT command channel. Therefore you could create a symlink post-fixed with -AT at the end.
In the case of detecting via AT commands the best and more common approach is to execute the AT command to see if the tty responds at all. You should get an echo back or an OK if your configured your modem not to echo.
For example:
AT
AT
OK
If you get a response this means you found either an AT control port or a PPP port. To check this simply execute a ATI command. If the response contains APP1, APP2, APP3 then you hit a PPP port. Otherwise you found your AT control port.
For example a AT control port:
ATI
Manufacturer: Sierra Wireless, Incorporated
Model: MC8795V
Revision: K2_0_7_46AP C:/WS/FW/K2_0_7_46AP/MSM6290/SRC 2010/10/27 22:15:30
IMEI: XXXXXXXXXXXXXXX
IMEI SV: 20
FSN: D9A2160146410
3GPP Release 6
+GCAP: +CGSM,+DS,+ES
OK
For example a PPP port:
ATI
Sierra Wireless, Incorporated
MC8795V
APP1
OK
A word of warning though. In the case of Sierra Wireless modules they clearly show which port is which. In the case of other manufacturers you'll need to check the USB interface guide to see if it is possible via ATI to take this approach.
I use this script to get Data and Control ports for 3g usb dongle.
#!/bin/sh
. /usr/share/libubox/jshn.sh
for a in `ls /sys/bus/usb/devices`; do
local vendor product
[ -z "$usb" -a -f /sys/bus/usb/devices/$a/idVendor -a -f /sys/bus/usb/devices/$a/idProduct ] || continue
vendor=$(cat /sys/bus/usb/devices/$a/idVendor)
product=$(cat /sys/bus/usb/devices/$a/idProduct)
echo Vendor $vendor, Product $product
[ -f /lib/network/wwan/$vendor:$product ] && {
usb=/lib/network/wwan/$vendor:$product
devicename=$a
echo usb: $usb devicename: $devicename
}
done
[ -n "$usb" ] && {
local old_cb control data
json_set_namespace wwan old_cb
json_init
json_load "$(cat $usb)"
echo "$(cat $usb)"
json_select
json_get_vars desc control data
json_set_namespace $old_cb
[ -n "$control" -a -n "$data" ] && {
ttys=$(ls -d /sys/bus/usb/devices/$devicename/${devicename}*/tty* | sed "s/.*\///g" | tr "\n" " ")
ctl_device=$(echo $ttys | cut -d" " -f $((control + 1)))
[ -n "$ctl_device" ] && ctl_device=/dev/$ctl_device
dat_device=$(echo $ttys | cut -d" " -f $((data + 1)))
[ -n "$dat_device" ] && dat_device=/dev/$dat_device
echo control_device: $ctl_device, data_device: $dat_device
}
}
Sample outputs:
Connected ZTE MF667
Vendor 1a40, Product 0101 #this is usb hub
Vendor 19d2, Product 0016
usb: /lib/network/wwan/19d2:0016 devicename: 1-1.2
{
"desc": "ONDA MF110/ZTE",
"control": 1,
"data": 2
}}
control_device: /dev/ttyUSB1, data_device: /dev/ttyUSB2
Connected Huawei E3131
Vendor 1a40, Product 0101 #this is usb hub
Vendor 12d1, Product 1506
usb: /lib/network/wwan/12d1:1506 devicename: 1-1.2
{
"desc": "Huawei E367/E398",
"control": 2,
"data": 0
}}
control_device: /dev/ttyUSB2, data_device: /dev/ttyUSB0
This works for me:
for device in $(mmcli -L | grep ModemManager | awk '{print $1}'); do
cport=$(mmcli -m $device | awk '/primary port:/{ print $NF }' | tr -d \')
ldevices=($(mmcli -m $device | grep "ports:" | pcregrep -o1 "(\w+) \(at\)"))
dport=$(echo "/dev/${ldevices[#]##$cport}")
[ -c $dport ] && echo $dport
done

Resources