| /****************************************************************************** |
| *(C) Copyright 2014 Marvell International Ltd. |
| * All Rights Reserved |
| ******************************************************************************/ |
| /* ------------------------------------------------------------------------------------------------------------------- |
| * |
| * Filename: main.c |
| * |
| * Authors: Adrian Zelezniak |
| * |
| * Description: Entry Point of the MBIM Translator |
| * |
| * HISTORY: |
| * |
| * Jan 7, 2014 - Initial Version |
| * |
| * Notes: |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * Include files |
| ******************************************************************************/ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <errno.h> |
| #include <signal.h> |
| #include <assert.h> |
| |
| |
| #define LOG_TAG "MBIM" |
| |
| #include "mbim_types.h" |
| #include "mbim_util.h" |
| #include "mbim_protocol.h" |
| |
| #if defined MBIM_MTIL |
| #include "mbim_mtil.h" |
| #include "mbim_pcap.h" |
| #include "mbim_cm.h" |
| #include "eeh_assert_notify.h" |
| #else |
| #include "mbim_ril.h" |
| #endif |
| |
| /****************************************************************************** |
| * Macros |
| ******************************************************************************/ |
| //#define USE_MTIL_INIT_THREAD 1 |
| |
| |
| /****************************************************************************** |
| * External variables |
| ******************************************************************************/ |
| unsigned int board_ip = 0; |
| extern MBIM_DATABASE mbimDb; |
| |
| /****************************************************************************** |
| * Function prototypes |
| ******************************************************************************/ |
| static void handleArg(int argc, char *argv[]); |
| static void printUsage(char *progName); |
| |
| /****************************************************************************** |
| * Code |
| ******************************************************************************/ |
| #if defined MBIM_MTIL |
| extern int property_get(const char *name, const char* value, const char* default_value); |
| #endif |
| |
| static void MbimDumpBuffer (char *buff, int len) |
| { |
| int i; |
| char *bufstr; |
| MBIM_LOGE("%s: buffer len = %d", __FUNCTION__, len); |
| |
| bufstr = malloc(len*3+3); |
| bufstr[0] = '\0'; |
| |
| for (i = 0 ; i < len ; i++) |
| { |
| sprintf(bufstr, " %02X", buff[i]); |
| } |
| |
| MBIM_LOGE("%s: buff = %s", __FUNCTION__, bufstr); |
| |
| free(bufstr); |
| |
| } |
| void MbimReadFromDevice(int fd) |
| { |
| int dataLen; |
| int index = 0; |
| |
| //Read from MBIM driver |
| if ( (dataLen = read(fd, mbimDb.inBuf, mbimDb.maxControlTransfer)) < 0 ) |
| { |
| MBIM_LOGE("Error while reading from MBIM device return\n"); |
| return; |
| } |
| |
| MBIM_LOGD("%s: read %d bytes to socket %d", __FUNCTION__, dataLen, fd); |
| |
| if (dataLen == 0) |
| { |
| MBIM_LOGD("Read Zero\n"); |
| return; |
| } |
| |
| do |
| { |
| P_MBIM_MESSAGE_HEADER mbimHdr_p = (P_MBIM_MESSAGE_HEADER)&mbimDb.inBuf[index]; |
| int msgLength = mbimHdr_p->messageLength; |
| |
| MBIM_LOGD("%s: MbimProcessEncapCommand, ptr = %p, len = %d", __FUNCTION__, &mbimDb.inBuf[index], mbimHdr_p->messageLength); |
| |
| if (msgLength == 0) |
| { |
| MbimDumpBuffer(&mbimDb.inBuf[index], dataLen); |
| break; |
| } |
| //Parse the received command (Need to later see whatt to do with fragmentation!!!) |
| if ( MbimProcessEncapCommand(&mbimDb.inBuf[index], msgLength) < MBIM_OK ) |
| { |
| MBIM_LOGE("Command message Error"); |
| } |
| dataLen -= msgLength; |
| index += msgLength; |
| MBIM_LOGD("%s: MbimProcessEncapCommand done, dataLen = %d, index = %d", __FUNCTION__, dataLen, index); |
| }while(dataLen > 0); |
| |
| //reset received buffer |
| memset(mbimDb.inBuf, 0, mbimDb.maxControlTransfer); |
| } |
| |
| static void *MbimMainLoopTask (void *arg) |
| { |
| int dataLen, ret; |
| int sock_fd; |
| |
| sock_fd = mbimDb.pipes_fd[1]; |
| |
| MBIM_LOGE("%s: MbimSocketClient returned socket fd = %d", __FUNCTION__, sock_fd); |
| |
| while (TRUE) |
| { |
| |
| //Read from MBIM driver |
| if ( (dataLen = read(mbimDb.mbimDeviceHandler, mbimDb.inBufFromDrv, mbimDb.maxControlTransferFromDrv)) < 0 ) |
| { |
| MBIM_LOGE("Error while reading from MBIM device return\n"); |
| sleep(2); |
| continue; |
| } |
| |
| if (dataLen == 0) |
| { |
| MBIM_LOGD("Read Zero\n"); |
| sleep(2); |
| continue; |
| } |
| |
| MBIM_LOGD("%s: write %d bytes from %08X to socket %d", __FUNCTION__, dataLen, mbimDb.inBufFromDrv, sock_fd); |
| ret = write(sock_fd, mbimDb.inBufFromDrv, dataLen); |
| MBIM_LOGD("%s: wrote %d bytes to socket %d", __FUNCTION__, ret, sock_fd); |
| |
| MbimHandleCommand (mbimDb.inBufFromDrv, dataLen); |
| |
| |
| //reset received buffer |
| memset(mbimDb.inBufFromDrv, 0, mbimDb.maxControlTransferFromDrv); |
| }; |
| return arg; |
| } |
| |
| |
| static void sighandler(int signo) |
| { |
| MBIM_LOGD("Received signal %d\n", signo); |
| |
| assert(0); |
| |
| return; |
| } |
| |
| static inline void sighandler_setup(void) |
| { |
| MBIM_LOGD("setup sighandler\n"); |
| |
| signal(SIGABRT, sighandler); |
| signal(SIGFPE, sighandler); |
| signal(SIGILL, sighandler); |
| signal(SIGINT, sighandler); |
| signal(SIGSEGV, sighandler); |
| signal(SIGTERM, sighandler); |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: main |
| \*******************************************************************************/ |
| int main(int argc, char *argv[]) |
| { |
| int rc = MBIM_OK; |
| #if defined (MBIM_MTIL) |
| int dataLen; |
| char prop [255]; //Added for testing LTE configuration in 3G NW (Will open 3 pdp's as VZN) |
| #endif |
| |
| #ifdef USE_MTIL_INIT_THREAD |
| pthread_t tid = 0; |
| #endif |
| |
| mbim_disableAutoDial(); |
| |
| /* |
| * ToDo - find alternative |
| * |
| * eeh_init_signal_handling("mbim", (SIG_TO_MASK(SIGALRM) | SIG_TO_MASK(SIGCHLD)), 0); |
| */ |
| |
| |
| mbimDb.debug_enable = 1; //make sure we print version info |
| |
| /*LOGCAT showing with ACAT Tool */ |
| set_service_log_tag(LOG_TAG); |
| |
| MBIM_LOGD("Vesion 3.0"); |
| |
| //memset(&mbimDb, 0, sizeof(mbimDb)); |
| //sighandler_setup(); |
| |
| //Handle the received Arguments |
| handleArg(argc, argv); |
| |
| //Init all the MBIM parameters |
| MbimInit(); |
| |
| #if defined (MBIM_MTIL) |
| //Register MTIL Client (Phase I --> In Phase II need to move to Open and close command) |
| if (MtilClient_Init(client_name) < 0) { |
| MBIM_LOGE("Failed MTIL ClientAPI Initializing.\n"); |
| exit(1); |
| } else |
| MBIM_LOGD("MTIL ClientAPI Initialized.\n"); |
| #else |
| if (MbimTelInit("MBIM") != 0) { |
| MBIM_LOGE("Failed MbimTelInit Initializing.\n"); |
| exit(1); |
| } else { |
| MBIM_LOGD("MbimTelInit Initialized.\n"); |
| } |
| |
| #endif |
| |
| //Bind to Kernel |
| if (MbimKernelBind() < MBIM_OK) { |
| MBIM_LOGE("Failed Kernel Bind Initializing.\n"); |
| exit(1); |
| } else |
| MBIM_LOGD("Kernel Bind Initialized.\n"); |
| |
| #if defined (MBIM_MTIL) |
| //check if we are in test mode for (3G VZN) |
| property_get(MBIM_VZN_APN_RULE_PROPERTY, (const char *)prop, "replace"); |
| if (strcmp(prop, MBIM_VZN_APN_RULE_3G_VZN_TEST) == 0) |
| { |
| //Send Simulated PLMN Indication |
| simulatePlmnInfoInd(); |
| } |
| |
| /* |
| * The following property listener will |
| * wait for activation and deactivation |
| * pcac logging |
| */ |
| PropertiesListenerInit(); |
| #endif |
| |
| #if defined (MBIM_USE_RIL) |
| if (pipe(mbimDb.pipes_fd) != 0) |
| { |
| int err = errno; |
| char *errstr = strerror(err); |
| MBIM_LOGE("%s: pipe failed with error %d [ %s ].", __FUNCTION__, err, errstr); |
| return -1; |
| } |
| |
| pthread_create(&mbimDb.tid, NULL, MbimMainLoopTask, NULL); |
| |
| MbimTelMainLoop(mbimDb.pipes_fd[0]); |
| |
| #else |
| //MBIM main loop |
| while (TRUE) |
| { |
| |
| //Read from MBIM driver |
| if ( (dataLen = read(mbimDb.mbimDeviceHandler, mbimDb.inBuf, mbimDb.maxControlTransfer)) < 0 ) |
| { |
| MBIM_LOGE("Error while reading from MBIM device return\n"); |
| rc = MBIM_BIND_READ_ERROR; |
| break; |
| } |
| |
| if (dataLen == 0) |
| { |
| MBIM_LOGD("Read Zero\n"); |
| sleep(2); |
| continue; |
| } |
| |
| /* pcap log */ |
| PCAP_CMD_WRITE(mbimDb.inBuf,dataLen); |
| |
| //Parse the received command (Need to later see whatt to do with fragmentation!!!) |
| if ( MbimProcessEncapCommand(mbimDb.inBuf,dataLen) < MBIM_OK ) |
| { |
| MBIM_LOGE("Command message Error"); |
| } |
| |
| //reset received buffer |
| memset(mbimDb.inBuf, 0, sizeof(mbimDb.inBuf)); |
| }; |
| #endif |
| |
| #if defined (MBIM_MTIL) |
| //Close MTIL Client |
| MtilClient_Deinit(); |
| #else |
| MbimTelDeinit(); |
| #endif |
| return rc; |
| } |
| |
| |
| |
| |
| |
| /*******************************************************************************\ |
| * Function: printUsage |
| \*******************************************************************************/ |
| static void printUsage(char *progName) |
| { |
| #if defined MBIM_MTIL |
| MBIM_LOGI("%s -- MTIL AT Command Server. Call with MtilATcmd [inputs [output]]\n", progName); |
| #endif |
| MBIM_LOGI("CopyRight (c) 2014 Marvell Israel\n"); |
| MBIM_LOGI("Usage: %s [-h]\n", progName); |
| |
| //// NEED to complete the USAGE explanation //// |
| |
| |
| |
| } |
| |
| /*******************************************************************************\ |
| * Function: handleArg |
| \*******************************************************************************/ |
| static void handleArg(int argc, char *argv[]) |
| { |
| int i; |
| char *cp, opt; |
| |
| for (i = 1; i < argc; i++) |
| { |
| cp = argv[i]; |
| if (*cp == '-' || *cp == '/') |
| { |
| opt = *(++cp); |
| |
| switch (opt) |
| { |
| case 'h': |
| printUsage(argv[0]); |
| exit(0); |
| break; |
| |
| case 'i': |
| if ((i + 1) < argc) { |
| i++; |
| board_ip = (unsigned long)inet_addr(argv[i]); |
| } |
| break; |
| |
| case 'd': |
| mbimDb.debug_enable = 1; |
| break; |
| default: |
| { |
| ; |
| } |
| break; |
| } |
| } |
| } |
| } |
| |
| |