Android 4.3 BLE connection with Raspbery Pi (Bluez 5.8) - android

Device1: Nexus 4 Android 4.3 BLE Central (Using BluetoothLeGatt sample app in API 18 SDK as is)
Device2: Raspberry Pi with working BT4.0 USB Dongle, Raspbian Whezzy 20130726. Compiled Bluez 5.8 from the sources.(Since the packaged ver is 4.99 which not officially support BLE yet)
Working as peripheral, I started bluetoothd with "-p alert" (GATT Alert profile).
Test1: Using two raspi (device2 above) I can connect and browse alert gatt service/characteristics on other device using gattool.
Test2: Using iPhone/iPad (free BLE app: LightBlue) as Central I can also connect and browse alert gatt services and characteristics value on the Raspi.
Test3: When connecting using Nexus 4 sample app, (which is unstable), it asking for authorization on both device.Even after I can get rid off the authorization, the hcidump look like they are exchanging SDP info, the service list still not come up on Android sample app.
Test4: Nexus 4 sample app can connect and browse service on Fitbit One and Wahoo HRM.
Using hcidump (on the raspi), I can see different connection initiation:
Test1/2:
>HCI Event: LE Meta Event (0x3e) plen 19
LE Connection Complete
status 0x00 handle 44, role slave
bdaddr ... (Public)
Test3:
>HCI Event: Connect Request (0x04) plen 10
bdaddr ... class 0x5a020c type ACL
(Is it Bluetooth classic connection?)
Question:
Is there any way I can make Android BLE connection to create HCI Event: LE Meta Event on Raspi?

Related

BluetoothPairingStateProvider: getUuids() returns null for device

Context:
I am working on a FIDO-U2F bluetooth authenticator with a nRF52 BLE SoC. and want it to test with google example.
So far I have implemented the FIDO Bluetooth specification and I have a device that advertises as a FIDO-compatible device.
Thanks to nRF Connect I have ensured that all the services and characteristics are correctly exposed and that I can interact with it only when my device is securely paired (with LTK):
Problem:
When the app scans for eligible FIDO device, it does not find mine.
I am stuck on the screen that ask to press a button for 5s, which I don't need to since my device responds to pairing request without user interaction and is already paired with my SAMSUNG A8.
I/BluetoothDevicePreference: onDeviceAttributesChanged :: Device = (N) D8BE86, isBonded = 12 , mIsOnProgressAddVI = false
I/Fido: [BleScanner] startScan()
E/Fido: [BluetoothPairingStateProvider] getUuids() returns null for device: D8:BE:86:4A:E5:65
I/Fido: [PreferredTransportProvider] BLE enabled but no device is paired
I/Fido: [AuthenticateBaseChimeraActivity] User selected transport ble
I/Fido: [ViewController] Accepting proposed view {"viewName":"ble_instructions","anyU2fDevicesPaired":false}: outranks current (2 > 0)
I/Fido: [ViewPresenter] viewSelected(...) ble_instructions
I/Fido: [U2fRequestController] onResultReceived(null, ErrorResponseData{errorCode=5})
I/Fido: [BleScanner] stopScan()
I tried to remove pairing data and all I have is:
I/BluetoothDevicePreference: onDeviceAttributesChanged :: Device = (N) D8BE86, isBonded = 10 , mIsOnProgressAddVI = false
The advertising flags are currently set to "BR/EDR not supported", but I also tried "LE Limited Discoverable Mode" and "LE General Discoverable Mode" without success.
I looked into android-fido sources but the BLE scan seems imported from elsewhere, I cannot debug it in this project.
Any pointer is welcome
Have you got to this screen?
We may need to add Service Data field (0x16) into advertising packet. This is mentioned in FIDO specification here
Android code snippet for advertising with Service Data field added:
AdvertiseData data = new AdvertiseData.Builder()
.addServiceUuid(new ParcelUuid(fido2GattService.getUuid()))
.setIncludeDeviceName(true)
.addServiceData(new ParcelUuid(fido2GattService.getUuid()), new byte[] {(byte)192, (byte)192, (byte)192})
.build();
If you want to capture bluetooth packets to see what is your advertising packet, you can use PacketLogger (for MacOS)
Here is the screenshot of the advertising packet
The red box is Service Data

BLE device works on ios but not on Android

Here's my problem
I have an electronic lock that uses BLE, it works fine on ios(Both LightBlue & the app I made)
But on Android, after bonding with the lock(I entered the pin code 000000), I can connect to the device, but one of the Service (UUID:7570) becomes empty, and I can't read or write to any characteristic.
Also the device always gets disconnected after about 20 seconds.
This is the ScreenShot from ios
This is the ScreenShot from android (with empty Service)
Here's the log I got from nRF Connect
nRF Connect, 2018-02-07
OHGA-ELock 60012 (68:C9:0B:15:99:0D)
V 17:57:52.234 Connecting to 68:C9:0B:15:99:0D...
D 17:57:52.234 gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE)
D 17:57:52.767 [Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I 17:57:52.767 Connected to 68:C9:0B:15:99:0D
D 17:57:52.769 wait(1600ms)
D 17:57:52.785 [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
V 17:57:54.373 Discovering services...
D 17:57:54.373 gatt.discoverServices()
D 17:57:54.395 [Callback] Services discovered with status: 0
I 17:57:54.395 Services discovered
V 17:57:54.414 Generic Access (0x1800)
- Device Name [R] (0x2A00)
- Appearance [R] (0x2A01)
- Peripheral Preferred Connection Parameters [R] (0x2A04)
Generic Attribute (0x1801)
Unknown Service (00007570-0000-0000-0000-000000000000)
Device Information (0x180A)
- System ID [R] (0x2A23)
- Model Number String [R] (0x2A24)
- Serial Number String [R] (0x2A25)
- Firmware Revision String [R] (0x2A26)
- Hardware Revision String [R] (0x2A27)
- Software Revision String [R] (0x2A28)
- Manufacturer Name String [R] (0x2A29)
D 17:58:10.701 [Callback] Connection state changed with status: 8 and new state: DISCONNECTED (0)
E 17:58:10.701 Error 8 (0x8): GATT CONN TIMEOUT
I 17:58:10.701 Disconnected
D 17:58:10.794 [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
I've tested it on different Android phones with different testing apps.
Is there a chance this is an issue of the BLE device?
Please let me know if more specific details are needed.
Any help or suggestion would be appreciated.
Thanks!
the device always gets disconnected after about 20 seconds
This is because of the supervision timeout. In Android it is hardcoded to 20 seconds during which a re-connect doesn’t work. For more information to know what this 20 seconds and supervision timeout take a look here- Android BLE connection timeouts and GATT internal errors

BLE peripheral pairing pin on android

I implemented a GATT Server and Client App on Android. The connection is working and I forced pairing by adding PERMISSION_READ/WRITE_ENCRYPTED_MITM to all of the GattCharacteristics.
But the pairing behavior differs on different clients:
1) Pin is shown on the client/central (Android 5 on Samsung Galaxy S3) and should be insert on the server/peripheral (Android 7 on Nexus 5).
2) Passkey is shown on both devices client/central (Android 5 on Samsung Galaxy S3) and server/peripheral (Android 6 on Nexus 7)
3) Pairing with Windows or iOS fails with server/peripheral expecing a pin for input.
What I expected and want to happen is:
Pin is shown on the server/peripheral and has to be insert on client/central
Is there any way to configure that behavior?
Thanks in advance!
EDIT
Here is my setup:
BluetoothGattService gattService = new BluetoothGattService(
serviceUUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
gattService.addCharacteristic(new BluetoothGattCharacteristic(
charReadUUID,
BluetoothGattCharacteristic.PROPERTY_READ,
BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED_MITM
));
gattService.addCharacteristic(new BluetoothGattCharacteristic(
charWriteUUID,
BluetoothGattCharacteristic.PROPERTY_WRITE,
BluetoothGattCharacteristic.PERMISSION_WRITE_ENCRYPTED_MITM
));
gattServer.addService(gattService);
...
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
.setConnectable(true)
.build();
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeTxPowerLevel(false)
.addServiceUuid(serviceUUID)
.build();
BluetoothLeAdvertiser advertiser = adaper.getBluetoothLeAdvertiser()
advertiser.startAdvertising(settings, data, callback);
Summary: Set the I/O Capabilites of your client to "Keyboard Only".
Explanation:
I am not fully sure what happens "under the hood" of your system. But I can tell you what should be happening according to the BLE CoreSpec. First see CoreSpec V4.2, Vol. 3, Part H, chap. 2.3.5.1, table 2.7 & 2.8. There it is defined which pairing is used, depending on the authentication requirements and the I/O capabilities of the devices.
What you want is described as "Passkey Entry: responder displays, initiator inputs". This is the case if legacy pairing (pairing according to Bluetooth V4.0) is used, and if:
the server (responder) has a display AND
the client (initiator) has a keyboard AND
server and client do NOT both have display AND keyboard.
(And if OOB data is not used and MITM is enforced, but I assume this as given.) Note that if both client and server have display and keyboard, the default case is that the client displays and the server inputs. It would seem that if your protocol automatically handles pairing, it will also automatically chose the pairing method as defined in the CoreSpec.
So what you see is corresponding to different I/O capabilities of different servers. It seems that your client has display and keyboard, so if you use a server with display and keyboard, the client will display the passkey and the responder will wait for input (which fits to your case 1). For case 2, we have Numeric Comparison; this is only possible if LE Secure Connections (pairing according to Bluetooth V4.2) is supported by both client and server.
For case 3, I don't know what is going on, but it may be a problem between an Android system and an iOS system not operating well together (but I have no idea why).
Since pairing seems to be fully automized here, the only possibility to change things is to change the I/O capabilities. There should be a function to change these capabilities, check your manual. If you do not want to use a display on the client, set its I/O capabilities to "Keyboard Only" and it will exhibit the behavior you expect.(*)
(*) This holds only if you use legacy pairing. If both devices support LE Secure Connections, it is recommended that you use this newer pairing protocol, since it removes security issues with the old protocol. (I would however assume that in this case, the newer protocol is used automatically anyway.)

Android BluetoothGatt status code 128 BLE connection

I'm trying to connect a BLE Device (Sigma chest strap) to my Sony Smartwatch 3 and the writeDescriptor() method fails to enable Notifications on the Device. The onDescriptorWrite() method displays the status code "128" which apparently stands for "GATT_NO_RESOURCES". Does anyone know what this error means or how to fix it?
Another BLE Device (Alpha Mio 2) works without any problems. descriptor is written and data received via onCharacteristicChanged().
Descriptor UUID: 00002902-0000-1000-8000-00805f9b34fb
Service UUID: 0000180d-0000-1000-8000-00805f9b34fb

Android Open Accessory Protocol using javax.usb

I'm working on getting any existing device communicating with Android devices. The device uses javax.usb (which is built on top of libusb) for usb communication and I am attempting to implement the Android Open Accessory Protocol using it. The device currently recognizes the android device and registers the android device with my application. However when I try to:
Attempt to Start in Accessory Mode - Send a 51 control request ("Get Protocol") to figure out if the device supports the Android accessory protocol.
I get a UsbStallException and my app dies. I know very little when it comes to usb from what I have been reading this should work.
Here's the relevant code:
byte req = (byte) (0x80 | 0x40);
UsbControlIrp irp = usbDev.createUsbControlIrp(req, (byte)51, (short)0, (short)0);
usbDev.syncSubmit(irp);
Any insights as to what I'm doing wrong would be appreciated.
PS: the device I'm running this on uses a 1.4 JVM so any solutions will be constrained by that

Categories

Resources