blob: 9dac2721e40574a3e8fb7b902e312d7ff6d0b2b7 [file] [log] [blame]
#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, &param, 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;
}