Esempio n. 1
0
/*******************************************************************************
**
** Function         gatt_process_prep_write_rsp
**
** Description      This function is called to handle the read response
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
                                  UINT16 len, UINT8 *p_data)
{
    tGATT_VALUE  value = {0};
    UINT8        *p= p_data;

    GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);

    STREAM_TO_UINT16 (value.handle, p);
    STREAM_TO_UINT16 (value.offset, p);

    value.len = len - 4;

    memcpy (value.value, p, value.len);

    if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
    {
        p_clcb->status = GATT_SUCCESS;
        /* application should verify handle offset
           and value are matched or not */

        gatt_end_operation(p_clcb, p_clcb->status, &value);
    }
    else if (p_clcb->op_subtype == GATT_WRITE )
    {
        if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
            gatt_send_prepare_write(p_tcb, p_clcb);
    }

}
Esempio n. 2
0
//*****************************************************************************
//
//!  hci_event_unsol_flowcontrol_handler
//!
//!  @param  pEvent  pointer to the string contains parameters for IPERF
//!  @return         ESUCCESS if successful, EFAIL if an error occurred
//!
//!  @brief  Called in case unsolicited event from type
//!          HCI_EVNT_DATA_UNSOL_FREE_BUFF has received.
//!				   Keep track on the number of packets transmitted and update the
//!					 number of free buffer in the SL device.
//
//*****************************************************************************
INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent)
{

	INT32 temp, value;
	UINT16 i;
	UINT16  pusNumberOfHandles=0;
	CHAR *pReadPayload;

	STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles);
	pReadPayload = ((CHAR *)pEvent +
		HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles));	
	temp = 0;

	for(i = 0; i < pusNumberOfHandles ; i++)
	{
		STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value);
		temp += value;
		pReadPayload += FLOW_CONTROL_EVENT_SIZE;  
	}

	tSLInformation.usNumberOfFreeBuffers += temp;
	tSLInformation.NumberOfReleasedPackets += temp;

	return(ESUCCESS);
}
Esempio n. 3
0
/*******************************************************************************
**
** Function         gatt_process_find_type_value_rsp
**
** Description      This function is called to handle find by type value response.
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
{
    tGATT_DISC_RES      result;
    tGATT_DISC_VALUE    record_value;
    UINT8               *p = p_data;

    GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp ");
    /* unexpected response */
    if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
        return;

    memset (&record_value, 0, sizeof(tGATT_DISC_VALUE));
    result.type.len = 2;
    result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;

    /* returns a series of handle ranges */
    while (len >= 4)
    {
        STREAM_TO_UINT16 (result.handle, p);
        STREAM_TO_UINT16 (record_value.handle, p);
        len -= 4;

        memcpy (&result.value, &record_value, sizeof (result.value));;

        if (p_clcb->p_reg->app_cb.p_disc_res_cb)
            (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
    }

    /* last handle  + 1 */
    p_clcb->s_handle = (record_value.handle == 0) ? 0 : (record_value.handle + 1);
    /* initiate another request */
    gatt_act_discovery(p_clcb) ;
}
Esempio n. 4
0
// Returns true if the event was intercepted and should not proceed to
// higher layers. Also inspects an incoming event for interesting
// information, like how many commands are now able to be sent.
static bool filter_incoming_event(BT_HDR *packet) {
  waiting_command_t *wait_entry = NULL;
  uint8_t *stream = packet->data;
  uint8_t event_code;
  command_opcode_t opcode;

  STREAM_TO_UINT8(event_code, stream);
  STREAM_SKIP_UINT8(stream); // Skip the parameter total length field

  if (event_code == HCI_COMMAND_COMPLETE_EVT) {
    STREAM_TO_UINT8(command_credits, stream);
    STREAM_TO_UINT16(opcode, stream);

    wait_entry = get_waiting_command(opcode);
    if (!wait_entry)
      LOG_WARN(LOG_TAG, "%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode);
    else if (wait_entry->complete_callback)
      wait_entry->complete_callback(packet, wait_entry->context);
    else if (wait_entry->complete_future)
      future_ready(wait_entry->complete_future, packet);

    goto intercepted;
  } else if (event_code == HCI_COMMAND_STATUS_EVT) {
    uint8_t status;
    STREAM_TO_UINT8(status, stream);
    STREAM_TO_UINT8(command_credits, stream);
    STREAM_TO_UINT16(opcode, stream);

    // If a command generates a command status event, it won't be getting a command complete event

    wait_entry = get_waiting_command(opcode);
    if (!wait_entry)
      LOG_WARN(LOG_TAG, "%s command status event with no matching command. opcode: 0x%x", __func__, opcode);
    else if (wait_entry->status_callback)
      wait_entry->status_callback(status, wait_entry->command, wait_entry->context);

    goto intercepted;
  }

  return false;
intercepted:;
  non_repeating_timer_restart_if(command_response_timer, !list_is_empty(commands_pending_response));

  if (wait_entry) {
    // If it has a callback, it's responsible for freeing the packet
    if (event_code == HCI_COMMAND_STATUS_EVT || (!wait_entry->complete_callback && !wait_entry->complete_future))
      buffer_allocator->free(packet);

    // If it has a callback, it's responsible for freeing the command
    if (event_code == HCI_COMMAND_COMPLETE_EVT || !wait_entry->status_callback)
      buffer_allocator->free(wait_entry->command);

    osi_free(wait_entry);
  } else {
    buffer_allocator->free(packet);
  }

  return true;
}
/*******************************************************************************
**
** Function         gap_ble_c_cmpl_cback
**
** Description      Client operation complete callback.
**
** Returns          void
**
*******************************************************************************/
static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)

