How can a scannable BLE beacon be implemented using the bluez stack? - rust

I'm trying to implement a BLE beacon which allows for additional information to be requested.
My understanding so far is that in BLE, a device can broadcast advertisement packets. An advertisement packet can indicate that the device is scannable. This means that a client can send a scan request to the beacon. A scan response can then be sent by the beacon, containing additional information.
So the exchanged packets would look like this: ADV_SCAN_IND -> SCAN_REQ -> SCAN_RSP.
I'm trying to understand how the beacon implementation should behave. Is this something implemented by the adapter (I would have to specify upfront the data to send back in a scan response)? Or should the beacon listen for SCAN_REQ packets and broadcast a SCAN_RSP when it sees one?
I've been looking for libraries to use in Rust or Go, however support for developing a BLE peripheral seems to be lacking when using bluez in those languages.
I'm fine with answers in any programming language / library, as long as it works on Linux
The closes I've gotten so far is using bluer for Rust.
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let session = bluer::Session::new().await?;
let adapter = session.default_adapter().await?;
adapter.set_powered(true).await?;
println!(
"Advertising on Bluetooth adapter {} with address {}",
adapter.name(),
adapter.address().await?
);
let mut data = BTreeMap::new();
data.insert(0, vec![1, 2, 3]);
let le_advertisement = Advertisement {
advertisement_type: bluer::adv::Type::Broadcast,
local_name: Some("le_advertise".to_string()),
advertisting_data: data,
..Default::default()
};
println!("{:?}", &le_advertisement);
let handle = adapter.advertise(le_advertisement).await?;
std::thread::sleep(std::time::Duration::from_secs(30));
println!("Removing advertisement");
drop(handle);
Ok(())
}
This works for broadcasting an advertisement. I can see it on my phone using nRF Connect.
However I cannot find a way to respond to scan requests, nor a way to indicate that the beacon can be scanned.

Starting with the theoretical part, you are right about your understanding of the scan response. The official definition from the Bluetooth SIG is (Bluetooth Core Specification v5.4, Vol 1, Part A, section 4.2.2.2):-
Advertising devices may receive scan requests from listening devices
in order to get additional user data from the advertising device. Scan
responses are sent by the advertising device to the device making the
scan request.
And this is also mentioned here (Bluetooth Core Specification v5.4, Vol 1, Part A, section 3.3.2.2.2):-
Some advertising events sent by the advertising device permit the
listening device (scanner) to concurrently send scan requests or
connection requests packets on the same advertising PHY channel in
which the advertising packet was received. The advertising device can
send a scan response packet again on the same advertising PHY channel
within the same advertising event.
Scan responses are usually set before a device even starts advertising, however, it is permitted that the scan response is set or changed when the device has already started advertising. This is mentioned in the Bluetooth Specification v5.4, Vol 4, Part E, 7.8.8 LES Set Scan Response Data command:-
If advertising is currently enabled, the Controller shall use the new
data in subsequent advertising events. If an advertising event is in
progress when this command is issued, the Controller may use the old
or new data for that event. If advertising is currently disabled, the
data shall be kept by the Controller and used once advertising is
enabled.
The default Scan_Response_Data_Length shall be zero and the default
Scan_Response_Data shall be 31 zero octets.
As for the practical part, you can easily send scan reports using the btmgmt tool and the following command on Linux:-
sudo btmgmt add-adv -d 02010606084142434400 -s 080954657374204C45
Where the -d option is for setting the advert data, and the -s is for setting the scan response data. The full list of btmgmt add-adv options are:-
Usage: add-adv [options] <instance_id>
Options:
-u, --uuid <uuid> Service UUID
-d, --adv-data <data> Advertising Data bytes
-s, --scan-rsp <data> Scan Response Data bytes
-t, --timeout <timeout> Timeout in seconds
-D, --duration <duration> Duration in seconds
-P, --phy <phy> Phy type, Specify 1M/2M/CODED
-c, --connectable "connectable" flag
-g, --general-discov "general-discoverable" flag
-l, --limited-discov "limited-discoverable" flag
-n, --scan-rsp-local-name "local-name" flag
-a, --scan-rsp-appearance "appearance" flag
-m, --managed-flags "managed-flags" flag
-p, --tx-power "tx-power" flag
e.g.:
add-adv -u 180d -u 180f -d 080954657374204C45 1
BLE data in adverts is decoded as follows (based on the Assigned Numbers Document):-
1st byte = length (n bytes)
2nd byte = Types
n-1 bytes = actual data
So the meaning of the advert data I added:-
02 Length (2 bytes)
01 Type (Flags)
06 Flag - 02 && 04 LE General Discoverable && BR/EDR Not supported
06 Length (6 bytes)
08 Type (Shortened Local Name)
4142434400 (ABCD)
And the meaning of the scan response data is:-
08 Length (8 bytes)
09 Type (Complete Local Name)
54657374204C45 (Test LE)
Some more useful links:-
Bluetooth 4.0 scan response
btmgmt add-adv command not working
BLE advertising raw data - how to decode

