This issue I am observing with kernel above 5.0.
And with controllers that have extended advertising enabled.
I have currently tested with bluez-5.50.
The issue is something to do with "MGMT_ADV_FLAG_SEC_MASK" flag is what I could get from the code. But when and how will this flag be modified is what I dont understand.
Config: kernel 5.4.24(issue seen with any 5.0+ kernel) , bluez 5.50
I am doing following steps:
1. hciattach the BLE extended ADV enabled controller.
2. hciconfig hci0 reset.
I am getting following error for Extended Scan rsp command (during the hciconfig hci0 reset sequence):
LE Set Extended Scan Response Data (0x08|0x0038) ncmd 1
Status: Invalid HCI Command Parameters (0x12)
And this I am getting because of below written in core_v5.2:
"If the advertising set is non-scannable and the Host uses this command other than to discard existing data, the Controller shall return the error code Invalid HCI Command Parameters (0x12). If the advertising set uses scannable legacy advertising PDUs and either Operation is not 0x03 or the Scan_Response_Data_Length parameter exceeds 31 octets, the Controller shall return the error code Invalid HCI Command Parameters (0x12). If Operation is not 0x03 and Scan_Response_Data_Length is zero, the Controller shall return the error code Invalid HCI Command Parameters (0x12) "
So in my extended HCI Command Extended Advertising set command just before extended scan rsp set:
*LE Set Extended Advertising Parameters (0x08|0x0036) plen 25
Handle: 0x00
Properties: 0x0010
Use legacy advertising PDUs: ADV_NONCONN_IND
This legacy advertising is set because of the MGMT_ADV_FLAG_SEC_MASK as checked in kernel code.
I want to know which parameter from the controller LE features or anything else is required to set it right.
In my bluetooth controller multi ADV is not supported , extended ADV is supported.
Got the issue, it was with extended adv for kernel 5.4.24. In the kernel version 5.7.7.
I found this difference in file hci_request.c, function get_adv_instance_scan_rsp_len, currently(kernel 5.4.24) the code is:
static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
{
struct adv_info *adv_instance;
/* Ignore instance 0 */
if (instance == 0x00)
return 0;
In the 5.7.7 it is changed to:
static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
{
struct adv_info *adv_instance;
/* Instance 0x00 always set local name */
if (instance == 0x00)
return 1;
What this should change is, it should satisfy the condition below, which currently wasn’t. So basically should set the scannable flag by which the scan rsp data cmd doesnt fail:
} else if (get_adv_instance_scan_rsp_len(hdev, instance)) {
if (secondary_adv)
cp.evt_properties = cpu_to_le16(LE_EXT_ADV_SCAN_IND);
else
cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);
Related
I am looking to connect to Bluetooth devices on Linux and store information about them in a database. I have used the code from here as the starting point. It uses
prop_changed = g_dbus_connection_signal_subscribe(con,
"org.bluez",
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
NULL,
"org.bluez.Adapter1",
G_DBUS_SIGNAL_FLAGS_NONE,
bluez_signal_adapter_changed,
NULL,
NULL);
to be notified when new Bluetooth devices appear. And I reuse its bluez_device_call_method() function to call the DBUS Connect() method documented in the BlueZ D-Bus Device API on every new device that appears:
bluez_device_call_method(object, "Connect");
Most devices just time out, but some devices appear to connect sucessfully. My question is, for those devices which I've connected successfully to, how do I get more information about the device I'm talking to?
The only other APIs documented in the BlueZ D-Bus Device API that seem like they'd let me retrieve more information are "void ConnectProfile(string uuid)" and "void Pair()". For ConnectProfile() how am I supposed to know the UUID? Is it just what's printed out via entries like the below?
[ /org/bluez/hci0/dev_48_57_DE_00_AA_09 ]
Address : s : 48:57:DE:00:AA:09
AddressType : s : random
Name : s : Blood Pressure
Alias : s : Blood Pressure
Paired : b : 0
Trusted : b : 0
Blocked : b : 0
LegacyPairing : b : 0
RSSI : n : -65
Connected : b : 0
UUIDs : a :
0000180a-0000-1000-8000-00805f9b34fb
00001810-0000-1000-8000-00805f9b34fb
And if it succeeds, where would I find the returned data?
And for Pair(), it says "This method will connect to the remote device, initiate pairing and then retrieve all SDP records (or GATT primary services).", but if it succeeds, where would I find the returned data?
So far I've tried:
ret = bluez_device_call_method(object, "Connect");
if(ret == -1){
bluez_device_call_method(object, "Pair");
}
else{
printf("Connect() succeeded! Now what?!\n");
}
But I don't think Pair() has ever succeeded, whereas Connect() has succeeded occasionally with some devices.
I am building my own kernel. The device tree of the kernel is modified, because of an own designed mainboard.
I can enable the can devices by:
// here ATMEL is defining the can0 and can1 memory mapped devices
#include "sama5d3_can.dtsi"
...
can0: can#f000c000 {
status = "okay";
};
can1: can#f8010000 {
status = "okay";
};
But now I want to switch the names of them. Can0 should become can1 and can1 should be can0.
How to do that?
PS: the error print when switching the labels and building the kernel:
| ERROR (duplicate_label): Duplicate label 'can0' on /ahb/apb/can#f8010000 and /ahb/apb/can#f000c000
| ERROR (duplicate_label): Duplicate label 'can1' on /ahb/apb/can#f8010000 and /ahb/apb/can#f000c000
The network "devices" do not take their name from the DTS at all. They get it from the name that is given to the netdevice.name.
In your case, the at91_can.c driver calls alloc_candev() that explicitely sets the interface's name to can%d (can0, can1, ...). The number "assigned" to each device in then strictly dependant on the sequence of the "enumeration" of the hardware and its registration with the at91_can driver.
Changing the device tree will not help you in changing the name of the network interfaces. If you really need to change the name of the can interfaces, you could write udev rules that do so.
I already thought that changing Historical bytes is limited to Pre-Personalization step. But, I found a method named setATRHistBytes in the GlobalPlatform APIs today.
This is its description(GlobalPlatform 2.2 Page 172) :
setATRHistBytes
public static boolean setATRHistBytes(byte[] baBuffer, short sOffset, bytebLength)
For contact cards according to ISO/IEC 7816-4 and Type A contactless cards according to ISO/IEC 14443-3, this method sets the historical bytes. The sequence of bytes will be visible on a subsequent power-up or reset.
Notes:
• The OPEN locates the entry of the current applet context in the GlobalPlatform Registry and verifies that the Application has the Card Reset privilege for the current card I/O interface;
• The OPEN is responsible for synchronizing the length of historical bytes in Format Character T0 of the ATR.
Parameters:
baBuffer - the source byte array containing the historical bytes. Must be a global array.
sOffset - offset of the historical bytes within the source byte array.
bLength - the number of historical bytes.
Returns:
true if historical bytes set, false if the Application does not have the required privilege
Now I want to change the Historical Bytes of my card. So I wrote the below program and convert it to its cap file successfully :
... /imports
public class HistoricalBytesChanger extends Applet {
public static byte[] state = { (byte) 0, (byte) 0 };
public static byte[] HistByteArray = { (byte) 0x01, (byte) 0x02,
(byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
(byte) 0x08, (byte) 0x09, (byte) 0x0a };
public static void install(byte[] bArray, short bOffset, byte bLength) {
new HistoricalBytesChanger().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00:
GPSystem.setATRHistBytes(HistByteArray, (short) 0, (byte) 10);
HistByteArray[0] = (byte) (HistByteArray[0] + 1);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}
As you see above it is written in way that assign 0102030405060708090A to Historical Bytes on reception of any APDU command with INS=0X00.
The problem is I don't have any idea how to set Card Reset privilege to this applet. I know that I must specify the privilege in the installation step, but I don't know how! Normally I upload my applets using GlobalPlatformPro tool. In the parameters that it support I couldn't see any related parameter :
E:\GP> gp -h
Option Description
------ -----------
-V, --version Show information about the program
-a, --apdu Send raw APDU (hex)
--all Work with multiple readers
--applet <AID> Applet AID
--cap <File> Use a CAP file as source
--create <AID> Create new instance of an applet
-d, --debug Show PC/SC and APDU trace
--default Indicate Default Selected privilege
--delete [AID] Delete something
--deletedeps Also delete dependencies
--dump <File> Dump APDU communication to <File>
--emv Use EMV diversification
--enc <GPKeySet$GPKey> Specify ENC key
-h, --help Shows this help string
-i, --info Show information
--install [File] Install applet(s) from CAP
--instance <AID> Instance AID
--kek <GPKeySet$GPKey> Specify KEK key
--key <GPKeySet$GPKey> Specify master key
--keyid <Integer> Specify key ID
--keyver <Integer> Specify key version
-l, --list List the contents of the card
--load <File> Load a CAP file
--lock <GPKeySet> Set new key
--lock-applet <AID> Lock specified applet
--mac <GPKeySet$GPKey> Specify MAC key
--make-default <AID> Make AID the default
--mode <GlobalPlatform$APDUMode> APDU mode to use (mac/enc/clr)
--new-keyver <Integer> key version for the new key
--nofix Do not try to fix PCSC/Java/OS issues
--package <AID> Package AID
--params Installation parameters
-r, --reader Use specific reader
--reinstall Remove card content during installation
--relax Relaxed error checking
--replay <File> Replay APDU responses from <File>
-s, --secure-apdu Send raw APDU (hex) via SCP
--scp <Integer> Force the use of SCP0X
--sdaid <AID> ISD AID
--sdomain Indicate Security Domain privilege
--terminate Indicate Card Lock+Terminate privilege
--uninstall <File> Uninstall applet/package
--unlock Set default key
--unlock-applet <AID> Lock specified applet
-v, --verbose Be verbose about operations
--virgin Card has virgin keys
--visa2 Use VISA2 diversification
E:\GP>
Note that I installed the applet normally, but while it return 0x9000 in reception of that command, it can't change Historical Bytes and I need to set the Card Reset privilege to my applet :
OpenSC: osc -a
Using reader with a card: ACS CCID USB Reader 0
3b:68:00:00:00:73:c8:40:12:00:90:00
OpenSC: osc -s 00A4040006010203040101 -s 00000000
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 01 01
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00
Received (SW1=0x90, SW2=0x00)
OpenSC: osc -a
Using reader with a card: ACS CCID USB Reader 0
3b:68:00:00:00:73:c8:40:12:00:90:00
OpenSC:
Questions:
1- How can I change/set the privilege of my applet?
2- Why the card return 0x9000 on reception of 0x00 0x00 x00 0x00? (I expect it to return an exception, because it is mentioned in description of setATRHistBytes that this method returns false in cases that applet privilege is not Card Reset)
The reset privilege was known before as the default selected privilege. This means you can just use the --default switch for your card - the same bit it flipped in the INSTALL for INSTALL privilege bytes if you do that.
Sometimes a card expects a cold reset (i.e. removing the card from the field or terminal) before the change in ATR bytes is communicated. This can also be a reader problem - not all readers perform a reset when reconnected, or they may cache the ATR bytes.
To set card reset privilege to an applet you need to set bit3 of first privilege byte in Install and make selectable command of the applet. If the applet is only being installed and not made selectable with the same INSTALL command the Card Reset privilege cannot be set
Actually if the card is GP201/GP211 compliance then we refer Card Reset privilege as Default Selected privilege.
If Default Selected privilege is set in GP201/GP211 compliance card then it provides two functionalities to the applet as:
The applet can modify the historical bytes
The applet will be default selected applet on basic logical channel after cold reset.
If Card Reset privilege is set in GP22 or above version of compliance card then it provides following functionalities to the applet as:
The applet can modify the historical bytes
The applet can be implicit selectability on basic logical channel if it has not been awarded to another Application by setting implicit selectable parameters to tat applet.
I would like to detect if a botton is pushed on my SensorTag using the gatttool, but I'm not able to do that.
In http://processors.wiki.ti.com/index.php/SensorTag_User_Guide TI reports that in order to read the pressed buttons, you should:
1) Enable test mode by writing the value 0x80 to the AA62 (CONFIGURATION) attribute.
I did that with the command:
[CON][BC:6A:29:AE:CD:E5][LE]> char-write-req 0x67 80
[CON][BC:6A:29:AE:CD:E5][LE]> Characteristic value was written successfully
Now I should be in test mode, and:
2) Enable Simple keys notification
Looking at the http://processors.wiki.ti.com/index.php/File:BLE_SensorTag_GATT_Server.pdf
and at the bluepy lib it seems I've to write 0100 in 0x60 for doing that. But
[CON][BC:6A:29:AE:CD:E5][LE]> char-write-req 0x60 0100
[CON][BC:6A:29:AE:CD:E5][LE]> Characteristic Write Request failed: Attribute can't be written
I observed that 0x61 is writtable and accept the value 0100, but I'm still not able to
detect if a key is pressed.
Any suggestion?
That PDF document may be out of date... I just tried using gatttool on my SensorTag and got button notifications with the following command: char-write-req 0x6c 0100
I'd stick with just the TI wiki for the SensorTag as it's probably more likely to be kept up-to-date. The wiki says you only need to do that "test mode" step if you want to get notifications when the side button is pressed (because normally it just activates the advertising).
Also, you probably have to figure out what handle to use on your specific device as every firmware will cause the handles to move around. What shouldn't change between firmwares is the UUID. Try the primary and characteristics commands in gatttool to get the details of the services on the device.
My primary showed this:
attr handle: 0x005e, end grp handle: 0x0068 uuid: f000aa50-0451-4000-b000-000000000000
attr handle: 0x0069, end grp handle: 0x006d uuid: 0000ffe0-0000-1000-8000-00805f9b34fb
attr handle: 0x006e, end grp handle: 0x0074 uuid: f000aa60-0451-4000-b000-000000000000
ffe0 is the UUID of the simple key service (though the wiki says it's f000ffe0, it's not on mine). So, all the handles you want to look at are from 0x69 to 0x6d
char-read-uuid 0x2902 0x69 0x6d will show all CCC (Client Characteristic Configuration) in that range:
handle: 0x006c value: 01 00
Setting that handle to 0100 will turn on notifications for that service.
Is there any way to receive data of a specific VLAN tagged frame? Currently I am receiving all VLAN tagged frames by giving htons(0x22f0) as input to socket() function like:
m_iSocketDesc = socket(AF_PACKET, SOCK_RAW, htons(0x22f0));
numBytes = recvfrom(m_iSocketDesc, message_data, 1522, 0, NULL, 0)
I had a similar requirement. To receive packets with a specific VLAN, I created a VLAN interface and bound my raw socket to it. Now I can just send 802.3 frames, the kernel inserts/extracts VLAN tag.
Create a VLAN interface, you should have root permission
ip link add link <phyInterface> name <phyInterface.VLANID> type vlan id VLANID
Eg: ip link add link eth0 name eth0.100 type vlan 100
Use normal bind function in your application to bind to the VLAN interface. In the above example eth0.100.
You can refer to the below two links for sample code (I am NOT the owner of the code)
Sending: https://gist.github.com/austinmarton/1922600
Receiving: https://gist.github.com/austinmarton/2862515#file-recvraweth-c
The only change needed is that instead of binding to physical interface, bind to the virtual VLAN interface. Note that the Ethernet frames received are un-tagged frames. Any frames sent on this interface will automatically tagged with the VLANID.