| /****************************************************************************** |
| *(C) Copyright 2014 Marvell International Ltd. |
| * All Rights Reserved |
| ******************************************************************************/ |
| /* ------------------------------------------------------------------------------------------------------------------- |
| * |
| * Filename: mbim_protocol.c |
| * |
| * Authors: Adrian Zelezniak |
| * |
| * Description: MBIM protocol functions are defined in this file |
| * |
| * HISTORY: |
| * Jan 7, 2014 - Initial Version |
| * |
| * Notes: |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * Include files |
| ******************************************************************************/ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <fcntl.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| #define LOG_TAG "MBIM" |
| |
| |
| #include "mbim_types.h" |
| #include "mbim_protocol.h" |
| #include "mbim_util.h" |
| #include "mbim_basic.h" |
| #include "mbim_sms.h" |
| #include "mbim_ussd.h" |
| #include "mbim_basic_extension.h" |
| #if defined MBIM_MTIL |
| #include "mbim_mtil_ind.h" |
| #include "mbim_mtil.h" |
| #include "mbim_pcap.h" |
| #else |
| #include "mbim_ril.h" |
| #include "mbim_ril_ind.h" |
| #endif |
| |
| /****************************************************************************** |
| * Defines |
| ******************************************************************************/ |
| //#define DUMMY 1 |
| |
| |
| /****************************************************************************** |
| * External Variables |
| ******************************************************************************/ |
| extern basicUuidProcessors basicCidProcessor[UUID_BASIC_CID_MAX]; |
| extern smsUuidProcessors smsCidProcessor[UUID_SMS_CID_MAX]; |
| extern ussdUuidProcessors ussdCidProcessor[UUID_USSD_CID_MAX]; |
| extern basicExtUuidProcessors basicExtCidProcessor[UUID_CID_BASICEXT_MAX]; |
| |
| extern UINT32 cidsFilterArray[UUID_MAX_SERVICE_INDEX][2]; |
| |
| extern char basicFilterArray[UUID_BASIC_CID_MAX]; |
| extern char smsFilterArray[UUID_SMS_CID_MAX]; |
| extern char ussdFilterArray[UUID_USSD_CID_MAX]; |
| |
| //BS |
| extern Boolean disableUnsolCidConnect; |
| |
| |
| /****************************************************************************** |
| * Macros |
| ******************************************************************************/ |
| #define BASIC_COMMAND_PROCESS(mbimCmd_p) (basicCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| #define SMS_COMMAND_PROCESS(mbimCmd_p) (smsCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| |
| #define USSD_COMMAND_PROCESS(mbimCmd_p) (ussdCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| #define PHONEBOOK_COMMAND_PROCESS(mbimCmd_p) (phonebookCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| #define STK_COMMAND_PROCESS(mbimCmd_p) (stkCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| #define AUTH_COMMAND_PROCESS(mbimCmd_p) (authCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| #define DSS_COMMAND_PROCESS(mbimCmd_p) (dssCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| #define BASIC_EXT_COMMAND_PROCESS(mbimCmd_p) (basicExtCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| #define UICC_COMMAND_PROCESS(mbimCmd_p) (uiccCidProcessor[mbimCmd_p->cid])( mbimCmd_p->cid, \ |
| mbimCmd_p->messageHeader.transactionId, \ |
| mbimCmd_p->commandType, \ |
| mbimCmd_p->informationBufferLength, \ |
| (char *)(&mbimCmd_p->InformationBuffer.data[0])); |
| |
| |
| /****************************************************************************** |
| * Global variables |
| ******************************************************************************/ |
| MBIM_DATABASE mbimDb; |
| |
| |
| /****************************************************************************** |
| * Function prototypes |
| ******************************************************************************/ |
| static void processOpenMsg(char *dataBuf); |
| static void processCloseMsg(char *dataBuf, Boolean reOpenState); |
| static void processCommandMsg(char *dataBuf); |
| static int mbimSend(char *msg, int length); |
| static void initFragmentDb(P_MBIM_COMMAND_MSG mbimCmd_p); |
| static void resetFragmentDb(Boolean freeBuffer); |
| static P_MBIM_COMMAND_MSG processFragment(P_MBIM_COMMAND_MSG mbimCmd_p); |
| |
| |
| |
| |
| |
| /****************************************************************************** |
| * Code |
| ******************************************************************************/ |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimProcessEncapCommand |
| * Description: This function is extract the MBIM command from the encapsualted message and call the |
| * related callback. |
| * Parameters: dataBuf - String |
| * |
| * Returns: 0=OK, <0=Error Code |
| \*******************************************************************************/ |
| int MbimProcessEncapCommand(char *dataBuf, UINT32 dataLen) |
| { |
| //Pick up pointer to struct |
| int rc = 0; |
| P_MBIM_MESSAGE_HEADER mbimHdr_p = (P_MBIM_MESSAGE_HEADER)dataBuf; |
| |
| //Check that we have valid data (DO we need this?) |
| if (dataBuf == NULL) |
| { |
| MBIM_LOGE("MbimProcessEncapCommand ERROR!!! Databug is NULL"); |
| return MBIM_ERROR_UNKNOWN; |
| } |
| |
| //Check that the message is at least as big as MBIM Header |
| if (dataLen < sizeof(MBIM_MESSAGE_HEADER) ) |
| { |
| MBIM_LOGE("MbimProcessEncapCommand ERROR!!! Data length shorter than sizeof(MBIM_MESSAGE_HEADER)"); |
| return MBIM_ERROR_LENGTH_MISMATCH; |
| } |
| |
| //Check the correct size of received message |
| if (mbimHdr_p->messageLength > dataLen) |
| { |
| MBIM_LOGE("MbimProcessEncapCommand ERROR!!! messageLength shorter than data length"); |
| return MBIM_ERROR_LENGTH_MISMATCH; |
| } |
| |
| //Log received Message |
| logReceivedMbimMsg(mbimHdr_p->messageType, mbimHdr_p->transactionId); |
| |
| //Check the received command |
| switch( mbimHdr_p->messageType ) |
| { |
| case MBIM_OPEN_MSG_E: |
| processOpenMsg(dataBuf); |
| break; |
| |
| case MBIM_CLOSE_MSG_E: |
| processCloseMsg(dataBuf, FALSE); |
| break; |
| |
| case MBIM_COMMAND_MSG_E: |
| processCommandMsg(dataBuf); |
| break; |
| |
| case MBIM_HOST_ERROR_MSG_E: |
| MBIM_LOGD("Received Host Error Message");//[TBD] what to do with the error (Need to read). |
| break; |
| |
| //Unknown message type. |
| default: |
| MBIM_LOGE("MbimProcessEncapCommand ERROR!!! Uknown message type: %d", mbimHdr_p->messageType); |
| rc = MBIM_ERROR_UNKNOWN; |
| break; |
| } |
| |
| return rc; |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimProcessOpenCmd |
| * Description: This function is extract the MBIM command from the encapsualted message and call the |
| * related callback. |
| * Parameters: dataBuf - String |
| * |
| * Returns: |
| \*******************************************************************************/ |
| static void processOpenMsg(char *dataBuf) |
| { |
| P_MBIM_OPEN_MSG msg_p = (P_MBIM_OPEN_MSG)dataBuf; |
| UINT32 transId = msg_p->messageHeader.transactionId; |
| |
| //We need to do re-open |
| if (mbimDb.open == TRUE) |
| { |
| processCloseMsg(dataBuf, TRUE); |
| } |
| |
| mbimDb.open = TRUE; |
| mbimDb.maxControlTransfer = msg_p->maxControlTransfer; //Used to know when to fragment the message |
| mbimDb.isForceDetach = FALSE; |
| |
| MBIM_FREE(mbimDb.inBuf); |
| mbimDb.inBuf = MBIM_MALLOC(mbimDb.maxControlTransfer); |
| |
| MBIM_LOGD("OPEN: maxControlTransfer = %d", mbimDb.maxControlTransfer); |
| |
| //Turn on all indications to MBIM |
| #if defined (MBIM_MTIL) |
| //It will filter them according to subscriber list |
| MtilSendInden(NULL, TRUE); |
| MtilConfigCmtiIndications(TRUE); |
| #else |
| MbimTelSetupIndications(TRUE); |
| #endif |
| //Send Open Done MSG |
| MbimSendOpenDone( transId, MBIM_STATUS_SUCCESS); |
| |
| } |
| |
| void MbimHandleCommand (char *dataBuf, int len) |
| { |
| P_MBIM_OPEN_MSG msg_p = (P_MBIM_OPEN_MSG)dataBuf; |
| |
| if (len == sizeof (*msg_p)) |
| { |
| if (msg_p->messageHeader.messageType == MBIM_OPEN_MSG_E) |
| { |
| if (msg_p->maxControlTransfer != mbimDb.maxControlTransferFromDrv) |
| { |
| mbimDb.maxControlTransferFromDrv = msg_p->maxControlTransfer; |
| MBIM_FREE(mbimDb.inBufFromDrv); |
| mbimDb.inBufFromDrv = MBIM_MALLOC(mbimDb.maxControlTransferFromDrv); |
| MBIM_LOGD("OPEN: maxControlTransferFromDrv = %d", mbimDb.maxControlTransferFromDrv); |
| } |
| } |
| } |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimProcessClose |
| * Description: This function is extract the MBIM command from the encapsualted message and call the |
| * related callback. |
| * Parameters: dataBuf - String |
| * |
| * Returns: |
| \*******************************************************************************/ |
| static void processCloseMsg(char *dataBuf, Boolean reOpenState) |
| { |
| P_MBIM_CLOSE_MSG msg_p = (P_MBIM_CLOSE_MSG)dataBuf; |
| UINT32 transId = msg_p->messageHeader.transactionId; |
| |
| //Need to discard all commands in transit [TBD] |
| |
| //Need to reset received fragments |
| resetFragmentDb(TRUE); |
| |
| if (reOpenState == FALSE) |
| { |
| //In phase II --> (Close indications). |
| |
| mbimDb.open = FALSE; |
| mbimDb.maxControlTransfer = MBIM_MAX_CONTROL_TRANS_DEFAULT; |
| |
| //Turn off all indications to MBIM |
| #if defined (MBIM_MTIL) |
| MtilSendInden(NULL, FALSE); |
| MtilConfigCmtiIndications(FALSE); |
| #else |
| MbimTelSetupIndications(FALSE); |
| #endif |
| //Send Close Done MSG |
| MbimSendCloseDone( transId, MBIM_STATUS_SUCCESS); |
| |
| MBIM_FREE(mbimDb.inBuf); |
| mbimDb.inBuf = MBIM_MALLOC(MBIM_MAX_CONTROL_TRANS_DEFAULT); |
| } |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimProcessEncapCommand |
| * Description: This function is extract the MBIM command from the encapsualted message and call the |
| * related callback. |
| * Parameters: dataBuf - String |
| * |
| * Returns: |
| \*******************************************************************************/ |
| static void processCommandMsg(char *dataBuf) |
| { |
| //Pick pu pointer to data |
| P_MBIM_COMMAND_MSG mbimCmd_p = (P_MBIM_COMMAND_MSG)dataBuf; |
| int uuidIndex; |
| |
| //check that the MBIM is open |
| if (mbimDb.open == FALSE) |
| { |
| //Send Error Message to host(MBIM Not OPEN) |
| MbimSendFunctionErrorMsg(mbimCmd_p->messageHeader.transactionId, MBIM_ERROR_NOT_OPENED); |
| return; |
| } |
| |
| //We always go through the (MBIM command is allocated during fragmentation) |
| mbimCmd_p = processFragment(mbimCmd_p); |
| if (mbimCmd_p != NULL) |
| { |
| if ( (uuidIndex = UUID2Index (&mbimCmd_p->deviceServiceId)) >= 0 ) |
| { |
| |
| MBIM_LOGD("UUID Index = %d, MessageCID = %d, TansId = %d, Length = %d Type = %d", |
| uuidIndex, |
| mbimCmd_p->cid, |
| mbimCmd_p->messageHeader.transactionId, |
| mbimCmd_p->messageHeader.messageLength, |
| mbimCmd_p->commandType); |
| switch(uuidIndex) |
| { |
| case UUID_BASIC_CONNECT_INDEX: |
| if (mbimCmd_p->cid < UUID_BASIC_CID_MAX) |
| { |
| BASIC_COMMAND_PROCESS(mbimCmd_p); |
| } |
| break; |
| |
| case UUID_SMS_INDEX: |
| if (mbimCmd_p->cid < UUID_SMS_CID_MAX) |
| { |
| SMS_COMMAND_PROCESS(mbimCmd_p); |
| } |
| break; |
| |
| case UUID_USSD_INDEX: |
| if (mbimCmd_p->cid < UUID_USSD_CID_MAX) |
| { |
| USSD_COMMAND_PROCESS(mbimCmd_p); |
| } |
| break; |
| |
| case UUID_PHONEBOOK_INDEX: |
| break; |
| |
| case UUID_STK_INDEX: |
| break; |
| |
| case UUID_AUTH_INDEX: |
| break; |
| |
| case UUID_DSS_INDEX: |
| break; |
| |
| case UUID_BASIC_CONNECT_EXTENSIONS_INDEX: |
| if (mbimCmd_p->cid < UUID_CID_BASICEXT_MAX) |
| { |
| BASIC_EXT_COMMAND_PROCESS(mbimCmd_p); |
| } |
| break; |
| |
| case UUID_MS_UICC_LOW_LEVEL_INDEX: |
| break; |
| |
| default: |
| break; |
| } |
| } |
| else |
| { |
| MBIM_LOGD("UUID is not supported!"); |
| //send unsupported |
| P_MBIM_COMMAND_DONE cmd_p = (P_MBIM_COMMAND_DONE)MBIM_MALLOC(sizeof(MBIM_COMMAND_DONE)); |
| cmd_p->messageHeader.messageType = MBIM_COMMAND_DONE_E; |
| cmd_p->messageHeader.messageLength = sizeof(MBIM_COMMAND_DONE); |
| cmd_p->messageHeader.transactionId = mbimCmd_p->messageHeader.transactionId; |
| cmd_p->fragmentHeader.totalFragments = 1; |
| cmd_p->fragmentHeader.currentFragment= 0; |
| |
| memcpy(cmd_p->deviceServiceId.uuid, mbimCmd_p->deviceServiceId.uuid, 16); |
| cmd_p->cid = mbimCmd_p->cid; |
| cmd_p->status = MBIM_STATUS_NO_DEVICE_SUPPORT; |
| cmd_p->informationBufferLength = 0; |
| |
| mbimSend((char *)cmd_p, sizeof(MBIM_COMMAND_DONE)); |
| MBIM_FREE(cmd_p); |
| } |
| }//end if mbimCmd_P != null |
| |
| //Free allocated pointer during fragmentation |
| MBIM_FREE(mbimCmd_p); |
| } |
| |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimSendOpenDone |
| * Description: This function returns Open Done to MBIM Host |
| * Parameters: int transId - Unique transaction id received from host |
| MBIM_STATUS_CODE_ENUM statusCode - The status of the command |
| * |
| * Returns: |
| \*******************************************************************************/ |
| int MbimSendOpenDone(UINT32 transId, MBIM_STATUS_CODE_ENUM statusCode) |
| { |
| MBIM_OPEN_DONE rsp; |
| |
| //MBIM MSG Header |
| rsp.messageHeader.messageType = MBIM_OPEN_DONE_E; |
| rsp.messageHeader.messageLength = sizeof(MBIM_OPEN_DONE); |
| rsp.messageHeader.transactionId = transId; |
| |
| //status Code |
| rsp.status = statusCode; |
| |
| memset(basicFilterArray, 1, sizeof(basicFilterArray)); |
| memset(smsFilterArray, 1, sizeof(smsFilterArray)); |
| memset(ussdFilterArray, 1, sizeof(ussdFilterArray)); |
| |
| // LogMessage(); |
| |
| return mbimSend((char *)&rsp, sizeof(MBIM_OPEN_DONE)); |
| } |
| |
| /*******************************************************************************\ |
| * Function: MbimSendCloseDone |
| * Description: This function returns Close Done to MBIM Host |
| * Parameters: int transId - Unique transaction id received from host |
| MBIM_STATUS_CODE_ENUM statusCode - The status of the command |
| * |
| * Returns: |
| \*******************************************************************************/ |
| int MbimSendCloseDone(UINT32 transId, MBIM_STATUS_CODE_ENUM statusCode) |
| { |
| MBIM_CLOSE_DONE rsp; |
| |
| //MBIM message Header |
| rsp.messageHeader.messageType = MBIM_CLOSE_DONE_E; |
| rsp.messageHeader.messageLength = sizeof(MBIM_CLOSE_DONE); |
| rsp.messageHeader.transactionId = transId; |
| |
| //status Code |
| rsp.status = statusCode; |
| |
| return mbimSend((char *)&rsp, sizeof(MBIM_CLOSE_DONE)); |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimSendFunctionErrorMsg |
| * Description: This function returns Error Message to MBIM Host |
| * Parameters: int transId - Unique transaction id received from host |
| MBIM_STATUS_CODE_ENUM statusCode - The status of the command |
| * |
| * Returns: |
| \*******************************************************************************/ |
| int MbimSendFunctionErrorMsg(UINT32 transId, MBIM_PROTOCOL_ERROR_CODES_ENUM statusCode) |
| { |
| MBIM_FUNCTION_ERROR_MSG rsp; |
| |
| MBIM_LOGD("Function Error: TransId = %d, StatusCode = %d", transId, statusCode); |
| |
| //MBIM message Header |
| rsp.messageHeader.messageType = MBIM_FUNCTION_ERROR_MSG_E; |
| rsp.messageHeader.messageLength = sizeof(MBIM_FUNCTION_ERROR_MSG); |
| rsp.messageHeader.transactionId = transId; |
| |
| //Status Code |
| rsp.errorStatusCode = statusCode; |
| |
| //Send response to MBIM host |
| return mbimSend((char *)&rsp, sizeof(MBIM_FUNCTION_ERROR_MSG)); |
| } |
| |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimSendCommandDone |
| * Description: This function returns Error Message to MBIM Host |
| * Parameters: int transId - Unique transaction id received from host |
| MBIM_STATUS_CODE_ENUM statusCode - The status of the command |
| * |
| * Returns: |
| \*******************************************************************************/ |
| int MbimSendCommandDone(UINT32 transId, int uuidIndex, int cid, MBIM_STATUS_CODE_ENUM status, int bufLen, char *rspData_p) |
| { |
| P_MBIM_COMMAND_DONE cmd_p; |
| char *rspBuf_p; |
| int fragIndex = 0; |
| int fragmentPayloadSize = mbimDb.maxControlTransfer - FRAGMENT_HDR_SIZE; |
| int remBufLen = bufLen; |
| int numOfFragments = getNumOfFragments(sizeof(MBIM_COMMAND_DONE), bufLen); |
| int rc = MBIM_OK; |
| |
| //Allocate the needed size for the response |
| if (numOfFragments == 1) |
| rspBuf_p = MBIM_MALLOC(sizeof(MBIM_COMMAND_DONE) + bufLen); |
| else |
| rspBuf_p = MBIM_MALLOC(mbimDb.maxControlTransfer); |
| if (rspBuf_p == 0) |
| { |
| MBIM_LOGE("Error Cannot allocate memory"); |
| return MBIM_BIND_MEM_ERROR; |
| } |
| |
| if (cid == UUID_CONNECT) |
| { |
| disableUnsolCidConnect = FALSE; |
| MBIM_LOGE("%s: disableUnsolCidConnect = FALSE, CID = %d", __FUNCTION__, cid); |
| } |
| |
| //Pick up pointer to first fragment |
| cmd_p = (P_MBIM_COMMAND_DONE)rspBuf_p; |
| |
| //MBIM message Header |
| cmd_p->messageHeader.messageType = MBIM_COMMAND_DONE_E; |
| cmd_p->messageHeader.messageLength = (sizeof(MBIM_COMMAND_DONE) + bufLen); |
| cmd_p->messageHeader.transactionId = transId; |
| cmd_p->fragmentHeader.totalFragments = numOfFragments; |
| cmd_p->fragmentHeader.currentFragment= 0; |
| |
| |
| //Fill the command fields that are sent olny once in frist fragment |
| if ( Index2UUID(&cmd_p->deviceServiceId, uuidIndex) != MBIM_OK ) { |
| MBIM_LOGE("Unknown UUID. uuidIndex = %d, Cid=%d, bufLen = %d, status = %d", uuidIndex, cid, bufLen, status); |
| MBIM_FREE(rspBuf_p); |
| return MBIM_UUID_UKNOWN_ERROR; |
| } |
| cmd_p->cid = cid; |
| cmd_p->status = status; |
| cmd_p->informationBufferLength = bufLen; |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| // Transmit First framgent |
| ///////////////////////////////////////////////////////////////////////////////////// |
| |
| //Copy payload data |
| memcpy((char *)&rspBuf_p[sizeof(MBIM_COMMAND_DONE)], (char *)&rspData_p[0], MIN((int)(mbimDb.maxControlTransfer-sizeof(MBIM_COMMAND_DONE)), remBufLen)); |
| |
| //transmit First Fragment(Send response to MBIM host) |
| if ( (rc = mbimSend(rspBuf_p, MIN(mbimDb.maxControlTransfer, (int)(sizeof(MBIM_COMMAND_DONE) + bufLen)))) < 0) |
| { |
| //Log error and break loop, return error value |
| MBIM_LOGE("MbimSendCommandDone: Error transmitting Fragment %d, from %d", fragIndex, numOfFragments); |
| MBIM_FREE(rspBuf_p); |
| return rc; |
| } |
| |
| //Advance Pointer and update remaining payload size |
| rspData_p += MIN(remBufLen,(int)(mbimDb.maxControlTransfer-sizeof(MBIM_COMMAND_DONE))); |
| remBufLen -= MIN(remBufLen,(int)(mbimDb.maxControlTransfer-sizeof(MBIM_COMMAND_DONE))); |
| |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| // Transmit all other framgents |
| ///////////////////////////////////////////////////////////////////////////////////// |
| |
| //See if we need to transmit more fragments, and transmit |
| for (fragIndex = 1 ; fragIndex < numOfFragments ; fragIndex++) |
| { |
| //the rest of the header still keeps the same position and value as before |
| cmd_p->fragmentHeader.currentFragment = fragIndex; |
| memcpy(&rspBuf_p[FRAGMENT_HDR_SIZE], rspData_p, MIN(remBufLen, fragmentPayloadSize)); |
| |
| //Transmit new fragment |
| if ( (rc = mbimSend(rspBuf_p, MIN(mbimDb.maxControlTransfer, (int)(FRAGMENT_HDR_SIZE + remBufLen)))) < 0 ) |
| { |
| //Log error and break loop, return error value |
| MBIM_LOGE("MbimSendCommandDone: Error transmitting Fragment %d, from %d", fragIndex, numOfFragments); |
| break; |
| } |
| |
| //Advance Pointer and update remaining payload size |
| rspData_p += MIN(remBufLen,fragmentPayloadSize); |
| remBufLen -= MIN(remBufLen,fragmentPayloadSize); |
| } |
| |
| //Free allocated buffer |
| MBIM_FREE(rspBuf_p); |
| |
| return rc; |
| |
| } |
| |
| |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimSendIndicateStatusMsg |
| * Description: This function returns Error Message to MBIM Host |
| * Parameters: |
| * |
| * Returns: |
| \*******************************************************************************/ |
| int MbimSendIndicateStatusMsg(int uuidIndex, int cid, int bufLen, char *rspData_p) |
| { |
| P_MBIM_INDICATION_STATUS_MSG ind_p; |
| char *rspBuf_p; |
| int fragIndex = 0; |
| int fragmentPayloadSize = mbimDb.maxControlTransfer - FRAGMENT_HDR_SIZE; |
| int remBufLen = bufLen; |
| int numOfFragments = getNumOfFragments(sizeof(MBIM_INDICATION_STATUS_MSG), bufLen); |
| int rc = MBIM_OK; |
| char *pFilterArray; |
| |
| //When the MBIM is CLose, remaining indication must be discarded |
| if (mbimDb.open == FALSE) |
| { |
| MBIM_LOGE("MBIM CLOSE, discaring Indication with CID = %d", cid); |
| return rc; |
| } |
| |
| MBIM_LOGD("MbimSendIndicateStatusMsg: uuidIndex = %d", uuidIndex); |
| if (cidsFilterArray[uuidIndex][0] != 0) |
| { |
| pFilterArray = (char *)cidsFilterArray[uuidIndex][0]; |
| if (pFilterArray[cid] == 0) |
| { |
| MBIM_LOGD("MbimSendIndicateStatusMsg: Indication with CID = %d is filtered out by host", cid); |
| return rc; |
| } |
| } |
| |
| if ((disableUnsolCidConnect == TRUE) && (cid == UUID_CONNECT)) |
| { |
| MBIM_LOGE("disableUnsolCidConnect, CID = %d", cid); |
| return rc; |
| } |
| |
| //Allocate the needed size for the response |
| if (numOfFragments == 1) |
| rspBuf_p = MBIM_MALLOC(sizeof(MBIM_INDICATION_STATUS_MSG) + bufLen); |
| else |
| rspBuf_p = MBIM_MALLOC(mbimDb.maxControlTransfer); |
| if (rspBuf_p == 0) |
| { |
| MBIM_LOGE("Error Cannot allocate memory"); |
| return MBIM_BIND_MEM_ERROR; |
| } |
| |
| //Pick up pointer to first fragment |
| ind_p = (P_MBIM_INDICATION_STATUS_MSG)rspBuf_p; |
| |
| //MBIM message Header |
| ind_p->messageHeader.messageType = MBIM_INDICATE_STATUS_MSG_E; |
| ind_p->messageHeader.messageLength = (sizeof(MBIM_INDICATION_STATUS_MSG) + bufLen); |
| ind_p->messageHeader.transactionId = 0; |
| ind_p->fragmentHeader.totalFragments = numOfFragments; |
| ind_p->fragmentHeader.currentFragment = 0; |
| |
| |
| //Fill the command fields that are sent olny once in frist fragment |
| if ( Index2UUID(&ind_p->deviceServiceId, uuidIndex) != MBIM_OK ) { |
| MBIM_LOGE("Unknown UUID. uuidIndex = %d, Cid=%d, bufLen = %d", uuidIndex, cid, bufLen); |
| MBIM_FREE(rspBuf_p); |
| return MBIM_UUID_UKNOWN_ERROR; |
| } |
| ind_p->cid = cid; |
| ind_p->informationBufferLength = bufLen; |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| // Transmit First framgent |
| ///////////////////////////////////////////////////////////////////////////////////// |
| |
| //Copy payload data |
| memcpy((char *)&rspBuf_p[sizeof(MBIM_INDICATION_STATUS_MSG)], (char *)&rspData_p[0], MIN((int)(mbimDb.maxControlTransfer-sizeof(MBIM_INDICATION_STATUS_MSG)), remBufLen)); |
| |
| //transmit First Fragment(Send response to MBIM host) |
| if ( (rc = mbimSend(rspBuf_p, MIN(mbimDb.maxControlTransfer, (int)(sizeof(MBIM_INDICATION_STATUS_MSG) + bufLen)))) < 0) |
| { |
| //Log error and break loop, return error value |
| MBIM_LOGE("MbimSendIndicateStatusMsg: Error transmitting Fragment %d, from %d", fragIndex, numOfFragments); |
| MBIM_FREE(rspBuf_p); |
| return rc; |
| } |
| |
| //Advance Pointer and update remaining payload size |
| rspData_p += MIN(remBufLen,(int)(mbimDb.maxControlTransfer-sizeof(MBIM_INDICATION_STATUS_MSG))); |
| remBufLen -= MIN(remBufLen,(int)(mbimDb.maxControlTransfer-sizeof(MBIM_INDICATION_STATUS_MSG))); |
| |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| // Transmit all other framgents |
| ///////////////////////////////////////////////////////////////////////////////////// |
| |
| //See if we need to transmit more fragments, and transmit |
| for (fragIndex = 1 ; fragIndex < numOfFragments ; fragIndex++) |
| { |
| //the rest of the header still keeps the same position and value as before |
| ind_p->fragmentHeader.currentFragment = fragIndex; |
| memcpy(&rspBuf_p[FRAGMENT_HDR_SIZE], rspData_p, MIN(remBufLen, fragmentPayloadSize)); |
| |
| //Transmit new fragment |
| if ( (rc = mbimSend(rspBuf_p, MIN(mbimDb.maxControlTransfer, (int)(FRAGMENT_HDR_SIZE + remBufLen)))) < 0 ) |
| { |
| //Log error and break loop, return error value |
| MBIM_LOGE("MbimSendIndicateStatusMsg: Error transmitting Fragment %d, from %d", fragIndex, numOfFragments); |
| break; |
| } |
| |
| //Advance Pointer and update remaining payload size |
| rspData_p += MIN(remBufLen,fragmentPayloadSize); |
| remBufLen -= MIN(remBufLen,fragmentPayloadSize); |
| } |
| |
| //Free allocated buffer |
| MBIM_FREE(rspBuf_p); |
| |
| return rc; |
| |
| } |
| |
| |
| |
| |
| /*******************************************************************************\ |
| * Function: mbimSend |
| * Description: This function writes the respond message to the binded MBIM interface |
| * Parameters: dataBuf - String |
| * |
| * Returns: 0=OK, <0=Error Code |
| \*******************************************************************************/ |
| static int mbimSend(char *msg, int length) |
| { |
| int kernelError = 0; |
| logSentMbimMsg(msg); |
| |
| if (!mbimDb.open) |
| { |
| MBIM_LOGE("%s: MBIM closed.", __FUNCTION__); |
| return MBIM_BIND_WRITE_ERROR; |
| } |
| |
| if (mbimDb.mbimDeviceHandler != 0) |
| { |
| /* pcap log */ |
| PCAP_RSP_WRITE(msg,length); |
| |
| kernelError = write(mbimDb.mbimDeviceHandler, (void*)msg, length); |
| if ( kernelError < 0 ) |
| { |
| //Send Error Trace |
| P_MBIM_MESSAGE_HEADER mbimHdr_p = (P_MBIM_MESSAGE_HEADER)msg; |
| MBIM_LOGE("Problem sending command %d, transId = %d, Len = %d, Kernel Error = %d", mbimHdr_p->messageType, mbimHdr_p->transactionId ,length, kernelError); |
| |
| MBIM_LOGE("Kernel Error = %d, closing MBIM", kernelError); |
| |
| //close indications and Close MBIM |
| //mbimDb.open = FALSE; // TODO: check if needed |
| |
| //Turn off all indications to MBIM |
| #if defined (MBIM_MTIL) |
| MtilSendInden(NULL, FALSE); |
| MtilConfigCmtiIndications(FALSE); |
| #else |
| MbimTelSetupIndications(FALSE); |
| #endif |
| |
| mbimDb.open = FALSE; |
| return MBIM_BIND_WRITE_ERROR; |
| } |
| return MBIM_OK; |
| } |
| else |
| { |
| MBIM_LOGE("MBIM Kernel not Binded"); |
| |
| //Should I do something more? Recover? Try to rebind? [TBD] |
| |
| return MBIM_BIND_ERROR; |
| } |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: MbimKernelBind |
| * Description: This function bind the MBim device to our code |
| * Parameters: dataBuf - String |
| * |
| * Returns: 0=OK, <0=Error Code |
| \*******************************************************************************/ |
| int MbimKernelBind(void) |
| { |
| char filename[80]; |
| |
| snprintf(filename, 79, "%s", MBIM_DEVICE_FILE); |
| mbimDb.mbimDeviceHandler = open(filename, O_RDWR); |
| |
| if (mbimDb.mbimDeviceHandler < 0) |
| { |
| MBIM_LOGE("ADRIAN --> BIND ERROR, code %d, error=%s", mbimDb.mbimDeviceHandler, strerror( errno )); |
| MBIM_LOGE("Driver Filename = %s, define = %s", filename, MBIM_DEVICE_FILE ); |
| return MBIM_BIND_ERROR; |
| } |
| |
| return MBIM_OK; |
| } |
| |
| |
| |
| /*******************************************************************************\ |
| * Function: initFragmentDb |
| * Description: Initialize the fragments in the Database |
| * Parameters: int transactionId, the transaction Id of the new fragmented packets we are going to receive. |
| * |
| * Returns: 0=OK, <0=Error Code |
| \*******************************************************************************/ |
| static void initFragmentDb(P_MBIM_COMMAND_MSG mbimCmd_p) |
| { |
| mbimDb.fragmentDb.transactionId = mbimCmd_p->messageHeader.transactionId; |
| mbimDb.fragmentDb.lastFragment = -1; |
| mbimDb.fragmentDb.dataOffset = 0; |
| mbimDb.fragmentDb.TotalAllocSize = mbimCmd_p->informationBufferLength + sizeof(MBIM_COMMAND_MSG); |
| mbimDb.fragmentDb.mbimCmd_p = (char *)MBIM_MALLOC(mbimDb.fragmentDb.TotalAllocSize); |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: resetFragmentDb |
| * Description: reset the fragment in the Database |
| * Parameters: int transactionId, the transaction Id of the new fragmented packets we are going to receive. |
| * |
| * Returns: 0=OK, <0=Error Code |
| \*******************************************************************************/ |
| static void resetFragmentDb(Boolean freeBuffer) |
| { |
| mbimDb.fragmentDb.transactionId = 0; |
| mbimDb.fragmentDb.lastFragment = -1; |
| mbimDb.fragmentDb.dataOffset = 0; |
| mbimDb.fragmentDb.TotalAllocSize = 0; |
| |
| //Check if we need to free the buffer or not. |
| if (freeBuffer == TRUE) |
| { |
| if ( mbimDb.fragmentDb.mbimCmd_p != NULL ) |
| MBIM_FREE(mbimDb.fragmentDb.mbimCmd_p); |
| } |
| mbimDb.fragmentDb.mbimCmd_p = NULL; |
| } |
| |
| |
| |
| |
| /*******************************************************************************\ |
| * Function: processFragment |
| * Description: Process the received fragments, and construct the new database. |
| * Parameters: int transactionId, the transaction Id of the new fragmented packets we are going to receive. |
| * |
| * Returns: P_MBIM_COMMAND_MSG - NULL of all fragments were not received are there was an error |
| * Pointer to complete MBIM message if we received all fragments |
| \*******************************************************************************/ |
| static P_MBIM_COMMAND_MSG processFragment(P_MBIM_COMMAND_MSG mbimCmd_p) |
| { |
| MBIM_PROTOCOL_ERROR_CODES_ENUM errorCode = MBIM_ERROR_NO_ERROR; |
| char *retPtr = NULL; |
| |
| /////////////////////////////////////////////////////////////// |
| // No fragmentation needed |
| /////////////////////////////////////////////////////////////// |
| if (mbimCmd_p->fragmentHeader.totalFragments == 1) |
| { |
| //Need to send error for previous transaction ID that was fragmented |
| if ( mbimDb.fragmentDb.transactionId != 0 ) |
| { |
| //Send Error to host |
| MbimSendFunctionErrorMsg(mbimDb.fragmentDb.transactionId, MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE); |
| resetFragmentDb(TRUE); |
| } |
| |
| //Allocate and copy data to new buffer |
| retPtr = MBIM_MALLOC(mbimCmd_p->messageHeader.messageLength); |
| memcpy(retPtr, (char *)mbimCmd_p, (mbimCmd_p->messageHeader.messageLength)); |
| return (P_MBIM_COMMAND_MSG)retPtr; |
| } |
| |
| /////////////////////////////////////////////////////////////// |
| // Take care of fragmented packets |
| /////////////////////////////////////////////////////////////// |
| if ( mbimDb.fragmentDb.transactionId == 0 ) |
| initFragmentDb(mbimCmd_p); |
| |
| //check that we received fragment for the correct transaction ID and fragment in sequence |
| if ( ( (UINT32)mbimDb.fragmentDb.transactionId != mbimCmd_p->messageHeader.transactionId ) || |
| ((UINT32)(mbimDb.fragmentDb.lastFragment+1) != mbimCmd_p->fragmentHeader.currentFragment ) ) |
| { |
| errorCode = MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE; |
| } |
| |
| if ( errorCode == MBIM_ERROR_NO_ERROR ) |
| { |
| //Copy first fragment |
| if (mbimCmd_p->fragmentHeader.currentFragment == 0) |
| { |
| //Check correct message length |
| if (mbimCmd_p->messageHeader.messageLength > (UINT32)mbimDb.fragmentDb.TotalAllocSize) |
| { |
| errorCode = MBIM_ERROR_LENGTH_MISMATCH; |
| } |
| else |
| { |
| memcpy(mbimDb.fragmentDb.mbimCmd_p, (char *)mbimCmd_p, mbimCmd_p->messageHeader.messageLength); |
| mbimDb.fragmentDb.dataOffset = mbimCmd_p->messageHeader.messageLength; |
| } |
| } |
| else |
| { |
| if ((mbimDb.fragmentDb.dataOffset + (mbimCmd_p->messageHeader.messageLength-FRAGMENT_HDR_SIZE)) > (UINT32)mbimDb.fragmentDb.TotalAllocSize) |
| { |
| errorCode = MBIM_ERROR_LENGTH_MISMATCH; |
| } |
| else |
| { |
| //Copy another fragment |
| memcpy(&mbimDb.fragmentDb.mbimCmd_p[mbimDb.fragmentDb.dataOffset], &(((char *)mbimCmd_p)[FRAGMENT_HDR_SIZE]), mbimCmd_p->messageHeader.messageLength-FRAGMENT_HDR_SIZE); |
| mbimDb.fragmentDb.dataOffset += (mbimCmd_p->messageHeader.messageLength-FRAGMENT_HDR_SIZE); |
| } |
| } |
| } |
| |
| if (errorCode != MBIM_ERROR_NO_ERROR) |
| { |
| //Send error message to Host |
| MbimSendFunctionErrorMsg(mbimDb.fragmentDb.transactionId, MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE); |
| resetFragmentDb(TRUE); |
| } |
| else |
| { |
| //Check if we received all fragments |
| if ( mbimCmd_p->fragmentHeader.totalFragments == (mbimCmd_p->fragmentHeader.currentFragment + 1)) |
| { |
| //Return pointer to Complete MBIM message |
| retPtr = mbimDb.fragmentDb.mbimCmd_p; |
| resetFragmentDb(FALSE); |
| } |
| } |
| |
| return (P_MBIM_COMMAND_MSG)retPtr; |
| } |
| |
| |
| |
| void MbimInit(void) |
| { |
| //MBIM initial state to Close |
| mbimDb.mbimDeviceHandler = 0; |
| mbimDb.open = FALSE; |
| mbimDb.maxControlTransfer = MBIM_MAX_CONTROL_TRANS_DEFAULT; |
| mbimDb.inBuf = MBIM_MALLOC(mbimDb.maxControlTransfer); |
| |
| #if defined (MBIM_USE_RIL) |
| mbimDb.maxControlTransferFromDrv = MBIM_MAX_CONTROL_TRANS_DEFAULT; |
| mbimDb.inBufFromDrv = MBIM_MALLOC(mbimDb.maxControlTransfer); |
| #endif |
| mbimDb.CimiRetryCounter = 0; |
| mbimDb.HomeProviderIdSize = 0; |
| memset(mbimDb.HomeProviderMccMnc, 0, 7); |
| memset(mbimDb.HomeProviderName, 0, MBIM_MAX_OPERATOR_NAME_SIZE); |
| |
| mbimDb.mbimRegisterTech = 0; |
| mbimDb.sim.simReadyState = MBIMSubscriberReadyStateSimNotInserted; |
| |
| //Added to align packet order |
| mbimDb.packetServiceIndPending = FALSE; |
| mbimDb.connectIndPending = FALSE; |
| mbimDb.connectIndPendingCid = 0; |
| mbimDb.mbimRegisterState = MBIMRegisterStateDeregistered; |
| |
| //No loopback on start |
| mbimDb.loopbackEnabled = FALSE; |
| mbimDb.loopbackSessionId = -1; |
| |
| mbimDb.internetSessionId = -1; |
| mbimDb.cidActivated = -1; |
| resetFragmentDb(TRUE); |
| |
| |
| //Init CM values |
| mbimDb.gbForceVZWOnly = FALSE; |
| mbimDb.gbIsPlmnVerizonNetwork = FALSE; |
| mbimDb.gbNVZW = FALSE; |
| mbimDb.gbNIMS = FALSE; |
| |
| mbimDb.mbimExVersion = MBIMEx_v3; |
| mbimDb.mbimNegVersion = MBIMEx_v3; |
| |
| |
| //Init Mutex |
| pthread_mutex_init(&mbimDb.ip_connect_mutex, NULL); |
| } |
| |
| |