📄 main.c
字号:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2000-2001 Qualcomm Incorporated * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2002-2008 Marcel Holtmann <marcel@holtmann.org> * * * 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 <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>#include <bluetooth/hci_lib.h>#include <glib.h>#include <dbus/dbus.h>#include "hcid.h"#include "sdpd.h"#include "adapter.h"#include "dbus-common.h"#include "dbus-database.h"#include "dbus-hci.h"#include "device.h"#include "agent.h"#include "manager.h"struct hcid_opts hcid;struct device_opts default_device;static struct device_list *device_list = NULL;static int child_pipe[2];static GKeyFile *load_config(const char *file){ GError *err = NULL; GKeyFile *keyfile; keyfile = g_key_file_new(); g_key_file_set_list_separator(keyfile, ','); if (!g_key_file_load_from_file(keyfile, file, 0, &err)) { error("Parsing %s failed: %s", file, err->message); g_error_free(err); g_key_file_free(keyfile); return NULL; } return keyfile;}static void parse_config(GKeyFile *config){ GError *err = NULL; char *str; int val; if (!config) return; debug("parsing main.conf"); str = g_key_file_get_string(config, "General", "OffMode", &err); if (err) { debug("%s", err->message); g_error_free(err); err = NULL; } else { debug("offmode=%s", str); if (g_str_equal(str, "DevDown")) hcid.offmode = HCID_OFFMODE_DEVDOWN; g_free(str); } val = g_key_file_get_integer(config, "General", "DiscoverableTimeout", &err); if (err) { debug("%s", err->message); g_error_free(err); err = NULL; } else { debug("discovto=%d", val); default_device.discovto = val; default_device.flags |= 1 << HCID_SET_DISCOVTO; } val = g_key_file_get_integer(config, "General", "PageTimeout", &err); if (err) { debug("%s", err->message); g_error_free(err); err = NULL; } else { debug("pageto=%d", val); default_device.pageto = val; default_device.flags |= 1 << HCID_SET_PAGETO; } str = g_key_file_get_string(config, "General", "Name", &err); if (err) { debug("%s", err->message); g_error_free(err); err = NULL; } else { debug("name=%s", str); g_free(default_device.name); default_device.name = g_strdup(str); default_device.flags |= 1 << HCID_SET_NAME; g_free(str); } str = g_key_file_get_string(config, "General", "Class", &err); if (err) { debug("%s", err->message); g_error_free(err); err = NULL; } else { debug("class=%s", str); default_device.class = strtol(str, NULL, 16); default_device.flags |= 1 << HCID_SET_CLASS; g_free(str); } default_device.link_mode = HCI_LM_ACCEPT; default_device.flags |= (1 << HCID_SET_LM); default_device.link_policy = HCI_LP_RSWITCH | HCI_LP_SNIFF | HCI_LP_HOLD | HCI_LP_PARK; default_device.flags |= (1 << HCID_SET_LP);}static inline void init_device_defaults(struct device_opts *device_opts){ memset(device_opts, 0, sizeof(*device_opts)); device_opts->scan = SCAN_PAGE; device_opts->mode = MODE_CONNECTABLE; device_opts->name = g_strdup("BlueZ"); device_opts->discovto = HCID_DEFAULT_DISCOVERABLE_TIMEOUT;}struct device_opts *alloc_device_opts(char *ref){ struct device_list *device; device = g_try_new(struct device_list, 1); if (!device) { info("Can't allocate devlist opts buffer: %s (%d)", strerror(errno), errno); exit(1); } device->ref = g_strdup(ref); device->next = device_list; device_list = device; memcpy(&device->opts, &default_device, sizeof(struct device_opts)); device->opts.name = g_strdup(default_device.name); return &device->opts;}static void free_device_opts(void){ struct device_list *device, *next; g_free(default_device.name); for (device = device_list; device; device = next) { g_free(device->ref); g_free(device->opts.name); next = device->next; g_free(device); } device_list = NULL;}static inline struct device_opts *find_device_opts(char *ref){ struct device_list *device; for (device = device_list; device; device = device->next) if (!strcmp(ref, device->ref)) return &device->opts; return NULL;}static struct device_opts *get_device_opts(int hdev){ struct device_opts *device_opts = NULL; struct hci_dev_info di; /* First try to get BD_ADDR based settings ... */ if (hci_devinfo(hdev, &di) == 0) { char addr[18]; ba2str(&di.bdaddr, addr); device_opts = find_device_opts(addr); } /* ... then try HCI based settings ... */ if (!device_opts) { char ref[8]; snprintf(ref, sizeof(ref) - 1, "hci%d", hdev); device_opts = find_device_opts(ref); } /* ... and last use the default settings. */ if (!device_opts) device_opts = &default_device; return device_opts;}static struct device_opts *get_opts(int hdev){ struct device_opts *device_opts = NULL; struct hci_dev_info di; char addr[18]; int sock; if (hdev < 0) return NULL; sock = hci_open_dev(hdev); if (sock < 0) goto no_address; if (hci_devinfo(hdev, &di) < 0) { close(sock); goto no_address; } close(sock); ba2str(&di.bdaddr, addr); device_opts = find_device_opts(addr);no_address: if (!device_opts) { char ref[8]; snprintf(ref, sizeof(ref) - 1, "hci%d", hdev); device_opts = find_device_opts(ref); } if (!device_opts) device_opts = &default_device; return device_opts;}uint8_t get_startup_scan(int hdev){ struct device_opts *device_opts = get_opts(hdev); if (!device_opts) return SCAN_DISABLED; return device_opts->scan;}uint8_t get_startup_mode(int hdev){ struct device_opts *device_opts = get_opts(hdev); if (!device_opts) return MODE_OFF; return device_opts->mode;}int get_discoverable_timeout(int hdev){ struct device_opts *device_opts = NULL; struct hci_dev_info di; char addr[18]; int sock, timeout; if (hdev < 0) return HCID_DEFAULT_DISCOVERABLE_TIMEOUT; sock = hci_open_dev(hdev); if (sock < 0) goto no_address; if (hci_devinfo(hdev, &di) < 0) { close(sock); goto no_address; } close(sock); if (read_discoverable_timeout(&di.bdaddr, &timeout) == 0) return timeout; ba2str(&di.bdaddr, addr); device_opts = find_device_opts(addr);no_address: if (!device_opts) { char ref[8]; snprintf(ref, sizeof(ref) - 1, "hci%d", hdev); device_opts = find_device_opts(ref); } if (!device_opts) device_opts = &default_device; return device_opts->discovto;}void update_service_classes(const bdaddr_t *bdaddr, uint8_t value){ struct hci_dev_list_req *dl; struct hci_dev_req *dr; int i, sk; sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (sk < 0) return; dl = g_malloc0(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl)); dl->dev_num = HCI_MAX_DEV; dr = dl->dev_req; if (ioctl(sk, HCIGETDEVLIST, dl) < 0) { close(sk); g_free(dl); return; } dr = dl->dev_req; for (i = 0; i < dl->dev_num; i++, dr++) { struct hci_dev_info di; uint8_t cls[3]; int dd; if (hci_devinfo(dr->dev_id, &di) < 0) continue; if (hci_test_bit(HCI_RAW, &di.flags)) continue; if (!hci_test_bit(HCI_UP, &di.flags)) continue; if (manager_get_adapter_class(di.dev_id, cls) < 0) continue; dd = hci_open_dev(di.dev_id); if (dd < 0) continue; set_service_classes(dd, cls, value); hci_close_dev(dd); manager_update_adapter(di.dev_id); } g_free(dl); close(sk);}/* * Device name expansion * %d - device id */static char *expand_name(char *dst, int size, char *str, int dev_id){ register int sp, np, olen; char *opt, buf[10]; if (!str && !dst) return NULL; sp = np = 0; while (np < size - 1 && str[sp]) { switch (str[sp]) { case '%': opt = NULL; switch (str[sp+1]) { case 'd': sprintf(buf, "%d", dev_id); opt = buf; break; case 'h': opt = hcid.host_name; break; case '%': dst[np++] = str[sp++]; /* fall through */ default: sp++; continue; } if (opt) { /* substitute */ olen = strlen(opt); if (np + olen < size - 1) memcpy(dst + np, opt, olen); np += olen; } sp += 2; continue; case '\\': sp++; /* fall through */ default: dst[np++] = str[sp++]; break; } } dst[np] = '\0'; 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 device_opts *device_opts; struct hci_dev_req dr; struct hci_dev_info di; char mode[14]; int dd; device_opts = get_device_opts(dev_id); if (hci_devinfo(dev_id, &di) < 0) return; if (hci_test_bit(HCI_RAW, &di.flags)) return; /* Set default discoverable timeout if not set */ if (!(device_opts->flags & (1 << HCID_SET_DISCOVTO)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -