| #include <unistd.h> | |
| #include <assert.h> | |
| #include <signal.h> | |
| #include <libubox/blobmsg.h> | |
| #include <libubus.h> | |
| #include <uci.h> | |
| #include "rilutil.h" | |
| #include "ril.h" | |
| #include "stk.h" | |
| #include "bip.h" | |
| #include <include/log.h> | |
| #include <sys/prctl.h> | |
| #include <telephony/cm.h> | |
| #define STK_PACKAGE_NAME "stk" | |
| #ifndef UNUSEDPARAM | |
| #define UNUSEDPARAM(param) (void)param; | |
| #endif | |
| static struct ubus_context *stk_ubus_ctx = NULL; | |
| static struct blob_buf b_stk_buf; | |
| static struct blob_buf b_stk_sms; | |
| static struct blob_buf b_stk_resp_buf; | |
| static char *proactiveSave = NULL; | |
| static char *proactive_setup_menu= NULL; | |
| static struct ubus_subscriber stk_unsol; | |
| static struct ubus_object_type stk_unsol_object_type; | |
| static void stk_add_subscriber(struct uloop_timeout *timeout); | |
| static int stk_handle_proactive_data(struct ubus_context *ctx, char *data, int simid); | |
| static int stk_handle_sms_pp_download(struct ubus_context *ctx, char *data, int simid); | |
| static unsigned char getValueFromHexStr( char *data_str , unsigned long index ); | |
| static void stk_service_request_cb(struct ubus_request *req, int type, struct blob_attr *msg); | |
| static int send_setup_menu_terminal_response(char *command_details); | |
| int stk_handle_ril_ind(struct ubus_context *ctx, unsigned int rilid, unsigned int rilerror, void *data, int data_len); | |
| static void complete_stk_async_cb(struct ubus_request *req, int ret); | |
| static int enable_stk(void); | |
| static struct uloop_timeout stk_add_subscribe_timeout = { | |
| .cb = stk_add_subscriber, | |
| }; | |
| uint32_t rilid; | |
| typedef enum | |
| { | |
| ATCI_MSG_CODING_DEFAULT = 0x00, | |
| ATCI_MSG_CODING_8BIT = 0x01, | |
| ATCI_MSG_CODING_UCS2 = 0x02, | |
| ATCI_MSG_CODING_RESERVED = 0x03, | |
| ATCI_MSG_CODING_NUM_OF | |
| }MSG_CODING; | |
| #define ATCI_SMS_TP_RP 0x80 /* TP-RP, reply path */ | |
| #define ATCI_SMS_TP_UDHI 0x40 /* TP User Data Header Indicator */ | |
| #define ATCI_SMS_TP_SRI 0x20 /* TP Status Report Indication */ | |
| #define ATCI_SMS_TP_SRR 0x20 /* TP Status Report Request */ | |
| #define ATCI_SMS_TP_SRQ 0x20 /* TP Status Report Qualifier */ | |
| #define ATCI_SMS_TP_VPF 0x18 /* TP Validity Period Format */ | |
| #define ATCI_SMS_TP_MMS 0x04 /* TP More Messages to Send */ | |
| #define ATCI_SMS_TP_RD 0x04 /* TP Reject Duplicates */ | |
| static char *newpdu[STK_MAX_SIM]; | |
| extern struct ubus_context *router_ubus_ctx; | |
| extern void STK_CleanupAllBIPChannel(int); | |
| extern void bip_process_sessionend(int); | |
| extern void handleCGEV(int simid, int cid); | |
| enum { | |
| STK_PROACTIVE, | |
| STK_EVENT_NOTIFY, | |
| }; | |
| enum { | |
| STK_PROFILE, | |
| }; | |
| enum { | |
| STK_COMMAND_RESP_COMMAND_DETAILS, | |
| STK_RESPONSE_RESULT, | |
| STK_RESPONSE_ADD_RESULT, | |
| STK_DCS, | |
| STK_STRING_DATA, | |
| }; | |
| enum { | |
| STK_ACCEPT_REJECT_CALL, | |
| }; | |
| enum { | |
| STK_ENVELOP_TYPE, | |
| STK_ENVELOP_DATA1, | |
| STK_ENVELOP_DATA2, | |
| }; | |
| static const struct blobmsg_policy stk_practive_pol[] = { | |
| [STK_PROACTIVE] = {.name = "proactive",.type = BLOBMSG_TYPE_STRING}, | |
| [STK_EVENT_NOTIFY] = {.name = "event_notify",.type = BLOBMSG_TYPE_STRING}, | |
| }; | |
| static const struct blobmsg_policy set_stk_profile_pol[] = { | |
| [STK_PROFILE] = { | |
| .name = "profile", | |
| .type = BLOBMSG_TYPE_STRING, | |
| }, | |
| }; | |
| static const struct blobmsg_policy send_terminal_response_pol[] = { | |
| [STK_COMMAND_RESP_COMMAND_DETAILS] = {.name = "commandDetails", .type = BLOBMSG_TYPE_STRING}, | |
| [STK_RESPONSE_RESULT] = {.name = "TerminalResponseResult", .type = BLOBMSG_TYPE_STRING }, | |
| [STK_RESPONSE_ADD_RESULT] = {.name = "TerminalResponseAddResult", .type = BLOBMSG_TYPE_STRING }, | |
| [STK_DCS] = {.name = "DataCodeSceme", .type = BLOBMSG_TYPE_STRING}, | |
| [STK_STRING_DATA] = {.name = "responseString", .type = BLOBMSG_TYPE_STRING}, | |
| }; | |
| static const struct blobmsg_policy send_call_setup_response_pol[] = { | |
| [STK_ACCEPT_REJECT_CALL] = {.name = "acceptRejectCall", .type = BLOBMSG_TYPE_STRING }, | |
| }; | |
| static const struct blobmsg_policy send_envelop_command_pol[] = { | |
| [STK_ENVELOP_TYPE] = {.name = "envelopType", .type = BLOBMSG_TYPE_STRING}, | |
| [STK_ENVELOP_DATA1] = {.name = "envelopData1", .type = BLOBMSG_TYPE_STRING }, | |
| [STK_ENVELOP_DATA2] = {.name = "envelopData2", .type = BLOBMSG_TYPE_STRING }, | |
| }; | |
| static struct ubus_object stk_notify_obj[3] = | |
| { | |
| {.name = "stk.unsol.proactive", .type = &stk_unsol_object_type,}, | |
| {.name = "stk.unsol.eventnotify", .type = &stk_unsol_object_type,}, | |
| {.name = "stk.unsol.sendsms", .type = &stk_unsol_object_type,}, | |
| }; | |
| static struct blob_buf stk_notify_blob; | |
| #define CHL_REQ_TIMEOUT 20000 | |
| static int stkmsg[STK_MAX_SIM]; | |
| static int stkmsg_cmdnumber[STK_MAX_SIM]; | |
| static int stkmsg_cmdqual[STK_MAX_SIM]; | |
| #ifdef CHL_COMPILE | |
| static unsigned int bip_chl_id; | |
| /****************************************************************************** | |
| * defines and structs for ubus invoke chl register | |
| ******************************************************************************/ | |
| /* blob for register response */ | |
| enum chl_blob_reg_resp { | |
| CHL_REG_REQ_STATUS, /*u32*/ | |
| CHL_REG_PDP_ID, /*u32*/ | |
| _CHL_REG_RESP_MAX | |
| }; | |
| static const struct blobmsg_policy chl_reg_resp_pol[] = { | |
| [CHL_REG_REQ_STATUS] = { | |
| .name = "req_status", | |
| .type = BLOBMSG_TYPE_INT32}, | |
| [CHL_REG_PDP_ID] = { | |
| .name = CHL_ID_STR, | |
| .type = BLOBMSG_TYPE_INT32}, | |
| }; | |
| enum chl_resp_table { | |
| CHL_REG_TABLE, /*table*/ | |
| _CHL_REG_TABLE_MAX | |
| }; | |
| static const struct blobmsg_policy chl_table_pol[] = { | |
| [CHL_REG_TABLE] = { | |
| .name = "response", | |
| .type = BLOBMSG_TYPE_TABLE}, | |
| }; | |
| struct chl_bip_reg_response { | |
| int req_status; | |
| int id; | |
| char method[20]; | |
| }; | |
| struct chl_bip_open_response { | |
| int req_status; | |
| int nw_status; | |
| int ril_status; | |
| }; | |
| /****************************************************************************** | |
| * defines and structs for ubus invoke chl open | |
| ******************************************************************************/ | |
| /* blob for open response */ | |
| enum chl_blob_open_resp { | |
| CHL_OPEN_REQ_STATUS, /*u32*/ | |
| CHL_OPEN_NW_STATUS, /*u32*/ | |
| CHL_OPEN_RIL_STATUS, /*u32*/ | |
| _CHL_OPEN_RESP_MAX | |
| }; | |
| static const struct blobmsg_policy chl_open_resp_pol[] = { | |
| [CHL_OPEN_REQ_STATUS] = { | |
| .name = "req_status", | |
| .type = BLOBMSG_TYPE_INT32}, | |
| [CHL_OPEN_NW_STATUS] = { | |
| .name = "nw_status", | |
| .type = BLOBMSG_TYPE_INT32}, | |
| [CHL_OPEN_RIL_STATUS] = { | |
| .name = "ril_status", | |
| .type = BLOBMSG_TYPE_INT32}, | |
| }; | |
| static inline enum chl_req_status str_to_req_status(char *str) | |
| { | |
| if (!strcmp(str,"CHL_OK")) | |
| return CHL_OK; | |
| if (!strcmp(str,"CHL_INVALID_REQ")) | |
| return CHL_INVALID_REQ; | |
| if (!strcmp(str,"CHL_INTERNAL_ERROR")) | |
| return CHL_INTERNAL_ERROR; | |
| if (!strcmp(str,"CHL_ID_NOT_FOUND")) | |
| return CHL_ID_NOT_FOUND; | |
| if (!strcmp(str,"RIL_ERROR_OCCURED")) | |
| return RIL_ERROR_OCCURED; | |
| return -1; | |
| } | |
| static inline enum chl_nw_status str_to_nw_state(char *str) | |
| { | |
| if (!strcmp(str,"DATA_UNAVAILABLE")) | |
| return DATA_UNAVAILABLE; | |
| if (!strcmp(str,"DATA_AVAILABLE")) | |
| return DATA_AVAILABLE; | |
| if (!strcmp(str,"DATA_PENDING")) | |
| return DATA_PENDING; | |
| return -1; | |
| } | |
| /****************************************************************************** | |
| * defines and structs for ubus invoke chl unregister/close | |
| ******************************************************************************/ | |
| /* struct for unregister/close response */ | |
| struct chl_bip_response { | |
| int req_status; | |
| int nw_status; | |
| }; | |
| /* blob for unregister/close response */ | |
| enum chl_blob_unreg_resp { | |
| CHL_UNREG_REQ_STATUS, /*u32*/ | |
| CHL_UNREG_NW_STATUS, /*u32*/ | |
| _CHL_UNREG_RESP_MAX | |
| }; | |
| static const struct blobmsg_policy chl_unregister_resp_pol[] = { | |
| [CHL_UNREG_REQ_STATUS] = { | |
| .name = "req_status", | |
| .type = BLOBMSG_TYPE_INT32}, | |
| [CHL_UNREG_NW_STATUS] = { | |
| .name = "nw_status", | |
| .type = BLOBMSG_TYPE_INT32}, | |
| }; | |
| /****************************************************************************** | |
| * defines and structs for ubus invoke chl set_route/del_route | |
| ******************************************************************************/ | |
| struct chl_bip_route_response { | |
| int req_status; | |
| bool add; | |
| }; | |
| static const struct blobmsg_policy chl_route_pol[] = { | |
| [CHL_UNREG_REQ_STATUS] = { | |
| .name = "req_status", | |
| .type = BLOBMSG_TYPE_INT32}, | |
| }; | |
| #endif | |
| static int stk_save_proactive_setup_menu(char *data_str) { | |
| if (!proactive_setup_menu) { | |
| proactive_setup_menu = malloc(strlen(data_str) + 1); | |
| if (!proactive_setup_menu) | |
| return -1; | |
| memset(proactive_setup_menu, 0, strlen(data_str) + 1); | |
| strcpy(proactive_setup_menu, data_str); | |
| } | |
| return 0; | |
| } | |
| static char *stk_get_proactive_setup_menu() { | |
| return proactive_setup_menu; | |
| } | |
| /*send TR at+mstk=11,data*/ | |
| void send_terminal_response(const char *pdata, int simid) | |
| { | |
| if(pdata == NULL) | |
| { | |
| LOG_OUT_E("%s,pdata is null", __FUNCTION__); | |
| return; | |
| } | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, | |
| (void *)pdata, strlen(pdata)+1); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb,0,0); | |
| } | |
| static void send_terminal_response_async(const char *pdata, int simid) | |
| { | |
| int ret; | |
| struct ubus_request *req = NULL; | |
| if(pdata == NULL) | |
| { | |
| LOG_OUT_E("%s,pdata is null", __FUNCTION__); | |
| return; | |
| } | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, | |
| (void *)pdata, strlen(pdata)+1); | |
| req = malloc(sizeof(struct ubus_request)); | |
| memset(req, 0, sizeof(struct ubus_request)); | |
| if ((ret = ubus_invoke_async(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, req)) != UBUS_STATUS_OK) { | |
| LOG_OUT_D("ubus_invoke_async failed"); | |
| free(req); | |
| } else { | |
| req->data_cb = stk_service_request_cb; | |
| req->complete_cb = complete_stk_async_cb; | |
| ubus_complete_request_async(stk_ubus_ctx, req); | |
| LOG_OUT_D("send tr"); | |
| } | |
| } | |
| /*send TR at+mstk=4,data*/ | |
| void send_envelope(const char *pdata, int simid) | |
| { | |
| int ret; | |
| struct ubus_request *req = NULL; | |
| LOG_OUT("send_envelope"); | |
| if(pdata == NULL) | |
| { | |
| LOG_OUT("%s,pdata is null", __FUNCTION__); | |
| return; | |
| } | |
| req = malloc(sizeof(struct ubus_request)); | |
| memset(req, 0, sizeof(struct ubus_request)); | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, | |
| (void *)pdata, strlen(pdata)+1); | |
| if ((ret = ubus_invoke_async(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, req)) != UBUS_STATUS_OK) { | |
| LOG_OUT_E("ubus_invoke_async send_envelope failed"); | |
| free(req); | |
| } else { | |
| req->data_cb = stk_service_request_cb; | |
| req->complete_cb = complete_stk_async_cb; | |
| ubus_complete_request_async(stk_ubus_ctx, req); | |
| } | |
| } | |
| void query_sim_status(int simid) | |
| { | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_GET_SIM_STATUS, NULL, 0); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb, 0, 0); | |
| } | |
| void stk_setproactivecmd(int enable, int simid) | |
| { | |
| LOG_OUT_D("%s,enable:%d\n", __FUNCTION__, enable); | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_SET_PROACTIVECMD, &enable, 1); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb, 0, 0); | |
| } | |
| void stk_queryCGACT(int simid) | |
| { | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_GET_CID_STATE, NULL, 0); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb, 0, 0); | |
| } | |
| int stk_querypdplist(void *req, int simid) | |
| { | |
| int ret; | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_DATA_CALL_LIST, NULL, 0); | |
| ret = ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb, req, 0); | |
| return ret; | |
| } | |
| void queryPdpIPApn(int cid, int simid) | |
| { | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_GET_PDPIPAPN, &cid, 1); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb, &cid, 0); | |
| } | |
| int bip_sendatcmd(char *atcmd, void *req, int simid) | |
| { | |
| int ret; | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_SEND_ATCMD, (void *)atcmd, strlen(atcmd)+1); | |
| ret = ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb, req, 0); | |
| return ret; | |
| } | |
| #ifdef CHL_COMPILE | |
| static int bip_ubus_invoke(struct blob_buf *b, | |
| uint32_t id, const char *method, ubus_data_handler_t cb, | |
| void *priv, unsigned int timeout) | |
| { | |
| int ret; | |
| ret = ubus_invoke(stk_ubus_ctx, id, method, b? b->head : NULL , cb, priv, | |
| timeout); | |
| if (ret) { | |
| LOG_OUT("ubus_invoke failed [id=%d, method=%s, err=%s]\n", id, | |
| method, ubus_strerror(ret)); | |
| return ret; | |
| } | |
| return ret; | |
| } | |
| static void bip_chl_register_cb(struct ubus_request *req, int type, struct blob_attr *msg) | |
| { | |
| (void)type; | |
| int ret; | |
| struct blob_attr *tb_table[_CHL_REG_TABLE_MAX]; | |
| struct blob_attr *tb[_CHL_REG_RESP_MAX]; | |
| char *method = ((struct chl_bip_reg_response *)(req->priv))->method; | |
| ret = blobmsg_parse(chl_table_pol, ARRAY_SIZE(chl_table_pol), tb_table, | |
| blob_data(msg), blob_len(msg)); | |
| if (ret || !tb_table[CHL_REG_TABLE]){ | |
| LOG_OUT("invalid call to %s, ret=%d\n",method,ret); | |
| LOG_OUT("unable to parse table\n"); | |
| } | |
| ret = blobmsg_parse(chl_reg_resp_pol, ARRAY_SIZE(chl_reg_resp_pol), tb, | |
| blobmsg_data(tb_table[CHL_REG_TABLE]), blobmsg_data_len(tb_table[CHL_REG_TABLE])); | |
| if (ret || !tb[CHL_REG_REQ_STATUS]) | |
| LOG_OUT("invalid call to %s, ret=%d\n",method,ret); | |
| if (tb[CHL_REG_REQ_STATUS]) | |
| ((struct chl_bip_reg_response *)(req->priv))->req_status = blobmsg_get_u32(tb[CHL_REG_REQ_STATUS]); | |
| if (tb[CHL_REG_PDP_ID]) | |
| ((struct chl_bip_reg_response *)(req->priv))->id = blobmsg_get_u32(tb[CHL_REG_PDP_ID]); | |
| } | |
| /*register pdp info in chl, return chl pdp id*/ | |
| int bip_register_pdp(char *apn, int cid) | |
| { | |
| int ret; | |
| char buf[20]; | |
| struct chl_bip_reg_response resp; | |
| enum chl_reg_req_status req_status; | |
| LOG_OUT("bip_register_pdp\n"); | |
| strcpy(resp.method,"register"); | |
| sprintf (buf, "chl_bip_pdp%d", cid); | |
| ret = blob_buf_init(&b_stk_buf, 0); | |
| if (ret) { | |
| LOG_OUT("blob_buf_init failed: %d\n", ret); | |
| return ret; | |
| } | |
| blobmsg_add_string(&b_stk_buf, CHL_REG_NAME_STR, buf); | |
| blobmsg_add_string(&b_stk_buf, CHL_REG_APN_STR, apn); | |
| blobmsg_add_u32(&b_stk_buf, CHL_REG_IP_TYPE_STR, IPV4); | |
| ret = bip_ubus_invoke(&b_stk_buf, bip_chl_id, resp.method, bip_chl_register_cb, &resp, CHL_REQ_TIMEOUT); | |
| if (ret){ | |
| LOG_OUT("invoke %s failed: %s\n",resp.method, ubus_strerror(ret)); | |
| return -1; | |
| } | |
| req_status = resp.req_status; | |
| switch (req_status) { | |
| case CHL_REG_OK: | |
| LOG_OUT("chl %s response: id=%d req=%s\n",resp.method, resp.id,reg_req_status_to_str(req_status) ); | |
| return resp.id; | |
| default: | |
| LOG_OUT("chl %s response: id=%d req=%s\n",resp.method, resp.id,reg_req_status_to_str(req_status) ); | |
| return -1; | |
| } | |
| } | |
| static void bip_chl_open_cb(struct ubus_request *req, int type, struct blob_attr *msg) | |
| { | |
| (void)type; | |
| int ret; | |
| struct blob_attr *tb_table[_CHL_REG_TABLE_MAX]; | |
| struct blob_attr *tb[_CHL_OPEN_RESP_MAX]; | |
| ret = blobmsg_parse(chl_table_pol, ARRAY_SIZE(chl_table_pol), tb_table, | |
| blob_data(msg), blob_len(msg)); | |
| if (ret || !tb_table[CHL_REG_TABLE]){ | |
| LOG_OUT("invalid call to open, ret=%d\n",ret); | |
| LOG_OUT("unable to parse table\n"); | |
| } | |
| ret = blobmsg_parse(chl_open_resp_pol, ARRAY_SIZE(chl_open_resp_pol), tb, | |
| blobmsg_data(tb_table[CHL_REG_TABLE]), blobmsg_data_len(tb_table[CHL_REG_TABLE])); | |
| if (ret || !tb[CHL_OPEN_REQ_STATUS]) | |
| LOG_OUT("invalid call to open, ret=%d\n",ret); | |
| if (tb[CHL_OPEN_REQ_STATUS]) | |
| ((struct chl_bip_open_response *)(req->priv))->req_status = blobmsg_get_u32(tb[CHL_OPEN_REQ_STATUS]); | |
| if (tb[CHL_OPEN_NW_STATUS]) | |
| ((struct chl_bip_open_response *)(req->priv))->nw_status = blobmsg_get_u32(tb[CHL_OPEN_NW_STATUS]); | |
| if (tb[CHL_OPEN_RIL_STATUS]) | |
| ((struct chl_bip_open_response *)(req->priv))->ril_status = blobmsg_get_u32(tb[CHL_OPEN_RIL_STATUS]); | |
| } | |
| /*open pdp by id in chl, return network status*/ | |
| int bip_open_pdp(int pdpid) | |
| { | |
| int ret; | |
| struct chl_bip_open_response resp; | |
| enum chl_req_status req_status; | |
| LOG_OUT("send open pdp request to CHL\n"); | |
| ret = blob_buf_init(&b_stk_buf, 0); | |
| if (ret) { | |
| LOG_OUT("blob_buf_init failed: %d\n", ret); | |
| return ret; | |
| } | |
| blobmsg_add_u32(&b_stk_buf, CHL_ID_STR, pdpid); | |
| ret = bip_ubus_invoke(&b_stk_buf, bip_chl_id, "open", bip_chl_open_cb, &resp, CHL_REQ_TIMEOUT); | |
| if (ret){ | |
| LOG_OUT("invoke open failed: %s\n", ubus_strerror(ret)); | |
| return -1; | |
| } | |
| req_status = resp.req_status; | |
| switch (req_status) { | |
| case CHL_OK: | |
| LOG_OUT("chl open response: req=%s, nw_status=%s, ril_status=%d\n" | |
| , req_status_to_str(req_status), nw_status_to_str(resp.nw_status), resp.ril_status); | |
| return resp.nw_status; | |
| default: | |
| LOG_OUT("chl open response: req=%s, nw_status=%s, ril_status=%d\n" | |
| , req_status_to_str(req_status), nw_status_to_str(resp.nw_status), resp.ril_status); | |
| return -1; | |
| } | |
| } | |
| static void bip_chl_close_cb(struct ubus_request *req, int type, struct blob_attr *msg) | |
| { | |
| (void)type; | |
| int ret; | |
| struct blob_attr *tb_table[_CHL_REG_TABLE_MAX]; | |
| struct blob_attr *tb[_CHL_UNREG_RESP_MAX]; | |
| ret = blobmsg_parse(chl_table_pol, ARRAY_SIZE(chl_table_pol), tb_table, | |
| blob_data(msg), blob_len(msg)); | |
| if (ret || !tb_table[CHL_REG_TABLE]){ | |
| LOG_OUT("invalid call to close, ret=%d\n",ret); | |
| LOG_OUT("unable to parse table\n"); | |
| } | |
| ret = blobmsg_parse(chl_unregister_resp_pol, ARRAY_SIZE(chl_unregister_resp_pol), tb, | |
| blobmsg_data(tb_table[CHL_REG_TABLE]), blobmsg_data_len(tb_table[CHL_REG_TABLE])); | |
| if (ret || !tb[CHL_UNREG_REQ_STATUS] || !tb[CHL_UNREG_NW_STATUS]) | |
| LOG_OUT("invalid call to close, ret=%d\n",ret); | |
| if (tb[CHL_UNREG_REQ_STATUS]) | |
| ((struct chl_bip_response *)(req->priv))->req_status = blobmsg_get_u32(tb[CHL_UNREG_REQ_STATUS]); | |
| if (tb[CHL_UNREG_NW_STATUS]) | |
| ((struct chl_bip_response *)(req->priv))->nw_status = blobmsg_get_u32(tb[CHL_UNREG_NW_STATUS]); | |
| } | |
| int bip_close_pdp(int pdpid) | |
| { | |
| int ret; | |
| struct chl_bip_response resp; | |
| enum chl_req_status req_status; | |
| LOG_OUT("send close pdp request to CHL\n"); | |
| ret = blob_buf_init(&b_stk_buf, 0); | |
| if (ret) { | |
| LOG_OUT("blob_buf_init failed: %d\n", ret); | |
| return ret; | |
| } | |
| blobmsg_add_u32(&b_stk_buf, CHL_ID_STR, pdpid); | |
| ret = bip_ubus_invoke(&b_stk_buf, bip_chl_id, "close", bip_chl_close_cb, &resp, CHL_REQ_TIMEOUT); | |
| if (ret){ | |
| LOG_OUT("invoke close failed: %s\n", ubus_strerror(ret)); | |
| return 1; | |
| } | |
| req_status = resp.req_status; | |
| switch (req_status) { | |
| case CHL_OK: | |
| LOG_OUT("chl close response: req=%s, nw_status=%s\n" | |
| , req_status_to_str(req_status), nw_status_to_str(resp.nw_status) ); | |
| return 0; | |
| default: | |
| LOG_OUT("chl close response: req=%s, nw_status=%s\n" | |
| , req_status_to_str(req_status), nw_status_to_str(resp.nw_status) ); | |
| return 1; | |
| } | |
| } | |
| static void bip_chl_unregister_cb(struct ubus_request *req, int type, struct blob_attr *msg) | |
| { | |
| (void)type; | |
| int ret; | |
| struct blob_attr *tb_table[_CHL_REG_TABLE_MAX]; | |
| struct blob_attr *tb[_CHL_UNREG_RESP_MAX]; | |
| ret = blobmsg_parse(chl_table_pol, ARRAY_SIZE(chl_table_pol), tb_table, | |
| blob_data(msg), blob_len(msg)); | |
| if (ret || !tb_table[CHL_REG_TABLE]){ | |
| LOG_OUT("invalid call to unregister, ret=%d\n",ret); | |
| LOG_OUT("unable to parse table\n"); | |
| } | |
| ret = blobmsg_parse(chl_unregister_resp_pol, ARRAY_SIZE(chl_unregister_resp_pol), tb, | |
| blobmsg_data(tb_table[CHL_REG_TABLE]), blobmsg_data_len(tb_table[CHL_REG_TABLE])); | |
| if (ret || !tb[CHL_UNREG_REQ_STATUS] || !tb[CHL_UNREG_NW_STATUS]) | |
| LOG_OUT("invalid call to unregister, ret=%d\n",ret); | |
| if (tb[CHL_UNREG_REQ_STATUS]) | |
| ((struct chl_bip_response *)(req->priv))->req_status = blobmsg_get_u32(tb[CHL_UNREG_REQ_STATUS]); | |
| if (tb[CHL_UNREG_NW_STATUS]) | |
| ((struct chl_bip_response *)(req->priv))->nw_status = blobmsg_get_u32(tb[CHL_UNREG_NW_STATUS]); | |
| } | |
| int bip_unregister_pdp(int pdpid) | |
| { | |
| int ret; | |
| struct chl_bip_response resp; | |
| enum chl_req_status req_status; | |
| LOG_OUT("send unregister pdp request to CHL\n"); | |
| ret = blob_buf_init(&b_stk_buf, 0); | |
| if (ret) { | |
| LOG_OUT("blob_buf_init failed: %d\n", ret); | |
| return ret; | |
| } | |
| blobmsg_add_u32(&b_stk_buf, CHL_ID_STR, pdpid); | |
| ret = bip_ubus_invoke(&b_stk_buf, bip_chl_id, "unregister", bip_chl_unregister_cb, &resp, CHL_REQ_TIMEOUT); | |
| if (ret){ | |
| LOG_OUT("invoke unregister failed: %s\n", ubus_strerror(ret)); | |
| return 1; | |
| } | |
| req_status = resp.req_status; | |
| switch (req_status) { | |
| case CHL_OK: | |
| LOG_OUT("chl unregister response: req=%s, nw_status=%s\n" | |
| , req_status_to_str(req_status), nw_status_to_str(resp.nw_status) ); | |
| return 0; | |
| default: | |
| LOG_OUT("chl unregister response: req=%s, nw_status=%s\n" | |
| , req_status_to_str(req_status), nw_status_to_str(resp.nw_status) ); | |
| return 1; | |
| } | |
| } | |
| static void bip_chl_route_cb(struct ubus_request *req, int type, struct blob_attr *msg) | |
| { | |
| (void)type; | |
| int ret; | |
| struct blob_attr *tb_table[_CHL_REG_TABLE_MAX]; | |
| struct blob_attr *tb[_CHL_UNREG_RESP_MAX]; | |
| char method[10] = {0}; | |
| if (((struct chl_bip_route_response *)(req->priv))->add) | |
| strcpy(method,"set_route"); | |
| else | |
| strcpy(method,"del_route"); | |
| ret = blobmsg_parse(chl_table_pol, ARRAY_SIZE(chl_table_pol), tb_table, | |
| blob_data(msg), blob_len(msg)); | |
| if (ret || !tb_table[CHL_REG_TABLE]){ | |
| LOG_OUT("invalid call to %s, ret=%d\n", method,ret); | |
| LOG_OUT("unable to parse table\n"); | |
| } | |
| ret = blobmsg_parse(chl_route_pol, ARRAY_SIZE(chl_route_pol), tb, | |
| blobmsg_data(tb_table[CHL_REG_TABLE]), blobmsg_data_len(tb_table[CHL_REG_TABLE])); | |
| if (ret || !tb[CHL_UNREG_REQ_STATUS] ) | |
| LOG_OUT("invalid call to %s, ret=%d\n", method,ret); | |
| if (tb[CHL_UNREG_REQ_STATUS]) | |
| ((struct chl_bip_route_response *)(req->priv))->req_status = blobmsg_get_u32(tb[CHL_UNREG_REQ_STATUS]); | |
| } | |
| int bip_route_op( char *route , int pdp_id, int add) | |
| { | |
| int ret; | |
| struct chl_bip_route_response resp; | |
| enum chl_req_status req_status; | |
| char method[10] = {0}; | |
| if (add) | |
| strcpy(method,"set_route"); | |
| else | |
| strcpy(method,"del_route"); | |
| resp.add = add; | |
| ret = blob_buf_init(&b_stk_buf, 0); | |
| if (ret) { | |
| LOG_OUT("blob_buf_init failed: %d\n", ret); | |
| return ret; | |
| } | |
| blobmsg_add_u32(&b_stk_buf, CHL_ID_STR, pdp_id); | |
| blobmsg_add_string(&b_stk_buf, CHL_RT_HOST_IP_STR, route); | |
| ret = bip_ubus_invoke(&b_stk_buf, bip_chl_id, method, bip_chl_route_cb, &resp, CHL_REQ_TIMEOUT); | |
| if (ret){ | |
| LOG_OUT("invoke %s failed: %s\n",method, ubus_strerror(ret)); | |
| return 1; | |
| } | |
| req_status = resp.req_status; | |
| switch (req_status) { | |
| case CHL_OK: | |
| LOG_OUT("chl %s response: req=%s\n" | |
| , method, req_status_to_str(req_status)); | |
| return 0; | |
| default: | |
| LOG_OUT("chl %s response: req=%s\n" | |
| , method, req_status_to_str(req_status)); | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| static int bip_chl_is_ready(struct ubus_context *ctx) | |
| { | |
| if (!ubus_lookup_id(ctx, "chl", &bip_chl_id)) | |
| return 1; | |
| return 0; | |
| } | |
| static int bip_lookup_chl(struct ubus_context *ctx) | |
| { | |
| int retries = 0; | |
| do { | |
| if (bip_chl_is_ready(ctx)) | |
| goto ready; | |
| sleep(1); | |
| } while (retries++ < 20); | |
| LOG_OUT("Failed to look up CHL object\n"); | |
| return 1; | |
| ready: | |
| return 0; | |
| } | |
| #endif | |
| /*bip ubus functions end*/ | |
| static void stk_service_request_cb(struct ubus_request *req, int type, struct blob_attr *msg) | |
| { | |
| unsigned int requestid = 0; | |
| unsigned int rilerrno = 0; | |
| void *response_data = NULL; | |
| int response_len = 0; | |
| int simid = isSim2Master()?1:0; | |
| UNUSEDPARAM(req); | |
| UNUSEDPARAM(type); | |
| if (rilutil_parseResponse(msg, &requestid, &rilerrno, &response_data, &response_len)) { | |
| LOG_OUT_E("%s, parse failed\n", __FUNCTION__); | |
| return; | |
| } | |
| LOG_OUT_D("%s,requestid:%d", __FUNCTION__, requestid); | |
| switch( requestid) | |
| { | |
| case RIL_REQUEST_STK_SET_PROFILE: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| LOG_OUT_D("Profile set OK\n"); | |
| } | |
| break; | |
| case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| LOG_OUT_D("Terminal Response send OK\n"); | |
| } | |
| break; | |
| case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| LOG_OUT_D("Call Set Up answer OK\n"); | |
| } | |
| break; | |
| case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| LOG_OUT_D("STK Service Request OK\n"); | |
| } | |
| break; | |
| case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| LOG_OUT_D("STK Envelop send OK\n"); | |
| } | |
| break; | |
| case RIL_REQUEST_GET_SIM_STATUS: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| RIL_CardStatus_v6 *p = (RIL_CardStatus_v6 *) response_data; | |
| bip_handle_cpin(p->applications[0].app_state == RIL_APPSTATE_READY ? 1 : 0, simid); | |
| } | |
| break; | |
| case RIL_REQUEST_SET_PROACTIVECMD: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| LOG_OUT_D("STK set proactive cmd send OK\n"); | |
| } | |
| break; | |
| case RIL_REQUEST_GET_CID_STATE: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| int cidcount = response_len; | |
| LOG_OUT("get cid state count:%d\n", cidcount); | |
| HandleCGACTGetCnf(cidcount, response_data); | |
| } | |
| break; | |
| case RIL_REQUEST_GET_PDPIPAPN: | |
| { | |
| if(rilerrno) | |
| goto done; | |
| HandleQueryPdpIPApn(*(int *)req->priv, response_data); | |
| } | |
| break; | |
| case RIL_REQUEST_SEND_SMS: | |
| { | |
| if(rilerrno) | |
| { | |
| LOG_OUT_D("ril return err %d, requestid:%d", rilerrno, requestid); | |
| if (stkmsg[simid] == 1) | |
| { | |
| LOG_OUT_D("stk_handle_ril_ind send_sms tr"); | |
| //send tr or send tr in at cmd server | |
| char tempBuf[100] = {0}; | |
| sprintf(tempBuf, "8103%02X%02X%02X820282818301%02X" , | |
| stkmsg_cmdnumber[simid], | |
| 0x13, | |
| stkmsg_cmdqual[simid], | |
| 0x21); | |
| send_terminal_response_async(tempBuf, simid); | |
| if(newpdu[simid]) | |
| { | |
| free(newpdu[simid]); | |
| newpdu[simid] = NULL; | |
| } | |
| } | |
| stkmsg[simid] = 0; | |
| goto done; | |
| } | |
| LOG_OUT_D("STK send sms OK\n"); | |
| break; | |
| } | |
| case RIL_REQUEST_SEND_ATCMD: | |
| { | |
| BIPRequest_S *bipreq = (BIPRequest_S *)req->priv; | |
| if (bipreq) | |
| bipreq->errcode = rilerrno; | |
| if(rilerrno) | |
| goto done; | |
| if (!bipreq) | |
| goto done; | |
| if (bipreq->cmdid == CGDCONTSET || bipreq->cmdid == CGACTSET || bipreq->cmdid == CGEQOSSET) | |
| { | |
| char *pstr = (char *)response_data; | |
| if (strstr(pstr, "OK")) | |
| bipreq->errcode = 0; | |
| else | |
| bipreq->errcode = -1; | |
| } | |
| else if (bipreq->cmdid == CGDATASET) | |
| { | |
| char *pstr = (char *)response_data; | |
| if (strstr(pstr, "CONNECT")) | |
| bipreq->errcode = 0; | |
| else | |
| bipreq->errcode = -1; | |
| } | |
| else if (bipreq->cmdid == CGCONTRDP) | |
| { | |
| bipreq->data = malloc(response_len+1); | |
| bipreq->dataLen = response_len+1; | |
| strncpy(bipreq->data, response_data, bipreq->dataLen); | |
| bipreq->errcode = 0; | |
| } | |
| } | |
| break; | |
| case RIL_REQUEST_DATA_CALL_LIST: | |
| { | |
| BIPReq_CGDGETCID_S *bipreq = (BIPReq_CGDGETCID_S *)req->priv; | |
| if (bipreq) | |
| bipreq->errcode = rilerrno; | |
| if(rilerrno) | |
| goto done; | |
| if (!bipreq) | |
| goto done; | |
| if (bipreq->cmdid == CGDCONTGET && bipreq->data) | |
| { | |
| Ubus_Data_Call_Response *datalist = (Ubus_Data_Call_Response *)response_data; | |
| int num = response_len/sizeof(Ubus_Data_Call_Response); | |
| int i = 0; | |
| for (i = 0; i < num; i++) | |
| { | |
| if (!strncasecmp(datalist[i].apn, bipreq->data, bipreq->dataLen)) | |
| { | |
| bipreq->cid = datalist[i].cid; | |
| LOG_OUT("Got cid %d with same apn %s", bipreq->cid, datalist[i].apn); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| break; | |
| default: | |
| LOG_OUT_D("The response not for the request\n"); | |
| break; | |
| } | |
| done: | |
| if(rilerrno) { | |
| LOG_OUT_E("%s return err %d, requestid:%d", __FUNCTION__, rilerrno, requestid); | |
| } | |
| if (response_data){ | |
| rilutil_freeResponseData(requestid, response_data, response_len); | |
| } | |
| } | |
| static int stk_unsol_cb(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) | |
| { | |
| unsigned int requestid = 0; | |
| unsigned int rilerrno = 0; | |
| void *response = NULL; | |
| int responselen = 0; | |
| int ret = 0; | |
| int simid = isSim2Master()?1:0; | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(req); | |
| UNUSEDPARAM(method); | |
| ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &response, &responselen); | |
| if(ret) | |
| return -1; | |
| if(rilerrno) | |
| { | |
| LOG_OUT_E("unsolicited id %d,error code %d\n", requestid,rilerrno); | |
| goto done; | |
| } | |
| switch(requestid) | |
| { | |
| case RIL_UNSOL_RADIO_POWER: | |
| { | |
| int status = *(int*)response; | |
| if (status == 0) | |
| { | |
| //cfun != 1 | |
| LOG_OUT("radiopower 0\n"); | |
| STK_CleanupAllBIPChannel(simid); | |
| } | |
| } | |
| break; | |
| case RIL_UNSOL_RESPONSE_SMS_SENT: | |
| if (stkmsg[simid] == 1) | |
| { | |
| LOG_OUT("stk_handle_ril_ind send_sms tr"); | |
| //send tr | |
| char tempBuf[100] = {0}; | |
| sprintf(tempBuf, "8103%02X%02X%02X820282818301%02X" , | |
| stkmsg_cmdnumber[simid], | |
| 0x13, | |
| stkmsg_cmdqual[simid], | |
| 0); | |
| send_terminal_response_async(tempBuf, simid); | |
| } | |
| stkmsg[simid] = 0; | |
| break; | |
| case RIL_UNSOL_RESPONSE_SMS_PP_DOWNLOAD: | |
| { | |
| LOG_OUT("Enter RIL_UNSOL_RESPONSE_SMS_PP_DOWNLOAD!"); | |
| ret = stk_handle_sms_pp_download(ctx, response, simid); | |
| if(ret < 0) | |
| { | |
| LOG_OUT("error: not SMS_PP_Download command\n"); | |
| } | |
| break; | |
| } | |
| case RIL_UNSOL_STK_SESSION_END: | |
| bip_process_sessionend(simid); | |
| LOG_OUT_D("STK session end\n"); | |
| break; | |
| case RIL_UNSOL_STK_PROACTIVE_COMMAND : | |
| //LOG_OUT("STK proactive received, len %d\n", responselen); | |
| ret = stk_handle_proactive_data(ctx, response, simid); | |
| if(ret >= 0) { | |
| blobmsg_buf_init(&stk_notify_blob); | |
| blobmsg_add_string(&stk_notify_blob,"proactive",response); | |
| LOG_OUT_D("%s L%d*******\n",__FUNCTION__,__LINE__); | |
| ubus_notify(ctx, &stk_notify_obj[0], stk_notify_obj[0].name, stk_notify_blob.head, -1); | |
| blob_buf_free(&stk_notify_blob); | |
| } else | |
| LOG_OUT("error :not proactive command\n"); | |
| break; | |
| case RIL_UNSOL_STK_EVENT_NOTIFY : | |
| ret = stk_handle_proactive_data(ctx, response, simid); | |
| if(ret >= 0) { | |
| blobmsg_buf_init(&stk_notify_blob); | |
| blobmsg_add_string(&stk_notify_blob,"event_notify",response); | |
| LOG_OUT_D("%s L%d*******\n",__FUNCTION__,__LINE__); | |
| ubus_notify(ctx, &stk_notify_obj[1], stk_notify_obj[1].name, stk_notify_blob.head, -1); | |
| blob_buf_free(&stk_notify_blob); | |
| } | |
| else | |
| LOG_OUT("error :not event notify command command\n"); | |
| break; | |
| case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: | |
| { | |
| #if 0 | |
| //bip query cpin | |
| query_sim_status(simid); | |
| #endif | |
| } | |
| break; | |
| case RIL_UNSOL_PDP_DEACTIVE_CID: | |
| { | |
| int deactivecid = *(int*)response; | |
| LOG_OUT("deactive cid:%d", deactivecid); | |
| handleCGEV(simid, deactivecid); | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| done: | |
| if(response){ | |
| if (requestid == RIL_UNSOL_STK_PROACTIVE_COMMAND) | |
| { | |
| if (proactiveSave) | |
| { | |
| free(proactiveSave); | |
| proactiveSave = NULL; | |
| } | |
| proactiveSave = malloc(responselen + 1); | |
| if (!proactiveSave) { | |
| LOG_OUT("No enough memory size %d\n", responselen); | |
| return -1; | |
| } | |
| memset(proactiveSave, 0, responselen + 1); | |
| memcpy(proactiveSave, response, responselen); | |
| } | |
| rilutil_freeResponseData(requestid, response, responselen); | |
| } | |
| return ret; | |
| } | |
| /*================================================ | |
| method: get_stk_proactive | |
| request: | |
| response: | |
| </response> | |
| OK/ERROR | |
| <stk proactive command> | |
| ================================================*/ | |
| static int get_stk_proactive(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, | |
| struct blob_attr *msg) | |
| { | |
| int ret_val; | |
| void *tb = NULL; | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(method); | |
| UNUSEDPARAM(msg); | |
| ret_val = blob_buf_init(&b_stk_resp_buf, 0); | |
| tb = blobmsg_open_table(&b_stk_resp_buf, "response"); | |
| if( (ret_val == UBUS_STATUS_OK)&&(proactiveSave != NULL) ) { | |
| LOG_OUT("proactive data: %s", proactiveSave); | |
| blobmsg_add_string(&b_stk_resp_buf, "proactive", proactiveSave); | |
| blobmsg_add_string(&b_stk_resp_buf,"setting_response","OK"); | |
| free(proactiveSave); | |
| proactiveSave = NULL; | |
| } | |
| else{ | |
| if(proactiveSave == NULL) | |
| ret_val = UBUS_STATUS_NO_DATA; | |
| blobmsg_add_string(&b_stk_resp_buf,"setting_response","ERROR"); | |
| } | |
| blobmsg_close_table(&b_stk_resp_buf, tb); | |
| ubus_send_reply(ctx, req, b_stk_resp_buf.head); | |
| blob_buf_free(&b_stk_resp_buf); | |
| return ret_val; | |
| } | |
| /*================================================ | |
| method: get_stk_proactive_setup_menu | |
| request: | |
| response: | |
| </response> | |
| OK/ERROR | |
| <stk proactive command> | |
| ================================================*/ | |
| static int get_stk_proactive_setup_menu(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, | |
| struct blob_attr *msg) | |
| { | |
| int ret_val; | |
| void *tb = NULL; | |
| char *setup_menu = stk_get_proactive_setup_menu(); | |
| struct blob_buf *b = &b_stk_resp_buf; | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(method); | |
| UNUSEDPARAM(msg); | |
| ret_val = blob_buf_init(b, 0); | |
| LOG_OUT_D("after STK buffer init"); | |
| tb = blobmsg_open_table(b, "response"); | |
| if( (ret_val == UBUS_STATUS_OK)&&(setup_menu != NULL) ) { | |
| blobmsg_add_string(b, "proactive", setup_menu); | |
| blobmsg_add_string(b, "setting_response", "OK"); | |
| } | |
| else{ | |
| if(setup_menu == NULL) | |
| ret_val = UBUS_STATUS_NO_DATA; | |
| blobmsg_add_string(b, "setting_response", "ERROR"); | |
| } | |
| blobmsg_close_table(b, tb); | |
| ubus_send_reply(ctx, req, b->head); | |
| blob_buf_free(b); | |
| return ret_val; | |
| } | |
| /*================================================ | |
| method: enable_stk_service | |
| request: | |
| response: | |
| OK/ERROR | |
| ================================================*/ | |
| static int enable_stk_service(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, | |
| struct blob_attr *msg) | |
| { | |
| int ret_val = 0; | |
| void *tb = NULL; | |
| unsigned int id; | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(method); | |
| blob_buf_init(&b_stk_buf, 0); | |
| blob_buf_init(&b_stk_resp_buf, 0); | |
| //LOG_OUT("after STK buffer init"); | |
| if(ubus_lookup_id(stk_ubus_ctx, "ril", &id)) | |
| { | |
| LOG_OUT("lookup ril object failed\n"); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| //LOG_OUT("after ubus_lookup_id %x\n",id); | |
| rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, NULL, 0); | |
| ret_val = ubus_invoke(stk_ubus_ctx, id, "ril_request", b_stk_buf.head, stk_service_request_cb,0,0); | |
| EXIT: | |
| tb = blobmsg_open_table(&b_stk_resp_buf, "response"); | |
| if(ret_val == UBUS_STATUS_OK) | |
| { | |
| blobmsg_add_string(&b_stk_resp_buf,"setting_response","OK"); | |
| } | |
| else | |
| { | |
| blobmsg_add_string(&b_stk_resp_buf,"setting_response","ERROR"); | |
| } | |
| blobmsg_close_table(&b_stk_resp_buf, tb); | |
| ubus_send_reply(ctx, req, b_stk_resp_buf.head); | |
| blob_buf_free(&b_stk_buf); | |
| blob_buf_free(&b_stk_resp_buf); | |
| LOG_OUT_D("leave"); | |
| return ret_val ; | |
| } | |
| static int set_stk_profile(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, | |
| struct blob_attr *msg) | |
| { | |
| struct blob_attr *tb_set_profile[ARRAY_SIZE(set_stk_profile_pol)]; | |
| int ret_val = 0; | |
| char *profile = NULL; | |
| void *tb = NULL; | |
| int size =0 ; | |
| int i =0; | |
| rilutilstrings data = {0}; | |
| LOG_OUT_D("enter"); | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(method); | |
| if (blobmsg_parse(set_stk_profile_pol, ARRAY_SIZE(set_stk_profile_pol), tb_set_profile, blob_data(msg), blob_len(msg)) != 0) { | |
| LOG_OUT_E("Parse failed\n"); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| if(tb_set_profile[STK_PROFILE]) | |
| { | |
| /*profile*/ | |
| profile = blobmsg_get_string(tb_set_profile[STK_PROFILE]); | |
| LOG_OUT("profile %s",profile ); | |
| data.str = (char **)malloc( sizeof(char *)); | |
| if (!data.str) { | |
| LOG_OUT_E("malloc failed"); | |
| ret_val = UBUS_STATUS_UNKNOWN_ERROR; | |
| goto EXIT; | |
| } | |
| data.str[data.num++] = strdup(profile); | |
| for(i=0; i < data.num; i++) | |
| { | |
| size += strlen(data.str[i])+1; | |
| } | |
| ret_val = rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_STK_SET_PROFILE, profile, size); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb,0,0); | |
| for(i=0; i<data.num;i++) | |
| { | |
| if(data.str[i]) | |
| { | |
| free(data.str[i]); | |
| data.str[i] = NULL; | |
| } | |
| } | |
| } | |
| EXIT: | |
| blob_buf_init(&b_stk_buf,0); | |
| tb = blobmsg_open_table(&b_stk_buf, "response"); | |
| if(ret_val == 0) | |
| { | |
| blobmsg_add_string(&b_stk_buf,"setting_response","OK"); | |
| } | |
| else | |
| { | |
| blobmsg_add_string(&b_stk_buf,"setting_response","ERROR"); | |
| } | |
| blobmsg_close_table(&b_stk_buf, tb); | |
| ubus_send_reply(ctx, req, b_stk_buf.head); | |
| blob_buf_free(&b_stk_buf); | |
| LOG_OUT_D("leave"); | |
| return ret_val ; | |
| } | |
| static int send_stk_terminal_response(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, | |
| struct blob_attr *msg) | |
| { | |
| struct blob_attr *tb_send_terminal_resp[ARRAY_SIZE(send_terminal_response_pol)]; | |
| int ret_val = 0; | |
| char *command_details = NULL; | |
| char *command_res = NULL; | |
| char *command_add_res = NULL; | |
| char *stk_dcs = NULL; | |
| char *stk_string_resp = NULL; | |
| void *tb = NULL; | |
| int size = 0, len = 0, data_len = 0; | |
| unsigned int num_of_paramters; | |
| char data[MAX_BUF_LEN] = { 0 }; | |
| char device_identities[TLV_BUF_SIZE] = { 0 }; | |
| char resp_result[TLV_BUF_SIZE] = { 0 }; | |
| char item_identifier[TLV_BUF_SIZE] = { 0 }; | |
| unsigned char command_type; | |
| struct blob_buf *b = &b_stk_buf; | |
| LOG_OUT_D("enter"); | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(method); | |
| if (blobmsg_parse(send_terminal_response_pol, ARRAY_SIZE(send_terminal_response_pol), tb_send_terminal_resp, blob_data(msg), blob_len(msg)) != 0) { | |
| LOG_OUT("Parse failed\n"); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| if(tb_send_terminal_resp[STK_COMMAND_RESP_COMMAND_DETAILS] && tb_send_terminal_resp[STK_RESPONSE_RESULT]){ | |
| num_of_paramters = 2; //ovious | |
| memset(data, 0, MAX_BUF_LEN); | |
| /*command type*/ | |
| command_details = blobmsg_get_string(tb_send_terminal_resp[STK_COMMAND_RESP_COMMAND_DETAILS]); | |
| LOG_OUT("command_details %s", command_details); | |
| command_type = getValueFromHexStr(command_details, 3); | |
| LOG_OUT("command_type %x", command_type); | |
| data_len += snprintf(data + data_len, MAX_BUF_LEN - data_len, "%s", command_details); | |
| len = (strlen(DEVICE_IDENTITY_TAG) + strlen(DEVICE_UICC))/2; | |
| snprintf(device_identities, TLV_BUF_SIZE, "%s%02x%s%s", DEVICE_IDENTITY_TAG, len, DEVICE_TERMINAL, DEVICE_UICC); | |
| data_len += snprintf(data + data_len, MAX_BUF_LEN - data_len, "%s", device_identities); | |
| command_res = blobmsg_get_string(tb_send_terminal_resp[STK_RESPONSE_RESULT]); | |
| LOG_OUT("command_res %s", command_res); | |
| snprintf(resp_result, TLV_BUF_SIZE, "%s02%s00", RESULT_TAG, command_res); | |
| data_len += snprintf(data + data_len, MAX_BUF_LEN - data_len, "%s", resp_result); | |
| command_add_res = blobmsg_get_string(tb_send_terminal_resp[STK_RESPONSE_ADD_RESULT]); | |
| if (command_add_res != NULL) { | |
| num_of_paramters++; | |
| LOG_OUT("command_add_res %s", command_add_res); | |
| switch (command_type) { | |
| case SELECT_ITEM: | |
| snprintf(item_identifier, TLV_BUF_SIZE, "%s01%s", ITEM_IDENTIFIER_TAG, command_add_res); | |
| data_len += snprintf(data + data_len, MAX_BUF_LEN - data_len, "%s", item_identifier); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| stk_dcs = blobmsg_get_string(tb_send_terminal_resp[STK_DCS]); | |
| if(stk_dcs != NULL){ | |
| num_of_paramters++; | |
| LOG_OUT("stk_dcs %s", stk_dcs ); | |
| } | |
| stk_string_resp = blobmsg_get_string(tb_send_terminal_resp[STK_STRING_DATA]); | |
| if (stk_string_resp != NULL) { | |
| num_of_paramters++; | |
| LOG_OUT("stk_string_resp %s", stk_string_resp ); | |
| len = strlen(stk_string_resp)/2 + 1; | |
| memset(resp_result, 0, TLV_BUF_SIZE); | |
| if (!stk_dcs) { | |
| /*UCS2*/ | |
| snprintf(resp_result, TLV_BUF_SIZE, "0D%02x08%s", len, stk_string_resp); | |
| } else { | |
| snprintf(resp_result, TLV_BUF_SIZE, "0D%02x%s%s", len, stk_dcs, stk_string_resp); | |
| } | |
| data_len += snprintf(data + data_len, MAX_BUF_LEN - data_len, "%s", resp_result); | |
| } else { | |
| if (!strcmp(command_res, "00") && command_type == GET_INPUT) { | |
| /*UCS2*/ | |
| snprintf(resp_result, TLV_BUF_SIZE, "0D0108"); | |
| data_len += snprintf(data + data_len, MAX_BUF_LEN - data_len, "%s", resp_result); | |
| } | |
| } | |
| size = strlen(data) + 1; | |
| rilutil_makeRequestBlob(b, RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, (void *)data, size); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b->head, stk_service_request_cb,0,0); | |
| } | |
| EXIT: | |
| blob_buf_init(b, 0); | |
| tb = blobmsg_open_table(b, "response"); | |
| if(ret_val == 0) | |
| { | |
| blobmsg_add_string(b,"setting_response","OK"); | |
| } | |
| else | |
| { | |
| blobmsg_add_string(b,"setting_response","ERROR"); | |
| } | |
| blobmsg_close_table(b, tb); | |
| ubus_send_reply(ctx, req, b->head); | |
| blob_buf_free(b); | |
| LOG_OUT("leave"); | |
| return ret_val ; | |
| } | |
| static int send_stk_setup_call_response(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, | |
| struct blob_attr *msg) | |
| { | |
| struct blob_attr *tb_send_call_setup[ARRAY_SIZE(send_call_setup_response_pol)]; | |
| int ret_val = 0; | |
| char *accept_reject = NULL; | |
| void *tb = NULL; | |
| int size =0 ; | |
| int i =0; | |
| rilutilstrings data = {0}; | |
| LOG_OUT_D("enter"); | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(method); | |
| if (blobmsg_parse(send_call_setup_response_pol, ARRAY_SIZE(send_call_setup_response_pol), tb_send_call_setup, blob_data(msg), blob_len(msg)) != 0) { | |
| LOG_OUT("Parse failed\n"); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| if(tb_send_call_setup[STK_ACCEPT_REJECT_CALL] ){ | |
| accept_reject = blobmsg_get_string(tb_send_call_setup[STK_ACCEPT_REJECT_CALL]); | |
| LOG_OUT("accept_reject %s", accept_reject); | |
| data.str = (char **)malloc( sizeof(char *)); | |
| if (!data.str) { | |
| LOG_OUT_E("malloc failed"); | |
| ret_val = UBUS_STATUS_UNKNOWN_ERROR; | |
| goto EXIT; | |
| } | |
| data.str[data.num++] = strdup(accept_reject); | |
| for(i=0; i < data.num; i++) | |
| { | |
| size += strlen(data.str[i])+1; | |
| } | |
| ret_val = rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM, (void *)&data, size); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb,0,0); | |
| for(i=0; i<data.num;i++) | |
| { | |
| if(data.str[i]) | |
| { | |
| free(data.str[i]); | |
| data.str[i] = NULL; | |
| } | |
| } | |
| } | |
| EXIT: | |
| blob_buf_init(&b_stk_buf,0); | |
| tb = blobmsg_open_table(&b_stk_buf, "response"); | |
| if(ret_val == 0) | |
| { | |
| blobmsg_add_string(&b_stk_buf,"setting_response","OK"); | |
| } | |
| else | |
| { | |
| blobmsg_add_string(&b_stk_buf,"setting_response","ERROR"); | |
| } | |
| blobmsg_close_table(&b_stk_buf, tb); | |
| ubus_send_reply(ctx, req, b_stk_buf.head); | |
| blob_buf_free(&b_stk_buf); | |
| LOG_OUT_D("leave"); | |
| return ret_val ; | |
| } | |
| static int send_stk_envelop_command(struct ubus_context *ctx, struct ubus_object *obj, | |
| struct ubus_request_data *req, const char *method, | |
| struct blob_attr *msg) | |
| { | |
| struct blob_attr *tb_send_envelop_command[ARRAY_SIZE(send_envelop_command_pol)]; | |
| int ret_val = 0; | |
| char *envelop_type = NULL; | |
| char *envelop_data1 = NULL; | |
| char *envelop_data2 = NULL; | |
| void *tb = NULL; | |
| int size = 0, len = 0; | |
| unsigned int num_of_paramters; | |
| char data[MAX_BUF_LEN] = { 0 }; | |
| char device_identities[TLV_BUF_SIZE] = { 0 }; | |
| char item_identifier[TLV_BUF_SIZE] = { 0 }; | |
| LOG_OUT_D("enter"); | |
| UNUSEDPARAM(obj); | |
| UNUSEDPARAM(method); | |
| if (blobmsg_parse(send_envelop_command_pol, ARRAY_SIZE(send_envelop_command_pol), tb_send_envelop_command, blob_data(msg), blob_len(msg)) != 0) { | |
| LOG_OUT("Parse failed\n"); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| if(tb_send_envelop_command[STK_ENVELOP_TYPE] && tb_send_envelop_command[STK_ENVELOP_DATA1]){ | |
| num_of_paramters = 2; | |
| memset(data, 0, MAX_BUF_LEN); | |
| envelop_type = blobmsg_get_string(tb_send_envelop_command[STK_ENVELOP_TYPE]); | |
| LOG_OUT("envelop_type %s", envelop_type); | |
| envelop_data1 = blobmsg_get_string(tb_send_envelop_command[STK_ENVELOP_DATA1]); | |
| LOG_OUT("envelop_data1 %s", envelop_data1); | |
| envelop_data2 = blobmsg_get_string(tb_send_envelop_command[STK_ENVELOP_DATA2]); | |
| if (envelop_data2 != NULL) { | |
| num_of_paramters++; | |
| LOG_OUT("envelop_data2 %s", envelop_data2 ); | |
| } | |
| if (!strcmp(envelop_type, MENU_SELECTION_TAG)) { | |
| len = (strlen(DEVICE_KEYPAD) + strlen(DEVICE_UICC))/2; | |
| snprintf(device_identities, TLV_BUF_SIZE, "%s%02x%s%s", DEVICE_IDENTITY_TAG, len, DEVICE_KEYPAD, DEVICE_UICC); | |
| len = strlen(envelop_data1)/2; | |
| snprintf(item_identifier, TLV_BUF_SIZE, "%s%02x%s", ITEM_IDENTIFIER_TAG, len, envelop_data1); | |
| len = (strlen(device_identities) + strlen(item_identifier))/2; | |
| snprintf(data, MAX_BUF_LEN, "%s%02x%s%s", envelop_type, len, device_identities, item_identifier); | |
| } | |
| size = strlen(data) + 1; | |
| LOG_OUT("envelop command data %s, size %d", data, size); | |
| ret_val = rilutil_makeRequestBlob(&b_stk_buf, RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, (void *)data, size); | |
| ubus_invoke(stk_ubus_ctx, rilid, "ril_request", b_stk_buf.head, stk_service_request_cb,0,0); | |
| } | |
| EXIT: | |
| blob_buf_init(&b_stk_buf,0); | |
| tb = blobmsg_open_table(&b_stk_buf, "response"); | |
| if(ret_val == 0) | |
| { | |
| blobmsg_add_string(&b_stk_buf,"setting_response","OK"); | |
| } | |
| else | |
| { | |
| blobmsg_add_string(&b_stk_buf,"setting_response","ERROR"); | |
| } | |
| blobmsg_close_table(&b_stk_buf, tb); | |
| ubus_send_reply(ctx, req, b_stk_buf.head); | |
| blob_buf_free(&b_stk_buf); | |
| LOG_OUT_D("leave"); | |
| return ret_val ; | |
| } | |
| static unsigned char getValueFromHexStr( char *data_str , unsigned long index ) | |
| { | |
| char str[3]; | |
| unsigned long x; | |
| str[0] = *(data_str+(index*2)); | |
| str[1] = *(data_str+(index*2+1)); | |
| str[2] = 0; | |
| sscanf(str,"%x",(unsigned int*)&x); | |
| return((unsigned char)x ); | |
| } | |
| static int stk_sms_send(char* smsc, char* pdu, int simid) | |
| { | |
| int ret = -1; | |
| rilutilstrings param; | |
| struct ubus_request *req = NULL; | |
| param.num = 2; | |
| char* strs[2]; | |
| strs[0] = smsc; | |
| strs[1] = pdu; | |
| param.str = strs; | |
| ret = rilutil_makeRequestBlob(&b_stk_sms, RIL_REQUEST_SEND_SMS, ¶m, sizeof(rilutilstrings)); | |
| req = malloc(sizeof(struct ubus_request)); | |
| memset(req, 0, sizeof(struct ubus_request)); | |
| if ((ret = ubus_invoke_async(stk_ubus_ctx, rilid, "ril_request", b_stk_sms.head, req)) != UBUS_STATUS_OK) { | |
| LOG_OUT("ubus_invoke_async send sms failed"); | |
| free(req); | |
| } else { | |
| req->data_cb = stk_service_request_cb; | |
| req->complete_cb = complete_stk_async_cb; | |
| ubus_complete_request_async(stk_ubus_ctx, req); | |
| LOG_OUT_D("send sms"); | |
| } | |
| return ret; | |
| } | |
| static int notify_stk_send_sms(struct ubus_context *ctx, char *pdu) | |
| { | |
| UNUSEDPARAM(ctx); | |
| blobmsg_buf_init(&stk_notify_blob); | |
| blobmsg_add_string(&stk_notify_blob,"pdu", pdu); | |
| LOG_OUT("notify stk send short message %s", pdu); | |
| int ret = ubus_notify(ctx, &stk_notify_obj[2], stk_notify_obj[2].name, stk_notify_blob.head, -1); | |
| LOG_OUT("notify_stk_send_sms %d", ret); | |
| blob_buf_free(&stk_notify_blob); | |
| return 0; | |
| } | |
| static void bip_libReadSmsAddress( UINT8 *pPdu, UINT8 *pIdx) | |
| { | |
| UINT8 *data, addrLen; | |
| /* Assertions */ | |
| if ( (pPdu == NULL) || (pIdx == NULL)) | |
| { | |
| return; | |
| } | |
| data = pPdu + *pIdx; | |
| /* Pick up the Address Length (number of BCD digits) */ | |
| addrLen = *data++; | |
| /* We're done -- update the PDU byte index */ | |
| *pIdx += (UINT8)( ((addrLen + 1) / 2) + 2 ); | |
| } | |
| static int bip_libReadSmsDcs( UINT8 *pPdu, UINT8 *pIdx) | |
| { | |
| UINT8 bDCS; | |
| BOOL tFlag = FALSE; | |
| int alphabet = 0; | |
| bDCS = pPdu[*pIdx]; | |
| switch (bDCS & 0xf0) | |
| { | |
| case 0x00: | |
| case 0x10: | |
| case 0x20: | |
| case 0x30: | |
| switch (bDCS & 0x0c) | |
| { | |
| case 0x00: | |
| alphabet = ATCI_MSG_CODING_DEFAULT; | |
| break; | |
| case 0x04: | |
| alphabet = ATCI_MSG_CODING_8BIT; | |
| break; | |
| case 0x08: | |
| alphabet = ATCI_MSG_CODING_UCS2; | |
| break; | |
| default: | |
| break; | |
| } | |
| break; | |
| case 0xd0: | |
| alphabet = ATCI_MSG_CODING_DEFAULT; | |
| tFlag = TRUE; | |
| // | |
| // Fall through | |
| // | |
| case 0xe0: | |
| if (!tFlag) | |
| { | |
| alphabet = ATCI_MSG_CODING_UCS2; | |
| } | |
| break; | |
| case 0xf0: | |
| if (bDCS & 0x04) | |
| { | |
| alphabet = ATCI_MSG_CODING_8BIT; | |
| } | |
| else | |
| { | |
| alphabet = ATCI_MSG_CODING_DEFAULT; | |
| } | |
| break; | |
| } | |
| *pIdx += 1; | |
| return alphabet; | |
| } | |
| static UINT16 EncodeGsm7BitData(UINT8 inPaddingBits, UINT8 *pInBuf, UINT16 inLen, UINT8 *pOutBuf) | |
| { | |
| UINT16 inIdx, outIdx; | |
| UINT8 bits; | |
| inIdx = 0; | |
| outIdx = 0; | |
| bits = 0; | |
| if (inPaddingBits) { | |
| bits = 7 - inPaddingBits; | |
| pOutBuf[outIdx] = pInBuf[inIdx] << (7 - bits); | |
| if ((++bits % 7) == 0) { | |
| bits = 0; | |
| inIdx++; | |
| } | |
| if (inIdx <= inLen) | |
| outIdx++; | |
| } | |
| while (inIdx < inLen) { | |
| pOutBuf[outIdx] = pInBuf[inIdx++] >> bits; | |
| if (inIdx == inLen) { | |
| ++outIdx; | |
| break; | |
| } | |
| pOutBuf[outIdx] |= pInBuf[inIdx] << (7 - bits); | |
| if ((++bits % 7) == 0) { | |
| bits = 0; | |
| inIdx++; | |
| } | |
| if (inIdx <= inLen) | |
| outIdx++; | |
| } | |
| return outIdx; | |
| } | |
| static int isDataAscii(unsigned char *data, int index, int len) | |
| { | |
| int i = 0; | |
| for (i = 0; i < len; i++) | |
| { | |
| if (data[index + i] & 0x80) | |
| return 0; | |
| } | |
| return 1; | |
| } | |
| static void checkdcs(char *opdu, int length, int packing, int simid) | |
| { | |
| UINT8 idx; | |
| int dcs = 0; | |
| int dcsindex = 0; | |
| int i=0,j=0; | |
| char *pstr; | |
| unsigned char *pdu; | |
| int number; | |
| unsigned char *ud7bit = NULL; | |
| int ud7bitlen = 0; | |
| newpdu[simid] = NULL; | |
| pdu = (unsigned char *)malloc(length+3); | |
| if (!pdu) { | |
| LOG_OUT( "malloc size %d failed", length+3); | |
| return; | |
| } | |
| memset(pdu, '\0', length); | |
| pstr = opdu; | |
| for(i = 0; i < length*2; i += 2,j++) | |
| { | |
| sscanf(pstr+i,"%02x", &number); | |
| pdu[j] = (unsigned char)number; | |
| } | |
| /* Decode destination address */ | |
| idx = 2; /* Address length should be in 3rd octet */ | |
| bip_libReadSmsAddress(pdu, &idx); | |
| //pid | |
| idx += 1; | |
| /* decode DCS */ | |
| dcsindex = idx; | |
| dcs = bip_libReadSmsDcs(pdu, &idx); | |
| /* Decode Validity Period */ | |
| if ((pdu[0] & ATCI_SMS_TP_VPF) == 0x10) | |
| idx++; | |
| else if ((pdu[0] & ATCI_SMS_TP_VPF) == 0x08 || (pdu[0] & ATCI_SMS_TP_VPF) == 0x18) | |
| idx+=7; | |
| //if include UDHI, don't process | |
| if ((pdu[0] & ATCI_SMS_TP_UDHI) == ATCI_SMS_TP_UDHI) | |
| { | |
| LOG_OUT("have UDHI"); | |
| goto end; | |
| } | |
| //only check 7bit & user data length | |
| if (dcs == ATCI_MSG_CODING_DEFAULT) | |
| { | |
| int udl = (unsigned char)pdu[idx]; | |
| if ((length-idx-1) == udl && isDataAscii(pdu, idx+1, length-idx-1)) //user data is 8bit actually | |
| { | |
| idx++; | |
| if (packing) | |
| { | |
| LOG_OUT("pack to 7bit\n"); | |
| //packing to 7bit | |
| ud7bit = (unsigned char *) malloc (length+1); | |
| ud7bitlen = EncodeGsm7BitData(0, pdu+idx, udl, ud7bit); | |
| } | |
| goto end; | |
| } | |
| else | |
| goto end; | |
| } | |
| else if (dcs == ATCI_MSG_CODING_8BIT) | |
| { | |
| int udl = (unsigned char)pdu[idx]; | |
| if (length-idx-1 != udl || udl > 160) | |
| { | |
| LOG_OUT("dcs or ud is wrong,udl:%d\n", udl); | |
| } | |
| if (udl > 140 && udl <= 160) | |
| { | |
| idx++; | |
| if (packing) | |
| { | |
| LOG_OUT("8bit pack to 7bit\n"); | |
| //packing to 7bit | |
| ud7bit = (unsigned char *) malloc (length+1); | |
| ud7bitlen = EncodeGsm7BitData(0, pdu+idx, udl, ud7bit); | |
| } | |
| goto end; | |
| } | |
| } | |
| else if (dcs == ATCI_MSG_CODING_UCS2) | |
| { | |
| int udl = pdu[idx]; | |
| if (length-idx-1 != udl || udl > 70) | |
| { | |
| LOG_OUT("dcs or ud isn't correct\n"); | |
| } | |
| } | |
| else | |
| { | |
| LOG_OUT("unknow dcs:%d\n", dcs); | |
| } | |
| end: | |
| if (ud7bit) | |
| { | |
| char *tmp; | |
| newpdu[simid] = (char *)malloc(length*2+3); | |
| memcpy(newpdu[simid], opdu, idx*2); | |
| tmp = newpdu[simid] + idx*2; | |
| for (i = 0, j = 0; i < ud7bitlen; i++,j+=2) | |
| { | |
| sprintf(tmp+j, "%02x", (unsigned char)ud7bit[i]); | |
| } | |
| if (dcs == ATCI_MSG_CODING_8BIT) | |
| newpdu[simid][dcsindex*2+1] &= ~(0x0C); | |
| free(ud7bit); | |
| } | |
| if (pdu) | |
| free(pdu); | |
| } | |
| static char *get_pdu_from_send_sms(char *data, char *smsc, int simid) | |
| { | |
| int length = 0, length_2bytes = 0, offset = 0; | |
| unsigned char proactive_tag = 0; | |
| unsigned char cmdqualifier = 0; | |
| length = getValueFromHexStr( data , PROACTIVE_LENGTH_OFFSET); | |
| if (length == 0x81) { | |
| length = getValueFromHexStr( data , PROACTIVE_LENGTH_OFFSET + 1); | |
| length_2bytes = 1; | |
| } | |
| /*command details*/ | |
| offset += (PROACTIVE_COMMAND_DETAILS_OFFSET + length_2bytes) * 2; | |
| proactive_tag = getValueFromHexStr(data, offset/2); | |
| if ((proactive_tag & CR_MASK) == COMMAND_DETAILS) | |
| { | |
| offset += 8; | |
| cmdqualifier = getValueFromHexStr(data, offset/2); | |
| offset += 2; | |
| } | |
| /*skip device identifier*/ | |
| offset += DEVICE_IDENTIFIER_BYTE_NUM * 2; | |
| proactive_tag = getValueFromHexStr(data, offset/2); | |
| offset += 2; | |
| if ((proactive_tag & CR_MASK) == ALPHA_ID) { | |
| length = getValueFromHexStr(data, offset/2); | |
| offset += 2*(length + 1); | |
| proactive_tag = getValueFromHexStr(data, offset/2); | |
| offset += 2; | |
| } | |
| if ((proactive_tag & CR_MASK) == ADDRESS_TAG) { | |
| length = getValueFromHexStr(data, offset/2); | |
| if(length != 0) | |
| memcpy(smsc, data+offset, (length+1)*2); | |
| offset += 2*(length + 1); | |
| proactive_tag = getValueFromHexStr(data, offset/2); | |
| offset += 2; | |
| } | |
| if ((proactive_tag & CR_MASK) == SMS_TPDU_TAG) { | |
| /*skip length*/ | |
| length = getValueFromHexStr(data, offset/2); | |
| if (length == 0x81) { | |
| length = getValueFromHexStr(data, offset/2+1); | |
| offset += 4; | |
| } | |
| else | |
| offset += 2; | |
| //check dcs & ud | |
| if (cmdqualifier) | |
| checkdcs(data+offset, length, cmdqualifier, simid); | |
| if (newpdu[simid]) | |
| return newpdu[simid]; | |
| else | |
| return (data + offset); | |
| } else | |
| return NULL; | |
| } | |
| static int checkSMSC(char *smsc) | |
| { | |
| int i = 0; | |
| for (i = 2; i < (int)strlen(smsc); i++) | |
| { | |
| if (smsc[i] > '9' || smsc[i] < '0') | |
| { | |
| if (smsc[i] == 'F' || smsc[i] == 'f') | |
| continue; | |
| else | |
| { | |
| LOG_OUT("invalid smsc:%s\n", smsc); | |
| return 1; | |
| } | |
| } | |
| } | |
| return 0; | |
| } | |
| static int stk_handle_proactive_data(struct ubus_context *ctx, char *data, int simid) | |
| { | |
| unsigned char proactive_tag,proactive_type; | |
| int ret = 0, length = 0; | |
| int length_2bytes = 0, offset = 0; | |
| char command_details[16] = { 0 }; | |
| char *sms_pdu = NULL; | |
| LOG_OUT("get new proactive : %s \n",data); | |
| if (!data) { | |
| LOG_OUT("proactive data is NULL\n"); | |
| ret = PROACTIVE_ERROR; | |
| goto EXIT; | |
| } | |
| proactive_tag = getValueFromHexStr( data , PROACTIVE_TAG_OFFSET); | |
| length = getValueFromHexStr( data , PROACTIVE_LENGTH_OFFSET); | |
| if (length == 0x81) { | |
| length = getValueFromHexStr( data , PROACTIVE_LENGTH_OFFSET + 1); | |
| length_2bytes = 1; | |
| } | |
| LOG_OUT("proactive length %d", length); | |
| proactive_type = getValueFromHexStr( data , PROACTIVE_TYPE_OFFSET + length_2bytes); | |
| memcpy(command_details, data + (PROACTIVE_COMMAND_DETAILS_OFFSET + length_2bytes) * 2, COMMAND_DETAILS_BYTE_NUM * 2); | |
| offset += (PROACTIVE_COMMAND_DETAILS_OFFSET + length_2bytes) * 2 + COMMAND_DETAILS_BYTE_NUM * 2; | |
| LOG_OUT("cmd type:0x%02x", proactive_type); | |
| if ((proactive_type == OPEN_CHANNEL) || (proactive_type == CLOSE_CHANNEL) || (proactive_type == RECEIVE_DATA) || | |
| (proactive_type == SEND_DATA) || (proactive_type == GET_CHANNEL_STATUS) || (proactive_type == REFRESH)) { | |
| handleBIPCommands(data, simid); | |
| ret = PROACTIVE_BIP; | |
| goto EXIT; | |
| } | |
| if (proactive_tag != PROACTIVE_COMMAND_TAG) { | |
| LOG_OUT("proactive data is mismatch\n"); | |
| ret = PROACTIVE_ERROR; | |
| goto EXIT; | |
| } | |
| if (proactive_type == SET_UP_MENU) { | |
| if (stk_save_proactive_setup_menu(data)) { | |
| ret = PROACTIVE_ERROR; | |
| goto EXIT; | |
| } | |
| #if 0 | |
| /*FIXME, the terminal response should trigger by WebUI, this is test version*/ | |
| if (send_setup_menu_terminal_response(command_details)) { | |
| ret = PROACTIVE_ERROR; | |
| goto EXIT; | |
| } | |
| #endif | |
| ret = PROACTIVE_SETUP_MENU; | |
| } | |
| if (proactive_type == SEND_SMS) { | |
| char smsc[50]; | |
| memset(smsc, 0, sizeof(smsc)); | |
| sms_pdu = get_pdu_from_send_sms(data, smsc, simid); | |
| if (sms_pdu) { | |
| ret = PROACTIVE_SEND_SMS; | |
| stkmsg[simid] = 1; | |
| stkmsg_cmdnumber[simid] = getValueFromHexStr(data, PROACTIVE_NUMBER_OFFSET + length_2bytes); | |
| stkmsg_cmdqual[simid] = getValueFromHexStr(data, PROACTIVE_QUALIFIER_OFFSET + length_2bytes); | |
| LOG_OUT(" %d,%02x", stkmsg_cmdnumber[simid], stkmsg_cmdqual[simid]); | |
| //notify_stk_send_sms(ctx, sms_pdu); | |
| stk_sms_send((strlen(smsc)==0||checkSMSC(smsc))?NULL:smsc, sms_pdu, simid); | |
| } | |
| } | |
| EXIT: | |
| return ret; | |
| } | |
| static int stk_sms_send_envelope(char* pdata, int datalen, int scalen, int simid) | |
| { | |
| int i, offset = 0, len = 0; | |
| int envSmsLen = 0; | |
| char *tempBuf; | |
| LOG_OUT("%s:Enter!\n", __FUNCTION__); | |
| envSmsLen = 8 + datalen + scalen; | |
| if(envSmsLen > 128) | |
| envSmsLen += 1; | |
| tempBuf = (char *)malloc(envSmsLen*2+20); | |
| if (!tempBuf) { | |
| LOG_OUT("malloc size %d failed", envSmsLen*2+20); | |
| return -1; | |
| } | |
| memset(tempBuf, 0, envSmsLen*2+20); | |
| if (envSmsLen > 128) | |
| len += sprintf(tempBuf, "D181%02x0202838106", envSmsLen); | |
| else | |
| len += sprintf(tempBuf, "D1%02x0202838106", envSmsLen); | |
| for(i = 0; i <= scalen; i++) | |
| { | |
| len += sprintf(tempBuf + len, "%02x", getValueFromHexStr(pdata, offset + i)); | |
| } | |
| if(datalen > 128) | |
| len += sprintf(tempBuf + len, "0B81%02x", datalen); | |
| else | |
| len += sprintf(tempBuf + len, "0B%02x", datalen); | |
| for(i = 0; i < datalen; i++) | |
| { | |
| offset = scalen + 1; | |
| len += sprintf(tempBuf + len, "%02x", getValueFromHexStr(pdata, offset + i)); | |
| } | |
| LOG_OUT("%s: temBuf[size %d] = %s\n", __FUNCTION__, len, tempBuf); | |
| send_envelope(tempBuf, simid); | |
| if (tempBuf) | |
| free(tempBuf); | |
| return 0; | |
| } | |
| static int stk_handle_sms_pp_download(struct ubus_context *ctx, char *data, int simid) | |
| { | |
| int datalen = 0, scalen = 0, offset = 0; | |
| int tpduFirstByte = 0, tpduLen = 0, tpdudatalen = 0; | |
| int pid = 0, dcs = 0; | |
| char *p = NULL; | |
| p = data; | |
| datalen = strlen(p); | |
| LOG_OUT("%s: pdata = %s\n, length = %d\n", __FUNCTION__, p, datalen); | |
| scalen = getValueFromHexStr(p, offset); | |
| tpduLen = (datalen - (scalen+1)*2)/2; | |
| LOG_OUT("%s: tpduLen = %d, scalen = %d\n", __FUNCTION__, tpduLen, scalen); | |
| offset = scalen + 1; | |
| tpduFirstByte = getValueFromHexStr(p, offset); | |
| offset = scalen + 2; | |
| if(tpduFirstByte != 0) | |
| { | |
| tpdudatalen = getValueFromHexStr(p, offset); | |
| if(tpdudatalen % 2 == 0) | |
| { | |
| offset = scalen + 4 + (tpdudatalen / 2); | |
| pid = getValueFromHexStr(p, offset); | |
| dcs = getValueFromHexStr(p, offset + 1); | |
| } | |
| else | |
| { | |
| offset = scalen + 4 + ((tpdudatalen + 1) / 2); | |
| pid = getValueFromHexStr(p, offset); | |
| dcs = getValueFromHexStr(p, offset + 1); | |
| } | |
| } | |
| else | |
| { | |
| pid = getValueFromHexStr(p, offset); | |
| dcs = getValueFromHexStr(p, offset + 1); | |
| } | |
| LOG_OUT("%s: pid = %d, dcs = %d\n", __FUNCTION__, pid, dcs); | |
| if((pid == 0x7C || pid == 0x7F) && (dcs & 0x03) == 0x02) | |
| { | |
| stk_sms_send_envelope(p, tpduLen, scalen, simid); | |
| } | |
| return 0; | |
| } | |
| static void stk_add_subscriber(struct uloop_timeout *timeout) | |
| { | |
| uint32_t id; | |
| if (ubus_lookup_id(stk_ubus_ctx, "ril", &id)) { | |
| LOG_OUT("%s, Failed to look up ril\n", __FUNCTION__); | |
| goto time_out; | |
| } | |
| ubus_subscribe(stk_ubus_ctx, &stk_unsol, id); | |
| if (ubus_lookup_id(stk_ubus_ctx, "ril.unsol.sim", &id)) { | |
| LOG_OUT("%s, Failed to look up service_unsol object\n", __FUNCTION__); | |
| goto time_out; | |
| } | |
| ubus_subscribe(stk_ubus_ctx, &stk_unsol, id); | |
| if (ubus_lookup_id(stk_ubus_ctx, "ril.unsol.msg", &id)) { | |
| LOG_OUT("%s, Failed to look up unsol.msg object\n", __FUNCTION__); | |
| goto time_out; | |
| } | |
| ubus_subscribe(stk_ubus_ctx, &stk_unsol, id); | |
| if (ubus_lookup_id(stk_ubus_ctx, "ril.unsol.ps", &id)) { | |
| LOG_OUT("%s, Failed to look up unsol.ps object\n", __FUNCTION__); | |
| goto time_out; | |
| } | |
| ubus_subscribe(stk_ubus_ctx, &stk_unsol, id); | |
| enable_stk(); | |
| return; | |
| time_out: | |
| uloop_timeout_set(timeout, 2000); | |
| return; | |
| } | |
| static const struct ubus_method stk_methods[] = { | |
| UBUS_METHOD_NOARG("enable_stk_service", enable_stk_service), | |
| UBUS_METHOD("set_stk_profile",set_stk_profile, set_stk_profile_pol), | |
| UBUS_METHOD("send_stk_terminal_response",send_stk_terminal_response, send_terminal_response_pol), | |
| UBUS_METHOD("send_stk_envelop", send_stk_envelop_command, send_envelop_command_pol), | |
| UBUS_METHOD("send_stk_callsetup_response", send_stk_setup_call_response, send_call_setup_response_pol), | |
| UBUS_METHOD_NOARG("get_stk_proactive", get_stk_proactive), | |
| UBUS_METHOD_NOARG("get_stk_proactive_setup_menu", get_stk_proactive_setup_menu), | |
| }; | |
| static struct ubus_object_type stk_object_type = UBUS_OBJECT_TYPE("test", stk_methods); | |
| static struct ubus_object stk_service_object = { | |
| .name = "stk", | |
| .type = &stk_object_type, | |
| .methods = stk_methods, | |
| .n_methods = ARRAY_SIZE(stk_methods), | |
| }; | |
| static void complete_stk_async_cb(struct ubus_request *req, int ret) | |
| { | |
| if (req) { | |
| free(req); | |
| } | |
| LOG_OUT("ret (%d)", ret); | |
| } | |
| int send_setup_menu_terminal_response(char *command_details) | |
| { | |
| struct ubus_request *req = NULL; | |
| struct blob_buf *b = &b_stk_buf; | |
| struct ubus_context *ctx = stk_ubus_ctx; | |
| unsigned int id = 0; | |
| int ret_val = UBUS_STATUS_OK; | |
| if (ubus_lookup_id(ctx, stk_service_object.name, &id)) { | |
| LOG_OUT("Failed to look up stk object"); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| blob_buf_init(b, 0); | |
| blobmsg_add_string(b, "commandDetails", command_details); | |
| blobmsg_add_string(b, "TerminalResponseResult", "00"); | |
| req = malloc(sizeof(struct ubus_request)); | |
| if (!req) { | |
| LOG_OUT( "malloc size %d failed", sizeof(struct ubus_request)); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| memset(req, 0, sizeof(struct ubus_request)); | |
| if ((ret_val = ubus_invoke_async(ctx, id, "send_stk_terminal_response", b->head, req)) != UBUS_STATUS_OK) { | |
| LOG_OUT("ubus_invoke_async send_stk_terminal_response failed %s", ubus_strerror(ret_val)); | |
| free(req); | |
| } else { | |
| req->complete_cb = complete_stk_async_cb; | |
| ubus_complete_request_async(ctx, req); | |
| } | |
| EXIT: | |
| return ret_val; | |
| } | |
| static int enable_stk(void) | |
| { | |
| struct ubus_request *req = NULL; | |
| struct blob_buf *b = &b_stk_buf; | |
| struct ubus_context *ctx = stk_ubus_ctx; | |
| unsigned int id; | |
| int ret_val = UBUS_STATUS_OK; | |
| if (ubus_lookup_id(ctx, stk_service_object.name, &id)) { | |
| LOG_OUT("Failed to look up stk object"); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| blob_buf_init(b, 0); | |
| req = malloc(sizeof(struct ubus_request)); | |
| if (!req) { | |
| LOG_OUT( "malloc size %d failed", sizeof(struct ubus_request)); | |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; | |
| goto EXIT; | |
| } | |
| memset(req, 0, sizeof(struct ubus_request)); | |
| if ((ret_val = ubus_invoke_async(ctx, id, "enable_stk_service", b->head, req)) != UBUS_STATUS_OK) { | |
| LOG_OUT("ubus_invoke_async enable_stk_service failed %s", ubus_strerror(ret_val)); | |
| free(req); | |
| } else { | |
| req->complete_cb = complete_stk_async_cb; | |
| ubus_complete_request_async(ctx, req); | |
| } | |
| EXIT: | |
| return ret_val; | |
| } | |
| static void stk_server_main(void) | |
| { | |
| int ret; | |
| //LOG_OUT("start"); | |
| #ifdef CHL_COMPILE | |
| ret = bip_lookup_chl(stk_ubus_ctx); | |
| if (ret) | |
| LOG_OUT("Failed to lookup chl"); | |
| #endif | |
| ret = ubus_add_object(stk_ubus_ctx, &stk_service_object); | |
| if (ret) | |
| LOG_OUT("Failed to add object: %s\n", ubus_strerror(ret)); | |
| ret = ubus_add_object(stk_ubus_ctx, &stk_notify_obj[0]); | |
| if (ret) | |
| LOG_OUT("Failed to add object: %s\n", ubus_strerror(ret)); | |
| ret = ubus_add_object(stk_ubus_ctx, &stk_notify_obj[1]); | |
| if (ret) | |
| LOG_OUT("Failed to add object: %s\n", ubus_strerror(ret)); | |
| ret = ubus_add_object(stk_ubus_ctx, &stk_notify_obj[2]); | |
| if (ret) | |
| LOG_OUT("Failed to add object: %s\n", ubus_strerror(ret)); | |
| stk_unsol.cb = stk_unsol_cb; | |
| ret = ubus_register_subscriber(stk_ubus_ctx, &stk_unsol); | |
| if (ret) | |
| { | |
| LOG_OUT("Failed to add subscriber stk_unsol: %s\n", ubus_strerror(ret)); | |
| return; | |
| } | |
| //subscribe ril.unsol.sim | |
| uloop_timeout_set(&stk_add_subscribe_timeout, 0); | |
| if(ubus_lookup_id(stk_ubus_ctx, "ril", &rilid)) | |
| { | |
| LOG_OUT("lookup ril object failed\n"); | |
| return; | |
| } | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| const char *ubus_socket = NULL; | |
| int ch; | |
| signal(SIGPIPE, SIG_IGN); | |
| set_service_log_tag("STK"); | |
| prctl(PR_SET_NAME, "stk"); | |
| while ((ch = getopt(argc, argv, "cs:")) != -1) { | |
| switch (ch) { | |
| case 's': | |
| ubus_socket = optarg; | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| argc -= optind; | |
| argv += optind; | |
| uloop_init(); | |
| signal(SIGPIPE, SIG_IGN); | |
| stk_ubus_ctx = ubus_connect(ubus_socket); | |
| if (!stk_ubus_ctx) { | |
| LOG_OUT_E("stk failed to connect to ubus\n"); | |
| return -1; | |
| } | |
| ubus_add_uloop(stk_ubus_ctx); | |
| stk_server_main(); | |
| uloop_run(); | |
| ubus_free(stk_ubus_ctx); | |
| uloop_done(); | |
| return 0; | |
| } |