From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mslow3.mail.gandi.net (mslow3.mail.gandi.net [217.70.178.249]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34E0F3F3285 for ; Tue, 4 Aug 2026 09:34:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.178.249 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785836092; cv=none; b=I5y5mKJ6H92wiWg08ftmEiP4V7TV/ht7f1wB/eyBS9AIiCY2b3FqLEJtKI3cMQ2//G5uuf3+ogyN3OA5vQ5IlYsJl/qXEQBO7chkh+klx3dQyOPeCCKPidnFpgA9ovW/VbRCrgnrnn+TBAuMDUXSVc265pYrXkHNGLPnWTIF4Jc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785836092; c=relaxed/simple; bh=Oc4iHhYO80sVO8NocuXwfWEnCSb3c15bA700zG2uKts=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=S75QueMlg3/AFJmTNeHgkDDpTVQBkx/zCLME3x6L2h2kla3TDjHGpPnrzypwz2uveGxxa/j9S/jmdmTCB7DEWHrg+LjbnkR3cuE/LY21GTgOABAsQ/8Sme3hq1hlSymGplfElPxwDtAKi+opWA3V/7gCpRDumROMxLoxfnBuUPo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hadess.net; spf=pass smtp.mailfrom=hadess.net; arc=none smtp.client-ip=217.70.178.249 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hadess.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=hadess.net Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::221]) by mslow3.mail.gandi.net (Postfix) with ESMTP id 623A7581D0A for ; Tue, 4 Aug 2026 09:23:42 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id E07F73EB9F for ; Tue, 4 Aug 2026 09:23:34 +0000 (UTC) From: Bastien Nocera To: linux-bluetooth@vger.kernel.org Subject: [BlueZ v1] unit: Remove Android avrcp.c dead-code Date: Tue, 4 Aug 2026 11:23:19 +0200 Message-ID: <20260804092326.2080562-1-hadess@hadess.net> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-GND-Sasl: hadess@hadess.net X-GND-State: clean X-GND-Score: 0 X-GND-Cause: dmFkZTGubcCOcMTRKj+6Z0eYTzWcy9mgzHdpOCmszoAPWrqv06Ck3y4ZDVhFGi3sz/9SpFitFU3snZAbXDqzOvLUgf4dhyJIvaWpSbosw160Ns816jTPgKpNTwNkHii6zjTIFwAv5twhh1PhPBix4feAWIEDli6OCwH0AaSXG6pMLB5+GG0cxsG4C4fTNVWW5Y93WTJdUZuZNUGt79WolRbPmComJyD5AHNgHn/P60zGG7p0HGGQZOqZottFCQQUSFe3AOyXYlBOl85w87hxUuyWIOo/PU7RILu3XqyASlwYrL1rNjdAPZme9pQ00zDzLkJg27H9rPpftp+msVSUa1bTMceVCEkKKUXjEhDagbFiXg0mRSR3FDYjpyqyPjTZMXnW7stdhEScmbvpMl+1j/LNjWELa8ltIi9a3hAE7XA+sN9nWa1gvqZFuJTjk3Hj+xIHDlx1WEmijWn0IuvSdySoZCeo2ze9/pldQNyKppVetUAr7WD92PlNro6sUMKsg9uFODlrqROIoHKcqiDOzx4N6lfs9YjztR3LlClQuppbhFiRO9YqouLFmbP9KQhwouLNZqX7hJwX9a+5UJeAa8WEQzcdX5Ab0YHIcHKkeiv27chJh0zoyJw/3jsbnCRFIsCDf016v/U1tQSK1z/ttGYf424luQBJQ0l6tU+DUUQL/7HkqA This code isn't referenced anywhere, and seems to have been part of the Android support in BlueZ, remove it now that Android support has been removed. --- unit/avrcp.c | 1161 -------------------------------------------------- unit/avrcp.h | 15 - 2 files changed, 1176 deletions(-) delete mode 100644 unit/avrcp.c delete mode 100644 unit/avrcp.h diff --git a/unit/avrcp.c b/unit/avrcp.c deleted file mode 100644 index 6eced0cc95d8..000000000000 --- a/unit/avrcp.c +++ /dev/null @@ -1,1161 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1-or-later -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2013-2014 Intel Corporation. All rights reserved. - * - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "btio/btio.h" -#include "bluetooth/bluetooth.h" -#include "bluetooth/sdp.h" -#include "bluetooth/sdp_lib.h" -#include "src/sdp-client.h" -#include "src/shared/util.h" -#include "src/log.h" - -#include "avctp.h" -#include "avrcp-lib.h" -#include "hal-msg.h" -#include "ipc-common.h" -#include "ipc.h" -#include "bluetooth.h" -#include "avrcp.h" -#include "utils.h" - -#define L2CAP_PSM_AVCTP 0x17 - -static bdaddr_t adapter_addr; -static uint32_t record_tg_id = 0; -static uint32_t record_ct_id = 0; -static GSList *devices = NULL; -static GIOChannel *server = NULL; -static struct ipc *hal_ipc = NULL; - -struct avrcp_request { - struct avrcp_device *dev; - uint8_t pdu_id; - uint8_t event_id; - uint8_t transaction; -}; - -struct avrcp_device { - bdaddr_t dst; - uint16_t version; - uint16_t features; - struct avrcp *session; - GIOChannel *io; - GQueue *queue; -}; - -static struct avrcp_request *pop_request(uint8_t pdu_id, uint8_t event_id, - bool peek) -{ - GSList *l; - - for (l = devices; l; l = g_slist_next(l)) { - struct avrcp_device *dev = l->data; - GList *reqs = g_queue_peek_head_link(dev->queue); - int i; - - for (i = 0; reqs; reqs = g_list_next(reqs), i++) { - struct avrcp_request *req = reqs->data; - - if (req->pdu_id != pdu_id || req->event_id != event_id) - continue; - - if (!peek) - g_queue_pop_nth(dev->queue, i); - - return req; - } - } - - return NULL; -} - -static void handle_get_play_status(const void *buf, uint16_t len) -{ - const struct hal_cmd_avrcp_get_play_status *cmd = buf; - uint8_t status; - struct avrcp_request *req; - int ret; - - DBG(""); - - req = pop_request(AVRCP_GET_PLAY_STATUS, 0, false); - if (!req) { - status = HAL_STATUS_FAILED; - goto done; - } - - ret = avrcp_get_play_status_rsp(req->dev->session, req->transaction, - cmd->position, cmd->duration, - cmd->status); - if (ret < 0) { - status = HAL_STATUS_FAILED; - g_free(req); - goto done; - } - - status = HAL_STATUS_SUCCESS; - g_free(req); - -done: - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_GET_PLAY_STATUS, status); -} - -static void handle_list_player_attrs(const void *buf, uint16_t len) -{ - DBG(""); - - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_LIST_PLAYER_ATTRS, HAL_STATUS_FAILED); -} - -static void handle_list_player_values(const void *buf, uint16_t len) -{ - DBG(""); - - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_LIST_PLAYER_VALUES, HAL_STATUS_FAILED); -} - -static void handle_get_player_attrs(const void *buf, uint16_t len) -{ - DBG(""); - - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_GET_PLAYER_ATTRS, HAL_STATUS_FAILED); -} - -static void handle_get_player_attrs_text(const void *buf, uint16_t len) -{ - DBG(""); - - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT, HAL_STATUS_FAILED); -} - -static void handle_get_player_values_text(const void *buf, uint16_t len) -{ - DBG(""); - - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT, HAL_STATUS_FAILED); -} - -static size_t write_element_text(uint8_t id, uint8_t text_len, uint8_t *text, - uint8_t *pdu) -{ - uint16_t charset = 106; - size_t len = 0; - - put_be32(id, pdu); - pdu += 4; - len += 4; - - put_be16(charset, pdu); - pdu += 2; - len += 2; - - put_be16(text_len, pdu); - pdu += 2; - len += 2; - - memcpy(pdu, text, text_len); - len += text_len; - - return len; -} - -static void write_element_attrs(uint8_t *ptr, uint8_t number, uint8_t *pdu, - size_t *len) -{ - int i; - - *pdu = number; - pdu++; - *len += 1; - - for (i = 0; i < number; i++) { - struct hal_avrcp_player_setting_text *text = (void *) ptr; - size_t ret; - - ret = write_element_text(text->id, text->len, text->text, pdu); - - ptr += sizeof(*text) + text->len; - pdu += ret; - *len += ret; - } -} - -static void handle_get_element_attrs_text(const void *buf, uint16_t len) -{ - struct hal_cmd_avrcp_get_element_attrs_text *cmd = (void *) buf; - uint8_t status; - struct avrcp_request *req; - uint8_t pdu[IPC_MTU]; - uint8_t *ptr; - size_t pdu_len; - int ret; - - DBG(""); - - req = pop_request(AVRCP_GET_ELEMENT_ATTRIBUTES, 0, false); - if (!req) { - status = HAL_STATUS_FAILED; - goto done; - } - - ptr = (uint8_t *) &cmd->values[0]; - pdu_len = 0; - write_element_attrs(ptr, cmd->number, pdu, &pdu_len); - - ret = avrcp_get_element_attrs_rsp(req->dev->session, req->transaction, - pdu, pdu_len); - if (ret < 0) { - status = HAL_STATUS_FAILED; - g_free(req); - goto done; - } - - status = HAL_STATUS_SUCCESS; - g_free(req); - -done: - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT, status); -} - -static void handle_set_player_attrs_value(const void *buf, uint16_t len) -{ - DBG(""); - - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE, HAL_STATUS_FAILED); -} - -static void handle_register_notification(const void *buf, uint16_t len) -{ - struct hal_cmd_avrcp_register_notification *cmd = (void *) buf; - uint8_t status; - struct avrcp_request *req; - uint8_t code; - bool peek = false; - int ret; - - DBG(""); - - switch (cmd->type) { - case HAL_AVRCP_EVENT_TYPE_INTERIM: - code = AVC_CTYPE_INTERIM; - peek = true; - break; - case HAL_AVRCP_EVENT_TYPE_CHANGED: - code = AVC_CTYPE_CHANGED; - break; - default: - status = HAL_STATUS_FAILED; - goto done; - } - - req = pop_request(AVRCP_REGISTER_NOTIFICATION, cmd->event, peek); - if (!req) { - status = HAL_STATUS_FAILED; - goto done; - } - - ret = avrcp_register_notification_rsp(req->dev->session, - req->transaction, code, - cmd->event, cmd->data, - cmd->len); - if (ret < 0) { - status = HAL_STATUS_FAILED; - if (!peek) - g_free(req); - goto done; - } - - status = HAL_STATUS_SUCCESS; - if (!peek) - g_free(req); - -done: - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_REGISTER_NOTIFICATION, status); -} - -static void handle_set_volume(const void *buf, uint16_t len) -{ - struct hal_cmd_avrcp_set_volume *cmd = (void *) buf; - struct avrcp_device *dev; - uint8_t status; - int ret; - - DBG(""); - - if (!devices) { - error("AVRCP: No device found to set volume"); - status = HAL_STATUS_FAILED; - goto done; - } - - /* - * Peek the first device since the HAL cannot really address a specific - * device it might mean there could only be one connected. - */ - dev = devices->data; - - ret = avrcp_set_volume(dev->session, cmd->value & 0x7f); - if (ret < 0) { - status = HAL_STATUS_FAILED; - goto done; - } - - status = HAL_STATUS_SUCCESS; - -done: - ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME, - status); -} - -static const struct ipc_handler cmd_handlers[] = { - /* HAL_OP_AVRCP_GET_PLAY_STATUS */ - { handle_get_play_status, false, - sizeof(struct hal_cmd_avrcp_get_play_status) }, - /* HAL_OP_AVRCP_LIST_PLAYER_ATTRS */ - { handle_list_player_attrs, true, - sizeof(struct hal_cmd_avrcp_list_player_attrs) }, - /* HAL_OP_AVRCP_LIST_PLAYER_VALUES */ - { handle_list_player_values, true, - sizeof(struct hal_cmd_avrcp_list_player_values) }, - /* HAL_OP_AVRCP_GET_PLAYER_ATTRS */ - { handle_get_player_attrs, true, - sizeof(struct hal_cmd_avrcp_get_player_attrs) }, - /* HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT */ - { handle_get_player_attrs_text, true, - sizeof(struct hal_cmd_avrcp_get_player_attrs_text) }, - /* HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT */ - { handle_get_player_values_text, true, - sizeof(struct hal_cmd_avrcp_get_player_values_text) }, - /* HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT */ - { handle_get_element_attrs_text, true, - sizeof(struct hal_cmd_avrcp_get_element_attrs_text) }, - /* HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE */ - { handle_set_player_attrs_value, true, - sizeof(struct hal_cmd_avrcp_set_player_attrs_value) }, - /* HAL_OP_AVRCP_REGISTER_NOTIFICATION */ - { handle_register_notification, true, - sizeof(struct hal_cmd_avrcp_register_notification) }, - /* HAL_OP_AVRCP_SET_VOLUME */ - { handle_set_volume, false, sizeof(struct hal_cmd_avrcp_set_volume) }, -}; - -static sdp_record_t *avrcp_tg_record(void) -{ - sdp_list_t *svclass_id, *pfseq, *apseq, *root; - uuid_t root_uuid, l2cap, avctp, avrtg; - sdp_profile_desc_t profile[1]; - sdp_list_t *aproto_control, *proto_control[2]; - sdp_record_t *record; - sdp_data_t *psm, *version, *features; - uint16_t lp = L2CAP_PSM_AVCTP; - uint16_t avrcp_ver = 0x0105, avctp_ver = 0x0104; - uint16_t feat = (AVRCP_FEATURE_CATEGORY_1 | - AVRCP_FEATURE_CATEGORY_2 | - AVRCP_FEATURE_CATEGORY_3 | - AVRCP_FEATURE_CATEGORY_4); - - record = sdp_record_alloc(); - if (!record) - return NULL; - - sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); - root = sdp_list_append(NULL, &root_uuid); - sdp_set_browse_groups(record, root); - - /* Service Class ID List */ - sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID); - svclass_id = sdp_list_append(NULL, &avrtg); - sdp_set_service_classes(record, svclass_id); - - /* Protocol Descriptor List */ - sdp_uuid16_create(&l2cap, L2CAP_UUID); - proto_control[0] = sdp_list_append(NULL, &l2cap); - psm = sdp_data_alloc(SDP_UINT16, &lp); - proto_control[0] = sdp_list_append(proto_control[0], psm); - apseq = sdp_list_append(NULL, proto_control[0]); - - sdp_uuid16_create(&avctp, AVCTP_UUID); - proto_control[1] = sdp_list_append(NULL, &avctp); - version = sdp_data_alloc(SDP_UINT16, &avctp_ver); - proto_control[1] = sdp_list_append(proto_control[1], version); - apseq = sdp_list_append(apseq, proto_control[1]); - - aproto_control = sdp_list_append(NULL, apseq); - sdp_set_access_protos(record, aproto_control); - - /* Bluetooth Profile Descriptor List */ - sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID); - profile[0].version = avrcp_ver; - pfseq = sdp_list_append(NULL, &profile[0]); - sdp_set_profile_descs(record, pfseq); - - features = sdp_data_alloc(SDP_UINT16, &feat); - sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features); - - sdp_set_info_attr(record, "AVRCP TG", NULL, NULL); - - sdp_data_free(psm); - sdp_data_free(version); - sdp_list_free(proto_control[0], NULL); - sdp_list_free(proto_control[1], NULL); - sdp_list_free(apseq, NULL); - sdp_list_free(aproto_control, NULL); - sdp_list_free(pfseq, NULL); - sdp_list_free(root, NULL); - sdp_list_free(svclass_id, NULL); - - return record; -} - -static sdp_record_t *avrcp_ct_record(void) -{ - sdp_list_t *svclass_id, *pfseq, *apseq, *root; - uuid_t root_uuid, l2cap, avctp, avrct, avrctr; - sdp_profile_desc_t profile[1]; - sdp_list_t *aproto, *proto[2]; - sdp_record_t *record; - sdp_data_t *psm, *version, *features; - uint16_t lp = AVCTP_CONTROL_PSM; - uint16_t avrcp_ver = 0x0105, avctp_ver = 0x0104; - uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 | - AVRCP_FEATURE_CATEGORY_2 | - AVRCP_FEATURE_CATEGORY_3 | - AVRCP_FEATURE_CATEGORY_4); - - record = sdp_record_alloc(); - if (!record) - return NULL; - - sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); - root = sdp_list_append(NULL, &root_uuid); - sdp_set_browse_groups(record, root); - - /* Service Class ID List */ - sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID); - svclass_id = sdp_list_append(NULL, &avrct); - sdp_uuid16_create(&avrctr, AV_REMOTE_CONTROLLER_SVCLASS_ID); - svclass_id = sdp_list_append(svclass_id, &avrctr); - sdp_set_service_classes(record, svclass_id); - - /* Protocol Descriptor List */ - sdp_uuid16_create(&l2cap, L2CAP_UUID); - proto[0] = sdp_list_append(NULL, &l2cap); - psm = sdp_data_alloc(SDP_UINT16, &lp); - proto[0] = sdp_list_append(proto[0], psm); - apseq = sdp_list_append(NULL, proto[0]); - - sdp_uuid16_create(&avctp, AVCTP_UUID); - proto[1] = sdp_list_append(NULL, &avctp); - version = sdp_data_alloc(SDP_UINT16, &avctp_ver); - proto[1] = sdp_list_append(proto[1], version); - apseq = sdp_list_append(apseq, proto[1]); - - aproto = sdp_list_append(NULL, apseq); - sdp_set_access_protos(record, aproto); - - /* Bluetooth Profile Descriptor List */ - sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID); - profile[0].version = avrcp_ver; - pfseq = sdp_list_append(NULL, &profile[0]); - sdp_set_profile_descs(record, pfseq); - - features = sdp_data_alloc(SDP_UINT16, &feat); - sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features); - - sdp_set_info_attr(record, "AVRCP CT", NULL, NULL); - - free(psm); - free(version); - sdp_list_free(proto[0], NULL); - sdp_list_free(proto[1], NULL); - sdp_list_free(apseq, NULL); - sdp_list_free(pfseq, NULL); - sdp_list_free(aproto, NULL); - sdp_list_free(root, NULL); - sdp_list_free(svclass_id, NULL); - - return record; -} - -static void queue_free(void *data, void *user_data) -{ - g_free(data); -} - -static void avrcp_device_free(void *data) -{ - struct avrcp_device *dev = data; - - if (dev->queue) { - g_queue_foreach(dev->queue, queue_free, NULL); - g_queue_free(dev->queue); - } - - if (dev->session) - avrcp_shutdown(dev->session); - - if (dev->io) { - g_io_channel_shutdown(dev->io, FALSE, NULL); - g_io_channel_unref(dev->io); - } - - g_free(dev); -} - -static void avrcp_device_remove(struct avrcp_device *dev) -{ - devices = g_slist_remove(devices, dev); - avrcp_device_free(dev); -} - -static struct avrcp_device *avrcp_device_new(const bdaddr_t *dst) -{ - struct avrcp_device *dev; - - dev = g_new0(struct avrcp_device, 1); - bacpy(&dev->dst, dst); - devices = g_slist_prepend(devices, dev); - - return dev; -} - -static int device_cmp(gconstpointer s, gconstpointer user_data) -{ - const struct avrcp_device *dev = s; - const bdaddr_t *dst = user_data; - - return bacmp(&dev->dst, dst); -} - -static struct avrcp_device *avrcp_device_find(const bdaddr_t *dst) -{ - GSList *l; - - l = g_slist_find_custom(devices, dst, device_cmp); - if (!l) - return NULL; - - return l->data; -} - -static void disconnect_cb(void *data) -{ - struct avrcp_device *dev = data; - - DBG(""); - - dev->session = NULL; - - avrcp_device_remove(dev); -} - -static bool handle_fast_forward(struct avrcp *session, bool pressed, - void *user_data) -{ - struct hal_ev_avrcp_passthrough_cmd ev; - - DBG("pressed %s", pressed ? "true" : "false"); - - ev.id = AVC_FAST_FORWARD; - ev.state = pressed; - - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev); - - return true; -} - -static bool handle_rewind(struct avrcp *session, bool pressed, - void *user_data) -{ - struct hal_ev_avrcp_passthrough_cmd ev; - - DBG("pressed %s", pressed ? "true" : "false"); - - ev.id = AVC_REWIND; - ev.state = pressed; - - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev); - - return true; -} - -static const struct avrcp_passthrough_handler passthrough_handlers[] = { - { AVC_FAST_FORWARD, handle_fast_forward }, - { AVC_REWIND, handle_rewind }, - { }, -}; - -static int handle_get_capabilities_cmd(struct avrcp *session, - uint8_t transaction, void *user_data) -{ - uint8_t events[] = { AVRCP_EVENT_STATUS_CHANGED, - AVRCP_EVENT_TRACK_CHANGED, - AVRCP_EVENT_PLAYBACK_POS_CHANGED }; - - DBG(""); - - /* - * Android do not provide this info via HAL so the list most - * be hardcoded according to what RegisterNotification can - * actually handle - */ - avrcp_get_capabilities_rsp(session, transaction, sizeof(events), - events); - - return 0; -} - -static void push_request(struct avrcp_device *dev, uint8_t pdu_id, - uint8_t event_id, uint8_t transaction) -{ - struct avrcp_request *req; - - req = g_new0(struct avrcp_request, 1); - req->dev = dev; - req->pdu_id = pdu_id; - req->event_id = event_id; - req->transaction = transaction; - - g_queue_push_tail(dev->queue, req); -} - -static int handle_get_play_status_cmd(struct avrcp *session, - uint8_t transaction, void *user_data) -{ - struct avrcp_device *dev = user_data; - - DBG(""); - - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_GET_PLAY_STATUS, 0, NULL); - - push_request(dev, AVRCP_GET_PLAY_STATUS, 0, transaction); - - return 0; -} - -static int handle_get_element_attrs_cmd(struct avrcp *session, - uint8_t transaction, uint64_t uid, - uint8_t number, uint32_t *attrs, - void *user_data) -{ - struct avrcp_device *dev = user_data; - uint8_t buf[IPC_MTU]; - struct hal_ev_avrcp_get_element_attrs *ev = (void *) buf; - int i; - - DBG(""); - - ev->number = number; - /* Set everything in case of empty list */ - if (ev->number == 0) { - for (i = 0; i < HAL_AVRCP_MEDIA_ATTR_DURATION; i++) { - /* Skip 0x00 as the attributes start with 0x01 */ - ev->attrs[i] = i + 1; - } - ev->number = i; - goto done; - } - - for (i = 0; i < number; i++) - ev->attrs[i] = attrs[i]; - -done: - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_GET_ELEMENT_ATTRS, - sizeof(*ev) + ev->number, ev); - - push_request(dev, AVRCP_GET_ELEMENT_ATTRIBUTES, 0, transaction); - - return 0; - -} - -static int handle_register_notification_cmd(struct avrcp *session, - uint8_t transaction, - uint8_t event, - uint32_t interval, - void *user_data) -{ - struct avrcp_device *dev = user_data; - struct hal_ev_avrcp_register_notification ev; - - DBG(""); - - /* TODO: Add any missing events supported by Android */ - switch (event) { - case AVRCP_EVENT_STATUS_CHANGED: - case AVRCP_EVENT_TRACK_CHANGED: - case AVRCP_EVENT_PLAYBACK_POS_CHANGED: - break; - default: - return -EINVAL; - } - - ev.event = event; - ev.param = interval; - - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_REGISTER_NOTIFICATION, - sizeof(ev), &ev); - - push_request(dev, AVRCP_REGISTER_NOTIFICATION, event, transaction); - - return 0; -} - -static const struct avrcp_control_ind control_ind = { - .get_capabilities = handle_get_capabilities_cmd, - .get_play_status = handle_get_play_status_cmd, - .get_element_attributes = handle_get_element_attrs_cmd, - .register_notification = handle_register_notification_cmd, -}; - -static bool handle_register_notification_rsp(struct avrcp *session, int err, - uint8_t code, uint8_t event, - void *params, - void *user_data) -{ - struct avrcp_device *dev = user_data; - struct hal_ev_avrcp_volume_changed ev; - uint8_t *volume = params; - - if (err < 0) { - error("AVRCP: %s", strerror(-err)); - return false; - } - - if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED) - return false; - - if (event != AVRCP_EVENT_VOLUME_CHANGED) - return false; - - ev.type = code; - ev.volume = volume[0]; - - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_VOLUME_CHANGED, - sizeof(ev), &ev); - - if (code == AVC_CTYPE_INTERIM) - return true; - - avrcp_register_notification(dev->session, event, 0); - return false; -} - -static void handle_get_capabilities_rsp(struct avrcp *session, int err, - uint8_t number, uint8_t *events, - void *user_data) -{ - struct avrcp_device *dev = user_data; - int i; - - if (err < 0) { - error("AVRCP: %s", strerror(-err)); - return; - } - - for (i = 0; i < number; i++) { - if (events[i] != AVRCP_EVENT_VOLUME_CHANGED) - continue; - - avrcp_register_notification(dev->session, events[i], 0); - break; - } - - return; -} - -static void handle_set_volume_rsp(struct avrcp *session, int err, - uint8_t value, void *user_data) -{ - struct hal_ev_avrcp_volume_changed ev; - - if (err < 0) { - ev.volume = 0; - ev.type = AVC_CTYPE_REJECTED; - goto done; - } - - ev.volume = value; - ev.type = AVC_CTYPE_ACCEPTED; - -done: - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_VOLUME_CHANGED, - sizeof(ev), &ev); -} - -static const struct avrcp_control_cfm control_cfm = { - .get_capabilities = handle_get_capabilities_rsp, - .register_notification = handle_register_notification_rsp, - .set_volume = handle_set_volume_rsp, -}; - -static int avrcp_device_add_session(struct avrcp_device *dev, int fd, - uint16_t imtu, uint16_t omtu) -{ - struct hal_ev_avrcp_remote_features ev; - char address[18]; - - dev->session = avrcp_new(fd, imtu, omtu, dev->version); - if (!dev->session) - return -EINVAL; - - avrcp_set_destroy_cb(dev->session, disconnect_cb, dev); - avrcp_set_passthrough_handlers(dev->session, passthrough_handlers, - dev); - avrcp_register_player(dev->session, &control_ind, &control_cfm, dev); - - dev->queue = g_queue_new(); - - ba2str(&dev->dst, address); - - /* FIXME: get the real name of the device */ - avrcp_init_uinput(dev->session, "bluetooth", address); - - bdaddr2android(&dev->dst, ev.bdaddr); - ev.features = HAL_AVRCP_FEATURE_NONE; - - DBG("version 0x%02x", dev->version); - - if (dev->version < 0x0103) - goto done; - - ev.features |= HAL_AVRCP_FEATURE_METADATA; - - if (dev->version < 0x0104) - goto done; - - ev.features |= HAL_AVRCP_FEATURE_ABSOLUTE_VOLUME; - - avrcp_get_capabilities(dev->session, CAP_EVENTS_SUPPORTED); - -done: - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_EV_AVRCP_REMOTE_FEATURES, - sizeof(ev), &ev); - - return 0; -} - -static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data) -{ - struct avrcp_device *dev = user_data; - uint16_t imtu, omtu; - char address[18]; - GError *gerr = NULL; - int fd; - - if (err) { - error("%s", err->message); - return; - } - - bt_io_get(chan, &gerr, - BT_IO_OPT_DEST, address, - BT_IO_OPT_IMTU, &imtu, - BT_IO_OPT_OMTU, &omtu, - BT_IO_OPT_INVALID); - if (gerr) { - error("%s", gerr->message); - g_error_free(gerr); - g_io_channel_shutdown(chan, TRUE, NULL); - return; - } - - fd = g_io_channel_unix_get_fd(chan); - if (avrcp_device_add_session(dev, fd, imtu, omtu) < 0) { - avrcp_device_free(dev); - return; - } - - g_io_channel_set_close_on_unref(chan, FALSE); - - if (dev->io) { - g_io_channel_unref(dev->io); - dev->io = NULL; - } - - DBG("%s connected", address); -} - -static bool avrcp_device_connect(struct avrcp_device *dev, BtIOConnect cb) -{ - GError *err = NULL; - - dev->io = bt_io_connect(cb, dev, NULL, &err, - BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, - BT_IO_OPT_DEST_BDADDR, &dev->dst, - BT_IO_OPT_PSM, L2CAP_PSM_AVCTP, - BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, - BT_IO_OPT_INVALID); - if (err) { - error("%s", err->message); - g_error_free(err); - return false; - } - - return true; -} - -static void search_cb(sdp_list_t *recs, int err, gpointer data) -{ - struct avrcp_device *dev = data; - sdp_list_t *list; - - DBG(""); - - if (!g_slist_find(devices, dev)) - return; - - if (err < 0) { - error("Unable to get AV_REMOTE_SVCLASS_ID SDP record: %s", - strerror(-err)); - goto fail; - } - - if (!recs || !recs->data) { - error("No AVRCP records found"); - goto fail; - } - - for (list = recs; list; list = list->next) { - sdp_record_t *rec = list->data; - sdp_list_t *l; - sdp_profile_desc_t *desc; - int features; - - if (sdp_get_profile_descs(rec, &l) < 0) - continue; - - desc = l->data; - dev->version = desc->version; - - if (sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES, - &features) == 0) - dev->features = features; - - sdp_list_free(l, free); - break; - } - - if (dev->io) { - GError *gerr = NULL; - if (!bt_io_accept(dev->io, connect_cb, dev, NULL, &gerr)) { - error("bt_io_accept: %s", gerr->message); - g_error_free(gerr); - goto fail; - } - return; - } - - if (!avrcp_device_connect(dev, connect_cb)) { - error("Unable to connect to AVRCP"); - goto fail; - } - - return; - -fail: - avrcp_device_remove(dev); -} - -static int avrcp_device_search(struct avrcp_device *dev) -{ - uuid_t uuid; - - sdp_uuid16_create(&uuid, AV_REMOTE_SVCLASS_ID); - - return bt_search_service(&adapter_addr, &dev->dst, &uuid, search_cb, - dev, NULL, 0); -} - -static void confirm_cb(GIOChannel *chan, gpointer data) -{ - struct avrcp_device *dev; - char address[18]; - bdaddr_t dst; - GError *err = NULL; - - bt_io_get(chan, &err, - BT_IO_OPT_DEST_BDADDR, &dst, - BT_IO_OPT_DEST, address, - BT_IO_OPT_INVALID); - if (err) { - error("%s", err->message); - g_error_free(err); - g_io_channel_shutdown(chan, TRUE, NULL); - return; - } - - DBG("incoming connect from %s", address); - - dev = avrcp_device_find(&dst); - if (dev && dev->session) { - error("AVRCP: Refusing unexpected connect"); - g_io_channel_shutdown(chan, TRUE, NULL); - return; - } - - dev = avrcp_device_new(&dst); - if (avrcp_device_search(dev) < 0) { - error("AVRCP: Failed to search SDP details"); - avrcp_device_free(dev); - g_io_channel_shutdown(chan, TRUE, NULL); - } - - dev->io = g_io_channel_ref(chan); -} - -bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode) -{ - GError *err = NULL; - sdp_record_t *rec; - - DBG(""); - - bacpy(&adapter_addr, addr); - - server = bt_io_listen(NULL, confirm_cb, NULL, NULL, &err, - BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, - BT_IO_OPT_PSM, L2CAP_PSM_AVCTP, - BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, - BT_IO_OPT_INVALID); - if (!server) { - error("Failed to listen on AVDTP channel: %s", err->message); - g_error_free(err); - return false; - } - - rec = avrcp_tg_record(); - if (!rec) { - error("Failed to allocate AVRCP TG record"); - goto fail; - } - - if (bt_adapter_add_record(rec, 0) < 0) { - error("Failed to register AVRCP TG record"); - sdp_record_free(rec); - goto fail; - } - record_tg_id = rec->handle; - - rec = avrcp_ct_record(); - if (!rec) { - error("Failed to allocate AVRCP CT record"); - bt_adapter_remove_record(record_tg_id); - goto fail; - } - - if (bt_adapter_add_record(rec, 0) < 0) { - error("Failed to register AVRCP CT record"); - bt_adapter_remove_record(record_tg_id); - sdp_record_free(rec); - goto fail; - } - record_ct_id = rec->handle; - - hal_ipc = ipc; - - ipc_register(hal_ipc, HAL_SERVICE_ID_AVRCP, cmd_handlers, - G_N_ELEMENTS(cmd_handlers)); - - return true; -fail: - g_io_channel_shutdown(server, TRUE, NULL); - g_io_channel_unref(server); - server = NULL; - - return false; -} - -void bt_avrcp_unregister(void) -{ - DBG(""); - - g_slist_free_full(devices, avrcp_device_free); - devices = NULL; - - ipc_unregister(hal_ipc, HAL_SERVICE_ID_AVRCP); - hal_ipc = NULL; - - bt_adapter_remove_record(record_tg_id); - record_tg_id = 0; - - bt_adapter_remove_record(record_ct_id); - record_ct_id = 0; - - if (server) { - g_io_channel_shutdown(server, TRUE, NULL); - g_io_channel_unref(server); - server = NULL; - } -} - -void bt_avrcp_connect(const bdaddr_t *dst) -{ - struct avrcp_device *dev; - char addr[18]; - - DBG(""); - - if (avrcp_device_find(dst)) - return; - - dev = avrcp_device_new(dst); - if (avrcp_device_search(dev) < 0) { - error("AVRCP: Failed to search SDP details"); - avrcp_device_free(dev); - } - - ba2str(&dev->dst, addr); - DBG("connecting to %s", addr); -} - -void bt_avrcp_disconnect(const bdaddr_t *dst) -{ - struct avrcp_device *dev; - - DBG(""); - - dev = avrcp_device_find(dst); - if (!dev) - return; - - if (dev->session) { - avrcp_shutdown(dev->session); - return; - } - - avrcp_device_remove(dev); -} diff --git a/unit/avrcp.h b/unit/avrcp.h deleted file mode 100644 index 474413b7cfb7..000000000000 --- a/unit/avrcp.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2013-2014 Intel Corporation. All rights reserved. - * - * - */ - -bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode); -void bt_avrcp_unregister(void); - -void bt_avrcp_connect(const bdaddr_t *dst); -void bt_avrcp_disconnect(const bdaddr_t *dst); -- 2.55.0