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 <bluetooth/bluetooth.h>
40 #include <bluetooth/hci.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 "src/shared/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 write_callback(const void *data, uint16_t len, void *user_data)
112 GIOChannel *channel = user_data;
116 fd = g_io_channel_unix_get_fd(channel);
118 written = write(fd, data, len);
123 static gboolean receive_bthost(GIOChannel *channel, GIOCondition condition,
126 struct bthost *bthost = user_data;
127 unsigned char buf[4096];
131 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
134 fd = g_io_channel_unix_get_fd(channel);
136 len = read(fd, buf, sizeof(buf));
140 bthost_receive_h4(bthost, buf, len);
145 static guint create_source_bthost(int fd, struct bthost *bthost)
150 channel = g_io_channel_unix_new(fd);
152 g_io_channel_set_close_on_unref(channel, TRUE);
153 g_io_channel_set_encoding(channel, NULL, NULL);
154 g_io_channel_set_buffered(channel, FALSE);
156 bthost_set_send_handler(bthost, write_callback, channel);
158 source = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
159 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
160 receive_bthost, bthost, NULL);
162 g_io_channel_unref(channel);
167 static gboolean receive_btdev(GIOChannel *channel, GIOCondition condition,
170 struct btdev *btdev = user_data;
171 unsigned char buf[4096];
175 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
178 fd = g_io_channel_unix_get_fd(channel);
180 len = read(fd, buf, sizeof(buf));
188 btdev_receive_h4(btdev, buf, len);
195 static guint create_source_btdev(int fd, struct btdev *btdev)
200 channel = g_io_channel_unix_new(fd);
202 g_io_channel_set_close_on_unref(channel, TRUE);
203 g_io_channel_set_encoding(channel, NULL, NULL);
204 g_io_channel_set_buffered(channel, FALSE);
206 btdev_set_send_handler(btdev, write_callback, channel);
208 source = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
209 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
210 receive_btdev, btdev, NULL);
212 g_io_channel_unref(channel);
217 static bool create_vhci(struct hciemu *hciemu)
220 uint8_t create_req[2];
224 btdev = btdev_create(hciemu->btdev_type, 0x00);
228 btdev_set_command_handler(btdev, master_command_callback, hciemu);
230 fd = open("/dev/vhci", O_RDWR | O_NONBLOCK | O_CLOEXEC);
232 perror("Opening /dev/vhci failed");
233 btdev_destroy(btdev);
237 create_req[0] = HCI_VENDOR_PKT;
238 create_req[1] = HCI_BREDR;
239 written = write(fd, create_req, sizeof(create_req));
242 btdev_destroy(btdev);
246 hciemu->master_dev = btdev;
248 hciemu->master_source = create_source_btdev(fd, btdev);
253 struct bthost *hciemu_client_get_host(struct hciemu *hciemu)
258 return hciemu->host_stack;
261 static bool create_stack(struct hciemu *hciemu)
264 struct bthost *bthost;
267 btdev = btdev_create(hciemu->btdev_type, 0x00);
271 bthost = bthost_create();
273 btdev_destroy(btdev);
277 btdev_set_command_handler(btdev, client_command_callback, hciemu);
279 if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
281 bthost_destroy(bthost);
282 btdev_destroy(btdev);
286 hciemu->client_dev = btdev;
287 hciemu->host_stack = bthost;
289 hciemu->client_source = create_source_btdev(sv[0], btdev);
290 hciemu->host_source = create_source_bthost(sv[1], bthost);
295 static gboolean start_stack(gpointer user_data)
297 struct hciemu *hciemu = user_data;
299 bthost_start(hciemu->host_stack);
304 struct hciemu *hciemu_new(enum hciemu_type type)
306 struct hciemu *hciemu;
308 hciemu = new0(struct hciemu, 1);
313 case HCIEMU_TYPE_BREDRLE:
314 hciemu->btdev_type = BTDEV_TYPE_BREDRLE;
316 case HCIEMU_TYPE_BREDR:
317 hciemu->btdev_type = BTDEV_TYPE_BREDR;
320 hciemu->btdev_type = BTDEV_TYPE_LE;
326 hciemu->post_command_hooks = queue_new();
327 if (!hciemu->post_command_hooks) {
332 if (!create_vhci(hciemu)) {
333 queue_destroy(hciemu->post_command_hooks, NULL);
338 if (!create_stack(hciemu)) {
339 g_source_remove(hciemu->master_source);
340 btdev_destroy(hciemu->master_dev);
341 queue_destroy(hciemu->post_command_hooks, NULL);
346 g_idle_add(start_stack, hciemu);
348 return hciemu_ref(hciemu);
351 struct hciemu *hciemu_ref(struct hciemu *hciemu)
356 __sync_fetch_and_add(&hciemu->ref_count, 1);
361 void hciemu_unref(struct hciemu *hciemu)
366 if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
369 queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
371 bthost_stop(hciemu->host_stack);
373 g_source_remove(hciemu->host_source);
374 g_source_remove(hciemu->client_source);
375 g_source_remove(hciemu->master_source);
377 bthost_destroy(hciemu->host_stack);
378 btdev_destroy(hciemu->client_dev);
379 btdev_destroy(hciemu->master_dev);
384 const char *hciemu_get_address(struct hciemu *hciemu)
388 if (!hciemu || !hciemu->master_dev)
391 addr = btdev_get_bdaddr(hciemu->master_dev);
392 sprintf(hciemu->bdaddr_str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
393 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
394 return hciemu->bdaddr_str;
397 uint8_t *hciemu_get_features(struct hciemu *hciemu)
399 if (!hciemu || !hciemu->master_dev)
402 return btdev_get_features(hciemu->master_dev);
405 const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu)
407 if (!hciemu || !hciemu->master_dev)
410 return btdev_get_bdaddr(hciemu->master_dev);
413 const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
415 if (!hciemu || !hciemu->client_dev)
418 return btdev_get_bdaddr(hciemu->client_dev);
421 bool hciemu_add_master_post_command_hook(struct hciemu *hciemu,
422 hciemu_command_func_t function, void *user_data)
424 struct hciemu_command_hook *hook;
429 hook = new0(struct hciemu_command_hook, 1);
433 hook->function = function;
434 hook->user_data = user_data;
436 if (!queue_push_tail(hciemu->post_command_hooks, hook)) {
444 int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
445 uint16_t opcode, hciemu_hook_func_t function,
448 enum btdev_hook_type hook_type;
454 case HCIEMU_HOOK_PRE_CMD:
455 hook_type = BTDEV_HOOK_PRE_CMD;
457 case HCIEMU_HOOK_POST_CMD:
458 hook_type = BTDEV_HOOK_POST_CMD;
460 case HCIEMU_HOOK_PRE_EVT:
461 hook_type = BTDEV_HOOK_PRE_EVT;
463 case HCIEMU_HOOK_POST_EVT:
464 hook_type = BTDEV_HOOK_POST_EVT;
470 return btdev_add_hook(hciemu->master_dev, hook_type, opcode, function,
474 bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
477 enum btdev_hook_type hook_type;
483 case HCIEMU_HOOK_PRE_CMD:
484 hook_type = BTDEV_HOOK_PRE_CMD;
486 case HCIEMU_HOOK_POST_CMD:
487 hook_type = BTDEV_HOOK_POST_CMD;
489 case HCIEMU_HOOK_PRE_EVT:
490 hook_type = BTDEV_HOOK_PRE_EVT;
492 case HCIEMU_HOOK_POST_EVT:
493 hook_type = BTDEV_HOOK_POST_EVT;
499 return btdev_del_hook(hciemu->master_dev, hook_type, opcode);