2a761d350903564dc53ece744aed3af61a0a2afb
[platform/core/connectivity/bluetooth-agent.git] / ag-agent / bluetooth-ag-handler.c
1 /*
2  * bluetooth-ag-handler.c
3  *
4  * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:     Hocheol Seo <hocheol.seo@samsung.com>
7  *              Chethan TN <chethan.tn@samsung.com>
8  *              Chanyeol Park <chanyeol.park@samsung.com>
9  *              Rakesh MK <rakesh.mk@samsung.com>
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *              http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  */
24 #include "bluetooth-ag-agent.h"
25 #include "bluetooth-ag-handler.h"
26 #include "vconf.h"
27 #include "vconf-keys.h"
28
29 extern bt_ag_status_t ag;
30 extern GSList *active_devices;
31 extern GDBusConnection *ag_dbus_conn;
32 extern gchar *remote_dev_path;
33
34  /* AT+CSQ : Returns received signal strength indication.
35      Command response: +CSQ: <rssi>,<ber>
36     <ber> is not supported and has a constant value of 99, included for compatibility reasons.
37 */
38 #define BT_SIGNAL_QUALITY_BER 99
39
40 wbs_options wbs_opts = {
41         .wbs_enable = FALSE,
42         .i2s_enable = 0x00,
43         .is_master = 0x00,
44         .clock_rate = 0x02,
45         .pcm_interface_rate = 0x00,
46 };
47
48 /* AT+BRSF response */
49 int _bt_hfp_supported_features(bt_ag_info_t *hs, const char *buf)
50 {
51         bt_ag_slconn_t *slconn = hs->slc;
52         int err;
53 //      bt_hfp_agent_error_t ret = BT_HFP_AGENT_ERROR_NONE;
54
55         DBG("AT + BRSF");
56         if (strlen(buf) < 9)
57                 return -EINVAL;
58
59         slconn->hs_features = strtoul(&buf[8], NULL, 10);
60 #if 0 /* SCO is crashed if below is called when SCO is opened by hf-agent */
61         if (slconn->hs_features & BT_HF_FEATURE_CODEC_NEGOTIATION) {
62                 ret = _bt_ag_set_codec(hs, "SetWbsParameters");
63                 if (ret != BT_HFP_AGENT_ERROR_NONE)
64                         ERR("Unable to set the default WBC codec");
65         } else {
66                 /* Default codec is NB */
67                 ret = _bt_ag_set_codec(hs, "SetNbParameters");
68                 if (ret != BT_HFP_AGENT_ERROR_NONE)
69                         ERR("Unable to set the default NBC codec");
70         }
71 #endif
72         err = _bt_ag_send_at(hs, "\r\n+BRSF: %u\r\n", ag.features);
73         if (err < 0)
74                 return err;
75
76         return _bt_ag_send_at(hs, "\r\nOK\r\n");
77 }
78
79 static char *__bt_get_indicator_ranges(const bt_ag_indicators_t *indicators)
80 {
81         int i;
82         GString *gstr;
83
84         DBG("__bt_get_indicator_ranges");
85         gstr = g_string_new("\r\n+CIND: ");
86
87         for (i = 0; indicators[i].indicator_desc != NULL; i++) {
88                 if (i == 0)
89                         g_string_append_printf(gstr, "(\"%s\",(%s))",
90                                 indicators[i].indicator_desc,
91                                 indicators[i].indicator_range);
92                 else
93                         g_string_append_printf(gstr, ",(\"%s\",(%s))",
94                                 indicators[i].indicator_desc,
95                                 indicators[i].indicator_range);
96         }
97         g_string_append(gstr, "\r\n");
98         return g_string_free(gstr, FALSE);
99 }
100
101 static char *__bt_get_indicator_values(const bt_ag_indicators_t *indicators)
102 {
103         int i;
104         GString *gstr;
105
106         gstr = g_string_new("\r\n+CIND: ");
107         DBG("__bt_get_indicator_values");
108         for (i = 0; indicators[i].indicator_range != NULL; i++) {
109                 if (i == 0)
110                         g_string_append_printf(gstr, "%d",
111                                 indicators[i].hfp_value);
112                 else
113                         g_string_append_printf(gstr, ",%d",
114                                 indicators[i].hfp_value);
115         }
116         g_string_append(gstr, "\r\n");
117
118         return g_string_free(gstr, FALSE);
119 }
120
121 static int __bt_check_hdset(bt_ag_info_t *hdset)
122 {
123         bt_ag_slconn_t *slconn = hdset->slc;
124
125         if (!hdset->hfp_active)
126                 return -1;
127
128         if (slconn->is_client_active)
129                 return 0;
130         else
131                 return -1;
132 }
133
134 static int __bt_hfp_cmp(bt_ag_info_t *hs)
135 {
136         if (hs->hfp_active)
137                 return 0;
138         else
139                 return -1;
140 }
141
142 static int __bt_cwa_cmp(bt_ag_info_t *hs)
143 {
144         if (!hs->hfp_active)
145                 return -1;
146
147         if (hs->slc->is_cwa_enabled)
148                 return 0;
149         else
150                 return -1;
151 }
152
153 gboolean __bt_ring_timer_cb(gpointer data)
154 {
155         _bt_ag_send_foreach_headset(active_devices, NULL, "\r\nRING\r\n");
156
157         if (ag.number)
158                 _bt_ag_send_foreach_headset(active_devices, __bt_check_hdset,
159                                         "\r\n+CLIP: \"%s\",%d\r\n",
160                                         ag.number, ag.number_type);
161
162         return TRUE;
163 }
164
165 int _bt_incoming_call_indicator(const char *number, int type)
166 {
167         bt_ag_info_t *hs;
168         bt_ag_slconn_t *slconn;
169
170         if (!active_devices)
171                 return -ENODEV;
172
173         /* Get the updated list of connected devices */
174         hs = active_devices->data;
175         slconn = hs->slc;
176
177         if (ag.ring_timer) {
178                 DBG("incoming_call_indicator: already calling....");
179                 return -EBUSY;
180         }
181
182         /*If inband ring supported then no need to send RING alert to HF */
183         if (!hs->hfp_active && slconn->is_inband_ring) {
184                 DBG("Inband ring tone supported");
185                 return 0;
186         }
187
188         DBG("Inband ring tone not supported.. so send a RING to HF");
189         g_free(ag.number);
190         ag.number = g_strdup(number);
191         ag.number_type = type;
192
193         if (slconn->is_inband_ring &&
194                                         hs->state != HEADSET_STATE_ON_CALL) {
195                 slconn->is_pending_ring = TRUE;
196                 return 0;
197         }
198
199         __bt_ring_timer_cb(NULL);
200         ag.ring_timer = g_timeout_add(AG_RING_INTERVAL, __bt_ring_timer_cb, NULL);
201
202         return 0;
203 }
204
205 int _bt_calling_stopped_indicator(void)
206 {
207         bt_ag_info_t *dev;
208
209         if (ag.ring_timer) {
210                 g_source_remove(ag.ring_timer);
211                 ag.ring_timer = 0;
212         }
213
214         if (!active_devices)
215                 return 0;
216
217         /* In case SCO is in intermediate state to connect */
218         dev = active_devices->data;
219
220         if (!dev->slc->is_pending_ring && !ag.ring_timer)
221                 return -EINVAL;
222
223         dev->slc->is_pending_ring = FALSE;
224
225         return 0;
226 }
227
228 void _bt_hfp_set_ag_indicator(uint32_t ag_features,
229                         const bt_ag_indicators_t *ag_indicators, int rh,
230                         const char *chld)
231 {
232         DBG("Set Ag Features");
233         ag.telephony_ready = TRUE;
234         ag.features = ag_features;
235         ag.indicators = ag_indicators;
236         ag.rh = rh;
237         ag.chld = chld;
238 }
239
240 void _bt_hfp_deinitialize(void)
241 {
242         g_free(ag.number);
243         memset(&ag, 0, sizeof(ag));
244         ag.rh = BT_RSP_HOLD_NOT_SUPPORTED;
245         ag.er_mode = 3;
246 }
247
248 /* Send event indication call from Statemanager module */
249 bt_hfp_agent_error_t _bt_hfp_event_indicator(int index)
250 {
251         if (!active_devices) {
252                 DBG("No Active devices present");
253                 return BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
254         }
255
256         if (!ag.er_ind) {
257                 DBG("Indicate event called but event reporting is disabled");
258                 return BT_HFP_AGENT_ERROR_INTERNAL;
259         }
260
261         DBG("Sending event notification to hf....");
262
263         _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
264                                 "\r\n+CIEV: %d,%d\r\n", index + 1,
265                                 ag.indicators[index].hfp_value);
266
267         return BT_HFP_AGENT_ERROR_NONE;
268 }
269
270 /* AT+CIND response */
271 int _bt_hfp_report_indicators(bt_ag_info_t *hs, const char *buf)
272 {
273         int err;
274         char *str;
275
276         if (strlen(buf) < 8)
277                 return -EINVAL;
278
279         if (buf[7] == '=')
280                 str = __bt_get_indicator_ranges(ag.indicators);
281         else
282                 str = __bt_get_indicator_values(ag.indicators);
283
284         err = _bt_ag_send_at(hs, "%s", str);
285
286         g_free(str);
287
288         if (err < 0)
289                 return err;
290
291         return _bt_ag_send_at(hs, "\r\nOK\r\n");
292 }
293
294 /* AT+CMER response */
295 int _bt_event_reporting_response(void *t_device,
296                                 bt_hfp_agent_error_t err)
297 {
298         bt_ag_info_t *hdset = t_device;
299         bt_ag_slconn_t *slconn = hdset->slc;
300         int ret_val;
301
302         if (err != (bt_hfp_agent_error_t) HFP_STATE_MNGR_ERR_NONE)
303                 return _bt_ag_send_response(t_device, err);
304
305         ret_val = _bt_ag_send_at(hdset, "\r\nOK\r\n");
306         if (ret_val < 0)
307                 return ret_val;
308
309         if (hdset->state != HEADSET_STATE_CONNECTING)
310                 return 0;
311
312         if (slconn->hs_features & HANDSFREE_FEATURE_CALL_WAITING_AND_3WAY &&
313                         ag.features & BT_AG_FEATURE_THREE_WAY_CALL)
314                 return 0;
315
316         _bt_ag_slconn_complete(hdset);
317
318         return 0;
319 }
320
321 int _bt_hfp_enable_indicators(bt_ag_info_t *hdset, const char *buffer)
322 {
323         if (strlen(buffer) < 13)
324                 return -EINVAL;
325
326         /* tokenks can be <mode>,<keyp>,<disp>,<ind>,<bfr>*/
327         char **ind_tokens = g_strsplit(&buffer[8], ",", 5);
328
329         if (g_strv_length(ind_tokens) < 4) {
330                 g_strfreev(ind_tokens);
331                 return -EINVAL;
332         }
333
334         ag.er_mode = atoi(ind_tokens[0]);
335         ag.er_ind = atoi(ind_tokens[3]);
336
337         DBG("hfp_enable_indicators (CMER): indicator=%d, mode=%d",
338                 ag.er_ind, ag.er_mode);
339
340         g_strfreev(ind_tokens);
341         ind_tokens = NULL;
342
343         switch (ag.er_ind) {
344         case 0:
345         case 1:
346                 _bt_hfp_update_event_request(ag.er_ind, hdset);
347                 break;
348         default:
349                 return -EINVAL;
350         }
351         return 0;
352 }
353
354         /* AT+CHLD response */
355 int _bt_hfp_call_hold(bt_ag_info_t *hs, const char *buf)
356 {
357         int err;
358
359         if (strlen(buf) < 9)
360                 return -EINVAL;
361
362         if (buf[8] != '?') {
363                 _bt_hfp_call_hold_request(&buf[8], hs);
364                 return 0;
365         }
366
367         err = _bt_ag_send_at(hs, "\r\n+CHLD: (%s)\r\n", ag.chld);
368         if (err < 0)
369                 return err;
370
371         err = _bt_ag_send_at(hs, "\r\nOK\r\n");
372         if (err < 0)
373                 return err;
374
375         _bt_ag_slconn_complete(hs);
376
377         return 0;
378 }
379
380 int _bt_key_press_response(void *t_device, bt_hfp_agent_error_t err)
381 {
382         return _bt_ag_send_response(t_device, err);
383 }
384
385 int _bt_hfp_key_press(bt_ag_info_t *hs, const char *buf)
386 {
387         if (strlen(buf) < 9)
388                 return -EINVAL;
389
390         if (ag.ring_timer) {
391                 g_source_remove(ag.ring_timer);
392                 ag.ring_timer = 0;
393         }
394
395         _bt_hfp_key_press_request(&buf[8], hs);
396
397         return 0;
398 }
399
400 int _bt_answer_call_response(void *hs, bt_hfp_agent_error_t err)
401 {
402         return _bt_ag_send_response(hs, err);
403 }
404
405 int _bt_hfp_answer_call(bt_ag_info_t *hs, const char *buf)
406 {
407         if (ag.ring_timer) {
408                 g_source_remove(ag.ring_timer);
409                 ag.ring_timer = 0;
410         }
411
412         if (ag.number) {
413                 g_free(ag.number);
414                 ag.number = NULL;
415         }
416
417         if (remote_dev_path)
418                 g_free(remote_dev_path);
419
420         remote_dev_path = g_strdup(hs->path);
421
422         _bt_hfp_answer_call_request(hs);
423
424         return 0;
425 }
426 int _bt_terminate_call_response(void *t_device,
427                                         hfp_state_manager_err_t err)
428 {
429         bt_ag_info_t *hs = t_device;
430
431         if (err != HFP_STATE_MNGR_ERR_NONE)
432                 return _bt_ag_send_response(hs, err);
433
434         return _bt_ag_send_at(hs, "\r\nOK\r\n");
435 }
436
437 int _bt_hfp_terminate_call(bt_ag_info_t *hs, const char *buf)
438 {
439         if (ag.number) {
440                 g_free(ag.number);
441                 ag.number = NULL;
442         }
443
444         if (ag.ring_timer) {
445                 g_source_remove(ag.ring_timer);
446                 ag.ring_timer = 0;
447         }
448
449         _bt_hfp_terminate_call_request(hs);
450
451         return 0;
452 }
453
454 int _bt_hfp_cli_notification(bt_ag_info_t *hs, const char *buf)
455 {
456         bt_ag_slconn_t *slconn = hs->slc;
457
458         if (strlen(buf) < 9)
459                 return -EINVAL;
460
461         slconn->is_client_active = buf[8] == '1' ? TRUE : FALSE;
462
463         return _bt_ag_send_at(hs, "\r\nOK\r\n");
464 }
465
466 int _bt_response_and_hold_response(void *t_device,
467                                         bt_hfp_agent_error_t err)
468 {
469         return _bt_ag_send_response(t_device, err);
470 }
471
472 int _bt_hfp_response_and_hold(bt_ag_info_t *hs, const char *buf)
473 {
474
475         if (strlen(buf) < 8)
476                 return -EINVAL;
477
478         if (ag.rh == BT_RSP_HOLD_NOT_SUPPORTED)
479                 return _bt_ag_send_response(hs,
480                         HFP_STATE_MNGR_ERR_NOT_SUPPORTED);
481
482         if (buf[7] == '=') {
483                 _bt_hfp_response_and_hold_request(hs);
484                 return 0;
485         }
486
487         if (ag.rh >= 0)
488                 _bt_ag_send_at(hs, "\r\n+BTRH: %d\r\n", ag.rh);
489
490         return _bt_ag_send_at(hs, "\r\nOK\r\n");
491 }
492
493 int _bt_hfp_last_dialed_number(bt_ag_info_t *hs, const char *buf)
494 {
495         if (remote_dev_path)
496                 g_free(remote_dev_path);
497
498         remote_dev_path = g_strdup(hs->path);
499         _bt_hfp_last_dialed_number_request(hs);
500
501         return 0;
502 }
503
504 int _bt_dial_number_response(void *t_device, bt_hfp_agent_error_t err)
505 {
506         return _bt_ag_send_response(t_device, err);
507 }
508
509 int _bt_hfp_dial_number(bt_ag_info_t *hs, const char *buf)
510 {
511         char number[MAX_BUFFER_SIZE];
512         size_t buf_len;
513
514         buf_len = strlen(buf);
515
516         if (buf[buf_len - 1] != ';') {
517                 DBG("Reject the non-voice call dial number request");
518                 return -EINVAL;
519         }
520
521         memset(number, 0, sizeof(number));
522         strncpy(number, &buf[3], buf_len - 4);
523
524         if (remote_dev_path)
525                 g_free(remote_dev_path);
526
527         remote_dev_path = g_strdup(hs->path);
528
529         _bt_hfp_dial_number_request(number, hs);
530
531         return 0;
532 }
533
534 static int __bt_headset_set_gain(bt_ag_info_t *hs, uint16_t gain, char type)
535 {
536         bt_ag_slconn_t *slconn = hs->slc;
537         const char *property;
538
539         if (gain > 15) {
540                 DBG("Invalid gain value: %u", gain);
541                 return -EINVAL;
542         }
543
544         switch (type) {
545         case BT_HFP_SPEAKER_GAIN:
546                 if (slconn->speaker_gain == gain) {
547                         DBG("Ignoring no-change in speaker gain");
548                         return -EALREADY;
549                 }
550                 property = "SpeakerGain";
551                 slconn->speaker_gain = gain;
552                 break;
553         case BT_HFP_MICROPHONE_GAIN:
554                 if (slconn->microphone_gain == gain) {
555                         DBG("Ignoring no-change in microphone gain");
556                         return -EALREADY;
557                 }
558                 property = "MicrophoneGain";
559                 slconn->microphone_gain = gain;
560                 break;
561         default:
562                 DBG("Unknown gain setting\n");
563                 return -EINVAL;
564         }
565
566         _bt_ag_agent_emit_property_changed(ag_dbus_conn, hs->path,
567                                 BT_HEADSET_INTERFACE, property,
568                                 g_variant_new("q", gain));
569         return 0;
570 }
571
572 int _bt_hfp_signal_gain_setting(bt_ag_info_t *hs, const char *buf)
573 {
574         uint16_t gain;
575         int err;
576
577         if (strlen(buf) < 8) {
578                 DBG("very short string to use for Gain setting\n");
579                 return -EINVAL;
580         }
581
582         gain = (uint16_t) strtol(&buf[7], NULL, 10);
583
584         err = __bt_headset_set_gain(hs, gain, buf[5]);
585         if (err < 0 && err != -EALREADY)
586                 return err;
587
588         return _bt_ag_send_at(hs, "\r\nOK\r\n");
589 }
590
591 int _bt_transmit_dtmf_response(void *t_device,
592                         bt_hfp_agent_error_t err)
593 {
594         return _bt_ag_send_response(t_device, err);
595 }
596
597 int _bt_hfp_dtmf_tone(bt_ag_info_t *hs, const char *buf)
598 {
599         char tone;
600
601         if (strlen(buf) < 8) {
602                 printf("Too short string for DTMF tone");
603                 return -EINVAL;
604         }
605
606         tone = buf[7];
607         if (tone >= '#' && tone <= 'D')
608                 _bt_hfp_channel_dtmf_request(tone, hs);
609         else
610                 return -EINVAL;
611
612         return 0;
613 }
614
615 int _bt_hfp_set_speaker_gain(bt_ag_info_t *hs,
616                 uint16_t gain_value)
617 {
618         int err;
619         char type = BT_HFP_SPEAKER_GAIN;
620
621         err = __bt_headset_set_gain(hs, gain_value, type);
622         if (err < 0)
623                 return BT_HFP_AGENT_ERROR_INTERNAL;
624
625         if (hs->state == HEADSET_STATE_ON_CALL) {
626                 err = _bt_ag_send_at(hs, "\r\n+VG%c=%u\r\n", type,
627                                 gain_value);
628                 if (err < 0)
629                         return BT_HFP_AGENT_ERROR_INTERNAL;
630         }
631         return BT_HFP_AGENT_ERROR_NONE;
632 }
633
634 int _bt_hfp_set_microphone_gain(bt_ag_info_t *hs,
635                 uint16_t gain_value)
636 {
637         int err;
638         char type = BT_HFP_MICROPHONE_GAIN;
639
640         if (hs == NULL) {
641                 DBG("hs is NULL");
642                 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
643         }
644
645         err = __bt_headset_set_gain(hs, gain_value, type);
646         if (err < 0)
647                 return BT_HFP_AGENT_ERROR_INTERNAL;
648
649         if (hs->state == HEADSET_STATE_ON_CALL) {
650                 err = _bt_ag_send_at(hs, "\r\n+VG%c=%u\r\n", type,
651                                 gain_value);
652                 if (err < 0)
653                         return BT_HFP_AGENT_ERROR_INTERNAL;
654         }
655         return BT_HFP_AGENT_ERROR_NONE;
656 }
657
658
659 int _bt_hfp_set_voice_dial(bt_ag_info_t *hs,
660                 gboolean enable)
661 {
662         DBG("_bt_hfp_set_voice_dial = %d", enable);
663
664         if (_bt_ag_send_at(hs, "\r\n+BVRA: %d\r\n", enable) < 0)
665                 return BT_HFP_AGENT_ERROR_INTERNAL;
666
667         return BT_HFP_AGENT_ERROR_NONE;
668 }
669
670 int _bt_hfp_send_vendor_cmd(bt_ag_info_t *hs,
671                 const char *cmd)
672 {
673         DBG("_bt_hfp_send_vendor_cmd = %d", cmd);
674
675         if (_bt_ag_send_at(hs, "\r\n%s\r\n", cmd) < 0)
676                 return BT_HFP_AGENT_ERROR_INTERNAL;
677
678         return BT_HFP_AGENT_ERROR_NONE;
679 }
680
681 int _bt_vendor_cmd_response(void *t_device,
682                         bt_hfp_agent_error_t err)
683 {
684         return _bt_ag_send_response(t_device, err);
685 }
686
687 int _bt_hfp_vendor_cmd(bt_ag_info_t *hs, const char *buf)
688 {
689         DBG("XSAT vendor command");
690
691         _bt_hfp_vendor_cmd_request(buf, hs);
692
693         return 0;
694 }
695
696 int _bt_list_current_call_indicator(bt_ag_info_t *hs, int index, int direction,
697         int mode, int status, const char *call_num, int conference, int t_num)
698 {
699         if (call_num && strlen(call_num) > 0) {
700                 _bt_ag_send_at(hs,
701                         "\r\n+CLCC: %d,%d,%d,%d,%d,\"%s\",%d\r\n",
702                         index, direction, status, mode, conference,
703                                 call_num, t_num);
704         } else {
705                 _bt_ag_send_at(hs,
706                         "\r\n+CLCC: %d,%d,%d,%d,%d\r\n",
707                         index, direction, status, mode, conference);
708         }
709
710         return 0;
711 }
712 int _bt_subscriber_number_indicator(const char *call_num, int type, int service)
713 {
714         if (!active_devices)
715                 return -ENODEV;
716
717         _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
718                                 "\r\n+CNUM: ,%s,%d,,%d\r\n",
719                                 call_num, type, service);
720         return 0;
721 }
722
723 int _bt_subscriber_number_response(void *t_device,
724                                         bt_hfp_agent_error_t err)
725 {
726         return _bt_ag_send_response(t_device, err);
727 }
728
729 int _bt_hfp_subscriber_number(bt_ag_info_t *hs, const char *buf)
730 {
731         _bt_hfp_subscriber_number_request(hs);
732
733         return 0;
734 }
735
736 int _bt_call_waiting_indicator(const char *number, int type)
737 {
738         if (!active_devices)
739                 return -ENODEV;
740
741         DBG("Call waiting indicator to hf");
742         _bt_ag_send_foreach_headset(active_devices, __bt_cwa_cmp,
743                                 "\r\n+CCWA: \"%s\",%d\r\n",
744                                 number, type);
745         return 0;
746 }
747
748 int _bt_list_current_calls_response(void *t_device,
749                                         bt_hfp_agent_error_t err)
750 {
751         return _bt_ag_send_response(t_device, err);
752 }
753
754 int _bt_hfp_list_current_calls(bt_ag_info_t *hs, const char *buf)
755 {
756         _bt_list_current_calls(hs);
757
758         return 0;
759 }
760
761 int _bt_hfp_extended_errors(bt_ag_info_t *hs, const char *buf)
762 {
763         bt_ag_slconn_t *slconn = hs->slc;
764
765         if (strlen(buf) < 9)
766                 return -EINVAL;
767
768         if (buf[8] == '1') {
769                 slconn->is_cme_enabled = TRUE;
770                 DBG("CME errors enabled for headset %p", hs);
771         } else {
772                 slconn->is_cme_enabled = FALSE;
773                 DBG("CME errors disabled for headset %p", hs);
774         }
775
776         return _bt_ag_send_at(hs, "\r\nOK\r\n");
777 }
778
779 int _bt_hfp_call_waiting_notify(bt_ag_info_t *hs, const char *buf)
780 {
781         bt_ag_slconn_t *slconn = hs->slc;
782
783         if (strlen(buf) < 9)
784                 return -EINVAL;
785
786         if (buf[8] == '1') {
787                 slconn->is_cwa_enabled = TRUE;
788                 DBG("Call waiting notification enabled for headset %p", hs);
789         } else {
790                 slconn->is_cwa_enabled = FALSE;
791                 DBG("Call waiting notification disabled for headset %p", hs);
792         }
793
794         return _bt_ag_send_at(hs, "\r\nOK\r\n");
795 }
796
797 int _bt_operator_selection_response(void *t_device,
798                                         bt_hfp_agent_error_t err)
799 {
800         return _bt_ag_send_response(t_device, err);
801 }
802
803 int _bt_call_hold_response(void *t_device, bt_hfp_agent_error_t err)
804 {
805         return _bt_ag_send_response(t_device, err);
806 }
807
808 int _bt_nr_and_ec_response(void *t_device, bt_hfp_agent_error_t err)
809 {
810         bt_ag_info_t *hs = t_device;
811         bt_ag_slconn_t *slconn = hs->slc;
812
813         if (err == (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
814                 GSList *l;
815
816                 for (l = hs->nrec_cbs; l; l = l->next) {
817                         struct hs_nrec_callback *nrec_cb = l->data;
818
819                         nrec_cb->cb(hs, slconn->is_nrec_req,
820                                 nrec_cb->user_data);
821                 }
822
823                 slconn->is_nrec = hs->slc->is_nrec_req;
824         }
825
826         return _bt_ag_send_response(t_device, err);
827 }
828
829 int _bt_voice_dial_response(void *t_device, bt_hfp_agent_error_t err)
830 {
831         return _bt_ag_send_response(t_device, err);
832 }
833
834 int _bt_operator_selection_indicator(int mode, const char *oper)
835 {
836         if (!active_devices)
837                 return -ENODEV;
838
839         _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
840                                 "\r\n+COPS: %d,0,\"%s\"\r\n",
841                                 mode, oper);
842         return 0;
843 }
844
845 int _bt_hfp_operator_selection(bt_ag_info_t *hs, const char *buf)
846 {
847         if (strlen(buf) < 8)
848                 return -EINVAL;
849
850         switch (buf[7]) {
851         case '?':
852                 _bt_hfp_get_operator_selection_request(hs);
853                 break;
854         case '=': {
855                 if (buf[8] == '?')
856                         return _bt_ag_send_at(hs, "\r\n+CME ERROR: %d\r\n",
857                                 HFP_STATE_MNGR_ERR_NOT_SUPPORTED);
858                 else
859                         return _bt_ag_send_at(hs, "\r\nOK\r\n");
860         }
861         default:
862                 return -EINVAL;
863         }
864
865         return 0;
866 }
867
868 int _bt_hfp_nr_and_ec(bt_ag_info_t *hs, const char *buf)
869 {
870         bt_ag_slconn_t *slconn = hs->slc;
871
872         if (strlen(buf) < 9)
873                 return -EINVAL;
874
875         if (buf[8] == '0')
876                 slconn->is_nrec_req = FALSE;
877         else
878                 slconn->is_nrec_req = TRUE;
879
880         _bt_hfp_noise_red_and_echo_cancel_request(slconn->is_nrec_req, hs);
881
882         return 0;
883 }
884
885 int _bt_hfp_voice_dial(bt_ag_info_t *hs, const char *buf)
886 {
887         bt_ag_slconn_t *slconn = hs->slc;
888         gboolean enable;
889
890         if (strlen(buf) < 9)
891                 return -EINVAL;
892
893         if (buf[8] == '0')
894                 enable = FALSE;
895         else
896                 enable = TRUE;
897
898         _bt_hfp_voice_dial_request(enable, hs);
899
900         slconn->is_voice_recognition_running = enable;
901
902         return 0;
903 }
904
905 int _bt_hfp_indicators_activation(bt_ag_info_t *hs, const char *buf)
906 {
907         if (strlen(buf) < 7) {
908                 printf("Invalid indicator activation request\n");
909                 return -EINVAL;
910         }
911
912         _bt_hfp_set_indicators(&buf[6], hs);
913         return 0;
914 }
915
916 int _bt_indicators_activation_response(void *t_device,
917                                         bt_hfp_agent_error_t err)
918 {
919         return _bt_ag_send_response(t_device, err);
920 }
921
922 int _bt_select_phonebook_memory_status_response(void *t_device,
923                                                 const char *path,
924                                                 uint32_t total, uint32_t used,
925                                                 bt_hfp_agent_error_t err)
926 {
927         bt_ag_info_t *hs = t_device;
928         bt_ag_slconn_t *slconn = hs->slc;
929
930         if (err != (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
931                 if (slconn->is_cme_enabled)
932                         return _bt_ag_send_at(hs,
933                                         "\r\n+CME ERROR: %d\r\n", err);
934                 else
935                         return _bt_ag_send_at(hs, "\r\nERROR\r\n");
936         }
937
938         if (!active_devices)
939                 return -ENODEV;
940
941         _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
942                         "\r\n+CPBS: %s,%d,%d\r\n",
943                         path, used, total);
944
945         return _bt_ag_send_at(hs, "\r\nOK\r\n");
946 }
947
948 int _bt_select_phonebook_memory_list_response(void *t_device,
949                                                 const char *buf,
950                                                 bt_hfp_agent_error_t err)
951 {
952         bt_ag_info_t *hs = t_device;
953         bt_ag_slconn_t *slconn = hs->slc;
954
955         if ((err != (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) ||
956                                 (NULL == buf)) {
957                 if (slconn->is_cme_enabled)
958                         return _bt_ag_send_at(hs,
959                                         "\r\n+CME ERROR: %d\r\n", err);
960                 else
961                         return _bt_ag_send_at(hs, "\r\nERROR\r\n");
962         }
963
964         if (NULL != buf) {
965                 if (!active_devices)
966                         return -ENODEV;
967
968                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
969                                         "\r\n+CPBS: %s\r\n", buf);
970
971         }
972         return _bt_ag_send_at(hs, "\r\nOK\r\n");
973 }
974
975 int _bt_select_phonebook_memory_response(void *t_device,
976                                                 bt_hfp_agent_error_t err)
977 {
978         return _bt_ag_send_response(t_device, err);
979 }
980
981 int _bt_hfp_select_pb_memory(bt_ag_info_t *hs, const char *buf)
982 {
983         if (strlen(buf) < 8)
984                 return -EINVAL;
985
986         if (buf[7] == '?') {
987                 _bt_hfp_select_phonebook_memory_status(hs);
988                 return 0;
989         }
990
991         if (buf[7] == '=') {
992                 if (buf[8] == '?') {
993                         _bt_hfp_select_phonebook_memory_list(hs);
994                         return 0;
995                 }
996                 _bt_hfp_select_phonebook_memory(hs, &buf[8]);
997                 return 0;
998         }
999
1000         return -EINVAL;
1001 }
1002
1003 int _bt_read_phonebook_entries_list_response(void *t_device,
1004                                                 uint32_t used,
1005                                                 uint32_t number_length,
1006                                                 uint32_t name_length,
1007                                                 bt_hfp_agent_error_t err)
1008 {
1009         bt_ag_info_t *hs = t_device;
1010         bt_ag_slconn_t *slconn = hs->slc;
1011
1012         int send_err = 0;
1013         int index = 1;
1014
1015         if (err != (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
1016                 if (slconn->is_cme_enabled)
1017                         return _bt_ag_send_at(hs,
1018                                         "\r\n+CME ERROR: %d\r\n", err);
1019                 else
1020                         return _bt_ag_send_at(hs, "\r\nERROR\r\n");
1021         }
1022
1023         if (used < 1)
1024                 index = 0;
1025
1026         send_err = _bt_ag_send_at(hs, "\r\n+CPBR: (%d-%d),%d,%d\r\n",
1027                         index, used, number_length, name_length);
1028         if (send_err < 0)
1029                 return send_err;
1030
1031         return _bt_ag_send_at(hs, "\r\nOK\r\n");
1032 }
1033
1034 int _bt_read_phonebook_entries_response(void *t_device,
1035                                         bt_hfp_agent_error_t err)
1036 {
1037         return _bt_ag_send_response(t_device, err);
1038 }
1039
1040 int _bt_read_phonebook_entries_indicator(const char *name, const char *number,
1041                                         uint32_t handle)
1042 {
1043         int type = 129;
1044         const char *pos = NULL;
1045
1046         pos = number;
1047         while (*pos == ' ' || *pos == '\t')
1048                 pos++;
1049
1050         /* 145 means international access code, otherwise 129 is used */
1051         if (*pos == '+')
1052                 type = 145;
1053
1054         _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1055                         "\r\n+CPBR: %d,\"%s\",%d,\"%s\"\r\n",
1056                         handle, number, type, name);
1057         return 0;
1058 }
1059
1060 int _bt_hfp_read_pb_entries(bt_ag_info_t *hs, const char *buf)
1061 {
1062         if (strlen(buf) < 8)
1063                 return -EINVAL;
1064
1065         if (buf[7] != '=')
1066                 return -EINVAL;
1067
1068         if (buf[8] == '?')
1069                 _bt_hfp_read_phonebook_entries_list(hs);
1070         else
1071                 _bt_hfp_read_phonebook_entries(hs, &buf[8]);
1072
1073         return 0;
1074 }
1075
1076 int _bt_find_phonebook_entries_status_response(void *t_device,
1077                                                 bt_hfp_agent_error_t err)
1078 {
1079         return _bt_ag_send_response(t_device, err);
1080 }
1081
1082 int _bt_find_phonebook_entries_response(void *t_device,
1083                                         bt_hfp_agent_error_t err)
1084 {
1085         return _bt_ag_send_response(t_device, err);
1086 }
1087
1088 int _bt_find_phonebook_entries_status_indicator(uint32_t number_length,
1089                                         uint32_t name_length)
1090 {
1091         _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1092                         "\r\n+CPBF: %d,%d\r\n",
1093                         number_length, name_length);
1094
1095         return 0;
1096 }
1097
1098 int _bt_hfp_find_pb_entires(bt_ag_info_t *hs, const char *buf)
1099 {
1100         if (strlen(buf) < 8)
1101                 return -EINVAL;
1102
1103         if (buf[7] != '=')
1104                 return -EINVAL;
1105
1106         if (buf[8] == '?')
1107                 _bt_hfp_find_phonebook_entries_status(hs);
1108         else
1109                 _bt_hfp_find_phonebook_entries(hs, &buf[8]);
1110
1111         return 0;
1112 }
1113
1114 int _bt_supported_character_generic_response(void *t_device,
1115                                                 char *character_set_list,
1116                                                 bt_hfp_agent_error_t err)
1117 {
1118         bt_ag_info_t *hs = t_device;
1119         bt_ag_slconn_t *slconn = hs->slc;
1120
1121         if (err != (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
1122                 if (slconn->is_cme_enabled)
1123                         return _bt_ag_send_at(hs,
1124                                         "\r\n+CME ERROR: %d\r\n", err);
1125                 else
1126                         return _bt_ag_send_at(hs, "\r\nERROR\r\n");
1127         }
1128
1129         if (NULL != character_set_list) {
1130                 if (!active_devices)
1131                         return -ENODEV;
1132
1133                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1134                         "\r\n+CSCS: %s\r\n", character_set_list);
1135         }
1136         return _bt_ag_send_at(hs, "\r\nOK\r\n");
1137 }
1138
1139 int _bt_set_characterset_generic_response(void *t_device,
1140                                         bt_hfp_agent_error_t err)
1141 {
1142         return _bt_ag_send_response(t_device, err);
1143 }
1144
1145 int _bt_hfp_select_character_set(bt_ag_info_t *hs, const char *buf)
1146 {
1147         if (NULL != buf) {
1148                 if (strlen(buf) < 7)
1149                         return -EINVAL;
1150
1151                 if (buf[7] == '?') {
1152                         _bt_hfp_get_character_set(hs);
1153                         return 0;
1154                 }
1155
1156                 if (buf[7] == '=') {
1157                         if (buf[8] == '?')
1158                                 _bt_hfp_list_supported_character(hs);
1159                         else
1160                                 _bt_hfp_set_character_set(hs, &buf[8]);
1161                 }
1162         }
1163         return 0;
1164
1165 }
1166
1167 int _bt_battery_charge_status_response(void *t_device,
1168                                                 int32_t bcs,
1169                                                 int32_t bcl,
1170                                                 bt_hfp_agent_error_t err)
1171 {
1172         bt_ag_info_t *hs = t_device;
1173
1174         if (err == (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
1175                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1176                                         "\r\n+CBC: %d,%d\r\n", bcs, bcl);
1177         }
1178
1179         return _bt_ag_send_response(hs, err);
1180 }
1181
1182 int _bt_hfp_get_battery_charge_status(bt_ag_info_t *hs, const char *buf)
1183 {
1184         if (strlen(buf) < 6)
1185                 return -EINVAL;
1186
1187         if (buf[6] == '=')
1188                 return _bt_ag_send_response(hs, HFP_STATE_MNGR_ERR_NONE);
1189
1190         _bt_hfp_get_battery_property(hs);
1191         return 0;
1192 }
1193
1194 int _bt_hfp_apl_command(bt_ag_info_t *hs, const char *buf)
1195 {
1196         DBG("Got Apple command: %s", buf);
1197
1198         return _bt_ag_send_response(hs, HFP_STATE_MNGR_ERR_NONE);
1199 }
1200
1201 /* convert signal strength to a RSSI level */
1202 static int __bt_telephony_convert_signal_to_rssi(int signal)
1203 {
1204         /* input  : BT signal strength (0~5) */
1205         /* output : RSSI strength (0~31) */
1206         switch (signal) {
1207         case 0: return 0;
1208         case 1: return 4;
1209         case 2: return 8;
1210         case 3: return 13;
1211         case 4: return 19;
1212         case 5: return 31;
1213         }
1214
1215         if (signal > 5)
1216                 return 31;
1217
1218         return 0;
1219 }
1220
1221 int _bt_signal_quality_response(void *t_device,
1222                                                 int32_t rssi,
1223                                                 int32_t ber,
1224                                                 bt_hfp_agent_error_t err)
1225 {
1226         bt_ag_info_t *hs = t_device;
1227
1228         if (err == (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
1229                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1230                         "\r\n+CSQ: %d,%d\r\n",
1231                         __bt_telephony_convert_signal_to_rssi(rssi), ber);
1232         }
1233         return _bt_ag_send_response(hs, err);
1234 }
1235
1236 int _bt_telephony_signal_quality_list_supported_response(void *t_device,
1237                                                 bt_hfp_agent_error_t err)
1238 {
1239         bt_ag_info_t *device = t_device;
1240
1241         if (err == (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
1242                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1243                                         "\r\n+CSQ: (0-31,99),(99)\r\n");
1244         }
1245         return _bt_ag_send_response(device, err);
1246 }
1247
1248 int _bt_hfp_get_signal_quality(bt_ag_info_t *hs, const char *buf)
1249 {
1250         if (strlen(buf) < 6)
1251                 return -EINVAL;
1252
1253         if (buf[6] == '=')
1254                 _bt_telephony_signal_quality_list_supported_response(hs,
1255                                         HFP_STATE_MNGR_ERR_NONE);
1256         else
1257                 _bt_ag_agent_get_signal_quality(hs);
1258
1259         return 0;
1260 }
1261
1262 int _bt_hfp_get_activity_status_rsp(void *t_device,
1263                                                 int status,
1264                                                 bt_hfp_agent_error_t err)
1265 {
1266         bt_ag_info_t *device = t_device;
1267
1268         if (err == (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE) {
1269                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1270                                         "\r\n+CPAS: %d\r\n", status);
1271         }
1272
1273         return _bt_ag_send_response(device, err);
1274 }
1275
1276 int _bt_hfp_get_activity_status(bt_ag_info_t *device, const char *buf)
1277 {
1278         if (strlen(buf) < 7)
1279                 return -EINVAL;
1280
1281         if (buf[7] == '?') {
1282                 return _bt_ag_send_response(device,
1283                                         HFP_STATE_MNGR_ERR_AG_FAILURE);
1284         } else if (buf[7] == '=') {
1285                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1286                                         "\r\n+CPAS: (0-4)\r\n");
1287                 return _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_NONE);
1288         }
1289
1290         _bt_get_activity_status(device);
1291         return 0;
1292 }
1293
1294 int _bt_hfp_get_equipment_identity_rsp(void *t_device,
1295                                 char *identity, bt_hfp_agent_error_t err)
1296 {
1297         if (identity)
1298                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1299                 "\r\n+CGSN: %s\r\n", identity);
1300         return _bt_ag_send_response(t_device, err);
1301 }
1302
1303 int _bt_hfp_get_imsi_rsp(void *t_device,
1304                 char *mcc, char *mnc, char *msin, bt_hfp_agent_error_t err)
1305 {
1306         if (err == (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE)
1307                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1308                                 "\r\n%s%s%s\r\n", mcc, mnc, msin);
1309         return _bt_ag_send_response(t_device, err);
1310 }
1311
1312 int _bt_hfp_get_creg_status_rsp(void *t_device,
1313                 int n, int status, bt_hfp_agent_error_t err)
1314 {
1315         if (err == (bt_hfp_agent_error_t)HFP_STATE_MNGR_ERR_NONE)
1316                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1317                                 "\r\n+CREG: %d,%d\r\n", n, status);
1318         return _bt_ag_send_response(t_device, err);
1319 }
1320
1321 int _bt_hfp_get_equipment_identity(bt_ag_info_t *device, const char *buf)
1322 {
1323         int len = strlen(buf);
1324
1325         if (len == 9 && buf[7] == '=' && buf[8] == '?')  /* AT+CGSN=? */
1326                 return _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_NONE);
1327
1328         else if (len > 7)
1329                 return -EINVAL;
1330
1331         _bt_hfp_get_equipment_identity_req(device); /* AT+CGSN */
1332         return 0;
1333 }
1334
1335 int _bt_hfp_get_model_info_rsp(void *t_device, char *model,
1336                                                 bt_hfp_agent_error_t err)
1337 {
1338         if (model)
1339                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1340                 "\r\n+CGMM: %s\r\n", model);
1341         return _bt_ag_send_response(t_device, err);
1342 }
1343
1344 int _bt_hfp_get_model_information(bt_ag_info_t *device, const char *buf)
1345 {
1346         int len = strlen(buf);
1347
1348         if (len == 9 && buf[7] == '=' && buf[8] == '?')  /* AT+CGMM=? */
1349                 return _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_NONE);
1350
1351         else if (len > 7)
1352                 return -EINVAL;
1353
1354         _bt_hfp_get_model_info_req(device);/* AT+CGMM */
1355         return 0;
1356 }
1357
1358 int _bt_hfp_get_device_manufacturer_rsp(void *t_device,
1359                                 char *manufacturer, bt_hfp_agent_error_t err)
1360 {
1361         if (manufacturer)
1362                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1363                 "\r\n+CGMI: %s\r\n", manufacturer);
1364         return _bt_ag_send_response(t_device, err);
1365 }
1366
1367 int _bt_hfp_get_device_manufacturer(bt_ag_info_t *device, const char *buf)
1368 {
1369         int len = strlen(buf);
1370
1371         if (len == 9 && buf[7] == '=' && buf[8] == '?')  /* AT+CGMI=? */
1372                 return _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_NONE);
1373
1374         else if (len > 7)
1375                 return -EINVAL;
1376
1377         _bt_hfp_get_device_manufacturer_req(device);
1378         return 0;
1379 }
1380
1381 int _bt_hfp_get_imsi(bt_ag_info_t *device, const char *buf)
1382 {
1383         int len = strlen(buf);
1384         DBG_SECURE("Buf %s", buf);
1385
1386         if (len == 7)
1387                 _bt_hfp_get_imsi_req(device);
1388         else
1389                 _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_INVALID_INDEX);
1390
1391         return 0;
1392 }
1393
1394 int _bt_hfp_get_creg_status(bt_ag_info_t *device, const char *buf)
1395 {
1396         int len = strlen(buf);
1397         DBG_SECURE("buf %s", buf);
1398         if (len < 7 || len > 9)
1399                 return -EINVAL;
1400         else if (len == 7)
1401                 _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_INVALID_INDEX);
1402         else if (buf[7] == '=')
1403                 _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_INVALID_INDEX);
1404         else if (buf[7] == '?')
1405                 _bt_hfp_get_creg_status_req(device);
1406
1407         return 0;
1408 }
1409 int _bt_hfp_get_revision_info_rsp(void *t_device, char *revision,
1410                                                 bt_hfp_agent_error_t err)
1411 {
1412         if (revision)
1413                 _bt_ag_send_foreach_headset(active_devices, __bt_hfp_cmp,
1414                 "\r\n+CGMR: %s\r\n", revision);
1415         return _bt_ag_send_response(t_device, err);
1416 }
1417
1418 int _bt_hfp_get_revision_information(bt_ag_info_t *device, const char *buf)
1419 {
1420         int len = strlen(buf);
1421
1422         if (len == 9 && buf[7] == '=' && buf[8] == '?')  /* AT+CGMR=? */
1423                 return _bt_ag_send_response(device, HFP_STATE_MNGR_ERR_NONE);
1424
1425         else if (len > 7)
1426                 return -EINVAL;
1427
1428         _bt_hfp_get_revision_info_req(device);
1429         return 0;
1430 }