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_BREDR;
247 written = write(fd, create_req, sizeof(create_req));
250 btdev_destroy(btdev);
254 hciemu->master_dev = btdev;
256 hciemu->master_source = create_source_btdev(fd, btdev);
261 struct bthost *hciemu_client_get_host(struct hciemu *hciemu)
266 return hciemu->host_stack;
269 static bool create_stack(struct hciemu *hciemu)
272 struct bthost *bthost;
275 btdev = btdev_create(hciemu->btdev_type, 0x00);
279 bthost = bthost_create();
281 btdev_destroy(btdev);
285 btdev_set_command_handler(btdev, client_command_callback, hciemu);
287 if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
289 bthost_destroy(bthost);
290 btdev_destroy(btdev);
294 hciemu->client_dev = btdev;
295 hciemu->host_stack = bthost;
297 hciemu->client_source = create_source_btdev(sv[0], btdev);
298 hciemu->host_source = create_source_bthost(sv[1], bthost);
303 static gboolean start_stack(gpointer user_data)
305 struct hciemu *hciemu = user_data;
307 bthost_start(hciemu->host_stack);
312 struct hciemu *hciemu_new(enum hciemu_type type)
314 struct hciemu *hciemu;
316 hciemu = new0(struct hciemu, 1);
321 case HCIEMU_TYPE_BREDRLE:
322 hciemu->btdev_type = BTDEV_TYPE_BREDRLE;
324 case HCIEMU_TYPE_BREDR:
325 hciemu->btdev_type = BTDEV_TYPE_BREDR;
328 hciemu->btdev_type = BTDEV_TYPE_LE;
334 hciemu->post_command_hooks = queue_new();
335 if (!hciemu->post_command_hooks) {
340 if (!create_vhci(hciemu)) {
341 queue_destroy(hciemu->post_command_hooks, NULL);
346 if (!create_stack(hciemu)) {
347 g_source_remove(hciemu->master_source);
348 btdev_destroy(hciemu->master_dev);
349 queue_destroy(hciemu->post_command_hooks, NULL);
354 g_idle_add(start_stack, hciemu);
356 return hciemu_ref(hciemu);
359 struct hciemu *hciemu_ref(struct hciemu *hciemu)
364 __sync_fetch_and_add(&hciemu->ref_count, 1);
369 void hciemu_unref(struct hciemu *hciemu)
374 if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
377 queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
379 g_source_remove(hciemu->host_source);
380 g_source_remove(hciemu->client_source);
381 g_source_remove(hciemu->master_source);
383 bthost_destroy(hciemu->host_stack);
384 btdev_destroy(hciemu->client_dev);
385 btdev_destroy(hciemu->master_dev);
390 const char *hciemu_get_address(struct hciemu *hciemu)
394 if (!hciemu || !hciemu->master_dev)
397 addr = btdev_get_bdaddr(hciemu->master_dev);
398 sprintf(hciemu->bdaddr_str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
399 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
400 return hciemu->bdaddr_str;
403 uint8_t *hciemu_get_features(struct hciemu *hciemu)
405 if (!hciemu || !hciemu->master_dev)
408 return btdev_get_features(hciemu->master_dev);
411 const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu)
413 if (!hciemu || !hciemu->master_dev)
416 return btdev_get_bdaddr(hciemu->master_dev);
419 const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
421 if (!hciemu || !hciemu->client_dev)
424 return btdev_get_bdaddr(hciemu->client_dev);
427 bool hciemu_add_master_post_command_hook(struct hciemu *hciemu,
428 hciemu_command_func_t function, void *user_data)
430 struct hciemu_command_hook *hook;
435 hook = new0(struct hciemu_command_hook, 1);
439 hook->function = function;
440 hook->user_data = user_data;
442 if (!queue_push_tail(hciemu->post_command_hooks, hook)) {
450 int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
451 uint16_t opcode, hciemu_hook_func_t function,
454 enum btdev_hook_type hook_type;
460 case HCIEMU_HOOK_PRE_CMD:
461 hook_type = BTDEV_HOOK_PRE_CMD;
463 case HCIEMU_HOOK_POST_CMD:
464 hook_type = BTDEV_HOOK_POST_CMD;
466 case HCIEMU_HOOK_PRE_EVT:
467 hook_type = BTDEV_HOOK_PRE_EVT;
469 case HCIEMU_HOOK_POST_EVT:
470 hook_type = BTDEV_HOOK_POST_EVT;
476 return btdev_add_hook(hciemu->master_dev, hook_type, opcode, function,
480 bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
483 enum btdev_hook_type hook_type;
489 case HCIEMU_HOOK_PRE_CMD:
490 hook_type = BTDEV_HOOK_PRE_CMD;
492 case HCIEMU_HOOK_POST_CMD:
493 hook_type = BTDEV_HOOK_POST_CMD;
495 case HCIEMU_HOOK_PRE_EVT:
496 hook_type = BTDEV_HOOK_PRE_EVT;
498 case HCIEMU_HOOK_POST_EVT:
499 hook_type = BTDEV_HOOK_POST_EVT;
505 return btdev_del_hook(hciemu->master_dev, hook_type, opcode);