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