65796fb7448010631c611b92d4f0535dde807277
[samsung-ril.git] / net.c
1 /*
2  * This file is part of Samsung-RIL.
3  *
4  * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
5  * Copyright (C) 2011-2012 Paul Kocialkowski <contact@paulk.fr>
6  *
7  * Samsung-RIL is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * Samsung-RIL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Samsung-RIL.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #define LOG_TAG "RIL-NET"
23 #include <utils/Log.h>
24
25 #include "samsung-ril.h"
26 #include "util.h"
27
28 #include <plmn_list.h>
29
30 unsigned char ipc2ril_reg_state(unsigned char reg_state)
31 {
32         switch(reg_state) {
33                 case IPC_NET_REGISTRATION_STATE_NONE:
34                         return 0;
35                 case IPC_NET_REGISTRATION_STATE_HOME:
36                         return 1;
37                 case IPC_NET_REGISTRATION_STATE_SEARCHING:
38                         return 2;
39                 case IPC_NET_REGISTRATION_STATE_EMERGENCY:
40                         return 10;
41                 case IPC_NET_REGISTRATION_STATE_ROAMING:
42                         return 5;
43                 case IPC_NET_REGISTRATION_STATE_UNKNOWN:
44                         return 4;
45                 default:
46                         LOGE("%s: invalid reg_state: %d", __func__, reg_state);
47                         return 0;
48         }
49 }
50
51 unsigned char ipc2ril_act(unsigned char act)
52 {
53         switch(act) {
54                 case IPC_NET_ACCESS_TECHNOLOGY_GPRS:
55                         return 1;
56                 case IPC_NET_ACCESS_TECHNOLOGY_EDGE:
57                         return 2;
58                 case IPC_NET_ACCESS_TECHNOLOGY_UMTS:
59                         return 3;
60                 case IPC_NET_ACCESS_TECHNOLOGY_GSM:
61                 case IPC_NET_ACCESS_TECHNOLOGY_GSM2:
62                 default:
63                         return 0;
64         }
65 }
66
67 unsigned char ipc2ril_gprs_act(unsigned char act)
68 {
69         switch(act) {
70                 case IPC_NET_ACCESS_TECHNOLOGY_GPRS:
71                         return 1;
72                 case IPC_NET_ACCESS_TECHNOLOGY_EDGE:
73                         return 2;
74                 case IPC_NET_ACCESS_TECHNOLOGY_UMTS:
75                         return 3;
76                 case IPC_NET_ACCESS_TECHNOLOGY_GSM:
77                 case IPC_NET_ACCESS_TECHNOLOGY_GSM2:
78                 default:
79                         return 0;
80         }
81 }
82
83 int ipc2ril_mode_sel(unsigned char mode)
84 {
85         switch(mode) {
86                 case 0:
87                         return 7; // auto mode
88                 case IPC_NET_MODE_SEL_GSM_UMTS:
89                         return 0;
90                 case IPC_NET_MODE_SEL_GSM_ONLY:
91                         return 1;
92                 case IPC_NET_MODE_SEL_UMTS_ONLY:
93                         return 2;
94                 default:
95                         return 0;
96         }
97 }
98
99 unsigned char ril2ipc_mode_sel(int mode)
100 {
101         switch(mode) {
102                 case 1: // GSM only
103                         return IPC_NET_MODE_SEL_GSM_ONLY;
104                 case 2: // WCDMA only
105                         return IPC_NET_MODE_SEL_UMTS_ONLY;
106                 case 0:
107                 default: // GSM/WCDMA + the rest
108                         return IPC_NET_MODE_SEL_GSM_UMTS;
109         }
110 }
111
112 int ipc2ril_plmn_sel(unsigned char mode)
113 {
114         switch(mode) {
115                 case IPC_NET_PLMN_SEL_MANUAL:
116                         return 1;
117                 case IPC_NET_PLMN_SEL_AUTO:
118                         return 0;
119                 default:
120                         return 0;
121         }
122 }
123
124 unsigned char ril2ipc_plmn_sel(int mode)
125 {
126         switch(mode) {
127                 case 0:
128                         return IPC_NET_PLMN_SEL_AUTO;
129                 case 1:
130                         return IPC_NET_PLMN_SEL_MANUAL;
131                 default:
132                         return 0;
133         }
134 }
135
136 void ipc2ril_reg_state_resp(struct ipc_net_regist_response *netinfo, char *response[15])
137 {
138         unsigned char reg_state;
139         unsigned char act;
140
141         if (netinfo == NULL || response == NULL)
142                 return;
143
144         reg_state = ipc2ril_reg_state(netinfo->reg_state);
145         act = ipc2ril_act(netinfo->act);
146
147         memset(response, 0, sizeof(response));
148
149         asprintf(&response[0], "%d", reg_state);
150         asprintf(&response[1], "%x", netinfo->lac);
151         asprintf(&response[2], "%x", netinfo->cid);
152         asprintf(&response[3], "%d", act);
153 }
154
155 void ipc2ril_gprs_reg_state_resp(struct ipc_net_regist_response *netinfo, char *response[4])
156 {
157         unsigned char reg_state;
158         unsigned char act;
159
160         if (netinfo == NULL || response == NULL)
161                 return;
162
163         reg_state = ipc2ril_reg_state(netinfo->reg_state);
164         act = ipc2ril_gprs_act(netinfo->act);
165
166         memset(response, 0, sizeof(response));
167
168         asprintf(&response[0], "%d", reg_state);
169         asprintf(&response[1], "%x", netinfo->lac);
170         asprintf(&response[2], "%x", netinfo->cid);
171         asprintf(&response[3], "%d", act);
172 }
173
174 /*
175  * Set all the tokens to data waiting.
176  * For instance when only operator is updated by modem NOTI, we don't need
177  * to ask the modem new NET Regist and GPRS Net Regist states so act like we got
178  * these from modem NOTI too so we don't have to make the requests
179  */
180 void ril_tokens_net_set_data_waiting(void)
181 {
182         ril_data.tokens.registration_state = RIL_TOKEN_DATA_WAITING;
183         ril_data.tokens.gprs_registration_state = RIL_TOKEN_DATA_WAITING;
184         ril_data.tokens.operator = RIL_TOKEN_DATA_WAITING;
185 }
186
187 /*
188  * Returns 1 if unsol data is waiting, 0 if not
189  */
190 int ril_tokens_net_get_data_waiting(void)
191 {
192         return ril_data.tokens.registration_state == RIL_TOKEN_DATA_WAITING || ril_data.tokens.gprs_registration_state == RIL_TOKEN_DATA_WAITING || ril_data.tokens.operator == RIL_TOKEN_DATA_WAITING;
193 }
194
195 void ril_tokens_net_state_dump(void)
196 {
197         LOGD("ril_tokens_net_state_dump:\n\
198         \tril_data.tokens.registration_state = %p\n\
199         \tril_data.tokens.gprs_registration_state = %p\n\
200         \tril_data.tokens.operator = %p\n", ril_data.tokens.registration_state, ril_data.tokens.gprs_registration_state, ril_data.tokens.operator);
201 }
202
203 void ril_plmn_split(char *plmn_data, char **plmn, unsigned int *mcc, unsigned int *mnc)
204 {
205         char plmn_t[7];
206         int i;
207
208         memset(plmn_t, 0, sizeof(plmn_t));
209         memcpy(plmn_t, plmn_data, 6);
210
211         if (plmn_t[5] == '#')
212                 plmn_t[5] = '\0';
213
214         if (plmn != NULL) {
215                 *plmn = malloc(sizeof(plmn_t));
216                 memcpy(*plmn, plmn_t, sizeof(plmn_t));
217         }
218
219         if (mcc == NULL || mnc == NULL)
220                 return;
221
222         sscanf(plmn_t, "%3u%2u", mcc, mnc);
223 }
224
225 void ril_plmn_string(char *plmn_data, char *response[3])
226 {
227         unsigned int mcc, mnc;
228         char *plmn = NULL;
229
230         int plmn_entries;
231         int i;
232
233         if (plmn_data == NULL || response == NULL)
234                 return;
235
236         ril_plmn_split(plmn_data, &plmn, &mcc, &mnc);
237
238         asprintf(&response[2], "%s", plmn);
239
240         if (plmn != NULL)
241                 free(plmn);
242
243         plmn_entries = sizeof(plmn_list) / sizeof(struct plmn_list_entry);
244
245         LOGD("Found %d plmn records", plmn_entries);
246
247         for (i=0 ; i < plmn_entries ; i++) {
248                 if (plmn_list[i].mcc == mcc && plmn_list[i].mnc == mnc) {
249                         asprintf(&response[0], "%s", plmn_list[i].operator_long);
250                         asprintf(&response[1], "%s", plmn_list[i].operator_short);
251                         return; 
252                 }
253         }
254
255         response[0] = NULL;
256         response[1] = NULL;
257 }
258
259 /*
260  * How to handle NET unsol data from modem:
261  * 1- Rx UNSOL (NOTI) data from modem
262  * 2- copy data in a sized variable stored in radio
263  * 3- make sure no SOL request is going on for this token
264  * 4- copy data to radio structure
265  * 5- if no UNSOL data is already waiting for a token, tell RILJ NETWORK_STATE_CHANGED
266  * 6- set all the net tokens to RIL_TOKEN_DATA_WAITING
267  * 7- RILJ will ask for OPERATOR, GPRS_REG_STATE and REG_STATE
268  * for each request:
269  * 8- if token is RIL_TOKEN_DATA_WAITING it's SOL request for modem UNSOL data
270  * 9- send back modem data and tell E_SUCCESS to RILJ request
271  * 10- set token to 0x00
272  *
273  * How to handle NET sol requests from RILJ:
274  * 1- if token is 0x00 it's UNSOL RILJ request for modem data
275  * 2- put RIL_Token in token
276  * 3- request data to the modem
277  * 4- Rx SOL (RESP) data from modem
278  * 5- copy data to radio structure
279  * 6- send back data to RILJ with token from modem message
280  * 7- if token != RIL_TOKEN_DATA_WAITING, reset token to 0x00
281  *
282  * What if both are appening at the same time?
283  * 1- RILJ requests modem data (UNSOL)
284  * 2- token is 0x00 so send request to modem
285  * 3- UNSOL data arrives from modem
286  * 4- set all tokens to RIL_TOKEN_DATA_WAITING
287  * 5- store data, tell RILJ NETWORK_STATE_CHANGED
288  * 6- Rx requested data from modem
289  * 7- copy data to radio structure
290  * 8- token mismatch (is now RIL_TOKEN_DATA_WAITING)
291  * 9- send back data to RIL with token from IPC message
292  * 10- don't reset token to 0x00
293  * 11- RILJ does SOL request for modem data (we know it's SOL because we didn't reset token)
294  * 12- send back last data we have (from UNSOL RILJ request here)
295  */
296
297 void ril_request_operator(RIL_Token t)
298 {
299         char *response[3];
300         size_t i;
301
302         // IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value
303         if (ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
304         ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
305         ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
306         ril_data.state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
307                 ril_request_complete(t, RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW, NULL, 0);
308
309                 ril_data.tokens.operator = (RIL_Token) 0x00;
310                 return;
311         }
312
313         if (ril_data.tokens.operator == RIL_TOKEN_DATA_WAITING) {
314                 LOGD("Got RILJ request for UNSOL data");
315
316                 /* Send back the data we got UNSOL */
317                 ril_plmn_string(ril_data.state.plmndata.plmn, response);
318
319                 ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
320
321                 for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
322                         if (response[i] != NULL)
323                                 free(response[i]);
324                 }
325
326                 ril_data.tokens.operator = (RIL_Token) 0x00;
327         } else if (ril_data.tokens.operator == (RIL_Token) 0x00) {
328                 LOGD("Got RILJ request for SOL data");
329                 /* Request data to the modem */
330                 ril_data.tokens.operator = t;
331
332                 ipc_fmt_send_get(IPC_NET_CURRENT_PLMN, ril_request_get_id(t));
333         } else {
334                 LOGE("Another request is going on, returning UNSOL data");
335
336                 /* Send back the data we got UNSOL */
337                 ril_plmn_string(ril_data.state.plmndata.plmn, response);
338
339                 ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
340
341                 for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
342                         if (response[i] != NULL)
343                                 free(response[i]);
344                 }
345         }
346
347         ril_tokens_net_state_dump();
348 }
349
350 void ipc_net_current_plmn(struct ipc_message_info *info)
351 {
352         struct ipc_net_current_plmn_response *plmndata;
353         RIL_Token t;
354
355         char *response[3];
356         size_t i;
357
358         if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_net_current_plmn_response))
359                 goto error;
360
361         plmndata = (struct ipc_net_current_plmn_response *) info->data;
362         t = ril_request_get_token(info->aseq);
363
364         switch (info->type) {
365                 case IPC_TYPE_NOTI:
366                         LOGD("Got UNSOL Operator message");
367
368                         // IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value
369                         if (ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
370                         ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
371                         ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
372                         ril_data.state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
373                                 /* Better keeping it up to date */
374                                 memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
375
376                                 return;
377                         } else {
378                                 if (ril_data.tokens.operator != (RIL_Token) 0x00 && ril_data.tokens.operator != RIL_TOKEN_DATA_WAITING) {
379                                         LOGE("Another Operator Req is in progress, skipping");
380                                         return;
381                                 }
382
383                                 memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
384
385                                 /* we already told RILJ to get the new data but it wasn't done yet */
386                                 if (ril_tokens_net_get_data_waiting() && ril_data.tokens.operator == RIL_TOKEN_DATA_WAITING) {
387                                         LOGD("Updating Operator data in background");
388                                 } else {
389                                         ril_tokens_net_set_data_waiting();
390 #if RIL_VERSION >= 6
391                                         ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
392 #else
393                                         ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
394 #endif
395                                 }
396                         }
397                         break;
398                 case IPC_TYPE_RESP:
399                         LOGD("Got SOL Operator message");
400
401                         // IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value
402                         if (ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
403                         ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
404                         ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
405                         ril_data.state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
406                                 /* Better keeping it up to date */
407                                 memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
408
409                                 ril_request_complete(t, RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW, NULL, 0);
410
411                                 if (ril_data.tokens.operator != RIL_TOKEN_DATA_WAITING)
412                                         ril_data.tokens.operator = (RIL_Token) 0x00;
413                                 return;
414                         } else {
415                                 if (ril_data.tokens.operator != t)
416                                         LOGE("Operator tokens mismatch");
417
418                                 /* Better keeping it up to date */
419                                 memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
420
421                                 ril_plmn_string(plmndata->plmn, response);
422
423                                 ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
424
425                                 for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
426                                         if (response[i] != NULL)
427                                                 free(response[i]);
428                                 }
429
430                                 if (ril_data.tokens.operator != RIL_TOKEN_DATA_WAITING)
431                                         ril_data.tokens.operator = (RIL_Token) 0x00;
432                         }
433                         break;
434                 default:
435                         LOGE("%s: unhandled ipc method: %d", __func__, info->type);
436                         break;
437         }
438
439         ril_tokens_net_state_dump();
440
441         return;
442
443 error:
444         if (info != NULL)
445                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
446 }
447
448 #if RIL_VERSION >= 6
449 void ril_request_voice_registration_state(RIL_Token t)
450 #else
451 void ril_request_registration_state(RIL_Token t)
452 #endif
453 {
454         struct ipc_net_regist_get regist_req;
455         char *response[4];
456         int i;
457
458         if (ril_data.tokens.registration_state == RIL_TOKEN_DATA_WAITING) {
459                 LOGD("Got RILJ request for UNSOL data");
460
461                 /* Send back the data we got UNSOL */
462                 ipc2ril_reg_state_resp(&(ril_data.state.netinfo), response);
463
464                 ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
465
466                 for (i = 0; i < (int) (sizeof(response) / sizeof(char *)) ; i++) {
467                         if (response[i] != NULL)
468                                 free(response[i]);
469                 }
470
471                 ril_data.tokens.registration_state = (RIL_Token) 0x00;
472         } else if (ril_data.tokens.registration_state == (RIL_Token) 0x00) {
473                 LOGD("Got RILJ request for SOL data");
474                 /* Request data to the modem */
475                 ril_data.tokens.registration_state = t;
476
477                 ipc_net_regist_get_setup(&regist_req, IPC_NET_SERVICE_DOMAIN_GSM);
478                 ipc_fmt_send(IPC_NET_REGIST, IPC_TYPE_GET, (void *)&regist_req, sizeof(struct ipc_net_regist_get), ril_request_get_id(t));
479         } else {
480                 LOGE("Another request is going on, returning UNSOL data");
481
482                 /* Send back the data we got UNSOL */
483                 ipc2ril_reg_state_resp(&(ril_data.state.netinfo), response);
484
485                 ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
486
487                 for (i = 0; i < (int) (sizeof(response) / sizeof(char *)) ; i++) {
488                         if (response[i] != NULL)
489                                 free(response[i]);
490                 }
491         }
492
493         ril_tokens_net_state_dump();
494 }
495
496 #if RIL_VERSION >= 6
497 void ril_request_data_registration_state(RIL_Token t)
498 #else
499 void ril_request_gprs_registration_state(RIL_Token t)
500 #endif
501 {
502         struct ipc_net_regist_get regist_req;
503         char *response[4];
504         size_t i;
505
506         if (ril_data.tokens.gprs_registration_state == RIL_TOKEN_DATA_WAITING) {
507                 LOGD("Got RILJ request for UNSOL data");
508
509                 /* Send back the data we got UNSOL */
510                 ipc2ril_gprs_reg_state_resp(&(ril_data.state.gprs_netinfo), response);
511
512                 ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
513
514                 for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
515                         if (response[i] != NULL)
516                                 free(response[i]);
517                 }
518
519                 ril_data.tokens.gprs_registration_state = (RIL_Token) 0x00;
520         } else if (ril_data.tokens.gprs_registration_state == (RIL_Token) 0x00) {
521                 LOGD("Got RILJ request for SOL data");
522
523                 /* Request data to the modem */
524                 ril_data.tokens.gprs_registration_state = t;
525
526                 ipc_net_regist_get_setup(&regist_req, IPC_NET_SERVICE_DOMAIN_GPRS);
527                 ipc_fmt_send(IPC_NET_REGIST, IPC_TYPE_GET, (void *)&regist_req, sizeof(struct ipc_net_regist_get), ril_request_get_id(t));
528         } else {
529                 LOGE("Another request is going on, returning UNSOL data");
530
531                 /* Send back the data we got UNSOL */
532                 ipc2ril_gprs_reg_state_resp(&(ril_data.state.gprs_netinfo), response);
533
534                 ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
535
536                 for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
537                         if (response[i] != NULL)
538                                 free(response[i]);
539                 }
540         }
541
542         ril_tokens_net_state_dump();
543 }
544
545 void ipc_net_regist_unsol(struct ipc_message_info *info)
546 {
547         struct ipc_net_regist_response *netinfo;
548
549         if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_net_regist_response))
550                 goto error;
551
552         netinfo = (struct ipc_net_regist_response *) info->data;
553
554         LOGD("Got UNSOL NetRegist message");
555
556         switch(netinfo->domain) {
557                 case IPC_NET_SERVICE_DOMAIN_GSM:
558                         if (ril_data.tokens.registration_state != (RIL_Token) 0 && ril_data.tokens.registration_state != RIL_TOKEN_DATA_WAITING) {
559                                 LOGE("Another NetRegist Req is in progress, skipping");
560                                 return;
561                         }
562
563                         memcpy(&(ril_data.state.netinfo), netinfo, sizeof(struct ipc_net_regist_response));
564
565                         /* we already told RILJ to get the new data but it wasn't done yet */
566                         if (ril_tokens_net_get_data_waiting() && ril_data.tokens.registration_state == RIL_TOKEN_DATA_WAITING) {
567                                 LOGD("Updating NetRegist data in background");
568                         } else {
569                                 ril_tokens_net_set_data_waiting();
570 #if RIL_VERSION >= 6
571                                 ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
572 #else
573                                 ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
574 #endif
575                         }
576                         break;
577
578                 case IPC_NET_SERVICE_DOMAIN_GPRS:
579                         if (ril_data.tokens.gprs_registration_state != (RIL_Token) 0 && ril_data.tokens.gprs_registration_state != RIL_TOKEN_DATA_WAITING) {
580                                 LOGE("Another GPRS NetRegist Req is in progress, skipping");
581                                 return;
582                         }
583
584                         memcpy(&(ril_data.state.gprs_netinfo), netinfo, sizeof(struct ipc_net_regist_response));
585
586                         /* we already told RILJ to get the new data but it wasn't done yet */
587                         if (ril_tokens_net_get_data_waiting() && ril_data.tokens.gprs_registration_state == RIL_TOKEN_DATA_WAITING) {
588                                 LOGD("Updating GPRSNetRegist data in background");
589                         } else {
590                                 ril_tokens_net_set_data_waiting();
591 #if RIL_VERSION >= 6
592                                 ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
593 #else
594                                 ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
595 #endif
596                         }
597                         break;
598                 default:
599                         LOGE("%s: unhandled service domain: %d", __func__, netinfo->domain);
600                         break;
601         }
602
603         ril_tokens_net_state_dump();
604
605         return;
606
607 error:
608         if (info != NULL)
609                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
610 }
611
612 void ipc_net_regist_sol(struct ipc_message_info *info)
613 {
614         struct ipc_net_regist_response *netinfo;
615         RIL_Token t;
616
617         char *response[4];
618         size_t i;
619
620         if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_net_regist_response))
621                 goto error;
622
623         netinfo = (struct ipc_net_regist_response *) info->data;
624         t = ril_request_get_token(info->aseq);
625
626         LOGD("Got SOL NetRegist message");
627
628         switch(netinfo->domain) {
629                 case IPC_NET_SERVICE_DOMAIN_GSM:
630                         if (ril_data.tokens.registration_state != t)
631                                 LOGE("Registration state tokens mismatch");
632
633                         /* Better keeping it up to date */
634                         memcpy(&(ril_data.state.netinfo), netinfo, sizeof(struct ipc_net_regist_response));
635
636                         ipc2ril_reg_state_resp(netinfo, response);
637
638                         ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
639
640                         for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
641                                 if (response[i] != NULL)
642                                         free(response[i]);
643                         }
644
645                         if (ril_data.tokens.registration_state != RIL_TOKEN_DATA_WAITING)
646                                 ril_data.tokens.registration_state = (RIL_Token) 0x00;
647                         break;
648                 case IPC_NET_SERVICE_DOMAIN_GPRS:
649                         if (ril_data.tokens.gprs_registration_state != t)
650                                 LOGE("GPRS registration state tokens mismatch");
651
652                         /* Better keeping it up to date */
653                         memcpy(&(ril_data.state.gprs_netinfo), netinfo, sizeof(struct ipc_net_regist_response));
654
655                         ipc2ril_gprs_reg_state_resp(netinfo, response);
656
657                         ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
658
659                         for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
660                                 if (response[i] != NULL)
661                                         free(response[i]);
662                         }
663                         if (ril_data.tokens.registration_state != RIL_TOKEN_DATA_WAITING)
664                                 ril_data.tokens.gprs_registration_state = (RIL_Token) 0x00;
665                         break;
666                 default:
667                         LOGE("%s: unhandled service domain: %d", __func__, netinfo->domain);
668                         break;
669         }
670
671         ril_tokens_net_state_dump();
672
673         return;
674
675 error:
676         if (info != NULL)
677                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
678 }
679
680 void ipc_net_regist(struct ipc_message_info *info)
681 {
682         if (info == NULL)
683                 return;
684
685         /* Don't consider this if modem isn't in normal power mode. */
686         if (ril_data.state.power_state != IPC_PWR_PHONE_STATE_NORMAL)
687                 return;
688
689         switch(info->type) {
690                 case IPC_TYPE_NOTI:
691                         ipc_net_regist_unsol(info);
692                         break;
693                 case IPC_TYPE_RESP:
694                         ipc_net_regist_sol(info);
695                         break;
696                 default:
697                         LOGE("%s: unhandled ipc method: %d", __func__, info->type);
698                         break;
699         }
700
701 }
702
703 void ril_request_query_available_networks(RIL_Token t)
704 {
705         ipc_fmt_send_get(IPC_NET_PLMN_LIST, ril_request_get_id(t));
706 }
707
708 void ipc_net_plmn_list(struct ipc_message_info *info)
709 {
710         struct ipc_net_plmn_entries *entries_info;
711         struct ipc_net_plmn_entry *entries;
712
713         char **response;
714         int length;
715         int count;
716
717         int index;
718         int i;
719
720         if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_net_plmn_entries))
721                 goto error;
722
723         entries_info = (struct ipc_net_plmn_entries *) info->data;
724         entries = (struct ipc_net_plmn_entry *) (info->data + sizeof(struct ipc_net_plmn_entries));
725
726         LOGD("Listed %d PLMNs\n", entries_info->num);
727
728         length = sizeof(char *) * 4 * entries_info->num;
729         response = (char **) calloc(1, length);
730
731         count = 0;
732         for (i=0 ; i < entries_info->num ; i++) {
733                 // Assumed type for 'emergency only' PLMNs
734                 if (entries[i].type == 0x01)
735                         continue;
736
737                 index = count * 4;
738                 ril_plmn_string(entries[i].plmn, &response[index]);
739
740                 index = count * 4 + 3;
741                 switch (entries[i].status) {
742                         case IPC_NET_PLMN_STATUS_AVAILABLE:
743                                 response[index] = strdup("available");
744                                 break;
745                         case IPC_NET_PLMN_STATUS_CURRENT:
746                                 response[index] = strdup("current");
747                                 break;
748                         case IPC_NET_PLMN_STATUS_FORBIDDEN:
749                                 response[index] = strdup("forbidden");
750                                 break;
751                         default:
752                                 response[index] = strdup("unknown");
753                                 break;
754                 }
755
756                 count++;
757         }
758
759         length = sizeof(char *) * 4 * count;
760         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, response, length);
761
762         for (i=0 ; i < entries_info->num ; i++)
763                 if (response[i] != NULL)
764                         free(response[i]);
765
766         free(response);
767
768         return;
769
770 error:
771         if (info != NULL)
772                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
773 }
774
775 void ril_request_get_preferred_network_type(RIL_Token t)
776 {
777         ipc_fmt_send_get(IPC_NET_MODE_SEL, ril_request_get_id(t));
778 }
779
780 void ril_request_set_preferred_network_type(RIL_Token t, void *data, size_t length)
781 {
782         int ril_mode;
783         struct ipc_net_mode_sel mode_sel;
784
785         if (data == NULL || length < (int) sizeof(int))
786                 goto error;
787
788         ril_mode = *((int *) data);
789
790         mode_sel.mode_sel = ril2ipc_mode_sel(ril_mode);
791
792         ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_NET_MODE_SEL);
793
794         ipc_fmt_send(IPC_NET_MODE_SEL, IPC_TYPE_SET, (unsigned char *) &mode_sel, sizeof(mode_sel), ril_request_get_id(t));
795
796         return;
797
798 error:
799         ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
800 }
801
802 void ipc_net_mode_sel(struct ipc_message_info *info)
803 {
804         struct ipc_net_mode_sel *mode_sel;
805         int ril_mode;
806
807         if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_net_mode_sel))
808                 goto error;
809
810         mode_sel = (struct ipc_net_mode_sel *) info->data;
811         ril_mode = ipc2ril_mode_sel(mode_sel->mode_sel);
812
813         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &ril_mode, sizeof(ril_mode));
814
815         return;
816
817 error:
818         if (info != NULL)
819                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
820 }
821
822 void ril_request_query_network_selection_mode(RIL_Token t)
823 {
824         ipc_fmt_send_get(IPC_NET_PLMN_SEL, ril_request_get_id(t));
825 }
826
827 void ipc_net_plmn_sel(struct ipc_message_info *info)
828 {
829         struct ipc_net_plmn_sel_get *plmn_sel;
830         int ril_mode;
831
832         if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_net_plmn_sel_get))
833                 goto error;
834
835         plmn_sel = (struct ipc_net_plmn_sel_get *) info->data;
836         ril_mode = ipc2ril_plmn_sel(plmn_sel->plmn_sel);
837
838         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &ril_mode, sizeof(ril_mode));
839
840         return;
841
842 error:
843         if (info != NULL)
844                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
845 }
846
847 void ipc_net_plmn_sel_complete(struct ipc_message_info *info)
848 {
849         struct ipc_gen_phone_res *phone_res;
850         int rc;
851
852         phone_res = (struct ipc_gen_phone_res *) info->data;
853
854         rc = ipc_gen_phone_res_check(phone_res);
855         if (rc < 0) {
856                 if ((phone_res->code & 0x00ff) == 0x6f) {
857                         LOGE("Not authorized to register to this network!");
858                         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_ILLEGAL_SIM_OR_ME, NULL, 0);
859                 } else {
860                         LOGE("There was an error during operator selection!");
861                         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
862                 }
863                 return;
864         }
865
866         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0);
867 }
868
869 void ril_request_set_network_selection_automatic(RIL_Token t)
870 {
871         struct ipc_net_plmn_sel_set plmn_sel;
872
873         ipc_net_plmn_sel_set_setup(&plmn_sel, IPC_NET_PLMN_SEL_AUTO, NULL, IPC_NET_ACCESS_TECHNOLOGY_UNKNOWN);
874
875         ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_NET_PLMN_SEL, ipc_net_plmn_sel_complete);
876
877         ipc_fmt_send(IPC_NET_PLMN_SEL, IPC_TYPE_SET, (unsigned char *) &plmn_sel, sizeof(plmn_sel), ril_request_get_id(t));
878 }
879
880 void ril_request_set_network_selection_manual(RIL_Token t, void *data, size_t length)
881 {
882         struct ipc_net_plmn_sel_set plmn_sel;
883
884         if (data == NULL || length < (int) sizeof(char *))
885                 return;
886
887         // FIXME: We always assume UMTS capability
888         ipc_net_plmn_sel_set_setup(&plmn_sel, IPC_NET_PLMN_SEL_MANUAL, data, IPC_NET_ACCESS_TECHNOLOGY_UMTS);
889
890         ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_NET_PLMN_SEL, ipc_net_plmn_sel_complete);
891
892         ipc_fmt_send(IPC_NET_PLMN_SEL, IPC_TYPE_SET, (unsigned char *) &plmn_sel, sizeof(plmn_sel), ril_request_get_id(t));
893 }