xref: /btstack/src/classic/avrcp_target.c (revision 55ab84a4163c247e7a5bb432b7e59e44dd16af21)
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  * [email protected]
35  *
36  */
37 
38 #define __BTSTACK_FILE__ "avrcp_target.c"
39 
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 #include "btstack.h"
46 #include "classic/avrcp.h"
47 
48 static avrcp_context_t avrcp_target_context;
49 
50 void avrcp_target_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint8_t browsing, uint16_t supported_features, const char * service_name, const char * service_provider_name){
51     avrcp_create_sdp_record(0, service, service_record_handle, browsing, supported_features, service_name, service_provider_name);
52 }
53 
54 static void avrcp_target_emit_respond_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t subeventID){
55     if (!callback) return;
56     uint8_t event[5];
57     int pos = 0;
58     event[pos++] = HCI_EVENT_AVRCP_META;
59     event[pos++] = sizeof(event) - 2;
60     event[pos++] = subeventID;
61     little_endian_store_16(event, pos, avrcp_cid);
62     pos += 2;
63     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
64 }
65 
66 static void avrcp_target_emit_respond_subunit_info_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t offset){
67     if (!callback) return;
68     uint8_t event[6];
69     int pos = 0;
70     event[pos++] = HCI_EVENT_AVRCP_META;
71     event[pos++] = sizeof(event) - 2;
72     event[pos++] = AVRCP_SUBEVENT_SUBUNIT_INFO_QUERY;
73     little_endian_store_16(event, pos, avrcp_cid);
74     pos += 2;
75     event[pos++] = offset;
76     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
77 }
78 
79 static void avrcp_target_emit_respond_vendor_dependent_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t subevent_id){
80     if (!callback) return;
81     uint8_t event[5];
82     int pos = 0;
83     event[pos++] = HCI_EVENT_AVRCP_META;
84     event[pos++] = sizeof(event) - 2;
85     event[pos++] = subevent_id;
86     little_endian_store_16(event, pos, avrcp_cid);
87     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
88 }
89 
90 static uint16_t avrcp_target_pack_single_element_attribute_number(uint8_t * packet, uint16_t size, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint32_t value){
91     UNUSED(size);
92     if ((attr_id < 1) || (attr_id > AVRCP_MEDIA_ATTR_COUNT)) return 0;
93     uint16_t attr_value_length = sprintf((char *)(packet+pos+8), "%u", value);
94     big_endian_store_32(packet, pos, attr_id);
95     pos += 4;
96     big_endian_store_16(packet, pos, UTF8);
97     pos += 2;
98     big_endian_store_16(packet, pos, attr_value_length);
99     pos += 2;
100     return 8 + attr_value_length;
101 }
102 
103 static uint16_t avrcp_target_pack_single_element_attribute_string(uint8_t * packet, uint16_t size, uint16_t pos, rfc2978_charset_mib_enumid_t mib_enumid, avrcp_media_attribute_id_t attr_id, uint8_t * attr_value, uint16_t attr_value_length){
104     UNUSED(size);
105     if (attr_value_length == 0) return 0;
106     if ((attr_id < 1) || (attr_id > AVRCP_MEDIA_ATTR_COUNT)) return 0;
107     big_endian_store_32(packet, pos, attr_id);
108     pos += 4;
109     big_endian_store_16(packet, pos, mib_enumid);
110     pos += 2;
111     big_endian_store_16(packet, pos, attr_value_length);
112     pos += 2;
113     memcpy(packet+pos, attr_value, attr_value_length);
114     pos += attr_value_length;
115     return 8 + attr_value_length;
116 }
117 
118 static int avrcp_target_send_now_playing_info(uint16_t cid, avrcp_connection_t * connection){
119     uint16_t pos = 0;
120     l2cap_reserve_packet_buffer();
121     uint8_t * packet = l2cap_get_outgoing_buffer();
122     uint16_t  size   = l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid);
123 
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 
129     // command_type
130     packet[pos++] = connection->command_type;
131     // subunit_type | subunit ID
132     packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
133     // opcode
134     packet[pos++] = (uint8_t)connection->command_opcode;
135 
136     // company id is 3 bytes long
137     big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
138     pos += 3;
139 
140     packet[pos++] = AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES;
141     packet[pos++] = 0;
142 
143     // num_attrs
144     int i;
145 
146     uint16_t playing_info_buffer_len = 1;
147     uint16_t playing_info_buffer_len_position = pos;
148 
149     uint8_t  media_attr_count = 0;
150     uint16_t media_attr_count_position = pos + 2;
151     pos += 3;
152 
153     for (i = 0; i < AVRCP_MEDIA_ATTR_COUNT; i++){
154         int attr_id = i+1;
155         int attr_len;
156         switch (attr_id){
157             case AVRCP_MEDIA_ATTR_TRACK:
158                 attr_len = avrcp_target_pack_single_element_attribute_number(packet, size, pos, attr_id, connection->track_nr);
159                 break;
160             case AVRCP_MEDIA_ATTR_TOTAL_TRACKS:
161                 attr_len = avrcp_target_pack_single_element_attribute_number(packet, size, pos, attr_id, connection->total_tracks);
162                 break;
163             case AVRCP_MEDIA_ATTR_SONG_LENGTH:
164                 attr_len = avrcp_target_pack_single_element_attribute_number(packet, size, pos, attr_id, connection->song_length_ms);
165                 break;
166             default:
167                 attr_len = avrcp_target_pack_single_element_attribute_string(packet, size, pos, UTF8, attr_id, connection->now_playing_info[i].value, connection->now_playing_info[i].len);
168                 break;
169         }
170         if (attr_len > 0) {
171             pos += attr_len;
172             playing_info_buffer_len += attr_len;
173             media_attr_count++;
174         }
175     }
176     big_endian_store_16(packet, playing_info_buffer_len_position, playing_info_buffer_len);
177     packet[media_attr_count_position] = media_attr_count;
178 
179     // TODO fragmentation
180     if (playing_info_buffer_len + pos > l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid)) {
181         return ERROR_CODE_MEMORY_CAPACITY_EXCEEDED;
182     }
183 
184     connection->wait_to_send = 0;
185     return l2cap_send_prepared(cid, pos);
186 }
187 
188 static int avrcp_target_send_response(uint16_t cid, avrcp_connection_t * connection){
189     int pos = 0;
190     l2cap_reserve_packet_buffer();
191     uint8_t * packet = l2cap_get_outgoing_buffer();
192 
193     // transport header
194     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
195     packet[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
196     // Profile IDentifier (PID)
197     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
198     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
199 
200     // command_type
201     packet[pos++] = connection->command_type;
202     // subunit_type | subunit ID
203     packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
204     // opcode
205     packet[pos++] = (uint8_t)connection->command_opcode;
206     // operands
207     memcpy(packet+pos, connection->cmd_operands, connection->cmd_operands_length);
208     pos += connection->cmd_operands_length;
209     connection->wait_to_send = 0;
210     return l2cap_send_prepared(cid, pos);
211 }
212 
213 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){
214     // AVRCP_CTYPE_RESPONSE_REJECTED
215     connection->command_type = AVRCP_CTYPE_RESPONSE_REJECTED;
216     connection->subunit_type = subunit_type;
217     connection->subunit_id =   subunit_id;
218     connection->command_opcode = opcode;
219 
220     // company id is 3 bytes long
221     int pos = connection->cmd_operands_length;
222     connection->cmd_operands[pos++] = pdu_id;
223     connection->cmd_operands[pos++] = 0;
224     // param length
225     big_endian_store_16(connection->cmd_operands, pos, 1);
226     pos += 2;
227     connection->cmd_operands[pos++] = status;
228     connection->cmd_operands_length = pos;
229 
230     connection->state = AVCTP_W2_SEND_RESPONSE;
231     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
232     return ERROR_CODE_SUCCESS;
233 }
234 
235 uint8_t avrcp_target_unit_info(uint16_t avrcp_cid, avrcp_subunit_type_t unit_type, uint32_t company_id){
236     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
237     if (!connection){
238         log_error("avrcp_unit_info: could not find a connection.");
239         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
240     }
241     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
242 
243     uint8_t unit = 0;
244     connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
245     connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique
246     connection->subunit_id =   AVRCP_SUBUNIT_ID_IGNORE;
247     connection->command_opcode = AVRCP_CMD_OPCODE_UNIT_INFO;
248 
249     connection->cmd_operands_length = 5;
250     connection->cmd_operands[0] = 0x07;
251     connection->cmd_operands[1] = (unit_type << 4) | unit;
252     // company id is 3 bytes long
253     big_endian_store_32(connection->cmd_operands, 2, company_id);
254 
255     connection->state = AVCTP_W2_SEND_RESPONSE;
256     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
257     return ERROR_CODE_SUCCESS;
258 }
259 
260 uint8_t avrcp_target_subunit_info(uint16_t avrcp_cid, avrcp_subunit_type_t subunit_type, uint8_t offset, uint8_t * subunit_info_data){
261     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
262     if (!connection){
263         log_error("avrcp_unit_info: could not find a connection.");
264         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
265     }
266     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
267 
268     connection->command_opcode = AVRCP_CMD_OPCODE_SUBUNIT_INFO;
269     connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
270     connection->subunit_type = subunit_type; //vendor unique
271     connection->subunit_id =   AVRCP_SUBUNIT_ID_IGNORE;
272 
273     uint8_t page = offset / 4;
274     uint8_t extension_code = 7;
275     connection->cmd_operands_length = 5;
276     connection->cmd_operands[0] = (page << 4) | extension_code;
277     memcpy(connection->cmd_operands+1, subunit_info_data + offset, 4);
278 
279     connection->state = AVCTP_W2_SEND_RESPONSE;
280     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
281     return ERROR_CODE_SUCCESS;
282 }
283 
284 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){
285     *out_connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
286     if (!*out_connection){
287         log_error("avrcp tartget: could not find a connection.");
288         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
289     }
290 
291     if ((*out_connection)->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
292     (*out_connection)->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
293     (*out_connection)->command_type    = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
294     (*out_connection)->subunit_type    = AVRCP_SUBUNIT_TYPE_PANEL;
295     (*out_connection)->subunit_id      = AVRCP_SUBUNIT_ID;
296 
297     (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = pdu_id;
298     // reserved
299     (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = 0;
300     // param length
301     big_endian_store_16((*out_connection)->cmd_operands, (*out_connection)->cmd_operands_length, param_length);
302     (*out_connection)->cmd_operands_length += 2;
303     return ERROR_CODE_SUCCESS;
304 }
305 
306 static uint8_t avrcp_target_capability(uint16_t avrcp_cid, avrcp_capability_id_t capability_id, uint8_t capabilities_num, uint8_t * capabilities, uint8_t size){
307     avrcp_connection_t * connection = NULL;
308     uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_CAPABILITIES, 2+size);
309     if (status != ERROR_CODE_SUCCESS) return status;
310 
311     connection->cmd_operands[connection->cmd_operands_length++] = capability_id;
312     connection->cmd_operands[connection->cmd_operands_length++] = capabilities_num;
313     memcpy(connection->cmd_operands+connection->cmd_operands_length, capabilities, size);
314     connection->cmd_operands_length += size;
315 
316     connection->state = AVCTP_W2_SEND_RESPONSE;
317     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
318     return ERROR_CODE_SUCCESS;
319 }
320 
321 uint8_t avrcp_target_supported_events(uint16_t avrcp_cid, uint8_t capabilities_num, uint8_t * capabilities, uint8_t size){
322     return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT, capabilities_num, capabilities, size);
323 }
324 
325 uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t capabilities_num, uint8_t * capabilities, uint8_t size ){
326     return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY, capabilities_num, capabilities, size);
327 }
328 
329 uint8_t avrcp_target_play_status(uint16_t avrcp_cid, uint32_t song_length_ms, uint32_t song_position_ms, avrcp_play_status_t play_status){
330     avrcp_connection_t * connection = NULL;
331     uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_PLAY_STATUS, 11);
332     if (status != ERROR_CODE_SUCCESS) return status;
333 
334     big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_length_ms);
335     connection->cmd_operands_length += 4;
336     big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_position_ms);
337     connection->cmd_operands_length += 4;
338     connection->cmd_operands[connection->cmd_operands_length++] = play_status;
339 
340     connection->state = AVCTP_W2_SEND_RESPONSE;
341     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
342     return ERROR_CODE_SUCCESS;
343 }
344 
345 uint8_t avrcp_target_now_playing_info(uint16_t avrcp_cid){
346     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
347     if (!connection){
348         log_error("avrcp tartget: could not find a connection.");
349         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
350     }
351 
352     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
353     connection->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
354     connection->command_type    = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
355     connection->subunit_type    = AVRCP_SUBUNIT_TYPE_PANEL;
356     connection->subunit_id      = AVRCP_SUBUNIT_ID;
357 
358     connection->now_playing_info_response = 1;
359     connection->state = AVCTP_W2_SEND_RESPONSE;
360     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
361     return ERROR_CODE_SUCCESS;
362 }
363 
364 static uint8_t avrcp_target_store_media_attr(uint16_t avrcp_cid, avrcp_media_attribute_id_t attr_id, const char * value){
365     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
366     if (!connection){
367         log_error("avrcp_unit_info: could not find a connection.");
368         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
369     }
370 
371     int index = attr_id - 1;
372     connection->now_playing_info[index].value = (uint8_t*)value;
373     connection->now_playing_info[index].len   = strlen(value);
374     return ERROR_CODE_SUCCESS;
375 }
376 
377 uint8_t avrcp_target_set_now_playing_title(uint16_t avrcp_cid, const char * title){
378     return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_TITLE, title);
379 }
380 
381 uint8_t avrcp_target_set_now_playing_artist(uint16_t avrcp_cid, const char * artist){
382     return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_ARTIST, artist);
383 }
384 
385 uint8_t avrcp_target_set_now_playing_album(uint16_t avrcp_cid, const char * album){
386     return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_ALBUM, album);
387 }
388 
389 uint8_t avrcp_target_set_now_playing_genre(uint16_t avrcp_cid, const char * genre){
390     return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_GENRE, genre);
391 }
392 
393 uint8_t avrcp_target_set_now_playing_song_length_ms(uint16_t avrcp_cid, const uint32_t song_length_ms){
394     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
395     if (!connection){
396         log_error("avrcp_unit_info: could not find a connection.");
397         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
398     }
399     connection->song_length_ms = song_length_ms;
400     return ERROR_CODE_SUCCESS;
401 }
402 
403 uint8_t avrcp_target_set_now_playing_total_tracks(uint16_t avrcp_cid, const int total_tracks){
404     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
405     if (!connection){
406         log_error("avrcp_unit_info: could not find a connection.");
407         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
408     }
409     connection->total_tracks = total_tracks;
410     return ERROR_CODE_SUCCESS;
411 }
412 
413 uint8_t avrcp_target_set_now_playing_track_nr(uint16_t avrcp_cid, const int track_nr){
414     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
415     if (!connection){
416         log_error("avrcp_unit_info: could not find a connection.");
417         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
418     }
419     connection->track_nr = track_nr;
420     return ERROR_CODE_SUCCESS;
421 }
422 
423 static uint8_t * avrcp_get_company_id(uint8_t *packet, uint16_t size){
424     UNUSED(size);
425     return packet + 6;
426 }
427 
428 static uint8_t * avrcp_get_pdu(uint8_t *packet, uint16_t size){
429     UNUSED(size);
430     return packet + 9;
431 }
432 
433 static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){
434     UNUSED(connection);
435     UNUSED(packet);
436     UNUSED(size);
437 
438     // uint8_t opcode;
439 
440     uint8_t transport_header = packet[0];
441     connection->transaction_label = transport_header >> 4;
442     // uint8_t packet_type = (transport_header & 0x0F) >> 2;
443     // uint8_t frame_type = (transport_header & 0x03) >> 1;
444     // uint8_t ipid = transport_header & 0x01;
445     // uint8_t byte_value = packet[2];
446     // uint16_t pid = (byte_value << 8) | packet[2];
447 
448     // avrcp_command_type_t ctype = (avrcp_command_type_t) packet[3];
449     // uint8_t byte_value = packet[4];
450     avrcp_subunit_type_t subunit_type = (avrcp_subunit_type_t) (packet[4] >> 3);
451     avrcp_subunit_id_t   subunit_id   = (avrcp_subunit_id_t) (packet[4] & 0x07);
452     // opcode = packet[pos++];
453 
454     // printf("    Transport header 0x%02x (transaction_label %d, packet_type %d, frame_type %d, ipid %d), pid 0x%4x\n",
455     //     transport_header, transaction_label, packet_type, frame_type, ipid, pid);
456     // printf_hexdump(packet+pos, size-pos);
457 
458     avrcp_command_opcode_t opcode = avrcp_cmd_opcode(packet,size);
459     uint8_t * company_id = avrcp_get_company_id(packet, size);
460     uint8_t * pdu = avrcp_get_pdu(packet, size);
461     // uint16_t param_length = big_endian_read_16(pdu, 2);
462 
463     int pos = 4;
464     uint8_t   pdu_id;
465     connection->cmd_operands_length = 0;
466 
467     switch (opcode){
468         case AVRCP_CMD_OPCODE_UNIT_INFO:
469             avrcp_target_emit_respond_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_UNIT_INFO_QUERY);
470             break;
471         case AVRCP_CMD_OPCODE_SUBUNIT_INFO:{
472             uint8_t offset =  4 * (packet[pos+2]>>4);
473             avrcp_target_emit_respond_subunit_info_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, offset);
474             break;
475         }
476         case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT:
477             pdu_id = pdu[0];
478             // 1 - reserved
479             // 2-3 param length,
480             memcpy(connection->cmd_operands, company_id, 3);
481             connection->cmd_operands_length = 3;
482             switch (pdu_id){
483                 case AVRCP_PDU_ID_GET_CAPABILITIES:{
484                     avrcp_capability_id_t capability_id = (avrcp_capability_id_t) pdu[pos];
485                     switch (capability_id){
486                         case AVRCP_CAPABILITY_ID_EVENT:
487                             avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_EVENT_IDS_QUERY);
488                             break;
489                         case AVRCP_CAPABILITY_ID_COMPANY:
490                             avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_COMPANY_IDS_QUERY);
491                             break;
492                         default:
493                             avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
494                             break;
495                     }
496                     break;
497                 }
498                 case AVRCP_PDU_ID_GET_PLAY_STATUS:
499                     avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_PLAY_STATUS_QUERY);
500                     break;
501                 case AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES:{
502                     uint8_t play_identifier[8];
503                     memset(play_identifier, 0, 8);
504                     if (memcmp(pdu+pos, play_identifier, 8) != 0) {
505                         avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
506                         return;
507                     }
508                     avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY);
509                     break;
510                 }
511                 default:
512                     printf("unhandled pdu id 0x%02x\n", pdu_id);
513                     avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND);
514                     break;
515             }
516             break;
517         default:
518             printf("AVRCP source: opcode 0x%02x not implemented\n", avrcp_cmd_opcode(packet,size));
519             break;
520     }
521 }
522 
523 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
524     avrcp_connection_t * connection;
525     switch (packet_type) {
526         case L2CAP_DATA_PACKET:
527             connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_target_context);
528             if (!connection) break;
529             avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size);
530             break;
531         case HCI_EVENT_PACKET:
532             switch (hci_event_packet_get_type(packet)){
533                 case L2CAP_EVENT_CAN_SEND_NOW:
534                     connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_target_context);
535                     if (!connection) break;
536                     switch (connection->state){
537                         case AVCTP_W2_SEND_RESPONSE:
538                             connection->state = AVCTP_CONNECTION_OPENED;
539                             if (connection->now_playing_info_response){
540                                 printf("now_playing_info_response  \n");
541                                 connection->now_playing_info_response = 0;
542                                 avrcp_target_send_now_playing_info(connection->l2cap_signaling_cid, connection);
543                                 break;
544                             }
545                             avrcp_target_send_response(connection->l2cap_signaling_cid, connection);
546                             break;
547                         default:
548                             return;
549                     }
550                     break;
551             default:
552                 avrcp_packet_handler(packet_type, channel, packet, size, &avrcp_target_context);
553                 break;
554         }
555         default:
556             break;
557     }
558 }
559 
560 void avrcp_target_init(void){
561     avrcp_target_context.role = AVRCP_TARGET;
562     avrcp_target_context.connections = NULL;
563     avrcp_target_context.packet_handler = avrcp_controller_packet_handler;
564     l2cap_register_service(&avrcp_controller_packet_handler, BLUETOOTH_PROTOCOL_AVCTP, 0xffff, LEVEL_0);
565 }
566 
567 void avrcp_target_register_packet_handler(btstack_packet_handler_t callback){
568     if (callback == NULL){
569         log_error("avrcp_register_packet_handler called with NULL callback");
570         return;
571     }
572     avrcp_target_context.avrcp_callback = callback;
573 }
574 
575 uint8_t avrcp_target_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid){
576     return avrcp_connect(bd_addr, &avrcp_target_context, avrcp_cid);
577 }
578 
579 uint8_t avrcp_target_disconnect(uint16_t avrcp_cid){
580     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context);
581     if (!connection){
582         log_error("avrcp_get_capabilities: could not find a connection.");
583         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
584     }
585     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
586     l2cap_disconnect(connection->l2cap_signaling_cid, 0);
587     return ERROR_CODE_SUCCESS;
588 }
589 
590