Output of 'hcitool con' - bluetooth

How do I interpret the output of 'hcitool con'?
% hcitool con
Connections:
< ACL 00:11:22:33:44:55 handle 1 state 1 lm SLAVE AUTH ENCRYPT
More specifically, I would need details of the following parts:
handle:
This seems to be some enumeration of connections, but can I be confident that a new connection always get the lowest free 'handle' number? Does 'handle 0' indicate ongoing connection?
state:
That are the states and which numbers are they associated with? I've seen 1, 5, 8, and 9.
SLAVE:
Does this mean that the remote device is slave? Or the local?
This question is more or less stated (but not answered) here: Need detail explanation of Bluetooth command "hcitool con" and hcitool sr

hcitool was deprecated by the BlueZ project in 2017. If you are following a tutorial that uses it, there is a chance that it might be out of date.
bluetoothctl is the command line tool that should be used for connecting to remote devices.
There is also the btmgmt tool where you can can get information on the current connection with sudo btmgmt con.

Related

Correct way to turn on Bluetooth discovery on Ubuntu command line

Looks like there are two different options to put Bluetooth in discovery mode:
First method:
$ sudo bluetoothctl
#discoverable on
#pairable on
#agent on
#default-agent
Second method:
$ sudo hciconfig hci0 piscan
Second method seems to be simpler. Is there any problem in using the second method? When does the first method make sense?
The first method should be used going forward because hciconfig has been deprecated along with a few other command line tools. I believe they are still bundled in your OS either because you have an older version of the OS or maybe because there's a grace period before the tools are fully removed.
You can also use btmgmt to get your device to be discoverable/connectable/pairable. The difference is that btmgmt is considered to be more system related while bluetoothctl is application-related. See this answer below for more information:-
Raspberry BLE Encryption / Pairing

BlueZ remote device presence

Using BlueZ, which
is the official Linux Bluetooth stack
I'd like to know which of the below two methods are better suited for detecting a device's presence in the nearby.
To be more exact, I want to periodically scan for a Bluetooth device (not BLE => no advertisement packets are sent).
I found two ways of detecting it:
1.) Using l2ping
# l2ping BTMAC
2.) Using hcitool
# hcitool name BTMAC
Both approaches working.
I'd like to know, which approach would drain more battery of the scanned device?
Looking at solution #1 (l2ping's source):
It uses a standard socket connect call to connect to the remote device, then uses the send command to send data to it:
send(sk, send_buf, L2CAP_CMD_HDR_SIZE + size, 0)
Now, L2CAP_CMD_HDR_SIZE is 4, and default size is 44, so altogether 48 bytes are sent, and received back with L2CAP_ECHO_REQ.
For hcitool I just have found the entrypoint:
int hci_read_remote_name(int dd, const bdaddr_t *bdaddr, int len, char *name, int to);
My questions:
which of these approaches are better (less power-consuming) for the remote device? If there is any difference at all.
shall I reduce the l2ping's size? What shall be the minimum?
is my assumption correct that hci_read_remote_name also connects to the remote device and sends some kind of request to it for getting back its name?
To answer your questions:-
which of these approaches are better (less power-consuming) for the remote device? If there is any difference at all.
l2ping BTMAC is the more suitable command purely because this is what it is meant to do. While "hcitool name BTMAC" is used to get the remote device's name, "l2ping" is used to detect its presence which is what you want to achieve. The difference in power consumption is really minimal, but if there is any then l2ping should be less power consuming.
shall I reduce the l2ping's size? What shall be the minimum?
If changing the l2ping size requires modifying the source code then I recommend leaving it the same. By leaving it the same you are using the same command that has been used countless times and the same command that was used to qualify the BlueZ stack. This way there's less chance for error and any change would not result in noticeable performance or power improvements.
is my assumption correct that hci_read_remote_name also connects to the remote device and sends some kind of request to it for getting back its name?
Yes your assumption is correct. According the Bluetooth Specification v5.2, Vol 4, Part E, Section 7.1.19 Remote Name Request Command:
If no connection exists between the local device and the device
corresponding to the BD_ADDR, a temporary Link Layer connection will
be established to obtain the LMP features and name of the remote
device.
I hope this helps.

USB bluetooth dongle with PuTTY

