Skip to content

Commit 86176f0

Browse files
gzh-terrym-alperen-sener
authored andcommitted
[nrf fromtree] Bluetooth: AVRCP: implementation for passthrough commands
This patch alllows to send passthough command from CT to TG. Signed-off-by: Zihao Gao <[email protected]> (cherry picked from commit 53bba45)
1 parent dc42a80 commit 86176f0

File tree

5 files changed

+281
-55
lines changed

5 files changed

+281
-55
lines changed

include/zephyr/bluetooth/classic/avrcp.h

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,99 @@
1616
extern "C" {
1717
#endif
1818

19+
/** @brief AV/C command types */
20+
typedef enum __packed {
21+
BT_AVRCP_CTYPE_CONTROL = 0x0,
22+
BT_AVRCP_CTYPE_STATUS = 0x1,
23+
BT_AVRCP_CTYPE_SPECIFIC_INQUIRY = 0x2,
24+
BT_AVRCP_CTYPE_NOTIFY = 0x3,
25+
BT_AVRCP_CTYPE_GENERAL_INQUIRY = 0x4,
26+
} bt_avrcp_ctype_t;
27+
28+
/** @brief AV/C response codes */
29+
typedef enum __packed {
30+
BT_AVRCP_RSP_NOT_IMPLEMENTED = 0x8,
31+
BT_AVRCP_RSP_ACCEPTED = 0x9,
32+
BT_AVRCP_RSP_REJECTED = 0xa,
33+
BT_AVRCP_RSP_IN_TRANSITION = 0xb,
34+
BT_AVRCP_RSP_IMPLEMENTED = 0xc, /**< For SPECIFIC_INQUIRY and GENERAL_INQUIRY commands */
35+
BT_AVRCP_RSP_STABLE = 0xc, /**< For STATUS commands */
36+
BT_AVRCP_RSP_CHANGED = 0xd,
37+
BT_AVRCP_RSP_INTERIM = 0xf,
38+
} bt_avrcp_rsp_t;
39+
40+
/** @brief AV/C operation ids used in AVRCP passthrough commands */
41+
typedef enum __packed {
42+
BT_AVRCP_OPID_SELECT = 0x00,
43+
BT_AVRCP_OPID_UP = 0x01,
44+
BT_AVRCP_OPID_DOWN = 0x02,
45+
BT_AVRCP_OPID_LEFT = 0x03,
46+
BT_AVRCP_OPID_RIGHT = 0x04,
47+
BT_AVRCP_OPID_RIGHT_UP = 0x05,
48+
BT_AVRCP_OPID_RIGHT_DOWN = 0x06,
49+
BT_AVRCP_OPID_LEFT_UP = 0x07,
50+
BT_AVRCP_OPID_LEFT_DOWN = 0x08,
51+
BT_AVRCP_OPID_ROOT_MENU = 0x09,
52+
BT_AVRCP_OPID_SETUP_MENU = 0x0a,
53+
BT_AVRCP_OPID_CONTENTS_MENU = 0x0b,
54+
BT_AVRCP_OPID_FAVORITE_MENU = 0x0c,
55+
BT_AVRCP_OPID_EXIT = 0x0d,
56+
57+
BT_AVRCP_OPID_0 = 0x20,
58+
BT_AVRCP_OPID_1 = 0x21,
59+
BT_AVRCP_OPID_2 = 0x22,
60+
BT_AVRCP_OPID_3 = 0x23,
61+
BT_AVRCP_OPID_4 = 0x24,
62+
BT_AVRCP_OPID_5 = 0x25,
63+
BT_AVRCP_OPID_6 = 0x26,
64+
BT_AVRCP_OPID_7 = 0x27,
65+
BT_AVRCP_OPID_8 = 0x28,
66+
BT_AVRCP_OPID_9 = 0x29,
67+
BT_AVRCP_OPID_DOT = 0x2a,
68+
BT_AVRCP_OPID_ENTER = 0x2b,
69+
BT_AVRCP_OPID_CLEAR = 0x2c,
70+
71+
BT_AVRCP_OPID_CHANNEL_UP = 0x30,
72+
BT_AVRCP_OPID_CHANNEL_DOWN = 0x31,
73+
BT_AVRCP_OPID_PREVIOUS_CHANNEL = 0x32,
74+
BT_AVRCP_OPID_SOUND_SELECT = 0x33,
75+
BT_AVRCP_OPID_INPUT_SELECT = 0x34,
76+
BT_AVRCP_OPID_DISPLAY_INFORMATION = 0x35,
77+
BT_AVRCP_OPID_HELP = 0x36,
78+
BT_AVRCP_OPID_PAGE_UP = 0x37,
79+
BT_AVRCP_OPID_PAGE_DOWN = 0x38,
80+
81+
BT_AVRCP_OPID_POWER = 0x40,
82+
BT_AVRCP_OPID_VOLUME_UP = 0x41,
83+
BT_AVRCP_OPID_VOLUME_DOWN = 0x42,
84+
BT_AVRCP_OPID_MUTE = 0x43,
85+
BT_AVRCP_OPID_PLAY = 0x44,
86+
BT_AVRCP_OPID_STOP = 0x45,
87+
BT_AVRCP_OPID_PAUSE = 0x46,
88+
BT_AVRCP_OPID_RECORD = 0x47,
89+
BT_AVRCP_OPID_REWIND = 0x48,
90+
BT_AVRCP_OPID_FAST_FORWARD = 0x49,
91+
BT_AVRCP_OPID_EJECT = 0x4a,
92+
BT_AVRCP_OPID_FORWARD = 0x4b,
93+
BT_AVRCP_OPID_BACKWARD = 0x4c,
94+
95+
BT_AVRCP_OPID_ANGLE = 0x50,
96+
BT_AVRCP_OPID_SUBPICTURE = 0x51,
97+
98+
BT_AVRCP_OPID_F1 = 0x71,
99+
BT_AVRCP_OPID_F2 = 0x72,
100+
BT_AVRCP_OPID_F3 = 0x73,
101+
BT_AVRCP_OPID_F4 = 0x74,
102+
BT_AVRCP_OPID_F5 = 0x75,
103+
BT_AVRCP_OPID_VENDOR_UNIQUE = 0x7e,
104+
} bt_avrcp_opid_t;
105+
106+
/** @brief AVRCP button state flag */
107+
typedef enum __packed {
108+
BT_AVRCP_BUTTON_PRESSED = 0,
109+
BT_AVRCP_BUTTON_RELEASED = 1,
110+
} bt_avrcp_button_state_t;
111+
19112
/** @brief AVRCP structure */
20113
struct bt_avrcp;
21114

@@ -28,7 +121,15 @@ struct bt_avrcp_subunit_info_rsp {
28121
uint8_t subunit_type;
29122
uint8_t max_subunit_id;
30123
const uint8_t *extended_subunit_type; /**< contains max_subunit_id items */
31-
const uint8_t *extended_subunit_id; /**< contains max_subunit_id items */
124+
const uint8_t *extended_subunit_id; /**< contains max_subunit_id items */
125+
};
126+
127+
struct bt_avrcp_passthrough_rsp {
128+
uint8_t response; /**< bt_avrcp_rsp_t */
129+
uint8_t operation_id; /**< bt_avrcp_opid_t */
130+
uint8_t state; /**< bt_avrcp_button_state_t */
131+
uint8_t len;
132+
const uint8_t *payload;
32133
};
33134

34135
struct bt_avrcp_cb {
@@ -40,6 +141,7 @@ struct bt_avrcp_cb {
40141
* @param avrcp AVRCP connection object.
41142
*/
42143
void (*connected)(struct bt_avrcp *avrcp);
144+
43145
/** @brief An AVRCP connection has been disconnected.
44146
*
45147
* This callback notifies the application that an avrcp connection
@@ -48,6 +150,7 @@ struct bt_avrcp_cb {
48150
* @param avrcp AVRCP connection object.
49151
*/
50152
void (*disconnected)(struct bt_avrcp *avrcp);
153+
51154
/** @brief Callback function for bt_avrcp_get_unit_info().
52155
*
53156
* Called when the get unit info process is completed.
@@ -56,6 +159,7 @@ struct bt_avrcp_cb {
56159
* @param rsp The response for UNIT INFO command.
57160
*/
58161
void (*unit_info_rsp)(struct bt_avrcp *avrcp, struct bt_avrcp_unit_info_rsp *rsp);
162+
59163
/** @brief Callback function for bt_avrcp_get_subunit_info().
60164
*
61165
* Called when the get subunit info process is completed.
@@ -64,6 +168,15 @@ struct bt_avrcp_cb {
64168
* @param rsp The response for SUBUNIT INFO command.
65169
*/
66170
void (*subunit_info_rsp)(struct bt_avrcp *avrcp, struct bt_avrcp_subunit_info_rsp *rsp);
171+
172+
/** @brief Callback function for bt_avrcp_passthrough().
173+
*
174+
* Called when a passthrough response is received.
175+
*
176+
* @param avrcp AVRCP connection object.
177+
* @param rsp The response for PASS THROUGH command.
178+
*/
179+
void (*passthrough_rsp)(struct bt_avrcp *avrcp, struct bt_avrcp_passthrough_rsp *rsp);
67180
};
68181

69182
/** @brief Connect AVRCP.
@@ -120,6 +233,22 @@ int bt_avrcp_get_unit_info(struct bt_avrcp *avrcp);
120233
*/
121234
int bt_avrcp_get_subunit_info(struct bt_avrcp *avrcp);
122235

236+
/** @brief Send AVRCP Pass Through command.
237+
*
238+
* This function send a pass through command to the remote device. Passsthhrough command is used
239+
* to transfer user operation information from a CT to Panel subunit of TG.
240+
*
241+
* @param avrcp The AVRCP instance.
242+
* @param operation_id The user operation id.
243+
* @param state The button state.
244+
* @param payload The payload of the pass through command. Should not be NULL if len is not zero.
245+
* @param len The length of the payload.
246+
*
247+
* @return 0 in case of success or error code in case of error.
248+
*/
249+
int bt_avrcp_passthrough(struct bt_avrcp *avrcp, bt_avrcp_opid_t operation_id,
250+
bt_avrcp_button_state_t state, const uint8_t *payload, uint8_t len);
251+
123252
#ifdef __cplusplus
124253
}
125254
#endif

subsys/bluetooth/host/classic/avctp.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ static int avctp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
8282
uint8_t tid;
8383
bt_avctp_pkt_type_t pkt_type;
8484
bt_avctp_cr_t cr;
85+
int err;
8586

8687
if (buf->len < sizeof(*hdr)) {
8788
LOG_ERR("invalid AVCTP header received");
@@ -117,7 +118,13 @@ static int avctp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
117118
if (!rsp) {
118119
return -ENOMEM;
119120
}
120-
return bt_avctp_send(session, rsp);
121+
122+
err = bt_avctp_send(session, rsp);
123+
if (err < 0) {
124+
net_buf_unref(rsp);
125+
LOG_ERR("AVCTP send fail, err = %d", err);
126+
return err;
127+
}
121128
}
122129
return 0; /* No need to report to the upper layer */
123130
}
@@ -189,16 +196,7 @@ struct net_buf *bt_avctp_create_pdu(struct bt_avctp *session, bt_avctp_cr_t cr,
189196

190197
int bt_avctp_send(struct bt_avctp *session, struct net_buf *buf)
191198
{
192-
int err;
193-
194-
err = bt_l2cap_chan_send(&session->br_chan.chan, buf);
195-
if (err < 0) {
196-
net_buf_unref(buf);
197-
LOG_ERR("L2CAP send fail err = %d", err);
198-
return err;
199-
}
200-
201-
return err;
199+
return bt_l2cap_chan_send(&session->br_chan.chan, buf);
202200
}
203201

204202
int bt_avctp_register(const struct bt_avctp_event_cb *cb)

0 commit comments

Comments
 (0)