Fork ESP-IDF's bluetooth component

i want better sbc encoding, and no cla will stop me
This commit is contained in:
jacqueline
2024-03-28 14:32:49 +11:00
parent 239e6d8950
commit ee29c25b29
1761 changed files with 737738 additions and 0 deletions
+789
View File
@@ -0,0 +1,789 @@
/******************************************************************************
*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the HID device action functions.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
#include "bta/bta_sys.h"
#include "bta_hd_int.h"
#include "osi/allocator.h"
#include "osi/osi.h"
#include "stack/btm_api.h"
#include <string.h>
static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata);
static bool check_descriptor(uint8_t *data, uint16_t length, bool *has_report_id)
{
uint8_t *ptr = data;
*has_report_id = FALSE;
while (ptr < data + length) {
uint8_t item = *ptr++;
switch (item) {
case 0xfe: // long item indicator
if (ptr < data + length) {
ptr += ((*ptr) + 2);
} else {
return false;
}
break;
case 0x85: // Report ID
*has_report_id = TRUE;
default:
ptr += (item & 0x03);
break;
}
}
return (ptr == data + length);
}
/*******************************************************************************
*
* Function bta_hd_api_enable
*
* Description Enables HID device
*
* Returns void
*
******************************************************************************/
void bta_hd_api_enable(tBTA_HD_DATA *p_data)
{
tBTA_HD_STATUS status = BTA_HD_ERROR;
tHID_STATUS ret;
APPL_TRACE_API("%s", __func__);
HID_DevInit();
memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
HID_DevSetSecurityLevel(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
/* store parameters */
bta_hd_cb.p_cback = p_data->api_enable.p_cback;
ret = HID_DevRegister(bta_hd_cback);
if (ret == HID_SUCCESS) {
status = BTA_HD_OK;
} else {
APPL_TRACE_ERROR("%s: Failed to register HID device (%d)", __func__, ret);
}
/* signal BTA call back event */
(*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, (tBTA_HD *)&status);
}
/*******************************************************************************
*
* Function bta_hd_api_disable
*
* Description Disables HID device
*
* Returns void
*
******************************************************************************/
void bta_hd_api_disable(void)
{
tBTA_HD_STATUS status = BTA_HD_ERROR;
tHID_STATUS ret;
APPL_TRACE_API("%s", __func__);
/* service is not enabled */
if (bta_hd_cb.p_cback == NULL)
return;
/* Remove service record */
if (bta_hd_cb.sdp_handle != 0) {
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
}
/* Deregister with lower layer */
ret = HID_DevDeregister();
if (ret == HID_SUCCESS) {
status = BTA_HD_OK;
} else {
APPL_TRACE_ERROR("%s: Failed to deregister HID device (%d)", __func__, ret);
}
(*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, (tBTA_HD *)&status);
memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
}
/*******************************************************************************
*
* Function bta_hd_register_act
*
* Description Registers SDP record
*
* Returns void
*
******************************************************************************/
void bta_hd_register_act(tBTA_HD_DATA *p_data)
{
tBTA_HD ret;
tBTA_HD_REGISTER_APP *p_app_data = (tBTA_HD_REGISTER_APP *)p_data;
bool use_report_id = FALSE;
APPL_TRACE_API("%s", __func__);
ret.reg_status.in_use = FALSE;
/* Check if len doesn't exceed BTA_HD_APP_DESCRIPTOR_LEN and descriptor
* itself is well-formed. Also check if descriptor has Report Id item so we
* know if report will have prefix or not. */
if (p_app_data->d_len > BTA_HD_APP_DESCRIPTOR_LEN ||
!check_descriptor(p_app_data->d_data, p_app_data->d_len, &use_report_id)) {
APPL_TRACE_ERROR("%s: Descriptor is too long or malformed", __func__);
ret.reg_status.status = BTA_HD_ERROR;
(*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
return;
}
ret.reg_status.status = BTA_HD_OK;
/* Remove old record if for some reason it's already registered */
if (bta_hd_cb.sdp_handle != 0) {
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
}
bta_hd_cb.use_report_id = use_report_id;
bta_hd_cb.sdp_handle = SDP_CreateRecord();
HID_DevAddRecord(bta_hd_cb.sdp_handle, p_app_data->name, p_app_data->description, p_app_data->provider,
p_app_data->subclass, p_app_data->d_len, p_app_data->d_data);
bta_sys_add_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
HID_DevSetIncomingQos(p_app_data->in_qos.service_type, p_app_data->in_qos.token_rate,
p_app_data->in_qos.token_bucket_size, p_app_data->in_qos.peak_bandwidth,
p_app_data->in_qos.access_latency, p_app_data->in_qos.delay_variation);
HID_DevSetOutgoingQos(p_app_data->out_qos.service_type, p_app_data->out_qos.token_rate,
p_app_data->out_qos.token_bucket_size, p_app_data->out_qos.peak_bandwidth,
p_app_data->out_qos.access_latency, p_app_data->out_qos.delay_variation);
// application is registered so we can accept incoming connections
HID_DevSetIncomingPolicy(TRUE);
if (HID_DevGetDevice(&ret.reg_status.bda) == HID_SUCCESS) {
ret.reg_status.in_use = TRUE;
}
(*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
}
/*******************************************************************************
*
* Function bta_hd_unregister_act
*
* Description Unregisters SDP record
*
* Returns void
*
******************************************************************************/
void bta_hd_unregister_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
{
tBTA_HD_STATUS status = BTA_HD_OK;
APPL_TRACE_API("%s", __func__);
// application is no longer registered so we do not want incoming connections
HID_DevSetIncomingPolicy(FALSE);
if (bta_hd_cb.sdp_handle != 0) {
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
}
bta_hd_cb.sdp_handle = 0;
bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
(*bta_hd_cb.p_cback)(BTA_HD_UNREGISTER_APP_EVT, (tBTA_HD *)&status);
}
/*******************************************************************************
*
* Function bta_hd_unregister2_act
*
* Description
*
* Returns void
*
******************************************************************************/
void bta_hd_unregister2_act(tBTA_HD_DATA *p_data)
{
APPL_TRACE_API("%s", __func__);
// close first
bta_hd_close_act(p_data);
// then unregister
bta_hd_unregister_act(p_data);
if (bta_hd_cb.disable_w4_close) {
bta_hd_api_disable();
}
}
/*******************************************************************************
*
* Function bta_hd_connect_act
*
* Description Connect to device (must be virtually plugged)
*
* Returns void
*
******************************************************************************/
extern void bta_hd_connect_act(tBTA_HD_DATA *p_data)
{
tHID_STATUS ret;
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
tBTA_HD cback_data;
APPL_TRACE_API("%s", __func__);
do {
ret = HID_DevPlugDevice(p_ctrl->addr);
if (ret != HID_SUCCESS) {
APPL_TRACE_WARNING("%s: HID_DevPlugDevice returned %d", __func__, ret);
return;
}
ret = HID_DevConnect();
if (ret != HID_SUCCESS) {
APPL_TRACE_WARNING("%s: HID_DevConnect returned %d", __func__, ret);
return;
}
} while (0);
bdcpy(cback_data.conn.bda, p_ctrl->addr);
cback_data.conn.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTING;
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_disconnect_act
*
* Description Disconnect from device
*
* Returns void
*
******************************************************************************/
extern void bta_hd_disconnect_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
{
tHID_STATUS ret;
tBTA_HD cback_data;
APPL_TRACE_API("%s", __func__);
ret = HID_DevDisconnect();
if (ret != HID_SUCCESS) {
APPL_TRACE_WARNING("%s: HID_DevDisconnect returned %d", __func__, ret);
return;
}
if (HID_DevGetDevice(&cback_data.conn.bda) == HID_SUCCESS) {
cback_data.conn.status = BTA_HD_OK;
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTING;
bta_hd_cb.p_cback(BTA_HD_CLOSE_EVT, &cback_data);
}
}
/*******************************************************************************
*
* Function bta_hd_add_device_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
APPL_TRACE_API("%s", __func__);
HID_DevPlugDevice(p_ctrl->addr);
}
/*******************************************************************************
*
* Function bta_hd_remove_device_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
APPL_TRACE_API("%s", __func__);
HID_DevUnplugDevice(p_ctrl->addr);
}
/*******************************************************************************
*
* Function bta_hd_send_report_act
*
* Description Sends report
*
* Returns void
*
******************************************************************************/
extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_SEND_REPORT *p_report = (tBTA_HD_SEND_REPORT *)p_data;
uint8_t channel;
uint8_t report_id;
tBTA_HD cback_data;
tHID_STATUS ret;
APPL_TRACE_VERBOSE("%s", __func__);
channel = p_report->use_intr ? HID_CHANNEL_INTR : HID_CHANNEL_CTRL;
report_id = (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) ? p_report->id : 0x00;
ret = HID_DevSendReport(channel, p_report->type, report_id, p_report->len, p_report->data);
/* trigger PM */
bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
cback_data.send_report.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
cback_data.send_report.reason = ret;
cback_data.send_report.report_id = report_id;
cback_data.send_report.report_type = p_report->type;
bta_hd_cb.p_cback(BTA_HD_SEND_REPORT_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_report_error_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_REPORT_ERR *p_report = (tBTA_HD_REPORT_ERR *)p_data;
tHID_STATUS ret;
tBTA_HD cback_data;
APPL_TRACE_API("%s: error = %d", __func__, p_report->error);
ret = HID_DevReportError(p_report->error);
if (ret != HID_SUCCESS) {
APPL_TRACE_WARNING("%s: HID_DevReportError returned %d", __func__, ret);
}
cback_data.report_err.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
cback_data.report_err.reason = ret;
bta_hd_cb.p_cback(BTA_HD_REPORT_ERR_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_vc_unplug_act
*
* Description Sends Virtual Cable Unplug
*
* Returns void
*
******************************************************************************/
extern void bta_hd_vc_unplug_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
{
tHID_STATUS ret;
tBTA_HD cback_data = {0};
BD_ADDR plugged_addr = {0};
APPL_TRACE_API("%s", __func__);
bta_hd_cb.vc_unplug = TRUE;
ret = HID_DevVirtualCableUnplug();
if (ret == HID_ERR_NO_CONNECTION) {
/* This is a local VUP without connection, set the vc_unplug to FALSE */
bta_hd_cb.vc_unplug = FALSE;
APPL_TRACE_WARNING("%s: HID_DevVirtualCableUnplug returned %d", __func__, ret);
if (HID_DevGetDevice(&plugged_addr) == HID_SUCCESS) {
HID_DevUnplugDevice(plugged_addr);
}
APPL_TRACE_DEBUG("%s local VUP, remove bda: %02x:%02x:%02x:%02x:%02x:%02x", __func__, plugged_addr[0],
plugged_addr[1], plugged_addr[2], plugged_addr[3], plugged_addr[4], plugged_addr[5]);
cback_data.conn.status = BTA_HD_OK;
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
bta_hd_cb.p_cback(BTA_HD_VC_UNPLUG_EVT, &cback_data);
return;
} else if (ret != HID_SUCCESS) {
APPL_TRACE_WARNING("%s: HID_DevVirtualCableUnplug returned %d", __func__, ret);
}
/* trigger PM */
bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
}
/*******************************************************************************
*
* Function bta_hd_open_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_open_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
tBTA_HD cback_data;
APPL_TRACE_API("%s", __func__);
HID_DevPlugDevice(p_cback->addr);
bta_sys_conn_open(BTA_ID_HD, 1, p_cback->addr);
bdcpy(cback_data.conn.bda, p_cback->addr);
bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
cback_data.conn.status = BTA_HD_OK;
cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTED;
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_close_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_close_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
tBTA_HD cback_data;
tBTA_HD_EVT cback_event = BTA_HD_CLOSE_EVT;
APPL_TRACE_API("%s", __func__);
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
if (bta_hd_cb.vc_unplug) {
bta_hd_cb.vc_unplug = FALSE;
HID_DevUnplugDevice(p_cback->addr);
cback_event = BTA_HD_VC_UNPLUG_EVT;
}
bdcpy(cback_data.conn.bda, p_cback->addr);
memset(bta_hd_cb.bd_addr, 0, sizeof(BD_ADDR));
cback_data.conn.status = BTA_HD_OK;
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
bta_hd_cb.p_cback(cback_event, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_intr_data_act
*
* Description Handles incoming DATA request on intr
*
* Returns void
*
******************************************************************************/
extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
BT_HDR *p_msg = p_cback->p_data;
uint16_t len = p_msg->len;
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
tBTA_HD_INTR_DATA ret;
APPL_TRACE_API("%s", __func__);
if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
ret.report_id = *p_buf;
len--;
p_buf++;
} else {
ret.report_id = 0;
}
ret.len = len;
ret.p_data = p_buf;
(*bta_hd_cb.p_cback)(BTA_HD_INTR_DATA_EVT, (tBTA_HD *)&ret);
if (p_msg) {
osi_free(p_msg);
}
}
/*******************************************************************************
*
* Function bta_hd_get_report_act
*
* Description Handles incoming GET_REPORT request
*
* Returns void
*
******************************************************************************/
extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
bool rep_size_follows = p_cback->data;
BT_HDR *p_msg = p_cback->p_data;
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
tBTA_HD_GET_REPORT ret = {0, 0, 0};
uint16_t remaining_len = p_msg->len;
APPL_TRACE_API("%s", __func__);
if (remaining_len < 1) {
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
return;
}
ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
p_buf++;
remaining_len--;
if (bta_hd_cb.use_report_id) {
if (remaining_len < 1) {
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
return;
}
ret.report_id = *p_buf;
p_buf++;
remaining_len--;
}
if (rep_size_follows) {
if (remaining_len < 2) {
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
return;
}
ret.buffer_size = *p_buf | (*(p_buf + 1) << 8);
}
(*bta_hd_cb.p_cback)(BTA_HD_GET_REPORT_EVT, (tBTA_HD *)&ret);
if (p_msg) {
osi_free(p_msg);
}
}
/*******************************************************************************
*
* Function bta_hd_set_report_act
*
* Description Handles incoming SET_REPORT request
*
* Returns void
*
******************************************************************************/
extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
BT_HDR *p_msg = p_cback->p_data;
uint16_t len = p_msg->len;
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
tBTA_HD_SET_REPORT ret = {0, 0, 0, NULL};
APPL_TRACE_API("%s", __func__);
ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
p_buf++;
len--;
if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
ret.report_id = *p_buf;
len--;
p_buf++;
} else {
ret.report_id = 0;
}
ret.len = len;
ret.p_data = p_buf;
(*bta_hd_cb.p_cback)(BTA_HD_SET_REPORT_EVT, (tBTA_HD *)&ret);
if (p_msg) {
osi_free(p_msg);
}
}
/*******************************************************************************
*
* Function bta_hd_set_protocol_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
tBTA_HD cback_data;
APPL_TRACE_API("%s", __func__);
bta_hd_cb.boot_mode = (p_cback->data == HID_PAR_PROTOCOL_BOOT_MODE);
cback_data.set_protocol = p_cback->data;
(*bta_hd_cb.p_cback)(BTA_HD_SET_PROTOCOL_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_vc_unplug_done_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
tBTA_HD cback_data;
APPL_TRACE_API("%s", __func__);
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
HID_DevUnplugDevice(p_cback->addr);
bdcpy(cback_data.conn.bda, p_cback->addr);
bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
cback_data.conn.status = BTA_HD_OK;
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
(*bta_hd_cb.p_cback)(BTA_HD_VC_UNPLUG_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_suspend_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
APPL_TRACE_API("%s", __func__);
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
}
/*******************************************************************************
*
* Function bta_hd_exit_suspend_act
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
APPL_TRACE_API("%s", __func__);
bta_sys_busy(BTA_ID_HD, 1, p_cback->addr);
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
}
/*******************************************************************************
*
* Function bta_hd_cback
*
* Description BTA HD callback function
*
* Returns void
*
******************************************************************************/
static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata)
{
tBTA_HD_CBACK_DATA *p_buf = NULL;
uint16_t sm_event = BTA_HD_INVALID_EVT;
APPL_TRACE_API("%s: event=%d", __func__, event);
switch (event) {
case HID_DHOST_EVT_OPEN:
sm_event = BTA_HD_INT_OPEN_EVT;
break;
case HID_DHOST_EVT_CLOSE:
sm_event = BTA_HD_INT_CLOSE_EVT;
break;
case HID_DHOST_EVT_GET_REPORT:
sm_event = BTA_HD_INT_GET_REPORT_EVT;
break;
case HID_DHOST_EVT_SET_REPORT:
sm_event = BTA_HD_INT_SET_REPORT_EVT;
break;
case HID_DHOST_EVT_SET_PROTOCOL:
sm_event = BTA_HD_INT_SET_PROTOCOL_EVT;
break;
case HID_DHOST_EVT_INTR_DATA:
sm_event = BTA_HD_INT_INTR_DATA_EVT;
break;
case HID_DHOST_EVT_VC_UNPLUG:
sm_event = BTA_HD_INT_VC_UNPLUG_EVT;
break;
case HID_DHOST_EVT_SUSPEND:
sm_event = BTA_HD_INT_SUSPEND_EVT;
break;
case HID_DHOST_EVT_EXIT_SUSPEND:
sm_event = BTA_HD_INT_EXIT_SUSPEND_EVT;
break;
}
if (sm_event != BTA_HD_INVALID_EVT &&
(p_buf = (tBTA_HD_CBACK_DATA *)osi_malloc(sizeof(tBTA_HD_CBACK_DATA) + sizeof(BT_HDR))) != NULL) {
p_buf->hdr.event = sm_event;
bdcpy(p_buf->addr, bd_addr);
p_buf->data = data;
p_buf->p_data = pdata;
bta_sys_sendmsg(p_buf);
}
}
#endif /* BTA_HD_INCLUDED */
+287
View File
@@ -0,0 +1,287 @@
/******************************************************************************
*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the HID DEVICE API in the subsystem of BTA.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
#include "bta/bta_hd_api.h"
#include "bta_hd_int.h"
#include "osi/allocator.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*****************************************************************************
* Constants
****************************************************************************/
static const tBTA_SYS_REG bta_hd_reg = {bta_hd_hdl_event, BTA_HdDisable};
/*******************************************************************************
*
* Function BTA_HdEnable
*
* Description Enables HID device
*
* Returns void
*
******************************************************************************/
void BTA_HdEnable(tBTA_HD_CBACK *p_cback)
{
tBTA_HD_API_ENABLE *p_buf;
APPL_TRACE_API("%s", __func__);
bta_sys_register(BTA_ID_HD, &bta_hd_reg);
p_buf = (tBTA_HD_API_ENABLE *)osi_malloc((uint16_t)sizeof(tBTA_HD_API_ENABLE));
if (p_buf != NULL) {
memset(p_buf, 0, sizeof(tBTA_HD_API_ENABLE));
p_buf->hdr.event = BTA_HD_API_ENABLE_EVT;
p_buf->p_cback = p_cback;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdDisable
*
* Description Disables HID device.
*
* Returns void
*
******************************************************************************/
void BTA_HdDisable(void)
{
BT_HDR *p_buf;
APPL_TRACE_API("%s", __func__);
bta_sys_deregister(BTA_ID_HD);
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HD_API_DISABLE_EVT;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdRegisterApp
*
* Description This function is called when application should be
*registered
*
* Returns void
*
******************************************************************************/
extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos)
{
tBTA_HD_REGISTER_APP *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (tBTA_HD_REGISTER_APP *)osi_malloc(sizeof(tBTA_HD_REGISTER_APP))) != NULL) {
p_buf->hdr.event = BTA_HD_API_REGISTER_APP_EVT;
if (p_app_info->p_name) {
strncpy(p_buf->name, p_app_info->p_name, BTA_HD_APP_NAME_LEN);
p_buf->name[BTA_HD_APP_NAME_LEN] = '\0';
} else {
p_buf->name[0] = '\0';
}
if (p_app_info->p_description) {
strncpy(p_buf->description, p_app_info->p_description, BTA_HD_APP_DESCRIPTION_LEN);
p_buf->description[BTA_HD_APP_DESCRIPTION_LEN] = '\0';
} else {
p_buf->description[0] = '\0';
}
if (p_app_info->p_provider) {
strncpy(p_buf->provider, p_app_info->p_provider, BTA_HD_APP_PROVIDER_LEN);
p_buf->provider[BTA_HD_APP_PROVIDER_LEN] = '\0';
} else {
p_buf->provider[0] = '\0';
}
p_buf->subclass = p_app_info->subclass;
p_buf->d_len = p_app_info->descriptor.dl_len;
memcpy(p_buf->d_data, p_app_info->descriptor.dsc_list, p_app_info->descriptor.dl_len);
// copy qos data as-is
memcpy(&p_buf->in_qos, p_in_qos, sizeof(tBTA_HD_QOS_INFO));
memcpy(&p_buf->out_qos, p_out_qos, sizeof(tBTA_HD_QOS_INFO));
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdUnregisterApp
*
* Description This function is called when application should be
*unregistered
*
* Returns void
*
******************************************************************************/
extern void BTA_HdUnregisterApp(void)
{
BT_HDR *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HD_API_UNREGISTER_APP_EVT;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdSendReport
*
* Description This function is called when report is to be sent
*
* Returns void
*
******************************************************************************/
extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report)
{
tBTA_HD_SEND_REPORT *p_buf;
APPL_TRACE_VERBOSE("%s", __func__);
if (p_report->len > BTA_HD_REPORT_LEN) {
APPL_TRACE_WARNING("%s, report len (%d) > MTU len (%d), can't send report."
" Increase value of HID_DEV_MTU_SIZE to send larger reports",
__func__, p_report->len, BTA_HD_REPORT_LEN);
return;
}
if ((p_buf = (tBTA_HD_SEND_REPORT *)osi_malloc(sizeof(tBTA_HD_SEND_REPORT))) != NULL) {
p_buf->hdr.event = BTA_HD_API_SEND_REPORT_EVT;
p_buf->use_intr = p_report->use_intr;
p_buf->type = p_report->type;
p_buf->id = p_report->id;
p_buf->len = p_report->len;
memcpy(p_buf->data, p_report->p_data, p_report->len);
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdVirtualCableUnplug
*
* Description This function is called when VCU shall be sent
*
* Returns void
*
******************************************************************************/
extern void BTA_HdVirtualCableUnplug(void)
{
BT_HDR *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HD_API_VC_UNPLUG_EVT;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdConnect
*
* Description This function is called when connection to host shall be
* made
*
* Returns void
*
******************************************************************************/
extern void BTA_HdConnect(BD_ADDR addr)
{
tBTA_HD_DEVICE_CTRL *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
p_buf->hdr.event = BTA_HD_API_CONNECT_EVT;
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdDisconnect
*
* Description This function is called when host shall be disconnected
*
* Returns void
*
******************************************************************************/
extern void BTA_HdDisconnect(void)
{
BT_HDR *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HD_API_DISCONNECT_EVT;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdAddDevice
*
* Description This function is called when a device is virtually cabled
*
* Returns void
*
******************************************************************************/
extern void BTA_HdAddDevice(BD_ADDR addr)
{
tBTA_HD_DEVICE_CTRL *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
p_buf->hdr.event = BTA_HD_API_ADD_DEVICE_EVT;
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdRemoveDevice
*
* Description This function is called when a device is virtually uncabled
*
* Returns void
*
******************************************************************************/
extern void BTA_HdRemoveDevice(BD_ADDR addr)
{
tBTA_HD_DEVICE_CTRL *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
p_buf->hdr.event = BTA_HD_API_REMOVE_DEVICE_EVT;
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
*
* Function BTA_HdReportError
*
* Description This function is called when reporting error for set report
*
* Returns void
*
******************************************************************************/
extern void BTA_HdReportError(uint8_t error)
{
tBTA_HD_REPORT_ERR *p_buf;
APPL_TRACE_API("%s", __func__);
if ((p_buf = (tBTA_HD_REPORT_ERR *)osi_malloc(sizeof(tBTA_HD_REPORT_ERR))) != NULL) {
p_buf->hdr.event = BTA_HD_API_REPORT_ERROR_EVT;
p_buf->error = error;
bta_sys_sendmsg(p_buf);
}
}
#endif /* BTA_HD_INCLUDED */
+337
View File
@@ -0,0 +1,337 @@
/******************************************************************************
*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the HID host main functions and state machine.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
#include "bta/bta_hd_api.h"
#include "bta_hd_int.h"
#include <string.h>
/*****************************************************************************
* Constants and types
****************************************************************************/
/* state machine states */
enum {
BTA_HD_INIT_ST,
BTA_HD_IDLE_ST, /* not connected, waiting for connection */
BTA_HD_CONN_ST, /* host connected */
BTA_HD_TRANSIENT_TO_INIT_ST, /* transient state: going back from CONN to INIT */
};
typedef uint8_t tBTA_HD_STATE;
/* state machine actions */
enum {
BTA_HD_REGISTER_ACT,
BTA_HD_UNREGISTER_ACT,
BTA_HD_UNREGISTER2_ACT,
BTA_HD_CONNECT_ACT,
BTA_HD_DISCONNECT_ACT,
BTA_HD_ADD_DEVICE_ACT,
BTA_HD_REMOVE_DEVICE_ACT,
BTA_HD_SEND_REPORT_ACT,
BTA_HD_REPORT_ERROR_ACT,
BTA_HD_VC_UNPLUG_ACT,
BTA_HD_OPEN_ACT,
BTA_HD_CLOSE_ACT,
BTA_HD_INTR_DATA_ACT,
BTA_HD_GET_REPORT_ACT,
BTA_HD_SET_REPORT_ACT,
BTA_HD_SET_PROTOCOL_ACT,
BTA_HD_VC_UNPLUG_DONE_ACT,
BTA_HD_SUSPEND_ACT,
BTA_HD_EXIT_SUSPEND_ACT,
BTA_HD_NUM_ACTIONS
};
#define BTA_HD_IGNORE BTA_HD_NUM_ACTIONS
typedef void (*tBTA_HD_ACTION)(tBTA_HD_DATA *p_data);
/* action functions */
const tBTA_HD_ACTION bta_hd_action[] = {
bta_hd_register_act, bta_hd_unregister_act, bta_hd_unregister2_act, bta_hd_connect_act,
bta_hd_disconnect_act, bta_hd_add_device_act, bta_hd_remove_device_act, bta_hd_send_report_act,
bta_hd_report_error_act, bta_hd_vc_unplug_act, bta_hd_open_act, bta_hd_close_act,
bta_hd_intr_data_act, bta_hd_get_report_act, bta_hd_set_report_act, bta_hd_set_protocol_act,
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act,
};
/* state table information */
#define BTA_HD_ACTION 0 /* position of action */
#define BTA_HD_NEXT_STATE 1 /* position of next state */
#define BTA_HD_NUM_COLS 2 /* number of columns */
const uint8_t bta_hd_st_init[][BTA_HD_NUM_COLS] = {
/* Event Action Next state
*/
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_REGISTER_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_INIT_ST},
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_INIT_ST},
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
};
const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = {
/* Event Action Next state
*/
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_UNREGISTER_ACT, BTA_HD_INIT_ST},
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_CONNECT_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
};
const uint8_t bta_hd_st_conn[][BTA_HD_NUM_COLS] = {
/* Event Action Next state */
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_CONN_ST},
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_CONN_ST},
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_CONN_ST},
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_CONN_ST},
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_REPORT_ERROR_ACT, BTA_HD_CONN_ST},
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_CLOSE_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_INTR_DATA_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_GET_REPORT_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_SET_REPORT_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_SET_PROTOCOL_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_DONE_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_SUSPEND_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_EXIT_SUSPEND_ACT, BTA_HD_CONN_ST},
};
const uint8_t bta_hd_st_transient_to_init[][BTA_HD_NUM_COLS] = {
/* Event Action Next state */
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST},
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST},
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
};
/* type for state table */
typedef const uint8_t (*tBTA_HD_ST_TBL)[BTA_HD_NUM_COLS];
/* state table */
const tBTA_HD_ST_TBL bta_hd_st_tbl[] = {bta_hd_st_init, bta_hd_st_idle, bta_hd_st_conn, bta_hd_st_transient_to_init};
/*****************************************************************************
* Global data
****************************************************************************/
#if BTA_DYNAMIC_MEMORY == FALSE
tBTA_HD_CB bta_hd_cb;
#else
tBTA_HD_CB *bta_hd_cb_ptr;
#endif
static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code);
static const char *bta_hd_state_code(tBTA_HD_STATE state_code);
/*******************************************************************************
*
* Function bta_hd_sm_execute
*
* Description State machine event handling function for HID Device
*
* Returns void
*
******************************************************************************/
void bta_hd_sm_execute(uint16_t event, tBTA_HD_DATA *p_data)
{
tBTA_HD_ST_TBL state_table;
tBTA_HD_STATE prev_state;
uint8_t action;
tBTA_HD cback_data;
APPL_TRACE_EVENT("%s: state=%s (%d) event=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state,
bta_hd_evt_code(event), event);
prev_state = bta_hd_cb.state;
memset(&cback_data, 0, sizeof(tBTA_HD));
state_table = bta_hd_st_tbl[bta_hd_cb.state];
event &= 0xff;
if ((action = state_table[event][BTA_HD_ACTION]) < BTA_HD_IGNORE) {
(*bta_hd_action[action])(p_data);
}
bta_hd_cb.state = state_table[event][BTA_HD_NEXT_STATE];
if (bta_hd_cb.state != prev_state) {
APPL_TRACE_EVENT("%s: [new] state=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state);
}
return;
}
/*******************************************************************************
*
* Function bta_hd_hdl_event
*
* Description HID device main event handling function.
*
* Returns void
*
******************************************************************************/
bool bta_hd_hdl_event(BT_HDR *p_msg)
{
APPL_TRACE_API("%s: p_msg->event=%d", __func__, p_msg->event);
switch (p_msg->event) {
case BTA_HD_API_ENABLE_EVT:
bta_hd_api_enable((tBTA_HD_DATA *)p_msg);
break;
case BTA_HD_API_DISABLE_EVT:
if (bta_hd_cb.state == BTA_HD_CONN_ST) {
APPL_TRACE_WARNING("%s: host connected, disconnect before disabling", __func__);
// unregister (and disconnect)
bta_hd_cb.disable_w4_close = TRUE;
bta_hd_sm_execute(BTA_HD_API_UNREGISTER_APP_EVT, (tBTA_HD_DATA *)p_msg);
} else {
bta_hd_api_disable();
}
break;
default:
bta_hd_sm_execute(p_msg->event, (tBTA_HD_DATA *)p_msg);
}
return (TRUE);
}
static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code)
{
switch (evt_code) {
case BTA_HD_API_REGISTER_APP_EVT:
return "BTA_HD_API_REGISTER_APP_EVT";
case BTA_HD_API_UNREGISTER_APP_EVT:
return "BTA_HD_API_UNREGISTER_APP_EVT";
case BTA_HD_API_CONNECT_EVT:
return "BTA_HD_API_CONNECT_EVT";
case BTA_HD_API_DISCONNECT_EVT:
return "BTA_HD_API_DISCONNECT_EVT";
case BTA_HD_API_ADD_DEVICE_EVT:
return "BTA_HD_API_ADD_DEVICE_EVT";
case BTA_HD_API_REMOVE_DEVICE_EVT:
return "BTA_HD_API_REMOVE_DEVICE_EVT";
case BTA_HD_API_SEND_REPORT_EVT:
return "BTA_HD_API_SEND_REPORT_EVT";
case BTA_HD_API_REPORT_ERROR_EVT:
return "BTA_HD_API_REPORT_ERROR_EVT";
case BTA_HD_API_VC_UNPLUG_EVT:
return "BTA_HD_API_VC_UNPLUG_EVT";
case BTA_HD_INT_OPEN_EVT:
return "BTA_HD_INT_OPEN_EVT";
case BTA_HD_INT_CLOSE_EVT:
return "BTA_HD_INT_CLOSE_EVT";
case BTA_HD_INT_INTR_DATA_EVT:
return "BTA_HD_INT_INTR_DATA_EVT";
case BTA_HD_INT_GET_REPORT_EVT:
return "BTA_HD_INT_GET_REPORT_EVT";
case BTA_HD_INT_SET_REPORT_EVT:
return "BTA_HD_INT_SET_REPORT_EVT";
case BTA_HD_INT_SET_PROTOCOL_EVT:
return "BTA_HD_INT_SET_PROTOCOL_EVT";
case BTA_HD_INT_VC_UNPLUG_EVT:
return "BTA_HD_INT_VC_UNPLUG_EVT";
case BTA_HD_INT_SUSPEND_EVT:
return "BTA_HD_INT_SUSPEND_EVT";
case BTA_HD_INT_EXIT_SUSPEND_EVT:
return "BTA_HD_INT_EXIT_SUSPEND_EVT";
default:
return "<unknown>";
}
}
static const char *bta_hd_state_code(tBTA_HD_STATE state_code)
{
switch (state_code) {
case BTA_HD_INIT_ST:
return "BTA_HD_INIT_ST";
case BTA_HD_IDLE_ST:
return "BTA_HD_IDLE_ST";
case BTA_HD_CONN_ST:
return "BTA_HD_CONN_ST";
case BTA_HD_TRANSIENT_TO_INIT_ST:
return "BTA_HD_TRANSIENT_TO_INIT_ST";
default:
return "<unknown>";
}
}
#if BT_HID_DEVICE_BQB_INCLUDED
tBTA_STATUS bta_hd_bqb_set_local_di_record(void)
{
tBTA_STATUS status = BTA_FAILURE;
tBTA_DI_RECORD bqb_device_info;
bqb_device_info.vendor = 0;
bqb_device_info.vendor_id_source = 0xff; // BTA_HH_VENDOR_ID_INVALID
bqb_device_info.product = 1;
bqb_device_info.version = 0;
bqb_device_info.primary_record = TRUE;
return BTA_DmSetLocalDiRecord(&bqb_device_info, &bta_hd_cb.sdp_handle);
}
#endif /* BT_HID_DEVICE_BQB_INCLUDED */
#endif /* BTA_HD_INCLUDED */
@@ -0,0 +1,168 @@
/******************************************************************************
*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains BTA HID Device internal definitions
*
******************************************************************************/
#ifndef BTA_HD_INT_H
#define BTA_HD_INT_H
#include "bta/bta_hd_api.h"
#include "bta/bta_sys.h"
#include "stack/hiddefs.h"
enum {
BTA_HD_API_REGISTER_APP_EVT = BTA_SYS_EVT_START(BTA_ID_HD),
BTA_HD_API_UNREGISTER_APP_EVT,
BTA_HD_API_CONNECT_EVT,
BTA_HD_API_DISCONNECT_EVT,
BTA_HD_API_ADD_DEVICE_EVT,
BTA_HD_API_REMOVE_DEVICE_EVT,
BTA_HD_API_SEND_REPORT_EVT,
BTA_HD_API_REPORT_ERROR_EVT,
BTA_HD_API_VC_UNPLUG_EVT,
BTA_HD_INT_OPEN_EVT,
BTA_HD_INT_CLOSE_EVT,
BTA_HD_INT_INTR_DATA_EVT,
BTA_HD_INT_GET_REPORT_EVT,
BTA_HD_INT_SET_REPORT_EVT,
BTA_HD_INT_SET_PROTOCOL_EVT,
BTA_HD_INT_VC_UNPLUG_EVT,
BTA_HD_INT_SUSPEND_EVT,
BTA_HD_INT_EXIT_SUSPEND_EVT,
/* handled outside state machine */
BTA_HD_API_ENABLE_EVT,
BTA_HD_API_DISABLE_EVT
};
typedef uint16_t tBTA_HD_INT_EVT;
#define BTA_HD_INVALID_EVT (BTA_HD_API_DISABLE_EVT + 1)
typedef struct {
BT_HDR hdr;
tBTA_HD_CBACK *p_cback;
} tBTA_HD_API_ENABLE;
#define BTA_HD_APP_NAME_LEN 50
#define BTA_HD_APP_DESCRIPTION_LEN 50
#define BTA_HD_APP_PROVIDER_LEN 50
#define BTA_HD_APP_DESCRIPTOR_LEN 2048
#define BTA_HD_STATE_DISABLED 0x00
#define BTA_HD_STATE_ENABLED 0x01
#define BTA_HD_STATE_IDLE 0x02
#define BTA_HD_STATE_CONNECTED 0x03
#define BTA_HD_STATE_DISABLING 0x04
#define BTA_HD_STATE_REMOVING 0x05
typedef struct {
BT_HDR hdr;
char name[BTA_HD_APP_NAME_LEN + 1];
char description[BTA_HD_APP_DESCRIPTION_LEN + 1];
char provider[BTA_HD_APP_PROVIDER_LEN + 1];
uint8_t subclass;
uint16_t d_len;
uint8_t d_data[BTA_HD_APP_DESCRIPTOR_LEN];
tBTA_HD_QOS_INFO in_qos;
tBTA_HD_QOS_INFO out_qos;
} tBTA_HD_REGISTER_APP;
#define BTA_HD_REPORT_LEN HID_DEV_MTU_SIZE
typedef struct {
BT_HDR hdr;
bool use_intr;
uint8_t type;
uint8_t id;
uint16_t len;
uint8_t data[BTA_HD_REPORT_LEN];
} tBTA_HD_SEND_REPORT;
typedef struct {
BT_HDR hdr;
BD_ADDR addr;
} tBTA_HD_DEVICE_CTRL;
typedef struct {
BT_HDR hdr;
uint8_t error;
} tBTA_HD_REPORT_ERR;
/* union of all event data types */
typedef union {
BT_HDR hdr;
tBTA_HD_API_ENABLE api_enable;
tBTA_HD_REGISTER_APP register_app;
tBTA_HD_SEND_REPORT send_report;
tBTA_HD_DEVICE_CTRL device_ctrl;
tBTA_HD_REPORT_ERR report_err;
} tBTA_HD_DATA;
typedef struct {
BT_HDR hdr;
BD_ADDR addr;
uint32_t data;
BT_HDR *p_data;
} tBTA_HD_CBACK_DATA;
/******************************************************************************
* Main Control Block
******************************************************************************/
typedef struct {
tBTA_HD_CBACK *p_cback;
uint32_t sdp_handle;
uint8_t trace_level;
uint8_t state;
BD_ADDR bd_addr;
bool use_report_id;
bool boot_mode;
bool vc_unplug;
bool disable_w4_close;
} tBTA_HD_CB;
#if BTA_DYNAMIC_MEMORY == FALSE
extern tBTA_HD_CB bta_hd_cb;
#else
extern tBTA_HD_CB *bta_hd_cb_ptr;
#define bta_hd_cb (*bta_hd_cb_ptr)
#endif
/*****************************************************************************
* Function prototypes
****************************************************************************/
extern bool bta_hd_hdl_event(BT_HDR *p_msg);
extern void bta_hd_api_enable(tBTA_HD_DATA *p_data);
extern void bta_hd_api_disable(void);
extern void bta_hd_register_act(tBTA_HD_DATA *p_data);
extern void bta_hd_unregister_act(tBTA_HD_DATA *p_data);
extern void bta_hd_unregister2_act(tBTA_HD_DATA *p_data);
extern void bta_hd_connect_act(tBTA_HD_DATA *p_data);
extern void bta_hd_disconnect_act(tBTA_HD_DATA *p_data);
extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data);
extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data);
extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data);
extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data);
extern void bta_hd_vc_unplug_act(tBTA_HD_DATA *p_data);
extern void bta_hd_open_act(tBTA_HD_DATA *p_data);
extern void bta_hd_close_act(tBTA_HD_DATA *p_data);
extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data);
extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data);
extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data);
extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data);
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data);
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data);
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data);
#endif