{
    tGAP_CLCB   *p_clcb = gap_ble_find_clcb_by_conn_id(conn_id);
    UINT16      op_type;
    UINT16      min, max, latency, tout;
    UINT16      len;
    UINT8       *pp;

    if (p_clcb == NULL)
        return;

    op_type = p_clcb->cl_op_uuid;

    GAP_TRACE_EVENT ("gap_ble_c_cmpl_cback() - op_code: 0x%02x  status: 0x%02x  read_type: 0x%04x", op, status, op_type);
    /* Currently we only issue read commands */
    if (op != GATTC_OPTYPE_READ)
        return;

    if (status != GATT_SUCCESS)
    {
        gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
        return;
    }

    pp = p_data->att_value.value;

    switch (op_type)
    {
        case GATT_UUID_GAP_PREF_CONN_PARAM:
            GAP_TRACE_EVENT ("GATT_UUID_GAP_PREF_CONN_PARAM");
            /* Extract the peripheral preferred connection parameters and save them */

            STREAM_TO_UINT16 (min, pp);
            STREAM_TO_UINT16 (max, pp);
            STREAM_TO_UINT16 (latency, pp);
            STREAM_TO_UINT16 (tout, pp);

            BTM_BleSetPrefConnParams (p_clcb->bda, min, max, latency, tout);
            /* release the connection here */
            gap_ble_cl_op_cmpl(p_clcb, TRUE, 0, NULL);
            break;

        case GATT_UUID_GAP_DEVICE_NAME:
            GAP_TRACE_EVENT ("GATT_UUID_GAP_DEVICE_NAME");
            len = (UINT16)strlen((char *)pp);
            if (len > GAP_CHAR_DEV_NAME_SIZE)
                len = GAP_CHAR_DEV_NAME_SIZE;
            gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp);
            break;
        case GATT_UUID_GAP_ICON:
            break;
    }
}
Esempio n. 6
0
/*******************************************************************************
**
** Function         nfc_enabled
**
** Description      NFCC enabled, proceed with stack start up.
**
** Returns          void
**
*******************************************************************************/
void nfc_enabled (tNFC_STATUS nfc_status, BT_HDR *p_init_rsp_msg)
{
    tNFC_RESPONSE evt_data;
    tNFC_CONN_CB  *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
    UINT8   *p;
    UINT8   num_interfaces = 0, xx;
    int     yy = 0;

    memset (&evt_data, 0, sizeof (tNFC_RESPONSE));

    if (nfc_status == NCI_STATUS_OK)
    {
        nfc_set_state (NFC_STATE_IDLE);

        p = (UINT8 *) (p_init_rsp_msg + 1) + p_init_rsp_msg->offset + NCI_MSG_HDR_SIZE + 1;
        /* we currently only support NCI of the same version.
        * We may need to change this, when we support multiple version of NFCC */
        evt_data.enable.nci_version = NCI_VERSION;
        STREAM_TO_UINT32 (evt_data.enable.nci_features, p);
        STREAM_TO_UINT8 (num_interfaces, p);

        evt_data.enable.nci_interfaces = 0;
        for (xx = 0; xx < num_interfaces; xx++)
        {
            if ((*p) <= NCI_INTERFACE_MAX)
                evt_data.enable.nci_interfaces |= (1 << (*p));
            #if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE)
            else if (((*p) >= NCI_INTERFACE_FIRST_VS) && (yy < NFC_NFCC_MAX_NUM_VS_INTERFACE))
            #else
            else if (((*p) > NCI_INTERFACE_FIRST_VS) && (yy < NFC_NFCC_MAX_NUM_VS_INTERFACE))
            #endif
            {
                /* save the VS RF interface in control block, if there's still room */
                nfc_cb.vs_interface[yy++] = *p;
            }
            p++;
        }
        nfc_cb.nci_interfaces    = evt_data.enable.nci_interfaces;
        memcpy (evt_data.enable.vs_interface, nfc_cb.vs_interface, NFC_NFCC_MAX_NUM_VS_INTERFACE);
        evt_data.enable.max_conn = *p++;
        STREAM_TO_UINT16 (evt_data.enable.max_ce_table, p);
#if (NFC_RW_ONLY == FALSE)
        nfc_cb.max_ce_table          = evt_data.enable.max_ce_table;
        nfc_cb.nci_features          = evt_data.enable.nci_features;
        nfc_cb.max_conn              = evt_data.enable.max_conn;
#endif
        nfc_cb.nci_ctrl_size         = *p++; /* Max Control Packet Payload Length */
        p_cb->init_credits           = p_cb->num_buff = 0;
        STREAM_TO_UINT16 (evt_data.enable.max_param_size, p);
        nfc_set_conn_id (p_cb, NFC_RF_CONN_ID);
        evt_data.enable.manufacture_id   = *p++;
        STREAM_TO_ARRAY (evt_data.enable.nfcc_info, p, NFC_NFCC_INFO_LEN);
        NFC_DiscoveryMap (nfc_cb.num_disc_maps, (tNCI_DISCOVER_MAPS *) nfc_cb.p_disc_maps, NULL);
    }
/*******************************************************************************
**
** Function         smp_rand_back
**
** Description      This function is to process the rand command finished,
**                  process the random/encrypted number for further action.
**
** Returns          void
**
*******************************************************************************/
static void smp_rand_back(tBTM_RAND_ENC *p)
{
    tSMP_CB *p_cb = &smp_cb;
    UINT8   *pp = p->param_buf;
    UINT8   failure = SMP_PAIR_FAIL_UNKNOWN;
    UINT8   state = p_cb->rand_enc_proc & ~0x80;

    SMP_TRACE_DEBUG1 ("smp_rand_back state=0x%x", state);
    if (p && p->status == HCI_SUCCESS)
    {
        switch (state)
        {

            case SMP_GEN_SRAND_MRAND:
                memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
                smp_genenrate_rand_cont(p_cb, NULL);
                break;

            case SMP_GEN_SRAND_MRAND_CONT:
                memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
                smp_genenrate_confirm(p_cb, NULL);
                break;

            case SMP_GEN_DIV_LTK:
                STREAM_TO_UINT16(p_cb->div, pp);
                smp_genenrate_ltk_cont(p_cb, NULL);
                break;

            case SMP_GEN_DIV_CSRK:
                STREAM_TO_UINT16(p_cb->div, pp);
                smp_compute_csrk(p_cb, NULL);
                break;

            case SMP_GEN_TK:
                smp_proc_passkey(p_cb, p);
                break;

            case SMP_GEN_RAND_V:
                memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN);
                smp_generate_y(p_cb, NULL);
                break;

        }

        return;
    }

    SMP_TRACE_ERROR1("smp_rand_back Key generation failed: (%d)", p_cb->rand_enc_proc);

    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);

}
Esempio n. 8
0
static void transmit_command(
    BT_HDR *command,
    command_complete_cb complete_callback,
    command_status_cb status_callback,
    void *context)
{
    uint8_t *stream;
    waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
    if (!wait_entry) {
        LOG_ERROR("%s couldn't allocate space for wait entry.", __func__);
        return;
    }

    stream = command->data + command->offset;
    STREAM_TO_UINT16(wait_entry->opcode, stream);
    wait_entry->complete_callback = complete_callback;
    wait_entry->status_callback = status_callback;
    wait_entry->command = command;
    wait_entry->context = context;

    // Store the command message type in the event field
    // in case the upper layer didn't already
    command->event = MSG_STACK_TO_HC_HCI_CMD;
    LOG_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", wait_entry->opcode);
    BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);

    fixed_queue_enqueue(hci_host_env.command_queue, wait_entry);
    hci_host_task_post();
}
Esempio n. 9
0
//*****************************************************************************
//
//!  SpiReadDataCont
//!
//!  @param  None
//!
//!  @return None
//!
//!  @brief  This function processes received SPI Header and in accordance with 
//!	         it - continues reading the packet
//
//*****************************************************************************
long
SpiReadDataCont(void)
{
	long data_to_recv;
	unsigned char *evnt_buff, type;
	
	//determine what type of packet we have
	evnt_buff =  sSpiInformation.pRxPacket;
	data_to_recv = 0;
	STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET,
									type);
	
	switch(type)
	{
	case HCI_TYPE_DATA:
		{
			// We need to read the rest of data..
			STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE), 
											 HCI_DATA_LENGTH_OFFSET, data_to_recv);
			if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1))
			{	
				data_to_recv++;
			}
			
			if (data_to_recv)
			{
				SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
			}
			break;
		}
	case HCI_TYPE_EVNT:
		{
			// Calculate the rest length of the data
			STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), 
											HCI_EVENT_LENGTH_OFFSET, data_to_recv);
			data_to_recv -= 1;
			
			// Add padding byte if needed
			if ((HEADERS_SIZE_EVNT + data_to_recv) & 1)
			{
				
				data_to_recv++;
			}
			
			if (data_to_recv)
			{
				SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
			}
			
			sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
			break;
		}
	}
	
	return (0);
}
/*******************************************************************************
**
** Function         gatt_process_mtu_rsp
**
** Description      This function is called to process the configure MTU response.
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
{
    UINT16 mtu;

    STREAM_TO_UINT16(mtu, p_data);

    if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
        p_tcb->payload_size = mtu;

    gatt_end_operation(p_clcb, p_clcb->status, NULL);
}
Esempio n. 11
0
void SpiReceiveHandler(void *pvBuffer)
{
  tSLInformation.pucReceivedData = (uint8_t *)pvBuffer;
  tSLInformation.usEventOrDataReceived = 1;

  uint16_t event_type;
  STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type);
  nllvdbg("Evtn:0x%x\n", event_type);

  hci_unsolicited_event_handler();
}
/*******************************************************************************
**
** Function         gatt_process_handle_rsp
**
** Description      This function is called to handle the write response
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_handle_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
{
    UINT16      handle;
    UINT8       * p= p_data;

    STREAM_TO_UINT16(handle, p);
    len -= 2;

    if (op_code == GATT_RSP_WRITE)
        gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
}
int32_t cc3000_event::hci_event_unsol_flowcontrol_handler(uint8_t *event) {
    int32_t temp, value;
    uint16_t i;
    uint16_t pusNumberOfHandles=0;
    uint8_t *pReadPayload;

    STREAM_TO_UINT16((uint8_t *)event,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles);
    pReadPayload = ((uint8_t *)event + HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles));
    temp = 0;

    for(i = 0; i < pusNumberOfHandles; i++) {
        STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value);
        temp += value;
        pReadPayload += FLOW_CONTROL_EVENT_SIZE;
    }

    _simple_link.set_number_free_buffers(_simple_link.get_number_free_buffers() + temp);
    _simple_link.set_number_of_released_packets(_simple_link.get_released_packets() + temp);

    return(ESUCCESS);
}
Esempio n. 14
0
/*******************************************************************************
**
** Function         hw_sco_cfg_cback
**
** Description      Callback function for SCO configuration rquest
**
** Returns          None
**
*******************************************************************************/
void hw_sco_cfg_cback(void *p_mem)
{
#if 0
    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
    uint8_t     *p;
    uint16_t    opcode;
    HC_BT_HDR  *p_buf=NULL;

    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
    STREAM_TO_UINT16(opcode,p);

    /* Free the RX event buffer */
    if (bt_vendor_cbacks)
        bt_vendor_cbacks->dealloc(p_evt_buf);

#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
    if (opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM)
    {
        uint8_t ret = FALSE;

        /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
        if (bt_vendor_cbacks)
            p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
                                                HCI_CMD_PREAMBLE_SIZE + \
                                                PCM_DATA_FORMAT_PARAM_SIZE);
        if (p_buf)
        {
            p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
            p_buf->offset = 0;
            p_buf->layer_specific = 0;
            p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE;

            p = (uint8_t *) (p_buf + 1);
            UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
            *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
            memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);

            if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,\
                                           p_buf, hw_sco_cfg_cback)) == FALSE)
            {
                bt_vendor_cbacks->dealloc(p_buf);
            }
            else
                return;
        }
    }
