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