/**************************************************************************** NAME connectionHandleReadInquiryTx DESCRIPTION This function will initiate a read of the inquiry tx power of the device RETURNS void */ void connectionHandleReadInquiryTx(connectionReadInfoState* infoState, connectionInquiryState *state, const CL_INTERNAL_DM_READ_INQUIRY_TX_REQ_T *req) { /* Check command supported by firmware */ if(infoState->version != bluetooth_unknown) { /* Check the state of the task lock before doing anything */ if (!state->inquiryLock) { /* One request at a time */ state->inquiryLock = req->theAppTask; /* Issue request to read the inquiry tx */ { MAKE_PRIM_C(DM_HCI_READ_INQUIRY_RESPONSE_TX_POWER_LEVEL_REQ); VmSendDmPrim(prim); } } else { /* Remote name request currently being performed, queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_INQUIRY_TX_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_INQUIRY_TX_REQ, message, &state->inquiryLock); } } else { /* Tell the app this is unsupported */ MAKE_CL_MESSAGE(CL_DM_READ_INQUIRY_TX_CFM); message->status = hci_error_unsupported_feature; message->tx_power = 0; MessageSend(req->theAppTask, CL_DM_READ_INQUIRY_TX_CFM, message); } }
/**************************************************************************** NAME connectionHandleReadEirDataRequest DESCRIPTION Handles request for Reading the Extended Inquiry Data. RETURNS void */ void connectionHandleReadEirDataRequest(connectionReadInfoState *infoState, connectionInquiryState *state, const CL_INTERNAL_DM_READ_EIR_DATA_REQ_T *req) { if(infoState->version >= bluetooth2_1) { /* Check the state of the task lock before doing anything */ if (!state->inquiryLock) { state->inquiryLock = req->task; { MAKE_PRIM_C(DM_HCI_READ_EXTENDED_INQUIRY_RESPONSE_DATA_REQ); VmSendDmPrim(prim); } } else { /* Inquiry currently being performed, queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_EIR_DATA_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_EIR_DATA_REQ, message, &state->inquiryLock); } } else { /* Not supported, tell the app */ MAKE_CL_MESSAGE(CL_DM_READ_EIR_DATA_CFM); message->status = hci_error_unsupported_feature; message->fec_required = FALSE; message->size_eir_data = 0; message->eir_data[0] = 0; MessageSend(state->inquiryLock, CL_DM_READ_EIR_DATA_CFM, message); } }
/**************************************************************************** NAME connectionHandleSdpOpenSearchRequest DESCRIPTION Send a request to BlueSTack to open an SDP search session RETURNS void */ void connectionHandleSdpOpenSearchRequest(connectionSdpState *state, const CL_INTERNAL_SDP_OPEN_SEARCH_REQ_T *req) { /* Check the state of the resource lock */ if (!state->sdpLock) { /* Resource free, set the lock */ state->sdpLock = req->theAppTask; /* Store the address of the device we're opening the search to */ state->sdpServerAddr = req->bd_addr; /* Send the request to BlueStack */ { MAKE_PRIM_T(SDC_OPEN_SEARCH_REQ); connectionConvertBdaddr_t(&prim->bd_addr, &req->bd_addr); VmSendSdpPrim(prim); } } else if(req->theAppTask != connectionGetCmTask()) { /* Resource busy so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_SDP_OPEN_SEARCH_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_SDP_OPEN_SEARCH_REQ, message, &state->sdpLock); } }
/**************************************************************************** NAME connectionHandleReadRemoteSupportedFeaturesRequest DESCRIPTION Request to read the supported features of a remote device. RETURNS void */ void connectionHandleReadRemoteSupportedFeaturesRequest(connectionReadInfoState *state, const CL_INTERNAL_DM_READ_REMOTE_SUPP_FEAT_REQ_T *req) { /* Check the resource lock */ if (!state->stateInfoLock) { bdaddr addr; /* Check we got a valid addr */ if (!SinkGetBdAddr(req->sink, &addr)) { /* Send an error to the app as it didn't pass in a valid sink */ sendRemoteSupportedFeaturesCfm(req->theAppTask, hci_error_no_connection, 0, req->sink); } else { /* Response not outstanding so issue request */ MAKE_PRIM_C(DM_HCI_READ_REMOTE_FEATURES); connectionConvertBdaddr_t(&prim->bd_addr, &addr); VmSendDmPrim(prim); /* Set the lock */ state->stateInfoLock = req->theAppTask; state->sink = req->sink; } } else { /* Lock set so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_REMOTE_SUPP_FEAT_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_REMOTE_SUPP_FEAT_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME connectionHandleSdpServiceSearchAttrRequest DESCRIPTION Handle a request to perfor a service/ attribute search. If allowed, send request to BlueStack otherwise queue it up until it can be sent. RETURNS void */ void connectionHandleSdpServiceSearchAttrRequest(connectionSdpState *state, const CL_INTERNAL_SDP_SERVICE_SEARCH_ATTRIBUTE_REQ_T *req) { sdp_search_req res = sendSearchRequest(req->theAppTask, state, &req->bd_addr); if (res == sdp_start_search) { /* Send the request to BlueStack */ MAKE_PRIM_T(SDC_SERVICE_SEARCH_ATTRIBUTE_REQ); prim->phandle = 0; connectionConvertBdaddr_t(&prim->bd_addr, &req->bd_addr); prim->size_srch_pttrn = req->size_search_pattern; if (req->size_search_pattern) prim->srch_pttrn = VmGetHandleFromPointer(req->search_pattern); else prim->srch_pttrn = 0; prim->size_attr_list = req->size_attribute_list; if (req->size_attribute_list) prim->attr_list = VmGetHandleFromPointer(req->attribute_list); else prim->attr_list = 0; prim->max_num_attr = req->max_num_attributes; VmSendSdpPrim(prim); /* Lock the resource */ state->sdpSearchLock = req->theAppTask; } else { Task *c = 0; /* Queue up the search request */ MAKE_CL_MESSAGE(CL_INTERNAL_SDP_SERVICE_SEARCH_ATTRIBUTE_REQ); COPY_CL_MESSAGE(req, message); /* Use the return value from searchRequest function to decide which resource to wait on */ if (res == sdp_lock_set) c = &state->sdpLock; else if (res == sdp_search_lock_set) c = &state->sdpSearchLock; else if (res == sdp_session_open_other_dev) c = &state->sdpLock; else /* Should not get here but if we do panic */ Panic(); /* Queus up message with condition determined above */ MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_SDP_SERVICE_SEARCH_ATTRIBUTE_REQ, message, c); } }
/**************************************************************************** NAME connectionHandleSetBtVersionReq DESCRIPTION Handle setting BT Version RETURNS void */ void connectionHandleSetBtVersionReq(connectionReadInfoState *state, const CL_INTERNAL_DM_SET_BT_VERSION_REQ_T *req) { if(!state->stateInfoLock) { state->stateInfoLock = req->theAppTask; { MAKE_PRIM_T(DM_SET_BT_VERSION_REQ); prim->version = req->version; VmSendDmPrim(prim); } } else { /* Lock set so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_SET_BT_VERSION_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_SET_BT_VERSION_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME connectionHandleReadInquiryModeRequest DESCRIPTION Read inquiry mode RETURNS void */ void connectionHandleReadInquiryModeRequest(connectionInquiryState *state, const CL_INTERNAL_DM_READ_INQUIRY_MODE_REQ_T *req) { /* Check the state of the task lock before doing anything */ if (!state->inquiryLock) { state->inquiryLock = req->theAppTask; { /* Issue inquiry mode read */ MAKE_PRIM_C(DM_HCI_READ_INQUIRY_MODE_REQ); VmSendDmPrim(prim); } } else { /* Inquiry currently being performed, queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_INQUIRY_MODE_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_INQUIRY_MODE_REQ, message, &state->inquiryLock); } }
/**************************************************************************** NAME connectionHandleReadLocalVersionRequest DESCRIPTION Request to read the version information of the local device. RETURNS void */ void connectionHandleReadLocalVersionRequest(connectionReadInfoState *state, const CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ_T *req) { /* Check the resource lock */ if (!state->stateInfoLock) { /* Response not outstanding so issue request */ MAKE_PRIM_C(DM_HCI_READ_LOCAL_VERSION); VmSendDmPrim(prim); /* Set the lock */ state->stateInfoLock = req->theAppTask; } else { /* Lock set so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME connectionHandleWriteInquiryModeRequest DESCRIPTION Write inquiry mode RETURNS void */ void connectionHandleWriteInquiryModeRequest(connectionInquiryState *state, const CL_INTERNAL_DM_WRITE_INQUIRY_MODE_REQ_T *req) { /* Check the state of the task lock before doing anything */ if (!state->inquiryLock) { state->inquiryLock = req->theAppTask; { /* Issue inquiry mode change with the supplied parameter */ MAKE_PRIM_C(DM_HCI_WRITE_INQUIRY_MODE_REQ); prim->mode = connectionConvertInquiryMode_t(req->mode); VmSendDmPrim(prim); } } else { /* Inquiry currently being performed, queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_WRITE_INQUIRY_MODE_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_WRITE_INQUIRY_MODE_REQ, message, &state->inquiryLock); } }
/**************************************************************************** NAME connectionHandleSdpClientConfigMtu DESCRIPTION Send a request to BlueStack to configure the SDP client MTU size RETURNS void */ void connectionHandleSdpClientConfigMtu(const connectionSdpState *state, const CL_INTERNAL_SDP_CONFIG_CLIENT_MTU_REQ_T *req) { /* We don't get a response from this so send it without setting the lock. Still have to make sure the lock isn't set though so check it before sending the prim */ if (!state->sdpLock) { MAKE_PRIM_T(SDC_CONFIG_REQ); prim->mtu = req->mtu; VmSendSdpPrim(prim); } else { /* Resource is locked, queue up the request for later */ MAKE_CL_MESSAGE(CL_INTERNAL_SDP_CONFIG_CLIENT_MTU_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_SDP_CONFIG_CLIENT_MTU_REQ, message, &state->sdpLock); } }
/**************************************************************************** NAME connectionHandleReadAddrRequest DESCRIPTION Handle an internal request to read the local bluetooth address RETURNS void */ void connectionHandleReadAddrRequest(connectionReadInfoState *state, const CL_INTERNAL_DM_READ_BD_ADDR_REQ_T *req) { if (!state->stateInfoLock) { /* Set the lock */ state->stateInfoLock = req->theAppTask; state->sink = 0; /* Response not outstanding so issue request */ { MAKE_PRIM_C(DM_HCI_READ_BD_ADDR); VmSendDmPrim(prim); } } else { /* Lock set so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_BD_ADDR_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_BD_ADDR_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME connectionHandleReadLocalName DESCRIPTION This function will initiate a read of the local name of the device RETURNS void */ void connectionHandleReadLocalName(connectionInquiryState *state, const CL_INTERNAL_DM_READ_LOCAL_NAME_REQ_T *req) { /* Check the state of the task lock before doing anything */ if (!state->nameLock) { /* One request at a time */ state->nameLock = req->theAppTask; /* Issue request to read the remote name */ { MAKE_PRIM_C(DM_HCI_READ_LOCAL_NAME_REQ); VmSendDmPrim(prim); } } else { /* Remote name request currently being performed, queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_LOCAL_NAME_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_LOCAL_NAME_REQ, message, &state->nameLock); } }
/**************************************************************************** NAME connectionHandleReadRemoteVersionRequest DESCRIPTION Request to read the version information of a remote device. RETURNS void */ void connectionHandleReadRemoteVersionRequest(connectionReadInfoState *state, const CL_INTERNAL_DM_READ_REMOTE_VERSION_REQ_T *req) { /* Check the resource lock */ if (!state->stateInfoLock) { bdaddr addr; /* Check we got a valid addr */ if (!SinkGetBdAddr(req->sink, &addr)) { /* Create and send the message */ MAKE_CL_MESSAGE(CL_DM_REMOTE_VERSION_CFM); message->status = hci_error_no_connection; message->lmpVersion = 0; message->manufacturerName = 0; message->lmpSubVersion = 0; MessageSend(req->theAppTask, CL_DM_REMOTE_VERSION_CFM, message); } else { /* Response not outstanding so issue request */ MAKE_PRIM_C(DM_HCI_READ_REMOTE_VERSION); connectionConvertBdaddr_t(&prim->bd_addr, &addr); VmSendDmPrim(prim); /* Set the lock */ state->stateInfoLock = req->theAppTask; } } else { /* Lock set so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_REMOTE_VERSION_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_REMOTE_VERSION_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME connectionHandleReadClassOfDeviceRequest DESCRIPTION Handles the internal message that initiates the read class of device RETURNS void */ void connectionHandleReadClassOfDeviceRequest(connectionReadInfoState *state, const CL_INTERNAL_DM_READ_CLASS_OF_DEVICE_REQ_T *req) { /* Check the lock */ if (!state->stateInfoLock) { /* Not currently processing one of these so set the lock */ state->stateInfoLock = req->theAppTask; state->sink = 0; { /* Issue the request to BlueStack */ MAKE_PRIM_C(DM_HCI_READ_CLASS_OF_DEVICE_REQ); VmSendDmPrim(prim); } } else { /* Currently busy processing a read cod request so queue this up */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_CLASS_OF_DEVICE_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_CLASS_OF_DEVICE_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME connectionHandleSdpUnregisterRequest DESCRIPTION Handle the request to unregister a particular service record RETURNS void */ void connectionHandleSdpUnregisterRequest(connectionSdpState *state, const CL_INTERNAL_SDP_UNREGISTER_RECORD_REQ_T *req) { /* Check the resource lock */ if (!state->sdpLock) { /* Set lock */ state->sdpLock = req->theAppTask; /* Resource free so send request down to BlueStack */ { MAKE_PRIM_T(SDS_UNREGISTER_REQ); prim->phandle = 0; prim->svc_rec_hndl = req->service_handle; VmSendSdpPrim(prim); } } else { /* Resource is locked, queue up the request for later */ MAKE_CL_MESSAGE(CL_INTERNAL_SDP_UNREGISTER_RECORD_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_SDP_UNREGISTER_RECORD_REQ, message, &state->sdpLock); } }
/**************************************************************************** NAME connectionHandleSdpRegisterRequest DESCRIPTION Sends a register request to the SDP server RETURNS void */ void connectionHandleSdpRegisterRequest(connectionSdpState *state, const CL_INTERNAL_SDP_REGISTER_RECORD_REQ_T *req) { /* If the resource is not locked, send downt he request */ if (!state->sdpLock) { /* Set the lock */ state->sdpLock = req->theAppTask; { MAKE_PRIM_T(SDS_REGISTER_REQ); prim->phandle = 0; prim->num_rec_bytes = req->record_length; prim->service_rec = VmGetHandleFromPointer(req->record); VmSendSdpPrim(prim); } } else { /* Resource locked, queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_SDP_REGISTER_RECORD_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_SDP_REGISTER_RECORD_REQ, message, &state->sdpLock); } }
/**************************************************************************** NAME connectionStartInquiry DESCRIPTION This function actually kicks off an inquiry message to BlueStack. RETURNS void */ void connectionHandleInquiryStart(connectionInquiryState *state, const CL_INTERNAL_DM_INQUIRY_REQ_T *inquiry_req) { /* Check the state of the task lock before doing anything */ if (!state->inquiryLock) { state->inquiryLock = inquiry_req->theAppTask; /* If the class of device field is set, set an event filter so we only receive inquiry results with devices with this class of device. By default we filter in all devices so if class of device mask set to zero we don't have to set the event filter. */ if (inquiry_req->class_of_device) { MAKE_PRIM_C(DM_HCI_SET_EVENT_FILTER_REQ); prim->filter_type = INQUIRY_RESULT_FILTER; prim->filter_condition_type = CLASS_OF_DEVICE_RESPONDED; prim->condition.class_mask.class_of_device = inquiry_req->class_of_device; /* We don't care what the bits other than the specific class of device are set to so set them to zero */ prim->condition.class_mask.mask = inquiry_req->class_of_device; VmSendDmPrim(prim); } { if (inquiry_req->min_period) { /* Start an periodic inquiry with the supplied parameters */ MAKE_PRIM_C(DM_HCI_PERIODIC_INQUIRY_MODE_REQ); prim->lap = inquiry_req->inquiry_lap; prim->inquiry_length = inquiry_req->timeout; prim->num_responses = inquiry_req->max_responses; prim->max_period_length = inquiry_req->max_period; prim->min_period_length = inquiry_req->min_period; VmSendDmPrim(prim); state->periodic_inquiry = TRUE; } else { /* Start an inquiry with the supplied parameters */ MAKE_PRIM_C(DM_HCI_INQUIRY_REQ); prim->lap = inquiry_req->inquiry_lap; prim->inquiry_length = inquiry_req->timeout; prim->num_responses = inquiry_req->max_responses; VmSendDmPrim(prim); state->periodic_inquiry = FALSE; } } } else { /* Inquiry currently being performed, queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_INQUIRY_REQ); COPY_CL_MESSAGE(inquiry_req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_INQUIRY_REQ, message, &state->inquiryLock); } }