#endif  // !SCO_USE_I2S_INTERFACE

if (bt_vendor_cbacks)
    bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
#endif
}
Esempio n. 15
0
uint16_t get_uuid16(tBT_UUID *p_uuid)
{
    if (p_uuid->len == LEN_UUID_16) {
        return p_uuid->uu.uuid16;
    } else if (p_uuid->len == LEN_UUID_128) {
        UINT16 u16;
        UINT8 *p = &p_uuid->uu.uuid128[LEN_UUID_128 - 4];
        STREAM_TO_UINT16(u16, p);
        return u16;
    } else { /* p_uuid->len == LEN_UUID_32 */
        return (UINT16) p_uuid->uu.uuid32;
    }
}
Esempio n. 16
0
static void fragment_and_dispatch(BT_HDR *packet)
{
    uint16_t continuation_handle;
    uint16_t max_data_size, max_packet_size, remaining_length;
    uint16_t event = packet->event & MSG_EVT_MASK;
    uint8_t *stream = packet->data + packet->offset;

    assert(packet != NULL);

    // We only fragment ACL packets
    if (event != MSG_STACK_TO_HC_HCI_ACL) {
        callbacks->fragmented(packet, true);
        return;
    }

    max_data_size =
        SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ?
        controller->get_acl_data_size_classic() :
        controller->get_acl_data_size_ble();

    max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE;
    remaining_length = packet->len;
    STREAM_TO_UINT16(continuation_handle, stream);
    continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle);
    if (remaining_length > max_packet_size) {
        current_fragment_packet = packet;
        UINT16_TO_STREAM(stream, max_data_size);
        packet->len = max_packet_size;
        callbacks->fragmented(packet, false);
        packet->offset += max_data_size;
        remaining_length -= max_data_size;
        packet->len = remaining_length;

        // Write the ACL header for the next fragment
        stream = packet->data + packet->offset;
        UINT16_TO_STREAM(stream, continuation_handle);
        UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE);
        // Apparently L2CAP can set layer_specific to a max number of segments to transmit
        if (packet->layer_specific) {
            packet->layer_specific--;
            if (packet->layer_specific == 0) {
                packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT;
                callbacks->transmit_finished(packet, false);
                return;
            }
        }
    } else {
        current_fragment_packet = NULL;
        callbacks->fragmented(packet, true);
    }
}
Esempio n. 17
0
/*******************************************************************************
**
** Function         gatt_process_read_info_rsp
**
** Description      This function is called to handle the read information
**                  response.
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
                                UINT16 len, UINT8 *p_data)
{
    tGATT_DISC_RES  result;
    UINT8   *p = p_data, uuid_len = 0, type;

    UNUSED(p_tcb);
    UNUSED(op_code);

    if (len < GATT_INFO_RSP_MIN_LEN) {
        GATT_TRACE_ERROR("invalid Info Response PDU received, discard.");
        gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
        return;
    }
    /* unexpected response */
    if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT) {
        return;
    }

    STREAM_TO_UINT8(type, p);
    len -= 1;

    if (type == GATT_INFO_TYPE_PAIR_16) {
        uuid_len = LEN_UUID_16;
    } else if (type == GATT_INFO_TYPE_PAIR_128) {
        uuid_len = LEN_UUID_128;
    }

    while (len >= uuid_len + 2) {
        STREAM_TO_UINT16 (result.handle, p);

        if (uuid_len > 0) {
            if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) {
                break;
            }
        } else {
            memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
        }

        len -= (uuid_len + 2);

        if (p_clcb->p_reg->app_cb.p_disc_res_cb) {
            (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
        }
    }

    p_clcb->s_handle = (result.handle == 0) ? 0 : (result.handle + 1);
    /* initiate another request */
    gatt_act_discovery(p_clcb) ;
}
Esempio n. 18
0
/*******************************************************************************
 **
 ** Function         btusb_isoc_check_hdr
 **
 ** Description      Check the packet header
 **
 ** Parameters       p_dev: device instance control block
 **
 ** Returns          void
 **
 *******************************************************************************/
