Exemplo n.º 1
0
Arquivo: sms.c Projeto: Conjuror/ofono
static gboolean parse_gsm_tpdu(GIsiSubBlockIter *parent, struct sms_addr *add,
				struct sms_common *com)
{
	GIsiSubBlockIter iter;

	for (g_isi_sb_subiter_init(parent, &iter, 2);
			g_isi_sb_iter_is_valid(&iter);
			g_isi_sb_iter_next(&iter)) {

		switch (g_isi_sb_iter_get_id(&iter)) {
		case SMS_ADDRESS:

			if (!parse_sms_address(&iter, 2, add))
				return FALSE;

			if (add->type != SMS_GSM_0411_ADDRESS)
				return FALSE;

			break;

		case SMS_COMMON_DATA:

			if (!parse_sms_tpdu(&iter, 2, com))
				return FALSE;

			break;
		}
	}

	return TRUE;
}
Exemplo n.º 2
0
static void registration_resp_cb(const GIsiMessage *msg, void *data)
{
    struct isi_cb_data *cbd = data;
    ofono_call_forwarding_set_cb_t cb = cbd->cb;
    GIsiSubBlockIter iter;
    uint8_t status;

    if (!check_resp(msg, SS_SERVICE_COMPLETED_RESP, SS_REGISTRATION))
        goto error;

    for (g_isi_sb_iter_init(&iter, msg, 6);
            g_isi_sb_iter_is_valid(&iter);
            g_isi_sb_iter_next(&iter)) {

        if (g_isi_sb_iter_get_id(&iter) != SS_GSM_FORWARDING_INFO)
            continue;

        if (!decode_gsm_forwarding_info(&iter, &status, NULL, NULL,
                                        NULL))
            goto error;

        if (status & (SS_GSM_ACTIVE | SS_GSM_REGISTERED)) {
            CALLBACK_WITH_SUCCESS(cb, cbd->data);
            return;
        }
    }

error:
    CALLBACK_WITH_FAILURE(cb, cbd->data);
}
Exemplo n.º 3
0
Arquivo: sms.c Projeto: Conjuror/ofono
static void bearer_query_resp_cb(const GIsiMessage *msg, void *data)
{
	struct isi_cb_data *cbd = data;
	ofono_sms_bearer_query_cb_t cb = cbd->cb;
	GIsiSubBlockIter iter;
	uint8_t sb, cs, ps;

	if (!check_sms(msg, SMS_SETTINGS_READ_RESP, SMS_OK))
		goto error;

	if (!g_isi_msg_data_get_byte(msg, 1, &sb))
		goto error;

	for (g_isi_sb_iter_init_full(&iter, msg, 2, TRUE, sb);
			g_isi_sb_iter_is_valid(&iter);
			g_isi_sb_iter_next(&iter)) {

		if (g_isi_sb_iter_get_id(&iter) != SMS_SB_ROUTE_INFO)
			continue;

		if (!g_isi_msg_data_get_byte(msg, 5, &cs))
			goto error;

		if (!g_isi_msg_data_get_byte(msg, 6, &ps))
			goto error;

		CALLBACK_WITH_SUCCESS(cb, cs_ps_pref_to_bearer(cs, ps),
					cbd->data);
		return;
	}

error:
	CALLBACK_WITH_FAILURE(cb, 0, cbd->data);
}
Exemplo n.º 4
0
Arquivo: sms.c Projeto: Conjuror/ofono
static void submit_gsm_tpdu_resp_cb(const GIsiMessage *msg, void *data)
{
	struct isi_cb_data *cbd = data;
	ofono_sms_submit_cb_t cb = cbd->cb;
	struct sms_report *report;
	size_t len = sizeof(struct sms_report);
	GIsiSubBlockIter iter;

	if (!check_sms(msg, SMS_MESSAGE_SEND_RESP, -1))
		goto error;

	for (g_isi_sb_iter_init(&iter, msg, 2);
			g_isi_sb_iter_is_valid(&iter);
			g_isi_sb_iter_next(&iter)) {

		if (g_isi_sb_iter_get_id(&iter) != SMS_GSM_REPORT)
			continue;

		if (!g_isi_sb_iter_get_struct(&iter, (void **) &report, len, 2))
			goto error;

		if (report->type == SMS_CAUSE_TYPE_COMMON &&
				report->cause == SMS_OK) {
			CALLBACK_WITH_SUCCESS(cb, report->ref, cbd->data);
			return;
		}

		submit_failure_debug(report);
	}

error:
	CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
Exemplo n.º 5
0
Arquivo: sms.c Projeto: Conjuror/ofono
static void received_msg_ind_cb(const GIsiMessage *msg, void *data)
{
	struct ofono_sms *sms = data;
	struct sms_data *sd = ofono_sms_get_data(sms);
	struct sms_common tpdu;
	struct sms_addr addr;
	GIsiSubBlockIter iter;

	uint8_t pdu[176];
	uint8_t sbcount;

	DBG("");

	if (g_isi_msg_id(msg) != SMS_RECEIVED_MSG_IND)
		return;

	if (!g_isi_msg_data_get_byte(msg, 1, &sbcount))
		return;

	for (g_isi_sb_iter_init_full(&iter, msg, 2, TRUE, sbcount);
			g_isi_sb_iter_is_valid(&iter);
			g_isi_sb_iter_next(&iter)) {

		switch (g_isi_sb_iter_get_id(&iter)) {
		case SMS_ADDRESS:

			if (!parse_sms_address(&iter, 4, &addr))
				return;

			if (addr.type != SMS_SMSC_ADDRESS)
				return;

			break;

		case SMS_SB_TPDU:

			if (!parse_sms_tpdu(&iter, 4, &tpdu))
				return;

			break;
		}
	}

	if (tpdu.data == NULL || addr.data == NULL ||
			tpdu.len + addr.len > sizeof(pdu))
		return;

	memcpy(pdu, addr.data, addr.len);
	memcpy(pdu + addr.len, tpdu.data, tpdu.len);

	/* 23.040 9.2.3.1 */
	if ((tpdu.data[0] & 0x03) == 0x02)
		ofono_sms_status_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);
	else
		ofono_sms_deliver_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);

	send_deliver_report(sd->client, TRUE, NULL, NULL);
}
Exemplo n.º 6
0
static void u8500_info_resp_cb(const GIsiMessage *msg, void *data)
{
	struct isi_cb_data *cbd = data;
	ofono_devinfo_query_cb_t cb = cbd->cb;
	GIsiSubBlockIter iter;
	uint8_t msgid;
	uint8_t status;

	msgid = g_isi_msg_id(msg);
	if (msgid != INFO_SERIAL_NUMBER_READ_RESP)
		goto error;

	if (g_isi_msg_error(msg) < 0)
		goto error;

	if (!g_isi_msg_data_get_byte(msg, 0, &status))
		goto error;

	if (status != INFO_OK)
		goto error;

	for (g_isi_sb_iter_init(&iter, msg, 2);
			g_isi_sb_iter_is_valid(&iter);
			g_isi_sb_iter_next(&iter)) {

		uint8_t id = g_isi_sb_iter_get_id(&iter);
		uint8_t chars;
		char *info = NULL;

		if (id != INFO_SB_PRODUCT_INFO_MANUFACTURER &&
				id != INFO_SB_PRODUCT_INFO_NAME &&
				id != INFO_SB_MCUSW_VERSION &&
				id != INFO_SB_SN_IMEI_PLAIN &&
				id != INFO_SB_MODEMSW_VERSION)
			continue;

		if (g_isi_sb_iter_get_len(&iter) < 5)
			goto error;

		if (!g_isi_sb_iter_get_byte(&iter, &chars, 3))
			goto error;

		if (!g_isi_sb_iter_get_latin_tag(&iter, &info, chars, 4))
			goto error;

		CALLBACK_WITH_SUCCESS(cb, info, cbd->data);

		g_free(info);
		return;
	}

error:
	CALLBACK_WITH_FAILURE(cb, "", cbd->data);
}
Exemplo n.º 7
0
static gboolean decode_gsm_forwarding_info(GIsiSubBlockIter *parent,
        uint8_t *status, uint8_t *ton,
        uint8_t *noreply, char **number)
{
    GIsiSubBlockIter iter;
    struct forw_info *info;
    size_t len = sizeof(struct forw_info);
    char *tag = NULL;

    for (g_isi_sb_subiter_init(parent, &iter, 4);
            g_isi_sb_iter_is_valid(&iter);
            g_isi_sb_iter_next(&iter)) {

        if (g_isi_sb_iter_get_id(&iter) != SS_GSM_FORWARDING_FEATURE)
            continue;

        if (!g_isi_sb_iter_get_struct(&iter, (void *) &info, len, 2))
            return FALSE;

        if (info->numlen != 0) {
            if (!g_isi_sb_iter_get_alpha_tag(&iter, &tag,
                                             info->numlen * 2,
                                             2 + len))
                return FALSE;

            if (number)
                *number = tag;
            else
                g_free(tag);
        } else {
            if (number)
                *number = g_strdup("");
        }

        if (status)
            *status = info->status;

        if (ton)
            *ton = info->ton;

        if (noreply)
            *noreply = info->noreply;

        return TRUE;
    }
    return FALSE;
}
Exemplo n.º 8
0
Arquivo: sms.c Projeto: Conjuror/ofono
static void routing_ntf_cb(const GIsiMessage *msg, void *data)
{
	struct ofono_sms *sms = data;
	struct sms_data *sd = ofono_sms_get_data(sms);
	struct sms_common tpdu;
	struct sms_addr addr;
	GIsiSubBlockIter iter;

	uint8_t pdu[176];

	if (g_isi_msg_id(msg) != SMS_PP_ROUTING_NTF)
		return;

	for (g_isi_sb_iter_init(&iter, msg, 2);
			g_isi_sb_iter_is_valid(&iter);
			g_isi_sb_iter_next(&iter)) {

		if (g_isi_sb_iter_get_id(&iter) != SMS_GSM_TPDU)
			continue;

		if (!parse_gsm_tpdu(&iter, &addr, &tpdu))
			return;
	}

	if (tpdu.data == NULL || addr.data == NULL ||
			tpdu.len + addr.len > sizeof(pdu))
		return;

	memcpy(pdu, addr.data, addr.len);
	memcpy(pdu + addr.len, tpdu.data, tpdu.len);

	/* 23.040 9.2.3.1 */
	if ((tpdu.data[0] & 0x03) == 0x02)
		ofono_sms_status_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);
	else
		ofono_sms_deliver_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);

	send_gsm_deliver_report(sd->client, TRUE, NULL, NULL);
}
Exemplo n.º 9
0
static int decode_read_response(const unsigned char *msg, size_t len,
				struct ofono_phonebook *pb)
{
	GIsiSubBlockIter iter;