As you have said that you will accept answers using any programming language/library -- I'd like to point you to the Qt framework. In particular the Qt connectivity module and its bluetooth component. The ask is for a bluez implementation: on Linux, the Qt bluetooth module is a C++ wrapper around bluez. Here's an example excerpt in which both advertising data and scan response data are configured.
QLowEnergyAdvertisingData advertisingData;
QLowEnergyAdvertisingData scanResponseData; // <- added to original example
advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
advertisingData.setIncludePowerLevel(true);
advertisingData.setLocalName("HeartRateServer");
advertisingData.setServices(QList<QBluetoothUuid>() << QBluetoothUuid::ServiceClassUuid::HeartRate);
scanResponseData.setManufacturerData(0x1234, QByteArray("Hello")); // <- added to example
bool errorOccurred = false;
const QScopedPointer<QLowEnergyController> leController(QLowEnergyController::createPeripheral());
auto errorHandler = [&leController,&errorOccurred](QLowEnergyController::Error errorCode)
{
qWarning().noquote().nospace() << errorCode << " occurred: "
<< leController->errorString();
if (errorCode != QLowEnergyController::RemoteHostClosedError) {
qWarning("Heartrate-server quitting due to the error.");
errorOccurred = true;
QCoreApplication::quit();
}
};
QObject::connect(leController.data(), &QLowEnergyController::errorOccurred, errorHandler);
QScopedPointer<QLowEnergyService> service(leController->addService(serviceData));
leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,
scanResponseData); // <- modified from original example
The above example illustrates how bluetooth stacks generally implement the scan response (specifically, note the second line and the last line in the example). Full source for the example is at https://code.qt.io/cgit/qt/qtconnectivity.git/tree/examples/bluetooth/heartrate-server/main.cpp?h=6.4 and is available under BSD license (note, however, the above excerpt was modified to highlight how to set the scan response).
I've verified the above code on RPi, and I can see that the resulting BTLE advertisement has the added mfr data using NRFConnect. To replicate my results on rpi:
sudo apt install qt5-default qtcreator qtconnectivity5-examples qtconnectivity5-dev
copy the examples to somewhere you can work on them (e.g. mkdir test && cd test && cp -R /usr/lib/arm-linux-gnueabihf/qt5/examples .) [I used an old rpi I had laying around -- yours may be newer and thus the examples will live in a different directory by default]
edit the example code (e.g. cd examples/bluetooth/heartrate-server && vim main.cpp) -- make the 3 edits I indicate above
qmake heartrate-server.pro
make
sudo ./heartrate-server
This example does not implement a beacon per se. However, the advertising portion of a ble device is largely the same whether the device is a beacon (advertising only) or if it has a service (or services). Connectability and the ability to respond to a scan request are orthoganal traits for a ble device. If you never connect to the toy service in the example, then it is functionally a beacon. In practice, commercial beacons do implement a service -- for the ower of the beacon to use when updating the info that the beacon is meant to convey to passers-by.
In any case, the above method would be employed when implementing a device that is strictly a beacon. Furthermore, you've indicated that you want to implement 'a beacon' but have given no further info to go on as to what type of beacon. Typically, one implements an iBeacon or an EddyStone beacon -- of course the BLE spec is open enough to allow you to invent your own beacon, too.
To answer your question about how the beacon implementation should behave: The scan response packet has the same structure as the advertisement packet, and it is normally configured at the same time that the advertisement data is configured. The Nordic stack, for example, works this way. Obviously, you can see above that's also how QT does it.
The raw linux HCI interface does it only slightly differently in that one must specify the scan response as a separate command, but the payload has the same format as the advertising data setup. Both the adv data and the scan response data are set up during the process of enabling advertising.
In general, your bluetooth package should enable you to set the scan response in a similar way to how you set the advertising data -- the two are quite closely linked. I'm much more familiar with the Nordic (softdevice) implementation, and on that particular platform one does have the option of fielding the SCAN_REQ event. That being said, the normal way to do things is to set up the scan response data ahead of time. From Linux userland, I doubt you can do anything else: the BTLE implementation needs to send the scan response pretty quickly after receiving the SCAN_REQ so there's no time for a round trip to userland. That data needs to be already in a buffer on the kernel side.
In your project, you need to do 2 things: First, indicate that your device can respond to the scan request. In the qt api, one does this with QLowEnergyAdvertisingParameters. Second, you need to provide the actual scan resonse data (see above).
Let's say you want to extend your rust package to provide the missing scan response function. One could do so by emulating the Qt implementation. If you dig around in the Qt implementation, you can (eventually) have a look at the implementation of QLeAdvertiserBluez; the method of interest is setScanResponseData which, in turn, delegates to setData. The call to setData is made with isScanResponsedata set to true, resulting in the OcfLeSetScanResponseData command being sent to the linux hci (along with the data in the object passed as the scan response). https://code.qt.io/cgit/qt/qtconnectivity.git/tree/src/bluetooth/qleadvertiser_bluez.cpp?h=5.15 line 339. OcfLeSetScanResponseData turns out to be opcode command field 0x9, which is passed to Qt's HciManager, and thence (via socket) to the linux HCI driver.
ocf 0x9 corresponds to
#define HCI_OP_LE_SET_SCAN_RSP_DATA 0x2009
struct hci_cp_le_set_scan_rsp_data {
__u8 length;
__u8 data[HCI_MAX_AD_LENGTH];
https://github.com/torvalds/linux/blob/master/include/net/bluetooth/hci.h Line 1651
So -- this is all doable. Qt obviously does it. What I can't figure out is why your Rust package did not expose this rather fundamental capability. And the BlueZ 'documentation' remains an impenetrable morass. Every time I think I want to use the userspace BlueZ stuff, I give up and just use the structure definitions from hci.h
[Edit]
While following up some dangling leads from the above research I found an alternate C API that may also be of interest. This one is direct from the bluez folks, but has a couple of major downsides. https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/shared That's bluez.git:src/shared -- apparently it is an unofficial API with no stability guarantees. Also, documentation for it appears to be thin to the point of non-existence (no worries, though -- code is self documenting, right?). There is an example at https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/tools/eddystone.c (bluez.git:tools/eddystone.c) which could probably be altered to make a beacon with a scan response. Look at adv_tx_power_callback in eddystone.c -- one could construct a bt_hci_cmd_le_set_scan_rsp_data struct, build the data array to contain a valid manufacturer info block (or a local name, or any other valid adv block), and then send the new struct with bt_hci_send(..., BT_HCI_CMD_LE_SET_SCAN_RSP_DATA,...)
[Final Edit]
Well, I've gotten pretty wrapped around this thing. But, for the sake of completeness: here is a full, working example of a pure (not connectable) eddystone beacon that also sends a response to the scan request. This, obviously is derived from the Qt example. It can be dropped into the above referenced heartrate server example, just replace main.cpp with this code.
In this example, I explicitly set the advertising parameters to indicate that the beacon is not connectable, but can respond to the scan request.
/***************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtBluetooth/qlowenergyadvertisingdata.h>
#include <QtBluetooth/qlowenergyadvertisingparameters.h>
#include <QtBluetooth/qlowenergycharacteristic.h>
#include <QtBluetooth/qlowenergycharacteristicdata.h>
#include <QtBluetooth/qlowenergydescriptordata.h>
#include <QtBluetooth/qlowenergycontroller.h>
#include <QtBluetooth/qlowenergyservice.h>
#include <QtBluetooth/qlowenergyservicedata.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qlist.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qtimer.h>
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
QCoreApplication app(argc, argv);
//! [Advertising Data]
QLowEnergyAdvertisingData advertisingData;
QLowEnergyAdvertisingData scanRespData;
uint8_t es2[21]; // eddystone advertising block -- taken from bluez eddystone example
es2[0] = 0x02; /* Field length */
es2[1] = 0x01; /* Flags */
es2[2] = 0x04; /* BR/EDR Not Supported */
es2[3] = 0x03; /* Field length */
es2[4] = 0x03; /* 16-bit Service UUID list */
es2[5] = 0xaa; /* Eddystone UUID */
es2[6] = 0xfe;
es2[7] = 0x0c; /* Field length */
es2[8] = 0x16; /* 16-bit Service UUID data */
es2[9] = 0xaa; /* Eddystone UUID */
es2[10] = 0xfe;
es2[11] = 0x10; /* Eddystone-URL frame type */
es2[12] = 0x00; /* Calibrated Tx power at 0m */
es2[13] = 0x00; /* URL Scheme Prefix http://www. */
es2[14] = 'b';
es2[15] = 'l';
es2[16] = 'u';
es2[17] = 'e';
es2[18] = 'z';
es2[19] = 0x01; /* .org/ */
es2[20] = 0x00; /* Field terminator */
advertisingData.setRawData(QByteArray((const char*)es2, 21));
scanRespData.setManufacturerData(0x1234, QByteArray("hello"));
//! [Advertising Data]
//! [Start Advertising]
const QScopedPointer<QLowEnergyController> leController(QLowEnergyController::createPeripheral());
//const QScopedPointer<QLowEnergyService> service(leController->addService(serviceData));
auto advParams = QLowEnergyAdvertisingParameters();
advParams.setMode(QLowEnergyAdvertisingParameters::AdvScanInd);
leController->startAdvertising(advParams, advertisingData,
scanRespData /*advertisingData*/);
//! [Start Advertising]
auto reconnect = [&leController, advertisingData, scanRespData, advParams]() {
leController->startAdvertising(advParams, advertisingData,
scanRespData);
};
QObject::connect(leController.data(), &QLowEnergyController::disconnected, reconnect);
return app.exec();
}

