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