BLE HID keyboard with gesture
Dependencies: BLE_API BLE_HID PAJ7620U2 mbed nRF51822
We have full tutorial, please visit our blog
main.cpp
- Committer:
- bcc6
- Date:
- 2017-01-17
- Revision:
- 3:656f8fb89f05
- Parent:
- 2:6109e375f9a7
File content as of revision 3:656f8fb89f05:
/* Copyright (c) 2016 MtM Technology Corporation, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "mbed.h" #include "ble/BLE.h" #include "debug.h" #include "PAJ7620U2.h" #include "BLE_HID/DeviceInformationService.h" #include "BLE_HID/BatteryService.h" #include "BLE_HID/HIDServiceBase.h" #include "BLE_HID/KeyboardService.h" #define DEVICE_NAME ("MtM_gHID") #define TX_POWER_dBm (0) // -40, -20, -16, -12, -8, -4, 0, 4 #define BD_ADDRESS_TYPE (BLEProtocol::AddressType::RANDOM_STATIC) #define BD_ADDRESS ((Gap::Address_t){0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC}) #define ENABLE_BONDING (true) #define REQUIRE_MITM (false) #define IOCAPS (SecurityManager::IO_CAPS_NONE) #define PASSKEY ((SecurityManager::Passkey_t){'1', '2', '3', '4', '5', '6'}) #define MANUFACTURERS_NAME ("MtM") #define MODEL_NAME (NULL) #define SERIAL_NUMBER (NULL) #define HW_VERSION (NULL) #define FW_VERSION (NULL) #define SW_VERSION (NULL) #if 0 #define PNP_ID &((PnPID_t){0x01, 0xFFFE, 0x0001, 0x0001}) // From Bluetooth SIG #else #define PNP_ID &((PnPID_t){0x02, 0x1915, 0xEEEE, 0x0001}) // From USB-IF #endif #define MIN_CONN_INTERVAL (Gap::MSEC_TO_GAP_DURATION_UNITS(10)); // 10ms #define MAX_CONN_INTERVAL (Gap::MSEC_TO_GAP_DURATION_UNITS(30)); // 30ms #define SLAVE_LATENCY (6) #define CONN_SUP_TIMEOUT (43) // 430ms #define ADV_INTERVAL (50) // 50ms #define ADV_TIMEOUT (60) // 60sec /* UART for debug (log, assert) */ Serial dbg(p5, p4); /* Sensor */ PAJ7620U2 gesture(p3, p2, p0); volatile bool gestureHasIntEvent = false; /* HID service */ KeyboardService *kbService = NULL; static void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { log("connection\n"); log("role(%d)\n", params->role); log("peerAddrType(%d), peerAddr(%02X:%02X:%02X:%02X:%02X:%02X)\n", params->peerAddrType, params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0]); log("ownAddrType(%d), ownAddr(%02X:%02X:%02X:%02X:%02X:%02X)\n", params->ownAddrType, params->ownAddr[5], params->ownAddr[4], params->ownAddr[3], params->ownAddr[2], params->ownAddr[1], params->ownAddr[0]); log("connectionParams(%d, %d, %d, %d)\n", params->connectionParams->minConnectionInterval, params->connectionParams->maxConnectionInterval, params->connectionParams->slaveLatency, params->connectionParams->connectionSupervisionTimeout); } static void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { BLE::Instance().gap().startAdvertising(); // restart advertising log("disconnection\n"); } static void timeoutCallback(const Gap::TimeoutSource_t source) { log("timeout(%d)\n", source); } static void securitySetupInitiatedCallback(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps) { log("Security setup initiated\r\n"); } static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) { if (status == SecurityManager::SEC_STATUS_SUCCESS) { log("Security success %d\r\n", status); } else { log("Security failed %d\r\n", status); } } static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) { log("Input passKey: "); for (unsigned i = 0; i < Gap::ADDR_LEN; i++) { log("%c", passkey[i]); } log("\r\n"); } static void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) { log("InitComplete\n"); BLE &ble = params->ble; ble_error_t error = params->error; assert(error == BLE_ERROR_NONE); /* Set Tx power */ error = ble.gap().setTxPower(TX_POWER_dBm); assert(error == BLE_ERROR_NONE); /* Set address */ error = ble.gap().setAddress(BD_ADDRESS_TYPE, BD_ADDRESS); assert(error == BLE_ERROR_NONE); /* Initialize BLE security */ error = ble.securityManager().init(ENABLE_BONDING, REQUIRE_MITM, IOCAPS, PASSKEY); assert(error == BLE_ERROR_NONE); #if 1 // After reset, clear bonding state /* Purge all bonding state */ error = ble.securityManager().purgeAllBondingState(); assert(error == BLE_ERROR_NONE); #endif #if 0 // Disable white-list /* Set white-list */ BLEProtocol::Address_t addresses[2]; Gap::Whitelist_t whitelist; whitelist.addresses = addresses; whitelist.size = 0; whitelist.capacity = 2; error = ble.securityManager().getAddressesFromBondTable(whitelist); assert(error == BLE_ERROR_NONE); log("getAddressesFromBondTable (%d)\n", whitelist.size); for(int i=0; i<whitelist.size; i++) { int type = (int)whitelist.addresses[i].type; uint8_t *addr = (uint8_t *)whitelist.addresses[i].address; log("type(%d), addr(%02X:%02X:%02X:%02X:%02X:%02X)\n", type, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); } error = ble.gap().setWhitelist(whitelist); assert(error == BLE_ERROR_NONE); error = ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); // Allow scan requests and connect requests from any device assert(error == BLE_ERROR_NONE); #endif /* Set callback functions */ ble.gap().onConnection(connectionCallback); ble.gap().onDisconnection(disconnectionCallback); ble.gap().onTimeout(timeoutCallback); ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback); ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback); /* Setup primary service */ DeviceInformationService deviceInfo(ble, MANUFACTURERS_NAME, MODEL_NAME, SERIAL_NUMBER, HW_VERSION, FW_VERSION, SW_VERSION, PNP_ID); BatteryService batteryInfo(ble, 80); kbService = new KeyboardService(ble); /* Connection parameters */ Gap::ConnectionParams_t conn_params; conn_params.minConnectionInterval = MIN_CONN_INTERVAL; conn_params.maxConnectionInterval = MAX_CONN_INTERVAL; conn_params.slaveLatency = SLAVE_LATENCY; conn_params.connectionSupervisionTimeout = CONN_SUP_TIMEOUT; ble.gap().setPreferredConnectionParams(&conn_params); /* Setup advertising. */ static const uint16_t uuid16_list[] = { GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE }; ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(ADV_INTERVAL); ble.gap().setAdvertisingTimeout(ADV_TIMEOUT); error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_LIMITED_DISCOVERABLE); assert(error == BLE_ERROR_NONE); error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); assert(error == BLE_ERROR_NONE); error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::KEYBOARD); assert(error == BLE_ERROR_NONE); error = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); assert(error == BLE_ERROR_NONE); error = ble.gap().setDeviceName((const uint8_t *)DEVICE_NAME); assert(error == BLE_ERROR_NONE); error = ble.gap().startAdvertising(); assert(error == BLE_ERROR_NONE); } static void gestureIntEventCallback() { log("gestureIntEventCallback\n"); gestureHasIntEvent = true; } int main(void) { /* Disable the hardware flow control of Serial */ *((uint32_t *)(0x40002000+0x56C)) = 0; log("\n"); log("~ Hell World ~\n"); log("\n"); /* Init BLE */ BLE& ble = BLE::Instance(); ble.init(bleInitComplete); while(ble.hasInitialized() == false) { /* spin loop */ } /* Config sensor */ log("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(); log("(0x%04X)\n", int_flag); /* Send HID code */ if(kbService!=NULL && kbService->isConnected()){ switch(int_flag){ case 0x0001: // Up log("UpArrow\n"); kbService->printf("%c", UP_ARROW); break; case 0x0002: // Down log("DownArrow\n"); kbService->printf("%c", DOWN_ARROW); break; case 0x0004: // Left log("LeftArrow\n"); kbService->printf("%c", LEFT_ARROW); break; case 0x0008: // Right log("RightArrow\n"); kbService->printf("%c", RIGHT_ARROW); break; case 0x0010: // Forward log("PageDown\n"); kbService->printf("%c", KEY_PAGE_DOWN); break; case 0x0020: // Backword log("PageUp\n"); kbService->printf("%c", KEY_PAGE_UP); break; case 0x0040: // Clockwise log("F5\n"); kbService->printf("%c", KEY_F5); break; case 0x0080: // Counter-Clockwise log("ESC\n"); kbService->printf("%c", 27); break; case 0x0100: // Wave log("Bye Bye\n"); kbService->printf("Bye Bye\n"); break; }// End of switch } } /* low power wait for event */ // log("sleep\n"); ble.waitForEvent(); // log("wakeup\n"); }// End of while }