summaryrefslogtreecommitdiffstats
path: root/gprs.c
blob: 3b4a9a83ced20cd55eba3f7e948931c3e4acc3f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
 * This file is part of samsung-ril.
 *
 * Copyright (C) 2011 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
 * Copyright (C) 2011 Paul Kocialkowski <contact@oaulk.fr>
 *
 * samsung-ril is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * samsung-ril is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <netinet/in.h>
#include <arpa/inet.h>

#define LOG_TAG "RIL-GPRS"
#include <utils/Log.h>

#include "samsung-ril.h"
#include "util.h"

/* FIXME: we don't want these hardcoded */
#define INTERFACE		"rmnet0"
#define IP_STRING_SIZE		15 + 1

// TODO: Put this in libsamsung-ipc headers
extern void ipc_gprs_define_pdp_context_setup(struct ipc_gprs_define_pdp_context *message, char *apn);

// libnetutils missing prototype
extern int ifc_configure(const char *ifname,
	in_addr_t address,
	in_addr_t netmask,
	in_addr_t gateway,
	in_addr_t dns1,
	in_addr_t dns2);

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_onRequestComplete(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_fmt_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
}

void ril_request_setup_data_call(RIL_Token t, void *data, int length)
{
	char *username = NULL;
	char *password = NULL;
	char *apn = NULL;

	struct ipc_gprs_define_pdp_context setup_apn_message;
	struct ipc_gprs_pdp_context activate_message;

	/* get the apn, username and password */
	apn = ((char **) data)[2];
	username = ((char **) data)[3];

	if(username != NULL) {
		if(strlen(username) < 2)
			username = "dummy";
	} else {
		username = "dummy";
	}

	password = ((char **) data)[4];

	if(password != NULL) {
		if(strlen(password) < 2)
			password = "dummy";
	} else {
		password = "dummy";
	}

	LOGD("Requesting data connection to APN '%s'\n", apn);

	/* create the structs with the apn */
	ipc_gprs_define_pdp_context_setup(&setup_apn_message, apn);

	/* create the structs with the username/password tuple */
	ipc_gprs_pdp_context_setup(&(ril_state.gprs_context), username, password);

	/* send the struct to the modem */
	ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET, 
			(void *) &setup_apn_message, sizeof(struct ipc_gprs_define_pdp_context), reqGetId(t));

	ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_GPRS_DEFINE_PDP_CONTEXT,
		ipc_gprs_pdp_context_complete);
}

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 *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->gateway)[0],(ip_config->gateway)[1],
                                                (ip_config->gateway)[2],(ip_config->gateway)[3]);

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

        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));

	// FIXME: check rc

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

	RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, response, sizeof(response));
}