Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / android / client / if-bt.c
1 /*
2  * Copyright (C) 2013 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <string.h>
19 #include <inttypes.h>
20
21 #include "if-main.h"
22 #include "terminal.h"
23 #include "../hal-msg.h"
24 #include "../hal-utils.h"
25
26 static hw_device_t *bt_device;
27 const bt_interface_t *if_bluetooth;
28
29 #define VERIFY_PROP_TYPE_ARG(n, typ) \
30         do { \
31                 if (n < argc) \
32                         typ = str2btpropertytype(argv[n]); \
33                 else { \
34                         haltest_error("No property type specified\n"); \
35                         return;\
36                 } \
37         } while (0)
38
39 static bt_scan_mode_t str2btscanmode(const char *str)
40 {
41         bt_scan_mode_t v = str2bt_scan_mode_t(str);
42
43         if ((int) v != -1)
44                 return v;
45
46         haltest_warn("WARN: %s cannot convert %s\n", __func__, str);
47         return (bt_scan_mode_t) atoi(str);
48 }
49
50 static bt_ssp_variant_t str2btsspvariant(const char *str)
51 {
52         bt_ssp_variant_t v = str2bt_ssp_variant_t(str);
53
54         if ((int) v != -1)
55                 return v;
56
57         haltest_warn("WARN: %s cannot convert %s\n", __func__, str);
58         return (bt_ssp_variant_t) atoi(str);
59 }
60
61 static bt_property_type_t str2btpropertytype(const char *str)
62 {
63         bt_property_type_t v = str2bt_property_type_t(str);
64
65         if ((int) v != -1)
66                 return v;
67
68         haltest_warn("WARN: %s cannot convert %s\n", __func__, str);
69         return (bt_property_type_t) atoi(str);
70 }
71
72 static void dump_properties(int num_properties, bt_property_t *properties)
73 {
74         int i;
75
76         for (i = 0; i < num_properties; i++) {
77                 /*
78                  * properities sometimes come unaligned hence memcp to
79                  * aligned buffer
80                  */
81                 bt_property_t prop;
82                 memcpy(&prop, properties + i, sizeof(prop));
83
84                 haltest_info("prop: %s\n", btproperty2str(&prop));
85         }
86 }
87
88 /* Cache for remote devices, stored in sorted array */
89 static bt_bdaddr_t *remote_devices = NULL;
90 static int remote_devices_cnt = 0;
91 static int remote_devices_capacity = 0;
92
93 /* Adds address to remote device set so it can be used in tab completion */
94 void add_remote_device(const bt_bdaddr_t *addr)
95 {
96         int i;
97
98         if (remote_devices == NULL) {
99                 remote_devices = malloc(4 * sizeof(bt_bdaddr_t));
100                 remote_devices_cnt = 0;
101                 if (remote_devices == NULL) {
102                         remote_devices_capacity = 0;
103                         return;
104                 }
105
106                 remote_devices_capacity = 4;
107         }
108
109         /* Array is sorted, search for right place */
110         for (i = 0; i < remote_devices_cnt; ++i) {
111                 int res = memcmp(&remote_devices[i], addr, sizeof(*addr));
112
113                 if (res == 0)
114                         return; /* Already added */
115                 else if (res > 0)
116                         break;
117         }
118
119         /* Realloc space if needed */
120         if (remote_devices_cnt >= remote_devices_capacity) {
121                 bt_bdaddr_t *tmp;
122
123                 remote_devices_capacity *= 2;
124                 /*
125                  * Save reference to previously allocated memory block so that
126                  * it can be freed in case realloc fails.
127                  */
128                 tmp = remote_devices;
129
130                 remote_devices = realloc(remote_devices, sizeof(bt_bdaddr_t) *
131                                                 remote_devices_capacity);
132                 if (remote_devices == NULL) {
133                         free(tmp);
134                         remote_devices_capacity = 0;
135                         remote_devices_cnt = 0;
136                         return;
137                 }
138         }
139
140         if (i < remote_devices_cnt)
141                 memmove(remote_devices + i + 1, remote_devices + i,
142                                 (remote_devices_cnt - i) * sizeof(bt_bdaddr_t));
143         remote_devices[i] = *addr;
144         remote_devices_cnt++;
145 }
146
147 const char *enum_devices(void *v, int i)
148 {
149         static char buf[MAX_ADDR_STR_LEN];
150
151         if (i >= remote_devices_cnt)
152                 return NULL;
153
154         bt_bdaddr_t2str(&remote_devices[i], buf);
155         return buf;
156 }
157
158 static void add_remote_device_from_props(int num_properties,
159                                                 const bt_property_t *properties)
160 {
161         int i;
162
163         for (i = 0; i < num_properties; i++) {
164                 /*
165                  * properities sometimes come unaligned hence memcp to
166                  * aligned buffer
167                  */
168                 bt_property_t property;
169
170                 memcpy(&property, properties + i, sizeof(property));
171                 if (property.type == BT_PROPERTY_BDADDR)
172                         add_remote_device((bt_bdaddr_t *) property.val);
173         }
174 }
175
176 bool close_hw_bt_dev(void)
177 {
178         if (!bt_device)
179                 return false;
180
181         bt_device->close(bt_device);
182         return true;
183 }
184
185 static void adapter_state_changed_cb(bt_state_t state)
186 {
187         haltest_info("%s: state=%s\n", __func__, bt_state_t2str(state));
188 }
189
190 static void adapter_properties_cb(bt_status_t status, int num_properties,
191                                                 bt_property_t *properties)
192 {
193         haltest_info("%s: status=%s num_properties=%d\n", __func__,
194                                 bt_status_t2str(status), num_properties);
195
196         dump_properties(num_properties, properties);
197 }
198
199 static void remote_device_properties_cb(bt_status_t status,
200                                         bt_bdaddr_t *bd_addr,
201                                         int num_properties,
202                                         bt_property_t *properties)
203 {
204         haltest_info("%s: status=%s bd_addr=%s num_properties=%d\n", __func__,
205                         bt_status_t2str(status), bdaddr2str(bd_addr),
206                         num_properties);
207
208         add_remote_device(bd_addr);
209
210         dump_properties(num_properties, properties);
211 }
212
213 static void device_found_cb(int num_properties, bt_property_t *properties)
214 {
215         haltest_info("%s: num_properties=%d\n", __func__, num_properties);
216
217         add_remote_device_from_props(num_properties, properties);
218
219         dump_properties(num_properties, properties);
220 }
221
222 static void discovery_state_changed_cb(bt_discovery_state_t state)
223 {
224         haltest_info("%s: state=%s\n", __func__,
225                                         bt_discovery_state_t2str(state));
226 }
227
228 /*
229  * Buffer for remote addres that came from one of bind request.
230  * It's stored for command completion.
231  */
232 static char last_remote_addr[MAX_ADDR_STR_LEN];
233 static bt_ssp_variant_t last_ssp_variant = (bt_ssp_variant_t) -1;
234
235 static bt_bdaddr_t pin_request_addr;
236 static void pin_request_answer(char *reply)
237 {
238         bt_pin_code_t pin;
239         int accept = 0;
240         int pin_len = strlen(reply);
241
242         if (pin_len > 0) {
243                 accept = 1;
244                 if (pin_len > 16)
245                         pin_len = 16;
246                 memcpy(&pin.pin, reply, pin_len);
247         }
248
249         EXEC(if_bluetooth->pin_reply, &pin_request_addr, accept, pin_len, &pin);
250 }
251
252 static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
253                                                                 uint32_t cod)
254 {
255         /* Store for command completion */
256         bt_bdaddr_t2str(remote_bd_addr, last_remote_addr);
257         pin_request_addr = *remote_bd_addr;
258
259         haltest_info("%s: remote_bd_addr=%s bd_name=%s cod=%06x\n", __func__,
260                                         last_remote_addr, bd_name->name, cod);
261         terminal_prompt_for("Enter pin: ", pin_request_answer);
262 }
263
264 /* Variables to store information from ssp_request_cb used for ssp_reply */
265 static bt_bdaddr_t ssp_request_addr;
266 static bt_ssp_variant_t ssp_request_variant;
267 static uint32_t ssp_request_pask_key;
268
269 /* Called when user hit enter on prompt for confirmation */
270 static void ssp_request_yes_no_answer(char *reply)
271 {
272         int accept = *reply == 0 || *reply == 'y' || *reply == 'Y';
273
274         if_bluetooth->ssp_reply(&ssp_request_addr, ssp_request_variant, accept,
275                                                         ssp_request_pask_key);
276 }
277
278 static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
279                                 uint32_t cod, bt_ssp_variant_t pairing_variant,
280                                 uint32_t pass_key)
281 {
282         static char prompt[50];
283
284         /* Store for command completion */
285         bt_bdaddr_t2str(remote_bd_addr, last_remote_addr);
286         last_ssp_variant = pairing_variant;
287
288         haltest_info("%s: remote_bd_addr=%s bd_name=%s cod=%06x pairing_variant=%s pass_key=%d\n",
289                         __func__, last_remote_addr, bd_name->name, cod,
290                         bt_ssp_variant_t2str(pairing_variant), pass_key);
291
292         switch (pairing_variant) {
293         case BT_SSP_VARIANT_PASSKEY_CONFIRMATION:
294                 sprintf(prompt, "Does other device show %d [Y/n] ?", pass_key);
295
296                 ssp_request_addr = *remote_bd_addr;
297                 ssp_request_variant = pairing_variant;
298                 ssp_request_pask_key = pass_key;
299
300                 terminal_prompt_for(prompt, ssp_request_yes_no_answer);
301                 break;
302         case BT_SSP_VARIANT_CONSENT:
303                 sprintf(prompt, "Consent pairing [Y/n] ?");
304
305                 ssp_request_addr = *remote_bd_addr;
306                 ssp_request_variant = pairing_variant;
307                 ssp_request_pask_key = 0;
308
309                 terminal_prompt_for(prompt, ssp_request_yes_no_answer);
310                 break;
311         case BT_SSP_VARIANT_PASSKEY_ENTRY:
312         case BT_SSP_VARIANT_PASSKEY_NOTIFICATION:
313         default:
314                 haltest_info("Not automatically handled\n");
315                 break;
316         }
317 }
318
319 static void bond_state_changed_cb(bt_status_t status,
320                                                 bt_bdaddr_t *remote_bd_addr,
321                                                 bt_bond_state_t state)
322 {
323         haltest_info("%s: status=%s remote_bd_addr=%s state=%s\n", __func__,
324                         bt_status_t2str(status), bdaddr2str(remote_bd_addr),
325                         bt_bond_state_t2str(state));
326 }
327
328 static void acl_state_changed_cb(bt_status_t status,
329                                                 bt_bdaddr_t *remote_bd_addr,
330                                                 bt_acl_state_t state)
331 {
332         haltest_info("%s: status=%s remote_bd_addr=%s state=%s\n", __func__,
333                         bt_status_t2str(status), bdaddr2str(remote_bd_addr),
334                         bt_acl_state_t2str(state));
335 }
336
337 static void thread_evt_cb(bt_cb_thread_evt evt)
338 {
339         haltest_info("%s: evt=%s\n", __func__, bt_cb_thread_evt2str(evt));
340 }
341
342 static void dut_mode_recv_cb(uint16_t opcode, uint8_t *buf, uint8_t len)
343 {
344         haltest_info("%s\n", __func__);
345 }
346
347 static void le_test_mode_cb(bt_status_t status, uint16_t num_packets)
348 {
349         haltest_info("%s %s %d\n", __func__, bt_status_t2str(status),
350                                                                 num_packets);
351 }
352
353 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
354 static void energy_info_cb(bt_activity_energy_info *energy_info)
355 {
356         haltest_info("%s status=%s, ctrl_state=0x%02X, tx_time=0x%jx,"
357                         "rx_time=0x%jx, idle_time=0x%jx, energu_used=0x%jx\n",
358                         __func__, bt_status_t2str(energy_info->status),
359                         energy_info->ctrl_state, energy_info->tx_time,
360                         energy_info->rx_time, energy_info->idle_time,
361                         energy_info->energy_used);
362 }
363 #endif
364
365 static bt_callbacks_t bt_callbacks = {
366         .size = sizeof(bt_callbacks),
367         .adapter_state_changed_cb = adapter_state_changed_cb,
368         .adapter_properties_cb = adapter_properties_cb,
369         .remote_device_properties_cb = remote_device_properties_cb,
370         .device_found_cb = device_found_cb,
371         .discovery_state_changed_cb = discovery_state_changed_cb,
372         .pin_request_cb = pin_request_cb,
373         .ssp_request_cb = ssp_request_cb,
374         .bond_state_changed_cb = bond_state_changed_cb,
375         .acl_state_changed_cb = acl_state_changed_cb,
376         .thread_evt_cb = thread_evt_cb,
377         .dut_mode_recv_cb = dut_mode_recv_cb,
378         .le_test_mode_cb = le_test_mode_cb,
379 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
380         .energy_info_cb = energy_info_cb,
381 #endif
382 };
383
384 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
385 static alarm_cb alarm_cb_p = NULL;
386 static void *alarm_cb_p_data = NULL;
387
388 static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb,
389                                                                 void *data)
390 {
391         haltest_info("%s: delay %"PRIu64" should_wake %u cb %p data %p\n",
392                                 __func__, delay_millis, should_wake, cb, data);
393
394         /* TODO call alarm callback after specified delay */
395         alarm_cb_p = cb;
396         alarm_cb_p_data = data;
397
398         return true;
399 }
400
401 static int acquire_wake_lock(const char *lock_name)
402 {
403         haltest_info("%s: %s\n", __func__, lock_name);
404
405         return BT_STATUS_SUCCESS;
406 }
407
408 static int release_wake_lock(const char *lock_name)
409 {
410         haltest_info("%s: %s\n", __func__, lock_name);
411
412         return BT_STATUS_SUCCESS;
413 }
414
415 static bt_os_callouts_t bt_os_callouts = {
416         .size = sizeof(bt_os_callouts),
417         .set_wake_alarm = set_wake_alarm,
418         .acquire_wake_lock = acquire_wake_lock,
419         .release_wake_lock = release_wake_lock,
420 };
421 #endif
422
423 static void init_p(int argc, const char **argv)
424 {
425         int err;
426         const hw_module_t *module;
427
428         err = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
429         if (err) {
430                 haltest_error("he_get_module returned %d\n", err);
431                 return;
432         }
433
434         err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &bt_device);
435         if (err) {
436                 haltest_error("module->methods->open returned %d\n", err);
437                 return;
438         }
439
440         if_bluetooth =
441                 ((bluetooth_device_t *) bt_device)->get_bluetooth_interface();
442         if (!if_bluetooth) {
443                 haltest_error("get_bluetooth_interface returned NULL\n");
444                 return;
445         }
446
447         EXEC(if_bluetooth->init, &bt_callbacks);
448
449 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
450         EXEC(if_bluetooth->set_os_callouts, &bt_os_callouts);
451 #endif
452 }
453
454 static void cleanup_p(int argc, const char **argv)
455 {
456         RETURN_IF_NULL(if_bluetooth);
457
458         EXECV(if_bluetooth->cleanup);
459
460         if_bluetooth = NULL;
461 }
462
463 static void enable_p(int argc, const char **argv)
464 {
465         RETURN_IF_NULL(if_bluetooth);
466
467         EXEC(if_bluetooth->enable);
468 }
469 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
470 static void read_energy_info_p(int argc, const char **argv)
471 {
472         RETURN_IF_NULL(if_bluetooth);
473
474         EXEC(if_bluetooth->read_energy_info);
475 }
476
477 #define get_connection_state_c complete_addr_c
478
479 static void get_connection_state_p(int argc, const char **argv)
480 {
481         bt_bdaddr_t addr;
482
483         RETURN_IF_NULL(if_bluetooth);
484
485         VERIFY_ADDR_ARG(2, &addr);
486
487         haltest_info("if_bluetooth->get_connection_state : %d\n",
488                                 if_bluetooth->get_connection_state(&addr));
489 }
490 #endif
491
492 static void disable_p(int argc, const char **argv)
493 {
494         RETURN_IF_NULL(if_bluetooth);
495
496         EXEC(if_bluetooth->disable);
497 }
498
499 static void get_adapter_properties_p(int argc, const char **argv)
500 {
501         RETURN_IF_NULL(if_bluetooth);
502
503         EXEC(if_bluetooth->get_adapter_properties);
504 }
505
506 static void get_adapter_property_c(int argc, const char **argv,
507                                         enum_func *enum_func, void **user)
508 {
509         if (argc == 3) {
510                 *user = TYPE_ENUM(bt_property_type_t);
511                 *enum_func = enum_defines;
512         }
513 }
514
515 static void get_adapter_property_p(int argc, const char **argv)
516 {
517         int type;
518
519         RETURN_IF_NULL(if_bluetooth);
520         VERIFY_PROP_TYPE_ARG(2, type);
521
522         EXEC(if_bluetooth->get_adapter_property, type);
523 }
524
525 static const char * const names[] = {
526         "BT_PROPERTY_BDNAME",
527         "BT_PROPERTY_ADAPTER_SCAN_MODE",
528         "BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT",
529         NULL
530 };
531
532 static void set_adapter_property_c(int argc, const char **argv,
533                                         enum_func *enum_func, void **user)
534 {
535         if (argc == 3) {
536                 *user = (void *) names;
537                 *enum_func = enum_strings;
538         } else if (argc == 4) {
539                 if (0 == strcmp(argv[2], "BT_PROPERTY_ADAPTER_SCAN_MODE")) {
540                         *user = TYPE_ENUM(bt_scan_mode_t);
541                         *enum_func = enum_defines;
542                 }
543         }
544 }
545
546 static void set_adapter_property_p(int argc, const char **argv)
547 {
548         bt_property_t property;
549         bt_scan_mode_t mode;
550         int timeout;
551
552         RETURN_IF_NULL(if_bluetooth);
553         VERIFY_PROP_TYPE_ARG(2, property.type);
554
555         if (argc <= 3) {
556                 haltest_error("No property value specified\n");
557                 return;
558         }
559         switch (property.type) {
560         case BT_PROPERTY_BDNAME:
561                 property.len = strlen(argv[3]) + 1;
562                 property.val = (char *) argv[3];
563                 break;
564
565         case BT_PROPERTY_ADAPTER_SCAN_MODE:
566                 mode = str2btscanmode(argv[3]);
567                 property.len = sizeof(bt_scan_mode_t);
568                 property.val = &mode;
569                 break;
570
571         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
572                 timeout = atoi(argv[3]);
573                 property.val = &timeout;
574                 property.len = sizeof(timeout);
575                 break;
576
577         case BT_PROPERTY_BDADDR:
578         case BT_PROPERTY_UUIDS:
579         case BT_PROPERTY_CLASS_OF_DEVICE:
580         case BT_PROPERTY_TYPE_OF_DEVICE:
581         case BT_PROPERTY_SERVICE_RECORD:
582         case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
583         case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
584         case BT_PROPERTY_REMOTE_RSSI:
585         case BT_PROPERTY_REMOTE_VERSION_INFO:
586         case BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP:
587 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
588         case BT_PROPERTY_LOCAL_LE_FEATURES:
589 #endif
590         default:
591                 haltest_error("Invalid property %s\n", argv[3]);
592                 return;
593         }
594
595         EXEC(if_bluetooth->set_adapter_property, &property);
596 }
597
598 /* This function is to be used for completion methods that need only address */
599 static void complete_addr_c(int argc, const char **argv, enum_func *enum_func,
600                                                                 void **user)
601 {
602         if (argc == 3) {
603                 *user = NULL;
604                 *enum_func = enum_devices;
605         }
606 }
607
608 /* Just addres to complete, use complete_addr_c */
609 #define get_remote_device_properties_c complete_addr_c
610
611 static void get_remote_device_properties_p(int argc, const char **argv)
612 {
613         bt_bdaddr_t addr;
614
615         RETURN_IF_NULL(if_bluetooth);
616         VERIFY_ADDR_ARG(2, &addr);
617
618         EXEC(if_bluetooth->get_remote_device_properties, &addr);
619 }
620
621 static void get_remote_device_property_c(int argc, const char **argv,
622                                                         enum_func *enum_func,
623                                                         void **user)
624 {
625         if (argc == 3) {
626                 *user = NULL;
627                 *enum_func = enum_devices;
628         } else if (argc == 4) {
629                 *user = TYPE_ENUM(bt_property_type_t);
630                 *enum_func = enum_defines;
631         }
632 }
633
634 static void get_remote_device_property_p(int argc, const char **argv)
635 {
636         bt_property_type_t type;
637         bt_bdaddr_t addr;
638
639         RETURN_IF_NULL(if_bluetooth);
640         VERIFY_ADDR_ARG(2, &addr);
641         VERIFY_PROP_TYPE_ARG(3, type);
642
643         EXEC(if_bluetooth->get_remote_device_property, &addr, type);
644 }
645
646 /*
647  * Same completion as for get_remote_device_property_c can be used for
648  * set_remote_device_property_c. No need to create separate function.
649  */
650 #define set_remote_device_property_c get_remote_device_property_c
651
652 static void set_remote_device_property_p(int argc, const char **argv)
653 {
654         bt_property_t property;
655         bt_bdaddr_t addr;
656
657         RETURN_IF_NULL(if_bluetooth);
658         VERIFY_ADDR_ARG(2, &addr);
659         VERIFY_PROP_TYPE_ARG(3, property.type);
660
661         switch (property.type) {
662         case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
663                 property.len = strlen(argv[4]);
664                 property.val = (char *) argv[4];
665                 break;
666         case BT_PROPERTY_BDNAME:
667         case BT_PROPERTY_BDADDR:
668         case BT_PROPERTY_UUIDS:
669         case BT_PROPERTY_CLASS_OF_DEVICE:
670         case BT_PROPERTY_TYPE_OF_DEVICE:
671         case BT_PROPERTY_SERVICE_RECORD:
672         case BT_PROPERTY_ADAPTER_SCAN_MODE:
673         case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
674         case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
675         case BT_PROPERTY_REMOTE_RSSI:
676         case BT_PROPERTY_REMOTE_VERSION_INFO:
677         case BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP:
678 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
679         case BT_PROPERTY_LOCAL_LE_FEATURES:
680 #endif
681         default:
682                 return;
683         }
684
685         EXEC(if_bluetooth->set_remote_device_property, &addr, &property);
686 }
687
688 /* For now uuid is not autocompleted. Use routine for complete_addr_c */
689 #define get_remote_service_record_c complete_addr_c
690
691 static void get_remote_service_record_p(int argc, const char **argv)
692 {
693         bt_bdaddr_t addr;
694         bt_uuid_t uuid;
695
696         RETURN_IF_NULL(if_bluetooth);
697         VERIFY_ADDR_ARG(2, &addr);
698
699         if (argc <= 3) {
700                 haltest_error("No uuid specified\n");
701                 return;
702         }
703
704         str2bt_uuid_t(argv[3], &uuid);
705
706         EXEC(if_bluetooth->get_remote_service_record, &addr, &uuid);
707 }
708
709 /* Just addres to complete, use complete_addr_c */
710 #define get_remote_services_c complete_addr_c
711
712 static void get_remote_services_p(int argc, const char **argv)
713 {
714         bt_bdaddr_t addr;
715
716         RETURN_IF_NULL(if_bluetooth);
717         VERIFY_ADDR_ARG(2, &addr);
718
719         EXEC(if_bluetooth->get_remote_services, &addr);
720 }
721
722 static void start_discovery_p(int argc, const char **argv)
723 {
724         RETURN_IF_NULL(if_bluetooth);
725
726         EXEC(if_bluetooth->start_discovery);
727 }
728
729 static void cancel_discovery_p(int argc, const char **argv)
730 {
731         RETURN_IF_NULL(if_bluetooth);
732
733         EXEC(if_bluetooth->cancel_discovery);
734 }
735
736 /* Just addres to complete, use complete_addr_c */
737 #define create_bond_c complete_addr_c
738
739 static void create_bond_p(int argc, const char **argv)
740 {
741         bt_bdaddr_t addr;
742 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
743         int transport;
744 #endif
745
746         RETURN_IF_NULL(if_bluetooth);
747         VERIFY_ADDR_ARG(2, &addr);
748
749 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
750         if (argc < 4)
751                 transport = BT_TRANSPORT_UNKNOWN;
752         else
753                 transport = atoi(argv[3]);
754
755         EXEC(if_bluetooth->create_bond, &addr, transport);
756 #else
757         EXEC(if_bluetooth->create_bond, &addr);
758 #endif
759 }
760
761 /* Just addres to complete, use complete_addr_c */
762 #define remove_bond_c complete_addr_c
763
764 static void remove_bond_p(int argc, const char **argv)
765 {
766         bt_bdaddr_t addr;
767
768         RETURN_IF_NULL(if_bluetooth);
769         VERIFY_ADDR_ARG(2, &addr);
770
771         EXEC(if_bluetooth->remove_bond, &addr);
772 }
773
774 /* Just addres to complete, use complete_addr_c */
775 #define cancel_bond_c complete_addr_c
776
777 static void cancel_bond_p(int argc, const char **argv)
778 {
779         bt_bdaddr_t addr;
780
781         RETURN_IF_NULL(if_bluetooth);
782         VERIFY_ADDR_ARG(2, &addr);
783
784         EXEC(if_bluetooth->cancel_bond, &addr);
785 }
786
787 static void pin_reply_c(int argc, const char **argv, enum_func *enum_func,
788                                                                 void **user)
789 {
790         static const char *const completions[] = { last_remote_addr, NULL };
791
792         if (argc == 3) {
793                 *user = (void *) completions;
794                 *enum_func = enum_strings;
795         }
796 }
797
798 static void pin_reply_p(int argc, const char **argv)
799 {
800         bt_bdaddr_t addr;
801         bt_pin_code_t pin;
802         int pin_len = 0;
803         int accept = 0;
804
805         RETURN_IF_NULL(if_bluetooth);
806         VERIFY_ADDR_ARG(2, &addr);
807
808         if (argc > 3) {
809                 accept = 1;
810                 pin_len = strlen(argv[3]);
811                 memcpy(pin.pin, argv[3], pin_len);
812         }
813
814         EXEC(if_bluetooth->pin_reply, &addr, accept, pin_len, &pin);
815 }
816
817 static void ssp_reply_c(int argc, const char **argv, enum_func *enum_func,
818                                                                 void **user)
819 {
820         if (argc == 3) {
821                 *user = last_remote_addr;
822                 *enum_func = enum_one_string;
823         } else if (argc == 5) {
824                 *user = "1";
825                 *enum_func = enum_one_string;
826         } else if (argc == 4) {
827                 if (-1 != (int) last_ssp_variant) {
828                         *user = (void *) bt_ssp_variant_t2str(last_ssp_variant);
829                         *enum_func = enum_one_string;
830                 } else {
831                         *user = TYPE_ENUM(bt_ssp_variant_t);
832                         *enum_func = enum_defines;
833                 }
834         }
835 }
836
837 static void ssp_reply_p(int argc, const char **argv)
838 {
839         bt_bdaddr_t addr;
840         bt_ssp_variant_t var;
841         int accept;
842         int passkey;
843
844         RETURN_IF_NULL(if_bluetooth);
845         VERIFY_ADDR_ARG(2, &addr);
846
847         if (argc < 4) {
848                 haltest_error("No ssp variant specified\n");
849                 return;
850         }
851
852         var = str2btsspvariant(argv[3]);
853         if (argc < 5) {
854                 haltest_error("No accept value specified\n");
855                 return;
856         }
857
858         accept = atoi(argv[4]);
859         passkey = 0;
860
861         if (accept && var == BT_SSP_VARIANT_PASSKEY_ENTRY && argc >= 5)
862                 passkey = atoi(argv[4]);
863
864         EXEC(if_bluetooth->ssp_reply, &addr, var, accept, passkey);
865 }
866
867 static void get_profile_interface_c(int argc, const char **argv,
868                                         enum_func *enum_func, void **user)
869 {
870         static const char *const profile_ids[] = {
871                 BT_PROFILE_HANDSFREE_ID,
872                 BT_PROFILE_ADVANCED_AUDIO_ID,
873                 BT_PROFILE_HEALTH_ID,
874                 BT_PROFILE_SOCKETS_ID,
875                 BT_PROFILE_HIDHOST_ID,
876                 BT_PROFILE_PAN_ID,
877                 BT_PROFILE_GATT_ID,
878                 BT_PROFILE_AV_RC_ID,
879 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
880                 BT_PROFILE_HANDSFREE_CLIENT_ID,
881                 BT_PROFILE_MAP_CLIENT_ID,
882                 BT_PROFILE_AV_RC_CTRL_ID,
883                 BT_PROFILE_ADVANCED_AUDIO_SINK_ID,
884 #endif
885                 NULL
886         };
887
888         if (argc == 3) {
889                 *user = (void *) profile_ids;
890                 *enum_func = enum_strings;
891         }
892 }
893
894 static void get_profile_interface_p(int argc, const char **argv)
895 {
896         const char *id;
897         const void **pif = NULL;
898
899         RETURN_IF_NULL(if_bluetooth);
900         if (argc <= 2) {
901                 haltest_error("No interface specified\n");
902                 return;
903         }
904
905         id = argv[2];
906
907         if (strcmp(BT_PROFILE_HANDSFREE_ID, id) == 0)
908                 pif = (const void **) &if_hf;
909         else if (strcmp(BT_PROFILE_ADVANCED_AUDIO_ID, id) == 0)
910                 pif = (const void **) &if_av;
911         else if (strcmp(BT_PROFILE_HEALTH_ID, id) == 0)
912                 pif = (const void **) &if_hl;
913         else if (strcmp(BT_PROFILE_SOCKETS_ID, id) == 0)
914                 pif = (const void **) &if_sock;
915         else if (strcmp(BT_PROFILE_HIDHOST_ID, id) == 0)
916                 pif = (const void **) &if_hh;
917         else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
918                 pif = (const void **) &if_pan;
919         else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
920                 pif = (const void **) &if_rc;
921         else if (strcmp(BT_PROFILE_GATT_ID, id) == 0)
922                 pif = (const void **) &if_gatt;
923 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
924         else if (strcmp(BT_PROFILE_AV_RC_CTRL_ID, id) == 0)
925                 pif = (const void **) &if_rc_ctrl;
926         else if (strcmp(BT_PROFILE_HANDSFREE_CLIENT_ID, id) == 0)
927                 pif = (const void **) &if_hf_client;
928         else if (strcmp(BT_PROFILE_MAP_CLIENT_ID, id) == 0)
929                 pif = (const void **) &if_mce;
930         else if (strcmp(BT_PROFILE_ADVANCED_AUDIO_SINK_ID, id) == 0)
931                 pif = (const void **) &if_av_sink;
932 #endif
933         else
934                 haltest_error("%s is not correct for get_profile_interface\n",
935                                                                         id);
936
937         if (pif != NULL) {
938                 *pif = if_bluetooth->get_profile_interface(id);
939                 haltest_info("get_profile_interface(%s) : %p\n", id, *pif);
940         }
941 }
942
943 static void dut_mode_configure_p(int argc, const char **argv)
944 {
945         uint8_t mode;
946
947         RETURN_IF_NULL(if_bluetooth);
948
949         if (argc <= 2) {
950                 haltest_error("No dut mode specified\n");
951                 return;
952         }
953
954         mode = strtol(argv[2], NULL, 0);
955
956         EXEC(if_bluetooth->dut_mode_configure, mode);
957 }
958
959 static void dut_mode_send_p(int argc, const char **argv)
960 {
961         haltest_error("not implemented\n");
962 }
963
964 static void le_test_mode_p(int argc, const char **argv)
965 {
966         haltest_error("not implemented\n");
967 }
968
969 static void config_hci_snoop_log_p(int argc, const char **argv)
970 {
971         uint8_t mode;
972
973         RETURN_IF_NULL(if_bluetooth);
974
975         if (argc <= 2) {
976                 haltest_error("No mode specified\n");
977                 return;
978         }
979
980         mode = strtol(argv[2], NULL, 0);
981
982         EXEC(if_bluetooth->config_hci_snoop_log, mode);
983 }
984
985 static struct method methods[] = {
986         STD_METHOD(init),
987         STD_METHOD(cleanup),
988         STD_METHOD(enable),
989         STD_METHOD(disable),
990         STD_METHOD(get_adapter_properties),
991         STD_METHODCH(get_adapter_property, "<prop_type>"),
992         STD_METHODCH(set_adapter_property, "<prop_type> <prop_value>"),
993         STD_METHODCH(get_remote_device_properties, "<addr>"),
994         STD_METHODCH(get_remote_device_property, "<addr> <property_type>"),
995         STD_METHODCH(set_remote_device_property,
996                                         "<addr> <property_type> <value>"),
997         STD_METHODCH(get_remote_service_record, "<addr> <uuid>"),
998         STD_METHODCH(get_remote_services, "<addr>"),
999         STD_METHOD(start_discovery),
1000         STD_METHOD(cancel_discovery),
1001 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
1002         STD_METHODCH(create_bond, "<addr> [<transport>]"),
1003         STD_METHOD(read_energy_info),
1004         STD_METHODCH(get_connection_state, "<addr>"),
1005 #else
1006         STD_METHODCH(create_bond, "<addr>"),
1007 #endif
1008         STD_METHODCH(remove_bond, "<addr>"),
1009         STD_METHODCH(cancel_bond, "<addr>"),
1010         STD_METHODCH(pin_reply, "<address> [<pin>]"),
1011         STD_METHODCH(ssp_reply, "<address> <ssp_veriant> 1|0 [<passkey>]"),
1012         STD_METHODCH(get_profile_interface, "<profile id>"),
1013         STD_METHODH(dut_mode_configure, "<dut mode>"),
1014         STD_METHOD(dut_mode_send),
1015         STD_METHOD(le_test_mode),
1016         STD_METHODH(config_hci_snoop_log, "<mode>"),
1017         END_METHOD
1018 };
1019
1020 const struct interface bluetooth_if = {
1021         .name = "bluetooth",
1022         .methods = methods
1023 };