avrcp_target.c 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  1. /*
  2. * Copyright (C) 2016 BlueKitchen GmbH
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. * 4. Any redistribution, use, or modification is done solely for
  17. * personal benefit and not for any commercial purpose or for
  18. * monetary gain.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
  24. * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * Please inquire about commercial licensing options at
  34. * contact@bluekitchen-gmbh.com
  35. *
  36. */
  37. #define BTSTACK_FILE__ "avrcp_target.c"
  38. #include <stdint.h>
  39. #include <string.h>
  40. #include <inttypes.h>
  41. #include "btstack.h"
  42. #include "classic/avrcp.h"
  43. #define AVRCP_ATTR_HEADER_LEN 8
  44. static const uint8_t AVRCP_NOTIFICATION_TRACK_SELECTED[] = {0,0,0,0,0,0,0,0};
  45. static const uint8_t AVRCP_NOTIFICATION_TRACK_NOT_SELECTED[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
  46. avrcp_context_t avrcp_target_context;
  47. static int avrcp_target_supports_browsing(uint16_t target_supported_features){
  48. return target_supported_features & AVRCP_FEATURE_MASK_BROWSING;
  49. }
  50. void avrcp_target_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){
  51. avrcp_create_sdp_record(0, service, service_record_handle, avrcp_target_supports_browsing(supported_features), supported_features, service_name, service_provider_name);
  52. }
  53. static void avrcp_target_emit_operation(btstack_packet_handler_t callback, uint16_t avrcp_cid, avrcp_operation_id_t operation_id, uint8_t operands_length, uint8_t operand){
  54. btstack_assert(callback != NULL);
  55. uint8_t event[8];
  56. int pos = 0;
  57. event[pos++] = HCI_EVENT_AVRCP_META;
  58. event[pos++] = sizeof(event) - 2;
  59. event[pos++] = AVRCP_SUBEVENT_OPERATION;
  60. little_endian_store_16(event, pos, avrcp_cid);
  61. pos += 2;
  62. event[pos++] = operation_id;
  63. event[pos++] = operands_length;
  64. event[pos++] = operand;
  65. (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
  66. }
  67. static void avrcp_target_emit_volume_changed(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t absolute_volume){
  68. btstack_assert(callback != NULL);
  69. uint8_t event[7];
  70. int offset = 0;
  71. event[offset++] = HCI_EVENT_AVRCP_META;
  72. event[offset++] = sizeof(event) - 2;
  73. event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED;
  74. little_endian_store_16(event, offset, avrcp_cid);
  75. offset += 2;
  76. event[offset++] = AVRCP_CTYPE_NOTIFY;
  77. event[offset++] = absolute_volume;
  78. (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
  79. }
  80. static void avrcp_target_emit_respond_vendor_dependent_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t subevent_id){
  81. btstack_assert(callback != NULL);
  82. uint8_t event[5];
  83. int pos = 0;
  84. event[pos++] = HCI_EVENT_AVRCP_META;
  85. event[pos++] = sizeof(event) - 2;
  86. event[pos++] = subevent_id;
  87. little_endian_store_16(event, pos, avrcp_cid);
  88. (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
  89. }
  90. // returns number of bytes stored
  91. static uint16_t avrcp_target_pack_single_element_header(uint8_t * packet, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint16_t attr_value_size){
  92. btstack_assert(attr_id >= 1);
  93. btstack_assert(attr_id <= AVRCP_MEDIA_ATTR_COUNT);
  94. big_endian_store_32(packet, pos, attr_id);
  95. big_endian_store_16(packet, pos+4, RFC2978_CHARSET_MIB_UTF8);
  96. big_endian_store_16(packet, pos+6, attr_value_size);
  97. return 8;
  98. }
  99. // returns number of bytes stored
  100. static uint16_t avrcp_target_pack_single_element_attribute_number(uint8_t * packet, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint32_t value){
  101. uint16_t attr_value_length = sprintf((char *)(packet+pos+8), "%0" PRIu32, value);
  102. (void) avrcp_target_pack_single_element_header(packet, pos, attr_id, attr_value_length);
  103. return 8 + attr_value_length;
  104. }
  105. // returns number of bytes stored
  106. static uint16_t avrcp_target_pack_single_element_attribute_string_fragment(uint8_t * packet, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint8_t * attr_value, uint16_t attr_value_to_copy, uint16_t attr_value_size, bool header){
  107. if (attr_value_size == 0) return 0;
  108. uint16_t bytes_stored = 0;
  109. if (header){
  110. bytes_stored += avrcp_target_pack_single_element_header(packet, pos, attr_id, attr_value_size);
  111. }
  112. (void)memcpy(packet + pos + bytes_stored, attr_value, attr_value_to_copy);
  113. bytes_stored += attr_value_to_copy;
  114. return bytes_stored;
  115. }
  116. static int avrcp_target_abort_continue_response(uint16_t cid, avrcp_connection_t * connection){
  117. uint16_t pos = 0;
  118. l2cap_reserve_packet_buffer();
  119. uint8_t * packet = l2cap_get_outgoing_buffer();
  120. connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
  121. connection->command_type = AVRCP_CTYPE_RESPONSE_ACCEPTED;
  122. connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
  123. connection->subunit_id = AVRCP_SUBUNIT_ID;
  124. packet[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
  125. // Profile IDentifier (PID)
  126. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
  127. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
  128. // command_type
  129. packet[pos++] = connection->command_type;
  130. // subunit_type | subunit ID
  131. packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
  132. // opcode
  133. packet[pos++] = (uint8_t)connection->command_opcode;
  134. // company id is 3 bytes long
  135. big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
  136. pos += 3;
  137. packet[pos++] = AVRCP_PDU_ID_REQUEST_ABORT_CONTINUING_RESPONSE;
  138. // reserve byte for packet type
  139. packet[pos++] = AVRCP_SINGLE_PACKET;
  140. big_endian_store_16(packet, pos, 0);
  141. pos += 2;
  142. return l2cap_send_prepared(cid, pos);
  143. }
  144. static int avrcp_target_send_now_playing_info(uint16_t cid, avrcp_connection_t * connection){
  145. uint16_t pos = 0;
  146. l2cap_reserve_packet_buffer();
  147. uint8_t * packet = l2cap_get_outgoing_buffer();
  148. uint16_t size = l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid);
  149. packet[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
  150. // Profile IDentifier (PID)
  151. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
  152. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
  153. // command_type
  154. packet[pos++] = connection->command_type;
  155. // subunit_type | subunit ID
  156. packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
  157. // opcode
  158. packet[pos++] = (uint8_t)connection->command_opcode;
  159. // company id is 3 bytes long
  160. big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
  161. pos += 3;
  162. packet[pos++] = AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES;
  163. // reserve byte for packet type
  164. uint8_t pos_packet_type = pos;
  165. pos++;
  166. uint16_t playing_info_buffer_len_position = pos;
  167. pos += 2;
  168. if (connection->next_attr_id == AVRCP_MEDIA_ATTR_NONE){
  169. packet[pos_packet_type] = AVRCP_SINGLE_PACKET;
  170. connection->packet_type = AVRCP_SINGLE_PACKET;
  171. packet[pos++] = count_set_bits_uint32(connection->now_playing_info_attr_bitmap);
  172. connection->next_attr_id = AVRCP_MEDIA_ATTR_ALL;
  173. }
  174. uint8_t fragmented = 0;
  175. int num_free_bytes = size - pos - 2;
  176. uint8_t MAX_NUMBER_ATTR_LEN = 10;
  177. while (!fragmented && (num_free_bytes > 0) && (connection->next_attr_id <= AVRCP_MEDIA_ATTR_SONG_LENGTH_MS)){
  178. avrcp_media_attribute_id_t attr_id = connection->next_attr_id;
  179. int attr_index = attr_id - 1;
  180. if (connection->now_playing_info_attr_bitmap & (1 << attr_id)){
  181. int num_written_bytes = 0;
  182. int num_bytes_to_write = 0;
  183. switch (attr_id){
  184. case AVRCP_MEDIA_ATTR_ALL:
  185. case AVRCP_MEDIA_ATTR_NONE:
  186. break;
  187. case AVRCP_MEDIA_ATTR_TRACK:
  188. num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN;
  189. if (num_free_bytes >= num_bytes_to_write){
  190. num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->track_nr);
  191. break;
  192. }
  193. fragmented = 1;
  194. connection->attribute_value_offset = 0;
  195. break;
  196. case AVRCP_MEDIA_ATTR_TOTAL_NUM_ITEMS:
  197. num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN;
  198. if (num_free_bytes >= num_bytes_to_write){
  199. num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->total_tracks);
  200. break;
  201. }
  202. fragmented = 1;
  203. connection->attribute_value_offset = 0;
  204. break;
  205. case AVRCP_MEDIA_ATTR_SONG_LENGTH_MS:
  206. num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN;
  207. if (num_free_bytes >= num_bytes_to_write){
  208. num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->song_length_ms);
  209. break;
  210. }
  211. fragmented = 1;
  212. connection->attribute_value_offset = 0;
  213. break;
  214. default:{
  215. bool header = connection->attribute_value_offset == 0;
  216. uint8_t * attr_value = (uint8_t *) (connection->now_playing_info[attr_index].value + connection->attribute_value_offset);
  217. uint16_t attr_value_len = connection->now_playing_info[attr_index].len - connection->attribute_value_offset;
  218. num_bytes_to_write = attr_value_len + (header * AVRCP_ATTR_HEADER_LEN);
  219. if (num_bytes_to_write <= num_free_bytes){
  220. connection->attribute_value_offset = 0;
  221. num_written_bytes = num_bytes_to_write;
  222. avrcp_target_pack_single_element_attribute_string_fragment(packet, pos, attr_id, attr_value, attr_value_len, connection->now_playing_info[attr_index].len, header);
  223. break;
  224. }
  225. fragmented = 1;
  226. num_written_bytes = num_free_bytes;
  227. attr_value_len = num_free_bytes - (header * AVRCP_ATTR_HEADER_LEN);
  228. avrcp_target_pack_single_element_attribute_string_fragment(packet, pos, attr_id, attr_value, attr_value_len, connection->now_playing_info[attr_index].len, header);
  229. connection->attribute_value_offset += attr_value_len;
  230. break;
  231. }
  232. }
  233. pos += num_written_bytes;
  234. num_free_bytes -= num_written_bytes;
  235. }
  236. if (!fragmented){
  237. // C++ compatible version of connection->next_attr_id++
  238. connection->next_attr_id = (avrcp_media_attribute_id_t) (((int) connection->next_attr_id) + 1);
  239. }
  240. }
  241. if (fragmented){
  242. switch (connection->packet_type){
  243. case AVRCP_SINGLE_PACKET:
  244. connection->packet_type = AVRCP_START_PACKET;
  245. break;
  246. default:
  247. connection->packet_type = AVRCP_CONTINUE_PACKET;
  248. break;
  249. }
  250. } else {
  251. if (connection->next_attr_id >= AVRCP_MEDIA_ATTR_SONG_LENGTH_MS){ // DONE
  252. if (connection->packet_type != AVRCP_SINGLE_PACKET){
  253. connection->packet_type = AVRCP_END_PACKET;
  254. }
  255. }
  256. }
  257. packet[pos_packet_type] = connection->packet_type;
  258. // store attr value length
  259. big_endian_store_16(packet, playing_info_buffer_len_position, pos - playing_info_buffer_len_position - 2);
  260. return l2cap_send_prepared(cid, size);
  261. }
  262. static int avrcp_target_send_response(uint16_t cid, avrcp_connection_t * connection){
  263. int pos = 0;
  264. l2cap_reserve_packet_buffer();
  265. uint8_t * packet = l2cap_get_outgoing_buffer();
  266. // transport header
  267. // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
  268. // TODO: check for fragmentation
  269. connection->packet_type = AVRCP_SINGLE_PACKET;
  270. packet[pos++] = (connection->transaction_label << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
  271. // Profile IDentifier (PID)
  272. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
  273. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
  274. // command_type
  275. packet[pos++] = connection->command_type;
  276. // subunit_type | subunit ID
  277. packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
  278. // opcode
  279. packet[pos++] = (uint8_t)connection->command_opcode;
  280. (void)memcpy(packet + pos, connection->cmd_operands,
  281. connection->cmd_operands_length);
  282. pos += connection->cmd_operands_length;
  283. connection->wait_to_send = false;
  284. return l2cap_send_prepared(cid, pos);
  285. }
  286. static void avrcp_target_response_setup(avrcp_connection_t * connection, avrcp_command_type_t command_type, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id,
  287. avrcp_command_opcode_t opcode){
  288. connection->command_type = command_type;
  289. connection->subunit_type = subunit_type;
  290. connection->subunit_id = subunit_id;
  291. connection->command_opcode = opcode;
  292. }
  293. static uint8_t avrcp_target_response_accept(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id, uint8_t status){
  294. // AVRCP_CTYPE_RESPONSE_REJECTED
  295. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_ACCEPTED, subunit_type, subunit_id, opcode);
  296. // company id is 3 bytes long
  297. int pos = connection->cmd_operands_length;
  298. connection->cmd_operands[pos++] = pdu_id;
  299. connection->cmd_operands[pos++] = 0;
  300. // param length
  301. big_endian_store_16(connection->cmd_operands, pos, 1);
  302. pos += 2;
  303. connection->cmd_operands[pos++] = status;
  304. connection->cmd_operands_length = pos;
  305. connection->accept_response = 1;
  306. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  307. return ERROR_CODE_SUCCESS;
  308. }
  309. static uint8_t avrcp_target_response_reject(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id, avrcp_status_code_t status){
  310. // AVRCP_CTYPE_RESPONSE_REJECTED
  311. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_REJECTED, subunit_type, subunit_id, opcode);
  312. // company id is 3 bytes long
  313. int pos = connection->cmd_operands_length;
  314. connection->cmd_operands[pos++] = pdu_id;
  315. connection->cmd_operands[pos++] = 0;
  316. // param length
  317. big_endian_store_16(connection->cmd_operands, pos, 1);
  318. pos += 2;
  319. connection->cmd_operands[pos++] = status;
  320. connection->cmd_operands_length = pos;
  321. connection->state = AVCTP_W2_SEND_RESPONSE;
  322. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  323. return ERROR_CODE_SUCCESS;
  324. }
  325. static uint8_t avrcp_target_response_not_implemented(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id, uint8_t event_id){
  326. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_NOT_IMPLEMENTED, subunit_type, subunit_id, opcode);
  327. // company id is 3 bytes long
  328. int pos = connection->cmd_operands_length;
  329. connection->cmd_operands[pos++] = pdu_id;
  330. connection->cmd_operands[pos++] = 0;
  331. // param length
  332. big_endian_store_16(connection->cmd_operands, pos, 1);
  333. pos += 2;
  334. connection->cmd_operands[pos++] = event_id;
  335. connection->cmd_operands_length = pos;
  336. connection->state = AVCTP_W2_SEND_RESPONSE;
  337. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  338. return ERROR_CODE_SUCCESS;
  339. }
  340. static uint8_t avrcp_target_response_vendor_dependent_interim(avrcp_connection_t * connection, avrcp_pdu_id_t pdu_id, uint8_t event_id, const uint8_t * value, uint16_t value_len){
  341. // company id is 3 bytes long
  342. int pos = connection->cmd_operands_length;
  343. connection->cmd_operands[pos++] = pdu_id;
  344. connection->cmd_operands[pos++] = 0;
  345. // param length
  346. big_endian_store_16(connection->cmd_operands, pos, 1 + value_len);
  347. pos += 2;
  348. connection->cmd_operands[pos++] = event_id;
  349. if (value && (value_len > 0)){
  350. (void)memcpy(connection->cmd_operands + pos, value, value_len);
  351. pos += value_len;
  352. }
  353. connection->cmd_operands_length = pos;
  354. connection->state = AVCTP_W2_SEND_RESPONSE;
  355. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  356. return ERROR_CODE_SUCCESS;
  357. }
  358. static uint8_t avrcp_target_response_addressed_player_changed_interim(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id){
  359. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode);
  360. // company id is 3 bytes long
  361. int pos = connection->cmd_operands_length;
  362. connection->cmd_operands[pos++] = pdu_id;
  363. connection->cmd_operands[pos++] = 0;
  364. // param length
  365. big_endian_store_16(connection->cmd_operands, pos, 5);
  366. pos += 2;
  367. connection->cmd_operands[pos++] = AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED;
  368. big_endian_read_16( &connection->cmd_operands[pos], connection->addressed_player_id);
  369. pos += 2;
  370. big_endian_read_16( &connection->cmd_operands[pos], connection->uid_counter);
  371. pos += 2;
  372. connection->cmd_operands_length = pos;
  373. connection->state = AVCTP_W2_SEND_RESPONSE;
  374. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  375. return ERROR_CODE_SUCCESS;
  376. }
  377. static uint8_t avrcp_target_pass_through_response(uint16_t avrcp_cid, avrcp_command_type_t cmd_type, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){
  378. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  379. if (!connection){
  380. log_error("Could not find a connection.");
  381. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  382. }
  383. avrcp_target_response_setup(connection, cmd_type, AVRCP_SUBUNIT_TYPE_PANEL, AVRCP_SUBUNIT_ID, AVRCP_CMD_OPCODE_PASS_THROUGH);
  384. int pos = 0;
  385. connection->cmd_operands[pos++] = opid;
  386. connection->cmd_operands[pos++] = operands_length;
  387. if (operands_length == 1){
  388. connection->cmd_operands[pos++] = operand;
  389. }
  390. connection->cmd_operands_length = pos;
  391. connection->state = AVCTP_W2_SEND_RESPONSE;
  392. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  393. return ERROR_CODE_SUCCESS;
  394. }
  395. uint8_t avrcp_target_operation_rejected(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){
  396. return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_REJECTED, opid, operands_length, operand);
  397. }
  398. uint8_t avrcp_target_operation_accepted(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){
  399. return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand);
  400. }
  401. uint8_t avrcp_target_operation_not_implemented(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){
  402. return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand);
  403. }
  404. void avrcp_target_set_unit_info(uint16_t avrcp_cid, avrcp_subunit_type_t unit_type, uint32_t company_id){
  405. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  406. if (!connection){
  407. log_error("avrcp_target_set_unit_info: could not find a connection.");
  408. return;
  409. }
  410. connection->unit_type = unit_type;
  411. connection->company_id = company_id;
  412. }
  413. void avrcp_target_set_subunit_info(uint16_t avrcp_cid, avrcp_subunit_type_t subunit_type, const uint8_t * subunit_info_data, uint16_t subunit_info_data_size){
  414. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  415. if (!connection){
  416. log_error("avrcp_target_set_subunit_info: could not find a connection.");
  417. return;
  418. }
  419. connection->subunit_info_type = subunit_type;
  420. connection->subunit_info_data = subunit_info_data;
  421. connection->subunit_info_data_size = subunit_info_data_size;
  422. }
  423. static uint8_t avrcp_target_unit_info(avrcp_connection_t * connection){
  424. if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
  425. uint8_t unit = 0;
  426. connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
  427. connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique
  428. connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE;
  429. connection->command_opcode = AVRCP_CMD_OPCODE_UNIT_INFO;
  430. connection->cmd_operands_length = 5;
  431. connection->cmd_operands[0] = 0x07;
  432. connection->cmd_operands[1] = (connection->unit_type << 4) | unit;
  433. // company id is 3 bytes long
  434. big_endian_store_32(connection->cmd_operands, 2, connection->company_id);
  435. connection->state = AVCTP_W2_SEND_RESPONSE;
  436. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  437. return ERROR_CODE_SUCCESS;
  438. }
  439. static uint8_t avrcp_target_subunit_info(avrcp_connection_t * connection, uint8_t offset){
  440. if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
  441. if ((offset - 4) > connection->subunit_info_data_size) return AVRCP_STATUS_INVALID_PARAMETER;
  442. connection->command_opcode = AVRCP_CMD_OPCODE_SUBUNIT_INFO;
  443. connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
  444. connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique
  445. connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE;
  446. uint8_t page = offset / 4;
  447. uint8_t extension_code = 7;
  448. connection->cmd_operands_length = 5;
  449. connection->cmd_operands[0] = (page << 4) | extension_code;
  450. (void)memcpy(connection->cmd_operands + 1,
  451. connection->subunit_info_data + offset, 4);
  452. connection->state = AVCTP_W2_SEND_RESPONSE;
  453. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  454. return ERROR_CODE_SUCCESS;
  455. }
  456. static inline uint8_t avrcp_prepare_vendor_dependent_response(uint16_t avrcp_cid, avrcp_connection_t ** out_connection, avrcp_pdu_id_t pdu_id, uint16_t param_length){
  457. *out_connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  458. if (!*out_connection){
  459. log_error("avrcp tartget: could not find a connection.");
  460. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  461. }
  462. if ((*out_connection)->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
  463. (*out_connection)->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
  464. (*out_connection)->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
  465. (*out_connection)->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
  466. (*out_connection)->subunit_id = AVRCP_SUBUNIT_ID;
  467. (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = pdu_id;
  468. // reserved
  469. (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = 0;
  470. // param length
  471. big_endian_store_16((*out_connection)->cmd_operands, (*out_connection)->cmd_operands_length, param_length);
  472. (*out_connection)->cmd_operands_length += 2;
  473. return ERROR_CODE_SUCCESS;
  474. }
  475. static uint8_t avrcp_target_capability(uint16_t avrcp_cid, avrcp_capability_id_t capability_id, uint8_t num_capabilities, uint8_t * capabilities, uint8_t capabilities_size){
  476. avrcp_connection_t * connection = NULL;
  477. uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_CAPABILITIES, 2 + capabilities_size);
  478. if (status != ERROR_CODE_SUCCESS) return status;
  479. connection->cmd_operands[connection->cmd_operands_length++] = capability_id;
  480. connection->cmd_operands[connection->cmd_operands_length++] = num_capabilities;
  481. (void)memcpy(connection->cmd_operands + connection->cmd_operands_length,
  482. capabilities, capabilities_size);
  483. connection->cmd_operands_length += capabilities_size;
  484. connection->state = AVCTP_W2_SEND_RESPONSE;
  485. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  486. return ERROR_CODE_SUCCESS;
  487. }
  488. uint8_t avrcp_target_supported_events(uint16_t avrcp_cid, uint8_t num_event_ids, uint8_t * event_ids, uint8_t event_ids_size){
  489. return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT, num_event_ids, event_ids, event_ids_size);
  490. }
  491. uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t num_company_ids, uint8_t * company_ids, uint8_t company_ids_size){
  492. return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY, num_company_ids, company_ids, company_ids_size);
  493. }
  494. uint8_t avrcp_target_play_status(uint16_t avrcp_cid, uint32_t song_length_ms, uint32_t song_position_ms, avrcp_playback_status_t play_status){
  495. avrcp_connection_t * connection = NULL;
  496. uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_PLAY_STATUS, 11);
  497. if (status != ERROR_CODE_SUCCESS) return status;
  498. big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_length_ms);
  499. connection->cmd_operands_length += 4;
  500. big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_position_ms);
  501. connection->cmd_operands_length += 4;
  502. connection->cmd_operands[connection->cmd_operands_length++] = play_status;
  503. connection->state = AVCTP_W2_SEND_RESPONSE;
  504. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  505. return ERROR_CODE_SUCCESS;
  506. }
  507. static uint8_t avrcp_target_now_playing_info(avrcp_connection_t * connection){
  508. if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
  509. connection->now_playing_info_response = 1;
  510. connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
  511. connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
  512. connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
  513. connection->subunit_id = AVRCP_SUBUNIT_ID;
  514. connection->state = AVCTP_W2_SEND_RESPONSE;
  515. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  516. return ERROR_CODE_SUCCESS;
  517. }
  518. static uint8_t avrcp_target_store_media_attr(avrcp_connection_t * connection, avrcp_media_attribute_id_t attr_id, const char * value){
  519. int index = attr_id - 1;
  520. if (!value) return AVRCP_STATUS_INVALID_PARAMETER;
  521. connection->now_playing_info[index].value = (uint8_t*)value;
  522. connection->now_playing_info[index].len = strlen(value);
  523. return ERROR_CODE_SUCCESS;
  524. }
  525. uint8_t avrcp_target_set_playback_status(uint16_t avrcp_cid, avrcp_playback_status_t playback_status){
  526. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  527. if (!connection){
  528. log_error("avrcp_unit_info: could not find a connection.");
  529. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  530. }
  531. if (connection->playback_status == playback_status) return ERROR_CODE_SUCCESS;
  532. connection->playback_status = playback_status;
  533. connection->playback_status_changed = 1;
  534. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  535. return ERROR_CODE_SUCCESS;
  536. }
  537. void avrcp_target_set_now_playing_info(uint16_t avrcp_cid, const avrcp_track_t * current_track, uint16_t total_tracks){
  538. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  539. if (!connection){
  540. log_error("avrcp_unit_info: could not find a connection. cid 0x%02x\n", avrcp_cid);
  541. return;
  542. }
  543. if (!current_track){
  544. connection->track_selected = 0;
  545. connection->playback_status = AVRCP_PLAYBACK_STATUS_ERROR;
  546. return;
  547. }
  548. (void)memcpy(connection->track_id, current_track->track_id, 8);
  549. connection->song_length_ms = current_track->song_length_ms;
  550. connection->track_nr = current_track->track_nr;
  551. connection->total_tracks = total_tracks;
  552. avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_TITLE, current_track->title);
  553. avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_ARTIST, current_track->artist);
  554. avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_ALBUM, current_track->album);
  555. avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_GENRE, current_track->genre);
  556. connection->track_selected = 1;
  557. if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED)) {
  558. connection->track_changed = 1;
  559. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  560. }
  561. return;
  562. }
  563. uint8_t avrcp_target_track_changed(uint16_t avrcp_cid, uint8_t * track_id){
  564. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  565. if (!connection){
  566. log_error("avrcp_target_track_changed: could not find connection.");
  567. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  568. }
  569. if (!track_id) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  570. if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED)) {
  571. connection->track_changed = 1;
  572. (void)memcpy(connection->track_id, track_id, 8);
  573. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  574. }
  575. return ERROR_CODE_SUCCESS;
  576. }
  577. uint8_t avrcp_target_playing_content_changed(uint16_t avrcp_cid){
  578. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  579. if (!connection){
  580. log_error("avrcp_target_playing_content_changed: could not find a connection.");
  581. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  582. }
  583. if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED)) {
  584. connection->playing_content_changed = 1;
  585. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  586. }
  587. return ERROR_CODE_SUCCESS;
  588. }
  589. uint8_t avrcp_target_addressed_player_changed(uint16_t avrcp_cid, uint16_t player_id, uint16_t uid_counter){
  590. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  591. if (!connection){
  592. log_error("avrcp_unit_info: could not find a connection.");
  593. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  594. }
  595. if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED)) {
  596. connection->uid_counter = uid_counter;
  597. connection->addressed_player_id = player_id;
  598. }
  599. return ERROR_CODE_SUCCESS;
  600. }
  601. uint8_t avrcp_target_battery_status_changed(uint16_t avrcp_cid, avrcp_battery_status_t battery_status){
  602. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  603. if (!connection){
  604. log_error("avrcp_unit_info: could not find a connection.");
  605. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  606. }
  607. if (connection->battery_status == battery_status) return ERROR_CODE_SUCCESS;
  608. if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED)) {
  609. connection->battery_status = battery_status;
  610. connection->battery_status_changed = 1;
  611. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  612. }
  613. return ERROR_CODE_SUCCESS;
  614. }
  615. uint8_t avrcp_target_volume_changed(uint16_t avrcp_cid, uint8_t volume_percentage){
  616. avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
  617. if (!connection){
  618. log_error("avrcp_unit_info: could not find a connection.");
  619. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  620. }
  621. connection->volume_percentage = volume_percentage;
  622. if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED )) {
  623. connection->notify_volume_percentage_changed = 1;
  624. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  625. }
  626. return ERROR_CODE_SUCCESS;
  627. }
  628. static void avrcp_target_set_transaction_label_for_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification, uint8_t transaction_label){
  629. if (notification > AVRCP_NOTIFICATION_EVENT_MAX_VALUE) return;
  630. connection->notifications_transaction_label[notification] = transaction_label;
  631. }
  632. static uint8_t avrcp_target_get_transaction_label_for_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification){
  633. if (notification > AVRCP_NOTIFICATION_EVENT_MAX_VALUE) return 0;
  634. return connection->notifications_transaction_label[notification];
  635. }
  636. static uint8_t * avrcp_get_company_id(uint8_t *packet, uint16_t size){
  637. UNUSED(size);
  638. return packet + 6;
  639. }
  640. static uint8_t * avrcp_get_pdu(uint8_t *packet, uint16_t size){
  641. UNUSED(size);
  642. return packet + 9;
  643. }
  644. static uint8_t avrcp_is_receive_pass_through_cmd(uint8_t operation_id){
  645. return operation_id & 0x80;
  646. }
  647. static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){
  648. if (size < 6u) return;
  649. uint16_t pid = 0;
  650. uint8_t transport_header = packet[0];
  651. connection->transaction_label = transport_header >> 4;
  652. avrcp_packet_type_t packet_type = (avrcp_packet_type_t) ((transport_header & 0x0F) >> 2);
  653. switch (packet_type){
  654. case AVRCP_SINGLE_PACKET:
  655. pid = big_endian_read_16(packet, 1);
  656. break;
  657. case AVRCP_START_PACKET:
  658. pid = big_endian_read_16(packet, 2);
  659. break;
  660. default:
  661. break;
  662. }
  663. switch (packet_type){
  664. case AVRCP_SINGLE_PACKET:
  665. case AVRCP_START_PACKET:
  666. if (pid != BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL){
  667. log_info("Invalid pid 0x%02x, expected 0x%02x", connection->invalid_pid, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL);
  668. connection->reject_transport_header = 1;
  669. connection->invalid_pid = pid;
  670. connection->transport_header = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2 ) | (AVRCP_RESPONSE_FRAME << 1) | 1;
  671. connection->state = AVCTP_W2_SEND_RESPONSE;
  672. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  673. return;
  674. }
  675. break;
  676. default:
  677. break;
  678. }
  679. if (packet_type != AVRCP_SINGLE_PACKET) return;
  680. avrcp_subunit_type_t subunit_type = (avrcp_subunit_type_t) (packet[4] >> 3);
  681. avrcp_subunit_id_t subunit_id = (avrcp_subunit_id_t) (packet[4] & 0x07);
  682. avrcp_command_opcode_t opcode = (avrcp_command_opcode_t) avrcp_cmd_opcode(packet,size);
  683. uint8_t * company_id = avrcp_get_company_id(packet, size);
  684. uint8_t * pdu = avrcp_get_pdu(packet, size);
  685. int pos = 4;
  686. uint16_t length;
  687. avrcp_pdu_id_t pdu_id;
  688. connection->cmd_operands_length = 0;
  689. switch (opcode){
  690. case AVRCP_CMD_OPCODE_UNIT_INFO:
  691. avrcp_target_unit_info(connection);
  692. break;
  693. case AVRCP_CMD_OPCODE_SUBUNIT_INFO:{
  694. uint8_t offset = 4 * (packet[pos+2]>>4);
  695. avrcp_target_subunit_info(connection, offset);
  696. break;
  697. }
  698. case AVRCP_CMD_OPCODE_PASS_THROUGH:{
  699. log_info("AVRCP_OPERATION_ID 0x%02x, operands length %d, operand %d", packet[6], packet[7], packet[8]);
  700. avrcp_operation_id_t operation_id = (avrcp_operation_id_t) packet[6];
  701. if (avrcp_is_receive_pass_through_cmd(operation_id)){
  702. operation_id = (avrcp_operation_id_t) (packet[6] & 0x7F);
  703. avrcp_target_operation_accepted(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
  704. break;
  705. }
  706. switch (operation_id){
  707. case AVRCP_OPERATION_ID_PLAY:
  708. case AVRCP_OPERATION_ID_PAUSE:
  709. case AVRCP_OPERATION_ID_STOP:
  710. case AVRCP_OPERATION_ID_VOLUME_UP:
  711. case AVRCP_OPERATION_ID_VOLUME_DOWN:
  712. case AVRCP_OPERATION_ID_REWIND:
  713. case AVRCP_OPERATION_ID_FAST_FORWARD:
  714. case AVRCP_OPERATION_ID_FORWARD:
  715. case AVRCP_OPERATION_ID_BACKWARD:
  716. case AVRCP_OPERATION_ID_SKIP:
  717. case AVRCP_OPERATION_ID_MUTE:
  718. case AVRCP_OPERATION_ID_CHANNEL_UP:
  719. case AVRCP_OPERATION_ID_CHANNEL_DOWN:
  720. case AVRCP_OPERATION_ID_SELECT:
  721. case AVRCP_OPERATION_ID_UP:
  722. case AVRCP_OPERATION_ID_DOWN:
  723. case AVRCP_OPERATION_ID_LEFT:
  724. case AVRCP_OPERATION_ID_RIGHT:
  725. case AVRCP_OPERATION_ID_ROOT_MENU:
  726. avrcp_target_operation_accepted(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
  727. avrcp_target_emit_operation(avrcp_target_context.avrcp_callback, connection->avrcp_cid, operation_id, packet[7], packet[8]);
  728. break;
  729. case AVRCP_OPERATION_ID_UNDEFINED:
  730. avrcp_target_operation_not_implemented(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
  731. return;
  732. default:
  733. avrcp_target_operation_not_implemented(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
  734. return;
  735. }
  736. break;
  737. }
  738. case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT:
  739. pdu_id = (avrcp_pdu_id_t) pdu[0];
  740. // 1 - reserved
  741. // 2-3 param length,
  742. length = big_endian_read_16(pdu, 2);
  743. (void)memcpy(connection->cmd_operands, company_id, 3);
  744. connection->cmd_operands_length = 3;
  745. switch (pdu_id){
  746. case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:{
  747. bool ok = length == 4;
  748. if (avrcp_target_context.set_addressed_player_callback != NULL){
  749. uint16_t player_id = big_endian_read_16(pdu, 4);
  750. ok = avrcp_target_context.set_addressed_player_callback(player_id);
  751. }
  752. if (ok){
  753. avrcp_target_response_accept(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_SUCCESS);
  754. } else {
  755. avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PLAYER_ID);
  756. }
  757. break;
  758. }
  759. case AVRCP_PDU_ID_GET_CAPABILITIES:{
  760. avrcp_capability_id_t capability_id = (avrcp_capability_id_t) pdu[pos];
  761. switch (capability_id){
  762. case AVRCP_CAPABILITY_ID_EVENT:
  763. avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_EVENT_IDS_QUERY);
  764. break;
  765. case AVRCP_CAPABILITY_ID_COMPANY:
  766. avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_COMPANY_IDS_QUERY);
  767. break;
  768. default:
  769. avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
  770. break;
  771. }
  772. break;
  773. }
  774. case AVRCP_PDU_ID_GET_PLAY_STATUS:
  775. avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_PLAY_STATUS_QUERY);
  776. break;
  777. case AVRCP_PDU_ID_REQUEST_ABORT_CONTINUING_RESPONSE:
  778. connection->cmd_operands[0] = pdu[4];
  779. connection->abort_continue_response = 1;
  780. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  781. break;
  782. case AVRCP_PDU_ID_REQUEST_CONTINUING_RESPONSE:
  783. if (pdu[4] != AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES){
  784. avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND);
  785. return;
  786. }
  787. connection->now_playing_info_response = 1;
  788. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  789. break;
  790. case AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES:{
  791. uint8_t play_identifier[8];
  792. memset(play_identifier, 0, 8);
  793. if (memcmp(pdu+pos, play_identifier, 8) != 0) {
  794. avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
  795. return;
  796. }
  797. pos += 8;
  798. uint8_t attribute_count = pdu[pos++];
  799. connection->next_attr_id = AVRCP_MEDIA_ATTR_NONE;
  800. if (!attribute_count){
  801. connection->now_playing_info_attr_bitmap = 0xFE;
  802. } else {
  803. int i;
  804. connection->now_playing_info_attr_bitmap = 0;
  805. for (i=0; i < attribute_count; i++){
  806. uint16_t attr_id = big_endian_read_16(pdu, pos);
  807. pos += 2;
  808. connection->now_playing_info_attr_bitmap |= (1 << attr_id);
  809. }
  810. }
  811. log_info("now_playing_info_attr_bitmap 0x%02x", connection->now_playing_info_attr_bitmap);
  812. avrcp_target_now_playing_info(connection);
  813. break;
  814. }
  815. case AVRCP_PDU_ID_REGISTER_NOTIFICATION:{
  816. // 0 - pdu id
  817. // 1 - reserved
  818. // 2-3 param length
  819. avrcp_notification_event_id_t event_id = (avrcp_notification_event_id_t) pdu[4];
  820. uint16_t event_mask = (1 << event_id);
  821. avrcp_target_set_transaction_label_for_notification(connection, event_id, connection->transaction_label);
  822. switch (event_id){
  823. case AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED:
  824. connection->notifications_enabled |= event_mask;
  825. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode);
  826. if (connection->track_selected){
  827. avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, AVRCP_NOTIFICATION_TRACK_SELECTED, 8);
  828. } else {
  829. avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, AVRCP_NOTIFICATION_TRACK_NOT_SELECTED, 8);
  830. }
  831. break;
  832. case AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED:
  833. connection->notifications_enabled |= event_mask;
  834. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode);
  835. avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, (const uint8_t *)&connection->playback_status, 1);
  836. break;
  837. case AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED:
  838. connection->notifications_enabled |= event_mask;
  839. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode);
  840. avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, NULL, 0);
  841. break;
  842. case AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED:
  843. connection->notify_volume_percentage_changed = 0;
  844. connection->notifications_enabled |= event_mask;
  845. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode);
  846. avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, (const uint8_t *)&connection->volume_percentage, 1);
  847. break;
  848. case AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED:
  849. connection->notifications_enabled |= event_mask;
  850. avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode);
  851. avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, (const uint8_t *)&connection->battery_status, 1);
  852. break;
  853. case AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED:
  854. case AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
  855. case AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED:
  856. avrcp_target_response_not_implemented(connection, subunit_type, subunit_id, opcode, pdu_id, event_id);
  857. return;
  858. case AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED:
  859. connection->notifications_enabled |= event_mask;
  860. avrcp_target_response_addressed_player_changed_interim(connection, subunit_type, subunit_id, opcode, pdu_id);
  861. return;
  862. default:
  863. avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
  864. return;
  865. }
  866. break;
  867. }
  868. case AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME: {
  869. if (length != 1){
  870. avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND);
  871. break;
  872. }
  873. uint8_t absolute_volume = pdu[4];
  874. if (absolute_volume < 0x80){
  875. connection->volume_percentage = absolute_volume;
  876. }
  877. avrcp_target_response_accept(connection, subunit_type, subunit_id, opcode, pdu_id, connection->volume_percentage);
  878. avrcp_target_emit_volume_changed(avrcp_target_context.avrcp_callback, connection->avrcp_cid, connection->volume_percentage);
  879. break;
  880. }
  881. default:
  882. log_info("AVRCP target: unhandled pdu id 0x%02x", pdu_id);
  883. avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND);
  884. break;
  885. }
  886. break;
  887. default:
  888. log_info("AVRCP target: opcode 0x%02x not implemented", avrcp_cmd_opcode(packet,size));
  889. break;
  890. }
  891. }
  892. static int avrcp_target_send_notification(uint16_t cid, avrcp_connection_t * connection, avrcp_notification_event_id_t notification_id, uint8_t * value, uint16_t value_len){
  893. if (!connection){
  894. log_error("avrcp tartget: could not find a connection.");
  895. return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
  896. }
  897. connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
  898. connection->command_type = AVRCP_CTYPE_RESPONSE_CHANGED_STABLE;
  899. connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
  900. connection->subunit_id = AVRCP_SUBUNIT_ID;
  901. connection->transaction_label = avrcp_target_get_transaction_label_for_notification(connection, notification_id);
  902. uint16_t pos = 0;
  903. l2cap_reserve_packet_buffer();
  904. uint8_t * packet = l2cap_get_outgoing_buffer();
  905. uint16_t size = l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid);
  906. connection->packet_type = AVRCP_SINGLE_PACKET;
  907. packet[pos++] = (connection->transaction_label << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
  908. // Profile IDentifier (PID)
  909. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
  910. packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
  911. // command_type
  912. packet[pos++] = connection->command_type;
  913. // subunit_type | subunit ID
  914. packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
  915. // opcode
  916. packet[pos++] = (uint8_t)connection->command_opcode;
  917. // company id is 3 bytes long
  918. big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
  919. pos += 3;
  920. packet[pos++] = AVRCP_PDU_ID_REGISTER_NOTIFICATION;
  921. packet[pos++] = 0;
  922. uint16_t remainig_outgoing_buffer_size = size - pos - 2;
  923. uint16_t caped_value_len = btstack_min(value_len + 1, remainig_outgoing_buffer_size);
  924. big_endian_store_16(packet, pos, caped_value_len);
  925. pos += 2;
  926. packet[pos++] = notification_id;
  927. (void)memcpy(packet + pos, value, caped_value_len - 1);
  928. pos += caped_value_len - 1;
  929. connection->wait_to_send = false;
  930. return l2cap_send_prepared(cid, pos);
  931. }
  932. static void avrcp_target_reset_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification_id){
  933. if (!connection){
  934. log_error("avrcp tartget: could not find a connection.");
  935. return;
  936. }
  937. connection->notifications_enabled &= ~(1 << notification_id);
  938. connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
  939. avrcp_target_set_transaction_label_for_notification(connection, notification_id, 0);
  940. }
  941. static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
  942. avrcp_connection_t * connection;
  943. switch (packet_type) {
  944. case L2CAP_DATA_PACKET:
  945. connection = avrcp_get_connection_for_l2cap_signaling_cid_for_role(AVRCP_TARGET, channel);
  946. avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size);
  947. break;
  948. case HCI_EVENT_PACKET:
  949. switch (hci_event_packet_get_type(packet)){
  950. case L2CAP_EVENT_CAN_SEND_NOW:{
  951. connection = avrcp_get_connection_for_l2cap_signaling_cid_for_role(AVRCP_TARGET, channel);
  952. if (connection->accept_response){
  953. connection->accept_response = 0;
  954. avrcp_target_send_response(connection->l2cap_signaling_cid, connection);
  955. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  956. return;
  957. }
  958. if (connection->abort_continue_response){
  959. connection->abort_continue_response = 0;
  960. connection->now_playing_info_response = 0;
  961. avrcp_target_abort_continue_response(connection->l2cap_signaling_cid, connection);
  962. return;
  963. }
  964. if (connection->now_playing_info_response){
  965. connection->now_playing_info_response = 0;
  966. avrcp_target_send_now_playing_info(connection->l2cap_signaling_cid, connection);
  967. return;
  968. }
  969. if (connection->track_changed){
  970. connection->track_changed = 0;
  971. avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, connection->track_id, 8);
  972. avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED);
  973. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  974. return;
  975. }
  976. if (connection->playback_status_changed){
  977. connection->playback_status_changed = 0;
  978. uint8_t playback_status = (uint8_t) connection->playback_status;
  979. avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, &playback_status, 1);
  980. avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED);
  981. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  982. return;
  983. }
  984. if (connection->playing_content_changed){
  985. connection->playing_content_changed = 0;
  986. avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, NULL, 0);
  987. avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);
  988. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  989. return;
  990. }
  991. if (connection->battery_status_changed){
  992. connection->battery_status_changed = 0;
  993. avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, (uint8_t *)&connection->battery_status, 1);
  994. avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED);
  995. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  996. return;
  997. }
  998. if (connection->notify_volume_percentage_changed){
  999. connection->notify_volume_percentage_changed = 0;
  1000. avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED, &connection->volume_percentage, 1);
  1001. avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
  1002. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  1003. return;
  1004. }
  1005. if (connection->reject_transport_header){
  1006. connection->state = AVCTP_CONNECTION_OPENED;
  1007. connection->reject_transport_header = 0;
  1008. l2cap_reserve_packet_buffer();
  1009. uint8_t * out_buffer = l2cap_get_outgoing_buffer();
  1010. out_buffer[0] = connection->transport_header;
  1011. big_endian_store_16(out_buffer, 1, connection->invalid_pid);
  1012. l2cap_send_prepared(connection->l2cap_signaling_cid, 3);
  1013. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  1014. return;
  1015. }
  1016. switch (connection->state){
  1017. case AVCTP_W2_SEND_RESPONSE:
  1018. connection->state = AVCTP_CONNECTION_OPENED;
  1019. avrcp_target_send_response(connection->l2cap_signaling_cid, connection);
  1020. avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
  1021. return;
  1022. default:
  1023. break;
  1024. }
  1025. break;
  1026. }
  1027. default:
  1028. break;
  1029. }
  1030. default:
  1031. break;
  1032. }
  1033. }
  1034. void avrcp_target_init(void){
  1035. avrcp_target_context.role = AVRCP_TARGET;
  1036. avrcp_target_context.packet_handler = avrcp_target_packet_handler;
  1037. avrcp_register_target_packet_handler(&avrcp_target_packet_handler);
  1038. }
  1039. void avrcp_target_register_packet_handler(btstack_packet_handler_t callback){
  1040. btstack_assert(callback != NULL);
  1041. avrcp_target_context.avrcp_callback = callback;
  1042. }
  1043. void avrcp_target_register_set_addressed_player_handler(bool (*callback)(uint16_t player_id)){
  1044. btstack_assert(callback != NULL);
  1045. avrcp_target_context.set_addressed_player_callback = callback;
  1046. }