7a02458201deaeb8d8ce58e5eca2438cbaf2809c
[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 void at_responses_queue_unlock(void)
494 {
495         // Only unlock if there are responses available
496         if(at_responses_handling.responses_queue.responses_count > 0 && at_responses_handling.responses_queue.responses != NULL) {
497                 AT_RESPONSES_QUEUE_UNLOCK();
498         }
499 }
500
501 int at_response_queue(struct at_response *response)
502 {
503         struct at_response **responses = NULL;
504         int index;
505         int count;
506
507         if(response == NULL) {
508                 return -1;
509         }
510
511         AT_RESPONSES_LOCK();
512
513         // Index is the request index in the responses array
514         index = at_responses_handling.responses_queue.responses_count;
515         // Count is the total count of responses in the array
516         count = index + 1;
517
518         // Save the previous data pointer
519         responses = at_responses_handling.responses_queue.responses;
520
521         // Alloc the array with the new size
522         at_responses_handling.responses_queue.responses = malloc(sizeof(struct at_response *) * count);
523
524         // Copy and free previous data
525         if(responses != NULL) {
526                 memcpy(at_responses_handling.responses_queue.responses, responses, sizeof(struct at_response *) * at_responses_handling.responses_queue.responses_count);
527                 free(responses);
528         }
529
530         responses = at_responses_handling.responses_queue.responses;
531
532         // Alloc new structure and copy obtained data
533         responses[index] = response;
534
535         at_responses_handling.responses_queue.responses_count = count;
536
537         AT_RESPONSES_UNLOCK();
538
539         return 0;
540 }
541
542 struct at_response *at_response_dequeue(void)
543 {
544         struct at_response *response = NULL;
545         struct at_response **responses = NULL;
546         int responses_count = 0;
547         int pos;
548         int i;
549
550         AT_RESPONSES_LOCK();
551
552         response = NULL;
553         responses = at_responses_handling.responses_queue.responses;
554         responses_count = at_responses_handling.responses_queue.responses_count;
555
556         while(responses_count <= 0 || responses == NULL) {
557                 LOGE("No response queued, blocking!");
558
559                 AT_RESPONSES_UNLOCK();
560                 AT_RESPONSES_QUEUE_LOCK();
561                 AT_RESPONSES_LOCK();
562
563                 responses = at_responses_handling.responses_queue.responses;
564                 responses_count = at_responses_handling.responses_queue.responses_count;
565
566                 LOGE("Unblocking: %d new responses queued!", responses_count);
567         }
568
569         for(i=0 ; i < responses_count ; i++) {
570                 if(responses[i] != NULL) {
571                         response = responses[i];
572                         pos = i;
573                         break;
574                 }
575         }
576
577         if(response == NULL) {
578                 LOGD("Found no valid response, aborting!");
579                 AT_RESPONSES_UNLOCK();
580                 return NULL;
581         }
582
583         responses[pos] = NULL;
584
585         // Move the elements back
586         for(i=pos ; i < responses_count-1 ; i++) {
587                 responses[i] = responses[i+1];
588         }
589
590         // Empty the latest element
591         if(pos != responses_count-1) {
592                 responses[responses_count-1] = NULL;
593         }
594
595         at_responses_handling.responses_queue.responses_count--;
596
597         if(at_responses_handling.responses_queue.responses_count == 0) {
598                 free(responses);
599                 at_responses_handling.responses_queue.responses = NULL;
600         }
601
602         AT_RESPONSES_UNLOCK();
603
604         return response;
605 }
606
607 /*
608  * Expect to func
609  */
610
611 int at_request_expect_to_func_queue(struct at_async_request *request)
612 {
613         struct at_async_request **requests = NULL;
614         int requests_count = 0;
615         int index;
616         int count;
617
618         if(request == NULL)
619                 return -1;
620
621         // Index is the request index in the requests array
622         index = at_responses_handling.async_queue.requests_count;
623         // Count is the total count of requests in the array
624         count = index + 1;
625
626         // Save the previous data pointer
627         requests = at_responses_handling.async_queue.requests;
628         requests_count = at_responses_handling.async_queue.requests_count;
629
630         // Alloc the array with the new size
631         at_responses_handling.async_queue.requests = malloc(sizeof(struct at_async_request *) * count);
632
633         // Copy and free previous data
634         if(requests != NULL) {
635                 memcpy(at_responses_handling.async_queue.requests, requests, sizeof(struct at_async_request *) * requests_count);
636                 free(requests);
637         }
638
639         requests = at_responses_handling.async_queue.requests;
640         requests[index] = request;
641
642         at_responses_handling.async_queue.requests_count = count;
643
644         LOGD("%d elements left in the async queue", at_responses_handling.async_queue.requests_count);
645
646         return 0;
647 }
648
649 void at_request_expect_to_func_dequeue(struct at_async_request *request)
650 {
651         struct at_async_request **requests = NULL;
652         int requests_count = 0;
653         int pos = -1;
654         int i;
655
656         if(request == NULL)
657                 return;
658
659         requests = at_responses_handling.async_queue.requests;
660         requests_count = at_responses_handling.async_queue.requests_count;
661
662         for(i=0 ; i < requests_count ; i++) {
663                 if(requests[i] == request) {
664                         pos = i;
665                         break;
666                 }
667         }
668
669         if(pos == -1) {
670                 LOGD("Found no matching request, aborting dequeue!");
671                 return;
672         }
673
674         requests[pos] = NULL;
675
676         // Move the elements back
677         for(i=pos ; i < requests_count-1 ; i++) {
678                 requests[i] = requests[i+1];
679         }
680
681         // Empty the latest element
682         if(pos != requests_count-1) {
683                 requests[requests_count-1] = NULL;
684         }
685
686         at_responses_handling.async_queue.requests_count--;
687
688         if(at_responses_handling.async_queue.requests_count == 0) {
689                 free(requests);
690                 at_responses_handling.async_queue.requests = NULL;
691         }
692
693         LOGD("%d elements left in the async queue", at_responses_handling.async_queue.requests_count);
694 }
695
696 void at_request_expect_to_func_release(struct at_async_request *request)
697 {
698         if(request == NULL)
699                 return;
700
701         if(request->command != NULL)
702                 free(request->command);
703         if(request->error != NULL)
704                 free(request->error);
705
706         free(request);
707 }
708
709 struct at_async_request *at_request_expect_to_func_find_command(char *command)
710 {
711         struct at_async_request *request = NULL;
712         struct at_async_request **requests = NULL;
713         int requests_count = 0;
714         int rc;
715         int i;
716
717         if(command == NULL)
718                 return NULL;
719
720         AT_ASYNC_LOCK();
721
722         request = NULL;
723         requests = at_responses_handling.async_queue.requests;
724         requests_count = at_responses_handling.async_queue.requests_count;
725
726         if(requests == NULL) {
727                 AT_ASYNC_UNLOCK();
728                 return NULL;
729         }
730
731         for(i=0 ; i < requests_count ; i++) {
732                 if(requests[i] != NULL) {
733                         if(requests[i]->command != NULL) {
734                                 rc = at_commands_compare(command, requests[i]->command);
735                                 if(rc) {
736                                         request = requests[i];
737                                         break;
738                                 }
739                         }
740                 }
741         }
742
743         AT_ASYNC_UNLOCK();
744
745         return request;
746 }
747
748 struct at_async_request *at_request_expect_to_func_find_handled(int handled)
749 {
750         struct at_async_request *request = NULL;
751         struct at_async_request **requests = NULL;
752         int requests_count = 0;
753         int rc;
754         int i;
755
756         AT_ASYNC_LOCK();
757
758         request = NULL;
759         requests = at_responses_handling.async_queue.requests;
760         requests_count = at_responses_handling.async_queue.requests_count;
761
762         if(requests == NULL) {
763                 AT_ASYNC_UNLOCK();
764                 return NULL;
765         }
766
767         for(i=0 ; i < requests_count ; i++) {
768                 if(requests[i] != NULL) {
769                         if(requests[i]->handled == handled) {
770                                 request = requests[i];
771                                 break;
772                         }
773                 }
774         }
775
776         AT_ASYNC_UNLOCK();
777
778         return request;
779 }
780
781 int at_request_expect_to_func(char *command, void *data, RIL_Token t, at_async_request_cb func)
782 {
783         struct at_async_request *request = NULL;
784         int rc;
785
786         if(command == NULL || func == NULL) {
787                 return -1;
788         }
789
790         AT_ASYNC_LOCK();
791
792         // Alloc new structure and copy obtained data
793         request = calloc(1, sizeof(struct at_async_request));
794         request->handled = AT_RESPONSE_WAITING;
795         request->status = AT_STATUS_UNDEF;
796         request->error = NULL;
797         request->command = strdup(command);
798         request->data = data;
799         request->token = t;
800         request->func = func;
801
802         rc = at_request_expect_to_func_queue(request);
803         if(rc < 0) {
804                 LOGE("Failed to queue async request, aborting");
805                 at_request_expect_to_func_release(request);
806         }
807
808         LOGD("Registered async function for command: %s", command);
809
810         AT_ASYNC_UNLOCK();
811
812         return 0;
813 }
814
815 int at_response_expect_to_func(struct at_response *response)
816 {
817         struct at_async_request *request = NULL;
818         int rc;
819
820         if(response == NULL || response->command == NULL)
821                 return -1;
822
823         request = at_request_expect_to_func_find_command(response->command);
824         if(request == NULL || request->func == NULL) {
825                 return -1;
826         }
827
828         LOGD("Found a matching request!");
829
830         // Use status and error from the request (filled after unhandled because of status)
831         if(response->status == AT_STATUS_UNDEF && request->status != AT_STATUS_UNDEF)
832                 response->status = request->status;
833         if(response->error == NULL && request->error != NULL)
834                 response->error = request->error;
835
836         // This prevents sync data not to be reported when the same command is issued in func and previous handled was unhandled for status reason
837         request->handled = AT_RESPONSE_WAITING;
838
839         at_request_expect_to_func_dequeue(request);
840
841         // This must run out of any mutex
842         rc = request->func(response, request->data, request->token);
843
844         // If the request was unhandled, update its status and requeue
845         if(rc == AT_RESPONSE_UNHANDELD_REASON_STATUS) {
846                 LOGD("Response not handled (missing status)");
847                 request->handled = AT_RESPONSE_UNHANDELD_REASON_STATUS;
848                 at_request_expect_to_func_queue(request);
849         } else if(rc == AT_RESPONSE_UNHANDELD_REASON_DATA) {
850                 LOGD("Response not handled (missing data)");
851                 request->handled = AT_RESPONSE_UNHANDELD_REASON_DATA;
852                 at_request_expect_to_func_queue(request);
853         } else {
854                 AT_ASYNC_LOCK();
855                 at_request_expect_to_func_release(request);
856                 AT_ASYNC_UNLOCK();
857         }
858
859         return rc;
860 }
861
862 /*
863  * Expect status
864  */
865
866 void at_response_expect_status_release(void)
867 {
868         AT_SYNC_UNLOCK();
869         at_responses_handling_sync_clean();
870         AT_SYNC_LOCK();
871 }
872
873 int at_request_expect_status(struct at_request *request)
874 {
875         // Register the request
876
877         if(request == NULL)
878                 return -1;
879
880         if(at_responses_handling.sync_request != NULL) {
881                 LOGE("There is already an AT sync request waiting, aborting!");
882                 return -1;
883         }
884
885         if(request->command == NULL) {
886                 LOGE("No command was given, aborting!");
887                 return -1;
888         }
889
890         at_responses_handling.sync_request = request;
891
892         return 0;
893 }
894
895 int at_response_expect_status(struct at_response *response)
896 {
897         struct at_async_request *request = NULL;
898         int rc;
899
900         if(response == NULL)
901                 return -1;
902
903         // If there is no request waiting for a status
904         if(at_responses_handling.sync_request == NULL && at_request_expect_to_func_find_handled(AT_RESPONSE_UNHANDELD_REASON_STATUS) == NULL)
905                 return -1;
906
907         // If we get an unsol response while we expect a status, there is something going wrong
908         if(response->command != NULL && at_responses_handling.sync_request != NULL && at_responses_handling.sync_request->command != NULL) {
909                 rc = at_commands_compare(response->command, at_responses_handling.sync_request->command);
910                 if(!rc) {
911                         // Only unlock is there is no async request waiting with this command (if it is unsol)!
912                         if(at_request_expect_to_func_find_command(response->command) == NULL) {
913                                 AT_SYNC_UNLOCK();
914                         }
915
916                         return -1;
917                 }
918         }
919
920         if(response->status == AT_STATUS_UNDEF && at_responses_handling.sync_request != NULL && at_responses_handling.sync_request->command != NULL) {
921                 if((response->data == NULL || response->data_count <= 0) && response->command != NULL) {
922                         rc = at_commands_compare(response->command, at_responses_handling.sync_request->command);
923                         if(rc) {
924                                 // Command is the one we expect, but there is no status nor data, so just skip it
925                                 LOGD("Skipping matching request with no status nor data");
926                                 at_response_free(response);
927                                 return 0;
928                         }
929                 }
930
931                 // Only unlock if there is a status and command differs
932                 return -1;
933         }
934
935         if(response->command == NULL) {
936                 // If there is an async response that was unhandled because it lacked status, fill it
937                 request = at_request_expect_to_func_find_handled(AT_RESPONSE_UNHANDELD_REASON_STATUS);
938                 if(request != NULL) {
939                         LOGD("Found an async function that needs a status!");
940
941                         request->status = response->status;
942                         if(response->error != NULL)
943                                 request->error = strdup(response->error);
944                         request->handled = AT_RESPONSE_WAITING;
945
946                         if(request->command != NULL)
947                                 response->command = strdup(request->command);
948
949                         return -1;
950                 }
951         }
952
953         if(at_responses_handling.sync_request == NULL)
954                 return -1;
955
956         at_responses_handling.sync_response = response;
957
958         AT_SYNC_UNLOCK();
959
960         return 0;
961 }
962
963 int at_expect_status(struct at_request *request)
964 {
965         int rc;
966
967         if(request == NULL)
968                 return -1;
969
970         if(at_responses_handling.sync_response == NULL) {
971                 LOGD("Blocking for sync response");
972
973                 // Second lock: block until sync_response is there
974                 AT_SYNC_LOCK();
975         }
976
977         if(at_responses_handling.sync_response == NULL)
978                 return -1;
979
980         if(at_responses_handling.sync_response->command != NULL) {
981                 rc = at_commands_compare(at_responses_handling.sync_response->command, request->command);
982                 if(!rc) {
983                         LOGE("Obtained command doesn't match, aborting!");
984                         return -1;
985                 }
986         }
987
988         LOGD("Found matching sync response");
989
990         request->status = at_responses_handling.sync_response->status;
991         if(at_responses_handling.sync_response->error != NULL)
992                 request->error = strdup(at_responses_handling.sync_response->error);
993
994         return 0;
995 }
996
997 /*
998  * Request
999  */
1000
1001 int at_request_send(struct at_request *request)
1002 {
1003         char *string = NULL;
1004         int length = 0;
1005
1006         int offset_separator_begin = 0;
1007         int length_separator_begin = 0;
1008         int offset_command = 0;
1009         int length_command = 0;
1010         int offset_data_separator = 0;
1011         int length_data_separator = 0;
1012         int offset_data = 0;
1013         int length_data = 0;
1014         int offset_separator_end = 0;
1015         int length_separator_end = 0;
1016
1017         int i, p;
1018
1019         // TODO: Do we send \r\n or only \r, begining/end or just end?
1020         char separator[] = "\r\n";
1021         char data_separator[] = "=";
1022
1023         if(request->command == NULL)
1024                 return -1;
1025
1026         offset_separator_begin = 0;
1027         length_separator_begin = strlen(separator);
1028         length += length_separator_begin;
1029
1030         offset_command = length;
1031         length_command = strlen(request->command);
1032         length += length_command;
1033
1034         if(request->data != NULL) {
1035                 offset_data_separator = length;
1036                 length_data_separator = strlen(data_separator);
1037                 length += length_data_separator;
1038
1039                 offset_data = length;
1040                 length_data = strlen(request->data);
1041                 length += length_data;
1042         }
1043
1044         offset_separator_end = length;
1045         length_separator_end = strlen(separator);
1046         length += length_separator_end;
1047
1048         // Alloc final string
1049         string = calloc(1, length);
1050
1051         // Copy the data to the string
1052         memcpy(string + offset_separator_begin, separator, length_separator_begin);
1053         memcpy(string + offset_command, request->command, length_command);
1054         if(request->data != NULL) {
1055                 memcpy(string + offset_data_separator, data_separator, length_data_separator);
1056                 memcpy(string + offset_data, request->data, length_data);
1057         }
1058         memcpy(string + offset_separator_end, separator, length_separator_end);
1059
1060         // Log request
1061         RIL_LOG_LOCK();
1062         ril_data_log(string, length);
1063         ril_send_log(request);
1064         RIL_LOG_UNLOCK();
1065
1066         ril_device_send(ril_device, string, length);
1067
1068         free(string);
1069
1070         return 0;
1071 }
1072
1073 struct at_request *at_request_create(char *command, char *data)
1074 {
1075         struct at_request *request = NULL;
1076         int i;
1077
1078         if(command == NULL)
1079                 return NULL;
1080
1081         request = calloc(1, sizeof(struct at_request));
1082
1083         asprintf(&(request->command), "%s", command);
1084
1085         if(data != NULL) {
1086                 asprintf(&(request->data), "%s", data);
1087         }
1088
1089         return request;
1090 }
1091
1092 void at_request_free(struct at_request *request)
1093 {
1094         int i;
1095
1096         if(request->command != NULL)
1097                 free(request->command);
1098
1099         if(request->data != NULL)
1100                 free(request->data);
1101
1102         if(request->error != NULL)
1103                 free(request->error);
1104 }
1105
1106 /*
1107  * Send
1108  */
1109
1110 int at_send(char *command, char *data)
1111 {
1112         struct at_request *request = NULL;
1113         int rc;
1114
1115         request = at_request_create(command, data);
1116         if(request == NULL) {
1117                 LOGE("Unable to create request, aborting!");
1118                 return -1;
1119         }
1120
1121         rc = at_request_send(request);
1122         if(rc < 0) {
1123                 LOGE("Unable to send request, aborting!");
1124                 at_request_free(request);
1125                 return -1;
1126         }
1127
1128         at_request_free(request);
1129
1130         return 0;
1131 }
1132
1133 int at_send_command(char *command)
1134 {
1135         return at_send(command, NULL);
1136 }
1137
1138 int at_send_expect_status(char *command, char *data)
1139 {
1140         struct at_request *request = NULL;
1141         int tries;
1142         int status;
1143         int rc;
1144         int i;
1145
1146         if(command == NULL)
1147                 return -1;
1148
1149         request = at_request_create(command, data);
1150         if(request == NULL) {
1151                 LOGE("Unable to create request, aborting!");
1152                 return AT_STATUS_INTERNAL_ERROR;
1153         }
1154
1155         // Try to register request 5 times, during 5 * 1s
1156         for(i=5 ; i > 0 ; i--) {
1157                 rc = at_request_expect_status(request);
1158                 if(rc < 0) {
1159                         LOGE("Unable to request expect status, retrying!");
1160                         sleep(1);
1161                 } else {
1162                         break;
1163                 }
1164         }
1165         if(rc < 0) {
1166                 LOGE("Unable to request expect status, aborting!");
1167                 at_request_free(request);
1168                 return AT_STATUS_INTERNAL_ERROR;
1169         }
1170
1171         rc = at_request_send(request);
1172         if(rc < 0) {
1173                 LOGE("Unable to send request, aborting!");
1174                 at_response_expect_status_release();
1175                 return AT_STATUS_INTERNAL_ERROR;
1176         }
1177
1178         // Block here
1179         rc = at_expect_status(request);
1180         if(rc < 0) {
1181                 LOGE("Unable to get expected status, aborting!");
1182                 at_response_expect_status_release();
1183                 return AT_STATUS_INTERNAL_ERROR;
1184         }
1185
1186         status = request->status;
1187
1188         // Release sync structures and lock the mutex
1189         at_response_expect_status_release();
1190
1191         return status;
1192 }
1193
1194 int at_send_expect_to_func(char *command, char *data, void *pdata, RIL_Token t, at_async_request_cb func)
1195 {
1196         struct at_request *request = NULL;
1197         int rc;
1198
1199         if(command == NULL)
1200                 return -1;
1201
1202         request = at_request_create(command, data);
1203         if(request == NULL) {
1204                 LOGE("Unable to create request, aborting!");
1205                 return -1;
1206         }
1207
1208         rc = at_request_expect_to_func(command, pdata, t, func);
1209         if(rc < 0) {
1210                 LOGE("Unable to request expect to func, aborting!");
1211                 at_request_free(request);
1212         }
1213
1214         rc = at_request_send(request);
1215         if(rc < 0) {
1216                 LOGE("Unable to send request, aborting!");
1217                 at_request_free(request);
1218                 return -1;
1219         }
1220
1221         return 0;
1222 }