Ejemplo n.º 1
0
void ipc_gprs_pdp_context_enable_complete(struct ipc_message_info *info)
{
	struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
	struct ril_gprs_connection *gprs_connection;
	int rc;

	gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq));

	if(!gprs_connection) {
		LOGE("Unable to find GPRS connection, aborting");

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	rc = ipc_gen_phone_res_check(phone_res);
	if(rc < 0) {
		LOGE("There was an error, aborting PDP context complete");

		gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
		gprs_connection->token = (RIL_Token) 0x00;
		ril_state.gprs_last_failed_cid = gprs_connection->cid;

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	LOGD("Waiting for IP configuration!");
}
Ejemplo n.º 2
0
void ipc_gprs_pdp_context_disable_complete(struct ipc_message_info *info)
{
	struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
	struct ril_gprs_connection *gprs_connection;
	int rc;

	gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq));

	if(!gprs_connection) {
		LOGE("Unable to find GPRS connection, aborting");

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	rc = ipc_gen_phone_res_check(phone_res);
	if(rc < 0) {
		LOGE("There was an error, aborting PDP context complete");

		// RILJ is not going to ask for fail reason
		ril_gprs_connection_del(gprs_connection);

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	LOGD("Waiting for GPRS call status");
}
Ejemplo n.º 3
0
/**
 * In: IPC_NET_PLMN_LIST
 * Send back available PLMN list
 *
 */
void ipc_net_plmn_list(struct ipc_message_info *info)
{
	struct ipc_net_plmn_entries *entries_info = (struct ipc_net_plmn_entries *) info->data;
	struct ipc_net_plmn_entry *entries = (struct ipc_net_plmn_entry *)
		(info->data + sizeof(struct ipc_net_plmn_entries));

	int i;
	int size = (4 * entries_info->num * sizeof(char*));
	int actual_size = 0;

	char **resp = malloc(size);
	char **resp_ptr = resp;

	LOGD("Listed %d PLMNs\n", entries_info->num);

	for(i = 0; i < entries_info->num; i++) {
		/* Assumed type for 'emergency only' PLMNs */
		if(entries[i].type == 0x01)
			continue;

		char *plmn = plmn_string(entries[i].plmn);

		LOGD("PLMN #%d: %s (%s)\n", i, plmn_lookup(plmn), plmn);

		/* Long (E)ONS */
		asprintf(&resp_ptr[0], "%s", plmn_lookup(plmn));

		/* Short (E)ONS - FIXME: real short EONS */
		asprintf(&resp_ptr[1], "%s", plmn_lookup(plmn));

		/* PLMN */
		asprintf(&resp_ptr[2], "%s", plmn);

		free(plmn);

		/* PLMN status */
		switch(entries[i].status) {
			case IPC_NET_PLMN_STATUS_AVAILABLE:
				asprintf(&resp_ptr[3], "available");
				break;
			case IPC_NET_PLMN_STATUS_CURRENT:
				asprintf(&resp_ptr[3], "current");
				break;
			case IPC_NET_PLMN_STATUS_FORBIDDEN:
				asprintf(&resp_ptr[3], "forbidden");
				break;
			default:
				asprintf(&resp_ptr[3], "unknown");
				break;
		}

		actual_size++;
		resp_ptr += 4;
	}

	ril_request_complete(reqGetToken(info->aseq), RIL_E_SUCCESS, resp, (4 * sizeof(char*) * actual_size));

	/* FIXME: free individual strings */
	free(resp);
}
Ejemplo n.º 4
0
void ipc_net_mode_sel(struct ipc_message_info *info)
{
	unsigned char ipc_mode = *(unsigned char *) info->data;
	int ril_mode = ipc2ril_modesel(ipc_mode);

	ril_request_complete(reqGetToken(info->aseq), RIL_E_SUCCESS, &ril_mode, sizeof(int*));
}
Ejemplo n.º 5
0
/**
 * In: IPC_GEN_PHONE_RES
 *   Check the ipc_gen_phone_res_expects queue and act accordingly
 */
void ipc_gen_phone_res(struct ipc_message_info *info)
{
	struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
	int id = ipc_gen_phone_res_get_id(info->aseq);
	RIL_Errno e;
	int rc;

	// In this case, it can be a real error or we just didn't queue
	if(id < 0) {
		LOGD("aseq: 0x%x not found in the IPC_GEN_PHONE_RES queue", info->aseq);
		return;
	}

	LOGD("aseq: 0x%x found in the IPC_GEN_PHONE_RES queue!", info->aseq);

	if(ipc_gen_phone_res_expects[id].command != IPC_COMMAND(phone_res)) {
		LOGE("IPC_GEN_PHONE_RES aseq (0x%x) doesn't match the queued one with command (0x%x)", 
				ipc_gen_phone_res_expects[id].aseq, ipc_gen_phone_res_expects[id].command);

		if(ipc_gen_phone_res_expects[id].func != NULL) {
			LOGE("Not safe to run the custom function, reporting generic failure");
			RIL_onRequestComplete(reqGetToken(ipc_gen_phone_res_expects[id].aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
		}
	}

	if(ipc_gen_phone_res_expects[id].func != NULL) {
		ipc_gen_phone_res_expects[id].func(info);
		ipc_gen_phone_res_clean_id(id);
		return;
	}

	rc = ipc_gen_phone_res_check(phone_res);
	if(rc < 0)
		e = RIL_E_GENERIC_FAILURE;
	else
		e = RIL_E_SUCCESS;

	if(ipc_gen_phone_res_expects[id].to_complete || (ipc_gen_phone_res_expects[id].to_abort && rc < 0)) {
		RIL_onRequestComplete(reqGetToken(ipc_gen_phone_res_expects[id].aseq), e, NULL, 0);
		ipc_gen_phone_res_clean_id(id);
		return;
	}

	ipc_gen_phone_res_clean_id(id);
}
Ejemplo n.º 6
0
void ipc_gprs_ip_configuration(struct ipc_message_info *info)
{
	/* Quick and dirty configuration, TODO: Handle that better */

        struct ipc_gprs_ip_configuration *ip_config = (struct ipc_gprs_ip_configuration *) info->data;

	char local_ip[IP_STRING_SIZE];
	char gateway[IP_STRING_SIZE];
	char subnet_mask[IP_STRING_SIZE];
	char dns1[IP_STRING_SIZE];
	char dns2[IP_STRING_SIZE];

	char dns_prop_name[PROPERTY_KEY_MAX];
	char gw_prop_name[PROPERTY_KEY_MAX];

	char *response[3];
	int rc;

	/* TODO: transform that into some macros */
	snprintf(local_ip, IP_STRING_SIZE, "%i.%i.%i.%i",(ip_config->ip)[0],(ip_config->ip)[1],
						(ip_config->ip)[2],(ip_config->ip)[3]);

        snprintf(gateway, IP_STRING_SIZE, "%i.%i.%i.%i",(ip_config->ip)[0],(ip_config->ip)[1],
                                                (ip_config->ip)[2],(ip_config->ip)[3]);

        snprintf(subnet_mask, IP_STRING_SIZE, "255.255.255.255");

        snprintf(dns1, IP_STRING_SIZE, "%i.%i.%i.%i",(ip_config->dns1)[0],(ip_config->dns1)[1],
                                                (ip_config->dns1)[2],(ip_config->dns1)[3]);

        snprintf(dns2, IP_STRING_SIZE , "%i.%i.%i.%i",(ip_config->dns2)[0],(ip_config->dns2)[1],
                                                (ip_config->dns2)[2],(ip_config->dns2)[3]);

        LOGD("GPRS configuration: ip:%s, gateway:%s, subnet_mask:%s, dns1:%s, dns2:%s",
							local_ip, gateway, subnet_mask ,dns1, dns2);
	rc = ifc_configure(INTERFACE, 
			inet_addr(local_ip),
			inet_addr(subnet_mask),
			inet_addr(gateway),
			inet_addr(dns1),
			inet_addr(dns2));
        LOGD("ifc_configure: %d",rc);

	snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", INTERFACE);
	property_set(dns_prop_name, dns1);
	snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", INTERFACE);
	property_set(dns_prop_name, dns2);
	snprintf(gw_prop_name, sizeof(gw_prop_name), "net.%s.gw", INTERFACE);
	property_set(dns_prop_name, gateway);

	response[0] = "0"; //FIXME: connection id
	response[1] = INTERFACE;
	response[2] = local_ip;

	ril_request_complete(reqGetToken(info->aseq), RIL_E_SUCCESS, response, sizeof(response));
}
Ejemplo n.º 7
0
void ipc_net_regist_sol(struct ipc_message_info *message)
{
	char *response[4];
	int i;

	struct ipc_net_regist *netinfo = (struct ipc_net_regist *) message->data;
	RIL_Token t = reqGetToken(message->aseq);

	LOGD("Got SOL NetRegist message");

	switch(netinfo->domain) {
		case IPC_NET_SERVICE_DOMAIN_GSM:
			if(ril_state.tokens.registration_state != t)
				LOGE("Registration state tokens mismatch");

			/* Better keeping it up to date */
			memcpy(&(ril_state.netinfo), netinfo, sizeof(struct ipc_net_regist));

			ipc2ril_reg_state_resp(netinfo, response);

			ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));

			for(i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
				if(response[i] != NULL)
					free(response[i]);
			}

			if(ril_state.tokens.registration_state != RIL_TOKEN_NET_DATA_WAITING)
				ril_state.tokens.registration_state = (RIL_Token) 0x00;
			break;
		case IPC_NET_SERVICE_DOMAIN_GPRS:
			if(ril_state.tokens.gprs_registration_state != t)
				LOGE("GPRS registration state tokens mismatch");

			/* Better keeping it up to date */
			memcpy(&(ril_state.gprs_netinfo), netinfo, sizeof(struct ipc_net_regist));

			ipc2ril_gprs_reg_state_resp(netinfo, response);

			ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));

			for(i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
				if(response[i] != NULL)
					free(response[i]);
			}
			if(ril_state.tokens.registration_state != RIL_TOKEN_NET_DATA_WAITING)
				ril_state.tokens.gprs_registration_state = (RIL_Token) 0x00;
			break;
		default:
			LOGE("%s: unhandled service domain: %d", __FUNCTION__, netinfo->domain);
			break;
	}

	ril_tokens_net_state_dump();
}
Ejemplo n.º 8
0
void ipc_gprs_port_list_complete(struct ipc_message_info *info)
{
	struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
	struct ril_gprs_connection *gprs_connection;
	int rc;
	int aseq;

	gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq));

	if(!gprs_connection) {
		LOGE("Unable to find GPRS connection, aborting");

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	rc = ipc_gen_phone_res_check(phone_res);
	if(rc < 0) {
		LOGE("There was an error, aborting port list complete");

		gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
		gprs_connection->token = (RIL_Token) 0x00;
		ril_state.gprs_last_failed_cid = gprs_connection->cid;

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	// We need to get a clean new aseq here
	aseq = ril_request_reg_id(reqGetToken(info->aseq));

	ipc_gen_phone_res_expect_to_func(aseq, IPC_GPRS_DEFINE_PDP_CONTEXT,
		ipc_gprs_define_pdp_context_complete);

	ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET,
		(void *) &(gprs_connection->define_context),
		sizeof(struct ipc_gprs_define_pdp_context),
		aseq);
}
Ejemplo n.º 9
0
/**
 * In: IPC_SAT_ENVELOPE_CMD EXEC
 *
 * Out: RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND
 *   Requests to send a SAT/USAT envelope command to SIM.
 *   The SAT/USAT envelope command refers to 3GPP TS 11.14 and 3GPP TS 31.111
 */
