BLE HID keyboard with gesture

Dependencies:   BLE_API BLE_HID PAJ7620U2 mbed nRF51822

https://mtmtechblog.files.wordpress.com/2017/01/mtsense04-pi-on-mbed.jpeg We have full tutorial, please visit our blog

Committer:
bcc6
Date:
Fri Dec 16 09:04:08 2016 +0000
Revision:
0:55c7f79a524c
Child:
2:6109e375f9a7
BLE HID keyboard with gesture

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bcc6 0:55c7f79a524c 1 #include "mbed.h"
bcc6 0:55c7f79a524c 2 #include "ble/BLE.h"
bcc6 0:55c7f79a524c 3 #include "ble/services/BatteryService.h"
bcc6 0:55c7f79a524c 4 #include "ble/services/DeviceInformationService.h"
bcc6 0:55c7f79a524c 5
bcc6 0:55c7f79a524c 6 #include "PAJ7620.h"
bcc6 0:55c7f79a524c 7
bcc6 0:55c7f79a524c 8 #include "HIDServiceBase.h"
bcc6 0:55c7f79a524c 9 //#include "MouseService.h"
bcc6 0:55c7f79a524c 10 //#include "JoystickService.h"
bcc6 0:55c7f79a524c 11 #include "KeyboardService.h"
bcc6 0:55c7f79a524c 12
bcc6 0:55c7f79a524c 13
bcc6 0:55c7f79a524c 14 /**
bcc6 0:55c7f79a524c 15 * IO capabilities of the device. During development, you most likely want "JustWorks", which means
bcc6 0:55c7f79a524c 16 * no IO capabilities.
bcc6 0:55c7f79a524c 17 * It is also possible to use IO_CAPS_DISPLAY_ONLY to generate and show a pincode on the serial
bcc6 0:55c7f79a524c 18 * output.
bcc6 0:55c7f79a524c 19 */
bcc6 0:55c7f79a524c 20 #ifndef HID_SECURITY_IOCAPS
bcc6 0:55c7f79a524c 21 #define HID_SECURITY_IOCAPS (SecurityManager::IO_CAPS_NONE)
bcc6 0:55c7f79a524c 22 #endif
bcc6 0:55c7f79a524c 23
bcc6 0:55c7f79a524c 24 /**
bcc6 0:55c7f79a524c 25 * Security level. MITM disabled forces "Just Works". If you require MITM, HID_SECURITY_IOCAPS must
bcc6 0:55c7f79a524c 26 * be at least IO_CAPS_DISPLAY_ONLY.
bcc6 0:55c7f79a524c 27 */
bcc6 0:55c7f79a524c 28 #ifndef HID_SECURITY_REQUIRE_MITM
bcc6 0:55c7f79a524c 29 #define HID_SECURITY_REQUIRE_MITM false
bcc6 0:55c7f79a524c 30 #endif
bcc6 0:55c7f79a524c 31
bcc6 0:55c7f79a524c 32
bcc6 0:55c7f79a524c 33 /* UART printf */
bcc6 0:55c7f79a524c 34 Serial pc(p5, p4);
bcc6 0:55c7f79a524c 35
bcc6 0:55c7f79a524c 36 /* Sensor */
bcc6 0:55c7f79a524c 37 PAJ7620 gesture(p3, p2, p0);
bcc6 0:55c7f79a524c 38 volatile bool gestureHasIntEvent = false;
bcc6 0:55c7f79a524c 39
bcc6 0:55c7f79a524c 40 /* HID service */
bcc6 0:55c7f79a524c 41 //MouseService *msService = NULL;
bcc6 0:55c7f79a524c 42 //JoystickService *jsService = NULL;
bcc6 0:55c7f79a524c 43 KeyboardService *kbService = NULL;
bcc6 0:55c7f79a524c 44
bcc6 0:55c7f79a524c 45 /* Device name */
bcc6 0:55c7f79a524c 46 static const char DEVICE_NAME[] = "MtM_gHID";
bcc6 0:55c7f79a524c 47 static const char SHORT_DEVICE_NAME[] = "gHID";
bcc6 0:55c7f79a524c 48
bcc6 0:55c7f79a524c 49
bcc6 0:55c7f79a524c 50 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
bcc6 0:55c7f79a524c 51 {
bcc6 0:55c7f79a524c 52 pc.printf("connection\n");
bcc6 0:55c7f79a524c 53 }
bcc6 0:55c7f79a524c 54
bcc6 0:55c7f79a524c 55 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
bcc6 0:55c7f79a524c 56 {
bcc6 0:55c7f79a524c 57 BLE::Instance().gap().startAdvertising(); // restart advertising
bcc6 0:55c7f79a524c 58
bcc6 0:55c7f79a524c 59 pc.printf("disconnection\n");
bcc6 0:55c7f79a524c 60 }
bcc6 0:55c7f79a524c 61
bcc6 0:55c7f79a524c 62 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey)
bcc6 0:55c7f79a524c 63 {
bcc6 0:55c7f79a524c 64 pc.printf("Input passKey: ");
bcc6 0:55c7f79a524c 65 for (unsigned i = 0; i < Gap::ADDR_LEN; i++) {
bcc6 0:55c7f79a524c 66 pc.printf("%c", passkey[i]);
bcc6 0:55c7f79a524c 67 }
bcc6 0:55c7f79a524c 68 pc.printf("\r\n");
bcc6 0:55c7f79a524c 69 }
bcc6 0:55c7f79a524c 70
bcc6 0:55c7f79a524c 71 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status)
bcc6 0:55c7f79a524c 72 {
bcc6 0:55c7f79a524c 73 if (status == SecurityManager::SEC_STATUS_SUCCESS) {
bcc6 0:55c7f79a524c 74 pc.printf("Security success %d\r\n", status);
bcc6 0:55c7f79a524c 75 } else {
bcc6 0:55c7f79a524c 76 pc.printf("Security failed %d\r\n", status);
bcc6 0:55c7f79a524c 77 }
bcc6 0:55c7f79a524c 78 }
bcc6 0:55c7f79a524c 79
bcc6 0:55c7f79a524c 80 static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps)
bcc6 0:55c7f79a524c 81 {
bcc6 0:55c7f79a524c 82 pc.printf("Security setup initiated\r\n");
bcc6 0:55c7f79a524c 83 }
bcc6 0:55c7f79a524c 84
bcc6 0:55c7f79a524c 85 void initializeSecurity(BLE &ble)
bcc6 0:55c7f79a524c 86 {
bcc6 0:55c7f79a524c 87 bool enableBonding = true;
bcc6 0:55c7f79a524c 88 bool requireMITM = HID_SECURITY_REQUIRE_MITM;
bcc6 0:55c7f79a524c 89
bcc6 0:55c7f79a524c 90 ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback);
bcc6 0:55c7f79a524c 91 ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback);
bcc6 0:55c7f79a524c 92 ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
bcc6 0:55c7f79a524c 93
bcc6 0:55c7f79a524c 94 ble.securityManager().init(enableBonding, requireMITM, HID_SECURITY_IOCAPS);
bcc6 0:55c7f79a524c 95 }
bcc6 0:55c7f79a524c 96
bcc6 0:55c7f79a524c 97 void initializeHOGP(BLE &ble)
bcc6 0:55c7f79a524c 98 {
bcc6 0:55c7f79a524c 99 static const uint16_t uuid16_list[] = {GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
bcc6 0:55c7f79a524c 100 GattService::UUID_DEVICE_INFORMATION_SERVICE,
bcc6 0:55c7f79a524c 101 GattService::UUID_BATTERY_SERVICE};
bcc6 0:55c7f79a524c 102
bcc6 0:55c7f79a524c 103 DeviceInformationService deviceInfo(ble, "ARM", "m1", "abc", "def", "ghi", "jkl");
bcc6 0:55c7f79a524c 104
bcc6 0:55c7f79a524c 105 BatteryService batteryInfo(ble, 80);
bcc6 0:55c7f79a524c 106
bcc6 0:55c7f79a524c 107 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED |
bcc6 0:55c7f79a524c 108 GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
bcc6 0:55c7f79a524c 109 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
bcc6 0:55c7f79a524c 110 (uint8_t *)uuid16_list, sizeof(uuid16_list));
bcc6 0:55c7f79a524c 111
bcc6 0:55c7f79a524c 112 // see 5.1.2: HID over GATT Specification (pg. 25)
bcc6 0:55c7f79a524c 113 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
bcc6 0:55c7f79a524c 114 // 30ms to 50ms is recommended (5.1.2)
bcc6 0:55c7f79a524c 115 ble.gap().setAdvertisingInterval(50);
bcc6 0:55c7f79a524c 116 }
bcc6 0:55c7f79a524c 117
bcc6 0:55c7f79a524c 118 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
bcc6 0:55c7f79a524c 119 {
bcc6 0:55c7f79a524c 120 BLE &ble = params->ble;
bcc6 0:55c7f79a524c 121 ble_error_t error = params->error;
bcc6 0:55c7f79a524c 122
bcc6 0:55c7f79a524c 123 if (error != BLE_ERROR_NONE) {
bcc6 0:55c7f79a524c 124 return;
bcc6 0:55c7f79a524c 125 }
bcc6 0:55c7f79a524c 126
bcc6 0:55c7f79a524c 127 ble.gap().onConnection(connectionCallback);
bcc6 0:55c7f79a524c 128 ble.gap().onDisconnection(disconnectionCallback);
bcc6 0:55c7f79a524c 129
bcc6 0:55c7f79a524c 130 /* Setup primary service. */
bcc6 0:55c7f79a524c 131 initializeSecurity(ble);
bcc6 0:55c7f79a524c 132 // msService = new MouseService(ble);
bcc6 0:55c7f79a524c 133 // jsService = new JoystickService(ble);
bcc6 0:55c7f79a524c 134 kbService = new KeyboardService(ble);
bcc6 0:55c7f79a524c 135 initializeHOGP(ble);
bcc6 0:55c7f79a524c 136
bcc6 0:55c7f79a524c 137 /* Setup advertising. */
bcc6 0:55c7f79a524c 138 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD/*MOUSE*/);
bcc6 0:55c7f79a524c 139 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
bcc6 0:55c7f79a524c 140 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME));
bcc6 0:55c7f79a524c 141 ble.gap().setDeviceName((const uint8_t *)DEVICE_NAME);
bcc6 0:55c7f79a524c 142 ble.gap().startAdvertising();
bcc6 0:55c7f79a524c 143 }
bcc6 0:55c7f79a524c 144
bcc6 0:55c7f79a524c 145 void gestureIntEventCallback()
bcc6 0:55c7f79a524c 146 {
bcc6 0:55c7f79a524c 147 pc.printf("gestureIntEventCallback\n");
bcc6 0:55c7f79a524c 148 gestureHasIntEvent = true;
bcc6 0:55c7f79a524c 149 }
bcc6 0:55c7f79a524c 150
bcc6 0:55c7f79a524c 151 int main(void)
bcc6 0:55c7f79a524c 152 {
bcc6 0:55c7f79a524c 153 /* Force to disable the hardware flow control of Serial */
bcc6 0:55c7f79a524c 154 *((uint32_t *)(0x40002000+0x56C)) = 0;
bcc6 0:55c7f79a524c 155 pc.printf("~ Hell World ~\n");
bcc6 0:55c7f79a524c 156
bcc6 0:55c7f79a524c 157 /* Init BLE */
bcc6 0:55c7f79a524c 158 BLE& ble = BLE::Instance();
bcc6 0:55c7f79a524c 159 ble.init(bleInitComplete);
bcc6 0:55c7f79a524c 160 while(ble.hasInitialized() == false) { /* spin loop */ }
bcc6 0:55c7f79a524c 161
bcc6 0:55c7f79a524c 162 /* Config sensor */
bcc6 0:55c7f79a524c 163 pc.printf("PID(0x%04X), VID(0x%02X)\n", gesture.PID, gesture.VID);
bcc6 0:55c7f79a524c 164 gesture.IntEvent(&gestureIntEventCallback);
bcc6 0:55c7f79a524c 165
bcc6 0:55c7f79a524c 166 /* Main loop */
bcc6 0:55c7f79a524c 167 while(1){
bcc6 0:55c7f79a524c 168 /* Process interrupt event */
bcc6 0:55c7f79a524c 169 if(gestureHasIntEvent && ble.getGapState().connected){
bcc6 0:55c7f79a524c 170 gestureHasIntEvent = false;
bcc6 0:55c7f79a524c 171
bcc6 0:55c7f79a524c 172 /* Get sensor data */
bcc6 0:55c7f79a524c 173 uint16_t int_flag = gesture.ReadIntFlag();
bcc6 0:55c7f79a524c 174 pc.printf("(0x%04X)\n", int_flag);
bcc6 0:55c7f79a524c 175
bcc6 0:55c7f79a524c 176 /* Send HID code */
bcc6 0:55c7f79a524c 177 if(kbService!=NULL && kbService->isConnected()){
bcc6 0:55c7f79a524c 178 switch(int_flag){
bcc6 0:55c7f79a524c 179 case 0x0001: // Up
bcc6 0:55c7f79a524c 180 pc.printf("UpArrow\n");
bcc6 0:55c7f79a524c 181 kbService->printf("%c", UP_ARROW);
bcc6 0:55c7f79a524c 182 break;
bcc6 0:55c7f79a524c 183 case 0x0002: // Down
bcc6 0:55c7f79a524c 184 pc.printf("DownArrow\n");
bcc6 0:55c7f79a524c 185 kbService->printf("%c", DOWN_ARROW);
bcc6 0:55c7f79a524c 186 break;
bcc6 0:55c7f79a524c 187 case 0x0004: // Left
bcc6 0:55c7f79a524c 188 pc.printf("LeftArrow\n");
bcc6 0:55c7f79a524c 189 kbService->printf("%c", LEFT_ARROW);
bcc6 0:55c7f79a524c 190 break;
bcc6 0:55c7f79a524c 191 case 0x0008: // Right
bcc6 0:55c7f79a524c 192 pc.printf("RightArrow\n");
bcc6 0:55c7f79a524c 193 kbService->printf("%c", RIGHT_ARROW);
bcc6 0:55c7f79a524c 194 break;
bcc6 0:55c7f79a524c 195 case 0x0010: // Forward
bcc6 0:55c7f79a524c 196 pc.printf("PageDown\n");
bcc6 0:55c7f79a524c 197 kbService->printf("%c", KEY_PAGE_DOWN);
bcc6 0:55c7f79a524c 198 break;
bcc6 0:55c7f79a524c 199 case 0x0020: // Backword
bcc6 0:55c7f79a524c 200 pc.printf("PageUp\n");
bcc6 0:55c7f79a524c 201 kbService->printf("%c", KEY_PAGE_UP);
bcc6 0:55c7f79a524c 202 break;
bcc6 0:55c7f79a524c 203 case 0x0040: // Clockwise
bcc6 0:55c7f79a524c 204 pc.printf("F5\n");
bcc6 0:55c7f79a524c 205 kbService->printf("%c", KEY_F5);
bcc6 0:55c7f79a524c 206 break;
bcc6 0:55c7f79a524c 207 case 0x0080: // Counter-Clockwise
bcc6 0:55c7f79a524c 208 pc.printf("ESC\n");
bcc6 0:55c7f79a524c 209 kbService->printf("%c", 27);
bcc6 0:55c7f79a524c 210 break;
bcc6 0:55c7f79a524c 211 case 0x0100: // Wave
bcc6 0:55c7f79a524c 212 pc.printf("Bye Bye\n");
bcc6 0:55c7f79a524c 213 kbService->printf("Bye Bye\n");
bcc6 0:55c7f79a524c 214 break;
bcc6 0:55c7f79a524c 215 }// End of switch
bcc6 0:55c7f79a524c 216 }
bcc6 0:55c7f79a524c 217 }
bcc6 0:55c7f79a524c 218
bcc6 0:55c7f79a524c 219 /* low power wait for event */
bcc6 0:55c7f79a524c 220 // pc.printf("sleep\n");
bcc6 0:55c7f79a524c 221 ble.waitForEvent();
bcc6 0:55c7f79a524c 222 // pc.printf("wakeup\n");
bcc6 0:55c7f79a524c 223
bcc6 0:55c7f79a524c 224 }// End of while
bcc6 0:55c7f79a524c 225 }