device.c revision 2c1effee41e974f97b21aec1bdd1a232ba48056a
1dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann/*
2dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
3dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
5f1659f19cfb3ef0c0c09b5f5b7e2b06d90d079abMarcel Holtmann *  Copyright (C) 2006-2007  Nokia Corporation
6e823c15e43a6f924779e466d434c51157002d9eeMarcel Holtmann *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
7dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
8dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
9dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  This program is free software; you can redistribute it and/or modify
10dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  it under the terms of the GNU General Public License as published by
11dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  the Free Software Foundation; either version 2 of the License, or
12dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  (at your option) any later version.
13dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
14dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  This program is distributed in the hope that it will be useful,
15dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  GNU General Public License for more details.
18dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
19dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  You should have received a copy of the GNU General Public License
20dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  along with this program; if not, write to the Free Software
21dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
23dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann */
24dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
25dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#ifdef HAVE_CONFIG_H
26dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <config.h>
27dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#endif
28dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
29dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <stdio.h>
30dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <errno.h>
31dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <stdlib.h>
32dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <stdarg.h>
33dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <sys/time.h>
346a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include <sys/stat.h>
35943b02e163e169795a010c36a3b3343cc5092a96Marcel Holtmann#include <sys/param.h>
36dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <sys/socket.h>
37dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
38dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/bluetooth.h>
39dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/hci.h>
40dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/hci_lib.h>
41dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <glib.h>
4386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
4486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <dbus/dbus.h>
4586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
4686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "dbus-helper.h"
4786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
4826e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann#include "hcid.h"
49eb4d49890ca8a4d8f567e81fdf82b6903d30f326Marcel Holtmann#include "sdpd.h"
5026e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann
5186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "logging.h"
526a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include "textfile.h"
53dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include "oui.h"
54dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
552c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes#include "adapter.h"
5686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "device.h"
5786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
58dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#define MAX_DEVICES 16
59dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
602c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes#define DEVICE_INTERFACE "org.bluez.Device"
612c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
62dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstruct hci_peer {
63dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct timeval lastseen;
64dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct timeval lastused;
65dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
66dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bdaddr_t bdaddr;
67dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint32_t class;
68dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int8_t   rssi;
69dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  data[240];
70dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  name[248];
71dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
72dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  pscan_rep_mode;
73dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  pscan_period_mode;
74dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  pscan_mode;
75dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t clock_offset;
76dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
77dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_peer *next;
78dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann};
79dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
80dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstruct hci_conn {
81dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bdaddr_t bdaddr;
82dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t handle;
83dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
84dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_conn *next;
85dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann};
86dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
87dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstruct hci_dev {
8857eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	int ignore;
8957eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann
90dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bdaddr_t bdaddr;
91dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  features[8];
92dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  lmp_ver;
93dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t lmp_subver;
940d7408aa899f84210d0e6418ee528636292276bcMarcel Holtmann	uint16_t hci_rev;
95dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t manufacturer;
96dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
970b727924102df07d609be955800793c1f33d6952Marcel Holtmann	uint8_t  ssp_mode;
986a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	uint8_t  name[248];
99277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	uint8_t  class[3];
1006a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
101dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_peer *peers;
102dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_conn *conns;
103dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann};
104dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
105dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstatic struct hci_dev devices[MAX_DEVICES];
106dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
107dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#define ASSERT_DEV_ID { if (dev_id >= MAX_DEVICES) return -ERANGE; }
108dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
10952a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannvoid init_adapters(void)
110dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
111dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int i;
112dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
113dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	for (i = 0; i < MAX_DEVICES; i++)
114dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		memset(devices + i, 0, sizeof(struct hci_dev));
115dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
116dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
117ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedbergstatic int device_read_bdaddr(uint16_t dev_id, bdaddr_t *bdaddr)
118ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg{
119ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	int dd;
120ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
121ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	dd = hci_open_dev(dev_id);
122ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	if (dd < 0) {
123ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		error("Can't open device hci%d",
1240b727924102df07d609be955800793c1f33d6952Marcel Holtmann					dev_id, strerror(errno), errno);
125ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		return -errno;
126ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	}
127ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
128ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	if (hci_read_bd_addr(dd, bdaddr, 2000) < 0) {
129fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		int err = errno;
130ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		error("Can't read address for hci%d: %s (%d)",
1310b727924102df07d609be955800793c1f33d6952Marcel Holtmann					dev_id, strerror(errno), errno);
132ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		hci_close_dev(dd);
133fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
134ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	}
135ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
136ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	hci_close_dev(dd);
137ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
138ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	return 0;
139ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg}
140ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
14152a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint add_adapter(uint16_t dev_id)
142dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
143dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
144dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev_info di;
145dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
146dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
147dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
148dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
149dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
15057eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	if (hci_devinfo(dev_id, &di) < 0) {
15157eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		dev->ignore = 1;
152dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -errno;
15357eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	}
15457eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann
15557eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	if (hci_test_bit(HCI_RAW, &di.flags)) {
15657eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		info("Device hci%d is using raw mode", dev_id);
15757eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		dev->ignore = 1;
15857eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	}
159dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
160ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	if (bacmp(&di.bdaddr, BDADDR_ANY))
161ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		bacpy(&dev->bdaddr, &di.bdaddr);
162ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	else {
1630b727924102df07d609be955800793c1f33d6952Marcel Holtmann		int err = device_read_bdaddr(dev_id, &dev->bdaddr);
1640b727924102df07d609be955800793c1f33d6952Marcel Holtmann		if (err < 0)
1650b727924102df07d609be955800793c1f33d6952Marcel Holtmann			return err;
166ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	}
167dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	memcpy(dev->features, di.features, 8);
168dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
169dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been added", dev_id);
170dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
171dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
172dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
173dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
17452a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint remove_adapter(uint16_t dev_id)
175dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
176dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
177dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
178dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
179dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
180dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
181dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
182dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	memset(dev, 0, sizeof(struct hci_dev));
183dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
184dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been removed", dev_id);
185dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
186dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
187dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
188dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
189b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmannstatic inline uint8_t get_inquiry_mode(struct hci_dev *dev)
190b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann{
191b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	if (dev->features[6] & LMP_EXT_INQ)
192b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann		return 2;
193b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
194b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	if (dev->features[3] & LMP_RSSI_INQ)
195b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann		return 1;
196b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
197e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann	if (dev->manufacturer == 11 &&
198e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann			dev->hci_rev == 0x00 && dev->lmp_subver == 0x0757)
199e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann		return 1;
200e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann
201431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann	if (dev->manufacturer == 15) {
202431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann		if (dev->hci_rev == 0x03 && dev->lmp_subver == 0x6963)
203431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann			return 1;
204431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann		if (dev->hci_rev == 0x09 && dev->lmp_subver == 0x6963)
205431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann			return 1;
206b98c93ed852d29557fe71de5262357b704f85592Marcel Holtmann		if (dev->hci_rev == 0x00 && dev->lmp_subver == 0x6965)
207b98c93ed852d29557fe71de5262357b704f85592Marcel Holtmann			return 1;
208431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann	}
20919fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann
21019fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann	if (dev->manufacturer == 31 &&
21119fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann			dev->hci_rev == 0x2005 && dev->lmp_subver == 0x1805)
21219fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann		return 1;
21319fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann
214b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	return 0;
215b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann}
216b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
2170b727924102df07d609be955800793c1f33d6952Marcel Holtmannstatic void update_ext_inquiry_response(int dd, struct hci_dev *dev)
2180b727924102df07d609be955800793c1f33d6952Marcel Holtmann{
2190b727924102df07d609be955800793c1f33d6952Marcel Holtmann	uint8_t fec = 0, data[240];
2200b727924102df07d609be955800793c1f33d6952Marcel Holtmann
2210b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (!(dev->features[6] & LMP_EXT_INQ))
2220b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return;
2230b727924102df07d609be955800793c1f33d6952Marcel Holtmann
2240b727924102df07d609be955800793c1f33d6952Marcel Holtmann	memset(data, 0, sizeof(data));
2250b727924102df07d609be955800793c1f33d6952Marcel Holtmann
226eb4d49890ca8a4d8f567e81fdf82b6903d30f326Marcel Holtmann	if (dev->ssp_mode > 0)
227eb4d49890ca8a4d8f567e81fdf82b6903d30f326Marcel Holtmann		create_ext_inquiry_response((char *) dev->name, data);
2280b727924102df07d609be955800793c1f33d6952Marcel Holtmann
2290b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_write_ext_inquiry_response(dd, fec, data, 2000) < 0)
2300b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't write extended inquiry response: %s (%d)",
2310b727924102df07d609be955800793c1f33d6952Marcel Holtmann						strerror(errno), errno);
2320b727924102df07d609be955800793c1f33d6952Marcel Holtmann}
2330b727924102df07d609be955800793c1f33d6952Marcel Holtmann
23452a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint start_adapter(uint16_t dev_id)
235dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
236dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
237dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_version ver;
238b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	uint8_t features[8], inqmode;
2393dfe93f27c455e07be72a38239f4f8335ba6a860Marcel Holtmann	uint8_t events[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00 };
2400b727924102df07d609be955800793c1f33d6952Marcel Holtmann	char name[249];
241277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	int dd, err;
242dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
243dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
244dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
245dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
246dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
24757eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	if (dev->ignore)
24857eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		return 0;
24957eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann
250dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dd = hci_open_dev(dev_id);
251dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (dd < 0) {
25226e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
253dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann					dev_id, strerror(errno), errno);
254dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -errno;
255dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	}
256dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
257dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (hci_read_local_version(dd, &ver, 1000) < 0) {
258fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		int err = errno;
25926e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't read version info for hci%d: %s (%d)",
260dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann					dev_id, strerror(errno), errno);
261276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmann		hci_close_dev(dd);
262fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
263dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	}
264dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
2650fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann	dev->hci_rev = ver.hci_rev;
266dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev->lmp_ver = ver.lmp_ver;
267dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev->lmp_subver = ver.lmp_subver;
268dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev->manufacturer = ver.manufacturer;
269dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
270b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	if (hci_read_local_features(dd, features, 1000) < 0) {
271277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		err = errno;
272b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann		error("Can't read features for hci%d: %s (%d)",
273277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi					dev_id, strerror(err), err);
274276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmann		hci_close_dev(dd);
275fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
276b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	}
277b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
278b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	memcpy(dev->features, features, 8);
279b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
280277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	if (hci_read_class_of_dev(dd, dev->class, 1000) < 0) {
281277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		err = errno;
2820b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't read class of device on hci%d: %s (%d)",
2830b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(err), err);
284277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		hci_close_dev(dd);
285277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		return -err;
286277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	}
287277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
2880b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_read_local_name(dd, sizeof(name), name, 2000) < 0) {
2890b727924102df07d609be955800793c1f33d6952Marcel Holtmann		err = errno;
2900b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't read local name on hci%d: %s (%d)",
2910b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(err), err);
2920b727924102df07d609be955800793c1f33d6952Marcel Holtmann		hci_close_dev(dd);
2930b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return -err;
2940b727924102df07d609be955800793c1f33d6952Marcel Holtmann	}
295b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
2960b727924102df07d609be955800793c1f33d6952Marcel Holtmann	memcpy(dev->name, name, 248);
2970b727924102df07d609be955800793c1f33d6952Marcel Holtmann
2980b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (!(features[6] & LMP_SIMPLE_PAIR))
2990b727924102df07d609be955800793c1f33d6952Marcel Holtmann		goto setup;
3000b727924102df07d609be955800793c1f33d6952Marcel Holtmann
3010b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_read_simple_pairing_mode(dd, &dev->ssp_mode, 1000) < 0) {
3020b727924102df07d609be955800793c1f33d6952Marcel Holtmann		err = errno;
3030b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't read simple pairing mode on hci%d: %s (%d)",
3040b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(err), err);
305276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmann		hci_close_dev(dd);
306fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
307b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	}
308b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
3090b727924102df07d609be955800793c1f33d6952Marcel Holtmannsetup:
31057290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann	if (ver.hci_rev > 1) {
31157290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		if (features[5] & LMP_SNIFF_SUBR)
31257290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann			events[5] |= 0x20;
31357290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
314a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann		if (features[5] & LMP_PAUSE_ENC)
315a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann			events[5] |= 0x80;
316a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann
31757290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		if (features[6] & LMP_EXT_INQ)
31857290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann			events[5] |= 0x40;
31957290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
320a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann		if (features[6] & LMP_NFLUSH_PKTS)
321a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann			events[7] |= 0x01;
322f4051e4e1bc3a5a00fc74b5b5eb7eb3794f67310Johan Hedberg
32357290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		if (features[7] & LMP_LSTO)
32457290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann			events[6] |= 0x80;
32557290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
3260b727924102df07d609be955800793c1f33d6952Marcel Holtmann		if (features[6] & LMP_SIMPLE_PAIR) {
3270b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x01;	/* IO Capability Request */
3280b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x02;	/* IO Capability Response */
3290b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x04;	/* User Confirmation Request */
3300b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x08;	/* User Passkey Request */
3310b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x10;	/* Remote OOB Data Request */
3320b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x20;	/* Simple Pairing Complete */
3330b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[7] |= 0x04;	/* User Passkey Notification */
3340b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[7] |= 0x08;	/* Keypress Notification */
3350b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[7] |= 0x10;	/* Remote Host Supported Features Notification */
3360b727924102df07d609be955800793c1f33d6952Marcel Holtmann		}
3370b727924102df07d609be955800793c1f33d6952Marcel Holtmann
33857290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		hci_send_cmd(dd, OGF_HOST_CTL, OCF_SET_EVENT_MASK,
33957290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann						sizeof(events), events);
34057290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann	}
34157290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
342c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann	if (read_local_name(&dev->bdaddr, name) == 0) {
343c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann		memcpy(dev->name, name, 248);
344c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann		hci_write_local_name(dd, name, 5000);
345c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann        }
346c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann
3470b727924102df07d609be955800793c1f33d6952Marcel Holtmann	update_ext_inquiry_response(dd, dev);
3480b727924102df07d609be955800793c1f33d6952Marcel Holtmann
3490b727924102df07d609be955800793c1f33d6952Marcel Holtmann	inqmode = get_inquiry_mode(dev);
3500b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (inqmode < 1)
3510b727924102df07d609be955800793c1f33d6952Marcel Holtmann		goto done;
3520b727924102df07d609be955800793c1f33d6952Marcel Holtmann
3530b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_write_inquiry_mode(dd, inqmode, 1000) < 0) {
3540b727924102df07d609be955800793c1f33d6952Marcel Holtmann		int err = errno;
3550b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't write inquiry mode for hci%d: %s (%d)",
3560b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(errno), err);
3570b727924102df07d609be955800793c1f33d6952Marcel Holtmann		hci_close_dev(dd);
3580b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return -err;
3590b727924102df07d609be955800793c1f33d6952Marcel Holtmann	}
3600b727924102df07d609be955800793c1f33d6952Marcel Holtmann
361276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmanndone:
362dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	hci_close_dev(dd);
363dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
364dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been activated", dev_id);
365dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
366dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
367dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
368dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
36952a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint stop_adapter(uint16_t dev_id)
370dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
371dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
372dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
373dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been disabled", dev_id);
374dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
375dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
376dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
377dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
3780e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmannint update_adapter(uint16_t dev_id)
3790e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann{
3800e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	struct hci_dev *dev;
3810e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	int dd;
3820e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3830e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	ASSERT_DEV_ID;
3840e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3850e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	dev = &devices[dev_id];
3860e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3870e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	if (dev->ignore)
3880e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann		return 0;
3890e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3900e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	dd = hci_open_dev(dev_id);
3910e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	if (dd < 0) {
3920e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann		error("Can't open device hci%d",
3930e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann					dev_id, strerror(errno), errno);
3940e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann		return -errno;
3950e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	}
3960e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3970e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	update_ext_inquiry_response(dd, dev);
3980e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3990e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	hci_close_dev(dd);
4000e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
4010e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	return 0;
4020e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann}
4030e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
404dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_address(uint16_t dev_id, char *address, size_t size)
405dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
4068586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	struct hci_dev *dev;
4078586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
408dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
409dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
410dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (size < 18)
411dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -ENOBUFS;
412dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4138586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	dev = &devices[dev_id];
4148586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4158586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	return ba2str(&dev->bdaddr, address);
416dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
417dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
418277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasiint get_device_class(uint16_t dev_id, uint8_t *cls)
419277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi{
420277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	struct hci_dev *dev;
421277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
422277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	ASSERT_DEV_ID;
423277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
424277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	dev = &devices[dev_id];
425277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	memcpy(cls, dev->class, 3);
426277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
427277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	return 0;
428277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi}
429277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
430f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmannint set_device_class(uint16_t dev_id, uint8_t *cls)
431f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann{
432f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	struct hci_dev *dev;
433f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann
434f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	ASSERT_DEV_ID;
435f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	dev = &devices[dev_id];
436f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	memcpy(dev->class, cls, 3);
437f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann
438f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	return 0;
439f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann}
440f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann
441dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_version(uint16_t dev_id, char *version, size_t size)
442dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
443dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
444dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	char edr[7], *tmp;
445dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int err;
446dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
447dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
448dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
449dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (size < 14)
450dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -ENOBUFS;
451dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
452dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
453dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
45498329bfce1a1ce33cf2f46007196ecc63441465aMarcel Holtmann	if ((dev->lmp_ver == 0x03 || dev->lmp_ver == 0x04) &&
455dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann			(dev->features[3] & (LMP_EDR_ACL_2M | LMP_EDR_ACL_3M)))
456dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		sprintf(edr, " + EDR");
457dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	else
458dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		edr[0] = '\0';
459dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
460dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	tmp = lmp_vertostr(dev->lmp_ver);
461dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
462dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (strlen(tmp) == 0)
463dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		err = snprintf(version, size, "not assigned");
464dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	else
465dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		err = snprintf(version, size, "Bluetooth %s%s", tmp, edr);
466dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
467dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bt_free(tmp);
468dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
469dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return err;
470dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
471dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4728586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmannstatic int digi_revision(uint16_t dev_id, char *revision, size_t size)
4738586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann{
4748586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	struct hci_request rq;
4758586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	unsigned char req[] = { 0x07 };
4768586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	unsigned char buf[102];
4778586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	int dd;
4788586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4798586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	dd = hci_open_dev(dev_id);
4808586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	if (dd < 0) {
48126e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
4828586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann					dev_id, strerror(errno), errno);
4838586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		return -errno;
4848586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	}
4858586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4868586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	memset(&rq, 0, sizeof(rq));
4878586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.ogf    = OGF_VENDOR_CMD;
4888586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.ocf    = 0x000e;
4898586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.cparam = req;
4908586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.clen   = sizeof(req);
4918586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.rparam = &buf;
4928586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.rlen   = sizeof(buf);
4938586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4948586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	if (hci_send_req(dd, &rq, 2000) < 0) {
4954c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		int err = errno;
49626e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't read revision for hci%d: %s (%d)",
4978586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann					dev_id, strerror(errno), errno);
4984c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		hci_close_dev(dd);
4994c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		return -err;
5008586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	}
5018586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5028586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	hci_close_dev(dd);
5038586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5048586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	return snprintf(revision, size, "%s", buf + 1);
5058586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann}
5068586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
507dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_revision(uint16_t dev_id, char *revision, size_t size)
508dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
5098586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	struct hci_dev *dev;
5108586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	int err;
5118586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
512dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
513dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
5148586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	dev = &devices[dev_id];
5158586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5168586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	switch (dev->manufacturer) {
5178586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	case 10:
5188586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		err = snprintf(revision, size, "Build %d", dev->lmp_subver);
5198586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		break;
5208586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	case 12:
5218586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		err = digi_revision(dev_id, revision, size);
5228586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		break;
5230fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann	case 15:
5240fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann		err = snprintf(revision, size, "%d.%d / %d",
5250fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann				dev->hci_rev & 0xff,
5260fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann				dev->lmp_subver >> 8, dev->lmp_subver & 0xff);
5270fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann		break;
5288586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	default:
5298586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		err = snprintf(revision, size, "0x%02x", dev->lmp_subver);
5308586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		break;
5318586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	}
5328586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5338586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	return err;
534dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
535dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
536dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_manufacturer(uint16_t dev_id, char *manufacturer, size_t size)
537dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
538dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	char *tmp;
539dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
540dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
541dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
542dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	tmp = bt_compidtostr(devices[dev_id].manufacturer);
543dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
544dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return snprintf(manufacturer, size, "%s", tmp);
545dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
546dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
547dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_company(uint16_t dev_id, char *company, size_t size)
548dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
549dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	char *tmp, oui[9];
550dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int err;
551dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
552dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
553dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
554dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ba2oui(&devices[dev_id].bdaddr, oui);
555dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	tmp = ouitocomp(oui);
556dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
557dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	err = snprintf(company, size, "%s", tmp);
558dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
559dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	free(tmp);
560dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
561dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return err;
562dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
5636a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
5640b727924102df07d609be955800793c1f33d6952Marcel Holtmannint set_simple_pairing_mode(uint16_t dev_id, uint8_t mode)
5650b727924102df07d609be955800793c1f33d6952Marcel Holtmann{
5660b727924102df07d609be955800793c1f33d6952Marcel Holtmann	struct hci_dev *dev;
5670b727924102df07d609be955800793c1f33d6952Marcel Holtmann	int dd;
5680b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5690b727924102df07d609be955800793c1f33d6952Marcel Holtmann	ASSERT_DEV_ID;
5700b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5710b727924102df07d609be955800793c1f33d6952Marcel Holtmann	dev = &devices[dev_id];
5720b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5730b727924102df07d609be955800793c1f33d6952Marcel Holtmann	dev->ssp_mode = mode;
5740b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5750b727924102df07d609be955800793c1f33d6952Marcel Holtmann	dd = hci_open_dev(dev_id);
5760b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (dd < 0) {
5770b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't open device hci%d",
5780b727924102df07d609be955800793c1f33d6952Marcel Holtmann					dev_id, strerror(errno), errno);
5790b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return -errno;
5800b727924102df07d609be955800793c1f33d6952Marcel Holtmann	}
5810b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5820b727924102df07d609be955800793c1f33d6952Marcel Holtmann	update_ext_inquiry_response(dd, dev);
5830b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5840b727924102df07d609be955800793c1f33d6952Marcel Holtmann	hci_close_dev(dd);
5850b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5860b727924102df07d609be955800793c1f33d6952Marcel Holtmann	return 0;
5870b727924102df07d609be955800793c1f33d6952Marcel Holtmann}
5880b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5896a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint get_device_name(uint16_t dev_id, char *name, size_t size)
5906a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
5916a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	char tmp[249];
5926a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	int dd;
5936a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
5946a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
5956a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
5966a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	memset(tmp, 0, sizeof(tmp));
5976a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
5986a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	dd = hci_open_dev(dev_id);
5996a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (dd < 0) {
60026e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
6016a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6026a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann		return -errno;
6036a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6046a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6056a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (hci_read_local_name(dd, sizeof(tmp), tmp, 2000) < 0) {
6064c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		int err = errno;
60726e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't read name for hci%d: %s (%d)",
6086a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6094c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		hci_close_dev(dd);
6104c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		return -err;
6116a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6126a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6136a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	hci_close_dev(dd);
6146a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6156a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	memcpy(devices[dev_id].name, tmp, 248);
6166a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6176a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return snprintf(name, size, "%s", tmp);
6186a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
6196a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6206a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint set_device_name(uint16_t dev_id, const char *name)
6216a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
622abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann	struct hci_dev *dev;
6236a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	int dd;
6246a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6256a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
6266a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
627abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann	dev = &devices[dev_id];
628abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann
6296a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	dd = hci_open_dev(dev_id);
6306a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (dd < 0) {
63126e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
6326a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6336a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann		return -errno;
6346a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6356a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6366a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (hci_write_local_name(dd, name, 5000) < 0) {
6374c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		int err = errno;
6383dec6f11d625a351bae0aada4160f3d2de429cddClaudio Takahasi		error("Can't write name for hci%d: %s (%d)",
6396a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6404c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		hci_close_dev(dd);
6414c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		return -err;
6426a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6436a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6440b727924102df07d609be955800793c1f33d6952Marcel Holtmann	memcpy(dev->name, name, 248);
645abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann
6460b727924102df07d609be955800793c1f33d6952Marcel Holtmann	update_ext_inquiry_response(dd, dev);
647abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann
6486a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	hci_close_dev(dd);
6496a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6506a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return 0;
6516a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
6526a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6536a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint get_device_alias(uint16_t dev_id, const bdaddr_t *bdaddr, char *alias, size_t size)
6546a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
6556a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	char filename[PATH_MAX + 1], addr[18], *tmp;
6566a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	int err;
6576a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6586a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
6596a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6606a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(&devices[dev_id].bdaddr, addr);
66117152022a5844275a6f3e3e71ef5b32dc2c0ec04Marcel Holtmann	create_name(filename, PATH_MAX, STORAGEDIR, addr, "aliases");
6626a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6636a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(bdaddr, addr);
6646a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6656a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	tmp = textfile_get(filename, addr);
6666a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (!tmp)
6676a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann		return -ENXIO;
6686a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6696a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	err = snprintf(alias, size, "%s", tmp);
6706a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6716a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	free(tmp);
6726a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6736a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return err;
6746a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
6756a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6766a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint set_device_alias(uint16_t dev_id, const bdaddr_t *bdaddr, const char *alias)
6776a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
6786a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	char filename[PATH_MAX + 1], addr[18];
6796a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6806a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
6816a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6826a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(&devices[dev_id].bdaddr, addr);
68317152022a5844275a6f3e3e71ef5b32dc2c0ec04Marcel Holtmann	create_name(filename, PATH_MAX, STORAGEDIR, addr, "aliases");
6846a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6856a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
6866a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6876a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(bdaddr, addr);
6886a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6896a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return textfile_put(filename, addr, alias);
6906a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
691129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
692129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmannint get_encryption_key_size(uint16_t dev_id, const bdaddr_t *baddr)
693129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann{
694129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	struct hci_dev *dev;
695129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	int size;
696129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
697129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	ASSERT_DEV_ID;
698129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
699129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	dev = &devices[dev_id];
700129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
701129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	switch (dev->manufacturer) {
702129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	default:
703129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann		size = -ENOENT;
704129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann		break;
705129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	}
706129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
707129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	return size;
708129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann}
70986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
71086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannstatic DBusConnection *connection = NULL;
71186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
71286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannstatic GSList *device_list = NULL;
71386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
71486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmanngboolean device_init(DBusConnection *conn)
71586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
71686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	connection = dbus_connection_ref(conn);
71786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (connection == NULL)
71886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return FALSE;
71986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
72086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	return TRUE;
72186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
72286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
7232c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic void device_destroy(struct device *device)
72486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
72586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	debug("Removing device %s", device->path);
72686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
72786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	dbus_connection_destroy_object_path(connection, device->path);
72886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
72986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
73086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannvoid device_cleanup(void)
73186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
73286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_slist_foreach(device_list, (GFunc) device_destroy, NULL);
73386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_slist_free(device_list);
73486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
73586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (connection == NULL)
73686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return;
73786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
73886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	dbus_connection_unref(connection);
73986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
74086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
74186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannvoid device_foreach(GFunc func, gpointer user_data)
74286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
74386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_slist_foreach(device_list, func, user_data);
74486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
74586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
7462c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic void device_free(struct device *device)
74786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
74886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device->path);
74986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device);
75086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
75186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
75286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannstatic void device_unregister(DBusConnection *conn, void *user_data)
75386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
7542c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	struct device *device = user_data;
75586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
75686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	device_list = g_slist_remove(device_list, device);
75786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
75886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	device_free(device);
75986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
76086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
7612c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusHandlerResult disconnect(DBusConnection *conn,
7622c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes					DBusMessage *msg, void *user_data)
7632c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
7642c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
7652c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
7662c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7672c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusHandlerResult get_properties(DBusConnection *conn,
7682c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes					DBusMessage *msg, void *user_data)
7692c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
7702c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
7712c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
7722c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7732c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusHandlerResult set_property(DBusConnection *conn,
7742c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes					DBusMessage *msg, void *user_data)
7752c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
7762c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
7772c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
7782c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7792c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusMethodVTable device_methods[] = {
7802c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "GetProperties",	get_properties,		"",	"a{sv}" },
7812c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "SetProperty",	set_property,		"sv",	""	},
7822c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "Disconnect",		disconnect,		"",	""	},
7832c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ NULL, NULL, NULL, NULL }
7842c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
7852c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7862c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusSignalVTable device_signals[] = {
7872c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "PropertyChanged",			"sv"	},
7882c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "DisconnectRequested",		""	},
7892c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ NULL, NULL }
7902c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
7912c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7922c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstruct device *device_create(struct adapter *adapter, const char *address)
79386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
7942c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	struct device *device;
79586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
7962c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	device = g_try_malloc0(sizeof(struct device));
79786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (device == NULL)
79886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
79986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
8002c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	device->path = g_strdup_printf("%s/dev_%s", adapter->address, address);
80186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_strdelimit(device->path, ":", '_');
80286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
80386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	debug("Creating device %s", device->path);
80486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
80586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (dbus_connection_create_object_path(connection, device->path,
80686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann					device, device_unregister) == FALSE) {
80786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		device_free(device);
80886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
80986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	}
8102c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	dbus_connection_register_interface(connection, device->path,
8112c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes			DEVICE_INTERFACE, device_methods, device_signals, NULL);
81286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
81386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	device_list = g_slist_append(device_list, device);
81486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
81586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	return device;
81686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
81786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
81886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannvoid device_remove(const char *path)
81986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
82086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
821