AT: Various code fixes, new async handled code, spare status/error handling
[hayes-ril.git] / hayes-ril.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 #define LOG_TAG "RIL"
20 #include <utils/Log.h>
21 #include <telephony/ril.h>
22
23 #include <hayes-ril.h>
24
25 #define RIL_VERSION_STRING "Hayes RIL"
26
27 struct ril_device *ril_device;
28 struct ril_globals ril_globals;
29
30 struct ril_dispatch_unsol ril_dispatch_unsol[] = {};
31
32 const char *ril_get_version(void)
33 {
34         return RIL_VERSION_STRING;
35 }
36
37 static const RIL_RadioFunctions ril_ops = {
38         RIL_VERSION,
39         NULL,
40         NULL,
41         NULL,
42         NULL,
43         ril_get_version
44 };
45
46 void *ril_dispatch(void *data)
47 {
48         struct at_response *response = NULL;
49         int rc;
50         int i, j;
51
52         for(i = 5 ; i > 0 ; i--) {
53                 while(1) {
54                         response = at_response_dequeue();
55                         if(response == NULL)
56                                 break;
57
58                         if(response->command == NULL) {
59                                 at_response_free(response);
60                                 continue;
61                         }
62
63                         // Dequeue works now
64                         if(i != 5)
65                                 i = 5;
66
67                         rc = at_response_expect_to_func(response);
68                         if(rc < 0) {
69                                 for(j=0 ; j < ril_globals.dispatch_unsol_count ; j++) {
70                                         if(at_commands_compare(response->command, ril_globals.dispatch_unsol[j].command) && ril_globals.dispatch_unsol[j].func != NULL) {
71                                                 ril_globals.dispatch_unsol[j].func(response);
72                                         }
73                                 }
74                         }
75
76                         at_response_free(response);
77                 }
78
79                 LOGE("RIL dispatch failed, retrying!");
80         }
81
82         LOGE("RIL dispatch failed too many times, aborting");
83
84         return NULL;
85 }
86
87 int ril_dispatch_thread_start(void)
88 {
89         pthread_attr_t attr;
90         int rc;
91
92         pthread_attr_init(&attr);
93         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
94
95         rc = pthread_create(&ril_globals.dispatch_thread, &attr, ril_dispatch, NULL);
96         if(rc != 0) {
97                 LOGE("Creating dispatch thread failed!");
98                 return -1;
99         }
100
101         return 0;
102 }
103
104 void ril_globals_init(void)
105 {
106         memset(&ril_globals, 0, sizeof(struct ril_globals));
107         ril_globals.dispatch_unsol = &ril_dispatch_unsol;
108         ril_globals.dispatch_unsol_count = sizeof(ril_dispatch_unsol) / sizeof(struct ril_dispatch_unsol);
109
110         LOGE("Registered %d unsol requests handlers", ril_globals.dispatch_unsol_count);
111
112         at_responses_handling_init();
113 }
114
115 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
116 {
117         int rc;
118
119         ril_globals_init();
120         ril_device_register(&ril_device);
121
122         LOGD("Starting %s for device: %s", RIL_VERSION_STRING, ril_device->name);
123
124         rc = ril_device_init(ril_device);
125         if(rc < 0) {
126                 LOGE("Failed to init device!");
127                 ril_device_deinit(ril_device);
128
129                 return NULL;
130         }
131
132         rc = ril_device_recv_thread_start(ril_device);
133         if(rc < 0) {
134                 LOGE("Failed to start device thread!");
135                 ril_device_deinit(ril_device);
136
137                 return NULL;
138         }
139
140         rc = ril_dispatch_thread_start();
141         if(rc < 0) {
142                 LOGE("Failed to start dispatch thread!");
143                 ril_device_deinit(ril_device);
144
145                 return NULL;
146         }
147
148         LOGD("Initialization complete");
149
150         return &ril_ops;
151 }