Hi Marcel/Johan/Luiz, Based on the discussion on #bluez, i am sending an updated patchset. Let me know what you think of it. Cheers, Alok.
From bd853f4c8a8a7ec49d8045f10c73b53338a87633 Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxxx> Date: Tue, 21 Apr 2009 20:16:04 +0530 Subject: [PATCH 1/8] Initialing HCI raw socket plugin "hciops". --- plugins/Makefile.am | 6 +++++- plugins/hciops.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletions(-) create mode 100644 plugins/hciops.c diff --git a/plugins/Makefile.am b/plugins/Makefile.am index a1e933f..bbabf64 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -13,7 +13,7 @@ else service_plugins = endif -plugin_LTLIBRARIES = hal.la $(netlink_plugins) $(service_plugins) +plugin_LTLIBRARIES = hal.la hciops.la $(netlink_plugins) $(service_plugins) noinst_LTLIBRARIES = echo.la storage.la @@ -21,6 +21,8 @@ echo_la_SOURCES = echo.c storage_la_SOURCES = storage.c +hciops_la_SOURCES = hciops.c + if NETLINK netlink_la_SOURCES = netlink.c @@ -47,6 +49,7 @@ all-local: @$(LN_S) -f $(top_srcdir)/network/.libs/network.so @$(LN_S) -f .libs/service.so @$(LN_S) -f .libs/hal.so + @$(LN_S) -f .libs/hciops.so clean-local: @rm -f hal.so @@ -55,3 +58,4 @@ clean-local: @rm -f serial.so @rm -f audio.so @rm -f input.so + @rm -f hciops.so diff --git a/plugins/hciops.c b/plugins/hciops.c new file mode 100644 index 0000000..4f56443 --- /dev/null +++ b/plugins/hciops.c @@ -0,0 +1,43 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2009 Marcel Holtmann <marcel@xxxxxxxxxxxx> + * Copyright (C) 2009 Alok Barsode <alok.barsode@xxxxxxxxxx> + * + * 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 <config.h> +#endif + +#include <bluetooth/bluetooth.h> + +#include "plugin.h" +#include "logging.h" + +static int hciops_init(void) +{ + return 0; +} + +static void hciops_exit(void) +{ +} + +BLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, + BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, hciops_init, hciops_exit) -- 1.5.6.3
From 3938033c5fc16766a551d9680770ca93e811e9d4 Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxxx> Date: Tue, 21 Apr 2009 21:58:07 +0530 Subject: [PATCH 2/8] exporting device_event(). --- src/hcid.h | 1 + src/main.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/hcid.h b/src/hcid.h index 6c26157..236449d 100644 --- a/src/hcid.h +++ b/src/hcid.h @@ -68,6 +68,7 @@ struct main_opts { extern struct main_opts main_opts; +void device_event(int event, int dev_id); void hci_req_queue_remove(int dev_id, bdaddr_t *dba); void start_security_manager(int hdev); diff --git a/src/main.c b/src/main.c index f39fc11..02b4ebf 100644 --- a/src/main.c +++ b/src/main.c @@ -556,30 +556,28 @@ static void init_defaults(void) strcpy(main_opts.host_name, "noname"); } -static inline void device_event(GIOChannel *chan, evt_stack_internal *si) +void device_event(int event, int dev_id) { - evt_si_device *sd = (void *) &si->data; - - switch (sd->event) { + switch (event) { case HCI_DEV_REG: - info("HCI dev %d registered", sd->dev_id); - device_devreg_setup(sd->dev_id, FALSE); + info("HCI dev %d registered", dev_id); + device_devreg_setup(dev_id, FALSE); break; case HCI_DEV_UNREG: - info("HCI dev %d unregistered", sd->dev_id); - manager_unregister_adapter(sd->dev_id); + info("HCI dev %d unregistered", dev_id); + manager_unregister_adapter(dev_id); break; case HCI_DEV_UP: - info("HCI dev %d up", sd->dev_id); - device_devup_setup(sd->dev_id); + info("HCI dev %d up", dev_id); + device_devup_setup(dev_id); break; case HCI_DEV_DOWN: - info("HCI dev %d down", sd->dev_id); - manager_stop_adapter(sd->dev_id); - stop_security_manager(sd->dev_id); + info("HCI dev %d down", dev_id); + manager_stop_adapter(dev_id); + stop_security_manager(dev_id); break; } } @@ -589,6 +587,7 @@ static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, { unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; evt_stack_internal *si; + evt_si_device *sd; hci_event_hdr *eh; int type; size_t len; @@ -620,7 +619,8 @@ static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, si = (evt_stack_internal *) ptr; switch (si->type) { case EVT_SI_DEVICE: - device_event(chan, si); + sd = (void *) &si->data; + device_event(sd->event, sd->dev_id); break; } -- 1.5.6.3
From a90b9364238d0f2edd763a3db669810c43bd8e96 Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxxx> Date: Thu, 23 Apr 2009 16:42:16 +0530 Subject: [PATCH 3/8] Modifying device_devreg_setup. Check if device is up in device_devreg_setup instead of using devup parameter. --- src/main.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main.c b/src/main.c index 02b4ebf..d12edc5 100644 --- a/src/main.c +++ b/src/main.c @@ -477,9 +477,10 @@ fail: exit(1); } -static void device_devreg_setup(int dev_id, gboolean devup) +static void device_devreg_setup(int dev_id) { struct hci_dev_info di; + gboolean devup; init_device(dev_id); @@ -488,6 +489,8 @@ static void device_devreg_setup(int dev_id, gboolean devup) if (hci_devinfo(dev_id, &di) < 0) return; + devup = hci_test_bit(HCI_UP, &di.flags); + if (!hci_test_bit(HCI_RAW, &di.flags)) manager_register_adapter(dev_id, devup); } @@ -528,10 +531,10 @@ static void init_all_devices(int ctl) for (i = 0; i < dl->dev_num; i++, dr++) { gboolean devup; - devup = hci_test_bit(HCI_UP, &dr->dev_opt); - info("HCI dev %d registered", dr->dev_id); - device_devreg_setup(dr->dev_id, devup); + device_devreg_setup(dr->dev_id); + + devup = hci_test_bit(HCI_UP, &dr->dev_opt); if (devup) { info("HCI dev %d already up", dr->dev_id); device_devup_setup(dr->dev_id); @@ -561,7 +564,7 @@ void device_event(int event, int dev_id) switch (event) { case HCI_DEV_REG: info("HCI dev %d registered", dev_id); - device_devreg_setup(dev_id, FALSE); + device_devreg_setup(dev_id); break; case HCI_DEV_UNREG: -- 1.5.6.3
From 0d891eece965c0197d3ddb45336a646dcc227994 Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxxx> Date: Thu, 23 Apr 2009 16:46:41 +0530 Subject: [PATCH 4/8] Using device_event to register and setup already known devices. --- src/main.c | 9 +++------ 1 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index d12edc5..93dbf71 100644 --- a/src/main.c +++ b/src/main.c @@ -531,14 +531,11 @@ static void init_all_devices(int ctl) for (i = 0; i < dl->dev_num; i++, dr++) { gboolean devup; - info("HCI dev %d registered", dr->dev_id); - device_devreg_setup(dr->dev_id); + device_event(HCI_DEV_REG, dr->dev_id); devup = hci_test_bit(HCI_UP, &dr->dev_opt); - if (devup) { - info("HCI dev %d already up", dr->dev_id); - device_devup_setup(dr->dev_id); - } + if (devup) + device_event(HCI_DEV_UP, dr->dev_id); } g_free(dl); -- 1.5.6.3
From 1763faa8262fdd65bb0fd5db6e6732bf89d5f8bb Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxxx> Date: Thu, 23 Apr 2009 17:35:02 +0530 Subject: [PATCH 5/8] Initializing hciops plugin. Adding IO event handing. --- plugins/hciops.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/main.c | 122 +------------------------------------------------ 2 files changed, 134 insertions(+), 122 deletions(-) diff --git a/plugins/hciops.c b/plugins/hciops.c index 4f56443..32f82d0 100644 --- a/plugins/hciops.c +++ b/plugins/hciops.c @@ -24,17 +24,149 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif +#include <errno.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/ioctl.h> #include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> +#include <glib.h> + +#include "hcid.h" #include "plugin.h" #include "logging.h" -static int hciops_init(void) + +static int init_all_devices(int ctl) { + struct hci_dev_list_req *dl; + struct hci_dev_req *dr; + int i; + + dl = g_try_malloc0(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t)); + if (!dl) { + info("Can't allocate devlist buffer: %s (%d)", + strerror(errno), errno); + return errno; + } + + dl->dev_num = HCI_MAX_DEV; + dr = dl->dev_req; + + if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) { + info("Can't get device list: %s (%d)", + strerror(errno), errno); + return errno; + } + + for (i = 0; i < dl->dev_num; i++, dr++) { + gboolean devup; + + device_event(HCI_DEV_REG, dr->dev_id); + + devup = hci_test_bit(HCI_UP, &dr->dev_opt); + if (devup) + device_event(HCI_DEV_UP, dr->dev_id); + } + + g_free(dl); return 0; } +static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; + evt_stack_internal *si; + evt_si_device *sd; + hci_event_hdr *eh; + int type; + size_t len; + GIOError err; + + ptr = buf; + + err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); + if (err) { + if (err == G_IO_ERROR_AGAIN) + return TRUE; + + error("Read from control socket failed: %s (%d)", + strerror(errno), errno); + return FALSE; + } + + type = *ptr++; + + if (type != HCI_EVENT_PKT) + return TRUE; + + eh = (hci_event_hdr *) ptr; + if (eh->evt != EVT_STACK_INTERNAL) + return TRUE; + + ptr += HCI_EVENT_HDR_SIZE; + + si = (evt_stack_internal *) ptr; + switch (si->type) { + case EVT_SI_DEVICE: + sd = (void *) &si->data; + device_event(sd->event, sd->dev_id); + break; + } + + return TRUE; +} + +static int hciops_init(void) +{ + struct sockaddr_hci addr; + struct hci_filter flt; + GIOChannel *ctl_io; + int sock; + + /* Create and bind HCI socket */ + sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (sock < 0) { + error("Can't open HCI socket: %s (%d)", strerror(errno), + errno); + return errno; + } + + /* Set filter */ + hci_filter_clear(&flt); + hci_filter_set_ptype(HCI_EVENT_PKT, &flt); + hci_filter_set_event(EVT_STACK_INTERNAL, &flt); + if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, + sizeof(flt)) < 0) { + error("Can't set filter: %s (%d)", strerror(errno), errno); + return errno; + } + + memset(&addr, 0, sizeof(addr)); + addr.hci_family = AF_BLUETOOTH; + addr.hci_dev = HCI_DEV_NONE; + if (bind(sock, (struct sockaddr *) &addr, + sizeof(addr)) < 0) { + error("Can't bind HCI socket: %s (%d)", + strerror(errno), errno); + return errno; + } + + ctl_io = g_io_channel_unix_new(sock); + g_io_channel_set_close_on_unref(ctl_io, TRUE); + + g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); + + g_io_channel_unref(ctl_io); + + /* Initialize already connected devices */ + return init_all_devices(sock); +} + static void hciops_exit(void) { } diff --git a/src/main.c b/src/main.c index 93dbf71..309d4bb 100644 --- a/src/main.c +++ b/src/main.c @@ -506,41 +506,6 @@ static void device_devup_setup(int dev_id) stop_security_manager(dev_id); } -static void init_all_devices(int ctl) -{ - struct hci_dev_list_req *dl; - struct hci_dev_req *dr; - int i; - - dl = g_try_malloc0(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t)); - if (!dl) { - info("Can't allocate devlist buffer: %s (%d)", - strerror(errno), errno); - exit(1); - } - - dl->dev_num = HCI_MAX_DEV; - dr = dl->dev_req; - - if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) { - info("Can't get device list: %s (%d)", - strerror(errno), errno); - exit(1); - } - - for (i = 0; i < dl->dev_num; i++, dr++) { - gboolean devup; - - device_event(HCI_DEV_REG, dr->dev_id); - - devup = hci_test_bit(HCI_UP, &dr->dev_opt); - if (devup) - device_event(HCI_DEV_UP, dr->dev_id); - } - - g_free(dl); -} - static void init_defaults(void) { /* Default HCId settings */ @@ -582,51 +547,6 @@ void device_event(int event, int dev_id) } } -static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, - gpointer data) -{ - unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; - evt_stack_internal *si; - evt_si_device *sd; - hci_event_hdr *eh; - int type; - size_t len; - GIOError err; - - ptr = buf; - - err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); - if (err) { - if (err == G_IO_ERROR_AGAIN) - return TRUE; - - error("Read from control socket failed: %s (%d)", - strerror(errno), errno); - return FALSE; - } - - type = *ptr++; - - if (type != HCI_EVENT_PKT) - return TRUE; - - eh = (hci_event_hdr *) ptr; - if (eh->evt != EVT_STACK_INTERNAL) - return TRUE; - - ptr += HCI_EVENT_HDR_SIZE; - - si = (evt_stack_internal *) ptr; - switch (si->type) { - case EVT_SI_DEVICE: - sd = (void *) &si->data; - device_event(sd->event, sd->dev_id); - break; - } - - return TRUE; -} - static GMainLoop *event_loop; static void sig_term(int sig) @@ -655,10 +575,8 @@ int main(int argc, char *argv[]) { GOptionContext *context; GError *err = NULL; - struct sockaddr_hci addr; - struct hci_filter flt; struct sigaction sa; - GIOChannel *ctl_io, *child_io; + GIOChannel *child_io; uint16_t mtu = 0; GKeyFile *config; @@ -706,34 +624,6 @@ int main(int argc, char *argv[]) enable_debug(); } - /* Create and bind HCI socket */ - main_opts.sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); - if (main_opts.sock < 0) { - error("Can't open HCI socket: %s (%d)", strerror(errno), - errno); - exit(1); - } - - /* Set filter */ - hci_filter_clear(&flt); - hci_filter_set_ptype(HCI_EVENT_PKT, &flt); - hci_filter_set_event(EVT_STACK_INTERNAL, &flt); - if (setsockopt(main_opts.sock, SOL_HCI, HCI_FILTER, &flt, - sizeof(flt)) < 0) { - error("Can't set filter: %s (%d)", strerror(errno), errno); - exit(1); - } - - memset(&addr, 0, sizeof(addr)); - addr.hci_family = AF_BLUETOOTH; - addr.hci_dev = HCI_DEV_NONE; - if (bind(main_opts.sock, (struct sockaddr *) &addr, - sizeof(addr)) < 0) { - error("Can't bind HCI socket: %s (%d)", - strerror(errno), errno); - exit(1); - } - config = load_config(CONFIGDIR "/main.conf"); parse_config(config); @@ -768,16 +658,6 @@ int main(int argc, char *argv[]) event_loop = g_main_loop_new(NULL, FALSE); - ctl_io = g_io_channel_unix_new(main_opts.sock); - g_io_channel_set_close_on_unref(ctl_io, TRUE); - - g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); - - g_io_channel_unref(ctl_io); - - /* Initialize already connected devices */ - init_all_devices(main_opts.sock); - starting = FALSE; manager_startup_complete(); -- 1.5.6.3
From dabb6568ca87e6eff9a0ef8d6da555d5050b6054 Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxx> Date: Fri, 24 Apr 2009 15:48:58 +0530 Subject: [PATCH 6/8] Moving all adapter initialization code to hciops plugin. --- plugins/hciops.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/hcid.h | 11 +++ src/main.c | 249 +----------------------------------------------------- 3 files changed, 259 insertions(+), 249 deletions(-) diff --git a/plugins/hciops.c b/plugins/hciops.c index 32f82d0..25f5171 100644 --- a/plugins/hciops.c +++ b/plugins/hciops.c @@ -24,10 +24,19 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif + +#include <stdio.h> #include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <sys/stat.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/ioctl.h> +#include <sys/wait.h> #include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> @@ -35,10 +44,235 @@ #include <glib.h> +#include <dbus/dbus.h> + #include "hcid.h" +#include "sdpd.h" +#include "adapter.h" #include "plugin.h" #include "logging.h" +#include "manager.h" +#include "storage.h" + +static int child_pipe[2]; + +static gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) +{ + int status, fd = g_io_channel_unix_get_fd(io); + pid_t child_pid; + + if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) { + error("child_exit: unable to read child pid from pipe"); + return TRUE; + } + + if (waitpid(child_pid, &status, 0) != child_pid) + error("waitpid(%d) failed", child_pid); + else + debug("child %d exited", child_pid); + + return TRUE; +} + +static void at_child_exit(void) +{ + pid_t pid = getpid(); + + if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid)) + error("unable to write to child pipe"); +} + +static void configure_device(int dev_id) +{ + struct hci_dev_info di; + uint16_t policy; + int dd; + + if (hci_devinfo(dev_id, &di) < 0) + return; + + if (hci_test_bit(HCI_RAW, &di.flags)) + return; + + dd = hci_open_dev(dev_id); + if (dd < 0) { + error("Can't open device hci%d: %s (%d)", + dev_id, strerror(errno), errno); + return; + } + + /* Set device name */ + if ((main_opts.flags & (1 << HCID_SET_NAME)) && main_opts.name) { + change_local_name_cp cp; + + memset(cp.name, 0, sizeof(cp.name)); + expand_name((char *) cp.name, sizeof(cp.name), + main_opts.name, dev_id); + + hci_send_cmd(dd, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, + CHANGE_LOCAL_NAME_CP_SIZE, &cp); + } + + /* Set device class */ + if ((main_opts.flags & (1 << HCID_SET_CLASS))) { + write_class_of_dev_cp cp; + uint32_t class; + uint8_t cls[3]; + + if (read_local_class(&di.bdaddr, cls) < 0) { + class = htobl(main_opts.class); + cls[2] = get_service_classes(&di.bdaddr); + memcpy(cp.dev_class, &class, 3); + } else { + if (!(main_opts.scan & SCAN_INQUIRY)) + cls[1] &= 0xdf; /* Clear discoverable bit */ + cls[2] = get_service_classes(&di.bdaddr); + memcpy(cp.dev_class, cls, 3); + } + + hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, + WRITE_CLASS_OF_DEV_CP_SIZE, &cp); + } + + /* Set page timeout */ + if ((main_opts.flags & (1 << HCID_SET_PAGETO))) { + write_page_timeout_cp cp; + + cp.timeout = htobs(main_opts.pageto); + hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, + WRITE_PAGE_TIMEOUT_CP_SIZE, &cp); + } + + /* Set default link policy */ + policy = htobs(main_opts.link_policy); + hci_send_cmd(dd, OGF_LINK_POLICY, + OCF_WRITE_DEFAULT_LINK_POLICY, 2, &policy); + + hci_close_dev(dd); +} + +static void init_device(int dev_id) +{ + struct hci_dev_req dr; + struct hci_dev_info di; + pid_t pid; + int dd; + + /* Do initialization in the separate process */ + pid = fork(); + switch (pid) { + case 0: + atexit(at_child_exit); + break; + case -1: + error("Fork failed. Can't init device hci%d: %s (%d)", + dev_id, strerror(errno), errno); + default: + debug("child %d forked", pid); + return; + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + error("Can't open device hci%d: %s (%d)", + dev_id, strerror(errno), errno); + exit(1); + } + memset(&dr, 0, sizeof(dr)); + dr.dev_id = dev_id; + + /* Set link mode */ + dr.dev_opt = main_opts.link_mode; + if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0) { + error("Can't set link mode on hci%d: %s (%d)", + dev_id, strerror(errno), errno); + } + + /* Set link policy */ + dr.dev_opt = main_opts.link_policy; + if (ioctl(dd, HCISETLINKPOL, (unsigned long) &dr) < 0 && + errno != ENETDOWN) { + error("Can't set link policy on hci%d: %s (%d)", + dev_id, strerror(errno), errno); + } + + /* Start HCI device */ + if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) { + error("Can't init device hci%d: %s (%d)", + dev_id, strerror(errno), errno); + goto fail; + } + + if (hci_devinfo(dev_id, &di) < 0) + goto fail; + + if (hci_test_bit(HCI_RAW, &di.flags)) + goto done; + +done: + hci_close_dev(dd); + exit(0); + +fail: + hci_close_dev(dd); + exit(1); +} + +static void device_devreg_setup(int dev_id) +{ + struct hci_dev_info di; + gboolean devup; + + init_device(dev_id); + + memset(&di, 0, sizeof(di)); + + if (hci_devinfo(dev_id, &di) < 0) + return; + + devup = hci_test_bit(HCI_UP, &di.flags); + + if (!hci_test_bit(HCI_RAW, &di.flags)) + manager_register_adapter(dev_id, devup); +} + +static void device_devup_setup(int dev_id) +{ + configure_device(dev_id); + + start_security_manager(dev_id); + + /* Return value 1 means ioctl(DEVDOWN) was performed */ + if (manager_start_adapter(dev_id) == 1) + stop_security_manager(dev_id); +} + +void device_event(int event, int dev_id) +{ + switch (event) { + case HCI_DEV_REG: + info("HCI dev %d registered", dev_id); + device_devreg_setup(dev_id); + break; + + case HCI_DEV_UNREG: + info("HCI dev %d unregistered", dev_id); + manager_unregister_adapter(dev_id); + break; + + case HCI_DEV_UP: + info("HCI dev %d up", dev_id); + device_devup_setup(dev_id); + break; + + case HCI_DEV_DOWN: + info("HCI dev %d down", dev_id); + manager_stop_adapter(dev_id); + stop_security_manager(dev_id); + break; + } +} static int init_all_devices(int ctl) { @@ -125,9 +359,21 @@ static int hciops_init(void) { struct sockaddr_hci addr; struct hci_filter flt; - GIOChannel *ctl_io; + GIOChannel *ctl_io, *child_io;; int sock; + if (pipe(child_pipe) < 0) { + error("pipe(): %s (%d)", strerror(errno), errno); + return errno; + } + + child_io = g_io_channel_unix_new(child_pipe[0]); + g_io_channel_set_close_on_unref(child_io, TRUE); + g_io_add_watch(child_io, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + child_exit, NULL); + g_io_channel_unref(child_io); + /* Create and bind HCI socket */ sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (sock < 0) { diff --git a/src/hcid.h b/src/hcid.h index 236449d..e6f85d3 100644 --- a/src/hcid.h +++ b/src/hcid.h @@ -42,6 +42,8 @@ #define MODE_LIMITED 0x03 #define MODE_UNKNOWN 0xff +#define HCID_DEFAULT_DISCOVERABLE_TIMEOUT 180 /* 3 minutes */ + /* Timeout for hci_send_req (milliseconds) */ #define HCI_REQ_TIMEOUT 5000 @@ -66,8 +68,17 @@ struct main_opts { int sock; }; +enum { + HCID_SET_NAME, + HCID_SET_CLASS, + HCID_SET_PAGETO, + HCID_SET_DISCOVTO, +}; + extern struct main_opts main_opts; +char *expand_name(char *dst, int size, char *str, int dev_id); + void device_event(int event, int dev_id); void hci_req_queue_remove(int dev_id, bdaddr_t *dba); diff --git a/src/main.c b/src/main.c index 309d4bb..a5a728c 100644 --- a/src/main.c +++ b/src/main.c @@ -28,17 +28,13 @@ #endif #include <stdio.h> -#include <errno.h> -#include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> -#include <signal.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/types.h> -#include <sys/wait.h> #include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> @@ -57,21 +53,9 @@ #include "dbus-common.h" #include "agent.h" #include "manager.h" -#include "storage.h" - -#define HCID_DEFAULT_DISCOVERABLE_TIMEOUT 180 /* 3 minutes */ - -enum { - HCID_SET_NAME, - HCID_SET_CLASS, - HCID_SET_PAGETO, - HCID_SET_DISCOVTO, -}; struct main_opts main_opts; -static int child_pipe[2]; - static gboolean starting = TRUE; static GKeyFile *load_config(const char *file) @@ -260,7 +244,7 @@ static void update_service_classes(const bdaddr_t *bdaddr, uint8_t value) * Device name expansion * %d - device id */ -static char *expand_name(char *dst, int size, char *str, int dev_id) +char *expand_name(char *dst, int size, char *str, int dev_id) { register int sp, np, olen; char *opt, buf[10]; @@ -314,198 +298,6 @@ static char *expand_name(char *dst, int size, char *str, int dev_id) return dst; } -static gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) -{ - int status, fd = g_io_channel_unix_get_fd(io); - pid_t child_pid; - - if (read(fd, &child_pid, sizeof(child_pid)) != sizeof(child_pid)) { - error("child_exit: unable to read child pid from pipe"); - return TRUE; - } - - if (waitpid(child_pid, &status, 0) != child_pid) - error("waitpid(%d) failed", child_pid); - else - debug("child %d exited", child_pid); - - return TRUE; -} - -static void at_child_exit(void) -{ - pid_t pid = getpid(); - - if (write(child_pipe[1], &pid, sizeof(pid)) != sizeof(pid)) - error("unable to write to child pipe"); -} - -static void configure_device(int dev_id) -{ - struct hci_dev_info di; - uint16_t policy; - int dd; - - if (hci_devinfo(dev_id, &di) < 0) - return; - - if (hci_test_bit(HCI_RAW, &di.flags)) - return; - - dd = hci_open_dev(dev_id); - if (dd < 0) { - error("Can't open device hci%d: %s (%d)", - dev_id, strerror(errno), errno); - return; - } - - /* Set device name */ - if ((main_opts.flags & (1 << HCID_SET_NAME)) && main_opts.name) { - change_local_name_cp cp; - - memset(cp.name, 0, sizeof(cp.name)); - expand_name((char *) cp.name, sizeof(cp.name), - main_opts.name, dev_id); - - hci_send_cmd(dd, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, - CHANGE_LOCAL_NAME_CP_SIZE, &cp); - } - - /* Set device class */ - if ((main_opts.flags & (1 << HCID_SET_CLASS))) { - write_class_of_dev_cp cp; - uint32_t class; - uint8_t cls[3]; - - if (read_local_class(&di.bdaddr, cls) < 0) { - class = htobl(main_opts.class); - cls[2] = get_service_classes(&di.bdaddr); - memcpy(cp.dev_class, &class, 3); - } else { - if (!(main_opts.scan & SCAN_INQUIRY)) - cls[1] &= 0xdf; /* Clear discoverable bit */ - cls[2] = get_service_classes(&di.bdaddr); - memcpy(cp.dev_class, cls, 3); - } - - hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, - WRITE_CLASS_OF_DEV_CP_SIZE, &cp); - } - - /* Set page timeout */ - if ((main_opts.flags & (1 << HCID_SET_PAGETO))) { - write_page_timeout_cp cp; - - cp.timeout = htobs(main_opts.pageto); - hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT, - WRITE_PAGE_TIMEOUT_CP_SIZE, &cp); - } - - /* Set default link policy */ - policy = htobs(main_opts.link_policy); - hci_send_cmd(dd, OGF_LINK_POLICY, - OCF_WRITE_DEFAULT_LINK_POLICY, 2, &policy); - - hci_close_dev(dd); -} - -static void init_device(int dev_id) -{ - struct hci_dev_req dr; - struct hci_dev_info di; - pid_t pid; - int dd; - - /* Do initialization in the separate process */ - pid = fork(); - switch (pid) { - case 0: - atexit(at_child_exit); - break; - case -1: - error("Fork failed. Can't init device hci%d: %s (%d)", - dev_id, strerror(errno), errno); - default: - debug("child %d forked", pid); - return; - } - - dd = hci_open_dev(dev_id); - if (dd < 0) { - error("Can't open device hci%d: %s (%d)", - dev_id, strerror(errno), errno); - exit(1); - } - - memset(&dr, 0, sizeof(dr)); - dr.dev_id = dev_id; - - /* Set link mode */ - dr.dev_opt = main_opts.link_mode; - if (ioctl(dd, HCISETLINKMODE, (unsigned long) &dr) < 0) { - error("Can't set link mode on hci%d: %s (%d)", - dev_id, strerror(errno), errno); - } - - /* Set link policy */ - dr.dev_opt = main_opts.link_policy; - if (ioctl(dd, HCISETLINKPOL, (unsigned long) &dr) < 0 && - errno != ENETDOWN) { - error("Can't set link policy on hci%d: %s (%d)", - dev_id, strerror(errno), errno); - } - - /* Start HCI device */ - if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) { - error("Can't init device hci%d: %s (%d)", - dev_id, strerror(errno), errno); - goto fail; - } - - if (hci_devinfo(dev_id, &di) < 0) - goto fail; - - if (hci_test_bit(HCI_RAW, &di.flags)) - goto done; - -done: - hci_close_dev(dd); - exit(0); - -fail: - hci_close_dev(dd); - exit(1); -} - -static void device_devreg_setup(int dev_id) -{ - struct hci_dev_info di; - gboolean devup; - - init_device(dev_id); - - memset(&di, 0, sizeof(di)); - - if (hci_devinfo(dev_id, &di) < 0) - return; - - devup = hci_test_bit(HCI_UP, &di.flags); - - if (!hci_test_bit(HCI_RAW, &di.flags)) - manager_register_adapter(dev_id, devup); -} - -static void device_devup_setup(int dev_id) -{ - configure_device(dev_id); - - start_security_manager(dev_id); - - /* Return value 1 means ioctl(DEVDOWN) was performed */ - if (manager_start_adapter(dev_id) == 1) - stop_security_manager(dev_id); -} - static void init_defaults(void) { /* Default HCId settings */ @@ -521,32 +313,6 @@ static void init_defaults(void) strcpy(main_opts.host_name, "noname"); } -void device_event(int event, int dev_id) -{ - switch (event) { - case HCI_DEV_REG: - info("HCI dev %d registered", dev_id); - device_devreg_setup(dev_id); - break; - - case HCI_DEV_UNREG: - info("HCI dev %d unregistered", dev_id); - manager_unregister_adapter(dev_id); - break; - - case HCI_DEV_UP: - info("HCI dev %d up", dev_id); - device_devup_setup(dev_id); - break; - - case HCI_DEV_DOWN: - info("HCI dev %d down", dev_id); - manager_stop_adapter(dev_id); - stop_security_manager(dev_id); - break; - } -} - static GMainLoop *event_loop; static void sig_term(int sig) @@ -576,7 +342,6 @@ int main(int argc, char *argv[]) GOptionContext *context; GError *err = NULL; struct sigaction sa; - GIOChannel *child_io; uint16_t mtu = 0; GKeyFile *config; @@ -628,18 +393,6 @@ int main(int argc, char *argv[]) parse_config(config); - if (pipe(child_pipe) < 0) { - error("pipe(): %s (%d)", strerror(errno), errno); - exit(1); - } - - child_io = g_io_channel_unix_new(child_pipe[0]); - g_io_channel_set_close_on_unref(child_io, TRUE); - g_io_add_watch(child_io, - G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - child_exit, NULL); - g_io_channel_unref(child_io); - agent_init(); if (hcid_dbus_init() < 0) { -- 1.5.6.3
From 68d889fc2ac063b89cddc09f755bf3a11c5cecda Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxx> Date: Mon, 27 Apr 2009 15:38:03 +0530 Subject: [PATCH 7/8] Adding btd_register_adapter_ops framework. --- plugins/hciops.c | 16 +++++++++++++++- src/adapter.c | 28 ++++++++++++++++++++++++++++ src/adapter.h | 8 ++++++++ 3 files changed, 51 insertions(+), 1 deletions(-) diff --git a/plugins/hciops.c b/plugins/hciops.c index 25f5171..26fa1dc 100644 --- a/plugins/hciops.c +++ b/plugins/hciops.c @@ -355,7 +355,7 @@ static gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, return TRUE; } -static int hciops_init(void) +static int hci_init(void) { struct sockaddr_hci addr; struct hci_filter flt; @@ -413,8 +413,22 @@ static int hciops_init(void) return init_all_devices(sock); } +static void hci_cleanup(void) +{ +} + +static struct btd_adapter_ops hci_ops = { + .init = hci_init, + .cleanup = hci_cleanup, +}; + +static int hciops_init(void) +{ + return btd_register_adapter_ops(&hci_ops); +} static void hciops_exit(void) { + btd_adapter_cleanup_ops(&hci_ops); } BLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, diff --git a/src/adapter.c b/src/adapter.c index 40c5ab0..c41b933 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -73,6 +73,7 @@ static DBusConnection *connection = NULL; static GSList *adapter_drivers = NULL; +static struct btd_adapter_ops *adapter_ops = NULL; struct session_req { struct btd_adapter *adapter; @@ -2905,6 +2906,33 @@ void btd_unregister_adapter_driver(struct btd_adapter_driver *driver) adapter_drivers = g_slist_remove(adapter_drivers, driver); } +int btd_register_adapter_ops(struct btd_adapter_ops *btd_adapter_ops) +{ + int err; + + /* Already registered */ + if (adapter_ops) + return 1; + + if (btd_adapter_ops->init == NULL) + return -1; + + err = btd_adapter_ops->init(); + if (err < 0) { + error("btd_register_adapter_ops failed:%s (%d)", strerror(-err), -err); + return -1; + } + + adapter_ops = btd_adapter_ops; + + return 0; +} + +void btd_adapter_cleanup_ops() +{ + adapter_ops->cleanup(); +} + static void agent_auth_cb(struct agent *agent, DBusError *derr, void *user_data) { diff --git a/src/adapter.h b/src/adapter.h index 8111d6f..4e4a3d2 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -147,3 +147,11 @@ const char *btd_adapter_any_request_path(void); void btd_adapter_any_release_path(void); gboolean adapter_is_pairable(struct btd_adapter *adapter); gboolean adapter_powering_down(struct btd_adapter *adapter); + +struct btd_adapter_ops { + int (*init)(); + void (*cleanup)(); +}; + +int btd_register_adapter_ops(struct btd_adapter_ops *btd_adapter_ops); +void btd_adapter_cleanup_ops(); -- 1.5.6.3
From fb33d026cdc31e6aa9ed0de52478e9cfb9b7e29e Mon Sep 17 00:00:00 2001 From: Alok Barsode <alok.barsode@xxxxxxxxx> Date: Mon, 27 Apr 2009 16:31:00 +0530 Subject: [PATCH 8/8] Exporting init_known_adapters from hciops plugin. --- plugins/hciops.c | 16 ++++++++-------- src/adapter.c | 8 ++++++++ src/adapter.h | 2 ++ src/main.c | 2 ++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/hciops.c b/plugins/hciops.c index 26fa1dc..3cd3868 100644 --- a/plugins/hciops.c +++ b/plugins/hciops.c @@ -54,6 +54,7 @@ #include "manager.h" #include "storage.h" +static int sock; static int child_pipe[2]; static gboolean child_exit(GIOChannel *io, GIOCondition cond, void *user_data) @@ -273,8 +274,8 @@ void device_event(int event, int dev_id) break; } } - -static int init_all_devices(int ctl) + /* Initialize already connected devices */ +static int init_all_devices(void) { struct hci_dev_list_req *dl; struct hci_dev_req *dr; @@ -290,7 +291,7 @@ static int init_all_devices(int ctl) dl->dev_num = HCI_MAX_DEV; dr = dl->dev_req; - if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) { + if (ioctl(sock, HCIGETDEVLIST, (void *) dl) < 0) { info("Can't get device list: %s (%d)", strerror(errno), errno); return errno; @@ -360,7 +361,6 @@ static int hci_init(void) struct sockaddr_hci addr; struct hci_filter flt; GIOChannel *ctl_io, *child_io;; - int sock; if (pipe(child_pipe) < 0) { error("pipe(): %s (%d)", strerror(errno), errno); @@ -409,8 +409,7 @@ static int hci_init(void) g_io_channel_unref(ctl_io); - /* Initialize already connected devices */ - return init_all_devices(sock); + return 0; } static void hci_cleanup(void) @@ -418,8 +417,9 @@ static void hci_cleanup(void) } static struct btd_adapter_ops hci_ops = { - .init = hci_init, - .cleanup = hci_cleanup, + .init = hci_init, + .cleanup = hci_cleanup, + .init_known_adapters = init_all_devices, }; static int hciops_init(void) diff --git a/src/adapter.c b/src/adapter.c index c41b933..d315698 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -2933,6 +2933,14 @@ void btd_adapter_cleanup_ops() adapter_ops->cleanup(); } +int init_known_adapters() +{ + if (!adapter_ops) + return -1; + + return adapter_ops->init_known_adapters(); +} + static void agent_auth_cb(struct agent *agent, DBusError *derr, void *user_data) { diff --git a/src/adapter.h b/src/adapter.h index 4e4a3d2..c4b6793 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -151,7 +151,9 @@ gboolean adapter_powering_down(struct btd_adapter *adapter); struct btd_adapter_ops { int (*init)(); void (*cleanup)(); + int (*init_known_adapters)(); }; int btd_register_adapter_ops(struct btd_adapter_ops *btd_adapter_ops); void btd_adapter_cleanup_ops(); +int init_known_adapters(); diff --git a/src/main.c b/src/main.c index a5a728c..346dc0c 100644 --- a/src/main.c +++ b/src/main.c @@ -411,6 +411,8 @@ int main(int argc, char *argv[]) event_loop = g_main_loop_new(NULL, FALSE); + init_known_adapters(); + starting = FALSE; manager_startup_complete(); -- 1.5.6.3