void l2c_rcv_acl_data(BT_HDR* p_msg)
{
L2CAP_TRACE_WARNING("L2CAP - l2c_rcv_acl_data");
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
//指向消息的数据域
macdbg_dmphex_kernel((const char*)p_msg->data, p_msg->len );
L2CAP_TRACE_WARNING("p_msg->offset = %x", p_msg->offset);
if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG)){
l2c_fcr_proc_pdu(p_ccb, p_msg);
L2CAP_TRACE_WARNING("p_lcb = 1q5" );
}else{
L2CAP_TRACE_WARNING("p_lcb = 1q6" );
osi_free(p_msg);
}
l2c_fcr_proc_pdu()
L2c_fcr.cc
void l2c_fcr_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf)
{
CHECK(p_ccb != NULL);
CHECK(p_buf != NULL);
uint8_t* p;
uint16_t fcs;
static void process_i_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, uint16_t ctrl_word,
bool delay_ack) {
static bool do_sar_reassembly(tL2C_CCB* p_ccb, BT_HDR* p_buf,
uint16_t ctrl_word) {
L2c_csm.cc
void l2c_csm_execute(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
if (!l2cu_is_ccb_active(p_ccb)) {
L2CAP_TRACE_WARNING("%s CCB not in use, event (%d) cannot be processed",
__func__, event);
return;
}
L2CAP_TRACE_ERROR("p_ccb->chnl_state = %x", p_ccb->chnl_state );
switch (p_ccb->chnl_state) {
case CST_CLOSED:
l2c_csm_closed(p_ccb, event, p_data);
break;
case CST_ORIG_W4_SEC_COMP:
l2c_csm_orig_w4_sec_comp(p_ccb, event, p_data);
break;
case CST_TERM_W4_SEC_COMP:
l2c_csm_term_w4_sec_comp(p_ccb, event, p_data);
break;
case CST_W4_L2CAP_CONNECT_RSP:
l2c_csm_w4_l2cap_connect_rsp(p_ccb, event, p_data);
break;
case CST_W4_L2CA_CONNECT_RSP:
l2c_csm_w4_l2ca_connect_rsp(p_ccb, event, p_data);
break;
case CST_CONFIG:
l2c_csm_config(p_ccb, event, p_data);
break;
case CST_OPEN:
l2c_csm_open(p_ccb, event, p_data);
break;
case CST_W4_L2CAP_DISCONNECT_RSP:
l2c_csm_w4_l2cap_disconnect_rsp(p_ccb, event, p_data);
break;
case CST_W4_L2CA_DISCONNECT_RSP:
l2c_csm_w4_l2ca_disconnect_rsp(p_ccb, event, p_data);
break;
default:
L2CAP_TRACE_DEBUG("Unhandled event! event = %d", event);
break;
}
}
static void l2c_csm_open(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
uint16_t local_cid = p_ccb->local_cid;
tL2CAP_CFG_INFO* p_cfg;
tL2C_CHNL_STATE tempstate;
uint8_t tempcfgdone;
uint8_t cfg_result;
uint16_t* credit;
L2CAP_TRACE_ERROR("L2CAP - LCID: 0x%04x st: OPEN evt: %s", p_ccb->local_cid,
l2c_csm_get_event_name(event));
switch (event) {
case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
L2CAP_TRACE_API(
"L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
p_ccb->local_cid);
l2cu_release_ccb(p_ccb);
if (p_ccb->p_rcb)
(*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, false);
break;
case L2CEVT_LP_QOS_VIOLATION_IND: /* QOS violation */
/* Tell upper layer. If service guaranteed, then clear the channel */
if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)
(*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(
p_ccb->p_lcb->remote_bd_addr);
break;
case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
p_cfg = (tL2CAP_CFG_INFO*)p_data;
tempstate = p_ccb->chnl_state;
tempcfgdone = p_ccb->config_done;
p_ccb->chnl_state = CST_CONFIG;
p_ccb->config_done &= ~IB_CFG_DONE;
alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
l2c_ccb_timer_timeout, p_ccb);
cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
if (cfg_result == L2CAP_PEER_CFG_OK) {
(*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
}
/* Error in config parameters: reset state and config flag */
else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE) {
alarm_cancel(p_ccb->l2c_ccb_timer);
p_ccb->chnl_state = tempstate;
p_ccb->config_done = tempcfgdone;
l2cu_send_peer_config_rsp(p_ccb, p_cfg);
} else /* L2CAP_PEER_CFG_DISCONNECT */
{
/* Disconnect if channels are incompatible
* Note this should not occur if reconfigure
* since this should have never passed original config.
*/
l2cu_disconnect_chnl(p_ccb);
}
break;
case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
/* Make sure we are not in sniff mode */
{
tBTM_PM_PWR_MD settings;
memset((void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
&settings);
}
}
p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
l2c_ccb_timer_timeout, p_ccb);
L2CAP_TRACE_API(
"L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed",
p_ccb->local_cid);
(*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true);
break;
case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
L2CAP_TRACE_ERROR("L2gh.0" );
if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb)){
L2CAP_TRACE_ERROR("L2gh.1" );
(*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR*)p_data);
//gap_data_ind
}
break;
case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
/* Make sure we are not in sniff mode */
{
tBTM_PM_PWR_MD settings;
memset((void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
&settings);
}
}
if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
l2cble_send_peer_disc_req(p_ccb);
else
l2cu_send_peer_disc_req(p_ccb);
p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
l2c_ccb_timer_timeout, p_ccb);
break;
case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
break;
case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
p_ccb->chnl_state = CST_CONFIG;
p_ccb->config_done &= ~CFG_DONE_MASK;
l2cu_process_our_cfg_req(p_ccb, (tL2CAP_CFG_INFO*)p_data);
l2cu_send_peer_config_req(p_ccb, (tL2CAP_CFG_INFO*)p_data);
alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
l2c_ccb_timer_timeout, p_ccb);
break;
case L2CEVT_TIMEOUT:
/* Process the monitor/retransmission time-outs in flow control/retrans
* mode */
if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
l2c_fcr_proc_tout(p_ccb);
break;
case L2CEVT_ACK_TIMEOUT:
l2c_fcr_proc_ack_tout(p_ccb);
break;
case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
L2CAP_TRACE_DEBUG("%s Sending credit", __func__);
credit = (uint16_t*)p_data;
l2cble_send_flow_control_credit(p_ccb, *credit);
break;
case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
credit = (uint16_t*)p_data;
L2CAP_TRACE_DEBUG("%s Credits received %d", __func__, *credit);
if ((p_ccb->peer_conn_cfg.credits + *credit) > L2CAP_LE_CREDIT_MAX) {
/* we have received credits more than max coc credits,
* so disconnecting the Le Coc Channel
*/
l2cble_send_peer_disc_req(p_ccb);
} else {
p_ccb->peer_conn_cfg.credits += *credit;
tL2CA_CREDITS_RECEIVED_CB* cr_cb =
p_ccb->p_rcb->api.pL2CA_CreditsReceived_Cb;
if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE && (cr_cb)) {
(*cr_cb)(p_ccb->local_cid, *credit, p_ccb->peer_conn_cfg.credits);
}
l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
}
break;
}
}
Gap_conn.cc
/*******************************************************************************
*
* Function gap_data_ind
*
* Description This function is called when data is received from L2CAP.
*
* Returns void
*
******************************************************************************/
static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
tGAP_CCB* p_ccb;
DVLOG(1) << StringPrintf("GAP_CONN - gap_data_ind Rcvd L2CAP disc, CID: ");
LOG(WARNING) << "******* gap_data_ind";
/* Find CCB based on CID */
p_ccb = gap_find_ccb_by_cid(l2cap_cid);
if (p_ccb == NULL) {
osi_free(p_msg);
return;
}
if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
fixed_queue_enqueue(p_ccb->rx_queue, p_msg);
p_ccb->rx_queue_size += p_msg->len;
/*
DVLOG(1) << StringPrintf ("gap_data_ind - rx_queue_size=%d, msg len=%d",
p_ccb->rx_queue_size, p_msg->len);
*/
//bta_jv_l2cap_server_cback
p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL, nullptr);
} else {
osi_free(p_msg);
}
}
/*******************************************************************************
*
* Function bta_jv_l2cap_server_cback
*
* Description handles the l2cap server callback
*
* Returns void
*
******************************************************************************/
static void bta_jv_l2cap_server_cback(uint16_t gap_handle, uint16_t event,
tGAP_CB_DATA* data) {
tBTA_JV_L2C_CB* p_cb = &bta_jv_cb.l2c_cb[gap_handle];
tBTA_JV evt_data;
tBTA_JV_L2CAP_CBACK* p_cback;
uint32_t socket_id;
if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) return;
VLOG(2) << __func__ << ": gap_handle2=" << gap_handle
<< ", evt=" << loghex(event);
VLOG(1) << __func__ << ": gap_handle1=" << gap_handle
<< ", evt=" << loghex(event);
VLOG(0) << __func__ << ": gap_handle0=" << gap_handle
<< ", evt=" << loghex(event);
evt_data.l2c_open.status = BTA_JV_SUCCESS;
evt_data.l2c_open.handle = gap_handle;
LOG(INFO) << "GapCallback event " << event;
switch (event) {
case GAP_EVT_CONN_OPENED:
evt_data.l2c_open.rem_bda = *GAP_ConnGetRemoteAddr(gap_handle);
evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
p_cb->state = BTA_JV_ST_SR_OPEN;
p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->l2cap_socket_id);
break;
case GAP_EVT_CONN_CLOSED:
evt_data.l2c_close.async = true;
evt_data.l2c_close.handle = p_cb->handle;
p_cback = p_cb->p_cback;
socket_id = p_cb->l2cap_socket_id;
evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb);
p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, socket_id);
break;
case GAP_EVT_CONN_DATA_AVAIL:
evt_data.data_ind.handle = gap_handle;
/* Reset idle timer to avoid requesting sniff mode while receiving data */
bta_jv_pm_conn_busy(p_cb->p_pm_cb);
p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data,
p_cb->l2cap_socket_id);
//btsock_l2cap_cbk
bta_jv_pm_conn_idle(p_cb->p_pm_cb);
break;
case GAP_EVT_TX_EMPTY:
bta_jv_pm_conn_idle(p_cb->p_pm_cb);
break;
case GAP_EVT_CONN_CONGESTED:
case GAP_EVT_CONN_UNCONGESTED:
p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? true : false;
evt_data.l2c_cong.cong = p_cb->cong;
p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->l2cap_socket_id);
break;
default:
break;
}
}
static void btsock_l2cap_cbk(tBTA_JV_EVT event, tBTA_JV* p_data,
uint32_t l2cap_socket_id) {
APPL_TRACE_WARNING("btsock_l2cap_cbk: event: %d", event);
switch (event) {
case BTA_JV_L2CAP_START_EVT:
on_srv_l2cap_listen_started(&p_data->l2c_start, l2cap_socket_id);
break;
static void on_l2cap_data_ind(tBTA_JV* evt, uint32_t id) {
l2cap_socket* sock;
int app_uid = -1;
uint32_t bytes_read = 0;
if (packet_put_tail_l(sock, buffer.data(), count)) {
bytes_read = count;
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
SOCK_THREAD_FD_WR, sock->id);
Btif_sock_l2cap.cc
接收的数据包放入单链表的尾部
/* makes a copy of the data, returns true on success */
static char packet_put_tail_l(l2cap_socket* sock, const void* data,
uint32_t len) {
if (sock->bytes_buffered >= L2CAP_MAX_RX_BUFFER) {
LOG(ERROR) << __func__ << ": buffer overflow";
return false;
}
struct packet* p = packet_alloc((const uint8_t*)data, len);
p->next = NULL;
p->prev = sock->last_packet;
sock->last_packet = p;
if (p->prev)
p->prev->next = p;
else
sock->first_packet = p;
sock->bytes_buffered += len;
return true;
}
下一步应该是从此链表中取出数据包
通过socket发送给java端的服务端进程