diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8ccd82bc..babef89d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -88,8 +88,11 @@ set(SDK_SOURCE_FILES set(TINYCRYPT_SRC libs/mynewt-nimble/ext/tinycrypt/src/aes_encrypt.c - libs/mynewt-nimble/ext/tinycrypt/src/utils.c - ) + libs/mynewt-nimble/ext/tinycrypt/src/utils.c + libs/mynewt-nimble/ext/tinycrypt/src/ecc.c + libs/mynewt-nimble/ext/tinycrypt/src/cmac_mode.c + libs/mynewt-nimble/ext/tinycrypt/src/ecc_dh.c + ) set(NIMBLE_SRC libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c @@ -161,6 +164,10 @@ set(NIMBLE_SRC libs/mynewt-nimble/nimble/host/services/gap/src/ble_svc_gap.c libs/mynewt-nimble/nimble/host/services/gatt/src/ble_svc_gatt.c libs/mynewt-nimble/nimble/host/util/src/addr.c + libs/mynewt-nimble/nimble/host/src/ble_sm.c + libs/mynewt-nimble/nimble/host/src/ble_sm_sc.c + libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c + ) set(LVGL_SRC @@ -339,6 +346,8 @@ list(APPEND SOURCE_FILES DisplayApp/Screens/Label.cpp DisplayApp/Screens/FirmwareUpdate.cpp DisplayApp/Screens/Music.cpp + Components/Ble/HidService.cpp + Components/Ble/BatteryInformationService.cpp DisplayApp/Screens/FirmwareValidation.cpp DisplayApp/Screens/ApplicationList.cpp main.cpp @@ -603,7 +612,7 @@ target_compile_options(lvgl PRIVATE set(EXECUTABLE_NAME "pinetime-app") set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld") -add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) +add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES} ) set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME}) target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl) target_compile_options(${EXECUTABLE_NAME} PUBLIC diff --git a/src/Components/Ble/BatteryInformationService.cpp b/src/Components/Ble/BatteryInformationService.cpp new file mode 100644 index 00000000..127a29d4 --- /dev/null +++ b/src/Components/Ble/BatteryInformationService.cpp @@ -0,0 +1,60 @@ +#include "BatteryInformationService.h" + +using namespace Pinetime::Controllers; + +constexpr ble_uuid16_t BatteryInformationService::batteryInformationServiceUuid; +constexpr ble_uuid16_t BatteryInformationService::batteryLevelUuid; + + + +int BatteryInformationServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + auto* batteryInformationService = static_cast(arg); + return batteryInformationService->OnBatteryServiceRequested(conn_handle, attr_handle, ctxt); +} + +BatteryInformationService::BatteryInformationService() : + characteristicDefinition{ + { + .uuid = (ble_uuid_t *) &batteryLevelUuid, + .access_cb = BatteryInformationServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = &batteryLevelHandle + }, + { + 0 + } + }, + serviceDefinition{ + { + /* Device Information Service */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = (ble_uuid_t *) &batteryInformationServiceUuid, + .characteristics = characteristicDefinition + }, + { + 0 + }, + }{ + +} + +void BatteryInformationService::Init() { + int res = 0; + res = ble_gatts_count_cfg(serviceDefinition); + ASSERT(res == 0); + + res = ble_gatts_add_svcs(serviceDefinition); + ASSERT(res == 0); +} + +int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, + ble_gatt_access_ctxt *context) { + if(attributeHandle == batteryLevelHandle) { + NRF_LOG_INFO("BATTERY : handle = %d", batteryLevelHandle); + static uint8_t batteryValue = 50; + int res = os_mbuf_append(context->om, &batteryValue, 1); + return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + return 0; +} diff --git a/src/Components/Ble/BatteryInformationService.h b/src/Components/Ble/BatteryInformationService.h new file mode 100644 index 00000000..550a5812 --- /dev/null +++ b/src/Components/Ble/BatteryInformationService.h @@ -0,0 +1,39 @@ +#pragma once +#include + +namespace Pinetime { + namespace System { + class SystemTask; + } + namespace Controllers { + class BatteryInformationService { + public: + BatteryInformationService(); + void Init(); + + int + OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context); + + private: + static constexpr uint16_t batteryInformationServiceId {0x180F}; + static constexpr uint16_t batteryLevelId {0x2A19}; + + static constexpr ble_uuid16_t batteryInformationServiceUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = batteryInformationServiceId + }; + + static constexpr ble_uuid16_t batteryLevelUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = batteryLevelId + }; + + struct ble_gatt_chr_def characteristicDefinition[3]; + struct ble_gatt_svc_def serviceDefinition[2]; + + uint16_t batteryLevelHandle; + + }; + } +} + diff --git a/src/Components/Ble/DeviceInformationService.cpp b/src/Components/Ble/DeviceInformationService.cpp index c1d55541..b3bc738a 100644 --- a/src/Components/Ble/DeviceInformationService.cpp +++ b/src/Components/Ble/DeviceInformationService.cpp @@ -8,6 +8,7 @@ constexpr ble_uuid16_t DeviceInformationService::serialNumberUuid; constexpr ble_uuid16_t DeviceInformationService::fwRevisionUuid; constexpr ble_uuid16_t DeviceInformationService::deviceInfoUuid; constexpr ble_uuid16_t DeviceInformationService::hwRevisionUuid; +constexpr ble_uuid16_t DeviceInformationService::pnpIdUuid;; int DeviceInformationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { auto deviceInformationService = static_cast(arg); @@ -27,7 +28,7 @@ void DeviceInformationService::Init() { int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt) { const char *str; - + size_t size = 0; switch (ble_uuid_u16(ctxt->chr->uuid)) { case manufacturerNameId: str = manufacturerName; @@ -44,11 +45,15 @@ int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16 case hwRevisionId: str = hwRevision; break; + case pnpIdId: + str = reinterpret_cast(pnpIdBuf); + size = 7; + break; default: return BLE_ATT_ERR_UNLIKELY; } - int res = os_mbuf_append(ctxt->om, str, strlen(str)); + int res = os_mbuf_append(ctxt->om, str, (size!=0) ? size : strlen(str)); return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } @@ -84,6 +89,12 @@ DeviceInformationService::DeviceInformationService() : .arg = this, .flags = BLE_GATT_CHR_F_READ, }, + { + .uuid = (ble_uuid_t *) &pnpIdUuid, + .access_cb = DeviceInformationCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ, + }, { 0 } diff --git a/src/Components/Ble/DeviceInformationService.h b/src/Components/Ble/DeviceInformationService.h index 7d7cea96..9b5aa265 100644 --- a/src/Components/Ble/DeviceInformationService.h +++ b/src/Components/Ble/DeviceInformationService.h @@ -21,12 +21,14 @@ namespace Pinetime { static constexpr uint16_t serialNumberId {0x2a25}; static constexpr uint16_t fwRevisionId {0x2a26}; static constexpr uint16_t hwRevisionId {0x2a27}; + static constexpr uint16_t pnpIdId {0x2a50}; static constexpr const char* manufacturerName = "Codingfield"; static constexpr const char* modelNumber = "1"; static constexpr const char* serialNumber = "9.8.7.6.5.4"; static constexpr const char* fwRevision = "0.7.0"; static constexpr const char* hwRevision = "1.0.0"; + uint8_t pnpIdBuf[7] {0x02, 0xc4, 0x10, 0x01, 0x00, 0x01, 0x00}; static constexpr ble_uuid16_t deviceInfoUuid { .u { .type = BLE_UUID_TYPE_16 }, @@ -58,7 +60,12 @@ namespace Pinetime { .value = hwRevisionId }; - struct ble_gatt_chr_def characteristicDefinition[6]; + static constexpr ble_uuid16_t pnpIdUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = pnpIdId + }; + + struct ble_gatt_chr_def characteristicDefinition[7]; struct ble_gatt_svc_def serviceDefinition[2]; diff --git a/src/Components/Ble/HidService.cpp b/src/Components/Ble/HidService.cpp new file mode 100644 index 00000000..4e0e18a7 --- /dev/null +++ b/src/Components/Ble/HidService.cpp @@ -0,0 +1,315 @@ +#include "HidService.h" + +using namespace Pinetime::Controllers; + +constexpr ble_uuid16_t HidService::hidServiceUuid; +constexpr ble_uuid16_t HidService::protocolModeUuid; +constexpr ble_uuid16_t HidService::reportUuid; +constexpr ble_uuid16_t HidService::reportMapUuid; +constexpr ble_uuid16_t HidService::bootKeyboardInputReportUuid; +constexpr ble_uuid16_t HidService::bootKeyboardOutputReportUuid; +constexpr ble_uuid16_t HidService::bootMouseInputReportUuid; +constexpr ble_uuid16_t HidService::informationUuid; +constexpr ble_uuid16_t HidService::controlPointUuid; +constexpr ble_uuid16_t HidService::descriptorUuid; +constexpr ble_uuid16_t HidService::descriptorMapUuid; + +namespace { + char* OperationToString(uint8_t op) { + char* operation; + switch(op) { + case BLE_GATT_ACCESS_OP_READ_CHR: operation = "READ CHR"; break; + case BLE_GATT_ACCESS_OP_WRITE_CHR: operation = "WRITE CHR"; break; + case BLE_GATT_ACCESS_OP_READ_DSC: operation = "READ DSC"; break; + case BLE_GATT_ACCESS_OP_WRITE_DSC: operation = "WRITE DSC"; break; + default: operation = "?"; break; + } + return operation; + } + + int HidServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + auto* hidService = static_cast(arg); + return hidService->OnHidServiceRequested(conn_handle, attr_handle, ctxt); + } + + int HidServiceReportDescriptorCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + auto* hidService = static_cast(arg); + return hidService->OnReportDescriptorRequested(conn_handle, attr_handle, ctxt); + } + + + int HidServiceReportMapDescriptorCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + auto* hidService = static_cast(arg); + return hidService->OnReportMapDescriptorRequested(conn_handle, attr_handle, ctxt); + } + + + static const uint8_t report_map_data[] = + {0x05, 0x01, // Usage Pg (Generic Desktop) + 0x09, 0x06, // Usage (Keyboard) + 0xA1, 0x01, // Collection: (Application) + 0x85, 0x01, // Report Id (1) + // + 0x05, 0x07, // Usage Pg (Key Codes) + 0x19, 0xE0, // Usage Min (224) + 0x29, 0xE7, // Usage Max (231) + 0x15, 0x00, // Log Min (0) + 0x25, 0x01, // Log Max (1) + // + // Modifier byte + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x81, 0x02, // Input: (Data, Variable, Absolute) + // + // Reserved byte + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x01, // Input: (Constant) + // + // LED report + 0x95, 0x05, // Report Count (5) + 0x75, 0x01, // Report Size (1) + 0x05, 0x08, // Usage Pg (LEDs) + 0x19, 0x01, // Usage Min (1) + 0x29, 0x05, // Usage Max (5) + 0x91, 0x02, // Output: (Data, Variable, Absolute) + // + // LED report padding + 0x95, 0x01, // Report Count (1) + 0x75, 0x03, // Report Size (3) + 0x91, 0x01, // Output: (Constant) + // + // Key arrays (6 bytes) + 0x95, 0x06, // Report Count (6) + 0x75, 0x08, // Report Size (8) + 0x15, 0x00, // Log Min (0) + 0x25, 0x65, // Log Max (101) + 0x05, 0x07, // Usage Pg (Key Codes) + 0x19, 0x00, // Usage Min (0) + 0x29, 0x65, // Usage Max (101) + 0x81, 0x00, // Input: (Data, Array) + // + 0xC0, // End Collection + }; +} + +HidService::HidService() : + reportInDescriptorDefinition { + { + .uuid = (const ble_uuid_t *) &descriptorUuid, + .att_flags = 5, + .access_cb = HidServiceCallback, + }, + {0} + }, + reportOutDescriptorDefinition { + { + .uuid = (const ble_uuid_t *) &descriptorUuid, + .att_flags = 5, + .access_cb = HidServiceCallback, + }, + {0} + }, + reportDescriptorDefinition{{ + .uuid = (const ble_uuid_t *) &descriptorUuid, + .att_flags = 5, + .access_cb = HidServiceReportDescriptorCallback, + },{0} + }, + reportMapDescriptorDefinitions{ + { + .uuid = (const ble_uuid_t *) &descriptorMapUuid, + .att_flags = 5, + .access_cb = HidServiceReportMapDescriptorCallback, + },{0} + }, + characteristicDefinition{ + { + .uuid = (ble_uuid_t *) &protocolModeUuid, + .access_cb = HidServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE_NO_RSP, + .val_handle = &protocolModeHandle + + }, + { + .uuid = (ble_uuid_t *) &reportUuid, + .access_cb = HidServiceCallback, + .arg = this, + .descriptors = reportDescriptorDefinition, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE, + .val_handle = &reportHandle + }, + { + .uuid = (ble_uuid_t *) &reportMapUuid, + .access_cb = HidServiceCallback, + .arg = this, + .descriptors = reportMapDescriptorDefinitions, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC, + .val_handle = &reportMapHandle + }, + /*{ + .uuid = (ble_uuid_t *) &bootKeyboardInputReportUuid, + .access_cb = HidServiceCallback, + .arg = this, + .descriptors = reportInDescriptorDefinition, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + }, + { + .uuid = (ble_uuid_t *) &bootKeyboardOutputReportUuid, + .access_cb = HidServiceCallback, + .arg = this, + .descriptors = reportOutDescriptorDefinition, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP, + }, + { + .uuid = (ble_uuid_t *) &bootMouseInputReportUuid, + .access_cb = HidServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + },*/ + { + .uuid = (ble_uuid_t *) &informationUuid, + .access_cb = HidServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = &informationHandle + }, + { + .uuid = (ble_uuid_t *) &controlPointUuid, + .access_cb = HidServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, + .val_handle = &controlPointHandle + }, + { + 0 + } + }, + serviceDefinition{ + { + /* Device Information Service */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = (ble_uuid_t *) &hidServiceUuid, + .characteristics = characteristicDefinition + }, + { + 0 + }, + }{ + +} + +void HidService::Init() { + int res = 0; + res = ble_gatts_count_cfg(serviceDefinition); + ASSERT(res == 0); + + res = ble_gatts_add_svcs(serviceDefinition); + ASSERT(res == 0); + asm("nop"); +} + +int +HidService::OnHidServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context) { + char* operation = ::OperationToString(context->op); + + int res = 0; + char* attribute; + if(attributeHandle == protocolModeHandle) { + attribute = "protocolModeHandle"; + static uint8_t protcoleModeValue = 1; + res = os_mbuf_append(context->om, &protcoleModeValue, 1); + } else if(attributeHandle == reportHandle) { + attribute = "reportHandle"; + } else if(attributeHandle == reportMapHandle) { + attribute = "reportMapHandle"; + res = os_mbuf_append(context->om, &report_map_data, sizeof(report_map_data)); + } + else if(attributeHandle == informationHandle) { + attribute = "informationHandle"; + static uint32_t infoValue = 0x01110002; + res = os_mbuf_append(context->om, &infoValue, 4); + + } + else if(attributeHandle == controlPointHandle) { + attribute = "controlPointHandle"; + } + else { + attribute = "???"; + } + + NRF_LOG_INFO("HID : Attribute = %d = %s, operation = %s",attributeHandle, attribute, operation); + return res; +} + +int HidService::OnReportDescriptorRequested(uint16_t connectionHandle, uint16_t attributeHandle, + ble_gatt_access_ctxt *context) { + NRF_LOG_INFO("HID : Attribute = %d = Callback report descriptor, operation = %s",attributeHandle, ::OperationToString(context->op)); + int res = 0; + static uint16_t reportValue = 0x0101; + + res = os_mbuf_append(context->om, &reportValue, 2); + return res; +} + +int HidService::OnReportMapDescriptorRequested(uint16_t connectionHandle, uint16_t attributeHandle, + ble_gatt_access_ctxt *context) { + NRF_LOG_INFO("HID : Attribute = %d = Callback report map descriptor, operation = %s",attributeHandle, ::OperationToString(context->op)); + int res = 0; + static uint16_t externalReportValue = 0x0036; + + res = os_mbuf_append(context->om, &externalReportValue, 2); + return res; +} + +uint8_t helloWorld[] { + 0x0b, + 0x08, + 0x0f, + 0x0f, + 0x12, + 0x2c, + 0x1d, + 0x12, + 0x15, + 0x0f, + 0x07, + 0x25 +}; +uint8_t testIndex = 0; +bool push = true; +void HidService::Test() { +# if 1 + uint8_t modif = (testIndex == 0) ? (1<<1) : 0; + if(push && testIndex < 12) { + uint8_t buf[9]{modif, 0x0, 0x00, helloWorld[testIndex], 0x00, 0x00, 0x00, 0x00, 0x00}; + auto *om = ble_hs_mbuf_from_flat(&buf, 9); + + uint16_t connectionHandle = 1; + + if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) { + return; + } + ble_gattc_notify_custom(1, reportHandle, om); + testIndex++; + push = false; + NRF_LOG_INFO("PUSH %d %d", helloWorld[testIndex], modif); + } else { + static uint8_t buf[9]{0, 0x0, 0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00}; + auto *om = ble_hs_mbuf_from_flat(&buf, 9); + + uint16_t connectionHandle = 1; + + if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) { + return; + } + ble_gattc_notify_custom(1, reportHandle, om); + NRF_LOG_INFO("Release"); + push = true; + } + +#endif +} + + diff --git a/src/Components/Ble/HidService.h b/src/Components/Ble/HidService.h new file mode 100644 index 00000000..a9d87d1f --- /dev/null +++ b/src/Components/Ble/HidService.h @@ -0,0 +1,112 @@ +#pragma once +#include + +namespace Pinetime { + namespace System { + class SystemTask; + } + namespace Controllers { + class HidService { + public: + HidService(); + void Init(); + + int OnHidServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context); + + int + OnReportDescriptorRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context); + + int OnReportMapDescriptorRequested(uint16_t connectionHandle, uint16_t attributeHandle, + ble_gatt_access_ctxt *context); + + void Test(); + + private: + static constexpr uint16_t hidServiceId {0x1812}; + static constexpr uint16_t protocolModeId {0x2A4E}; + static constexpr uint16_t reportId {0x2A4D}; + static constexpr uint16_t reportMapId {0x2A4B}; + static constexpr uint16_t bootKeyboardInputReportId {0x2A22}; + static constexpr uint16_t bootKeyboardOutputReportId {0x2A32}; + static constexpr uint16_t bootMouseInputReportId {0x2A33}; + static constexpr uint16_t informationId {0x2A4A}; + static constexpr uint16_t controlPointId {0x2A4C}; + + static constexpr uint16_t descriptorId {0x2908}; + static constexpr uint16_t reportMapDescriptorId {0x2907}; + + static constexpr ble_uuid16_t hidServiceUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = hidServiceId + }; + + static constexpr ble_uuid16_t protocolModeUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = protocolModeId + }; + + static constexpr ble_uuid16_t reportUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = reportId + }; + + static constexpr ble_uuid16_t reportMapUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = reportMapId + }; + + static constexpr ble_uuid16_t bootKeyboardInputReportUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = bootKeyboardInputReportId + }; + + static constexpr ble_uuid16_t bootKeyboardOutputReportUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = bootKeyboardOutputReportId + }; + + static constexpr ble_uuid16_t bootMouseInputReportUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = bootMouseInputReportId + }; + + static constexpr ble_uuid16_t informationUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = informationId + }; + + static constexpr ble_uuid16_t controlPointUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = controlPointId + }; + + static constexpr ble_uuid16_t descriptorUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = descriptorId + }; + + + static constexpr ble_uuid16_t descriptorMapUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = reportMapDescriptorId + }; + + + struct ble_gatt_dsc_def reportInDescriptorDefinition[2]; + struct ble_gatt_dsc_def reportOutDescriptorDefinition[2]; + struct ble_gatt_dsc_def reportDescriptorDefinition[2]; + struct ble_gatt_dsc_def reportMapDescriptorDefinitions[2]; + struct ble_gatt_chr_def characteristicDefinition[9]; + struct ble_gatt_svc_def serviceDefinition[2]; + + uint16_t protocolModeHandle; + uint16_t reportHandle; + uint16_t reportMapHandle; + uint16_t informationHandle; + uint16_t controlPointHandle; + + char *OperationToString(uint8_t op); + }; + } +} + diff --git a/src/Components/Ble/NimbleController.cpp b/src/Components/Ble/NimbleController.cpp index a865a824..bc1d5097 100644 --- a/src/Components/Ble/NimbleController.cpp +++ b/src/Components/Ble/NimbleController.cpp @@ -37,7 +37,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, anService{systemTask, notificationManager}, alertNotificationClient{systemTask, notificationManager}, currentTimeService{dateTimeController}, - musicService{systemTask} { + musicService{systemTask}, + hidService{}{ } @@ -83,6 +84,8 @@ void NimbleController::Init() { currentTimeClient.Init(); currentTimeService.Init(); musicService.Init(); + hidService.Init(); + batteryInformationService.Init(); anService.Init(); @@ -133,7 +136,12 @@ void NimbleController::StartAdvertising() { fields.uuids128 = &dfuServiceUuid; fields.num_uuids128 = 1; fields.uuids128_is_complete = 1; + fields.uuids16 = &hidServiceUuid; + fields.num_uuids16 = 1; + fields.uuids16_is_complete = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + fields.appearance = 962; + fields.appearance_is_present = 1; rsp_fields.name = (uint8_t *)"Pinetime-JF"; rsp_fields.name_len = strlen("Pinetime-JF"); @@ -185,6 +193,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) { bleController.Connect(); systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleConnected); connectionHandle = event->connect.conn_handle; + ble_gap_security_initiate(connectionHandle); // Service discovery is deffered via systemtask } } @@ -332,3 +341,7 @@ uint16_t NimbleController::connHandle() { return connectionHandle; } +void NimbleController::Test() { + hidService.Test(); +} + diff --git a/src/Components/Ble/NimbleController.h b/src/Components/Ble/NimbleController.h index 49f4377b..300b5f5b 100644 --- a/src/Components/Ble/NimbleController.h +++ b/src/Components/Ble/NimbleController.h @@ -8,6 +8,8 @@ #include "DfuService.h" #include "CurrentTimeService.h" #include "MusicService.h" +#include "HidService.h" +#include "BatteryInformationService.h" #include namespace Pinetime { @@ -42,6 +44,8 @@ namespace Pinetime { uint16_t connHandle(); + void Test(); + private: static constexpr const char* deviceName = "Pinetime-JF"; Pinetime::System::SystemTask& systemTask; @@ -57,6 +61,8 @@ namespace Pinetime { AlertNotificationClient alertNotificationClient; CurrentTimeService currentTimeService; MusicService musicService; + HidService hidService; + BatteryInformationService batteryInformationService; uint8_t addrType; // 1 = Random, 0 = PUBLIC uint16_t connectionHandle = 0; @@ -66,6 +72,11 @@ namespace Pinetime { .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00} }; + + ble_uuid16_t hidServiceUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = 0x1812 + }; }; } } diff --git a/src/SystemTask/SystemTask.cpp b/src/SystemTask/SystemTask.cpp index b515d1ab..66d429e2 100644 --- a/src/SystemTask/SystemTask.cpp +++ b/src/SystemTask/SystemTask.cpp @@ -101,7 +101,7 @@ void SystemTask::Work() { while(true) { uint8_t msg; - if (xQueueReceive(systemTaksMsgQueue, &msg, isSleeping?2500 : 1000)) { + if (xQueueReceive(systemTaksMsgQueue, &msg, isSleeping?100 : 100)) { Messages message = static_cast(msg); switch(message) { case Messages::GoToRunning: @@ -126,7 +126,7 @@ void SystemTask::Work() { case Messages::BleConnected: ReloadIdleTimer(); isBleDiscoveryTimerRunning = true; - bleDiscoveryTimer = 5; + bleDiscoveryTimer = 50; break; case Messages::BleFirmwareUpdateStarted: doNotGoToSleep = true; @@ -159,10 +159,12 @@ void SystemTask::Work() { if(isBleDiscoveryTimerRunning) { if(bleDiscoveryTimer == 0) { - isBleDiscoveryTimerRunning = false; + //isBleDiscoveryTimerRunning = false; // Services discovery is deffered from 3 seconds to avoid the conflicts between the host communicating with the // tharget and vice-versa. I'm not sure if this is the right way to handle this... - nimbleController.StartDiscovery(); + //nimbleController.StartDiscovery(); + nimbleController.Test(); + bleDiscoveryTimer = 0; } else { bleDiscoveryTimer--; } diff --git a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h index 6efa3f28..05dc8e66 100644 --- a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h +++ b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h @@ -695,7 +695,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_BONDING -#define MYNEWT_VAL_BLE_SM_BONDING (0) +#define MYNEWT_VAL_BLE_SM_BONDING (1) #endif #ifndef MYNEWT_VAL_BLE_SM_IO_CAP @@ -723,27 +723,27 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST -#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (1) #endif #ifndef MYNEWT_VAL_BLE_SM_SC -#define MYNEWT_VAL_BLE_SM_SC (0) +#define MYNEWT_VAL_BLE_SM_SC (1) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (1) #endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST -#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (1) #endif #ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS -#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3) +#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (6) #endif #ifndef MYNEWT_VAL_BLE_STORE_MAX_CCCDS -#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8) +#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (20) #endif /*** @apache-mynewt-nimble/nimble/host/services/ans */ diff --git a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c index 64196b36..088601ba 100644 --- a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c +++ b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c @@ -46,6 +46,6 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * have separate task for NimBLE host, but since something needs to handle * default queue it is just easier to make separate task which does this. */ - xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 200, + xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 300, NULL, tskIDLE_PRIORITY + 1, &host_task_h); } diff --git a/src/sdk_config.h b/src/sdk_config.h index aa1bbb3a..58bd634b 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -8460,15 +8460,15 @@ // NRF_LOG_ENABLED - nrf_log - Logger //========================================================== #ifndef NRF_LOG_ENABLED -#define NRF_LOG_ENABLED 0 +#define NRF_LOG_ENABLED 1 #endif #ifndef NRF_LOG_BACKEND_RTT_ENABLED -#define NRF_LOG_BACKEND_RTT_ENABLED 0 +#define NRF_LOG_BACKEND_RTT_ENABLED 1 #endif #ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT -#define NRF_LOG_BACKEND_SERIAL_USES_RTT 0 +#define NRF_LOG_BACKEND_SERIAL_USES_RTT 1 #endif // Log message pool - Configuration of log message pool