3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library 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 GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include <sys/socket.h>
39 #include "lib/bluetooth.h"
42 #include "monitor/bt.h"
43 #include "emulator/btdev.h"
44 #include "emulator/bthost.h"
45 #include "src/shared/util.h"
46 #include "src/shared/queue.h"
47 #include "emulator/hciemu.h"
51 enum btdev_type btdev_type;
52 struct bthost *host_stack;
53 struct btdev *master_dev;
54 struct btdev *client_dev;
58 struct queue *post_command_hooks;
62 struct hciemu_command_hook {
63 hciemu_command_func_t function;
67 static void destroy_command_hook(void *data)
69 struct hciemu_command_hook *hook = data;
80 static void run_command_hook(void *data, void *user_data)
82 struct hciemu_command_hook *hook = data;
83 struct run_data *run_data = user_data;
86 hook->function(run_data->opcode, run_data->data,
87 run_data->len, hook->user_data);
90 static void master_command_callback(uint16_t opcode,
91 const void *data, uint8_t len,
92 btdev_callback callback, void *user_data)
94 struct hciemu *hciemu = user_data;
95 struct run_data run_data = { .opcode = opcode,
96 .data = data, .len = len };
98 btdev_command_default(callback);
100 queue_foreach(hciemu->post_command_hooks, run_command_hook, &run_data);
103 static void client_command_callback(uint16_t opcode,
104 const void *data, uint8_t len,
105 btdev_callback callback, void *user_data)
107 btdev_command_default(callback);
110 static void writev_callback(const struct iovec *iov, int iovlen,
113 GIOChannel *channel = user_data;
117 fd = g_io_channel_unix_get_fd(channel);
119 written = writev(fd, iov, iovlen);
124 static gboolean receive_bthost(GIOChannel *channel, GIOCondition condition,
127 struct bthost *bthost = user_data;
128 unsigned char buf[4096];
132 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
135 fd = g_io_channel_unix_get_fd(channel);
137 len = read(fd, buf, sizeof(buf));
141 bthost_receive_h4(bthost, buf, len);
146 static guint create_source_bthost(int fd, struct bthost *bthost)
151 channel = g_io_channel_unix_new(fd);
153 g_io_channel_set_close_on_unref(channel, TRUE);
154 g_io_channel_set_encoding(channel, NULL, NULL);
155 g_io_channel_set_buffered(channel, FALSE);
157 bthost_set_send_handler(bthost, writev_callback, channel);
159 source = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
160 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
161 receive_bthost, bthost, NULL);
163 g_io_channel_unref(channel);
168 static gboolean receive_btdev(GIOChannel *channel, GIOCondition condition,
171 struct btdev *btdev = user_data;
172 unsigned char buf[4096];
176 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
179 fd = g_io_channel_unix_get_fd(channel);
181 len = read(fd, buf, sizeof(buf));
183 if (errno == EAGAIN || errno == EINTR)
196 btdev_receive_h4(btdev, buf, len);
203 static guint create_source_btdev(int fd, struct btdev *btdev)
208 channel = g_io_channel_unix_new(fd);
210 g_io_channel_set_close_on_unref(channel, TRUE);
211 g_io_channel_set_encoding(channel, NULL, NULL);
212 g_io_channel_set_buffered(channel, FALSE);
214 btdev_set_send_handler(btdev, writev_callback, channel);
216 source = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
217 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
218 receive_btdev, btdev, NULL);
220 g_io_channel_unref(channel);
225 static bool create_vhci(struct hciemu *hciemu)
228 uint8_t create_req[2];
232 btdev = btdev_create(hciemu->btdev_type, 0x00);
236 btdev_set_command_handler(btdev, master_command_callback, hciemu);
238 fd = open("/dev/vhci", O_RDWR | O_NONBLOCK | O_CLOEXEC);
240 perror("Opening /dev/vhci failed");
241 btdev_destroy(btdev);
245 create_req[0] = HCI_VENDOR_PKT;
246 create_req[1] = HCI_PRIMARY;
248 written = write(fd, create_req, sizeof(create_req));
251 btdev_destroy(btdev);
255 hciemu->master_dev = btdev;
257 hciemu->master_source = create_source_btdev(fd, btdev);
262 struct bthost *hciemu_client_get_host(struct hciemu *hciemu)
267 return hciemu->host_stack;
270 static bool create_stack(struct hciemu *hciemu)
273 struct bthost *bthost;
276 btdev = btdev_create(hciemu->btdev_type, 0x00);
280 bthost = bthost_create();
282 btdev_destroy(btdev);
286 btdev_set_command_handler(btdev, client_command_callback, hciemu);
288 if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
290 bthost_destroy(bthost);
291 btdev_destroy(btdev);
295 hciemu->client_dev = btdev;
296 hciemu->host_stack = bthost;
298 hciemu->client_source = create_source_btdev(sv[0], btdev);
299 hciemu->host_source = create_source_bthost(sv[1], bthost);
304 static gboolean start_stack(gpointer user_data)
306 struct hciemu *hciemu = user_data;
308 bthost_start(hciemu->host_stack);
313 struct hciemu *hciemu_new(enum hciemu_type type)
315 struct hciemu *hciemu;
317 hciemu = new0(struct hciemu, 1);
322 case HCIEMU_TYPE_BREDRLE:
323 hciemu->btdev_type = BTDEV_TYPE_BREDRLE;
325 case HCIEMU_TYPE_BREDR:
326 hciemu->btdev_type = BTDEV_TYPE_BREDR;
329 hciemu->btdev_type = BTDEV_TYPE_LE;
331 case HCIEMU_TYPE_LEGACY:
332 hciemu->btdev_type = BTDEV_TYPE_BREDR20;
338 hciemu->post_command_hooks = queue_new();
339 if (!hciemu->post_command_hooks) {
344 if (!create_vhci(hciemu)) {
345 queue_destroy(hciemu->post_command_hooks, NULL);
350 if (!create_stack(hciemu)) {
351 g_source_remove(hciemu->master_source);
352 btdev_destroy(hciemu->master_dev);
353 queue_destroy(hciemu->post_command_hooks, NULL);
358 g_idle_add(start_stack, hciemu);
360 return hciemu_ref(hciemu);
363 struct hciemu *hciemu_ref(struct hciemu *hciemu)
368 __sync_fetch_and_add(&hciemu->ref_count, 1);
373 void hciemu_unref(struct hciemu *hciemu)
378 if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
381 queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
383 g_source_remove(hciemu->host_source);
384 g_source_remove(hciemu->client_source);
385 g_source_remove(hciemu->master_source);
387 bthost_destroy(hciemu->host_stack);
388 btdev_destroy(hciemu->client_dev);
389 btdev_destroy(hciemu->master_dev);
394 const char *hciemu_get_address(struct hciemu *hciemu)
398 if (!hciemu || !hciemu->master_dev)
401 addr = btdev_get_bdaddr(hciemu->master_dev);
402 sprintf(hciemu->bdaddr_str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
403 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
404 return hciemu->bdaddr_str;
407 uint8_t *hciemu_get_features(struct hciemu *hciemu)
409 if (!hciemu || !hciemu->master_dev)
412 return btdev_get_features(hciemu->master_dev);
415 const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu)
417 if (!hciemu || !hciemu->master_dev)
420 return btdev_get_bdaddr(hciemu->master_dev);
423 const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
425 if (!hciemu || !hciemu->client_dev)
428 return btdev_get_bdaddr(hciemu->client_dev);
431 uint8_t hciemu_get_master_scan_enable(struct hciemu *hciemu)
433 if (!hciemu || !hciemu->master_dev)
436 return btdev_get_scan_enable(hciemu->master_dev);
439 uint8_t hciemu_get_master_le_scan_enable(struct hciemu *hciemu)
441 if (!hciemu || !hciemu->master_dev)
444 return btdev_get_le_scan_enable(hciemu->master_dev);
447 void hciemu_set_master_le_states(struct hciemu *hciemu, const uint8_t *le_states)
449 if (!hciemu || !hciemu->master_dev)
452 btdev_set_le_states(hciemu->master_dev, le_states);
455 bool hciemu_add_master_post_command_hook(struct hciemu *hciemu,
456 hciemu_command_func_t function, void *user_data)
458 struct hciemu_command_hook *hook;
463 hook = new0(struct hciemu_command_hook, 1);
467 hook->function = function;
468 hook->user_data = user_data;
470 if (!queue_push_tail(hciemu->post_command_hooks, hook)) {
478 bool hciemu_clear_master_post_command_hooks(struct hciemu *hciemu)
483 queue_remove_all(hciemu->post_command_hooks,
484 NULL, NULL, destroy_command_hook);
488 int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
489 uint16_t opcode, hciemu_hook_func_t function,
492 enum btdev_hook_type hook_type;
498 case HCIEMU_HOOK_PRE_CMD:
499 hook_type = BTDEV_HOOK_PRE_CMD;
501 case HCIEMU_HOOK_POST_CMD:
502 hook_type = BTDEV_HOOK_POST_CMD;
504 case HCIEMU_HOOK_PRE_EVT:
505 hook_type = BTDEV_HOOK_PRE_EVT;
507 case HCIEMU_HOOK_POST_EVT:
508 hook_type = BTDEV_HOOK_POST_EVT;
514 return btdev_add_hook(hciemu->master_dev, hook_type, opcode, function,
518 bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
521 enum btdev_hook_type hook_type;
527 case HCIEMU_HOOK_PRE_CMD:
528 hook_type = BTDEV_HOOK_PRE_CMD;
530 case HCIEMU_HOOK_POST_CMD:
531 hook_type = BTDEV_HOOK_POST_CMD;
533 case HCIEMU_HOOK_PRE_EVT:
534 hook_type = BTDEV_HOOK_PRE_EVT;
536 case HCIEMU_HOOK_POST_EVT:
537 hook_type = BTDEV_HOOK_POST_EVT;
543 return btdev_del_hook(hciemu->master_dev, hook_type, opcode);