3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2013 Intel Corporation. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include "lib/bluetooth.h"
39 #include "monitor/bt.h"
40 #include "emulator/bthost.h"
41 #include "emulator/hciemu.h"
43 #include "src/shared/tester.h"
44 #include "src/shared/mgmt.h"
47 const void *test_data;
50 struct hciemu *hciemu;
51 enum hciemu_type hciemu_type;
56 struct sco_client_data {
60 static void mgmt_debug(const char *str, void *user_data)
62 const char *prefix = user_data;
64 tester_print("%s%s", prefix, str);
67 static void read_info_callback(uint8_t status, uint16_t length,
68 const void *param, void *user_data)
70 struct test_data *data = tester_get_data();
71 const struct mgmt_rp_read_info *rp = param;
73 uint16_t manufacturer;
74 uint32_t supported_settings, current_settings;
76 tester_print("Read Info callback");
77 tester_print(" Status: 0x%02x", status);
79 if (status || !param) {
80 tester_pre_setup_failed();
84 ba2str(&rp->bdaddr, addr);
85 manufacturer = btohs(rp->manufacturer);
86 supported_settings = btohl(rp->supported_settings);
87 current_settings = btohl(rp->current_settings);
89 tester_print(" Address: %s", addr);
90 tester_print(" Version: 0x%02x", rp->version);
91 tester_print(" Manufacturer: 0x%04x", manufacturer);
92 tester_print(" Supported settings: 0x%08x", supported_settings);
93 tester_print(" Current settings: 0x%08x", current_settings);
94 tester_print(" Class: 0x%02x%02x%02x",
95 rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
96 tester_print(" Name: %s", rp->name);
97 tester_print(" Short name: %s", rp->short_name);
99 if (strcmp(hciemu_get_address(data->hciemu), addr)) {
100 tester_pre_setup_failed();
104 tester_pre_setup_complete();
107 static void index_added_callback(uint16_t index, uint16_t length,
108 const void *param, void *user_data)
110 struct test_data *data = tester_get_data();
112 tester_print("Index Added callback");
113 tester_print(" Index: 0x%04x", index);
115 data->mgmt_index = index;
117 mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
118 read_info_callback, NULL, NULL);
121 static void index_removed_callback(uint16_t index, uint16_t length,
122 const void *param, void *user_data)
124 struct test_data *data = tester_get_data();
126 tester_print("Index Removed callback");
127 tester_print(" Index: 0x%04x", index);
129 if (index != data->mgmt_index)
132 mgmt_unregister_index(data->mgmt, data->mgmt_index);
134 mgmt_unref(data->mgmt);
137 tester_post_teardown_complete();
140 static void read_index_list_callback(uint8_t status, uint16_t length,
141 const void *param, void *user_data)
143 struct test_data *data = tester_get_data();
145 tester_print("Read Index List callback");
146 tester_print(" Status: 0x%02x", status);
148 if (status || !param) {
149 tester_pre_setup_failed();
153 mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
154 index_added_callback, NULL, NULL);
156 mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
157 index_removed_callback, NULL, NULL);
159 data->hciemu = hciemu_new(HCIEMU_TYPE_BREDRLE);
161 tester_warn("Failed to setup HCI emulation");
162 tester_pre_setup_failed();
165 tester_print("New hciemu instance created");
167 if (data->disable_esco) {
170 tester_print("Disabling eSCO packet type support");
172 features = hciemu_get_features(data->hciemu);
174 features[3] &= ~0x80;
178 static void test_pre_setup(const void *test_data)
180 struct test_data *data = tester_get_data();
182 data->mgmt = mgmt_new_default();
184 tester_warn("Failed to setup management interface");
185 tester_pre_setup_failed();
189 if (tester_use_debug())
190 mgmt_set_debug(data->mgmt, mgmt_debug, "mgmt: ", NULL);
192 mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL,
193 read_index_list_callback, NULL, NULL);
196 static void test_post_teardown(const void *test_data)
198 struct test_data *data = tester_get_data();
200 hciemu_unref(data->hciemu);
204 static void test_data_free(void *test_data)
206 struct test_data *data = test_data;
209 g_source_remove(data->io_id);
214 #define test_sco_full(name, data, setup, func, _disable_esco) \
216 struct test_data *user; \
217 user = malloc(sizeof(struct test_data)); \
220 user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
222 user->test_data = data; \
223 user->disable_esco = _disable_esco; \
224 tester_add_full(name, data, \
225 test_pre_setup, setup, func, NULL, \
226 test_post_teardown, 2, user, test_data_free); \
229 #define test_sco(name, data, setup, func) \
230 test_sco_full(name, data, setup, func, false)
232 #define test_sco_11(name, data, setup, func) \
233 test_sco_full(name, data, setup, func, true)
235 static const struct sco_client_data connect_success = {
239 static const struct sco_client_data connect_failure = {
240 .expect_err = EOPNOTSUPP
243 static void client_connectable_complete(uint16_t opcode, uint8_t status,
244 const void *param, uint8_t len,
247 if (opcode != BT_HCI_CMD_WRITE_SCAN_ENABLE)
250 tester_print("Client set connectable status 0x%02x", status);
253 tester_setup_failed();
255 tester_setup_complete();
258 static void setup_powered_callback(uint8_t status, uint16_t length,
259 const void *param, void *user_data)
261 struct test_data *data = tester_get_data();
262 struct bthost *bthost;
264 if (status != MGMT_STATUS_SUCCESS) {
265 tester_setup_failed();
269 tester_print("Controller powered on");
271 bthost = hciemu_client_get_host(data->hciemu);
272 bthost_set_cmd_complete_cb(bthost, client_connectable_complete, data);
273 bthost_write_scan_enable(bthost, 0x03);
276 static void setup_powered(const void *test_data)
278 struct test_data *data = tester_get_data();
279 unsigned char param[] = { 0x01 };
281 tester_print("Powering on controller");
283 mgmt_send(data->mgmt, MGMT_OP_SET_CONNECTABLE, data->mgmt_index,
284 sizeof(param), param,
287 mgmt_send(data->mgmt, MGMT_OP_SET_SSP, data->mgmt_index,
288 sizeof(param), param, NULL, NULL, NULL);
290 mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index,
291 sizeof(param), param, NULL, NULL, NULL);
293 mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
294 sizeof(param), param,
295 setup_powered_callback, NULL, NULL);
298 static void test_framework(const void *test_data)
300 tester_test_passed();
303 static void test_socket(const void *test_data)
307 sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
309 tester_warn("Can't create socket: %s (%d)", strerror(errno),
311 tester_test_failed();
317 tester_test_passed();
320 static void test_getsockopt(const void *test_data)
324 struct bt_voice voice;
326 sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
328 tester_warn("Can't create socket: %s (%d)", strerror(errno),
330 tester_test_failed();
335 memset(&voice, 0, len);
337 err = getsockopt(sk, SOL_BLUETOOTH, BT_VOICE, &voice, &len);
339 tester_warn("Can't get socket option : %s (%d)",
340 strerror(errno), errno);
341 tester_test_failed();
345 if (voice.setting != BT_VOICE_CVSD_16BIT) {
346 tester_warn("Invalid voice setting");
347 tester_test_failed();
351 tester_test_passed();
357 static void test_setsockopt(const void *test_data)
361 struct bt_voice voice;
363 sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
365 tester_warn("Can't create socket: %s (%d)", strerror(errno),
367 tester_test_failed();
373 memset(&voice, 0, len);
375 err = getsockopt(sk, SOL_BLUETOOTH, BT_VOICE, &voice, &len);
377 tester_warn("Can't get socket option : %s (%d)",
378 strerror(errno), errno);
379 tester_test_failed();
383 if (voice.setting != BT_VOICE_CVSD_16BIT) {
384 tester_warn("Invalid voice setting");
385 tester_test_failed();
389 memset(&voice, 0, sizeof(voice));
390 voice.setting = BT_VOICE_TRANSPARENT;
392 err = setsockopt(sk, SOL_BLUETOOTH, BT_VOICE, &voice, sizeof(voice));
394 tester_warn("Can't set socket option : %s (%d)",
395 strerror(errno), errno);
396 tester_test_failed();
401 memset(&voice, 0, len);
403 err = getsockopt(sk, SOL_BLUETOOTH, BT_VOICE, &voice, &len);
405 tester_warn("Can't get socket option : %s (%d)",
406 strerror(errno), errno);
407 tester_test_failed();
411 if (voice.setting != BT_VOICE_TRANSPARENT) {
412 tester_warn("Invalid voice setting");
413 tester_test_failed();
417 tester_test_passed();
423 static int create_sco_sock(struct test_data *data)
425 const uint8_t *master_bdaddr;
426 struct sockaddr_sco addr;
429 sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK,
433 tester_warn("Can't create socket: %s (%d)", strerror(errno),
438 master_bdaddr = hciemu_get_master_bdaddr(data->hciemu);
439 if (!master_bdaddr) {
440 tester_warn("No master bdaddr");
444 memset(&addr, 0, sizeof(addr));
445 addr.sco_family = AF_BLUETOOTH;
446 bacpy(&addr.sco_bdaddr, (void *) master_bdaddr);
448 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
450 tester_warn("Can't bind socket: %s (%d)", strerror(errno),
459 static int connect_sco_sock(struct test_data *data, int sk)
461 const uint8_t *client_bdaddr;
462 struct sockaddr_sco addr;
465 client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
466 if (!client_bdaddr) {
467 tester_warn("No client bdaddr");
471 memset(&addr, 0, sizeof(addr));
472 addr.sco_family = AF_BLUETOOTH;
473 bacpy(&addr.sco_bdaddr, (void *) client_bdaddr);
475 err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
476 if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
478 tester_warn("Can't connect socket: %s (%d)", strerror(errno),
486 static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
489 struct test_data *data = tester_get_data();
490 const struct sco_client_data *scodata = data->test_data;
492 socklen_t len = sizeof(sk_err);
496 sk = g_io_channel_unix_get_fd(io);
498 if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
504 tester_warn("Connect failed: %s (%d)", strerror(-err), -err);
506 tester_print("Successfully connected");
508 if (-err != scodata->expect_err)
509 tester_test_failed();
511 tester_test_passed();
516 static void test_connect(const void *test_data)
518 struct test_data *data = tester_get_data();
522 sk = create_sco_sock(data);
524 tester_test_failed();
528 if (connect_sco_sock(data, sk) < 0) {
530 tester_test_failed();
534 io = g_io_channel_unix_new(sk);
535 g_io_channel_set_close_on_unref(io, TRUE);
537 data->io_id = g_io_add_watch(io, G_IO_OUT, sco_connect_cb, NULL);
539 g_io_channel_unref(io);
541 tester_print("Connect in progress");
544 static void test_connect_transp(const void *test_data)
546 struct test_data *data = tester_get_data();
547 const struct sco_client_data *scodata = data->test_data;
549 struct bt_voice voice;
551 sk = create_sco_sock(data);
553 tester_test_failed();
557 memset(&voice, 0, sizeof(voice));
558 voice.setting = BT_VOICE_TRANSPARENT;
560 err = setsockopt(sk, SOL_BLUETOOTH, BT_VOICE, &voice, sizeof(voice));
562 tester_warn("Can't set socket option : %s (%d)",
563 strerror(errno), errno);
564 tester_test_failed();
568 err = connect_sco_sock(data, sk);
570 tester_warn("Connect returned %s (%d), expected %s (%d)",
571 strerror(-err), -err,
572 strerror(scodata->expect_err), scodata->expect_err);
574 if (-err != scodata->expect_err)
575 tester_test_failed();
577 tester_test_passed();
583 int main(int argc, char *argv[])
585 tester_init(&argc, &argv);
587 test_sco("Basic Framework - Success", NULL, setup_powered,
590 test_sco("Basic SCO Socket - Success", NULL, setup_powered,
593 test_sco("Basic SCO Get Socket Option - Success", NULL, setup_powered,
596 test_sco("Basic SCO Set Socket Option - Success", NULL, setup_powered,
599 test_sco("eSCO CVSD - Success", &connect_success, setup_powered,
602 test_sco("eSCO mSBC - Success", &connect_success, setup_powered,
603 test_connect_transp);
605 test_sco_11("SCO CVSD 1.1 - Success", &connect_success, setup_powered,
608 test_sco_11("SCO mSBC 1.1 - Failure", &connect_failure, setup_powered,
609 test_connect_transp);