Device: Added AT handlers
[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         { "AT+CREG",    at_creg_unexpect },
32         { "NO CARRIER", no_carrier_unexpect },
33         { "AT+CRING",   at_cring }
34 };
35
36 void ril_on_request(int request, void *data, size_t length, RIL_Token t)
37 {
38         switch(request) {
39                 // Power
40                 case RIL_REQUEST_RADIO_POWER:
41                         ril_request_radio_power(t, data, length);
42                         break;
43                 // SIM
44                 case RIL_REQUEST_GET_SIM_STATUS:
45                         ril_request_get_sim_status(t, data, length);
46                         break;
47                 case RIL_REQUEST_ENTER_SIM_PIN:
48                         ril_request_enter_sim_pin(t, data, length);
49                         break;
50                 case RIL_REQUEST_SIM_IO:
51                         ril_request_sim_io(t, data, length);
52                         break;
53                 // Network
54                 case RIL_REQUEST_SIGNAL_STRENGTH:
55                         ril_request_signal_strength(t, data, length);
56                         break;
57                 case RIL_REQUEST_REGISTRATION_STATE:
58                         ril_request_registration_state(t, data, length);
59                         break;
60                 case RIL_REQUEST_OPERATOR:
61                         ril_request_operator(t, data, length);
62                         break;
63                 // Call
64                 case RIL_REQUEST_GET_CURRENT_CALLS:
65                         ril_request_get_current_calls(t, data, length);
66                         break;
67                 case RIL_REQUEST_DIAL:
68                         ril_request_dial(t, data, length);
69                         break;
70                 case RIL_REQUEST_ANSWER:        
71                         ril_request_anwswer(t, data, length);
72                         break;
73                 case RIL_REQUEST_HANGUP:
74                         ril_request_hangup(t, data, length);
75                         break;
76                 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
77                         ril_request_hangup_waiting_or_background(t, data, length);
78                         break;
79                 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
80                         ril_request_hangup_foreground_resume_background(t, data, length);
81                         break;
82                 case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
83                         ril_request_switch_waiting_or_holding_and_active(t, data, length);
84                         break;
85                 default:
86                         LOGE("Request not implemented: %d\n", request);
87                         RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
88                         break;
89         }
90 }
91
92 const char *ril_get_version(void)
93 {
94         return RIL_VERSION_STRING;
95 }
96
97 RIL_RadioState ril_on_state_request(void)
98 {
99         LOGD("State request");
100         return ril_globals.radio_state;
101 }
102
103 int ril_on_supports(int requestCode)
104 {
105         return 1;
106 }
107
108 void ril_on_cancel(RIL_Token t)
109 {
110         return;
111 }
112
113 static const RIL_RadioFunctions ril_ops = {
114         RIL_VERSION,
115         ril_on_request,
116         ril_on_state_request,
117         ril_on_supports,
118         ril_on_cancel,
119         ril_get_version
120 };
121
122 void *ril_dispatch(void *data)
123 {
124         struct at_response *response = NULL;
125         int rc;
126         int i, j;
127
128         for(i = 5 ; i > 0 ; i--) {
129                 while(1) {
130                         response = at_response_dequeue();
131                         if(response == NULL)
132                                 break;
133
134                         // Dequeue works now
135                         if(i != 5)
136                                 i = 5;
137
138                         // Handle async
139                         rc = at_async_response_dequeue(response);
140                         if(rc < 0) {
141                                 // Handle UNSOL
142                                 if(response->command == NULL) {
143                                         at_response_free(response);
144                                         continue;
145                                 }
146
147                                 for(j=0 ; j < ril_globals.dispatch_unsol_count ; j++) {
148                                         if(at_commands_compare(response->command, ril_globals.dispatch_unsol[j].command) && ril_globals.dispatch_unsol[j].func != NULL) {
149                                                 ril_globals.dispatch_unsol[j].func(response);
150                                         }
151                                 }
152                         }
153
154                         at_response_free(response);
155                 }
156
157                 LOGE("RIL dispatch failed, retrying!");
158         }
159
160         LOGE("RIL dispatch failed too many times, aborting");
161
162         return NULL;
163 }
164
165 int ril_dispatch_thread_start(void)
166 {
167         pthread_attr_t attr;
168         int rc;
169
170         pthread_attr_init(&attr);
171         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
172
173         rc = pthread_create(&ril_globals.dispatch_thread, &attr, ril_dispatch, NULL);
174         if(rc != 0) {
175                 LOGE("Creating dispatch thread failed!");
176                 return -1;
177         }
178
179         return 0;
180 }
181
182 void ril_globals_init(void)
183 {
184         memset(&ril_globals, 0, sizeof(struct ril_globals));
185         ril_globals.dispatch_unsol = &ril_dispatch_unsol;
186         ril_globals.dispatch_unsol_count = sizeof(ril_dispatch_unsol) / sizeof(struct ril_dispatch_unsol);
187
188         LOGE("Registered %d unsol requests handlers", ril_globals.dispatch_unsol_count);
189
190         ril_globals.radio_state = RADIO_STATE_OFF;
191
192         at_handling_init();
193 }
194
195 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
196 {
197         int rc;
198
199         ril_globals_init();
200         ril_device_register(&ril_device);
201
202         LOGD("Starting %s for device: %s", RIL_VERSION_STRING, ril_device->name);
203
204         rc = ril_device_init(ril_device);
205         if(rc < 0) {
206                 LOGE("Failed to init device!");
207                 ril_device_deinit(ril_device);
208
209                 return NULL;
210         }
211
212         rc = ril_device_transport_recv_thread_start(ril_device);
213         if(rc < 0) {
214                 LOGE("Failed to start device recv thread!");
215                 ril_device_deinit(ril_device);
216
217                 return NULL;
218         }
219
220         rc = ril_dispatch_thread_start();
221         if(rc < 0) {
222                 LOGE("Failed to start dispatch thread!");
223                 ril_device_deinit(ril_device);
224
225                 return NULL;
226         }
227
228         rc = ril_device_setup(ril_device);
229         if(rc < 0) {
230                 LOGE("Failed to setup device!");
231                 ril_device_deinit(ril_device);
232
233                 return NULL;
234         }
235
236         LOGD("Initialization complete");
237
238         return &ril_ops;
239 }