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