void respondSatEnvelopeCmd(struct ipc_message_info *info)
{
	int data_len = (info->length-2);
	char *hexdata;

	hexdata = (char*)malloc(data_len*2+1);

	bin2hex((unsigned char*)info->data+2, data_len, hexdata);

	ril_request_complete(reqGetToken(info->aseq), RIL_E_SUCCESS, hexdata, sizeof(char*));

	free(hexdata);
}
Ejemplo n.º 10
0
void ipc_gprs_pdp_context_complete(struct ipc_message_info *info)
{
	struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
	int rc;
	int aseq;

	rc = ipc_gen_phone_res_check(phone_res);
	if(rc < 0) {
		ril_request_complete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
		LOGE("There was an error, aborting PDP context complete");
		return;
	}

	/* We need to get a clean new aseq here */
	aseq = ril_request_reg_id(reqGetToken(info->aseq));

	/* activate the connection */
	ipc_send(IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET, 
			(void *) &(ril_state.gprs_context), sizeof(struct ipc_gprs_pdp_context), aseq);

	ipc_gen_phone_res_expect_to_abort(aseq, IPC_GPRS_PDP_CONTEXT);
	// TODO: if this aborts, last fail cause will be: PDP_FAIL_ERROR_UNSPECIFIED
}
Ejemplo n.º 11
0
void ipc_gprs_ip_configuration(struct ipc_message_info *info)
{
	struct ril_gprs_connection *gprs_connection;
        struct ipc_gprs_ip_configuration *ip_configuration =
		(struct ipc_gprs_ip_configuration *) info->data;

	gprs_connection = ril_gprs_connection_get_cid(ip_configuration->cid);

	if(!gprs_connection) {
		LOGE("Unable to find GPRS connection, aborting");

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	LOGD("Obtained IP Configuration");

	// Copy the obtained IP configuration to the GPRS connection structure
	memcpy(&(gprs_connection->ip_configuration),
		ip_configuration, sizeof(struct ipc_gprs_ip_configuration));

	LOGD("Waiting for GPRS call status");
}
Ejemplo n.º 12
0
void ipc_gprs_pdp_context(struct ipc_message_info *info)
{
	struct ril_gprs_connection *gprs_connection;
        struct ipc_gprs_ip_configuration *ip_configuration;
	struct ipc_gprs_pdp_context_get *context =
		(struct ipc_gprs_pdp_context_get *) info->data;

#if RIL_VERSION >= 6
	RIL_Data_Call_Response_v6 data_call_list[IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT];
#else
	RIL_Data_Call_Response data_call_list[IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT];
#endif

	memset(data_call_list, 0, sizeof(data_call_list));

	int i;

	for(i=0 ; i < IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT ; i++) {
		data_call_list[i].cid = context->desc[i].cid;
		data_call_list[i].active =
			ipc2ril_gprs_connection_active(context->desc[i].state);

		if(context->desc[i].state == IPC_GPRS_STATE_ENABLED) {
			gprs_connection = ril_gprs_connection_get_cid(context->desc[i].cid);

			if(gprs_connection == NULL) {
				LOGE("CID %d reported as enabled but not listed here",
					context->desc[i].cid);
				continue;
			}

			ip_configuration = &(gprs_connection->ip_configuration);

			char *addr = NULL;
			asprintf(&addr, "%i.%i.%i.%i",
				(ip_configuration->ip)[0],
				(ip_configuration->ip)[1],
				(ip_configuration->ip)[2],
				(ip_configuration->ip)[3]);

#if RIL_VERSION >= 6
			RIL_Data_Call_Response_v6 *resp = &data_call_list[i];
#else
			RIL_Data_Call_Response *resp = &data_call_list[i];
#endif

			resp->type = strdup("IP");

#if RIL_VERSION < 6
			resp->address = addr;
			asprintf(&(resp->apn), "%s",
				gprs_connection->define_context.apn);
#else
			resp->addresses = addr;
			resp->gateways = strdup(addr);
			resp->ifname = strdup(gprs_connection->interface);
			asprintf(&resp->dnses, "%i.%i.%i.%i %i.%i.%i.%i",
				ip_configuration->dns1[0],
				ip_configuration->dns1[1],
				ip_configuration->dns1[2],
				ip_configuration->dns1[3],

				ip_configuration->dns2[0],
				ip_configuration->dns2[1],
				ip_configuration->dns2[2],
				ip_configuration->dns2[3]);
#endif
		}
	}

	ipc_gprs_pdp_context_fix(data_call_list, IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT);

	if(info->aseq == 0xff)
		RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
			&data_call_list, sizeof(data_call_list));
	else
		RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS,
			&data_call_list, sizeof(data_call_list));

	for(i = 0; i < IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT; i++) {
		ril_data_call_response_free(data_call_list + i);
	}
}
Ejemplo n.º 13
0
void ipc_gprs_call_status(struct ipc_message_info *info)
{
	struct ril_gprs_connection *gprs_connection;
	struct ipc_gprs_call_status *call_status =
		(struct ipc_gprs_call_status *) info->data;

#if RIL_VERSION >= 6
	RIL_Data_Call_Response_v6 setup_data_call_response;
	memset(&setup_data_call_response, 0, sizeof(setup_data_call_response));
#else
	char *setup_data_call_response[3] = { NULL, NULL, NULL };
#endif

	int rc;

	gprs_connection = ril_gprs_connection_get_cid(call_status->cid);

	if(!gprs_connection) {
		LOGE("Unable to find GPRS connection, aborting");

		RIL_onRequestComplete(reqGetToken(info->aseq),
			RIL_E_GENERIC_FAILURE, NULL, 0);
		return;
	}

	if(call_status->fail_cause == 0) {
		if(!gprs_connection->enabled &&
			call_status->state == IPC_GPRS_STATE_ENABLED &&
			gprs_connection->token != (RIL_Token) 0x00) {
			LOGD("GPRS connection is now enabled");

			rc = ipc_gprs_connection_enable(gprs_connection,
				&setup_data_call_response);
			if(rc < 0) {
				LOGE("Failed to enable and configure GPRS interface");

				gprs_connection->enabled = 0;
				gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
				ril_state.gprs_last_failed_cid = gprs_connection->cid;

				RIL_onRequestComplete(gprs_connection->token,
					RIL_E_GENERIC_FAILURE, NULL, 0);
			} else {
				LOGD("GPRS interface enabled");

				gprs_connection->enabled = 1;

				RIL_onRequestComplete(gprs_connection->token,
					RIL_E_SUCCESS, &setup_data_call_response,
					sizeof(setup_data_call_response));
				gprs_connection->token = (RIL_Token) 0x00;
			}
#if RIL_VERSION >= 6
			ril_data_call_response_free(&setup_data_call_response);
#else
			if(setup_data_call_response[0] != NULL)
				free(setup_data_call_response[0]);
			if(setup_data_call_response[1] != NULL)
				free(setup_data_call_response[1]);
			if(setup_data_call_response[2] != NULL)
				free(setup_data_call_response[2]);
#endif
		} else if(gprs_connection->enabled &&
			call_status->state == IPC_GPRS_STATE_DISABLED &&
			gprs_connection->token != (RIL_Token) 0x00) {
			LOGD("GPRS connection is now disabled");

			rc = ipc_gprs_connection_disable(gprs_connection);
			if(rc < 0) {
				LOGE("Failed to disable GPRS interface");

				RIL_onRequestComplete(gprs_connection->token,
					RIL_E_GENERIC_FAILURE, NULL, 0);

				// RILJ is not going to ask for fail reason
				ril_gprs_connection_del(gprs_connection);
			} else {
				LOGD("GPRS interface disabled");

				gprs_connection->enabled = 0;

				RIL_onRequestComplete(gprs_connection->token,
					RIL_E_SUCCESS, NULL, 0);

				ril_gprs_connection_del(gprs_connection);
			}
		} else {
			LOGE("GPRS connection reported as changed though state is not OK:"
			"\n\tgprs_connection->enabled=%d\n\tgprs_connection->token=0x%x",
				gprs_connection->enabled, (unsigned)gprs_connection->token);

			ril_unsol_data_call_list_changed();
		}
	} else {
		if(!gprs_connection->enabled &&
			(call_status->state == IPC_GPRS_STATE_NOT_ENABLED ||
			call_status->state == IPC_GPRS_STATE_DISABLED) &&
			gprs_connection->token != (RIL_Token) 0x00) {
			LOGE("Failed to enable GPRS connection");

			gprs_connection->enabled = 0;
			gprs_connection->fail_cause =
				ipc2ril_gprs_fail_cause(call_status->fail_cause);
			ril_state.gprs_last_failed_cid = gprs_connection->cid;

			RIL_onRequestComplete(gprs_connection->token,
				RIL_E_GENERIC_FAILURE, NULL, 0);
			gprs_connection->token = (RIL_Token) 0x00;

			ril_unsol_data_call_list_changed();
		} else if(gprs_connection->enabled &&
			call_status->state == IPC_GPRS_STATE_DISABLED) {
			LOGE("GPRS connection suddently got disabled");

			rc = ipc_gprs_connection_disable(gprs_connection);
			if(rc < 0) {
				LOGE("Failed to disable GPRS interface");

				// RILJ is not going to ask for fail reason
				ril_gprs_connection_del(gprs_connection);
			} else {
				LOGE("GPRS interface disabled");

				gprs_connection->enabled = 0;
				ril_gprs_connection_del(gprs_connection);
			}

			ril_unsol_data_call_list_changed();
		} else {
			LOGE("GPRS connection reported to have failed though state is OK:"
			"\n\tgprs_connection->enabled=%d\n\tgprs_connection->token=0x%x",
				gprs_connection->enabled, (unsigned)gprs_connection->token);

			ril_unsol_data_call_list_changed();
		}
	}
}
Ejemplo n.º 14
0
/**
 * In: IPC_NET_CURRENT_PLMN
 *   This can be SOL (RESP) or UNSOL (NOTI) message from modem
 *
 * Out: RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED
 *   enqueue modem data if UNSOL modem message and then call
 *   RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED
 *   if SOL message, send back data to RILJ
 */
