device.c revision 5d5d89bb2dbc295443900d59d8a7172dc2f279c7
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>
415d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp.h>
425d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp_lib.h>
43dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <glib.h>
4586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
4686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <dbus/dbus.h>
4786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
4886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "dbus-helper.h"
4986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
5026e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann#include "hcid.h"
51eb4d49890ca8a4d8f567e81fdf82b6903d30f326Marcel Holtmann#include "sdpd.h"
5226e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann
5386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "logging.h"
546a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include "textfile.h"
55dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include "oui.h"
56dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
572c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes#include "adapter.h"
5886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "device.h"
59da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi#include "dbus-common.h"
6086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
61dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#define MAX_DEVICES 16
62dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
632c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes#define DEVICE_INTERFACE "org.bluez.Device"
642c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
65dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstruct hci_peer {
66dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct timeval lastseen;
67dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct timeval lastused;
68dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
69dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bdaddr_t bdaddr;
70dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint32_t class;
71dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int8_t   rssi;
72dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  data[240];
73dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  name[248];
74dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
75dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  pscan_rep_mode;
76dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  pscan_period_mode;
77dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  pscan_mode;
78dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t clock_offset;
79dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
80dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_peer *next;
81dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann};
82dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
83dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstruct hci_conn {
84dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bdaddr_t bdaddr;
85dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t handle;
86dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
87dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_conn *next;
88dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann};
89dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
90dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstruct hci_dev {
9157eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	int ignore;
9257eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann
93dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bdaddr_t bdaddr;
94dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  features[8];
95dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint8_t  lmp_ver;
96dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t lmp_subver;
970d7408aa899f84210d0e6418ee528636292276bcMarcel Holtmann	uint16_t hci_rev;
98dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	uint16_t manufacturer;
99dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
1000b727924102df07d609be955800793c1f33d6952Marcel Holtmann	uint8_t  ssp_mode;
1016a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	uint8_t  name[248];
102277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	uint8_t  class[3];
1036a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
104dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_peer *peers;
105dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_conn *conns;
106dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann};
107dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
108dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannstatic struct hci_dev devices[MAX_DEVICES];
109dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
110dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#define ASSERT_DEV_ID { if (dev_id >= MAX_DEVICES) return -ERANGE; }
111dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
11252a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannvoid init_adapters(void)
113dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
114dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int i;
115dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
116dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	for (i = 0; i < MAX_DEVICES; i++)
117dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		memset(devices + i, 0, sizeof(struct hci_dev));
118dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
119dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
120ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedbergstatic int device_read_bdaddr(uint16_t dev_id, bdaddr_t *bdaddr)
121ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg{
122ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	int dd;
123ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
124ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	dd = hci_open_dev(dev_id);
125ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	if (dd < 0) {
126ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		error("Can't open device hci%d",
1270b727924102df07d609be955800793c1f33d6952Marcel Holtmann					dev_id, strerror(errno), errno);
128ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		return -errno;
129ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	}
130ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
131ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	if (hci_read_bd_addr(dd, bdaddr, 2000) < 0) {
132fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		int err = errno;
133ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		error("Can't read address for hci%d: %s (%d)",
1340b727924102df07d609be955800793c1f33d6952Marcel Holtmann					dev_id, strerror(errno), errno);
135ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		hci_close_dev(dd);
136fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
137ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	}
138ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
139ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	hci_close_dev(dd);
140ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
141ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	return 0;
142ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg}
143ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg
14452a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint add_adapter(uint16_t dev_id)
145dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
146dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
147dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev_info di;
148dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
149dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
150dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
151dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
152dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
15357eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	if (hci_devinfo(dev_id, &di) < 0) {
15457eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		dev->ignore = 1;
155dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -errno;
15657eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	}
15757eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann
15857eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	if (hci_test_bit(HCI_RAW, &di.flags)) {
15957eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		info("Device hci%d is using raw mode", dev_id);
16057eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		dev->ignore = 1;
16157eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	}
162dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
163ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	if (bacmp(&di.bdaddr, BDADDR_ANY))
164ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg		bacpy(&dev->bdaddr, &di.bdaddr);
165ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	else {
1660b727924102df07d609be955800793c1f33d6952Marcel Holtmann		int err = device_read_bdaddr(dev_id, &dev->bdaddr);
1670b727924102df07d609be955800793c1f33d6952Marcel Holtmann		if (err < 0)
1680b727924102df07d609be955800793c1f33d6952Marcel Holtmann			return err;
169ca6e6c5a32dda535b9f76f9b0f8433f71f977efaJohan Hedberg	}
170dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	memcpy(dev->features, di.features, 8);
171dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
172dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been added", dev_id);
173dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
174dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
175dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
176dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
17752a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint remove_adapter(uint16_t dev_id)
178dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
179dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
180dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
181dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
182dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
183dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
184dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
185dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	memset(dev, 0, sizeof(struct hci_dev));
186dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
187dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been removed", dev_id);
188dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
189dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
190dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
191dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
192b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmannstatic inline uint8_t get_inquiry_mode(struct hci_dev *dev)
193b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann{
194b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	if (dev->features[6] & LMP_EXT_INQ)
195b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann		return 2;
196b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
197b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	if (dev->features[3] & LMP_RSSI_INQ)
198b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann		return 1;
199b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
200e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann	if (dev->manufacturer == 11 &&
201e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann			dev->hci_rev == 0x00 && dev->lmp_subver == 0x0757)
202e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann		return 1;
203e833fda08627147d42a251d76308408e5ac6c5fdMarcel Holtmann
204431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann	if (dev->manufacturer == 15) {
205431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann		if (dev->hci_rev == 0x03 && dev->lmp_subver == 0x6963)
206431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann			return 1;
207431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann		if (dev->hci_rev == 0x09 && dev->lmp_subver == 0x6963)
208431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann			return 1;
209b98c93ed852d29557fe71de5262357b704f85592Marcel Holtmann		if (dev->hci_rev == 0x00 && dev->lmp_subver == 0x6965)
210b98c93ed852d29557fe71de5262357b704f85592Marcel Holtmann			return 1;
211431ac89881eaed4c44f2204736ba5debe2d29a33Marcel Holtmann	}
21219fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann
21319fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann	if (dev->manufacturer == 31 &&
21419fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann			dev->hci_rev == 0x2005 && dev->lmp_subver == 0x1805)
21519fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann		return 1;
21619fb70a42ac27051f8fe1adc2502943dd56c5f0dMarcel Holtmann
217b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	return 0;
218b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann}
219b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
2200b727924102df07d609be955800793c1f33d6952Marcel Holtmannstatic void update_ext_inquiry_response(int dd, struct hci_dev *dev)
2210b727924102df07d609be955800793c1f33d6952Marcel Holtmann{
2220b727924102df07d609be955800793c1f33d6952Marcel Holtmann	uint8_t fec = 0, data[240];
2230b727924102df07d609be955800793c1f33d6952Marcel Holtmann
2240b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (!(dev->features[6] & LMP_EXT_INQ))
2250b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return;
2260b727924102df07d609be955800793c1f33d6952Marcel Holtmann
2270b727924102df07d609be955800793c1f33d6952Marcel Holtmann	memset(data, 0, sizeof(data));
2280b727924102df07d609be955800793c1f33d6952Marcel Holtmann
229eb4d49890ca8a4d8f567e81fdf82b6903d30f326Marcel Holtmann	if (dev->ssp_mode > 0)
230eb4d49890ca8a4d8f567e81fdf82b6903d30f326Marcel Holtmann		create_ext_inquiry_response((char *) dev->name, data);
2310b727924102df07d609be955800793c1f33d6952Marcel Holtmann
2320b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_write_ext_inquiry_response(dd, fec, data, 2000) < 0)
2330b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't write extended inquiry response: %s (%d)",
2340b727924102df07d609be955800793c1f33d6952Marcel Holtmann						strerror(errno), errno);
2350b727924102df07d609be955800793c1f33d6952Marcel Holtmann}
2360b727924102df07d609be955800793c1f33d6952Marcel Holtmann
23752a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint start_adapter(uint16_t dev_id)
238dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
239dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
240dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_version ver;
241b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	uint8_t features[8], inqmode;
2423dfe93f27c455e07be72a38239f4f8335ba6a860Marcel Holtmann	uint8_t events[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00 };
2430b727924102df07d609be955800793c1f33d6952Marcel Holtmann	char name[249];
244277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	int dd, err;
245dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
246dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
247dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
248dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
249dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
25057eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann	if (dev->ignore)
25157eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann		return 0;
25257eb59510dc89b134cc35bdac9949bceab7da1d6Marcel Holtmann
253dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dd = hci_open_dev(dev_id);
254dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (dd < 0) {
25526e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
256dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann					dev_id, strerror(errno), errno);
257dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -errno;
258dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	}
259dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
260dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (hci_read_local_version(dd, &ver, 1000) < 0) {
261fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		int err = errno;
26226e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't read version info for hci%d: %s (%d)",
263dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann					dev_id, strerror(errno), errno);
264276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmann		hci_close_dev(dd);
265fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
266dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	}
267dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
2680fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann	dev->hci_rev = ver.hci_rev;
269dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev->lmp_ver = ver.lmp_ver;
270dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev->lmp_subver = ver.lmp_subver;
271dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev->manufacturer = ver.manufacturer;
272dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
273b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	if (hci_read_local_features(dd, features, 1000) < 0) {
274277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		err = errno;
275b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann		error("Can't read features for hci%d: %s (%d)",
276277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi					dev_id, strerror(err), err);
277276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmann		hci_close_dev(dd);
278fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
279b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	}
280b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
281b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	memcpy(dev->features, features, 8);
282b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
283277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	if (hci_read_class_of_dev(dd, dev->class, 1000) < 0) {
284277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		err = errno;
2850b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't read class of device on hci%d: %s (%d)",
2860b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(err), err);
287277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		hci_close_dev(dd);
288277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi		return -err;
289277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	}
290277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
2910b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_read_local_name(dd, sizeof(name), name, 2000) < 0) {
2920b727924102df07d609be955800793c1f33d6952Marcel Holtmann		err = errno;
2930b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't read local name on hci%d: %s (%d)",
2940b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(err), err);
2950b727924102df07d609be955800793c1f33d6952Marcel Holtmann		hci_close_dev(dd);
2960b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return -err;
2970b727924102df07d609be955800793c1f33d6952Marcel Holtmann	}
298b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
2990b727924102df07d609be955800793c1f33d6952Marcel Holtmann	memcpy(dev->name, name, 248);
3000b727924102df07d609be955800793c1f33d6952Marcel Holtmann
3010b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (!(features[6] & LMP_SIMPLE_PAIR))
3020b727924102df07d609be955800793c1f33d6952Marcel Holtmann		goto setup;
3030b727924102df07d609be955800793c1f33d6952Marcel Holtmann
3040b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_read_simple_pairing_mode(dd, &dev->ssp_mode, 1000) < 0) {
3050b727924102df07d609be955800793c1f33d6952Marcel Holtmann		err = errno;
3060b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't read simple pairing mode on hci%d: %s (%d)",
3070b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(err), err);
308276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmann		hci_close_dev(dd);
309fdba3b26687425c6523f728f7e79d5f7a76af367Ulisses Furquim		return -err;
310b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann	}
311b1609cb6ebaa241102257152e8eb8f248726035fMarcel Holtmann
3120b727924102df07d609be955800793c1f33d6952Marcel Holtmannsetup:
31357290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann	if (ver.hci_rev > 1) {
31457290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		if (features[5] & LMP_SNIFF_SUBR)
31557290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann			events[5] |= 0x20;
31657290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
317a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann		if (features[5] & LMP_PAUSE_ENC)
318a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann			events[5] |= 0x80;
319a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann
32057290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		if (features[6] & LMP_EXT_INQ)
32157290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann			events[5] |= 0x40;
32257290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
323a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann		if (features[6] & LMP_NFLUSH_PKTS)
324a47211b0097fe3612b96246f08bf37dccd15fd61Marcel Holtmann			events[7] |= 0x01;
325f4051e4e1bc3a5a00fc74b5b5eb7eb3794f67310Johan Hedberg
32657290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		if (features[7] & LMP_LSTO)
32757290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann			events[6] |= 0x80;
32857290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
3290b727924102df07d609be955800793c1f33d6952Marcel Holtmann		if (features[6] & LMP_SIMPLE_PAIR) {
3300b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x01;	/* IO Capability Request */
3310b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x02;	/* IO Capability Response */
3320b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x04;	/* User Confirmation Request */
3330b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x08;	/* User Passkey Request */
3340b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x10;	/* Remote OOB Data Request */
3350b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[6] |= 0x20;	/* Simple Pairing Complete */
3360b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[7] |= 0x04;	/* User Passkey Notification */
3370b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[7] |= 0x08;	/* Keypress Notification */
3380b727924102df07d609be955800793c1f33d6952Marcel Holtmann			events[7] |= 0x10;	/* Remote Host Supported Features Notification */
3390b727924102df07d609be955800793c1f33d6952Marcel Holtmann		}
3400b727924102df07d609be955800793c1f33d6952Marcel Holtmann
34157290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann		hci_send_cmd(dd, OGF_HOST_CTL, OCF_SET_EVENT_MASK,
34257290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann						sizeof(events), events);
34357290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann	}
34457290a1e2c13f79d353a21f7c67388ee8c142897Marcel Holtmann
345c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann	if (read_local_name(&dev->bdaddr, name) == 0) {
346c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann		memcpy(dev->name, name, 248);
347c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann		hci_write_local_name(dd, name, 5000);
348c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann        }
349c3cd59ae39ebb53e27ddd99ee48f1875bd480c1dMarcel Holtmann
3500b727924102df07d609be955800793c1f33d6952Marcel Holtmann	update_ext_inquiry_response(dd, dev);
3510b727924102df07d609be955800793c1f33d6952Marcel Holtmann
3520b727924102df07d609be955800793c1f33d6952Marcel Holtmann	inqmode = get_inquiry_mode(dev);
3530b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (inqmode < 1)
3540b727924102df07d609be955800793c1f33d6952Marcel Holtmann		goto done;
3550b727924102df07d609be955800793c1f33d6952Marcel Holtmann
3560b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (hci_write_inquiry_mode(dd, inqmode, 1000) < 0) {
3570b727924102df07d609be955800793c1f33d6952Marcel Holtmann		int err = errno;
3580b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't write inquiry mode for hci%d: %s (%d)",
3590b727924102df07d609be955800793c1f33d6952Marcel Holtmann						dev_id, strerror(errno), err);
3600b727924102df07d609be955800793c1f33d6952Marcel Holtmann		hci_close_dev(dd);
3610b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return -err;
3620b727924102df07d609be955800793c1f33d6952Marcel Holtmann	}
3630b727924102df07d609be955800793c1f33d6952Marcel Holtmann
364276a7aeaed518f61b0ec85f9658c62829d99a925Marcel Holtmanndone:
365dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	hci_close_dev(dd);
366dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
367dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been activated", dev_id);
368dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
369dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
370dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
371dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
37252a124ee19a84ca68171dbe88057d8b01b9d16d8Marcel Holtmannint stop_adapter(uint16_t dev_id)
373dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
374dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
375dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
376dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	info("Device hci%d has been disabled", dev_id);
377dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
378dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return 0;
379dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
380dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
3810e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmannint update_adapter(uint16_t dev_id)
3820e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann{
3830e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	struct hci_dev *dev;
3840e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	int dd;
3850e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3860e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	ASSERT_DEV_ID;
3870e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3880e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	dev = &devices[dev_id];
3890e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3900e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	if (dev->ignore)
3910e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann		return 0;
3920e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
3930e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	dd = hci_open_dev(dev_id);
3940e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	if (dd < 0) {
3950e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann		error("Can't open device hci%d",
3960e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann					dev_id, strerror(errno), errno);
3970e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann		return -errno;
3980e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	}
3990e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
4000e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	update_ext_inquiry_response(dd, dev);
4010e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
4020e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	hci_close_dev(dd);
4030e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
4040e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann	return 0;
4050e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann}
4060e8c93725dbdc6ce76ca48da92f9d15b2a706111Marcel Holtmann
407dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_address(uint16_t dev_id, char *address, size_t size)
408dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
4098586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	struct hci_dev *dev;
4108586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
411dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
412dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
413dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (size < 18)
414dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -ENOBUFS;
415dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4168586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	dev = &devices[dev_id];
4178586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4188586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	return ba2str(&dev->bdaddr, address);
419dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
420dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
421277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasiint get_device_class(uint16_t dev_id, uint8_t *cls)
422277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi{
423277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	struct hci_dev *dev;
424277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
425277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	ASSERT_DEV_ID;
426277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
427277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	dev = &devices[dev_id];
428277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	memcpy(cls, dev->class, 3);
429277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
430277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi	return 0;
431277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi}
432277e0363f2839a05b80c1bc4263cfeaf9909be8cClaudio Takahasi
433f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmannint set_device_class(uint16_t dev_id, uint8_t *cls)
434f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann{
435f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	struct hci_dev *dev;
436f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann
437f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	ASSERT_DEV_ID;
438f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	dev = &devices[dev_id];
439f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	memcpy(dev->class, cls, 3);
440f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann
441f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann	return 0;
442f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann}
443f205cd06dc4e9da2c1d5109e570008d7d80b8380Marcel Holtmann
444dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_version(uint16_t dev_id, char *version, size_t size)
445dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
446dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	struct hci_dev *dev;
447dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	char edr[7], *tmp;
448dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int err;
449dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
450dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
451dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
452dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (size < 14)
453dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		return -ENOBUFS;
454dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
455dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	dev = &devices[dev_id];
456dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
45798329bfce1a1ce33cf2f46007196ecc63441465aMarcel Holtmann	if ((dev->lmp_ver == 0x03 || dev->lmp_ver == 0x04) &&
458dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann			(dev->features[3] & (LMP_EDR_ACL_2M | LMP_EDR_ACL_3M)))
459dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		sprintf(edr, " + EDR");
460dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	else
461dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		edr[0] = '\0';
462dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
463dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	tmp = lmp_vertostr(dev->lmp_ver);
464dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
465dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	if (strlen(tmp) == 0)
466dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		err = snprintf(version, size, "not assigned");
467dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	else
468dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann		err = snprintf(version, size, "Bluetooth %s%s", tmp, edr);
469dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
470dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	bt_free(tmp);
471dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
472dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return err;
473dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
474dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4758586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmannstatic int digi_revision(uint16_t dev_id, char *revision, size_t size)
4768586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann{
4778586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	struct hci_request rq;
4788586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	unsigned char req[] = { 0x07 };
4798586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	unsigned char buf[102];
4808586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	int dd;
4818586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4828586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	dd = hci_open_dev(dev_id);
4838586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	if (dd < 0) {
48426e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
4858586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann					dev_id, strerror(errno), errno);
4868586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		return -errno;
4878586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	}
4888586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4898586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	memset(&rq, 0, sizeof(rq));
4908586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.ogf    = OGF_VENDOR_CMD;
4918586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.ocf    = 0x000e;
4928586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.cparam = req;
4938586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.clen   = sizeof(req);
4948586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.rparam = &buf;
4958586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	rq.rlen   = sizeof(buf);
4968586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
4978586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	if (hci_send_req(dd, &rq, 2000) < 0) {
4984c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		int err = errno;
49926e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't read revision for hci%d: %s (%d)",
5008586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann					dev_id, strerror(errno), errno);
5014c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		hci_close_dev(dd);
5024c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		return -err;
5038586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	}
5048586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5058586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	hci_close_dev(dd);
5068586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5078586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	return snprintf(revision, size, "%s", buf + 1);
5088586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann}
5098586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
510dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_revision(uint16_t dev_id, char *revision, size_t size)
511dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
5128586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	struct hci_dev *dev;
5138586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	int err;
5148586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
515dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
516dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
5178586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	dev = &devices[dev_id];
5188586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5198586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	switch (dev->manufacturer) {
5208586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	case 10:
5218586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		err = snprintf(revision, size, "Build %d", dev->lmp_subver);
5228586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		break;
5238586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	case 12:
5248586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		err = digi_revision(dev_id, revision, size);
5258586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		break;
5260fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann	case 15:
5270fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann		err = snprintf(revision, size, "%d.%d / %d",
5280fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann				dev->hci_rev & 0xff,
5290fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann				dev->lmp_subver >> 8, dev->lmp_subver & 0xff);
5300fe4da23f22cf74624a4576fb879d6dd500dfc5cMarcel Holtmann		break;
5318586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	default:
5328586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		err = snprintf(revision, size, "0x%02x", dev->lmp_subver);
5338586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann		break;
5348586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	}
5358586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann
5368586fc0c0dc8d6fe219f7eb7a697f359827b39a0Marcel Holtmann	return err;
537dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
538dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
539dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_manufacturer(uint16_t dev_id, char *manufacturer, size_t size)
540dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
541dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	char *tmp;
542dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
543dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
544dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
545dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	tmp = bt_compidtostr(devices[dev_id].manufacturer);
546dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
547dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return snprintf(manufacturer, size, "%s", tmp);
548dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
549dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
550dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmannint get_device_company(uint16_t dev_id, char *company, size_t size)
551dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann{
552dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	char *tmp, oui[9];
553dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	int err;
554dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
555dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ASSERT_DEV_ID;
556dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
557dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	ba2oui(&devices[dev_id].bdaddr, oui);
558dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	tmp = ouitocomp(oui);
559dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
560dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	err = snprintf(company, size, "%s", tmp);
561dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
562dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	free(tmp);
563dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
564dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann	return err;
565dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann}
5666a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
5670b727924102df07d609be955800793c1f33d6952Marcel Holtmannint set_simple_pairing_mode(uint16_t dev_id, uint8_t mode)
5680b727924102df07d609be955800793c1f33d6952Marcel Holtmann{
5690b727924102df07d609be955800793c1f33d6952Marcel Holtmann	struct hci_dev *dev;
5700b727924102df07d609be955800793c1f33d6952Marcel Holtmann	int dd;
5710b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5720b727924102df07d609be955800793c1f33d6952Marcel Holtmann	ASSERT_DEV_ID;
5730b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5740b727924102df07d609be955800793c1f33d6952Marcel Holtmann	dev = &devices[dev_id];
5750b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5760b727924102df07d609be955800793c1f33d6952Marcel Holtmann	dev->ssp_mode = mode;
5770b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5780b727924102df07d609be955800793c1f33d6952Marcel Holtmann	dd = hci_open_dev(dev_id);
5790b727924102df07d609be955800793c1f33d6952Marcel Holtmann	if (dd < 0) {
5800b727924102df07d609be955800793c1f33d6952Marcel Holtmann		error("Can't open device hci%d",
5810b727924102df07d609be955800793c1f33d6952Marcel Holtmann					dev_id, strerror(errno), errno);
5820b727924102df07d609be955800793c1f33d6952Marcel Holtmann		return -errno;
5830b727924102df07d609be955800793c1f33d6952Marcel Holtmann	}
5840b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5850b727924102df07d609be955800793c1f33d6952Marcel Holtmann	update_ext_inquiry_response(dd, dev);
5860b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5870b727924102df07d609be955800793c1f33d6952Marcel Holtmann	hci_close_dev(dd);
5880b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5890b727924102df07d609be955800793c1f33d6952Marcel Holtmann	return 0;
5900b727924102df07d609be955800793c1f33d6952Marcel Holtmann}
5910b727924102df07d609be955800793c1f33d6952Marcel Holtmann
5926a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint get_device_name(uint16_t dev_id, char *name, size_t size)
5936a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
5946a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	char tmp[249];
5956a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	int dd;
5966a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
5976a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
5986a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
5996a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	memset(tmp, 0, sizeof(tmp));
6006a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6016a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	dd = hci_open_dev(dev_id);
6026a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (dd < 0) {
60326e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
6046a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6056a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann		return -errno;
6066a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6076a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6086a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (hci_read_local_name(dd, sizeof(tmp), tmp, 2000) < 0) {
6094c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		int err = errno;
61026e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't read name for hci%d: %s (%d)",
6116a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6124c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		hci_close_dev(dd);
6134c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		return -err;
6146a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6156a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6166a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	hci_close_dev(dd);
6176a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6186a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	memcpy(devices[dev_id].name, tmp, 248);
6196a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6206a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return snprintf(name, size, "%s", tmp);
6216a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
6226a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6236a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint set_device_name(uint16_t dev_id, const char *name)
6246a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
625abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann	struct hci_dev *dev;
6266a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	int dd;
6276a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6286a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
6296a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
630abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann	dev = &devices[dev_id];
631abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann
6326a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	dd = hci_open_dev(dev_id);
6336a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (dd < 0) {
63426e7f9195005deda91eea83f368c0d53ec95856cMarcel Holtmann		error("Can't open device hci%d",
6356a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6366a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann		return -errno;
6376a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6386a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6396a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (hci_write_local_name(dd, name, 5000) < 0) {
6404c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		int err = errno;
6413dec6f11d625a351bae0aada4160f3d2de429cddClaudio Takahasi		error("Can't write name for hci%d: %s (%d)",
6426a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann					dev_id, strerror(errno), errno);
6434c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		hci_close_dev(dd);
6444c172501d839e5d7c3f46510432b731ea2768dbfClaudio Takahasi		return -err;
6456a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	}
6466a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6470b727924102df07d609be955800793c1f33d6952Marcel Holtmann	memcpy(dev->name, name, 248);
648abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann
6490b727924102df07d609be955800793c1f33d6952Marcel Holtmann	update_ext_inquiry_response(dd, dev);
650abe03b24985eef4659c9d058c354f9b7df0a41f0Marcel Holtmann
6516a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	hci_close_dev(dd);
6526a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6536a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return 0;
6546a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
6556a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6566a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint get_device_alias(uint16_t dev_id, const bdaddr_t *bdaddr, char *alias, size_t size)
6576a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
6586a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	char filename[PATH_MAX + 1], addr[18], *tmp;
6596a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	int err;
6606a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6616a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
6626a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6636a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(&devices[dev_id].bdaddr, addr);
66417152022a5844275a6f3e3e71ef5b32dc2c0ec04Marcel Holtmann	create_name(filename, PATH_MAX, STORAGEDIR, addr, "aliases");
6656a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6666a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(bdaddr, addr);
6676a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6686a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	tmp = textfile_get(filename, addr);
6696a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	if (!tmp)
6706a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann		return -ENXIO;
6716a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6726a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	err = snprintf(alias, size, "%s", tmp);
6736a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6746a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	free(tmp);
6756a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6766a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return err;
6776a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
6786a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6796a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmannint set_device_alias(uint16_t dev_id, const bdaddr_t *bdaddr, const char *alias)
6806a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann{
6816a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	char filename[PATH_MAX + 1], addr[18];
6826a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6836a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ASSERT_DEV_ID;
6846a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6856a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(&devices[dev_id].bdaddr, addr);
68617152022a5844275a6f3e3e71ef5b32dc2c0ec04Marcel Holtmann	create_name(filename, PATH_MAX, STORAGEDIR, addr, "aliases");
6876a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6886a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
6896a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6906a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	ba2str(bdaddr, addr);
6916a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann
6926a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann	return textfile_put(filename, addr, alias);
6936a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann}
694129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
695129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmannint get_encryption_key_size(uint16_t dev_id, const bdaddr_t *baddr)
696129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann{
697129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	struct hci_dev *dev;
698129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	int size;
699129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
700129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	ASSERT_DEV_ID;
701129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
702129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	dev = &devices[dev_id];
703129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
704129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	switch (dev->manufacturer) {
705129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	default:
706129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann		size = -ENOENT;
707129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann		break;
708129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	}
709129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann
710129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann	return size;
711129147b47b9df4895888c6a674f8d15dc35e9a16Marcel Holtmann}
71286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
71386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannstatic DBusConnection *connection = NULL;
71486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
71586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannstatic GSList *device_list = NULL;
71686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
71786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmanngboolean device_init(DBusConnection *conn)
71886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
71986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	connection = dbus_connection_ref(conn);
72086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (connection == NULL)
72186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return FALSE;
72286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
72386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	return TRUE;
72486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
72586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
7262c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic void device_destroy(struct device *device)
72786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
72886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	debug("Removing device %s", device->path);
72986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
73086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	dbus_connection_destroy_object_path(connection, device->path);
73186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
73286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
73386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannvoid device_cleanup(void)
73486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
73586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_slist_foreach(device_list, (GFunc) device_destroy, NULL);
73686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_slist_free(device_list);
73786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
73886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (connection == NULL)
73986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return;
74086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
74186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	dbus_connection_unref(connection);
74286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
74386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
74486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannvoid device_foreach(GFunc func, gpointer user_data)
74586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
74686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_slist_foreach(device_list, func, user_data);
74786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
74886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
7492c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic void device_free(struct device *device)
75086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
7515d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi	sdp_list_free(device->uuids, (sdp_free_func_t) free);
75286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device->path);
75386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device);
75486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
75586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
75686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannstatic void device_unregister(DBusConnection *conn, void *user_data)
75786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
7582c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	struct device *device = user_data;
75986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
76086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	device_list = g_slist_remove(device_list, device);
76186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
76286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	device_free(device);
76386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
76486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
7652c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusHandlerResult disconnect(DBusConnection *conn,
7662c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes					DBusMessage *msg, void *user_data)
7672c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
7682c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
7692c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
7702c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7712c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusHandlerResult get_properties(DBusConnection *conn,
7722c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes					DBusMessage *msg, void *user_data)
7732c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
7742c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
7752c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
7762c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7772c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusHandlerResult set_property(DBusConnection *conn,
7782c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes					DBusMessage *msg, void *user_data)
7792c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
7802c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
7812c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
7822c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7832c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusMethodVTable device_methods[] = {
7842c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "GetProperties",	get_properties,		"",	"a{sv}" },
7852c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "SetProperty",	set_property,		"sv",	""	},
7862c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "Disconnect",		disconnect,		"",	""	},
7872c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ NULL, NULL, NULL, NULL }
7882c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
7892c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
7902c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomesstatic DBusSignalVTable device_signals[] = {
7912c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "PropertyChanged",			"sv"	},
7922c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ "DisconnectRequested",		""	},
7932c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	{ NULL, NULL }
7942c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
7952c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
796da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasiconst char *device_create(struct adapter *adapter,
7975d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi		const char *address, sdp_list_t *uuids)
79886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
7992c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	struct device *device;
80086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
8012c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	device = g_try_malloc0(sizeof(struct device));
80286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (device == NULL)
80386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
80486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
805da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi	device->path = g_strdup_printf("%s/hci%d/dev_%s",
806da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi				BASE_PATH, adapter->dev_id, address);
80786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_strdelimit(device->path, ":", '_');
80886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
80986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	debug("Creating device %s", device->path);
81086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
81186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (dbus_connection_create_object_path(connection, device->path,
81286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann					device, device_unregister) == FALSE) {
81386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		device_free(device);
81486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
81586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	}
816da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
8172c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes	dbus_connection_register_interface(connection, device->path,
8182c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes			DEVICE_INTERFACE, device_methods, device_signals, NULL);
81986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
82086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	device_list = g_slist_append(device_list, device);
82186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
822da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi	device->adapter = adapter;
8235d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi	device->uuids = uuids;
824da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
825da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi	return device->path;
82686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
82786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
82886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmannvoid device_remove(const char *path)
82986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
83086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
831