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