void ipc_net_current_plmn(struct ipc_message_info *message)
{
	RIL_Token t = reqGetToken(message->aseq);
	struct ipc_net_current_plmn *plmndata = (struct ipc_net_current_plmn *) message->data;

	char *response[3];
	int i;

	switch(message->type) {
		case IPC_TYPE_NOTI:
			LOGD("Got UNSOL Operator message");

			// IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value 
			if(ril_state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
			ril_state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
			ril_state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
			ril_state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
				/* Better keeping it up to date */
				memcpy(&(ril_state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn));

				return;
			} else {
				if(ril_state.tokens.operator != (RIL_Token) 0x00 && ril_state.tokens.operator != RIL_TOKEN_NET_DATA_WAITING) {
					LOGE("Another Operator Req is in progress, skipping");
					return;
				}

				memcpy(&(ril_state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn));

				/* we already told RILJ to get the new data but it wasn't done yet */
				if(ril_tokens_net_get_data_waiting() && ril_state.tokens.operator == RIL_TOKEN_NET_DATA_WAITING) {
					LOGD("Updating Operator data in background");
				} else {
					ril_tokens_net_set_data_waiting();
					ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
				}
			}
			break;
		case IPC_TYPE_RESP:
			// IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value 
			if(ril_state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
			ril_state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
			ril_state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
			ril_state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
				/* Better keeping it up to date */
				memcpy(&(ril_state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn));

				ril_request_complete(t, RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW, NULL, 0);

				if(ril_state.tokens.operator != RIL_TOKEN_NET_DATA_WAITING)
					ril_state.tokens.operator = (RIL_Token) 0x00;
				return;
			} else {
				if(ril_state.tokens.operator != t)
					LOGE("Operator tokens mismatch");

				/* Better keeping it up to date */
				memcpy(&(ril_state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn));

				ril_plmn_string(plmndata, response);

				ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));

				for(i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
					if(response[i] != NULL)
						free(response[i]);
				}

				if(ril_state.tokens.operator != RIL_TOKEN_NET_DATA_WAITING)
					ril_state.tokens.operator = (RIL_Token) 0x00;
			}
			break;
		default:
			LOGE("%s: unhandled ipc method: %d", __FUNCTION__, message->type);
			break;
	}

	ril_tokens_net_state_dump();
}