device.c revision 1d3715db11f573060cb02a2b7b7c44f06607d337
1c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky/* 2f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky BlueZ - Bluetooth protocol stack for Linux 3f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky Copyright (C) 2000-2001 Qualcomm Incorporated 4f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky 5f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 6f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky 7f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky This program is free software; you can redistribute it and/or modify 8f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky it under the terms of the GNU General Public License version 2 as 9f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky published by the Free Software Foundation; 10f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky 11f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 12f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 14f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, 15f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER 16f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 17f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 18f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky USE OR PERFORMANCE OF THIS SOFTWARE. 19f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky 20f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, 21f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. 22c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky*/ 235ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 24c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky/* 25c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky * $Id$ 26c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky */ 27c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 281d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann#ifdef HAVE_CONFIG_H 291d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann#include <config.h> 301d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann#endif 311d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann 32c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <stdio.h> 33c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <stdlib.h> 34c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <unistd.h> 35c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <string.h> 36c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <signal.h> 37c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <fcntl.h> 38c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <syslog.h> 39c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <errno.h> 40c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <time.h> 41c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <fcntl.h> 42c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 43c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <sys/ioctl.h> 44c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <sys/socket.h> 45c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <sys/time.h> 46f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <sys/stat.h> 47c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 48f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <bluetooth/bluetooth.h> 49f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <bluetooth/hci.h> 50f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <bluetooth/hci_lib.h> 51c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 52c7c04aac86fec5084e3e1caf3eaaa3abd545f58dMarcel Holtmann#include "glib-ectomy.h" 53c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 54c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include "hcid.h" 55c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include "lib.h" 56c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 57c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystruct hcid_opts hcid; 585ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstruct device_opts default_device; 595ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstruct device_opts *parser_device; 605ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic struct device_list *device_list = NULL; 61c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 62c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic GMainLoop *event_loop; 63c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 64c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskygboolean io_stack_event(GIOChannel *chan, GIOCondition cond, gpointer data); 65c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskygboolean io_security_event(GIOChannel *chan, GIOCondition cond, gpointer data); 66c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 67c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void usage(void) 68c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 69c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky printf("hcid - HCI daemon ver %s\n", VERSION); 70c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky printf("Usage: \n"); 71c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky printf("\thcid [-n not_daemon] [-f config file]\n"); 72c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 73c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 745ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic inline void init_device_defaults(struct device_opts *device_opts) 755ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{ 765ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann memset(device_opts, 0, sizeof(*device_opts)); 775ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_opts->scan = SCAN_PAGE | SCAN_INQUIRY; 785ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann} 795ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 805ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstruct device_opts *alloc_device_opts(char *ref) 815ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{ 825ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann struct device_list *device; 835ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 845ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device = malloc(sizeof(struct device_list)); 855ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (!device) { 865ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann syslog(LOG_INFO, "Can't allocate devlist opts buffer. %s(%d)", 875ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann strerror(errno), errno); 885ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann exit(1); 895ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann } 905ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 915ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device->ref = ref; 925ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device->next = device_list; 935ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_list = device; 945ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 955ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann init_device_defaults(&device->opts); 965ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 975ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann return &device->opts; 985ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann} 995ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1005ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic void free_device_opts(void) 1015ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{ 1025ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann struct device_list *device, *next; 1035ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1045ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (default_device.name) { 1055ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann free(default_device.name); 1065ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann default_device.name = NULL; 1075ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann } 1085ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1095ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann for (device = device_list; device; device = next) { 1105ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann free(device->ref); 1115ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device->opts.name) 1125ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann free(device->opts.name); 1135ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann next = device->next; 1145ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann free(device); 1155ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann } 1165ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1175ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_list = NULL; 1185ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann} 1195ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1205ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic inline struct device_opts *find_device_opts(char *ref) 1215ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{ 1225ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann struct device_list *device; 1235ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1245ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann for (device = device_list; device; device = device->next) 1255ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (!strcmp(ref, device->ref)) 1265ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann return &device->opts; 1275ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1285ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann return NULL; 1295ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann} 1305ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1315ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic struct device_opts *get_device_opts(int sock, int hdev) 1325ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{ 1335ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann struct device_opts *device_opts = NULL; 1345ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann struct hci_dev_info di; 1355ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1365ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann /* First try to get BD_ADDR based settings ... */ 1375ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann di.dev_id = hdev; 1385ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (!ioctl(sock, HCIGETDEVINFO, (void *) &di)) { 1395ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann char addr[18]; 1405ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann ba2str(&di.bdaddr, addr); 1415ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_opts = find_device_opts(addr); 1425ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann } 1435ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1445ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann /* ... then try HCI based settings ... */ 1455ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (!device_opts) { 1465ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann char ref[8]; 1475ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann snprintf(ref, sizeof(ref) - 1, "hci%d", hdev); 1485ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_opts = find_device_opts(ref); 1495ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann } 1505ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1515ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann /* ... and last use the default settings. */ 1525ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (!device_opts) 1535ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_opts = &default_device; 1545ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 1555ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann return device_opts; 1565ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann} 1575ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 15830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyanskystatic void configure_device(int hdev) 159c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 1605ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann struct device_opts *device_opts; 161c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky struct hci_dev_req dr; 162c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky int s; 163c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 16430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky /* Do configuration in the separate process */ 165c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky switch (fork()) { 166c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky case 0: 167c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky break; 168c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky case -1: 16930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky syslog(LOG_ERR, "Fork failed. Can't init device hci%d. %s(%d)\n", 170c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hdev, strerror(errno), errno); 171c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky default: 172c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky return; 173c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 174c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 17530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky set_title("hci%d config", hdev); 176c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 177c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if ((s = hci_open_dev(hdev)) < 0) { 178c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Can't open device hci%d. %s(%d)\n", hdev, strerror(errno), errno); 179c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(1); 180c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 181c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 1825ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann dr.dev_id = hdev; 1835ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_opts = get_device_opts(s, hdev); 184c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 185c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Set scan mode */ 1865ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann dr.dev_opt = device_opts->scan; 1875ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (ioctl(s, HCISETSCAN, (unsigned long) &dr) < 0) { 188c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Can't set scan mode on hci%d. %s(%d)\n", 189c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hdev, strerror(errno), errno); 190c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 191c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 192c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Set authentication */ 1935ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device_opts->auth) 194c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky dr.dev_opt = AUTH_ENABLED; 195c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky else 196c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky dr.dev_opt = AUTH_DISABLED; 197c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 1985ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (ioctl(s, HCISETAUTH, (unsigned long) &dr) < 0) { 199c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Can't set auth on hci%d. %s(%d)\n", 200c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hdev, strerror(errno), errno); 201c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 202c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 203c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Set encryption */ 2045ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device_opts->encrypt) 205c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky dr.dev_opt = ENCRYPT_P2P; 206c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky else 207c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky dr.dev_opt = ENCRYPT_DISABLED; 208c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 2095ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (ioctl(s, HCISETENCRYPT, (unsigned long) &dr) < 0) { 210c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Can't set encrypt on hci%d. %s(%d)\n", 211c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hdev, strerror(errno), errno); 212c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 213c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 2145ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann /* Set device class */ 2155ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device_opts->class) { 2165ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann uint32_t class = htobl(device_opts->class); 217c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky write_class_of_dev_cp cp; 2185ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 219c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky memcpy(cp.dev_class, &class, 3); 220c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hci_send_cmd(s, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, 221c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky WRITE_CLASS_OF_DEV_CP_SIZE, (void *) &cp); 222c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 223c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 224c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Set device name */ 2255ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device_opts->name) { 226c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky change_local_name_cp cp; 2275ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann expand_name(cp.name, device_opts->name, hdev); 228c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 229c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hci_send_cmd(s, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, 230c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky CHANGE_LOCAL_NAME_CP_SIZE, (void *) &cp); 231c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 232c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 233c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(0); 234c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 235c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 23630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyanskystatic void init_device(int hdev) 23730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky{ 2385ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann struct device_opts *device_opts; 23930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky struct hci_dev_req dr; 24030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky int s; 24130fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 24230fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky /* Do initialization in the separate process */ 24330fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky switch (fork()) { 24430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky case 0: 24530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky break; 24630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky case -1: 24730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky syslog(LOG_ERR, "Fork failed. Can't init device hci%d. %s(%d)\n", 24830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky hdev, strerror(errno), errno); 24930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky default: 25030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky return; 25130fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 25230fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 25330fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky set_title("hci%d init", hdev); 25430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 25530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky if ((s = hci_open_dev(hdev)) < 0) { 25630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky syslog(LOG_ERR, "Can't open device hci%d. %s(%d)\n", hdev, strerror(errno), errno); 25730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky exit(1); 25830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 25930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 260cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky /* Start HCI device */ 261cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky if (ioctl(s, HCIDEVUP, hdev) < 0 && errno != EALREADY) { 262cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky syslog(LOG_ERR, "Can't init device hci%d. %s(%d)\n", hdev, 263cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky strerror(errno), errno); 264cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky exit(1); 265cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky } 266cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky 2675ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann dr.dev_id = hdev; 2685ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann device_opts = get_device_opts(s, hdev); 26930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 27030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky /* Set packet type */ 2715ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device_opts->pkt_type) { 2725ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann dr.dev_opt = device_opts->pkt_type; 2735ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (ioctl(s, HCISETPTYPE, (unsigned long) &dr) < 0) { 27430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky syslog(LOG_ERR, "Can't set packet type on hci%d. %s(%d)\n", 27530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky hdev, strerror(errno), errno); 27630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 27730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 27830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 27930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky /* Set link mode */ 2805ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device_opts->link_mode) { 2815ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann dr.dev_opt = device_opts->link_mode; 2825ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (ioctl(s, HCISETLINKMODE, (unsigned long) &dr) < 0) { 28330fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky syslog(LOG_ERR, "Can't set link mode on hci%d. %s(%d)\n", 28430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky hdev, strerror(errno), errno); 28530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 28630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 28730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 28830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky /* Set link policy */ 2895ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (device_opts->link_policy) { 2905ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann dr.dev_opt = device_opts->link_policy; 2915ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (ioctl(s, HCISETLINKPOL, (unsigned long) &dr) < 0) { 29230fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky syslog(LOG_ERR, "Can't set link policy on hci%d. %s(%d)\n", 29330fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky hdev, strerror(errno), errno); 29430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 29530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky } 29630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 29730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky exit(0); 29830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky} 29930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 300c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void init_all_devices(int ctl) 301c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 302c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky struct hci_dev_list_req *dl; 303c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky struct hci_dev_req *dr; 304c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky int i; 305c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 306c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (!(dl = malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t)))) { 307c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "Can't allocate devlist buffer. %s(%d)", 308c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky strerror(errno), errno); 309c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(1); 310c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 311c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky dl->dev_num = HCI_MAX_DEV; 312c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky dr = dl->dev_req; 313c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 3145ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) { 31530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky syslog(LOG_INFO, "Can't get device list. %s(%d)", 316c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky strerror(errno), errno); 317c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(1); 318c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 319c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 3205ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann for (i = 0; i < dl->dev_num; i++, dr++) { 321c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (hcid.auto_init) 322c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky init_device(dr->dev_id); 323c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 324cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky if (hcid.auto_init && hci_test_bit(HCI_UP, &dr->dev_opt)) 32530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky configure_device(dr->dev_id); 32630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky 327cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky if (hcid.security && hci_test_bit(HCI_UP, &dr->dev_opt)) 328c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky start_security_manager(dr->dev_id); 329c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 3305ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 331c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky free(dl); 332c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 333c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 334c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void init_defaults(void) 335c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 336c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hcid.auto_init = 0; 337c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hcid.security = 0; 338c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 3395ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann init_device_defaults(&default_device); 340c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 341c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 342c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void sig_usr1(int sig) 343c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 344c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky toggle_pairing(0); 345c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky} 346c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky 347c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyanskystatic void sig_usr2(int sig) 348c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky{ 349c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky toggle_pairing(1); 350c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 351c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 352c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void sig_term(int sig) 353c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 354c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky g_main_quit(event_loop); 355c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 356c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 357c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void sig_hup(int sig) 358c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 359c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "Reloading config file"); 3605ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 361c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky init_defaults(); 3625ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 363c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (read_config(hcid.config_file) < 0) 364c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Config reload failed"); 365c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 366ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky init_security_data(); 367ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky 368c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky init_all_devices(hcid.sock); 369c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 370c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 371c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic inline void device_event(GIOChannel *chan, evt_stack_internal *si) 372c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 373c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky evt_si_device *sd = (void *) &si->data; 374c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 375c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky switch (sd->event) { 376c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky case HCI_DEV_REG: 377c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "HCI dev %d registered", sd->dev_id); 378c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (hcid.auto_init) 379c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky init_device(sd->dev_id); 380c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky break; 381c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 382c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky case HCI_DEV_UNREG: 383c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "HCI dev %d unregistered", sd->dev_id); 384c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky break; 385c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 386c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky case HCI_DEV_UP: 387c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "HCI dev %d up", sd->dev_id); 38830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky if (hcid.auto_init) 38930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky configure_device(sd->dev_id); 390c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (hcid.security) 391c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky start_security_manager(sd->dev_id); 392c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky break; 393c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 394c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky case HCI_DEV_DOWN: 395c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "HCI dev %d down", sd->dev_id); 396c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (hcid.security) 397c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky stop_security_manager(sd->dev_id); 398c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky break; 399c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 400c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 401c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 402c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskygboolean io_stack_event(GIOChannel *chan, GIOCondition cond, gpointer data) 403c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 4048100e0c660e200a9d789dcd054f25a20778379cdMarcel Holtmann unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr; 405c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky evt_stack_internal *si; 406c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hci_event_hdr *eh; 4078100e0c660e200a9d789dcd054f25a20778379cdMarcel Holtmann int type; 4088100e0c660e200a9d789dcd054f25a20778379cdMarcel Holtmann size_t len; 409c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky GIOError err; 410c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 411c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky ptr = buf; 412c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 413c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if ((err = g_io_channel_read(chan, buf, sizeof(buf), &len))) { 414c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (err == G_IO_ERROR_AGAIN) 415c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky return TRUE; 416c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 417c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Read from control socket failed. %s(%d)", 418c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky strerror(errno), errno); 419c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky g_main_quit(event_loop); 420c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky return FALSE; 421c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 422c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 423c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky type = *ptr++; 424c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 425c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (type != HCI_EVENT_PKT) 426c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky return TRUE; 427c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 428c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky eh = (hci_event_hdr *) ptr; 429c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (eh->evt != EVT_STACK_INTERNAL) 430c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky return TRUE; 431c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 432c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky ptr += HCI_EVENT_HDR_SIZE; 433c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 434c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky si = (evt_stack_internal *) ptr; 435c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky switch (si->type) { 436c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky case EVT_SI_DEVICE: 437c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky device_event(chan, si); 438c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky break; 439c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 440c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 441c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky return TRUE; 442c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 443c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 4445ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannextern int optind, opterr, optopt; 445c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskyextern char *optarg; 446c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 447c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskyint main(int argc, char *argv[], char *env[]) 448c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{ 449c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky int daemon, dofork, opt, fd; 450c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky struct sockaddr_hci addr; 451c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky struct hci_filter flt; 452c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky struct sigaction sa; 453c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky GIOChannel *ctl_io; 454c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 455c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky daemon = 1; dofork = 1; 456c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 457c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Default HCId settings */ 458c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hcid.config_file = HCID_CONFIG_FILE; 4595ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann hcid.host_name = get_host_name(); 4605ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann hcid.security = HCID_SEC_AUTO; 4615ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann hcid.pairing = HCID_PAIRING_MULTI; 462c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 4635ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann hcid.pin_file = strdup(HCID_PIN_FILE); 4645ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann hcid.pin_helper = strdup(HCID_PIN_HELPER); 4655ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann hcid.key_file = strdup(HCID_KEY_FILE); 466c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 467c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky init_defaults(); 468c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 4695ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann while ((opt = getopt(argc, argv, "f:n")) != EOF) { 4705ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann switch (opt) { 471ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky case 'n': 472ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky daemon = 0; 473ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky break; 474c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 475ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky case 'f': 476ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky hcid.config_file = strdup(optarg); 477ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky break; 478c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 479ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky default: 480ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky usage(); 481ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky exit(1); 482c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 483c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 484c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 485c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (daemon) { 486c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (dofork && fork()) 487c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(0); 488c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 489c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Direct stdin,stdout,stderr to '/dev/null' */ 490c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky fd = open("/dev/null", O_RDWR); 491c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); 492c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky close(fd); 493c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 494c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky setsid(); 495c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 496c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky chdir("/"); 497c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 498c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 499f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky umask(0077); 5005ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 5015ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann init_title(argc, argv, env, "hcid: "); 502c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky set_title("initializing"); 503c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 504c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Start logging to syslog and stderr */ 505c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky openlog("hcid", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); 506c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "HCI daemon ver %s started", VERSION); 507c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 508c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky memset(&sa, 0, sizeof(sa)); 509c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sa.sa_flags = SA_NOCLDSTOP; 510c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sa.sa_handler = sig_term; 511c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sigaction(SIGTERM, &sa, NULL); 512c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sigaction(SIGINT, &sa, NULL); 513c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sa.sa_handler = sig_hup; 514c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sigaction(SIGHUP, &sa, NULL); 515c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sa.sa_handler = sig_usr1; 516c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sigaction(SIGUSR1, &sa, NULL); 517c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky sa.sa_handler = sig_usr2; 518c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky sigaction(SIGUSR2, &sa, NULL); 519c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 520c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sa.sa_handler = SIG_IGN; 521c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sigaction(SIGCHLD, &sa, NULL); 522c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky sigaction(SIGPIPE, &sa, NULL); 523c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 524c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Create and bind HCI socket */ 525c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if ((hcid.sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) { 526c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Can't open HCI socket. %s(%d)", strerror(errno), errno); 527c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(1); 528c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 529c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 530c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Set filter */ 531c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hci_filter_clear(&flt); 532c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hci_filter_set_ptype(HCI_EVENT_PKT, &flt); 533c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky hci_filter_set_event(EVT_STACK_INTERNAL, &flt); 534c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (setsockopt(hcid.sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { 535c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Can't set filter. %s(%d)", strerror(errno), errno); 536c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(1); 537c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 538c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 539c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky addr.hci_family = AF_BLUETOOTH; 540c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky addr.hci_dev = HCI_DEV_NONE; 5415ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann if (bind(hcid.sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 542c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Can't bind HCI socket. %s(%d)\n", strerror(errno), errno); 543c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky exit(1); 544c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky } 545c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 546c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky if (read_config(hcid.config_file) < 0) 547c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_ERR, "Config load failed"); 548c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 549f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann#ifdef ENABLE_DBUS 550f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann if (hcid_dbus_init() == FALSE && hcid.dbus_pin_helper) { 551f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann syslog(LOG_ERR, "Unable to get on D-BUS"); 552f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann exit(1); 553f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann } 554f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann#else 555f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann if (hcid.dbus_pin_helper) { 556f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann syslog(LOG_ERR, "D-BUS not configured in this build of hcid"); 557f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann exit(1); 558f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann } 559f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann#endif 560f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann 561ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky init_security_data(); 562ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky 563c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Create event loop */ 564c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky event_loop = g_main_new(FALSE); 565c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 566c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Initialize already connected devices */ 567c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky init_all_devices(hcid.sock); 568c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 569c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky set_title("processing events"); 570c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 571c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky ctl_io = g_io_channel_unix_new(hcid.sock); 572c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL); 573c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 574c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky /* Start event processor */ 575c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky g_main_run(event_loop); 576c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky 5775ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann free_device_opts(); 5785ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann 579c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky syslog(LOG_INFO, "Exit."); 580c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky return 0; 581c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky} 582