static bool btusb_isoc_check_hdr(struct btusb *p_dev)
{
    unsigned char *p_data = p_dev->voice_rx.hdr;
    int idx;
    unsigned short sco_handle;
    unsigned char size;
    struct btusb_voice_pkt *p_pkt;
    BT_HDR *p_hdr;
    struct btusb_voice_channel *p_chan;

    STREAM_TO_UINT16(sco_handle, p_data);
    sco_handle &= 0x0fff;
    STREAM_TO_UINT8(size, p_data);

    for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_rx.channels); idx++)
    {
        p_chan = &p_dev->voice_rx.channels[idx];
        if ((p_chan->used) &&
            (sco_handle == p_chan->handle) &&
            (size <= (2 * p_chan->burst)))
        {
            /* check if there is already a message being consolidated */
            if (unlikely(!p_chan->p_pkt))
            {
                if (!btusb_cq_get(&p_dev->voice_rx_list, &p_pkt))
                {
                    BTUSB_ERR("No buffer available for SCO defragmentation\n");
                    return false;
                }
                p_hdr = &p_pkt->bt_hdr;
                p_hdr->len = BTUSB_VOICE_HEADER_SIZE;
                p_hdr->offset = 0;
                p_hdr->layer_specific = 0;

                p_data = (unsigned char *) (p_hdr + 1);

                /* add sco handle and buffer size */
                UINT16_TO_STREAM(p_data, sco_handle);
                UINT8_TO_STREAM(p_data, BTUSB_SCO_RX_LEN);

                p_chan->p_pkt = p_pkt;
            }
            p_dev->voice_rx.remaining = size;
            p_dev->voice_rx.pp_pkt = &p_chan->p_pkt;

            return true;
        }
    }
    return false;
}
Esempio n. 19
0
/*******************************************************************************
**
**  Function        l2c_ucd_check_pending_in_sec_q
**
**  Description     check incoming security
**
**  Return          TRUE if any UCD packet for security
**
*******************************************************************************/
BOOLEAN l2c_ucd_check_pending_in_sec_q(tL2C_CCB  *p_ccb)
{
    BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);

    if (p_buf != NULL) {
        UINT16 psm;
        UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
        STREAM_TO_UINT16(psm, p)

        p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
        btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm,
                                  p_ccb->p_lcb->handle, CONNLESS_TERM, &l2c_link_sec_comp, p_ccb);

        return (TRUE);
    }
    return (FALSE);
}
/*******************************************************************************
**
** Function         smp_genenrate_smp_process_edivltk_cont
**
** Description      This function is to calculate EDIV = Y xor DIV
**
** Returns          void
**
*******************************************************************************/
static void smp_process_ediv(tSMP_CB *p_cb, tSMP_ENC *p)
{
    tSMP_KEY    key;
    UINT8 *pp= p->param_buf;
    UINT16  y;

    SMP_TRACE_DEBUG0 ("smp_process_ediv ");
    STREAM_TO_UINT16(y, pp);

    /* EDIV = Y xor DIV */
    p_cb->ediv = p_cb->div ^ y;
    /* send LTK ready */
    SMP_TRACE_ERROR0("LTK ready");
    key.key_type = SMP_KEY_TYPE_LTK;
    key.p_data   = p->param_buf;

    smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
}
Esempio n. 21
0
/*******************************************************************************
 **
 ** Function         bta_av_co_cp_is_scmst
 **
 ** Description      Check if a content protection service is SCMS-T
 **
 ** Returns          TRUE if this CP is SCMS-T, FALSE otherwise
 **
 *******************************************************************************/
