AT: Better failure handling and removed wrong unlock
[hayes-ril.git] / call.c
1 /*
2  * This file is part of hayes-ril.
3  *
4  * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
5  *
6  * Parts of this code are based on htcgeneric-ril, reference-ril:
7  * Copyright 2006-2011, htcgeneric-ril contributors
8  * Copyright 2006, The Android Open Source Project
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22
23 #define LOG_TAG "RIL-CALL"
24 #include <utils/Log.h>
25 #include <telephony/ril.h>
26
27 #include <hayes-ril.h>
28
29 /*
30  * Calls list
31  */
32
33 RIL_CallState at2ril_call_state(int state)
34 {
35         switch(state) {
36                 case 0:
37                         return RIL_CALL_ACTIVE;
38                 case 1:
39                         return RIL_CALL_HOLDING;
40                 case 2:
41                         return RIL_CALL_DIALING;
42                 case 3:
43                         return RIL_CALL_ALERTING;
44                 case 4:
45                         return RIL_CALL_INCOMING;
46                 case 5:
47                         return RIL_CALL_WAITING;
48                 default:
49                         return -1;
50         }
51 }
52
53 void at2ril_call_list(RIL_Call *call, char *data)
54 {
55         struct at_response_data **response_data = NULL;
56         int response_data_count = 0;
57         char *number = NULL;
58         int state = 0;
59         int mode = 0;
60
61         response_data_count = at_response_data_process(&response_data, data, strlen(data));
62         if(response_data_count < 7)
63                 goto error;
64
65         // 1,0,2,0,0,"0557514206",129
66
67         if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
68                 goto error;
69         call->index = response_data[0]->value.n;
70
71         if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
72                 goto error;
73         call->isMT = response_data[1]->value.n;
74
75         if(response_data[2]->type != AT_RESPONSE_DATA_NUMERIC)
76                 goto error;
77         state = response_data[2]->value.n;
78         call->state = at2ril_call_state(state);
79
80         if(response_data[3]->type != AT_RESPONSE_DATA_NUMERIC)
81                 goto error;
82         mode = response_data[3]->value.n;
83         call->isVoice = (mode == 0);
84
85         if(response_data[4]->type != AT_RESPONSE_DATA_NUMERIC)
86                 goto error;
87         call->isMpty = response_data[4]->value.n;
88
89         if(response_data[5]->type != AT_RESPONSE_DATA_STRING)
90                 goto error;
91         number = strdup(response_data[5]->value.s);
92         if(number != NULL && strspn(number, "+0123456789") == 0)
93                 number = NULL;
94         call->number = number;
95
96         if(response_data[6]->type != AT_RESPONSE_DATA_NUMERIC)
97                 goto error;
98         call->toa = response_data[6]->value.n;
99
100         at_response_data_free(response_data, response_data_count);
101
102         return;
103
104 error:
105         LOGE("Error while parsing call list!");
106         at_response_data_free(response_data, response_data_count);
107 }
108
109 int at_clcc_expect(struct at_response *response, void *data, RIL_Token t)
110 {
111         RIL_Call **calls = NULL;
112         int calls_count = 0;
113         int poll = 0;
114         int i;
115
116         // TODO: ifdef poll with flags (not all devices need this)
117         struct timeval poll_interval = {0, 750000};
118
119         if(response->status == AT_STATUS_UNDEF)
120                 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
121
122         LOGE("Caught valid AT+CLCC unsol!");
123
124         if(at_status_error(response->status)) {
125                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
126         }
127
128         calls_count = response->data_count;
129         if(calls_count > 0) {
130                 calls = calloc(1, sizeof(RIL_Call *) * calls_count);
131
132                 LOGD("Got %d call(s) ingoing!", calls_count);
133
134                 for(i=0 ; i < calls_count ; i++) {
135                         calls[i] = calloc(1, sizeof(RIL_Call));
136                         at2ril_call_list(calls[i], response->data[i]);
137
138                         if(calls[i]->state != RIL_CALL_ACTIVE && calls[i]->state != RIL_CALL_HOLDING)
139                                 poll = 1;
140                 }
141
142                 RIL_requestTimedCallback(ril_call_state_changed, NULL, &poll_interval);
143         }
144
145         RIL_onRequestComplete(t, RIL_E_SUCCESS, calls, sizeof(RIL_Call *) * calls_count);
146
147         for(i=0 ; i < calls_count ; i++) {
148                 if(calls[i] != NULL) {
149                         if(calls[i]->number != NULL)
150                                 free(calls[i]->number);
151                         free(calls[i]);
152                 }
153         }
154
155         if(calls != NULL)
156                 free(calls);
157
158         return AT_RESPONSE_HANDLED_OK;
159 }
160
161 void ril_request_get_current_calls(RIL_Token t, void *data, size_t length)
162 {
163         if(ril_globals.radio_state == RADIO_STATE_OFF) {
164                 RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
165                 return;
166         }
167         at_send_expect_to_func("AT+CLCC", NULL, NULL, t, at_clcc_expect);
168 }
169
170 void ril_call_state_changed(void *data)
171 {
172         RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
173 }
174
175 void at_cring(struct at_response *response)
176 {
177         RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
178 }
179
180 void ril_request_anwswer(RIL_Token t, void *data, size_t length)
181 {
182         int status;
183
184         status = at_send_expect_status("ATA", NULL);
185
186         if(at_status_error(status))
187                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
188         else
189                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
190 }
191
192 /*
193  * Dial
194  */
195
196 void ril_request_dial(RIL_Token t, void *data, size_t length)
197 {
198         RIL_Dial *dial;
199         char *command = NULL;
200         char *clir = NULL;
201         int status = AT_STATUS_UNDEF;
202
203         dial = (RIL_Dial *) data;
204
205         switch(dial->clir) {
206                 case 1: clir = "I"; break;  // invocation
207                 case 2: clir = "i"; break;  // suppression
208                 default:
209                 case 0: clir = ""; break;   // subscription default
210         }
211
212         asprintf(&command, "ATD%s%s;", dial->address, clir);
213
214         status = at_send_expect_status(command, NULL);
215
216         free(command);
217
218         if(at_status_error(status))
219                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
220         else
221                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
222 }
223
224 void no_carrier_unexpect(struct at_response *response)
225 {
226         // This comes to notify call end
227         RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
228 }
229
230 void ril_request_hangup(RIL_Token t, void *data, size_t length)
231 {
232         char *command = NULL;
233         int index = 0;
234         int status = AT_STATUS_UNDEF;
235
236         index = *((int *) data);
237
238         asprintf(&command, "AT+CHLD=1%d", index);
239
240         status = at_send_expect_status(command, NULL);
241
242         free(command);
243
244         if(at_status_error(status))
245                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
246         else
247                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
248 }
249
250 void at_chld_request(RIL_Token t, char *data)
251 {
252         int status;
253
254         status = at_send_expect_status("AT+CHLD", data);
255
256         if(at_status_error(status))
257                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
258         else
259                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
260 }
261
262 void ril_request_hangup_waiting_or_background(RIL_Token t, void *data, size_t length)
263 {
264         at_chld_request(t, "0");
265 }
266
267 void ril_request_hangup_foreground_resume_background(RIL_Token t, void *data, size_t length)
268 {
269         at_chld_request(t, "1");
270 }
271
272 void ril_request_switch_waiting_or_holding_and_active(RIL_Token t, void *data, size_t length)
273 {
274         at_chld_request(t, "2");
275 }