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