static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo)
{
    UINT16 cp_id;
    FUNC_TRACE();

    if (*p_protectinfo >= BTA_AV_CP_LOSC)
    {
        p_protectinfo++;
        STREAM_TO_UINT16(cp_id, p_protectinfo);
        if (cp_id == BTA_AV_CP_SCMS_T_ID)
        {
            APPL_TRACE_DEBUG0("bta_av_co_cp_is_scmst: SCMS-T found");
            return TRUE;
        }
    }

    return FALSE;
}
Esempio n. 22
0
static future_t *transmit_command_futured(BT_HDR *command) {
  waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
  assert(wait_entry != NULL);

  future_t *future = future_new();

  uint8_t *stream = command->data + command->offset;
  STREAM_TO_UINT16(wait_entry->opcode, stream);
  wait_entry->complete_future = future;
  wait_entry->command = command;

  // Store the command message type in the event field
  // in case the upper layer didn't already
  command->event = MSG_STACK_TO_HC_HCI_CMD;

  fixed_queue_enqueue(command_queue, wait_entry);
  return future;
}
/*******************************************************************************
**
** Function         bta_gattc_pack_attr_uuid
**
** Description      pack UUID into a stream.
**
** Returns
**
*******************************************************************************/
void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid)
{
    UINT8 *pp = (UINT8 *)p_attr->p_uuid;

    memset(p_uuid, 0, sizeof(tBT_UUID));

    p_uuid->len = p_attr->uuid_len;

    if (p_attr->uuid_len == LEN_UUID_16)
    {
        STREAM_TO_UINT16(p_uuid->uu.uuid16, pp);
    }
    else
    {
        memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128);
    }

    return;
}
Esempio n. 24
0
/*******************************************************************************
**
** Function         gatt_process_mtu_rsp
**
** Description      This function is called to process the configure MTU response.
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
{
    UINT16 mtu;
    tGATT_STATUS    status = GATT_SUCCESS;

    if (len < GATT_MTU_RSP_MIN_LEN) {
        GATT_TRACE_ERROR("invalid MTU response PDU received, discard.");
        status = GATT_INVALID_PDU;
    } else {
        STREAM_TO_UINT16(mtu, p_data);

        if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE) {
            p_tcb->payload_size = mtu;
        }
    }

    l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
    gatt_end_operation(p_clcb, status, NULL);
}
Esempio n. 25
0
/*******************************************************************************
**
** Function         gatt_process_error_rsp
**
** Description      This function is called to handle the error response
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
                            UINT16 len, UINT8 *p_data)
{
    UINT8   opcode, reason, * p= p_data;
    UINT16  handle;
    tGATT_VALUE  *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;

    UNUSED(op_code);
    UNUSED(len);

    GATT_TRACE_DEBUG("gatt_process_error_rsp ");
    STREAM_TO_UINT8(opcode, p);
    STREAM_TO_UINT16(handle, p);
    STREAM_TO_UINT8(reason, p);

    if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
    {
        gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason);
    }
    else
    {
        if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
             (p_clcb->op_subtype == GATT_WRITE) &&
             (opcode == GATT_REQ_PREPARE_WRITE) &&
             (p_attr) &&
             (handle == p_attr->handle)  )
        {
            p_clcb->status = reason;
            gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
        }
        else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
                 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
                  (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
                 (opcode == GATT_REQ_READ_BLOB) &&
                 p_clcb->first_read_blob_after_read &&
                 (reason == GATT_NOT_LONG))
        {
            gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
        }
        else
            gatt_end_operation(p_clcb, reason, NULL);
    }
}
Esempio n. 26
0
void SimpleLinkWaitData(uint8_t *pBuf, uint8_t *from, uint8_t *fromlen)
{
  /* In the blocking implementation the control to caller will be returned only
   * after the end of current transaction, i.e. only after data will be received
   */

  nllvdbg("Looking for Data\n");
  uint16_t event_type;
  uint16_t opcode = tSLInformation.usRxEventOpcode;

  do
    {
      tSLInformation.pucReceivedData = cc3000_wait();
      tSLInformation.usEventOrDataReceived = 1;

      if (*tSLInformation.pucReceivedData == HCI_TYPE_DATA)
        {
          tSLInformation.usRxDataPending = 1;
          hci_event_handler(pBuf, from, fromlen);
          break;
        }
      else
        {
          STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET, event_type);
          nllvdbg("Evtn:0x%x\n", event_type);

          if (hci_unsolicited_event_handler() == 1)
            {
              nllvdbg("Processed Event  0x%x want Data! Opcode 0x%x\n", event_type, opcode);
            }
          else
            {
              nllvdbg("!!!!!opcode 0x%x\n", opcode);
            }

          UNUSED(event_type);
        }
    }
  while (*tSLInformation.pucReceivedData == HCI_TYPE_EVNT);

  nllvdbg("Done for Data 0x%x\n", opcode);
  UNUSED(opcode);
}
Esempio n. 27
0
/*******************************************************************************
**
** Function         hw_epilog_cback
**
** Description      Callback function for Command Complete Events from HCI
**                  commands sent in epilog process.
**
** Returns          None
**
*******************************************************************************/
void hw_epilog_cback(void *p_mem)
{
    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
    char        *p_name, *p_tmp;
    uint8_t     *p, status;
    uint16_t    opcode;

    status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
    STREAM_TO_UINT16(opcode,p);

    ALOGI("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);

    /* Must free the RX event buffer */
    q.cb->dealloc(p_evt_buf);

    /* Once epilog process is done, must call callback to notify caller */
    q.cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);

}
Esempio n. 28
0
/*******************************************************************************
**
** Function         btm_delete_stored_link_key_complete
**
** Description      This function is called when the command complete message
**                  is received from the HCI for the delete stored link key command.
**
** Returns          void
**
*******************************************************************************/
void btm_delete_stored_link_key_complete (UINT8 *p)
{
    tBTM_CMPL_CB         *p_cb = btm_cb.devcb.p_stored_link_key_cmpl_cb;
    tBTM_DELETE_STORED_LINK_KEY_COMPLETE  result;

    /* If there was a callback registered for read stored link key, call it */
    btm_cb.devcb.p_stored_link_key_cmpl_cb = NULL;

    if (p_cb)
    {
        /* Set the call back event to indicate command complete */
        result.event = BTM_CB_EVT_DELETE_STORED_LINK_KEYS;

        /* Extract the result fields from the HCI event */
        STREAM_TO_UINT8  (result.status, p);
        STREAM_TO_UINT16 (result.num_keys, p);

        /* Call the call back and pass the result */
        (*p_cb)(&result);
    }
}
Esempio n. 29
0
/*******************************************************************************
**
** Function         l2c_ucd_data_ind_cback
**
** Description      UCD Data callback
**
** Returns          void
**
*******************************************************************************/
static void l2c_ucd_data_ind_cback (BD_ADDR rem_bda, BT_HDR *p_buf)
{
    UINT8 *p;
    UINT16 psm;
    tL2C_RCB    *p_rcb;

    L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_data_ind_cback");

    p = (UINT8 *)(p_buf + 1) + p_buf->offset;
    STREAM_TO_UINT16(psm, p)

    p_buf->offset += L2CAP_UCD_OVERHEAD;
    p_buf->len    -= L2CAP_UCD_OVERHEAD;

    if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) {
        L2CAP_TRACE_ERROR ("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x", psm);
        osi_free (p_buf);
    } else {
        p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf);
    }
}
/*******************************************************************************
**
** Function         gatt_process_read_info_rsp
**
** Description      This function is called to handle the read information
**                  response.
**
**
** Returns          void
**
*******************************************************************************/
void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
                                UINT16 len, UINT8 *p_data)
{
    tGATT_DISC_RES  result;
    UINT8   *p = p_data, uuid_len = 0, type;

    /* unexpected response */
    if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
        return;

    STREAM_TO_UINT8(type, p);
    len -= 1;

    if (type == GATT_INFO_TYPE_PAIR_16)
        uuid_len = LEN_UUID_16;
    else if (type == GATT_INFO_TYPE_PAIR_128)
        uuid_len = LEN_UUID_128;

    while (len >= uuid_len + 2)
    {
        STREAM_TO_UINT16 (result.handle, p);

        if (uuid_len > 0)
        {
            if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p))
                break;
        }
        else
            memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));

        len -= (uuid_len + 2);

        if (p_clcb->p_reg->app_cb.p_disc_res_cb)
            (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
    }

    p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1);
    /* initiate another request */
    gatt_act_discovery(p_clcb) ;
}