| /* Copyright Statement: |
| * |
| * This software/firmware and related documentation ("MediaTek Software") are |
| * protected under relevant copyright laws. The information contained herein |
| * is confidential and proprietary to MediaTek Inc. and/or its licensors. |
| * Without the prior written permission of MediaTek inc. and/or its licensors, |
| * any reproduction, modification, use or disclosure of MediaTek Software, |
| * and information contained herein, in whole or in part, shall be strictly prohibited. |
| */ |
| /* MediaTek Inc. (C) 2010. All rights reserved. |
| * |
| * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES |
| * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") |
| * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON |
| * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. |
| * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE |
| * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR |
| * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH |
| * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES |
| * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES |
| * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK |
| * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR |
| * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND |
| * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, |
| * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, |
| * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO |
| * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. |
| * |
| * The following software/firmware and/or related documentation ("MediaTek Software") |
| * have been modified by MediaTek Inc. All revisions are subject to any receiver's |
| * applicable license agreements with MediaTek Inc. |
| */ |
| #include <string.h> |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| #include <signal.h> |
| #include <errno.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <vendor-ril/telephony/ril.h> |
| |
| #include "common.h" |
| #include "util/utils.h" |
| #include "atci/ATCI.h" |
| #include "atci_util.h" |
| #include "atci_at_util.h" |
| #include "Radio_capability_switch_util.h" |
| |
| #ifdef ATCI_PARSE |
| #include "atci_sys_cmd.h" |
| #include "atci_ss_cmd.h" |
| #include "atci_cc_cmd.h" |
| #endif |
| |
| struct sockaddr_un atci_server_addr; |
| //struct sockaddr_in atci_server_addr; |
| //struct sockaddr_un atci_client_addr; |
| #undef LOG_TAG |
| #define LOG_TAG "DEMO_ATCI" |
| |
| #if ATCI_ENABLE_RESPONSE |
| char Respose_buf[RESPONSE_BUF_SIZE]; |
| #endif |
| |
| #ifdef ATCI_PARSE |
| int atci_dispatch_cmd(char *line); |
| #endif |
| |
| int atci_server_socket_fd, atci_client_connect; |
| namespace android { |
| extern int s_registerCalled; |
| } |
| |
| #define SOCKET_ZERO 0 |
| #define SOCKET_SUCC 1 |
| #define SOCKET_FAIL -1 |
| static int ATCI_Token = 0; |
| |
| int ATCISupport(int request) { |
| switch (request) { |
| case TELEPHONY_REQUEST_SET_CALL_FORWARD: |
| return 1; |
| case TELEPHONY_REQUEST_SET_CALL_WAITING: |
| return 1; |
| case TELEPHONY_REQUEST_SET_CALL_BARRING: |
| return 1; |
| case TELEPHONY_REQUEST_DIAL: |
| return 1; |
| case TELEPHONY_REQUEST_DROP_CONF_CALL_MEMBER: |
| return 1; |
| case TELEPHONY_REQUEST_FLIGHT: |
| return 1; |
| case TELEPHONY_REQUEST_SET_MUTE: |
| return 1; |
| case TELEPHONY_REQUEST_MERGE_CONF_CALLS: |
| return 1; |
| case TELEPHONY_REQUEST_CREATE_IMS_CONF_CALL: |
| return 1; |
| case TELEPHONY_REQUEST_DIAL_WITH_SIP_URI: |
| return 1; |
| default: |
| return 0; |
| } |
| } |
| const char * ATCIReqRspToString(int request) { |
| switch (request) { |
| case TELEPHONY_REQUEST_SET_CALL_FORWARD: |
| return "SET_CALL_FORWARD"; |
| case TELEPHONY_REQUEST_SET_CALL_WAITING: |
| return "SET_CALL_WAITING"; |
| case TELEPHONY_REQUEST_SET_CALL_BARRING: |
| return "SET_CALL_BARRING"; |
| case TELEPHONY_REQUEST_DIAL: |
| return "DIAL"; |
| case TELEPHONY_REQUEST_DROP_CONF_CALL_MEMBER: |
| return "DROP_CONF_CALL_MEMBER"; |
| case TELEPHONY_REQUEST_FLIGHT: |
| return "FLIGHT"; |
| case TELEPHONY_RESPONSE_FLIGHT: |
| return "RSP_FLIGHT"; |
| case TELEPHONY_REQUEST_SET_MUTE: |
| return "SET_MUTE"; |
| case TELEPHONY_REQUEST_MERGE_CONF_CALLS: |
| return "MERGE_CONF_CALLS"; |
| case TELEPHONY_REQUEST_CREATE_IMS_CONF_CALL: |
| return "CREATE_IMS_CONF_CALL"; |
| case TELEPHONY_REQUEST_DIAL_WITH_SIP_URI: |
| return "DIAL_WITH_SIP_URI"; |
| default: |
| return "<unknown request>"; |
| } |
| } |
| //return requestNumber |
| int ATCIParserRequest(int request) { |
| //char* cPoint = buf; |
| //int reqNum = 0; |
| |
| RLOGD("ATCI Parser request number start!"); |
| |
| //memcpy(&reqNum,cPoint,sizeof(int)); |
| RLOGD("Request is %d,%s", request, ATCIReqRspToString(request)); |
| |
| if (ATCISupport(request) != 1) |
| return -1; |
| |
| return request; |
| } |
| |
| int MappingATCI2RIL(int reqNum) { |
| int request = 0; |
| switch (reqNum) { |
| case TELEPHONY_REQUEST_SET_CALL_FORWARD: |
| request = RIL_REQUEST_SET_CALL_FORWARD; |
| break; |
| case TELEPHONY_REQUEST_SET_CALL_WAITING: |
| request = RIL_REQUEST_SET_CALL_WAITING; |
| break; |
| case TELEPHONY_REQUEST_SET_CALL_BARRING: |
| request = RIL_REQUEST_SET_FACILITY_LOCK; |
| break; |
| case TELEPHONY_REQUEST_DIAL: |
| request = RIL_REQUEST_DIAL; |
| break; |
| case TELEPHONY_REQUEST_DROP_CONF_CALL_MEMBER: |
| request = RIL_REQUEST_REMOVE_IMS_CONFERENCE_CALL_MEMBER; |
| break; |
| case TELEPHONY_REQUEST_FLIGHT: |
| request = RIL_REQUEST_RADIO_POWER; |
| break; |
| case TELEPHONY_REQUEST_SET_MUTE: |
| request = RIL_REQUEST_SET_MUTE; |
| break; |
| case TELEPHONY_REQUEST_MERGE_CONF_CALLS: |
| request = RIL_REQUEST_CONFERENCE; |
| break; |
| case TELEPHONY_REQUEST_CREATE_IMS_CONF_CALL: |
| request = RIL_REQUEST_CONFERENCE_DIAL; |
| break; |
| case TELEPHONY_REQUEST_DIAL_WITH_SIP_URI: |
| request = RIL_REQUEST_DIAL_WITH_SIP_URI; |
| break; |
| default: |
| request = -1; |
| } |
| |
| return request; |
| } |
| |
| int MappingParameter(int reqNum, int length, char* data, char* buf, |
| char** argv) { |
| int argc = 1; |
| char* cPoint; |
| |
| cPoint = buf; |
| switch (reqNum) { |
| case TELEPHONY_REQUEST_SET_CALL_FORWARD: { |
| if (length != sizeof(telephonyRequestSetCallForward)) { |
| RLOGD("Set_Call_Forward data error!"); |
| return -1; |
| } |
| telephonyRequestSetCallForward tempSCF; |
| memset(&tempSCF, 0, sizeof(tempSCF)); |
| memcpy(&tempSCF, data, length); |
| |
| //cmd parameter sequence: status, reason, number, time_seconds, service_class; other not need. |
| argv[1] = cPoint; //status |
| cPoint += sizeof(tempSCF.status); |
| sprintf(argv[1], "%d", tempSCF.status); |
| |
| argv[2] = cPoint; //reason |
| cPoint += sizeof(tempSCF.reason); |
| sprintf(argv[2], "%d", tempSCF.reason); |
| |
| argv[5] = cPoint; //service_class |
| cPoint += sizeof(tempSCF.service_class); |
| sprintf(argv[5], "%d", tempSCF.service_class); |
| |
| argv[6] = cPoint; //toa |
| cPoint += sizeof(tempSCF.toa); |
| sprintf(argv[6], "%d", tempSCF.toa); |
| |
| argv[3] = cPoint; //number |
| cPoint += sizeof(tempSCF.number); |
| sprintf(argv[3], "%s", tempSCF.number); |
| |
| argv[4] = cPoint; //time_seconds |
| sprintf(argv[4], "%d", tempSCF.time_seconds); |
| |
| argc += 5; |
| RLOGD( |
| "TELEPHONY_REQUEST_SET_CALL_FORWARD status(%s) reason(%s) number(%s) time_seconds(%s) service_class(%s) --toa(%s)", |
| argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); |
| } |
| break; |
| case TELEPHONY_REQUEST_SET_CALL_WAITING: { |
| if (length != sizeof(telephonyRequestSetCallWaiting)) { |
| RLOGD("Set_Call_Waiting data error!"); |
| return -1; |
| } |
| telephonyRequestSetCallWaiting tempSCW; |
| memset(&tempSCW, 0, sizeof(tempSCW)); |
| memcpy(&tempSCW, data, length); |
| |
| //cmd parameter sequence: statue, service_code |
| argv[1] = cPoint; //status |
| cPoint += sizeof(tempSCW.status); |
| sprintf(argv[1], "%d", tempSCW.status); |
| |
| argv[2] = cPoint; //service_class |
| sprintf(argv[2], "%d", tempSCW.service_class); |
| |
| argc += 2; |
| RLOGD("TELEPHONY_REQUEST_SET_CALL_WAITING status(%s) service_class(%s)", |
| argv[1], argv[2]); |
| } |
| break; |
| case TELEPHONY_REQUEST_SET_CALL_BARRING: { |
| if (length != sizeof(telephonyRequestSetCallBarring)) { |
| RLOGD("Set_Call_Barring data error!"); |
| return -1; |
| } |
| telephonyRequestSetCallBarring tempSCB; |
| memset(&tempSCB, 0, sizeof(tempSCB)); |
| memcpy(&tempSCB, data, length); |
| |
| //cmd parameter sequence: facility, password, serviceclass,enable; other not need. |
| argv[4] = cPoint; //status |
| cPoint += sizeof(tempSCB.status); |
| sprintf(argv[4], "%d", tempSCB.status); |
| |
| argv[1] = cPoint; //facility |
| cPoint += sizeof(tempSCB.facility); |
| sprintf(argv[1], "%s", tempSCB.facility); |
| |
| argv[2] = cPoint; //password |
| cPoint += sizeof(tempSCB.password); |
| sprintf(argv[2], "%s", tempSCB.password); |
| |
| argv[3] = cPoint; //serviceclass |
| cPoint += sizeof(tempSCB.serviceClass); |
| sprintf(argv[3], "%d", tempSCB.serviceClass); |
| |
| argc += 4; |
| RLOGD( |
| "TELEPHONY_REQUEST_SET_CALL_Barring facility(%s) password(%s) service_class(%s) status(enable)(%s)", |
| argv[1], argv[2], argv[3], argv[4]); |
| } |
| break; |
| case TELEPHONY_REQUEST_DIAL: { |
| if (length != sizeof(telephonyRequestDial)) { |
| RLOGD("Request dail data error!"); |
| return -1; |
| } |
| telephonyRequestDial tempDIAL; |
| memset(&tempDIAL, 0, sizeof(tempDIAL)); |
| memcpy(&tempDIAL, data, length); |
| |
| //cmd parameter sequence: callnumber, clir; |
| argv[2] = cPoint; //clir |
| cPoint += sizeof(tempDIAL.clir); |
| sprintf(argv[2], "%d", tempDIAL.clir); |
| |
| argv[1] = cPoint; //phonyNumber |
| sprintf(argv[1], "%s", tempDIAL.phonyNumber); |
| |
| argc += 2; |
| RLOGD("TELEPHONY_REQUEST_DIAL CLIR(%s) PhoneNumber(%s)", argv[2], argv[1]); |
| } |
| break; |
| case TELEPHONY_REQUEST_DROP_CONF_CALL_MEMBER: { |
| if (length != sizeof(telephonyRequestDropConfCallMember)) { |
| RLOGD("DropConfCallMember data error!"); |
| return -1; |
| } |
| telephonyRequestDropConfCallMember tempDCCM; |
| memset(&tempDCCM, 0, sizeof(tempDCCM)); |
| memcpy(&tempDCCM, data, length); |
| |
| //cmd parameter sequence: callId, addr, ToAdd; other not need. |
| argv[1] = cPoint; //ConfCallID |
| cPoint += sizeof(tempDCCM.confCallID); |
| sprintf(argv[1], "%d", tempDCCM.confCallID); |
| |
| argv[2] = cPoint; //phonyNumber |
| cPoint += sizeof(tempDCCM.phonyNumber); |
| sprintf(argv[2], "%d", tempDCCM.phonyNumber); |
| |
| argv[3] = cPoint; //callIDToAdd |
| sprintf(argv[3], "%d", tempDCCM.callIDToAdd); |
| |
| argc += 3; |
| RLOGD( |
| "TELEPHONY_REQUEST_DROP_CONF_CALL_MEMBER ConfCallID(%s) phonyNumber(%s) callIDToAdd(%s)", |
| argv[1], argv[2], argv[3]); |
| } |
| break; |
| case TELEPHONY_REQUEST_FLIGHT: { |
| if (length != sizeof(telephonyRequestFlight)) { |
| RLOGD("Request flight data error!"); |
| return -1; |
| } |
| telephonyRequestFlight tempFT; |
| memset(&tempFT, 0, sizeof(tempFT)); |
| memcpy(&tempFT, data, length); |
| |
| //cmd parameter sequence: mode. |
| argv[1] = cPoint; //flightModeOn |
| sprintf(argv[1], "%d", (tempFT.flightModeOn == 1 ? 0 : 1)); |
| |
| argc += 1; |
| RLOGD("TELEPHONY_REQUEST_FLIGHT flight Mode is %s-->(%s)", |
| (tempFT.flightModeOn == 1 ? "On" : "Off"), argv[1]); |
| } |
| break; |
| case TELEPHONY_REQUEST_SET_MUTE: { |
| if (length != sizeof(telephonyRequestSetMute)) { |
| RLOGD("Request flight data error!"); |
| return -1; |
| } |
| telephonyRequestSetMute tempSM; |
| memset(&tempSM, 0, sizeof(tempSM)); |
| memcpy(&tempSM, data, length); |
| |
| //cmd parameter sequence: mode. |
| argv[1] = cPoint; //isMute |
| sprintf(argv[1], "%d", tempSM.isMute); |
| |
| argc += 1; |
| RLOGD("TELEPHONY_REQUERT_SET_MUTE isMute(%s)", argv[1]); |
| } |
| break; |
| case TELEPHONY_REQUEST_MERGE_CONF_CALLS: { |
| RLOGD("TELEPHONY_REQUERT_MERGE_CONF_CALLS (No Parm.)"); |
| } |
| break; |
| case TELEPHONY_REQUEST_CREATE_IMS_CONF_CALL: { |
| //cmd parameter sequence: DialMethod, ParticipantsNumber, addresses, clir; |
| argv[1] = cPoint; //DialMethod |
| sprintf(argv[1], "%d", 0); |
| cPoint += sizeof(int); |
| |
| argv[2] = cPoint; //ParticipantsNumber |
| sprintf(argv[2], "%d", 0); |
| cPoint += sizeof(int); |
| //no address |
| argv[3] = cPoint; //CLIR |
| sprintf(argv[2], "%s", "0"); |
| |
| argc += 3; |
| RLOGD( |
| "TELEPHONY_REQUEST_CREATE_IMS_CONF_CALL dialMethod(%d) PhoneNumber(%d),clir(%s)", |
| argv[1], argv[2], argv[3]); |
| } |
| break; |
| case TELEPHONY_REQUEST_DIAL_WITH_SIP_URI: { |
| if (length != sizeof(telephonyRequestDial)) //struct with the same as DIAL |
| { |
| RLOGD("Request DialWithSipUri data error!"); |
| return -1; |
| } |
| telephonyRequestDial tempDWSU; |
| memset(&tempDWSU, 0, sizeof(tempDWSU)); |
| memcpy(&tempDWSU, data, length); |
| |
| //cmd parameter sequence: address, clir; |
| argv[2] = cPoint; //clir |
| cPoint += sizeof(tempDWSU.clir); |
| sprintf(argv[2], "%d", tempDWSU.clir); |
| |
| argv[1] = cPoint; //address |
| sprintf(argv[1], "%s", tempDWSU.phonyNumber); |
| |
| argc += 2; |
| RLOGD("TELEPHONY_REQUEST_DIAL_WITH_SIP_URI CLIR(%d) PhoneNumber(%s)", |
| argv[2], argv[1]); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return argc; |
| } |
| |
| void ATCIResponse(int token, int error, char* data, int reqNum) |
| { |
| //int reqNum; |
| char buf[64]; |
| if(token&ATCI_TOKEN_MARK != ATCI_TOKEN_MARK) { |
| if(token == 0 && data == NULL && reqNum == 0) { |
| RLOGD("AT%RESTART: %d", error); |
| } else { |
| RLOGE("ATCIRespnse Error, Token not ATCI\n"); |
| } |
| |
| } else { |
| RLOGD("token is %d,%s",reqNum,android::requestToString(reqNum)); |
| } |
| |
| memset(buf, 0, sizeof(buf)); |
| if(error == 1){ |
| sprintf(buf,"%s","ERROR"); |
| } else { |
| sprintf(buf,"%s","OK"); |
| } |
| |
| int len_s = send(atci_client_connect, buf, strlen(buf), 0); |
| RLOGD("Response Buf is %s, send length is %d",buf,len_s); |
| } |
| |
| #ifdef ATCI_PARSE |
| int acti_cmd_recv(int fd, char *buf, int len) { |
| int ret = 0; |
| fd_set rfds; |
| //FD_CLR(fd, &rfds); |
| FD_SET(fd, &rfds); |
| ret = select(fd + 1, &rfds, NULL, NULL, NULL); |
| if (ret <= 0) { |
| RLOGE("acti_cmd_recv select error, ret=%d, error=%s(%d),fd=%d", ret, |
| strerror(errno), errno, fd); |
| return SOCKET_FAIL; |
| } |
| if (FD_ISSET(fd, &rfds)) { |
| ret = recv(fd, buf, len, 0); |
| if (ret < 0) { |
| RLOGE("acti_cmd_recv select error, ret=%d, error=%s(%d),fd=%d", ret, |
| strerror(errno), errno, fd); |
| return SOCKET_FAIL; |
| } else if (ret == 0) { |
| RLOGE("acti_cmd_recv recv error, ret=%d, error=%s(%d),fd=%d", ret, |
| strerror(errno), errno, fd); |
| return SOCKET_ZERO; |
| } else { |
| //buf[ret] = '\0'; |
| } |
| |
| } |
| return SOCKET_SUCC; |
| } |
| #endif |
| |
| int atci_sock_recv(int fd, char *buf, int len) { |
| int ret = 0; |
| int offset = 0; |
| |
| while (offset < len) { |
| fd_set rfds; |
| FD_SET(fd, &rfds); |
| ret = select(fd + 1, &rfds, NULL, NULL, NULL); |
| if (ret < 0) { |
| if (errno == EINTR || errno == EAGAIN) { |
| continue; |
| } |
| RLOGE("atci_sock_recv select error, ret=%d, error=%s(%d),fd=%d", ret, |
| strerror(errno), errno, fd); |
| return SOCKET_FAIL; |
| } else if (ret == 0) { |
| continue; |
| } |
| if (FD_ISSET(fd, &rfds)) { |
| ret = recv(fd, buf + offset, len - offset, 0); |
| if (ret < 0) { |
| RLOGE("atci_sock_recv recv error, ret=%d, error=%s(%d),fd=%d", ret, |
| strerror(errno), errno, fd); |
| return SOCKET_FAIL; |
| } else if (ret == 0) { |
| RLOGE("atci_sock_recv recv error, ret=%d, error=%s(%d),fd=%d", ret, |
| strerror(errno), errno, fd); |
| return SOCKET_ZERO; |
| } |
| offset += ret; |
| } |
| } |
| return SOCKET_SUCC; |
| } |
| |
| void sendAtciRequest(int request, char* reqStr, int argc, char** argv) { |
| //for dsds, should close two slot radio. |
| if(utils::is_support_dsds() && (request == RIL_REQUEST_RADIO_POWER)){ |
| int enable = atoi(argv[1])? 1 : 0; |
| for(int i = 0; i < 2; i++) { |
| //For GCF, enhance AT%Flight=0. only SIM is inserted, radio can open. |
| if(enable){ |
| if (Radio_capability_switch_util::is_sim_inserted(i)) { |
| RequestInfo* pRI = (RequestInfo*) (calloc(1, sizeof(RequestInfo))); |
| pRI->socket_id = (RIL_SOCKET_ID)i; |
| android::ATCIRequest(request, reqStr, (void*) (pRI), argc, argv); |
| } { |
| RLOGD("ignore radio power on command because of absent SIM Card"); |
| } |
| } else { |
| RequestInfo* pRI = (RequestInfo*) (calloc(1, sizeof(RequestInfo))); |
| pRI->socket_id = (RIL_SOCKET_ID)i; |
| android::ATCIRequest(request, reqStr, (void*) (pRI), argc, argv); |
| } |
| } |
| } else { |
| RequestInfo* pRI = (RequestInfo*) (calloc(1, sizeof(RequestInfo))); |
| android::ATCIRequest(request, reqStr, (void*) (pRI), argc, argv); |
| } |
| return; |
| } |
| |
| void * StartATCISocket(void *param) { |
| RLOGD("StartATCISocket start\n"); |
| socklen_t server_len, client_len; |
| struct sockaddr_un atci_client_addr; |
| //struct sockaddr_in atci_client_addr; |
| char parser_buf[SOCKET_BUF_SIZE]; |
| char *argv[ATCI_MAX_ARGS]; |
| int argc = 0; |
| |
| prctl(PR_SET_NAME, (unsigned long) "ATCI_Thr"); |
| |
| /* create socket */ |
| unlink(ATCI_SERVER_SOCKET); |
| atci_server_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); |
| //atci_server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); |
| if (atci_server_socket_fd == -1) { |
| RLOGE("Create ATCI Socket Failed:"); |
| exit(1); |
| } |
| memset(&atci_server_addr, 0, sizeof(atci_server_addr)); |
| atci_server_addr.sun_family = AF_UNIX; |
| //atci_server_addr.sin_family = AF_INET; |
| //atci_server_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
| //atci_server_addr.sin_port = htons(10004); |
| strcpy(atci_server_addr.sun_path, ATCI_SERVER_SOCKET); |
| server_len = sizeof(atci_server_addr); |
| /* bind socket port*/ |
| if (-1 |
| == bind(atci_server_socket_fd, (struct sockaddr *) &atci_server_addr, |
| server_len)) { |
| RLOGE("Server Bind Failed:"); |
| exit(1); |
| } |
| |
| if (listen(atci_server_socket_fd, 1) == -1) { |
| RLOGE("listen fail!"); |
| close(atci_server_socket_fd); |
| exit(1); |
| } |
| #ifdef ATCI_PARSE |
| DbgMsg("init cmd handle"); |
| if(/*atci_generic_init(NULL)||*/atci_cc_init(NULL)||atci_ss_init(NULL)||atci_sys_init(NULL)) { |
| ErrMsg("module init function error,exit"); |
| exit(-1); |
| } |
| #endif |
| TryNewLink: |
| client_len = sizeof(atci_client_addr); |
| int conn = accept(atci_server_socket_fd, |
| (struct sockaddr *) &atci_client_addr, &client_len); |
| if (conn <= 0) { |
| RLOGE("accept error!"); |
| close(conn); |
| exit(1); |
| } |
| RLOGD("Accept a client , fd is %d", conn); |
| atci_client_connect = conn; |
| socketData recv_data; |
| int ret; |
| /* tranlate data */ |
| while (true) { |
| if (!android::s_registerCalled) { |
| sleep(1); |
| continue; |
| } |
| #ifdef ATCI_PARSE |
| memset(parser_buf, 0, sizeof(parser_buf)); |
| ret = acti_cmd_recv(conn, parser_buf, SOCKET_BUF_SIZE); |
| if (ret < 0) { |
| RLOGE("receive CMD error"); |
| continue; |
| } else if (ret == SOCKET_ZERO) { |
| RLOGE("maybe client socket closed 1. retry new link!"); |
| goto TryNewLink; |
| } |
| atci_dispatch_cmd(parser_buf); |
| #else |
| memset(parser_buf, 0, sizeof(parser_buf)); |
| memset(&recv_data, 0, sizeof(socketData)); |
| |
| //receive_ID |
| ret = atci_sock_recv(conn, (char*) &recv_data.requestId, |
| sizeof(recv_data.requestId)); |
| if (ret < 0) { |
| RLOGE("reveive request id is error"); |
| continue; |
| } else if (ret == SOCKET_ZERO) { |
| RLOGE("maybe client socket closed 1. retry new link!"); |
| goto TryNewLink; |
| } |
| RLOGE("reveive request id is %d", recv_data.requestId); |
| |
| //receive_length |
| ret = atci_sock_recv(conn, (char*) &recv_data.datalen, |
| sizeof(recv_data.datalen)); |
| if (ret < 0) { |
| RLOGE("reveive request lenth is error"); |
| continue; |
| } else if (ret == SOCKET_ZERO) { |
| RLOGE("maybe client socket closed 2. retry new link!"); |
| goto TryNewLink; |
| } |
| RLOGE("reveive request lenth is %d", recv_data.datalen); |
| |
| //receive_data |
| recv_data.data = (char*) calloc(recv_data.datalen, 1); |
| if (NULL == recv_data.data) { |
| RLOGE("alloc mem error"); |
| continue; |
| } |
| ret = atci_sock_recv(conn, recv_data.data, recv_data.datalen); |
| if (ret < 0) { |
| RLOGE("reveive request data is error"); |
| free(recv_data.data); |
| recv_data.data = NULL; |
| continue; |
| } else if (ret == SOCKET_ZERO) { |
| RLOGE("maybe client socket closed 3. retry new link!"); |
| free(recv_data.data); |
| recv_data.data = NULL; |
| goto TryNewLink; |
| } |
| |
| int reqNum = ATCIParserRequest(recv_data.requestId); |
| if (reqNum <= 0) { |
| RLOGE("ATCI command is error!"); |
| continue; |
| } |
| |
| int request = MappingATCI2RIL(reqNum); |
| char reqStr[RIL_REQUEST_STRING_LENGTH]; |
| |
| memcpy(reqStr, request2RILStr(request), |
| strlen(request2RILStr(request)) + 1); |
| RLOGD("request is %s", reqStr); |
| argc = MappingParameter(reqNum, recv_data.datalen, recv_data.data, |
| parser_buf, argv); |
| if (argc <= 0) { |
| RLOGE("ATCI command is error!"); |
| continue; |
| } |
| free(recv_data.data); |
| recv_data.data = NULL; |
| sendAtciRequest(request, reqStr, argc, argv); |
| #endif |
| }; |
| |
| RLOGD("close socket fd!"); |
| close(atci_server_socket_fd); |
| |
| RLOGD("exist start ATCI socket thread, errno:%d", errno); |
| // kill self to restart on error |
| kill(0, SIGKILL); |
| return NULL; |
| } |
| |
| #ifdef ATCI_PARSE |
| char* atci_get_cmd_prefix(char *line) { |
| int buf_len; |
| char *prefix; |
| char *end_ptr; |
| if (NULL == line) { |
| RLOGD("input is null"); |
| return NULL; |
| } |
| end_ptr = line; |
| while (!ATCI_IS_CAHR(*end_ptr, ATCI_EQUAL) |
| && !ATCI_IS_CAHR(*end_ptr, ATCI_QUESTION_MARK) |
| && !ATCI_IS_CAHR(*end_ptr, ATCI_END_CHAR) |
| && !ATCI_IS_CAHR(*end_ptr, ATCI_CR) && !ATCI_IS_CAHR(*end_ptr, ATCI_LF)) { |
| end_ptr++; |
| } |
| buf_len = end_ptr - line + 1; |
| prefix = (char *) calloc(buf_len, 1); |
| if (prefix) { |
| int i; |
| char *in_ptr = line; |
| char *out_ptr = prefix; |
| for (i = 0; i < buf_len - 1; i++) { |
| if (!ATCI_IS_CAHR(*in_ptr, ATCI_SPACE)) { |
| *out_ptr = ATCI_UPPER_TO_LOWER(*in_ptr); |
| out_ptr++; |
| } |
| in_ptr++; |
| } |
| *out_ptr = ATCI_END_CHAR; |
| } |
| RLOGD("get cmd prefix [%d][%s]", buf_len, prefix); |
| return prefix; |
| } |
| |
| int atci_get_cmd_mode(char *line) { |
| int reasult = AT_WRONG_MODE; |
| char *p_cur = NULL; |
| if (NULL == line) { |
| reasult = AT_WRONG_MODE; |
| RLOGD("atci_get_cmd_mode error, input is NULL"); |
| return reasult; |
| } |
| p_cur = strchr(line, ATCI_EQUAL); |
| if (NULL == p_cur) { |
| p_cur = strchr(line, ATCI_QUESTION_MARK); |
| if (NULL == p_cur) { |
| reasult = AT_ACTIVE_MODE; |
| } else { |
| reasult = AT_READ_MODE; |
| } |
| } else { |
| p_cur++; |
| atci_at_skip_space(&p_cur); |
| if (ATCI_QUESTION_MARK == *p_cur) { |
| reasult = AT_TEST_MODE; |
| } else { |
| reasult = AT_SET_MODE; |
| } |
| } |
| RLOGD("atci_get_cmd_mode success[%d]", reasult); |
| return reasult; |
| } |
| |
| int atci_dispatch_cmd(char *line) { |
| int ret = SYS_FAIL; |
| char *prefix = NULL; |
| //atci_Info_t* atci_ptr = atci_info_get(); |
| atci_cmd_type_t* cmd_handle = NULL; |
| if (NULL == line) { |
| RLOGD("CMD is null"); |
| return SYS_FAIL; |
| } |
| RLOGD("enter: %s", line); |
| |
| prefix = atci_get_cmd_prefix(line); |
| if (NULL == prefix) { |
| RLOGD("atci_cut_cmd_prefix error"); |
| return SYS_FAIL; |
| } |
| RLOGD("find prefix [%s]", prefix); |
| cmd_handle = atci_find_cmd_handler(prefix); |
| free(prefix); |
| if (NULL == cmd_handle) { |
| RLOGD("not find handler"); |
| } else { |
| RLOGD("find handler"); |
| int cmd_mode = atci_get_cmd_mode(line); |
| char response[MAX_RESP_BUF_LENGTH]; |
| memset(response, 0, sizeof(response)); |
| RLOGD("write to handler"); |
| ret = cmd_handle->cmd_handle_func(line, cmd_mode, cmd_handle->target, |
| response); |
| if (SYS_FAIL == ret) { |
| RLOGD("cmd_handle_func error"); |
| } else { |
| RLOGD("cmd_handle_func success"); |
| } |
| } |
| return ret; |
| } |
| #endif |