I would appreciate advice on how to query an Edison Bluetooth HCI controller to return absolute Bluetooth RSSI levels, rather than ones measured as a deviation from the Golden Receive Power Range. I am writing an application in c++ using the Eclipse IDE and default libraries from the Intel website, which I understand includes the BlueZ protocol stack.
By way of background, the Bluetooth specification provides two formats for reporting RSSI in response to an HCI_Read_RSSI command. An LE controller returns absolute power level in db. A BR/EDR controller returns a value of 0db if the received power level is within the Golden Receive Power Range; otherwise, it returns a value that is the amount in db that the measured power is outside the Golden Receive Power Range. (See, e.g., Bluetooth Specification Version 4.2 [Vol 2, Part E], pp806-807, attached.)
I would like to access the absolute power measurement but have yet to find a way. I have accessed RSSI in what appears to be the BR/EDR format using a function in the hci.h library (part of Intel's default libraries that download with the Eclipse IDE) called "hci_read_rssi". (See hci_read_rssi.tiff, attached, which is from the source file hci.c). The hci.h library offers what appears to be a number of LE-specific commands, but not an LE command for reading RSSI. For example, the hci.h library includes two commands for creating connections: hci_create_connection and hci_le_create_conn. Presumably one follows a BR/EDR protocol, while the other follows an LE protocol. I did not find anything like an "hci_le_read_rssi" function.
I suspect it is possible to get absolute power, either as specified for an LE controller or perhaps through an "undocumented feature." The le.c library (also part of the default Eclipse library) hints that there may be a different command code to query for the LE format. Intuition tells me there is probably a convenient hook that I have not found, and I thought it worth asking the experts.
Any enlightenment would be appreciated.
P.s., as a small side question, I would be grateful if someone could confirm some terminology: once the hci_create_connection command completes successfully to a remote device, is it correct to say that remote device is now in the initiating device's "piconet"?
Thank you very much for the detailed explanation, I have seen some comments before regarding the RSSI value obtained through this library.
I'm not sure if you have already tried with the methods provided in the following links:
You can also try with python, https://pybluez.googlecode.com/svn/trunk/examples/advanced/inquiry-with-rssi.py https://pybluez.googlecode.com/svn/trunk/examples/advanced/inquiry-with-rssi.py, please let me know if there is a difference while using this one.
Regarding the hci_create_connection command, look at this document: http://affon.narod.ru/BT/bluetooth_app_c10.pdf http://affon.narod.ru/BT/bluetooth_app_c10.pdf (page 33/242)
Thanks for following up. The Python reference is helpful for another task (more on that as a postscript below), but not the RSSI question, because the Python script appears to exercises the same bluetooth controller interface I have been exercising using c++.
I now hypothesize that the format of the RSSI value is context dependent. The Bluetooth specification permits two types of devices: "BR" (basic rate) and "LE" (low energy). Connections between devices may be of different types, depending on whether the devices are following the BR or LE portion of the specification. Some devices, like Edison, support both. If the connection for which RSSI is being read is a "BR" connection created using the hci_create_connection command, a subsequent hci_read_rssi command would return rssi in the BR (Golden Range) format. On the other hand, if the connection is a "LE" connection created using the different, le_create_connection command, a subsequent hci_read_rssi command would return RSSI in the absolute value format, even though the same command is used to read rssi in both contexts. If there is any kind of a switch or option to get an absolute value RSSI reading for a BR connection, it is perhaps known only to the Edison system integrators. If it is possible to ask the system integrators, that might put the question to rest forever.
I haven't had time to test this hypothesis but hope to and will report back when I do. In the meantime, I will share below some supporting research in case anyone else in the Edison community might be interested. What seems certain is:
(1) The Bluetooth specification defines requirements for devices that claim to be both Basic Rate and Low Energy compliant, such as the Edison. See "BT Spec 86," attached.
(2) The Bluetooth specification requires all Basic Rate (BR) controllers to report RSSI using the "Golden Range" format, and all Low Energy (LE) devices to report RSSI in absolute value (if, as in the case with Edison, the LE controller supports transmitting and receiving data packets). See "BT Spec 765," attached. "C3" means the controller supports packets.
(3) Intel integrated lower portions of the BlueZ protocol stack into Edison's Linux kernel, including the HCI controller. See "Intel Bluetooth Integration". The BlueZ, hci.h library is the application interface to the HCI controller. All we see from the hci.c library is that the application-level function, hci_read_rssi, fires off a hex command (OCF 0x0005) to the lower levels, and the function returns whatever RSSI value comes up from the kernel. Somewhere in between, the hardware makes an RSSI measurement.
The kernel probably decides whether to return BR- or LE- formatted rssi to the hci_read_rssi function, because the radio chipset likely returns only an absolute power measurement useful for both contexts. We might explore the voluminous, BlueZ, kernel-level source code, but even that might not provide a definitive answer, because the system integrators might have made modifications for the specific Edison radio chipset.
Postscript: I would be grateful if someone might point me at some suggestions on how my application could be interrupted by, or monitor for, unscheduled events reported from the HCI controller to the HCI host. HCI commands initiated from my application often trigger events, so those are automatically reported to the application as a return for the command. But other events are initiated from outside the application, like when an Edison receives a request to make a connection. I would like my application either to be interrupted when such non-application-initiated events occur, or at least to be able to check periodically for any such events. Thanks!
Have you been able to work on this? Do you have some updates or improvements?
In order to monitor your application, have you tried by running in parallel hcidump or by checking all the processes on the board? You can also try with dmesg.
On the RSSI question, it appears that the RSSI format is context dependent based on the type of connection. I've now observed some RSSI values for low energy connections, and the reported values are much lower than for BR/EDR connections and always below zero (0) db. The highest value I observed was about -30 db with two Edison's side by side. This presumably was an absolute power measurement and not a "Golden Range" measurement. Low energy transmit power is lower than BR/EDR transmit power, but I would expect at that distance that even a low-energy connection would be well within the receiver's optimum operational range, and hence withing the Golden range, but that is an unsupported assumption. For example, if the Golden Range for Edison were -40 db to + 10 db (absolute), the Edison HCI controller would report a measurement of -30db (absolute) as zero (0) db (Golden Range). But since I don't know the receiver upper-and lower range values, I see no way to relate the two measurements. Anyway, I will accept reality and proceed accordingly.
On monitoring for Bluetooth events that are sourced from outside my application, like BT connection requests from other devices, BlueZ appears to have made somewhat recent changes to this process in going to Version 5 and appears to be trying to standardize around D-Bus procedures (with which I have no prior experience). See http://www.bluez.org/bluez-5-api-introduction-and-porting-guide/ BlueZ " Blog Archive " BlueZ 5 API introduction and porting guide My application now directs commands to the HCI controller through a socket invoked in the following call from library file hci.c:
dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); ).
When my application initiates commands to the HCI controller, it directs them to this socket, and my application receives some information about responsive events as returns to the commands. However, hcidump reveals messages that the HCI controller sources independently of any application command, and it is those independent message that I want to capture in my application. I am not clear on the relationship between this socket and any channel (such as a D-Bus instance) on which the HCI controller might be sending event messages. That is, can I change settings on the socket and listen for independent events, or do I have to separately register on a D-Bus instance, or is this distinction an entirely wrong way of thinking about the process?
Life is a learning process.
Thanks again for all your help.
Thank you for the update. I will investigate if it is necessary to change the settings on the socket and how to receive the independent messages, as soon as I get some information I will post it here.