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