blob: caf933508c098e5fe2d5ff325d333392f8808fa3 [file] [log] [blame]
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001/*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
Marcel Holtmanncde69652014-02-11 10:42:56 -08005 * Copyright (C) 2013-2014 Intel Corporation. All rights reserved.
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02006 *
7 *
Marcel Holtmanncde69652014-02-11 10:42:56 -08008 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020012 *
Marcel Holtmanncde69652014-02-11 10:42:56 -080013 * This library is distributed in the hope that it will be useful,
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Marcel Holtmanncde69652014-02-11 10:42:56 -080015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020017 *
Marcel Holtmanncde69652014-02-11 10:42:56 -080018 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
Luiz Augusto von Dentzfaeb9f02014-03-06 14:55:57 +020028#include <stdlib.h>
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020029#include <stdbool.h>
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +020030#include <errno.h>
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020031#include <glib.h>
32
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020033#include "btio/btio.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020034#include "lib/bluetooth.h"
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +020035#include "lib/sdp.h"
36#include "lib/sdp_lib.h"
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +020037#include "src/sdp-client.h"
Claudio Takahasifbf21032014-03-24 16:25:23 -030038#include "src/shared/util.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020039#include "src/log.h"
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +020040
Andrei Emeltchenkoded70b72014-02-26 16:32:14 +020041#include "avctp.h"
Andrei Emeltchenko4351d462014-02-13 17:20:07 +020042#include "avrcp-lib.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020043#include "hal-msg.h"
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020044#include "ipc-common.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020045#include "ipc.h"
Szymon Jancdd1e44f2014-02-24 13:44:12 +010046#include "bluetooth.h"
47#include "avrcp.h"
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +020048#include "utils.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020049
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +020050#define L2CAP_PSM_AVCTP 0x17
51
52#define AVRCP_FEATURE_CATEGORY_1 0x0001
53#define AVRCP_FEATURE_CATEGORY_2 0x0002
54#define AVRCP_FEATURE_CATEGORY_3 0x0004
55#define AVRCP_FEATURE_CATEGORY_4 0x0008
56
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020057static bdaddr_t adapter_addr;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +020058static uint32_t record_id = 0;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020059static GSList *devices = NULL;
60static GIOChannel *server = NULL;
Szymon Jancdd1e44f2014-02-24 13:44:12 +010061static struct ipc *hal_ipc = NULL;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020062
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020063struct avrcp_request {
64 struct avrcp_device *dev;
65 uint8_t pdu_id;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010066 uint8_t event_id;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020067 uint8_t transaction;
68};
69
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020070struct avrcp_device {
71 bdaddr_t dst;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +020072 uint16_t version;
73 uint16_t features;
Andrei Emeltchenko4351d462014-02-13 17:20:07 +020074 struct avrcp *session;
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +020075 GIOChannel *io;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020076 GQueue *queue;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020077};
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020078
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010079static struct avrcp_request *pop_request(uint8_t pdu_id, uint8_t event_id,
80 bool peek)
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020081{
82 GSList *l;
83
84 for (l = devices; l; l = g_slist_next(l)) {
85 struct avrcp_device *dev = l->data;
86 GList *reqs = g_queue_peek_head_link(dev->queue);
87 int i;
88
89 for (i = 0; reqs; reqs = g_list_next(reqs), i++) {
90 struct avrcp_request *req = reqs->data;
91
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010092 if (req->pdu_id != pdu_id || req->event_id != event_id)
93 continue;
94
95 if (!peek)
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020096 g_queue_pop_nth(dev->queue, i);
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010097
98 return req;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020099 }
100 }
101
102 return NULL;
103}
104
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200105static void handle_get_play_status(const void *buf, uint16_t len)
106{
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200107 const struct hal_cmd_avrcp_get_play_status *cmd = buf;
108 uint8_t status;
109 struct avrcp_request *req;
110 int ret;
111
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200112 DBG("");
113
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100114 req = pop_request(AVRCP_GET_PLAY_STATUS, 0, false);
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200115 if (!req) {
116 status = HAL_STATUS_FAILED;
117 goto done;
118 }
119
120 ret = avrcp_get_play_status_rsp(req->dev->session, req->transaction,
121 cmd->position, cmd->duration,
122 cmd->status);
123 if (ret < 0) {
124 status = HAL_STATUS_FAILED;
125 g_free(req);
126 goto done;
127 }
128
129 status = HAL_STATUS_SUCCESS;
130 g_free(req);
131
132done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100133 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200134 HAL_OP_AVRCP_GET_PLAY_STATUS, status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200135}
136
137static void handle_list_player_attrs(const void *buf, uint16_t len)
138{
139 DBG("");
140
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100141 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
142 HAL_OP_AVRCP_LIST_PLAYER_ATTRS, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200143}
144
145static void handle_list_player_values(const void *buf, uint16_t len)
146{
147 DBG("");
148
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100149 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
150 HAL_OP_AVRCP_LIST_PLAYER_VALUES, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200151}
152
153static void handle_get_player_attrs(const void *buf, uint16_t len)
154{
155 DBG("");
156
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100157 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
158 HAL_OP_AVRCP_GET_PLAYER_ATTRS, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200159}
160
161static void handle_get_player_attrs_text(const void *buf, uint16_t len)
162{
163 DBG("");
164
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100165 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
166 HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200167}
168
169static void handle_get_player_values_text(const void *buf, uint16_t len)
170{
171 DBG("");
172
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100173 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
174 HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200175}
176
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100177static size_t write_element_text(uint8_t id, uint8_t text_len, uint8_t *text,
178 uint8_t *pdu)
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200179{
180 uint16_t charset = 106;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100181 size_t len = 0;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200182
Claudio Takahasic729b662014-03-24 16:25:26 -0300183 put_be32(id, pdu);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200184 pdu += 4;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100185 len += 4;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200186
Claudio Takahasia515e9e2014-03-24 16:25:25 -0300187 put_be16(charset, pdu);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200188 pdu += 2;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100189 len += 2;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200190
Claudio Takahasia515e9e2014-03-24 16:25:25 -0300191 put_be16(text_len, pdu);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200192 pdu += 2;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100193 len += 2;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200194
195 memcpy(pdu, text, text_len);
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100196 len += text_len;
197
198 return len;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200199}
200
201static void write_element_attrs(uint8_t *ptr, uint8_t number, uint8_t *pdu,
202 size_t *len)
203{
204 int i;
205
206 *pdu = number;
207 pdu++;
208 *len += 1;
209
210 for (i = 0; i < number; i++) {
211 struct hal_avrcp_player_setting_text *text = (void *) ptr;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100212 size_t ret;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200213
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100214 ret = write_element_text(text->id, text->len, text->text, pdu);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200215
216 ptr += sizeof(*text) + text->len;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100217 pdu += ret;
218 *len += ret;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200219 }
220}
221
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200222static void handle_get_element_attrs_text(const void *buf, uint16_t len)
223{
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200224 struct hal_cmd_avrcp_get_element_attrs_text *cmd = (void *) buf;
225 uint8_t status;
226 struct avrcp_request *req;
227 uint8_t pdu[IPC_MTU];
228 uint8_t *ptr;
229 size_t pdu_len;
230 int ret;
231
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200232 DBG("");
233
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100234 req = pop_request(AVRCP_GET_ELEMENT_ATTRIBUTES, 0, false);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200235 if (!req) {
236 status = HAL_STATUS_FAILED;
237 goto done;
238 }
239
240 ptr = (uint8_t *) &cmd->values[0];
241 pdu_len = 0;
242 write_element_attrs(ptr, cmd->number, pdu, &pdu_len);
243
244 ret = avrcp_get_element_attrs_rsp(req->dev->session, req->transaction,
245 pdu, pdu_len);
246 if (ret < 0) {
247 status = HAL_STATUS_FAILED;
248 g_free(req);
249 goto done;
250 }
251
252 status = HAL_STATUS_SUCCESS;
253 g_free(req);
254
255done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100256 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200257 HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT, status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200258}
259
260static void handle_set_player_attrs_value(const void *buf, uint16_t len)
261{
262 DBG("");
263
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100264 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
265 HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200266}
267
268static void handle_register_notification(const void *buf, uint16_t len)
269{
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200270 struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
271 uint8_t status;
272 struct avrcp_request *req;
273 uint8_t pdu[IPC_MTU];
274 size_t pdu_len;
Andrzej Kaczmarek5071d7d2014-03-04 21:43:21 +0100275 uint8_t code;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100276 bool peek = false;
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200277 int ret;
278
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200279 DBG("");
280
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100281 switch (cmd->type) {
282 case HAL_AVRCP_EVENT_TYPE_INTERIM:
283 code = AVC_CTYPE_INTERIM;
284 peek = true;
285 break;
286 case HAL_AVRCP_EVENT_TYPE_CHANGED:
287 code = AVC_CTYPE_CHANGED;
288 break;
289 default:
290 status = HAL_STATUS_FAILED;
291 goto done;
292 }
293
294 req = pop_request(AVRCP_REGISTER_NOTIFICATION, cmd->event, peek);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200295 if (!req) {
296 status = HAL_STATUS_FAILED;
297 goto done;
298 }
299
300 pdu[0] = cmd->event;
301 pdu_len = 1;
302
303 switch (cmd->event) {
304 case AVRCP_EVENT_STATUS_CHANGED:
305 case AVRCP_EVENT_TRACK_CHANGED:
306 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
307 memcpy(&pdu[1], cmd->data, cmd->len);
308 pdu_len += cmd->len;
309 break;
310 default:
311 status = HAL_STATUS_FAILED;
312 goto done;
313 }
314
315 ret = avrcp_register_notification_rsp(req->dev->session,
Andrzej Kaczmarek5071d7d2014-03-04 21:43:21 +0100316 req->transaction, code,
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200317 pdu, pdu_len);
318 if (ret < 0) {
319 status = HAL_STATUS_FAILED;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100320 if (!peek)
321 g_free(req);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200322 goto done;
323 }
324
325 status = HAL_STATUS_SUCCESS;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100326 if (!peek)
327 g_free(req);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200328
329done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100330 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200331 HAL_OP_AVRCP_REGISTER_NOTIFICATION, status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200332}
333
334static void handle_set_volume(const void *buf, uint16_t len)
335{
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200336 struct hal_cmd_avrcp_set_volume *cmd = (void *) buf;
337 struct avrcp_device *dev;
338 uint8_t status;
339 int ret;
340
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200341 DBG("");
342
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200343 if (!devices) {
344 error("AVRCP: No device found to set volume");
345 status = HAL_STATUS_FAILED;
346 goto done;
347 }
348
Szymon Janc7a2d6042014-04-29 13:17:25 +0200349 /*
350 * Peek the first device since the HAL cannot really address a specific
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200351 * device it might mean there could only be one connected.
352 */
353 dev = devices->data;
354
Luiz Augusto von Dentz94b32ee2014-04-03 17:59:27 +0300355 ret = avrcp_set_volume(dev->session, cmd->value & 0x7f);
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200356 if (ret < 0) {
357 status = HAL_STATUS_FAILED;
358 goto done;
359 }
360
361 status = HAL_STATUS_SUCCESS;
362
363done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100364 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200365 status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200366}
367
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +0200368static const struct ipc_handler cmd_handlers[] = {
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200369 /* HAL_OP_AVRCP_GET_PLAY_STATUS */
370 { handle_get_play_status, false,
371 sizeof(struct hal_cmd_avrcp_get_play_status) },
372 /* HAL_OP_AVRCP_LIST_PLAYER_ATTRS */
373 { handle_list_player_attrs, true,
374 sizeof(struct hal_cmd_avrcp_list_player_attrs) },
375 /* HAL_OP_AVRCP_LIST_PLAYER_VALUES */
376 { handle_list_player_values, true,
377 sizeof(struct hal_cmd_avrcp_list_player_values) },
378 /* HAL_OP_AVRCP_GET_PLAYER_ATTRS */
379 { handle_get_player_attrs, true,
380 sizeof(struct hal_cmd_avrcp_get_player_attrs) },
381 /* HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT */
382 { handle_get_player_attrs_text, true,
383 sizeof(struct hal_cmd_avrcp_get_player_attrs_text) },
384 /* HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT */
385 { handle_get_player_values_text, true,
386 sizeof(struct hal_cmd_avrcp_get_player_values_text) },
387 /* HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT */
388 { handle_get_element_attrs_text, true,
389 sizeof(struct hal_cmd_avrcp_get_element_attrs_text) },
390 /* HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE */
391 { handle_set_player_attrs_value, true,
392 sizeof(struct hal_cmd_avrcp_set_player_attrs_value) },
393 /* HAL_OP_AVRCP_REGISTER_NOTIFICATION */
394 { handle_register_notification, true,
395 sizeof(struct hal_cmd_avrcp_register_notification) },
396 /* HAL_OP_AVRCP_SET_VOLUME */
397 { handle_set_volume, false, sizeof(struct hal_cmd_avrcp_set_volume) },
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +0200398};
399
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +0200400static sdp_record_t *avrcp_record(void)
401{
402 sdp_list_t *svclass_id, *pfseq, *apseq, *root;
403 uuid_t root_uuid, l2cap, avctp, avrtg;
404 sdp_profile_desc_t profile[1];
405 sdp_list_t *aproto_control, *proto_control[2];
406 sdp_record_t *record;
407 sdp_data_t *psm, *version, *features;
408 uint16_t lp = L2CAP_PSM_AVCTP;
Szymon Jancc8420c92014-03-18 15:40:04 +0100409 uint16_t avrcp_ver = 0x0105, avctp_ver = 0x0104;
Szymon Janc45eb43e2014-03-20 14:27:07 +0100410 uint16_t feat = (AVRCP_FEATURE_CATEGORY_1 |
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +0200411 AVRCP_FEATURE_CATEGORY_2 |
412 AVRCP_FEATURE_CATEGORY_3 |
413 AVRCP_FEATURE_CATEGORY_4);
414
415 record = sdp_record_alloc();
416 if (!record)
417 return NULL;
418
419 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
420 root = sdp_list_append(NULL, &root_uuid);
421 sdp_set_browse_groups(record, root);
422
423 /* Service Class ID List */
424 sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
425 svclass_id = sdp_list_append(NULL, &avrtg);
426 sdp_set_service_classes(record, svclass_id);
427
428 /* Protocol Descriptor List */
429 sdp_uuid16_create(&l2cap, L2CAP_UUID);
430 proto_control[0] = sdp_list_append(NULL, &l2cap);
431 psm = sdp_data_alloc(SDP_UINT16, &lp);
432 proto_control[0] = sdp_list_append(proto_control[0], psm);
433 apseq = sdp_list_append(NULL, proto_control[0]);
434
435 sdp_uuid16_create(&avctp, AVCTP_UUID);
436 proto_control[1] = sdp_list_append(NULL, &avctp);
437 version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
438 proto_control[1] = sdp_list_append(proto_control[1], version);
439 apseq = sdp_list_append(apseq, proto_control[1]);
440
441 aproto_control = sdp_list_append(NULL, apseq);
442 sdp_set_access_protos(record, aproto_control);
443
444 /* Bluetooth Profile Descriptor List */
445 sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
446 profile[0].version = avrcp_ver;
447 pfseq = sdp_list_append(NULL, &profile[0]);
448 sdp_set_profile_descs(record, pfseq);
449
450 features = sdp_data_alloc(SDP_UINT16, &feat);
451 sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
452
Andrei Emeltchenko9f42e2d2014-02-21 17:23:48 +0200453 sdp_set_info_attr(record, "AVRCP TG", NULL, NULL);
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +0200454
455 sdp_data_free(psm);
456 sdp_data_free(version);
457 sdp_list_free(proto_control[0], NULL);
458 sdp_list_free(proto_control[1], NULL);
459 sdp_list_free(apseq, NULL);
460 sdp_list_free(aproto_control, NULL);
461 sdp_list_free(pfseq, NULL);
462 sdp_list_free(root, NULL);
463 sdp_list_free(svclass_id, NULL);
464
465 return record;
466}
467
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200468static void avrcp_device_free(void *data)
469{
470 struct avrcp_device *dev = data;
471
Luiz Augusto von Dentz05cb6b82014-03-06 14:58:02 +0200472 if (dev->queue) {
473 g_queue_foreach(dev->queue, (GFunc) g_free, NULL);
474 g_queue_free(dev->queue);
475 }
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200476
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200477 if (dev->session)
Andrei Emeltchenko4351d462014-02-13 17:20:07 +0200478 avrcp_shutdown(dev->session);
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200479
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +0200480 if (dev->io) {
481 g_io_channel_shutdown(dev->io, FALSE, NULL);
482 g_io_channel_unref(dev->io);
483 }
484
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200485 g_free(dev);
486}
487
Luiz Augusto von Dentz939d25f2014-02-06 14:32:18 +0200488static void avrcp_device_remove(struct avrcp_device *dev)
489{
490 devices = g_slist_remove(devices, dev);
491 avrcp_device_free(dev);
492}
493
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200494static struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
495{
496 struct avrcp_device *dev;
497
498 dev = g_new0(struct avrcp_device, 1);
499 bacpy(&dev->dst, dst);
500 devices = g_slist_prepend(devices, dev);
501
502 return dev;
503}
504
505static int device_cmp(gconstpointer s, gconstpointer user_data)
506{
507 const struct avrcp_device *dev = s;
508 const bdaddr_t *dst = user_data;
509
510 return bacmp(&dev->dst, dst);
511}
512
Andrei Emeltchenko4351d462014-02-13 17:20:07 +0200513static struct avrcp_device *avrcp_device_find(const bdaddr_t *dst)
514{
515 GSList *l;
516
517 l = g_slist_find_custom(devices, dst, device_cmp);
518 if (!l)
519 return NULL;
520
521 return l->data;
522}
523
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200524static void disconnect_cb(void *data)
525{
526 struct avrcp_device *dev = data;
527
528 DBG("");
529
530 dev->session = NULL;
531
Luiz Augusto von Dentz939d25f2014-02-06 14:32:18 +0200532 avrcp_device_remove(dev);
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200533}
534
Luiz Augusto von Dentz611c2ca2014-03-01 16:29:23 +0200535static bool handle_fast_forward(struct avrcp *session, bool pressed,
536 void *user_data)
537{
538 struct hal_ev_avrcp_passthrough_cmd ev;
539
540 DBG("pressed %s", pressed ? "true" : "false");
541
542 ev.id = AVC_FAST_FORWARD;
543 ev.state = pressed;
544
545 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
546 HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev);
547
548 return true;
549}
550
Luiz Augusto von Dentz44019b82014-03-01 16:48:34 +0200551static bool handle_rewind(struct avrcp *session, bool pressed,
552 void *user_data)
553{
554 struct hal_ev_avrcp_passthrough_cmd ev;
555
556 DBG("pressed %s", pressed ? "true" : "false");
557
558 ev.id = AVC_REWIND;
559 ev.state = pressed;
560
561 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
562 HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev);
563
564 return true;
565}
566
Luiz Augusto von Dentz611c2ca2014-03-01 16:29:23 +0200567static const struct avrcp_passthrough_handler passthrough_handlers[] = {
568 { AVC_FAST_FORWARD, handle_fast_forward },
Luiz Augusto von Dentz44019b82014-03-01 16:48:34 +0200569 { AVC_REWIND, handle_rewind },
Luiz Augusto von Dentz611c2ca2014-03-01 16:29:23 +0200570 { },
571};
572
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200573static int handle_get_capabilities_cmd(struct avrcp *session,
574 uint8_t transaction, void *user_data)
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200575{
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200576 uint8_t events[] = { AVRCP_EVENT_STATUS_CHANGED,
577 AVRCP_EVENT_TRACK_CHANGED,
578 AVRCP_EVENT_PLAYBACK_POS_CHANGED };
579
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200580 DBG("");
581
Szymon Janc7a2d6042014-04-29 13:17:25 +0200582 /*
583 * Android do not provide this info via HAL so the list most
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200584 * be hardcoded according to what RegisterNotification can
Szymon Janc7a2d6042014-04-29 13:17:25 +0200585 * actually handle
586 */
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200587 avrcp_get_capabilities_rsp(session, transaction, sizeof(events),
588 events);
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200589
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200590 return -EAGAIN;
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200591}
592
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200593static void push_request(struct avrcp_device *dev, uint8_t pdu_id,
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100594 uint8_t event_id, uint8_t transaction)
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200595{
596 struct avrcp_request *req;
597
598 req = g_new0(struct avrcp_request, 1);
599 req->dev = dev;
600 req->pdu_id = pdu_id;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100601 req->event_id = event_id;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200602 req->transaction = transaction;
603
604 g_queue_push_tail(dev->queue, req);
605}
606
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200607static int handle_get_play_status_cmd(struct avrcp *session,
608 uint8_t transaction, void *user_data)
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200609{
610 struct avrcp_device *dev = user_data;
611
612 DBG("");
613
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200614 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
615 HAL_EV_AVRCP_GET_PLAY_STATUS, 0, NULL);
616
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100617 push_request(dev, AVRCP_GET_PLAY_STATUS, 0, transaction);
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200618
619 return -EAGAIN;
620}
621
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200622static int handle_get_element_attrs_cmd(struct avrcp *session,
623 uint8_t transaction, uint64_t uid,
624 uint8_t number, uint32_t *attrs,
625 void *user_data)
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200626{
627 struct avrcp_device *dev = user_data;
628 uint8_t buf[IPC_MTU];
629 struct hal_ev_avrcp_get_element_attrs *ev = (void *) buf;
630 int i;
631
632 DBG("");
633
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200634 ev->number = number;
Luiz Augusto von Dentzfac848f2014-03-08 00:43:38 +0200635 /* Set everything in case of empty list */
636 if (ev->number == 0) {
637 for (i = 0; i < HAL_AVRCP_MEDIA_ATTR_DURATION; i++) {
638 /* Skip 0x00 as the attributes start with 0x01 */
639 ev->attrs[i] = i + 1;
640 }
641 ev->number = i;
642 goto done;
643 }
644
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200645 for (i = 0; i < number; i++)
646 ev->attrs[i] = attrs[i];
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200647
Luiz Augusto von Dentzfac848f2014-03-08 00:43:38 +0200648done:
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200649 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
650 HAL_EV_AVRCP_GET_ELEMENT_ATTRS,
651 sizeof(*ev) + ev->number, ev);
652
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100653 push_request(dev, AVRCP_GET_ELEMENT_ATTRIBUTES, 0, transaction);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200654
655 return -EAGAIN;
656
657}
658
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200659static int handle_register_notification_cmd(struct avrcp *session,
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200660 uint8_t transaction,
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200661 uint8_t event,
662 uint32_t interval,
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200663 void *user_data)
664{
665 struct avrcp_device *dev = user_data;
666 struct hal_ev_avrcp_register_notification ev;
667
668 DBG("");
669
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200670 /* TODO: Add any missing events supported by Android */
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200671 switch (event) {
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200672 case AVRCP_EVENT_STATUS_CHANGED:
673 case AVRCP_EVENT_TRACK_CHANGED:
674 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
675 break;
676 default:
677 return -EINVAL;
678 }
679
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200680 ev.event = event;
681 ev.param = interval;
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200682
683 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
684 HAL_EV_AVRCP_REGISTER_NOTIFICATION,
685 sizeof(ev), &ev);
686
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200687 push_request(dev, AVRCP_REGISTER_NOTIFICATION, event, transaction);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200688
689 return -EAGAIN;
690}
691
Luiz Augusto von Dentz524fceb2014-03-16 19:39:46 +0200692static const struct avrcp_control_ind control_ind = {
693 .get_capabilities = handle_get_capabilities_cmd,
694 .get_play_status = handle_get_play_status_cmd,
695 .get_element_attributes = handle_get_element_attrs_cmd,
696 .register_notification = handle_register_notification_cmd,
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200697};
698
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200699static bool handle_register_notification_rsp(struct avrcp *session, int err,
700 uint8_t code, uint8_t event,
701 uint8_t *params,
702 void *user_data)
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200703{
704 struct avrcp_device *dev = user_data;
705 struct hal_ev_avrcp_volume_changed ev;
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200706
707 if (err < 0) {
708 error("AVRCP: %s", strerror(-err));
709 return false;
710 }
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200711
712 if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200713 return false;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200714
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200715 if (event != AVRCP_EVENT_VOLUME_CHANGED)
716 return false;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200717
Luiz Augusto von Dentz69027f82014-03-10 13:56:25 +0200718 ev.type = code;
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200719 ev.volume = params[0] & 0x7f;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200720
721 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
722 HAL_EV_AVRCP_VOLUME_CHANGED,
723 sizeof(ev), &ev);
724
725 if (code == AVC_CTYPE_INTERIM)
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200726 return true;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200727
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200728 avrcp_register_notification(dev->session, event, 0);
729 return false;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200730}
731
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200732static void handle_get_capabilities_rsp(struct avrcp *session, int err,
733 uint8_t number, uint8_t *events,
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200734 void *user_data)
735{
736 struct avrcp_device *dev = user_data;
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200737 int i;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200738
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200739 if (err < 0) {
740 error("AVRCP: %s", strerror(-err));
741 return;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200742 }
743
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200744 for (i = 0; i < number; i++) {
745 if (events[i] != AVRCP_EVENT_VOLUME_CHANGED)
746 continue;
747
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200748 avrcp_register_notification(dev->session, events[i], 0);
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200749 break;
750 }
751
752 return;
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200753}
754
Luiz Augusto von Dentz94b32ee2014-04-03 17:59:27 +0300755static void handle_set_volume_rsp(struct avrcp *session, int err,
756 uint8_t value, void *user_data)
757{
758 struct hal_ev_avrcp_volume_changed ev;
759
760 if (err < 0) {
761 ev.volume = 0;
762 ev.type = AVC_CTYPE_REJECTED;
763 goto done;
764 }
765
766 ev.volume = value;
767 ev.type = AVC_CTYPE_ACCEPTED;
768
769done:
770 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
771 HAL_EV_AVRCP_VOLUME_CHANGED,
772 sizeof(ev), &ev);
773}
774
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200775static const struct avrcp_control_cfm control_cfm = {
776 .get_capabilities = handle_get_capabilities_rsp,
Luiz Augusto von Dentz8878bd42014-03-26 14:25:08 +0200777 .register_notification = handle_register_notification_rsp,
Luiz Augusto von Dentz94b32ee2014-04-03 17:59:27 +0300778 .set_volume = handle_set_volume_rsp,
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200779};
780
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200781static int avrcp_device_add_session(struct avrcp_device *dev, int fd,
782 uint16_t imtu, uint16_t omtu)
783{
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +0200784 struct hal_ev_avrcp_remote_features ev;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200785 char address[18];
786
787 dev->session = avrcp_new(fd, imtu, omtu, dev->version);
788 if (!dev->session)
789 return -EINVAL;
790
791 avrcp_set_destroy_cb(dev->session, disconnect_cb, dev);
792 avrcp_set_passthrough_handlers(dev->session, passthrough_handlers,
793 dev);
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200794 avrcp_register_player(dev->session, &control_ind, &control_cfm, dev);
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200795
796 dev->queue = g_queue_new();
797
798 ba2str(&dev->dst, address);
799
800 /* FIXME: get the real name of the device */
801 avrcp_init_uinput(dev->session, "bluetooth", address);
802
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +0200803 bdaddr2android(&dev->dst, ev.bdaddr);
804 ev.features = HAL_AVRCP_FEATURE_NONE;
805
806 DBG("version 0x%02x", dev->version);
807
808 if (dev->version < 0x0103)
809 goto done;
810
811 ev.features |= HAL_AVRCP_FEATURE_METADATA;
812
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200813 if (dev->version < 0x0104)
814 goto done;
815
816 ev.features |= HAL_AVRCP_FEATURE_ABSOLUTE_VOLUME;
817
Luiz Augusto von Dentz545963a2014-03-19 16:59:07 +0200818 avrcp_get_capabilities(dev->session, CAP_EVENTS_SUPPORTED);
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200819
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +0200820done:
821 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
822 HAL_EV_AVRCP_REMOTE_FEATURES,
823 sizeof(ev), &ev);
824
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200825 return 0;
826}
827
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200828static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
829{
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200830 struct avrcp_device *dev = user_data;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200831 uint16_t imtu, omtu;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200832 char address[18];
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200833 GError *gerr = NULL;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200834 int fd;
835
836 if (err) {
837 error("%s", err->message);
838 return;
839 }
840
841 bt_io_get(chan, &gerr,
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200842 BT_IO_OPT_DEST, address,
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200843 BT_IO_OPT_IMTU, &imtu,
844 BT_IO_OPT_OMTU, &omtu,
845 BT_IO_OPT_INVALID);
846 if (gerr) {
847 error("%s", gerr->message);
848 g_error_free(gerr);
849 g_io_channel_shutdown(chan, TRUE, NULL);
850 return;
851 }
852
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200853 fd = g_io_channel_unix_get_fd(chan);
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200854 if (avrcp_device_add_session(dev, fd, imtu, omtu) < 0) {
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200855 avrcp_device_free(dev);
856 return;
857 }
858
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200859 g_io_channel_set_close_on_unref(chan, FALSE);
860
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +0200861 if (dev->io) {
862 g_io_channel_unref(dev->io);
863 dev->io = NULL;
864 }
865
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200866 DBG("%s connected", address);
867}
868
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200869static bool avrcp_device_connect(struct avrcp_device *dev, BtIOConnect cb)
870{
871 GError *err = NULL;
872
873 dev->io = bt_io_connect(cb, dev, NULL, &err,
874 BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
875 BT_IO_OPT_DEST_BDADDR, &dev->dst,
876 BT_IO_OPT_PSM, L2CAP_PSM_AVCTP,
877 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
878 BT_IO_OPT_INVALID);
879 if (err) {
880 error("%s", err->message);
881 g_error_free(err);
882 return false;
883 }
884
885 return true;
886}
887
888static void search_cb(sdp_list_t *recs, int err, gpointer data)
889{
890 struct avrcp_device *dev = data;
891 sdp_list_t *list;
892
893 DBG("");
894
895 if (err < 0) {
896 error("Unable to get AV_REMOTE_SVCLASS_ID SDP record: %s",
897 strerror(-err));
898 goto fail;
899 }
900
901 if (!recs || !recs->data) {
902 error("No AVRCP records found");
903 goto fail;
904 }
905
906 for (list = recs; list; list = list->next) {
907 sdp_record_t *rec = list->data;
Luiz Augusto von Dentzfaeb9f02014-03-06 14:55:57 +0200908 sdp_list_t *l;
909 sdp_profile_desc_t *desc;
910 int features;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200911
Luiz Augusto von Dentzfaeb9f02014-03-06 14:55:57 +0200912 if (sdp_get_profile_descs(rec, &l) < 0)
913 continue;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200914
Luiz Augusto von Dentzfaeb9f02014-03-06 14:55:57 +0200915 desc = l->data;
916 dev->version = desc->version;
917
918 if (sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES,
919 &features) == 0)
920 dev->features = features;
921
922 sdp_list_free(l, free);
923 break;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200924 }
925
926 if (dev->io) {
927 GError *gerr = NULL;
928 if (!bt_io_accept(dev->io, connect_cb, dev, NULL, &gerr)) {
929 error("bt_io_accept: %s", gerr->message);
930 g_error_free(gerr);
931 goto fail;
932 }
933 return;
934 }
935
936 if (!avrcp_device_connect(dev, connect_cb)) {
937 error("Unable to connect to AVRCP");
938 goto fail;
939 }
940
941 return;
942
943fail:
944 avrcp_device_remove(dev);
945}
946
947static int avrcp_device_search(struct avrcp_device *dev)
948{
949 uuid_t uuid;
950
951 sdp_uuid16_create(&uuid, AV_REMOTE_SVCLASS_ID);
952
953 return bt_search_service(&adapter_addr, &dev->dst, &uuid, search_cb,
954 dev, NULL, 0);
955}
956
957static void confirm_cb(GIOChannel *chan, gpointer data)
958{
959 struct avrcp_device *dev;
960 char address[18];
Szymon Janc641128b2014-04-23 14:01:42 +0200961 bdaddr_t dst;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200962 GError *err = NULL;
963
964 bt_io_get(chan, &err,
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200965 BT_IO_OPT_DEST_BDADDR, &dst,
966 BT_IO_OPT_DEST, address,
967 BT_IO_OPT_INVALID);
968 if (err) {
969 error("%s", err->message);
970 g_error_free(err);
971 g_io_channel_shutdown(chan, TRUE, NULL);
972 return;
973 }
974
975 DBG("incoming connect from %s", address);
976
977 dev = avrcp_device_find(&dst);
978 if (dev && dev->session) {
979 error("AVRCP: Refusing unexpected connect");
980 g_io_channel_shutdown(chan, TRUE, NULL);
981 return;
982 }
983
984 dev = avrcp_device_new(&dst);
985 if (avrcp_device_search(dev) < 0) {
986 error("AVRCP: Failed to search SDP details");
987 avrcp_device_free(dev);
988 g_io_channel_shutdown(chan, TRUE, NULL);
989 }
990
991 dev->io = g_io_channel_ref(chan);
992}
993
Szymon Janc14fc3c52014-03-03 00:50:44 +0100994bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +0200995{
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200996 GError *err = NULL;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +0200997 sdp_record_t *rec;
998
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +0200999 DBG("");
1000
1001 bacpy(&adapter_addr, addr);
1002
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +02001003 server = bt_io_listen(NULL, confirm_cb, NULL, NULL, &err,
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +02001004 BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
1005 BT_IO_OPT_PSM, L2CAP_PSM_AVCTP,
1006 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
1007 BT_IO_OPT_INVALID);
1008 if (!server) {
1009 error("Failed to listen on AVDTP channel: %s", err->message);
1010 g_error_free(err);
1011 return false;
1012 }
1013
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001014 rec = avrcp_record();
1015 if (!rec) {
1016 error("Failed to allocate AVRCP record");
Andrei Emeltchenko1d7219c2014-01-30 15:23:43 +02001017 goto fail;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001018 }
1019
1020 if (bt_adapter_add_record(rec, 0) < 0) {
1021 error("Failed to register AVRCP record");
1022 sdp_record_free(rec);
Andrei Emeltchenko1d7219c2014-01-30 15:23:43 +02001023 goto fail;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001024 }
1025 record_id = rec->handle;
1026
Szymon Jancdd1e44f2014-02-24 13:44:12 +01001027 hal_ipc = ipc;
1028
1029 ipc_register(hal_ipc, HAL_SERVICE_ID_AVRCP, cmd_handlers,
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001030 G_N_ELEMENTS(cmd_handlers));
1031
1032 return true;
Andrei Emeltchenko1d7219c2014-01-30 15:23:43 +02001033fail:
1034 g_io_channel_shutdown(server, TRUE, NULL);
1035 g_io_channel_unref(server);
1036 server = NULL;
1037
1038 return false;
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001039}
1040
1041void bt_avrcp_unregister(void)
1042{
1043 DBG("");
1044
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +02001045 g_slist_free_full(devices, avrcp_device_free);
1046 devices = NULL;
1047
Szymon Jancdd1e44f2014-02-24 13:44:12 +01001048 ipc_unregister(hal_ipc, HAL_SERVICE_ID_AVRCP);
1049 hal_ipc = NULL;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001050
1051 bt_adapter_remove_record(record_id);
1052 record_id = 0;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +02001053
1054 if (server) {
1055 g_io_channel_shutdown(server, TRUE, NULL);
1056 g_io_channel_unref(server);
1057 server = NULL;
1058 }
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001059}
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001060
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001061void bt_avrcp_connect(const bdaddr_t *dst)
1062{
1063 struct avrcp_device *dev;
1064 char addr[18];
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001065
1066 DBG("");
1067
Andrei Emeltchenko4351d462014-02-13 17:20:07 +02001068 if (avrcp_device_find(dst))
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001069 return;
1070
1071 dev = avrcp_device_new(dst);
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +02001072 if (avrcp_device_search(dev) < 0) {
1073 error("AVRCP: Failed to search SDP details");
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001074 avrcp_device_free(dev);
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001075 }
1076
1077 ba2str(&dev->dst, addr);
1078 DBG("connecting to %s", addr);
1079}
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001080
1081void bt_avrcp_disconnect(const bdaddr_t *dst)
1082{
1083 struct avrcp_device *dev;
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001084
1085 DBG("");
1086
Andrei Emeltchenko4351d462014-02-13 17:20:07 +02001087 dev = avrcp_device_find(dst);
1088 if (!dev)
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001089 return;
1090
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001091 if (dev->session) {
Andrei Emeltchenko4351d462014-02-13 17:20:07 +02001092 avrcp_shutdown(dev->session);
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001093 return;
1094 }
1095
Luiz Augusto von Dentz939d25f2014-02-06 14:32:18 +02001096 avrcp_device_remove(dev);
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001097}