avrc_bld_ct.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2006-2013 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. #include <string.h>
  19. #include "common/bt_target.h"
  20. #include "stack/avrc_api.h"
  21. #include "stack/avrc_defs.h"
  22. #include "avrc_int.h"
  23. #include "osi/allocator.h"
  24. #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
  25. /*****************************************************************************
  26. ** Global data
  27. *****************************************************************************/
  28. #if (AVRC_METADATA_INCLUDED == TRUE)
  29. /*******************************************************************************
  30. **
  31. ** Function avrc_bld_next_cmd
  32. **
  33. ** Description This function builds the Request Continue or Abort command.
  34. **
  35. ** Returns AVRC_STS_NO_ERROR, if the command is built successfully
  36. ** Otherwise, the error code.
  37. **
  38. *******************************************************************************/
  39. static tAVRC_STS avrc_bld_next_cmd (tAVRC_NEXT_CMD *p_cmd, BT_HDR *p_pkt)
  40. {
  41. UINT8 *p_data, *p_start;
  42. AVRC_TRACE_API("avrc_bld_next_cmd");
  43. /* get the existing length, if any, and also the num attributes */
  44. p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
  45. p_data = p_start + 2; /* pdu + rsvd */
  46. /* add fixed lenth 1 - pdu_id (1) */
  47. UINT16_TO_BE_STREAM(p_data, 1);
  48. UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu);
  49. p_pkt->len = (p_data - p_start);
  50. return AVRC_STS_NO_ERROR;
  51. }
  52. /*****************************************************************************
  53. ** the following commands are introduced in AVRCP 1.4
  54. *****************************************************************************/
  55. #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
  56. /*******************************************************************************
  57. **
  58. ** Function avrc_bld_set_abs_volume_cmd
  59. **
  60. ** Description This function builds the Set Absolute Volume command.
  61. **
  62. ** Returns AVRC_STS_NO_ERROR, if the command is built successfully
  63. ** Otherwise, the error code.
  64. **
  65. *******************************************************************************/
  66. static tAVRC_STS avrc_bld_set_abs_volume_cmd (tAVRC_SET_VOLUME_CMD *p_cmd, BT_HDR *p_pkt)
  67. {
  68. UINT8 *p_data, *p_start;
  69. AVRC_TRACE_API("avrc_bld_set_abs_volume_cmd");
  70. /* get the existing length, if any, and also the num attributes */
  71. p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
  72. p_data = p_start + 2; /* pdu + rsvd */
  73. /* add fixed lenth 1 - volume (1) */
  74. UINT16_TO_BE_STREAM(p_data, 1);
  75. UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume));
  76. p_pkt->len = (p_data - p_start);
  77. return AVRC_STS_NO_ERROR;
  78. }
  79. /*******************************************************************************
  80. **
  81. ** Function avrc_bld_vol_change_notfn
  82. **
  83. ** Description This function builds the register notification for volume change.
  84. **
  85. ** Returns AVRC_STS_NO_ERROR, if the command is built successfully
  86. ** Otherwise, the error code.
  87. **
  88. *******************************************************************************/
  89. static tAVRC_STS avrc_bld_register_change_notfn(UINT8 event_id, UINT32 event_parameter, BT_HDR *p_pkt)
  90. {
  91. UINT8 *p_data, *p_start;
  92. AVRC_TRACE_API("avrc_bld_vol_change");
  93. /* get the existing length, if any, and also the num attributes */
  94. // Set the notify value
  95. p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
  96. p_data = p_start + 2; /* pdu + rsvd */
  97. /* add fixed length 5 -*/
  98. UINT16_TO_BE_STREAM(p_data, 5);
  99. UINT8_TO_BE_STREAM(p_data, event_id);
  100. UINT32_TO_BE_STREAM(p_data, event_parameter);
  101. p_pkt->len = (p_data - p_start);
  102. return AVRC_STS_NO_ERROR;
  103. }
  104. #endif
  105. /*******************************************************************************
  106. **
  107. ** Function avrc_bld_init_cmd_buffer
  108. **
  109. ** Description This function initializes the command buffer based on PDU
  110. **
  111. ** Returns NULL, if no GKI buffer or failure to build the message.
  112. ** Otherwise, the GKI buffer that contains the initialized message.
  113. **
  114. *******************************************************************************/
  115. static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd)
  116. {
  117. UINT8 opcode = avrc_opcode_from_pdu(p_cmd->pdu);
  118. AVRC_TRACE_API("avrc_bld_init_cmd_buffer: pdu=%x, opcode=%x", p_cmd->pdu, opcode);
  119. UINT16 offset = 0;
  120. switch (opcode) {
  121. case AVRC_OP_PASS_THRU:
  122. offset = AVRC_MSG_PASS_THRU_OFFSET;
  123. break;
  124. case AVRC_OP_VENDOR:
  125. offset = AVRC_MSG_VENDOR_OFFSET;
  126. break;
  127. }
  128. /* allocate and initialize the buffer */
  129. BT_HDR *p_pkt = (BT_HDR *)osi_malloc(AVRC_META_CMD_BUF_SIZE);
  130. if (p_pkt) {
  131. UINT8 *p_data, *p_start;
  132. p_pkt->layer_specific = AVCT_DATA_CTRL;
  133. p_pkt->event = opcode;
  134. p_pkt->offset = offset;
  135. p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
  136. p_start = p_data;
  137. /* pass thru - group navigation - has a two byte op_id, so dont do it here */
  138. if (opcode != AVRC_OP_PASS_THRU) {
  139. *p_data++ = p_cmd->pdu;
  140. }
  141. switch (opcode) {
  142. case AVRC_OP_VENDOR:
  143. /* reserved 0, packet_type 0 */
  144. UINT8_TO_BE_STREAM(p_data, 0);
  145. /* continue to the next "case to add length */
  146. /* add fixed lenth - 0 */
  147. UINT16_TO_BE_STREAM(p_data, 0);
  148. break;
  149. }
  150. p_pkt->len = (p_data - p_start);
  151. }
  152. p_cmd->cmd.opcode = opcode;
  153. return p_pkt;
  154. }
  155. /*******************************************************************************
  156. **
  157. ** Function avrc_bld_set_player_value_cmd
  158. **
  159. ** Description This function builds the Set Player Application Value command.
  160. **
  161. ** Returns AVRC_STS_NO_ERROR, if the command is built successfully
  162. ** Otherwise, the error code.
  163. **
  164. *******************************************************************************/
  165. static tAVRC_STS avrc_bld_set_player_value_cmd(tAVRC_SET_APP_VALUE_CMD *p_cmd, BT_HDR *p_pkt)
  166. {
  167. UINT8 *p_data, *p_start;
  168. /* get the existing length, if any, and also the num attributes */
  169. p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
  170. p_data = p_start + 2; /* pdu + rsvd */
  171. /* add length */
  172. UINT16_TO_BE_STREAM(p_data, 3);
  173. /* Number of attributes */
  174. UINT8_TO_BE_STREAM(p_data, 1);
  175. UINT8_TO_BE_STREAM(p_data, p_cmd->p_vals->attr_id);
  176. UINT8_TO_BE_STREAM(p_data, p_cmd->p_vals->attr_val);
  177. p_pkt->len = (p_data - p_start);
  178. return AVRC_STS_NO_ERROR;
  179. }
  180. /*******************************************************************************
  181. **
  182. ** Function avrc_bld_get_element_attr_cmd
  183. **
  184. ** Description This function builds the Get Element Attribute command.
  185. **
  186. ** Returns AVRC_STS_NO_ERROR, if the command is built successfully
  187. ** Otherwise, the error code.
  188. **
  189. *******************************************************************************/
  190. static tAVRC_STS avrc_bld_get_element_attr_cmd (tAVRC_GET_ELEM_ATTRS_CMD *p_cmd, BT_HDR *p_pkt)
  191. {
  192. int i;
  193. UINT8 *p_data, *p_start;
  194. AVRC_TRACE_API("avrc_bld_get_element_attr_cmd num_attr: %d", p_cmd->num_attr);
  195. /* get the existing length, if any, and also the num attributes */
  196. p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
  197. p_data = p_start + 2; /* pdu + rsvd */
  198. /* add length */
  199. UINT16_TO_BE_STREAM(p_data, 8 + 1 /* id + attr count */ + p_cmd->num_attr * sizeof(UINT32));
  200. /* Identifier 0x0 (PLAYING) */
  201. UINT64_TO_BE_STREAM(p_data, (UINT64)(0));
  202. /* Attribute count */
  203. UINT8_TO_BE_STREAM(p_data, p_cmd->num_attr);
  204. for (i = 0; i < p_cmd->num_attr; i++) {
  205. AVRC_TRACE_API("avrc_bld_get_element_attr_cmd attr_id: %d", p_cmd->attrs[i]);
  206. UINT32_TO_BE_STREAM(p_data, p_cmd->attrs[i]);
  207. }
  208. p_pkt->len = (p_data - p_start);
  209. return AVRC_STS_NO_ERROR;
  210. }
  211. static tAVRC_STS avrc_bld_get_caps_cmd(tAVRC_GET_CAPS_CMD *p_cmd, BT_HDR *p_pkt)
  212. {
  213. UINT8 *p_data, *p_start;
  214. AVRC_TRACE_API("avrc_bld_get_caps");
  215. /* get the existing length, if any, and also the num attributes */
  216. // Set the notify value
  217. p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
  218. p_data = p_start + 2; /* pdu + rsvd */
  219. /* add fixed length 1 */
  220. UINT16_TO_BE_STREAM(p_data, 1);
  221. /* capability id */
  222. UINT8_TO_BE_STREAM(p_data, p_cmd->capability_id);
  223. p_pkt->len = (p_data - p_start);
  224. return AVRC_STS_NO_ERROR;
  225. }
  226. /*******************************************************************************
  227. **
  228. ** Function AVRC_BldCommand
  229. **
  230. ** Description This function builds the given AVRCP command to the given
  231. ** GKI buffer
  232. **
  233. ** Returns AVRC_STS_NO_ERROR, if the command is built successfully
  234. ** Otherwise, the error code.
  235. **
  236. *******************************************************************************/
  237. tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt)
  238. {
  239. tAVRC_STS status = AVRC_STS_BAD_PARAM;
  240. BT_HDR *p_pkt;
  241. BOOLEAN alloc = FALSE;
  242. AVRC_TRACE_API("AVRC_BldCommand: pdu=%x status=%x", p_cmd->cmd.pdu, p_cmd->cmd.status);
  243. if (!p_cmd || !pp_pkt) {
  244. AVRC_TRACE_API("AVRC_BldCommand. Invalid parameters passed. p_cmd=%p, pp_pkt=%p",
  245. p_cmd, pp_pkt);
  246. return AVRC_STS_BAD_PARAM;
  247. }
  248. if (*pp_pkt == NULL) {
  249. if ((*pp_pkt = avrc_bld_init_cmd_buffer(p_cmd)) == NULL) {
  250. AVRC_TRACE_API("AVRC_BldCommand: Failed to initialize command buffer");
  251. return AVRC_STS_INTERNAL_ERR;
  252. }
  253. alloc = TRUE;
  254. }
  255. status = AVRC_STS_NO_ERROR;
  256. p_pkt = *pp_pkt;
  257. switch (p_cmd->pdu) {
  258. case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
  259. status = avrc_bld_next_cmd(&p_cmd->continu, p_pkt);
  260. break;
  261. case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
  262. status = avrc_bld_next_cmd(&p_cmd->abort, p_pkt);
  263. break;
  264. #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
  265. case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
  266. status = avrc_bld_set_abs_volume_cmd(&p_cmd->volume, p_pkt);
  267. break;
  268. #endif
  269. case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
  270. status = avrc_bld_set_player_value_cmd(&p_cmd->set_app_val, p_pkt);
  271. break;
  272. case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
  273. status = avrc_bld_get_element_attr_cmd(&p_cmd->get_elem_attrs, p_pkt);
  274. break;
  275. case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
  276. status = avrc_bld_register_change_notfn(p_cmd->reg_notif.event_id, p_cmd->reg_notif.param, p_pkt);
  277. break;
  278. case AVRC_PDU_GET_CAPABILITIES:
  279. status = avrc_bld_get_caps_cmd(&p_cmd->get_caps, p_pkt);
  280. break;
  281. }
  282. if (alloc && (status != AVRC_STS_NO_ERROR) ) {
  283. osi_free(p_pkt);
  284. *pp_pkt = NULL;
  285. }
  286. AVRC_TRACE_API("AVRC_BldCommand: returning %d", status);
  287. return status;
  288. }
  289. #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
  290. #endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */