HID scanner demo

Dependencies:   BLE_API WIFI_API_32kRAM nRF51822 mbed

BLE HID function in this demo is temporary working with Android phone ONLY. Will be fixed to support iOS device in next update.

Files at this revision

API Documentation at this revision

Comitter:
Marcomissyou
Date:
Thu Jul 02 01:35:08 2015 +0000
Child:
1:51535675abf4
Commit message:
HID Keyboard with Bluetooth 4.0

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
HIDService.cpp Show annotated file Show diff for this revision Revisions of this file
HIDService.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLE_API.lib	Thu Jul 02 01:35:08 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#9f4251b3355c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HIDService.cpp	Thu Jul 02 01:35:08 2015 +0000
@@ -0,0 +1,46 @@
+#include "HIDService.h"
+
+const uint8_t KeyboardReportMap[] =
+    {   0x05, 0x01,                 // Usage Page (Generic Desktop)
+        0x09, 0x06,                 // Usage (Keyboard)
+        0xA1, 0x01,                 // Collection (Application)
+        0x05, 0x07,                 //     Usage Page (Key Codes)
+        0x19, 0xe0,                 //     Usage Minimum (224)
+        0x29, 0xe7,                 //     Usage Maximum (231)
+        0x15, 0x00,                 //     Logicagl Minimum (0)
+        0x25, 0x01,                 //     Logical Maximum (1)
+        0x75, 0x01,                 //     Report Size (1)
+        0x95, 0x08,                 //     Report Count (8)
+        0x81, 0x02,                 //     Input (Data, Variable, Absolute)
+        
+        0x95, 0x01,                 //     Report Count (1)
+        0x75, 0x08,                 //     Report Size (8)
+        0x81, 0x01,                 //     Input (Constant) reserved byte(1)
+
+        0x95, 0x05,                 //     Report Count (5)
+        0x75, 0x01,                 //     Report Size (1)
+        0x05, 0x08,                 //     Usage Page (Page# for LEDs)
+        0x19, 0x01,                 //     Usage Minimum (1)
+        0x29, 0x05,                 //     Usage Maximum (5)
+        0x91, 0x02,                 //     Output (Data, Variable, Absolute), Led report
+        0x95, 0x01,                 //     Report Count (1)
+        0x75, 0x03,                 //     Report Size (3)
+        0x91, 0x01,                 //     Output (Data, Variable, Absolute), Led report padding
+
+        0x95, 0x06,                 //     Report Count (6)
+        0x75, 0x08,                 //     Report Size (8)
+        0x15, 0x00,                 //     Logical Minimum (0)
+        0x25, 0x65,                 //     Logical Maximum (101)
+        0x05, 0x07,                 //     Usage Page (Key codes)
+        0x19, 0x00,                 //     Usage Minimum (0)
+        0x29, 0x65,                 //     Usage Maximum (101)
+        0x81, 0x00,                 //     Input (Data, Array) Key array(6 bytes)
+
+        0x09, 0x05,                 //     Usage (Vendor Defined)
+        0x15, 0x00,                 //     Logical Minimum (0)
+        0x26, 0xFF, 0x00,           //     Logical Maximum (255)
+        0x75, 0x08,                 //     Report Count (2)
+        0x95, 0x02,                 //     Report Size (8 bit)
+        0xB1, 0x02,                 //     Feature (Data, Variable, Absolute)
+        0xC0                        // End Collection (Application)
+    };
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HIDService.h	Thu Jul 02 01:35:08 2015 +0000
@@ -0,0 +1,124 @@
+#ifndef __BLE_HID_SERVICE_H__
+#define __BLE_HID_SERVICE_H__
+
+#include "BLE.h"
+/**
+* @class Human Interface Device Service
+* @brief BLE Human Interface Device Service. This service displays the Glucose measurement value represented as a 16bit Float format.<br>
+* @Author: Marco.Hsu  
+* @Email: marco.missyou@gmail.com  
+*/
+
+extern const uint8_t KeyboardReportMap[76];
+        
+class HIDService {
+public:
+    HIDService(BLEDevice &_ble, const uint8_t* key = &KeyboardReportMap[0]):
+        ble(_ble),
+        protocol_modeValue(1),  // Report Protocol Mode(1), Boot Protocol Mode(0)
+        KeyboardMap(key),
+        Protocol_Mode(GattCharacteristic::UUID_PROTOCOL_MODE_CHAR, &protocol_modeValue, 1, 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
+        ReportMap(GattCharacteristic::UUID_REPORT_MAP_CHAR, KeyboardMap.getPointer(), 76, sizeof(KeyboardMap), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        Report(GattCharacteristic::UUID_REPORT_CHAR, reportValue.getPointer(), 8, 8, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY|GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
+        HID_Information(GattCharacteristic::UUID_HID_INFORMATION_CHAR, hidInformation.getPointer(), 4, 4, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
+        HID_Control_Point(GattCharacteristic::UUID_HID_CONTROL_POINT_CHAR, &hidcontrolPointer, 1, 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE)
+        {
+            static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
+            if (serviceAdded) {
+            return;
+            }
+            //Report.requireSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK);
+            GattCharacteristic *charTable[] = {&Protocol_Mode, &ReportMap, &Report, &HID_Information, &HID_Control_Point};
+            GattService         HIDGattService(GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+            ble.addService(HIDGattService);
+            serviceAdded = true;
+            ble.onDataWritten(this, &HIDService::onDataWritten);
+        }
+public:
+    void updateReport(uint8_t modifydata, uint8_t data) {
+        reportValue.updateReportValue(modifydata, data);
+        ble.updateCharacteristicValue(Report.getValueAttribute().getHandle(), reportValue.getPointer(), 8);
+    }
+    
+    virtual void onDataWritten(const GattWriteCallbackParams *params) {
+        if (params->handle == HID_Control_Point.getValueAttribute().getHandle()) {
+            uint16_t bytesRead = params->len;
+            if (bytesRead == 1) {
+                memcpy(&hidcontrolPointer, params->data, bytesRead);
+            }
+        }
+        if (params->handle == Report.getValueAttribute().getHandle()) {
+            uint16_t bytesRead = params->len;
+            if (bytesRead <= 4) {
+                memcpy(&reportValue, params->data, bytesRead);
+            }
+        }
+    }
+
+private:
+    struct ReportMapStructure{
+            uint8_t KeyboardMap[76];
+            ReportMapStructure(const uint8_t* data): KeyboardMap() {
+            memcpy(&KeyboardMap[0], data, 76);
+            }
+            uint8_t     *getPointer(void) {
+            return      KeyboardMap;
+            }
+    };
+
+private:
+   struct ReportStructure {
+            // Initial setting report value
+            ReportStructure(): reportValue() {
+                uint8_t data= 0x00;
+                updateReportValue(data, data);
+            }
+            
+            void updateReportValue(uint8_t modifyKey, uint8_t data){
+                memset(&reportValue[0], 0 ,8);
+                memcpy(&reportValue[0], &modifyKey, 1);
+                memcpy(&reportValue[2], &data, 1);
+            }
+        
+            uint8_t     *getPointer(void) {
+            return      reportValue;
+            }
+
+            uint8_t reportValue[8];
+        };
+        
+private:
+    struct HIDInforStructure{
+            uint16_t    bcdHID;
+            uint8_t     bCountryCode;
+            uint8_t     Flags;
+            
+            HIDInforStructure():bcdHID(0),bCountryCode(0),Flags(0){
+                    memcpy(&hidInformation[0], &bcdHID, 2);
+                    memcpy(&hidInformation[2], &bCountryCode, 1);
+                    memcpy(&hidInformation[3], &Flags, 1);
+                }
+            uint8_t     *getPointer(void) {
+            return      hidInformation;
+            }
+            
+            uint8_t hidInformation[4];
+        };
+        
+private:
+    BLEDevice           &ble;
+    uint8_t             protocol_modeValue;
+    ReportStructure     reportValue;
+    uint8_t             hidcontrolPointer;
+    ReportMapStructure  KeyboardMap;
+    HIDInforStructure   hidInformation;
+    GattCharacteristic      Protocol_Mode;
+    GattCharacteristic      ReportMap;
+    GattCharacteristic      Report;
+//    ReadOnlyGattCharacteristic         Boot_Keyboard_Input_Report;
+//    ReadWriteGattCharacteristic        Boot_Keyboard_Output_Report;
+//    ReadOnlyGattCharacteristic         Boot_Mouse_Input_Report;
+    GattCharacteristic      HID_Information;
+    GattCharacteristic      HID_Control_Point;
+};
+#endif /* #ifndef __BLE_GLUCOSE_SERVICE_H__*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Jul 02 01:35:08 2015 +0000
@@ -0,0 +1,91 @@
+#include "mbed.h"
+#include "BLE.h"
+#include "BatteryService.h"
+#include "DeviceInformationService.h"
+#include "HIDService.h"
+ 
+BLEDevice  ble;
+DigitalOut led01(LED1);
+Serial uart(p25,p23);
+
+unsigned char keyData;
+bool is_input = false; 
+static const char     DEVICE_NAME[]        = "HID_Keyboard";
+static const uint16_t uuid16_list[]        = {GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE};
+static volatile bool  triggerSensorPolling = false;
+
+void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
+{
+    ble.startAdvertising(); // restart advertising
+}
+
+
+static uint8_t key_press_scan_buff[30];
+static uint8_t modifyKey[30];
+int main(void)
+{   uart.baud(9600);
+    uart.printf("Starting HID Service\n");
+    //uart.attach(&uart_rx);
+    led01 = 1;
+    ble.init();
+    bool enableBonding = false;
+    bool requireMITM   = false;
+    ble.initializeSecurity(enableBonding, requireMITM);
+    ble.onDisconnection(disconnectionCallback);
+ 
+    /* Setup primary service. */
+    HIDService hidService(ble);
+    /* Setup auxiliary service. */
+    DeviceInformationService deviceInfo(ble, "ARM", "CYNTEC", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
+    /* Setup advertising. */
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.setAdvertisingInterval(1000);
+    ble.startAdvertising();
+    uart.printf("Starting advertising\n");
+    int index = 0;
+    while (1) {
+        if (uart.readable() == 1) {
+            keyData = uart.getc();
+            uart.putc(keyData);
+            if(keyData <= 0x39 && keyData >= 0x30){             //number
+                if(keyData == 0x30){
+                    modifyKey[index] = 0x00;
+                    key_press_scan_buff[index] = 0x27;
+                    } else {
+                    modifyKey[index] = 0x00;
+                    key_press_scan_buff[index] = keyData-0x13;
+                    }
+                } else if(keyData <= 0x7a && keyData >= 0x61 ){ //lowercase letters
+                    modifyKey[index] = 0x00;
+                    key_press_scan_buff[index] = keyData-0x5d;
+                } else if(keyData <= 0x5a && keyData >= 0x41){  //uppercase letters
+                    modifyKey[index] = 0x02;
+                    key_press_scan_buff[index] = keyData-0x3d;
+                } else if (keyData == 0x20) {
+                    modifyKey[index] = 0x00;
+                    key_press_scan_buff[index] = 0x2c;
+                } else {
+                    modifyKey[index] = 0x00;
+                    //key_press_scan_buff[index] = 0x28;
+                    //key_press_scan_buff[index++] = 0x73;
+                    key_press_scan_buff[index] = 0x73;
+            }
+            index++;
+            if(keyData == 0x0a && ble.getGapState().connected){
+                for(int i = 0; i < index; i++){
+                //uart.putc(key_press_scan_buff[i]);
+                hidService.updateReport(modifyKey[i], key_press_scan_buff[i]);
+                wait(0.1);
+                }
+            index = 0;
+            memset(modifyKey, 0, 30);
+            memset(key_press_scan_buff, 0, 30);
+            }
+            
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Jul 02 01:35:08 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7cff1c4259d7
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51822.lib	Thu Jul 02 01:35:08 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#7c68c8d67e1f