I have a USB Bluetooth dongle that I am trying to use in order to extract information from an ELM327 OBD-II interface.
I am trying to communicate with the ELM327 through PuTTY. According to the ELM327 documentation, I need to use baud rate 38,400 if the PP 0C pin hasn't been changed or 9,600 if pin 6 = 0 V.
I tried setting PuTTY according to the Device Manager details with:
Baud rate 9,600 or 38,400
8 data bits
No parity
1 stop bits
No flow control
When I open PuTTY, the window is blank, and I cannot send commands to the device.
What could be the issue here?
Your problem might be with PuTTY and Windows 10. Neither PuTTY nor Hyperterminal allowed me to connect to my ELM327 on Windows 10 (I am using the USB connection for talking to ELM327). It might be some kind of problem of these software on the latest version on Windows.
Looking for a similar software that works well on Windows 10 I found RealTerm. You can download it from this link. A brief tutorial about how to use RealTerm is available here (pay attention to the procedure to open a serial port by clicking twice on the button "open", an how to send commands from the send tab).
After downloading it, just configure your serial connection with the values you were using:
Baud rate 38,400 (or 9,600)
8 data bits
No parity
1 stop bits
No flow control
Also, do not forget to add a CR (carriage return) at the end of the commands you send to the ELM327, if you forget it, the ELM327 will ignore the commands. You can do it by clicking on the EOL options shown in the figure below.
This solved my problem and now I am able to talk to the ELM327 and receive its answers, e.g. the commands atz returns the ELM327 version. The OBD2 command 0100 returns the PIDs available on a car's ECU. I don't know why but the CR is shown on the RealTerm display and hides some characters (as it happens with the 'a' of the "atz" command in the figure).
I hope this helps you.

How to initiate BLE pairing on BlueZ

I want to initiate pairing on Bluez with a Bluetooth Low Energy device.
While there are some posts on how to trigger the SMP procedures using GATT, there is not much available if you do not want to use GATT.
My use case is that I want to use an encrypted link for bluetooth-6lowpan which exchanges data over L2CAP credit based mode and not ATT/GATT.
Further, I would like to use the OOB mode for SMP pairing.
Pointers on how I could trigger SMP pairing either using command line or writing a C program is appreciated.
Thank you!
I don't think it's possible to perform BLE pairing without the use of GATT commands (from the command line only). The reason for this is that security in LE is GATT-action-based. In other words, the characteristic/service permissions dictate whether you need to pair with the device or not (i.e. to read the heart rate characteristic, the device might dictate that you need to be paired first). For this, the operation would be something like:
gatttool --sec-level=high --device=00:11:22:33:44:55:66 --char-read --uuid=0x2A37
This command will establish pairing first before reading the characteristic.
As for how to perform this using a C program, You can download the BlueZ source code and have a look at what passing this "sec-level" option does. I've quickly browsed through the code and found this in utils.c:-
chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err,
BT_IO_OPT_SOURCE_BDADDR, &sba,
BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
BT_IO_OPT_DEST_BDADDR, &dba,
BT_IO_OPT_DEST_TYPE, dest_type,
BT_IO_OPT_CID, ATT_CID,
BT_IO_OPT_SEC_LEVEL, sec,
BT_IO_OPT_INVALID);
where sec is set with sec = BT_IO_SEC_HIGH;
I hope this helps.

Controlling a USB power supply (on/off) with Linux

