1 /******************************************************************************
2 *
3 * Copyright 2003-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * Interface to AVRCP optional commands
22 *
23 ******************************************************************************/
24 #include <bluetooth/log.h>
25 #include <string.h>
26
27 #include "avrc_api.h"
28 #include "avrc_int.h"
29 #include "internal_include/bt_target.h"
30 #include "osi/include/allocator.h"
31 #include "stack/include/bt_hdr.h"
32
33 using namespace bluetooth;
34
35 /******************************************************************************
36 *
37 * Function avrc_vendor_msg
38 *
39 * Description Compose a VENDOR DEPENDENT command according to p_msg
40 *
41 * Input Parameters:
42 * p_msg: Pointer to VENDOR DEPENDENT message structure.
43 *
44 * Output Parameters:
45 * None.
46 *
47 * Returns pointer to a valid GKI buffer if successful.
48 * NULL if p_msg is NULL.
49 *
50 *****************************************************************************/
avrc_vendor_msg(tAVRC_MSG_VENDOR * p_msg)51 static BT_HDR* avrc_vendor_msg(tAVRC_MSG_VENDOR* p_msg) {
52 BT_HDR* p_cmd;
53 uint8_t* p_data;
54
55 /*
56 An AVRC cmd consists of at least of:
57 - A BT_HDR, plus
58 - AVCT_MSG_OFFSET, plus
59 - 3 bytes for ctype, subunit_type and op_vendor, plus
60 - 3 bytes for company_id
61 */
62 #define AVRC_MIN_VENDOR_CMD_LEN (sizeof(BT_HDR) + AVCT_MSG_OFFSET + 3 + 3)
63
64 if (p_msg == nullptr ||
65 AVRC_META_CMD_BUF_SIZE < AVRC_MIN_VENDOR_CMD_LEN + p_msg->vendor_len) {
66 return nullptr;
67 }
68
69 p_cmd = (BT_HDR*)osi_calloc(AVRC_META_CMD_BUF_SIZE);
70
71 p_cmd->offset = AVCT_MSG_OFFSET;
72 p_data = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
73 *p_data++ = (p_msg->hdr.ctype & AVRC_CTYPE_MASK);
74 *p_data++ =
75 (p_msg->hdr.subunit_type << AVRC_SUBTYPE_SHIFT) | p_msg->hdr.subunit_id;
76 *p_data++ = AVRC_OP_VENDOR;
77 AVRC_CO_ID_TO_BE_STREAM(p_data, p_msg->company_id);
78 if (p_msg->vendor_len && p_msg->p_vendor_data)
79 memcpy(p_data, p_msg->p_vendor_data, p_msg->vendor_len);
80 p_cmd->len = (uint16_t)(p_data + p_msg->vendor_len - (uint8_t*)(p_cmd + 1) -
81 p_cmd->offset);
82 p_cmd->layer_specific = AVCT_DATA_CTRL;
83
84 return p_cmd;
85 }
86
87 /******************************************************************************
88 *
89 * Function AVRC_UnitCmd
90 *
91 * Description Send a UNIT INFO command to the peer device. This
92 * function can only be called for controller role connections.
93 * Any response message from the peer is passed back through
94 * the tAVRC_MSG_CBACK callback function.
95 *
96 * Input Parameters:
97 * handle: Handle of this connection.
98 *
99 * label: Transaction label.
100 *
101 * Output Parameters:
102 * None.
103 *
104 * Returns AVRC_SUCCESS if successful.
105 * AVRC_BAD_HANDLE if handle is invalid.
106 *
107 *****************************************************************************/
AVRC_UnitCmd(uint8_t handle,uint8_t label)108 uint16_t AVRC_UnitCmd(uint8_t handle, uint8_t label) {
109 BT_HDR* p_cmd = (BT_HDR*)osi_calloc(AVRC_CMD_BUF_SIZE);
110 uint8_t* p_data;
111
112 p_cmd->offset = AVCT_MSG_OFFSET;
113 p_data = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
114 *p_data++ = AVRC_CMD_STATUS;
115 /* unit & id ignore */
116 *p_data++ = (AVRC_SUB_UNIT << AVRC_SUBTYPE_SHIFT) | AVRC_SUBID_IGNORE;
117 *p_data++ = AVRC_OP_UNIT_INFO;
118 memset(p_data, AVRC_CMD_OPRND_PAD, AVRC_UNIT_OPRND_BYTES);
119 p_cmd->len =
120 p_data + AVRC_UNIT_OPRND_BYTES - (uint8_t*)(p_cmd + 1) - p_cmd->offset;
121 p_cmd->layer_specific = AVCT_DATA_CTRL;
122
123 return AVCT_MsgReq(handle, label, AVCT_CMD, p_cmd);
124 }
125
126 /******************************************************************************
127 *
128 * Function AVRC_SubCmd
129 *
130 * Description Send a SUBUNIT INFO command to the peer device. This
131 * function can only be called for controller role connections.
132 * Any response message from the peer is passed back through
133 * the tAVRC_MSG_CBACK callback function.
134 *
135 * Input Parameters:
136 * handle: Handle of this connection.
137 *
138 * label: Transaction label.
139 *
140 * page: Specifies which part of the subunit type table
141 * is requested. For AVRCP it is typically zero.
142 * Value range is 0-7.
143 *
144 * Output Parameters:
145 * None.
146 *
147 * Returns AVRC_SUCCESS if successful.
148 * AVRC_BAD_HANDLE if handle is invalid.
149 *
150 *****************************************************************************/
AVRC_SubCmd(uint8_t handle,uint8_t label,uint8_t page)151 uint16_t AVRC_SubCmd(uint8_t handle, uint8_t label, uint8_t page) {
152 BT_HDR* p_cmd = (BT_HDR*)osi_calloc(AVRC_CMD_BUF_SIZE);
153 uint8_t* p_data;
154
155 p_cmd->offset = AVCT_MSG_OFFSET;
156 p_data = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
157 *p_data++ = AVRC_CMD_STATUS;
158 /* unit & id ignore */
159 *p_data++ = (AVRC_SUB_UNIT << AVRC_SUBTYPE_SHIFT) | AVRC_SUBID_IGNORE;
160 *p_data++ = AVRC_OP_SUB_INFO;
161 *p_data++ =
162 ((page & AVRC_SUB_PAGE_MASK) << AVRC_SUB_PAGE_SHIFT) | AVRC_SUB_EXT_CODE;
163 memset(p_data, AVRC_CMD_OPRND_PAD, AVRC_SUB_OPRND_BYTES);
164 p_cmd->len =
165 p_data + AVRC_SUB_OPRND_BYTES - (uint8_t*)(p_cmd + 1) - p_cmd->offset;
166 p_cmd->layer_specific = AVCT_DATA_CTRL;
167
168 return AVCT_MsgReq(handle, label, AVCT_CMD, p_cmd);
169 }
170
171 /******************************************************************************
172 *
173 * Function AVRC_VendorCmd
174 *
175 * Description Send a VENDOR DEPENDENT command to the peer device. This
176 * function can only be called for controller role connections.
177 * Any response message from the peer is passed back through
178 * the tAVRC_MSG_CBACK callback function.
179 *
180 * Input Parameters:
181 * handle: Handle of this connection.
182 *
183 * label: Transaction label.
184 *
185 * p_msg: Pointer to VENDOR DEPENDENT message structure.
186 *
187 * Output Parameters:
188 * None.
189 *
190 * Returns AVRC_SUCCESS if successful.
191 * AVRC_BAD_HANDLE if handle is invalid.
192 *
193 *****************************************************************************/
AVRC_VendorCmd(uint8_t handle,uint8_t label,tAVRC_MSG_VENDOR * p_msg)194 uint16_t AVRC_VendorCmd(uint8_t handle, uint8_t label,
195 tAVRC_MSG_VENDOR* p_msg) {
196 BT_HDR* p_buf = avrc_vendor_msg(p_msg);
197 if (p_buf)
198 return AVCT_MsgReq(handle, label, AVCT_CMD, p_buf);
199 else
200 return AVCT_NO_RESOURCES;
201 }
202
203 /******************************************************************************
204 *
205 * Function AVRC_VendorRsp
206 *
207 * Description Send a VENDOR DEPENDENT response to the peer device. This
208 * function can only be called for target role connections.
209 * This function must be called when a VENDOR DEPENDENT
210 * command message is received from the peer through the
211 * tAVRC_MSG_CBACK callback function.
212 *
213 * Input Parameters:
214 * handle: Handle of this connection.
215 *
216 * label: Transaction label. Must be the same value as
217 * passed with the command message in the callback
218 * function.
219 *
220 * p_msg: Pointer to VENDOR DEPENDENT message structure.
221 *
222 * Output Parameters:
223 * None.
224 *
225 * Returns AVRC_SUCCESS if successful.
226 * AVRC_BAD_HANDLE if handle is invalid.
227 *
228 *****************************************************************************/
AVRC_VendorRsp(uint8_t handle,uint8_t label,tAVRC_MSG_VENDOR * p_msg)229 uint16_t AVRC_VendorRsp(uint8_t handle, uint8_t label,
230 tAVRC_MSG_VENDOR* p_msg) {
231 BT_HDR* p_buf = avrc_vendor_msg(p_msg);
232 if (p_buf)
233 return AVCT_MsgReq(handle, label, AVCT_RSP, p_buf);
234 else
235 return AVCT_NO_RESOURCES;
236 }
237