	char *name = NULL;
	char *number = NULL;
	char *sne = NULL;
	char *anr = NULL;
	char *email = NULL;

	int location = -1;
	guint8 status = 0;

	if (len < 3 || msg[0] != SIM_PB_RESP_SIM_PB_READ)
		goto error;

	if (msg[1] != SIM_PB_READ)
		goto error;

	for (g_isi_sb_iter_init_full(&iter, msg, len, 3, TRUE, msg[2]);
	     g_isi_sb_iter_is_valid(&iter);
	     g_isi_sb_iter_next(&iter)) {

		switch (g_isi_sb_iter_get_id(&iter)) {

		case SIM_PB_ADN: {
			guint16 loc;
			guint8 namelen;
			guint8 numberlen;

			if (!g_isi_sb_iter_get_word(&iter, &loc, 4) ||
				!g_isi_sb_iter_get_byte(&iter, &namelen, 6) ||
				!g_isi_sb_iter_get_byte(&iter, &numberlen, 7))
				goto error;

			if (!g_isi_sb_iter_get_alpha_tag(&iter, &name,
						namelen * 2, 8))
				goto error;

			if (!g_isi_sb_iter_get_alpha_tag(&iter, &number,
						numberlen * 2, 8 + namelen * 2))
				goto error;

			location = loc;
			break;
		}

		case SIM_PB_SNE: {
			guint8 snelen;

			if (!g_isi_sb_iter_get_byte(&iter, &snelen, 6))
				goto error;

			if (!g_isi_sb_iter_get_alpha_tag(&iter, &sne,
						snelen * 2, 8))
				goto error;
			break;
		}

		case SIM_PB_ANR: {
			guint8 anrlen;

			if (!g_isi_sb_iter_get_byte(&iter, &anrlen, 6))
				goto error;

			if (!g_isi_sb_iter_get_alpha_tag(&iter, &anr,
						anrlen * 2, 8))
				goto error;
			break;
		}

		case SIM_PB_EMAIL: {
			guint8 emaillen;

			if (!g_isi_sb_iter_get_byte(&iter, &emaillen, 6))
				goto error;

			if (!g_isi_sb_iter_get_alpha_tag(&iter, &email,
						emaillen * 2, 8))
				goto error;
			break;
		}

		case SIM_PB_STATUS:

			if (!g_isi_sb_iter_get_byte(&iter, &status, 4))
				goto error;

			break;

		default:
			DBG("Skipping sub-block: %s (%zd bytes)",
				sim_subblock_name(g_isi_sb_iter_get_id(&iter)),
				g_isi_sb_iter_get_len(&iter));
			break;
		}
	}

