/*************************************************************************** * * Copyright 2015-2019 BES. * All rights reserved. All unpublished rights reserved. * * No part of this work may be used or reproduced in any form or by any * means, or stored in a database or retrieval system, without prior written * permission of BES. * * Use of this work is governed by a license granted by BES. * This work contains confidential and proprietary information of * BES. which is protected by copyright, trade secret, * trademark and other intellectual property rights. * ****************************************************************************/ /** **************************************************************************************** * @addtogroup APP * @{ **************************************************************************************** */ #include "rwip_config.h" // SW configuration #include #include #if (BLE_APP_HID) /* * INCLUDE FILES **************************************************************************************** */ #include "app.h" // Application Definitions #include "app_hid.h" // HID Application Module Definitions #include "app_sec.h" // Application Security Module API #include "app_task.h" // Application task definitions #include "arch.h" // Platform Definitions #include "hogpd_task.h" // HID Over GATT Profile Device Role Functions #include "ke_timer.h" // kernel timer #include "prf.h" #include "prf_types.h" // Profile common types Definition #if (NVDS_SUPPORT) #include "nvds.h" // NVDS Definitions #endif //(NVDS_SUPPORT) #if (DISPLAY_SUPPORT) #include "app_display.h" // Application Display Module #endif //(DISPLAY_SUPPORT) #include "co_utils.h" // Common functions #if (KE_PROFILING) #include "ke_mem.h" #endif //(KE_PROFILING) /* * DEFINES **************************************************************************************** */ /// Length of the HID Mouse Report #define APP_HID_MOUSE_REPORT_LEN (6) /// Length of the Report Descriptor for an HID Mouse #define APP_HID_MOUSE_REPORT_MAP_LEN (sizeof(app_hid_mouse_report_map)) /// Duration before connection update procedure if no report received (mouse is /// silent) - 20s #define APP_HID_SILENCE_DURATION_1 (2000) /// Duration before disconnection if no report is received after connection /// update - 60s #define APP_HID_SILENCE_DURATION_2 (6000) /// Number of reports that can be sent #define APP_HID_NB_SEND_REPORT (10) /* * ENUMERATIONS **************************************************************************************** */ /// States of the Application HID Module enum app_hid_states { /// Module is disabled (Service not added in DB) APP_HID_DISABLED, /// Module is idle (Service added but profile not enabled) APP_HID_IDLE, /// Module is enabled (Device is connected and the profile is enabled) APP_HID_ENABLED, /// The application can send reports APP_HID_READY, /// Waiting for a report APP_HID_WAIT_REP, APP_HID_STATE_MAX, }; /* * LOCAL VARIABLE DEFINITIONS **************************************************************************************** */ /// HID Application Module Environment Structure static struct app_hid_env_tag app_hid_env; /// HID Mouse Report Descriptor static const uint8_t app_hid_mouse_report_map[] = { /** * -------------------------------------------------------------------------- * Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * -------------------------------------------------------------------------- * Byte 0 | Not Used | Middle| Right | Left * | * -------------------------------------------------------------------------- * Byte 1 | X Axis Relative Movement | * -------------------------------------------------------------------------- * Byte 2 | Y Axis Relative Movement | * -------------------------------------------------------------------------- * Byte 3 | Wheel Relative Movement | * -------------------------------------------------------------------------- */ 0x05, 0x01, /// USAGE PAGE (Generic Desktop) 0x09, 0x02, /// USAGE (Mouse) 0xA1, 0x01, /// COLLECTION (Application) 0x85, 0x01, /// REPORT ID (1) - MANDATORY 0x09, 0x01, /// USAGE (Pointer) 0xA1, 0x00, /// COLLECTION (Physical) /** * ---------------------------------------------------------------------------- * BUTTONS * ---------------------------------------------------------------------------- */ 0x05, 0x09, /// USAGE PAGE (Buttons) 0x19, 0x01, /// USAGE MINIMUM (1) 0x29, 0x08, /// USAGE MAXIMUM (8) 0x15, 0x00, /// LOGICAL MINIMUM (0) 0x25, 0x01, /// LOGICAL MAXIMUM (1) 0x75, 0x01, /// REPORT SIZE (1) 0x95, 0x08, /// REPORT COUNT (8) 0x81, 0x02, /// INPUT (Data, Variable, Absolute) /** * ---------------------------------------------------------------------------- * MOVEMENT DATA * ---------------------------------------------------------------------------- */ 0x05, 0x01, /// USAGE PAGE (Generic Desktop) 0x16, 0x08, 0xFF, /// LOGICAL MINIMUM (-255) 0x26, 0xFF, 0x00, /// LOGICAL MAXIMUM (255) 0x75, 0x10, /// REPORT SIZE (16) 0x95, 0x02, /// REPORT COUNT (2) 0x09, 0x30, /// USAGE (X) 0x09, 0x31, /// USAGE (Y) 0x81, 0x06, /// INPUT (Data, Variable, Relative) 0x15, 0x81, /// LOGICAL MINIMUM (-127) 0x25, 0x7F, /// LOGICAL MAXIMUM (127) 0x75, 0x08, /// REPORT SIZE (8) 0x95, 0x01, /// REPORT COUNT (1) 0x09, 0x38, /// USAGE (Wheel) 0x81, 0x06, /// INPUT (Data, Variable, Relative) 0xC0, /// END COLLECTION (Physical) 0xC0 /// END COLLECTION (Application) }; /* * GLOBAL FUNCTION DEFINITIONS **************************************************************************************** */ void app_hid_init(void) { #if (NVDS_SUPPORT) // Length of the mouse timeout value uint8_t length = NVDS_LEN_MOUSE_TIMEOUT; #endif // Reset the environment memset(&app_hid_env, 0, sizeof(app_hid_env)); app_hid_env.nb_report = APP_HID_NB_SEND_REPORT; /* * Get the timeout value from the NVDS - This value is used each time a report * is received from the PS2 driver, store it in the environment. */ #if (NVDS_SUPPORT) if (nvds_get(NVDS_TAG_MOUSE_TIMEOUT, &length, (uint8_t *)&app_hid_env.timeout) != NVDS_OK) #endif { app_hid_env.timeout = APP_HID_SILENCE_DURATION_1; } } /* **************************************************************************************** * @brief Function called when get GAP manager command complete events. * **************************************************************************************** */ void app_hid_start_mouse(void) { /*----------------------------------------------------------------------------------- * CONFIGURE THE MOUSE *----------------------------------------------------------------------------------*/ #if (PS2_SUPPORT) // Default mouse rate (200 report/s) uint8_t rate = 200; #if (NVDS_SUPPORT) uint8_t length = NVDS_LEN_MOUSE_SAMPLE_RATE; // Get sample rate from NVDS if (nvds_get(NVDS_TAG_MOUSE_SAMPLE_RATE, &length, &rate) == NVDS_OK) { // Check if value is among supported set if ((rate != 10) && (rate != 20) && (rate != 40) && (rate != 60) && (rate != 80) && (rate != 100) && (rate != 200)) { // Default value rate = 200; } } #endif //(NVDS_SUPPORT) // Start PS2_mouse ps2_mouse_start(rate, &app_hid_send_mouse_report); #endif //(PS2_SUPPORT) } void app_hid_add_hids(void) { struct hogpd_db_cfg *db_cfg; // Prepare the HOGPD_CREATE_DB_REQ message struct gapm_profile_task_add_cmd *req = KE_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD, TASK_GAPM, TASK_APP, gapm_profile_task_add_cmd, sizeof(struct hogpd_db_cfg)); // Fill message req->operation = GAPM_PROFILE_TASK_ADD; #if BLE_CONNECTION_MAX > 1 req->sec_lvl = PERM(SVC_AUTH, ENABLE) | PERM(SVC_MI, ENABLE); #else req->sec_lvl = PERM(SVC_AUTH, ENABLE); #endif req->prf_task_id = TASK_ID_HOGPD; req->app_task = TASK_APP; req->start_hdl = 0; // Set parameters db_cfg = (struct hogpd_db_cfg *)req->param; // Only one HIDS instance is useful db_cfg->hids_nb = 1; // The device is a mouse db_cfg->cfg[0].svc_features = HOGPD_CFG_MOUSE; // Only one Report Characteristic is requested db_cfg->cfg[0].report_nb = 1; /// db_cfg->cfg[0].report_id = 1; db_cfg->cfg[0].report_id[0] = 1; // The report is an input report db_cfg->cfg[0].report_char_cfg[0] = HOGPD_CFG_REPORT_IN; // HID Information db_cfg->cfg[0].hid_info.bcdHID = 0x0111; // HID Version 1.11 db_cfg->cfg[0].hid_info.bCountryCode = 0x00; db_cfg->cfg[0].hid_info.flags = HIDS_REMOTE_WAKE_CAPABLE | HIDS_NORM_CONNECTABLE; // Send the message ke_msg_send(req); } /* **************************************************************************************** * @brief Function called when get connection complete event from the GAP * **************************************************************************************** */ void app_hid_enable_prf(uint8_t conidx) { // Requested connection parameters struct gapc_conn_param conn_param; uint16_t ntf_cfg; // Store the connection handle app_hid_env.conidx = conidx; // Allocate the message struct hogpd_enable_req *req = KE_MSG_ALLOC(HOGPD_ENABLE_REQ, KE_BUILD_ID(prf_get_task_from_id(TASK_ID_HOGPD), conidx), TASK_APP, hogpd_enable_req); // Fill in the parameter structure req->conidx = conidx; // Notifications are disabled ntf_cfg = 0; // Go to Enabled state app_hid_env.state = APP_HID_ENABLED; #if (NVDS_SUPPORT) // If first connection with the peer device if (app_sec_get_bond_status()) { // Length of the value read in NVDS uint8_t length = NVDS_LEN_MOUSE_NTF_CFG; // Notification configuration if (nvds_get(NVDS_TAG_MOUSE_NTF_CFG, &length, (uint8_t *)&ntf_cfg) != NVDS_OK) { // If we are bonded this information should be present in the NVDS ASSERT_ERR(0); } // CCC enable notification if ((ntf_cfg & HOGPD_CFG_REPORT_NTF_EN) != 0) { // The device is ready to send reports to the peer device app_hid_env.state = APP_HID_READY; app_hid_env.nb_report = APP_HID_NB_SEND_REPORT; // Restart the mouse timeout timer if needed if (app_hid_env.timeout != 0) { ke_timer_set(APP_HID_MOUSE_TIMEOUT_TIMER, TASK_APP, (uint16_t)(app_hid_env.timeout)); app_hid_env.timer_enabled = true; } } } #endif //(NVDS_SUPPORT) req->ntf_cfg[conidx] = ntf_cfg; /* * Requested connection interval: 10ms * Latency: 25 * Supervision Timeout: 2s */ conn_param.intv_min = 8; conn_param.intv_max = 8; conn_param.latency = 25; conn_param.time_out = 200; appm_update_param(conidx, &conn_param); // Send the message ke_msg_send(req); } /* **************************************************************************************** * @brief Function called from PS2 driver * **************************************************************************************** */ void app_hid_send_mouse_report(struct ps2_mouse_msg report) { // app_display_update_hid_value_screen(report.b, report.x, report.y, // report.w); switch (app_hid_env.state) { case (APP_HID_READY): { // Check if the report can be sent if (app_hid_env.nb_report) { // Buffer used to create the Report uint8_t report_buff[APP_HID_MOUSE_REPORT_LEN]; // X, Y and wheel relative movements int16_t x; int16_t y; #if (DISPLAY_SUPPORT) // Display all the received information on the LCD screen // app_display_update_hid_value_screen(report.b, report.x, report.y, report.w); #endif //(DISPLAY_SUPPORT) // Clean the report buffer memset(&report_buff[0], 0, APP_HID_MOUSE_REPORT_LEN); // Set the button states report_buff[0] = (report.b & 0x07); // If X value is negative if (report.b & 0x10) { report.x = ~report.x; report.x += 1; x = (int16_t)report.x; x *= (-1); } else { x = (int16_t)report.x; } // If Y value is negative if (report.b & 0x20) { report.y = ~report.y; report.y += 1; y = (int16_t)report.y; } else { y = (int16_t)report.y; y *= (-1); } // Set the X and Y movement value in the report co_write16p(&report_buff[1], x); co_write16p(&report_buff[3], y); report_buff[5] = (signed char)(-1) * report.w; // Allocate the HOGPD_REPORT_UPD_REQ message struct hogpd_report_upd_req *req = KE_MSG_ALLOC_DYN( HOGPD_REPORT_UPD_REQ, prf_get_task_from_id(TASK_ID_HOGPD), TASK_APP, hogpd_report_upd_req, APP_HID_MOUSE_REPORT_LEN); req->conidx = app_hid_env.conidx; // now fill report req->report.hid_idx = app_hid_env.conidx; req->report.type = HOGPD_REPORT; // HOGPD_BOOT_MOUSE_INPUT_REPORT;// req->report.idx = 0; // 0 for boot reports and report map req->report.length = APP_HID_MOUSE_REPORT_LEN; memcpy(&req->report.value[0], &report_buff[0], APP_HID_MOUSE_REPORT_LEN); ke_msg_send(req); app_hid_env.nb_report--; // Restart the mouse timeout timer if needed if (app_hid_env.timeout != 0) { ke_timer_set(APP_HID_MOUSE_TIMEOUT_TIMER, TASK_APP, (uint16_t)(app_hid_env.timeout)); app_hid_env.timer_enabled = true; } } } break; case (APP_HID_WAIT_REP): { // Requested connection parameters struct gapc_conn_param conn_param; /* * Requested connection interval: 10ms * Latency: 25 * Supervision Timeout: 2s */ conn_param.intv_min = 8; conn_param.intv_max = 8; conn_param.latency = 25; conn_param.time_out = 200; appm_update_param(app_hid_env.conidx, &conn_param); // Restart the mouse timeout timer if needed if (app_hid_env.timeout != 0) { ke_timer_set(APP_HID_MOUSE_TIMEOUT_TIMER, TASK_APP, (uint16_t)(app_hid_env.timeout)); app_hid_env.timer_enabled = true; } // Go back to the ready state app_hid_env.state = APP_HID_READY; } break; case (APP_HID_IDLE): { // Try to restart advertising if needed } break; // DISABLE and ENABLED states default: { // Drop the message } break; } #if (KE_PROFILING) // app_display_hdl_env_size(0xFFFF, ke_get_mem_usage(KE_MEM_ENV)); // app_display_hdl_db_size(0xFFFF, ke_get_mem_usage(KE_MEM_ATT_DB)); // app_display_hdl_msg_size((uint16_t)ke_get_max_mem_usage(), // ke_get_mem_usage(KE_MEM_KE_MSG)); #endif //(KE_PROFILING) } /* * MESSAGE HANDLERS **************************************************************************************** */ static int hogpd_ctnl_pt_ind_handler(ke_msg_id_t const msgid, struct hogpd_ctnl_pt_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if (param->conidx == app_hid_env.conidx) { // make use of param->hid_ctnl_pt struct hogpd_report_cfm *req = KE_MSG_ALLOC_DYN( HOGPD_REPORT_CFM, prf_get_task_from_id(TASK_ID_HOGPD), /* src_id */ TASK_APP, hogpd_report_cfm, 0); req->conidx = param->conidx; /// app_hid_env.conidx; ///??? /// Operation requested (read/write @see enum hogpd_op) req->operation = HOGPD_OP_REPORT_WRITE; /// Status of the request req->status = GAP_ERR_NO_ERROR; ///??? /// Report Info // req->report; /// HIDS Instance req->report.hid_idx = app_hid_env.conidx; ///??? /// type of report (@see enum hogpd_report_type) req->report.type = -1; // outside /// Report Length (uint8_t) req->report.length = 0; /// Report Instance - 0 for boot reports and report map req->report.idx = 0; /// Report data // Send the message ke_msg_send(req); } return (KE_MSG_CONSUMED); } static int hogpd_ntf_cfg_ind_handler(ke_msg_id_t const msgid, struct hogpd_ntf_cfg_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if (app_hid_env.conidx == param->conidx) { if ((param->ntf_cfg[param->conidx] & HOGPD_CFG_REPORT_NTF_EN) != 0) { // The device is ready to send reports to the peer device app_hid_env.state = APP_HID_READY; } else { // Come back to the Enabled state if (app_hid_env.state == APP_HID_READY) { app_hid_env.state = APP_HID_ENABLED; } } #if (NVDS_SUPPORT) // Store the notification configuration in the database if (nvds_put(NVDS_TAG_MOUSE_NTF_CFG, NVDS_LEN_MOUSE_NTF_CFG, (uint8_t *)¶m->ntf_cfg[param->conidx]) != NVDS_OK) { // Should not happen ASSERT_ERR(0); } #endif } return (KE_MSG_CONSUMED); } static int hogpd_report_req_ind_handler( ke_msg_id_t const msgid, struct hogpd_report_req_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if ((param->operation == HOGPD_OP_REPORT_READ) && (param->report.type == HOGPD_REPORT_MAP)) { struct hogpd_report_cfm *req = KE_MSG_ALLOC_DYN( HOGPD_REPORT_CFM, src_id, /// prf_get_task_from_id(TASK_ID_HOGPD),/* src_id */ dest_id, /// TASK_APP, hogpd_report_cfm, APP_HID_MOUSE_REPORT_MAP_LEN); req->conidx = app_hid_env.conidx; ///??? /// Operation requested (read/write @see enum hogpd_op) req->operation = HOGPD_OP_REPORT_READ; /// Status of the request req->status = GAP_ERR_NO_ERROR; ///??? /// Report Info // req->report; /// HIDS Instance req->report.hid_idx = param->report.hid_idx; /// ???///app_hid_env.conidx; ///??? /// type of report (@see enum hogpd_report_type) req->report.type = HOGPD_REPORT_MAP; /// Report Length (uint8_t) req->report.length = APP_HID_MOUSE_REPORT_MAP_LEN; /// Report Instance - 0 for boot reports and report map req->report.idx = 0; /// Report data memcpy(&req->report.value[0], &app_hid_mouse_report_map[0], APP_HID_MOUSE_REPORT_MAP_LEN); // Send the message ke_msg_send(req); } else { if (param->report.type == HOGPD_BOOT_MOUSE_INPUT_REPORT) { // request of boot mouse report struct hogpd_report_cfm *req = KE_MSG_ALLOC_DYN( HOGPD_REPORT_CFM, prf_get_task_from_id(TASK_ID_HOGPD), /* src_id */ TASK_APP, hogpd_report_cfm, 0 /*param->report.length*/); req->conidx = param->conidx; /// app_hid_env.conidx; ///??? /// Operation requested (read/write @see enum hogpd_op) req->operation = HOGPD_OP_REPORT_READ; /// Status of the request req->status = GAP_ERR_NO_ERROR; ///??? /// HIDS Instance req->report.hid_idx = app_hid_env.conidx; ///??? /// type of report (@see enum hogpd_report_type) req->report.type = param->report.type; //-1;//outside /// Report Length (uint8_t) req->report.length = 0; // param->report.length; /// Report Instance - 0 for boot reports and report map req->report.idx = param->report.idx; // 0; /// Report data // Send the message ke_msg_send(req); } else if (param->report.type == HOGPD_REPORT) { // request of mouse report struct hogpd_report_cfm *req = KE_MSG_ALLOC_DYN( HOGPD_REPORT_CFM, prf_get_task_from_id(TASK_ID_HOGPD), /* src_id */ TASK_APP, hogpd_report_cfm, 8 /*param->report.length*/); req->conidx = param->conidx; /// app_hid_env.conidx; ///??? /// Operation requested (read/write @see enum hogpd_op) req->operation = HOGPD_OP_REPORT_READ; /// Status of the request req->status = GAP_ERR_NO_ERROR; ///??? /// Report Info // req->report; /// HIDS Instance req->report.hid_idx = app_hid_env.conidx; ///??? /// type of report (@see enum hogpd_report_type) req->report.type = param->report.type; //-1;//outside /// Report Length (uint8_t) req->report.length = 8; // param->report.length; /// Report Instance - 0 for boot reports and report map req->report.idx = param->report.idx; // 0; /// Report data memset(&req->report.value[0], 0, 8); //??? req->report.value[0] = param->report.hid_idx; /// HIDS Instance req->report.value[1] = param->report.type; /// type of report (@see enum hogpd_report_type) req->report.value[2] = param->report.length; /// Report Length (uint8_t) req->report.value[3] = param->report .idx; /// Report Instance - 0 for boot reports and report map // Send the message ke_msg_send(req); } else { struct hogpd_report_cfm *req = KE_MSG_ALLOC_DYN( HOGPD_REPORT_CFM, prf_get_task_from_id(TASK_ID_HOGPD), /* src_id */ TASK_APP, hogpd_report_cfm, 8 /*param->report.length*/); req->conidx = param->conidx; /// app_hid_env.conidx; ///??? /// Operation requested (read/write @see enum hogpd_op) req->operation = HOGPD_OP_REPORT_READ; /// Status of the request req->status = GAP_ERR_NO_ERROR; ///??? /// Report Info // req->report; /// HIDS Instance req->report.hid_idx = app_hid_env.conidx; ///??? /// type of report (@see enum hogpd_report_type) req->report.type = param->report.type; //-1;//outside /// Report Length (uint8_t) req->report.length = 8; // param->report.length; /// Report Instance - 0 for boot reports and report map req->report.idx = param->report.idx; // 0; /// Report data memset(&req->report.value[0], 0, 8); //??? req->report.value[0] = param->report.hid_idx; /// HIDS Instance req->report.value[1] = param->report.type; /// type of report (@see enum hogpd_report_type) req->report.value[2] = param->report.length; /// Report Length (uint8_t) req->report.value[3] = param->report .idx; /// Report Instance - 0 for boot reports and report map // Send the message ke_msg_send(req); } } return (KE_MSG_CONSUMED); } static int hogpd_proto_mode_req_ind_handler( ke_msg_id_t const msgid, struct hogpd_proto_mode_req_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if ((param->conidx == app_hid_env.conidx) && (param->operation == HOGPD_OP_PROT_UPDATE)) { // make use of param->proto_mode struct hogpd_proto_mode_cfm *req = KE_MSG_ALLOC_DYN( HOGPD_PROTO_MODE_CFM, prf_get_task_from_id(TASK_ID_HOGPD), /* src_id */ TASK_APP, hogpd_proto_mode_cfm, 0); /// Connection Index req->conidx = app_hid_env.conidx; /// Status of the request req->status = GAP_ERR_NO_ERROR; /// HIDS Instance req->hid_idx = app_hid_env.conidx; /// New Protocol Mode Characteristic Value req->proto_mode = param->proto_mode; // Send the message ke_msg_send(req); } else { struct hogpd_proto_mode_cfm *req = KE_MSG_ALLOC_DYN( HOGPD_PROTO_MODE_CFM, prf_get_task_from_id(TASK_ID_HOGPD), /* src_id */ TASK_APP, hogpd_proto_mode_cfm, 0); /// Status of the request req->status = ATT_ERR_APP_ERROR; /// Connection Index req->conidx = app_hid_env.conidx; /// HIDS Instance req->hid_idx = app_hid_env.conidx; /// New Protocol Mode Characteristic Value req->proto_mode = param->proto_mode; // Send the message ke_msg_send(req); } return (KE_MSG_CONSUMED); } static int hogpd_report_upd_handler(ke_msg_id_t const msgid, struct hogpd_report_upd_rsp const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if (app_hid_env.conidx == param->conidx) { if (GAP_ERR_NO_ERROR == param->status) { if (app_hid_env.nb_report < APP_HID_NB_SEND_REPORT) { app_hid_env.nb_report++; } } else { // we get this message if error occur while sending report // most likely - disconnect // Go back to the ready state app_hid_env.state = APP_HID_IDLE; // change mode // restart adv // Try to restart advertising if needed // report was not success - need to restart??? } } return (KE_MSG_CONSUMED); } static int hogpd_enable_rsp_handler(ke_msg_id_t const msgid, struct hogpd_enable_rsp const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { return (KE_MSG_CONSUMED); } /** **************************************************************************************** * @brief Function called when the APP_HID_MOUSE_TIMEOUT_TIMER expires. * * @param[in] msgid Id of the message received. * @param[in] param Pointer to the parameters of the message. * @param[in] dest_id ID of the receiving task instance (TASK_GAP). * @param[in] src_id ID of the sending task instance. * * @return If the message was consumed or not. **************************************************************************************** */ static int app_hid_mouse_timeout_timer_handler(ke_msg_id_t const msgid, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { app_hid_env.timer_enabled = false; if (app_hid_env.state == APP_HID_READY) { // Requested connection parameters struct gapc_conn_param conn_param; // Length #if (NVDS_SUPPORT) uint8_t length = NVDS_LEN_MOUSE_TIMEOUT; #endif // Timer value uint16_t timer_val; /* * Request an update of the connection parameters * Requested connection interval: 10ms * Latency: 200 * Supervision Timeout: 5s */ conn_param.intv_min = 8; conn_param.intv_max = 8; conn_param.latency = 200; conn_param.time_out = 500; appm_update_param(app_hid_env.conidx, &conn_param); // Go to the Wait for Report state app_hid_env.state = APP_HID_WAIT_REP; #if (NVDS_SUPPORT) // Get the timer value from the NVDS if (nvds_get(NVDS_TAG_MOUSE_ENERGY_SAFE, &length, (uint8_t *)&timer_val) != NVDS_OK) #endif { timer_val = APP_HID_SILENCE_DURATION_2; } // Relaunch the timer ke_timer_set(APP_HID_MOUSE_TIMEOUT_TIMER, TASK_APP, timer_val); app_hid_env.timer_enabled = true; } else if (app_hid_env.state == APP_HID_WAIT_REP) { // Disconnect the link with the device appm_disconnect(app_hid_env.conidx); // Go back to the ready state app_hid_env.state = APP_HID_IDLE; } return (KE_MSG_CONSUMED); } /** **************************************************************************************** * @brief * * @param[in] msgid Id of the message received. * @param[in] param Pointer to the parameters of the message. * @param[in] dest_id ID of the receiving task instance (TASK_GAP). * @param[in] src_id ID of the sending task instance. * * @return If the message was consumed or not. **************************************************************************************** */ static int app_hid_msg_dflt_handler(ke_msg_id_t const msgid, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Drop the message return (KE_MSG_CONSUMED); } /** **************************************************************************************** * @brief Set the value of the Report Map Characteristic in the database **************************************************************************************** */ void app_hid_set_report_map(void); /* * LOCAL VARIABLE DEFINITIONS **************************************************************************************** */ /// Default State handlers definition const struct ke_msg_handler app_hid_msg_handler_list[] = { // Note: first message is latest message checked by kernel so default is put // on top. {KE_MSG_DEFAULT_HANDLER, (ke_msg_func_t)app_hid_msg_dflt_handler}, {HOGPD_ENABLE_RSP, (ke_msg_func_t)hogpd_enable_rsp_handler}, /// notification configuration changed {HOGPD_NTF_CFG_IND, (ke_msg_func_t)hogpd_ntf_cfg_ind_handler}, {HOGPD_REPORT_REQ_IND, (ke_msg_func_t)hogpd_report_req_ind_handler}, {HOGPD_PROTO_MODE_REQ_IND, (ke_msg_func_t)hogpd_proto_mode_req_ind_handler}, {HOGPD_CTNL_PT_IND, (ke_msg_func_t)hogpd_ctnl_pt_ind_handler}, {HOGPD_REPORT_UPD_RSP, (ke_msg_func_t)hogpd_report_upd_handler}, {APP_HID_MOUSE_TIMEOUT_TIMER, (ke_msg_func_t)app_hid_mouse_timeout_timer_handler}, }; const struct ke_state_handler app_hid_table_handler = { &app_hid_msg_handler_list[0], (sizeof(app_hid_msg_handler_list) / sizeof(struct ke_msg_handler))}; #endif //(BLE_APP_HID) /// @} APP