device.c revision a721957f20ec79b1a19537e5c43d3a12e4286c6c
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;
90a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	char		name[248];
9118614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter	*adapter;
92ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	GSList		*uuids;
93b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode	GSList		*drivers;		/* List of driver_data */
94ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	gboolean	temporary;
95ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	struct agent	*agent;
96ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	guint		disconn_timer;
97ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	int		discov_active;		/* Service discovery active */
987c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg	char		*discov_requestor;	/* discovery requestor unique
997c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						 * name */
100ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	guint		discov_listener;
101013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	guint		discov_timer;
1022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
1032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *authr;	/* authentication request */
104ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
105ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	/* For Secure Simple Pairing */
106ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	uint8_t		cap;
107ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	uint8_t		auth;
108e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
109c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	uint16_t	handle;			/* Connection handle */
110e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
111e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	/* Whether were creating a security mode 3 connection */
112e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	gboolean	secmode3;
113548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
114548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	sdp_list_t	*tmp_records;
115bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
116bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	gboolean	renewed_key;
117ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode};
118ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
1193d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentzstruct browse_req {
1203d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	DBusConnection *conn;
1213d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	DBusMessage *msg;
122555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device;
1230dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	GSList *match_uuids;
1240dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	GSList *profiles_added;
1250dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	GSList *profiles_removed;
126681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	sdp_list_t *records;
127d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	int search_uuid;
1283d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz};
1293d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
130d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmannstatic uint16_t uuid_list[] = {
1310dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	L2CAP_UUID,
1321c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	PNP_INFO_SVCLASS_ID,
1330dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	PUBLIC_BROWSE_GROUP,
134d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	0
135d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann};
136d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
137c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzstatic GSList *device_drivers = NULL;
138c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
1392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn,
1402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						DBusMessage *msg, int err)
1412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return error_common_reply(conn, msg,
1432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			ERROR_INTERFACE ".ConnectionAttemptFailed",
1442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			err > 0 ? strerror(err) : "Connection attempt failed");
1452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic DBusHandlerResult error_failed(DBusConnection *conn,
1482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusMessage *msg, const char * desc)
1492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return error_common_reply(conn, msg, ERROR_INTERFACE ".Failed", desc);
1512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic DBusHandlerResult error_failed_errno(DBusConnection *conn,
1542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						DBusMessage *msg, int err)
1552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	const char *desc = strerror(err);
1572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return error_failed(conn, msg, desc);
1592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic inline DBusMessage *no_such_adapter(DBusMessage *msg)
1622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchAdapter",
1642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							"No such adapter");
1652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic inline DBusMessage *in_progress(DBusMessage *msg, const char *str)
1682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
1692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress", str);
1702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
172e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic void device_free(gpointer user_data)
17386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
174555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
1752f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
1762f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct agent *agent = adapter_get_agent(adapter);
177e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi
178fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite	if (device->agent)
179fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite		agent_destroy(device->agent, FALSE);
180f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
1812f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	if (agent && agent_is_busy(agent, device))
1822f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz		agent_cancel(agent);
1832f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz
184ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_foreach(device->uuids, (GFunc) g_free, NULL);
185ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_free(device->uuids);
186f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
1875d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	if (device->disconn_timer)
1885d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		g_source_remove(device->disconn_timer);
1895d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
190401374312bdc966bf386a1d89bf6cd0f74a4314cLuiz Augusto von Dentz	if (device->discov_timer)
191401374312bdc966bf386a1d89bf6cd0f74a4314cLuiz Augusto von Dentz		g_source_remove(device->discov_timer);
192401374312bdc966bf386a1d89bf6cd0f74a4314cLuiz Augusto von Dentz
19386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device->path);
19486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device);
19586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
19686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
197555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestatic gboolean device_is_paired(struct btd_device *device)
198769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz{
19918614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
200cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char filename[PATH_MAX + 1], *str;
201cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
202769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	gboolean ret;
203cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
2042a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
205cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
206cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
207cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
208769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
209769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR,
210cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode			srcaddr, "linkkeys");
211cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	str = textfile_caseget(filename, dstaddr);
212769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	ret = str ? TRUE : FALSE;
213769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	g_free(str);
214769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
215769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	return ret;
216769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz}
217769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
218e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *get_properties(DBusConnection *conn,
219e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *user_data)
2202c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
221555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
22218614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
2234e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessage *reply;
2244e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter iter;
2254e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter dict;
226cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
227cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char name[248], srcaddr[18], dstaddr[18];
2288a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi	char **uuids;
2292a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	const char *ptr;
2304e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_bool_t boolean;
2314e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	uint32_t class;
232769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	int i;
233769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	GSList *l;
2344e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
235cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
236cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
2374e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	reply = dbus_message_new_method_return(msg);
2384e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	if (!reply)
239e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return NULL;
2404e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2414e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
2424e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2434e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
2444e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
2454e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
2464e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
2474e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2484e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Address */
249cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ptr = dstaddr;
2501262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Address", DBUS_TYPE_STRING, &ptr);
2514e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2524e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Name */
253506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	ptr = NULL;
254506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	memset(name, 0, sizeof(name));
2552a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
256cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
2578a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi
258a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	if (device->name) {
259a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz		ptr = device->name;
2601262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg		dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &ptr);
2614e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	}
2624e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
263afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann	/* Alias (fallback to name or address) */
264afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann	if (read_device_alias(srcaddr, dstaddr, name, sizeof(name)) < 1) {
265afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann		if (!ptr) {
266afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann			g_strdelimit(dstaddr, ":", '-');
267afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann			ptr = dstaddr;
268afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann		}
269afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann	} else
270506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		ptr = name;
271506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
272506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	if (ptr)
2731262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg		dict_append_entry(&dict, "Alias", DBUS_TYPE_STRING, &ptr);
274506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
2754e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Class */
276cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
277e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann		const char *icon = class_to_icon(class);
278e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann
2791262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg		dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
280e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann
281e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann		if (icon)
2821262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg			dict_append_entry(&dict, "Icon",
283e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann						DBUS_TYPE_STRING, &icon);
2844e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	}
2854e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2864e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Paired */
287769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	boolean = device_is_paired(device);
2881262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Paired", DBUS_TYPE_BOOLEAN, &boolean);
2894e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2904e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Trusted */
291cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	boolean = read_trust(&src, dstaddr, GLOBAL_TRUST);
2921262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Trusted", DBUS_TYPE_BOOLEAN, &boolean);
2934e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2944e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Connected */
295c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	boolean = (device->handle != 0);
296c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN,
297c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz				&boolean);
2984e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
299ba93fb91ea81a35be0834ac395650e020a6b3fd3Claudio Takahasi	/* UUIDs */
300769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
301769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
302769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz		uuids[i] = l->data;
3033a11e84a573785024b11d89ed4f9b06e43b06ca6Johan Hedberg	dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &uuids, i);
304769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	g_free(uuids);
3054e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
30674fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz	/* Adapter */
3078a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi	ptr = adapter_get_path(adapter);
3081262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Adapter", DBUS_TYPE_OBJECT_PATH, &ptr);
30974fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz
3104e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
3114e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
312e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return reply;
3132c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
3142c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
315e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,
3167fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					const char *alias, void *data)
3177fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
318555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
31918614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
320cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
321cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
322506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	int err;
3237fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
324cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
325cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
326cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
3272a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
328cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	/* Remove alias if empty string */
329cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	err = write_device_alias(srcaddr, dstaddr,
330506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi			g_str_equal(alias, "") ? NULL : alias);
331506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	if (err < 0)
332e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return g_dbus_create_error(msg,
333e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				ERROR_INTERFACE ".Failed",
334506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi				strerror(-err));
3357fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
336c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, dbus_message_get_path(msg),
337c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DEVICE_INTERFACE, "Alias",
338c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DBUS_TYPE_STRING, &alias);
3397fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
340e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
3417fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
3427fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
343e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,
3447fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					dbus_bool_t value, void *data)
3457fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
346555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
34718614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
348cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
349cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
3502a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
351cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
352cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
353cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
3542a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
355cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	write_trust(srcaddr, dstaddr, GLOBAL_TRUST, value);
3567fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
357c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, dbus_message_get_path(msg),
358c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DEVICE_INTERFACE, "Trusted",
359c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DBUS_TYPE_BOOLEAN, &value);
3607fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
361e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
3627fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
3637fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
364e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic inline DBusMessage *invalid_args(DBusMessage *msg)
365e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi{
366e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return g_dbus_create_error(msg,
367e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			ERROR_INTERFACE ".InvalidArguments",
368e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			"Invalid arguments in method call");
369e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi}
370e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi
371e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_property(DBusConnection *conn,
372e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *data)
3732c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
3747fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter iter;
3757fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter sub;
3767fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	const char *property;
3777fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3787fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (!dbus_message_iter_init(msg, &iter))
379e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3807fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3817fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
382e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3837fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3847fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_get_basic(&iter, &property);
3857fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_next(&iter);
3867fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3877fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
388e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return invalid_args(msg);
3897fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_recurse(&iter, &sub);
3907fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3917fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (g_str_equal("Trusted", property)) {
3927fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_bool_t value;
3937fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3947fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
395e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			return invalid_args(msg);
3967fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &value);
3977fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
3987fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_trust(conn, msg, value, data);
3997fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	} else if (g_str_equal("Alias", property)) {
400506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		const char *alias;
4017fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
4027fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)
403e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi			return invalid_args(msg);
4047fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &alias);
4057fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
4067fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_alias(conn, msg, alias, data);
4077fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	}
4087fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
409e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return invalid_args(msg);
4102c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
4112c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
4121f5107e65f9786bd6b84ecfb4d84691e9b34529aMarcel Holtmannstatic void discover_services_req_exit(DBusConnection *conn, void *user_data)
413342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz{
414555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
41518614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
416cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
4172a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
4182a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
419342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
420342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	debug("DiscoverDevices requestor exited");
421342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
422cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bt_cancel_discovery(&src, &device->bdaddr);
423342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz}
424342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
42594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *discover_services(DBusConnection *conn,
42694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
42794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
428555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
42994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	const char *pattern;
430342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	int err;
431342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
432342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (device->discov_active)
433342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
4347c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						"Discover in progress");
43594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
43694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
43794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						DBUS_TYPE_INVALID) == FALSE)
438342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		goto fail;
43994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
440a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (strlen(pattern) == 0) {
44169adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		err = device_browse(device, conn, msg, NULL, FALSE);
442342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
443342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
444342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	} else {
445040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		uuid_t uuid;
446040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi
447040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		if (bt_string2uuid(&uuid, pattern) < 0)
448342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			return invalid_args(msg);
449a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann
4504b1914903cb105acf843b84833e81d5470133879Johan Hedberg		sdp_uuid128_to_uuid(&uuid);
4514b1914903cb105acf843b84833e81d5470133879Johan Hedberg
45269adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		err = device_browse(device, conn, msg, &uuid, FALSE);
453342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
454342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
455342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	}
45694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
45794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return NULL;
458342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
459342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentzfail:
460342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
461342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz					"Discovery Failed");
46294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
46394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
46494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *cancel_discover(DBusConnection *conn,
46594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
46694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
467555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
46818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
4697c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg	const char *sender = dbus_message_get_sender(msg);
470cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
4712a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
4722a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
47319b4c8b0e51a20a1b95ede34b092ebc56e1183aeMarcel Holtmann
474342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (!device->discov_active)
475342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg,
476342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				ERROR_INTERFACE ".Failed",
477342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				"No pending discovery");
478342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
479342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	/* only the discover requestor can cancel the inquiry process */
480342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	if (!device->discov_requestor ||
4817c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg				!g_str_equal(device->discov_requestor, sender))
482342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		return g_dbus_create_error(msg,
483342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				ERROR_INTERFACE ".NotAuthorized",
484342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz				"Not Authorized");
485342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
486cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (bt_cancel_discovery(&src, &device->bdaddr) < 0)
487289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz		return g_dbus_create_error(msg,
488289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz				ERROR_INTERFACE ".Failed",
489289e29c6c4a073569c7e7aa3c8fc51ed5c46993fLuiz Augusto von Dentz				"No pending discover");
49094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
49194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return dbus_message_new_method_return(msg);
49294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
49394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
4945d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasistatic gboolean disconnect_timeout(gpointer user_data)
4955d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi{
496555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
4975d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	disconnect_cp cp;
4985d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	int dd;
499661a10565362c5ae0aad6a2ebf6513390cba868eAlok Barsode	uint16_t dev_id = adapter_get_dev_id(device->adapter);
5005d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5015d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	device->disconn_timer = 0;
5025d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
503661a10565362c5ae0aad6a2ebf6513390cba868eAlok Barsode	dd = hci_open_dev(dev_id);
5045d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	if (dd < 0)
5055d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		goto fail;
5065d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5075d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	memset(&cp, 0, sizeof(cp));
508c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	cp.handle = htobs(device->handle);
5095d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	cp.reason = HCI_OE_USER_ENDED_CONNECTION;
5105d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5115d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	hci_send_cmd(dd, OGF_LINK_CTL, OCF_DISCONNECT,
5125d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DISCONNECT_CP_SIZE, &cp);
5135d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5145d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	close(dd);
5155d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5165d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasifail:
5175d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	return FALSE;
5185d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi}
5195d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5207c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedbergstatic DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
5217c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg							void *user_data)
52294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
523555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
5245d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
525c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (!device->handle)
5265d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		return g_dbus_create_error(msg,
5275d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi				ERROR_INTERFACE ".NotConnected",
5285d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi				"Device is not connected");
5295d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5305d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	g_dbus_emit_signal(conn, device->path,
5315d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DEVICE_INTERFACE, "DisconnectRequested",
5325d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi			DBUS_TYPE_INVALID);
5335d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
5345d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER,
5355d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi						disconnect_timeout, device);
53694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
53794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return dbus_message_new_method_return(msg);
53894c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
53994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
540e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusMethodTable device_methods[] = {
541e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "GetProperties",	"",	"a{sv}",	get_properties	},
542e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "SetProperty",	"sv",	"",		set_property	},
543e0d13d6da4b527ee02838af6b9dd7d53615e4896Marcel Holtmann	{ "DiscoverServices",	"s",	"a{us}",	discover_services,
54494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						G_DBUS_METHOD_FLAG_ASYNC},
54594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "CancelDiscovery",	"",	"",		cancel_discover	},
546e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "Disconnect",		"",	"",		disconnect	},
54794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
5482c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
5492c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
550e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusSignalTable device_signals[] = {
55194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "PropertyChanged",		"sv"	},
55294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "DisconnectRequested",	""	},
55394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
5542c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
5552c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
556c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzgboolean device_is_connected(struct btd_device *device)
557e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg{
558c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	return (device->handle != 0);
559e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg}
560e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
5617c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedbergstatic void device_set_connected(struct btd_device *device,
5627c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg					DBusConnection *conn,
5637c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg					gboolean connected)
564013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
565c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, device->path, DEVICE_INTERFACE,
566c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				"Connected", DBUS_TYPE_BOOLEAN, &connected);
567e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
568e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	if (connected && device->secmode3) {
569e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		struct btd_adapter *adapter = device_get_adapter(device);
570e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		bdaddr_t sba;
571e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
572e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		adapter_get_address(adapter, &sba);
573e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
574e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		device->secmode3 = FALSE;
575e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
576e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg		hcid_dbus_bonding_process_complete(&sba, &device->bdaddr, 0);
577e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	}
578e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg}
579e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
580c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzvoid device_add_connection(struct btd_device *device, DBusConnection *conn,
581c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz				uint16_t handle)
582c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
583c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (device->handle) {
584c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		error("%s: Unable to add connection %u, %u already exist)",
585c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz			device->path, handle, device->handle);
586c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		return;
587c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	}
588c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
589c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device->handle = handle;
590c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
591c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device_set_connected(device, conn, TRUE);
592c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
593c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
594c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzvoid device_remove_connection(struct btd_device *device, DBusConnection *conn,
595c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz				uint16_t handle)
596c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
597c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (device->handle != handle) {
598c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		error("%s: Unable to remove connection %u, handle mismatch (%u)",
599c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz			device->path, handle, device->handle);
600c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		return;
601c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	}
602c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
603c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device->handle = 0;
604c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
605c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	device_set_connected(device, conn, FALSE);
606c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
607c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
608c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzgboolean device_has_connection(struct btd_device *device, uint16_t handle)
609c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
610c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	return (handle == device->handle);
611c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
612c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
613e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedbergvoid device_set_secmode3_conn(struct btd_device *device, gboolean enable)
614e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg{
615e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg	device->secmode3 = enable;
616013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
617013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
6187c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedbergstruct btd_device *device_create(DBusConnection *conn,
6197c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg					struct btd_adapter *adapter,
62036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz					const gchar *address)
62186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
622ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	gchar *address_up;
623555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device;
624139c2014be451848fcc3fa31cdc07653148f596eMarcel Holtmann	const gchar *adapter_path = adapter_get_path(adapter);
625a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	bdaddr_t src;
626a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	char srcaddr[18];
62786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
628555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	device = g_try_malloc0(sizeof(struct btd_device));
62986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (device == NULL)
63086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
63186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
632ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	address_up = g_ascii_strup(address, -1);
633139c2014be451848fcc3fa31cdc07653148f596eMarcel Holtmann	device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up);
63486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_strdelimit(device->path, ":", '_');
635ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	g_free(address_up);
63686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
63786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	debug("Creating device %s", device->path);
63886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
639e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE,
640e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device_methods, device_signals, NULL,
641e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device, device_free) == FALSE) {
64286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		device_free(device);
64386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
64486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	}
645da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
646cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	str2ba(address, &device->bdaddr);
647da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi	device->adapter = adapter;
648a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	adapter_get_address(adapter, &src);
649a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	ba2str(&src, srcaddr);
650a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	read_device_name(srcaddr, address, device->name);
651da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
6528493d6363e61f1ef68763aab8e65f75be7f67facJohan Hedberg	device->auth = 0xff;
6538493d6363e61f1ef68763aab8e65f75be7f67facJohan Hedberg
6546bfa88d706cc57a0c975c980dabec5d8ed67dcc0Claudio Takahasi	return device;
65586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
65686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
657a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentzvoid device_set_name(struct btd_device *device, const char *name)
658a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz{
659a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	DBusConnection *conn = get_dbus_connection();
660a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	char alias[248];
661a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	char srcaddr[18], dstaddr[18];
662a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	bdaddr_t src;
663a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
664a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	if (strncmp(name, device->name, 248) == 0)
665a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz		return;
666a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
667a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	strncpy(device->name, name, 248);
668a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
669a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	emit_property_changed(conn, device->path,
670a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DEVICE_INTERFACE, "Name",
671a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DBUS_TYPE_STRING, &name);
672a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
673a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	adapter_get_address(device->adapter, &src);
674a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	ba2str(&src, srcaddr);
675a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	ba2str(&device->bdaddr, dstaddr);
676a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
677a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	if (read_device_alias(srcaddr, dstaddr, alias, sizeof(alias)) == 0)
678a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz		return;
679a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
680a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	emit_property_changed(conn, device->path,
681a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DEVICE_INTERFACE, "Alias",
682a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DBUS_TYPE_STRING, &name);
683a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz}
684a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
6857c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedbergstatic void device_remove_bonding(struct btd_device *device,
6867c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg							DBusConnection *conn)
6872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
6882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char filename[PATH_MAX + 1];
6892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char *str, srcaddr[18], dstaddr[18];
6902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	int dd, dev_id;
6912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bdaddr_t bdaddr;
6922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	gboolean paired;
6932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	adapter_get_address(device->adapter, &bdaddr);
6952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&bdaddr, srcaddr);
6962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&device->bdaddr, dstaddr);
6972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
6982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dev_id = adapter_get_dev_id(device->adapter);
6992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dd = hci_open_dev(dev_id);
7012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (dd < 0)
7022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
7032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
7052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			"linkkeys");
7062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* textfile_del doesn't return an error when the key is not found */
7082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	str = textfile_caseget(filename, dstaddr);
7092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	paired = str ? TRUE : FALSE;
7102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_free(str);
7112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!paired)
7132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
7142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* Delete the link key from storage */
7162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	textfile_casedel(filename, dstaddr);
7172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* Delete the link key from the Bluetooth chip */
7192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	hci_delete_stored_link_key(dd, &device->bdaddr, 0, HCI_REQ_TIMEOUT);
7202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* Send the HCI disconnect command */
722c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	if (device->handle) {
723c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		int err = hci_disconnect(dd, htobs(device->handle),
7242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					HCI_OE_USER_ENDED_CONNECTION,
7252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					HCI_REQ_TIMEOUT);
7262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (err < 0)
7272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			error("Disconnect: %s (%d)", strerror(-err), -err);
7282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
7292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	hci_close_dev(dd);
7312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	paired = FALSE;
7332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	emit_property_changed(conn, device->path, DEVICE_INTERFACE,
7342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				"Paired", DBUS_TYPE_BOOLEAN, &paired);
7352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
7362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7377dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentzstatic void device_remove_stored(struct btd_device *device,
7387dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz					DBusConnection *conn)
7397dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz{
7407dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	bdaddr_t src;
7417dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	char addr[18];
7427dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz
7437dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	adapter_get_address(device->adapter, &src);
7447dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	ba2str(&device->bdaddr, addr);
7457dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	device_remove_bonding(device, conn);
7467dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	delete_entry(&src, "profiles", addr);
7477dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	delete_entry(&src, "trusts", addr);
7487dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz}
7497dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz
75058c15493922277539cca11e8b55776c5d0fbccbaJohan Hedbergvoid device_remove(struct btd_device *device, DBusConnection *conn,
7517dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz						gboolean remove_stored)
75275add5651e5dbc49c9c144acceac7e2c32d9bd16Claudio Takahasi{
7536061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	GSList *list;
7546061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	struct btd_device_driver *driver;
755f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	gchar *path = g_strdup(device->path);
756f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
757f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	debug("Removing device %s", path);
758f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
7592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding)
7602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device_cancel_bonding(device, HCI_OE_USER_ENDED_CONNECTION);
7612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7627dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	if (!device->temporary && remove_stored)
7637dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz		device_remove_stored(device, conn);
7642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
7656061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	for (list = device->drivers; list; list = list->next) {
766b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_driver_data *driver_data = list->data;
767b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		driver = driver_data->driver;
7686061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann
769e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz		driver->remove(device);
770b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		g_free(driver_data);
7716061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	}
7726061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann
77367d8c4fbc43e4e72174da96734572c3c2291bc4bJohan Hedberg
774f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	g_dbus_unregister_interface(conn, path, DEVICE_INTERFACE);
77575add5651e5dbc49c9c144acceac7e2c32d9bd16Claudio Takahasi
776f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann	g_free(path);
77786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
778ff296428a08dee619db1cc702146faefa91087faCidorvan Leite
779555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegint device_address_cmp(struct btd_device *device, const gchar *address)
780ff296428a08dee619db1cc702146faefa91087faCidorvan Leite{
781cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char addr[18];
782cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
783cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, addr);
784cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	return strcasecmp(addr, address);
785ff296428a08dee619db1cc702146faefa91087faCidorvan Leite}
7863d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
7873870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedbergstatic gboolean record_has_uuid(const sdp_record_t *rec,
7883870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg				const char *profile_uuid)
789f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
7903870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	sdp_list_t *pat;
791f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7923870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	for (pat = rec->pattern; pat != NULL; pat = pat->next) {
793f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		char *uuid;
7943870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		int ret;
795f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
7963870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		uuid = bt_uuid2string(pat->data);
797f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!uuid)
798f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
799f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
8003870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		ret = strcasecmp(uuid, profile_uuid);
801f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
8023870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		g_free(uuid);
8033870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg
8043870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		if (ret == 0)
8053870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg			return TRUE;
806f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	}
807f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
8083870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	return FALSE;
809f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
810f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
811f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzstatic GSList *device_match_pattern(struct btd_device *device,
812878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg					const char *match_uuid,
813f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					GSList *profiles)
814f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
815f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *l, *uuids = NULL;
816f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
817f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (l = profiles; l; l = l->next) {
818878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg		char *profile_uuid = l->data;
819f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		const sdp_record_t *rec;
8203bb7c1527ce3ec67127200b54a8fbc01a196ebadJohan Hedberg
821878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg		rec = btd_device_get_record(device, profile_uuid);
822f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!rec)
823f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
824f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
825a01801fd21056ef6f7fffc6a205b6c2b9e99899fJohan Hedberg		if (record_has_uuid(rec, match_uuid))
826878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg			uuids = g_slist_append(uuids, profile_uuid);
827cdfe8a8246013031f55c647092e41adbb29ace81Johan Hedberg	}
828f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
829f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	return uuids;
830f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
831f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
832f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzstatic GSList *device_match_driver(struct btd_device *device,
833f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					struct btd_device_driver *driver,
834f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					GSList *profiles)
835f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann{
8366061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	const char **uuid;
837f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *uuids = NULL;
838f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
839f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (uuid = driver->uuids; *uuid; uuid++) {
840f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		GSList *match;
841f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
8429b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz		/* skip duplicated uuids */
8439b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz		if (g_slist_find_custom(uuids, *uuid,
8449b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz				(GCompareFunc) strcasecmp))
8459b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz			continue;
8469b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz
847f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		/* match profile driver */
848f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		match = g_slist_find_custom(profiles, *uuid,
849f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					(GCompareFunc) strcasecmp);
850f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (match) {
851f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			uuids = g_slist_append(uuids, match->data);
852f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
853f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		}
854f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
855f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		/* match pattern driver */
856f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		match = device_match_pattern(device, *uuid, profiles);
857a01801fd21056ef6f7fffc6a205b6c2b9e99899fJohan Hedberg		for (; match; match = match->next)
858f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			uuids = g_slist_append(uuids, match->data);
859f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	}
860f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
861f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	return uuids;
862f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
863f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
864f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzvoid device_probe_drivers(struct btd_device *device, GSList *profiles)
865f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
866f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *list;
867f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	int err;
868f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
869f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	debug("Probe drivers for %s", device->path);
870f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
871c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	for (list = device_drivers; list; list = list->next) {
872e0863545e6239ac338fa7fbe9647a5748a60b436Marcel Holtmann		struct btd_device_driver *driver = list->data;
873f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		GSList *probe_uuids;
874f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		struct btd_driver_data *driver_data;
875f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
876f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		probe_uuids = device_match_driver(device, driver, profiles);
8774b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode
878f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!probe_uuids)
879f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
880081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz
881f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		driver_data = g_new0(struct btd_driver_data, 1);
882b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
883f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		err = driver->probe(device, probe_uuids);
884f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (err < 0) {
885f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			error("probe failed with driver %s for device %s",
886f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					driver->name, device->path);
887b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
888f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			g_free(driver_data);
889548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			g_slist_free(probe_uuids);
890f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
891f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann		}
892f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
893f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		driver_data->driver = driver;
894f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		device->drivers = g_slist_append(device->drivers, driver_data);
895f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		g_slist_free(probe_uuids);
896f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	}
89736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
898f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (list = profiles; list; list = list->next) {
899c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		GSList *l = g_slist_find_custom(device->uuids, list->data,
9007c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						(GCompareFunc) strcasecmp);
901c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		if (l)
902c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann			continue;
903c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann
90436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		device->uuids = g_slist_insert_sorted(device->uuids,
9057c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						g_strdup(list->data),
9067c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						(GCompareFunc) strcasecmp);
907548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	}
908548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
909548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (device->tmp_records) {
910548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		sdp_list_free(device->tmp_records,
911548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg				(sdp_free_func_t) sdp_record_free);
912548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		device->tmp_records = NULL;
913c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann	}
91436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
91536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
91699bc055edc4b9ba8ccda791757a6439fb03ff8f2Marcel Holtmannstatic void device_remove_drivers(struct btd_device *device, GSList *uuids)
91736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
91818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
919352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg	GSList *list, *next;
920cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
9212a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
922548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	sdp_list_t *records;
9232a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
9242a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
925cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
926cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
92736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
928548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	records = read_records(&src, &device->bdaddr);
929548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
93036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	debug("Remove drivers for %s", device->path);
93136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
932352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg	for (list = device->drivers; list; list = next) {
933b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_driver_data *driver_data = list->data;
934b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode		struct btd_device_driver *driver = driver_data->driver;
93536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		const char **uuid;
93636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
937352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg		next = list->next;
938352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg
93936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		for (uuid = driver->uuids; *uuid; uuid++) {
9409b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			sdp_record_t *rec;
94136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
9429b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			if (!g_slist_find_custom(uuids, *uuid,
9439b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz					(GCompareFunc) strcasecmp))
94436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz				continue;
94536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
9467c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg			debug("UUID %s was removed from device %s",
9477c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg							*uuid, dstaddr);
948548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
949e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz			driver->remove(device);
95036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			device->drivers = g_slist_remove(device->drivers,
951b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode								driver_data);
952b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode			g_free(driver_data);
953b76fbc7d29f28a95a9ea25aae1f6f2d9c10adb19Alok Barsode
954548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			rec = find_record_in_list(records, *uuid);
9559b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			if (!rec)
9562d370d5d678973644c2c3c75b22d5f24b7a2c638Johan Hedberg				break;
9579b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz
958cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode			delete_record(srcaddr, dstaddr, rec->handle);
959548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
960548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			records = sdp_list_remove(records, rec);
961548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			sdp_record_free(rec);
9622d370d5d678973644c2c3c75b22d5f24b7a2c638Johan Hedberg
9632d370d5d678973644c2c3c75b22d5f24b7a2c638Johan Hedberg			break;
96436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		}
96536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
96636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
967548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (records)
968548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		sdp_list_free(records, (sdp_free_func_t) sdp_record_free);
969548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
97036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (list = uuids; list; list = list->next)
97136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		device->uuids = g_slist_remove(device->uuids, list->data);
972f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann}
973f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
974bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmannstatic void iter_append_record(DBusMessageIter *dict, uint32_t handle,
975bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann							const char *record)
976bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann{
977bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	DBusMessageIter entry;
978bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
979bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
980bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann							NULL, &entry);
981bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
982bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_append_basic(&entry, DBUS_TYPE_UINT32, &handle);
983bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
984bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &record);
985bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
986bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann	dbus_message_iter_close_container(dict, &entry);
987bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann}
988bbe56de7715cf62e37026711a6eb3f1c5be6d1cdMarcel Holtmann
989730775d1226a30c37ff551955f093ddfcd18e600Claudio Takahasistatic void append_and_grow_string(void *data, const char *str)
990c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz{
991c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	sdp_buf_t *buff = data;
992c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	int len;
993c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
994c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	len = strlen(str);
995c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
996c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	if (!buff->data) {
997c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->data = malloc(DEFAULT_XML_BUF_SIZE);
998c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		if (!buff->data)
999c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz			return;
1000c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->buf_size = DEFAULT_XML_BUF_SIZE;
1001c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	}
1002c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
1003c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	/* Grow string */
1004c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	while (buff->buf_size < (buff->data_size + len + 1)) {
1005c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		void *tmp;
1006c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		uint32_t new_size;
1007c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
1008c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		/* Grow buffer by a factor of 2 */
1009c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		new_size = (buff->buf_size << 1);
1010c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
1011c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		tmp = realloc(buff->data, new_size);
1012c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		if (!tmp)
1013c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz			return;
1014c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
1015c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->data = tmp;
1016c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz		buff->buf_size = new_size;
1017c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	}
1018c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
1019c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	/* Include the NULL character */
1020c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	memcpy(buff->data + buff->data_size, str, len + 1);
1021c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz	buff->data_size += len;
1022c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz}
1023c36942e998cd6187181df3033e53f1d624a5fd1aLuiz Augusto von Dentz
10241e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentzstatic void discover_device_reply(struct browse_req *req, sdp_list_t *recs)
10251e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz{
10261e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	DBusMessage *reply;
10271e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	DBusMessageIter iter, dict;
10281e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	sdp_list_t *seq;
10291e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10301e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	reply = dbus_message_new_method_return(req->msg);
10311e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	if (!reply)
10321e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		return;
10331e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10341e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
10351e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10361e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
10371e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
10381e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_STRING_AS_STRING
10391e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
10401e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10411e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
10421e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
10431e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		sdp_buf_t result;
10441e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10451e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		if (!rec)
10461e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			break;
10471e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10481e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		memset(&result, 0, sizeof(sdp_buf_t));
10491e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10501e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		convert_sdp_record_to_xml(rec, &result,
10511e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz				append_and_grow_string);
10521e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10531e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		if (result.data) {
10541e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			const char *val = (char *) result.data;
10551e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			iter_append_record(&dict, rec->handle, val);
10561e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz			free(result.data);
10571e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		}
10581e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	}
10591e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
10601e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
10611e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
1062a5883ecb1aa94b09bcf0e7ce4184d262027c5939Johan Hedberg	g_dbus_send_message(req->conn, reply);
10631e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz}
10641e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz
106517541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergstatic void services_changed(struct btd_device *device)
10663d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
1067533655873c4978091edf3698b20d2b96c43dafc8Johan Hedberg	DBusConnection *conn = get_dbus_connection();
10683d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	char **uuids;
10693d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	GSList *l;
107036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	int i;
10713d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
107236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
107336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
107436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		uuids[i] = l->data;
107536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
107658f06324289d7d343a52a9104d02121cb8db1047Johan Hedberg	emit_array_property_changed(conn, device->path, DEVICE_INTERFACE,
107758f06324289d7d343a52a9104d02121cb8db1047Johan Hedberg					"UUIDs", DBUS_TYPE_STRING, &uuids);
107836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
107936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(uuids);
108036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
108136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
10828b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedbergstatic int rec_cmp(const void *a, const void *b)
10838b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg{
10848b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r1 = a;
10858b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r2 = b;
10868b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
10878b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	return r1->handle - r2->handle;
10888b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg}
10898b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
109036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentzstatic void update_services(struct browse_req *req, sdp_list_t *recs)
109136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
1092555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
109318614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
109436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	sdp_list_t *seq;
1095cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
10962a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
10972a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
10982a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
1099cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
1100cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
11013d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
110236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
11033d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
110436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_t *svcclass = NULL;
11050dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		gchar *profile_uuid;
110636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		GSList *l;
11073d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
11083d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		if (!rec)
11093d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz			break;
11103d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
111136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (sdp_get_service_classes(rec, &svcclass) < 0)
111236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
111336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
111436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		/* Extract the first element and skip the remainning */
11150dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		profile_uuid = bt_uuid2string(svcclass->data);
11160dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		if (!profile_uuid) {
1117aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg			sdp_list_free(svcclass, free);
111836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
1119aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg		}
112036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
11210dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		if (!strcasecmp(profile_uuid, PNP_UUID)) {
1122fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			uint16_t source, vendor, product, version;
1123e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			sdp_data_t *pdlist;
1124e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1125fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID_SOURCE);
1126fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			source = pdlist ? pdlist->val.uint16 : 0x0000;
1127fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann
1128e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
1129e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			vendor = pdlist ? pdlist->val.uint16 : 0x0000;
1130e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1131e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
1132e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			product = pdlist ? pdlist->val.uint16 : 0x0000;
1133e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1134e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
1135e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			version = pdlist ? pdlist->val.uint16 : 0x0000;
1136e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1137fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			if (source || vendor || product || version)
1138fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann				store_device_id(srcaddr, dstaddr, source,
1139fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann						vendor, product, version);
1140e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse		}
1141e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
114237a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg		/* Check for duplicates */
1143981f4416220e01a3eab92aa3c8d03c16dcad450dJohan Hedberg		if (sdp_list_find(req->records, rec, rec_cmp)) {
11440dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			g_free(profile_uuid);
1145aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg			sdp_list_free(svcclass, free);
114637a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg			continue;
1147981f4416220e01a3eab92aa3c8d03c16dcad450dJohan Hedberg		}
114837a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
1149cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		store_record(srcaddr, dstaddr, rec);
115037a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
1151681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		/* Copy record */
11527c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg		req->records = sdp_list_append(req->records,
11537c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg							sdp_copy_record(rec));
1154681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
11550dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		l = g_slist_find_custom(device->uuids, profile_uuid,
1156c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann							(GCompareFunc) strcmp);
115736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (!l)
11580dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			req->profiles_added =
11590dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg					g_slist_append(req->profiles_added,
11600dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg							profile_uuid);
116136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		else {
11620dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			req->profiles_removed =
11630dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg					g_slist_remove(req->profiles_removed,
11640dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg							l->data);
11650dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			g_free(profile_uuid);
11663d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		}
11673d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
116836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_free(svcclass, free);
11693d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	}
117036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
117136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
117217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergstatic void store_profiles(struct btd_device *device)
117336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
117418614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
1175cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
117636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	char *str;
11773d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
11782a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
11793d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
118036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	if (!device->uuids) {
1181cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		write_device_profiles(&src, &device->bdaddr, "");
118236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		return;
118336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
118436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
118536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	str = bt_list2string(device->uuids);
1186cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	write_device_profiles(&src, &device->bdaddr, str);
118736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(str);
118836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
118936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
1190a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentzstatic void browse_req_free(struct browse_req *req)
1191a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz{
1192a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	struct btd_device *device = req->device;
1193a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1194a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	device->discov_active = 0;
1195a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1196a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (device->discov_requestor) {
1197a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		g_dbus_remove_watch(req->conn, device->discov_listener);
1198a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		device->discov_listener = 0;
1199a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		g_free(device->discov_requestor);
1200a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		device->discov_requestor = NULL;
1201a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	}
1202a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1203a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (req->msg)
1204a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		dbus_message_unref(req->msg);
1205a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (req->conn)
1206a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		dbus_connection_unref(req->conn);
12070dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	g_slist_foreach(req->profiles_added, (GFunc) g_free, NULL);
12080dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	g_slist_free(req->profiles_added);
12090dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	g_slist_free(req->profiles_removed);
1210a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (req->records)
1211a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
1212a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	g_free(req);
1213a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz}
1214a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1215da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void search_cb(sdp_list_t *recs, int err, gpointer user_data)
121636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
121736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	struct browse_req *req = user_data;
1218555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
121936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	DBusMessage *reply;
12202a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
1221681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	if (err < 0) {
1222681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		error("%s: error updating services: %s (%d)",
1223681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz				device->path, strerror(-err), -err);
122436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		goto proceed;
1225681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	}
122636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
122736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	update_services(req, recs);
122836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
12290dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (!req->profiles_added && !req->profiles_removed) {
1230e62d9fec6ad663d335a8f915568e5f35cd0633b1Luiz Augusto von Dentz		debug("%s: No service update", device->path);
123136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		goto proceed;
1232681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	}
12332efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
1234548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (device->tmp_records && req->records) {
12357c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg		sdp_list_free(device->tmp_records,
12367c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg					(sdp_free_func_t) sdp_record_free);
1237548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		device->tmp_records = req->records;
1238548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		req->records = NULL;
1239548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	}
1240548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
124136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Probe matching drivers for services added */
12420dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (req->profiles_added)
12430dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		device_probe_drivers(device, req->profiles_added);
12442efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
124536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Remove drivers for services removed */
12460dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (req->profiles_removed)
12470dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		device_remove_drivers(device, req->profiles_removed);
12482efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
124936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Propagate services changes */
125017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	services_changed(req->device);
1251f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
12527b67507336f98dda5523902806dd2e33684fab6bLuiz Augusto von Dentzproceed:
1253681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	/* Store the device's profiles in the filesystem */
125417541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	store_profiles(device);
1255681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
12562ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg	if (!req->msg)
12572ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg		goto cleanup;
12582ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg
1259438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz	if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
1260438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz					"DiscoverServices")) {
1261438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz		discover_device_reply(req, req->records);
1262438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz		goto cleanup;
1263438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz	}
1264438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz
12653d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	/* Reply create device request */
12663d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	reply = dbus_message_new_method_return(req->msg);
12673d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	if (!reply)
12681e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentz		goto cleanup;
12693d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
12703d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &device->path,
1271a2529a9b417959a52f5d501cba4bcaf32caf6964Marcel Holtmann							DBUS_TYPE_INVALID);
12723d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1273a5883ecb1aa94b09bcf0e7ce4184d262027c5939Johan Hedberg	g_dbus_send_message(req->conn, reply);
12743d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
12751e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentzcleanup:
1276a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	browse_req_free(req);
1277da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
1278da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1279da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
1280da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
1281da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct browse_req *req = user_data;
1282da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_device *device = req->device;
1283da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
1284cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
1285da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	uuid_t uuid;
1286da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
12877c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg	/* If we have a valid response and req->search_uuid == 2, then L2CAP
12887c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg	 * UUID & PNP searching was successful -- we are done */
12890dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (err < 0 || (req->search_uuid == 2 && req->records))
1290da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		goto done;
1291da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1292da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	update_services(req, recs);
1293da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1294da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	adapter_get_address(adapter, &src);
1295da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1296da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	/* Search for mandatory uuids */
12977d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse	if (uuid_list[req->search_uuid]) {
12987d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
1299c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		bt_search_service(&src, &device->bdaddr, &uuid,
1300c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann						browse_cb, user_data, NULL);
1301da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		return;
1302da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	}
1303da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1304da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzdone:
1305da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	search_cb(recs, err, user_data);
1306da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
1307da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
130869adac833c5633714b84bf840c75aa814193b8a6Johan Hedbergstatic void init_browse(struct browse_req *req, gboolean reverse)
1309da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
1310da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	GSList *l;
1311da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
131269adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	/* If we are doing reverse-SDP don't try to detect removed profiles
131369adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 * since some devices hide their service records while they are
131469adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 * connected
131569adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 */
131669adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	if (reverse)
131769adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		return;
131869adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg
1319da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	for (l = req->device->uuids; l; l = l->next)
13200dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		req->profiles_removed = g_slist_append(req->profiles_removed,
1321da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz						l->data);
13223d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
13233d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1324555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeint device_browse(struct btd_device *device, DBusConnection *conn,
132569adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg			DBusMessage *msg, uuid_t *search, gboolean reverse)
13263d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
132718614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
13283d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	struct browse_req *req;
1329cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
1330d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	uuid_t uuid;
1331da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	bt_callback_t cb;
1332a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	int err;
13332a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
13341af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg	if (device->discov_active)
13351af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg		return -EBUSY;
13361af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg
13372a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
13383d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
13393d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req = g_new0(struct browse_req, 1);
1340438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz
1341d2244495dfc50c22ce275f6194c19d3293de70cbJohan Hedberg	if (conn == NULL)
1342d2244495dfc50c22ce275f6194c19d3293de70cbJohan Hedberg		conn = get_dbus_connection();
1343438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz
1344d2244495dfc50c22ce275f6194c19d3293de70cbJohan Hedberg	req->conn = dbus_connection_ref(conn);
13453d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	req->device = device;
13463d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1347a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (search) {
1348040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		memcpy(&uuid, search, sizeof(uuid_t));
1349da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = search_cb;
1350a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	} else {
13517d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
135269adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		init_browse(req, reverse);
1353da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = browse_cb;
1354a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	}
1355d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
135695e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz	device->discov_active = 1;
1357d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg
1358d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg	if (msg) {
13597c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg		const char *sender = dbus_message_get_sender(msg);
13607c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg
13615c6426eff87049c9f8e49877f650772840907239Luiz Augusto von Dentz		req->msg = dbus_message_ref(msg);
13627c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg		device->discov_requestor = g_strdup(sender);
1363d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		/* Track the request owner to cancel it
1364d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		 * automatically if the owner exits */
1365d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		device->discov_listener = g_dbus_add_disconnect_watch(conn,
13667c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						sender,
136795e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						discover_services_req_exit,
136895e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						device, NULL);
1369d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg	}
137095e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz
1371a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	err = bt_search_service(&src, &device->bdaddr,
1372a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz				&uuid, cb, req, NULL);
1373a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	if (err < 0)
1374a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz		browse_req_free(req);
1375a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz
1376a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	return err;
13773d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
137824cce397c3479e95f3e525da9285234fbafd2984Marcel Holtmann
137918614bd2b008cb9f3879990883c569c37b72f195Alok Barsodestruct btd_adapter *device_get_adapter(struct btd_device *device)
1380dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode{
1381dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	if (!device)
1382dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode		return NULL;
1383dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
1384dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	return device->adapter;
1385dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode}
1386dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
138719ce4933f3dadf3b04a2a9bd84d66d750cc010c3Alok Barsodevoid device_get_address(struct btd_device *device, bdaddr_t *bdaddr)
1388aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode{
1389cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bacpy(bdaddr, &device->bdaddr);
1390aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode}
1391aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode
1392555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeconst gchar *device_get_path(struct btd_device *device)
139346fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode{
139446fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	if (!device)
139546fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode		return NULL;
139646fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
139746fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	return device->path;
139846fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode}
139946fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
1400555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestruct agent *device_get_agent(struct btd_device *device)
1401a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode{
1402a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode	if (!device)
1403a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode		return NULL;
1404a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
1405a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode	return  device->agent;
1406a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode}
1407a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
1408555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_agent(struct btd_device *device, struct agent *agent)
1409d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode{
1410d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode	if (!device)
1411d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode		return;
1412d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode
1413d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode	device->agent = agent;
1414d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode}
1415d8b1e6017c0198bc996f9f9518037d69902b7830Alok Barsode
1416555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_busy(struct btd_device *device)
14179f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode{
14189f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode	return device->discov_active ? TRUE : FALSE;
14199f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode}
14209f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode
1421555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_temporary(struct btd_device *device)
1422f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode{
1423f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode	return device->temporary;
1424f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode}
1425f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode
1426555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_temporary(struct btd_device *device, gboolean temporary)
1427595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode{
1428595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode	if (!device)
1429595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode		return;
1430595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode
1431595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode	device->temporary = temporary;
1432595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode}
1433595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode
1434555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_cap(struct btd_device *device, uint8_t cap)
1435491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode{
1436491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode	if (!device)
1437491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode		return;
1438491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode
1439491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode	device->cap = cap;
1440491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode}
1441491190e5dde601e4876f24a922f1ba16ae4d2e6dAlok Barsode
1442f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberguint8_t device_get_cap(struct btd_device *device)
1443f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg{
1444f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg	return device->cap;
1445f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg}
1446f6646fcfe84b703d0657a0e827682702d64a4788Johan Hedberg
1447555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_auth(struct btd_device *device, uint8_t auth)
144829227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode{
144929227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode	if (!device)
145029227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode		return;
145129227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode
145229227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode	device->auth = auth;
145329227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode}
145429227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode
1455555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeuint8_t device_get_auth(struct btd_device *device)
14562203f153c53189ec1c30df99b717e035681196e6Alok Barsode{
14572203f153c53189ec1c30df99b717e035681196e6Alok Barsode	return device->auth;
14582203f153c53189ec1c30df99b717e035681196e6Alok Barsode}
1459c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
1460013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedbergstatic gboolean start_discovery(gpointer user_data)
1461013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
1462013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	struct btd_device *device = user_data;
1463013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
146469adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	device_browse(device, NULL, NULL, NULL, TRUE);
1465013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
1466013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	device->discov_timer = 0;
1467013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
1468013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	return FALSE;
1469013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
1470013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
14712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von DentzDBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
1472013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
14732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (status) {
14742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x00: /* success */
14752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_method_return(msg);
14762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x04: /* page timeout */
14782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x08: /* connection timeout */
14792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x10: /* connection accept timeout */
14802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x22: /* LMP response timeout */
14812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x28: /* instant passed - is this a timeout? */
14822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationTimeout",
14842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Timeout");
14852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x17: /* too frequent pairing attempts */
14862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".RepeatedAttempts",
14882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Repeated Attempts");
14892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x06:
14912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */
14922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
14932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationRejected",
14942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Rejected");
14952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
14962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x07: /* memory capacity */
14972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x09: /* connection limit */
14982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0a: /* synchronous connection limit */
14992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0d: /* limited resources */
15002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x13: /* user ended the connection */
15012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x14: /* terminated due to low resources */
15022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
15032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationCanceled",
15042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Canceled");
15052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x05: /* authentication failure */
15072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0E: /* rejected due to security reasons - is this auth failure? */
15082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x25: /* encryption mode not acceptable - is this auth failure? */
15092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x26: /* link key cannot be changed - is this auth failure? */
15102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x29: /* pairing with unit key unsupported - is this auth failure? */
15112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x2f: /* insufficient security - is this auth failure? */
15122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	default:
15132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
15142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationFailed",
15152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Failed");
15162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
15182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1519fb6feead6323073b28fc8147aae5c211894d139dJohan Hedbergstatic void bonding_request_free(struct bonding_req *bonding, gboolean close)
15202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
15212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device;
15222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding)
15242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
15252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->listener_id)
15272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_dbus_remove_watch(bonding->conn, bonding->listener_id);
152868b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
15292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->msg)
15302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		dbus_message_unref(bonding->msg);
15312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->conn)
15332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		dbus_connection_unref(bonding->conn);
15342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->io_id)
15362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_source_remove(bonding->io_id);
15372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1538fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg	if (bonding->io) {
1539fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg		if (close)
1540fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg			g_io_channel_close(bonding->io);
15412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_io_channel_unref(bonding->io);
1542fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg	}
15432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device = bonding->device;
15452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device && device->agent) {
15472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		agent_destroy(device->agent, FALSE);
15482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->agent = NULL;
15492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding = NULL;
15522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_free(bonding);
15532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
15542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void device_set_paired(struct btd_device *device, gboolean value)
15562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
15572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusConnection *conn = get_dbus_connection();
155868b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
1559c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Paired",
15602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				DBUS_TYPE_BOOLEAN, &value);
15612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
15622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void device_agent_removed(struct agent *agent, void *user_data)
15642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
15652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = user_data;
15662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device_set_agent(device, NULL);
15682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
15702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->authr->agent = NULL;
15712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
15722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic struct bonding_req *bonding_request_new(DBusConnection *conn,
15742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						DBusMessage *msg,
15752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						struct btd_device *device,
15762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						const char *agent_path,
15772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						uint8_t capability)
15782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
15792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
15802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	const char *name = dbus_message_get_sender(msg);
15812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
15822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: requesting bonding", device->path);
15842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent_path)
15862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto proceed;
15872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	agent = agent_create(device->adapter, name, agent_path,
15892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					capability,
15902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device_agent_removed,
15912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device);
15922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent) {
15932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Unable to create a new agent");
15942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return NULL;
15952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
15962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->agent = agent;
15982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
15992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("Temporary agent registered for %s at %s:%s",
16002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			device->path, name, agent_path);
16012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzproceed:
16032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding = g_new0(struct bonding_req, 1);
16042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->conn = dbus_connection_ref(conn);
16062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->msg = dbus_message_ref(msg);
16072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return bonding;
16092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
16102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic gboolean create_bonding_io_cb(GIOChannel *io, GIOCondition cond,
16122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					struct btd_device *device)
16132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
16142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct hci_request rq;
16152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth_requested_cp cp;
16162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	evt_cmd_status rp;
16172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct l2cap_conninfo cinfo;
16182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	socklen_t len;
16192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	int sk, dd, ret;
16202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16215331a26b8a3c2d69d30a4334e023238db197080bJohan Hedberg	if (!device->bonding) {
16222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_io_channel_close(io);
16232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return FALSE;
16242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (cond & G_IO_NVAL) {
16272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (device->bonding) {
16282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			DBusMessage *reply;
16292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			reply = new_authentication_return(device->bonding->msg,
16312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							0x09);
16322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			g_dbus_send_message(device->bonding->conn, reply);
16332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		}
16342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto cleanup;
16362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (cond & (G_IO_HUP | G_IO_ERR)) {
16392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		debug("Hangup or error on bonding IO channel");
16402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (device->bonding)
16422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			error_connection_attempt_failed(device->bonding->conn,
16432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							device->bonding->msg,
16442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							ENETDOWN);
16452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	sk = g_io_channel_unix_get_fd(io);
16502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	len = sizeof(ret);
16522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
16532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Can't get socket error: %s (%d)",
16542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				strerror(errno), errno);
16552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
16562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				errno);
16572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (ret != 0) {
16612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		if (device->bonding)
16622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			error_connection_attempt_failed(device->bonding->conn,
16632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							device->bonding->msg,
16642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz							ret);
16652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	len = sizeof(cinfo);
16692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) {
16702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Can't get connection info: %s (%d)",
16712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				strerror(errno), errno);
16722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
16732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				errno);
16742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dd = hci_open_dev(adapter_get_dev_id(device->adapter));
16782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (dd < 0) {
16792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		DBusMessage *reply = no_such_adapter(device->bonding->msg);
16802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_dbus_send_message(device->bonding->conn, reply);
16812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
16822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
16832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	memset(&rp, 0, sizeof(rp));
16852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	memset(&cp, 0, sizeof(cp));
16872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	cp.handle = htobs(cinfo.hci_handle);
16882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	memset(&rq, 0, sizeof(rq));
16902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.ogf    = OGF_LINK_CTL;
16912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.ocf    = OCF_AUTH_REQUESTED;
16922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.cparam = &cp;
16932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.clen   = AUTH_REQUESTED_CP_SIZE;
16942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.rparam = &rp;
16952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.rlen   = EVT_CMD_STATUS_SIZE;
16962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	rq.event  = EVT_CMD_STATUS;
16972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
16982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (hci_send_req(dd, &rq, HCI_REQ_TIMEOUT) < 0) {
16992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Unable to send HCI request: %s (%d)",
17002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					strerror(errno), errno);
17012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
17022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				errno);
17032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		hci_close_dev(dd);
17042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
17052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
17062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (rp.status) {
17082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("HCI_Authentication_Requested failed with status 0x%02x",
17092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				rp.status);
17102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error_failed_errno(device->bonding->conn, device->bonding->msg,
17112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				bt_error(rp.status));
17122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		hci_close_dev(dd);
17132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
17142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
17152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	hci_close_dev(dd);
17172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding->io_id = g_io_add_watch(io,
17192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						G_IO_NVAL | G_IO_HUP | G_IO_ERR,
17202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						(GIOFunc) create_bonding_io_cb,
17212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						device);
17222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return FALSE;
17242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzfailed:
17262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_io_channel_close(io);
17272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzcleanup:
17292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding->io_id = 0;
1730fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg	bonding_request_free(device->bonding, FALSE);
17312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return FALSE;
17332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
17342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void create_bond_req_exit(DBusConnection *conn, void *user_data)
17362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
17372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = user_data;
17382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: requestor exited before bonding was completed", device->path);
17402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
1742f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg		device_cancel_authentication(device, FALSE);
17432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
17442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding) {
17452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->bonding->listener_id = 0;
17462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_io_channel_close(device->bonding->io);
1747fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg		bonding_request_free(device->bonding, TRUE);
17482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
17492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
17502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1751f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedbergstatic int l2raw_connect(const bdaddr_t *src, const bdaddr_t *dst,
1752f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg						gboolean *auth_required)
1753f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg{
1754f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	struct sockaddr_l2 addr;
1755f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	long arg;
1756d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	int sk, err, opt;
1757f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1758f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
1759f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (sk < 0) {
1760f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't create socket: %s (%d)", strerror(errno), errno);
1761f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		return sk;
1762f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1763f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1764f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	memset(&addr, 0, sizeof(addr));
1765f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	addr.l2_family = AF_BLUETOOTH;
1766f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	bacpy(&addr.l2_bdaddr, src);
1767f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1768f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1769f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't bind socket: %s (%d)", strerror(errno), errno);
1770f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1771f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1772f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
177397dd9b6963ee0f8517bf8e2633d28b6505f2f7baMarcel Holtmann	opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE;
1774f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1775d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	err = setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt));
1776d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	if (err < 0) {
1777d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg		error("setsockopt: %s (%d)", strerror(errno), errno);
1778d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg		goto failed;
1779d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	}
1780f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1781f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	arg = fcntl(sk, F_GETFL);
1782f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (arg < 0) {
1783f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't get file flags: %s (%d)", strerror(errno), errno);
1784f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1785f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1786f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1787f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	arg |= O_NONBLOCK;
1788f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (fcntl(sk, F_SETFL, arg) < 0) {
1789f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't set file flags: %s (%d)", strerror(errno), errno);
1790f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1791f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1792f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1793f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	memset(&addr, 0, sizeof(addr));
1794f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	addr.l2_family = AF_BLUETOOTH;
1795f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	bacpy(&addr.l2_bdaddr, dst);
1796f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1797f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1798f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		if (errno == EAGAIN || errno == EINPROGRESS)
1799f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg			return sk;
1800f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		error("Can't connect socket: %s (%d)", strerror(errno), errno);
1801f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg		goto failed;
1802f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	}
1803f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1804d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg	if (auth_required)
1805d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg		*auth_required = TRUE;
1806d9b5a3fcb122277222b80ff40ac786d2c5ad4ab8Johan Hedberg
1807f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	return sk;
1808f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
1809f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedbergfailed:
1810f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	close(sk);
1811f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	return -1;
1812f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg}
1813f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg
18142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von DentzDBusMessage *device_create_bonding(struct btd_device *device,
18152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusConnection *conn,
18162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusMessage *msg,
18172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					const char *agent_path,
18182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					uint8_t capability)
18192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
18202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char filename[PATH_MAX + 1];
18212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char *str, srcaddr[18], dstaddr[18];
18222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
18232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
18242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bdaddr_t src;
1825f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	int sk;
1826f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	gboolean auth_required;
18272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	adapter_get_address(adapter, &src);
18292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&src, srcaddr);
18302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&device->bdaddr, dstaddr);
18312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding)
18332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return in_progress(msg, "Bonding in progress");
18342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* check if a link key already exists */
18362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
18372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			"linkkeys");
18382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	str = textfile_caseget(filename, dstaddr);
18402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (str) {
18412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		free(str);
18422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return g_dbus_create_error(msg,
18432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				ERROR_INTERFACE ".AlreadyExists",
18442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				"Bonding already exists");
18452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
18462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1847dd10ec5d830d2e2187f93bd2d7e60be947335f0bJohan Hedberg
1848f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	sk = l2raw_connect(&src, &device->bdaddr, &auth_required);
18492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (sk < 0)
18502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return g_dbus_create_error(msg,
18512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				ERROR_INTERFACE ".ConnectionAttemptFailed",
18522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				"Connection attempt failed");
18532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding = bonding_request_new(conn, msg, device, agent_path,
18552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					capability);
18562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding) {
18572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		close(sk);
18582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return NULL;
18592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
18602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1861f8f494cb4880fa6a3f8b641bf6676acfce659753Johan Hedberg	bonding->auth_required = auth_required;
1862dd10ec5d830d2e2187f93bd2d7e60be947335f0bJohan Hedberg
18632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->io = g_io_channel_unix_new(sk);
18642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->io_id = g_io_add_watch(bonding->io,
18652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
18662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					(GIOFunc) create_bonding_io_cb,
18672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device);
18682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->listener_id = g_dbus_add_disconnect_watch(conn,
18702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						dbus_message_get_sender(msg),
18712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						create_bond_req_exit, device,
18722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						NULL);
18732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding = bonding;
18752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->device = device;
18762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return NULL;
18782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
18792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1880e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedbergvoid device_simple_pairing_complete(struct btd_device *device, uint8_t status)
1881e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg{
1882e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	struct authentication_req *auth = device->authr;
1883e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg
1884e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	if (auth && auth->type == AUTH_TYPE_NOTIFY && auth->agent)
1885e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg		agent_cancel(auth->agent);
1886e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg}
1887e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg
18882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzvoid device_bonding_complete(struct btd_device *device, uint8_t status)
18892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
18902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
1891e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	struct authentication_req *auth = device->authr;
1892e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg
1893e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	if (auth && auth->type == AUTH_TYPE_NOTIFY && auth->agent)
1894e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg		agent_cancel(auth->agent);
18952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
18962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (status)
18972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto failed;
18982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1899f8c2a96432a78aab515e7b4f3cd044f53946d908Marcel Holtmann	device->auth = 0xff;
19002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->temporary = FALSE;
190168b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
1902bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	g_free(device->authr);
1903bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	device->authr = NULL;
1904bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
1905bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	if (device->renewed_key)
1906bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg		return;
1907bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
190868b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	/* If we were initiators start service discovery immediately.
190968b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * However if the other end was the initator wait a few seconds
191068b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * before SDP. This is due to potential IOP issues if the other
191168b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * end starts doing SDP at the same time as us */
1912e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg	if (bonding) {
1913e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		/* If we are initiators remove any discovery timer and just
1914e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		 * start discovering services directly */
1915e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		if (device->discov_timer) {
1916e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg			g_source_remove(device->discov_timer);
1917e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg			device->discov_timer = 0;
1918e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		}
1919e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg
19202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device_browse(device, bonding->conn, bonding->msg,
19212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				NULL, FALSE);
1922bdf140bd02cee6c39ebb8c6d71ac1d4f6f7eaa07Johan Hedberg	} else if (!device->discov_active && !device->discov_timer &&
1923bdf140bd02cee6c39ebb8c6d71ac1d4f6f7eaa07Johan Hedberg			main_opts.reverse_sdp) {
19242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		/* If we are not initiators and there is no currently active
19252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		 * discovery or discovery timer, set the discovery timer */
19265fe418c129889a18df976050c68a0dab28dc766cMarcel Holtmann		debug("setting timer for reverse service discovery");
19272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->discov_timer = g_timeout_add_seconds(DISCOVERY_TIMER,
19282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						start_discovery,
19292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						device);
1930e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg	}
1931e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg
19322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device_set_paired(device, TRUE);
19332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1934fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg	bonding_request_free(bonding, TRUE);
19352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return;
19372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzfailed:
19392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device_cancel_bonding(device, status);
19402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzgboolean device_is_bonding(struct btd_device *device, const char *sender)
19432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
19452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!device->bonding)
19472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return FALSE;
19482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!sender)
19502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return TRUE;
19512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return g_str_equal(sender, dbus_message_get_sender(bonding->msg));
19532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
1954e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
19552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzvoid device_cancel_bonding(struct btd_device *device, uint8_t status)
19562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
19582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusMessage *reply;
19592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding)
19612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
19622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: canceling bonding request", device->path);
19642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
1966f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg		device_cancel_authentication(device, FALSE);
19672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	reply = new_authentication_return(bonding->msg, status);
19692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_dbus_send_message(bonding->conn, reply);
19702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1971fb6feead6323073b28fc8147aae5c211894d139dJohan Hedberg	bonding_request_free(bonding, TRUE);
19722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,
19752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			void *data)
19762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
19782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
19792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
19812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
19822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
19832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_pincode_cb) auth->cb)(agent, err, pincode, device);
19852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
19872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void confirm_cb(struct agent *agent, DBusError *err, void *data)
19902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
19922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
19932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
19952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
19962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
19972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_cb) auth->cb)(agent, err, device);
19992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
20012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
20042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			void *data)
20052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
20072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
20082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
20102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
20112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
20122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_passkey_cb) auth->cb)(agent, err, passkey, device);
20142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
20162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzint device_request_authentication(struct btd_device *device, auth_type_t type,
20192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				uint32_t passkey, void *cb)
20202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth;
20222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
20232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	int ret;
20242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: requesting agent authentication", device->path);
20262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	agent = device->agent;
20282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent)
20302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		agent = adapter_get_agent(device->adapter);
20312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent) {
20332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("No agent available for %u request", type);
20342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return -EPERM;
20352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
20362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth = g_new0(struct authentication_req, 1);
20382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->agent = agent;
20392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->device = device;
20402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = cb;
20412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->type = type;
20422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->authr = auth;
20432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (type) {
20452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PINCODE:
20462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_request_pincode(agent, device, pincode_cb,
20472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					auth);
20482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PASSKEY:
20502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_request_passkey(agent, device, passkey_cb,
20512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					auth);
20522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_CONFIRM:
20542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_request_confirmation(agent, device, passkey,
20552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					confirm_cb, auth);
20562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_NOTIFY:
20582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = agent_display_passkey(agent, device, passkey);
20592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_AUTO:
20612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = 0;
20622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	default:
20642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		ret = -EINVAL;
20652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
20662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (ret < 0) {
20682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Failed requesting authentication");
20692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_free(auth);
20702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->authr = NULL;
20712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
20722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return ret;
20742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void cancel_authentication(struct authentication_req *auth)
20772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
20792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent = auth->agent;
20802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusError err;
20812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth->cb)
20832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
20842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_error_init(&err);
20862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_set_error_const(&err, "org.bluez.Error.Canceled", NULL);
20872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (auth->type) {
20892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PINCODE:
20902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_pincode_cb) auth->cb)(agent, &err, NULL, device);
20912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_CONFIRM:
20932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_cb) auth->cb)(agent, &err, device);
20942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PASSKEY:
20962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
20972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
20982aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_NOTIFY:
20992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_AUTO:
21002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		/* User Notify/Auto doesn't require any reply */
21012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
21022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
21032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_error_free(&err);
21052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
21062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
21072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2108f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedbergvoid device_cancel_authentication(struct btd_device *device, gboolean aborted)
21092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
21102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = device->authr;
21112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth)
21132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
21142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	debug("%s: canceling authentication request", device->path);
21162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (auth->agent)
21182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		agent_cancel(auth->agent);
21192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2120f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg	if (!aborted)
2121f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg		cancel_authentication(auth);
2122f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg
21232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->authr = NULL;
21242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_free(auth);
21252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
21262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzgboolean device_is_authenticating(struct btd_device *device)
21282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
21292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return (device->authr != NULL);
2130013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
2131013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
2132bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedbergvoid device_set_renewed_key(struct btd_device *device, gboolean renewed)
2133bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg{
2134bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg	device->renewed_key = renewed;
2135bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg}
2136bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
213717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergvoid btd_device_add_uuid(struct btd_device *device, const char *uuid)
213817541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg{
213917541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	GSList *uuid_list;
214017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	char *new_uuid;
214117541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
214217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	if (g_slist_find_custom(device->uuids, uuid,
214317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg				(GCompareFunc) strcasecmp))
214417541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg		return;
214517541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
214617541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	new_uuid = g_strdup(uuid);
214717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	uuid_list = g_slist_append(NULL, new_uuid);
214817541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
214917541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	device_probe_drivers(device, uuid_list);
215017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
21510e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg	g_free(new_uuid);
215217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	g_slist_free(uuid_list);
215317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
21540e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg	store_profiles(device);
215517541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	services_changed(device);
215617541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg}
215717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
2158548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedbergconst sdp_record_t *btd_device_get_record(struct btd_device *device,
2159548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg						const char *uuid)
2160548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg{
2161548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	bdaddr_t src;
2162548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2163548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (device->tmp_records)
2164548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		return find_record_in_list(device->tmp_records, uuid);
2165548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2166548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	adapter_get_address(device->adapter, &src);
2167548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2168548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	device->tmp_records = read_records(&src, &device->bdaddr);
2169548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (!device->tmp_records)
2170548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		return NULL;
2171548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2172548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	return find_record_in_list(device->tmp_records, uuid);
2173548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg}
2174548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2175c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzint btd_register_device_driver(struct btd_device_driver *driver)
2176c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
2177c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_append(device_drivers, driver);
2178c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
2179c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	return 0;
2180c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
2181c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
2182c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzvoid btd_unregister_device_driver(struct btd_device_driver *driver)
2183c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
2184c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_remove(device_drivers, driver);
2185c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
2186