	if (status != SIM_SERV_OK) {
		DBG("Request failed: %s (0x%02X)",
			sim_isi_cause_name(status), status);
		goto error;
	}

	ofono_phonebook_entry(pb, -1, number, -1, name, -1, NULL,
				anr, -1, sne, email, NULL, NULL);

error:
	g_free(name);
	g_free(number);
	g_free(sne);
	g_free(anr);
	g_free(email);

	return location;
}
Exemplo n.º 10
0
static void isi_registration(struct ofono_call_forwarding *cf, int type,
                             int cls,
                             const struct ofono_phone_number *number,
                             int time, ofono_call_forwarding_set_cb_t cb,
                             void *data)
{
    struct forw_data *fd = ofono_call_forwarding_get_data(cf);
    struct isi_cb_data *cbd = isi_cb_data_new(cf, cb, data);
    int ss_code = forw_type_to_isi_code(type);

    char *ucs2 = NULL;

    size_t numlen = strlen(number->number);
    size_t sb_len = ALIGN4(6 + 2 * numlen);
    size_t pad_len = sb_len - (6 + 2 * numlen);

    uint8_t msg[7 + 6 + 28 * 2 + 3] = {
        SS_SERVICE_REQ,
        SS_REGISTRATION,
        SS_GSM_TELEPHONY,
        ss_code >> 8, ss_code & 0xFF,
        SS_SEND_ADDITIONAL_INFO,
        1,	/* Subblock count */
        SS_FORWARDING,
        sb_len,
        number->type,
        ss_code == SS_GSM_FORW_NO_REPLY ? time : SS_UNDEFINED_TIME,
        numlen,
        0,	/* Sub address length */
        /*
         * Followed by number in UCS-2 (no NULL termination),
         * zero sub address bytes, and 0 to 3 bytes of filler
         */
    };
    size_t msg_len = 7 + 6 + numlen * 2 + pad_len;

    if (cbd == NULL || fd == NULL || numlen > 28)
        goto error;

    DBG("forwarding type %d class %d number %s", type, cls, number->number);

    if (ss_code < 0)
        goto error;

    ucs2 = g_convert(number->number, numlen, "UCS-2BE", "UTF-8//TRANSLIT",
                     NULL, NULL, NULL);
    if (ucs2 == NULL)
        goto error;

    memcpy(msg + 13, ucs2, numlen * 2);
    g_free(ucs2);

    if (g_isi_client_send(fd->client, msg, msg_len, registration_resp_cb,
                          cbd, g_free))
        return;

error:
    CALLBACK_WITH_FAILURE(cb, data);
    g_free(cbd);
}

