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