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