/*--------------------------------------------------------------------------- * TCPSTACK_ServerDeinit() *--------------------------------------------------------------------------- * * Synopsis: Deinitialize the OBEX Server transport. This function returns * success if the server is not initialized. * * Return: TRUE - Server stack deinitialized. * FALSE - Server cannot deinitialize. * */ BOOL TCPSTACK_ServerDeinit(ObTcpServerTransport *txp) { ObexServerTransports *transport = ContainingRecord(txp, ObexServerTransports, ObexServerTcpTrans); ObexAppHandle *appHndl = (ObexAppHandle*)ContainingRecord(transport, ObexServerApp, trans); if (txp->server.state == OCS_UNINITIALIZED) { return TRUE; } ASSERT(txp->server.app == appHndl); if (txp->server.state != OCS_IDLE) { return FALSE; } /* Close registration socket */ closesocket(txp->serverReg); txp->serverReg = INVALID_SOCKET; txp->server.state = OCS_UNINITIALIZED; txp->server.app = 0; RemoveEntryList(&txp->server.node); return TRUE; }
static void _time_gatt_read_characteristic_value_cb(BtGattEvent *event) { // To be modified. BtStatus status; BtGattReadCharacteristicValueResultEvent *ptr; TimePacket *pkt; TimeCTransport *pChnl; U16 uuid = 0; ptr = (BtGattReadCharacteristicValueResultEvent *) event->parms; pkt = ContainingRecord(event->pGattOp, TimePacket, gatt_op); pChnl = (TimeCTransport *) pkt->chnl; switch (ptr->flag) { case BT_GATT_EVENT_RESULT_DONE_COMPLETED: OS_Report("[Time] Read Characteristic Value with result DONE_COMPLETED"); _time_gatt_notify_query_result(pkt, ptr->data, ptr->length, BT_STATUS_SUCCESS); break; case BT_GATT_EVENT_RESULT_ERROR: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; case BT_GATT_EVENT_RESULT_DISCONNECT: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; } }
U8 time_att_db_update_ctrl_point_callback(U8 type, BtRemoteDevice *link, U16 *len, U8 **raw) { TimeSTransport *pChnl; TimeSContext *pCntx; pChnl = times_find_server_tp(link->bdAddr.addr); if (pChnl == NULL) { return BT_STATUS_FAILED; } OS_Report("[Time] %s(), type: %d", __FUNCTION__, type); pCntx = ContainingRecord(pChnl, TimeSContext, chnl); if (type == ATT_OP_WRITE || type == ATT_OP_EXECUTE_WRITE) { if ((pChnl->update_status.cur_state == TIME_UPDATE_STATE_IDLE) && (*raw[0] == TIME_UPDATE_CTRL_REQUEST)) { pChnl->update_status.cur_state = TIME_UPDATE_STATE_UPDATE_PENDING; times_notify_request_server_update(pCntx); return BT_STATUS_SUCCESS; } else if ((pChnl->update_status.cur_state == TIME_UPDATE_STATE_UPDATE_PENDING) && (*raw[0] == TIME_UPDATE_CTRL_CANCEL)) { pChnl->update_status.cur_state = TIME_UPDATE_STATE_IDLE; pChnl->update_status.result = TIME_UPDATE_RESULT_CANCELED; times_notify_cancel_server_update(pCntx); return BT_STATUS_SUCCESS; } } return BT_STATUS_FAILED; }
static void _time_gatt_write_characteristic_descriptor_cb(BtGattEvent *event) { BtStatus status; BtGattWriteCharDescriptorResultEvent *ptr; TimePacket *pkt; TimeCTransport *pChnl; U16 uuid = 0; ptr = (BtGattWriteCharDescriptorResultEvent *) event->parms; pkt = ContainingRecord(event->pGattOp, TimePacket, gatt_op); pChnl = (TimeCTransport *) pkt->chnl; switch (ptr->flag) { case BT_GATT_EVENT_RESULT_DONE_COMPLETED: OS_Report("[Time] Write Characteristic Descriptor with result DONE_COMPLETED"); _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_SUCCESS); break; case BT_GATT_EVENT_RESULT_ERROR: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; case BT_GATT_EVENT_RESULT_DISCONNECT: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; } }
BtStatus AvrcpCreateAclLink(BD_ADDR *Addr, CmgrHandler *Handler, CmgrCallback Callback) { AvrcpChannel *chnl = ContainingRecord(Handler, AvrcpChannel, cmgrHandler); BtStatus status; status = CMGR_CreateDataLink(Handler, Addr); kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_CREATEACL, status); if (status == BT_STATUS_SUCCESS) { #ifdef __BT_AVRCP_V14__ status = AvrcpStartServiceQuery(chnl, BSQM_FIRST); #else #ifdef __BT_AVRCP_V13__ status = AvrcpStartServiceQuery(chnl, BSQM_FIRST); #else status = AvrcpStartMultiServiceQuery(chnl, BSQM_FIRST, chnl->role); #endif #endif } return status; }
static void avrcpQueryCallback(SdpQueryToken *sqt, U8 result, U8 serv_chn) { SdpQueryToken *token; BtRemoteDevice *remDev; AvrcpChannel *chnl = ContainingRecord( sqt, AvrcpChannel, sdpQueryToken ); token = sqt; if(chnl->cmgrHandler.bdc ==0) { /* The remote side connects our AVRCP after we send avrcp connect req. We will reject the remote side avrcp connect req but will get a disconnect ind. The Avrcp connect req from our side will think the connect requestion is failed and remove the cmgr and rem at the same time. */ if (sqt->rm !=0) sqt->rm->discFlag = 1; return; } remDev = chnl->cmgrHandler.bdc->link; #if 1 kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_QUERY_CB, result); switch (result) { case BT_STATUS_SUCCESS: // status = AVCTP_Connect(&chnl->chnl, remDev); if(chnl->conntimer.func!=0) EVM_CancelTimer(&chnl->conntimer); chnl->conntimer.func = AVRCP_Connect_Timeout; chnl->conntimer.context = remDev; EVM_StartTimer(&chnl->conntimer, 20); /* AVRCP implementor shall handle the status report, ESI not handle it!*/ break; case BT_STATUS_CONNECTION_FAILED: break; case BT_STATUS_FAILED: AvrcpReportFailedConnect(chnl); /* Do we not indicate this back somehow? */ break; case BT_STATUS_NOSERVICES: AvrcpReportFailedConnect(chnl); break; } #endif // AVCTP_Connect(&chnl->chnl, remDev); }
static void _time_gatt_discovery_characteristic_descriptors_cb(BtGattEvent *event) { BtStatus status = BT_STATUS_FAILED; BtGattDiscoveryAllCharacteristicDescriptorsResultEvent *ptr; TimePacket *pkt; TimeCTransport *pChnl; U16 uuid = 0; ptr = (BtGattDiscoveryAllCharacteristicDescriptorsResultEvent *) event->parms; pkt = ContainingRecord(event->pGattOp, TimePacket, gatt_op); pChnl = (TimeCTransport *) pkt->chnl; switch (ptr->flag) { case BT_GATT_EVENT_RESULT_CONTINUE_DATA: OS_Report("[Time] Characteristic Descriptor found. type: %d, uuid: 0x%04x", ptr->type, ptr->uuid16); OS_Report("[Time] Char desc value handle: 0x%04x", ptr->attributeHandle); pkt->start_handle = ptr->attributeHandle; pkt->success_flag = 1; break; case BT_GATT_EVENT_RESULT_DONE_COMPLETED: OS_Report("[Time] Discovery Characteristic Descriptor with result DONE_COMPLETED"); if (pkt->success_flag != 1) { _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); return; } _time_access_value_handle_cache(pChnl, pkt->value_id, 1, &pkt->start_handle); if (pkt->value_id == GATT_TIME_CTTIME_NOTIFY) { switch (pkt->type) { case TIME_PKT_READ: status = _time_gatt_read_characteristic_descriptor(pkt, pkt->start_handle); break; case TIME_PKT_WRITE: status = _time_gatt_write_characteristic_descriptor(pkt, pkt->start_handle); break; } if (status != BT_STATUS_SUCCESS && status != BT_STATUS_PENDING) { _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); } } else { _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); } break; case BT_GATT_EVENT_RESULT_ERROR: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; case BT_GATT_EVENT_RESULT_DISCONNECT: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; } }
/*--------------------------------------------------------------------------- * TCPSTACK_ClientDeinit() *--------------------------------------------------------------------------- * * Synopsis: Deinitialize the OBEX Client transport. This function returns * success if the client is not initialized. * * Return: TRUE - Client stack deinitialized. * FALSE - Client cannot deinitialize. * */ BOOL TCPSTACK_ClientDeinit(ObTcpClientTransport *txp) { ObexClientTransports *transport = ContainingRecord(txp, ObexClientTransports, ObexClientTcpTrans); ObexAppHandle *appHndl = (ObexAppHandle*)ContainingRecord(transport, ObexClientApp, trans); if (txp->client.state == OCS_UNINITIALIZED) { return TRUE; } ASSERT(txp->client.app == appHndl); if (txp->client.state != OCS_IDLE) { return FALSE; } txp->client.state = OCS_UNINITIALIZED; txp->client.app = 0; RemoveEntryList(&txp->client.node); return TRUE; }
void time_gatt_notify_value_callback(void *user_data, BtGattEvent *event) { BtGattValueNotificationResultEvent *ptr; TimePacket *pkt; TimeSContext *pCntx; OS_Report("[Time] %s(), event: 0x%02x (should be 0x12)",__FUNCTION__, event->eType); if (event->eType != BT_GATT_OPERATOR_NOTIFICATIONS) { return; } ptr = (BtGattValueNotificationResultEvent *) event->parms; pkt = ContainingRecord(user_data, TimePacket, gatt_op); pCntx = ContainingRecord(pkt->chnl, TimeSContext, chnl); OS_Report("[Time] Notify Value with result: %d", ptr->flag); if (pCntx != NULL) { times_notify_notify_value_result(pCntx); } else { OS_Report("[Time] ERROR: %s() with NULL context", __FUNCTION__); } }
/*--------------------------------------------------------------------------- * TCPSTACK_ClientInit() *--------------------------------------------------------------------------- * * Synopsis: Initialize the OBEX Client Tcp transport. This function is * called by OBSTACK_ClientInit() in obstack.c. * * Return: OB_STATUS_SUCCESS - Initialized successfully * OB_STATUS_FAILED - Unable to bind to the stack. * */ ObStatus TCPSTACK_ClientInit(ObTcpClientTransport *txp) { ObexClientTransports *transport = ContainingRecord(txp, ObexClientTransports, ObexClientTcpTrans); ObexAppHandle *appHndl = (ObexAppHandle*)ContainingRecord(transport, ObexClientApp, trans); /* Initialize the TCP client transport */ InitTcpClientTransport(txp); ASSERT(txp->client.state == OCS_UNINITIALIZED); /* Only initialize the socket list once */ if (flags == 0) { InitializeListHead(&clientList); InitializeListHead(&serverList); flags = 1; } /* The same Async event handler is used for all clients. */ if (asyncEventHandle == 0) { if ((asyncEventHandle = InitAsyncCallback()) == 0) return OB_STATUS_FAILED; } txp->client.conn = INVALID_SOCKET; txp->client.state = OCS_IDLE; txp->client.transport.connected = &txp->client.state; txp->client.transport.funcTab = &TcpStkFuncTable; txp->client.transport.context = (ObexTransportContext)&txp->client.conn; txp->client.transport.tpType = OBEX_TP_TCP; txp->client.app = appHndl; InsertTailList(&clientList, &txp->client.node); return OB_STATUS_SUCCESS; }
/*--------------------------------------------------------------------------- * TCPSTACK_SendTxBuffer() *--------------------------------------------------------------------------- * * Synopsis: Send a buffer over the transport connection. * * Return: Status of the Send operation. */ static ObStatus TCPSTACK_SendTxBuffer(ObexTransportContext con, U8 *buff, U16 len) { ObexPacket *obp; I32 rcode; ObTcpCommonTransport *txp; ASSERT(len <= TCPSTACK_MaxTxSize(con)); /* Get the correct the TCP transport structure for this callback */ txp = ContainingRecord((SOCKET *)con, ObTcpCommonTransport, conn); rcode = send(*(SOCKET *)con, buff, len, 0); if (rcode == len) { /* Complete the transmit now */ obp = ContainingRecord(buff, ObexPacket, buffer); ASSERT(obp->buffer == buff); /* NOTE: While it is permitted to complete a transmit while in the * context of the request, there is some risk in doing this. * The risk is associated with a recursive loop that develops * between the transmit code and the transmit done code. This * code will recursively loop until the entire OBEX packet * has been sent. If stack overflow is at risk, you must * complete the packets asynchronously or use small OBEX * packet size multiples. */ ASSERT(txp); OBPROT_TxDone(txp->app, obp); return OB_STATUS_SUCCESS; } /* Tx Failed! Put the packet back into the queue. */ OBPROT_ReturnTxBuffer(buff); return OB_STATUS_FAILED; }
/************************************************************************* * FUNCTION * AVRCP_Connect_Timeout * DESCRIPTION * The function is called by Timer * It is used to delay the connect action * * PARAMETERS * Timer * RETURNS * None * LOCAL AFFECTED * *************************************************************************/ void AVRCP_Connect_Timeout(EvmTimer *Timer) { AvrcpChannel *channel; BtStatus status = BT_STATUS_FAILED; channel = ContainingRecord(Timer, AvrcpChannel, conntimer); kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_CONNECT_TIMEOUT, channel->chnl.channelType); status = AVCTP_Connect(&channel->chnl, (BtRemoteDevice *)Timer->context); OS_Report("[AVRCP] status:%d", status); if( status != BT_STATUS_PENDING ){ AvrcpReportFailedConnect(channel); } }
/*--------------------------------------------------------------------------- * TCPSTACK_DisconnectReq() *--------------------------------------------------------------------------- * * Synopsis: Disconnect the underlying transport connection. * * Return: Status of the Disconnect operation. */ static ObStatus TCPSTACK_DisconnectReq(ObexTransportContext con) { I32 rcode; ObTcpCommonTransport *txp; /* Get the correct the TCP transport structure for this callback */ txp = ContainingRecord((SOCKET *)con, ObTcpCommonTransport, conn); rcode = closesocket(*(SOCKET *)con); ASSERT(rcode != SOCKET_ERROR); /* We want an asynchronous disconnect completion so post a * disconnect message to the event handler and return PENDING. */ PostMessage(asyncEventHandle, WM_SELECT, txp->conn, FD_CLOSE); return OB_STATUS_PENDING; }
BtStatus time_gatt_notify_value(TimePacket *pkt, U8 seq_num, U32 value_id) { BtStatus status = BT_STATUS_FAILED; TimeSTransport *pChnl = pkt->chnl; TimeSContext *pCntx = ContainingRecord(pChnl, TimeSContext, chnl); U8 *data = NULL; U16 value_handle = 0x0000, size = 0; time_t rawtime; struct tm *timeinfo; OS_Report("[Time] %s(), valud_id: %d, config: 0x%x", __FUNCTION__, value_id, pChnl->cttime_notify_config); if (pCntx != NULL && (pChnl->cttime_notify_config & GATT_CHAR_PROP_NOTIFY)) { switch (value_id) { case GATT_TIME_CTTIME: // TODO: Check don't-notify conditions. Within 15 min, Time adjust < 1min, etc. time(&rawtime); timeinfo = localtime(&rawtime); _time_server_info.ct_time.year = timeinfo->tm_year + 1900; _time_server_info.ct_time.month = (U8) timeinfo->tm_mon + 1; _time_server_info.ct_time.day = (U8) timeinfo->tm_mday; _time_server_info.ct_time.hours = (U8) timeinfo->tm_hour; _time_server_info.ct_time.minutes = (U8) timeinfo->tm_min; _time_server_info.ct_time.seconds = (U8) timeinfo->tm_sec; _time_server_info.ct_time.wday = (U8) timeinfo->tm_wday + 1; _time_server_info.ct_time.frac = 0; _time_server_info.ct_time.adj_reason = pCntx->adj_reason; value_handle = ATT_HANDLE_CHARACTERISTIC_CT_TIME_VALUE; data = (U8 *) &_time_server_info.ct_time; size = sizeof(_time_server_info.ct_time); break; } status = _time_gatt_notify_value(pkt, value_handle, size, data); } return status; }
/*--------------------------------------------------------------------------- * TCPSTACK_GetTpConnInfo() *--------------------------------------------------------------------------- * * Synopsis: Retrieves OBEX transport layer connection information. This * function can be called when a transport connection is active * to retrieve connection specific information. It should be used * in conjunction with the receive flow control API to retrieve * the minimum amount of application storage space (low water mark) * used when deciding to pause and resume data flow. * * Return: TRUE - The structure was successfully completed. * FALSE - The transport is not connected. */ static BOOL TCPSTACK_GetTpConnInfo(ObexTransportContext con, ObexTpConnInfo *tpConnInfo) { SOCKADDR name; U32 len; ObTcpCommonTransport *txp; tpConnInfo->tpType = OBEX_TP_TCP; tpConnInfo->minRxBuffs = 1; tpConnInfo->maxPduSize = 1450; /* Get the local device address for the transport being used */ txp = ContainingRecord((SOCKET *)con, ObTcpCommonTransport, conn); /* We do not have a transport connection */ if (txp->state != OCS_CONNECTED) return FALSE; len = sizeof(SOCKADDR); if (getsockname(txp->conn, &name, &len) != 0) return FALSE; ASSERT(len == 16); /* Get the server IP address and store it Big Endian */ OS_MemCopy(txp->devAddr, name.sa_data+2, 4); tpConnInfo->devAddr = txp->devAddr; return TRUE; }
static void _time_gatt_notify_query_result(TimePacket *pkt, U8 *data, U8 len, U8 result) { TimeCContext *pCntx; if (pkt == NULL) { OS_Report("[Time] Error: %s with NULL packet", __FUNCTION__); return; } if (pkt->chnl == NULL) { OS_Report("[Time] Error: %s with NULL channel", __FUNCTION__); return; } pCntx = ContainingRecord(pkt->chnl, TimeCContext, chnl); switch (pkt->value_id) { case GATT_TIME_CTTIME: if (result == BT_STATUS_SUCCESS && len > 9) { pCntx->date_time[0] = (0x00ff & data[0]) | (0xff00 & (data[1] << 8)); pCntx->date_time[1] = (U16) data[2]; pCntx->date_time[2] = (U16) data[3]; pCntx->date_time[3] = (U16) data[4]; pCntx->date_time[4] = (U16) data[5]; pCntx->date_time[5] = (U16) data[6]; pCntx->day_of_week = data[7]; pCntx->frac = data[8]; pCntx->adj_reason = data[9]; timec_notify_read_remote_value_result(pCntx, result, pkt); } else { timec_notify_read_remote_value_result(pCntx, BT_STATUS_FAILED, pkt); } break; case GATT_TIME_CTTIME_NOTIFY: switch (pkt->type) { case TIME_PKT_READ: if (result == BT_STATUS_SUCCESS && len > 1) { pCntx->cttime_notify_config = (0x00ff & data[0]) | (0xff00 & (data[1] << 8)); timec_notify_read_remote_value_result(pCntx, result, pkt); } else { timec_notify_read_remote_value_result(pCntx, BT_STATUS_FAILED, pkt); } break; case TIME_PKT_WRITE: timec_notify_write_remote_value_result(pCntx, result, pkt); break; } break; case GATT_TIME_LOCAL_TIME_INFO: if (result == BT_STATUS_SUCCESS && len > 1) { pCntx->time_zone = data[0]; pCntx->dst = data[1]; timec_notify_read_remote_value_result(pCntx, result, pkt); } else { timec_notify_read_remote_value_result(pCntx, BT_STATUS_FAILED, pkt); } break; case GATT_TIME_REF_TIME_INFO: if (result == BT_STATUS_SUCCESS && len > 3) { pCntx->time_source = data[0]; pCntx->accuracy = data[1]; pCntx->days_since_update = data[2]; pCntx->hours_since_update = data[3]; timec_notify_read_remote_value_result(pCntx, result, pkt); } else { timec_notify_read_remote_value_result(pCntx, BT_STATUS_FAILED, pkt); } break; case GATT_TIME_DST_INFO: if (result == BT_STATUS_SUCCESS && len > 7) { pCntx->date_time[0] = (0x00ff & data[0]) | (0xff00 & (data[1] << 8)); pCntx->date_time[1] = (U16) data[2]; pCntx->date_time[2] = (U16) data[3]; pCntx->date_time[3] = (U16) data[4]; pCntx->date_time[4] = (U16) data[5]; pCntx->date_time[5] = (U16) data[6]; pCntx->dst = data[7]; timec_notify_read_remote_value_result(pCntx, result, pkt); } else { timec_notify_read_remote_value_result(pCntx, BT_STATUS_FAILED, pkt); } break; case GATT_TIME_SERVER_UPDATE_CTRL: timec_notify_write_remote_value_result(pCntx, result, pkt); break; case GATT_TIME_SERVER_UPDATE_STATE: if (result == BT_STATUS_SUCCESS && len > 1) { timec_notify_read_remote_value_result(pCntx, result, pkt); } else { timec_notify_read_remote_value_result(pCntx, BT_STATUS_FAILED, pkt); } break; } }
/*--------------------------------------------------------------------------- * 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; } }
/*--------------------------------------------------------------------------- * ChnServiceConnectionCallback() *--------------------------------------------------------------------------- * * Synopsis: Called by device manager with link state events. * * Return: (See header file) * */ void ChnServiceConnectionCallback(CmgrHandler *Handler, CmgrEvent Event, BtStatus Status) { ChnChannel *Channel = ContainingRecord(Handler, ChnChannel, cmgrHandler); BtStatus return_code; Report(("+ ChnServiceConnectionCallback: Event=%d, Status=%d.", Event, Status)); switch (Event) { case CMEVENT_DATA_LINK_CON_CNF: DBG_PRINT_EVENT(("[CHN][EVENT] CMGR Event : CMEVENT_DATA_LINK_CON_CNF, Status=%d.", Status)); if(ChnGetSubstate(Channel) == CHN_SUBSTATE_CONN_OUT1) { if (Status == BT_STATUS_SUCCESS) { Channel->linkFlags |= CHN_LINK_ACL; /* FLOW : Start SDP query */ if ((return_code = ChnStartServiceQuery(Channel, BSQM_FIRST)) == BT_STATUS_PENDING) { ChnChangeSubstate(Channel, CHN_SUBSTATE_CONN_OUT2); } else { ChnChangeSubstate(Channel, CHN_SUBSTATE_CLOSED1); } } else { /* This event shall not be received in other substates other than C1 */ ChnChangeSubstate(Channel, CHN_SUBSTATE_CLOSED1); } } else if(ChnGetSubstate(Channel) == CHN_SUBSTATE_DISC1) { ChnDisconnecting(Channel); } else { DBG_PRINT_ERROR( ("[CHN][ERR] Unexpected substate==0x%X - (%s,%d)", ChnGetSubstate(Channel), __FILE__, __LINE__) ); ChnChangeSubstate(Channel, CHN_SUBSTATE_CLOSED1); } break; case CMEVENT_DATA_LINK_DIS: /* We shall never run into this case */ DBG_PRINT_EVENT(("[CHN][EVENT] CMGR Event : CMEVENT_DATA_LINK_DIS, Status=%d.", Status)); DBG_PRINT_ERROR( ("[CHN][ERR] Unexpected substate==0x%X - (%s,%d)", ChnGetSubstate(Channel), __FILE__, __LINE__) ); ChnCloseChannel(Channel); break; case CMEVENT_AUDIO_LINK_CON: DBG_PRINT_EVENT(("[CHN][EVENT] CMGR Event : CMEVENT_AUDIO_LINK_CON, Status=%d.", Status)); /* Clear SCO connecting flag */ Channel->linkFlags &= ~CHN_LINK_SCO_CONNECTING; ChnAppCallback(Channel, CHN_EVENT_AUDIO_CONNECTED, Status, (U32)&Channel->cmgrHandler.bdc->link->bdAddr); if(ChnGetSubstate(Channel) == CHN_SUBSTATE_SLC1) { /* Remote connect SCO link */ /* It could happen in SLC1 but no action needed */ } else if(ChnGetSubstate(Channel) == CHN_SUBSTATE_SLC2) { ChnChangeSubstate(Channel, CHN_SUBSTATE_SLC1); } else if(ChnGetSubstate(Channel) == CHN_SUBSTATE_DISC1) { ChnDisconnecting(Channel); } else { DBG_PRINT_ERROR( ("[CHN][ERR] Unexpected substate==0x%X - (%s,%d)", ChnGetSubstate(Channel), __FILE__, __LINE__) ); } break; case CMEVENT_AUDIO_LINK_DIS: DBG_PRINT_EVENT(("[CHN][EVENT] CMGR Event : CMEVENT_AUDIO_LINK_DIS, Status=%d.", Status)); /* Clear SCO disconnecting flag */ Channel->linkFlags &= ~CHN_LINK_SCO_DISCONNECTING; ChnAppCallback(Channel, CHN_EVENT_AUDIO_DISCONNECTED, Status, (U32)&Channel->cmgrHandler.bdc->link->bdAddr); if(ChnGetSubstate(Channel) == CHN_SUBSTATE_SLC1) { /* Remote disconnect SCO link */ /* It could happen in SLC1 but no action needed */ } else if(ChnGetSubstate(Channel) == CHN_SUBSTATE_SLC2) { ChnChangeSubstate(Channel, CHN_SUBSTATE_SLC1); } else if(ChnGetSubstate(Channel) == CHN_SUBSTATE_DISC1) { ChnDisconnecting(Channel); } else { DBG_PRINT_ERROR( ("[CHN][ERR] Unexpected substate==0x%X - (%s,%d)", ChnGetSubstate(Channel), __FILE__, __LINE__) ); } break; #if BT_SCO_HCI_DATA == XA_ENABLED case CMEVENT_AUDIO_DATA: DBG_PRINT_EVENT(("[CHN][EVENT] CMGR Event : CMEVENT_AUDIO_DATA, Status=%d.", Status)); ChnAppCallback(Channel, CHN_EVENT_AUDIO_DATA, Status, (U32)&Handler->audioData); break; case CMEVENT_AUDIO_DATA_SENT: DBG_PRINT_EVENT(("[CHN][EVENT] CMGR Event : CMEVENT_AUDIO_DATA_SENT, Status=%d.", Status)); ChnAppCallback(Channel, CHN_EVENT_AUDIO_DATA_SENT, Status, (U32)&Handler->audioPacket); break; #endif } Report(("- ChnServiceConnectionCallback.")); }
/*--------------------------------------------------------------------------- * TCPSTACK_ServerInit() *--------------------------------------------------------------------------- * * Synopsis: Initialize the OBEX Server Tcp transport. This function will * usually perform service registration, where necessary. This * function is called by OBSTACK_ServerInit() in obstack.c. * * Return: OB_STATUS_SUCCESS - Initialized successfully * OB_STATUS_FAILED - Unable to bind to the stack. * OB_STATUS_NO_RESOURCES - Out of resources * */ ObStatus TCPSTACK_ServerInit(ObTcpServerTransport *txp) { I32 rcode; I32 myAddrLen; SOCKADDR_IN myAddr = {AF_INET, htons(650), INADDR_ANY, 0}; ObexServerTransports *transport = ContainingRecord(txp, ObexServerTransports, ObexServerTcpTrans); ObexAppHandle *appHndl = (ObexAppHandle*)ContainingRecord(transport, ObexServerApp, trans); /* Initialize the TCP server transport */ InitTcpServerTransport(txp); ASSERT (txp->server.state == OCS_UNINITIALIZED); /* Only initialize the socket list once */ if (flags == 0) { InitializeListHead(&clientList); InitializeListHead(&serverList); flags = 1; } /* The same Async event handler is used for all servers. */ if (asyncEventHandle == 0) { if ((asyncEventHandle = InitAsyncCallback()) == 0) return OB_STATUS_FAILED; } txp->server.conn = INVALID_SOCKET; txp->server.transport.connected = &txp->server.state; txp->server.transport.funcTab = &TcpStkFuncTable; txp->server.transport.context = (ObexTransportContext)&txp->server.conn; txp->server.transport.tpType = OBEX_TP_TCP; /* Register TCP Server by opening OBEX Server port */ txp->serverReg = socket(AF_INET, SOCK_STREAM, 0); if (txp->serverReg == INVALID_SOCKET) { return OB_STATUS_NO_RESOURCES; } /* Try for the OBEX TCP Port first, if it's busy, any port will do. */ rcode = bind(txp->serverReg, (struct sockaddr *)&myAddr, sizeof(SOCKADDR_IN)); if (rcode == SOCKET_ERROR) { myAddr.sin_port = 0; rcode = bind(txp->serverReg, (struct sockaddr *)&myAddr, sizeof(SOCKADDR_IN)); } /* Record the port the server is listening on */ myAddrLen = sizeof(struct sockaddr); getsockname(txp->serverReg, (struct sockaddr *)&myAddr, &myAddrLen); txp->serverPort = ntohs(myAddr.sin_port); if (rcode != SOCKET_ERROR) { rcode = listen(txp->serverReg, 1); if (rcode != SOCKET_ERROR) { rcode = WSAAsyncSelect(txp->serverReg, asyncEventHandle, WM_SELECT, FD_ACCEPT|FD_CLOSE); ASSERT(rcode != SOCKET_ERROR); txp->server.state = OCS_IDLE; txp->server.app = appHndl; InsertTailList(&serverList, &txp->server.node); return OB_STATUS_SUCCESS; } } kal_trace(BT_TRACE_G6_OBEX,TCPSTACK_SOCKET_FAILURExD ,WSAGetLastError()); closesocket(txp->serverReg); txp->serverReg = INVALID_SOCKET; return OB_STATUS_FAILED; }
static void timec_gatt_connection_callback(void *handler, BtGattEvent *event) { TimeCContext *pCntx; switch (event->eType) { case BT_GATT_APP_EVENT_CONNECTED: OS_Report("[Time] BT_GATT_APP_EVENT_CONNECTED"); if (event->link && _cur_timec_chnl) { pCntx = ContainingRecord(_cur_timec_chnl, TimeCContext, chnl); timec_notify_connect_result(pCntx, BT_STATUS_SUCCESS); } else { OS_Report("[Time] Ignore. event->link: 0x%x, _cur_timec_chnl: 0x%x", event->link, _cur_timec_chnl); } break; case BT_GATT_APP_EVENT_DISCONNECTED: OS_Report("[Time] BT_GATT_APP_EVENT_DISCONNECTED"); if (event->link && _cur_timec_chnl) { pCntx = ContainingRecord(_cur_timec_chnl, TimeCContext, chnl); timec_notify_disconnect_result(pCntx, BT_STATUS_SUCCESS); _cur_timec_chnl = NULL; } else { OS_Report("[Time] Ignore. event->link: 0x%x, _cur_timec_chnl: 0x%x", event->link); } break; case BT_GATT_APP_EVENT_VALUE_NOTIFICATION: OS_Report("[Time] BT_GATT_APP_EVENT_VALUE_NOTIFICATION"); if (event->link && _cur_timec_chnl) { BtGattValueNotificationEvent *ptr = (BtGattValueNotificationEvent *) event->parms; // TODO: Compare the handle value with the cached one if (ptr->attributeHandle != ATT_HANDLE_CHARACTERISTIC_CT_TIME_VALUE) { OS_Report("[Time] Unrecognized handle: %d, ignore", ptr->attributeHandle); return; } if (ptr->attributeValue && ptr->attributeValueLen > 9) { pCntx = ContainingRecord(_cur_timec_chnl, TimeCContext, chnl); pCntx->date_time[0] = (0x00ff & ptr->attributeValue[0]) | (0xff00 & (ptr->attributeValue[1] << 8)); pCntx->date_time[1] = (U16) ptr->attributeValue[2]; pCntx->date_time[2] = (U16) ptr->attributeValue[3]; pCntx->date_time[3] = (U16) ptr->attributeValue[4]; pCntx->date_time[4] = (U16) ptr->attributeValue[5]; pCntx->date_time[5] = (U16) ptr->attributeValue[6]; pCntx->day_of_week = ptr->attributeValue[7]; pCntx->frac = ptr->attributeValue[8]; pCntx->adj_reason = ptr->attributeValue[9]; timec_notify_server_notification(pCntx, GATT_TIME_CTTIME); } } else { OS_Report("[Time] Ignore. event->link: 0x%x, _cur_timec_chnl: 0x%x", event->link); } break; case BT_GATT_APP_EVENT_VALUE_INDICATION: OS_Report("[Time] BT_GATT_APP_EVENT_VALUE_INDICATION"); break; default: break; } }
/************************************************************************* * FUNCTION * avrcpQueryCTCallback * DESCRIPTION * The function is called by SDAP to indicate the profiles the search result * Modified by MTK Dlight mtk01239 * * PARAMETERS * sqt : SdpQueryToken contains information such as remote device information. uuid... * result : The service search result. * serv_chn: It is not used in AVRCP profile * RETURNS * None * LOCAL AFFECTED * *************************************************************************/ void avrcpQueryCTCallback(SdpQueryToken *sqt, U8 result, U8 attribute_index, U8 *attribute_value) { SdpQueryToken *token; BtRemoteDevice *remDev; U16 feature = 0; BtStatus status = 0; AvrcpChannel *chnl = ContainingRecord( sqt, AvrcpChannel, sdpQueryToken ); token = sqt; if(chnl->cmgrHandler.bdc ==0) { /* The remote side connects our AVRCP after we send avrcp connect req. We will reject the remote side avrcp connect req but will get a disconnect ind. The Avrcp connect req from our side will think the connect requestion is failed and remove the cmgr and rem at the same time. */ if (sqt->rm !=0) sqt->rm->discFlag = 1; return; } remDev = chnl->cmgrHandler.bdc->link; if( chnl ){ /// has do the search chnl->remoteCTSdp.ctValid = TRUE; } kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_CT_CALLBACK , result, attribute_index); switch (result) { case BT_STATUS_SUCCESS: { /// remote has a TG record chnl->remoteCTSdp.ctAvailable= TRUE; switch( avrcp_sdp_attribute_id_list[attribute_index] ){ case AID_PROTOCOL_DESC_LIST: { /// update the result chnl->remoteCTSdp.ctVersion = BEtoHost16(attribute_value); } break; case AID_SUPPORTED_FEATURES: { /// update the result chnl->remoteCTSdp.ctFeatureFlag = BEtoHost16(attribute_value); OS_Report("[AVRCP] SDP attr_value[0]:0x%x attr_value[1]:0x%x attr_value[2]:0x%x attr_value[3]:0x%x", attribute_value[0], attribute_value[1], attribute_value[2], attribute_value[3]); chnl->remoteCTSdp.ctSupportBrowse = chnl->remoteCTSdp.ctFeatureFlag && 0x40; OS_Report("[AVRCP] SDP chnl->remoteCTSdp.ctFeatureFlag:%d", chnl->remoteCTSdp.ctFeatureFlag); /// search is finished. try to connect if( 2 == avrcp_sdp_attribute_num ){ if( chnl->connFlag == 1 ){ if(chnl->conntimer.func!=0) EVM_CancelTimer(&chnl->conntimer); chnl->conntimer.func = AVRCP_Connect_Timeout; chnl->conntimer.context = remDev; EVM_StartTimer(&chnl->conntimer, 20); AVRCP_UtilAVRCPSDPQueryInd(chnl, 0, chnl->remoteTGSdp.tgVersion, chnl->remoteTGSdp.tgFeatureFlag, chnl->remoteCTSdp.ctVersion, chnl->remoteCTSdp.ctFeatureFlag); } } } break; case AID_BT_PROFILE_DESC_LIST: //case AID_ADDITIONAL_PROT_DESC_LISTS: { chnl->remoteCTSdp.ctVersion = BEtoHost16(attribute_value); status = parseAvrcpVersion(attribute_value, &feature); if( BT_STATUS_SUCCESS == status ){ chnl->remoteCTSdp.ctVersion = feature; }else{ OS_Report("[AVRCP] SDP error status:%d", status); } kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_CT_INFO , chnl->remoteCTSdp.ctAvailable, chnl->remoteCTSdp.ctVersion, chnl->remoteCTSdp.ctFeatureFlag, chnl->remoteCTSdp.ctSupportBrowse); OS_Report("[AVRCP] SDP ctVersion:%d", chnl->remoteCTSdp.ctVersion); if( chnl->connFlag == 1 ){ if(chnl->conntimer.func!=0) EVM_CancelTimer(&chnl->conntimer); chnl->conntimer.func = AVRCP_Connect_Timeout; chnl->conntimer.context = remDev; EVM_StartTimer(&chnl->conntimer, 20); } AVRCP_UtilAVRCPSDPQueryInd(chnl, 0, chnl->remoteTGSdp.tgVersion, chnl->remoteTGSdp.tgFeatureFlag, chnl->remoteCTSdp.ctVersion, chnl->remoteCTSdp.ctFeatureFlag); } break; } } break; case BT_STATUS_CONNECTION_FAILED: case BT_STATUS_FAILED: case BT_STATUS_NOSERVICES: { kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_CT_INFO , chnl->remoteCTSdp.ctAvailable, chnl->remoteCTSdp.ctVersion, chnl->remoteCTSdp.ctFeatureFlag, chnl->remoteCTSdp.ctSupportBrowse); /// NO TG record available => search CT /// One of CT or TG is available => try to conne ct if( FALSE == chnl->remoteCTSdp.ctAvailable && FALSE == chnl->remoteTGSdp.tgAvailable ){ AvrcpReportFailedConnect(chnl); }else{ /// After a TG connect if(chnl->conntimer.func!=0) EVM_CancelTimer(&chnl->conntimer); chnl->conntimer.func = AVRCP_Connect_Timeout; chnl->conntimer.context = remDev; EVM_StartTimer(&chnl->conntimer, 20); } AVRCP_UtilAVRCPSDPQueryInd(chnl, 1, 0, 0, 0 , 0); } break; } }
/************************************************************************* * FUNCTION * avrcpQueryTGCallback * DESCRIPTION * The function is called by SDAP to indicate the profiles the search result * * PARAMETERS * sqt : SdpQueryToken contains information such as remote device information. uuid... * result : The service search result. * serv_chn: It is not used in AVRCP profile * RETURNS * None * LOCAL AFFECTED * *************************************************************************/ void avrcpQueryTGCallback(SdpQueryToken *sqt, U8 result, U8 attribute_index, U8 *attribute_value) { SdpQueryToken *token; BtRemoteDevice *remDev; AvrcpChannel *chnl = ContainingRecord( sqt, AvrcpChannel, sdpQueryToken ); token = sqt; if(chnl->cmgrHandler.bdc ==0) { /* The remote side connects our AVRCP after we send avrcp connect req. We will reject the remote side avrcp connect req but will get a disconnect ind. The Avrcp connect req from our side will think the connect requestion is failed and remove the cmgr and rem at the same time. */ if (sqt->rm !=0) sqt->rm->discFlag = 1; return; } if( chnl ){ /// has do the search chnl->remoteTGSdp.tgValid = TRUE; } remDev = chnl->cmgrHandler.bdc->link; kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_TG_CALLBACK , result, attribute_index); switch (result) { case BT_STATUS_SUCCESS: { /// remote has a TG record chnl->remoteTGSdp.tgAvailable= TRUE; switch( avrcp_sdp_attribute_id_list[attribute_index] ){ case AID_PROTOCOL_DESC_LIST: { /// update the result chnl->remoteTGSdp.tgVersion = BEtoHost16(attribute_value); } break; case AID_SUPPORTED_FEATURES: { /// update the result chnl->remoteTGSdp.tgFeatureFlag = BEtoHost16(attribute_value); /// search is finished. try to connect if( 2 == avrcp_sdp_attribute_num ){ if( chnl->connFlag == 1 ){ // pending connect if(chnl->conntimer.func!=0) EVM_CancelTimer(&chnl->conntimer); chnl->conntimer.func = AVRCP_Connect_Timeout; chnl->conntimer.context = remDev; EVM_StartTimer(&chnl->conntimer, 20); } AVRCP_UtilAVRCPSDPQueryInd(chnl, 0, chnl->remoteCTSdp.ctFeatureFlag, chnl->remoteTGSdp.tgFeatureFlag); } } break; case AID_BT_PROFILE_DESC_LIST: //AID_ADDITIONAL_PROT_DESC_LISTS: { chnl->remoteTGSdp.tgSupportBrowse = BEtoHost16(attribute_value); kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_TG_INFO , chnl->remoteTGSdp.tgVersion, chnl->remoteTGSdp.tgFeatureFlag, chnl->remoteTGSdp.tgSupportBrowse); if( chnl->connFlag == 1 ){ // pending connect if(chnl->conntimer.func!=0) EVM_CancelTimer(&chnl->conntimer); chnl->conntimer.func = AVRCP_Connect_Timeout; chnl->conntimer.context = remDev; EVM_StartTimer(&chnl->conntimer, 20); } AVRCP_UtilAVRCPSDPQueryInd(chnl, 0, chnl->remoteTGSdp.tgFeatureFlag, chnl->remoteCTSdp.ctFeatureFlag); } break; } } /* AVRCP implementor shall handle the status report, ESI not handle it!*/ break; case BT_STATUS_CONNECTION_FAILED: case BT_STATUS_FAILED: case BT_STATUS_NOSERVICES: /// NO CT or TG record available => report fail /// One of CT or TG is available => try to connect kal_trace( BT_TRACE_G8_AVRCP, BT_AVRCP_SDP_TG_INFO , chnl->remoteTGSdp.tgAvailable, chnl->remoteTGSdp.tgVersion, chnl->remoteTGSdp.tgFeatureFlag, chnl->remoteTGSdp.tgSupportBrowse); if( FALSE == chnl->remoteCTSdp.ctAvailable && FALSE == chnl->remoteTGSdp.tgAvailable ){ // search remote's CT role and try to connect it AvrcpStartMultiServiceQuery(chnl, BSQM_FIRST, AVRCP_TG); // local is TG }else{ /// After a TG connect if(chnl->conntimer.func!=0) EVM_CancelTimer(&chnl->conntimer); chnl->conntimer.func = AVRCP_Connect_Timeout; chnl->conntimer.context = remDev; EVM_StartTimer(&chnl->conntimer, 20); } AVRCP_UtilAVRCPSDPQueryInd(chnl, 1, 0, 0); break; } }
static void _time_gatt_discovery_primary_service_by_uuid_cb(BtGattEvent *event) { BtStatus status; BtGattDiscoveryAllPrimaryServiceResultEvent *ptr; TimePacket *pkt; TimeCTransport *pChnl; U16 uuid = 0; ptr = (BtGattDiscoveryAllPrimaryServiceResultEvent *) event->parms; pkt = ContainingRecord(event->pGattOp, TimePacket, gatt_op); pChnl = (TimeCTransport *) pkt->chnl; switch (ptr->flag) { case BT_GATT_EVENT_RESULT_CONTINUE_DATA: // There should be only one instance of any service of Time profile OS_Report("[Time] Primary Service found. type: %d, uuid: 0x%04x", ptr->type, ptr->uuid2); OS_Report("[Time] Handle reange: 0x%04x to 0x%04x", ptr->startHandle, ptr->endHandle); pkt->start_handle = ptr->startHandle; pkt->end_handle = ptr->endHandle; pkt->success_flag = 1; break; case BT_GATT_EVENT_RESULT_DONE_COMPLETED: OS_Report("[Time] Discovery Primary Service by UUID with result DONE_COMPLETED. success: %d", pkt->success_flag); if (pkt->success_flag == 1) { _time_access_service_handle_cache(pChnl, pkt->value_id, 1, &pkt->start_handle, &pkt->end_handle); switch (pkt->value_id) { case GATT_TIME_CTTIME: case GATT_TIME_CTTIME_NOTIFY: uuid = BT_UUID_CT_TIME; break; case GATT_TIME_LOCAL_TIME_INFO: uuid = BT_UUID_LOCAL_TIME_INFO; break; case GATT_TIME_REF_TIME_INFO: uuid = BT_UUID_REF_TIME_INFO; break; case GATT_TIME_DST_INFO: uuid = BT_UUID_TIME_WITH_DST; break; case GATT_TIME_SERVER_UPDATE_CTRL: uuid = BT_UUID_TIME_UPDATE_CONTROL_POINT; break; case GATT_TIME_SERVER_UPDATE_STATE: uuid = BT_UUID_TIME_UPDATE_STATE; break; default: break; } status = _time_gatt_discovery_characteristic_by_uuid( pkt, uuid, pkt->start_handle, pkt->end_handle); OS_Report("[Time] Discovery Characteristic, status: %d", status); if (status != BT_STATUS_PENDING && status != BT_STATUS_SUCCESS) _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); } else { _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); } break; case BT_GATT_EVENT_RESULT_ERROR: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; case BT_GATT_EVENT_RESULT_DISCONNECT: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; } }
static void _time_gatt_discovery_characteristic_by_uuid_cb(BtGattEvent *event) { BtStatus status = BT_STATUS_FAILED; BtGattDiscoveryCharacteristicByUUIDResultEvent *ptr; TimePacket *pkt; TimeCTransport *pChnl; U16 dsp_handle; ptr = (BtGattDiscoveryCharacteristicByUUIDResultEvent *) event->parms; pkt = ContainingRecord(event->pGattOp, TimePacket, gatt_op); pChnl = (TimeCTransport *) pkt->chnl; switch (ptr->flag) { case BT_GATT_EVENT_RESULT_CONTINUE_DATA: OS_Report("[Time] Characteristic found. type: %d, uuid: 0x%04x", ptr->type, ptr->charUUID); OS_Report("[Time] Char handle: 0x%04x, property: 0x%02x ", ptr->attributeHandle, ptr->charProperty); OS_Report("[Time] Char value handle: 0x%04x", ptr->charValueAttributeHandle); pkt->start_handle = ptr->charValueAttributeHandle; pkt->success_flag = 1; break; case BT_GATT_EVENT_RESULT_DONE_COMPLETED: OS_Report("[Time] Discovery Characteristic by UUID with result DONE_COMPLETED. success: %d", pkt->success_flag); if (pkt->success_flag == 1) { switch (pkt->value_id) { case GATT_TIME_CTTIME: dsp_handle = pkt->start_handle + 1; _time_access_value_handle_cache(pChnl, pkt->value_id, 1, &pkt->start_handle); _time_access_value_handle_cache(pChnl, GATT_TIME_CTTIME_NOTIFY, 1, &dsp_handle); status = _time_gatt_read_characteristic_value(pkt, pkt->start_handle); break; case GATT_TIME_CTTIME_NOTIFY: dsp_handle = pkt->start_handle + 1; _time_access_value_handle_cache(pChnl, GATT_TIME_CTTIME, 1, &pkt->start_handle); _time_access_value_handle_cache(pChnl, pkt->value_id, 1, &dsp_handle); if (pkt->type == TIME_PKT_READ) { status = _time_gatt_read_characteristic_descriptor(pkt, pkt->start_handle + 1); } else { // TIME_PKT_WRITE status = _time_gatt_write_characteristic_descriptor(pkt, pkt->start_handle + 1); } break; case GATT_TIME_LOCAL_TIME_INFO: case GATT_TIME_REF_TIME_INFO: case GATT_TIME_DST_INFO: case GATT_TIME_SERVER_UPDATE_STATE: _time_access_value_handle_cache(pChnl, pkt->value_id, 1, &pkt->start_handle); status = _time_gatt_read_characteristic_value(pkt, pkt->start_handle); break; case GATT_TIME_SERVER_UPDATE_CTRL: _time_access_value_handle_cache(pChnl, pkt->value_id, 1, &pkt->start_handle); status = _time_gatt_write_without_response(pkt, pkt->start_handle); break; default: break; } if (status != BT_STATUS_PENDING && status != BT_STATUS_SUCCESS) _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); } else { _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); } break; case BT_GATT_EVENT_RESULT_ERROR: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; case BT_GATT_EVENT_RESULT_DISCONNECT: _time_gatt_notify_query_result(pkt, 0, 0, BT_STATUS_FAILED); break; } }
/***************************************************************************** * FUNCTION * RfL2Callback * DESCRIPTION * Callback routine for L2CAP connections. * PARAMETERS * L2ChannelId [IN] * info [IN] * RETURNS * void *****************************************************************************/ void A2MPMainChannelL2Callback(L2capChannelId L2ChannelId, L2capCallbackParms *info) { A2MP_MAIN_CONN *main_channel; A2MP_CONN *amp_psm_channel; BtRxPacket *rxPacket; U8 i=0; Report(("A2MPMainChannelL2Callback:%d,L2ChannelId:%d", info->event,L2ChannelId)); switch (info->event) { case L2EVENT_DISCONNECTED: break; case L2EVENT_NOTIFY_AMP_PAL_CHANNEL_DISCONNECTED: main_channel = A2MP_FindMainChannel(info->aclLink); if(main_channel !=0) { Report(("The L2ChannelId:%d",L2ChannelId)); Report(("The main_channel->localCid:%d",main_channel->localCid)); if(info->ptrs.NotifyL2CAPA2MPPDisconnected.localCid != main_channel->localCid) // ME_DisconnectPhysicalLink(&info->aclLink->remoteWifiAMP, 0x13); { BTA2MP_PhysicalLinkClose(info->aclLink); } } break; case L2EVENT_NOTIFY_AMP_NORMAL_CHANNEL_DISCONNECTED: main_channel = A2MP_FindMainChannel(info->aclLink); if(main_channel !=0) { Report(("The L2ChannelId:%d",L2ChannelId)); Report(("The main_channel->localCid:%d",main_channel->localCid)); for(i=0; i< BT_AMP_SUPPORTED_LOGICAL_CHANNEL; i++) { Report(("%d,%d,%d,%d",main_channel->remDev->remoteWifiAMP.logicalLink[i].l2cap_id, main_channel->remDev->remoteWifiAMP.logicalLink[i].logical_link_sate, main_channel->remDev->remoteWifiAMP.logicalLink[i].logical_link_type, info->ptrs.NotifyL2CAPA2MPPDisconnected.localCid)); if((main_channel->remDev->remoteWifiAMP.logicalLink[i].l2cap_id == info->ptrs.NotifyL2CAPA2MPPDisconnected.localCid) && (main_channel->remDev->remoteWifiAMP.logicalLink[i].logical_link_sate == BDS_CONNECTED) && (main_channel->remDev->remoteWifiAMP.logicalLink[i].logical_link_type > 0x01)) { ME_DisconnectLogicalLink(&info->aclLink->remoteWifiAMP, main_channel->remDev->remoteWifiAMP.logicalLink[i].logical_link_handle); break; } } } break; case L2EVENT_AMP_CHANNEL_DETECTED: if(info->status == 0x00) { if(info->aclLink->remoteWifiAMP.detected == 0) { BtA2MPDiscoveryReq discoveryReq; U8 extendedFeatureMask[2]; /* Start AMP discovery procedure. */ info->aclLink->remoteWifiAMP.detected = 1; info->aclLink->remoteWifiAMP.exists = 0; discoveryReq.mtu = 670; discoveryReq.extendedFeatureMaskSize = 0; extendedFeatureMask[0] = 0x00; extendedFeatureMask[1] = 0x00; discoveryReq.extendedFeatureMask = (U8 *)extendedFeatureMask; discoveryReq.extendedFeatureMaskSize = 2; BTA2MP_SendDiscoveryRequest(info->aclLink, &discoveryReq); } else { Report(("Remote A2MP feature detected before, no A2MP operation")); } } break; case L2EVENT_PACKET_HANDLED: { BtA2MPPacket *a2mptxPacket; main_channel = A2MP_FindMainChannel(info->aclLink); if (info->ptrs.packet->flags & BTP_FLAG_LSYSTEM) Assert(0); a2mptxPacket = ContainingRecord(info->ptrs.packet, BtA2MPPacket, btPacket); InsertTailList(&main_channel->freeTtxPacketsList, &(a2mptxPacket->node)); } break; #if L2CAP_FLOW_NON_BASIC_MODE == XA_ENABLED case L2EVENT_FLOW_DATA_IND: Report(("L2EVENT_FLOW_DATA_IND")); main_channel = A2MP_FindMainChannel(info->aclLink); rxPacket = (BtRxPacket *)RemoveHeadList(&main_channel->receivedPacketsList); info->ptrs.data = rxPacket->data; info->dataLen = rxPacket->dataLen; BTA2MP_RecvDataInd(info->aclLink, info->ptrs.data, info->dataLen); rxPacket->dataLen = 0; InsertTailList(&main_channel->rxPacketsBufferList, &rxPacket->node); L2CAP_UpdateSduDataBufferSeq(main_channel->localCid); break; #endif case L2EVENT_LOCKSTEP_CONFIG_REQ: Report(("info->ptrs.lockstepConfigReq.createChannelnitiator:%d",info->ptrs.lockstepConfigReq.createChannelnitiator)); Assert(0); break; case L2EVENT_MOVE_CHANNEL_REQ: /* info->ptrs.moveChannelReq; */ amp_psm_channel = A2MP_FindPSMChannelByCid(L2ChannelId); break; case L2EVENT_MOVE_CHANNEL_RSP: amp_psm_channel = A2MP_FindPSMChannelByCid(L2ChannelId); /* info->ptrs.moveChannelRsp.result; */ break; case L2EVENT_MOVE_CHANNEL_CNF_REQ: amp_psm_channel = A2MP_FindPSMChannelByCid(L2ChannelId); /* info->ptrs.moveChannelCnfReq.result; */ break; case L2EVENT_MOVE_CHANNEL_CNF_RSP: amp_psm_channel = A2MP_FindPSMChannelByCid(L2ChannelId); break; } }