Is it possible to turn on/off power supplies from USB manually with Linux?
There's this external USB cooling fan (the kind you use to cool yourself off, not the PC), and it would be nice to be able to control it from the terminal, because I want to position the fan somewhere far away.
I suppose this could also be useful for a variety of other things as well, because there's a lot of USB toys out there. Maybe air purifiers, etc. (I heard they don't really work though).
According to the docs, there were several changes to the USB power management from kernels 2.6.32, which seem to settle in 2.6.38. Now you'll need to wait for the device to become idle, which is governed by the particular device driver. The driver needs to support it, otherwise the device will never reach this state. Unluckily, now the user has no chance to force this. However, if you're lucky and your device can become idle, then to turn this off you need to:
echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend"
echo "auto" > "/sys/bus/usb/devices/usbX/power/level"
or, for kernels around 2.6.38 and above:
echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend_delay_ms"
echo "auto" > "/sys/bus/usb/devices/usbX/power/control"
This literally means, go suspend at the moment the device becomes idle.
So unless your fan is something "intelligent" that can be seen as a device and controlled by a driver, you probably won't have much luck on current kernels.
Note. The information in this answer is relevant for the older kernels (up to 2.6.32). See tlwhitec's answer for the information on the newer kernels.
# disable external wake-up; do this only once
echo disabled > /sys/bus/usb/devices/usb1/power/wakeup
echo on > /sys/bus/usb/devices/usb1/power/level # turn on
echo suspend > /sys/bus/usb/devices/usb1/power/level # turn off
(You may need to change usb1 to usb n)
Source: Documentation/usb/power-management.txt.gz
PowerTOP from Intel allows you to toggle devices such as usb peripherals in real-time. These are called 'tunables'.
sudo apt install powertop
sudo powertop
Tab over to 'tunables'.
Scroll down to your device.
Hit enter to toggle power saving mode (Good/Bad)
Note that Bad means the device is always on. Toggling to Good will turn off the device after the preset inactive saving time (default is 2000ms).
See the PowerTOP docs for details on how to make these changes permanent.It generates the config scripts for you (pretty much as described by other posters on this thread).
NOTE: These scripts do not affect USB pin power (which is always on).
These only send the driver protocol to activate and deactivate a device.
If you want to control pin power, you could use either a supported smart USB hub, or better yet a microcontroller.
I have found these solutions that at least work for properly configured Terminus FE 1.1 USB hub chip:
1.To turn off power on all USB ports of a hub, you may unbind the hub from kernel using:
echo "1-4.4.4" > /sys/bus/usb/drivers/usb/unbind
to turn power back on - you may bind it back using
echo "1-4.4.4" > /sys/bus/usb/drivers/usb/bind
2.Switching power at each port individually is trickier: I was able to use hubpower to control each port - but it comes with a downside: hubpower first disconnects the usbdevfs wich causes all of the USB devices to disconect from system, at least on ubuntu:
usb_ioctl.ioctl_code = USBDEVFS_DISCONNECT;
rc = ioctl(fd, USBDEVFS_IOCTL, &usb_ioctl);
With this ioctl disabled I was able to switch off individual port power without detaching all devices - but the power goes back on immediately (probably due to kernel seeing an uninitialized device) which causes USB device just to do a "cold restart" which is what I generally wanted to do. My patched hubpower is here
You could use my tool uhubctl to control USB power per port for compatible USB hubs.
I wanted to do this, and with my USB hardware I couldn't. I wrote a hacky way how to do it here:
http://pintant.cat/2012/05/12/power-off-usb-device/ .
In a short way: I used a USB relay to open/close the VCC of another USB cable...
echo '2-1' |sudo tee /sys/bus/usb/drivers/usb/unbind
works for ubuntu
The reason why folks post questions such as this is due to the dreaded- indeed "EVIL"- USB Auto-Suspend "feature".
Auto suspend winds-down the power to an "idle" USB device and unless the device's driver supports this feature correctly, the device can become uncontactable. So powering a USB port on/off is a symptom of the problem, not the problem in itself.
I'll show you how to GLOBALLY disable auto-suspend, negating the need to manually toggle the USB ports on & off:
Short Answer:
You do NOT need to edit "autosuspend_delay_ms" individually: USB autosuspend can be disabled globally and PERSISTENTLY using the following commands:
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/&usbcore.autosuspend=-1 /' /etc/default/grub
update-grub
systemctl reboot
An Ubuntu 18.04 screen-grab follows at the end of the "Long Answer" illustrating how my results were achieved.
Long Answer:
It's true that the USB Power Management Kernel Documentation states autosuspend is to be deprecated and in in its' place "autosuspend_delay_ms" used to disable USB autosuspend:
"In 2.6.38 the "autosuspend" file will be deprecated
and replaced by the "autosuspend_delay_ms" file."
HOWEVER my testing reveals that setting usbcore.autosuspend=-1 in /etc/default/grub as below can be used as a GLOBAL toggle for USB autosuspend functionality- you do NOT need to edit individual "autosuspend_delay_ms" files.
The same document linked above states a value of "0" is ENABLED and a negative value is DISABLED:
power/autosuspend_delay_ms
<snip> 0 means to autosuspend
as soon as the device becomes idle, and negative
values mean never to autosuspend. You can write a
number to the file to change the autosuspend
idle-delay time.
In the annotated Ubuntu 18.04 screen-grab below illustrating how my results were achieved (and reproducible), please remark the default is "0" (enabled) in autosuspend_delay_ms.
Then note that after ONLY setting usbcore.autosuspend=-1 in Grub, these values are now negative (disabled) after reboot. This will save me the bother of editing individual values and can now script disabling USB autosuspend.
Hope this makes disabling USB autosuspend a little easier and more scriptable-
I had a problem when connecting my android phone, I couldn't charge my phone because the power switch on and then off ...
PowerTop let me find this setting and was useful to fix the issue ( auto value was causing issue):
echo 'on' | sudo tee /sys/bus/usb/devices/1-1/power/control
USB 5v power is always on (even when the computer is turned off, on some computers and on some ports.) You will probably need to program an Arduino with some sort of switch, and control it via Serial library from USB plugged in to the computer.
In other words, a combination of this switch tutorial and this tutorial on communicating via Serial libary to Arduino plugged in via USB.
So far I came to the conclusion that you cannot control the power of a USB port. The 5V USB is always provided, and it's up to the device to use it or not. You can check this with a 5V fan or light.
I've tried various methods (disconnect/reconnect/bind/unbind/reset signal). Best so far are bind/unbind as it forces a cold restart of the device (but no power cycle).
I came up with a solution to reset USB devices, ports and controllers in a python script, which supports all of the above methods.
You can find the script at my Github page
Usage:
usb_reset.py -d 8086:1001 --reset-hub
The script uses among others the following solution to reset USB hubs/controllers:
Unbindind a USB port / controller works best via:
echo "myhub" > "/sys/bus/usb/drivers/usb/unbind"
echo "myhub" > "/sys/bus/usb/drivers/usb/bind"
Where myhub is found in /sys/bus/usb/devices/*
Or litteral controllers:
echo "mycontroller" > "/sys/bus/pci/drivers/unbind"
echo "mycontroller" > "/sys/bus/pci/drivers/bind"
Where mycontroller is found in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*

Resources