static void ril_radio_state_changed(struct ril_msg *message, gpointer user_data) { struct ofono_modem *modem = user_data; struct ril_data *rd = ofono_modem_get_data(modem); struct parcel rilp; int radio_state; g_ril_init_parcel(message, &rilp); radio_state = parcel_r_int32(&rilp); if (rilp.malformed) { ofono_error("%s: malformed parcel received", __func__); ofono_modem_set_powered(modem, FALSE); return; } g_ril_append_print_buf(rd->ril, "(state: %s)", ril_radio_state_to_string(radio_state)); g_ril_print_unsol(rd->ril, message); switch (radio_state) { case RADIO_STATE_ON: break; case RADIO_STATE_UNAVAILABLE: ofono_modem_set_powered(modem, FALSE); break; case RADIO_STATE_OFF: break; } }
struct unsol_supp_svc_notif *g_ril_unsol_parse_supp_svc_notif(GRil *gril, struct ril_msg *message) { struct parcel rilp; char *tmp_number; int type; struct unsol_supp_svc_notif *unsol = g_new0(struct unsol_supp_svc_notif, 1); g_ril_init_parcel(message, &rilp); unsol->notif_type = parcel_r_int32(&rilp); unsol->code = parcel_r_int32(&rilp); unsol->index = parcel_r_int32(&rilp); type = parcel_r_int32(&rilp); tmp_number = parcel_r_string(&rilp); if (tmp_number != NULL) { strncpy(unsol->number.number, tmp_number, OFONO_MAX_PHONE_NUMBER_LENGTH); unsol->number.type = type; g_free(tmp_number); } g_ril_append_print_buf(gril, "{%d,%d,%d,%d,%s}", unsol->notif_type, unsol->code, unsol->index, type, tmp_number); g_ril_print_unsol(gril, message); return unsol; }
int g_ril_unsol_parse_connected(GRil *gril, const struct ril_msg *message) { struct parcel rilp; int size; int version; DBG(""); g_ril_init_parcel(message, &rilp); size = parcel_r_int32(&rilp); version = parcel_r_int32(&rilp); /* * For something that looks like a bug we get an extra int in mtk2 * modems. RIL version is the second integer in this case. This * happens when we get duplicated connected events, which should * not happen either. In these cases the first event has the right * size, but not those appearing after. */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK2 && size > 1) version = parcel_r_int32(&rilp); if (rilp.malformed) { ofono_error("%s: malformed parcel", __func__); version = RIL_VERSION_UNSPECIFIED; } g_ril_append_print_buf(gril, "{size: %d, [%d]}", size, version); g_ril_print_unsol(gril, message); return version; }
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data) { struct ofono_ussd *ussd = user_data; struct ussd_data *ud = ofono_ussd_get_data(ussd); struct parcel rilp; int numstr; char *typestr; int type; char *str = NULL; gsize written; char *ucs2; g_ril_init_parcel(message, &rilp); numstr = parcel_r_int32(&rilp); if (numstr < 1) return; typestr = parcel_r_string(&rilp); if (typestr == NULL || *typestr == '\0') return; type = *typestr - '0'; g_free(typestr); if (numstr > 1) str = parcel_r_string(&rilp); g_ril_append_print_buf(ud->ril, "{%d,%s}", type, str); g_ril_print_unsol(ud->ril, message); /* To fix bug in MTK: USSD-Notify arrive with type 2 instead of 0 */ if (g_ril_vendor(ud->ril) == OFONO_RIL_VENDOR_MTK && str != NULL && type == 2) type = 0; if (str == NULL) { ofono_ussd_notify(ussd, type, 0, NULL, 0); return; } /* * With data coding scheme 0x48, we are saying that the ussd string is a * UCS-2 string, uncompressed, and with unspecified message class. For * the DCS coding, see 3gpp 23.038, sect. 5. */ ucs2 = g_convert(str, -1, "UCS-2BE//TRANSLIT", "UTF-8", NULL, &written, NULL); g_free(str); if (ucs2 == NULL) { ofono_error("%s: Error transcoding", __func__); return; } ofono_ussd_notify(ussd, type, 0x48, (unsigned char *) ucs2, written); g_free(ucs2); }
static void ril_radio_state_changed(struct ril_msg *message, gpointer user_data) { struct ofono_modem *modem = user_data; struct ril_data *rd = ofono_modem_get_data(modem); struct parcel rilp; int radio_state; g_ril_init_parcel(message, &rilp); radio_state = parcel_r_int32(&rilp); if (rilp.malformed) { ofono_error("%s: malformed parcel received", __func__); ofono_modem_set_powered(modem, FALSE); return; } g_ril_append_print_buf(rd->ril, "(state: %s)", ril_radio_state_to_string(radio_state)); g_ril_print_unsol(rd->ril, message); if (radio_state != rd->radio_state) { ofono_info("%s: state: %s rd->ofono_online: %d", __func__, ril_radio_state_to_string(radio_state), rd->ofono_online); rd->radio_state = radio_state; switch (radio_state) { case RADIO_STATE_ON: if (rd->radio_settings == NULL) rd->radio_settings = ofono_radio_settings_create(modem, rd->vendor, RILMODEM, rd->ril); break; case RADIO_STATE_UNAVAILABLE: case RADIO_STATE_OFF: /* * Unexpected radio state change, as we are supposed to * be online. UNAVAILABLE has been seen occassionally * when powering off the phone. We wait 5 secs to avoid * too fast re-spawns, then exit with error to make * upstart re-start ofono. */ if (rd->ofono_online) ofono_error("%s: radio self-powered off!", __func__); break; } } }
struct unsol_ussd *g_ril_unsol_parse_ussd(GRil *gril, struct ril_msg *message) { struct parcel rilp; struct unsol_ussd *ussd; char *typestr = NULL; int numstr; ussd = g_try_malloc0(sizeof(*ussd)); if (ussd == NULL) { ofono_error("%s out of memory", __func__); goto error; } g_ril_init_parcel(message, &rilp); numstr = parcel_r_int32(&rilp); if (numstr < 1) { ofono_error("%s malformed parcel", __func__); goto error; } typestr = parcel_r_string(&rilp); if (typestr == NULL || *typestr == '\0') { ofono_error("%s wrong type", __func__); goto error; } ussd->type = *typestr - '0'; g_free(typestr); if (numstr > 1) ussd->message = parcel_r_string(&rilp); g_ril_append_print_buf(gril, "{%d,%s}", ussd->type, ussd->message); g_ril_print_unsol(gril, message); return ussd; error: g_free(typestr); g_free(ussd); return NULL; }
struct unsol_sms_data *g_ril_unsol_parse_new_sms(GRil *gril, const struct ril_msg *message) { struct parcel rilp; char *ril_pdu; size_t ril_pdu_len; struct unsol_sms_data *sms_data; sms_data = g_new0(struct unsol_sms_data, 1); if (sms_data == NULL) { ofono_error("%s out of memory", __func__); goto error; } g_ril_init_parcel(message, &rilp); ril_pdu = parcel_r_string(&rilp); if (ril_pdu == NULL) { ofono_error("%s Unable to parse notification", __func__); goto error; } ril_pdu_len = strlen(ril_pdu); sms_data->data = decode_hex(ril_pdu, ril_pdu_len, &sms_data->length, -1); if (sms_data->data == NULL) { ofono_error("%s Unable to decode notification", __func__); goto error_dec; } g_ril_append_print_buf(gril, "{%s}", ril_pdu); g_ril_print_unsol(gril, message); g_free(ril_pdu); return sms_data; error_dec: g_free(ril_pdu); error: g_ril_unsol_free_sms_data(sms_data); return NULL; }
static void ril_nitz_notify(struct ril_msg *message, gpointer user_data) { struct ofono_netreg *netreg = user_data; struct netreg_data *nd = ofono_netreg_get_data(netreg); struct parcel rilp; int year, mon, mday, hour, min, sec, dst, tzi; char tzs, tz[4]; gchar *nitz; if (message->req != RIL_UNSOL_NITZ_TIME_RECEIVED) goto error; ril_util_init_parcel(message, &rilp); nitz = parcel_r_string(&rilp); g_ril_append_print_buf(nd->ril, "(%s)", nitz); g_ril_print_unsol(nd->ril, message); sscanf(nitz, "%u/%u/%u,%u:%u:%u%c%u,%u", &year, &mon, &mday, &hour, &min, &sec, &tzs, &tzi, &dst); sprintf(tz, "%c%d", tzs, tzi); nd->time.utcoff = atoi(tz) * 15 * 60; nd->time.dst = dst; nd->time.sec = sec; nd->time.min = min; nd->time.hour = hour; nd->time.mday = mday; nd->time.mon = mon; nd->time.year = 2000 + year; ofono_netreg_time_notify(netreg, &nd->time); g_free(nitz); return; error: ofono_error("Unable to notify ofono about nitz"); }
int g_ril_unsol_parse_radio_state_changed(GRil *gril, const struct ril_msg *message) { struct parcel rilp; int radio_state; g_ril_init_parcel(message, &rilp); radio_state = parcel_r_int32(&rilp); if (rilp.malformed) { ofono_error("%s: malformed parcel received", __func__); radio_state = -1; } g_ril_append_print_buf(gril, "(state: %s)", ril_radio_state_to_string(radio_state)); g_ril_print_unsol(gril, message); return radio_state; }
char *g_ril_unsol_parse_nitz(GRil *gril, const struct ril_msg *message) { struct parcel rilp; gchar *nitz = NULL; DBG(""); if (message->buf_len < MIN_NITZ_SIZE) { ofono_error("%s: NITZ too small: %d", __func__, (int) message->buf_len); goto error; } g_ril_init_parcel(message, &rilp); nitz = parcel_r_string(&rilp); g_ril_append_print_buf(gril, "(%s)", nitz); g_ril_print_unsol(gril, message); error: return nitz; }
static void ril_sms_notify(struct ril_msg *message, gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *sd = ofono_sms_get_data(sms); struct parcel rilp; char *ril_pdu; int ril_pdu_len; unsigned int smsc_len; long ril_buf_len; guchar *ril_data; DBG("req: %d; data_len: %d", message->req, message->buf_len); switch (message->req) { case RIL_UNSOL_RESPONSE_NEW_SMS: case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: break; default: goto error; } ril_util_init_parcel(message, &rilp); ril_pdu = parcel_r_string(&rilp); if (ril_pdu == NULL) goto error; ril_pdu_len = strlen(ril_pdu); DBG("ril_pdu_len is %d", ril_pdu_len); ril_data = decode_hex(ril_pdu, ril_pdu_len, &ril_buf_len, -1); if (ril_data == NULL) goto error; /* The first octect in the pdu contains the SMSC address length * which is the X following octects it reads. We add 1 octet to * the read length to take into account this read octet in order * to calculate the proper tpdu length. */ smsc_len = ril_data[0] + 1; DBG("smsc_len is %d", smsc_len); g_ril_append_print_buf(sd->ril, "(%s)", ril_pdu); g_ril_print_unsol(sd->ril, message); if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS) { /* Last parameter is 'tpdu_len' ( substract SMSC length ) */ ofono_sms_deliver_notify(sms, ril_data, ril_buf_len, ril_buf_len - smsc_len); } else if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT) { ofono_sms_status_notify(sms, ril_data, ril_buf_len, ril_buf_len - smsc_len); } ril_ack_delivery(sms); return; error: ofono_error("Unable to parse NEW_SMS notification"); }
int g_ril_unsol_parse_signal_strength(GRil *gril, const struct ril_msg *message, int ril_tech) { struct parcel rilp; int gw_sigstr, gw_signal, cdma_dbm, evdo_dbm; int lte_sigstr = -1, lte_rsrp = -1, lte_rssnr = -1; int lte_signal; int signal; g_ril_init_parcel(message, &rilp); /* RIL_SignalStrength_v5 */ /* GW_SignalStrength */ gw_sigstr = parcel_r_int32(&rilp); gw_signal = get_gsm_strength(gw_sigstr); parcel_r_int32(&rilp); /* bitErrorRate */ /* * CDMA/EVDO values are not processed as CDMA is not supported */ /* CDMA_SignalStrength */ cdma_dbm = parcel_r_int32(&rilp); parcel_r_int32(&rilp); /* ecio */ /* EVDO_SignalStrength */ evdo_dbm = parcel_r_int32(&rilp); parcel_r_int32(&rilp); /* ecio */ parcel_r_int32(&rilp); /* signalNoiseRatio */ /* Present only for RIL_SignalStrength_v6 or newer */ if (parcel_data_avail(&rilp) > 0) { /* LTE_SignalStrength */ lte_sigstr = parcel_r_int32(&rilp); lte_rsrp = parcel_r_int32(&rilp); parcel_r_int32(&rilp); /* rsrq */ lte_rssnr = parcel_r_int32(&rilp); parcel_r_int32(&rilp); /* cqi */ lte_signal = get_lte_strength(lte_sigstr, lte_rsrp, lte_rssnr); } else { lte_signal = -1; } g_ril_append_print_buf(gril, "{gw: %d, cdma: %d, evdo: %d, lte: %d %d %d}", gw_sigstr, cdma_dbm, evdo_dbm, lte_sigstr, lte_rsrp, lte_rssnr); if (message->unsolicited) g_ril_print_unsol(gril, message); else g_ril_print_response(gril, message); /* Return the first valid one */ if (gw_signal != -1 && lte_signal != -1) if (ril_tech == RADIO_TECH_LTE) signal = lte_signal; else signal = gw_signal; else if (gw_signal != -1) signal = gw_signal; else if (lte_signal != -1) signal = lte_signal; else signal = -1; return signal; }
/* * This function handles RIL_UNSOL_DATA_CALL_LIST_CHANGED messages, * as well as RIL_REQUEST_DATA_CALL_LIST/SETUP_DATA_CALL replies, as * all have the same payload. */ struct ril_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril, const struct ril_msg *message) { struct ril_data_call *call; struct parcel rilp; struct ril_data_call_list *reply = NULL; unsigned int active, cid, i, num_calls, retry, status; char *type = NULL, *ifname = NULL, *raw_addrs = NULL; char *raw_dns = NULL, *raw_gws = NULL; DBG(""); /* Can happen for RIL_REQUEST_DATA_CALL_LIST replies */ if (message->buf_len < MIN_DATA_CALL_LIST_SIZE) { if (message->req == RIL_REQUEST_SETUP_DATA_CALL) { ofono_error("%s: message too small: %d", __func__, (int) message->buf_len); goto error; } else { g_ril_append_print_buf(gril, "{"); goto done; } } reply = g_try_new0(struct ril_data_call_list, 1); if (reply == NULL) { ofono_error("%s: out of memory", __func__); goto error; } g_ril_init_parcel(message, &rilp); /* * ril.h documents the reply to a RIL_REQUEST_DATA_CALL_LIST * as being an array of RIL_Data_Call_Response_v6 structs, * however in reality, the response also includes a version * to start. */ reply->version = parcel_r_int32(&rilp); num_calls = parcel_r_int32(&rilp); g_ril_append_print_buf(gril, "{version=%d,num=%d", reply->version, num_calls); for (i = 0; i < num_calls; i++) { status = parcel_r_int32(&rilp); retry = parcel_r_int32(&rilp); /* ignore */ cid = parcel_r_int32(&rilp); active = parcel_r_int32(&rilp); type = parcel_r_string(&rilp); ifname = parcel_r_string(&rilp); raw_addrs = parcel_r_string(&rilp); raw_dns = parcel_r_string(&rilp); raw_gws = parcel_r_string(&rilp); /* malformed check */ if (rilp.malformed) { ofono_error("%s: malformed parcel received", __func__); goto error; } g_ril_append_print_buf(gril, "%s [status=%d,retry=%d,cid=%d," "active=%d,type=%s,ifname=%s," "address=%s,dns=%s,gateways=%s]", print_buf, status, retry, cid, active, type, ifname, raw_addrs, raw_dns, raw_gws); call = g_try_new0(struct ril_data_call, 1); if (call == NULL) { ofono_error("%s: out of memory", __func__); goto error; } call->status = status; call->cid = cid; call->active = active; if (message->req == RIL_REQUEST_SETUP_DATA_CALL && status == PDP_FAIL_NONE && handle_settings(call, type, ifname, raw_addrs, raw_dns, raw_gws) == FALSE) goto error; g_free(type); g_free(ifname); g_free(raw_addrs); g_free(raw_dns); g_free(raw_gws); reply->calls = g_slist_insert_sorted(reply->calls, call, data_call_compare); } done: g_ril_append_print_buf(gril, "%s}", print_buf); if (message->unsolicited) g_ril_print_unsol(gril, message); else g_ril_print_response(gril, message); return reply; error: g_free(type); g_free(ifname); g_free(raw_addrs); g_free(raw_dns); g_free(raw_gws); g_ril_unsol_free_data_call_list(reply); return NULL; }
static void ril_sms_notify(struct ril_msg *message, gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *sd = ofono_sms_get_data(sms); struct parcel rilp; char *ril_pdu; int ril_pdu_len; unsigned int smsc_len; long ril_buf_len; guchar *ril_data; int request = RIL_REQUEST_SMS_ACKNOWLEDGE; int ret; DBG("req: %d; data_len: %d", message->req, (int) message->buf_len); if (message->req != RIL_UNSOL_RESPONSE_NEW_SMS) goto error; ril_util_init_parcel(message, &rilp); ril_pdu = parcel_r_string(&rilp); if (ril_pdu == NULL) goto error; ril_pdu_len = strlen(ril_pdu); DBG("ril_pdu_len is %d", ril_pdu_len); ril_data = decode_hex(ril_pdu, ril_pdu_len, &ril_buf_len, -1); if (ril_data == NULL) goto error; /* The first octect in the pdu contains the SMSC address length * which is the X following octects it reads. We add 1 octet to * the read length to take into account this read octet in order * to calculate the proper tpdu length. */ smsc_len = ril_data[0] + 1; DBG("smsc_len is %d", smsc_len); g_ril_append_print_buf(sd->ril, "(%s)", ril_pdu); g_ril_print_unsol(sd->ril, message); /* Last parameter is 'tpdu_len' ( substract SMSC length ) */ ofono_sms_deliver_notify(sms, ril_data, ril_buf_len, ril_buf_len - smsc_len); /* Re-use rilp, so initilize */ parcel_init(&rilp); parcel_w_int32(&rilp, 2); /* Number of int32 values in array */ parcel_w_int32(&rilp, 1); /* Successful receipt */ parcel_w_int32(&rilp, 0); /* error code */ /* TODO: should ACK be sent for either of the error cases? */ /* ACK the incoming NEW_SMS; ignore response so no cb needed */ ret = g_ril_send(sd->ril, request, rilp.data, rilp.size, NULL, NULL, NULL); g_ril_append_print_buf(sd->ril, "(1,0)"); g_ril_print_request(sd->ril, ret, request); parcel_free(&rilp); return; error: ofono_error("Unable to parse NEW_SMS notification"); }