SIM: Completed SIM status handling
[hayes-ril.git] / at.c
1 /*
2  * This file is part of hayes-ril.
3  *
4  * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <string.h>
20 #include <ctype.h>
21
22 #define LOG_TAG "RIL-AT"
23 #include <utils/Log.h>
24
25 #include <hayes-ril.h>
26
27 /*
28  * Globals
29  */
30
31 struct at_responses_handling at_responses_handling;
32
33 /*
34  * Utilities
35  */
36
37 int at_strings_compare(char *major, char *minor)
38 {
39         int major_length = strlen(major);
40         int minor_length = strlen(minor);
41
42         // We can't check against the whole major string
43         if(major_length > minor_length)
44                 return 0;
45
46         if(strncmp(major, minor, major_length) == 0)
47                 return 1;
48         else
49                 return 0;
50 }
51
52 int at_strings_raw_compare(char *major, char *minor)
53 {
54         int major_length = strlen(major);
55
56         // Only consider major length (minor might not have \0)
57         if(strncmp(major, minor, major_length) == 0)
58                 return 1;
59         else
60                 return 0;
61 }
62
63 // Major is response string, minor is request (reference) string
64 int at_commands_compare(char *major, char *minor)
65 {
66         int rc;
67
68         // Assume major is corect
69
70         if(at_strings_compare(major, minor))
71                 return 1;
72
73         // Compare without AT prefix
74         if(at_strings_compare("AT", minor) && !at_strings_compare("AT", major) && strlen(minor) > 2)
75                 return at_strings_compare(major, minor + 2);
76
77         if(at_strings_compare("AT", major) && !at_strings_compare("AT", minor) && strlen(major) > 2)
78                 return at_strings_compare(major + 2, minor);
79
80         return 0;
81 }
82
83 void at_string_clean(char *string, int length)
84 {
85         int i=0;
86
87         for(i=length-1; i >= 0 ; i--) {
88                 if(!isprint(string[i]))
89                         string[i] = '\0';
90         }
91 }
92
93 int at_status_error(int status)
94 {
95         switch(status) {
96                 case AT_STATUS_CONNECT:
97                         return 0;
98                 case AT_STATUS_OK:
99                         return 0;
100                 default:
101                         return 1;
102         }
103 }
104
105 /*
106  * Line parsers
107  */
108
109 int at_line_parse_status(char *data, int length, char **error_p)
110 {
111         char *response_command = NULL;
112         char *response_error = NULL;
113         int response_error_length = 0;
114
115         *error_p = NULL;
116
117         if(at_strings_compare("OK", data)) {
118                 *error_p = NULL;
119                 return AT_STATUS_OK;
120         }
121
122         if(at_strings_compare("CONNECT", data)) {
123                 *error_p = NULL;
124                 return AT_STATUS_CONNECT;
125         }
126
127         if(at_strings_compare("ERROR", data)) {
128                 *error_p = NULL;
129                 return AT_STATUS_ERROR;
130         }
131
132         if(at_strings_compare("+CME ERROR", data)) {
133                 response_error_length = at_line_parse_command_data(data, length, &response_command, &response_error);
134                 if(response_error != NULL && response_error_length > 0) {
135                         at_string_clean(response_error, strlen(response_error) + 1);
136                         *error_p = response_error;
137                 }
138
139                 if(response_command != NULL)
140                         free(response_command);
141
142                 return AT_STATUS_CME_ERROR;
143         }
144
145         return AT_STATUS_UNDEF;
146 }
147
148 int at_line_parse_command_data(char *data, int length, char **response_command, char **response_data)
149 {
150         char *string = NULL;
151         int string_length = 0;
152         int close_your_eyes = 0;
153         int mark = 0;
154         int i;
155
156
157         for(i=0 ; i < length ; i++) {
158                 if(data[i] == ':' && mark == 0) {
159                         if(i > 0) {
160                                 data[i] = '\0';
161
162                                 string_length = i + 1;
163                                 string = strndup(data, string_length);
164
165                                 if(!isprint(string[0])) {
166                                         free(string);
167                                 } else {
168                                         *response_command = string;
169                                 }
170
171                                 mark = i + 1;
172                         }
173
174                         while(isspace(data[i+1])) {
175                                 mark = i + 2;
176                                 i++;
177                         }
178                 }
179
180                 if(data[i] == '"') {
181                         if(close_your_eyes & AT_PARSE_DOUBLE_QUOTE)
182                                 close_your_eyes &= ~AT_PARSE_DOUBLE_QUOTE;
183                         else
184                                 close_your_eyes |= AT_PARSE_DOUBLE_QUOTE;
185                 }
186
187                 if(data[i] == '\'') {
188                         if(close_your_eyes & AT_PARSE_SINGLE_QUOTE)
189                                 close_your_eyes &= ~AT_PARSE_SINGLE_QUOTE;
190                         else
191                                 close_your_eyes |= AT_PARSE_SINGLE_QUOTE;
192                 }
193
194                 // Found = or ? outside of any quotes: assume no data
195                 if(!close_your_eyes && (data[i] == '=' || data[i] == '?') && mark == 0) {
196                         data[i] = '\0';
197
198                         string_length = i + 1;
199                         string = strndup(data, string_length);
200
201                         if(!isprint(string[0])) {
202                                 free(string);
203                         } else {
204                                 *response_command = string;
205                         }
206
207                         return 0;
208                 }
209         }
210
211
212         if(length - mark > 0) {
213                 string_length = length - mark;
214                 string = strndup(data + mark, string_length);
215
216                 if(mark == 0) {
217                         *response_command = string;
218                         return 0;
219                 } else {
220                         *response_data = string;
221                         return string_length;
222                 }
223         }
224
225         return 0;
226 }
227
228 /*
229  * Responses line processor
230  */
231
232 int at_responses_process_line(struct at_response ***responses_p, int responses_count, char *data, int length)
233 {
234         struct at_response **responses = NULL;
235
236         char *response_command = NULL;
237         char *response_data = NULL;
238         int response_data_length = 0;
239         char *response_error = NULL;
240         int response_status = 0;
241
242         char **response_previous_data = NULL;
243         int response_data_count = 0;
244
245         int index = -1;
246         int count = 0;
247         int i;
248
249         if(responses_p == NULL || data == NULL || length < 0) {
250                 LOGE("Failed to process AT response: wrong arguments!");
251                 return 0;
252         }
253
254         responses = *responses_p;
255
256         // Parse status
257         response_status = at_line_parse_status(data, length, &response_error);
258
259         if(response_status != AT_STATUS_UNDEF) {
260                 if(responses_count > 0 && responses != NULL) {
261                         for(i=responses_count-1 ; i >= 0; i--) {
262                                 if(responses[i]->status == AT_STATUS_UNDEF) {
263                                         responses[i]->status = response_status;
264                                         responses[i]->error = response_error;
265
266                                         // Do not alloc a new response
267                                         if(index == -1)
268                                                 index = i;
269                                 }
270                         }
271                 }
272
273                 // Alloc a new response
274                 if(index == -1) {
275                         // Index is the request index in the requests array
276                         index = responses_count;
277                         // Count is the total count of requests in the array
278                         count = index + 1;
279
280                         // Alloc the array with the new size
281                         *responses_p = malloc(sizeof(struct at_response *) * count);
282
283                         // Copy and free previous data
284                         if(responses != NULL) {
285                                 memcpy(*responses_p, responses, sizeof(struct at_response *) * responses_count);
286                                 free(responses);
287                         }
288
289                         responses = *responses_p;
290
291                         // Alloc new structure and copy obtained data
292                         responses[index] = calloc(1, sizeof(struct at_response));
293                         responses[index]->status = response_status;
294                         responses[index]->error = response_error;
295                 }
296         } else {
297                 // Parse command and data
298                 response_data_length = at_line_parse_command_data(data, length, &response_command, &response_data);
299
300                 if(response_command == NULL) {
301                         LOGE("Failed to parse command!");
302                         return responses_count;
303                 }
304
305                 at_string_clean(response_command, strlen(response_command) + 1);
306
307                 if(responses_count > 0 && responses != NULL) {
308                         for(i=responses_count-1 ; i >= 0; i--) {
309                                 if(responses[i]->command != NULL) {
310                                         if(at_commands_compare(responses[i]->command, response_command))
311                                                 // Do not alloc a new response
312                                                 index = i;
313                                 }
314                         }
315                 }
316
317                 // Alloc a new response
318                 if(index == -1) {
319                         // Index is the request index in the requests array
320                         index = responses_count;
321                         // Count is the total count of requests in the array
322                         count = index + 1;
323
324                         // Alloc the array with the new size
325                         *responses_p = malloc(sizeof(struct at_response *) * count);
326
327                         // Copy and free previous data
328                         if(responses != NULL) {
329                                 memcpy(*responses_p, responses, sizeof(struct at_response *) * responses_count);
330                                 free(responses);
331                         }
332
333                         responses = *responses_p;
334
335                         // Alloc new structure and copy obtained data
336                         responses[index] = calloc(1, sizeof(struct at_response));
337                         responses[index]->command = response_command;
338                         responses[index]->status = AT_STATUS_UNDEF;
339                 }
340
341                 if(response_data_length > 0 && response_data != NULL) {
342                         at_string_clean(response_data, response_data_length);
343
344                         response_previous_data = responses[index]->data;
345
346                         // Data count is the total count of elements in the request data
347                         response_data_count = responses[index]->data_count + 1;
348
349                         // Alloc the array with the new size
350                         responses[index]->data = malloc(sizeof(char *) * response_data_count);
351
352                         // Copy and free previous data
353                         if(response_previous_data != NULL) {
354                                 memcpy(responses[index]->data, response_previous_data, sizeof(char *) * responses[index]->data_count);
355                                 free(response_previous_data);
356                         }
357
358                         responses[index]->data_count = response_data_count;
359                         responses[index]->data[response_data_count - 1] = response_data;
360                 }
361         }
362
363         return count > responses_count ? count : responses_count;
364 }
365
366 /*
367  * Responses structures processing
368  */
369
370 int at_responses_process(struct at_response ***responses_p, char *data, int length)
371 {
372         int responses_count = 0;
373         int count = 0;
374
375         char *string = NULL;
376         int string_length = 0;
377         int mark = 0;
378         int i;
379
380         if(responses_p == NULL || data == NULL || length < 0) {
381                 LOGE("Failed to process AT response: wrong arguments!");
382                 return 0;
383         }
384
385         for(i=0 ; i < length ; i++) {
386                 if(data[i] == '\r' || data[i] == ';') {
387                         if(i - mark > 0) {
388                                 data[i] = '\0';
389
390                                 string_length = i - mark + 1;
391                                 string = strndup(data + mark, string_length);
392
393                                 if(!isprint(string[0])) {
394                                         free(string);
395                                 }
396                                 else {
397                                         count = at_responses_process_line(responses_p, responses_count, string, string_length);
398                                         if(count > responses_count)
399                                                 responses_count = count;
400
401                                         free(string);
402                                 }
403
404                                 mark = i + 1;
405                         }
406
407                         while(isspace(data[i+1])) {
408                                 mark = i + 2;
409                                 i++;
410                         }
411                 }
412         }
413
414         if(length - mark > 0) {
415                 for(i=mark ; i < length ; i++)
416                         if(!isprint(data[i]))
417                                 break;
418
419                 if(i - mark > 0) {
420                         string_length = i - mark + 1;
421                         string = calloc(1, string_length);
422
423                         memcpy(string, data + mark, string_length - 1);
424                         string[string_length - 1] = '\0';
425
426                         count = at_responses_process_line(responses_p, responses_count, string , string_length);
427                         if(count > responses_count)
428                                 responses_count = count;
429
430                         free(string);
431                 }
432         }
433
434         return responses_count;
435 }
436
437 void at_response_free(struct at_response *response)
438 {
439         int i;
440
441         if(response->data_count > 0 && response->data != NULL) {
442                 for(i=0 ; i < response->data_count ; i++) {
443                         if(response->data[i] != NULL) {
444                                 free(response->data[i]);
445                                 response->data[i] = NULL;
446                         }
447                 }
448
449                 free(response->data);
450                 response->data_count = 0;
451         }
452
453         if(response->command != NULL) {
454                 free(response->command);
455                 response->command = NULL;
456         }
457
458         if(response->error != NULL) {
459                 free(response->error);
460                 response->error = NULL;
461         }
462 }
463
464 void at_responses_free(struct at_response **responses, int responses_count)
465 {
466         int i;
467
468         for(i=0 ; i < responses_count ; i++) {
469                 at_response_free(responses[i]);
470         }
471 }
472
473 /*
474  * Responses handling
475  */
476
477 void at_responses_handling_init(void)
478 {
479         memset(&at_responses_handling, 0, sizeof(struct at_responses_handling));
480         pthread_mutex_init(&(at_responses_handling.sync_mutex), NULL);
481
482         // First lock
483         AT_SYNC_LOCK();
484         AT_RESPONSES_QUEUE_LOCK();
485 }
486
487 void at_responses_handling_sync_clean(void)
488 {
489         if(at_responses_handling.sync_request != NULL) {
490                 at_request_free(at_responses_handling.sync_request);
491                 at_responses_handling.sync_request = NULL;
492         }
493
494         if(at_responses_handling.sync_response != NULL) {
495                 at_response_free(at_responses_handling.sync_response);
496                 at_responses_handling.sync_response = NULL;
497         }
498 }
499
500 /*
501  * Responses queue
502  */
503
504 void at_responses_queue_unlock(void)
505 {
506         // Only unlock if there are responses available
507         if(at_responses_handling.responses_queue.responses_count > 0 && at_responses_handling.responses_queue.responses != NULL) {
508                 AT_RESPONSES_QUEUE_UNLOCK();
509         }
510 }
511
512 int at_response_queue(struct at_response *response)
513 {
514         struct at_response **responses = NULL;
515         int index;
516         int count;
517
518         if(response == NULL) {
519                 return -1;
520         }
521
522         AT_RESPONSES_LOCK();
523
524         // Index is the request index in the responses array
525         index = at_responses_handling.responses_queue.responses_count;
526         // Count is the total count of responses in the array
527         count = index + 1;
528
529         // Save the previous data pointer
530         responses = at_responses_handling.responses_queue.responses;
531
532         // Alloc the array with the new size
533         at_responses_handling.responses_queue.responses = malloc(sizeof(struct at_response *) * count);
534
535         // Copy and free previous data
536         if(responses != NULL) {
537                 memcpy(at_responses_handling.responses_queue.responses, responses, sizeof(struct at_response *) * at_responses_handling.responses_queue.responses_count);
538                 free(responses);
539         }
540
541         responses = at_responses_handling.responses_queue.responses;
542
543         // Alloc new structure and copy obtained data
544         responses[index] = response;
545
546         at_responses_handling.responses_queue.responses_count = count;
547
548         AT_RESPONSES_UNLOCK();
549
550         return 0;
551 }
552
553 struct at_response *at_response_dequeue(void)
554 {
555         struct at_response *response = NULL;
556         struct at_response **responses = NULL;
557         int responses_count = 0;
558         int pos;
559         int i;
560
561         AT_RESPONSES_LOCK();
562
563         response = NULL;
564         responses = at_responses_handling.responses_queue.responses;
565         responses_count = at_responses_handling.responses_queue.responses_count;
566
567         while(responses_count <= 0 || responses == NULL) {
568                 LOGE("No response queued, blocking!");
569
570                 AT_RESPONSES_UNLOCK();
571                 AT_RESPONSES_QUEUE_LOCK();
572                 AT_RESPONSES_LOCK();
573
574                 responses = at_responses_handling.responses_queue.responses;
575                 responses_count = at_responses_handling.responses_queue.responses_count;
576
577                 LOGE("Unblocking: %d new responses queued!", responses_count);
578         }
579
580         for(i=0 ; i < responses_count ; i++) {
581                 if(responses[i] != NULL) {
582                         response = responses[i];
583                         pos = i;
584                         break;
585                 }
586         }
587
588         if(response == NULL) {
589                 LOGD("Found no valid response, aborting!");
590                 AT_RESPONSES_UNLOCK();
591                 return NULL;
592         }
593
594         responses[pos] = NULL;
595
596         // Move the elements back
597         for(i=pos ; i < responses_count-1 ; i++) {
598                 responses[i] = responses[i+1];
599         }
600
601         // Empty the latest element
602         if(pos != responses_count-1) {
603                 responses[responses_count-1] = NULL;
604         }
605
606         at_responses_handling.responses_queue.responses_count--;
607
608         if(at_responses_handling.responses_queue.responses_count == 0) {
609                 free(responses);
610                 at_responses_handling.responses_queue.responses = NULL;
611         }
612
613         AT_RESPONSES_UNLOCK();
614
615         return response;
616 }
617
618 /*
619  * Expect to func
620  */
621
622 int at_request_expect_to_func_queue(struct at_async_request *request)
623 {
624         struct at_async_request **requests = NULL;
625         int requests_count = 0;
626         int index;
627         int count;
628
629         if(request == NULL)
630                 return -1;
631
632         // Index is the request index in the requests array
633         index = at_responses_handling.async_queue.requests_count;
634         // Count is the total count of requests in the array
635         count = index + 1;
636
637         // Save the previous data pointer
638         requests = at_responses_handling.async_queue.requests;
639         requests_count = at_responses_handling.async_queue.requests_count;
640
641         // Alloc the array with the new size
642         at_responses_handling.async_queue.requests = malloc(sizeof(struct at_async_request *) * count);
643
644         // Copy and free previous data
645         if(requests != NULL) {
646                 memcpy(at_responses_handling.async_queue.requests, requests, sizeof(struct at_async_request *) * requests_count);
647                 free(requests);
648         }
649
650         requests = at_responses_handling.async_queue.requests;
651         requests[index] = request;
652
653         at_responses_handling.async_queue.requests_count = count;
654
655         LOGD("%d elements left in the async queue", at_responses_handling.async_queue.requests_count);
656
657         return 0;
658 }
659
660 void at_request_expect_to_func_dequeue(struct at_async_request *request)
661 {
662         struct at_async_request **requests = NULL;
663         int requests_count = 0;
664         int pos = -1;
665         int i;
666
667         if(request == NULL)
668                 return;
669
670         requests = at_responses_handling.async_queue.requests;
671         requests_count = at_responses_handling.async_queue.requests_count;
672
673         for(i=0 ; i < requests_count ; i++) {
674                 if(requests[i] == request) {
675                         pos = i;
676                         break;
677                 }
678         }
679
680         if(pos == -1) {
681                 LOGD("Found no matching request, aborting dequeue!");
682                 return;
683         }
684
685         requests[pos] = NULL;
686
687         // Move the elements back
688         for(i=pos ; i < requests_count-1 ; i++) {
689                 requests[i] = requests[i+1];
690         }
691
692         // Empty the latest element
693         if(pos != requests_count-1) {
694                 requests[requests_count-1] = NULL;
695         }
696
697         at_responses_handling.async_queue.requests_count--;
698
699         if(at_responses_handling.async_queue.requests_count == 0) {
700                 free(requests);
701                 at_responses_handling.async_queue.requests = NULL;
702         }
703
704         LOGD("%d elements left in the async queue", at_responses_handling.async_queue.requests_count);
705 }
706
707 void at_request_expect_to_func_release(struct at_async_request *request)
708 {
709         if(request == NULL)
710                 return;
711
712         if(request->command != NULL)
713                 free(request->command);
714         if(request->error != NULL)
715                 free(request->error);
716
717         free(request);
718 }
719
720 struct at_async_request *at_request_expect_to_func_find_command(char *command)
721 {
722         struct at_async_request *request = NULL;
723         struct at_async_request **requests = NULL;
724         int requests_count = 0;
725         int rc;
726         int i;
727
728         if(command == NULL)
729                 return NULL;
730
731         AT_ASYNC_LOCK();
732
733         request = NULL;
734         requests = at_responses_handling.async_queue.requests;
735         requests_count = at_responses_handling.async_queue.requests_count;
736
737         if(requests == NULL) {
738                 AT_ASYNC_UNLOCK();
739                 return NULL;
740         }
741
742         for(i=0 ; i < requests_count ; i++) {
743                 if(requests[i] != NULL) {
744                         if(requests[i]->command != NULL) {
745                                 rc = at_commands_compare(command, requests[i]->command);
746                                 if(rc) {
747                                         request = requests[i];
748                                         break;
749                                 }
750                         }
751                 }
752         }
753
754         AT_ASYNC_UNLOCK();
755
756         return request;
757 }
758
759 struct at_async_request *at_request_expect_to_func_find_handled(int handled)
760 {
761         struct at_async_request *request = NULL;
762         struct at_async_request **requests = NULL;
763         int requests_count = 0;
764         int rc;
765         int i;
766
767         AT_ASYNC_LOCK();
768
769         request = NULL;
770         requests = at_responses_handling.async_queue.requests;
771         requests_count = at_responses_handling.async_queue.requests_count;
772
773         if(requests == NULL) {
774                 AT_ASYNC_UNLOCK();
775                 return NULL;
776         }
777
778         for(i=0 ; i < requests_count ; i++) {
779                 if(requests[i] != NULL) {
780                         if(requests[i]->handled == handled) {
781                                 request = requests[i];
782                                 break;
783                         }
784                 }
785         }
786
787         AT_ASYNC_UNLOCK();
788
789         return request;
790 }
791
792 int at_request_expect_to_func(char *command, void *data, RIL_Token t, at_async_request_cb func)
793 {
794         struct at_async_request *request = NULL;
795         int rc;
796
797         if(command == NULL || func == NULL) {
798                 return -1;
799         }
800
801         AT_ASYNC_LOCK();
802
803         // Alloc new structure and copy obtained data
804         request = calloc(1, sizeof(struct at_async_request));
805         request->handled = AT_RESPONSE_WAITING;
806         request->status = AT_STATUS_UNDEF;
807         request->error = NULL;
808         request->command = strdup(command);
809         request->data = data;
810         request->token = t;
811         request->func = func;
812
813         rc = at_request_expect_to_func_queue(request);
814         if(rc < 0) {
815                 LOGE("Failed to queue async request, aborting");
816                 at_request_expect_to_func_release(request);
817         }
818
819         LOGD("Registered async function for command: %s", command);
820
821         AT_ASYNC_UNLOCK();
822
823         return 0;
824 }
825
826 int at_response_expect_to_func(struct at_response *response)
827 {
828         struct at_async_request *request = NULL;
829         int rc;
830
831         if(response == NULL || response->command == NULL)
832                 return -1;
833
834         request = at_request_expect_to_func_find_command(response->command);
835         if(request == NULL || request->func == NULL) {
836                 return -1;
837         }
838
839         LOGD("Found a matching request!");
840
841         // Use status and error from the request (filled after unhandled because of status)
842         if(response->status == AT_STATUS_UNDEF && request->status != AT_STATUS_UNDEF)
843                 response->status = request->status;
844         if(response->error == NULL && request->error != NULL)
845                 response->error = request->error;
846
847         // This prevents sync data not to be reported when the same command is issued in func and previous handled was unhandled for status reason
848         request->handled = AT_RESPONSE_WAITING;
849
850         at_request_expect_to_func_dequeue(request);
851
852         // This must run out of any mutex
853         rc = request->func(response, request->data, request->token);
854
855         // If the request was unhandled, update its status and requeue
856         if(rc == AT_RESPONSE_UNHANDELD_REASON_STATUS) {
857                 LOGD("Response not handled (missing status)");
858                 request->handled = AT_RESPONSE_UNHANDELD_REASON_STATUS;
859                 at_request_expect_to_func_queue(request);
860         } else if(rc == AT_RESPONSE_UNHANDELD_REASON_DATA) {
861                 LOGD("Response not handled (missing data)");
862                 request->handled = AT_RESPONSE_UNHANDELD_REASON_DATA;
863                 at_request_expect_to_func_queue(request);
864         } else {
865                 AT_ASYNC_LOCK();
866                 at_request_expect_to_func_release(request);
867                 AT_ASYNC_UNLOCK();
868         }
869
870         return rc;
871 }
872
873 /*
874  * Expect status
875  */
876
877 void at_response_expect_status_release(void)
878 {
879         AT_SYNC_UNLOCK();
880         at_responses_handling_sync_clean();
881         AT_SYNC_LOCK();
882 }
883
884 int at_request_expect_status(struct at_request *request)
885 {
886         // Register the request
887
888         if(request == NULL)
889                 return -1;
890
891         if(at_responses_handling.sync_request != NULL) {
892                 LOGE("There is already an AT sync request waiting, aborting!");
893                 return -1;
894         }
895
896         if(request->command == NULL) {
897                 LOGE("No command was given, aborting!");
898                 return -1;
899         }
900
901         at_responses_handling.sync_request = request;
902
903         return 0;
904 }
905
906 int at_response_expect_status(struct at_response *response)
907 {
908         struct at_async_request *request = NULL;
909         int rc;
910
911         if(response == NULL)
912                 return -1;
913
914         // If there is no request waiting for a status
915         if(at_responses_handling.sync_request == NULL && at_request_expect_to_func_find_handled(AT_RESPONSE_UNHANDELD_REASON_STATUS) == NULL)
916                 return -1;
917
918         // If we get an unsol response while we expect a status, there is something going wrong
919         if(response->command != NULL && at_responses_handling.sync_request != NULL && at_responses_handling.sync_request->command != NULL) {
920                 rc = at_commands_compare(response->command, at_responses_handling.sync_request->command);
921                 if(!rc) {
922                         // Only unlock is there is no async request waiting with this command (if it is unsol)!
923                         if(at_request_expect_to_func_find_command(response->command) == NULL) {
924                                 AT_SYNC_UNLOCK();
925                         }
926
927                         return -1;
928                 }
929         }
930
931         if(response->status == AT_STATUS_UNDEF && at_responses_handling.sync_request != NULL && at_responses_handling.sync_request->command != NULL) {
932                 if((response->data == NULL || response->data_count <= 0) && response->command != NULL) {
933                         rc = at_commands_compare(response->command, at_responses_handling.sync_request->command);
934                         if(rc) {
935                                 // Command is the one we expect, but there is no status nor data, so just skip it
936                                 LOGD("Skipping matching request with no status nor data");
937                                 at_response_free(response);
938                                 return 0;
939                         }
940                 }
941
942                 // Only unlock if there is a status and command differs
943                 return -1;
944         }
945
946         if(response->command == NULL) {
947                 // If there is an async response that was unhandled because it lacked status, fill it
948                 request = at_request_expect_to_func_find_handled(AT_RESPONSE_UNHANDELD_REASON_STATUS);
949                 if(request != NULL) {
950                         LOGD("Found an async function that needs a status!");
951
952                         request->status = response->status;
953                         if(response->error != NULL)
954                                 request->error = strdup(response->error);
955                         request->handled = AT_RESPONSE_WAITING;
956
957                         if(request->command != NULL)
958                                 response->command = strdup(request->command);
959
960                         return -1;
961                 }
962         }
963
964         if(at_responses_handling.sync_request == NULL)
965                 return -1;
966
967         at_responses_handling.sync_response = response;
968
969         AT_SYNC_UNLOCK();
970
971         return 0;
972 }
973
974 int at_expect_status(struct at_request *request)
975 {
976         int rc;
977
978         if(request == NULL)
979                 return -1;
980
981         if(at_responses_handling.sync_response == NULL) {
982                 LOGD("Blocking for sync response");
983
984                 // Second lock: block until sync_response is there
985                 AT_SYNC_LOCK();
986         }
987
988         if(at_responses_handling.sync_response == NULL)
989                 return -1;
990
991         if(at_responses_handling.sync_response->command != NULL) {
992                 rc = at_commands_compare(at_responses_handling.sync_response->command, request->command);
993                 if(!rc) {
994                         LOGE("Obtained command doesn't match, aborting!");
995                         return -1;
996                 }
997         }
998
999         LOGD("Found matching sync response");
1000
1001         request->status = at_responses_handling.sync_response->status;
1002         if(at_responses_handling.sync_response->error != NULL)
1003                 request->error = strdup(at_responses_handling.sync_response->error);
1004
1005         return 0;
1006 }
1007
1008 /*
1009  * Request
1010  */
1011
1012 int at_request_send(struct at_request *request)
1013 {
1014         char *string = NULL;
1015         int length = 0;
1016
1017         int offset_separator_begin = 0;
1018         int length_separator_begin = 0;
1019         int offset_command = 0;
1020         int length_command = 0;
1021         int offset_data_separator = 0;
1022         int length_data_separator = 0;
1023         int offset_data = 0;
1024         int length_data = 0;
1025         int offset_separator_end = 0;
1026         int length_separator_end = 0;
1027
1028         int i, p;
1029
1030         // TODO: Do we send \r\n or only \r, begining/end or just end?
1031         char separator[] = "\r\n";
1032         char data_separator[] = "=";
1033
1034         if(request->command == NULL)
1035                 return -1;
1036
1037         offset_separator_begin = 0;
1038         length_separator_begin = strlen(separator);
1039         length += length_separator_begin;
1040
1041         offset_command = length;
1042         length_command = strlen(request->command);
1043         length += length_command;
1044
1045         if(request->data != NULL) {
1046                 offset_data_separator = length;
1047                 length_data_separator = strlen(data_separator);
1048                 length += length_data_separator;
1049
1050                 offset_data = length;
1051                 length_data = strlen(request->data);
1052                 length += length_data;
1053         }
1054
1055         offset_separator_end = length;
1056         length_separator_end = strlen(separator);
1057         length += length_separator_end;
1058
1059         // Alloc final string
1060         string = calloc(1, length);
1061
1062         // Copy the data to the string
1063         memcpy(string + offset_separator_begin, separator, length_separator_begin);
1064         memcpy(string + offset_command, request->command, length_command);
1065         if(request->data != NULL) {
1066                 memcpy(string + offset_data_separator, data_separator, length_data_separator);
1067                 memcpy(string + offset_data, request->data, length_data);
1068         }
1069         memcpy(string + offset_separator_end, separator, length_separator_end);
1070
1071         // Log request
1072         RIL_LOG_LOCK();
1073         ril_data_log(string, length);
1074         ril_send_log(request);
1075         RIL_LOG_UNLOCK();
1076
1077         ril_device_send(ril_device, string, length);
1078
1079         free(string);
1080
1081         return 0;
1082 }
1083
1084 struct at_request *at_request_create(char *command, char *data)
1085 {
1086         struct at_request *request = NULL;
1087         int i;
1088
1089         if(command == NULL)
1090                 return NULL;
1091
1092         request = calloc(1, sizeof(struct at_request));
1093
1094         asprintf(&(request->command), "%s", command);
1095
1096         if(data != NULL) {
1097                 asprintf(&(request->data), "%s", data);
1098         }
1099
1100         return request;
1101 }
1102
1103 void at_request_free(struct at_request *request)
1104 {
1105         int i;
1106
1107         if(request->command != NULL)
1108                 free(request->command);
1109
1110         if(request->data != NULL)
1111                 free(request->data);
1112
1113         if(request->error != NULL)
1114                 free(request->error);
1115 }
1116
1117 /*
1118  * Send
1119  */
1120
1121 int at_send(char *command, char *data)
1122 {
1123         struct at_request *request = NULL;
1124         int rc;
1125
1126         request = at_request_create(command, data);
1127         if(request == NULL) {
1128                 LOGE("Unable to create request, aborting!");
1129                 return -1;
1130         }
1131
1132         rc = at_request_send(request);
1133         if(rc < 0) {
1134                 LOGE("Unable to send request, aborting!");
1135                 at_request_free(request);
1136                 return -1;
1137         }
1138
1139         at_request_free(request);
1140
1141         return 0;
1142 }
1143
1144 int at_send_command(char *command)
1145 {
1146         return at_send(command, NULL);
1147 }
1148
1149 int at_send_expect_status(char *command, char *data)
1150 {
1151         struct at_request *request = NULL;
1152         int tries;
1153         int status;
1154         int rc;
1155         int i;
1156
1157         if(command == NULL)
1158                 return -1;
1159
1160         request = at_request_create(command, data);
1161         if(request == NULL) {
1162                 LOGE("Unable to create request, aborting!");
1163                 return AT_STATUS_INTERNAL_ERROR;
1164         }
1165
1166         // Try to register request 5 times, during 5 * 1s
1167         for(i=5 ; i > 0 ; i--) {
1168                 rc = at_request_expect_status(request);
1169                 if(rc < 0) {
1170                         LOGE("Unable to request expect status, retrying!");
1171                         sleep(1);
1172                 } else {
1173                         break;
1174                 }
1175         }
1176         if(rc < 0) {
1177                 LOGE("Unable to request expect status, aborting!");
1178                 at_request_free(request);
1179                 return AT_STATUS_INTERNAL_ERROR;
1180         }
1181
1182         rc = at_request_send(request);
1183         if(rc < 0) {
1184                 LOGE("Unable to send request, aborting!");
1185                 at_response_expect_status_release();
1186                 return AT_STATUS_INTERNAL_ERROR;
1187         }
1188
1189         // Block here
1190         rc = at_expect_status(request);
1191         if(rc < 0) {
1192                 LOGE("Unable to get expected status, aborting!");
1193                 at_response_expect_status_release();
1194                 return AT_STATUS_INTERNAL_ERROR;
1195         }
1196
1197         status = request->status;
1198
1199         // Release sync structures and lock the mutex
1200         at_response_expect_status_release();
1201
1202         return status;
1203 }
1204
1205 int at_send_expect_to_func(char *command, char *data, void *pdata, RIL_Token t, at_async_request_cb func)
1206 {
1207         struct at_request *request = NULL;
1208         int rc;
1209
1210         if(command == NULL)
1211                 return -1;
1212
1213         request = at_request_create(command, data);
1214         if(request == NULL) {
1215                 LOGE("Unable to create request, aborting!");
1216                 return -1;
1217         }
1218
1219         rc = at_request_expect_to_func(command, pdata, t, func);
1220         if(rc < 0) {
1221                 LOGE("Unable to request expect to func, aborting!");
1222                 at_request_free(request);
1223         }
1224
1225         rc = at_request_send(request);
1226         if(rc < 0) {
1227                 LOGE("Unable to send request, aborting!");
1228                 at_request_free(request);
1229                 return -1;
1230         }
1231
1232         return 0;
1233 }