device.c revision f6646fcfe84b703d0657a0e827682702d64a4788
1dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann/*
2dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
3dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
5f1659f19cfb3ef0c0c09b5f5b7e2b06d90d079abMarcel Holtmann *  Copyright (C) 2006-2007  Nokia Corporation
6fb333f1c88df9c50529a390297565a6627bcf7adMarcel Holtmann *  Copyright (C) 2004-2009  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>
32f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg#include <fcntl.h>
336a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include <sys/stat.h>
341af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg#include <errno.h>
35dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
36dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/bluetooth.h>
37dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/hci.h>
38dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/hci_lib.h>
392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz#include <bluetooth/l2cap.h>
405d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp.h>
415d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp_lib.h>
42dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <glib.h>
4486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <dbus/dbus.h>
4515ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#include <gdbus.h>
4686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
4786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "logging.h"
486a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include "textfile.h"
49dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
50506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi#include "hcid.h"
512c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes#include "adapter.h"
5286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "device.h"
53da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi#include "dbus-common.h"
544e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz#include "dbus-hci.h"
557fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz#include "error.h"
563d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz#include "glib-helper.h"
57fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite#include "agent.h"
583d3cdef8da6b3e1b14c3cdccda8c099cbad4f3aeMarcel Holtmann#include "sdp-xml.h"
59506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi#include "storage.h"
6086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
61c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz#define DEFAULT_XML_BUF_SIZE	1024
625d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi#define DISCONNECT_TIMER	2
637ec871d37de442fd3731a0eef319851c61fb04ccLuiz Augusto von Dentz#define DISCOVERY_TIMER		2
64dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
65e3afaa0b7ff373d89fd3fa257110a34df7495df7Luiz Augusto von Dentzstruct btd_driver_data {
66b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode	struct btd_device_driver *driver;
67b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode	void *priv;
68b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode};
69b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstruct bonding_req {
712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusConnection *conn;
722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusMessage *msg;
732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	GIOChannel *io;
742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	guint io_id;
752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	guint listener_id;
76dd10ec5d830d2e2187f93bd2d7e60be947335f0bJohan Hedberg	gboolean auth_required;
772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device;
782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz};
792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstruct authentication_req {
812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth_type_t type;
822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	void *cb;
832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device;
852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz};
862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
87555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestruct btd_device {
88cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t	bdaddr;
89ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	gchar		*path;
9018614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter	*adapter;
91ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	GSList		*uuids;
92b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode	GSList		*drivers;		/* List of driver_data */
93ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	gboolean	temporary;
94ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	struct agent	*agent;
95ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	guint		disconn_timer;
96ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	int		discov_active;		/* Service discovery active */
97ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	char		*discov_requestor;	/* discovery requestor unique name */
98ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	guint		discov_listener;
99013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	guint		discov_timer;
1002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
1012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *authr;	/* authentication request */
102ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
103ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	/* For Secure Simple Pairing */
104ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	uint8_t		cap;
105ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	uint8_t		auth;
106e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
107c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	uint16_t	handle;			/* Connection handle */
108e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
109e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	/* Whether were creating a security mode 3 connection */
110e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	gboolean	secmode3;
111548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
112548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	sdp_list_t	*tmp_records;
113bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
114bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	gboolean	renewed_key;
115ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode};
116ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
1173d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentzstruct browse_req {
1183d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	DBusConnection *conn;
1193d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	DBusMessage *msg;
120555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device;
1210dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	GSList *match_uuids;
1220dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	GSList *profiles_added;
1230dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	GSList *profiles_removed;
124681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	sdp_list_t *records;
125d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	int search_uuid;
1263d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz};
1273d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
128d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmannstatic uint16_t uuid_list[] = {
1290dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	L2CAP_UUID,
1301c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	PNP_INFO_SVCLASS_ID,
1310dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	PUBLIC_BROWSE_GROUP,
132d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	0
133d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann};
134d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
135c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzstatic GSList *device_drivers = NULL;
136c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
1372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn,
1382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						DBusMessage *msg, int err)
1392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return error_common_reply(conn, msg,
1412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			ERROR_INTERFACE ".ConnectionAttemptFailed",
1422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			err > 0 ? strerror(err) : "Connection attempt failed");
1432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic DBusHandlerResult error_failed(DBusConnection *conn,
1462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusMessage *msg, const char * desc)
1472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return error_common_reply(conn, msg, ERROR_INTERFACE ".Failed", desc);
1492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic DBusHandlerResult error_failed_errno(DBusConnection *conn,
1522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						DBusMessage *msg, int err)
1532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	const char *desc = strerror(err);
1552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return error_failed(conn, msg, desc);
1572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic inline DBusMessage *no_such_adapter(DBusMessage *msg)
1602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchAdapter",
1622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							"No such adapter");
1632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic inline DBusMessage *in_progress(DBusMessage *msg, const char *str)
1662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress", str);
1682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
170e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic void device_free(gpointer user_data)
17186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
172555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
1732f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
1742f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct agent *agent = adapter_get_agent(adapter);
175e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi
176fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite	if (device->agent)
177fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite		agent_destroy(device->agent, FALSE);
178f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
1792f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	if (agent && agent_is_busy(agent, device))
1802f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz		agent_cancel(agent);
1812f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz
182ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_foreach(device->uuids, (GFunc) g_free, NULL);
183ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_free(device->uuids);
184f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
1855d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	if (device->disconn_timer)
1865d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		g_source_remove(device->disconn_timer);
1875d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
188401374312bdc966bf386a1d89bf6cd0f74a4314cLuiz Augusto von Dentz	if (device->discov_timer)
189401374312bdc966bf386a1d89bf6cd0f74a4314cLuiz Augusto von Dentz		g_source_remove(device->discov_timer);
190401374312bdc966bf386a1d89bf6cd0f74a4314cLuiz Augusto von Dentz
19186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device->path);
19286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device);
19386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
19486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
195555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestatic gboolean device_is_paired(struct btd_device *device)
196769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz{
19718614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
198cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char filename[PATH_MAX + 1], *str;
199cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
200769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	gboolean ret;
201cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
2022a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
203cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
204cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
205cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
206769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
207769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR,
208cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode			srcaddr, "linkkeys");
209cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	str = textfile_caseget(filename, dstaddr);
210769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	ret = str ? TRUE : FALSE;
211769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	g_free(str);
212769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
213769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	return ret;
214769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz}
215769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
216e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *get_properties(DBusConnection *conn,
217e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *user_data)
2182c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
219555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
22018614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
2214e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessage *reply;
2224e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter iter;
2234e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter dict;
224cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
225cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char name[248], srcaddr[18], dstaddr[18];
2268a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi	char **uuids;
2272a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	const char *ptr;
2284e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_bool_t boolean;
2294e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	uint32_t class;
230769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	int i;
231769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	GSList *l;
2324e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
233cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
234cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
2354e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	reply = dbus_message_new_method_return(msg);
2364e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	if (!reply)
237e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return NULL;
2384e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2394e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
2404e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2414e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
2424e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
2434e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
2444e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
2454e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2464e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Address */
247cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ptr = dstaddr;
2481262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Address", DBUS_TYPE_STRING, &ptr);
2494e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2504e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Name */
251506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	ptr = NULL;
252506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	memset(name, 0, sizeof(name));
2532a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
254cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
2558a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi
256cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (read_device_name(srcaddr, dstaddr, name) == 0) {
257506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		ptr = name;
2581262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg		dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &ptr);
2594e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	}
2604e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
261afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann	/* Alias (fallback to name or address) */
262afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann	if (read_device_alias(srcaddr, dstaddr, name, sizeof(name)) < 1) {
263afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann		if (!ptr) {
264afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann			g_strdelimit(dstaddr, ":", '-');
265afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann			ptr = dstaddr;
266afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann		}
267afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann	} else
268506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		ptr = name;
269506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
270506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	if (ptr)
2711262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg		dict_append_entry(&dict, "Alias", DBUS_TYPE_STRING, &ptr);
272506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
2734e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Class */
274cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
275e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann		const char *icon = class_to_icon(class);
276e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann
2771262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg		dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
278e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann
279e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann		if (icon)
2801262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg			dict_append_entry(&dict, "Icon",
281e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann						DBUS_TYPE_STRING, &icon);
2824e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	}
2834e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2844e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Paired */
285769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	boolean = device_is_paired(device);
2861262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Paired", DBUS_TYPE_BOOLEAN, &boolean);
2874e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2884e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Trusted */
289cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	boolean = read_trust(&src, dstaddr, GLOBAL_TRUST);
2901262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Trusted", DBUS_TYPE_BOOLEAN, &boolean);
2914e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2924e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Connected */
293c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	boolean = (device->handle != 0);
294c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN,
295c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz				&boolean);
2964e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
297ba93fb91ea81a35be0834ac395650e020a6b3fd3Claudio Takahasi	/* UUIDs */
298769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
299769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
300769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz		uuids[i] = l->data;
3013a11e84a573785024b11d89ed4f9b06e43b06ca6Johan Hedberg	dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
302769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	g_free(uuids);
3034e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
30474fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz	/* Adapter */
3058a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi	ptr = adapter_get_path(adapter);
3061262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Adapter", DBUS_TYPE_OBJECT_PATH, &ptr);
30774fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz
3084e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
3094e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
310e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return reply;
3112c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
3122c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
313e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,
3147fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					const char *alias, void *data)
3157fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
316555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
31718614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
318cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
319cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
320506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	int err;
3217fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
322cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
323cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
324cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
3252a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
326cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	/* Remove alias if empty string */
327cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	err = write_device_alias(srcaddr, dstaddr,
328506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi			g_str_equal(alias, "") ? NULL : alias);
329506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	if (err < 0)
330e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return g_dbus_create_error(msg,
331e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				ERROR_INTERFACE ".Failed",
332506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi				strerror(-err));
3337fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
334c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, dbus_message_get_path(msg),
335c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DEVICE_INTERFACE, "Alias",
336c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DBUS_TYPE_STRING, &alias);
3377fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
338e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
3397fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
3407fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
341e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,
3427fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					dbus_bool_t value, void *data)
3437fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
344555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
34518614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
346cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
347cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
3482a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
3497fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
350cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
351cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
352cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
3532a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
354cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	write_trust(srcaddr, dstaddr, GLOBAL_TRUST, value);
3557fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
356c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, dbus_message_get_path(msg),
357c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DEVICE_INTERFACE, "Trusted",
358c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DBUS_TYPE_BOOLEAN, &value);
3597fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
360e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
3617fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
3627fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
363e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic inline DBusMessage *invalid_args(DBusMessage *msg)
364e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi{
365e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return g_dbus_create_error(msg,
366e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			ERROR_INTERFACE ".InvalidArguments",
367e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			"Invalid arguments in method call");
368e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi}
369e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi
370e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_property(DBusConnection *conn,
371e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *data)
3722c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
3737fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter iter;
3747fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter sub;
3757fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	const char *property;
3767fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3777fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (!dbus_message_iter_init(msg, &iter))
378e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3797fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3807fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
381e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3827fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3837fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_get_basic(&iter, &property);
3847fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_next(&iter);
3857fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3867fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
387e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3887fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_recurse(&iter, &sub);
3897fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3907fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (g_str_equal("Trusted", property)) {
3917fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_bool_t value;
3927fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3937fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
394e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			return invalid_args(msg);
3957fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &value);
3967fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3977fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_trust(conn, msg, value, data);
3987fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	} else if (g_str_equal("Alias", property)) {
399506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		const char *alias;
4007fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
4017fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)
402e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			return invalid_args(msg);
4037fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &alias);
4047fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
4057fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_alias(conn, msg, alias, data);
4067fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	}
4077fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
408e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return invalid_args(msg);
4092c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
4102c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
4111f5107e65f9786bd6b84ecfb4d84691e9b34529aMarcel Holtmannstatic void discover_services_req_exit(DBusConnection *conn, void *user_data)
412342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz{
413555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
41418614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
415cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
4162a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
4172a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
418342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
419342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	debug("DiscoverDevices requestor exited");
420342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
421cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bt_cancel_discovery(&src, &device->bdaddr);
422342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz}
423342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
42494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *discover_services(DBusConnection *conn,
42594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
42694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
427555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
42894c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	const char *pattern;
429342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	int err;
430342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
431342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (device->discov_active)
432342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
433342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz							"Discover in progress");
43494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
43594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
43694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						DBUS_TYPE_INVALID) == FALSE)
437342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		goto fail;
43894c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
439a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (strlen(pattern) == 0) {
44069adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		err = device_browse(device, conn, msg, NULL, FALSE);
441342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
442342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
443342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	} else {
444040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		uuid_t uuid;
445040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi
446040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		if (bt_string2uuid(&uuid, pattern) < 0)
447342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			return invalid_args(msg);
448a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann
4494b1914903cb105acf843b84833e81d5470133879Johan Hedberg		sdp_uuid128_to_uuid(&uuid);
4504b1914903cb105acf843b84833e81d5470133879Johan Hedberg
45169adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		err = device_browse(device, conn, msg, &uuid, FALSE);
452342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
453342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
454342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	}
45594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
45694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return NULL;
457342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
458342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentzfail:
459342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
460342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz					"Discovery Failed");
46194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
46294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
46394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *cancel_discover(DBusConnection *conn,
46494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
46594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
466555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
46718614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
468cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
4692a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
4702a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
47119b4c8b0e51a20a1b95ede34b092ebc56e1183aeMarcel Holtmann
472342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (!device->discov_active)
473342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg,
474342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				ERROR_INTERFACE ".Failed",
475342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				"No pending discovery");
476342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
477342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	/* only the discover requestor can cancel the inquiry process */
478342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (!device->discov_requestor ||
479342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			strcmp(device->discov_requestor, dbus_message_get_sender(msg)))
480342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg,
481342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				ERROR_INTERFACE ".NotAuthorized",
482342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				"Not Authorized");
483342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
484cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (bt_cancel_discovery(&src, &device->bdaddr) < 0)
485289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz		return g_dbus_create_error(msg,
486289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz				ERROR_INTERFACE ".Failed",
487289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz				"No pending discover");
48894c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
48994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return dbus_message_new_method_return(msg);
49094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
49194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
4925d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasistatic gboolean disconnect_timeout(gpointer user_data)
4935d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi{
494555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
4955d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	disconnect_cp cp;
4965d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	int dd;
497661a10565362c5ae0aad6a2ebf6513390cba868eAlok Barsode	uint16_t dev_id = adapter_get_dev_id(device->adapter);
4985d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
4995d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	device->disconn_timer = 0;
5005d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
501661a10565362c5ae0aad6a2ebf6513390cba868eAlok Barsode	dd = hci_open_dev(dev_id);
5025d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	if (dd < 0)
5035d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		goto fail;
5045d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5055d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	memset(&cp, 0, sizeof(cp));
506c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	cp.handle = htobs(device->handle);
5075d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	cp.reason = HCI_OE_USER_ENDED_CONNECTION;
5085d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5095d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	hci_send_cmd(dd, OGF_LINK_CTL, OCF_DISCONNECT,
5105d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DISCONNECT_CP_SIZE, &cp);
5115d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5125d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	close(dd);
5135d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5145d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasifail:
5155d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	return FALSE;
5165d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi}
5175d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
51894c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *disconnect(DBusConnection *conn,
51994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
52094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
521555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
5225d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
523c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (!device->handle)
5245d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		return g_dbus_create_error(msg,
5255d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi				ERROR_INTERFACE ".NotConnected",
5265d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi				"Device is not connected");
5275d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5285d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	g_dbus_emit_signal(conn, device->path,
5295d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DEVICE_INTERFACE, "DisconnectRequested",
5305d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DBUS_TYPE_INVALID);
5315d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5325d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER,
5335d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi						disconnect_timeout, device);
53494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
53594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return dbus_message_new_method_return(msg);
53694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
53794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
538e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusMethodTable device_methods[] = {
539e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "GetProperties",	"",	"a{sv}",	get_properties	},
540e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "SetProperty",	"sv",	"",		set_property	},
541e0d13d6da4b527ee02838af6b9dd7d53615e4896Marcel Holtmann	{ "DiscoverServices",	"s",	"a{us}",	discover_services,
54294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						G_DBUS_METHOD_FLAG_ASYNC},
54394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "CancelDiscovery",	"",	"",		cancel_discover	},
544e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "Disconnect",		"",	"",		disconnect	},
54594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
5462c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
5472c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
548e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusSignalTable device_signals[] = {
54994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "PropertyChanged",		"sv"	},
55094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "DisconnectRequested",	""	},
55194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
5522c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
5532c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
554c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzgboolean device_is_connected(struct btd_device *device)
555e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg{
556c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	return (device->handle != 0);
557e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg}
558e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
559c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzstatic void device_set_connected(struct btd_device *device, DBusConnection *conn,
560013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg			gboolean connected)
561013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
562c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, device->path, DEVICE_INTERFACE,
563c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				"Connected", DBUS_TYPE_BOOLEAN, &connected);
564e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
565e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	if (connected && device->secmode3) {
566e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		struct btd_adapter *adapter = device_get_adapter(device);
567e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		bdaddr_t sba;
568e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
569e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		adapter_get_address(adapter, &sba);
570e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
571e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		device->secmode3 = FALSE;
572e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
573e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		hcid_dbus_bonding_process_complete(&sba, &device->bdaddr, 0);
574e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	}
575e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg}
576e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
577c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzvoid device_add_connection(struct btd_device *device, DBusConnection *conn,
578c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz				uint16_t handle)
579c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
580c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (device->handle) {
581c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		error("%s: Unable to add connection %u, %u already exist)",
582c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz			device->path, handle, device->handle);
583c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		return;
584c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	}
585c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
586c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device->handle = handle;
587c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
588c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device_set_connected(device, conn, TRUE);
589c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
590c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
591c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzvoid device_remove_connection(struct btd_device *device, DBusConnection *conn,
592c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz				uint16_t handle)
593c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
594c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (device->handle != handle) {
595c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		error("%s: Unable to remove connection %u, handle mismatch (%u)",
596c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz			device->path, handle, device->handle);
597c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		return;
598c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	}
599c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
600c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device->handle = 0;
601c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
602c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device_set_connected(device, conn, FALSE);
603c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
604c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
605c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzgboolean device_has_connection(struct btd_device *device, uint16_t handle)
606c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
607c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	return (handle == device->handle);
608c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
609c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
610e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedbergvoid device_set_secmode3_conn(struct btd_device *device, gboolean enable)
611e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg{
612e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	device->secmode3 = enable;
613013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
614013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
61518614bd2b008cb9f3879990883c569c37b72f195Alok Barsodestruct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
61636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz					const gchar *address)
61786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
618ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	gchar *address_up;
619555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device;
620139c2014be451848fcc3fa31cdc07653148f596eMarcel Holtmann	const gchar *adapter_path = adapter_get_path(adapter);
62186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
622555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	device = g_try_malloc0(sizeof(struct btd_device));
62386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (device == NULL)
62486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
62586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
626ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	address_up = g_ascii_strup(address, -1);
627139c2014be451848fcc3fa31cdc07653148f596eMarcel Holtmann	device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up);
62886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_strdelimit(device->path, ":", '_');
629ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	g_free(address_up);
63086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
63186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	debug("Creating device %s", device->path);
63286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
633e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE,
634e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device_methods, device_signals, NULL,
635e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device, device_free) == FALSE) {
63686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		device_free(device);
63786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
63886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	}
639da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
640cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	str2ba(address, &device->bdaddr);
641da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi	device->adapter = adapter;
642da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
6436bfa88d706cc57a0c975c980dabec5d8ed67dcc0Claudio Takahasi	return device;
64486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
64586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
6462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void device_remove_bonding(struct btd_device *device, DBusConnection *conn)
6472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
6482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char filename[PATH_MAX + 1];
6492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char *str, srcaddr[18], dstaddr[18];
6502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	int dd, dev_id;
6512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bdaddr_t bdaddr;
6522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	gboolean paired;
6532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	adapter_get_address(device->adapter, &bdaddr);
6552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&bdaddr, srcaddr);
6562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&device->bdaddr, dstaddr);
6572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dev_id = adapter_get_dev_id(device->adapter);
6592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dd = hci_open_dev(dev_id);
6612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (dd < 0)
6622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
6632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
6652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			"linkkeys");
6662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* textfile_del doesn't return an error when the key is not found */
6682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	str = textfile_caseget(filename, dstaddr);
6692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	paired = str ? TRUE : FALSE;
6702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_free(str);
6712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!paired)
6732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
6742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* Delete the link key from storage */
6762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	textfile_casedel(filename, dstaddr);
6772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* Delete the link key from the Bluetooth chip */
6792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	hci_delete_stored_link_key(dd, &device->bdaddr, 0, HCI_REQ_TIMEOUT);
6802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* Send the HCI disconnect command */
682c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (device->handle) {
683c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		int err = hci_disconnect(dd, htobs(device->handle),
6842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					HCI_OE_USER_ENDED_CONNECTION,
6852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					HCI_REQ_TIMEOUT);
6862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (err < 0)
6872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			error("Disconnect: %s (%d)", strerror(-err), -err);
6882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
6892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	hci_close_dev(dd);
6912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	paired = FALSE;
6932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	emit_property_changed(conn, device->path, DEVICE_INTERFACE,
6942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				"Paired", DBUS_TYPE_BOOLEAN, &paired);
6952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
6962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
69758c15493922277539cca11e8b55776c5d0fbccbaJohan Hedbergvoid device_remove(struct btd_device *device, DBusConnection *conn,
69858c15493922277539cca11e8b55776c5d0fbccbaJohan Hedberg						gboolean remove_bonding)
69975add5651e5dbc49c9c144acceac7e2c32d9bd16Claudio Takahasi{
7006061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	GSList *list;
7016061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	struct btd_device_driver *driver;
702f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	gchar *path = g_strdup(device->path);
703f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
704f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	debug("Removing device %s", path);
705f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
7062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding)
7072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device_cancel_bonding(device, HCI_OE_USER_ENDED_CONNECTION);
7082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
70958c15493922277539cca11e8b55776c5d0fbccbaJohan Hedberg	if (!device->temporary && remove_bonding)
7102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device_remove_bonding(device, conn);
7112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7126061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	for (list = device->drivers; list; list = list->next) {
713b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_driver_data *driver_data = list->data;
714b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		driver = driver_data->driver;
7156061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann
716e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz		driver->remove(device);
717b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		g_free(driver_data);
7186061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	}
7196061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann
720f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	g_dbus_unregister_interface(conn, path, DEVICE_INTERFACE);
72175add5651e5dbc49c9c144acceac7e2c32d9bd16Claudio Takahasi
722f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	g_free(path);
72386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
724ff296428a08dee619db1cc702146faefa91087faCidorvan Leite
725555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegint device_address_cmp(struct btd_device *device, const gchar *address)
726ff296428a08dee619db1cc702146faefa91087faCidorvan Leite{
727cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char addr[18];
728cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
729cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, addr);
730cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	return strcasecmp(addr, address);
731ff296428a08dee619db1cc702146faefa91087faCidorvan Leite}
7323d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
7333870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedbergstatic gboolean record_has_uuid(const sdp_record_t *rec,
7343870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg				const char *profile_uuid)
735f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
7363870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	sdp_list_t *pat;
737f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7383870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	for (pat = rec->pattern; pat != NULL; pat = pat->next) {
739f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		char *uuid;
7403870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		int ret;
741f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7423870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		uuid = bt_uuid2string(pat->data);
743f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!uuid)
744f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
745f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7463870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		ret = strcasecmp(uuid, profile_uuid);
747f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7483870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		g_free(uuid);
7493870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg
7503870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		if (ret == 0)
7513870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg			return TRUE;
752f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	}
753f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7543870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	return FALSE;
755f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
756f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
757f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzstatic GSList *device_match_pattern(struct btd_device *device,
758878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg					const char *match_uuid,
759f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					GSList *profiles)
760f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
761f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *l, *uuids = NULL;
762f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
763f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (l = profiles; l; l = l->next) {
764878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg		char *profile_uuid = l->data;
765f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		const sdp_record_t *rec;
7663bb7c1527ce3ec67127200b54a8fbc01a196ebadJohan Hedberg
767878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg		rec = btd_device_get_record(device, profile_uuid);
768f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!rec)
769f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
770f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
771a01801fd21056ef6f7fffc6a205b6c2b9e99899fJohan Hedberg		if (record_has_uuid(rec, match_uuid))
772878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg			uuids = g_slist_append(uuids, profile_uuid);
773cdfe8a8246013031f55c647092e41adbb29ace81Johan Hedberg	}
774f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
775f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	return uuids;
776f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
777f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
778f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzstatic GSList *device_match_driver(struct btd_device *device,
779f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					struct btd_device_driver *driver,
780f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					GSList *profiles)
781f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann{
7826061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	const char **uuid;
783f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *uuids = NULL;
784f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
785f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (uuid = driver->uuids; *uuid; uuid++) {
786f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		GSList *match;
787f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7889b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz		/* skip duplicated uuids */
7899b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz		if (g_slist_find_custom(uuids, *uuid,
7909b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz				(GCompareFunc) strcasecmp))
7919b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz			continue;
7929b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz
793f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		/* match profile driver */
794f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		match = g_slist_find_custom(profiles, *uuid,
795f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					(GCompareFunc) strcasecmp);
796f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (match) {
797f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			uuids = g_slist_append(uuids, match->data);
798f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
799f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		}
800f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
801f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		/* match pattern driver */
802f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		match = device_match_pattern(device, *uuid, profiles);
803a01801fd21056ef6f7fffc6a205b6c2b9e99899fJohan Hedberg		for (; match; match = match->next)
804f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			uuids = g_slist_append(uuids, match->data);
805f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	}
806f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
807f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	return uuids;
808f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
809f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
810f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzvoid device_probe_drivers(struct btd_device *device, GSList *profiles)
811f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
812f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *list;
813f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	int err;
814f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
815f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	debug("Probe drivers for %s", device->path);
816f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
817c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	for (list = device_drivers; list; list = list->next) {
818e0863545e6239ac338fa7fbe9647a5748a60b436Marcel Holtmann		struct btd_device_driver *driver = list->data;
819f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		GSList *probe_uuids;
820f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		struct btd_driver_data *driver_data;
821f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
822f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		probe_uuids = device_match_driver(device, driver, profiles);
8234b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode
824f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!probe_uuids)
825f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
826081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz
827f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		driver_data = g_new0(struct btd_driver_data, 1);
828b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
829f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		err = driver->probe(device, probe_uuids);
830f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (err < 0) {
831f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			error("probe failed with driver %s for device %s",
832f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					driver->name, device->path);
833b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
834f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			g_free(driver_data);
835548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			g_slist_free(probe_uuids);
836f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
837f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann		}
838f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
839f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		driver_data->driver = driver;
840f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		device->drivers = g_slist_append(device->drivers, driver_data);
841f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		g_slist_free(probe_uuids);
842f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	}
84336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
844f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (list = profiles; list; list = list->next) {
845c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		GSList *l = g_slist_find_custom(device->uuids, list->data,
846548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg							(GCompareFunc) strcasecmp);
847c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		if (l)
848c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann			continue;
849c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann
85036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		device->uuids = g_slist_insert_sorted(device->uuids,
8510e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg							g_strdup(list->data),
8520e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg							(GCompareFunc) strcasecmp);
853548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	}
854548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
855548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (device->tmp_records) {
856548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		sdp_list_free(device->tmp_records,
857548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg				(sdp_free_func_t) sdp_record_free);
858548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		device->tmp_records = NULL;
859c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann	}
86036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
86136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
86299bc055edc4b9ba8ccda791757a6439fb03ff8f2Marcel Holtmannstatic void device_remove_drivers(struct btd_device *device, GSList *uuids)
86336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
86418614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
865352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg	GSList *list, *next;
866cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
8672a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
868548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	sdp_list_t *records;
8692a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
8702a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
871cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
872cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
87336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
874548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	records = read_records(&src, &device->bdaddr);
875548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
87636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	debug("Remove drivers for %s", device->path);
87736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
878352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg	for (list = device->drivers; list; list = next) {
879b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_driver_data *driver_data = list->data;
880b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_device_driver *driver = driver_data->driver;
88136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		const char **uuid;
88236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
883352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg		next = list->next;
884352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg
88536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		for (uuid = driver->uuids; *uuid; uuid++) {
8869b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			sdp_record_t *rec;
88736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
8889b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			if (!g_slist_find_custom(uuids, *uuid,
8899b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz					(GCompareFunc) strcasecmp))
89036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz				continue;
89136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
8920e9c10ab506becad2ce0e323ff77813ecb8ce5d8Johan Hedberg			debug("UUID %s was removed from device %s", *uuid, dstaddr);
893548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
894e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz			driver->remove(device);
89536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			device->drivers = g_slist_remove(device->drivers,
896b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode								driver_data);
897b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode			g_free(driver_data);
898b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
899548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			rec = find_record_in_list(records, *uuid);
9009b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			if (!rec)
9012d370d5d678973644c2c3c75b22d5f24b7a2c638Johan Hedberg				break;
9029b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz
903cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode			delete_record(srcaddr, dstaddr, rec->handle);
904548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
905548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			records = sdp_list_remove(records, rec);
906548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			sdp_record_free(rec);
9072d370d5d678973644c2c3c75b22d5f24b7a2c638Johan Hedberg
9082d370d5d678973644c2c3c75b22d5f24b7a2c638Johan Hedberg			break;
90936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		}
91036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
91136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
912548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (records)
913548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		sdp_list_free(records, (sdp_free_func_t) sdp_record_free);
914548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
91536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (list = uuids; list; list = list->next)
91636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		device->uuids = g_slist_remove(device->uuids, list->data);
917f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann}
918f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
919bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmannstatic void iter_append_record(DBusMessageIter *dict, uint32_t handle,
920bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann							const char *record)
921bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann{
922bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	DBusMessageIter entry;
923bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
924bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
925bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann							NULL, &entry);
926bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
927bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_append_basic(&entry, DBUS_TYPE_UINT32, &handle);
928bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
929bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &record);
930bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
931bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_close_container(dict, &entry);
932bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann}
933bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
934730775d1226a30c37ff551955f093ddfcd18e600Claudio Takahasistatic void append_and_grow_string(void *data, const char *str)
935c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz{
936c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	sdp_buf_t *buff = data;
937c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	int len;
938c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
939c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	len = strlen(str);
940c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
941c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	if (!buff->data) {
942c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->data = malloc(DEFAULT_XML_BUF_SIZE);
943c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		if (!buff->data)
944c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz			return;
945c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->buf_size = DEFAULT_XML_BUF_SIZE;
946c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	}
947c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
948c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	/* Grow string */
949c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	while (buff->buf_size < (buff->data_size + len + 1)) {
950c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		void *tmp;
951c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		uint32_t new_size;
952c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
953c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		/* Grow buffer by a factor of 2 */
954c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		new_size = (buff->buf_size << 1);
955c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
956c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		tmp = realloc(buff->data, new_size);
957c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		if (!tmp)
958c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz			return;
959c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
960c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->data = tmp;
961c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->buf_size = new_size;
962c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	}
963c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
964c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	/* Include the NULL character */
965c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	memcpy(buff->data + buff->data_size, str, len + 1);
966c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	buff->data_size += len;
967c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz}
968c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
9691e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentzstatic void discover_device_reply(struct browse_req *req, sdp_list_t *recs)
9701e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz{
9711e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	DBusMessage *reply;
9721e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	DBusMessageIter iter, dict;
9731e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	sdp_list_t *seq;
9741e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9751e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	reply = dbus_message_new_method_return(req->msg);
9761e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	if (!reply)
9771e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		return;
9781e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9791e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
9801e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9811e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
9821e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
9831e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_STRING_AS_STRING
9841e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
9851e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9861e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
9871e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
9881e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		sdp_buf_t result;
9891e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9901e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		if (!rec)
9911e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			break;
9921e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9931e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		memset(&result, 0, sizeof(sdp_buf_t));
9941e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9951e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		convert_sdp_record_to_xml(rec, &result,
9961e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz				append_and_grow_string);
9971e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
9981e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		if (result.data) {
9991e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			const char *val = (char *) result.data;
10001e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			iter_append_record(&dict, rec->handle, val);
10011e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			free(result.data);
10021e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		}
10031e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	}
10041e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10051e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
10061e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
1007a5883ecb1aa94b09bcf0e7ce4184d262027c5939Johan Hedberg	g_dbus_send_message(req->conn, reply);
10081e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz}
10091e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
101017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergstatic void services_changed(struct btd_device *device)
10113d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
1012533655873c4978091edf3698b20d2b96c43dafc8Johan Hedberg	DBusConnection *conn = get_dbus_connection();
10133d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	char **uuids;
10143d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	GSList *l;
101536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	int i;
10163d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
101736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
101836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
101936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		uuids[i] = l->data;
102036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
102158f06324289d7d343a52a9104d02121cb8db1047Johan Hedberg	emit_array_property_changed(conn, device->path, DEVICE_INTERFACE,
102258f06324289d7d343a52a9104d02121cb8db1047Johan Hedberg					"UUIDs", DBUS_TYPE_STRING, &uuids);
102336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
102436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(uuids);
102536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
102636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
10278b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedbergstatic int rec_cmp(const void *a, const void *b)
10288b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg{
10298b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r1 = a;
10308b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r2 = b;
10318b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
10328b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	return r1->handle - r2->handle;
10338b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg}
10348b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
103536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentzstatic void update_services(struct browse_req *req, sdp_list_t *recs)
103636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
1037555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
103818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
103936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	sdp_list_t *seq;
1040cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
10412a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
10422a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
10432a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
1044cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
1045cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
10463d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
104736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
10483d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
104936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_t *svcclass = NULL;
10500dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		gchar *profile_uuid;
105136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		GSList *l;
10523d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
10533d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		if (!rec)
10543d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz			break;
10553d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
105636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (sdp_get_service_classes(rec, &svcclass) < 0)
105736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
105836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
105936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		/* Extract the first element and skip the remainning */
10600dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		profile_uuid = bt_uuid2string(svcclass->data);
10610dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		if (!profile_uuid) {
1062aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg			sdp_list_free(svcclass, free);
106336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
1064aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg		}
106536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
10660dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		if (!strcasecmp(profile_uuid, PNP_UUID)) {
1067fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			uint16_t source, vendor, product, version;
1068e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			sdp_data_t *pdlist;
1069e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1070fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID_SOURCE);
1071fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			source = pdlist ? pdlist->val.uint16 : 0x0000;
1072fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann
1073e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
1074e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			vendor = pdlist ? pdlist->val.uint16 : 0x0000;
1075e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1076e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
1077e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			product = pdlist ? pdlist->val.uint16 : 0x0000;
1078e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1079e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
1080e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			version = pdlist ? pdlist->val.uint16 : 0x0000;
1081e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1082fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			if (source || vendor || product || version)
1083fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann				store_device_id(srcaddr, dstaddr, source,
1084fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann						vendor, product, version);
1085e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse		}
1086e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
108737a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg		/* Check for duplicates */
1088981f4416220e01a3eab92aa3c8d03c16dcad450dJohan Hedberg		if (sdp_list_find(req->records, rec, rec_cmp)) {
10890dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			g_free(profile_uuid);
1090aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg			sdp_list_free(svcclass, free);
109137a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg			continue;
1092981f4416220e01a3eab92aa3c8d03c16dcad450dJohan Hedberg		}
109337a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
1094cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		store_record(srcaddr, dstaddr, rec);
109537a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
1096681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		/* Copy record */
1097204180c7dc2e20b9b701275a3fefb52707720f54Luiz Augusto von Dentz		req->records = sdp_list_append(req->records, sdp_copy_record(rec));
1098681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
10990dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		l = g_slist_find_custom(device->uuids, profile_uuid,
1100c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann							(GCompareFunc) strcmp);
110136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (!l)
11020dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			req->profiles_added =
11030dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg					g_slist_append(req->profiles_added,
11040dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg							profile_uuid);
110536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		else {
11060dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			req->profiles_removed =
11070dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg					g_slist_remove(req->profiles_removed,
11080dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg							l->data);
11090dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			g_free(profile_uuid);
11103d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		}
11113d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
111236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_free(svcclass, free);
11133d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	}
111436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
111536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
111617541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergstatic void store_profiles(struct btd_device *device)
111736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
111818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
1119cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
112036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	char *str;
11213d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
11222a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
11233d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
112436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	if (!device->uuids) {
1125cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		write_device_profiles(&src, &device->bdaddr, "");
112636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		return;
112736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
112836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
112936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	str = bt_list2string(device->uuids);
1130cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	write_device_profiles(&src, &device->bdaddr, str);
113136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(str);
113236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
113336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
1134a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentzstatic void browse_req_free(struct browse_req *req)
1135a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz{
1136a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	struct btd_device *device = req->device;
1137a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1138a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	device->discov_active = 0;
1139a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1140a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (device->discov_requestor) {
1141a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		g_dbus_remove_watch(req->conn, device->discov_listener);
1142a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		device->discov_listener = 0;
1143a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		g_free(device->discov_requestor);
1144a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		device->discov_requestor = NULL;
1145a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	}
1146a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1147a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (req->msg)
1148a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		dbus_message_unref(req->msg);
1149a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (req->conn)
1150a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		dbus_connection_unref(req->conn);
11510dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	g_slist_foreach(req->profiles_added, (GFunc) g_free, NULL);
11520dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	g_slist_free(req->profiles_added);
11530dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	g_slist_free(req->profiles_removed);
1154a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (req->records)
1155a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
1156a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	g_free(req);
1157a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz}
1158a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1159da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void search_cb(sdp_list_t *recs, int err, gpointer user_data)
116036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
116136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	struct browse_req *req = user_data;
1162555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
116336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	DBusMessage *reply;
11642a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
1165681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	if (err < 0) {
1166681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		error("%s: error updating services: %s (%d)",
1167681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz				device->path, strerror(-err), -err);
116836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		goto proceed;
1169681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	}
117036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
117136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	update_services(req, recs);
117236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
11730dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (!req->profiles_added && !req->profiles_removed) {
1174e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		debug("%s: No service update", device->path);
117536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		goto proceed;
1176681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	}
11772efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
1178548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (device->tmp_records && req->records) {
1179548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		sdp_list_free(device->tmp_records, (sdp_free_func_t) sdp_record_free);
1180548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		device->tmp_records = req->records;
1181548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		req->records = NULL;
1182548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	}
1183548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
118436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Probe matching drivers for services added */
11850dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (req->profiles_added)
11860dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		device_probe_drivers(device, req->profiles_added);
11872efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
118836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Remove drivers for services removed */
11890dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (req->profiles_removed)
11900dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		device_remove_drivers(device, req->profiles_removed);
11912efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
119236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Propagate services changes */
119317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	services_changed(req->device);
1194f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
11957b67507336f98dda5523902806dd2e33684fab6bLuiz Augusto von Dentzproceed:
1196681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	/* Store the device's profiles in the filesystem */
119717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	store_profiles(device);
1198681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
11992ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg	if (!req->msg)
12002ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg		goto cleanup;
12012ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg
1202438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz	if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
1203438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz					"DiscoverServices")) {
1204438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz		discover_device_reply(req, req->records);
1205438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz		goto cleanup;
1206438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz	}
1207438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz
12083d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	/* Reply create device request */
12093d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	reply = dbus_message_new_method_return(req->msg);
12103d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	if (!reply)
12111e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		goto cleanup;
12123d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
12133d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &device->path,
1214a2529a9b417959a52f5d501cba4bcaf32caf6964Marcel Holtmann							DBUS_TYPE_INVALID);
12153d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1216a5883ecb1aa94b09bcf0e7ce4184d262027c5939Johan Hedberg	g_dbus_send_message(req->conn, reply);
12173d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
12181e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentzcleanup:
1219a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	browse_req_free(req);
1220da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
1221da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1222da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
1223da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
1224da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct browse_req *req = user_data;
1225da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_device *device = req->device;
1226da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
1227cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
1228da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	uuid_t uuid;
1229da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
12300dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	/* If we have a valid response and req->search_uuid == 2, then
12310dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	   L2CAP UUID & PNP searching was successful -- we are done */
12320dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (err < 0 || (req->search_uuid == 2 && req->records))
1233da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		goto done;
1234da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1235da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	update_services(req, recs);
1236da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1237da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	adapter_get_address(adapter, &src);
1238da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1239da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	/* Search for mandatory uuids */
12407d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse	if (uuid_list[req->search_uuid]) {
12417d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
1242c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		bt_search_service(&src, &device->bdaddr, &uuid,
1243c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann						browse_cb, user_data, NULL);
1244da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		return;
1245da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	}
1246da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1247da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzdone:
1248da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	search_cb(recs, err, user_data);
1249da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
1250da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
125169adac833c5633714b84bf840c75aa814193b8a6Johan Hedbergstatic void init_browse(struct browse_req *req, gboolean reverse)
1252da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
1253da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	GSList *l;
1254da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
125569adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	/* If we are doing reverse-SDP don't try to detect removed profiles
125669adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 * since some devices hide their service records while they are
125769adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 * connected
125869adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 */
125969adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	if (reverse)
126069adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		return;
126169adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg
1262da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	for (l = req->device->uuids; l; l = l->next)
12630dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		req->profiles_removed = g_slist_append(req->profiles_removed,
1264da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz						l->data);
12653d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
12663d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1267555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeint device_browse(struct btd_device *device, DBusConnection *conn,
126869adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg			DBusMessage *msg, uuid_t *search, gboolean reverse)
12693d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
127018614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
12713d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	struct browse_req *req;
1272cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
1273d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	uuid_t uuid;
1274da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	bt_callback_t cb;
1275a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	int err;
12762a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
12771af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg	if (device->discov_active)
12781af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg		return -EBUSY;
12791af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg
12802a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
12813d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
12823d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req = g_new0(struct browse_req, 1);
1283438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz
1284d2244495dfc50c22ce275f6194c19d3293de70cbJohan Hedberg	if (conn == NULL)
1285d2244495dfc50c22ce275f6194c19d3293de70cbJohan Hedberg		conn = get_dbus_connection();
1286438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz
1287d2244495dfc50c22ce275f6194c19d3293de70cbJohan Hedberg	req->conn = dbus_connection_ref(conn);
12883d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req->device = device;
12893d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1290a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (search) {
1291040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		memcpy(&uuid, search, sizeof(uuid_t));
1292da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = search_cb;
1293a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	} else {
12947d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
129569adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		init_browse(req, reverse);
1296da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = browse_cb;
1297a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	}
1298d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
129995e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz	device->discov_active = 1;
1300d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg
1301d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg	if (msg) {
13025c6426eff87049c9f8e49877f650772840907239Luiz Augusto von Dentz		req->msg = dbus_message_ref(msg);
1303d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		device->discov_requestor = g_strdup(dbus_message_get_sender(msg));
1304d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		/* Track the request owner to cancel it
1305d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		 * automatically if the owner exits */
1306d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		device->discov_listener = g_dbus_add_disconnect_watch(conn,
130795e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						dbus_message_get_sender(msg),
130895e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						discover_services_req_exit,
130995e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						device, NULL);
1310d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg	}
131195e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz
1312a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	err = bt_search_service(&src, &device->bdaddr,
1313a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz				&uuid, cb, req, NULL);
1314a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (err < 0)
1315a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		browse_req_free(req);
1316a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1317a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	return err;
13183d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
131924cce397c3479e95f3e525da9285234fbafd2984Marcel Holtmann
132018614bd2b008cb9f3879990883c569c37b72f195Alok Barsodestruct btd_adapter *device_get_adapter(struct btd_device *device)
1321dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode{
1322dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	if (!device)
1323dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode		return NULL;
1324dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
1325dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	return device->adapter;
1326dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode}
1327dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
132819ce4933f3dadf3b04a2a9bd84d66d750cc010c3Alok Barsodevoid device_get_address(struct btd_device *device, bdaddr_t *bdaddr)
1329aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode{
1330cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bacpy(bdaddr, &device->bdaddr);
1331aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode}
1332aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode
1333555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeconst gchar *device_get_path(struct btd_device *device)
133446fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode{
133546fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	if (!device)
133646fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode		return NULL;
133746fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
133846fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	return device->path;
133946fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode}
134046fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
1341555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestruct agent *device_get_agent(struct btd_device *device)
1342a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode{
1343a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode	if (!device)
1344a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode		return NULL;
1345a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
1346a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode	return  device->agent;
1347a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode}
1348a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
1349555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_agent(struct btd_device *device, struct agent *agent)
1350d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode{
1351d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode	if (!device)
1352d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode		return;
1353d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode
1354d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode	device->agent = agent;
1355d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode}
1356d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode
1357555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_busy(struct btd_device *device)
13589f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode{
13599f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode	return device->discov_active ? TRUE : FALSE;
13609f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode}
13619f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode
1362555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_temporary(struct btd_device *device)
1363f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode{
1364f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode	return device->temporary;
1365f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode}
1366f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode
1367555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_temporary(struct btd_device *device, gboolean temporary)
1368595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode{
1369595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode	if (!device)
1370595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode		return;
1371595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode
1372595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode	device->temporary = temporary;
1373595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode}
1374595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode
1375555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_cap(struct btd_device *device, uint8_t cap)
1376491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode{
1377491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode	if (!device)
1378491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode		return;
1379491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode
1380491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode	device->cap = cap;
1381491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode}
1382491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode
1383f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberguint8_t device_get_cap(struct btd_device *device)
1384f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg{
1385f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg	return device->cap;
1386f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg}
1387f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg
1388555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_auth(struct btd_device *device, uint8_t auth)
138929227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode{
139029227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode	if (!device)
139129227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode		return;
139229227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode
139329227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode	device->auth = auth;
139429227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode}
139529227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode
1396555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeuint8_t device_get_auth(struct btd_device *device)
13972203f153c53189ec1c30df99b717e035681196e6Alok Barsode{
13982203f153c53189ec1c30df99b717e035681196e6Alok Barsode	return device->auth;
13992203f153c53189ec1c30df99b717e035681196e6Alok Barsode}
1400c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
1401013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedbergstatic gboolean start_discovery(gpointer user_data)
1402013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
1403013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	struct btd_device *device = user_data;
1404013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
140569adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	device_browse(device, NULL, NULL, NULL, TRUE);
1406013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
1407013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	device->discov_timer = 0;
1408013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
1409013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	return FALSE;
1410013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
1411013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
14122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von DentzDBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
1413013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
14142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (status) {
14152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x00: /* success */
14162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_method_return(msg);
14172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x04: /* page timeout */
14192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x08: /* connection timeout */
14202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x10: /* connection accept timeout */
14212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x22: /* LMP response timeout */
14222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x28: /* instant passed - is this a timeout? */
14232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationTimeout",
14252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Timeout");
14262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x17: /* too frequent pairing attempts */
14272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".RepeatedAttempts",
14292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Repeated Attempts");
14302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x06:
14322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */
14332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationRejected",
14352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Rejected");
14362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x07: /* memory capacity */
14382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x09: /* connection limit */
14392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0a: /* synchronous connection limit */
14402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0d: /* limited resources */
14412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x13: /* user ended the connection */
14422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x14: /* terminated due to low resources */
14432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationCanceled",
14452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Canceled");
14462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x05: /* authentication failure */
14482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0E: /* rejected due to security reasons - is this auth failure? */
14492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x25: /* encryption mode not acceptable - is this auth failure? */
14502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x26: /* link key cannot be changed - is this auth failure? */
14512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x29: /* pairing with unit key unsupported - is this auth failure? */
14522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x2f: /* insufficient security - is this auth failure? */
14532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	default:
14542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationFailed",
14562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Failed");
14572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
14582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
14592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void bonding_request_free(struct bonding_req *bonding)
14612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
14622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device;
14632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding)
14652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
14662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->listener_id)
14682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_dbus_remove_watch(bonding->conn, bonding->listener_id);
146968b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
14702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->msg)
14712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		dbus_message_unref(bonding->msg);
14722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->conn)
14742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		dbus_connection_unref(bonding->conn);
14752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->io_id)
14772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_source_remove(bonding->io_id);
14782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->io)
14802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_io_channel_unref(bonding->io);
14812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device = bonding->device;
14832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device && device->agent) {
14852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		agent_destroy(device->agent, FALSE);
14862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->agent = NULL;
14872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
14882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding = NULL;
14902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_free(bonding);
14912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
14922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void device_set_paired(struct btd_device *device, gboolean value)
14942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
14952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusConnection *conn = get_dbus_connection();
149668b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
1497c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Paired",
14982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				DBUS_TYPE_BOOLEAN, &value);
14992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
15002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void device_agent_removed(struct agent *agent, void *user_data)
15022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
15032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = user_data;
15042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device_set_agent(device, NULL);
15062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
15082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->authr->agent = NULL;
15092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
15102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic struct bonding_req *bonding_request_new(DBusConnection *conn,
15122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						DBusMessage *msg,
15132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						struct btd_device *device,
15142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						const char *agent_path,
15152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						uint8_t capability)
15162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
15172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
15182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	const char *name = dbus_message_get_sender(msg);
15192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
15202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: requesting bonding", device->path);
15222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent_path)
15242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto proceed;
15252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	agent = agent_create(device->adapter, name, agent_path,
15272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					capability,
15282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device_agent_removed,
15292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device);
15302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent) {
15312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Unable to create a new agent");
15322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return NULL;
15332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->agent = agent;
15362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("Temporary agent registered for %s at %s:%s",
15382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			device->path, name, agent_path);
15392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzproceed:
15412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding = g_new0(struct bonding_req, 1);
15432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->conn = dbus_connection_ref(conn);
15452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->msg = dbus_message_ref(msg);
15462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return bonding;
15482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
15492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic gboolean create_bonding_io_cb(GIOChannel *io, GIOCondition cond,
15512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					struct btd_device *device)
15522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
15532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct hci_request rq;
15542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth_requested_cp cp;
15552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	evt_cmd_status rp;
15562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct l2cap_conninfo cinfo;
15572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	socklen_t len;
15582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	int sk, dd, ret;
15592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15605331a26b8a3c2d69d30a4334e023238db197080bJohan Hedberg	if (!device->bonding) {
15612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_io_channel_close(io);
15622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return FALSE;
15632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (cond & G_IO_NVAL) {
15662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (device->bonding) {
15672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			DBusMessage *reply;
15682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			reply = new_authentication_return(device->bonding->msg,
15702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							0x09);
15712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			g_dbus_send_message(device->bonding->conn, reply);
15722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		}
15732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto cleanup;
15752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (cond & (G_IO_HUP | G_IO_ERR)) {
15782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		debug("Hangup or error on bonding IO channel");
15792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (device->bonding)
15812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			error_connection_attempt_failed(device->bonding->conn,
15822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							device->bonding->msg,
15832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							ENETDOWN);
15842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
15862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	sk = g_io_channel_unix_get_fd(io);
15892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	len = sizeof(ret);
15912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
15922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Can't get socket error: %s (%d)",
15932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				strerror(errno), errno);
15942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
15952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				errno);
15962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
15972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (ret != 0) {
16002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (device->bonding)
16012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			error_connection_attempt_failed(device->bonding->conn,
16022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							device->bonding->msg,
16032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							ret);
16042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	len = sizeof(cinfo);
16082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) {
16092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Can't get connection info: %s (%d)",
16102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				strerror(errno), errno);
16112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
16122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				errno);
16132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dd = hci_open_dev(adapter_get_dev_id(device->adapter));
16172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (dd < 0) {
16182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		DBusMessage *reply = no_such_adapter(device->bonding->msg);
16192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_dbus_send_message(device->bonding->conn, reply);
16202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	memset(&rp, 0, sizeof(rp));
16242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	memset(&cp, 0, sizeof(cp));
16262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	cp.handle = htobs(cinfo.hci_handle);
16272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	memset(&rq, 0, sizeof(rq));
16292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.ogf    = OGF_LINK_CTL;
16302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.ocf    = OCF_AUTH_REQUESTED;
16312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.cparam = &cp;
16322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.clen   = AUTH_REQUESTED_CP_SIZE;
16332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.rparam = &rp;
16342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.rlen   = EVT_CMD_STATUS_SIZE;
16352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.event  = EVT_CMD_STATUS;
16362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (hci_send_req(dd, &rq, HCI_REQ_TIMEOUT) < 0) {
16382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Unable to send HCI request: %s (%d)",
16392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					strerror(errno), errno);
16402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
16412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				errno);
16422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		hci_close_dev(dd);
16432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (rp.status) {
16472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("HCI_Authentication_Requested failed with status 0x%02x",
16482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				rp.status);
16492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
16502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				bt_error(rp.status));
16512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		hci_close_dev(dd);
16522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	hci_close_dev(dd);
16562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding->io_id = g_io_add_watch(io,
16582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						G_IO_NVAL | G_IO_HUP | G_IO_ERR,
16592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						(GIOFunc) create_bonding_io_cb,
16602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						device);
16612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return FALSE;
16632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzfailed:
16652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_io_channel_close(io);
16662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzcleanup:
16682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding->io_id = 0;
16692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding_request_free(device->bonding);
16702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return FALSE;
16722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
16732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void create_bond_req_exit(DBusConnection *conn, void *user_data)
16752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
16762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = user_data;
16772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: requestor exited before bonding was completed", device->path);
16792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
16812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device_cancel_authentication(device);
16822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding) {
16842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->bonding->listener_id = 0;
16852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_io_channel_close(device->bonding->io);
16862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		bonding_request_free(device->bonding);
16872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
16892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1690f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedbergstatic int l2raw_connect(const bdaddr_t *src, const bdaddr_t *dst,
1691f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg						gboolean *auth_required)
1692f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg{
1693f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	struct sockaddr_l2 addr;
1694f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	long arg;
1695d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	int sk, err, opt;
1696f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1697f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
1698f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (sk < 0) {
1699f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't create socket: %s (%d)", strerror(errno), errno);
1700f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		return sk;
1701f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1702f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1703f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	memset(&addr, 0, sizeof(addr));
1704f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	addr.l2_family = AF_BLUETOOTH;
1705f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	bacpy(&addr.l2_bdaddr, src);
1706f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1707f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1708f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't bind socket: %s (%d)", strerror(errno), errno);
1709f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1710f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1711f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1712d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
1713f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1714d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	err = setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt));
1715d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	if (err < 0) {
1716d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg		error("setsockopt: %s (%d)", strerror(errno), errno);
1717d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg		goto failed;
1718d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	}
1719f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1720f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	arg = fcntl(sk, F_GETFL);
1721f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (arg < 0) {
1722f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't get file flags: %s (%d)", strerror(errno), errno);
1723f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1724f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1725f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1726f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	arg |= O_NONBLOCK;
1727f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (fcntl(sk, F_SETFL, arg) < 0) {
1728f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't set file flags: %s (%d)", strerror(errno), errno);
1729f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1730f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1731f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1732f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	memset(&addr, 0, sizeof(addr));
1733f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	addr.l2_family = AF_BLUETOOTH;
1734f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	bacpy(&addr.l2_bdaddr, dst);
1735f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1736f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1737f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		if (errno == EAGAIN || errno == EINPROGRESS)
1738f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg			return sk;
1739f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't connect socket: %s (%d)", strerror(errno), errno);
1740f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1741f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1742f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1743d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	if (auth_required)
1744d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg		*auth_required = TRUE;
1745d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg
1746f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	return sk;
1747f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1748f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedbergfailed:
1749f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	close(sk);
1750f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	return -1;
1751f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg}
1752f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
17532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von DentzDBusMessage *device_create_bonding(struct btd_device *device,
17542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusConnection *conn,
17552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusMessage *msg,
17562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					const char *agent_path,
17572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					uint8_t capability)
17582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
17592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char filename[PATH_MAX + 1];
17602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char *str, srcaddr[18], dstaddr[18];
17612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
17622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
17632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bdaddr_t src;
1764f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	int sk;
1765f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	gboolean auth_required;
17662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	adapter_get_address(adapter, &src);
17682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&src, srcaddr);
17692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&device->bdaddr, dstaddr);
17702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding)
17722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return in_progress(msg, "Bonding in progress");
17732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* check if a link key already exists */
17752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
17762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			"linkkeys");
17772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	str = textfile_caseget(filename, dstaddr);
17792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (str) {
17802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		free(str);
17812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return g_dbus_create_error(msg,
17822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				ERROR_INTERFACE ".AlreadyExists",
17832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				"Bonding already exists");
17842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
17852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1786dd10ec5d830d2e2187f93bd2d7e60be947335f0bJohan Hedberg
1787f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	sk = l2raw_connect(&src, &device->bdaddr, &auth_required);
17882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (sk < 0)
17892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return g_dbus_create_error(msg,
17902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				ERROR_INTERFACE ".ConnectionAttemptFailed",
17912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				"Connection attempt failed");
17922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding = bonding_request_new(conn, msg, device, agent_path,
17942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					capability);
17952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding) {
17962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		close(sk);
17972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return NULL;
17982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
17992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1800f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	bonding->auth_required = auth_required;
1801dd10ec5d830d2e2187f93bd2d7e60be947335f0bJohan Hedberg
18022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->io = g_io_channel_unix_new(sk);
18032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->io_id = g_io_add_watch(bonding->io,
18042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
18052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					(GIOFunc) create_bonding_io_cb,
18062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device);
18072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->listener_id = g_dbus_add_disconnect_watch(conn,
18092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						dbus_message_get_sender(msg),
18102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						create_bond_req_exit, device,
18112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						NULL);
18122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding = bonding;
18142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->device = device;
18152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return NULL;
18172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
18182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzvoid device_bonding_complete(struct btd_device *device, uint8_t status)
18202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
18212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
18222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (status)
18242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
18252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->temporary = FALSE;
182768b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
1828bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	g_free(device->authr);
1829bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	device->authr = NULL;
1830bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
1831bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	if (device->renewed_key)
1832bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg		return;
1833bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
183468b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	/* If we were initiators start service discovery immediately.
183568b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * However if the other end was the initator wait a few seconds
183668b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * before SDP. This is due to potential IOP issues if the other
183768b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * end starts doing SDP at the same time as us */
1838e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg	if (bonding) {
1839e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		/* If we are initiators remove any discovery timer and just
1840e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		 * start discovering services directly */
1841e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		if (device->discov_timer) {
1842e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg			g_source_remove(device->discov_timer);
1843e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg			device->discov_timer = 0;
1844e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		}
1845e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg
18462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device_browse(device, bonding->conn, bonding->msg,
18472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				NULL, FALSE);
1848bdf140bd02cee6c39ebb8c6d71ac1d4f6f7eaa07Johan Hedberg	} else if (!device->discov_active && !device->discov_timer &&
1849bdf140bd02cee6c39ebb8c6d71ac1d4f6f7eaa07Johan Hedberg			main_opts.reverse_sdp) {
18502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		/* If we are not initiators and there is no currently active
18512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		 * discovery or discovery timer, set the discovery timer */
18525fe418c129889a18df976050c68a0dab28dc766cMarcel Holtmann		debug("setting timer for reverse service discovery");
18532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->discov_timer = g_timeout_add_seconds(DISCOVERY_TIMER,
18542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						start_discovery,
18552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						device);
1856e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg	}
1857e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg
18582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device_set_paired(device, TRUE);
18592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding_request_free(bonding);
18612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return;
18632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzfailed:
18652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device_cancel_bonding(device, status);
18672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
18682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzgboolean device_is_bonding(struct btd_device *device, const char *sender)
18702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
18712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
18722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!device->bonding)
18742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return FALSE;
18752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!sender)
18772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return TRUE;
18782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return g_str_equal(sender, dbus_message_get_sender(bonding->msg));
18802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1881e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
18822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzvoid device_cancel_bonding(struct btd_device *device, uint8_t status)
18832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
18842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
18852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusMessage *reply;
18862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding)
18882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
18892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: canceling bonding request", device->path);
18912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
18932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device_cancel_authentication(device);
18942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	reply = new_authentication_return(bonding->msg, status);
18962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_dbus_send_message(bonding->conn, reply);
18972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding_request_free(bonding);
18992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,
19022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			void *data)
19032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
19052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
19062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
19082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
19092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
19102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_pincode_cb) auth->cb)(agent, err, pincode, device);
19122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
19142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void confirm_cb(struct agent *agent, DBusError *err, void *data)
19172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
19192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
19202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
19222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
19232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
19242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_cb) auth->cb)(agent, err, device);
19262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
19282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
19312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			void *data)
19322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
19342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
19352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
19372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
19382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
19392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_passkey_cb) auth->cb)(agent, err, passkey, device);
19412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
19432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzint device_request_authentication(struct btd_device *device, auth_type_t type,
19462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				uint32_t passkey, void *cb)
19472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth;
19492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
19502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	int ret;
19512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: requesting agent authentication", device->path);
19532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	agent = device->agent;
19552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent)
19572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		agent = adapter_get_agent(device->adapter);
19582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent) {
19602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("No agent available for %u request", type);
19612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return -EPERM;
19622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
19632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth = g_new0(struct authentication_req, 1);
19652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->agent = agent;
19662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->device = device;
19672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = cb;
19682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->type = type;
19692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->authr = auth;
19702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (type) {
19722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PINCODE:
19732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_request_pincode(agent, device, pincode_cb,
19742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					auth);
19752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
19762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PASSKEY:
19772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_request_passkey(agent, device, passkey_cb,
19782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					auth);
19792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
19802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_CONFIRM:
19812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_request_confirmation(agent, device, passkey,
19822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					confirm_cb, auth);
19832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
19842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_NOTIFY:
19852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_display_passkey(agent, device, passkey);
19862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
19872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_AUTO:
19882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = 0;
19892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
19902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	default:
19912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = -EINVAL;
19922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
19932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (ret < 0) {
19952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Failed requesting authentication");
19962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_free(auth);
19972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->authr = NULL;
19982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
19992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return ret;
20012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void cancel_authentication(struct authentication_req *auth)
20042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
20062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent = auth->agent;
20072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusError err;
20082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
20102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
20112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_error_init(&err);
20132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_set_error_const(&err, "org.bluez.Error.Canceled", NULL);
20142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (auth->type) {
20162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PINCODE:
20172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_pincode_cb) auth->cb)(agent, &err, NULL, device);
20182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_CONFIRM:
20202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_cb) auth->cb)(agent, &err, device);
20212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PASSKEY:
20232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
20242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_NOTIFY:
20262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_AUTO:
20272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		/* User Notify/Auto doesn't require any reply */
20282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
20302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_error_free(&err);
20322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
20332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzvoid device_cancel_authentication(struct btd_device *device)
20362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = device->authr;
20382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth)
20402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
20412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: canceling authentication request", device->path);
20432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (auth->agent)
20452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		agent_cancel(auth->agent);
20462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	cancel_authentication(auth);
20482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->authr = NULL;
20492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_free(auth);
20502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzgboolean device_is_authenticating(struct btd_device *device)
20532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return (device->authr != NULL);
2055013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
2056013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
2057bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedbergvoid device_set_renewed_key(struct btd_device *device, gboolean renewed)
2058bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg{
2059bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	device->renewed_key = renewed;
2060bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg}
2061bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
206217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergvoid btd_device_add_uuid(struct btd_device *device, const char *uuid)
206317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg{
206417541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	GSList *uuid_list;
206517541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	char *new_uuid;
206617541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
206717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	if (g_slist_find_custom(device->uuids, uuid,
206817541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg				(GCompareFunc) strcasecmp))
206917541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg		return;
207017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
207117541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	new_uuid = g_strdup(uuid);
207217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	uuid_list = g_slist_append(NULL, new_uuid);
207317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
207417541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	device_probe_drivers(device, uuid_list);
207517541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
20760e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg	g_free(new_uuid);
207717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	g_slist_free(uuid_list);
207817541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
20790e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg	store_profiles(device);
208017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	services_changed(device);
208117541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg}
208217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
2083548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedbergconst sdp_record_t *btd_device_get_record(struct btd_device *device,
2084548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg						const char *uuid)
2085548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg{
2086548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	bdaddr_t src;
2087548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2088548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (device->tmp_records)
2089548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		return find_record_in_list(device->tmp_records, uuid);
2090548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2091548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	adapter_get_address(device->adapter, &src);
2092548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2093548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	device->tmp_records = read_records(&src, &device->bdaddr);
2094548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (!device->tmp_records)
2095548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		return NULL;
2096548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2097548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	return find_record_in_list(device->tmp_records, uuid);
2098548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg}
2099548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2100c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzint btd_register_device_driver(struct btd_device_driver *driver)
2101c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
2102c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_append(device_drivers, driver);
2103c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
2104c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	return 0;
2105c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
2106c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
2107c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzvoid btd_unregister_device_driver(struct btd_device_driver *driver)
2108c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
2109c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_remove(device_drivers, driver);
2110c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
2111