BLE HID keyboard with gesture
Dependencies: BLE_API BLE_HID PAJ7620U2 mbed nRF51822
We have full tutorial, please visit our blog
Diff: main.cpp
- Revision:
- 0:55c7f79a524c
- Child:
- 2:6109e375f9a7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Dec 16 09:04:08 2016 +0000 @@ -0,0 +1,225 @@ +#include "mbed.h" +#include "ble/BLE.h" +#include "ble/services/BatteryService.h" +#include "ble/services/DeviceInformationService.h" + +#include "PAJ7620.h" + +#include "HIDServiceBase.h" +//#include "MouseService.h" +//#include "JoystickService.h" +#include "KeyboardService.h" + + +/** + * IO capabilities of the device. During development, you most likely want "JustWorks", which means + * no IO capabilities. + * It is also possible to use IO_CAPS_DISPLAY_ONLY to generate and show a pincode on the serial + * output. + */ +#ifndef HID_SECURITY_IOCAPS +#define HID_SECURITY_IOCAPS (SecurityManager::IO_CAPS_NONE) +#endif + +/** + * Security level. MITM disabled forces "Just Works". If you require MITM, HID_SECURITY_IOCAPS must + * be at least IO_CAPS_DISPLAY_ONLY. + */ +#ifndef HID_SECURITY_REQUIRE_MITM +#define HID_SECURITY_REQUIRE_MITM false +#endif + + +/* UART printf */ +Serial pc(p5, p4); + +/* Sensor */ +PAJ7620 gesture(p3, p2, p0); +volatile bool gestureHasIntEvent = false; + +/* HID service */ +//MouseService *msService = NULL; +//JoystickService *jsService = NULL; +KeyboardService *kbService = NULL; + +/* Device name */ +static const char DEVICE_NAME[] = "MtM_gHID"; +static const char SHORT_DEVICE_NAME[] = "gHID"; + + +void connectionCallback(const Gap::ConnectionCallbackParams_t *params) +{ + pc.printf("connection\n"); +} + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) +{ + BLE::Instance().gap().startAdvertising(); // restart advertising + + pc.printf("disconnection\n"); +} + +static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) +{ + pc.printf("Input passKey: "); + for (unsigned i = 0; i < Gap::ADDR_LEN; i++) { + pc.printf("%c", passkey[i]); + } + pc.printf("\r\n"); +} + +static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) +{ + if (status == SecurityManager::SEC_STATUS_SUCCESS) { + pc.printf("Security success %d\r\n", status); + } else { + pc.printf("Security failed %d\r\n", status); + } +} + +static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) +{ + pc.printf("Security setup initiated\r\n"); +} + +void initializeSecurity(BLE &ble) +{ + bool enableBonding = true; + bool requireMITM = HID_SECURITY_REQUIRE_MITM; + + ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback); + ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback); + ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); + + ble.securityManager().init(enableBonding, requireMITM, HID_SECURITY_IOCAPS); +} + +void initializeHOGP(BLE &ble) +{ + static const uint16_t uuid16_list[] = {GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, + GattService::UUID_DEVICE_INFORMATION_SERVICE, + GattService::UUID_BATTERY_SERVICE}; + + DeviceInformationService deviceInfo(ble, "ARM", "m1", "abc", "def", "ghi", "jkl"); + + BatteryService batteryInfo(ble, 80); + + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | + GapAdvertisingData::LE_GENERAL_DISCOVERABLE); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, + (uint8_t *)uuid16_list, sizeof(uuid16_list)); + + // see 5.1.2: HID over GATT Specification (pg. 25) + ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + // 30ms to 50ms is recommended (5.1.2) + ble.gap().setAdvertisingInterval(50); +} + +void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) +{ + BLE &ble = params->ble; + ble_error_t error = params->error; + + if (error != BLE_ERROR_NONE) { + return; + } + + ble.gap().onConnection(connectionCallback); + ble.gap().onDisconnection(disconnectionCallback); + + /* Setup primary service. */ + initializeSecurity(ble); +// msService = new MouseService(ble); +// jsService = new JoystickService(ble); + kbService = new KeyboardService(ble); + initializeHOGP(ble); + + /* Setup advertising. */ + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD/*MOUSE*/); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME)); + ble.gap().setDeviceName((const uint8_t *)DEVICE_NAME); + ble.gap().startAdvertising(); +} + +void gestureIntEventCallback() +{ + pc.printf("gestureIntEventCallback\n"); + gestureHasIntEvent = true; +} + +int main(void) +{ + /* Force to disable the hardware flow control of Serial */ + *((uint32_t *)(0x40002000+0x56C)) = 0; + pc.printf("~ Hell World ~\n"); + + /* Init BLE */ + BLE& ble = BLE::Instance(); + ble.init(bleInitComplete); + while(ble.hasInitialized() == false) { /* spin loop */ } + + /* Config sensor */ + pc.printf("PID(0x%04X), VID(0x%02X)\n", gesture.PID, gesture.VID); + gesture.IntEvent(&gestureIntEventCallback); + + /* Main loop */ + while(1){ + /* Process interrupt event */ + if(gestureHasIntEvent && ble.getGapState().connected){ + gestureHasIntEvent = false; + + /* Get sensor data */ + uint16_t int_flag = gesture.ReadIntFlag(); + pc.printf("(0x%04X)\n", int_flag); + + /* Send HID code */ + if(kbService!=NULL && kbService->isConnected()){ + switch(int_flag){ + case 0x0001: // Up + pc.printf("UpArrow\n"); + kbService->printf("%c", UP_ARROW); + break; + case 0x0002: // Down + pc.printf("DownArrow\n"); + kbService->printf("%c", DOWN_ARROW); + break; + case 0x0004: // Left + pc.printf("LeftArrow\n"); + kbService->printf("%c", LEFT_ARROW); + break; + case 0x0008: // Right + pc.printf("RightArrow\n"); + kbService->printf("%c", RIGHT_ARROW); + break; + case 0x0010: // Forward + pc.printf("PageDown\n"); + kbService->printf("%c", KEY_PAGE_DOWN); + break; + case 0x0020: // Backword + pc.printf("PageUp\n"); + kbService->printf("%c", KEY_PAGE_UP); + break; + case 0x0040: // Clockwise + pc.printf("F5\n"); + kbService->printf("%c", KEY_F5); + break; + case 0x0080: // Counter-Clockwise + pc.printf("ESC\n"); + kbService->printf("%c", 27); + break; + case 0x0100: // Wave + pc.printf("Bye Bye\n"); + kbService->printf("Bye Bye\n"); + break; + }// End of switch + } + } + + /* low power wait for event */ +// pc.printf("sleep\n"); + ble.waitForEvent(); +// pc.printf("wakeup\n"); + + }// End of while +}