/****************************************************************************
NAME	
    inquirySendResult

DESCRIPTION
    Send a CL_DM_INQUIRE_RESULT message to the client

RETURNS
    void
*/
static void inquirySendResult(Task theAppTask, inquiry_status status, const bdaddr *addr, uint32 dev_class, uint16 clock_offset, page_scan_rep_mode_t ps_rep_mode, page_scan_mode_t ps_mode, int16 rssi, uint8 size_eir_data, uint8* eir_data)
{
    if (theAppTask)
    {	
        /* Create an inquiry result message and populate it with the supplied args */
        MAKE_CL_MESSAGE_WITH_LEN(CL_DM_INQUIRE_RESULT,size_eir_data);
        message->status = status;
        
        /* Check the address has been set */
        if (addr)
            message->bd_addr = *addr;
        else
            BdaddrSetZero(&message->bd_addr);
        
        message->dev_class = dev_class;
        message->clock_offset = clock_offset;
        message->page_scan_rep_mode = connectionConvertPageScanRepMode_t(ps_rep_mode);
        message->page_scan_mode = connectionConvertPageScanMode_t(ps_mode);
        message->rssi = rssi;
		message->size_eir_data = size_eir_data;
		if(size_eir_data)
		{
            memmove(message->eir_data, eir_data, size_eir_data);
		}
		else
		{
			message->eir_data[0] = 0;
		}
        MessageSend(theAppTask, CL_DM_INQUIRE_RESULT, message);
    }
}
/****************************************************************************
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    
    localNameComplete

DESCRIPTION
    Send a CL_DM_LOCAL_NAME_COMPLETE message to the client

RETURNS
    void
*/
static void localNameComplete(Task theAppTask, hci_status status, char* name, uint16 length)
{
    if (theAppTask)
    {
        MAKE_CL_MESSAGE_WITH_LEN(CL_DM_LOCAL_NAME_COMPLETE, length);
        message->status = status;
        
        message->size_local_name = length;
        
        /* Populate local name fields */
        if (length)
        {
            memmove(message->local_name, name, length);    
            free(name);
        }    
        else
            message->local_name[0] = 0;    
        
        /* Send onto Client */
        MessageSend(theAppTask, CL_DM_LOCAL_NAME_COMPLETE, message);
    }
    else
    {
        if (length)
            free(name);
    }
}
/****************************************************************************
NAME
	connectionAuthGetAttribute

FUNCTION
	This function is called to read the specified data from the specified 
	persistent store key.  The persistent store key is calulated from
	the specified base + the index of the specified device in TDL.

RETURNS
*/
void connectionAuthGetAttribute(Task appTask, uint16 ps_base, const bdaddr* bd_addr, uint16 size_psdata)
{
	/* Find device in the TDL */
	uint16 index = find_trusted_device(bd_addr);
	
    if (appTask)
	{
		/* Send a message back to the application task */
		MAKE_CL_MESSAGE_WITH_LEN(CL_SM_GET_ATTRIBUTE_CFM, size_psdata);
		message->status = fail;
		message->size_psdata = size_psdata;
		message->psdata[0] = 0;
	
		/* If an entry exists in the TDL for the specified device */
		if(index)
		{
			index--;
			if(size_psdata)
			{
				/* Read attribute data */
				if(PsRetrieve(ps_base + index, message->psdata, size_psdata))
				{
					message->status = success;
				}
			}
		}	
		MessageSend(appTask, CL_SM_GET_ATTRIBUTE_CFM, message);
	}
}
void ConnectionWriteInquiryAccessCode(Task theAppTask, const uint32 *iac, uint16 num_iac)
{
	/* Check params are within allowed values - debug build only */
#ifdef CONNECTION_DEBUG_LIB
	if ((num_iac < MIN_WRITE_IAC_LAP) || (num_iac > MAX_WRITE_IAC_LAP))
	{
		CL_DEBUG(("Out of range num_iac 0x%x\n", num_iac));
	}
#endif

	{
		MAKE_CL_MESSAGE_WITH_LEN(CL_INTERNAL_DM_WRITE_IAC_LAP_REQ, sizeof(uint32) * num_iac);
		message->theAppTask = theAppTask;
		message->num_iac = num_iac;
		memmove(&message->iac, iac, sizeof(uint32) * num_iac);
		MessageSendConditionally(connectionGetCmTask(), CL_INTERNAL_DM_WRITE_IAC_LAP_REQ, message, (const uint16 *)&theCm.inqState.inquiryLock);
	}
}
/****************************************************************************
NAME
    connectionHandleReadEirDataComplete

DESCRIPTION
    Handles result from Reading the Extended Inquiry Data.

RETURNS
    void
*/
void connectionHandleReadEirDataComplete(connectionInquiryState *state, const DM_HCI_READ_EXTENDED_INQUIRY_RESPONSE_DATA_CFM_T *cfm)
{
	if(state->inquiryLock)
	{
		uint8 size_eir_data = 0;
        uint8* eir_data = inquiryParseEir(&size_eir_data, (uint8**)cfm->eir_data_part, FALSE);
		
		MAKE_CL_MESSAGE_WITH_LEN(CL_DM_READ_EIR_DATA_CFM, size_eir_data);
		message->status = connectionConvertHciStatus(cfm->status);
		message->fec_required = cfm->fec_required;
		message->size_eir_data = size_eir_data;
        memmove(message->eir_data, eir_data, size_eir_data);
    	MessageSend(state->inquiryLock, CL_DM_READ_EIR_DATA_CFM, message);
		
		free(eir_data);
	}
	state->inquiryLock = 0;
}
/****************************************************************************
NAME
	connectionAuthGetAttribute

FUNCTION
	This function is called to read the specified data from the specified 
	persistent store key.  The persistent store key is calulated from
	the specified base + the index of the specified device in TDL.

RETURNS
*/
void connectionAuthGetIndexedAttribute(Task appTask, uint16 ps_base, uint16 mru_index, uint16 size_psdata)
{
	TrustedDeviceIndexType		tdi;
    TrustedDeviceRecordType     record;
	
	
	{
		/* Send a message back to the application task */
		MAKE_CL_MESSAGE_WITH_LEN(CL_SM_GET_INDEXED_ATTRIBUTE_CFM, size_psdata);
		message->status = fail;
		message->size_psdata = size_psdata;
		message->psdata[0] = 0;
		
		/* Read Trusted Device Index from Persistent store */
		if ((mru_index < MAX_TRUSTED_DEVICES) && PsRetrieve(TRUSTED_DEVICE_INDEX, &tdi, sizeof(tdi)))
		{
			/* Read the device record from the Trusted Device List */
			if (tdi.order[mru_index] && PsRetrieve((TRUSTED_DEVICE_LIST_BASE + tdi.order[mru_index] - 1), &record, sizeof(TrustedDeviceRecordType)))
			{
                /* Get Bluetooth address of device */
                message->bd_addr = record.bd_addr;
                
                /* Check if application wants attribute data */
				if (size_psdata != 0)
				{
					/* Read attribute data */
					if(PsRetrieve(ps_base + tdi.order[mru_index]-1, message->psdata, size_psdata))
						message->status = success;
				}
				else
				{
                    /* No attribute data required, so just indicate success */
					message->status = success;
				}
			}
		}

        /* Send confirmation back to application */
		MessageSend(appTask, CL_SM_GET_INDEXED_ATTRIBUTE_CFM, message);
	}
}
/****************************************************************************
NAME    
    remoteNameComplete

DESCRIPTION
    Send a CL_DM_REMOTE_NAME_COMPLETE message to the client

RETURNS
    void
*/
static void remoteNameComplete(Task theAppTask, const bdaddr *addr, hci_status status, char* name, uint16 length)
{
    if (theAppTask)
    {
        MAKE_CL_MESSAGE_WITH_LEN(CL_DM_REMOTE_NAME_COMPLETE, length);
        message->status = status;
        
        /* Check the address has been set */
        if (addr)
        {
            message->bd_addr = *addr;
        }
        else
        {
            BdaddrSetZero(&message->bd_addr);
        }
        
        message->size_remote_name = length;
        
        /* Populate remote name fields */
        if (length)
        {
            memmove(message->remote_name, name, length);
        }    
        else
        {
            message->remote_name[0] = 0;    
        }
        
        free(name);
        
        /* Send onto Client */
        MessageSend(theAppTask, CL_DM_REMOTE_NAME_COMPLETE, message);
    }
    else
    {
        if (length)
            free(name);
    }
}
/****************************************************************************
NAME	
    connectionHandleWriteIacLapRequest

DESCRIPTION
    Write IAC

RETURNS
    void
*/
void connectionHandleWriteIacLapRequest(connectionInquiryState *state, const CL_INTERNAL_DM_WRITE_IAC_LAP_REQ_T *req)
{
	/* Check the state of the task lock before doing anything */
	if (!state->iacLock)
	{
		uint16 index;
		uint24_t *ptr;
        MAKE_PRIM_C(DM_HCI_WRITE_CURRENT_IAC_LAP_REQ);

		/* One request at a time */
		state->iacLock = req->theAppTask;

		/* Store number of IACs */
		prim->num_current_iac = req->num_iac;
	
		/* Zero the entries */
		memset(prim->iac_lap, 0, sizeof(uint24_t *) * HCI_IAC_LAP_PTRS);

		/* Allocate memory block */
		prim->iac_lap[0] = (uint24_t *)malloc(sizeof(uint24_t) * prim->num_current_iac);
		ptr = prim->iac_lap[0];

		/* Copy IACs */
		for (index = 0; index < req->num_iac; index++)
			ptr[index] = req->iac[index];
	
		/* Vm friendly */
		prim->iac_lap[0] = VmGetHandleFromPointer(prim->iac_lap[0]);

		/* Send request */
		VmSendDmPrim(prim);
	}
	else
	{
		/* Inquiry currently being performed, queue up the request */
		MAKE_CL_MESSAGE_WITH_LEN(CL_INTERNAL_DM_WRITE_IAC_LAP_REQ, sizeof(uint32) * req->num_iac);
		COPY_CL_MESSAGE_WITH_LEN(CL_INTERNAL_DM_WRITE_IAC_LAP_REQ, sizeof(uint32) * req->num_iac, req, message);
		MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_WRITE_IAC_LAP_REQ, message, &state->iacLock);
	}
}
/*****************************************************************************/
#define REF_FLAG 0x8000 /* Pass result as a reference instead of a value */
void ConnectionSdpServiceSearchAttributeRequest(Task appTask, const bdaddr *addr, uint16 max_attributes, uint16 size_search_pattern, const uint8 *search_pattern, uint16 size_attr_list, const uint8 *attr_list)
{
#ifdef CONNECTION_DEBUG_LIB	
	if (size_search_pattern == 0)
		CL_DEBUG(("sdp - search pattern not supplied\n"));
	if (size_attr_list == 0)
		CL_DEBUG(("sdp - attribute search pattern not supplied\n"));
	if (max_attributes == 0)
		CL_DEBUG(("sdp - max number of attribute bytes set to zero\n"));
#endif

	{
		MAKE_CL_MESSAGE_WITH_LEN( CL_INTERNAL_SDP_SERVICE_SEARCH_ATTRIBUTE_REQ , 
                                  size_search_pattern + size_attr_list );

        /* Get reference flag from max_attributes */
        if (max_attributes & REF_FLAG)
        {
            message->flags = CONNECTION_FLAG_SDP_REFERENCE;
            max_attributes &= ~REF_FLAG;
        }
        else
        {
            message->flags = 0;
        }

        message->theAppTask = appTask;
		message->bd_addr = *addr;
		message->max_num_attributes = max_attributes;
		message->size_search_pattern = size_search_pattern;
		message->size_attribute_list = size_attr_list;
        memmove(message->search_attr,search_pattern, size_search_pattern );
        memmove(message->search_attr + size_search_pattern, 
                attr_list, size_attr_list );
		MessageSend(connectionGetCmTask(), CL_INTERNAL_SDP_SERVICE_SEARCH_ATTRIBUTE_REQ, message);
	}
}
/****************************************************************************
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);
        }
    }
}