Related

Ethtool Structs elements and what are they. What settings and info defined on them

I am reading driver code from Intel E1000E AND Realtek r1869 driver. I hvae the devices for both,
Currently I am studying ethtool_ops. I know Ethtool can be a tool for
Long story short, ethtool is a means to display and adjust generic NIC/driver parameters
(identification, the number of receive and transmit queues, receive and transmit offloads, you > name it) in a userspace application
But if you look at the struct ethtool_ops not everythhing is crystal clear
Below is a Ethtool struct
static const struct ethtool_ops rtl8169_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES,
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
.get_link = ethtool_op_get_link,
.get_coalesce = rtl_get_coalesce,
.set_coalesce = rtl_set_coalesce,
.get_regs = rtl8169_get_regs,
.get_wol = rtl8169_get_wol,
.set_wol = rtl8169_set_wol,
.get_strings = rtl8169_get_strings,
.get_sset_count = rtl8169_get_sset_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
.get_ts_info = ethtool_op_get_ts_info,
.nway_reset = phy_ethtool_nway_reset,
.get_eee = rtl8169_get_eee,
.set_eee = rtl8169_set_eee,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
};
What I don't get it is some info on this page, for example, show doing settings. But when you look at the struct much make no sense https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/monitoring-and-tuning-the-rx-ring-buffer_configuring-and-managing-networking
https://linoxide.com/linux-how-to/ethtool-command-with-examples/
So I like to know what if I have to do these following thinges using ethtool userspace application. then which ethtool_ops function handlers this
Displaying the number of dropped packets: I for that I have .get_ethtool_stats = rtl8169_get_ethtool_stats, in r8169 driver from RealTek. Correct me if I am wrong that this info managed by kernel stack.
Increasing the RX ring buffer to reduce a high packet drop rate. I couldn't figure out which member of struct ethtool_ops handles this
Flow control in full duplex can be enabled by 'PAUSE' parameter in the latest MAC and GMAC embedded devices.
Set Duplex Mode
Which function handlers transmit offloads like Transmit segmentation offload for group sending of packets
TCP segmentation Offload.
Also what is ksettings operation in the struct
Check with ethtool -h which command is responsible for the respective action
Check in ethtool source code how command is handled
Check in net/ethtool/ on the kernel side
And a general hint: Basically no network driver implements all ethtool functionalities.

