📄 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 "logging.h"#include "hcid.h"#include "sdpd.h"#include "adapter.h"#include "dbus-hci.h"#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 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_clear_error(&err); } else { debug("offmode=%s", str); if (g_str_equal(str, "DevDown")) main_opts.offmode = HCID_OFFMODE_DEVDOWN; g_free(str); } val = g_key_file_get_integer(config, "General", "DiscoverableTimeout", &err); if (err) { debug("%s", err->message); g_clear_error(&err); } else { debug("discovto=%d", val); main_opts.discovto = val; main_opts.flags |= 1 << HCID_SET_DISCOVTO; } val = g_key_file_get_integer(config, "General", "PairableTimeout", &err); if (err) { debug("%s", err->message); g_clear_error(&err); } else { debug("pairto=%d", val); main_opts.pairto = val; } val = g_key_file_get_integer(config, "General", "PageTimeout", &err); if (err) { debug("%s", err->message); g_clear_error(&err); } else { debug("pageto=%d", val); main_opts.pageto = val; main_opts.flags |= 1 << HCID_SET_PAGETO; } str = g_key_file_get_string(config, "General", "Name", &err); if (err) { debug("%s", err->message); g_clear_error(&err); } else { debug("name=%s", str); g_free(main_opts.name); main_opts.name = g_strdup(str); main_opts.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_clear_error(&err); } else { debug("class=%s", str); main_opts.class = strtol(str, NULL, 16); main_opts.flags |= 1 << HCID_SET_CLASS; g_free(str); } val = g_key_file_get_integer(config, "General", "DiscoverSchedulerInterval", &err); if (err) { debug("%s", err->message); g_clear_error(&err); } else { debug("inqmode=%d", val); main_opts.inqmode = val; } main_opts.link_mode = HCI_LM_ACCEPT; main_opts.link_policy = HCI_LP_RSWITCH | HCI_LP_SNIFF | HCI_LP_HOLD | HCI_LP_PARK;}static 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 = main_opts.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 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -