From ccbbb8dd3ce840b332b4d5b971bd58609396a043 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Jan 2014 12:17:09 -0800 Subject: [PATCH] emulator: Add simple HFP emulator for testing --- .gitignore | 1 + Makefile.tools | 9 +++- emulator/hfp.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 emulator/hfp.c diff --git a/.gitignore b/.gitignore index 03216679e..e2b23fc82 100644 --- a/.gitignore +++ b/.gitignore @@ -93,6 +93,7 @@ tools/btsnoop monitor/btmon emulator/btvirt emulator/b1ee +emulator/hfp client/bluetoothctl src/bluetoothd.8 diff --git a/Makefile.tools b/Makefile.tools index 52e49fb33..9199222a2 100644 --- a/Makefile.tools +++ b/Makefile.tools @@ -36,7 +36,7 @@ monitor_btmon_LDADD = lib/libbluetooth-internal.la @UDEV_LIBS@ endif if EXPERIMENTAL -noinst_PROGRAMS += emulator/btvirt emulator/b1ee tools/3dsp \ +noinst_PROGRAMS += emulator/btvirt emulator/b1ee emulator/hfp tools/3dsp \ tools/mgmt-tester tools/gap-tester \ tools/l2cap-tester tools/sco-tester \ tools/smp-tester tools/hci-tester \ @@ -55,6 +55,13 @@ emulator_btvirt_LDADD = lib/libbluetooth-internal.la emulator_b1ee_SOURCES = emulator/b1ee.c monitor/mainloop.h monitor/mainloop.c +emulator_hfp_SOURCES = emulator/hfp.c \ + monitor/mainloop.h monitor/mainloop.c \ + src/shared/io.h src/shared/io-mainloop.c \ + src/shared/util.h src/shared/util.c \ + src/shared/ringbuf.h src/shared/ringbuf.c \ + src/shared/hfp.h src/shared/hfp.c + tools_3dsp_SOURCES = tools/3dsp.c monitor/bt.h \ monitor/mainloop.h monitor/mainloop.c \ src/shared/io.h src/shared/io-mainloop.c \ diff --git a/emulator/hfp.c b/emulator/hfp.c new file mode 100644 index 000000000..928a72937 --- /dev/null +++ b/emulator/hfp.c @@ -0,0 +1,119 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2011-2012 Intel Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "monitor/mainloop.h" +#include "src/shared/hfp.h" + +static void hfp_debug(const char *str, void *user_data) +{ + const char *prefix = user_data; + + printf("%s%s\n", prefix, str); +} + +static void command_handler(const char *command, void *user_data) +{ + struct hfp_gw *hfp = user_data; + + printf("Command: %s\n", command); + + hfp_gw_send_result(hfp, HFP_RESULT_ERROR); +} + +static bool open_connection(void) +{ + static const char SOCKET_PATH[] = "\0hfp-headset"; + struct hfp_gw *hfp; + struct sockaddr_un addr; + int fd; + + fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + perror("Failed to create Unix socket"); + return false; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, SOCKET_PATH, sizeof(SOCKET_PATH)); + + if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("Failed to connect Unix socket"); + close(fd); + return false; + } + + hfp = hfp_gw_new(fd); + if (!hfp) { + close(fd); + return false; + } + + hfp_gw_set_close_on_unref(hfp, true); + + hfp_gw_set_debug(hfp, hfp_debug, "HFP: ", NULL); + + hfp_gw_set_command_handler(hfp, command_handler, hfp, NULL); + + return true; +} + +static void signal_callback(int signum, void *user_data) +{ + switch (signum) { + case SIGINT: + case SIGTERM: + mainloop_quit(); + break; + } +} + +int main(int argc, char *argv[]) +{ + sigset_t mask; + + mainloop_init(); + + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGTERM); + + mainloop_set_signal(&mask, signal_callback, NULL, NULL); + + if (!open_connection()) + return EXIT_FAILURE; + + return mainloop_run(); +} -- 2.47.3