device.c revision 0144612a3d800c5d657cf141634f6b6cd47b4128
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 <stdlib.h>
315d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi#include <unistd.h>
326a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include <sys/stat.h>
33dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
34dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/bluetooth.h>
35dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/hci.h>
36dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/hci_lib.h>
375d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp.h>
385d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp_lib.h>
39dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <glib.h>
4186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <dbus/dbus.h>
4215ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#include <gdbus.h>
4386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
4486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "logging.h"
456a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include "textfile.h"
46dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
47506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi#include "hcid.h"
482c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes#include "adapter.h"
4986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "device.h"
50da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi#include "dbus-common.h"
514e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz#include "dbus-hci.h"
527fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz#include "error.h"
533d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz#include "glib-helper.h"
54fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite#include "agent.h"
553d3cdef8da6b3e1b14c3cdccda8c099cbad4f3aeMarcel Holtmann#include "sdp-xml.h"
56506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi#include "storage.h"
5786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
58c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz#define DEFAULT_XML_BUF_SIZE	1024
595d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi#define DISCONNECT_TIMER	2
60dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
61e3afaa0b7ff373d89fd3fa257110a34df7495df7Luiz Augusto von Dentzstruct btd_driver_data {
62b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode	struct btd_device_driver *driver;
63b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode	void *priv;
64b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode};
65b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
66555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestruct btd_device {
67cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t	bdaddr;
68ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	gchar		*path;
6918614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter	*adapter;
70ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	GSList		*uuids;
71b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode	GSList		*drivers;		/* List of driver_data */
72ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	gboolean	temporary;
73ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	struct agent	*agent;
74ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	guint		disconn_timer;
75ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	int		discov_active;		/* Service discovery active */
76ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	char		*discov_requestor;	/* discovery requestor unique name */
77ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	guint		discov_listener;
78ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
79ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	/* For Secure Simple Pairing */
80ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	uint8_t		cap;
81ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	uint8_t		auth;
82ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode};
83ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
843d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentzstruct browse_req {
853d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	DBusConnection *conn;
863d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	DBusMessage *msg;
87555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device;
8858d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz	GSList *uuids;
8936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	GSList *uuids_added;
9036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	GSList *uuids_removed;
91681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	sdp_list_t *records;
92d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	int search_uuid;
933d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz};
943d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
95d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmannstatic uint16_t uuid_list[] = {
96d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	PUBLIC_BROWSE_GROUP,
971c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	PNP_INFO_SVCLASS_ID,
98f22b20c3d40bd7571944af6a4946f756dc39f812Marcel Holtmann	HID_SVCLASS_ID,
99d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	GENERIC_AUDIO_SVCLASS_ID,
100d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	ADVANCED_AUDIO_SVCLASS_ID,
101d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	AV_REMOTE_SVCLASS_ID,
1021c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	PANU_SVCLASS_ID,
1031c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	GN_SVCLASS_ID,
1041c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	NAP_SVCLASS_ID,
1051c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	SERIAL_PORT_SVCLASS_ID,
106d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	0
107d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann};
108d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
109c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzstatic GSList *device_drivers = NULL;
110c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
111e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic void device_free(gpointer user_data)
11286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
113555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
1142f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
1152f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct agent *agent = adapter_get_agent(adapter);
116e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi
117fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite	if (device->agent)
118fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite		agent_destroy(device->agent, FALSE);
119f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
1202f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	if (agent && agent_is_busy(agent, device))
1212f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz		agent_cancel(agent);
1222f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz
123ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_foreach(device->uuids, (GFunc) g_free, NULL);
124ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_free(device->uuids);
125f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
1265d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	if (device->disconn_timer)
1275d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		g_source_remove(device->disconn_timer);
1285d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
12986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device->path);
13086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device);
13186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
13286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
133555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestatic gboolean device_is_paired(struct btd_device *device)
134769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz{
13518614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
136cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char filename[PATH_MAX + 1], *str;
137cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
138769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	gboolean ret;
139cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
1402a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
141cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
142cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
143cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
144769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
145769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR,
146cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode			srcaddr, "linkkeys");
147cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	str = textfile_caseget(filename, dstaddr);
148769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	ret = str ? TRUE : FALSE;
149769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	g_free(str);
150769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
151769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	return ret;
152769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz}
153769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
154e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *get_properties(DBusConnection *conn,
155e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *user_data)
1562c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
157555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
15818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
1594e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessage *reply;
1604e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter iter;
1614e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter dict;
162cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
163cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char name[248], srcaddr[18], dstaddr[18];
1648a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi	char **uuids;
1652a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	const char *ptr;
1664e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_bool_t boolean;
1674e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	uint32_t class;
168769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	int i;
169769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	GSList *l;
170bcb5f7e4d5e570c1acfd5364547d36e970408394Alok Barsode	struct active_conn_info *dev;
1714e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
172cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
173cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
1744e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	reply = dbus_message_new_method_return(msg);
1754e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	if (!reply)
176e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return NULL;
1774e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
1784e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
1794e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
1804e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1814e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1824e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
1834e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
1844e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
1854e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Address */
186cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ptr = dstaddr;
1874e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_append_dict_entry(&dict, "Address", DBUS_TYPE_STRING,
188cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode			&ptr);
1894e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
1904e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Name */
191506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	ptr = NULL;
192506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	memset(name, 0, sizeof(name));
1932a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
194cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
1958a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi
196cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (read_device_name(srcaddr, dstaddr, name) == 0) {
197506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		ptr = name;
1984e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz		dbus_message_iter_append_dict_entry(&dict, "Name",
199506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi				DBUS_TYPE_STRING, &ptr);
2004e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	}
2014e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
202cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (read_device_alias(srcaddr, dstaddr, name, sizeof(name)) > 0)
203506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		ptr = name;
204506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
205506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	/* Alias: use Name if Alias doesn't exist */
206506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	if (ptr)
207506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		dbus_message_iter_append_dict_entry(&dict, "Alias",
208506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi				DBUS_TYPE_STRING, &ptr);
209506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
2104e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Class */
211cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
2124e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz		dbus_message_iter_append_dict_entry(&dict, "Class",
2134e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz				DBUS_TYPE_UINT32, &class);
2144e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	}
2154e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2164e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Paired */
217769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	boolean = device_is_paired(device);
2184e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_append_dict_entry(&dict, "Paired",
2194e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_TYPE_BOOLEAN, &boolean);
2204e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2214e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Trusted */
222cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	boolean = read_trust(&src, dstaddr, GLOBAL_TRUST);
2234e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_append_dict_entry(&dict, "Trusted",
2244e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_TYPE_BOOLEAN, &boolean);
2254e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2264e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Connected */
227cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	dev = adapter_search_active_conn_by_bdaddr(adapter, &device->bdaddr);
228bcb5f7e4d5e570c1acfd5364547d36e970408394Alok Barsode	if (dev)
2294e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz		boolean = TRUE;
2304e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	else
2314e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz		boolean = FALSE;
2324e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2334e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_append_dict_entry(&dict, "Connected",
2344e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_TYPE_BOOLEAN, &boolean);
2354e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
236ba93fb91ea81a35be0834ac395650e020a6b3fd3Claudio Takahasi	/* UUIDs */
237769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
238769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
239769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz		uuids[i] = l->data;
2408afa46e246f1598ebfac26725606823cee2dd0ecLuiz Augusto von Dentz	dbus_message_iter_append_dict_entry(&dict, "UUIDs",
241769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz			DBUS_TYPE_ARRAY, &uuids);
242769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	g_free(uuids);
2434e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
24474fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz	/* Adapter */
2458a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi	ptr = adapter_get_path(adapter);
24674fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz	dbus_message_iter_append_dict_entry(&dict, "Adapter",
2478a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi			DBUS_TYPE_OBJECT_PATH, &ptr);
24874fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz
2494e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
2504e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
251e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return reply;
2522c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
2532c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
254e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,
2557fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					const char *alias, void *data)
2567fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
257555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
25818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
259cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
260cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
261506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	int err;
2627fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
263cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
264cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
265cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
2662a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
267cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	/* Remove alias if empty string */
268cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	err = write_device_alias(srcaddr, dstaddr,
269506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi			g_str_equal(alias, "") ? NULL : alias);
270506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	if (err < 0)
271e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return g_dbus_create_error(msg,
272e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				ERROR_INTERFACE ".Failed",
273506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi				strerror(-err));
2747fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
2757fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_connection_emit_property_changed(conn, dbus_message_get_path(msg),
2767fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					DEVICE_INTERFACE, "Alias",
277506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi					DBUS_TYPE_STRING, &alias);
2787fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
279e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
2807fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
2817fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
282e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,
2837fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					dbus_bool_t value, void *data)
2847fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
285555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
28618614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
287cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
288cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
2892a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
2907fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
291cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
292cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
293cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
2942a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
295cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	write_trust(srcaddr, dstaddr, GLOBAL_TRUST, value);
2967fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
2977fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_connection_emit_property_changed(conn, dbus_message_get_path(msg),
2987fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					DEVICE_INTERFACE, "Trusted",
2997fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					DBUS_TYPE_BOOLEAN, &value);
3007fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
301e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
3027fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
3037fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
304e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic inline DBusMessage *invalid_args(DBusMessage *msg)
305e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi{
306e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return g_dbus_create_error(msg,
307e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			ERROR_INTERFACE ".InvalidArguments",
308e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			"Invalid arguments in method call");
309e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi}
310e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi
311e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_property(DBusConnection *conn,
312e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *data)
3132c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
3147fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter iter;
3157fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter sub;
3167fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	const char *property;
3177fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3187fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (!dbus_message_iter_init(msg, &iter))
319e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3207fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3217fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
322e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3237fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3247fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_get_basic(&iter, &property);
3257fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_next(&iter);
3267fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3277fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
328e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3297fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_recurse(&iter, &sub);
3307fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3317fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (g_str_equal("Trusted", property)) {
3327fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_bool_t value;
3337fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3347fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
335e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			return invalid_args(msg);
3367fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &value);
3377fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3387fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_trust(conn, msg, value, data);
3397fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	} else if (g_str_equal("Alias", property)) {
340506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		const char *alias;
3417fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3427fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)
343e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			return invalid_args(msg);
3447fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &alias);
3457fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3467fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_alias(conn, msg, alias, data);
3477fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	}
3487fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
349e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return invalid_args(msg);
3502c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
3512c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
352342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentzstatic void discover_services_req_exit(void *user_data)
353342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz{
354555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
35518614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
356cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
3572a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
3582a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
359342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
360342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	debug("DiscoverDevices requestor exited");
361342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
362cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bt_cancel_discovery(&src, &device->bdaddr);
363342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz}
364342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
36594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *discover_services(DBusConnection *conn,
36694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
36794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
368555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
36994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	const char *pattern;
370342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	int err;
371342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
372342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (device->discov_active)
373342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
374342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz							"Discover in progress");
37594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
37694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
37794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						DBUS_TYPE_INVALID) == FALSE)
378342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		goto fail;
37994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
380a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (strlen(pattern) == 0) {
381040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		err = device_browse(device, conn, msg, NULL);
382342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
383342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
384342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	} else {
385040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		uuid_t uuid;
386040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi
387040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		if (bt_string2uuid(&uuid, pattern) < 0)
388342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			return invalid_args(msg);
389a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann
390040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		err = device_browse(device, conn, msg, &uuid);
391342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
392342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
393342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	}
39494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
39594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return NULL;
396342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
397342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentzfail:
398342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
399342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz					"Discovery Failed");
40094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
40194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
40294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *cancel_discover(DBusConnection *conn,
40394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
40494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
405555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
40618614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
407cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
4082a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
4092a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
41019b4c8b0e51a20a1b95ede34b092ebc56e1183aeMarcel Holtmann
411342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (!device->discov_active)
412342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg,
413342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				ERROR_INTERFACE ".Failed",
414342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				"No pending discovery");
415342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
416342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	/* only the discover requestor can cancel the inquiry process */
417342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (!device->discov_requestor ||
418342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			strcmp(device->discov_requestor, dbus_message_get_sender(msg)))
419342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg,
420342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				ERROR_INTERFACE ".NotAuthorized",
421342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				"Not Authorized");
422342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
423cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (bt_cancel_discovery(&src, &device->bdaddr) < 0)
424289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz		return g_dbus_create_error(msg,
425289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz				ERROR_INTERFACE ".Failed",
426289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz				"No pending discover");
42794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
42894c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return dbus_message_new_method_return(msg);
42994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
43094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
4315d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasistatic gboolean disconnect_timeout(gpointer user_data)
4325d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi{
433555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
4345d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	struct active_conn_info *ci;
4355d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	disconnect_cp cp;
4365d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	int dd;
437661a10565362c5ae0aad6a2ebf6513390cba868eAlok Barsode	uint16_t dev_id = adapter_get_dev_id(device->adapter);
4385d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4395d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	device->disconn_timer = 0;
4405d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
441cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ci = adapter_search_active_conn_by_bdaddr(device->adapter,
442cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode							&device->bdaddr);
443bcb5f7e4d5e570c1acfd5364547d36e970408394Alok Barsode
444bcb5f7e4d5e570c1acfd5364547d36e970408394Alok Barsode	if (!ci)
4455d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		return FALSE;
4465d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
447661a10565362c5ae0aad6a2ebf6513390cba868eAlok Barsode	dd = hci_open_dev(dev_id);
4485d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	if (dd < 0)
4495d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		goto fail;
4505d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4515d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	memset(&cp, 0, sizeof(cp));
4525d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	cp.handle = htobs(ci->handle);
4535d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	cp.reason = HCI_OE_USER_ENDED_CONNECTION;
4545d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4555d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	hci_send_cmd(dd, OGF_LINK_CTL, OCF_DISCONNECT,
4565d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DISCONNECT_CP_SIZE, &cp);
4575d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4585d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	close(dd);
4595d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4605d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasifail:
4615d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	return FALSE;
4625d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi}
4635d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
46494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *disconnect(DBusConnection *conn,
46594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
46694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
467555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
468bcb5f7e4d5e570c1acfd5364547d36e970408394Alok Barsode	struct active_conn_info *dev;
4695d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
470cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	dev = adapter_search_active_conn_by_bdaddr(device->adapter,
471cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode							&device->bdaddr);
472bcb5f7e4d5e570c1acfd5364547d36e970408394Alok Barsode
473bcb5f7e4d5e570c1acfd5364547d36e970408394Alok Barsode	if (!dev)
4745d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		return g_dbus_create_error(msg,
4755d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi				ERROR_INTERFACE ".NotConnected",
4765d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi				"Device is not connected");
4775d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4785d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	g_dbus_emit_signal(conn, device->path,
4795d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DEVICE_INTERFACE, "DisconnectRequested",
4805d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DBUS_TYPE_INVALID);
4815d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4825d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER,
4835d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi						disconnect_timeout, device);
48494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
48594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return dbus_message_new_method_return(msg);
48694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
48794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
488e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusMethodTable device_methods[] = {
489e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "GetProperties",	"",	"a{sv}",	get_properties	},
490e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "SetProperty",	"sv",	"",		set_property	},
491e0d13d6da4b527ee02838af6b9dd7d53615e4896Marcel Holtmann	{ "DiscoverServices",	"s",	"a{us}",	discover_services,
49294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						G_DBUS_METHOD_FLAG_ASYNC},
49394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "CancelDiscovery",	"",	"",		cancel_discover	},
494e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "Disconnect",		"",	"",		disconnect	},
49594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
4962c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
4972c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
498e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusSignalTable device_signals[] = {
49994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "PropertyChanged",		"sv"	},
50094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "DisconnectRequested",	""	},
50194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
5022c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
5032c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
50418614bd2b008cb9f3879990883c569c37b72f195Alok Barsodestruct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
50536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz					const gchar *address)
50686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
507ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	gchar *address_up;
508555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device;
509661a10565362c5ae0aad6a2ebf6513390cba868eAlok Barsode	uint16_t dev_id = adapter_get_dev_id(adapter);
51086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
511555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	device = g_try_malloc0(sizeof(struct btd_device));
51286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (device == NULL)
51386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
51486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
515ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	address_up = g_ascii_strup(address, -1);
51693fbf4400a81f68cd3642084bd6d2aa51a173250Marcel Holtmann	device->path = g_strdup_printf("%s/hci%d/dev_%s", "/org/bluez",
51793fbf4400a81f68cd3642084bd6d2aa51a173250Marcel Holtmann							dev_id, address_up);
51886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_strdelimit(device->path, ":", '_');
519ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	g_free(address_up);
52086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
52186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	debug("Creating device %s", device->path);
52286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
523e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE,
524e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device_methods, device_signals, NULL,
525e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device, device_free) == FALSE) {
52686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		device_free(device);
52786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
52886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	}
529da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
530cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	str2ba(address, &device->bdaddr);
531da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi	device->adapter = adapter;
532da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
5336bfa88d706cc57a0c975c980dabec5d8ed67dcc0Claudio Takahasi	return device;
53486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
53586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
536555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_remove(DBusConnection *conn, struct btd_device *device)
53775add5651e5dbc49c9c144acceac7e2c32d9bd16Claudio Takahasi{
5386061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	GSList *list;
5396061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	struct btd_device_driver *driver;
540f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	gchar *path = g_strdup(device->path);
541f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
542f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	debug("Removing device %s", path);
543f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
5446061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	for (list = device->drivers; list; list = list->next) {
545b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_driver_data *driver_data = list->data;
546b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		driver = driver_data->driver;
5476061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann
548e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz		driver->remove(device);
549b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		g_free(driver_data);
5506061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	}
5516061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann
552f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	g_dbus_unregister_interface(conn, path, DEVICE_INTERFACE);
55375add5651e5dbc49c9c144acceac7e2c32d9bd16Claudio Takahasi
554f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	g_free(path);
55586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
556ff296428a08dee619db1cc702146faefa91087faCidorvan Leite
557555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegint device_address_cmp(struct btd_device *device, const gchar *address)
558ff296428a08dee619db1cc702146faefa91087faCidorvan Leite{
559cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char addr[18];
560cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
561cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, addr);
562cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	return strcasecmp(addr, address);
563ff296428a08dee619db1cc702146faefa91087faCidorvan Leite}
5643d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
5654b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsodesdp_record_t *get_record(sdp_list_t *recs, const char *uuid)
566dde6ea8284f922181318ee84fd58144e06ee39b2Marcel Holtmann{
5674b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode	sdp_list_t *seq;
5684b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode
5694b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode	for (seq = recs; seq; seq = seq->next) {
5704b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		sdp_record_t *rec = (sdp_record_t *) seq->data;
5714b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		sdp_list_t *svcclass = NULL;
5724b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		char *uuid_str;
5734b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode
5744b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		if (sdp_get_service_classes(rec, &svcclass) < 0)
5754b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode			continue;
5764b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode
5774b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		/* Extract the uuid */
5784b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		uuid_str = bt_uuid2string(svcclass->data);
5794b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		if (!uuid_str)
5804b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode			continue;
581dde6ea8284f922181318ee84fd58144e06ee39b2Marcel Holtmann
5824b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		if (!strcasecmp(uuid_str, uuid)) {
5834b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode			sdp_list_free(svcclass, free);
5844b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode			free(uuid_str);
5854b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode			return rec;
5864b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		}
5874b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		sdp_list_free(svcclass, free);
5884b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		free(uuid_str);
5894b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode	}
5904b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode	return NULL;
591dde6ea8284f922181318ee84fd58144e06ee39b2Marcel Holtmann}
592dde6ea8284f922181318ee84fd58144e06ee39b2Marcel Holtmann
5934b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsodevoid device_probe_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs)
594f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann{
595c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	GSList *list;
5966061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	const char **uuid;
597f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	int err;
598f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
599f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	debug("Probe drivers for %s", device->path);
600f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
601c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	for (list = device_drivers; list; list = list->next) {
602e0863545e6239ac338fa7fbe9647a5748a60b436Marcel Holtmann		struct btd_device_driver *driver = list->data;
6034b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		GSList *records = NULL;
604f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
6056061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann		for (uuid = driver->uuids; *uuid; uuid++) {
606081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz			sdp_record_t *rec;
6074b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode
608081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz			if (!g_slist_find_custom(uuids, *uuid,
609081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz					(GCompareFunc) strcasecmp))
610081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz				continue;
611081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz
612081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz			rec = get_record(recs, *uuid);
613081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz			if (!rec)
614081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz				continue;
615081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz
616081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz			records = g_slist_append(records, rec);
617f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann		}
618f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
6194b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode		if (records) {
620b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode			struct btd_driver_data *driver_data = g_new0(struct btd_driver_data, 1);
621b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
622e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz			err = driver->probe(device, records);
623fad3b8ad7a07de0c96c34b9d624ec174c2754817Marcel Holtmann			if (err < 0) {
624f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann				error("probe failed for driver %s",
625f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann							driver->name);
626b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
627b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode				g_free(driver_data);
628fad3b8ad7a07de0c96c34b9d624ec174c2754817Marcel Holtmann				continue;
629fad3b8ad7a07de0c96c34b9d624ec174c2754817Marcel Holtmann			}
630fad3b8ad7a07de0c96c34b9d624ec174c2754817Marcel Holtmann
631b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode			driver_data->driver = driver;
632fad3b8ad7a07de0c96c34b9d624ec174c2754817Marcel Holtmann			device->drivers = g_slist_append(device->drivers,
633b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode								driver_data);
634f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann		}
635f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	}
63636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
63736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (list = uuids; list; list = list->next)
63836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		device->uuids = g_slist_insert_sorted(device->uuids,
63936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz				list->data, (GCompareFunc) strcmp);
64036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
64136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
6424b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsodevoid device_remove_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs)
64336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
64418614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
64536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	GSList *list;
646cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
6472a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
6482a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
6492a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
650cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
651cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
65236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
65336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	debug("Remove drivers for %s", device->path);
65436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
65536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (list = device->drivers; list; list = list->next) {
656b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_driver_data *driver_data = list->data;
657b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_device_driver *driver = driver_data->driver;
65836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		const char **uuid;
65936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
66036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		for (uuid = driver->uuids; *uuid; uuid++) {
6619b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			sdp_record_t *rec;
66236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
6639b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			if (!g_slist_find_custom(uuids, *uuid,
6649b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz					(GCompareFunc) strcasecmp))
66536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz				continue;
66636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
667e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz			driver->remove(device);
66836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			device->drivers = g_slist_remove(device->drivers,
669b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode								driver_data);
670b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
671b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode			g_free(driver_data);
672b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
6739b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			rec = get_record(recs, *uuid);
6749b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			if (!rec)
6759b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz				continue;
6769b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz
677cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode			delete_record(srcaddr, dstaddr, rec->handle);
67836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		}
67936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
68036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
68136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (list = uuids; list; list = list->next)
68236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		device->uuids = g_slist_remove(device->uuids, list->data);
683f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann}
684f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
685bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmannstatic void iter_append_record(DBusMessageIter *dict, uint32_t handle,
686bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann							const char *record)
687bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann{
688bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	DBusMessageIter entry;
689bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
690bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
691bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann							NULL, &entry);
692bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
693bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_append_basic(&entry, DBUS_TYPE_UINT32, &handle);
694bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
695bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &record);
696bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
697bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_close_container(dict, &entry);
698bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann}
699bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
700730775d1226a30c37ff551955f093ddfcd18e600Claudio Takahasistatic void append_and_grow_string(void *data, const char *str)
701c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz{
702c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	sdp_buf_t *buff = data;
703c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	int len;
704c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
705c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	len = strlen(str);
706c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
707c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	if (!buff->data) {
708c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->data = malloc(DEFAULT_XML_BUF_SIZE);
709c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		if (!buff->data)
710c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz			return;
711c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->buf_size = DEFAULT_XML_BUF_SIZE;
712c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	}
713c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
714c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	/* Grow string */
715c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	while (buff->buf_size < (buff->data_size + len + 1)) {
716c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		void *tmp;
717c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		uint32_t new_size;
718c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
719c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		/* Grow buffer by a factor of 2 */
720c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		new_size = (buff->buf_size << 1);
721c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
722c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		tmp = realloc(buff->data, new_size);
723c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		if (!tmp)
724c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz			return;
725c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
726c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->data = tmp;
727c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->buf_size = new_size;
728c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	}
729c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
730c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	/* Include the NULL character */
731c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	memcpy(buff->data + buff->data_size, str, len + 1);
732c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	buff->data_size += len;
733c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz}
734c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
7351e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentzstatic void discover_device_reply(struct browse_req *req, sdp_list_t *recs)
7361e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz{
7371e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	DBusMessage *reply;
7381e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	DBusMessageIter iter, dict;
7391e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	sdp_list_t *seq;
7401e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7411e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	reply = dbus_message_new_method_return(req->msg);
7421e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	if (!reply)
7431e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		return;
7441e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7451e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
7461e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7471e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
7481e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
7491e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_STRING_AS_STRING
7501e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
7511e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7521e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
7531e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
7541e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		sdp_buf_t result;
7551e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7561e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		if (!rec)
7571e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			break;
7581e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7591e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		memset(&result, 0, sizeof(sdp_buf_t));
7601e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7611e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		convert_sdp_record_to_xml(rec, &result,
7621e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz				append_and_grow_string);
7631e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7641e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		if (result.data) {
7651e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			const char *val = (char *) result.data;
7661e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			iter_append_record(&dict, rec->handle, val);
7671e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			free(result.data);
7681e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		}
7691e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	}
7701e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7711e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
7721e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
7731e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_connection_send(req->conn, reply, NULL);
7741e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_unref(reply);
7751e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz}
7761e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
77736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentzstatic void services_changed(struct browse_req *req)
7783d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
779555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
7803d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	char **uuids;
7813d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	GSList *l;
78236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	int i;
7833d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
78436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
78536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
78636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		uuids[i] = l->data;
78736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
78836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	dbus_connection_emit_property_changed(req->conn, device->path,
78936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz					DEVICE_INTERFACE, "UUIDs",
79036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz					DBUS_TYPE_ARRAY, &uuids);
79136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
79236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(uuids);
79336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
79436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
7958b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedbergstatic int rec_cmp(const void *a, const void *b)
7968b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg{
7978b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r1 = a;
7988b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r2 = b;
7998b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
8008b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	return r1->handle - r2->handle;
8018b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg}
8028b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
80336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentzstatic void update_services(struct browse_req *req, sdp_list_t *recs)
80436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
805555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
80618614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
80736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	sdp_list_t *seq;
808cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
8092a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
8102a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
8112a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
812cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
813cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
8143d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
81536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
8163d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
817681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		sdp_buf_t pdu;
81836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_t *svcclass = NULL;
81936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		gchar *uuid_str;
82036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		GSList *l;
8213d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
8223d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		if (!rec)
8233d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz			break;
8243d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
82536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (sdp_get_service_classes(rec, &svcclass) < 0)
82636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
82736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
82836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		/* Extract the first element and skip the remainning */
82936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		uuid_str = bt_uuid2string(svcclass->data);
83036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (!uuid_str)
83136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
83236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
83358d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz		/* Driver uuid found */
83458d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz		l = g_slist_find_custom(req->uuids, uuid_str,
83558d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz				(GCompareFunc) strcasecmp);
836e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		if (l) {
837e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz			char *uuid = l->data;
838e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz
839e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz			req->uuids = g_slist_remove(req->uuids, uuid);
840e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz			g_free(uuid);
841e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		}
84258d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz
84337a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg		/* Check for duplicates */
8448b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg		if (sdp_list_find(req->records, rec, rec_cmp))
84537a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg			continue;
84637a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
847cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		store_record(srcaddr, dstaddr, rec);
84837a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
849681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		/* Copy record */
850681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		if (sdp_gen_record_pdu(rec, &pdu) == 0) {
851681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz			sdp_record_t *record;
852681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz			int scanned;
853681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
854681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz			record = sdp_extract_pdu(pdu.data, pdu.data_size,
855681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz						&scanned);
8561d40bababe8114b88ec654b7764ff20c22a258c1Johan Hedberg			free(pdu.data);
857681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz			req->records = sdp_list_append(req->records, record);
858681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		}
859681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
86036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		l = g_slist_find_custom(device->uuids, uuid_str,
86136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz				(GCompareFunc) strcmp);
86236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (!l)
86336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			req->uuids_added = g_slist_append(req->uuids_added,
86436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz					uuid_str);
86536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		else {
86636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			req->uuids_removed = g_slist_remove(req->uuids_removed,
86736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz					l->data);
86836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			g_free(uuid_str);
8693d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		}
8703d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
87136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_free(svcclass, free);
8723d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	}
87336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
87436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
875555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestatic void store(struct btd_device *device)
87636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
87718614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
878cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
87936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	char *str;
8803d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
8812a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
8823d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
88336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	if (!device->uuids) {
884cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		write_device_profiles(&src, &device->bdaddr, "");
88536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		return;
88636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
88736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
88836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	str = bt_list2string(device->uuids);
889cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	write_device_profiles(&src, &device->bdaddr, str);
89036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(str);
89136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
89236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
893da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void search_cb(sdp_list_t *recs, int err, gpointer user_data)
89436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
89536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	struct browse_req *req = user_data;
896555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
89736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	DBusMessage *reply;
8982a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
899681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	if (err < 0) {
900681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		error("%s: error updating services: %s (%d)",
901681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz				device->path, strerror(-err), -err);
90236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		goto proceed;
903681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	}
90436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
90536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	update_services(req, recs);
90636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
907681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	if (!req->uuids_added && !req->uuids_removed) {
908e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		debug("%s: No service update", device->path);
90936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		goto proceed;
910681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	}
9112efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
91236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Probe matching drivers for services added */
91336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	if (req->uuids_added)
914681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		device_probe_drivers(device, req->uuids_added, req->records);
9152efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
91636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Remove drivers for services removed */
91736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	if (req->uuids_removed)
918681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		device_remove_drivers(device, req->uuids_removed, req->records);
9192efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
92036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Propagate services changes */
92136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	services_changed(req);
922f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
9237b67507336f98dda5523902806dd2e33684fab6bLuiz Augusto von Dentzproceed:
924681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
925681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	/* Store the device's profiles in the filesystem */
926681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	store(device);
927681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
9281e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
9291e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			"DiscoverServices")) {
930681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		discover_device_reply(req, req->records);
9311e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		goto cleanup;
932a2529a9b417959a52f5d501cba4bcaf32caf6964Marcel Holtmann	}
933a2529a9b417959a52f5d501cba4bcaf32caf6964Marcel Holtmann
934f80a7215275b229a597cf8d2bbc7e4e208af522cMarcel Holtmann	g_dbus_emit_signal(req->conn, dbus_message_get_path(req->msg),
9358d8f45c98ddabe1ffb5b2b4f93fa3983027ba740Luiz Augusto von Dentz				ADAPTER_INTERFACE, "DeviceCreated",
9368d8f45c98ddabe1ffb5b2b4f93fa3983027ba740Luiz Augusto von Dentz				DBUS_TYPE_OBJECT_PATH, &device->path,
9378d8f45c98ddabe1ffb5b2b4f93fa3983027ba740Luiz Augusto von Dentz				DBUS_TYPE_INVALID);
9388d8f45c98ddabe1ffb5b2b4f93fa3983027ba740Luiz Augusto von Dentz
9393d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	/* Reply create device request */
9403d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	reply = dbus_message_new_method_return(req->msg);
9413d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	if (!reply)
9421e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		goto cleanup;
9433d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
9443d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &device->path,
945a2529a9b417959a52f5d501cba4bcaf32caf6964Marcel Holtmann							DBUS_TYPE_INVALID);
9463d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
9470472470e5059e702f0e7e69ee0155dfea11baa25Marcel Holtmann	dbus_connection_send(req->conn, reply, NULL);
9480472470e5059e702f0e7e69ee0155dfea11baa25Marcel Holtmann	dbus_message_unref(reply);
9493d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
9501e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentzcleanup:
9512efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz	device->discov_active = 0;
9522efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
9532efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz	if (device->discov_requestor) {
9542efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz		g_dbus_remove_watch(req->conn, device->discov_listener);
9552efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz		device->discov_listener = 0;
9562efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz		g_free(device->discov_requestor);
9572efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz		device->discov_requestor = NULL;
9582efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz	}
9592efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
9603d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	dbus_message_unref(req->msg);
9613d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	dbus_connection_unref(req->conn);
96236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_slist_free(req->uuids_added);
96336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_slist_free(req->uuids_removed);
964681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	if (req->records)
965681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
9663d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	g_free(req);
967da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
968da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
969da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
970da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
971da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
972da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct browse_req *req = user_data;
973da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_device *device = req->device;
974da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
975cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
976da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	uuid_t uuid;
977da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
9787d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse	/* If we have a valid response and req->search_uuid == 1, then
9797d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse	   public browsing was successful -- we don't need any more */
9807d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse	if (err < 0 || (req->search_uuid == 1 && recs))
981da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		goto done;
982da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
983da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	update_services(req, recs);
984da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
985da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	adapter_get_address(adapter, &src);
986da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
987da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	/* Search for mandatory uuids */
9887d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse	if (uuid_list[req->search_uuid]) {
9897d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
990cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		bt_search_service(&src, &device->bdaddr, &uuid, browse_cb, user_data, NULL);
991da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		return;
992da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	}
993da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
99458d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz	/* Search for drivers uuids */
99558d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz	if (req->uuids) {
996e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		char *uuid_str = req->uuids->data;
997e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz
998e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		bt_string2uuid(&uuid, uuid_str);
999e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		req->uuids = g_slist_remove(req->uuids, uuid_str);
1000e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		g_free(uuid_str);
1001cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		bt_search_service(&src, &device->bdaddr, &uuid, browse_cb, user_data, NULL);
100258d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz		return;
100378eadf19bbee1f52b738d39133296186b3e944feLuiz Augusto von Dentz	}
100478eadf19bbee1f52b738d39133296186b3e944feLuiz Augusto von Dentz
100578eadf19bbee1f52b738d39133296186b3e944feLuiz Augusto von Dentz	/* Search for l2cap uuid */
100678eadf19bbee1f52b738d39133296186b3e944feLuiz Augusto von Dentz	if (!req->records) {
100778eadf19bbee1f52b738d39133296186b3e944feLuiz Augusto von Dentz		sdp_uuid16_create(&uuid, L2CAP_UUID);
1008cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		bt_search_service(&src, &device->bdaddr, &uuid, search_cb, user_data, NULL);
100978eadf19bbee1f52b738d39133296186b3e944feLuiz Augusto von Dentz		return;
101058d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz	}
101158d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz
1012da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzdone:
1013da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	search_cb(recs, err, user_data);
1014da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
1015da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1016da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void init_browse(struct browse_req *req)
1017da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
1018da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	GSList *l;
1019da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
102058d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz	for (l = device_drivers; l; l = l->next) {
102158d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz		struct btd_device_driver *driver = l->data;
102258d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz		int i;
102358d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz
102458d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz		for (i = 0; driver->uuids[i]; i++) {
1025e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz			char *uuid;
10260144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse			int j;
10270144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse
10280144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse			/* Eliminate duplicates of UUIDs in uuid_list[]... */
10290144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse			if (strlen(driver->uuids[i]) == 36 &&
10300144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse			    !strncmp(driver->uuids[i], "0000", 4) &&
10310144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse			    !strcasecmp(driver->uuids[i] + 8,
10320144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse					"-0000-1000-8000-00805F9B34FB")) {
10330144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse				uint16_t uuid16 = strtol(driver->uuids[i],
10340144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse							 NULL, 16);
10350144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse				for (j = 0; uuid_list[j]; j++) {
10360144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse					if (uuid16 == uuid_list[j])
10370144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse						continue;
10380144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse				}
10390144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse
10400144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse			}
10410144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse			/* ... and of UUIDs another driver already asked for */
104258d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz			if (g_slist_find_custom(req->uuids, driver->uuids[i],
104358d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz					(GCompareFunc) strcasecmp))
10440144612a3d800c5d657cf141634f6b6cd47b4128David Woodhouse				continue;
1045e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz
1046e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz			uuid = g_strdup(driver->uuids[i]);
1047e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz			req->uuids = g_slist_append(req->uuids, uuid);
104858d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz		}
104958d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz	}
105058d8ea3c3a8ea69e652d8a39649a19426f31933bLuiz Augusto von Dentz
1051da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	for (l = req->device->uuids; l; l = l->next)
1052da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		req->uuids_removed = g_slist_append(req->uuids_removed,
1053da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz						l->data);
10543d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
10553d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1056555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeint device_browse(struct btd_device *device, DBusConnection *conn,
1057040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi			DBusMessage *msg, uuid_t *search)
10583d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
105918614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
10603d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	struct browse_req *req;
1061cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
1062d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	uuid_t uuid;
1063da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	bt_callback_t cb;
10642a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
10652a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
10663d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
10673d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req = g_new0(struct browse_req, 1);
10683d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req->conn = dbus_connection_ref(conn);
10693d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req->msg = dbus_message_ref(msg);
10703d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req->device = device;
10713d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1072a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (search) {
1073040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		memcpy(&uuid, search, sizeof(uuid_t));
1074da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = search_cb;
1075a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	} else {
10767d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
1077da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		init_browse(req);
1078da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = browse_cb;
1079a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	}
1080d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
108195e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz	device->discov_active = 1;
108295e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz	device->discov_requestor = g_strdup(dbus_message_get_sender(msg));
1083040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi	/* Track the request owner to cancel it
1084040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi	 * automatically if the owner exits */
108595e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz	device->discov_listener = g_dbus_add_disconnect_watch(conn,
108695e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						dbus_message_get_sender(msg),
108795e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						discover_services_req_exit,
108895e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						device, NULL);
108995e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz
1090cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	return bt_search_service(&src, &device->bdaddr,
10917d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse					&uuid, cb, req, NULL);
10923d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
109324cce397c3479e95f3e525da9285234fbafd2984Marcel Holtmann
109418614bd2b008cb9f3879990883c569c37b72f195Alok Barsodestruct btd_adapter *device_get_adapter(struct btd_device *device)
1095dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode{
1096dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	if (!device)
1097dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode		return NULL;
1098dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
1099dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	return device->adapter;
1100dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode}
1101dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
110219ce4933f3dadf3b04a2a9bd84d66d750cc010c3Alok Barsodevoid device_get_address(struct btd_device *device, bdaddr_t *bdaddr)
1103aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode{
1104cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bacpy(bdaddr, &device->bdaddr);
1105aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode}
1106aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode
1107555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeconst gchar *device_get_path(struct btd_device *device)
110846fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode{
110946fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	if (!device)
111046fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode		return NULL;
111146fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
111246fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	return device->path;
111346fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode}
111446fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
1115555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestruct agent *device_get_agent(struct btd_device *device)
1116a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode{
1117a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode	if (!device)
1118a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode		return NULL;
1119a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
1120a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode	return  device->agent;
1121a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode}
1122a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
1123555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_agent(struct btd_device *device, struct agent *agent)
1124d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode{
1125d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode	if (!device)
1126d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode		return;
1127d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode
1128d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode	device->agent = agent;
1129d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode}
1130d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode
1131555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_busy(struct btd_device *device)
11329f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode{
11339f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode	return device->discov_active ? TRUE : FALSE;
11349f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode}
11359f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode
1136555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_temporary(struct btd_device *device)
1137f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode{
1138f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode	return device->temporary;
1139f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode}
1140f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode
1141555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_temporary(struct btd_device *device, gboolean temporary)
1142595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode{
1143595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode	if (!device)
1144595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode		return;
1145595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode
1146595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode	device->temporary = temporary;
1147595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode}
1148595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode
1149555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_cap(struct btd_device *device, uint8_t cap)
1150491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode{
1151491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode	if (!device)
1152491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode		return;
1153491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode
1154491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode	device->cap = cap;
1155491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode}
1156491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode
1157555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_auth(struct btd_device *device, uint8_t auth)
115829227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode{
115929227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode	if (!device)
116029227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode		return;
116129227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode
116229227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode	device->auth = auth;
116329227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode}
116429227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode
1165555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeuint8_t device_get_auth(struct btd_device *device)
11662203f153c53189ec1c30df99b717e035681196e6Alok Barsode{
11672203f153c53189ec1c30df99b717e035681196e6Alok Barsode	return device->auth;
11682203f153c53189ec1c30df99b717e035681196e6Alok Barsode}
1169c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
1170c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzint btd_register_device_driver(struct btd_device_driver *driver)
1171c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
1172c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_append(device_drivers, driver);
1173c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
1174c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	return 0;
1175c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
1176c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
1177c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzvoid btd_unregister_device_driver(struct btd_device_driver *driver)
1178c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
1179c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_remove(device_drivers, driver);
1180c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
1181