/******************************************************************************* ** ** Function gap_release_ccb ** ** Description This function releases a CCB. ** ** Returns void ** *******************************************************************************/ static void gap_release_ccb (tGAP_CCB *p_ccb) { UINT16 xx; UINT16 psm = p_ccb->psm; UINT8 service_id = p_ccb->service_id; /* Drop any buffers we may be holding */ p_ccb->rx_queue_size = 0; while (p_ccb->rx_queue._p_first) GKI_freebuf (GKI_dequeue (&p_ccb->rx_queue)); while (p_ccb->tx_queue._p_first) GKI_freebuf (GKI_dequeue (&p_ccb->tx_queue)); p_ccb->con_state = GAP_CCB_STATE_IDLE; /* If no-one else is using the PSM, deregister from L2CAP */ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) { if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm)) return; } /* Free the security record for this PSM */ BTM_SecClrService(service_id); L2CA_DEREGISTER (psm); }
/******************************************************************************* ** ** Function avdt_ccb_clear_ccb ** ** Description This function clears out certain buffers, queues, and ** other data elements of a ccb. ** ** ** Returns void. ** *******************************************************************************/ static void avdt_ccb_clear_ccb(tAVDT_CCB *p_ccb) { BT_HDR *p_buf; /* clear certain ccb variables */ p_ccb->cong = FALSE; p_ccb->ret_count = 0; /* free message being fragmented */ if (p_ccb->p_curr_msg != NULL) { GKI_freebuf(p_ccb->p_curr_msg); p_ccb->p_curr_msg = NULL; } /* free message being reassembled */ if (p_ccb->p_rx_msg != NULL) { GKI_freebuf(p_ccb->p_rx_msg); p_ccb->p_rx_msg = NULL; } /* clear out response queue */ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_ccb->rsp_q)) != NULL) { GKI_freebuf(p_buf); } }
/******************************************************************************* ** ** Function nfc_hal_send_nci_msg_to_nfc_task ** ** Description This function is called to send nci message to nfc task ** ** Returns void ** *******************************************************************************/ void nfc_hal_send_nci_msg_to_nfc_task (NFC_HDR * p_msg) { #ifdef SWISSKNIFEVERSION if(!shortCircuit && !sent){ #ifdef NFC_HAL_SHARED_GKI /* Using shared NFC/HAL GKI resources - send message buffer directly to NFC_TASK for processing */ p_msg->event = BT_EVT_TO_NFC_NCI; GKI_send_msg (NFC_TASK, NFC_MBOX_ID, p_msg); #else /* Send NCI message to the stack */ nfc_hal_cb.p_data_cback (p_msg->len, (UINT8 *) ((p_msg + 1) + p_msg->offset)); GKI_freebuf(p_msg); #endif } else{ GKI_freebuf(p_msg); } #else #ifdef NFC_HAL_SHARED_GKI /* Using shared NFC/HAL GKI resources - send message buffer directly to NFC_TASK for processing */ p_msg->event = BT_EVT_TO_NFC_NCI; GKI_send_msg (NFC_TASK, NFC_MBOX_ID, p_msg); #else /* Send NCI message to the stack */ nfc_hal_cb.p_data_cback (p_msg->len, (UINT8 *) ((p_msg + 1) + p_msg->offset)); GKI_freebuf(p_msg); #endif #endif }
/******************************************************************************* ** ** Function nfc_hal_main_handle_terminate ** ** Description Handle NFI transport shutdown ** ** Returns nothing ** *******************************************************************************/ static void nfc_hal_main_handle_terminate (void) { NFC_HDR *p_msg; /* dequeue and free buffer */ if (nfc_hal_cb.ncit_cb.p_pend_cmd != NULL) { GKI_freebuf (nfc_hal_cb.ncit_cb.p_pend_cmd); nfc_hal_cb.ncit_cb.p_pend_cmd = NULL; } /* Free unsent nfc rx buffer */ if (nfc_hal_cb.ncit_cb.p_rcv_msg) { GKI_freebuf (nfc_hal_cb.ncit_cb.p_rcv_msg); nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; } /* Free buffer for pending fragmented response/notification */ if (nfc_hal_cb.ncit_cb.p_frag_msg) { GKI_freebuf (nfc_hal_cb.ncit_cb.p_frag_msg); nfc_hal_cb.ncit_cb.p_frag_msg = NULL; } /* Free buffers in the tx mbox */ while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL) { GKI_freebuf (p_msg); } /* notify closing transport */ nfc_hal_dm_shutting_down_nfcc (); }
/******************************************************************************* ** ** Function btusb_lite_hci_acl_send ** ** Description Send an ACL packet to HCI ** ** Returns Void ** *******************************************************************************/ int btusb_lite_hci_acl_send(struct btusb *p_dev, BT_HDR *p_msg, UINT16 con_hdl) { UINT8 *p_data; /* Sanity */ if (p_msg->offset < BTUSB_LITE_HCI_ACL_HDR_SIZE) { BTUSB_ERR("offset too small=%d\n", p_msg->offset); GKI_freebuf(p_msg); /* Free this ACL buffer */ return -1; } /* Decrement offset to add headers */ p_msg->offset -= BTUSB_LITE_HCI_ACL_HDR_SIZE; /* Get address of the HCI Header */ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset; /* Write L2CAP Header (length field is SBC Frames + RTP/A2DP/Media Header) */ p_data = btusb_lite_hci_write_acl_header(p_data, con_hdl, p_msg->len); /* Increment length */ p_msg->len += BTUSB_LITE_HCI_ACL_HDR_SIZE; p_data = (UINT8 *)(p_msg + 1) + p_msg->offset; btusb_submit_acl(p_dev, p_data, p_msg->len); GKI_freebuf(p_msg); /* Free this ACL buffer */ return 0; }
/******************************************************************************* ** ** Function gap_data_ind ** ** Description This function is called when data is received from L2CAP. ** ** Returns void ** *******************************************************************************/ static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) { tGAP_CCB *p_ccb; /* Find CCB based on CID */ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) { GKI_freebuf (p_msg); return; } if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) { GKI_enqueue (&p_ccb->rx_queue, p_msg); p_ccb->rx_queue_size += p_msg->len; /* GAP_TRACE_EVENT ("gap_data_ind - rx_queue_size=%d, msg len=%d", p_ccb->rx_queue_size, p_msg->len); */ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL); } else { GKI_freebuf (p_msg); } }
int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) { pthread_mutex_lock(&slot_lock); int ret = 0; uint32_t id = (uintptr_t)user_data; rfc_slot_t *slot = find_rfc_slot_by_id(id); if (!slot) goto out; if (list_is_empty(slot->incoming_queue)) { switch (send_data_to_app(slot->fd, p_buf)) { case SENT_NONE: case SENT_PARTIAL: list_append(slot->incoming_queue, p_buf); btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_WR, slot->id); break; case SENT_ALL: GKI_freebuf(p_buf); ret = 1; // Enable data flow. break; case SENT_FAILED: GKI_freebuf(p_buf); cleanup_rfc_slot(slot); break; } } else { list_append(slot->incoming_queue, p_buf); } out:; pthread_mutex_unlock(&slot_lock); return ret; // Return 0 to disable data flow. }
/******************************************************************************* ** ** Function rfc_port_sm_sabme_wait_ua ** ** Description This function handles events when SABME on the DLC was ** sent and SM is waiting for UA or DM. ** ** Returns void ** *******************************************************************************/ void rfc_port_sm_sabme_wait_ua (tPORT *p_port, UINT16 event, void *p_data) { switch (event) { case RFC_EVENT_OPEN: case RFC_EVENT_ESTABLISH_RSP: RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; case RFC_EVENT_CLOSE: rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT); rfc_send_disc (p_port->rfc.p_mcb, p_port->dlci); p_port->rfc.expected_rsp = 0; p_port->rfc.state = RFC_STATE_DISC_WAIT_UA; return; case RFC_EVENT_CLEAR: rfc_port_closed (p_port); return; case RFC_EVENT_DATA: GKI_freebuf (p_data); break; case RFC_EVENT_UA: rfc_port_timer_stop (p_port); p_port->rfc.state = RFC_STATE_OPENED; PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_SUCCESS); return; case RFC_EVENT_DM: p_port->rfc.p_mcb->is_disc_initiator = TRUE; PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR); rfc_port_closed (p_port); return; case RFC_EVENT_DISC: rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR); rfc_port_closed (p_port); return; case RFC_EVENT_SABME: /* Continue to wait for the UA the SABME this side sent */ rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); return; case RFC_EVENT_UIH: GKI_freebuf (p_data); return; case RFC_EVENT_TIMEOUT: p_port->rfc.state = RFC_STATE_CLOSED; PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR); return; } RFCOMM_TRACE_WARNING ("Port state sabme_wait_ua Event ignored %d", event); }
/******************************************************************************* ** ** Function gatt_enc_cmpl_cback ** ** Description link encryption complete callback. ** ** Returns ** *******************************************************************************/ void gatt_enc_cmpl_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, tBTM_STATUS result) { tGATT_TCB *p_tcb; UINT8 sec_flag; BOOLEAN status = FALSE; tGATT_PENDING_ENC_CLCB *p_buf; UINT16 count; UNUSED(p_ref_data); GATT_TRACE_DEBUG("gatt_enc_cmpl_cback"); if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, transport)) != NULL) { if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) return; if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL) { if (result == BTM_SUCCESS) { if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM ) { BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, transport); if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) { status = TRUE; } } else { status = TRUE; } } gatt_sec_check_complete(status , p_buf->p_clcb, p_tcb->sec_act); GKI_freebuf(p_buf); /* start all other pending operation in queue */ count = p_tcb->pending_enc_clcb.count; for (; count > 0; count --) { if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL) { gatt_security_check_start(p_buf->p_clcb); GKI_freebuf(p_buf); } else break; } } else { GATT_TRACE_ERROR("Unknown operation encryption completed"); } } else { GATT_TRACE_ERROR("enc callback for unknown bd_addr"); } }
/******************************************************************************* ** ** Function rfc_port_sm_state_closed ** ** Description This function handles events when the port is in ** CLOSED state. This state exists when port is ** being initially established. ** ** Returns void ** *******************************************************************************/ void rfc_port_sm_state_closed (tPORT *p_port, UINT16 event, void *p_data) { switch (event) { case RFC_EVENT_OPEN: p_port->rfc.state = RFC_STATE_ORIG_WAIT_SEC_CHECK; btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, TRUE, BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2), &rfc_sec_check_complete, p_port); return; case RFC_EVENT_CLOSE: break; case RFC_EVENT_CLEAR: return; case RFC_EVENT_DATA: GKI_freebuf (p_data); break; case RFC_EVENT_SABME: /* make sure the multiplexer disconnect timer is not running (reconnect case) */ rfc_timer_stop(p_port->rfc.p_mcb ); /* Open will be continued after security checks are passed */ p_port->rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK; btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, FALSE, BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2), &rfc_sec_check_complete, p_port); return; case RFC_EVENT_UA: return; case RFC_EVENT_DM: rfc_port_closed (p_port); return; case RFC_EVENT_UIH: GKI_freebuf (p_data); rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE); return; case RFC_EVENT_DISC: rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE); return; case RFC_EVENT_TIMEOUT: Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ; RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; } RFCOMM_TRACE_WARNING ("Port state closed Event ignored %d", event); return; }
/******************************************************************************* ** ** Function bta_pan_tx_path ** ** Description Handle the TX data path (data sent from BTA to the phone). ** ** ** Returns void ** *******************************************************************************/ void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) { BT_HDR * p_buf; /* if data path configured for tx pull */ if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PULL) { bta_pan_pm_conn_busy(p_scb); /* call application callout function for tx path */ bta_pan_co_tx_path(p_scb->handle, p_scb->app_id); /* free data that exceeds queue level */ while(p_scb->data_queue.count > bta_pan_cb.q_level) GKI_freebuf(GKI_dequeue(&p_scb->data_queue)); bta_pan_pm_conn_idle(p_scb); } /* if configured for zero copy push */ else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF) { /* if app can accept data */ if (p_scb->app_flow_enable == TRUE) { /* read data from the queue */ if ((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) { /* send data to application */ bta_pan_co_tx_writebuf(p_scb->handle, p_scb->app_id, ((tBTA_PAN_DATA_PARAMS *)p_buf)->src, ((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol, p_buf, ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext, ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward); } /* free data that exceeds queue level */ while(p_scb->data_queue.count > bta_pan_cb.q_level) GKI_freebuf(GKI_dequeue(&p_scb->data_queue)); /* if there is more data to be passed to upper layer */ if(p_scb->data_queue.count) { if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) { p_buf->layer_specific = p_scb->handle; p_buf->event = BTA_PAN_RX_FROM_BNEP_READY_EVT; bta_sys_sendmsg(p_buf); } } } } }
/******************************************************************************* ** ** Function bta_pan_data_buf_ind_cback ** ** Description data indication callback from pan profile ** ** ** Returns void ** *******************************************************************************/ static void bta_pan_data_buf_ind_cback(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf, BOOLEAN ext, BOOLEAN forward) { tBTA_PAN_SCB *p_scb; BT_HDR * p_event; BT_HDR *p_new_buf; if ( sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset ) { /* offset smaller than data structure in front of actual data */ p_new_buf = (BT_HDR *)GKI_getpoolbuf( PAN_POOL_ID ); if(!p_new_buf) { APPL_TRACE_WARNING0("Cannot get a PAN GKI buffer"); GKI_freebuf( p_buf ); return; } else { memcpy( (UINT8 *)(p_new_buf+1)+sizeof(tBTA_PAN_DATA_PARAMS), (UINT8 *)(p_buf+1)+p_buf->offset, p_buf->len ); p_new_buf->len = p_buf->len; p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS); GKI_freebuf( p_buf ); } } else { p_new_buf = p_buf; } /* copy params into the space before the data */ bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->src, src); bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->dst, dst); ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->protocol = protocol; ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->ext = ext; ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->forward = forward; if((p_scb = bta_pan_scb_by_handle(handle)) == NULL) { GKI_freebuf( p_new_buf ); return; } GKI_enqueue(&p_scb->data_queue, p_new_buf); if ((p_event = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) { p_event->layer_specific = handle; p_event->event = BTA_PAN_RX_FROM_BNEP_READY_EVT; bta_sys_sendmsg(p_event); } }
/******************************************************************************* ** ** Function smp_br_data_received ** ** Description This function is called when data is received from L2CAP on ** SMP BR channel. ** ** Returns void ** *******************************************************************************/ static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf) { tSMP_CB *p_cb = &smp_cb; UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; UINT8 cmd ; SMP_TRACE_EVENT ("SMDBG l2c %s", __func__); STREAM_TO_UINT8(cmd, p); /* sanity check */ if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd)) { SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd); GKI_freebuf(p_buf); return; } /* reject the pairing request if there is an on-going SMP pairing */ if (SMP_OPCODE_PAIRING_REQ == cmd) { if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE)) { p_cb->role = HCI_ROLE_SLAVE; p_cb->smp_over_br = TRUE; memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN); } else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN)) { GKI_freebuf (p_buf); smp_reject_unexpected_pairing_command(bd_addr); return; } /* else, out of state pairing request received, passed into State Machine */ } if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0) { btu_stop_timer (&p_cb->rsp_timer_ent); btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD, SMP_WAIT_FOR_RSP_TOUT); p_cb->rcvd_cmd_code = cmd; p_cb->rcvd_cmd_len = (UINT8) p_buf->len; smp_br_state_machine_event(p_cb, cmd, p); } GKI_freebuf (p_buf); }
/******************************************************************************* ** ** Function GAP_ConnBTWrite ** ** Description Bluetooth Aware applications can call this function to write data. ** ** Parameters: handle - Handle of the connection returned in the Open ** p_buf - pointer to address of buffer with data, ** ** Returns BT_PASS - data read ** GAP_ERR_BAD_HANDLE - invalid handle ** GAP_ERR_BAD_STATE - connection not established ** GAP_INVALID_BUF_OFFSET - buffer offset is invalid *******************************************************************************/ UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf) { tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle); if (!p_ccb) { GKI_freebuf (p_buf); return (GAP_ERR_BAD_HANDLE); } if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) { GKI_freebuf (p_buf); return (GAP_ERR_BAD_STATE); } if (p_buf->offset < L2CAP_MIN_OFFSET) { GKI_freebuf (p_buf); return (GAP_ERR_BUF_OFFSET); } GKI_enqueue (&p_ccb->tx_queue, p_buf); if (p_ccb->is_congested) { return (BT_PASS); } /* Send the buffer through L2CAP */ #if (GAP_CONN_POST_EVT_INCLUDED == TRUE) gap_send_event (gap_handle); #else while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL) { UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf); if (status == L2CAP_DW_CONGESTED) { p_ccb->is_congested = TRUE; break; } else if (status != L2CAP_DW_SUCCESS) return (GAP_ERR_BAD_STATE); } #endif return (BT_PASS); }
/******************************************************************************* ** ** Function nfc_hal_main_open_transport ** ** Description Open transport and prepare for new incoming message; ** ** Returns nothing ** *******************************************************************************/ static void nfc_hal_main_open_transport (void) { tUSERIAL_OPEN_CFG open_cfg; /* Initialize control block */ nfc_hal_cb.ncit_cb.rcv_state = NFC_HAL_RCV_IDLE_ST; /* to process packet type */ if (nfc_hal_cb.ncit_cb.p_rcv_msg) { GKI_freebuf (nfc_hal_cb.ncit_cb.p_rcv_msg); nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; } /* open transport */ open_cfg.fmt = (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1); open_cfg.baud = nfc_hal_trans_cfg.userial_baud; open_cfg.fc = nfc_hal_trans_cfg.userial_fc; open_cfg.buf = USERIAL_BUF_BYTE; USERIAL_Open (USERIAL_NFC_PORT, &open_cfg, nfc_hal_main_userial_cback); { /* Wait for NFCC to enable - Core reset notification */ NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_NFCC_ENABLE); /* NFCC Enable timeout */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_NFCC_ENABLE, ((p_nfc_hal_cfg->nfc_hal_nfcc_enable_timeout)*QUICK_TIMER_TICKS_PER_SEC)/1000); } }
/******************************************************************************* ** ** Function HID_HostWriteDev ** ** Description This function is called when the host has a report to send. ** ** report_id: is only used on GET_REPORT transaction if is specified. ** only valid when it's a non-zero value. ** ** Returns void ** *******************************************************************************/ tHID_STATUS HID_HostWriteDev( UINT8 dev_handle, UINT8 t_type, UINT8 param, UINT16 data, UINT8 report_id, BT_HDR *pbuf ) { tHID_STATUS status = HID_SUCCESS; if( !hh_cb.reg_flag ) { HIDH_TRACE_ERROR0("HID_ERR_NOT_REGISTERED"); status = HID_ERR_NOT_REGISTERED; } if( (dev_handle >= HID_HOST_MAX_DEVICES) || (!hh_cb.devices[dev_handle].in_use) ) { HIDH_TRACE_ERROR0("HID_ERR_INVALID_PARAM"); status = HID_ERR_INVALID_PARAM; } if( hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED ) { HIDH_TRACE_ERROR1("HID_ERR_NO_CONNECTION dev_handle %d", dev_handle); status = HID_ERR_NO_CONNECTION; } if (status != HID_SUCCESS) { if (pbuf) GKI_freebuf ((void *)pbuf); } else status = hidh_conn_snd_data( dev_handle, t_type, param, data, report_id, pbuf ) ; return status; }
/******************************************************************************* ** ** Function btm_ble_dequeue_direct_conn_req ** ** Description This function dequeues the direct connection request ** ** Returns None. ** *******************************************************************************/ void btm_ble_dequeue_direct_conn_req(BD_ADDR rem_bda) { tBTM_BLE_CONN_REQ *p_req = NULL; tL2C_LCB *p_lcb; if(btm_cb.ble_ctr_cb.conn_pending_q.count) { p_req = (tBTM_BLE_CONN_REQ*)GKI_getfirst(&btm_cb.ble_ctr_cb.conn_pending_q); } while(p_req != NULL) { p_lcb = (tL2C_LCB *)p_req->p_param; if((p_lcb != NULL) && (p_lcb->in_use)) { //If BD address matches if(!memcmp (rem_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN)) { GKI_remove_from_queue(&btm_cb.ble_ctr_cb.conn_pending_q, p_req); l2cu_release_lcb ((tL2C_LCB *)p_req->p_param); GKI_freebuf((void *)p_req); break; } } p_req = (tBTM_BLE_CONN_REQ*)GKI_getnext(p_req); } }
/******************************************************************************* ** ** Function cmac_aes_cleanup ** ** Description clean up function for AES_CMAC algorithm. ** ** Returns void ** *******************************************************************************/ static void cmac_aes_cleanup(void) { if (cmac_cb.text != NULL) { GKI_freebuf(cmac_cb.text); } memset(&cmac_cb, 0, sizeof(tCMAC_CB)); }
/******************************************************************************* ** ** Function bta_pan_disable ** ** Description ** ** ** ** Returns void ** *******************************************************************************/ void bta_pan_disable(void) { BT_HDR *p_buf; tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0]; UINT8 i; /* close all connections */ PAN_SetRole (0, NULL, NULL, NULL, NULL); #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE) bta_sys_remove_uuid(UUID_SERVCLASS_NAP); bta_sys_remove_uuid(UUID_SERVCLASS_GN); bta_sys_remove_uuid(UUID_SERVCLASS_PANU); #endif /* free all queued up data buffers */ for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) { if (p_scb->in_use) { while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) GKI_freebuf(p_buf); bta_pan_co_close(p_scb->handle, p_scb->app_id); } } PAN_Deregister(); }
/******************************************************************************* ** ** Function avdt_ad_tc_data_ind ** ** Description This function is called by the L2CAP interface layer when ** incoming data is received from L2CAP. It looks up the CCB ** or SCB for the channel and routes the data accordingly. ** ** ** Returns Nothing. ** *******************************************************************************/ void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf) { tAVDT_CCB *p_ccb; tAVDT_SCB *p_scb; /* store type (media, recovery, reporting) */ p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid); /* if signaling channel, handle control message */ if (p_tbl->tcid == 0) { p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); avdt_msg_ind(p_ccb, p_buf); } /* if media or other channel, send event to scb */ else { p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl); if (p_scb != NULL) { avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf); } else { GKI_freebuf(p_buf); AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed"); } } }
/******************************************************************************* ** ** Function avct_lcb_dealloc ** ** Description Deallocate a link control block. ** ** ** Returns void. ** *******************************************************************************/ void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data) { tAVCT_CCB *p_ccb = &avct_cb.ccb[0]; BOOLEAN found = FALSE; int i; UNUSED(p_data); AVCT_TRACE_DEBUG("avct_lcb_dealloc %d", p_lcb->allocated); for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { /* if ccb allocated and */ if (p_ccb->allocated) { if (p_ccb->p_lcb == p_lcb) { AVCT_TRACE_DEBUG("avct_lcb_dealloc used by ccb: %d", i); found = TRUE; break; } } } if (!found) { AVCT_TRACE_DEBUG("avct_lcb_dealloc now"); /* clear reassembled msg buffer if in use */ if (p_lcb->p_rx_msg != NULL) { GKI_freebuf(p_lcb->p_rx_msg); } memset(p_lcb, 0, sizeof(tAVCT_LCB)); } }
/******************************************************************************* ** ** Function llcp_sdp_proc_deactivation ** ** Description Report SDP failure for any pending request because of deactivation ** ** ** Returns void ** *******************************************************************************/ void llcp_sdp_proc_deactivation (void) { UINT8 i; LLCP_TRACE_DEBUG0 ("llcp_sdp_proc_deactivation ()"); for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++) { if (llcp_cb.sdp_cb.transac[i].p_cback) { (*llcp_cb.sdp_cb.transac[i].p_cback) (llcp_cb.sdp_cb.transac[i].tid, 0x00); llcp_cb.sdp_cb.transac[i].p_cback = NULL; } } /* free any pending SNL PDU */ if (llcp_cb.sdp_cb.p_snl) { GKI_freebuf (llcp_cb.sdp_cb.p_snl); llcp_cb.sdp_cb.p_snl = NULL; } llcp_cb.sdp_cb.next_tid = 0; #if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE) llcp_cb.dta_snl_resp = FALSE; #endif }
/******************************************************************************* ** ** Function llcp_sdp_proc_deactivation ** ** Description Report SDP failure for any pending request because of deactivation ** ** ** Returns void ** *******************************************************************************/ void llcp_sdp_proc_deactivation (void) { UINT8 i; LLCP_TRACE_DEBUG0 ("llcp_sdp_proc_deactivation ()"); for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++) { if (llcp_cb.sdp_cb.transac[i].p_cback) { (*llcp_cb.sdp_cb.transac[i].p_cback) (llcp_cb.sdp_cb.transac[i].tid, 0x00); llcp_cb.sdp_cb.transac[i].p_cback = NULL; } } /* free any pending SNL PDU */ if (llcp_cb.sdp_cb.p_snl) { GKI_freebuf (llcp_cb.sdp_cb.p_snl); llcp_cb.sdp_cb.p_snl = NULL; } llcp_cb.sdp_cb.next_tid = 0; }
/******************************************************************************* ** ** Function avdt_ccb_cmd_fail ** ** Description This function is called when there is a response timeout. ** The currently pending command is freed and we fake a ** reject message back to ourselves. ** ** ** Returns void. ** *******************************************************************************/ void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { tAVDT_MSG msg; UINT8 evt; tAVDT_SCB *p_scb; if (p_ccb->p_curr_cmd != NULL) { /* set up data */ msg.hdr.err_code = p_data->err_code; msg.hdr.err_param = 0; msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb); /* pretend that we received a rej message */ evt = avdt_msg_rej_2_evt[p_ccb->p_curr_cmd->event - 1]; if (evt & AVDT_CCB_MKR) { avdt_ccb_event(p_ccb, (UINT8) (evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg); } else { /* we get the scb out of the current cmd */ p_scb = avdt_scb_by_hdl(*((UINT8 *)(p_ccb->p_curr_cmd + 1))); if (p_scb != NULL) { avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg); } } GKI_freebuf(p_ccb->p_curr_cmd); p_ccb->p_curr_cmd = NULL; } }
/******************************************************************************* ** ** Function sdp_data_ind ** ** Description This function is called when data is received from L2CAP. ** if we are the originator of the connection, we are the SDP ** client, and the received message is queued up for the client. ** ** If we are the destination of the connection, we are the SDP ** server, so the message is passed to the server processing ** function. ** ** Returns void ** *******************************************************************************/ static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) { tCONN_CB *p_ccb; /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) != NULL) { if (p_ccb->con_state == SDP_STATE_CONNECTED) { if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) sdp_disc_server_rsp (p_ccb, p_msg); else sdp_server_handle_client_req (p_ccb, p_msg); } else { SDP_TRACE_WARNING2 ("SDP - Ignored L2CAP data while in state: %d, CID: 0x%x", p_ccb->con_state, l2cap_cid); } } else { SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid); } GKI_freebuf (p_msg); }
/******************************************************************************* ** ** Function gatt_notify_enc_cmpl ** ** Description link encryption complete notification for all encryption process ** initiated outside GATT. ** ** Returns ** *******************************************************************************/ void gatt_notify_enc_cmpl(BD_ADDR bd_addr) { tGATT_TCB *p_tcb; tGATT_PENDING_ENC_CLCB *p_buf; UINT16 count; UINT8 i = 0; if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE)) != NULL) { for (i = 0; i < GATT_MAX_APPS; i++) { if (gatt_cb.cl_rcb[i].in_use && gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb) { (*gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)(gatt_cb.cl_rcb[i].gatt_if, bd_addr); } } if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) { gatt_set_sec_act(p_tcb, GATT_SEC_NONE); count = GKI_queue_length(&p_tcb->pending_enc_clcb); for (; count > 0; count --) { if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL) { gatt_security_check_start(p_buf->p_clcb); GKI_freebuf(p_buf); } else { break; } } } } else { GATT_TRACE_DEBUG("notify GATT for encryption completion of unknown device"); } return; }
/******************************************************************************* ** ** Function bta_ag_free_db ** ** Description Free discovery database. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_free_db(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { if (p_scb->p_disc_db != NULL) { GKI_freebuf(p_scb->p_disc_db); p_scb->p_disc_db = NULL; } }
/******************************************************************************* ** ** Function avdt_ccb_free_cmd ** ** Description This function is called when a response is received for a ** currently pending command. The command is freed. ** ** ** Returns void. ** *******************************************************************************/ void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { if (p_ccb->p_curr_cmd != NULL) { GKI_freebuf(p_ccb->p_curr_cmd); p_ccb->p_curr_cmd = NULL; } }
/******************************************************************************* ** ** Function mca_ccb_snd_req ** ** Description This function builds a request and sends it to the peer. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_snd_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data; BT_HDR *p_pkt; UINT8 *p, *p_start; BOOLEAN is_abort = FALSE; tMCA_DCB *p_dcb; MCA_TRACE_DEBUG ("mca_ccb_snd_req cong=%d req=%d", p_ccb->cong, p_msg->op_code); /* check for abort request */ if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (p_msg->op_code == MCA_OP_MDL_ABORT_REQ)) { p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx); /* the Abort API does not have the associated mdl_id. * Get the mdl_id in dcb to compose the request */ if (p_dcb) { p_msg->mdl_id = p_dcb->mdl_id; mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL); } mca_free_buf ((void **)&p_ccb->p_tx_req); p_ccb->status = MCA_CCB_STAT_NORM; is_abort = TRUE; } /* no pending outgoing messages or it's an abort request for a pending data channel */ if ((!p_ccb->p_tx_req) || is_abort) { p_ccb->p_tx_req = p_msg; if (!p_ccb->cong) { p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU); if (p_pkt) { p_pkt->offset = L2CAP_MIN_OFFSET; p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET; *p++ = p_msg->op_code; UINT16_TO_BE_STREAM (p, p_msg->mdl_id); if (p_msg->op_code == MCA_OP_MDL_CREATE_REQ) { *p++ = p_msg->mdep_id; *p++ = p_msg->param; } p_msg->hdr.layer_specific = TRUE; /* mark this message as sent */ p_pkt->len = p - p_start; L2CA_DataWrite (p_ccb->lcid, p_pkt); p_ccb->timer_entry.param = (TIMER_PARAM_TYPE) p_ccb; btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_MCA_CCB_RSP, p_ccb->p_rcb->reg.rsp_tout); } } /* else the L2CAP channel is congested. keep the message to be sent later */ } else { MCA_TRACE_WARNING ("dropping api req"); GKI_freebuf (p_data); } }
/******************************************************************************* ** ** Function rfc_port_sm_disc_wait_ua ** ** Description This function handles events when DISC on the DLC was ** sent and SM is waiting for UA or DM. ** ** Returns void ** *******************************************************************************/ void rfc_port_sm_disc_wait_ua (tPORT *p_port, UINT16 event, void *p_data) { switch (event) { case RFC_EVENT_OPEN: case RFC_EVENT_ESTABLISH_RSP: RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; case RFC_EVENT_CLEAR: rfc_port_closed (p_port); return; case RFC_EVENT_DATA: GKI_freebuf (p_data); return; case RFC_EVENT_UA: p_port->rfc.p_mcb->is_disc_initiator = TRUE; /* Case falls through */ case RFC_EVENT_DM: rfc_port_closed (p_port); return; case RFC_EVENT_SABME: rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE); return; case RFC_EVENT_DISC: rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE); return; case RFC_EVENT_UIH: GKI_freebuf (p_data); rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE); return; case RFC_EVENT_TIMEOUT: rfc_port_closed (p_port); return; } RFCOMM_TRACE_WARNING ("Port state disc_wait_ua Event ignored %d", event); }