/*--------------------------------------------------------------------------- * HidStateDiscPending() *--------------------------------------------------------------------------- * * Synopsis: Disconnect Pending state for the HID channel. * * Return: void */ void HidStateDiscPending(HidChannel *Channel, L2capChannelId Cid, L2capCallbackParms *Parms) { BtStatus status; kal_trace(BT_TRACE_G2_PROFILES,HIDSTATEDISCPENDINGx02X_CIDx02X ,Parms->event, Cid, Parms->status); CMGR_HidNoRoleSwitch(0); switch (Parms->event) { case L2EVENT_DISCONNECTED: /* The connection is down, adjust the connection reference count */ kal_trace(BT_TRACE_G2_PROFILES,HID_CHANNELCONCOUNTx02X ,Channel->conCount); if (Channel->conCount > 0) { Channel->conCount--; } kal_trace(BT_TRACE_G2_PROFILES,CHANNELCTRLCIDx02XCHANNELINTRCIDx02X , Channel->ctrlCid, Channel->intrCid); if (Cid == Channel->ctrlCid) { Channel->ctrlCid = 0; } else { Channel->intrCid = 0; } if (Channel->conCount > 0) { if (Channel->flags & CHNL_FLAG_TERMINATOR) { kal_trace(BT_TRACE_G2_PROFILES,HID_TRY_TO_DISCONNECT_INTR_CHANNEL); /* First connection disconnect is complete, disconnect the 2nd */ /* Disconnect control channel secondly */ status = L2CAP_DisconnectReq(Channel->ctrlCid); kal_trace(BT_TRACE_G2_PROFILES,HID_L2CAP_DISCONNECT_REQ_CID_CIDx02X_STATUSx02X ,Channel->intrCid, status); } } else if (Channel->state == HID_STATE_CONN_PENDING && (Channel->ctrlCid != 0 || Channel->intrCid != 0)) { /* This means the connection is still ongoing */ } else { kal_trace(BT_TRACE_G2_PROFILES,HIDCLEARCONNECTION); if (Channel->flags & CHNL_FLAG_SERVICE_QUERY) { /* if SDP query is not completed yet, not remove the connection until SDP query is done */ Channel->bSDPDiscPending = TRUE; } else { /* Clear the connection structure and notify the application */ HidClearConnection(Channel, BT_STATUS_SUCCESS, Parms->status); } } } }
/*--------------------------------------------------------------------------- * HidCmgrCallback() *--------------------------------------------------------------------------- * * Synopsis: Called by connection manager with link state events. * * Return: (See header file) * */ void HidCmgrCallback(CmgrHandler *Handler, CmgrEvent Event, BtStatus Status) { BtStatus ret; HidChannel *channel = ContainingRecord(Handler, HidChannel, cmgrHandler); kal_trace(BT_TRACE_G2_PROFILES,HIDCMGRCALLBACKx02X ,Event); switch (Event) { case CMEVENT_DATA_LINK_CON_CNF: if (channel == NULL) { kal_trace(BT_TRACE_G2_PROFILES,HID_NOT_THE_CONNECT_BD_ADDR); return; } if(channel->cmgrHandler.bdc == 0) { kal_trace(BT_TRACE_G2_PROFILES,HIDCHANNELCMGRHANDLERBDC0); return; } kal_trace(BT_TRACE_G2_PROFILES,HID_STATUSx02X ,Status); if (Status != BT_STATUS_SUCCESS) { /* Indicate the query response failure to the application */ HidClearConnection(channel, Status, 0); return; } else { #ifdef __BT_4_0_BLE__ kal_trace(BT_TRACE_BLE_PROFILES, HID_CMGRCALLBACK_DEVTYPE, channel->cmgrHandler.bdc->devType); if (channel->cmgrHandler.bdc->devType == BT_DEV_TYPE_LE) { ret = GattClientConnect(channel->cmgrHandler.remDev); Report(("[HID] GattClientConnect ret: %d", ret)); /* Since HID Gatt callback will be called even if connection is existed, there is unnecessary to handle return success case here. */ /* if (ret == BT_STATUS_SUCCESS) { ret = HidStartGattServiceQuery(channel); if (ret != BT_STATUS_PENDING) { channel->flags &= ~CHNL_FLAG_SERVICE_QUERY; HidAppCallback(channel, HIDEVENT_QUERY_CNF, ret, &channel->queryRsp, (U16)(sizeof(HidQueryRsp))); } } */ } else #endif { if (channel->flags & CHNL_FLAG_SERVICE_QUERY) { HidStartServiceQuery(channel); } else { kal_trace(BT_TRACE_G2_PROFILES,HID_START_L2CAP_CONNECTION); /* Start the L2CAP connection */ if (L2CAP_ConnectReq(&HID(hidCtrlPsm), BT_PSM_HID_CTRL, channel->cmgrHandler.remDev, 0, &(channel->ctrlCid)) == BT_STATUS_PENDING) { channel->state = HID_STATE_CONN_PENDING; channel->flags |= CHNL_FLAG_INITIATOR; break; } } } } break; case CMEVENT_DATA_LINK_DIS: { HidClearConnection(channel, Status, 0); return; } default: break; } }
void HidSdpEventHandler(SdpQueryToken *sqt, U8 result, U8 attr_idx, U8 *attr_val) { HidChannel *channel = ContainingRecord(sqt, HidChannel, sdpQueryToken); ReportDescriptorList* reportDescriptorList = NULL; HidParseData* hpd ; kal_trace(BT_TRACE_G2_PROFILES,BT_HID_SDP_QUERY_CALLBACK_x02X ,result); switch (result) { case BT_STATUS_SDP_CONT_STATE: kal_trace(BT_TRACE_G2_PROFILES,HID_SDP_SUCCESSFULLY); HidVerifySdpQueryRsp(channel, bt_hid_attr_id_list[attr_idx], attr_val, sqt->availValueLen, result); break; case BT_STATUS_SUCCESS: HidVerifySdpQueryRsp(channel, bt_hid_attr_id_list[attr_idx], attr_val, sqt->availValueLen, result); if (channel->bSDPDiscPending) { HidClearConnection(channel, result, 0); } else { hpd = (HidParseData*)hid_malloc(sizeof(HidParseData)); Hid_Init_Parser(hpd); channel->reportCons[0] = (HidReportConstructor*)hid_malloc(HID_REPORT_ID_MAX * sizeof(HidReportConstructor)); btmtk_os_memset((U8*) channel->reportCons[0], 0, HID_REPORT_ID_MAX * sizeof(HidReportConstructor)); reportDescriptorList = HidFindReportDescriptorByAddr(channel->cmgrHandler.remDev->bdAddr); if(reportDescriptorList != NULL ) { btmtk_os_memset(reportDescriptorList->BtAddr.addr, 0, 6); reportDescriptorList->inUse = FALSE; hid_free(reportDescriptorList->reportDescriptor); reportDescriptorList->reportDescriptorLength = 0; } HidCacheReportDescriptor(channel->cmgrHandler.remDev->bdAddr, channel->queryRsp.descriptorList, channel->queryRsp.descriptorLen); if(HidAddDescriptor(channel) == BT_STATUS_SUCCESS) bt_prompt_trace(MOD_BT,"[HID]HidAddDescriptor Successed!"); else bt_prompt_trace(MOD_BT,"[HID]HidAddDescriptor failed!"); Hid_Free_Parser(hpd); channel->flags &= ~CHNL_FLAG_SERVICE_QUERY; HidSdpCallback(channel, result); } break; case BT_STATUS_NOSERVICES: { static const U8 HidDescriptorList[] = { HID_DESCRIPTOR }; channel->queryRsp.descriptorLen = HID_DESCRIPTOR_LEN; channel->queryRsp.descriptorList = (U8*)hid_malloc(HID_DESCRIPTOR_LEN); btmtk_os_memset((U8*) channel->queryRsp.descriptorList, 0, HID_DESCRIPTOR_LEN); btmtk_os_memcpy((U8*) channel->queryRsp.descriptorList, HidDescriptorList, HID_DESCRIPTOR_LEN); hpd = (HidParseData*)hid_malloc(sizeof(HidParseData)); Hid_Init_Parser(hpd); channel->reportCons[0] = (HidReportConstructor*)hid_malloc(HID_REPORT_ID_MAX * sizeof(HidReportConstructor)); btmtk_os_memset((U8*) channel->reportCons[0], 0, HID_REPORT_ID_MAX * sizeof(HidReportConstructor)); if(HidAddDescriptor(channel) == BT_STATUS_SUCCESS) bt_prompt_trace(MOD_BT,"[HID]HidAddDescriptor Successed!"); else bt_prompt_trace(MOD_BT,"[HID]HidAddDescriptor failed!"); Hid_Free_Parser(hpd); channel->flags &= ~CHNL_FLAG_SERVICE_QUERY; HidSdpCallback(channel, BT_STATUS_SUCCESS); break; } case BT_STATUS_CONNECTION_FAILED: case BT_STATUS_FAILED: default: channel->flags &= ~CHNL_FLAG_SERVICE_QUERY; HidClearConnection(channel, result, 0); break; } }