What is ethtool and is it important for usable ethernet NIC. Can I remove it from device driver and still able to use network

I am studying realtek device driver and came across ethtool operations like ethtool_ops there are many operation included in the operations object. Following is the code
static const struct ethtool_ops rtl8169_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES,
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
.get_link = ethtool_op_get_link,
.get_coalesce = rtl_get_coalesce,
.set_coalesce = rtl_set_coalesce,
.get_regs = rtl8169_get_regs,
.get_wol = rtl8169_get_wol,
.set_wol = rtl8169_set_wol,
.get_strings = rtl8169_get_strings,
.get_sset_count = rtl8169_get_sset_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
.get_ts_info = ethtool_op_get_ts_info,
.nway_reset = phy_ethtool_nway_reset,
.get_eee = rtl8169_get_eee,
.set_eee = rtl8169_set_eee,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
};
What are these operations
for example there is eee mentioned so I am interested in what its matching functionality with higher level layers like ip or tcp.
What are these: coalesce, wol, stats, ksettings, ts_info and eee from list above. I believe they have something to do with physical layer of OSI model, But if u can give me what higher level functions they achieve. For each these functions matching high level brief info will be great
For example wol is something like
Wake-on-LAN is an Ethernet or Token Ring computer networking standard
that allows a computer to be turned on or awakened by a network message. > The message is usually sent to the target computer by a program executed > on a device connected to the same local area network, such as a
smartphone. Wikipedia
And Coalese is
Packet coalescing is the grouping of packets as a way of limiting the
number of receive interrupts and, as a result, lowering the amount of
processing required.
Just give me some technical info on kernel api about these functions. Thanks
Long story short, ethtool is a means to display and adjust generic NIC/driver parameters (identification, the number of receive and transmit queues, receive and transmit offloads, you name it) in a userspace application. On the one side, there's kernel API which a NIC driver is connected to (in particular, by means of struct ethtool_ops). On the other side, there's an ioctl command named SIOCETHTOOL which a userspace application can use to send requests to the kernel side and get responses.
Sub-identifiers enumerating specific commands for SIOCETHTOOL exist, and they correspond to the methods of struct ethtool_ops. From the question of yours it follows that it's struct ethtool_ops that should be explained.
I suggest that you take a look at include/linux/ethtool.h. There's a comment section right before the definition of struct ethtool_ops. In particular:
* #get_wol: Report whether Wake-on-Lan is enabled
* #set_wol: Turn Wake-on-Lan on or off. Returns a negative error code
* #get_coalesce: Get interrupt coalescing parameters. Returns a negative
* error code or zero.
* #set_coalesce: Set interrupt coalescing parameters. Supported coalescing
* types should be set in #supported_coalesce_params.
* Returns a negative error code or zero.
* #get_ts_info: Get the time stamping and PTP hardware clock capabilities.
* Drivers supporting transmit time stamps in software should set this to
* ethtool_op_get_ts_info().
* #get_eee: Get Energy-Efficient (EEE) supported and status.
* #set_eee: Set EEE status (enable/disable) as well as LPI timers.
For WoL feature and interrupt coalescing, these brief comments mostly match the explanations in the question of yours. The rest of the comments in the header file are also of great use. You may refer to them to get the gist.
It may also come in handy to take a look at ethtool mechanism from the userspace perspective. The most commonly used userspace application to use ethtool mechanism is also named ethtool; it's available as a package in popular distributions (Debian, Ubuntu, you name it). It's the man page of the package which contains useful information. In example:
ethtool -c|--show-coalesce devname
ethtool -C|--coalesce devname [adaptive-rx on|off]
[adaptive-tx on|off] [rx-usecs N] [rx-frames N]
[rx-usecs-irq N] [rx-frames-irq N] [tx-usecs N]
[tx-frames N] [tx-usecs-irq N] [tx-frames-irq N]
[stats-block-usecs N] [pkt-rate-low N] [rx-usecs-low N]
[rx-frames-low N] [tx-usecs-low N] [tx-frames-low N]
[pkt-rate-high N] [rx-usecs-high N] [rx-frames-high N]
[tx-usecs-high N] [tx-frames-high N] [sample-interval N]
-c --show-coalesce
Queries the specified network device for coalescing
information.
-C --coalesce
Changes the coalescing settings of the specified network
device.
All in all, there might be quite a few places which you may take a look at to clarify the meaning of ethtool commands/methods. These commands (as well as the features they serve) do not necessarily have something to do with the physical layer of OSI model. Some may be out of scope of the OSI model (like device identification); some may correspond to higher levels of the OSI model, in example, controls for packet offloads like TCP segmentation offload, RSS (Receive Side Scaling), etc. A particular feature can be discussed separately should the need arise.

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.

