blob: eab519ae1a8375e39e6fd721364169ea5664117d [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"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020038#include "src/log.h"
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +020039
Andrei Emeltchenkoded70b72014-02-26 16:32:14 +020040#include "avctp.h"
Andrei Emeltchenko4351d462014-02-13 17:20:07 +020041#include "avrcp-lib.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020042#include "hal-msg.h"
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020043#include "ipc-common.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020044#include "ipc.h"
Szymon Jancdd1e44f2014-02-24 13:44:12 +010045#include "bluetooth.h"
46#include "avrcp.h"
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +020047#include "utils.h"
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020048
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +020049#define L2CAP_PSM_AVCTP 0x17
50
51#define AVRCP_FEATURE_CATEGORY_1 0x0001
52#define AVRCP_FEATURE_CATEGORY_2 0x0002
53#define AVRCP_FEATURE_CATEGORY_3 0x0004
54#define AVRCP_FEATURE_CATEGORY_4 0x0008
55
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020056static bdaddr_t adapter_addr;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +020057static uint32_t record_id = 0;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020058static GSList *devices = NULL;
59static GIOChannel *server = NULL;
Szymon Jancdd1e44f2014-02-24 13:44:12 +010060static struct ipc *hal_ipc = NULL;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020061
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020062struct avrcp_request {
63 struct avrcp_device *dev;
64 uint8_t pdu_id;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010065 uint8_t event_id;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020066 uint8_t transaction;
67};
68
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020069struct avrcp_device {
70 bdaddr_t dst;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +020071 uint16_t version;
72 uint16_t features;
Andrei Emeltchenko4351d462014-02-13 17:20:07 +020073 struct avrcp *session;
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +020074 GIOChannel *io;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020075 GQueue *queue;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +020076};
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +020077
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010078static struct avrcp_request *pop_request(uint8_t pdu_id, uint8_t event_id,
79 bool peek)
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020080{
81 GSList *l;
82
83 for (l = devices; l; l = g_slist_next(l)) {
84 struct avrcp_device *dev = l->data;
85 GList *reqs = g_queue_peek_head_link(dev->queue);
86 int i;
87
88 for (i = 0; reqs; reqs = g_list_next(reqs), i++) {
89 struct avrcp_request *req = reqs->data;
90
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010091 if (req->pdu_id != pdu_id || req->event_id != event_id)
92 continue;
93
94 if (!peek)
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020095 g_queue_pop_nth(dev->queue, i);
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +010096
97 return req;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +020098 }
99 }
100
101 return NULL;
102}
103
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200104static void handle_get_play_status(const void *buf, uint16_t len)
105{
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200106 const struct hal_cmd_avrcp_get_play_status *cmd = buf;
107 uint8_t status;
108 struct avrcp_request *req;
109 int ret;
110
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200111 DBG("");
112
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100113 req = pop_request(AVRCP_GET_PLAY_STATUS, 0, false);
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200114 if (!req) {
115 status = HAL_STATUS_FAILED;
116 goto done;
117 }
118
119 ret = avrcp_get_play_status_rsp(req->dev->session, req->transaction,
120 cmd->position, cmd->duration,
121 cmd->status);
122 if (ret < 0) {
123 status = HAL_STATUS_FAILED;
124 g_free(req);
125 goto done;
126 }
127
128 status = HAL_STATUS_SUCCESS;
129 g_free(req);
130
131done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100132 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200133 HAL_OP_AVRCP_GET_PLAY_STATUS, status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200134}
135
136static void handle_list_player_attrs(const void *buf, uint16_t len)
137{
138 DBG("");
139
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100140 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
141 HAL_OP_AVRCP_LIST_PLAYER_ATTRS, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200142}
143
144static void handle_list_player_values(const void *buf, uint16_t len)
145{
146 DBG("");
147
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100148 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
149 HAL_OP_AVRCP_LIST_PLAYER_VALUES, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200150}
151
152static void handle_get_player_attrs(const void *buf, uint16_t len)
153{
154 DBG("");
155
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100156 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
157 HAL_OP_AVRCP_GET_PLAYER_ATTRS, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200158}
159
160static void handle_get_player_attrs_text(const void *buf, uint16_t len)
161{
162 DBG("");
163
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100164 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
165 HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200166}
167
168static void handle_get_player_values_text(const void *buf, uint16_t len)
169{
170 DBG("");
171
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100172 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
173 HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200174}
175
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100176static size_t write_element_text(uint8_t id, uint8_t text_len, uint8_t *text,
177 uint8_t *pdu)
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200178{
179 uint16_t charset = 106;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100180 size_t len = 0;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200181
182 bt_put_be32(id, pdu);
183 pdu += 4;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100184 len += 4;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200185
186 bt_put_be16(charset, pdu);
187 pdu += 2;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100188 len += 2;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200189
190 bt_put_be16(text_len, pdu);
191 pdu += 2;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100192 len += 2;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200193
194 memcpy(pdu, text, text_len);
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100195 len += text_len;
196
197 return len;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200198}
199
200static void write_element_attrs(uint8_t *ptr, uint8_t number, uint8_t *pdu,
201 size_t *len)
202{
203 int i;
204
205 *pdu = number;
206 pdu++;
207 *len += 1;
208
209 for (i = 0; i < number; i++) {
210 struct hal_avrcp_player_setting_text *text = (void *) ptr;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100211 size_t ret;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200212
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100213 ret = write_element_text(text->id, text->len, text->text, pdu);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200214
215 ptr += sizeof(*text) + text->len;
Andrzej Kaczmarek3b205292014-03-04 21:43:23 +0100216 pdu += ret;
217 *len += ret;
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200218 }
219}
220
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200221static void handle_get_element_attrs_text(const void *buf, uint16_t len)
222{
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200223 struct hal_cmd_avrcp_get_element_attrs_text *cmd = (void *) buf;
224 uint8_t status;
225 struct avrcp_request *req;
226 uint8_t pdu[IPC_MTU];
227 uint8_t *ptr;
228 size_t pdu_len;
229 int ret;
230
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200231 DBG("");
232
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100233 req = pop_request(AVRCP_GET_ELEMENT_ATTRIBUTES, 0, false);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200234 if (!req) {
235 status = HAL_STATUS_FAILED;
236 goto done;
237 }
238
239 ptr = (uint8_t *) &cmd->values[0];
240 pdu_len = 0;
241 write_element_attrs(ptr, cmd->number, pdu, &pdu_len);
242
243 ret = avrcp_get_element_attrs_rsp(req->dev->session, req->transaction,
244 pdu, pdu_len);
245 if (ret < 0) {
246 status = HAL_STATUS_FAILED;
247 g_free(req);
248 goto done;
249 }
250
251 status = HAL_STATUS_SUCCESS;
252 g_free(req);
253
254done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100255 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200256 HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT, status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200257}
258
259static void handle_set_player_attrs_value(const void *buf, uint16_t len)
260{
261 DBG("");
262
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100263 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
264 HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE, HAL_STATUS_FAILED);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200265}
266
267static void handle_register_notification(const void *buf, uint16_t len)
268{
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200269 struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
270 uint8_t status;
271 struct avrcp_request *req;
272 uint8_t pdu[IPC_MTU];
273 size_t pdu_len;
Andrzej Kaczmarek5071d7d2014-03-04 21:43:21 +0100274 uint8_t code;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100275 bool peek = false;
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200276 int ret;
277
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200278 DBG("");
279
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100280 switch (cmd->type) {
281 case HAL_AVRCP_EVENT_TYPE_INTERIM:
282 code = AVC_CTYPE_INTERIM;
283 peek = true;
284 break;
285 case HAL_AVRCP_EVENT_TYPE_CHANGED:
286 code = AVC_CTYPE_CHANGED;
287 break;
288 default:
289 status = HAL_STATUS_FAILED;
290 goto done;
291 }
292
293 req = pop_request(AVRCP_REGISTER_NOTIFICATION, cmd->event, peek);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200294 if (!req) {
295 status = HAL_STATUS_FAILED;
296 goto done;
297 }
298
299 pdu[0] = cmd->event;
300 pdu_len = 1;
301
302 switch (cmd->event) {
303 case AVRCP_EVENT_STATUS_CHANGED:
304 case AVRCP_EVENT_TRACK_CHANGED:
305 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
306 memcpy(&pdu[1], cmd->data, cmd->len);
307 pdu_len += cmd->len;
308 break;
309 default:
310 status = HAL_STATUS_FAILED;
311 goto done;
312 }
313
314 ret = avrcp_register_notification_rsp(req->dev->session,
Andrzej Kaczmarek5071d7d2014-03-04 21:43:21 +0100315 req->transaction, code,
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200316 pdu, pdu_len);
317 if (ret < 0) {
318 status = HAL_STATUS_FAILED;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100319 if (!peek)
320 g_free(req);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200321 goto done;
322 }
323
324 status = HAL_STATUS_SUCCESS;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100325 if (!peek)
326 g_free(req);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200327
328done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100329 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200330 HAL_OP_AVRCP_REGISTER_NOTIFICATION, status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200331}
332
Luiz Augusto von Dentze173ce42014-03-09 13:17:42 +0200333static gboolean set_volume_rsp(struct avctp *conn,
334 uint8_t code, uint8_t subunit,
335 uint8_t *operands, size_t operand_count,
336 void *user_data)
337{
338 struct hal_ev_avrcp_volume_changed ev;
339 uint8_t *params;
340
341 if (code != AVC_CTYPE_ACCEPTED) {
342 ev.volume = 0;
343 ev.type = code;
344 goto done;
345 }
346
347 if (operands == NULL || operand_count < 7)
348 return FALSE;
349
350 params = &operands[7];
351
352 ev.volume = params[0] & 0x7F;
353 ev.type = code;
354
355done:
356 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
357 HAL_EV_AVRCP_VOLUME_CHANGED,
358 sizeof(ev), &ev);
359
360 return FALSE;
361}
362
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200363static void handle_set_volume(const void *buf, uint16_t len)
364{
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200365 struct hal_cmd_avrcp_set_volume *cmd = (void *) buf;
366 struct avrcp_device *dev;
367 uint8_t status;
368 int ret;
369
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200370 DBG("");
371
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200372 if (!devices) {
373 error("AVRCP: No device found to set volume");
374 status = HAL_STATUS_FAILED;
375 goto done;
376 }
377
378 /* Peek the first device since the HAL cannot really address a specific
379 * device it might mean there could only be one connected.
380 */
381 dev = devices->data;
382
Luiz Augusto von Dentze173ce42014-03-09 13:17:42 +0200383 ret = avrcp_set_volume(dev->session, cmd->value & 0x7f, set_volume_rsp,
384 dev);
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200385 if (ret < 0) {
386 status = HAL_STATUS_FAILED;
387 goto done;
388 }
389
390 status = HAL_STATUS_SUCCESS;
391
392done:
Szymon Jancdd1e44f2014-02-24 13:44:12 +0100393 ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
Luiz Augusto von Dentz75a75612014-03-07 13:16:00 +0200394 status);
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200395}
396
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +0200397static const struct ipc_handler cmd_handlers[] = {
Luiz Augusto von Dentzb41ca5f2014-02-19 18:58:47 +0200398 /* HAL_OP_AVRCP_GET_PLAY_STATUS */
399 { handle_get_play_status, false,
400 sizeof(struct hal_cmd_avrcp_get_play_status) },
401 /* HAL_OP_AVRCP_LIST_PLAYER_ATTRS */
402 { handle_list_player_attrs, true,
403 sizeof(struct hal_cmd_avrcp_list_player_attrs) },
404 /* HAL_OP_AVRCP_LIST_PLAYER_VALUES */
405 { handle_list_player_values, true,
406 sizeof(struct hal_cmd_avrcp_list_player_values) },
407 /* HAL_OP_AVRCP_GET_PLAYER_ATTRS */
408 { handle_get_player_attrs, true,
409 sizeof(struct hal_cmd_avrcp_get_player_attrs) },
410 /* HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT */
411 { handle_get_player_attrs_text, true,
412 sizeof(struct hal_cmd_avrcp_get_player_attrs_text) },
413 /* HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT */
414 { handle_get_player_values_text, true,
415 sizeof(struct hal_cmd_avrcp_get_player_values_text) },
416 /* HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT */
417 { handle_get_element_attrs_text, true,
418 sizeof(struct hal_cmd_avrcp_get_element_attrs_text) },
419 /* HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE */
420 { handle_set_player_attrs_value, true,
421 sizeof(struct hal_cmd_avrcp_set_player_attrs_value) },
422 /* HAL_OP_AVRCP_REGISTER_NOTIFICATION */
423 { handle_register_notification, true,
424 sizeof(struct hal_cmd_avrcp_register_notification) },
425 /* HAL_OP_AVRCP_SET_VOLUME */
426 { handle_set_volume, false, sizeof(struct hal_cmd_avrcp_set_volume) },
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +0200427};
428
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +0200429static sdp_record_t *avrcp_record(void)
430{
431 sdp_list_t *svclass_id, *pfseq, *apseq, *root;
432 uuid_t root_uuid, l2cap, avctp, avrtg;
433 sdp_profile_desc_t profile[1];
434 sdp_list_t *aproto_control, *proto_control[2];
435 sdp_record_t *record;
436 sdp_data_t *psm, *version, *features;
437 uint16_t lp = L2CAP_PSM_AVCTP;
Luiz Augusto von Dentz2f6781a2014-03-07 23:23:18 +0200438 uint16_t avrcp_ver = 0x0105, avctp_ver = 0x0103;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +0200439 uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
440 AVRCP_FEATURE_CATEGORY_2 |
441 AVRCP_FEATURE_CATEGORY_3 |
442 AVRCP_FEATURE_CATEGORY_4);
443
444 record = sdp_record_alloc();
445 if (!record)
446 return NULL;
447
448 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
449 root = sdp_list_append(NULL, &root_uuid);
450 sdp_set_browse_groups(record, root);
451
452 /* Service Class ID List */
453 sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
454 svclass_id = sdp_list_append(NULL, &avrtg);
455 sdp_set_service_classes(record, svclass_id);
456
457 /* Protocol Descriptor List */
458 sdp_uuid16_create(&l2cap, L2CAP_UUID);
459 proto_control[0] = sdp_list_append(NULL, &l2cap);
460 psm = sdp_data_alloc(SDP_UINT16, &lp);
461 proto_control[0] = sdp_list_append(proto_control[0], psm);
462 apseq = sdp_list_append(NULL, proto_control[0]);
463
464 sdp_uuid16_create(&avctp, AVCTP_UUID);
465 proto_control[1] = sdp_list_append(NULL, &avctp);
466 version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
467 proto_control[1] = sdp_list_append(proto_control[1], version);
468 apseq = sdp_list_append(apseq, proto_control[1]);
469
470 aproto_control = sdp_list_append(NULL, apseq);
471 sdp_set_access_protos(record, aproto_control);
472
473 /* Bluetooth Profile Descriptor List */
474 sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
475 profile[0].version = avrcp_ver;
476 pfseq = sdp_list_append(NULL, &profile[0]);
477 sdp_set_profile_descs(record, pfseq);
478
479 features = sdp_data_alloc(SDP_UINT16, &feat);
480 sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
481
Andrei Emeltchenko9f42e2d2014-02-21 17:23:48 +0200482 sdp_set_info_attr(record, "AVRCP TG", NULL, NULL);
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +0200483
484 sdp_data_free(psm);
485 sdp_data_free(version);
486 sdp_list_free(proto_control[0], NULL);
487 sdp_list_free(proto_control[1], NULL);
488 sdp_list_free(apseq, NULL);
489 sdp_list_free(aproto_control, NULL);
490 sdp_list_free(pfseq, NULL);
491 sdp_list_free(root, NULL);
492 sdp_list_free(svclass_id, NULL);
493
494 return record;
495}
496
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200497static void avrcp_device_free(void *data)
498{
499 struct avrcp_device *dev = data;
500
Luiz Augusto von Dentz05cb6b82014-03-06 14:58:02 +0200501 if (dev->queue) {
502 g_queue_foreach(dev->queue, (GFunc) g_free, NULL);
503 g_queue_free(dev->queue);
504 }
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200505
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200506 if (dev->session)
Andrei Emeltchenko4351d462014-02-13 17:20:07 +0200507 avrcp_shutdown(dev->session);
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200508
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +0200509 if (dev->io) {
510 g_io_channel_shutdown(dev->io, FALSE, NULL);
511 g_io_channel_unref(dev->io);
512 }
513
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200514 g_free(dev);
515}
516
Luiz Augusto von Dentz939d25f2014-02-06 14:32:18 +0200517static void avrcp_device_remove(struct avrcp_device *dev)
518{
519 devices = g_slist_remove(devices, dev);
520 avrcp_device_free(dev);
521}
522
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200523static struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
524{
525 struct avrcp_device *dev;
526
527 dev = g_new0(struct avrcp_device, 1);
528 bacpy(&dev->dst, dst);
529 devices = g_slist_prepend(devices, dev);
530
531 return dev;
532}
533
534static int device_cmp(gconstpointer s, gconstpointer user_data)
535{
536 const struct avrcp_device *dev = s;
537 const bdaddr_t *dst = user_data;
538
539 return bacmp(&dev->dst, dst);
540}
541
Andrei Emeltchenko4351d462014-02-13 17:20:07 +0200542static struct avrcp_device *avrcp_device_find(const bdaddr_t *dst)
543{
544 GSList *l;
545
546 l = g_slist_find_custom(devices, dst, device_cmp);
547 if (!l)
548 return NULL;
549
550 return l->data;
551}
552
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200553static void disconnect_cb(void *data)
554{
555 struct avrcp_device *dev = data;
556
557 DBG("");
558
559 dev->session = NULL;
560
Luiz Augusto von Dentz939d25f2014-02-06 14:32:18 +0200561 avrcp_device_remove(dev);
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200562}
563
Luiz Augusto von Dentz611c2ca2014-03-01 16:29:23 +0200564static bool handle_fast_forward(struct avrcp *session, bool pressed,
565 void *user_data)
566{
567 struct hal_ev_avrcp_passthrough_cmd ev;
568
569 DBG("pressed %s", pressed ? "true" : "false");
570
571 ev.id = AVC_FAST_FORWARD;
572 ev.state = pressed;
573
574 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
575 HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev);
576
577 return true;
578}
579
Luiz Augusto von Dentz44019b82014-03-01 16:48:34 +0200580static bool handle_rewind(struct avrcp *session, bool pressed,
581 void *user_data)
582{
583 struct hal_ev_avrcp_passthrough_cmd ev;
584
585 DBG("pressed %s", pressed ? "true" : "false");
586
587 ev.id = AVC_REWIND;
588 ev.state = pressed;
589
590 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
591 HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev);
592
593 return true;
594}
595
Luiz Augusto von Dentz611c2ca2014-03-01 16:29:23 +0200596static const struct avrcp_passthrough_handler passthrough_handlers[] = {
597 { AVC_FAST_FORWARD, handle_fast_forward },
Luiz Augusto von Dentz44019b82014-03-01 16:48:34 +0200598 { AVC_REWIND, handle_rewind },
Luiz Augusto von Dentz611c2ca2014-03-01 16:29:23 +0200599 { },
600};
601
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200602static ssize_t handle_get_capabilities_cmd(struct avrcp *session,
603 uint8_t transaction,
604 uint16_t params_len,
605 uint8_t *params,
606 void *user_data)
607{
608 DBG("");
609
610 if (params_len != 1)
611 return -EINVAL;
612
613 switch (params[0]) {
614 case CAP_COMPANY_ID:
615 params[params_len++] = 1;
616 hton24(&params[params_len], IEEEID_BTSIG);
617 return params_len + 3;
618 case CAP_EVENTS_SUPPORTED:
619 /* Android do not provide this info via HAL so the list most
620 * be hardcoded according to what RegisterNotification can
621 * actually handle */
622 params[params_len++] = 3;
623 params[params_len++] = AVRCP_EVENT_STATUS_CHANGED;
624 params[params_len++] = AVRCP_EVENT_TRACK_CHANGED;
625 params[params_len++] = AVRCP_EVENT_PLAYBACK_POS_CHANGED;
626 return params_len;
627 }
628
629 return -EINVAL;
630}
631
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200632static void push_request(struct avrcp_device *dev, uint8_t pdu_id,
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100633 uint8_t event_id, uint8_t transaction)
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200634{
635 struct avrcp_request *req;
636
637 req = g_new0(struct avrcp_request, 1);
638 req->dev = dev;
639 req->pdu_id = pdu_id;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100640 req->event_id = event_id;
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200641 req->transaction = transaction;
642
643 g_queue_push_tail(dev->queue, req);
644}
645
646static ssize_t handle_get_play_status_cmd(struct avrcp *session,
647 uint8_t transaction,
648 uint16_t params_len,
649 uint8_t *params,
650 void *user_data)
651{
652 struct avrcp_device *dev = user_data;
653
654 DBG("");
655
656 if (params_len != 0)
657 return -EINVAL;
658
659 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
660 HAL_EV_AVRCP_GET_PLAY_STATUS, 0, NULL);
661
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100662 push_request(dev, AVRCP_GET_PLAY_STATUS, 0, transaction);
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200663
664 return -EAGAIN;
665}
666
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200667static ssize_t handle_get_element_attrs_cmd(struct avrcp *session,
668 uint8_t transaction,
669 uint16_t params_len,
670 uint8_t *params,
671 void *user_data)
672{
673 struct avrcp_device *dev = user_data;
674 uint8_t buf[IPC_MTU];
675 struct hal_ev_avrcp_get_element_attrs *ev = (void *) buf;
676 int i;
677
678 DBG("");
679
680 if (params_len < 9)
681 return -EINVAL;
682
683 ev->number = params[8];
684
685 if (params_len < ev->number * sizeof(uint32_t) + 1)
686 return -EINVAL;
687
688 params += 9;
Luiz Augusto von Dentzfac848f2014-03-08 00:43:38 +0200689
690 /* Set everything in case of empty list */
691 if (ev->number == 0) {
692 for (i = 0; i < HAL_AVRCP_MEDIA_ATTR_DURATION; i++) {
693 /* Skip 0x00 as the attributes start with 0x01 */
694 ev->attrs[i] = i + 1;
695 }
696 ev->number = i;
697 goto done;
698 }
699
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200700 for (i = 0; i < ev->number; i++) {
701 ev->attrs[i] = bt_get_be32(params);
702 params += 4;
703 }
704
Luiz Augusto von Dentzfac848f2014-03-08 00:43:38 +0200705done:
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200706 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
707 HAL_EV_AVRCP_GET_ELEMENT_ATTRS,
708 sizeof(*ev) + ev->number, ev);
709
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100710 push_request(dev, AVRCP_GET_ELEMENT_ATTRIBUTES, 0, transaction);
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200711
712 return -EAGAIN;
713
714}
715
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200716static ssize_t handle_register_notification_cmd(struct avrcp *session,
717 uint8_t transaction,
718 uint16_t params_len,
719 uint8_t *params,
720 void *user_data)
721{
722 struct avrcp_device *dev = user_data;
723 struct hal_ev_avrcp_register_notification ev;
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100724 uint8_t event_id;
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200725
726 DBG("");
727
728 if (params_len != 5)
729 return -EINVAL;
730
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100731 event_id = params[0];
732
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200733 /* TODO: Add any missing events supported by Android */
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100734 switch (event_id) {
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200735 case AVRCP_EVENT_STATUS_CHANGED:
736 case AVRCP_EVENT_TRACK_CHANGED:
737 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
738 break;
739 default:
740 return -EINVAL;
741 }
742
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100743 ev.event = event_id;
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200744 ev.param = bt_get_be32(&params[1]);
745
746 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
747 HAL_EV_AVRCP_REGISTER_NOTIFICATION,
748 sizeof(ev), &ev);
749
Andrzej Kaczmarek45aa22f2014-03-04 21:43:22 +0100750 push_request(dev, AVRCP_REGISTER_NOTIFICATION, event_id, transaction);
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200751
752 return -EAGAIN;
753}
754
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200755static const struct avrcp_control_handler control_handlers[] = {
756 { AVRCP_GET_CAPABILITIES,
757 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
758 handle_get_capabilities_cmd },
Luiz Augusto von Dentzdc049cf2014-03-01 19:03:34 +0200759 { AVRCP_GET_PLAY_STATUS,
760 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
761 handle_get_play_status_cmd },
Luiz Augusto von Dentz9a192472014-03-02 16:39:36 +0200762 { AVRCP_GET_ELEMENT_ATTRIBUTES,
763 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
764 handle_get_element_attrs_cmd },
Luiz Augusto von Dentzc656e952014-03-02 17:48:55 +0200765 { AVRCP_REGISTER_NOTIFICATION,
766 AVC_CTYPE_NOTIFY, AVC_CTYPE_INTERIM,
767 handle_register_notification_cmd },
Luiz Augusto von Dentzfb079ff2014-03-01 17:30:34 +0200768 { },
769};
770
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200771static gboolean register_notification_rsp(struct avctp *conn,
772 uint8_t code, uint8_t subunit,
773 uint8_t *operands, size_t operand_count,
774 void *user_data)
775{
776 struct avrcp_device *dev = user_data;
777 struct hal_ev_avrcp_volume_changed ev;
778 uint8_t *params;
779
780 if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)
781 return FALSE;
782
783 if (operands == NULL || operand_count < 7)
784 return FALSE;
785
786 params = &operands[7];
787
788 if (params == NULL || params[0] != AVRCP_EVENT_VOLUME_CHANGED)
789 return FALSE;
790
791 switch (code) {
792 case AVC_CTYPE_INTERIM:
793 ev.type = HAL_AVRCP_EVENT_TYPE_INTERIM;
794 break;
795 case AVC_CTYPE_CHANGED:
796 ev.type = HAL_AVRCP_EVENT_TYPE_CHANGED;
797 break;
798 default:
799 return FALSE;
800 }
801
802 ev.volume = params[1] & 0x7F;
803
804 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
805 HAL_EV_AVRCP_VOLUME_CHANGED,
806 sizeof(ev), &ev);
807
808 if (code == AVC_CTYPE_INTERIM)
809 return TRUE;
810
811 avrcp_register_notification(dev->session, params[0], 0,
812 register_notification_rsp, dev);
813 return FALSE;
814}
815
816static gboolean get_capabilities_rsp(struct avctp *conn,
817 uint8_t code, uint8_t subunit,
818 uint8_t *operands, size_t operand_count,
819 void *user_data)
820{
821 struct avrcp_device *dev = user_data;
822 uint8_t *params;
823 uint8_t count;
824
825 if (operands == NULL || operand_count < 7)
826 return FALSE;
827
828 params = &operands[7];
829
830 if (params == NULL || params[0] != CAP_EVENTS_SUPPORTED)
831 return FALSE;
832
833 for (count = params[1]; count > 0; count--) {
834 uint8_t event = params[1 + count];
835
836 if (event != AVRCP_EVENT_VOLUME_CHANGED)
837 continue;
838
839 avrcp_register_notification(dev->session, event, 0,
840 register_notification_rsp,
841 dev);
842 return FALSE;
843 }
844
845 return FALSE;
846}
847
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200848static int avrcp_device_add_session(struct avrcp_device *dev, int fd,
849 uint16_t imtu, uint16_t omtu)
850{
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +0200851 struct hal_ev_avrcp_remote_features ev;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200852 char address[18];
853
854 dev->session = avrcp_new(fd, imtu, omtu, dev->version);
855 if (!dev->session)
856 return -EINVAL;
857
858 avrcp_set_destroy_cb(dev->session, disconnect_cb, dev);
859 avrcp_set_passthrough_handlers(dev->session, passthrough_handlers,
860 dev);
861 avrcp_set_control_handlers(dev->session, control_handlers, dev);
862
863 dev->queue = g_queue_new();
864
865 ba2str(&dev->dst, address);
866
867 /* FIXME: get the real name of the device */
868 avrcp_init_uinput(dev->session, "bluetooth", address);
869
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +0200870 bdaddr2android(&dev->dst, ev.bdaddr);
871 ev.features = HAL_AVRCP_FEATURE_NONE;
872
873 DBG("version 0x%02x", dev->version);
874
875 if (dev->version < 0x0103)
876 goto done;
877
878 ev.features |= HAL_AVRCP_FEATURE_METADATA;
879
Luiz Augusto von Dentz2ee055e2014-03-07 12:44:41 +0200880 if (dev->version < 0x0104)
881 goto done;
882
883 ev.features |= HAL_AVRCP_FEATURE_ABSOLUTE_VOLUME;
884
885 avrcp_get_capabilities(dev->session, CAP_EVENTS_SUPPORTED,
886 get_capabilities_rsp, dev);
887
Luiz Augusto von Dentzaf213842014-03-05 14:48:00 +0200888done:
889 ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
890 HAL_EV_AVRCP_REMOTE_FEATURES,
891 sizeof(ev), &ev);
892
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200893 return 0;
894}
895
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200896static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
897{
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200898 struct avrcp_device *dev = user_data;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200899 uint16_t imtu, omtu;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200900 char address[18];
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200901 GError *gerr = NULL;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200902 int fd;
903
904 if (err) {
905 error("%s", err->message);
906 return;
907 }
908
909 bt_io_get(chan, &gerr,
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200910 BT_IO_OPT_DEST, address,
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200911 BT_IO_OPT_IMTU, &imtu,
912 BT_IO_OPT_OMTU, &omtu,
913 BT_IO_OPT_INVALID);
914 if (gerr) {
915 error("%s", gerr->message);
916 g_error_free(gerr);
917 g_io_channel_shutdown(chan, TRUE, NULL);
918 return;
919 }
920
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200921 fd = g_io_channel_unix_get_fd(chan);
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200922 if (avrcp_device_add_session(dev, fd, imtu, omtu) < 0) {
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200923 avrcp_device_free(dev);
924 return;
925 }
926
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200927 g_io_channel_set_close_on_unref(chan, FALSE);
928
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +0200929 if (dev->io) {
930 g_io_channel_unref(dev->io);
931 dev->io = NULL;
932 }
933
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +0200934 DBG("%s connected", address);
935}
936
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200937static bool avrcp_device_connect(struct avrcp_device *dev, BtIOConnect cb)
938{
939 GError *err = NULL;
940
941 dev->io = bt_io_connect(cb, dev, NULL, &err,
942 BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
943 BT_IO_OPT_DEST_BDADDR, &dev->dst,
944 BT_IO_OPT_PSM, L2CAP_PSM_AVCTP,
945 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
946 BT_IO_OPT_INVALID);
947 if (err) {
948 error("%s", err->message);
949 g_error_free(err);
950 return false;
951 }
952
953 return true;
954}
955
956static void search_cb(sdp_list_t *recs, int err, gpointer data)
957{
958 struct avrcp_device *dev = data;
959 sdp_list_t *list;
960
961 DBG("");
962
963 if (err < 0) {
964 error("Unable to get AV_REMOTE_SVCLASS_ID SDP record: %s",
965 strerror(-err));
966 goto fail;
967 }
968
969 if (!recs || !recs->data) {
970 error("No AVRCP records found");
971 goto fail;
972 }
973
974 for (list = recs; list; list = list->next) {
975 sdp_record_t *rec = list->data;
Luiz Augusto von Dentzfaeb9f02014-03-06 14:55:57 +0200976 sdp_list_t *l;
977 sdp_profile_desc_t *desc;
978 int features;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200979
Luiz Augusto von Dentzfaeb9f02014-03-06 14:55:57 +0200980 if (sdp_get_profile_descs(rec, &l) < 0)
981 continue;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200982
Luiz Augusto von Dentzfaeb9f02014-03-06 14:55:57 +0200983 desc = l->data;
984 dev->version = desc->version;
985
986 if (sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES,
987 &features) == 0)
988 dev->features = features;
989
990 sdp_list_free(l, free);
991 break;
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +0200992 }
993
994 if (dev->io) {
995 GError *gerr = NULL;
996 if (!bt_io_accept(dev->io, connect_cb, dev, NULL, &gerr)) {
997 error("bt_io_accept: %s", gerr->message);
998 g_error_free(gerr);
999 goto fail;
1000 }
1001 return;
1002 }
1003
1004 if (!avrcp_device_connect(dev, connect_cb)) {
1005 error("Unable to connect to AVRCP");
1006 goto fail;
1007 }
1008
1009 return;
1010
1011fail:
1012 avrcp_device_remove(dev);
1013}
1014
1015static int avrcp_device_search(struct avrcp_device *dev)
1016{
1017 uuid_t uuid;
1018
1019 sdp_uuid16_create(&uuid, AV_REMOTE_SVCLASS_ID);
1020
1021 return bt_search_service(&adapter_addr, &dev->dst, &uuid, search_cb,
1022 dev, NULL, 0);
1023}
1024
1025static void confirm_cb(GIOChannel *chan, gpointer data)
1026{
1027 struct avrcp_device *dev;
1028 char address[18];
1029 bdaddr_t src, dst;
1030 GError *err = NULL;
1031
1032 bt_io_get(chan, &err,
1033 BT_IO_OPT_SOURCE_BDADDR, &src,
1034 BT_IO_OPT_DEST_BDADDR, &dst,
1035 BT_IO_OPT_DEST, address,
1036 BT_IO_OPT_INVALID);
1037 if (err) {
1038 error("%s", err->message);
1039 g_error_free(err);
1040 g_io_channel_shutdown(chan, TRUE, NULL);
1041 return;
1042 }
1043
1044 DBG("incoming connect from %s", address);
1045
1046 dev = avrcp_device_find(&dst);
1047 if (dev && dev->session) {
1048 error("AVRCP: Refusing unexpected connect");
1049 g_io_channel_shutdown(chan, TRUE, NULL);
1050 return;
1051 }
1052
1053 dev = avrcp_device_new(&dst);
1054 if (avrcp_device_search(dev) < 0) {
1055 error("AVRCP: Failed to search SDP details");
1056 avrcp_device_free(dev);
1057 g_io_channel_shutdown(chan, TRUE, NULL);
1058 }
1059
1060 dev->io = g_io_channel_ref(chan);
1061}
1062
Szymon Janc14fc3c52014-03-03 00:50:44 +01001063bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001064{
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +02001065 GError *err = NULL;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001066 sdp_record_t *rec;
1067
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001068 DBG("");
1069
1070 bacpy(&adapter_addr, addr);
1071
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +02001072 server = bt_io_listen(NULL, confirm_cb, NULL, NULL, &err,
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +02001073 BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
1074 BT_IO_OPT_PSM, L2CAP_PSM_AVCTP,
1075 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
1076 BT_IO_OPT_INVALID);
1077 if (!server) {
1078 error("Failed to listen on AVDTP channel: %s", err->message);
1079 g_error_free(err);
1080 return false;
1081 }
1082
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001083 rec = avrcp_record();
1084 if (!rec) {
1085 error("Failed to allocate AVRCP record");
Andrei Emeltchenko1d7219c2014-01-30 15:23:43 +02001086 goto fail;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001087 }
1088
1089 if (bt_adapter_add_record(rec, 0) < 0) {
1090 error("Failed to register AVRCP record");
1091 sdp_record_free(rec);
Andrei Emeltchenko1d7219c2014-01-30 15:23:43 +02001092 goto fail;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001093 }
1094 record_id = rec->handle;
1095
Szymon Jancdd1e44f2014-02-24 13:44:12 +01001096 hal_ipc = ipc;
1097
1098 ipc_register(hal_ipc, HAL_SERVICE_ID_AVRCP, cmd_handlers,
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001099 G_N_ELEMENTS(cmd_handlers));
1100
1101 return true;
Andrei Emeltchenko1d7219c2014-01-30 15:23:43 +02001102fail:
1103 g_io_channel_shutdown(server, TRUE, NULL);
1104 g_io_channel_unref(server);
1105 server = NULL;
1106
1107 return false;
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001108}
1109
1110void bt_avrcp_unregister(void)
1111{
1112 DBG("");
1113
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +02001114 g_slist_free_full(devices, avrcp_device_free);
1115 devices = NULL;
1116
Szymon Jancdd1e44f2014-02-24 13:44:12 +01001117 ipc_unregister(hal_ipc, HAL_SERVICE_ID_AVRCP);
1118 hal_ipc = NULL;
Luiz Augusto von Dentz538237b2014-01-23 15:31:45 +02001119
1120 bt_adapter_remove_record(record_id);
1121 record_id = 0;
Luiz Augusto von Dentzdc675d82014-01-23 17:58:05 +02001122
1123 if (server) {
1124 g_io_channel_shutdown(server, TRUE, NULL);
1125 g_io_channel_unref(server);
1126 server = NULL;
1127 }
Luiz Augusto von Dentzc466e792014-01-23 15:04:12 +02001128}
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001129
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001130void bt_avrcp_connect(const bdaddr_t *dst)
1131{
1132 struct avrcp_device *dev;
1133 char addr[18];
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001134
1135 DBG("");
1136
Andrei Emeltchenko4351d462014-02-13 17:20:07 +02001137 if (avrcp_device_find(dst))
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001138 return;
1139
1140 dev = avrcp_device_new(dst);
Luiz Augusto von Dentz95f8bca2014-03-04 17:34:34 +02001141 if (avrcp_device_search(dev) < 0) {
1142 error("AVRCP: Failed to search SDP details");
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001143 avrcp_device_free(dev);
Luiz Augusto von Dentzd0d30ca2014-02-05 12:26:57 +02001144 }
1145
1146 ba2str(&dev->dst, addr);
1147 DBG("connecting to %s", addr);
1148}
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001149
1150void bt_avrcp_disconnect(const bdaddr_t *dst)
1151{
1152 struct avrcp_device *dev;
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001153
1154 DBG("");
1155
Andrei Emeltchenko4351d462014-02-13 17:20:07 +02001156 dev = avrcp_device_find(dst);
1157 if (!dev)
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001158 return;
1159
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001160 if (dev->session) {
Andrei Emeltchenko4351d462014-02-13 17:20:07 +02001161 avrcp_shutdown(dev->session);
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001162 return;
1163 }
1164
Luiz Augusto von Dentz939d25f2014-02-06 14:32:18 +02001165 avrcp_device_remove(dev);
Luiz Augusto von Dentz65cfccf2014-02-05 12:26:58 +02001166}