static void erasure_resp_cb(const GIsiMessage *msg, void *data)
{
    struct isi_cb_data *cbd = data;
    ofono_call_forwarding_set_cb_t cb = cbd->cb;
    GIsiSubBlockIter iter;
    uint8_t status;

    if (!check_resp(msg, SS_SERVICE_COMPLETED_RESP, SS_ERASURE))
        goto error;

    for (g_isi_sb_iter_init(&iter, msg, 6);
            g_isi_sb_iter_is_valid(&iter);
            g_isi_sb_iter_next(&iter)) {

        if (g_isi_sb_iter_get_id(&iter) != SS_GSM_FORWARDING_INFO)
            continue;

        if (!decode_gsm_forwarding_info(&iter, &status,	NULL, NULL,
                                        NULL))
            goto error;

        if (status & (SS_GSM_ACTIVE | SS_GSM_REGISTERED))
            goto error;

    }
    CALLBACK_WITH_SUCCESS(cb, cbd->data);
    return;

error:
    CALLBACK_WITH_FAILURE(cb, cbd->data);
}

static void isi_erasure(struct ofono_call_forwarding *cf, int type, int cls,
                        ofono_call_forwarding_set_cb_t cb, void *data)
{
    struct forw_data *fd = ofono_call_forwarding_get_data(cf);
    struct isi_cb_data *cbd = isi_cb_data_new(cf, cb, data);
    int ss_code = forw_type_to_isi_code(type);

    const uint8_t msg[] = {
        SS_SERVICE_REQ,
        SS_ERASURE,
        SS_GSM_TELEPHONY,
        ss_code >> 8, ss_code & 0xFF,
        SS_SEND_ADDITIONAL_INFO,
        0,		/* Subblock count */
    };

    DBG("forwarding type %d class %d", type, cls);

    if (cbd == NULL || fd == NULL || ss_code < 0)
        goto error;

    if (g_isi_client_send(fd->client, msg, sizeof(msg),
                          erasure_resp_cb, cbd, g_free))
        return;

error:
    CALLBACK_WITH_FAILURE(cb, data);
    g_free(cbd);
}

