/************************************************************************* * 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; } }
/*--------------------------------------------------------------------------- * BipInitiatorCallback *--------------------------------------------------------------------------- * * Synopsis: This function processes Initiator events. * * Return: void * */ void BipInitiatorCallback(GoepClientEvent *event) { BipObexClient *client; BipCallbackParms parms; BipImgHandlePtr ih; U8 *p; parms.obex.client = FindBipInitiator(event->handler); if (parms.obex.client == 0) { kal_trace(BT_TRACE_G6_OBEX,BT_BIP_INITIATOR_NOT_FOUND); return; } client = parms.obex.client; switch (event->event) { case GOEP_EVENT_TP_CONNECTED: /* The transport layer connection is up. Send an OBEX Connect. */ //Report(("BIP: Client: Transport Layer connection established.\n")); GOEP_Connect(&client->cApp, &client->connect); break; case GOEP_EVENT_TP_DISCONNECTED: /* The transport layer connection has been disconnected. */ //Report(("BIP: Client: The transport connection has been disconnected.\n")); if (client->state == BIPCHS_CONNECTING) { BipAppCallBack(&parms, event->reason, BIPINITIATOR_FAILED); } client->data = &client->tData; client->data->bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, OB_STATUS_DISCONNECT, BIPINITIATOR_COMPLETE); client->tData.offset = client->tData.totLen = 0; if (client->pushPull.object) { BIPOBS_Close((BipObStoreHandle *)&client->pushPull.object); } break; case GOEP_EVENT_COMPLETE: /* The requested operation has completed. */ switch (event->oper) { case GOEP_OPER_CONNECT: /* OBEX connection is established. */ client->state = BIPCHS_CONNECTED; //Report(("BIP: Client: OBEX Connect Operation is complete.\n")); client->data->bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, OB_STATUS_SUCCESS, BIPINITIATOR_COMPLETE); break; case GOEP_OPER_PUSH: Assert(client->pushPull.object); BIPOBS_Close((BipObStoreHandle *)&client->pushPull.object); /* OBEX put is complete. */ client->state = BIPCHS_COMPLETED; //Report(("BIP: Client: OBEX Put Operation is complete.\n")); BipAppCallBack(&parms, OB_STATUS_SUCCESS, BIPINITIATOR_COMPLETE); client->state = BIPCHS_CONNECTED; break; case GOEP_OPER_PULL: BIPOBS_Close((BipObStoreHandle *)&client->pushPull.object); client->state = BIPCHS_COMPLETED; //Report(("BIP: Client: OBEX Pull Operation is complete.\n")); BipAppCallBack(&parms, OB_STATUS_SUCCESS, BIPINITIATOR_COMPLETE); client->state = BIPCHS_CONNECTED; break; case GOEP_OPER_DISCONNECT: /* OBEX Disconnect is complete, disconnect link. */ //Report(("BIP: Client: OBEX Disconnect Operation is complete.\n")); client->state = BIPCHS_INITIALIZED; GOEP_TpDisconnect(&client->cApp); client->b_TpDisconnect_called = KAL_TRUE; break; case GOEP_OPER_ABORT: //Report(("BIP: Client: OBEX Abort Operation is complete.\n")); client->state = BIPCHS_ABORTED; BipAppCallBack(&parms, event->reason, BIPINITIATOR_ABORT); if (client->pushPull.object) { /* close any objects associated with the aborted operation */ BIPOBS_Close((BipObStoreHandle *)&client->pushPull.object); } client->state = BIPCHS_CONNECTED; break; default: //Report(("BIP: Client: OBEX Operation %d is complete.\n", event->oper)); break; } client->tData.offset = client->tData.totLen = 0; client->data = &client->tData; client->tData.bipOp = BIPOP_NOP; break; case GOEP_EVENT_ABORTED: /* Handle the Partial Content special case on PutImage */ if (event->oper == GOEP_OPER_PUSH && ((BipObStoreHandle)client->pushPull.object)->bipOp == BIPOP_PUT_IMAGE && event->reason == OBRC_PARTIAL_CONTENT) { BIPOBS_Close((BipObStoreHandle *)&client->pushPull.object); client->state = BIPCHS_COMPLETED; kal_trace(BT_TRACE_G6_OBEX,BT_BIP_I_PARTIALCONTENT_PUTIMG); BipAppCallBack(&parms, OBRC_PARTIAL_CONTENT, BIPINITIATOR_COMPLETE); client->state = BIPCHS_CONNECTED; break; } if (event->oper == GOEP_OPER_PULL && client->pushPull.object && ((BipObStoreHandle)client->pushPull.object)->bipOp == BIPOP_GET_IMAGES_LIST && event->reason == OBRC_PARTIAL_CONTENT) { BIPOBS_Close((BipObStoreHandle *)&client->pushPull.object); client->state = BIPCHS_COMPLETED; kal_trace(BT_TRACE_G6_OBEX,BT_BIP_I_PARTIALCONTENT_GETIMGLIST); BipAppCallBack(&parms, OBRC_PARTIAL_CONTENT, BIPINITIATOR_COMPLETE); client->state = BIPCHS_CONNECTED; break; } if(event->oper == GOEP_OPER_CONNECT) { //Report(("BIP: Client: Received failed connect response, disconnect the transport layer.\n")); if (event->reason == OBRC_LINK_DISCONNECT) { /* in case of TP_DISCONNECT, OBEX will invoke ABORT firtly */ client->state = BIPCHS_INITIALIZED; client->b_TpDisconnect_called = KAL_TRUE; break; } if (client->state == BIPCHS_AUTHENTICATING) { client->data = &client->tData; client->data->bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, (U16)(event->failed_rsp_code & 0x7F), BIPINITIATOR_ABORT); } else { client->state = BIPCHS_INITIALIZED; GOEP_TpDisconnect(&client->cApp); } break; } /* The requested operation has failed. Alert the user and cleanup. */ //Report(("BIP: Client: The Operation was aborted, %d.\n", event->reason)); client->state = BIPCHS_ABORTED; //BipAppCallBack(&parms, event->reason, BIPINITIATOR_ABORT); BipAppCallBack(&parms, (U16)(event->failed_rsp_code & 0x7F), BIPINITIATOR_ABORT); if (client->pushPull.object) { /* close any objects associated with the aborted operation */ BIPOBS_Close((BipObStoreHandle *)&client->pushPull.object); } client->state = BIPCHS_CONNECTED; break; case GOEP_EVENT_CONTINUE: BipAppCallBack(&parms, event->reason, BIPINITIATOR_CONTINUE); /* Allways continue on sender side */ /* GOEP_ClientContinue(&client->cApp); */ break; case GOEP_EVENT_HEADER_RX: switch (event->header.type) { case OBEXH_LENGTH: if (event->oper == GOEP_OPER_PULL) { /* Set the object length for Pull operations only */ BIPOBS_SetObjectLen((BipObStoreHandle)client->pushPull.object, event->info.pull.objectLen); } break; case BIPH_IMG_DESCRIPTION: if (event->header.len == 0 || event->header.len == event->header.totalLen) { /* reset the offset */ client->data->offset = 0; } if (event->header.len != 0) { /* tell the initiator we have data */ client->data->totLen = event->header.totalLen; client->data->len = event->header.len; switch (client->data->bipOp) { case BIPOP_GET_IMAGES_LIST: client->data->i.iHDsc.buff = event->header.buffer; client->data->dataType = BIPIND_HANDLES_DESCRIPTOR; break; case BIPOP_PUT_IMAGE: case BIPOP_GET_IMAGE: client->data->i.iIDsc.buff = event->header.buffer; client->data->dataType = BIPIND_IMAGE_DESCRIPTOR; break; default: break; } BipAppCallBack(&parms, 0, BIPINITIATOR_DATA_IND); /* Check if we have the entire description */ if (client->data->totLen > event->header.len + client->data->offset) { client->data->offset += event->header.len; } else { /* Set the offset back to null */ client->data->offset = client->data->totLen = 0; } } break; case BIPH_IMG_HANDLE: /* GOEP indicates the entire Unicode header */ if (event->header.len != 0) { int i; switch (client->data->bipOp) { case BIPOP_PUT_IMAGE: case BIPOP_REMOTE_DISPLAY: case BIPOP_GET_MONITORING_IMAGE: ih = client->data->i.iHndl.imgHandle; client->data->dataType = BIPIND_IMAGE_HANDLE; break; default: /* We don't expect an Image Handle for other ops, * but this is the end of the op, so ignore it. */ //Report(("BIP: Image Handle %s ignored.\n", event->header.buffer)); return; } /* copy the data from the buffer */ for(i=0; i < (event->header.len/2); i++) { ih[i] = event->header.buffer[2*i + 1]; } /* OS_MemCopy((U8 *)ih, event->header.buffer, event->header.len); */ /* Indicate the complete Image Handle header */ BipAppCallBack(&parms, 0, BIPINITIATOR_DATA_IND); } break; case OBEXH_APP_PARAMS: /* Check for parameters */ if (event->header.len == 0) { break; } /* Reassemble the parameters */ ASSERT(client->appParms[0] + event->header.len <= sizeof(client->appParms)); p = client->appParms + client->appParms[0] + 1; OS_MemCopy(p, event->header.buffer, event->header.len); client->appParms[0] += event->header.len; if (client->appParms[0] == event->header.totalLen) { /* Parse the App Parameters */ p = client->appParms + 1; while (p - (client->appParms + 1) < event->header.totalLen) { switch (p[0]) { case BIPAPTAG_NB_RETURNED_HANDLES: client->data->i.iList.nbReturnedHandles = BEtoHost16(p + 2); break; case BIPAPTAG_LIST_START_OFFSET: break; case BIPAPTAG_LATEST_CAPTURED_IMAGES: break; case BIPAPTAG_PARTIAL_FILE_LENGTH: case BIPAPTAG_PARTIAL_FILE_START_OFFSET: case BIPAPTAG_TOTAL_FILE_SIZE: case BIPAPTAG_END_FLAG: case BIPAPTAG_REMOTE_DISPLAY: case BIPAPTAG_SERVICE_ID: case BIPAPTAG_STORE_FLAG: break; default: break; } p += p[1] + 2; } /* Reset the App Param length */ client->appParms[0] = 0; } break; default: break; } break; case GOEP_EVENT_DISCOVERY_FAILED: case GOEP_EVENT_NO_SERVICE_FOUND: client->data = &client->tData; client->data->bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, BIP_NO_SERVICE_FOUND, BIPINITIATOR_FAILED); break; case GOEP_EVENT_SCO_REJECT: client->data = &client->tData; client->data->bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, BIP_SCO_REJECT, BIPINITIATOR_FAILED); break; case GOEP_EVENT_BTCHIP_REJECT: client->data = &client->tData; client->data->bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, BIP_BTCHIP_REJECT, BIPINITIATOR_FAILED); break; #if OBEX_AUTHENTICATION == XA_ENABLED case GOEP_EVENT_AUTH_CHALLENGE: client->state = BIPCHS_AUTHENTICATING; parms.challenge = &event->challenge; BipAppCallBack(&parms, 0, BIP_OBAUTH_CHAL); break; case GOEP_EVENT_AUTH_RESPONSE: parms.response = &event->response; BipAppCallBack(&parms, 0, BIP_OBAUTH_RSP); break; #endif /* OBEX_AUTHENTICATION == XA_ENABLED */ default: //Report(("BIP: Client Event %d ignored.\n", event)); 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; } }
/*--------------------------------------------------------------------------- * BipResponderCallback *--------------------------------------------------------------------------- * * Synopsis: This function processes Responder events. * * Return: void * */ void BipResponderCallback(GoepServerEvent *event) { ObexRespCode rcode; ObStatus status; BipObexServer *server; BipCallbackParms parms; U8 *p; BipImgHandlePtr ih = NULL; parms.obex.server = FindBipResponder(event->handler); if (parms.obex.server == 0) { kal_trace(BT_TRACE_G6_OBEX,BT_BIP_RESPONDER_NOT_FOUND); return; } server = parms.obex.server; switch (event->event) { case GOEP_EVENT_TP_CONNECTED: //Report(("[BIP ADP] Server: Transport Connection has come up.\n")); break; case GOEP_EVENT_TP_DISCONNECTED: //Report(("[BIP ADP] Server: Transport Connection has been disconnected.\n")); if (server->object) { /* close any objects associated with the aborted operation */ BIPOBS_Close(&server->object); } server->request.bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, OB_STATUS_DISCONNECT, BIPRESPONDER_COMPLETE); server->request.offset = server->request.totLen = 0; break; case GOEP_EVENT_ABORTED: /* since OBEX do not updated now... if (event->abortReason != OBRC_LINK_DISCONNECT) */ { /* Check if thumbnail is requested by Partial Content rspcode */ if ((event->oper == GOEP_OPER_PUSH) && (server->object) && (server->object->bipOp == BIPOP_PUT_IMAGE) && (server->object->code == OBRC_PARTIAL_CONTENT)) { /* Handle the Partial Content special case on PutImage */ BIPOBS_Close(&server->object); BipAppCallBack(&parms, OBRC_PARTIAL_CONTENT, BIPRESPONDER_COMPLETE); break; } if ((event->oper == GOEP_OPER_PULL) && server->object && (server->object->bipOp == BIPOP_GET_IMAGES_LIST) && (server->object->code == OBRC_PARTIAL_CONTENT)) { /* Handle the Partial Content special case on PutImage */ BIPOBS_Close(&server->object); BipAppCallBack(&parms, OBRC_PARTIAL_CONTENT, BIPRESPONDER_COMPLETE); break; } } kal_trace(BT_TRACE_G6_OBEX,BT_BIP_SERVER_OPER_ABORTED, event->oper); if (server->object) { /* close any objects associated with the aborted operation */ BIPOBS_Close(&server->object); } /* Tell the responder to abort */ BipAppCallBack(&parms, 0, BIPRESPONDER_ABORT); break; case GOEP_EVENT_PRECOMPLETE: if ((event->oper == GOEP_OPER_PUSH) && (server->object->bipOp == BIPOP_PUT_IMAGE) && (server->object->code == OBRC_PARTIAL_CONTENT)) { /* Handle the Partial Content special case on PutImage */ kal_trace(BT_TRACE_G6_OBEX,BT_BIP_SERVER_PARTIAL_CONTENT_PUTIMG); GOEP_ServerAbort(&server->sApp, OBRC_PARTIAL_CONTENT); } else if ((event->oper == GOEP_OPER_PULL) && (server->object->bipOp == BIPOP_GET_IMAGES_LIST) && (server->object->code == OBRC_PARTIAL_CONTENT)) { /* Handle the Partial Content special case on PutImage */ kal_trace(BT_TRACE_G6_OBEX,BT_BIP_SERVER_PARTIAL_CONTENT_GETIMGLIST); GOEP_ServerAbort(&server->sApp, OBRC_PARTIAL_CONTENT); } break; case GOEP_EVENT_CONTINUE: status = OB_STATUS_SUCCESS; switch(event->oper) { case GOEP_OPER_DISCONNECT: status = OB_STATUS_DISCONNECT; /* No break; fall through */ case GOEP_OPER_ABORT: /* <!-- added by yfchu on 2007.8.16 */ GOEP_ServerContinue(&server->sApp); /* --> */ return; case GOEP_OPER_CONNECT: server->request.bipOp = BIPOP_CONNECT; break; case GOEP_OPER_PUSH: if ((server->object->bipOp == BIPOP_PUT_IMAGE) && (event->info.pushpull.finalBit)) { /* Queue the Image Handle header in the final Put Response packet */ /* Avoid to abort operation for lack of image handle info if (server->request.r.rImg.imgHandle[0] == 0) { GOEP_ServerAbort(&server->sApp, OBRC_INTERNAL_SERVER_ERR); } */ if (server->request.r.rImg.imgHandle != 0) { int i = 0; server->request.r.rImg.imgHandle[7] = 0; while (server->request.r.rImg.imgHandle[i] != 0) { server->request.r.rImg.imgHandleUni[2*i] = 0; server->request.r.rImg.imgHandleUni[2*i + 1] = server->request.r.rImg.imgHandle[i]; i++; } server->request.r.rImg.imgHandleUni[2*i] = 0; server->request.r.rImg.imgHandleUni[2*i + 1] = 0; if (GOEP_ServerQueueHeader(&server->sApp, BIPH_IMG_HANDLE, (U8 *)server->request.r.rImg.imgHandleUni, (U16)(2*i+2)) == FALSE) { GOEP_ServerAbort(&server->sApp, OBRC_INTERNAL_SERVER_ERR); } } } else if (server->request.bipOp == BIPOP_PUT_IMAGE && (server->request.r.rImg.name[0] == 0 && server->request.r.rImg.name[1] == 0)) { OS_MemCopy(server->request.r.rImg.name, server->object->name, GOEP_MAX_UNICODE_LEN*2); server->request.r.rImg.img_len = server->object->objLen; } break; } parms.FinalPacket = event->info.pushpull.finalBit; BipAppCallBack(&parms, status, BIPRESPONDER_CONTINUE); break; case GOEP_EVENT_COMPLETE: switch (event->oper) { case GOEP_OPER_CONNECT: server->request.bipOp = BIPOP_CONNECT; BipAppCallBack(&parms, OB_STATUS_SUCCESS, BIPRESPONDER_COMPLETE); break; case GOEP_OPER_PUSH: case GOEP_OPER_PULL: rcode = BIPOBS_Close(&server->object); if (rcode != OBRC_SUCCESS) { GOEP_ServerAbort(&server->sApp, rcode); } BipAppCallBack(&parms, OB_STATUS_SUCCESS, BIPRESPONDER_COMPLETE); break; default: break; } //Report(("BIP: Server: %d operation complete.\n", event->oper)); server->request.offset = server->request.totLen = 0; server->request.bipOp = BIPOP_NOP; break; case GOEP_EVENT_START: if (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH) { BipObexServer *rServer = parms.obex.server; rServer->object = BIPOBS_New(&rServer->sApp); Assert(rServer->object); /* New operation, initialize BipData */ OS_MemSet((U8 *)&rServer->request, 0, sizeof(BipData)); } if (event->oper == GOEP_OPER_CONNECT) { BipObexServer *rServer = parms.obex.server; /* New operation, initialize connect target */ OS_MemSet(rServer->request.r.rConnect.targetUuid, 0, sizeof(rServer->request.r.rConnect.targetUuid)); rServer->request.r.rConnect.targetLen = 0; rServer->request.r.rConnect.targetService = 0; } break; case GOEP_EVENT_HEADER_RX: switch (event->header.type) { case OBEXH_LENGTH: if (event->oper == GOEP_OPER_PUSH) { /* Set the object length for Put operations only */ BIPOBS_SetObjectLen(server->object, event->info.pushpull.objectLen); } break; case BIPH_IMG_DESCRIPTION: if (event->header.len == 0 || event->header.len == event->header.totalLen) { /* reset the offset */ server->request.offset = 0; } if (event->header.len != 0) { /* tell the responder we have data */ server->request.totLen = event->header.totalLen; server->request.len = event->header.len; switch (server->request.bipOp) { case BIPOP_GET_IMAGES_LIST: server->request.i.iHDsc.buff = event->header.buffer; server->request.dataType = BIPIND_HANDLES_DESCRIPTOR; break; case BIPOP_PUT_IMAGE: case BIPOP_GET_IMAGE: server->request.i.iIDsc.buff = event->header.buffer; server->request.dataType = BIPIND_IMAGE_DESCRIPTOR; break; default: if (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH) { BipResponderOp(event, &parms); } server->request.i.iIDsc.buff = event->header.buffer; server->request.dataType = BIPIND_IMAGE_DESCRIPTOR; break; } BipAppCallBack(&parms, 0, BIPRESPONDER_DATA_IND); /* Check if we have the entire description */ if (server->request.totLen > event->header.len + server->request.offset) { server->request.offset += event->header.len; } else { /* Set the offset back to null */ server->request.offset = server->request.totLen = 0; } } break; case BIPH_IMG_HANDLE: /* GOEP indicates the entire Unicode header */ if (event->header.len != 0) { int i; switch (server->request.bipOp) { case BIPOP_GET_IMAGE_PROPERTIES: ih = server->request.r.rProp.imgHandle; break; case BIPOP_PUT_LINKED_THUMBNAIL: case BIPOP_GET_LINKED_THUMBNAIL: ih = server->request.r.rThm.imgHandle; break; case BIPOP_GET_IMAGE: ih = server->request.r.rImg.imgHandle; break; default: /* We must not have the type header yet. Assume this is * a PUT_LINKED_THUMBNAIL. */ if (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH) { BipResponderOp(event, &parms); ih = server->request.r.rThm.imgHandle; } break; } /* copy the data from the buffer */ if (ih != NULL) { for(i = 0; i < (event->header.len/2); i++) { ih[i] = event->header.buffer[2*i+1]; } /*OS_MemCopy((U8 *)ih, event->header.buffer, event->header.len); */ } } break; case OBEXH_APP_PARAMS: /* Check for parameters */ if (event->header.len == 0) { break; } /* Reassemble the parameters */ ASSERT(server->appParms[0] + event->header.len <= sizeof(server->appParms)); p = server->appParms + server->appParms[0] + 1; OS_MemCopy(p, event->header.buffer, event->header.len); server->appParms[0] += event->header.len; if (server->appParms[0] == event->header.totalLen) { /* Parse the App Parameters */ p = server->appParms + 1; while (p - (server->appParms + 1) < event->header.totalLen) { switch (p[0]) { case BIPAPTAG_NB_RETURNED_HANDLES: server->request.r.rList.nbReturnedHandles = BEtoHost16(p + 2); break; case BIPAPTAG_LIST_START_OFFSET: server->request.r.rList.listStartOffset = BEtoHost16(p + 2); break; case BIPAPTAG_LATEST_CAPTURED_IMAGES: server->request.r.rList.latestCapturedImages = p[2]; break; case BIPAPTAG_STORE_FLAG: server->request.r.rMon.storeFlag = p[2]; break; case BIPAPTAG_PARTIAL_FILE_LENGTH: case BIPAPTAG_PARTIAL_FILE_START_OFFSET: case BIPAPTAG_TOTAL_FILE_SIZE: case BIPAPTAG_END_FLAG: case BIPAPTAG_REMOTE_DISPLAY: case BIPAPTAG_SERVICE_ID: break; default: break; } p += p[1] + 2; } /* Reset the App Param length */ server->appParms[0] = 0; } break; case OBEXH_BODY: break; case OBEXH_END_BODY: break; case OBEXH_TARGET: /* CONNECT TARGET header */ { U8 len; /* Reassemble the header */ ASSERT (server->request.r.rConnect.targetLen + event->header.len <= sizeof(server->request.r.rConnect.targetUuid)); p = (U8*)(server->request.r.rConnect.targetUuid) + server->request.r.rConnect.targetLen; OS_MemCopy(p, event->header.buffer, event->header.len); server->request.r.rConnect.targetLen += event->header.len; len = server->request.r.rConnect.targetLen; p = (U8 *)(server->request.r.rConnect.targetUuid); if (len == event->header.totalLen) { BipService targetService = 0; /* target header received */ if (OS_MemCmp(p, len, server->bipImgPullUuid, sizeof(server->bipImgPullUuid))) { targetService = BIPSVC_IMAGE_PULL; } else if (OS_MemCmp(p, len, server->bipImgPushUuid, sizeof(server->bipImgPushUuid))) { targetService = BIPSVC_IMAGE_PUSH; } server->request.r.rConnect.targetService = targetService; } } break; default: break; } break; case GOEP_EVENT_PROVIDE_OBJECT: /* If an operation has not yet been assigned, figure it out */ if ((server->request.bipOp == BIPOP_NOP) && (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH)) { BipResponderOp(event, &parms); } if (event->oper == GOEP_OPER_PULL && server->request.bipOp & BIPOP_PULL_MASK) { BipAppCallBack(&parms, 0, BIPRESPONDER_REQUEST); if ((server->object->objLen != 0) && (server->request.bipOp == BIPOP_GET_IMAGE || server->request.bipOp == BIPOP_GET_MONITORING_IMAGE)) { /* Setup the LENGTH header for a Get Image response only */ event->info.pushpull.objectLen = server->object->objLen; } else { /* Make sure we do not issue a LENGTH header for any other responses. It * is possible that we could have a value, if we received a LENGTH header * in a GET Request, so we always want to reset this value to zero. */ event->info.pushpull.objectLen = 0; } } else if (event->oper == GOEP_OPER_PUSH && (server->request.bipOp == BIPOP_PUT_IMAGE || server->request.bipOp == BIPOP_PUT_LINKED_THUMBNAIL)) { if (server->request.bipOp == BIPOP_PUT_IMAGE) { OS_MemCopy(server->request.r.rImg.name, server->object->name, GOEP_MAX_UNICODE_LEN*2); server->request.r.rImg.img_len = server->object->objLen; } BipAppCallBack(&parms, 0, BIPRESPONDER_REQUEST); } GOEP_ServerAccept(&server->sApp, server->object); break; case GOEP_EVENT_AUTHORIZE_IND: BipAppCallBack(&parms, 0, BIPRESPONDER_AUTHORIZE_IND); break; #if OBEX_AUTHENTICATION == XA_ENABLED case GOEP_EVENT_AUTH_CHALLENGE: parms.challenge = &event->challenge; BipAppCallBack(&parms, 0, BIP_OBAUTH_CHAL); break; case GOEP_EVENT_AUTH_RESPONSE: parms.response = &event->response; BipAppCallBack(&parms, 0, BIP_OBAUTH_RSP); break; #endif /* OBEX_AUTHENTICATION == XA_ENABLED */ default: //Report(("BIP: Server Event %d ignored.\n", event)); break; } }