Loading system/bta/hh/bta_hh_act.cc +0 −8 Original line number Diff line number Diff line Loading @@ -659,9 +659,6 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { bta_hh.hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data); if (bta_hh.hs_data.status == BTA_HH_OK) bta_hh.hs_data.status = BTA_HH_HS_TRANS_NOT_SPT; if (p_cb->w4_evt == BTA_HH_GET_RPT_EVT) bta_hh_co_get_rpt_rsp(bta_hh.dev_status.handle, bta_hh.hs_data.status, NULL, 0); (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh); p_cb->w4_evt = 0; break; Loading @@ -673,9 +670,6 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { bta_hh.dev_status.handle = p_cb->hid_handle; bta_hh.dev_status.status = bta_hh_get_trans_status(p_data->hid_cback.data); if (p_cb->w4_evt == BTA_HH_SET_RPT_EVT) bta_hh_co_set_rpt_rsp(bta_hh.dev_status.handle, bta_hh.dev_status.status); (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh); p_cb->w4_evt = 0; break; Loading Loading @@ -732,8 +726,6 @@ void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { break; case BTA_HH_GET_RPT_EVT: hs_data.rsp_data.p_rpt_data = pdata; bta_hh_co_get_rpt_rsp(hs_data.handle, hs_data.status, pdata->data, pdata->len); break; case BTA_HH_GET_PROTO_EVT: /* match up BTE/BTA report/boot mode def*/ Loading system/bta/hh/bta_hh_le.cc +25 −29 Original line number Diff line number Diff line Loading @@ -1726,56 +1726,53 @@ void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB* p_cb) { static void read_report_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* data) { tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT) { LOG_WARN("Unexpected Read response, w4_evt = %d", p_dev_cb->w4_evt); return; } const gatt::Characteristic* p_char = BTA_GATTC_GetCharacteristic(conn_id, handle); if (p_char == NULL) return; uint16_t char_uuid = p_char->uuid.As16Bit(); if (char_uuid != GATT_UUID_HID_REPORT && char_uuid != GATT_UUID_HID_BT_KB_INPUT && char_uuid != GATT_UUID_HID_BT_KB_OUTPUT && char_uuid != GATT_UUID_HID_BT_MOUSE_INPUT && char_uuid != GATT_UUID_BATTERY_LEVEL) { APPL_TRACE_ERROR("%s: Unexpected Read UUID: 0x%04x", __func__, char_uuid); if (p_char == nullptr) { LOG_ERROR("Unknown handle"); return; } tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT) { APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt); uint16_t char_uuid = p_char->uuid.As16Bit(); switch (char_uuid) { case GATT_UUID_HID_REPORT: case GATT_UUID_HID_BT_KB_INPUT: case GATT_UUID_HID_BT_KB_OUTPUT: case GATT_UUID_HID_BT_MOUSE_INPUT: case GATT_UUID_BATTERY_LEVEL: break; default: LOG_ERROR("Unexpected Read UUID: 0x%04x", char_uuid); return; } /* GET_REPORT */ BT_HDR* p_buf = NULL; tBTA_HH_LE_RPT* p_rpt; tBTA_HH_HSDATA hs_data; uint8_t* pp; memset(&hs_data, 0, sizeof(hs_data)); tBTA_HH_HSDATA hs_data = {}; hs_data.status = BTA_HH_ERR; hs_data.handle = p_dev_cb->hid_handle; if (status == GATT_SUCCESS) { tBTA_HH_LE_RPT* p_rpt; const gatt::Service* p_svc = BTA_GATTC_GetOwningService(conn_id, p_char->value_handle); p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, char_uuid, p_char->value_handle); if (p_rpt != NULL && len) { p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1); if (p_rpt != nullptr && len) { BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1); /* pack data send to app */ hs_data.status = BTA_HH_OK; p_buf->len = len + 1; p_buf->layer_specific = 0; p_buf->offset = 0; uint8_t* pp = (uint8_t*)(p_buf + 1); /* attach report ID as the first byte of the report before sending it to * USB HID driver */ pp = (uint8_t*)(p_buf + 1); UINT8_TO_STREAM(pp, p_rpt->rpt_id); memcpy(pp, value, len); Loading @@ -1785,8 +1782,7 @@ static void read_report_cb(uint16_t conn_id, tGATT_STATUS status, p_dev_cb->w4_evt = 0; (*bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH*)&hs_data); osi_free_and_reset((void**)&p_buf); osi_free(hs_data.rsp_data.p_rpt_data); } /******************************************************************************* Loading system/bta/include/bta_hh_co.h +1 −1 Original line number Diff line number Diff line Loading @@ -103,7 +103,7 @@ extern void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status); * ******************************************************************************/ extern void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, uint8_t* p_rpt, uint16_t len); const uint8_t* p_rpt, uint16_t len); /******************************************************************************* * Loading system/bta/test/bta_hh_test.cc +1 −2 Original line number Diff line number Diff line Loading @@ -104,6 +104,5 @@ TEST_F(BtaHhTest, bta_hh_ctrl_dat_act__BTA_HH_GET_RPT_EVT) { }; bta_hh_ctrl_dat_act(&cb, &data); ASSERT_EQ(get_func_call_count("bta_hh_co_get_rpt_rsp"), 1); ASSERT_EQ(cb.w4_evt, 0); } system/btif/co/bta_hh_co.cc +136 −100 Original line number Diff line number Diff line Loading @@ -45,11 +45,13 @@ const char* dev_path = "/dev/uhid"; #include "btif_config.h" #define BTA_HH_NV_LOAD_MAX 16 static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; #define GET_RPT_RSP_OFFSET 9 #define BTA_HH_CACHE_REPORT_VERSION 1 #define THREAD_NORMAL_PRIORITY 0 #define BT_HH_THREAD "bt_hh_thread" static const bthh_report_type_t map_rtype_uhid_hh[] = { BTHH_FEATURE_REPORT, BTHH_OUTPUT_REPORT, BTHH_INPUT_REPORT}; void uhid_set_non_blocking(int fd) { int opts = fcntl(fd, F_GETFL); if (opts < 0) Loading @@ -63,6 +65,62 @@ void uhid_set_non_blocking(int fd) { strerror(errno)); } static bool uhid_feature_req_handler(btif_hh_device_t* p_dev, struct uhid_feature_req& req) { LOG_DEBUG("Report type = %d, id = %d", req.rtype, req.rnum); if (req.rtype > UHID_INPUT_REPORT) { LOG_ERROR("Invalid report type %d", req.rtype); return false; } if (p_dev->get_rpt_id_queue == nullptr) { LOG_ERROR("Queue is not initialized"); return false; } uint32_t* context = (uint32_t*)osi_malloc(sizeof(uint32_t)); *context = req.id; if (!fixed_queue_try_enqueue(p_dev->get_rpt_id_queue, (void*)context)) { osi_free(context); LOG_ERROR("Queue is full, dropping event %d", req.id); return false; } btif_hh_getreport(p_dev, map_rtype_uhid_hh[req.rtype], req.rnum, 0); return true; } #if ENABLE_UHID_SET_REPORT static bool uhid_set_report_req_handler(btif_hh_device_t* p_dev, struct uhid_set_report_req& req) { LOG_DEBUG("Report type = %d, id = %d", req.rtype, req.rnum); if (req.rtype > UHID_INPUT_REPORT) { LOG_ERROR("Invalid report type %d", req.rtype); return false; } if (p_dev->set_rpt_id_queue == nullptr) { LOG_ERROR("Queue is not initialized"); return false; } uint32_t* context = (uint32_t*)osi_malloc(sizeof(uint32_t)); *context = req.id; if (!fixed_queue_try_enqueue(p_dev->set_rpt_id_queue, (void*)context)) { osi_free(context); LOG_ERROR("Queue is full, dropping event %d", req.id); return false; } btif_hh_setreport(p_dev, map_rtype_uhid_hh[req.rtype], req.size, req.data); return true; } #endif // ENABLE_UHID_SET_REPORT /*Internal function to perform UHID write and error checking*/ static int uhid_write(int fd, const struct uhid_event* ev) { ssize_t ret; Loading Loading @@ -146,74 +204,37 @@ static int uhid_read_event(btif_hh_device_t* p_dev) { } APPL_TRACE_DEBUG("UHID_OUTPUT_EV from uhid-dev\n"); break; case UHID_FEATURE: case UHID_FEATURE: // UHID_GET_REPORT if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.feature))) { APPL_TRACE_ERROR( "%s: UHID_FEATURE: Invalid size read from uhid-dev: %zd < %zu", __func__, ret, sizeof(ev.type) + sizeof(ev.u.feature)); LOG_ERROR("UHID_GET_REPORT: Invalid size read from uhid-dev: %zd < %zu", ret, sizeof(ev.type) + sizeof(ev.u.feature)); return -EFAULT; } APPL_TRACE_DEBUG("UHID_FEATURE: Report type = %d", ev.u.feature.rtype); p_dev->get_rpt_snt++; if (p_dev->get_rpt_id_queue) { uint32_t* get_rpt_id = (uint32_t*)osi_malloc(sizeof(uint32_t)); *get_rpt_id = ev.u.feature.id; auto ok = fixed_queue_try_enqueue(p_dev->get_rpt_id_queue, (void*)get_rpt_id); if (!ok) { LOG_ERROR("get_rpt_id_queue is full, dropping event %d", *get_rpt_id); osi_free(get_rpt_id); if (!uhid_feature_req_handler(p_dev, ev.u.feature)) { return -EFAULT; } } if (ev.u.feature.rtype == UHID_FEATURE_REPORT) btif_hh_getreport(p_dev, BTHH_FEATURE_REPORT, ev.u.feature.rnum, 0); else APPL_TRACE_ERROR("%s: UHID_FEATURE: Invalid report type = %d", __func__, ev.u.feature.rtype); break; #if ENABLE_UHID_SET_REPORT case UHID_SET_REPORT: { bool sent = true; if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.set_report))) { LOG_ERROR("Invalid size read from uhid-dev: %zd < %zu", ret, sizeof(ev.type) + sizeof(ev.u.set_report)); LOG_ERROR("UHID_SET_REPORT: Invalid size read from uhid-dev: %zd < %zu", ret, sizeof(ev.type) + sizeof(ev.u.set_report)); return -EFAULT; } LOG_DEBUG("UHID_SET_REPORT: Report type = %d, report_size = %d", ev.u.set_report.rtype, ev.u.set_report.size); if (ev.u.set_report.rtype == UHID_FEATURE_REPORT) { btif_hh_setreport(p_dev, BTHH_FEATURE_REPORT, ev.u.set_report.size, ev.u.set_report.data); } else if (ev.u.set_report.rtype == UHID_OUTPUT_REPORT) { btif_hh_setreport(p_dev, BTHH_OUTPUT_REPORT, ev.u.set_report.size, ev.u.set_report.data); } else if (ev.u.set_report.rtype == UHID_INPUT_REPORT) { btif_hh_setreport(p_dev, BTHH_INPUT_REPORT, ev.u.set_report.size, ev.u.set_report.data); } else { LOG_ERROR("UHID_SET_REPORT: Invalid Report type = %d", ev.u.set_report.rtype); sent = false; } if (sent && p_dev->set_rpt_id_queue) { uint32_t* set_rpt_id = (uint32_t*)osi_malloc(sizeof(uint32_t)); *set_rpt_id = ev.u.set_report.id; auto ok = fixed_queue_try_enqueue(p_dev->set_rpt_id_queue, (void*)set_rpt_id); if (!ok) { LOG_ERROR("set_rpt_id_queue is full, dropping event %d", *set_rpt_id); osi_free(set_rpt_id); if (!uhid_set_report_req_handler(p_dev, ev.u.set_report)) { return -EFAULT; } } break; } #endif // ENABLE_UHID_SET_REPORT default: APPL_TRACE_DEBUG("Invalid event from uhid-dev: %u\n", ev.type); LOG_ERROR("Invalid event from uhid-dev: %u\n", ev.type); } return 0; Loading Loading @@ -612,33 +633,42 @@ void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) { btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_handle(dev_handle); if (p_dev == nullptr) { LOG_WARN("Error: unknown HID device handle %d", dev_handle); LOG_WARN("Unknown HID device handle %d", dev_handle); return; } if (!p_dev->set_rpt_id_queue) { LOG_WARN("Error: missing UHID_SET_REPORT id queue"); LOG_WARN("Missing UHID_SET_REPORT id queue"); return; } // Send the HID set report reply to the kernel. if (p_dev->fd >= 0) { uint32_t* set_rpt_id = (uint32_t*)fixed_queue_try_dequeue(p_dev->set_rpt_id_queue); if (set_rpt_id) { struct uhid_event ev = {}; ev.type = UHID_SET_REPORT_REPLY; ev.u.set_report_reply.id = *set_rpt_id; ev.u.set_report_reply.err = status; osi_free(set_rpt_id); uhid_write(p_dev->fd, &ev); } else { LOG_VERBOSE("No pending UHID_SET_REPORT"); if (p_dev->fd < 0) { LOG_ERROR("Unexpected Set Report response"); return; } uint32_t* context = (uint32_t*)fixed_queue_try_dequeue(p_dev->set_rpt_id_queue); if (context == nullptr) { LOG_WARN("No pending UHID_SET_REPORT"); return; } struct uhid_event ev = { .type = UHID_SET_REPORT_REPLY, .u = { .set_report_reply = { .id = *context, .err = status, }, }, }; uhid_write(p_dev->fd, &ev); osi_free(context); #else LOG_ERROR("Error: UHID_SET_REPORT_REPLY not supported"); LOG_ERROR("UHID_SET_REPORT_REPLY not supported"); #endif // ENABLE_UHID_SET_REPORT } Loading @@ -652,49 +682,55 @@ void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) { * Returns void. * ******************************************************************************/ void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, uint8_t* p_rpt, uint16_t len) { struct uhid_event ev; void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, const uint8_t* p_rpt, uint16_t len) { btif_hh_device_t* p_dev; APPL_TRACE_VERBOSE("%s: dev_handle = %d", __func__, dev_handle); LOG_VERBOSE("dev_handle = %d, status = %d", dev_handle, status); p_dev = btif_hh_find_connected_dev_by_handle(dev_handle); if (p_dev == NULL) { APPL_TRACE_WARNING("%s: Error: unknown HID device handle %d", __func__, dev_handle); if (p_dev == nullptr) { LOG_WARN("Unknown HID device handle %d", dev_handle); return; } if (!p_dev->get_rpt_id_queue) { APPL_TRACE_WARNING("%s: Error: missing UHID_GET_REPORT id queue", __func__); LOG_WARN("Missing UHID_GET_REPORT id queue"); return; } // Send the HID report to the kernel. if (p_dev->fd >= 0 && p_dev->get_rpt_snt > 0 && p_dev->get_rpt_snt--) { uint32_t* get_rpt_id = (uint32_t*)fixed_queue_try_dequeue(p_dev->get_rpt_id_queue); if (get_rpt_id == nullptr) { APPL_TRACE_WARNING("%s: Error: UHID_GET_REPORT queue is empty", __func__); if (p_dev->fd < 0) { LOG_WARN("Unexpected Get Report response"); return; } memset(&ev, 0, sizeof(ev)); ev.type = UHID_FEATURE_ANSWER; ev.u.feature_answer.id = *get_rpt_id; ev.u.feature_answer.err = status; ev.u.feature_answer.size = len; osi_free(get_rpt_id); if (len > 0) { if (len > UHID_DATA_MAX) { APPL_TRACE_WARNING("%s: Report size greater than allowed size", __func__); uint32_t* context = (uint32_t*)fixed_queue_try_dequeue(p_dev->get_rpt_id_queue); if (context == nullptr) { LOG_WARN("No pending UHID_GET_REPORT"); return; } memcpy(ev.u.feature_answer.data, p_rpt + GET_RPT_RSP_OFFSET, len); uhid_write(p_dev->fd, &ev); } if (len == 0 || len > UHID_DATA_MAX) { LOG_WARN("Invalid report size = %d", len); return; } struct uhid_event ev = { .type = UHID_FEATURE_ANSWER, .u = { .feature_answer = { .id = *context, .err = status, .size = len, }, }, }; memcpy(ev.u.feature_answer.data, p_rpt, len); uhid_write(p_dev->fd, &ev); osi_free(context); } /******************************************************************************* Loading Loading
system/bta/hh/bta_hh_act.cc +0 −8 Original line number Diff line number Diff line Loading @@ -659,9 +659,6 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { bta_hh.hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data); if (bta_hh.hs_data.status == BTA_HH_OK) bta_hh.hs_data.status = BTA_HH_HS_TRANS_NOT_SPT; if (p_cb->w4_evt == BTA_HH_GET_RPT_EVT) bta_hh_co_get_rpt_rsp(bta_hh.dev_status.handle, bta_hh.hs_data.status, NULL, 0); (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh); p_cb->w4_evt = 0; break; Loading @@ -673,9 +670,6 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { bta_hh.dev_status.handle = p_cb->hid_handle; bta_hh.dev_status.status = bta_hh_get_trans_status(p_data->hid_cback.data); if (p_cb->w4_evt == BTA_HH_SET_RPT_EVT) bta_hh_co_set_rpt_rsp(bta_hh.dev_status.handle, bta_hh.dev_status.status); (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh); p_cb->w4_evt = 0; break; Loading Loading @@ -732,8 +726,6 @@ void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { break; case BTA_HH_GET_RPT_EVT: hs_data.rsp_data.p_rpt_data = pdata; bta_hh_co_get_rpt_rsp(hs_data.handle, hs_data.status, pdata->data, pdata->len); break; case BTA_HH_GET_PROTO_EVT: /* match up BTE/BTA report/boot mode def*/ Loading
system/bta/hh/bta_hh_le.cc +25 −29 Original line number Diff line number Diff line Loading @@ -1726,56 +1726,53 @@ void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB* p_cb) { static void read_report_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* data) { tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT) { LOG_WARN("Unexpected Read response, w4_evt = %d", p_dev_cb->w4_evt); return; } const gatt::Characteristic* p_char = BTA_GATTC_GetCharacteristic(conn_id, handle); if (p_char == NULL) return; uint16_t char_uuid = p_char->uuid.As16Bit(); if (char_uuid != GATT_UUID_HID_REPORT && char_uuid != GATT_UUID_HID_BT_KB_INPUT && char_uuid != GATT_UUID_HID_BT_KB_OUTPUT && char_uuid != GATT_UUID_HID_BT_MOUSE_INPUT && char_uuid != GATT_UUID_BATTERY_LEVEL) { APPL_TRACE_ERROR("%s: Unexpected Read UUID: 0x%04x", __func__, char_uuid); if (p_char == nullptr) { LOG_ERROR("Unknown handle"); return; } tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT) { APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt); uint16_t char_uuid = p_char->uuid.As16Bit(); switch (char_uuid) { case GATT_UUID_HID_REPORT: case GATT_UUID_HID_BT_KB_INPUT: case GATT_UUID_HID_BT_KB_OUTPUT: case GATT_UUID_HID_BT_MOUSE_INPUT: case GATT_UUID_BATTERY_LEVEL: break; default: LOG_ERROR("Unexpected Read UUID: 0x%04x", char_uuid); return; } /* GET_REPORT */ BT_HDR* p_buf = NULL; tBTA_HH_LE_RPT* p_rpt; tBTA_HH_HSDATA hs_data; uint8_t* pp; memset(&hs_data, 0, sizeof(hs_data)); tBTA_HH_HSDATA hs_data = {}; hs_data.status = BTA_HH_ERR; hs_data.handle = p_dev_cb->hid_handle; if (status == GATT_SUCCESS) { tBTA_HH_LE_RPT* p_rpt; const gatt::Service* p_svc = BTA_GATTC_GetOwningService(conn_id, p_char->value_handle); p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, char_uuid, p_char->value_handle); if (p_rpt != NULL && len) { p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1); if (p_rpt != nullptr && len) { BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + 1); /* pack data send to app */ hs_data.status = BTA_HH_OK; p_buf->len = len + 1; p_buf->layer_specific = 0; p_buf->offset = 0; uint8_t* pp = (uint8_t*)(p_buf + 1); /* attach report ID as the first byte of the report before sending it to * USB HID driver */ pp = (uint8_t*)(p_buf + 1); UINT8_TO_STREAM(pp, p_rpt->rpt_id); memcpy(pp, value, len); Loading @@ -1785,8 +1782,7 @@ static void read_report_cb(uint16_t conn_id, tGATT_STATUS status, p_dev_cb->w4_evt = 0; (*bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH*)&hs_data); osi_free_and_reset((void**)&p_buf); osi_free(hs_data.rsp_data.p_rpt_data); } /******************************************************************************* Loading
system/bta/include/bta_hh_co.h +1 −1 Original line number Diff line number Diff line Loading @@ -103,7 +103,7 @@ extern void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status); * ******************************************************************************/ extern void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, uint8_t* p_rpt, uint16_t len); const uint8_t* p_rpt, uint16_t len); /******************************************************************************* * Loading
system/bta/test/bta_hh_test.cc +1 −2 Original line number Diff line number Diff line Loading @@ -104,6 +104,5 @@ TEST_F(BtaHhTest, bta_hh_ctrl_dat_act__BTA_HH_GET_RPT_EVT) { }; bta_hh_ctrl_dat_act(&cb, &data); ASSERT_EQ(get_func_call_count("bta_hh_co_get_rpt_rsp"), 1); ASSERT_EQ(cb.w4_evt, 0); }
system/btif/co/bta_hh_co.cc +136 −100 Original line number Diff line number Diff line Loading @@ -45,11 +45,13 @@ const char* dev_path = "/dev/uhid"; #include "btif_config.h" #define BTA_HH_NV_LOAD_MAX 16 static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; #define GET_RPT_RSP_OFFSET 9 #define BTA_HH_CACHE_REPORT_VERSION 1 #define THREAD_NORMAL_PRIORITY 0 #define BT_HH_THREAD "bt_hh_thread" static const bthh_report_type_t map_rtype_uhid_hh[] = { BTHH_FEATURE_REPORT, BTHH_OUTPUT_REPORT, BTHH_INPUT_REPORT}; void uhid_set_non_blocking(int fd) { int opts = fcntl(fd, F_GETFL); if (opts < 0) Loading @@ -63,6 +65,62 @@ void uhid_set_non_blocking(int fd) { strerror(errno)); } static bool uhid_feature_req_handler(btif_hh_device_t* p_dev, struct uhid_feature_req& req) { LOG_DEBUG("Report type = %d, id = %d", req.rtype, req.rnum); if (req.rtype > UHID_INPUT_REPORT) { LOG_ERROR("Invalid report type %d", req.rtype); return false; } if (p_dev->get_rpt_id_queue == nullptr) { LOG_ERROR("Queue is not initialized"); return false; } uint32_t* context = (uint32_t*)osi_malloc(sizeof(uint32_t)); *context = req.id; if (!fixed_queue_try_enqueue(p_dev->get_rpt_id_queue, (void*)context)) { osi_free(context); LOG_ERROR("Queue is full, dropping event %d", req.id); return false; } btif_hh_getreport(p_dev, map_rtype_uhid_hh[req.rtype], req.rnum, 0); return true; } #if ENABLE_UHID_SET_REPORT static bool uhid_set_report_req_handler(btif_hh_device_t* p_dev, struct uhid_set_report_req& req) { LOG_DEBUG("Report type = %d, id = %d", req.rtype, req.rnum); if (req.rtype > UHID_INPUT_REPORT) { LOG_ERROR("Invalid report type %d", req.rtype); return false; } if (p_dev->set_rpt_id_queue == nullptr) { LOG_ERROR("Queue is not initialized"); return false; } uint32_t* context = (uint32_t*)osi_malloc(sizeof(uint32_t)); *context = req.id; if (!fixed_queue_try_enqueue(p_dev->set_rpt_id_queue, (void*)context)) { osi_free(context); LOG_ERROR("Queue is full, dropping event %d", req.id); return false; } btif_hh_setreport(p_dev, map_rtype_uhid_hh[req.rtype], req.size, req.data); return true; } #endif // ENABLE_UHID_SET_REPORT /*Internal function to perform UHID write and error checking*/ static int uhid_write(int fd, const struct uhid_event* ev) { ssize_t ret; Loading Loading @@ -146,74 +204,37 @@ static int uhid_read_event(btif_hh_device_t* p_dev) { } APPL_TRACE_DEBUG("UHID_OUTPUT_EV from uhid-dev\n"); break; case UHID_FEATURE: case UHID_FEATURE: // UHID_GET_REPORT if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.feature))) { APPL_TRACE_ERROR( "%s: UHID_FEATURE: Invalid size read from uhid-dev: %zd < %zu", __func__, ret, sizeof(ev.type) + sizeof(ev.u.feature)); LOG_ERROR("UHID_GET_REPORT: Invalid size read from uhid-dev: %zd < %zu", ret, sizeof(ev.type) + sizeof(ev.u.feature)); return -EFAULT; } APPL_TRACE_DEBUG("UHID_FEATURE: Report type = %d", ev.u.feature.rtype); p_dev->get_rpt_snt++; if (p_dev->get_rpt_id_queue) { uint32_t* get_rpt_id = (uint32_t*)osi_malloc(sizeof(uint32_t)); *get_rpt_id = ev.u.feature.id; auto ok = fixed_queue_try_enqueue(p_dev->get_rpt_id_queue, (void*)get_rpt_id); if (!ok) { LOG_ERROR("get_rpt_id_queue is full, dropping event %d", *get_rpt_id); osi_free(get_rpt_id); if (!uhid_feature_req_handler(p_dev, ev.u.feature)) { return -EFAULT; } } if (ev.u.feature.rtype == UHID_FEATURE_REPORT) btif_hh_getreport(p_dev, BTHH_FEATURE_REPORT, ev.u.feature.rnum, 0); else APPL_TRACE_ERROR("%s: UHID_FEATURE: Invalid report type = %d", __func__, ev.u.feature.rtype); break; #if ENABLE_UHID_SET_REPORT case UHID_SET_REPORT: { bool sent = true; if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.set_report))) { LOG_ERROR("Invalid size read from uhid-dev: %zd < %zu", ret, sizeof(ev.type) + sizeof(ev.u.set_report)); LOG_ERROR("UHID_SET_REPORT: Invalid size read from uhid-dev: %zd < %zu", ret, sizeof(ev.type) + sizeof(ev.u.set_report)); return -EFAULT; } LOG_DEBUG("UHID_SET_REPORT: Report type = %d, report_size = %d", ev.u.set_report.rtype, ev.u.set_report.size); if (ev.u.set_report.rtype == UHID_FEATURE_REPORT) { btif_hh_setreport(p_dev, BTHH_FEATURE_REPORT, ev.u.set_report.size, ev.u.set_report.data); } else if (ev.u.set_report.rtype == UHID_OUTPUT_REPORT) { btif_hh_setreport(p_dev, BTHH_OUTPUT_REPORT, ev.u.set_report.size, ev.u.set_report.data); } else if (ev.u.set_report.rtype == UHID_INPUT_REPORT) { btif_hh_setreport(p_dev, BTHH_INPUT_REPORT, ev.u.set_report.size, ev.u.set_report.data); } else { LOG_ERROR("UHID_SET_REPORT: Invalid Report type = %d", ev.u.set_report.rtype); sent = false; } if (sent && p_dev->set_rpt_id_queue) { uint32_t* set_rpt_id = (uint32_t*)osi_malloc(sizeof(uint32_t)); *set_rpt_id = ev.u.set_report.id; auto ok = fixed_queue_try_enqueue(p_dev->set_rpt_id_queue, (void*)set_rpt_id); if (!ok) { LOG_ERROR("set_rpt_id_queue is full, dropping event %d", *set_rpt_id); osi_free(set_rpt_id); if (!uhid_set_report_req_handler(p_dev, ev.u.set_report)) { return -EFAULT; } } break; } #endif // ENABLE_UHID_SET_REPORT default: APPL_TRACE_DEBUG("Invalid event from uhid-dev: %u\n", ev.type); LOG_ERROR("Invalid event from uhid-dev: %u\n", ev.type); } return 0; Loading Loading @@ -612,33 +633,42 @@ void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) { btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_handle(dev_handle); if (p_dev == nullptr) { LOG_WARN("Error: unknown HID device handle %d", dev_handle); LOG_WARN("Unknown HID device handle %d", dev_handle); return; } if (!p_dev->set_rpt_id_queue) { LOG_WARN("Error: missing UHID_SET_REPORT id queue"); LOG_WARN("Missing UHID_SET_REPORT id queue"); return; } // Send the HID set report reply to the kernel. if (p_dev->fd >= 0) { uint32_t* set_rpt_id = (uint32_t*)fixed_queue_try_dequeue(p_dev->set_rpt_id_queue); if (set_rpt_id) { struct uhid_event ev = {}; ev.type = UHID_SET_REPORT_REPLY; ev.u.set_report_reply.id = *set_rpt_id; ev.u.set_report_reply.err = status; osi_free(set_rpt_id); uhid_write(p_dev->fd, &ev); } else { LOG_VERBOSE("No pending UHID_SET_REPORT"); if (p_dev->fd < 0) { LOG_ERROR("Unexpected Set Report response"); return; } uint32_t* context = (uint32_t*)fixed_queue_try_dequeue(p_dev->set_rpt_id_queue); if (context == nullptr) { LOG_WARN("No pending UHID_SET_REPORT"); return; } struct uhid_event ev = { .type = UHID_SET_REPORT_REPLY, .u = { .set_report_reply = { .id = *context, .err = status, }, }, }; uhid_write(p_dev->fd, &ev); osi_free(context); #else LOG_ERROR("Error: UHID_SET_REPORT_REPLY not supported"); LOG_ERROR("UHID_SET_REPORT_REPLY not supported"); #endif // ENABLE_UHID_SET_REPORT } Loading @@ -652,49 +682,55 @@ void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) { * Returns void. * ******************************************************************************/ void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, uint8_t* p_rpt, uint16_t len) { struct uhid_event ev; void bta_hh_co_get_rpt_rsp(uint8_t dev_handle, uint8_t status, const uint8_t* p_rpt, uint16_t len) { btif_hh_device_t* p_dev; APPL_TRACE_VERBOSE("%s: dev_handle = %d", __func__, dev_handle); LOG_VERBOSE("dev_handle = %d, status = %d", dev_handle, status); p_dev = btif_hh_find_connected_dev_by_handle(dev_handle); if (p_dev == NULL) { APPL_TRACE_WARNING("%s: Error: unknown HID device handle %d", __func__, dev_handle); if (p_dev == nullptr) { LOG_WARN("Unknown HID device handle %d", dev_handle); return; } if (!p_dev->get_rpt_id_queue) { APPL_TRACE_WARNING("%s: Error: missing UHID_GET_REPORT id queue", __func__); LOG_WARN("Missing UHID_GET_REPORT id queue"); return; } // Send the HID report to the kernel. if (p_dev->fd >= 0 && p_dev->get_rpt_snt > 0 && p_dev->get_rpt_snt--) { uint32_t* get_rpt_id = (uint32_t*)fixed_queue_try_dequeue(p_dev->get_rpt_id_queue); if (get_rpt_id == nullptr) { APPL_TRACE_WARNING("%s: Error: UHID_GET_REPORT queue is empty", __func__); if (p_dev->fd < 0) { LOG_WARN("Unexpected Get Report response"); return; } memset(&ev, 0, sizeof(ev)); ev.type = UHID_FEATURE_ANSWER; ev.u.feature_answer.id = *get_rpt_id; ev.u.feature_answer.err = status; ev.u.feature_answer.size = len; osi_free(get_rpt_id); if (len > 0) { if (len > UHID_DATA_MAX) { APPL_TRACE_WARNING("%s: Report size greater than allowed size", __func__); uint32_t* context = (uint32_t*)fixed_queue_try_dequeue(p_dev->get_rpt_id_queue); if (context == nullptr) { LOG_WARN("No pending UHID_GET_REPORT"); return; } memcpy(ev.u.feature_answer.data, p_rpt + GET_RPT_RSP_OFFSET, len); uhid_write(p_dev->fd, &ev); } if (len == 0 || len > UHID_DATA_MAX) { LOG_WARN("Invalid report size = %d", len); return; } struct uhid_event ev = { .type = UHID_FEATURE_ANSWER, .u = { .feature_answer = { .id = *context, .err = status, .size = len, }, }, }; memcpy(ev.u.feature_answer.data, p_rpt, len); uhid_write(p_dev->fd, &ev); osi_free(context); } /******************************************************************************* Loading