1dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann/*
2dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
3dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann *
55592142cb9383df0556b27ac59e96547b380310bJohan Hedberg *  Copyright (C) 2006-2010  Nokia Corporation
69184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann *  Copyright (C) 2004-2010  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>
341e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg#include <sys/ioctl.h>
351af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg#include <errno.h>
36dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
37dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann#include <bluetooth/bluetooth.h>
38a278db781a26c639267b1d88d5fbe08f99af6c61Elvis Pfützenreuter#include <bluetooth/uuid.h>
395d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp.h>
405d5d89bb2dbc295443900d59d8a7172dc2f279c7Claudio Takahasi#include <bluetooth/sdp_lib.h>
41dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
4286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <glib.h>
4386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include <dbus/dbus.h>
4415ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#include <gdbus.h>
4586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
46e891f7df6225c758da0d95f7554c6cc67f72f31eGustavo F. Padovan#include "log.h"
476a3ea0f9f9aa9dd550f9f2af4a36639961846643Marcel Holtmann#include "textfile.h"
48dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
49d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario#include "att.h"
50506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi#include "hcid.h"
512c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes#include "adapter.h"
5286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann#include "device.h"
53da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi#include "dbus-common.h"
5416d507e0bb939b1c98f9d5ab14c656339757b878Johan Hedberg#include "event.h"
557fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz#include "error.h"
563d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz#include "glib-helper.h"
575399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi#include "gattrib.h"
585399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi#include "gatt.h"
59fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite#include "agent.h"
603d3cdef8da6b3e1b14c3cdccda8c099cbad4f3aeMarcel Holtmann#include "sdp-xml.h"
61506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi#include "storage.h"
6296762463061ffbe566c7f8916d230b4190ec3b6fJohan Hedberg#include "btio.h"
6342d618a69af838356edc566d124b39c405da9495Jaikumar Ganesh#include "../attrib/client.h"
6486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
655d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi#define DISCONNECT_TIMER	2
667ec871d37de442fd3731a0eef319851c61fb04ccLuiz Augusto von Dentz#define DISCOVERY_TIMER		2
67dfc20857eb381b464b8fd6efdaac59e4a15f5d6dMarcel Holtmann
680948c4c0e87f2a4179320e903123acbb296935f6Claudio Takahasi/* When all services should trust a remote device */
690948c4c0e87f2a4179320e903123acbb296935f6Claudio Takahasi#define GLOBAL_TRUST "[all]"
700948c4c0e87f2a4179320e903123acbb296935f6Claudio Takahasi
718d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentzstruct btd_disconnect_data {
728d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	guint id;
738d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	disconnect_watch watch;
748d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	void *user_data;
758d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	GDestroyNotify destroy;
768d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz};
778d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstruct bonding_req {
792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusConnection *conn;
802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusMessage *msg;
812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	GIOChannel *io;
822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	guint listener_id;
832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device;
842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz};
852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstruct authentication_req {
872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth_type_t type;
882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	void *cb;
892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device;
912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz};
922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
93a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentzstruct browse_req {
94a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	DBusConnection *conn;
95a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	DBusMessage *msg;
965399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	GAttrib *attrib;
97a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	struct btd_device *device;
98a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	GSList *match_uuids;
99a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	GSList *profiles_added;
100a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	GSList *profiles_removed;
101a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	sdp_list_t *records;
102a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	int search_uuid;
103a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	int reconnect_attempt;
104a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	guint listener_id;
105a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz};
106a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
107555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestruct btd_device {
108cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t	bdaddr;
109f1beea3e80b6e02f49eeea926d398366b13d291cClaudio Takahasi	device_type_t	type;
110ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	gchar		*path;
11108fef64ca40b85782a0de1c1fd098934355b5e24Johan Hedberg	char		name[MAX_NAME_LENGTH + 1];
11248a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	char		*alias;
11318614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter	*adapter;
114ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	GSList		*uuids;
115b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	GSList		*services;		/* Primary services path */
11683d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes	GSList		*primaries;		/* List of primary services */
117521006ef7b0737739e4e2c66564ed458a348f566Claudio Takahasi	GSList		*drivers;		/* List of device drivers */
1188d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	GSList		*watches;		/* List of disconnect_data */
119ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	gboolean	temporary;
120ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	struct agent	*agent;
121ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode	guint		disconn_timer;
122013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	guint		discov_timer;
123a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	struct browse_req *browse;		/* service discover request */
1242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
1252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *authr;	/* authentication request */
126c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	GSList		*disconnects;		/* disconnects message */
127ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
128bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	gboolean	connected;
129e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
130548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	sdp_list_t	*tmp_records;
131bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
1326da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	gboolean	trusted;
1336fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg	gboolean	paired;
1341e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	gboolean	blocked;
1353e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	gboolean	bonded;
136837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg
137837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg	gboolean	authorizing;
1380ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	gint		ref;
139ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode};
140ea245383ac6650cbf34c327ed095d956b84ac5fbAlok Barsode
141d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmannstatic uint16_t uuid_list[] = {
1420dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	L2CAP_UUID,
1431c284b3ba427638179d936286f4c4866fff99e28Luiz Augusto von Dentz	PNP_INFO_SVCLASS_ID,
1440dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	PUBLIC_BROWSE_GROUP,
145d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann	0
146d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann};
147d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
148c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzstatic GSList *device_drivers = NULL;
149c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
150a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentzstatic void browse_request_free(struct browse_req *req)
151a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz{
152a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (req->listener_id)
153a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		g_dbus_remove_watch(req->conn, req->listener_id);
154a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (req->msg)
155a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		dbus_message_unref(req->msg);
156a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (req->conn)
157a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		dbus_connection_unref(req->conn);
1582499fb1f1775b8afcb374ba3aefc0c5484e78fa4Johan Hedberg	if (req->device)
1592499fb1f1775b8afcb374ba3aefc0c5484e78fa4Johan Hedberg		btd_device_unref(req->device);
160a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	g_slist_foreach(req->profiles_added, (GFunc) g_free, NULL);
161a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	g_slist_free(req->profiles_added);
162a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	g_slist_free(req->profiles_removed);
163a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (req->records)
164a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
1655399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
1661b0d082bf58143aaad02a819037989fddc6c6b95Vinicius Costa Gomes	if (req->attrib)
1675399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		g_attrib_unref(req->attrib);
1685399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
169a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	g_free(req);
170a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz}
171a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
172a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentzstatic void browse_request_cancel(struct browse_req *req)
173a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz{
174a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	struct btd_device *device = req->device;
175a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
176a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	bdaddr_t src;
177a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
1783d8bdaa95b00ee42ecea513ba8d72772c6ffa075Johan Hedberg	if (device_is_creating(device, NULL))
1793d8bdaa95b00ee42ecea513ba8d72772c6ffa075Johan Hedberg		device_set_temporary(device, TRUE);
1803d8bdaa95b00ee42ecea513ba8d72772c6ffa075Johan Hedberg
181a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	adapter_get_address(adapter, &src);
182a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
1835c36b74c0b43ae0532e26c03b6ce8a1abba7d874Claudio Takahasi	bt_cancel_discovery(&src, &device->bdaddr);
184a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
185a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	device->browse = NULL;
1862499fb1f1775b8afcb374ba3aefc0c5484e78fa4Johan Hedberg	browse_request_free(req);
187a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz}
188a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
189e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic void device_free(gpointer user_data)
19086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
191555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
1922f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
1932f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz	struct agent *agent = adapter_get_agent(adapter);
194e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi
195fb27732e05fb7b69c3b784ed8a6aaed2d9d939aeCidorvan Leite	if (device->agent)
196cc35f24a2a728c4e8c31ea0c6c11c6b701901861Johan Hedberg		agent_free(device->agent);
197f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
198929f754fbd780a7e36463fc335f145ed6109ca51Johan Hedberg	if (agent && (agent_is_busy(agent, device) ||
199929f754fbd780a7e36463fc335f145ed6109ca51Johan Hedberg				agent_is_busy(agent, device->authr)))
2002f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz		agent_cancel(agent);
2012f9fbeeb5931cda983aa72ed9a53b1f22d0aa85dLuiz Augusto von Dentz
202b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	g_slist_foreach(device->services, (GFunc) g_free, NULL);
203b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	g_slist_free(device->services);
204b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes
205ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_foreach(device->uuids, (GFunc) g_free, NULL);
206ea00a446dbacead62040dd2bd7e663774c205c04Claudio Takahasi	g_slist_free(device->uuids);
207f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
20883d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes	g_slist_foreach(device->primaries, (GFunc) g_free, NULL);
20983d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes	g_slist_free(device->primaries);
21083d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes
2114bec43039626e853489e72149014868f8c8afedcJohan Hedberg	if (device->tmp_records)
2124bec43039626e853489e72149014868f8c8afedcJohan Hedberg		sdp_list_free(device->tmp_records,
2134bec43039626e853489e72149014868f8c8afedcJohan Hedberg					(sdp_free_func_t) sdp_record_free);
2144bec43039626e853489e72149014868f8c8afedcJohan Hedberg
2155d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi	if (device->disconn_timer)
2165d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi		g_source_remove(device->disconn_timer);
2175d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
21832c90b2a21d936d3881a71c137441e4cb7dd1901Luiz Augusto von Dentz	if (device->discov_timer)
21932c90b2a21d936d3881a71c137441e4cb7dd1901Luiz Augusto von Dentz		g_source_remove(device->discov_timer);
22032c90b2a21d936d3881a71c137441e4cb7dd1901Luiz Augusto von Dentz
2210f775bfff64dc5e073b3bd098c296da4660aa072Luiz Augusto von Dentz	DBG("%p", device);
2220ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
223929f754fbd780a7e36463fc335f145ed6109ca51Johan Hedberg	g_free(device->authr);
22486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device->path);
22548a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	g_free(device->alias);
22686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_free(device);
22786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
22886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
229fee17aefe6b727ec790568aa4994039ff94bf44eJohan Hedberggboolean device_is_paired(struct btd_device *device)
230769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz{
2316fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg	return device->paired;
232769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz}
233769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz
2346da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentzgboolean device_is_trusted(struct btd_device *device)
2356da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz{
2366da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	return device->trusted;
2376da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz}
2386da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz
239e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *get_properties(DBusConnection *conn,
240e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *user_data)
2412c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
242555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
24318614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
2444e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessage *reply;
2454e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter iter;
2464e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	DBusMessageIter dict;
247cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
24808fef64ca40b85782a0de1c1fd098934355b5e24Johan Hedberg	char name[MAX_NAME_LENGTH + 1], srcaddr[18], dstaddr[18];
249b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	char **str;
2502a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	const char *ptr;
2514e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_bool_t boolean;
2524e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	uint32_t class;
253769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	int i;
254769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	GSList *l;
2554e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
256cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
257cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
2584e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	reply = dbus_message_new_method_return(msg);
2594e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	if (!reply)
260e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi		return NULL;
2614e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2624e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
2634e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2644e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
2654e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
2664e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
2674e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
2684e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2694e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Address */
270cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ptr = dstaddr;
2711262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Address", DBUS_TYPE_STRING, &ptr);
2724e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
2734e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Name */
274506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	ptr = NULL;
275506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	memset(name, 0, sizeof(name));
2762a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
277cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
2788a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi
2794d0426730e110b82b1e2d94d62ce57e4fa1b8382Johan Hedberg	ptr = device->name;
2804d0426730e110b82b1e2d94d62ce57e4fa1b8382Johan Hedberg	dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &ptr);
2814e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
282e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby#ifdef ANDROID
283e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby	/* Alias (Android doesn't fallback to name or address) */
284e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby	if (device->alias != NULL) {
285e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby		ptr = device->alias;
286e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby		dict_append_entry(&dict, "Alias", DBUS_TYPE_STRING, &ptr);
287e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby	}
288e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby#else
289afda5bee3495e4fe070cf59e2f240127c341faf4Marcel Holtmann	/* Alias (fallback to name or address) */
29048a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	if (device->alias != NULL)
29148a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz		ptr = device->alias;
29248a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	else if (strlen(ptr) == 0) {
29348a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz		g_strdelimit(dstaddr, ":", '-');
29448a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz		ptr = dstaddr;
29548a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	}
296506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
2974d0426730e110b82b1e2d94d62ce57e4fa1b8382Johan Hedberg	dict_append_entry(&dict, "Alias", DBUS_TYPE_STRING, &ptr);
298e73c02b4397b97f6bc5b7fd862ca3babf18da497Jake Hamby#endif
299506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi
3004e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Class */
301cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
302e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann		const char *icon = class_to_icon(class);
303e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann
3041262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg		dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
305e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann
306e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann		if (icon)
3071262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg			dict_append_entry(&dict, "Icon",
308e1a6c133d7a7fd2acf6d3462d200f47ff6124c1bMarcel Holtmann						DBUS_TYPE_STRING, &icon);
3094e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	}
3104e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
3114e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Paired */
312769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	boolean = device_is_paired(device);
3131262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Paired", DBUS_TYPE_BOOLEAN, &boolean);
3144e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
3154e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Trusted */
3166da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	boolean = device_is_trusted(device);
3171262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Trusted", DBUS_TYPE_BOOLEAN, &boolean);
3184e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
3191e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	/* Blocked */
3201e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	boolean = device->blocked;
3211e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	dict_append_entry(&dict, "Blocked", DBUS_TYPE_BOOLEAN, &boolean);
3221e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
3234e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	/* Connected */
324c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN,
325bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg							&device->connected);
3264e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
327ba93fb91ea81a35be0834ac395650e020a6b3fd3Claudio Takahasi	/* UUIDs */
328b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	str = g_new0(char *, g_slist_length(device->uuids) + 1);
329769c4b021665a26c9a6c20457ef9b7ded54c8ad6Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
330b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes		str[i] = l->data;
331b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING, &str, i);
332b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	g_free(str);
333b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes
334b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	/* Services */
335b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	str = g_new0(char *, g_slist_length(device->services) + 1);
336b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	for (i = 0, l = device->services; l; l = l->next, i++)
337b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes		str[i] = l->data;
338b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	dict_append_array(&dict, "Services", DBUS_TYPE_OBJECT_PATH, &str, i);
339b3d33e592dea372f4e58ed3cf2ad76e7e23aaa10Vinicius Costa Gomes	g_free(str);
3404e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
34174fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz	/* Adapter */
3428a68b5fe931db5a432f924b0de22ed3acee024baClaudio Takahasi	ptr = adapter_get_path(adapter);
3431262c4767c74f084d37c84bec778513f3d862a3eJohan Hedberg	dict_append_entry(&dict, "Adapter", DBUS_TYPE_OBJECT_PATH, &ptr);
34474fdac28eafca963c8081ea39dcf057459cf491aLuiz Augusto von Dentz
3454e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
3464e6726e8029f20be3e08b44760c56fc7a419090bLuiz Augusto von Dentz
347e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return reply;
3482c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
3492c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
350e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,
3517fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz					const char *alias, void *data)
3527fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
353555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
35418614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
355cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
356cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
357506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	int err;
3587fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
35948a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	/* No change */
36048a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	if ((device->alias == NULL && g_str_equal(alias, "")) ||
36148a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz			g_strcmp0(device->alias, alias) == 0)
36248a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz		return dbus_message_new_method_return(msg);
36348a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz
364cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
365cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
366cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
3672a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
368cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	/* Remove alias if empty string */
369cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	err = write_device_alias(srcaddr, dstaddr,
370506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi			g_str_equal(alias, "") ? NULL : alias);
371506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi	if (err < 0)
37292a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan		return btd_error_failed(msg, strerror(-err));
3737fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
37448a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	g_free(device->alias);
37548a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	device->alias = g_str_equal(alias, "") ? NULL : g_strdup(alias);
37648a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz
377c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, dbus_message_get_path(msg),
378c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DEVICE_INTERFACE, "Alias",
379c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DBUS_TYPE_STRING, &alias);
3807fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
381e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
3827fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
3837fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
384e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,
3856da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz					gboolean value, void *data)
3867fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz{
387555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = data;
38818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
389cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
390cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
3916da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	int err;
3926da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz
3936da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	if (device->trusted == value)
3946da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz		return dbus_message_new_method_return(msg);
3952a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
396cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	adapter_get_address(adapter, &src);
397cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
398cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
3992a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
4006da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	err = write_trust(srcaddr, dstaddr, GLOBAL_TRUST, value);
4016da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	if (err < 0)
40292a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan		return btd_error_failed(msg, strerror(-err));
4036da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz
4046da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	device->trusted = value;
4057fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
406c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, dbus_message_get_path(msg),
407c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DEVICE_INTERFACE, "Trusted",
408c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DBUS_TYPE_BOOLEAN, &value);
4097fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
410e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	return dbus_message_new_method_return(msg);
4117fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz}
4127fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
413521006ef7b0737739e4e2c66564ed458a348f566Claudio Takahasistatic void driver_remove(struct btd_device_driver *driver,
4141e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg						struct btd_device *device)
4151e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg{
4161e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	driver->remove(device);
4171e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
418521006ef7b0737739e4e2c66564ed458a348f566Claudio Takahasi	device->drivers = g_slist_remove(device->drivers, driver);
4191e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg}
4201e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4211e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedbergstatic gboolean do_disconnect(gpointer user_data)
4221e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg{
4231e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	struct btd_device *device = user_data;
4241e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4251e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	device->disconn_timer = 0;
4261e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
427bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	btd_adapter_disconnect_device(device->adapter, &device->bdaddr);
4281e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4291e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	return FALSE;
4301e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg}
4311e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4321e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedbergstatic int device_block(DBusConnection *conn, struct btd_device *device)
4331e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg{
434885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg	int err;
4351e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	bdaddr_t src;
4361e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4371e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	if (device->blocked)
4381e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		return 0;
4391e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
440bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	if (device->connected)
4411e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		do_disconnect(device);
4421e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4431e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	g_slist_foreach(device->drivers, (GFunc) driver_remove, device);
4441e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
445885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg	err = btd_adapter_block_address(device->adapter, &device->bdaddr);
446885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg	if (err < 0)
4471e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		return err;
4481e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4491e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	device->blocked = TRUE;
4501e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4511e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	adapter_get_address(device->adapter, &src);
4521e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4531e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	err = write_blocked(&src, &device->bdaddr, TRUE);
4541e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	if (err < 0)
4551e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		error("write_blocked(): %s (%d)", strerror(-err), -err);
4561e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4571e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	device_set_temporary(device, FALSE);
4581e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4591e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Blocked",
4601e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg					DBUS_TYPE_BOOLEAN, &device->blocked);
4611e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4621e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	return 0;
4631e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg}
4641e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
465e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadiusstatic int device_unblock(DBusConnection *conn, struct btd_device *device,
466e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius							gboolean silent)
4671e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg{
468885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg	int err;
4691e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	bdaddr_t src;
4701e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4711e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	if (!device->blocked)
4721e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		return 0;
4731e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
474885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg	err = btd_adapter_unblock_address(device->adapter, &device->bdaddr);
475885c513fdf93404aa713ee6bf4ddb089b42dc5dfJohan Hedberg	if (err < 0)
4761e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		return err;
4771e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4781e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	device->blocked = FALSE;
4791e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4801e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	adapter_get_address(device->adapter, &src);
4811e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4821e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	err = write_blocked(&src, &device->bdaddr, FALSE);
4831e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	if (err < 0)
4841e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		error("write_blocked(): %s (%d)", strerror(-err), -err);
4851e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
486e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius	if (!silent) {
487e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius		emit_property_changed(conn, device->path,
488e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius					DEVICE_INTERFACE, "Blocked",
4891e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg					DBUS_TYPE_BOOLEAN, &device->blocked);
490e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius		device_probe_drivers(device, device->uuids);
491e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius	}
4921e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4931e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	return 0;
4941e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg}
4951e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
4961e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedbergstatic DBusMessage *set_blocked(DBusConnection *conn, DBusMessage *msg,
4971e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg						gboolean value, void *data)
4981e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg{
4991e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	struct btd_device *device = data;
5001e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	int err;
5011e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
5021e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	if (value)
5031e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		err = device_block(conn, device);
5041e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	else
505e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius		err = device_unblock(conn, device, FALSE);
5061e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
5071e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	switch (-err) {
5081e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	case 0:
5091e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		return dbus_message_new_method_return(msg);
5101e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	case EINVAL:
51192a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan		return btd_error_failed(msg, "Kernel lacks blacklist support");
5121e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	default:
51392a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan		return btd_error_failed(msg, strerror(-err));
5141e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	}
5151e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg}
5161e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
517e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic DBusMessage *set_property(DBusConnection *conn,
518e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				DBusMessage *msg, void *data)
5192c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes{
5207fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter iter;
5217fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	DBusMessageIter sub;
5227fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	const char *property;
5237fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5247fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (!dbus_message_iter_init(msg, &iter))
525696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan		return btd_error_invalid_args(msg);
5267fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5277fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
528696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan		return btd_error_invalid_args(msg);
5297fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5307fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_get_basic(&iter, &property);
5317fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_next(&iter);
5327fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5337fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
534696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan		return btd_error_invalid_args(msg);
5357fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	dbus_message_iter_recurse(&iter, &sub);
5367fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5377fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	if (g_str_equal("Trusted", property)) {
5387fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_bool_t value;
5397fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
540696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan			return btd_error_invalid_args(msg);
5417fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &value);
5427fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5437fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_trust(conn, msg, value, data);
5447fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	} else if (g_str_equal("Alias", property)) {
545506c95298346d318304aa7e2211dfba5dbe6e3e0Claudio Takahasi		const char *alias;
5467fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5477fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)
548696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan			return btd_error_invalid_args(msg);
5497fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		dbus_message_iter_get_basic(&sub, &alias);
5507fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
5517fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz		return set_alias(conn, msg, alias, data);
5521e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	} else if (g_str_equal("Blocked", property)) {
5531e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		dbus_bool_t value;
5541e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
5551e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
556696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan			return btd_error_invalid_args(msg);
5571e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
5581e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		dbus_message_iter_get_basic(&sub, &value);
5591e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
5601e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		return set_blocked(conn, msg, value, data);
5617fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz	}
5627fe6ac58638e86d11494f5a785bcf1d074ca2c37Luiz Augusto von Dentz
563696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan	return btd_error_invalid_args(msg);
5642c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes}
5652c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
5661f5107e65f9786bd6b84ecfb4d84691e9b34529aMarcel Holtmannstatic void discover_services_req_exit(DBusConnection *conn, void *user_data)
567342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz{
568e8610fcbe0341a4879b8230d97cd27f5f8cf9f58Luiz Augusto von Dentz	struct browse_req *req = user_data;
5692a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
5708e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan	DBG("DiscoverServices requestor exited");
571e8610fcbe0341a4879b8230d97cd27f5f8cf9f58Luiz Augusto von Dentz
572a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	browse_request_cancel(req);
573342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz}
574342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
57594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *discover_services(DBusConnection *conn,
57694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
57794c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
578555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
57994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	const char *pattern;
580342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	int err;
581342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
582a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (device->browse)
583bd3cf4860d056d3044b7eb8a4e03c53934eb20a6Gustavo F. Padovan		return btd_error_in_progress(msg);
58494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
58594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
58694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						DBUS_TYPE_INVALID) == FALSE)
587a78a0693a6ca2c927a7e88adbef8001f72a16ac1Gustavo F. Padovan		return btd_error_invalid_args(msg);
58894c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
589a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (strlen(pattern) == 0) {
5907e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		err = device_browse_sdp(device, conn, msg, NULL, FALSE);
591342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
592342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
593342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	} else {
594040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		uuid_t uuid;
595040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi
596040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		if (bt_string2uuid(&uuid, pattern) < 0)
597696c18c48f9648274c375a77a70a45f5f31053fbGustavo F. Padovan			return btd_error_invalid_args(msg);
598a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann
5994b1914903cb105acf843b84833e81d5470133879Johan Hedberg		sdp_uuid128_to_uuid(&uuid);
6004b1914903cb105acf843b84833e81d5470133879Johan Hedberg
6017e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		err = device_browse_sdp(device, conn, msg, &uuid, FALSE);
602342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz		if (err < 0)
603342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz			goto fail;
604342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz	}
60594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
60694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return NULL;
607342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
608342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentzfail:
60992a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan	return btd_error_failed(msg, strerror(-err));
61094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
61194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
612a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentzstatic const char *browse_request_get_requestor(struct browse_req *req)
613a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz{
614a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (!req->msg)
615a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		return NULL;
616a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
617a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	return dbus_message_get_sender(req->msg);
618a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz}
619a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
620a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentzstatic void iter_append_record(DBusMessageIter *dict, uint32_t handle,
621a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz							const char *record)
622a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz{
623a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	DBusMessageIter entry;
624a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
625a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
626a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz							NULL, &entry);
627a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
628a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	dbus_message_iter_append_basic(&entry, DBUS_TYPE_UINT32, &handle);
629a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
630a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &record);
631a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
632a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	dbus_message_iter_close_container(dict, &entry);
633a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz}
634a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
635a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentzstatic void discover_services_reply(struct browse_req *req, int err,
636a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz							sdp_list_t *recs)
637a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz{
638a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	DBusMessage *reply;
639a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	DBusMessageIter iter, dict;
640a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	sdp_list_t *seq;
641a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
642a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (err) {
643a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		const char *err_if;
644a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
645a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		if (err == -EHOSTDOWN)
646a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz			err_if = ERROR_INTERFACE ".ConnectionAttemptFailed";
647a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		else
648a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz			err_if = ERROR_INTERFACE ".Failed";
649a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
650a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		reply = dbus_message_new_error(req->msg, err_if,
651a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz							strerror(-err));
652a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		g_dbus_send_message(req->conn, reply);
653a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		return;
654a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	}
655a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
656a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	reply = dbus_message_new_method_return(req->msg);
657a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (!reply)
658a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		return;
659a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
660a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
661a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
662a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
663a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
664a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz			DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_STRING_AS_STRING
665a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
666a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
667a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
668a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
669a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		GString *result;
670a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
671a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		if (!rec)
672a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz			break;
673a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
674a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		result = g_string_new(NULL);
675a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
676a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		convert_sdp_record_to_xml(rec, result,
677a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz				(void *) g_string_append);
678a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
679a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		if (result->len)
680a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz			iter_append_record(&dict, rec->handle, result->str);
681a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
682a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		g_string_free(result, TRUE);
683a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	}
684a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
685a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
686a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
687a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	g_dbus_send_message(req->conn, reply);
688a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz}
689a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
69094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmannstatic DBusMessage *cancel_discover(DBusConnection *conn,
69194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann					DBusMessage *msg, void *user_data)
69294c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
693555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
6947c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg	const char *sender = dbus_message_get_sender(msg);
695a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	const char *requestor;
6962a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
697a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (!device->browse)
6983df548164d179e08032c82b90cc56edbf83ef9bfGustavo F. Padovan		return btd_error_does_not_exist(msg);
699342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
700a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (!dbus_message_is_method_call(device->browse->msg, DEVICE_INTERFACE,
701a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz					"DiscoverServices"))
702b7d1fc1f399e6ea445520b93961f3a11243d8b04Gustavo F. Padovan		return btd_error_not_authorized(msg);
703342293a80657406a02003452e3a23d097dd9c73eLuiz Augusto von Dentz
704a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	requestor = browse_request_get_requestor(device->browse);
705a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
706a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	/* only the discover requestor can cancel the inquiry process */
707a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	if (!requestor || !g_str_equal(requestor, sender))
708b7d1fc1f399e6ea445520b93961f3a11243d8b04Gustavo F. Padovan		return btd_error_not_authorized(msg);
709a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
710a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	discover_services_reply(device->browse, -ECANCELED, NULL);
711a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz
712a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	browse_request_cancel(device->browse);
71394c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
71494c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	return dbus_message_new_method_return(msg);
71594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
71694c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
717c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentzstatic void bonding_request_cancel(struct bonding_req *bonding)
718c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz{
719b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	struct btd_device *device = bonding->device;
720b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	struct btd_adapter *adapter = device->adapter;
721c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
722b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	adapter_cancel_bonding(adapter, &device->bdaddr);
723c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz}
724c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
725c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentzvoid device_request_disconnect(struct btd_device *device, DBusMessage *msg)
7268d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz{
727c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	DBusConnection *conn = get_dbus_connection();
728c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
729c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	if (device->bonding)
730c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz		bonding_request_cancel(device->bonding);
731c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
73288386d8ee86158137eca2cc849f80136af12f635Claudio Takahasi	if (device->browse) {
73388386d8ee86158137eca2cc849f80136af12f635Claudio Takahasi		discover_services_reply(device->browse, -ECANCELED, NULL);
734c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz		browse_request_cancel(device->browse);
73588386d8ee86158137eca2cc849f80136af12f635Claudio Takahasi	}
736c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
737c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	if (msg)
738c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz		device->disconnects = g_slist_append(device->disconnects,
739c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz						dbus_message_ref(msg));
740c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
741c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	if (device->disconn_timer)
742c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz		return;
7438d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
744d5d0fa3be8f7a20d128dcbaf8fc529c38bc52395Johan Hedberg	while (device->watches) {
745d5d0fa3be8f7a20d128dcbaf8fc529c38bc52395Johan Hedberg		struct btd_disconnect_data *data = device->watches->data;
7468d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
7478d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz		if (data->watch)
748a381d5342d27b99612fd31dc9cc80b01f412ad39Luiz Augusto von Dentz			/* temporary is set if device is going to be removed */
749a381d5342d27b99612fd31dc9cc80b01f412ad39Luiz Augusto von Dentz			data->watch(device, device->temporary,
750d5d0fa3be8f7a20d128dcbaf8fc529c38bc52395Johan Hedberg							data->user_data);
7518d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
752b2b27c53f8d1987be3538b227b6fb45eacb0ed5dLuiz Augusto von Dentz		/* Check if the watch has been removed by callback function */
753b2b27c53f8d1987be3538b227b6fb45eacb0ed5dLuiz Augusto von Dentz		if (!g_slist_find(device->watches, data))
754b2b27c53f8d1987be3538b227b6fb45eacb0ed5dLuiz Augusto von Dentz			continue;
755b2b27c53f8d1987be3538b227b6fb45eacb0ed5dLuiz Augusto von Dentz
756d5d0fa3be8f7a20d128dcbaf8fc529c38bc52395Johan Hedberg		device->watches = g_slist_remove(device->watches, data);
757d5d0fa3be8f7a20d128dcbaf8fc529c38bc52395Johan Hedberg		g_free(data);
758d5d0fa3be8f7a20d128dcbaf8fc529c38bc52395Johan Hedberg	}
7598d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
7608d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER,
761c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz						do_disconnect, device);
762c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
763c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	g_dbus_emit_signal(conn, device->path,
764c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz			DEVICE_INTERFACE, "DisconnectRequested",
765c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz			DBUS_TYPE_INVALID);
7668d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz}
7678d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
7687c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedbergstatic DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
7697c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg							void *user_data)
77094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann{
771555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = user_data;
7725d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
773bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	if (!device->connected)
77457c9bf4d916f8fc0ecb8234404a255f0bdee250bGustavo F. Padovan		return btd_error_not_connected(msg);
7755d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
776c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	device_request_disconnect(device, msg);
7775d49d848060b0809a25acb9a20b176600f52e66dClaudio Takahasi
778c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	return NULL;
77994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann}
78094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann
78196c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganeshstatic DBusMessage *get_service_attribute_value_reply(DBusMessage *msg, DBusConnection *conn,
78296c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh							sdp_data_t *attr)
78396c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh{
78496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	DBusMessage *reply;
78596c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	DBusMessageIter iter;
78696c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
78796c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	reply = dbus_message_new_method_return(msg);
78896c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	if (!reply)
789a8e69319f00c3fe65b5f3bce1ea370e3c3eb3582Jing Yu		return NULL;
79096c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	sdp_data_t *curr;
79196c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	sdp_list_t *ap = 0;
79296c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	for (; attr; attr = attr->next) {
79396c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		sdp_list_t *pds = 0;
79496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		for (curr = attr->val.dataseq; curr; curr = curr->next)
79596c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh			pds = sdp_list_append(pds, curr->val.dataseq);
79696c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		ap = sdp_list_append(ap, pds);
79796c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	}
79896c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
79996c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	int ch = sdp_get_proto_port(ap, RFCOMM_UUID);
80096c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	sdp_list_foreach(ap, (sdp_list_func_t) sdp_list_free, NULL);
80196c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	sdp_list_free(ap, NULL);
80296c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	ap = NULL;
80396c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
80496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	dbus_message_append_args(reply, DBUS_TYPE_INT32, &ch, DBUS_TYPE_INVALID);
80596c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
80696c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	return reply;
80796c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh}
80896c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
80996c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganeshstatic DBusMessage *get_service_attribute_value(DBusConnection *conn,
81096c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh						DBusMessage *msg,
81196c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh						void *user_data)
81296c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh{
81396c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	struct btd_device *device = user_data;
81496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	const sdp_record_t *rec;
81596c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	sdp_data_t *attr_data;
81696c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	const char *pattern;
81796c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	uint16_t attrId;
81896c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	int err;
81996c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
82096c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
82196c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh					DBUS_TYPE_UINT16, &attrId,
82296c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh					DBUS_TYPE_INVALID) == FALSE)
82396c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		goto fail;
82496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
82596c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	if (strlen(pattern) == 0)
82696c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		return btd_error_invalid_args(msg);
82796c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
82896c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	rec = btd_device_get_record(device, pattern);
82996c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	if (rec == NULL) {
83096c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		error("rec is NULL");
83196c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		goto fail;
83296c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	}
83396c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
83496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	attr_data = sdp_data_get(rec, attrId);
83596c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
83696c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	if (attr_data == NULL) {
83796c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		error("attr in null");
83896c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh		goto fail;
83996c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	}
84096c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	return get_service_attribute_value_reply(msg, conn, attr_data);
84196c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganeshfail:
84296c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
84396c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh					"GetServiceAttribute Failed");
84496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh}
84596c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh
846e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusMethodTable device_methods[] = {
847e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "GetProperties",	"",	"a{sv}",	get_properties	},
848e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	{ "SetProperty",	"sv",	"",		set_property	},
849e0d13d6da4b527ee02838af6b9dd7d53615e4896Marcel Holtmann	{ "DiscoverServices",	"s",	"a{us}",	discover_services,
85094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann						G_DBUS_METHOD_FLAG_ASYNC},
85194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "CancelDiscovery",	"",	"",		cancel_discover	},
852c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz	{ "Disconnect",		"",	"",		disconnect,
853c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz						G_DBUS_METHOD_FLAG_ASYNC},
85496c354b4b6b1f3480c4129621cf7f82171577057Jaikumar Ganesh	{ "GetServiceAttributeValue",  "sq", "i",       get_service_attribute_value},
85594c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
8562c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
8572c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
858e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasistatic GDBusSignalTable device_signals[] = {
85994c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "PropertyChanged",		"sv"	},
86094c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ "DisconnectRequested",	""	},
86194c199911b1dc1395a8025647f0686f58e6bf4f6Marcel Holtmann	{ }
8622c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes};
8632c1effee41e974f97b21aec1bdd1a232ba48056aVinicius Costa Gomes
864c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentzgboolean device_is_connected(struct btd_device *device)
865e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg{
866bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	return device->connected;
867e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg}
868e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
869bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedbergvoid device_add_connection(struct btd_device *device, DBusConnection *conn)
870c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
871bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	if (device->connected) {
87216348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		char addr[18];
87316348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		ba2str(&device->bdaddr, addr);
874bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg		error("Device %s is already connected", addr);
875c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		return;
876c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	}
877c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
878bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	device->connected = TRUE;
879c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
880b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	emit_property_changed(conn, device->path,
881b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg					DEVICE_INTERFACE, "Connected",
882b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg					DBUS_TYPE_BOOLEAN, &device->connected);
883c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
884c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
885bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedbergvoid device_remove_connection(struct btd_device *device, DBusConnection *conn)
886c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz{
887bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	if (!device->connected) {
88816348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		char addr[18];
88916348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		ba2str(&device->bdaddr, addr);
890bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg		error("Device %s isn't connected", addr);
891c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz		return;
892c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz	}
893c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
894bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	device->connected = FALSE;
895c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
896ff0bc3cc49f697bf1d4b84e3d2be1c338b2ddb09Daniel Orstadius	if (device->disconn_timer > 0) {
897ff0bc3cc49f697bf1d4b84e3d2be1c338b2ddb09Daniel Orstadius		g_source_remove(device->disconn_timer);
898ff0bc3cc49f697bf1d4b84e3d2be1c338b2ddb09Daniel Orstadius		device->disconn_timer = 0;
899ff0bc3cc49f697bf1d4b84e3d2be1c338b2ddb09Daniel Orstadius	}
900ff0bc3cc49f697bf1d4b84e3d2be1c338b2ddb09Daniel Orstadius
9015c60413b3f97c203d164ae717af02de10cfbac34Luiz Augusto von Dentz	while (device->disconnects) {
9025c60413b3f97c203d164ae717af02de10cfbac34Luiz Augusto von Dentz		DBusMessage *msg = device->disconnects->data;
9035c60413b3f97c203d164ae717af02de10cfbac34Luiz Augusto von Dentz
9045c60413b3f97c203d164ae717af02de10cfbac34Luiz Augusto von Dentz		g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
9055c60413b3f97c203d164ae717af02de10cfbac34Luiz Augusto von Dentz		device->disconnects = g_slist_remove(device->disconnects, msg);
9065c60413b3f97c203d164ae717af02de10cfbac34Luiz Augusto von Dentz	}
9075c60413b3f97c203d164ae717af02de10cfbac34Luiz Augusto von Dentz
9083e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	if (device_is_paired(device) && !device->bonded)
9093e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy		device_set_paired(device, FALSE);
9103e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy
911b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	emit_property_changed(conn, device->path,
912b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg					DEVICE_INTERFACE, "Connected",
913b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg					DBUS_TYPE_BOOLEAN, &device->connected);
914c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz}
915c4338c0b7a46d6288e350b8c05fc02ee28b4bdbcLuiz Augusto von Dentz
9168d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentzguint device_add_disconnect_watch(struct btd_device *device,
9178d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz				disconnect_watch watch, void *user_data,
9188d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz				GDestroyNotify destroy)
9198d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz{
9208d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	struct btd_disconnect_data *data;
9218d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	static guint id = 0;
9228d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
9238d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	data = g_new0(struct btd_disconnect_data, 1);
9248d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	data->id = ++id;
9258d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	data->watch = watch;
9268d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	data->user_data = user_data;
9278d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	data->destroy = destroy;
9288d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
9298d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	device->watches = g_slist_append(device->watches, data);
9308d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
9318d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	return data->id;
9328d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz}
9338d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
9348d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentzvoid device_remove_disconnect_watch(struct btd_device *device, guint id)
9358d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz{
9368d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	GSList *l;
9378d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
9388d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	for (l = device->watches; l; l = l->next) {
9398d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz		struct btd_disconnect_data *data = l->data;
9408d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
9418d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz		if (data->id == id) {
9428d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz			device->watches = g_slist_remove(device->watches,
9438d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz							data);
9448d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz			if (data->destroy)
9458d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz				data->destroy(data->user_data);
9468d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz			g_free(data);
9478d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz			return;
9488d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz		}
9498d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	}
9508d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz}
9518d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz
9527c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedbergstruct btd_device *device_create(DBusConnection *conn,
953f1beea3e80b6e02f49eeea926d398366b13d291cClaudio Takahasi				struct btd_adapter *adapter,
954f1beea3e80b6e02f49eeea926d398366b13d291cClaudio Takahasi				const gchar *address, device_type_t type)
95586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann{
956ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	gchar *address_up;
957555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device;
958139c2014be451848fcc3fa31cdc07653148f596eMarcel Holtmann	const gchar *adapter_path = adapter_get_path(adapter);
959a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	bdaddr_t src;
96048a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	char srcaddr[18], alias[MAX_NAME_LENGTH + 1];
96186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
962555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	device = g_try_malloc0(sizeof(struct btd_device));
96386892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	if (device == NULL)
96486892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
96586892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
966ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	address_up = g_ascii_strup(address, -1);
967139c2014be451848fcc3fa31cdc07653148f596eMarcel Holtmann	device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up);
96886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	g_strdelimit(device->path, ":", '_');
969ecbcc749831ab86da7ed8d15c36f1bd1fb380be8Cidorvan Leite	g_free(address_up);
97086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
9718e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan	DBG("Creating device %s", device->path);
97286892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
973e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi	if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE,
974e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device_methods, device_signals, NULL,
975e2731d4c2e3ef7d1677a73aca5fa58f044075980Claudio Takahasi				device, device_free) == FALSE) {
97686892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		device_free(device);
97786892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann		return NULL;
97886892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann	}
979da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
980cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	str2ba(address, &device->bdaddr);
981da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi	device->adapter = adapter;
982f1beea3e80b6e02f49eeea926d398366b13d291cClaudio Takahasi	device->type = type;
983a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	adapter_get_address(adapter, &src);
984a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	ba2str(&src, srcaddr);
985a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	read_device_name(srcaddr, address, device->name);
98648a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	if (read_device_alias(srcaddr, address, alias, sizeof(alias)) == 0)
98748a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz		device->alias = g_strdup(alias);
9886da6e4e3de7f1800e5b736add0b944d33d3acf37Luiz Augusto von Dentz	device->trusted = read_trust(&src, address, GLOBAL_TRUST);
989da0e7105811dc046d13d0365404efc1189ee4a8cClaudio Takahasi
9901e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	if (read_blocked(&src, &device->bdaddr))
9911e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		device_block(conn, device);
9921e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
9933e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	if (read_link_key(&src, &device->bdaddr, NULL, NULL) == 0) {
9946fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg		device->paired = TRUE;
9953e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy		device_set_bonded(device, TRUE);
9963e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	}
9976fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg
9980ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	return btd_device_ref(device);
99986892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
100086892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann
1001a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentzvoid device_set_name(struct btd_device *device, const char *name)
1002a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz{
1003a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	DBusConnection *conn = get_dbus_connection();
1004a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
100508fef64ca40b85782a0de1c1fd098934355b5e24Johan Hedberg	if (strncmp(name, device->name, MAX_NAME_LENGTH) == 0)
1006a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz		return;
1007a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
100808fef64ca40b85782a0de1c1fd098934355b5e24Johan Hedberg	strncpy(device->name, name, MAX_NAME_LENGTH);
1009a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
1010a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	emit_property_changed(conn, device->path,
1011a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DEVICE_INTERFACE, "Name",
1012a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DBUS_TYPE_STRING, &name);
1013a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
101448a2c31cdbc1f2ac2a2bbadbd505976f84a9eacaLuiz Augusto von Dentz	if (device->alias != NULL)
1015a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz		return;
1016a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
1017a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz	emit_property_changed(conn, device->path,
1018a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DEVICE_INTERFACE, "Alias",
1019a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz				DBUS_TYPE_STRING, &name);
1020a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz}
1021a721957f20ec79b1a19537e5c43d3a12e4286c6cLuiz Augusto von Dentz
10225d787d0c25ea650672d93459d7a898491f0b6344Johan Hedbergvoid device_get_name(struct btd_device *device, char *name, size_t len)
10235d787d0c25ea650672d93459d7a898491f0b6344Johan Hedberg{
10245d787d0c25ea650672d93459d7a898491f0b6344Johan Hedberg	strncpy(name, device->name, len);
10255d787d0c25ea650672d93459d7a898491f0b6344Johan Hedberg}
10265d787d0c25ea650672d93459d7a898491f0b6344Johan Hedberg
10277e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demariodevice_type_t device_get_type(struct btd_device *device)
10287e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario{
10297e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	return device->type;
10307e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario}
10317e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario
1032b31576d0de87754f2fa1c3ba2d231cdccbffaee1Luiz Augusto von Dentzvoid device_remove_bonding(struct btd_device *device)
10332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
10342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char filename[PATH_MAX + 1];
1035204ab018f03d0d65f07b19cf4f777660b7d54249Claudio Takahasi	char srcaddr[18], dstaddr[18];
10362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bdaddr_t bdaddr;
10372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
10382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	adapter_get_address(device->adapter, &bdaddr);
10392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&bdaddr, srcaddr);
10402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&device->bdaddr, dstaddr);
10412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
10422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
10432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			"linkkeys");
10442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1045204ab018f03d0d65f07b19cf4f777660b7d54249Claudio Takahasi	/* Delete the link key from storage */
1046204ab018f03d0d65f07b19cf4f777660b7d54249Claudio Takahasi	textfile_casedel(filename, dstaddr);
10473e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	device_set_bonded(device, FALSE);
10482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
10491bf7ec6b5c5a786775813650a6ef00f47b4d11ecJohan Hedberg	btd_adapter_remove_bonding(device->adapter, &device->bdaddr);
10502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
10512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
1052204ab018f03d0d65f07b19cf4f777660b7d54249Claudio Takahasistatic void device_remove_stored(struct btd_device *device)
10537dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz{
10547dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	bdaddr_t src;
10557dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	char addr[18];
1056e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius	DBusConnection *conn = get_dbus_connection();
10577dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz
10587dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	adapter_get_address(device->adapter, &src);
10597dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	ba2str(&device->bdaddr, addr);
1060e9071e3bfdf24666ff126d0023f3f4cf2ca74b2fJaikumar Ganesh
10616fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg	if (device->paired)
10626fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg		device_remove_bonding(device);
10637dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	delete_entry(&src, "profiles", addr);
10647dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz	delete_entry(&src, "trusts", addr);
10655ae3733f9c81cd590e735a1e2cac1f261e881f9aVinicius Costa Gomes	delete_entry(&src, "types", addr);
10665ae3733f9c81cd590e735a1e2cac1f261e881f9aVinicius Costa Gomes	delete_entry(&src, "primary", addr);
1067e9071e3bfdf24666ff126d0023f3f4cf2ca74b2fJaikumar Ganesh	delete_all_records(&src, &device->bdaddr);
1068727ae28e17be0910c9d5cdba6c8e373a704f7dbfClaudio Takahasi	delete_device_service(&src, &device->bdaddr);
1069e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius
1070e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius	if (device->blocked)
1071e0eddab0745f605fba545d03e84ed13769d744c8Daniel Orstadius		device_unblock(conn, device, TRUE);
10727dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz}
10737dfdd472eed6368bbae14aa989e712a49f3e7f12Luiz Augusto von Dentz
1074204ab018f03d0d65f07b19cf4f777660b7d54249Claudio Takahasivoid device_remove(struct btd_device *device, gboolean remove_stored)
107575add5651e5dbc49c9c144acceac7e2c32d9bd16Claudio Takahasi{
1076f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
10778e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan	DBG("Removing device %s", device->path);
1078f62f8d892b5d5cc5aedef83779671c1ed54a35daMarcel Holtmann
107950996c3a0b0eb98f3cb1c202257d063992c7220dJohan Hedberg	if (device->agent)
108050996c3a0b0eb98f3cb1c202257d063992c7220dJohan Hedberg		agent_free(device->agent);
108150996c3a0b0eb98f3cb1c202257d063992c7220dJohan Hedberg
1082253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg	if (device->bonding) {
1083253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg		uint8_t status;
1084253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg
1085253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg		if (device->connected)
1086253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg			status = HCI_OE_USER_ENDED_CONNECTION;
1087253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg		else
1088253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg			status = HCI_PAGE_TIMEOUT;
1089253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg
1090253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg		device_cancel_bonding(device, status);
1091253209e37f869638caec4f9ab9a7e45586380c07Johan Hedberg	}
10922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
109388386d8ee86158137eca2cc849f80136af12f635Claudio Takahasi	if (device->browse) {
109488386d8ee86158137eca2cc849f80136af12f635Claudio Takahasi		discover_services_reply(device->browse, -ECANCELED, NULL);
1095c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz		browse_request_cancel(device->browse);
109688386d8ee86158137eca2cc849f80136af12f635Claudio Takahasi	}
1097c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
1098bda6bb0079268b7db27695f40168aba07e960d8bJohan Hedberg	if (device->connected)
109902d1a26d52d077c2b61c740fff96a28a940fee6fLuiz Augusto von Dentz		do_disconnect(device);
1100c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz
110104e2e66722dfc8f26b159bdd280c981d9903258cLuiz Augusto von Dentz	if (remove_stored)
1102204ab018f03d0d65f07b19cf4f777660b7d54249Claudio Takahasi		device_remove_stored(device);
11032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
11046c212766c4e44ea1b47be61c2eb34a02ba50b81aJohan Hedberg	g_slist_foreach(device->drivers, (GFunc) driver_remove, device);
11051e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	g_slist_free(device->drivers);
11061e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	device->drivers = NULL;
11076061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann
1108279a53827334deab5093876e27261d38937bda36Vinicius Costa Gomes	attrib_client_unregister(device);
1109279a53827334deab5093876e27261d38937bda36Vinicius Costa Gomes
11100ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	btd_device_unref(device);
111186892be8d38960096f9b9c5613ba28fc9003d288Marcel Holtmann}
1112ff296428a08dee619db1cc702146faefa91087faCidorvan Leite
1113555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegint device_address_cmp(struct btd_device *device, const gchar *address)
1114ff296428a08dee619db1cc702146faefa91087faCidorvan Leite{
1115cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char addr[18];
1116cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode
1117cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, addr);
1118cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	return strcasecmp(addr, address);
1119ff296428a08dee619db1cc702146faefa91087faCidorvan Leite}
11203d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
11213870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedbergstatic gboolean record_has_uuid(const sdp_record_t *rec,
11223870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg				const char *profile_uuid)
1123f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
11243870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	sdp_list_t *pat;
1125f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
11263870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	for (pat = rec->pattern; pat != NULL; pat = pat->next) {
1127f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		char *uuid;
11283870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		int ret;
1129f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
11303870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		uuid = bt_uuid2string(pat->data);
1131f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!uuid)
1132f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
1133f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
11343870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		ret = strcasecmp(uuid, profile_uuid);
1135f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
11363870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		g_free(uuid);
11373870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg
11383870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg		if (ret == 0)
11393870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg			return TRUE;
1140f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	}
1141f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
11423870d6ab80711042b0c9224eac34293cb6b16aeaJohan Hedberg	return FALSE;
1143f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
1144f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1145f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzstatic GSList *device_match_pattern(struct btd_device *device,
1146878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg					const char *match_uuid,
1147f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					GSList *profiles)
1148f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
1149f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *l, *uuids = NULL;
1150f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1151f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (l = profiles; l; l = l->next) {
1152878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg		char *profile_uuid = l->data;
1153f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		const sdp_record_t *rec;
11543bb7c1527ce3ec67127200b54a8fbc01a196ebadJohan Hedberg
1155878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg		rec = btd_device_get_record(device, profile_uuid);
1156f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!rec)
1157f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
1158f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1159a01801fd21056ef6f7fffc6a205b6c2b9e99899fJohan Hedberg		if (record_has_uuid(rec, match_uuid))
1160878dee664d16eb6643e0ba2d5d9c2452f98f172eJohan Hedberg			uuids = g_slist_append(uuids, profile_uuid);
1161cdfe8a8246013031f55c647092e41adbb29ace81Johan Hedberg	}
1162f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1163f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	return uuids;
1164f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
1165f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1166f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzstatic GSList *device_match_driver(struct btd_device *device,
1167f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					struct btd_device_driver *driver,
1168f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					GSList *profiles)
1169f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann{
11706061f1a889c90d4d408ca12b63b2db6235c73baeMarcel Holtmann	const char **uuid;
1171f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *uuids = NULL;
1172f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1173f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (uuid = driver->uuids; *uuid; uuid++) {
1174f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		GSList *match;
1175f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
11769b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz		/* skip duplicated uuids */
11779b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz		if (g_slist_find_custom(uuids, *uuid,
11789b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz				(GCompareFunc) strcasecmp))
11799b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz			continue;
11809b953c8757093b51eb86e6593d514e9839fd8d7dLuiz Augusto von Dentz
1181f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		/* match profile driver */
1182f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		match = g_slist_find_custom(profiles, *uuid,
1183f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz					(GCompareFunc) strcasecmp);
1184f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (match) {
1185f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			uuids = g_slist_append(uuids, match->data);
1186f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
1187f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		}
1188f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1189f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		/* match pattern driver */
1190f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		match = device_match_pattern(device, *uuid, profiles);
1191b358f4f350211dfd9d52a0b4fbc611b0c711bcddClaudio Takahasi		uuids = g_slist_concat(uuids, match);
1192f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	}
1193f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1194f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	return uuids;
1195f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz}
1196f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1197f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentzvoid device_probe_drivers(struct btd_device *device, GSList *profiles)
1198f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz{
1199f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	GSList *list;
120016348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	char addr[18];
1201f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	int err;
1202f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
120316348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	ba2str(&device->bdaddr, addr);
120416348199ed59c49a710805a5061c3f22477715bfJohan Hedberg
12051e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	if (device->blocked) {
120616348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		DBG("Skipping drivers for blocked device %s", addr);
12071e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg		goto add_uuids;
12081e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg	}
12091e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedberg
121016348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	DBG("Probing drivers for %s", addr);
1211f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
1212c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	for (list = device_drivers; list; list = list->next) {
1213e0863545e6239ac338fa7fbe9647a5748a60b436Marcel Holtmann		struct btd_device_driver *driver = list->data;
1214f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		GSList *probe_uuids;
1215f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
1216f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		probe_uuids = device_match_driver(device, driver, profiles);
12174b0ab7e43f4fa555641902b07f2f7ab3821f2b75Alok Barsode
1218f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (!probe_uuids)
1219f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
1220081d9d1df3cde11e3e3833201f4cadac6f355da0Luiz Augusto von Dentz
1221f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		err = driver->probe(device, probe_uuids);
1222f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		if (err < 0) {
122316348199ed59c49a710805a5061c3f22477715bfJohan Hedberg			error("%s driver probe failed for device %s",
122416348199ed59c49a710805a5061c3f22477715bfJohan Hedberg							driver->name, addr);
1225548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg			g_slist_free(probe_uuids);
1226f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz			continue;
1227f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann		}
1228f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz
1229521006ef7b0737739e4e2c66564ed458a348f566Claudio Takahasi		device->drivers = g_slist_append(device->drivers, driver);
1230f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz		g_slist_free(probe_uuids);
1231f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann	}
123236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
12331e4d4fe0ed499adaf3e61b1e593dccd3c0928158Johan Hedbergadd_uuids:
1234f1c3d8c1fabd801eac34c9069038d3f4cadcb58dLuiz Augusto von Dentz	for (list = profiles; list; list = list->next) {
1235c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		GSList *l = g_slist_find_custom(device->uuids, list->data,
12367c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						(GCompareFunc) strcasecmp);
1237c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		if (l)
1238c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann			continue;
1239c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann
124036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		device->uuids = g_slist_insert_sorted(device->uuids,
12417c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						g_strdup(list->data),
12427c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						(GCompareFunc) strcasecmp);
1243548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	}
124436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
124536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
124699bc055edc4b9ba8ccda791757a6439fb03ff8f2Marcel Holtmannstatic void device_remove_drivers(struct btd_device *device, GSList *uuids)
124736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
124818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
1249352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg	GSList *list, *next;
1250cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
12512a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
1252548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	sdp_list_t *records;
12532a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
12542a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
1255cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
1256cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
125736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
1258548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	records = read_records(&src, &device->bdaddr);
1259548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
126016348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	DBG("Removing drivers for %s", dstaddr);
126136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
1262352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg	for (list = device->drivers; list; list = next) {
1263521006ef7b0737739e4e2c66564ed458a348f566Claudio Takahasi		struct btd_device_driver *driver = list->data;
126436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		const char **uuid;
126536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
1266352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg		next = list->next;
1267352a65d3de4fdf6e1e507f958685097f33e3b899Johan Hedberg
126836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		for (uuid = driver->uuids; *uuid; uuid++) {
12699b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz			if (!g_slist_find_custom(uuids, *uuid,
1270155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh						(GCompareFunc) strcasecmp))
127136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz				continue;
127236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
12738e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan			DBG("UUID %s was removed from device %s",
12747c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg							*uuid, dstaddr);
1275548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
1276e780c7bd8ec0527723db3c19f28365063bbe7d93Luiz Augusto von Dentz			driver->remove(device);
127736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			device->drivers = g_slist_remove(device->drivers,
1278521006ef7b0737739e4e2c66564ed458a348f566Claudio Takahasi								driver);
1279155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh			break;
1280155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		}
1281155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh	}
12829b4bfa74d25e360932402994a32305bf2145eb34Luiz Augusto von Dentz
1283155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh	for (list = uuids; list; list = list->next) {
1284155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		sdp_record_t *rec;
1285548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
1286155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		device->uuids = g_slist_remove(device->uuids, list->data);
1287155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh
1288155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		rec = find_record_in_list(records, list->data);
1289155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		if (!rec)
1290155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh			continue;
1291155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh
1292155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		delete_record(srcaddr, dstaddr, rec->handle);
1293155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh
1294155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		records = sdp_list_remove(records, rec);
1295155e4e6fe2af8d662e26843c5fc15e6814622ddbJaikumar Ganesh		sdp_record_free(rec);
12962d370d5d678973644c2c3c75b22d5f24b7a2c638Johan Hedberg
129736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
129836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
1299548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (records)
1300548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		sdp_list_free(records, (sdp_free_func_t) sdp_record_free);
1301f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann}
1302f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
130317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergstatic void services_changed(struct btd_device *device)
13043d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
1305533655873c4978091edf3698b20d2b96c43dafc8Johan Hedberg	DBusConnection *conn = get_dbus_connection();
13063d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	char **uuids;
13073d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	GSList *l;
130836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	int i;
13093d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
131036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
131136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (i = 0, l = device->uuids; l; l = l->next, i++)
131236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		uuids[i] = l->data;
131336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
131458f06324289d7d343a52a9104d02121cb8db1047Johan Hedberg	emit_array_property_changed(conn, device->path, DEVICE_INTERFACE,
1315d5e700051b1263b2028331d41d60de02a5a6f90eVinicius Costa Gomes					"UUIDs", DBUS_TYPE_STRING, &uuids, i);
131636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
131736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(uuids);
131836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
131936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
13208b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedbergstatic int rec_cmp(const void *a, const void *b)
13218b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg{
13228b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r1 = a;
13238b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	const sdp_record_t *r2 = b;
13248b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
13258b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg	return r1->handle - r2->handle;
13268b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg}
13278b2e688eaf5b71006c72cf91a8e4df3c0c41c306Johan Hedberg
132836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentzstatic void update_services(struct browse_req *req, sdp_list_t *recs)
132936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
1330555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
133118614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device_get_adapter(device);
133236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	sdp_list_t *seq;
1333cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	char srcaddr[18], dstaddr[18];
13342a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	bdaddr_t src;
13352a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
13362a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
1337cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&src, srcaddr);
1338cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	ba2str(&device->bdaddr, dstaddr);
13393d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
134036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	for (seq = recs; seq; seq = seq->next) {
13413d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		sdp_record_t *rec = (sdp_record_t *) seq->data;
134236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_t *svcclass = NULL;
13430dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		gchar *profile_uuid;
134436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		GSList *l;
13453d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
13463d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		if (!rec)
13473d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz			break;
13483d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
134936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (sdp_get_service_classes(rec, &svcclass) < 0)
135036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
135136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
135223844f34167a89b687970d308e2620f8e106f8dfJohan Hedberg		/* Check for empty service classes list */
135323844f34167a89b687970d308e2620f8e106f8dfJohan Hedberg		if (svcclass == NULL) {
13548e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan			DBG("Skipping record with no service classes");
135523844f34167a89b687970d308e2620f8e106f8dfJohan Hedberg			continue;
135623844f34167a89b687970d308e2620f8e106f8dfJohan Hedberg		}
135723844f34167a89b687970d308e2620f8e106f8dfJohan Hedberg
135836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		/* Extract the first element and skip the remainning */
13590dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		profile_uuid = bt_uuid2string(svcclass->data);
13600dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		if (!profile_uuid) {
1361aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg			sdp_list_free(svcclass, free);
136236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz			continue;
1363aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg		}
136436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
13650dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		if (!strcasecmp(profile_uuid, PNP_UUID)) {
1366fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			uint16_t source, vendor, product, version;
1367e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			sdp_data_t *pdlist;
1368e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1369fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID_SOURCE);
1370fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			source = pdlist ? pdlist->val.uint16 : 0x0000;
1371fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann
1372e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
1373e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			vendor = pdlist ? pdlist->val.uint16 : 0x0000;
1374e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1375e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
1376e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			product = pdlist ? pdlist->val.uint16 : 0x0000;
1377e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1378e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
1379e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse			version = pdlist ? pdlist->val.uint16 : 0x0000;
1380e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
1381fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann			if (source || vendor || product || version)
1382fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann				store_device_id(srcaddr, dstaddr, source,
1383fce6db565f747ca9ad560f7d8bff6a45522d905cMarcel Holtmann						vendor, product, version);
1384e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse		}
1385e2a5786af8c8278eeeb0bedccda32c7422e9a2b7David Woodhouse
138637a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg		/* Check for duplicates */
1387981f4416220e01a3eab92aa3c8d03c16dcad450dJohan Hedberg		if (sdp_list_find(req->records, rec, rec_cmp)) {
13880dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			g_free(profile_uuid);
1389aaf0f75d2a18a86bca3c418ddd63e936627c4446Johan Hedberg			sdp_list_free(svcclass, free);
139037a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg			continue;
1391981f4416220e01a3eab92aa3c8d03c16dcad450dJohan Hedberg		}
139237a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
1393cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		store_record(srcaddr, dstaddr, rec);
139437a7d2aba17bcb47a3e9bfba78ad23a8a3cbe420Johan Hedberg
1395681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		/* Copy record */
13967c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg		req->records = sdp_list_append(req->records,
13977c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg							sdp_copy_record(rec));
1398681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz
13990dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		l = g_slist_find_custom(device->uuids, profile_uuid,
1400c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann							(GCompareFunc) strcmp);
140136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		if (!l)
14020dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			req->profiles_added =
14030dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg					g_slist_append(req->profiles_added,
14040dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg							profile_uuid);
140536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		else {
14060dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			req->profiles_removed =
14070dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg					g_slist_remove(req->profiles_removed,
14080dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg							l->data);
14090dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg			g_free(profile_uuid);
14103d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz		}
14113d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
141236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		sdp_list_free(svcclass, free);
14133d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	}
141436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
141536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
141617541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergstatic void store_profiles(struct btd_device *device)
141736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
141818614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
1419cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
142036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	char *str;
14213d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
14222a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
14233d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
142436dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	if (!device->uuids) {
1425cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode		write_device_profiles(&src, &device->bdaddr, "");
142636dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz		return;
142736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	}
142836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
142936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	str = bt_list2string(device->uuids);
1430cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	write_device_profiles(&src, &device->bdaddr, str);
143136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	g_free(str);
143236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz}
143336dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
143432c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadiusstatic void create_device_reply(struct btd_device *device, struct browse_req *req)
143532c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius{
143632c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	DBusMessage *reply;
143732c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius
143832c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	reply = dbus_message_new_method_return(req->msg);
143932c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	if (!reply)
144032c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		return;
144132c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius
144232c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &device->path,
144332c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius					DBUS_TYPE_INVALID);
144432c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius
144532c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	g_dbus_send_message(req->conn, reply);
144632c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius}
144732c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius
1448d14f607a0374bc313e410987ddd357581336003eClaudio TakahasiGSList *device_services_from_record(struct btd_device *device, GSList *profiles)
1449612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi{
1450612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	GSList *l, *prim_list = NULL;
1451612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	char *att_uuid;
1452612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	uuid_t proto_uuid;
1453612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1454612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	sdp_uuid16_create(&proto_uuid, ATT_UUID);
1455612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	att_uuid = bt_uuid2string(&proto_uuid);
1456612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1457612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	for (l = profiles; l; l = l->next) {
1458612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		const char *profile_uuid = l->data;
1459612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		const sdp_record_t *rec;
1460612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		struct att_primary *prim;
1461612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		uint16_t start = 0, end = 0, psm = 0;
1462612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		uuid_t prim_uuid;
1463612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1464612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		rec = btd_device_get_record(device, profile_uuid);
1465612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		if (!rec)
1466612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi			continue;
1467612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1468612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		if (!record_has_uuid(rec, att_uuid))
1469612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi			continue;
1470612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1471612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		if (!gatt_parse_record(rec, &prim_uuid, &psm, &start, &end))
1472612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi			continue;
1473612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1474612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		prim = g_new0(struct att_primary, 1);
1475612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		prim->start = start;
1476612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		prim->end = end;
1477612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		sdp_uuid2strn(&prim_uuid, prim->uuid, sizeof(prim->uuid));
1478612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1479612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		prim_list = g_slist_append(prim_list, prim);
1480612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	}
1481612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1482612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	g_free(att_uuid);
1483612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1484612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	return prim_list;
1485612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi}
1486612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
1487da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void search_cb(sdp_list_t *recs, int err, gpointer user_data)
148836dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz{
148936dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	struct browse_req *req = user_data;
1490555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsode	struct btd_device *device = req->device;
149116348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	char addr[18];
149216348199ed59c49a710805a5061c3f22477715bfJohan Hedberg
149316348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	ba2str(&device->bdaddr, addr);
14942a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
1495681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	if (err < 0) {
1496681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz		error("%s: error updating services: %s (%d)",
149716348199ed59c49a710805a5061c3f22477715bfJohan Hedberg				addr, strerror(-err), -err);
149832c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		goto send_reply;
1499681e50c618d246483728bca6628a18c1c44c5b36Luiz Augusto von Dentz	}
150036dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
150136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	update_services(req, recs);
150236dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz
150345bc7305c6e0baeb6d0a3591e8622ef7c7135d74Luiz Augusto von Dentz	if (device->tmp_records)
15047c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg		sdp_list_free(device->tmp_records,
15057c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg					(sdp_free_func_t) sdp_record_free);
150645bc7305c6e0baeb6d0a3591e8622ef7c7135d74Luiz Augusto von Dentz
150745bc7305c6e0baeb6d0a3591e8622ef7c7135d74Luiz Augusto von Dentz	device->tmp_records = req->records;
150845bc7305c6e0baeb6d0a3591e8622ef7c7135d74Luiz Augusto von Dentz	req->records = NULL;
1509548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
1510cfea4ccc6fc8e014bfbd5bb80de0a2b854fc373bJaikumar Ganesh	if (!req->profiles_added && !req->profiles_removed) {
151116348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		DBG("%s: No service update", addr);
151232c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		goto send_reply;
1513cfea4ccc6fc8e014bfbd5bb80de0a2b854fc373bJaikumar Ganesh	}
1514cfea4ccc6fc8e014bfbd5bb80de0a2b854fc373bJaikumar Ganesh
151536dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Probe matching drivers for services added */
1516612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	if (req->profiles_added) {
1517612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		GSList *list;
1518612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
15190dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		device_probe_drivers(device, req->profiles_added);
15202efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
1521d14f607a0374bc313e410987ddd357581336003eClaudio Takahasi		list = device_services_from_record(device, req->profiles_added);
1522612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi		if (list)
15231f8969c0435f8d49c20f46dba9bece21031997c7Johan Hedberg			device_register_services(req->conn, device, list,
15241f8969c0435f8d49c20f46dba9bece21031997c7Johan Hedberg								ATT_PSM);
1525612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi	}
1526612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi
152736dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Remove drivers for services removed */
15280dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg	if (req->profiles_removed)
15290dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		device_remove_drivers(device, req->profiles_removed);
15302efdbe3a944fb2c8c6e0f581b899140b4ef84bcbLuiz Augusto von Dentz
153136dedff329b5ced8979a2161075e6a9d38c58785Luiz Augusto von Dentz	/* Propagate services changes */
153217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	services_changed(req->device);
1533f4eb9e2dea643f41e261bb9e2bff33fc03bd9eccMarcel Holtmann
153432c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadiussend_reply:
15352ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg	if (!req->msg)
15362ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg		goto cleanup;
15372ba670eae0d7d0d57160b7e5bd387079f86d933cJohan Hedberg
1538438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz	if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
153932c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius					"DiscoverServices"))
154045bc7305c6e0baeb6d0a3591e8622ef7c7135d74Luiz Augusto von Dentz		discover_services_reply(req, err, device->tmp_records);
154132c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	else if (dbus_message_is_method_call(req->msg, ADAPTER_INTERFACE,
154232c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius						"CreatePairedDevice"))
154332c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		create_device_reply(device, req);
154432c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	else if (dbus_message_is_method_call(req->msg, ADAPTER_INTERFACE,
154532c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius						"CreateDevice")) {
154632c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		if (err < 0) {
154792a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan			DBusMessage *reply;
154892a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan			reply = btd_error_failed(req->msg, strerror(-err));
154992a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan			g_dbus_send_message(req->conn, reply);
155032c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius			goto cleanup;
155132c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		}
15523d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
155332c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		create_device_reply(device, req);
155432c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		device_set_temporary(device, FALSE);
155532c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius	}
1556048cda340a2e17a89cab71e8c40ff9a1c66ea5c1Luiz Augusto von Dentz
15571e8fbfbfa6fbcf88a668f77e5601bbc505eb483fLuiz Augusto von Dentzcleanup:
155827b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes	if (!device->temporary) {
155927b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes		bdaddr_t sba, dba;
156027b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes
156127b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes		adapter_get_address(device->adapter, &sba);
156227b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes		device_get_address(device, &dba);
156327b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes
156432c43b955601343cbaa041be0ec1c8671071db5cDaniel Orstadius		store_profiles(device);
156527b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes		write_device_type(&sba, &dba, device->type);
156627b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes	}
156727b16a98221951d9fb931e46b8af65bd8d185324Vinicius Costa Gomes
1568a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	device->browse = NULL;
15692499fb1f1775b8afcb374ba3aefc0c5484e78fa4Johan Hedberg	browse_request_free(req);
1570da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
1571da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1572da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzstatic void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
1573da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
1574da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct browse_req *req = user_data;
1575da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_device *device = req->device;
1576da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
1577cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
1578da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	uuid_t uuid;
1579da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
15807c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg	/* If we have a valid response and req->search_uuid == 2, then L2CAP
15817c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg	 * UUID & PNP searching was successful -- we are done */
15820cd8e651b6f004bcc64387d59f6bcb29190ffed6Johan Hedberg	if (err < 0 || (req->search_uuid == 2 && req->records)) {
15830cd8e651b6f004bcc64387d59f6bcb29190ffed6Johan Hedberg		if (err == -ECONNRESET && req->reconnect_attempt < 1) {
15840cd8e651b6f004bcc64387d59f6bcb29190ffed6Johan Hedberg			req->search_uuid--;
15850cd8e651b6f004bcc64387d59f6bcb29190ffed6Johan Hedberg			req->reconnect_attempt++;
15860cd8e651b6f004bcc64387d59f6bcb29190ffed6Johan Hedberg		} else
15870cd8e651b6f004bcc64387d59f6bcb29190ffed6Johan Hedberg			goto done;
15880cd8e651b6f004bcc64387d59f6bcb29190ffed6Johan Hedberg	}
1589da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1590da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	update_services(req, recs);
1591da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1592da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	adapter_get_address(adapter, &src);
1593da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1594da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	/* Search for mandatory uuids */
15957d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse	if (uuid_list[req->search_uuid]) {
15967d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
1597c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann		bt_search_service(&src, &device->bdaddr, &uuid,
1598c4c130d3922dedc992e00fbf94bde64a180306c2Marcel Holtmann						browse_cb, user_data, NULL);
1599da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		return;
1600da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	}
1601da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
1602da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentzdone:
1603da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	search_cb(recs, err, user_data);
1604da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz}
1605da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
160669adac833c5633714b84bf840c75aa814193b8a6Johan Hedbergstatic void init_browse(struct browse_req *req, gboolean reverse)
1607da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz{
1608da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	GSList *l;
1609da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz
161069adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	/* If we are doing reverse-SDP don't try to detect removed profiles
161169adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 * since some devices hide their service records while they are
161269adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 * connected
161369adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	 */
161469adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg	if (reverse)
161569adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		return;
161669adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg
1617da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz	for (l = req->device->uuids; l; l = l->next)
16180dabe8201eac11459010694bca66d6b217936fcbJohan Hedberg		req->profiles_removed = g_slist_append(req->profiles_removed,
1619da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz						l->data);
16203d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
16213d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1622d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demariostatic char *primary_list_to_string(GSList *primary_list)
1623d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario{
1624d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	GString *services;
1625d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	GSList *l;
1626d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1627d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	services = g_string_new(NULL);
1628d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1629d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	for (l = primary_list; l; l = l->next) {
1630d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario		struct att_primary *primary = l->data;
1631d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario		char service[64];
1632d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1633d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario		memset(service, 0, sizeof(service));
1634d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1635d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario		snprintf(service, sizeof(service), "%04X#%04X#%s ",
1636d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario				primary->start, primary->end, primary->uuid);
1637d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1638d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario		services = g_string_append(services, service);
1639d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	}
1640d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1641d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	return g_string_free(services, FALSE);
1642d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario}
1643d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1644399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasistatic void store_services(struct btd_device *device)
1645399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi{
1646399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	struct btd_adapter *adapter = device->adapter;
1647399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	bdaddr_t dba, sba;
16483a4be695834ccfac110c548cf870dc729c00f44cVinicius Costa Gomes	char *str = primary_list_to_string(device->primaries);
1649399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi
1650399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	adapter_get_address(adapter, &sba);
1651399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	device_get_address(device, &dba);
1652399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi
1653399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	write_device_type(&sba, &dba, device->type);
1654399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	write_device_services(&sba, &dba, str);
1655399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi
1656399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	g_free(str);
1657399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi}
1658399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi
16595399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasistatic void primary_cb(GSList *services, guint8 status, gpointer user_data)
1660d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi{
1661d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	struct browse_req *req = user_data;
1662d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	struct btd_device *device = req->device;
1663d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	GSList *l, *uuids = NULL;
1664d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
16655399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	if (status) {
166692a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan		DBusMessage *reply;
16675399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		reply = btd_error_failed(req->msg, att_ecode2str(status));
166892a56b931f72b218e0825f57a9bb8b7a4dbd44e7Gustavo F. Padovan		g_dbus_send_message(req->conn, reply);
1669d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi		goto done;
1670d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	}
1671d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
16725c36b74c0b43ae0532e26c03b6ce8a1abba7d874Claudio Takahasi	services_changed(device);
16735c36b74c0b43ae0532e26c03b6ce8a1abba7d874Claudio Takahasi	device_set_temporary(device, FALSE);
1674d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1675d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	for (l = services; l; l = l->next) {
1676d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario		struct att_primary *prim = l->data;
1677d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario		uuids = g_slist_append(uuids, prim->uuid);
1678d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	}
1679d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1680d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	device_probe_drivers(device, uuids);
1681bb5eda2bc85b68e9cf3908f39972b476afb6633fVinicius Costa Gomes
1682f194be5c746d1ad6f093d1b175b7b0e1ccafad58Bruna Moreira	device_register_services(req->conn, device, g_slist_copy(services), -1);
1683bb5eda2bc85b68e9cf3908f39972b476afb6633fVinicius Costa Gomes
1684d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario	g_slist_free(uuids);
1685d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
16865c36b74c0b43ae0532e26c03b6ce8a1abba7d874Claudio Takahasi	create_device_reply(device, req);
1687d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
1688399ad77a2fc90c8df9ee9deae2cb85ce61639403Claudio Takahasi	store_services(device);
1689d3cb258b9b9af0dcacfba0e6aa0db3f280554fb0Sheldon Demario
1690d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasidone:
1691d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	device->browse = NULL;
1692d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	browse_request_free(req);
1693d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi}
1694d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
16955399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasistatic void gatt_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
16965399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi{
16975399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	struct browse_req *req = user_data;
16985399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	struct btd_device *device = req->device;
16995399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17005399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	if (gerr) {
17015399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		DBusMessage *reply;
17025399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17035399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		DBG("%s", gerr->message);
17045399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17055399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		reply = btd_error_failed(req->msg, gerr->message);
17065399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		g_dbus_send_message(req->conn, reply);
17075399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17085399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		device->browse = NULL;
17095399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		browse_request_free(req);
17105399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17115399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		return;
17125399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	}
17135399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17145399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	req->attrib = g_attrib_new(io);
17151b0d082bf58143aaad02a819037989fddc6c6b95Vinicius Costa Gomes	g_io_channel_unref(io);
17161b0d082bf58143aaad02a819037989fddc6c6b95Vinicius Costa Gomes
17175399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	gatt_discover_primary(req->attrib, NULL, primary_cb, req);
17185399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi}
17195399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17207e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demarioint device_browse_primary(struct btd_device *device, DBusConnection *conn,
17217e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario				DBusMessage *msg, gboolean secure)
17223d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz{
172318614bd2b008cb9f3879990883c569c37b72f195Alok Barsode	struct btd_adapter *adapter = device->adapter;
17243d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz	struct browse_req *req;
17255399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	BtIOSecLevel sec_level;
17261b0d082bf58143aaad02a819037989fddc6c6b95Vinicius Costa Gomes	GIOChannel *io;
1727cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bdaddr_t src;
17287e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario
17297e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	if (device->browse)
17307e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		return -EBUSY;
17312a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode
1732d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	req = g_new0(struct browse_req, 1);
1733d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	req->device = btd_device_ref(device);
17341af86fb9d1717a27b3a776fc0fb62c96045ccb9aJohan Hedberg
17352a8fb41c4c57b24a22f3adaab472b416faae122eAlok Barsode	adapter_get_address(adapter, &src);
17363d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
17375399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	sec_level = secure ? BT_IO_SEC_HIGH : BT_IO_SEC_LOW;
17385399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17391b0d082bf58143aaad02a819037989fddc6c6b95Vinicius Costa Gomes	io = bt_io_connect(BT_IO_L2CAP, gatt_connect_cb, req, NULL, NULL,
17405399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi				BT_IO_OPT_SOURCE_BDADDR, &src,
17415399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi				BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
17421f8969c0435f8d49c20f46dba9bece21031997c7Johan Hedberg				BT_IO_OPT_CID, ATT_CID,
17435399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi				BT_IO_OPT_SEC_LEVEL, sec_level,
17445399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi				BT_IO_OPT_INVALID);
17455399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi
17461b0d082bf58143aaad02a819037989fddc6c6b95Vinicius Costa Gomes	if (io == NULL ) {
1747d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi		browse_request_free(req);
17485399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi		return -EIO;
17497e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	}
1750438ab01b43075b715345df0d85447aaf338fd4fcLuiz Augusto von Dentz
17517e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	if (conn == NULL)
17527e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		conn = get_dbus_connection();
17537e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario
17547e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	req->conn = dbus_connection_ref(conn);
17557e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	device->browse = req;
17567e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario
17577e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	if (msg) {
17587e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		const char *sender = dbus_message_get_sender(msg);
17597e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario
17607e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		req->msg = dbus_message_ref(msg);
17617e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		/* Track the request owner to cancel it
17627e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		 * automatically if the owner exits */
17637e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		req->listener_id = g_dbus_add_disconnect_watch(conn,
17647e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario						sender,
17657e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario						discover_services_req_exit,
17667e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario						req, NULL);
1767d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	}
1768d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
17695399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi	return 0;
1770d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi}
1771d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
17727e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demarioint device_browse_sdp(struct btd_device *device, DBusConnection *conn,
17737e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario			DBusMessage *msg, uuid_t *search, gboolean reverse)
1774d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi{
1775d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	struct btd_adapter *adapter = device->adapter;
1776d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	struct browse_req *req;
1777d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	bt_callback_t cb;
1778d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	bdaddr_t src;
1779d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	uuid_t uuid;
17807e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	int err;
17817e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario
17827e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	if (device->browse)
17837e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		return -EBUSY;
17843d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz
1785d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	adapter_get_address(adapter, &src);
1786d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
1787d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	req = g_new0(struct browse_req, 1);
1788d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	req->device = btd_device_ref(device);
1789a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	if (search) {
1790040728e5019fce4eba5790939329fae0aa9104ffClaudio Takahasi		memcpy(&uuid, search, sizeof(uuid_t));
1791da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = search_cb;
1792a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	} else {
17937d3301934f1b30d90646c97f40464ed198be91d3David Woodhouse		sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
179469adac833c5633714b84bf840c75aa814193b8a6Johan Hedberg		init_browse(req, reverse);
1795da8ef81cf060726782614baeea5b7e2c466b2341Luiz Augusto von Dentz		cb = browse_cb;
1796a6f07d2bf12942854072c37c3c42d7447921beeeMarcel Holtmann	}
1797d69e08eb0d567b61106ca37e0546402f4ae0c34eMarcel Holtmann
17987e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	err = bt_search_service(&src, &device->bdaddr, &uuid, cb, req, NULL);
17997e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	if (err < 0) {
1800d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi		browse_request_free(req);
1801d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi		return err;
18027e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	}
1803d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
1804d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	if (conn == NULL)
1805d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi		conn = get_dbus_connection();
1806d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi
1807d49c4e8457a3169f32c9b7466516b2d2e83b0f6cClaudio Takahasi	req->conn = dbus_connection_ref(conn);
1808a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	device->browse = req;
1809d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg
1810d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg	if (msg) {
18117c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg		const char *sender = dbus_message_get_sender(msg);
18127c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg
18135c6426eff87049c9f8e49877f650772840907239Luiz Augusto von Dentz		req->msg = dbus_message_ref(msg);
1814d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		/* Track the request owner to cancel it
1815d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg		 * automatically if the owner exits */
1816a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz		req->listener_id = g_dbus_add_disconnect_watch(conn,
18177c9a25e3a7bfbc50d4e7e8c151d08c213076d960Johan Hedberg						sender,
181895e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz						discover_services_req_exit,
1819e8610fcbe0341a4879b8230d97cd27f5f8cf9f58Luiz Augusto von Dentz						req, NULL);
1820d0c0409d8ad37a042539706ff5382899acc81395Johan Hedberg	}
182195e5960735be4066d43f77d91ebe78771cd76a43Luiz Augusto von Dentz
1822a4145c63530b4c3575b7da5f117c0df352f939fcLuiz Augusto von Dentz	return err;
18233d9966f38f1d6ca12c9e9e2eace5181ba04844b4Luiz Augusto von Dentz}
182424cce397c3479e95f3e525da9285234fbafd2984Marcel Holtmann
182518614bd2b008cb9f3879990883c569c37b72f195Alok Barsodestruct btd_adapter *device_get_adapter(struct btd_device *device)
1826dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode{
1827dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	if (!device)
1828dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode		return NULL;
1829dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
1830dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode	return device->adapter;
1831dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode}
1832dcf5298e8173e946e3ac2ef6150ad78d030b15d0Alok Barsode
183319ce4933f3dadf3b04a2a9bd84d66d750cc010c3Alok Barsodevoid device_get_address(struct btd_device *device, bdaddr_t *bdaddr)
1834aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode{
1835cbf6ef965b0db117ec9b762aad9cff995fd3b0bfAlok Barsode	bacpy(bdaddr, &device->bdaddr);
1836aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode}
1837aec749f0732638f182c4b50fb59d6c905a80d42dAlok Barsode
1838555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodeconst gchar *device_get_path(struct btd_device *device)
183946fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode{
184046fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	if (!device)
184146fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode		return NULL;
184246fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
184346fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode	return device->path;
184446fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode}
184546fd7beaa5b27f74e64d77449247e5459d7a3084Alok Barsode
1846555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodestruct agent *device_get_agent(struct btd_device *device)
1847a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode{
1848a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode	if (!device)
1849a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode		return NULL;
1850a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
185150996c3a0b0eb98f3cb1c202257d063992c7220dJohan Hedberg	if (device->agent)
185250996c3a0b0eb98f3cb1c202257d063992c7220dJohan Hedberg		return device->agent;
185350996c3a0b0eb98f3cb1c202257d063992c7220dJohan Hedberg
185450996c3a0b0eb98f3cb1c202257d063992c7220dJohan Hedberg	return adapter_get_agent(device->adapter);
1855a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode}
1856a2335a65bb61313b3e46be861c90ca8bdb786eb8Alok Barsode
1857555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_busy(struct btd_device *device)
18589f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode{
1859a6a65ceb00cf583c8be297b4bf489eec7a92a768Luiz Augusto von Dentz	return device->browse ? TRUE : FALSE;
18609f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode}
18619f94306bcd017a6acb152685c940ed6d027a98c7Alok Barsode
1862555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodegboolean device_is_temporary(struct btd_device *device)
1863f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode{
1864f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode	return device->temporary;
1865f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode}
1866f169545f05c25960c094c12f11a4ee452fb96ba8Alok Barsode
1867555fcc9b4bf67e923708af8de46aa91b7077f050Alok Barsodevoid device_set_temporary(struct btd_device *device, gboolean temporary)
1868595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode{
1869595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode	if (!device)
1870595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode		return;
1871595bd38a9fe105ef20d1b0527e04c7d28532d22dAlok Barsode
1872b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	DBG("temporary %d", temporary);
187329227ad09e8996699e1b1d7e1c90d45fc80cab65Alok Barsode
1874b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	device->temporary = temporary;
18752203f153c53189ec1c30df99b717e035681196e6Alok Barsode}
1876c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
18773e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliyvoid device_set_bonded(struct btd_device *device, gboolean bonded)
18783e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy{
18793e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	if (!device)
18803e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy		return;
18813e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy
18823e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	DBG("bonded %d", bonded);
18833e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy
18843e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy	device->bonded = bonded;
18853e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy}
18863e28ead202ff45d0fd66876f6a9cd3e8c3dbf42eDmitriy Paliy
1887fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomesvoid device_set_type(struct btd_device *device, device_type_t type)
1888fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomes{
1889fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomes	if (!device)
1890fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomes		return;
1891fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomes
1892fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomes	device->type = type;
1893fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomes}
1894fba8f0e7d1fdefe35074f808a691e242d19edf92Vinicius Costa Gomes
1895013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedbergstatic gboolean start_discovery(gpointer user_data)
1896013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
1897013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	struct btd_device *device = user_data;
1898013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
18997e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario	device_browse_sdp(device, NULL, NULL, NULL, TRUE);
1900013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
1901013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	device->discov_timer = 0;
1902013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
1903013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg	return FALSE;
1904013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
1905013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
19068b78d14dd4ac9776f5848dee94ce2fcf976fd6d8Luiz Augusto von Dentzstatic DBusMessage *new_authentication_return(DBusMessage *msg, int status)
1907013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg{
19082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (status) {
19092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x00: /* success */
19102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_method_return(msg);
19112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x04: /* page timeout */
191396762463061ffbe566c7f8916d230b4190ec3b6fJohan Hedberg		return dbus_message_new_error(msg,
191496762463061ffbe566c7f8916d230b4190ec3b6fJohan Hedberg				ERROR_INTERFACE ".ConnectionAttemptFailed",
191596762463061ffbe566c7f8916d230b4190ec3b6fJohan Hedberg				"Page Timeout");
19162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x08: /* connection timeout */
191796762463061ffbe566c7f8916d230b4190ec3b6fJohan Hedberg		return dbus_message_new_error(msg,
191896762463061ffbe566c7f8916d230b4190ec3b6fJohan Hedberg				ERROR_INTERFACE ".ConnectionAttemptFailed",
191996762463061ffbe566c7f8916d230b4190ec3b6fJohan Hedberg				"Connection Timeout");
19202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x10: /* connection accept timeout */
19212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x22: /* LMP response timeout */
19222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x28: /* instant passed - is this a timeout? */
19232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
19242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationTimeout",
19252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Timeout");
19262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x17: /* too frequent pairing attempts */
19272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
19282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".RepeatedAttempts",
19292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Repeated Attempts");
19302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x06:
19322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */
19332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
19342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationRejected",
19352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Rejected");
19362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x07: /* memory capacity */
19382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x09: /* connection limit */
19392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0a: /* synchronous connection limit */
19402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0d: /* limited resources */
19412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x13: /* user ended the connection */
19422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x14: /* terminated due to low resources */
1943922daca3e63d106c8cb8a56575cec0d1d9bd45a5Luiz Augusto von Dentz	case 0x16: /* connection terminated */
19442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
19452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationCanceled",
19462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Canceled");
19472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x05: /* authentication failure */
19492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x0E: /* rejected due to security reasons - is this auth failure? */
19502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x25: /* encryption mode not acceptable - is this auth failure? */
19512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x26: /* link key cannot be changed - is this auth failure? */
19522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x29: /* pairing with unit key unsupported - is this auth failure? */
19532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case 0x2f: /* insufficient security - is this auth failure? */
19542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	default:
19552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return dbus_message_new_error(msg,
19562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					ERROR_INTERFACE ".AuthenticationFailed",
19572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					"Authentication Failed");
19582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
19592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19618d07c9eea9156c18c9323cb08728566e5f446703Luiz Augusto von Dentzstatic void bonding_request_free(struct bonding_req *bonding)
19622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
19632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device;
19642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding)
19662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
19672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->listener_id)
19692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_dbus_remove_watch(bonding->conn, bonding->listener_id);
197068b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
19712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->msg)
19722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		dbus_message_unref(bonding->msg);
19732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (bonding->conn)
19752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		dbus_connection_unref(bonding->conn);
19762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19778d07c9eea9156c18c9323cb08728566e5f446703Luiz Augusto von Dentz	if (bonding->io)
19782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		g_io_channel_unref(bonding->io);
19792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device = bonding->device;
19814c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz	g_free(bonding);
19822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19834c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz	if (!device)
19844c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz		return;
19852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding = NULL;
19874c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz
19883ba95c2c6e3ae23b385d70e96cd733626ca87244Luiz Augusto von Dentz	adapter_resume_discovery(device->adapter);
19893ba95c2c6e3ae23b385d70e96cd733626ca87244Luiz Augusto von Dentz
19904c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz	if (!device->agent)
19914c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz		return;
19924c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz
19932975f0c78ce85dd5cfa85be196ac14a4d570e48cJohan Hedberg	agent_cancel(device->agent);
1994cc35f24a2a728c4e8c31ea0c6c11c6b701901861Johan Hedberg	agent_free(device->agent);
19954c736d92510c0a61fa8df49698903676c4e21d4bLuiz Augusto von Dentz	device->agent = NULL;
19962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
19972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
19986fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedbergvoid device_set_paired(struct btd_device *device, gboolean value)
19992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusConnection *conn = get_dbus_connection();
200168b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg
20026fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg	if (device->paired == value)
20036fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg		return;
20046fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg
20056fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg	device->paired = value;
20066fe85942c1272ef3d4ef68a35eade7a276219bb6Johan Hedberg
2007c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Paired",
20082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				DBUS_TYPE_BOOLEAN, &value);
20092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void device_agent_removed(struct agent *agent, void *user_data)
20122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = user_data;
20142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2015e5e25c761845284c6aca75599bc75c8e0d901311Johan Hedberg	device->agent = NULL;
20162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20172aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
20182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->authr->agent = NULL;
20192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic struct bonding_req *bonding_request_new(DBusConnection *conn,
20222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						DBusMessage *msg,
20232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						struct btd_device *device,
20242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						const char *agent_path,
20252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						uint8_t capability)
20262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
20282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	const char *name = dbus_message_get_sender(msg);
20292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
203016348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	char addr[18];
20312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
203216348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	ba2str(&device->bdaddr, addr);
203316348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	DBG("Requesting bonding for %s", addr);
20342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent_path)
20362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		goto proceed;
20372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	agent = agent_create(device->adapter, name, agent_path,
20392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					capability,
20402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device_agent_removed,
20412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					device);
20422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent) {
20432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Unable to create a new agent");
20442aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return NULL;
20452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
20462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->agent = agent;
20482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20498e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan	DBG("Temporary agent registered for %s at %s:%s",
205016348199ed59c49a710805a5061c3f22477715bfJohan Hedberg			addr, name, agent_path);
20512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzproceed:
20532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding = g_new0(struct bonding_req, 1);
20542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->conn = dbus_connection_ref(conn);
20562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->msg = dbus_message_ref(msg);
20572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20583ba95c2c6e3ae23b385d70e96cd733626ca87244Luiz Augusto von Dentz	adapter_suspend_discovery(device->adapter);
20593ba95c2c6e3ae23b385d70e96cd733626ca87244Luiz Augusto von Dentz
20602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return bonding;
20612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20632aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void create_bond_req_exit(DBusConnection *conn, void *user_data)
20642aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = user_data;
206616348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	char addr[18];
20672aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
206816348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	ba2str(&device->bdaddr, addr);
206916348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	DBG("%s: requestor exited before bonding was completed", addr);
20702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
2072f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg		device_cancel_authentication(device, FALSE);
20732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20742aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding) {
20752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		device->bonding->listener_id = 0;
2076c3cfa26a86a25e35d8b0e7c24978a44f9af80a2aLuiz Augusto von Dentz		device_request_disconnect(device, NULL);
20772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
20782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
20792aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von DentzDBusMessage *device_create_bonding(struct btd_device *device,
20812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusConnection *conn,
20822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					DBusMessage *msg,
20832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					const char *agent_path,
20842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					uint8_t capability)
20852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
20862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char filename[PATH_MAX + 1];
20872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	char *str, srcaddr[18], dstaddr[18];
20882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_adapter *adapter = device->adapter;
20892aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding;
20902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bdaddr_t src;
2091b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	int err;
20922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	adapter_get_address(adapter, &src);
20942aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&src, srcaddr);
20952aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	ba2str(&device->bdaddr, dstaddr);
20962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
20972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->bonding)
2098bd3cf4860d056d3044b7eb8a4e03c53934eb20a6Gustavo F. Padovan		return btd_error_in_progress(msg);
20992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* check if a link key already exists */
21012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
21022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz			"linkkeys");
21032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	str = textfile_caseget(filename, dstaddr);
21052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (str) {
21062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		free(str);
210773774f1b253c882f9fa2a21b3df4b2bd52fbc3ceGustavo F. Padovan		return btd_error_already_exists(msg);
21082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
21092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2110b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	err = adapter_create_bonding(adapter, &device->bdaddr, capability);
2111b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	if (err < 0)
2112b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg		return btd_error_failed(msg, strerror(-err));
21132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding = bonding_request_new(conn, msg, device, agent_path,
21152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz					capability);
21162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding) {
2117b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg		adapter_cancel_bonding(adapter, &device->bdaddr);
21182aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return NULL;
21192aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
21202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21212aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->listener_id = g_dbus_add_disconnect_watch(conn,
21222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						dbus_message_get_sender(msg),
21232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						create_bond_req_exit, device,
21242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz						NULL);
21252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->bonding = bonding;
21272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	bonding->device = device;
21282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21292aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return NULL;
21302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
21312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2132e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedbergvoid device_simple_pairing_complete(struct btd_device *device, uint8_t status)
2133e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg{
2134e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	struct authentication_req *auth = device->authr;
2135e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg
2136e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	if (auth && auth->type == AUTH_TYPE_NOTIFY && auth->agent)
2137e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg		agent_cancel(auth->agent);
2138e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg}
2139e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg
2140a53621433ce81981a1fc2e610086ff528f1770efJohan Hedbergstatic void device_auth_req_free(struct btd_device *device)
2141f0ab6f3c4c8de3a49591d484a59c30a021b4e4c1Johan Hedberg{
2142f0ab6f3c4c8de3a49591d484a59c30a021b4e4c1Johan Hedberg	g_free(device->authr);
2143f0ab6f3c4c8de3a49591d484a59c30a021b4e4c1Johan Hedberg	device->authr = NULL;
2144f0ab6f3c4c8de3a49591d484a59c30a021b4e4c1Johan Hedberg}
2145f0ab6f3c4c8de3a49591d484a59c30a021b4e4c1Johan Hedberg
21462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzvoid device_bonding_complete(struct btd_device *device, uint8_t status)
21472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
21482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
2149e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	struct authentication_req *auth = device->authr;
2150f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh	bdaddr_t bdaddr;
2151e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg
2152b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	DBG("bonding %p status 0x%02x", bonding, status);
2153b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg
2154e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg	if (auth && auth->type == AUTH_TYPE_NOTIFY && auth->agent)
2155e35dd0c0246236371269b79cc28b1a23f4999560Johan Hedberg		agent_cancel(auth->agent);
21562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
21578bbc3fa4c0456c39c4174ab4be4bf39efe0de091jhtop.kim	// Temporary hack till we move to mgmt interface.
21588bbc3fa4c0456c39c4174ab4be4bf39efe0de091jhtop.kim	if (status == 0x06 && auth == NULL) {
2159f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh		device_remove_bonding(device);
2160f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh		device_get_address(device, &bdaddr);
2161f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh		btd_adapter_retry_authentication(device->adapter, &bdaddr);
21628bbc3fa4c0456c39c4174ab4be4bf39efe0de091jhtop.kim		return;
2163f945a68fa973a13a0f57437e291258eb9f05dd7aJaikumar Ganesh	} else if (status) {
21644a4471e7e071fe8e8ae68d1b130dac6db9748fe2Luiz Augusto von Dentz		device_cancel_authentication(device, TRUE);
2165bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg		device_cancel_bonding(device, status);
2166bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg		return;
2167bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg	}
21682aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2169a53621433ce81981a1fc2e610086ff528f1770efJohan Hedberg	device_auth_req_free(device);
2170bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
2171b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	/* If we're already paired nothing more is needed */
2172b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	if (device->paired)
2173bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg		return;
2174bcb6af7fc78234948ba1c997825c8859464b170bJohan Hedberg
2175b9efb73d372a913dc52b3ba216cb7ac8de9f4cbcJohan Hedberg	device_set_paired(device, TRUE);
2176e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg
217768b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	/* If we were initiators start service discovery immediately.
217868b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * However if the other end was the initator wait a few seconds
217968b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * before SDP. This is due to potential IOP issues if the other
218068b27e68b50b1e68d663142d2b0432c435329ea6Johan Hedberg	 * end starts doing SDP at the same time as us */
2181e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg	if (bonding) {
2182629c9dbe7f161c0c285749bb014f55a2b30fd65cJohan Hedberg		DBG("Proceeding with service discovery");
2183e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		/* If we are initiators remove any discovery timer and just
2184e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		 * start discovering services directly */
2185e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		if (device->discov_timer) {
2186e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg			g_source_remove(device->discov_timer);
2187e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg			device->discov_timer = 0;
2188e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg		}
2189e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg
21907e6edb65cfabc1b9a7f131f6f51938bb1f57f0f9Sheldon Demario		device_browse_sdp(device, bonding->conn, bonding->msg,
21912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz				NULL, FALSE);
21925e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz
2193e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg		bonding_request_free(bonding);
2194e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	} else {
21955e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz		if (!device->browse && !device->discov_timer &&
21965e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz				main_opts.reverse_sdp) {
21975e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz			/* If we are not initiators and there is no currently
21985e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz			 * active discovery or discovery timer, set discovery
21995e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz			 * timer */
22008e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan			DBG("setting timer for reverse service discovery");
22015e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz			device->discov_timer = g_timeout_add_seconds(
22025e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz							DISCOVERY_TIMER,
22035e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz							start_discovery,
22045e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz							device);
22055e5fbd39b64ff0ad84e9be9a51daa020638e679bLuiz Augusto von Dentz		}
2206e4d0a3b9051923b015ce633f9385e5af126211feJohan Hedberg	}
22072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
22082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2209e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberggboolean device_is_creating(struct btd_device *device, const char *sender)
2210e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg{
2211e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	DBusMessage *msg;
2212e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg
2213e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	if (device->bonding && device->bonding->msg)
2214e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg		msg = device->bonding->msg;
2215e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	else if (device->browse && device->browse->msg)
2216e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg		msg = device->browse->msg;
2217e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	else
2218e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg		return FALSE;
2219e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg
2220e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	if (!dbus_message_is_method_call(msg, ADAPTER_INTERFACE,
2221e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg						"CreatePairedDevice") &&
2222e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg			!dbus_message_is_method_call(msg, ADAPTER_INTERFACE,
2223e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg							"CreateDevice"))
2224e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg		return FALSE;
2225e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg
2226e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	if (sender == NULL)
2227e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg		return TRUE;
2228e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg
2229e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg	return g_str_equal(sender, dbus_message_get_sender(msg));
2230e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg}
2231e164ff20b95acd2a25c70623212c190abf7eee19Johan Hedberg
22322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzgboolean device_is_bonding(struct btd_device *device, const char *sender)
22332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
22342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
22352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!device->bonding)
22372aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return FALSE;
22382aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!sender)
22402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return TRUE;
22412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return g_str_equal(sender, dbus_message_get_sender(bonding->msg));
22432aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
2244e21ec2652c54dbc8abbf84039b43fbd3be0b5ebcJohan Hedberg
22452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzvoid device_cancel_bonding(struct btd_device *device, uint8_t status)
22462aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
22472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct bonding_req *bonding = device->bonding;
22482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusMessage *reply;
224916348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	char addr[18];
22502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!bonding)
22522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
22532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
225416348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	ba2str(&device->bdaddr, addr);
225516348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	DBG("Canceling bonding request for %s", addr);
22562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (device->authr)
2258f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg		device_cancel_authentication(device, FALSE);
22592aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22602aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	reply = new_authentication_return(bonding->msg, status);
22612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	g_dbus_send_message(bonding->conn, reply);
22622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22638d07c9eea9156c18c9323cb08728566e5f446703Luiz Augusto von Dentz	bonding_request_cancel(bonding);
22648d07c9eea9156c18c9323cb08728566e5f446703Luiz Augusto von Dentz	bonding_request_free(bonding);
22652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
22662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2267bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedbergstatic void pincode_cb(struct agent *agent, DBusError *err,
2268bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg					const char *pincode, void *data)
22692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
22702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
22712aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
22722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22732aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
22742bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz	if (auth->cb == NULL)
22752aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
22762aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22772aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_pincode_cb) auth->cb)(agent, err, pincode, device);
22782aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2279a9c4e4a0aec81cecbc2bded149b924028953a952Luiz Augusto von Dentz	device->authr->cb = NULL;
2280a9c4e4a0aec81cecbc2bded149b924028953a952Luiz Augusto von Dentz	device->authr->agent = NULL;
22812aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
22822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void confirm_cb(struct agent *agent, DBusError *err, void *data)
22842aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
22852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
22862aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
22872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
22892bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz	if (auth->cb == NULL)
22902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
22912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
22922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_cb) auth->cb)(agent, err, device);
22932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2294a9c4e4a0aec81cecbc2bded149b924028953a952Luiz Augusto von Dentz	device->authr->cb = NULL;
2295a9c4e4a0aec81cecbc2bded149b924028953a952Luiz Augusto von Dentz	device->authr->agent = NULL;
22962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
22972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2298bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedbergstatic void passkey_cb(struct agent *agent, DBusError *err,
2299bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg						uint32_t passkey, void *data)
23002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
23012aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = data;
23022aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct btd_device *device = auth->device;
23032aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
23042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	/* No need to reply anything if the authentication already failed */
23052bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz	if (auth->cb == NULL)
23062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
23072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
23082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	((agent_passkey_cb) auth->cb)(agent, err, passkey, device);
23092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2310a9c4e4a0aec81cecbc2bded149b924028953a952Luiz Augusto von Dentz	device->authr->cb = NULL;
2311a9c4e4a0aec81cecbc2bded149b924028953a952Luiz Augusto von Dentz	device->authr->agent = NULL;
23122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
23132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
23147050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganeshstatic void pairing_consent_cb(struct agent *agent, DBusError *err, void *data)
23157050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh{
23167050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	struct authentication_req *auth = data;
23177050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	struct btd_device *device = auth->device;
23187050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh
23197050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	/* No need to reply anything if the authentication already failed */
23207050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	if (!auth->cb)
23217050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh		return;
23227050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh
23237050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	((agent_cb) auth->cb)(agent, err, device);
23247050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh
23257050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	auth->cb = NULL;
23267050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh}
23277050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh
23282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzint device_request_authentication(struct btd_device *device, auth_type_t type,
2329bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg						uint32_t passkey, void *cb)
23302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
23312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth;
23322aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct agent *agent;
233316348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	char addr[18];
2334bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg	int err;
23352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
233616348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	ba2str(&device->bdaddr, addr);
233716348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	DBG("Requesting agent authentication for %s", addr);
233816348199ed59c49a710805a5061c3f22477715bfJohan Hedberg
2339508fdc901e7e1721eef19de5d8ab6e2f1f313dd7Rafal Michalski	if (device->authr) {
234016348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		error("Authentication already requested for %s", addr);
2341508fdc901e7e1721eef19de5d8ab6e2f1f313dd7Rafal Michalski		return -EALREADY;
2342508fdc901e7e1721eef19de5d8ab6e2f1f313dd7Rafal Michalski	}
2343508fdc901e7e1721eef19de5d8ab6e2f1f313dd7Rafal Michalski
2344ca0465aff7258cc249e7cba0631fbb11b7829b9eJohan Hedberg	agent = device_get_agent(device);
23452aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!agent) {
234616348199ed59c49a710805a5061c3f22477715bfJohan Hedberg		error("No agent available for request type %d", type);
23472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return -EPERM;
23482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
23492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
23502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth = g_new0(struct authentication_req, 1);
23512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->agent = agent;
23522aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->device = device;
23532aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = cb;
23542aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->type = type;
23552aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	device->authr = auth;
23562aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
23572aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (type) {
23582aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PINCODE:
2359bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg		err = agent_request_pincode(agent, device, pincode_cb,
2360fc4c6f53f10e4aba7c3183ba294618ec489fc683Johan Hedberg								auth, NULL);
23612aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
23622aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PASSKEY:
2363bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg		err = agent_request_passkey(agent, device, passkey_cb,
2364fc4c6f53f10e4aba7c3183ba294618ec489fc683Johan Hedberg								auth, NULL);
23652aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
23662aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_CONFIRM:
2367bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg		err = agent_request_confirmation(agent, device, passkey,
2368fc4c6f53f10e4aba7c3183ba294618ec489fc683Johan Hedberg						confirm_cb, auth, NULL);
23692aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
23702aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_NOTIFY:
2371bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg		err = agent_display_passkey(agent, device, passkey);
23722aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
23737050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	case AUTH_TYPE_AUTO:
23747050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh		err = 0;
23757050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh		break;
23767050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	case AUTH_TYPE_PAIRING_CONSENT:
23777050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh		err = agent_request_pairing_consent(agent, device,
23787050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh							pairing_consent_cb, auth, NULL);
23797050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh		break;
23802aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	default:
2381bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg		err = -EINVAL;
23822aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
23832aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2384bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg	if (err < 0) {
23852aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		error("Failed requesting authentication");
2386a53621433ce81981a1fc2e610086ff528f1770efJohan Hedberg		device_auth_req_free(device);
23872aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
23882aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2389bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg	return err;
23902aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
23912aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
23922aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzstatic void cancel_authentication(struct authentication_req *auth)
23932aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
23942bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz	struct btd_device *device;
23952bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz	struct agent *agent;
23962aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	DBusError err;
23972aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
239837b02c1ef9be4f989c9ad5e511f519d35f2bc088Johan Hedberg	if (!auth || !auth->cb)
23992aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
24002aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
24012bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz	device = auth->device;
24022bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz	agent = auth->agent;
24032bf0e14286389430bde40885f1aa6ce51b1e8b8eLuiz Augusto von Dentz
24042aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_error_init(&err);
24052aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_set_error_const(&err, "org.bluez.Error.Canceled", NULL);
24062aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
24072aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	switch (auth->type) {
24082aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PINCODE:
24092aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_pincode_cb) auth->cb)(agent, &err, NULL, device);
24102aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
24112aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_CONFIRM:
24122aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_cb) auth->cb)(agent, &err, device);
24132aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
24142aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_PASSKEY:
24152aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
24162aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
24177050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh	case AUTH_TYPE_PAIRING_CONSENT:
24187050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh		((agent_cb) auth->cb) (agent, &err, device);
24197050b0c6c21919186cddda6f2286f43cb99798b2Jaikumar Ganesh		break;
24202aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	case AUTH_TYPE_NOTIFY:
24214d21e85715580f468c7f190a3cd25d7fadaba9aaJohan Hedberg		/* User Notify doesn't require any reply */
24222aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		break;
24232aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	}
24242aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
24252aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	dbus_error_free(&err);
24262aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	auth->cb = NULL;
24272aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
24282aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2429f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedbergvoid device_cancel_authentication(struct btd_device *device, gboolean aborted)
24302aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
24312aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	struct authentication_req *auth = device->authr;
243216348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	char addr[18];
24332aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
24342aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (!auth)
24352aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		return;
24362aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
243716348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	ba2str(&device->bdaddr, addr);
243816348199ed59c49a710805a5061c3f22477715bfJohan Hedberg	DBG("Canceling authentication request for %s", addr);
24392aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
24402aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	if (auth->agent)
24412aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz		agent_cancel(auth->agent);
24422aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
2443f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg	if (!aborted)
2444f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg		cancel_authentication(auth);
2445f7d1ee361e410e096929bd3918178af356c50bbdJohan Hedberg
2446a53621433ce81981a1fc2e610086ff528f1770efJohan Hedberg	device_auth_req_free(device);
24472aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz}
24482aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz
24492aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentzgboolean device_is_authenticating(struct btd_device *device)
24502aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz{
24512aad1cf41acbc69481915d24cef33fa721d4e1fdLuiz Augusto von Dentz	return (device->authr != NULL);
2452013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg}
2453013d376e47dc68ec385e9f88d6bc6c07c921ee1aJohan Hedberg
2454837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberggboolean device_is_authorizing(struct btd_device *device)
2455837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg{
2456837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg	return device->authorizing;
2457837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg}
2458837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg
2459837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedbergvoid device_set_authorizing(struct btd_device *device, gboolean auth)
2460837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg{
2461837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg	device->authorizing = auth;
2462837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg}
2463837d65f3a7f94ed4e6fe95f4e845d7ae3242be24Johan Hedberg
24645eb9d13c5b75f3659454466d511533c2f413cbbdClaudio Takahasivoid device_register_services(DBusConnection *conn, struct btd_device *device,
24655eb9d13c5b75f3659454466d511533c2f413cbbdClaudio Takahasi						GSList *prim_list, int psm)
246683d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes{
24678447ce5c943e5b73149321fd4f61ed482c4e9427Claudio Takahasi	device->services = attrib_client_register(conn, device, psm, NULL,
24688447ce5c943e5b73149321fd4f61ed482c4e9427Claudio Takahasi								prim_list);
24695eb9d13c5b75f3659454466d511533c2f413cbbdClaudio Takahasi	device->primaries = g_slist_concat(device->primaries, prim_list);
247083d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes}
247183d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes
247283d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa GomesGSList *btd_device_get_primaries(struct btd_device *device)
247383d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes{
247483d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes	return device->primaries;
247583d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes}
247683d8b6546ccd98ce30c65bc7ec716c42437e569aVinicius Costa Gomes
247717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedbergvoid btd_device_add_uuid(struct btd_device *device, const char *uuid)
247817541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg{
247917541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	GSList *uuid_list;
248017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	char *new_uuid;
248117541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
248217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	if (g_slist_find_custom(device->uuids, uuid,
248317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg				(GCompareFunc) strcasecmp))
248417541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg		return;
248517541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
248617541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	new_uuid = g_strdup(uuid);
248717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	uuid_list = g_slist_append(NULL, new_uuid);
248817541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
248917541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	device_probe_drivers(device, uuid_list);
249017541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
24910e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg	g_free(new_uuid);
249217541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	g_slist_free(uuid_list);
249317541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
24940e073403c77dd0906cd89dbd2d2b6707f4493188Johan Hedberg	store_profiles(device);
249517541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg	services_changed(device);
249617541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg}
249717541956196b13ee083852fd4124cd8cfd0928a4Johan Hedberg
2498548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedbergconst sdp_record_t *btd_device_get_record(struct btd_device *device,
2499bac81ba536a0d77154e01a71b8bb1bd1712d42f6Johan Hedberg							const char *uuid)
2500548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg{
2501548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	bdaddr_t src;
2502548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
250382520ced2eb56caef66cf1265858a76d714fa6c5Luiz Augusto von Dentz	if (device->tmp_records) {
250482520ced2eb56caef66cf1265858a76d714fa6c5Luiz Augusto von Dentz		const sdp_record_t *record;
250582520ced2eb56caef66cf1265858a76d714fa6c5Luiz Augusto von Dentz
250682520ced2eb56caef66cf1265858a76d714fa6c5Luiz Augusto von Dentz		record = find_record_in_list(device->tmp_records, uuid);
250782520ced2eb56caef66cf1265858a76d714fa6c5Luiz Augusto von Dentz		if (record != NULL)
250882520ced2eb56caef66cf1265858a76d714fa6c5Luiz Augusto von Dentz			return record;
250982520ced2eb56caef66cf1265858a76d714fa6c5Luiz Augusto von Dentz	}
2510548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2511548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	adapter_get_address(device->adapter, &src);
2512548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2513548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	device->tmp_records = read_records(&src, &device->bdaddr);
2514548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	if (!device->tmp_records)
2515548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg		return NULL;
2516548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2517548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg	return find_record_in_list(device->tmp_records, uuid);
2518548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg}
2519548026e08bd9b83b3685d515a916e2cf674184f3Johan Hedberg
2520c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzint btd_register_device_driver(struct btd_device_driver *driver)
2521c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
2522c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_append(device_drivers, driver);
2523c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
2524c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	return 0;
2525c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
2526c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz
2527c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentzvoid btd_unregister_device_driver(struct btd_device_driver *driver)
2528c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz{
2529c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz	device_drivers = g_slist_remove(device_drivers, driver);
2530c560d02ccf1dd156f068b1da8a3e7d75d2319dfdLuiz Augusto von Dentz}
25310ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25320ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentzstruct btd_device *btd_device_ref(struct btd_device *device)
25330ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz{
25340ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	device->ref++;
25350ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25360f775bfff64dc5e073b3bd098c296da4660aa072Luiz Augusto von Dentz	DBG("%p: ref=%d", device, device->ref);
25370ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25380ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	return device;
25390ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz}
25400ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25410ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentzvoid btd_device_unref(struct btd_device *device)
25420ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz{
25438d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	DBusConnection *conn = get_dbus_connection();
25440ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	gchar *path;
25450ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25460ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	device->ref--;
25470ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25480f775bfff64dc5e073b3bd098c296da4660aa072Luiz Augusto von Dentz	DBG("%p: ref=%d", device, device->ref);
25490ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25500ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	if (device->ref > 0)
25510ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz		return;
25520ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25530ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	path = g_strdup(device->path);
25540ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25558d7017d8be3305ed828dee928fc2731d0d89a27bLuiz Augusto von Dentz	g_dbus_unregister_interface(conn, path, DEVICE_INTERFACE);
25560ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz
25570ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz	g_free(path);
25580ba18c28575090e30fcb3023ea1b4039a2e27610Luiz Augusto von Dentz}
25591f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demario
25601f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demariovoid device_set_class(struct btd_device *device, uint32_t value)
25611f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demario{
25621f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demario	DBusConnection *conn = get_dbus_connection();
25631f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demario
25641f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demario	emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Class",
25651f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demario				DBUS_TYPE_UINT32, &value);
25661f921e01c700151bcac3dc9477d85bfff36e05d3Sheldon Demario}
2567