Пример #1
0
/****************************************************************************
NAME	
	connectionHandleSdpAttributeSearchCfm

DESCRIPTION
	A confirm to the attribute search has been received, handle it here.

RETURNS
	void	
*/
void connectionHandleSdpAttributeSearchCfm(connectionSdpState *state, const SDC_EX_SERVICE_ATTRIBUTE_CFM_T *cfm)
{
    if (state->sdpSearchLock)
    {
        /* Send a cfm to the client task */	
        MAKE_CL_MESSAGE_WITH_LEN(CL_SDP_ATTRIBUTE_SEARCH_CFM, cfm->size_attr_list);
        message->status = connectionConvertSdpSearchStatus(cfm->response);
        message->error_code = cfm->err_code;
        connectionConvertBdaddr(&message->bd_addr, &cfm->bd_addr);
        message->size_attributes = cfm->size_attr_list;	
        
        if (cfm->size_attr_list)
        {
            uint8 *attribute_list = VmGetPointerFromHandle(cfm->attr_list);
            memcpy(message->attributes, attribute_list, cfm->size_attr_list);
            free(attribute_list);
        }
        else
            message->attributes[0] = 0;
        
        MessageSend(state->sdpSearchLock, CL_SDP_ATTRIBUTE_SEARCH_CFM, message);
        
        /* Reset the resource lock */
        state->sdpSearchLock = 0;
    }
    else
    {
        if (cfm->size_attr_list)
        {
            uint8 *attribute_list = VmGetPointerFromHandle(cfm->attr_list);
            free(attribute_list);
        }
    }
}
/*************************************************************************
NAME    
    handleAttPrepareWriteCfmPrepare
    
DESCRIPTION
    This function handles Bluestack response for ATT_PREPARE_WRITE_REQ
    during Prepare Write.
    
RETURNS
    
*/
static void handleAttPrepareWriteCfmPrepare(cid_map_t *conn,
                                            ATT_PREPARE_WRITE_CFM_T *m)
{
    gatt_write_reliable_t *data = &conn->data.req.write_reliable;
    STASH(conn, stash, RELIABLE_WRITE_PREPARE);

    /* convert the data pointer */
    m->value = VmGetPointerFromHandle(m->value);
    
    if (m->result == ATT_RESULT_SUCCESS &&
        /* check that the value matches */
        (m->offset != data->offs ||
         m->size_value != data->size_value ||
         memcmp8(m->value, data->value, m->size_value)))
    {
        stash->status = gatt_status_value_mismatch;
    }
    else
    {
        stash->status = gatt_message_status(m->result);
    }

    /* send the response */
    gatt_message_send(conn, GATT_RELIABLE_WRITE_PREPARE_CFM);
    gattSetConnState(conn, NULL, gatt_ms_none);

    /* free the stored data */
    free(data->value);

    /* free the data pointer */
    free(m->value);
}
/****************************************************************************
NAME	
    connectionHandleInquiryResultWithRssi

DESCRIPTION
    This function handles inquiry results with RSSI as they arrive from BlueStack.

RETURNS
    void
*/
void connectionHandleInquiryResultWithRssi(const connectionInquiryState *state, const DM_HCI_INQUIRY_RESULT_WITH_RSSI_IND_T*inq_result)
{
	uint16 array;
	uint16 index;
	uint16 results_left = inq_result->num_responses;

	/* Iterate through the array of inquiry result ptrs */
	for (array = 0; array < (inq_result->num_responses+HCI_MAX_INQ_RESULT_PER_PTR-1)/HCI_MAX_INQ_RESULT_PER_PTR; array++)
	{
		uint16 res_this_block = HCI_MAX_INQ_RESULT_PER_PTR;
		HCI_INQ_RESULT_WITH_RSSI_T *resarray = (HCI_INQ_RESULT_WITH_RSSI_T *) VmGetPointerFromHandle(inq_result->result[array]);
		
		if (results_left < res_this_block)
			res_this_block = results_left;
		
		for (index = 0; index< res_this_block; index++)
		{
			/* Send an inquiry result message to the client */
			bdaddr	addr;
			BdaddrConvertBluestackToVm(&addr, &((resarray+index)->bd_addr));
			inquirySendResult(state->inquiryLock, inquiry_status_result, &addr, 
				(resarray+index)->dev_class, (resarray+index)->clock_offset,
				(resarray+index)->page_scan_rep_mode, 0, (int16)(resarray+index)->rssi,
				0, NULL);
		}
		
		/* Free the data */
		free(resarray);
	}
}
/****************************************************************************
NAME    
    connectionHandleRemoteNameComplete

DESCRIPTION
    Remote name result

RETURNS
    void
*/
void connectionHandleRemoteNameComplete(connectionInquiryState *state, const DM_HCI_REMOTE_NAME_CFM_T* prim)
{
    bdaddr    addr;
    BdaddrConvertBluestackToVm(&addr, &prim->bd_addr);
    
    /* Providing the read was a success and we have a vaid name */
    if (!prim->status && prim->name_part[0])
    {
        uint16    length;
        uint8    i;

        /* Only handle the first segment */
        char*    name = VmGetPointerFromHandle(prim->name_part[0]);

        /* Find the length of the string in the first segment, limiting to     MAX_NAME_LENGTH bytes */
        for(length = 0; length < MAX_NAME_LENGTH; length++)
        {
            if (name[length] == '\0')
                break;
        }
        
        name[length] = '\0';
        
        /*     Free any other segments */
        for(i = 1;i < HCI_LOCAL_NAME_BYTE_PACKET_PTRS;i++)
        {
            if (prim->name_part[i] != NULL)
                free(VmGetPointerFromHandle(prim->name_part[i]));
        }
        
        /* Remote name read, send Client message to notify them of the result */
        remoteNameComplete(state->nameLock, &addr, rnr_success, name, length);
    }
    else
    {
        
        /* Read failed, send Client message to notify them of the result */
        remoteNameComplete(state->nameLock, &addr, 
                           prim->status? rnr_error: rnr_completed, NULL, 0);
    }
    
    /* Reset resource lock */
    state->nameLock = 0;
}
/*************************************************************************
NAME    
    handleAttPrepareWriteCfmLong
    
DESCRIPTION
    This function handles Bluestack response for ATT_PREPARE_WRITE_REQ
    during Long Characteristic Write.
    
RETURNS
    
*/
static void handleAttPrepareWriteCfmLong(cid_map_t *conn,
                                         ATT_PREPARE_WRITE_CFM_T *m)
{
    gatt_write_reliable_t *data = &conn->data.req.write_reliable;

    if (m->result == ATT_RESULT_SUCCESS)
    {
        data->offs += MAX_PREPARE_SIZE(conn->mtu);

        /* send next packet */
        if (data->offs < data->size_value)
        {
            gatt_prepare_write_req(m->cid, data->handle, data->offs,
                                   data->size_value - data->offs,
                                   data->value + data->offs);
        }

        /* execute write */
        else
        {
            gatt_execute_write_req(m->cid, ATT_EXECUTE_WRITE);
        }
    }

    /* cancel ongoing write queue */
    else if (data->offs)
    {
        STASH(conn, stash, WRITE_LONG_CHARACTERISTIC_VALUE);

        stash->status = gatt_message_status(m->result);
        gatt_execute_write_req(m->cid, ATT_EXECUTE_CANCEL);
    }

    /* send failure */
    else
    {
        STASH(conn, stash, WRITE_LONG_CHARACTERISTIC_VALUE);

        stash->status = gatt_message_status(m->result);
        gatt_message_send(conn, GATT_WRITE_LONG_CHARACTERISTIC_VALUE_CFM);
        gattSetConnState(conn, NULL, gatt_ms_none);

        free(data->value);
    }
    
    /* free the data */
    free(VmGetPointerFromHandle(m->value));
}
Пример #6
0
/****************************************************************************
NAME	
	connectionHandleSdpServiceSearchCfm

DESCRIPTION
	SDP service search results received so handle them here.

RETURNS
	void	
*/
void connectionHandleSdpServiceSearchCfm(connectionSdpState *state, const SDC_EX_SERVICE_SEARCH_CFM_T *cfm)
{
	if (state->sdpSearchLock == connectionGetCmTask())
	{
		/* Internal CFM means we're SDP Pinging */
		uint8* sdp_ptr = (uint8 *) SdpPingServiceRequest;
		
		/* Create next request */
		MAKE_CL_MESSAGE(CL_INTERNAL_SDP_SERVICE_SEARCH_REQ);
	
		message->theAppTask = connectionGetCmTask();
		message->bd_addr = state->sdpServerAddr;
		message->max_responses = 1;
		message->length = sizeof(SdpPingServiceRequest);				 
		message->search_pattern = (uint8*) PanicUnlessMalloc(sizeof(SdpPingServiceRequest));
		memcpy(message->search_pattern, sdp_ptr, sizeof(SdpPingServiceRequest));
		
		/* Send after 2 seconds to avoid thrashing the radio */
		MessageSendLater(connectionGetCmTask(), CL_INTERNAL_SDP_SERVICE_SEARCH_REQ, message, D_SEC(2));
		
		/* Tidy up memory in cfm */
		if (cfm->size_rec_list)
        {
            uint8 *record_list = VmGetPointerFromHandle(cfm->rec_list);
            free(record_list);
        }
        
		/* Free the lock so the next request can be handled */
		state->sdpSearchLock = 0;
	}
    else if (state->sdpSearchLock)
    {
        /* Send a cfm to the client task */
        MAKE_CL_MESSAGE_WITH_LEN(CL_SDP_SERVICE_SEARCH_CFM, cfm->size_rec_list);
        message->status = connectionConvertSdpSearchStatus(cfm->response);
        message->num_records = cfm->num_recs_ret;
        message->error_code = cfm->err_code;
        connectionConvertBdaddr(&message->bd_addr, &cfm->bd_addr);
        message->size_records = cfm->size_rec_list;
        
        if (cfm->size_rec_list)
        {
            uint8 *record_list = VmGetPointerFromHandle(cfm->rec_list);
            memcpy(message->records, record_list, cfm->size_rec_list);
            free(record_list);
        }
        else
            message->records[0] = 0;
        
        MessageSend(state->sdpSearchLock, CL_SDP_SERVICE_SEARCH_CFM, message);
        
        /* Reset the resource lock */
        state->sdpSearchLock = 0;
    }
    else
    {
        if (cfm->size_rec_list)
        {
            uint8 *record_list = VmGetPointerFromHandle(cfm->rec_list);
            free(record_list);
        }
    }
}
/*************************************************************************
NAME    
    gattHandleAttReadByTypeCfmCharacteristic
    
DESCRIPTION
    This function handles Bluestack response for ATT_READ_BY_TYPE_REQ
    during Relationship Discovery.
    
RETURNS
    
*/
void gattHandleAttReadByTypeCfmCharacteristic(ATT_READ_BY_TYPE_CFM_T *m)
{
    cid_map_t *conn = PanicNull(gattFindConn(m->cid)); /* never NULL */
    STASH(conn, stash, DISCOVER_ALL_CHARACTERISTICS);
    uint8 *data;
    uint8 *p;
    bool more;
    bool send;

    p = data = VmGetPointerFromHandle(m->value);

    if (!gatt_message_prepare(conn,
                              &more, &send, m->result,
                              m->handle >= conn->data.req.discover_all_characteristics.end,
                              stash ? &stash->more_to_come : NULL,
                              GATT_DISCOVER_ALL_CHARACTERISTICS_CFM))
    {
        free(data);
        return;
    }

    /* Create the message */
    MAKE_STASH(conn, stash, DISCOVER_ALL_CHARACTERISTICS);

    stash->cid = m->cid;
    stash->more_to_come = more;
    stash->status = gatt_message_status(m->result);
    stash->declaration = m->handle;

    /* read values from the response */
    if (stash->status == ATT_RESULT_SUCCESS)
    {
        stash->properties = gatt_read8(&p);
        stash->handle = gatt_read16(&p);

        gatt_get_att_uuid(stash->uuid, &stash->uuid_type,
                          m->size_value - 3, p);

    }
    
    /* schedule new round for getting more information */
    if (!send)
    {
        gatt_read_by_type_req(m->cid,
                              m->handle + 1,
                              conn->data.req.discover_all_characteristics.end,
                              ATT_UUID16, &uuid_characteristic);
    }
    
    /* only sent the message if we are not waiting for more information */
    else
    {
        gatt_message_send(conn, GATT_DISCOVER_ALL_CHARACTERISTICS_CFM);

        if (!more)
        {
            gattSetConnState(conn, NULL, gatt_ms_none);
        }
    }
    
    free(data);
}
/****************************************************************************
NAME    
    inquiryParseEir

DESCRIPTION
    Take the EIR data structure received from bluestack and concat the data 
	into a single block to send to the application

RETURNS
    A pointer to a single block containing the EIR data and the size of the 
	eir data
*/
static uint8* inquiryParseEir(uint8* size_eir_data, uint8 *inquiry_data[HCI_EIR_DATA_PACKET_PTRS], bool limit_data_size)
{
    /* Data Part */
    uint8 i = 0;                    /* Index into inquiry_data */
    uint8 size_data_part;           /* Size un-parsed data left in current part */
    uint8* eir_data_part;           /* Pointer to start of un-parsed data */
    uint8* eir_data_part_base;      /* Pointer to base of the current data part */
	
    /* Field Data */
    uint8 size_field;               /* Size of the field we're parsing */
    bool limit_exceeded;            /* If the field should be written */
	
    /* Result */
    uint8* eir_data = NULL;         /* Parsed EIR Data */
    *size_eir_data  = 0;            /* Size of Parsed Data */
	
    /* Return early if we have nothing to parse */
    if(inquiry_data[0] == NULL)
		{
        return eir_data;
    }
		
    /* Setup First Data Part */
    size_data_part = HCI_EIR_DATA_BYTES_PER_PTR;
    eir_data_part_base = VmGetPointerFromHandle(inquiry_data[i]);
    eir_data_part = eir_data_part_base;
	
    /* Get the size of the first field */
    size_field = (*eir_data_part) + 1;
    limit_exceeded = (((*size_eir_data) + size_field) > MAX_EIR_DATA_SIZE);
		
    /* Keep going until we reach NULL terminator */
    while(*eir_data_part != 0)
    {
        /* If the field is all in this part */
        if(size_field < size_data_part)
        {
            /* Copy to the end of field */
            if(!limit_data_size || !limit_exceeded)
                eir_data = inquiryAddEirData(size_eir_data, eir_data, size_field, eir_data_part);
            /* Move to the next field */
            size_data_part -= size_field;
            eir_data_part += size_field;
            size_field = (*eir_data_part) + 1;
            limit_exceeded = (((*size_eir_data) + size_field) > MAX_EIR_DATA_SIZE);
        }
        /* Field is split over multiple parts */
        else
        {
            /* Copy to the end of the data part */
            if(!limit_data_size || !limit_exceeded)
                eir_data = inquiryAddEirData(size_eir_data, eir_data, size_data_part, eir_data_part);
	
            /* Check if there's any more data parts to go */
            if(inquiry_data[++i] != NULL)
            {
                /* We're finished with this part so free it */
                free(eir_data_part_base);
	
                /* Move to the next data part */
                size_field -= size_data_part;
                size_data_part = HCI_EIR_DATA_BYTES_PER_PTR;
                eir_data_part_base = VmGetPointerFromHandle(inquiry_data[i]);
                eir_data_part = eir_data_part_base;
	
                /* Update field size if new field */
                if(size_field == 0)
                {
                    size_field = (*eir_data_part) + 1;
                    limit_exceeded = (((*size_eir_data) + size_field) > MAX_EIR_DATA_SIZE);
                }
            }
            /* Out of data */
            else
            {
                /* Data part will be freed below, just break */
                break;
            }
        }
	}
	
    /* Free the final data part */
    free(eir_data_part_base);
            
    /* NULL Terminate Data */
    (*size_eir_data)++;
    eir_data = PanicNull( realloc(eir_data, *size_eir_data) );
    *(eir_data + (*size_eir_data) - 1) = 0;
    
	return eir_data;
}