Enabling a USB Audio Class 2.0 Audio Input Stream

I've been trying to set up a USB Audio Input Stream on my microcontroller device. I know that each USB Audio stream has two alternate settings; Alternate setting 0 is where no stream is available; Alternate setting 1 is when there is a stream available.
I've already set up USB Audio Output so I know the stream descriptors work fine. Obviously, the microcontroller calls a USB interrupt to activate the output when the host tells it when audio is coming through (tells microcontroller to enable alternate setting 1...). However, now I'm confused how to enable the USB Audio input side. I'm confused because obviously the host doesn't tell the microcontroller that input is coming through... rather the device tells the host it's sending data through.
If anyone could give me insight how I would properly enable the input stream properly that would be wonderful. I'm wondering if I should just hard enable the endpoint and just send data that way? I can give more code to if need be but I guess this is more of a thinking type/algorithmic approach of question.
Here is my descriptor of the stream's alternate settings:
.iface_alt0.bLength = sizeof(usb_iface_desc_t)
.iface_alt0.bDescriptorType = USB_DT_INTERFACE
.iface_alt0.bInterfaceNumber = UDI_AUDIO_IFACE_DATA_IN_NUMBER
.iface_alt0.bAlternateSetting = 0
.iface_alt0.bNumEndpoints = 0
.iface_alt0.bInterfaceClass = AUDIO_IFACE_CLASS
.iface_alt0.bInterfaceSubClass = AUDIO_IFACE_SUBCLASS_STREAMING
.iface_alt0.bInterfaceProtocol = AUDIO_IFACE_IP_VERSION_02_00
.iface_alt0.iInterface = 0
.iface_alt1.bLength = sizeof(usb_iface_desc_t)
.iface_alt1.bDescriptorType = USB_DT_INTERFACE
.iface_alt1.bInterfaceNumber = UDI_AUDIO_IFACE_DATA_IN_NUMBER
.iface_alt1.bAlternateSetting = 1
.iface_alt1.bNumEndpoints = UDI_AUDIO_IN_NB_ENDPOINTS
.iface_alt1.bInterfaceClass = AUDIO_IFACE_CLASS
.iface_alt1.bInterfaceSubClass = AUDIO_IFACE_SUBCLASS_STREAMING
.iface_alt1.bInterfaceProtocol = AUDIO_IFACE_IP_VERSION_02_00
.iface_alt1.iInterface = 0
Thanks!
EDIT - Just read this source:
"When this configuration is enabled, the first two interface descriptors with bAlternativeSettings equal to zero is used. However during operation the host can send a SetInterface request directed to that of Interface one with a alternative setting of one to enable the other interface descriptor." - USB in a Nutshell
Revised Question: How do I send a SetInterface Request to enable the USB device accept an input stream?
new update - Is there a way I can set the alternate setting active through the descriptors? I was reading this about the stream descriptor -> "The bmControls field contains a set of bit pairs, indicating which Controls are present and what their capabilities are." "D1..0 Active Alternate Setting Control", "D3..2 Valid Alternate Setting Control".
resolved sort of -
So it looks like I just had to open up an audio app on my host device to enable the alternate setting... I didn't know that was the case.
int libusb_set_interface_alt_setting (libusb_device_handle * dev,
int interface_number, int alternate_setting)
http://libusb.org/static/api-1.0/group__dev.html#ga3047fea29830a56524388fd423068b53
in general the fields in a descriptor are like pointers to memory locations. if the mapping is faulty the device will not work.as the host has a certain mapping in its driver the device has to obey this mapping
in http://www.usb.org/developers/docs/devclass_docs/audio10.pdf on page 117 is said that there is a top-level Standard AudioControl descriptor and lower-level Class-Specific Audio Control Descriptors.
Beside the AudioStreaming descriptor you have to set other descriptors also correctly. In the example in http://www.usb.org/developers/docs/devclass_docs/audio10.pdf page 126 has to be set Standard Audio Streaming Interface Descriptor, Class-Specific Audio Streaming Descriptor, Type I format descriptor, Standard Endpoint Descriptor, Class-specific Isochronous Audio Data Endpoint Descriptor
i do not know what class your device implements, maybe you should set all these descriptors then it will possibly work
i can not find a bmControl field in the AudioStreaming descriptor.
Normally alternate settings are used to switch between the endpoints or the AudioStreaming Interfaces, see the Class-specific Interface Descriptor on page 117
in http://www.usb.org/developers/docs/devclass_docs/audio10.pdf from page 58-64 are all audio streaming relevant descriptors
in the linux USB audio driver there is a bmControl field:
/* 22 * bmControl field decoders
23 *
24 * From the USB Audio spec v2.0:
25 *
26 * bmaControls() is a (ch+1)-element array of 4-byte bitmaps,
27 * each containing a set of bit pairs. **If a Control is present,
28 * it must be Host readable.** If a certain Control is not
29 * present then the bit pair must be set to 0b00.
30 * If a Control is present but read-only, the bit pair must be
31 * set to 0b01. If a Control is also Host programmable, the bit
32 * pair must be set to 0b11. The value 0b10 is not allowed.
33 *
34 */
http://lxr.free-electrons.com/source/include/linux/usb/audio-v2.h
(http://www.usb.org/developers/docs/devclass_docs/audio10.pdf on page 36)

BLED112 advertise GATT services list

I am trying to make a BLED112 behave like an iBEacon and also advertise few more GATT services. While advertising user data for iBeacon as in Bluegiga examples works fine, I do not know how to also advertise the list of available GATT services. Any ideas are highly appreciated!
Take a look at my website for some potential help regarding using the BLED112 and Bluegiga tools: http://www.sureshjoshi.com/tag/bluegiga/
Otherwise, you shouldn't really be explicitly advertising anything. If you've set up your gatt.xml correctly, the GATT characteristics are advertised inherently (it's a BLE thing, not an explicit thing).
Are you sure you're setting them up correctly? Take a look at my BLE113 examples, specifically dealing with gatt.xml and see if there is anything helpful there: https://github.com/sureshjoshi/ble113-firmware-examples
One approach would be to use the Bluegiga dual-mode advertising as a guide and instead of the Physical Web Beacon, advertise your GATT service there. Assuming you have a 128 bit service UUID of 112233-4455-6677-8899-00AABBCCDDEEFF your advertising data would look like this:
procedure gatt_service_advertisement()
# Beacon mode
beaconMode = 1
#Stop advertisement
call gap_set_mode(0,0)
# Length
service_adv(0:1) = $11
# Incomplete list of 128 bit UUIDs (use $07 if the list is complete)
service_adv(1:1) = $06
# GATT Service UUID - should be little endian I think
service_adv(2:1) = $FF
service_adv(3:1) = $EE
...
service_adv(16:1) = $11
service_adv(17:1) = $00
# Set advertisement interval to 100ms.
# Use all three advertisement channels
call gap_set_adv_parameters(160, 160, 7)
# Set advertisement data
call gap_set_adv_data(0, 18, service_adv(0:18))
#set to advertising mode - with user data
call gap_set_mode(4, gap_undirected_connectable)
end
You can use that procedure to alternate advertisements between iBeacon and your GATT service by calling it in a repeating timer like in the linked dual-mode example.
Another approach would be to advertise the GATT service in the scan response, but without knowing more about your particular use case, it's hard to say if that's an option for you.

Resources