device.c revision 632a9432774ff3a0c6e556e8f32a565b38890767
1c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky/*
272074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *
372074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
472074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *
572074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *  Copyright (C) 2000-2001  Qualcomm Incorporated
672074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
71798ef015acd1da838f3a265bb0003efe94757adMarcel Holtmann *  Copyright (C) 2002-2005  Marcel Holtmann <marcel@holtmann.org>
872074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *
972074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *
1072074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *  This program is free software; you can redistribute it and/or modify
11632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  it under the terms of the GNU General Public License as published by
12632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  the Free Software Foundation; either version 2 of the License, or
13632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  (at your option) any later version.
1472074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *
15632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  This program is distributed in the hope that it will be useful,
16632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  GNU General Public License for more details.
1972074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *
20632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  You should have received a copy of the GNU General Public License
21632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  along with this program; if not, write to the Free Software
22632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2372074e1e63e6cbe934c1e5eb9fd583ec81057a22Marcel Holtmann *
24c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky */
25c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
261d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann#ifdef HAVE_CONFIG_H
271d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann#include <config.h>
281d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann#endif
291d3715db11f573060cb02a2b7b7c44f06607d337Marcel Holtmann
30c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <stdio.h>
31632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann#include <errno.h>
32632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann#include <fcntl.h>
33c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <unistd.h>
34632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann#include <stdlib.h>
35c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <string.h>
36c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <signal.h>
37c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <syslog.h>
38c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <sys/time.h>
39f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <sys/stat.h>
40632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann#include <sys/ioctl.h>
41632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann#include <sys/socket.h>
42c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
43f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <bluetooth/bluetooth.h>
44f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <bluetooth/hci.h>
45f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky#include <bluetooth/hci_lib.h>
46c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
47c7c04aac86fec5084e3e1caf3eaaa3abd545f58dMarcel Holtmann#include "glib-ectomy.h"
48c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
49c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include "hcid.h"
50c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include "lib.h"
51c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
52c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystruct hcid_opts hcid;
535ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstruct device_opts default_device;
545ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstruct device_opts *parser_device;
555ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic struct device_list *device_list = NULL;
56c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
57c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic GMainLoop *event_loop;
58c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
59c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void usage(void)
60c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
61c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	printf("hcid - HCI daemon ver %s\n", VERSION);
62c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	printf("Usage: \n");
63c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	printf("\thcid [-n not_daemon] [-f config file]\n");
64c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
65c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
665ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic inline void init_device_defaults(struct device_opts *device_opts)
675ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{
685ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	memset(device_opts, 0, sizeof(*device_opts));
695ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device_opts->scan = SCAN_PAGE | SCAN_INQUIRY;
705ac3c1ef76b8d1640bad9a21b74b197a82111874Marcel Holtmann	device_opts->name = strdup("BlueZ");
715ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann}
725ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
735ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstruct device_opts *alloc_device_opts(char *ref)
745ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{
755ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	struct device_list *device;
765ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
775ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device = malloc(sizeof(struct device_list));
785ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (!device) {
790dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_INFO, "Can't allocate devlist opts buffer: %s (%d)",
800dab40dad416805e31cb5312956880609dc21443Marcel Holtmann							strerror(errno), errno);
815ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		exit(1);
825ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	}
835ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
845ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device->ref = ref;
855ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device->next = device_list;
865ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device_list = device;
875ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
885ac3c1ef76b8d1640bad9a21b74b197a82111874Marcel Holtmann	memcpy(&device->opts, &default_device, sizeof(struct device_opts));
895ac3c1ef76b8d1640bad9a21b74b197a82111874Marcel Holtmann	device->opts.name = strdup(default_device.name);
905ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
915ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	return &device->opts;
925ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann}
935ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
945ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic void free_device_opts(void)
955ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{
965ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	struct device_list *device, *next;
975ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
985ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (default_device.name) {
995ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		free(default_device.name);
1005ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		default_device.name = NULL;
1015ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	}
1025ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1035ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	for (device = device_list; device; device = next) {
1045ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		free(device->ref);
1055ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		if (device->opts.name)
1065ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann			free(device->opts.name);
1075ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		next = device->next;
1085ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		free(device);
1095ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	}
1105ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1115ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device_list = NULL;
1125ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann}
1135ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1145ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic inline struct device_opts *find_device_opts(char *ref)
1155ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{
1165ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	struct device_list *device;
1175ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1185ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	for (device = device_list; device; device = device->next)
1195ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		if (!strcmp(ref, device->ref))
1205ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann			return &device->opts;
1215ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1225ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	return NULL;
1235ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann}
1245ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1255ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannstatic struct device_opts *get_device_opts(int sock, int hdev)
1265ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann{
1275ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	struct device_opts *device_opts = NULL;
1285ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	struct hci_dev_info di;
1295ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1305ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	/* First try to get BD_ADDR based settings ... */
1315ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	di.dev_id = hdev;
1325ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (!ioctl(sock, HCIGETDEVINFO, (void *) &di)) {
1335ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		char addr[18];
1345ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		ba2str(&di.bdaddr, addr);
1355ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		device_opts = find_device_opts(addr);
1365ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	}
1375ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1385ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	/* ... then try HCI based settings ... */
1395ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (!device_opts) {
1405ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		char ref[8];
1415ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		snprintf(ref, sizeof(ref) - 1, "hci%d", hdev);
1425ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		device_opts = find_device_opts(ref);
1435ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	}
1445ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1455ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	/* ... and last use the default settings. */
1465ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (!device_opts)
1475ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		device_opts = &default_device;
1485ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
1495ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	return device_opts;
1505ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann}
1515ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
15230fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyanskystatic void configure_device(int hdev)
153c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
1545ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	struct device_opts *device_opts;
155c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct hci_dev_req dr;
156747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	struct hci_dev_info di;
157c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	int s;
158c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
15930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	/* Do configuration in the separate process */
160c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	switch (fork()) {
161c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 0:
162c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
163c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case -1:
1640dab40dad416805e31cb5312956880609dc21443Marcel Holtmann			syslog(LOG_ERR, "Fork failed. Can't init device hci%d: %s (%d)",
1650dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
166c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		default:
167c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			return;
168c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
169c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
17030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	set_title("hci%d config", hdev);
171c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
172c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if ((s = hci_open_dev(hdev)) < 0) {
1730dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't open device hci%d: %s (%d)",
1740dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
175c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
176c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
177c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
178747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	di.dev_id = hdev;
179747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	if (ioctl(s, HCIGETDEVINFO, (void *) &di) < 0)
180747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann		exit(1);
181747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann
182747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	if (hci_test_bit(HCI_RAW, &di.flags))
183747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann		exit(0);
184747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann
1855ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	dr.dev_id   = hdev;
1865ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device_opts = get_device_opts(s, hdev);
187c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
188c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Set scan mode */
1895ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	dr.dev_opt = device_opts->scan;
1905ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (ioctl(s, HCISETSCAN, (unsigned long) &dr) < 0) {
1910dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't set scan mode on hci%d: %s (%d)",
1920dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
193c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
194c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
195c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Set authentication */
1965ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (device_opts->auth)
197c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		dr.dev_opt = AUTH_ENABLED;
198c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	else
199c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		dr.dev_opt = AUTH_DISABLED;
200c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2015ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (ioctl(s, HCISETAUTH, (unsigned long) &dr) < 0) {
2020dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't set auth on hci%d: %s (%d)",
2030dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
204c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
205c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
206c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Set encryption */
2075ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (device_opts->encrypt)
208c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		dr.dev_opt = ENCRYPT_P2P;
209c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	else
210c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		dr.dev_opt = ENCRYPT_DISABLED;
211c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2125ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (ioctl(s, HCISETENCRYPT, (unsigned long) &dr) < 0) {
2130dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't set encrypt on hci%d: %s (%d)",
2140dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
215c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
216c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2172bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	/* Set device name */
2182bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_NAME)) && device_opts->name) {
2192bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann		change_local_name_cp cp;
22052bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		write_ext_inquiry_response_cp ip;
22152bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		uint8_t len;
22252bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann
2232bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann		memset(cp.name, 0, sizeof(cp.name));
2241f422e5f2b343d35a8c77ce4be16f74b2819b2bfMarcel Holtmann		expand_name((char *) cp.name, sizeof(cp.name), device_opts->name, hdev);
2252bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann
22652bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		ip.fec = 0x00;
22752bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		memset(ip.data, 0, sizeof(ip.data));
22852bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		len = strlen((char *) cp.name);
22952bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		if (len > 48) {
23052bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann			len = 48;
23152bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann			ip.data[1] = 0x08;
23252bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		} else
23352bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann			ip.data[1] = 0x09;
23452bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		ip.data[0] = len + 1;
23552bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		memcpy(ip.data + 2, cp.name, len);
23652bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann
2372bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann		hci_send_cmd(s, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME,
2388d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann					CHANGE_LOCAL_NAME_CP_SIZE, &cp);
23952bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann
24052bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann		if (di.features[6] & LMP_EXT_INQ)
24152bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann			hci_send_cmd(s, OGF_HOST_CTL, OCF_WRITE_EXT_INQUIRY_RESPONSE,
24252bd6030faf7f3448beadab2b9388e339de08811Marcel Holtmann					WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &ip);
2432bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	}
2442bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann
2455ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	/* Set device class */
2462bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_CLASS))) {
2475ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		uint32_t class = htobl(device_opts->class);
248c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		write_class_of_dev_cp cp;
2495ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
250c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		memcpy(cp.dev_class, &class, 3);
251c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		hci_send_cmd(s, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV,
2528d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann					WRITE_CLASS_OF_DEV_CP_SIZE, &cp);
253c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
254c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2552bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	/* Set voice setting */
2562bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_VOICE))) {
2572bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann		write_voice_setting_cp cp;
258c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2592bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann		cp.voice_setting = htobl(device_opts->voice);
2602bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann		hci_send_cmd(s, OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING,
2618d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann					WRITE_VOICE_SETTING_CP_SIZE, &cp);
262c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
263c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
264959b1e8c1d5ad023e1b3c8157a844c61df44a0a1Marcel Holtmann	/* Set inquiry mode */
26514e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_INQMODE))) {
266959b1e8c1d5ad023e1b3c8157a844c61df44a0a1Marcel Holtmann		write_inquiry_mode_cp cp;
267959b1e8c1d5ad023e1b3c8157a844c61df44a0a1Marcel Holtmann
26814e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann		switch (device_opts->inqmode) {
26914e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann		case 2:
27014e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann			if (di.features[6] & LMP_EXT_INQ) {
27114e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann				cp.mode = 2;
27214e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann				break;
27314e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann			}
27414e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann		case 1:
27514e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann			if (di.features[3] & LMP_RSSI_INQ) {
27614e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann				cp.mode = 1;
27714e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann				break;
27814e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann			}
27914e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann		default:
28014e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann			cp.mode = 0;
28114e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann			break;
28214e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann		}
28314e7b4e9a3c868b3bded7b08488aac89210984a6Marcel Holtmann
284959b1e8c1d5ad023e1b3c8157a844c61df44a0a1Marcel Holtmann		hci_send_cmd(s, OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE,
2858d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann					WRITE_INQUIRY_MODE_CP_SIZE, &cp);
2868d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann	}
2878d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann
2888d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann	/* Set page timeout */
2898d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_PAGETO))) {
2908d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann		write_page_timeout_cp cp;
2918d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann
2928d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann		cp.timeout = htobs(device_opts->pageto);
2938d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann		hci_send_cmd(s, OGF_HOST_CTL, OCF_WRITE_PAGE_TIMEOUT,
2948d07fe695736cfc4126f1aad4144303161c61e21Marcel Holtmann					WRITE_PAGE_TIMEOUT_CP_SIZE, &cp);
295959b1e8c1d5ad023e1b3c8157a844c61df44a0a1Marcel Holtmann	}
296959b1e8c1d5ad023e1b3c8157a844c61df44a0a1Marcel Holtmann
297c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	exit(0);
298c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
299c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
30030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyanskystatic void init_device(int hdev)
30130fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky{
3025ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	struct device_opts *device_opts;
30330fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	struct hci_dev_req dr;
304747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	struct hci_dev_info di;
30530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	int s;
30630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
30730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	/* Do initialization in the separate process */
30830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	switch (fork()) {
30930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		case 0:
31030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky			break;
31130fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		case -1:
3120dab40dad416805e31cb5312956880609dc21443Marcel Holtmann			syslog(LOG_ERR, "Fork failed. Can't init device hci%d: %s (%d)",
3130dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
31430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		default:
31530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky			return;
31630fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	}
31730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
31830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	set_title("hci%d init", hdev);
31930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
32030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	if ((s = hci_open_dev(hdev)) < 0) {
3210dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't open device hci%d: %s (%d)",
3220dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
32330fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		exit(1);
32430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	}
32530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
326cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky	/* Start HCI device */
327cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky	if (ioctl(s, HCIDEVUP, hdev) < 0 && errno != EALREADY) {
3280dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't init device hci%d: %s (%d)",
3290dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
330cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky		exit(1);
331cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky	}
332cbc274c6e3ce3b2135c21c101d19271d66d3215eMax Krasnyansky
333747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	di.dev_id = hdev;
334747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	if (ioctl(s, HCIGETDEVINFO, (void *) &di) < 0)
335747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann		exit(1);
336747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann
337747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann	if (hci_test_bit(HCI_RAW, &di.flags))
338747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann		exit(0);
339747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann
3405ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	dr.dev_id   = hdev;
3415ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	device_opts = get_device_opts(s, hdev);
34230fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
34330fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	/* Set packet type */
3442bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_PTYPE))) {
3455ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		dr.dev_opt = device_opts->pkt_type;
3465ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		if (ioctl(s, HCISETPTYPE, (unsigned long) &dr) < 0) {
3470dab40dad416805e31cb5312956880609dc21443Marcel Holtmann			syslog(LOG_ERR, "Can't set packet type on hci%d: %s (%d)",
3480dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
34930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		}
35030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	}
35130fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
35230fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	/* Set link mode */
3532bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_LM))) {
3545ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		dr.dev_opt = device_opts->link_mode;
3555ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		if (ioctl(s, HCISETLINKMODE, (unsigned long) &dr) < 0) {
3560dab40dad416805e31cb5312956880609dc21443Marcel Holtmann			syslog(LOG_ERR, "Can't set link mode on hci%d: %s (%d)",
3570dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
35830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		}
35930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	}
36030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
36130fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	/* Set link policy */
3622bc66b1d0af2e2a01e545493510347578928ae33Marcel Holtmann	if ((device_opts->flags & (1 << HCID_SET_LP))) {
3635ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		dr.dev_opt = device_opts->link_policy;
3645ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		if (ioctl(s, HCISETLINKPOL, (unsigned long) &dr) < 0) {
3650dab40dad416805e31cb5312956880609dc21443Marcel Holtmann			syslog(LOG_ERR, "Can't set link policy on hci%d: %s (%d)",
3660dab40dad416805e31cb5312956880609dc21443Marcel Holtmann						hdev, strerror(errno), errno);
36730fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		}
36830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	}
36930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
37030fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky	exit(0);
37130fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky}
37230fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
373c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void init_all_devices(int ctl)
374c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
375c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct hci_dev_list_req *dl;
376c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct hci_dev_req *dr;
377c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	int i;
378c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
379c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if (!(dl = malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t)))) {
3800dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_INFO, "Can't allocate devlist buffer: %s (%d)",
3810dab40dad416805e31cb5312956880609dc21443Marcel Holtmann							strerror(errno), errno);
382c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
383c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
384c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	dl->dev_num = HCI_MAX_DEV;
385c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	dr = dl->dev_req;
386c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
3875ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) {
3880dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_INFO, "Can't get device list: %s (%d)",
3890dab40dad416805e31cb5312956880609dc21443Marcel Holtmann							strerror(errno), errno);
390c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
391c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
392c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
3935ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	for (i = 0; i < dl->dev_num; i++, dr++) {
394c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		if (hcid.auto_init)
395c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			init_device(dr->dev_id);
396c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
397747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann		if (hcid.auto_init && hci_test_bit(HCI_UP, &dr->dev_opt))
39830fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky			configure_device(dr->dev_id);
39930fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky
400747bc0b292ee5655ef2695c4e8e18f55c4037567Marcel Holtmann		if (hcid.security && hci_test_bit(HCI_UP, &dr->dev_opt))
401c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			start_security_manager(dr->dev_id);
40234e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann
40334e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#ifdef ENABLE_DBUS
4047a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann		if (hci_test_bit(HCI_UP, &dr->dev_opt))
4057a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann			hcid_dbus_register_manager(dr->dev_id);
4067a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann
40734e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann		hcid_dbus_register_device(dr->dev_id);
40834e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#endif
409c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
4105ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
411c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	free(dl);
412c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
413c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
414c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void init_defaults(void)
415c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
416c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	hcid.auto_init = 0;
417c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	hcid.security  = 0;
418c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4195ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	init_device_defaults(&default_device);
420c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
421c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
422c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void sig_usr1(int sig)
423c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
424c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky	toggle_pairing(0);
425c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky}
426c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky
427c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyanskystatic void sig_usr2(int sig)
428c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky{
429c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky	toggle_pairing(1);
430c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
431c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
432c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void sig_term(int sig)
433c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
434c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	g_main_quit(event_loop);
435c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
436c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
437c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic void sig_hup(int sig)
438c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
439c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	syslog(LOG_INFO, "Reloading config file");
4405ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
441c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	init_defaults();
4425ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
443c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if (read_config(hcid.config_file) < 0)
444c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		syslog(LOG_ERR, "Config reload failed");
445c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
446ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky	init_security_data();
447ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky
448c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	init_all_devices(hcid.sock);
449c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
450c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
451c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskystatic inline void device_event(GIOChannel *chan, evt_stack_internal *si)
452c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
453c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	evt_si_device *sd = (void *) &si->data;
454c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
455c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	switch (sd->event) {
456c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	case HCI_DEV_REG:
457c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		syslog(LOG_INFO, "HCI dev %d registered", sd->dev_id);
458c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		if (hcid.auto_init)
459c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			init_device(sd->dev_id);
4607a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann#ifdef ENABLE_DBUS
4617a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann		hcid_dbus_register_device(sd->dev_id);
4627a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann#endif
463c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		break;
464c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
465c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	case HCI_DEV_UNREG:
466c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		syslog(LOG_INFO, "HCI dev %d unregistered", sd->dev_id);
4677a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann#ifdef ENABLE_DBUS
4687a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann		hcid_dbus_unregister_device(sd->dev_id);
4697a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann#endif
470c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		break;
471c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
472c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	case HCI_DEV_UP:
473c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		syslog(LOG_INFO, "HCI dev %d up", sd->dev_id);
47430fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky		if (hcid.auto_init)
47530fc590d680e1dddd718316e9a0936e6dfa04be6Max Krasnyansky			configure_device(sd->dev_id);
476c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		if (hcid.security)
477c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			start_security_manager(sd->dev_id);
47834e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#ifdef ENABLE_DBUS
4797a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann		hcid_dbus_register_manager(sd->dev_id);
48034e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#endif
481c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		break;
482c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
483c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	case HCI_DEV_DOWN:
484c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		syslog(LOG_INFO, "HCI dev %d down", sd->dev_id);
485c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		if (hcid.security)
486c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			stop_security_manager(sd->dev_id);
48734e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#ifdef ENABLE_DBUS
4887a58f1b38a86d30477048e84d979d627ebfec10bMarcel Holtmann		hcid_dbus_unregister_manager(sd->dev_id);
48934e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#endif
490c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		break;
491c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
492c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
493c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4941798ef015acd1da838f3a265bb0003efe94757adMarcel Holtmannstatic gboolean io_stack_event(GIOChannel *chan, GIOCondition cond, gpointer data)
495c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
4968100e0c660e200a9d789dcd054f25a20778379cdMarcel Holtmann	unsigned char buf[HCI_MAX_FRAME_SIZE], *ptr;
497c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	evt_stack_internal *si;
498c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	hci_event_hdr *eh;
4998100e0c660e200a9d789dcd054f25a20778379cdMarcel Holtmann	int type;
5008100e0c660e200a9d789dcd054f25a20778379cdMarcel Holtmann	size_t len;
501c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	GIOError err;
502c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
503c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	ptr = buf;
504c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
5051f422e5f2b343d35a8c77ce4be16f74b2819b2bfMarcel Holtmann	if ((err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len))) {
506c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		if (err == G_IO_ERROR_AGAIN)
507c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			return TRUE;
508c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
5090dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Read from control socket failed: %s (%d)",
5100dab40dad416805e31cb5312956880609dc21443Marcel Holtmann							strerror(errno), errno);
511c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		g_main_quit(event_loop);
512c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		return FALSE;
513c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
514c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
515c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	type = *ptr++;
516c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
517c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if (type != HCI_EVENT_PKT)
518c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		return TRUE;
519c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
520c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	eh = (hci_event_hdr *) ptr;
521c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if (eh->evt != EVT_STACK_INTERNAL)
522c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		return TRUE;
523c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
524c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	ptr += HCI_EVENT_HDR_SIZE;
525c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
526c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	si = (evt_stack_internal *) ptr;
527c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	switch (si->type) {
528c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	case EVT_SI_DEVICE:
529c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		device_event(chan, si);
530c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		break;
531c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
532c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
533c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	return TRUE;
534c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
535c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
5365ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmannextern int optind, opterr, optopt;
537c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskyextern char *optarg;
538c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
539c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskyint main(int argc, char *argv[], char *env[])
540c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
541c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	int daemon, dofork, opt, fd;
542c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct sockaddr_hci addr;
543c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct hci_filter flt;
544c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct sigaction sa;
545c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	GIOChannel *ctl_io;
546c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
547c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	daemon = 1; dofork = 1;
548c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
549c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Default HCId settings */
550c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	hcid.config_file = HCID_CONFIG_FILE;
5515ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	hcid.host_name   = get_host_name();
5525ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	hcid.security    = HCID_SEC_AUTO;
5535ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	hcid.pairing     = HCID_PAIRING_MULTI;
554c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
5555ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	hcid.pin_file    = strdup(HCID_PIN_FILE);
5565ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	hcid.pin_helper  = strdup(HCID_PIN_HELPER);
5575ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	hcid.key_file    = strdup(HCID_KEY_FILE);
558c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
559c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	init_defaults();
5606aa87b34ea5135cfb8dd403f1bfca8fe10172fd1Marcel Holtmann
5615ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	while ((opt = getopt(argc, argv, "f:n")) != EOF) {
5625ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann		switch (opt) {
563ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky		case 'n':
564ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky			daemon = 0;
565ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky			break;
566c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
567ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky		case 'f':
568ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky			hcid.config_file = strdup(optarg);
569ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky			break;
570c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
571ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky		default:
572ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky			usage();
573ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky			exit(1);
574c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
575c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
576c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
577c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if (daemon) {
578c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		if (dofork && fork())
579c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			exit(0);
580c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
581c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		/* Direct stdin,stdout,stderr to '/dev/null' */
582c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		fd = open("/dev/null", O_RDWR);
583c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		dup2(fd, 0); dup2(fd, 1); dup2(fd, 2);
584c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		close(fd);
585c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
586c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		setsid();
587c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
588c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		chdir("/");
589c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
590c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
591f79b2c879c633667916d1fb17870c54597294d8eMax Krasnyansky	umask(0077);
5925ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
5935ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	init_title(argc, argv, env, "hcid: ");
594c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	set_title("initializing");
595c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
596c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Start logging to syslog and stderr */
597c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	openlog("hcid", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
5984c65d109ee2ced4a49a511ec185da11a8b27f069Marcel Holtmann	syslog(LOG_INFO, "Bluetooth HCI daemon");
599c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
600c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	memset(&sa, 0, sizeof(sa));
601c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sa.sa_flags = SA_NOCLDSTOP;
602c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sa.sa_handler = sig_term;
603c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sigaction(SIGTERM, &sa, NULL);
604c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sigaction(SIGINT,  &sa, NULL);
605c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sa.sa_handler = sig_hup;
606c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sigaction(SIGHUP, &sa, NULL);
607c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sa.sa_handler = sig_usr1;
608c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sigaction(SIGUSR1, &sa, NULL);
609c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky	sa.sa_handler = sig_usr2;
610c5dca08e234386563667e8f790b4e1122c364c5dMax Krasnyansky	sigaction(SIGUSR2, &sa, NULL);
611c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
612c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sa.sa_handler = SIG_IGN;
613c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sigaction(SIGCHLD, &sa, NULL);
614c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sigaction(SIGPIPE, &sa, NULL);
615c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
616c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Create and bind HCI socket */
617c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if ((hcid.sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {
6180dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't open HCI socket: %s (%d)",
6190dab40dad416805e31cb5312956880609dc21443Marcel Holtmann							strerror(errno), errno);
620c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
621c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
622c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
623c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Set filter */
624c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	hci_filter_clear(&flt);
625c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
626c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	hci_filter_set_event(EVT_STACK_INTERNAL, &flt);
627c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if (setsockopt(hcid.sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
6280dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't set filter: %s (%d)",
6290dab40dad416805e31cb5312956880609dc21443Marcel Holtmann							strerror(errno), errno);
630c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
631c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
632c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
633c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	addr.hci_family = AF_BLUETOOTH;
634c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	addr.hci_dev = HCI_DEV_NONE;
6355ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	if (bind(hcid.sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
6360dab40dad416805e31cb5312956880609dc21443Marcel Holtmann		syslog(LOG_ERR, "Can't bind HCI socket: %s (%d)",
6370dab40dad416805e31cb5312956880609dc21443Marcel Holtmann							strerror(errno), errno);
638c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
639c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
640c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
641c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	if (read_config(hcid.config_file) < 0)
642c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		syslog(LOG_ERR, "Config load failed");
643c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
644f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann#ifdef ENABLE_DBUS
645f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann	if (hcid_dbus_init() == FALSE && hcid.dbus_pin_helper) {
646f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann		syslog(LOG_ERR, "Unable to get on D-BUS");
647f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann		exit(1);
648f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann	}
649f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann#else
650f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann	if (hcid.dbus_pin_helper) {
651f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann		syslog(LOG_ERR, "D-BUS not configured in this build of hcid");
652f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann		exit(1);
653f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann	}
654f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann#endif
655f17bb94f47090f3397b60b5e264aa9f18dbf203dMarcel Holtmann
656ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky	init_security_data();
657ccb0bf6ad34beb532176a49731537f09fe01875cMax Krasnyansky
658c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Create event loop */
659c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	event_loop = g_main_new(FALSE);
660c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
661c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Initialize already connected devices */
662c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	init_all_devices(hcid.sock);
663c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
664c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	set_title("processing events");
665c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
666c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	ctl_io = g_io_channel_unix_new(hcid.sock);
667c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	g_io_add_watch(ctl_io, G_IO_IN, io_stack_event, NULL);
668c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
669c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Start event processor */
670c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	g_main_run(event_loop);
671c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
6725ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann	free_device_opts();
6735ff58cb0e277fb4cb4613aa3d2a83e7237c59894Marcel Holtmann
67434e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#ifdef ENABLE_DBUS
67534e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann	hcid_dbus_exit();
67634e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann#endif
67734e266aaa88d0ff1e5930946d96783420c232895Marcel Holtmann
678c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	syslog(LOG_INFO, "Exit.");
679c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	return 0;
680c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
681