static void query_resp_cb(const GIsiMessage *msg, void *data)
{
    struct isi_cb_data *cbd = data;
    ofono_call_forwarding_query_cb_t cb = cbd->cb;
    GIsiSubBlockIter iter;

    struct ofono_call_forwarding_condition list = {
        .status = 0,
        .cls = 7,
        .time = 0,
        .phone_number = {
            .number[0] = '\0',
            .type = 0,
        },
    };
    uint8_t status;
    uint8_t ton;
    uint8_t noreply;
    char *number = NULL;

    if (!check_resp(msg, SS_SERVICE_COMPLETED_RESP, SS_INTERROGATION))
        goto error;

    for (g_isi_sb_iter_init(&iter, msg, 6);
            g_isi_sb_iter_is_valid(&iter);
            g_isi_sb_iter_next(&iter)) {

        DBG("Got %s", ss_subblock_name(g_isi_sb_iter_get_id(&iter)));

        if (g_isi_sb_iter_get_id(&iter) != SS_GSM_FORWARDING_INFO)
            continue;

        if (!decode_gsm_forwarding_info(&iter, &status, &ton, &noreply,
                                        &number))
            goto error;

        list.status = status & (SS_GSM_ACTIVE | SS_GSM_REGISTERED |
                                SS_GSM_PROVISIONED);
        list.time = noreply;
        list.phone_number.type = ton | 0x80;

        DBG("Number <%s>", number);

        strncpy(list.phone_number.number, number,
                OFONO_MAX_PHONE_NUMBER_LENGTH);
        list.phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
        g_free(number);

        DBG("forwarding query: %d, %d, %s(%d) - %d sec",
            list.status, list.cls, list.phone_number.number,
            list.phone_number.type, list.time);
    }
    CALLBACK_WITH_SUCCESS(cb, 1, &list, cbd->data);
    return;

error:
    CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
}


static void isi_query(struct ofono_call_forwarding *cf, int type, int cls,
                      ofono_call_forwarding_query_cb_t cb,
                      void *data)
{
    struct forw_data *fd = ofono_call_forwarding_get_data(cf);
    struct isi_cb_data *cbd = isi_cb_data_new(cf, cb, data);
    int ss_code = forw_type_to_isi_code(type);

    const uint8_t msg[] = {
        SS_SERVICE_REQ,
        SS_INTERROGATION,
        SS_GSM_TELEPHONY,
        ss_code >> 8, ss_code & 0xFF,
        SS_SEND_ADDITIONAL_INFO,
        0, /* Subblock count */
    };

    DBG("forwarding type %d class %d", type, cls);

    if (cbd == NULL || fd == NULL || cls != 7 || ss_code < 0)
        goto error;

    if (g_isi_client_send(fd->client, msg, sizeof(msg), query_resp_cb,
                          cbd, g_free))
        return;

error:
    CALLBACK_WITH_FAILURE(cb, 0, NULL, data);
    g_free(cbd);
}

static void reachable_cb(const GIsiMessage *msg, void *data)
{
    struct ofono_call_forwarding *cf = data;

    if (g_isi_msg_error(msg) < 0) {
        ofono_call_forwarding_remove(cf);
        return;
    }

    ISI_RESOURCE_DBG(msg);

    ofono_call_forwarding_register(cf);
}


static int isi_call_forwarding_probe(struct ofono_call_forwarding *cf,
                                     unsigned int vendor, void *user)
{
    GIsiModem *modem = user;
    struct forw_data *fd;

    fd = g_try_new0(struct forw_data, 1);
    if (fd == NULL)
        return -ENOMEM;

    fd->client = g_isi_client_create(modem, PN_SS);
    if (fd->client == NULL) {
        g_free(fd);
        return -ENOMEM;
    }

    ofono_call_forwarding_set_data(cf, fd);

    g_isi_client_verify(fd->client, reachable_cb, cf, NULL);

    return 0;
}