xref: /btstack/src/classic/avrcp_target.c (revision ff3cc4a5378c2f681cc9b75cf54d154a12a3051e)
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 #define AVRCP_ATTR_HEADER_LEN  8
50 
51 static const uint8_t AVRCP_NOTIFICATION_TRACK_SELECTED[] = {0,0,0,0,0,0,0,0};
52 static const uint8_t AVRCP_NOTIFICATION_TRACK_NOT_SELECTED[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
53 
54 avrcp_context_t avrcp_target_context;
55 
56 static int avrcp_target_supports_browsing(uint16_t target_supported_features){
57     return target_supported_features & (1 << AVRCP_TARGET_SUPPORTED_FEATURE_BROWSING);
58 }
59 
60 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){
61     avrcp_create_sdp_record(0, service, service_record_handle, avrcp_target_supports_browsing(supported_features), supported_features, service_name, service_provider_name);
62 }
63 
64 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){
65     if (!callback) return;
66     uint8_t event[8];
67     int pos = 0;
68     event[pos++] = HCI_EVENT_AVRCP_META;
69     event[pos++] = sizeof(event) - 2;
70     event[pos++] = AVRCP_SUBEVENT_OPERATION;
71     little_endian_store_16(event, pos, avrcp_cid);
72     pos += 2;
73     event[pos++] = operation_id;
74     event[pos++] = operands_length;
75     event[pos++] = operand;
76     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
77 }
78 
79 static void avrcp_target_emit_volume_changed(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t absolute_volume){
80     if (!callback) return;
81     uint8_t event[7];
82     int offset = 0;
83     event[offset++] = HCI_EVENT_AVRCP_META;
84     event[offset++] = sizeof(event) - 2;
85     event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED;
86     little_endian_store_16(event, offset, avrcp_cid);
87     offset += 2;
88     event[offset++] = AVRCP_CTYPE_NOTIFY;
89     event[offset++] = absolute_volume;
90     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
91 }
92 
93 static void avrcp_target_emit_respond_vendor_dependent_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t subevent_id){
94     if (!callback) return;
95     uint8_t event[5];
96     int pos = 0;
97     event[pos++] = HCI_EVENT_AVRCP_META;
98     event[pos++] = sizeof(event) - 2;
99     event[pos++] = subevent_id;
100     little_endian_store_16(event, pos, avrcp_cid);
101     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
102 }
103 
104 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){
105     if ((attr_id < 1) || (attr_id > AVRCP_MEDIA_ATTR_COUNT)) return 0;
106     uint16_t attr_value_length = sprintf((char *)(packet+pos+8), "%0" PRIu32, value);
107     big_endian_store_32(packet, pos, attr_id);
108     pos += 4;
109     big_endian_store_16(packet, pos, RFC2978_CHARSET_MIB_UTF8);
110     pos += 2;
111     big_endian_store_16(packet, pos, attr_value_length);
112     pos += 2;
113     return 8 + attr_value_length;
114 }
115 
116 static uint16_t avrcp_target_pack_single_element_attribute_string(uint8_t * packet, 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_to_copy, uint16_t attr_value_size, uint8_t header){
117     if (attr_value_size == 0) return 0;
118     if ((attr_id < 1) || (attr_id > AVRCP_MEDIA_ATTR_COUNT)) return 0;
119     if (header){
120         big_endian_store_32(packet, pos, attr_id);
121         pos += 4;
122         big_endian_store_16(packet, pos, mib_enumid);
123         pos += 2;
124         big_endian_store_16(packet, pos, attr_value_size);
125         pos += 2;
126     }
127     (void)memcpy(packet + pos, attr_value, attr_value_to_copy);
128     pos += attr_value_size;
129     return (header * 8) + attr_value_size;
130 }
131 
132 static int avrcp_target_abort_continue_response(uint16_t cid, avrcp_connection_t * connection){
133     uint16_t pos = 0;
134     l2cap_reserve_packet_buffer();
135     uint8_t * packet = l2cap_get_outgoing_buffer();
136 
137     connection->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
138     connection->command_type    = AVRCP_CTYPE_RESPONSE_ACCEPTED;
139     connection->subunit_type    = AVRCP_SUBUNIT_TYPE_PANEL;
140     connection->subunit_id      = AVRCP_SUBUNIT_ID;
141 
142     packet[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
143     // Profile IDentifier (PID)
144     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
145     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
146 
147     // command_type
148     packet[pos++] = connection->command_type;
149     // subunit_type | subunit ID
150     packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
151     // opcode
152     packet[pos++] = (uint8_t)connection->command_opcode;
153 
154     // company id is 3 bytes long
155     big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
156     pos += 3;
157 
158     packet[pos++] = AVRCP_PDU_ID_REQUEST_ABORT_CONTINUING_RESPONSE;
159 
160     // reserve byte for packet type
161     packet[pos++] = AVRCP_SINGLE_PACKET;
162     big_endian_store_16(packet, pos, 0);
163     pos += 2;
164     return l2cap_send_prepared(cid, pos);
165 }
166 
167 static int avrcp_target_send_now_playing_info(uint16_t cid, avrcp_connection_t * connection){
168     uint16_t pos = 0;
169     l2cap_reserve_packet_buffer();
170     uint8_t * packet = l2cap_get_outgoing_buffer();
171     uint16_t  size   = l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid);
172 
173     packet[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
174     // Profile IDentifier (PID)
175     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
176     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
177 
178     // command_type
179     packet[pos++] = connection->command_type;
180     // subunit_type | subunit ID
181     packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
182     // opcode
183     packet[pos++] = (uint8_t)connection->command_opcode;
184 
185     // company id is 3 bytes long
186     big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
187     pos += 3;
188 
189     packet[pos++] = AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES;
190 
191     // reserve byte for packet type
192     uint8_t pos_packet_type = pos;
193     pos++;
194 
195     uint16_t playing_info_buffer_len_position = pos;
196     pos += 2;
197     // printf("connection->next_attr_id %d \n", connection->next_attr_id);
198     if (connection->next_attr_id == AVRCP_MEDIA_ATTR_NONE){
199         packet[pos_packet_type] = AVRCP_SINGLE_PACKET;
200         connection->packet_type = AVRCP_SINGLE_PACKET;
201         packet[pos++] = count_set_bits_uint32(connection->now_playing_info_attr_bitmap);
202         connection->next_attr_id = AVRCP_MEDIA_ATTR_ALL;
203     }
204     // printf("updated connection->next_attr_id %d, connection->attribute_value_offset %d \n", connection->next_attr_id, connection->attribute_value_offset);
205 
206     uint8_t fragmented = 0;
207     int num_free_bytes = size - pos - 2;
208     uint8_t MAX_NUMBER_ATTR_LEN = 10;
209 
210     while (!fragmented && (num_free_bytes > 0) && (connection->next_attr_id <= AVRCP_MEDIA_ATTR_SONG_LENGTH_MS)){
211         avrcp_media_attribute_id_t attr_id = connection->next_attr_id;
212         int attr_index = attr_id - 1;
213 
214         if (connection->now_playing_info_attr_bitmap & (1 << attr_id)){
215             int num_written_bytes = 0;
216             int num_bytes_to_write = 0;
217             switch (attr_id){
218                 case AVRCP_MEDIA_ATTR_ALL:
219                 case AVRCP_MEDIA_ATTR_NONE:
220                     break;
221                 case AVRCP_MEDIA_ATTR_TRACK:
222                     num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN;
223                     if (num_free_bytes >= num_bytes_to_write){
224                         num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->track_nr);
225                         break;
226                     }
227                     fragmented = 1;
228                     connection->attribute_value_offset = 0;
229                     break;
230                 case AVRCP_MEDIA_ATTR_TOTAL_NUM_ITEMS:
231                     num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN;
232                     if (num_free_bytes >= num_bytes_to_write){
233                         num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->total_tracks);
234                         break;
235                     }
236                     fragmented = 1;
237                     connection->attribute_value_offset = 0;
238                     break;
239                 case AVRCP_MEDIA_ATTR_SONG_LENGTH_MS:
240                     num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN;
241                     if (num_free_bytes >= num_bytes_to_write){
242                         num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->song_length_ms);
243                         break;
244                     }
245                     fragmented = 1;
246                     connection->attribute_value_offset = 0;
247                     break;
248                 default:{
249                     uint8_t   header = (connection->attribute_value_offset == 0);
250                     uint8_t * attr_value =     (uint8_t *) (connection->now_playing_info[attr_index].value + connection->attribute_value_offset);
251                     uint16_t  attr_value_len = connection->now_playing_info[attr_index].len - connection->attribute_value_offset;
252 
253                     num_bytes_to_write = attr_value_len + (header * AVRCP_ATTR_HEADER_LEN);
254                     if (num_bytes_to_write <= num_free_bytes){
255                         connection->attribute_value_offset = 0;
256                         num_written_bytes = num_bytes_to_write;
257                         avrcp_target_pack_single_element_attribute_string(packet, pos, RFC2978_CHARSET_MIB_UTF8, attr_id, attr_value, attr_value_len, connection->now_playing_info[attr_index].len, header);
258                         break;
259                     }
260                     fragmented = 1;
261                     num_written_bytes = num_free_bytes;
262                     attr_value_len = num_free_bytes - (header * AVRCP_ATTR_HEADER_LEN);
263                     avrcp_target_pack_single_element_attribute_string(packet, pos, RFC2978_CHARSET_MIB_UTF8, attr_id, attr_value, attr_value_len, connection->now_playing_info[attr_index].len, header);
264                     connection->attribute_value_offset += attr_value_len;
265                     break;
266                 }
267             }
268             pos += num_written_bytes;
269             num_free_bytes -= num_written_bytes;
270         }
271         if (!fragmented){
272             // C++ compatible version of connection->next_attr_id++
273             connection->next_attr_id = (avrcp_media_attribute_id_t) (((int) connection->next_attr_id) + 1);
274         }
275     }
276 
277     if (fragmented){
278         switch (connection->packet_type){
279             case AVRCP_SINGLE_PACKET:
280                 connection->packet_type = AVRCP_START_PACKET;
281                 break;
282             default:
283                 connection->packet_type = AVRCP_CONTINUE_PACKET;
284                 break;
285         }
286     } else {
287         if (connection->next_attr_id >= AVRCP_MEDIA_ATTR_SONG_LENGTH_MS){ // DONE
288             if (connection->packet_type != AVRCP_SINGLE_PACKET){
289                 connection->packet_type = AVRCP_END_PACKET;
290             }
291         }
292     }
293     packet[pos_packet_type] = connection->packet_type;
294     // store attr value length
295     big_endian_store_16(packet, playing_info_buffer_len_position, pos - playing_info_buffer_len_position - 2);
296     return l2cap_send_prepared(cid, size);
297 }
298 
299 
300 
301 static int avrcp_target_send_response(uint16_t cid, avrcp_connection_t * connection){
302     int pos = 0;
303     l2cap_reserve_packet_buffer();
304     uint8_t * packet = l2cap_get_outgoing_buffer();
305 
306     // transport header
307     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
308 
309     // TODO: check for fragmentation
310     connection->packet_type = AVRCP_SINGLE_PACKET;
311 
312     packet[pos++] = (connection->transaction_label << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
313     // Profile IDentifier (PID)
314     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
315     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
316     // command_type
317     packet[pos++] = connection->command_type;
318     // subunit_type | subunit ID
319     packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
320     // opcode
321     packet[pos++] = (uint8_t)connection->command_opcode;
322 
323     // if (connection->command_opcode  == AVRCP_CMD_OPCODE_VENDOR_DEPENDENT){
324     //     // company id is 3 bytes long
325     //     big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
326     //     pos += 3;
327     // }
328     // operands
329     (void)memcpy(packet + pos, connection->cmd_operands,
330                  connection->cmd_operands_length);
331     pos += connection->cmd_operands_length;
332     // printf(" pos to send %d\n", pos);
333     // printf_hexdump(packet, pos);
334 
335     connection->wait_to_send = 0;
336     return l2cap_send_prepared(cid, pos);
337 }
338 
339 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){
340     // AVRCP_CTYPE_RESPONSE_REJECTED
341     connection->command_type = AVRCP_CTYPE_RESPONSE_ACCEPTED;
342     connection->subunit_type = subunit_type;
343     connection->subunit_id =   subunit_id;
344     connection->command_opcode = opcode;
345     // company id is 3 bytes long
346     int pos = connection->cmd_operands_length;
347     connection->cmd_operands[pos++] = pdu_id;
348     connection->cmd_operands[pos++] = 0;
349     // param length
350     big_endian_store_16(connection->cmd_operands, pos, 1);
351     pos += 2;
352     connection->cmd_operands[pos++] = status;
353     connection->cmd_operands_length = pos;
354     connection->accept_response = 1;
355     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
356     return ERROR_CODE_SUCCESS;
357 }
358 
359 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){
360     // AVRCP_CTYPE_RESPONSE_REJECTED
361     connection->command_type = AVRCP_CTYPE_RESPONSE_REJECTED;
362     connection->subunit_type = subunit_type;
363     connection->subunit_id =   subunit_id;
364     connection->command_opcode = opcode;
365     // company id is 3 bytes long
366     int pos = connection->cmd_operands_length;
367     connection->cmd_operands[pos++] = pdu_id;
368     connection->cmd_operands[pos++] = 0;
369     // param length
370     big_endian_store_16(connection->cmd_operands, pos, 1);
371     pos += 2;
372     connection->cmd_operands[pos++] = status;
373     connection->cmd_operands_length = pos;
374     connection->state = AVCTP_W2_SEND_RESPONSE;
375     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
376     return ERROR_CODE_SUCCESS;
377 }
378 
379 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){
380     connection->command_type = AVRCP_CTYPE_RESPONSE_NOT_IMPLEMENTED;
381     connection->subunit_type = subunit_type;
382     connection->subunit_id =   subunit_id;
383     connection->command_opcode = opcode;
384 
385     // company id is 3 bytes long
386     int pos = connection->cmd_operands_length;
387     connection->cmd_operands[pos++] = pdu_id;
388     connection->cmd_operands[pos++] = 0;
389     // param length
390     big_endian_store_16(connection->cmd_operands, pos, 1);
391     pos += 2;
392     connection->cmd_operands[pos++] = event_id;
393     connection->cmd_operands_length = pos;
394 
395     connection->state = AVCTP_W2_SEND_RESPONSE;
396     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
397     return ERROR_CODE_SUCCESS;
398 }
399 
400 static uint8_t avrcp_target_response_vendor_dependent_interim(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id,
401     avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id, uint8_t event_id, const uint8_t * value, uint16_t value_len){
402     connection->command_type = AVRCP_CTYPE_RESPONSE_INTERIM;
403     connection->subunit_type = subunit_type;
404     connection->subunit_id =   subunit_id;
405     connection->command_opcode = opcode;
406 
407     // company id is 3 bytes long
408     int pos = connection->cmd_operands_length;
409     connection->cmd_operands[pos++] = pdu_id;
410     connection->cmd_operands[pos++] = 0;
411     // param length
412     big_endian_store_16(connection->cmd_operands, pos, 1 + value_len);
413     pos += 2;
414     connection->cmd_operands[pos++] = event_id;
415     if (value && (value_len > 0)){
416         (void)memcpy(connection->cmd_operands + pos, value, value_len);
417         pos += value_len;
418     }
419     connection->cmd_operands_length = pos;
420     connection->state = AVCTP_W2_SEND_RESPONSE;
421     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
422     return ERROR_CODE_SUCCESS;
423 }
424 
425 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){
426     connection->command_type = AVRCP_CTYPE_RESPONSE_INTERIM;
427     connection->subunit_type = subunit_type;
428     connection->subunit_id =   subunit_id;
429     connection->command_opcode = opcode;
430 
431     // company id is 3 bytes long
432     int pos = connection->cmd_operands_length;
433     connection->cmd_operands[pos++] = pdu_id;
434     connection->cmd_operands[pos++] = 0;
435     // param length
436     big_endian_store_16(connection->cmd_operands, pos, 5);
437     pos += 2;
438     connection->cmd_operands[pos++] = AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED;
439     big_endian_read_16( &connection->cmd_operands[pos], connection->addressed_player_id);
440     pos += 2;
441     big_endian_read_16( &connection->cmd_operands[pos], connection->uid_counter);
442     pos += 2;
443 
444     connection->cmd_operands_length = pos;
445     connection->state = AVCTP_W2_SEND_RESPONSE;
446     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
447     return ERROR_CODE_SUCCESS;
448 }
449 
450 
451 // static uint8_t avrcp_target_response_vendor_dependent_changed(avrcp_connection_t * connection, avrcp_pdu_id_t pdu_id, uint8_t event_id){
452 //     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
453 //     connection->command_type = AVRCP_CTYPE_RESPONSE_CHANGED_STABLE;
454 //     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
455 //     connection->subunit_id = AVRCP_SUBUNIT_ID;
456 
457 //     // company id is 3 bytes long
458 //     int pos = connection->cmd_operands_length;
459 //     connection->cmd_operands[pos++] = pdu_id;
460 //     connection->cmd_operands[pos++] = 0;
461 //     // param length
462 //     big_endian_store_16(connection->cmd_operands, pos, 1);
463 //     pos += 2;
464 //     connection->cmd_operands[pos++] = event_id;
465 //     connection->cmd_operands_length = pos;
466 
467 //     connection->state = AVCTP_W2_SEND_RESPONSE;
468 //     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
469 //     return ERROR_CODE_SUCCESS;
470 // }
471 
472 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){
473     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
474     if (!connection){
475         log_error("Could not find a connection.");
476         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
477     }
478     connection->command_type = cmd_type;
479     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
480     connection->subunit_id =   AVRCP_SUBUNIT_ID;
481     connection->command_opcode = AVRCP_CMD_OPCODE_PASS_THROUGH;
482 
483     int pos = 0;
484     connection->cmd_operands[pos++] = opid;
485     connection->cmd_operands[pos++] = operands_length;
486     if (operands_length == 1){
487         connection->cmd_operands[pos++] = operand;
488     }
489     connection->cmd_operands_length = pos;
490 
491     connection->state = AVCTP_W2_SEND_RESPONSE;
492     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
493     return ERROR_CODE_SUCCESS;
494 }
495 
496 uint8_t avrcp_target_operation_rejected(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){
497     return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_REJECTED, opid, operands_length, operand);
498 }
499 
500 uint8_t avrcp_target_operation_accepted(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){
501     return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand);
502 }
503 
504 uint8_t avrcp_target_operation_not_implemented(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){
505     return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand);
506 }
507 
508 void avrcp_target_set_unit_info(uint16_t avrcp_cid, avrcp_subunit_type_t unit_type, uint32_t company_id){
509     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
510     if (!connection){
511         log_error("avrcp_target_operation_reject: could not find a connection.");
512         return;
513     }
514     connection->unit_type = unit_type;
515     connection->company_id = company_id;
516 }
517 
518 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){
519     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
520     if (!connection){
521         log_error("avrcp_target_operation_reject: could not find a connection.");
522         return;
523     }
524     connection->subunit_info_type = subunit_type;
525     connection->subunit_info_data = subunit_info_data;
526     connection->subunit_info_data_size = subunit_info_data_size;
527 }
528 
529 static uint8_t avrcp_target_unit_info(avrcp_connection_t * connection){
530     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
531 
532     uint8_t unit = 0;
533     connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
534     connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique
535     connection->subunit_id =   AVRCP_SUBUNIT_ID_IGNORE;
536     connection->command_opcode = AVRCP_CMD_OPCODE_UNIT_INFO;
537 
538     connection->cmd_operands_length = 5;
539     connection->cmd_operands[0] = 0x07;
540     connection->cmd_operands[1] = (connection->unit_type << 4) | unit;
541     // company id is 3 bytes long
542     big_endian_store_32(connection->cmd_operands, 2, connection->company_id);
543 
544     connection->state = AVCTP_W2_SEND_RESPONSE;
545     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
546     return ERROR_CODE_SUCCESS;
547 }
548 
549 
550 static uint8_t avrcp_target_subunit_info(avrcp_connection_t * connection, uint8_t offset){
551     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
552     if ((offset - 4) > connection->subunit_info_data_size) return AVRCP_STATUS_INVALID_PARAMETER;
553 
554     connection->command_opcode = AVRCP_CMD_OPCODE_SUBUNIT_INFO;
555     connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
556     connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique
557     connection->subunit_id =   AVRCP_SUBUNIT_ID_IGNORE;
558     // printf("avrcp_target_subunit_info  subunit_type %d\n", connection->subunit_type);
559 
560     uint8_t page = offset / 4;
561     uint8_t extension_code = 7;
562     connection->cmd_operands_length = 5;
563     connection->cmd_operands[0] = (page << 4) | extension_code;
564 
565     (void)memcpy(connection->cmd_operands + 1,
566                  connection->subunit_info_data + offset, 4);
567 
568     connection->state = AVCTP_W2_SEND_RESPONSE;
569     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
570     return ERROR_CODE_SUCCESS;
571 }
572 
573 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){
574     *out_connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
575     if (!*out_connection){
576         log_error("avrcp tartget: could not find a connection.");
577         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
578     }
579 
580     if ((*out_connection)->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
581     (*out_connection)->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
582     (*out_connection)->command_type    = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
583     (*out_connection)->subunit_type    = AVRCP_SUBUNIT_TYPE_PANEL;
584     (*out_connection)->subunit_id      = AVRCP_SUBUNIT_ID;
585 
586     (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = pdu_id;
587     // reserved
588     (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = 0;
589     // param length
590     big_endian_store_16((*out_connection)->cmd_operands, (*out_connection)->cmd_operands_length, param_length);
591     (*out_connection)->cmd_operands_length += 2;
592     return ERROR_CODE_SUCCESS;
593 }
594 
595 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){
596     avrcp_connection_t * connection = NULL;
597     uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_CAPABILITIES, 2+size);
598     if (status != ERROR_CODE_SUCCESS) return status;
599 
600     connection->cmd_operands[connection->cmd_operands_length++] = capability_id;
601     connection->cmd_operands[connection->cmd_operands_length++] = capabilities_num;
602     (void)memcpy(connection->cmd_operands + connection->cmd_operands_length,
603                  capabilities, size);
604     connection->cmd_operands_length += size;
605 
606     connection->state = AVCTP_W2_SEND_RESPONSE;
607     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
608     return ERROR_CODE_SUCCESS;
609 }
610 
611 uint8_t avrcp_target_supported_events(uint16_t avrcp_cid, uint8_t capabilities_num, uint8_t * capabilities, uint8_t size){
612     return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT, capabilities_num, capabilities, size);
613 }
614 
615 uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t capabilities_num, uint8_t * capabilities, uint8_t size ){
616     return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY, capabilities_num, capabilities, size);
617 }
618 
619 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){
620     avrcp_connection_t * connection = NULL;
621     uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_PLAY_STATUS, 11);
622     if (status != ERROR_CODE_SUCCESS) return status;
623 
624     big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_length_ms);
625     connection->cmd_operands_length += 4;
626     big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_position_ms);
627     connection->cmd_operands_length += 4;
628     connection->cmd_operands[connection->cmd_operands_length++] = play_status;
629 
630     connection->state = AVCTP_W2_SEND_RESPONSE;
631     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
632     return ERROR_CODE_SUCCESS;
633 }
634 
635 static uint8_t avrcp_target_now_playing_info(avrcp_connection_t * connection){
636     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
637     connection->now_playing_info_response = 1;
638     connection->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
639     connection->command_type    = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE;
640     connection->subunit_type    = AVRCP_SUBUNIT_TYPE_PANEL;
641     connection->subunit_id      = AVRCP_SUBUNIT_ID;
642 
643     connection->state = AVCTP_W2_SEND_RESPONSE;
644     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
645     return ERROR_CODE_SUCCESS;
646 }
647 
648 static uint8_t avrcp_target_store_media_attr(avrcp_connection_t * connection, avrcp_media_attribute_id_t attr_id, const char * value){
649     int index = attr_id - 1;
650     if (!value) return AVRCP_STATUS_INVALID_PARAMETER;
651     connection->now_playing_info[index].value = (uint8_t*)value;
652     connection->now_playing_info[index].len   = strlen(value);
653     // printf("store %lu bytes, %s\n",  strlen(value), value);
654     return ERROR_CODE_SUCCESS;
655 }
656 
657 uint8_t avrcp_target_set_playback_status(uint16_t avrcp_cid, avrcp_playback_status_t playback_status){
658     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
659     if (!connection){
660         log_error("avrcp_unit_info: could not find a connection.");
661         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
662     }
663     if (connection->playback_status == playback_status) return ERROR_CODE_SUCCESS;
664 
665     connection->playback_status = playback_status;
666     connection->playback_status_changed = 1;
667     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
668     return ERROR_CODE_SUCCESS;
669 }
670 
671 void avrcp_target_set_now_playing_info(uint16_t avrcp_cid, const avrcp_track_t * current_track, uint16_t total_tracks){
672     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
673     if (!connection){
674         log_error("avrcp_unit_info: could not find a connection. cid 0x%02x\n", avrcp_cid);
675         return;
676     }
677     if (!current_track){
678         connection->track_selected = 0;
679         connection->playback_status = AVRCP_PLAYBACK_STATUS_ERROR;
680         return;
681     }
682     (void)memcpy(connection->track_id, current_track->track_id, 8);
683     connection->song_length_ms = current_track->song_length_ms;
684     connection->track_nr = current_track->track_nr;
685     connection->total_tracks = total_tracks;
686     avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_TITLE, current_track->title);
687     avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_ARTIST, current_track->artist);
688     avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_ALBUM, current_track->album);
689     avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_GENRE, current_track->genre);
690     connection->track_selected = 1;
691 
692     if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED)) {
693         connection->track_changed = 1;
694         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
695     }
696     return;
697 }
698 
699 uint8_t avrcp_target_track_changed(uint16_t avrcp_cid, uint8_t * track_id){
700     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
701     if (!connection){
702         log_error("avrcp_target_track_changed: could not find connection.");
703         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
704     }
705     if (!track_id) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
706 
707     if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED)) {
708         connection->track_changed = 1;
709         (void)memcpy(connection->track_id, track_id, 8);
710         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
711     }
712     return ERROR_CODE_SUCCESS;
713 }
714 
715 uint8_t avrcp_target_playing_content_changed(uint16_t avrcp_cid){
716     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
717     if (!connection){
718         log_error("avrcp_target_playing_content_changed: could not find a connection.");
719         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
720     }
721     if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED)) {
722         connection->playing_content_changed = 1;
723         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
724     }
725     return ERROR_CODE_SUCCESS;
726 }
727 
728 uint8_t avrcp_target_addressed_player_changed(uint16_t avrcp_cid, uint16_t player_id, uint16_t uid_counter){
729     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
730     if (!connection){
731         log_error("avrcp_unit_info: could not find a connection.");
732         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
733     }
734     if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED)) {
735         // printf("send AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED\n");
736         // connection->addressed_player_changed = 1;
737         connection->uid_counter = uid_counter;
738         connection->addressed_player_id = player_id;
739         // avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
740     }
741     return ERROR_CODE_SUCCESS;
742 }
743 
744 uint8_t avrcp_target_battery_status_changed(uint16_t avrcp_cid, avrcp_battery_status_t battery_status){
745     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
746     if (!connection){
747         log_error("avrcp_unit_info: could not find a connection.");
748         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
749     }
750     if (connection->battery_status == battery_status) return ERROR_CODE_SUCCESS;
751     if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED)) {
752         connection->battery_status = battery_status;
753         connection->battery_status_changed = 1;
754         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
755     }
756     return ERROR_CODE_SUCCESS;
757 }
758 
759 uint8_t avrcp_target_volume_changed(uint16_t avrcp_cid, uint8_t volume_percentage){
760     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
761     if (!connection){
762         log_error("avrcp_unit_info: could not find a connection.");
763         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
764     }
765     // if (connection->volume_percentage == volume_percentage) return ERROR_CODE_SUCCESS;
766     if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED )) {
767         connection->volume_percentage = volume_percentage;
768         connection->notify_volume_percentage_changed = 1;
769         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
770     }
771     return ERROR_CODE_SUCCESS;
772 }
773 
774 static void avrcp_target_set_transaction_label_for_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification, uint8_t transaction_label){
775     if (notification > AVRCP_NOTIFICATION_EVENT_MAX_VALUE) return;
776     connection->notifications_transaction_label[notification] = transaction_label;
777 }
778 
779 static uint8_t avrcp_target_get_transaction_label_for_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification){
780     if (notification > AVRCP_NOTIFICATION_EVENT_MAX_VALUE) return 0;
781     return connection->notifications_transaction_label[notification];
782 }
783 
784 static uint8_t * avrcp_get_company_id(uint8_t *packet, uint16_t size){
785     UNUSED(size);
786     return packet + 6;
787 }
788 
789 static uint8_t * avrcp_get_pdu(uint8_t *packet, uint16_t size){
790     UNUSED(size);
791     return packet + 9;
792 }
793 
794 static uint8_t avrcp_is_receive_pass_through_cmd(uint8_t operation_id){
795     return operation_id & 0x80;
796 }
797 
798 static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){
799     UNUSED(connection);
800     UNUSED(packet);
801     UNUSED(size);
802 
803     // uint8_t opcode;
804     uint16_t pid = 0;
805     uint8_t transport_header = packet[0];
806     connection->transaction_label = transport_header >> 4;
807     // uint8_t frame_type = (transport_header & 0x03) >> 1;
808     avrcp_packet_type_t packet_type = (avrcp_packet_type_t) ((transport_header & 0x0F) >> 2);
809     switch (packet_type){
810         case AVRCP_SINGLE_PACKET:
811             pid =  big_endian_read_16(packet, 1);
812             break;
813         case AVRCP_START_PACKET:
814             pid =  big_endian_read_16(packet, 2);
815             break;
816         default:
817             break;
818     }
819 
820     switch (packet_type){
821         case AVRCP_SINGLE_PACKET:
822         case AVRCP_START_PACKET:
823             if (pid != BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL){
824                 log_info("Invalid pid 0x%02x, expected 0x%02x", connection->invalid_pid, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL);
825                 connection->reject_transport_header = 1;
826                 connection->invalid_pid = pid;
827                 connection->transport_header = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2 ) | (AVRCP_RESPONSE_FRAME << 1) | 1;
828                 connection->state = AVCTP_W2_SEND_RESPONSE;
829                 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
830                 return;
831             }
832             break;
833         default:
834             break;
835     }
836 
837     // avrcp_command_type_t ctype = (avrcp_command_type_t) packet[3];
838     // uint8_t byte_value = packet[4];
839     avrcp_subunit_type_t subunit_type = (avrcp_subunit_type_t) (packet[4] >> 3);
840     avrcp_subunit_id_t   subunit_id   = (avrcp_subunit_id_t) (packet[4] & 0x07);
841     // opcode = packet[pos++];
842     // printf("    Transport header 0x%02x (transaction_label %d, packet_type %d, frame_type %d, ipid %d), pid 0x%4x\n",
843     //     transport_header, transaction_label, packet_type, frame_type, ipid, pid);
844     // printf_hexdump(packet+pos, size-pos);
845 
846     avrcp_command_opcode_t opcode = (avrcp_command_opcode_t) avrcp_cmd_opcode(packet,size);
847     uint8_t * company_id = avrcp_get_company_id(packet, size);
848     uint8_t * pdu = avrcp_get_pdu(packet, size);
849     // uint16_t param_length = big_endian_read_16(pdu, 2);
850 
851     int pos = 4;
852     uint16_t length;
853     avrcp_pdu_id_t   pdu_id;
854     connection->cmd_operands_length = 0;
855 
856     switch (opcode){
857         case AVRCP_CMD_OPCODE_UNIT_INFO:
858             avrcp_target_unit_info(connection);
859             break;
860         case AVRCP_CMD_OPCODE_SUBUNIT_INFO:{
861             uint8_t offset =  4 * (packet[pos+2]>>4);
862             avrcp_target_subunit_info(connection, offset);
863             break;
864         }
865         case AVRCP_CMD_OPCODE_PASS_THROUGH:{
866             log_info("AVRCP_OPERATION_ID 0x%02x, operands length %d, operand %d", packet[6], packet[7], packet[8]);
867             avrcp_operation_id_t operation_id = (avrcp_operation_id_t) packet[6];
868 
869             if (avrcp_is_receive_pass_through_cmd(operation_id)){
870                 operation_id = (avrcp_operation_id_t) (packet[6] & 0x7F);
871                 avrcp_target_operation_accepted(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
872                 break;
873             }
874 
875             switch (operation_id){
876                 case AVRCP_OPERATION_ID_PLAY:
877                 case AVRCP_OPERATION_ID_PAUSE:
878                 case AVRCP_OPERATION_ID_STOP:
879                 case AVRCP_OPERATION_ID_VOLUME_UP:
880                 case AVRCP_OPERATION_ID_VOLUME_DOWN:
881                 case AVRCP_OPERATION_ID_REWIND:
882                 case AVRCP_OPERATION_ID_FAST_FORWARD:
883                 case AVRCP_OPERATION_ID_FORWARD:
884                 case AVRCP_OPERATION_ID_BACKWARD:
885                 case AVRCP_OPERATION_ID_SKIP:
886                 case AVRCP_OPERATION_ID_MUTE:
887                 case AVRCP_OPERATION_ID_CHANNEL_UP:
888                 case AVRCP_OPERATION_ID_CHANNEL_DOWN:
889                 case AVRCP_OPERATION_ID_SELECT:
890                 case AVRCP_OPERATION_ID_UP:
891                 case AVRCP_OPERATION_ID_DOWN:
892                 case AVRCP_OPERATION_ID_LEFT:
893                 case AVRCP_OPERATION_ID_RIGHT:
894                 case AVRCP_OPERATION_ID_ROOT_MENU:
895                     avrcp_target_operation_accepted(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
896                     avrcp_target_emit_operation(avrcp_target_context.avrcp_callback, connection->avrcp_cid, operation_id, packet[7], packet[8]);
897                     break;
898                 case AVRCP_OPERATION_ID_UNDEFINED:
899                     avrcp_target_operation_not_implemented(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
900                     return;
901                 default:
902                     avrcp_target_operation_not_implemented(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]);
903                     return;
904             }
905             break;
906         }
907 
908         case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT:
909             pdu_id = (avrcp_pdu_id_t) pdu[0];
910             // 1 - reserved
911             // 2-3 param length,
912             length = big_endian_read_16(pdu, 2);
913             (void)memcpy(connection->cmd_operands, company_id, 3);
914             connection->cmd_operands_length = 3;
915             switch (pdu_id){
916                 case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:{
917                     if (length == 0){
918                         avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PLAYER_ID);
919                         break;
920                     }
921                     avrcp_target_response_accept(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_SUCCESS);
922                     break;
923                 }
924                 case AVRCP_PDU_ID_GET_CAPABILITIES:{
925                     avrcp_capability_id_t capability_id = (avrcp_capability_id_t) pdu[pos];
926                     switch (capability_id){
927                         case AVRCP_CAPABILITY_ID_EVENT:
928                             avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_EVENT_IDS_QUERY);
929                             break;
930                         case AVRCP_CAPABILITY_ID_COMPANY:
931                             avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_COMPANY_IDS_QUERY);
932                             break;
933                         default:
934                             avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
935                             break;
936                     }
937                     break;
938                 }
939                 case AVRCP_PDU_ID_GET_PLAY_STATUS:
940                     avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_PLAY_STATUS_QUERY);
941                     break;
942                 case AVRCP_PDU_ID_REQUEST_ABORT_CONTINUING_RESPONSE:
943                     connection->cmd_operands[0] = pdu[4];
944                     connection->abort_continue_response = 1;
945                     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
946                     break;
947                 case AVRCP_PDU_ID_REQUEST_CONTINUING_RESPONSE:
948                     if (pdu[4] != AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES){
949                         avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND);
950                         return;
951                     }
952                     connection->now_playing_info_response = 1;
953                     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
954                     break;
955                 case AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES:{
956                     uint8_t play_identifier[8];
957                     memset(play_identifier, 0, 8);
958                     if (memcmp(pdu+pos, play_identifier, 8) != 0) {
959                         avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
960                         return;
961                     }
962                     pos += 8;
963                     uint8_t attribute_count = pdu[pos++];
964                     // printf("AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES attribute count %d\n", attribute_count);
965                     connection->next_attr_id = AVRCP_MEDIA_ATTR_NONE;
966                     if (!attribute_count){
967                         connection->now_playing_info_attr_bitmap = 0xFE;
968                     } else {
969                         int i;
970                         connection->now_playing_info_attr_bitmap = 0;
971                         for (i=0; i < attribute_count; i++){
972                             uint16_t attr_id = big_endian_read_16(pdu, pos);
973                             pos += 2;
974                             connection->now_playing_info_attr_bitmap |= (1 << attr_id);
975                         }
976                     }
977                     log_info("now_playing_info_attr_bitmap 0x%02x", connection->now_playing_info_attr_bitmap);
978                     avrcp_target_now_playing_info(connection);
979                     break;
980                 }
981                 case AVRCP_PDU_ID_REGISTER_NOTIFICATION:{
982                     // 0 - pdu id
983                     // 1 - reserved
984                     // 2-3 param length
985                     avrcp_notification_event_id_t event_id = (avrcp_notification_event_id_t) pdu[4];
986                     uint16_t event_mask = (1 << event_id);
987                     avrcp_target_set_transaction_label_for_notification(connection, event_id, connection->transaction_label);
988 
989                     switch (event_id){
990                         case AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED:
991                             connection->notifications_enabled |= event_mask;
992                             if (connection->track_selected){
993                                 avrcp_target_response_vendor_dependent_interim(connection, subunit_type, subunit_id, opcode, pdu_id, event_id, AVRCP_NOTIFICATION_TRACK_SELECTED, 8);
994                             } else {
995                                 avrcp_target_response_vendor_dependent_interim(connection, subunit_type, subunit_id, opcode, pdu_id, event_id, AVRCP_NOTIFICATION_TRACK_NOT_SELECTED, 8);
996                             }
997                             break;
998                         case AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED:
999                             connection->notifications_enabled |= event_mask;
1000                             avrcp_target_response_vendor_dependent_interim(connection, subunit_type, subunit_id, opcode, pdu_id, event_id, (const uint8_t *)&connection->playback_status, 1);
1001                             break;
1002                         case AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED:
1003                             connection->notifications_enabled |= event_mask;
1004                             avrcp_target_response_vendor_dependent_interim(connection, subunit_type, subunit_id, opcode, pdu_id, event_id, NULL, 0);
1005                             break;
1006                         case AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED:
1007                             connection->notify_volume_percentage_changed = 0;
1008                             connection->notifications_enabled |= event_mask;
1009                             avrcp_target_response_vendor_dependent_interim(connection, subunit_type, subunit_id, opcode, pdu_id, event_id, (const uint8_t *)&connection->volume_percentage, 1);
1010                             break;
1011                         case AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED:
1012                             connection->notifications_enabled |= event_mask;
1013                             avrcp_target_response_vendor_dependent_interim(connection, subunit_type, subunit_id, opcode, pdu_id, event_id, (const uint8_t *)&connection->battery_status, 1);
1014                             break;
1015                         case AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED:
1016                         case AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
1017                         case AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED:
1018                             avrcp_target_response_not_implemented(connection, subunit_type, subunit_id, opcode, pdu_id, event_id);
1019                             return;
1020                         case AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED:
1021                             connection->notifications_enabled |= event_mask;
1022                             avrcp_target_response_addressed_player_changed_interim(connection, subunit_type, subunit_id, opcode, pdu_id);
1023                             return;
1024                         default:
1025                             avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER);
1026                             return;
1027                     }
1028                     break;
1029                 }
1030                 case AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME: {
1031                     if (length != 1){
1032                         avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND);
1033                         break;
1034                     }
1035 
1036                     uint8_t absolute_volume = pdu[4];
1037                     if (absolute_volume < 0x80){
1038                         connection->volume_percentage = absolute_volume;
1039                     }
1040                     avrcp_target_response_accept(connection, subunit_type, subunit_id, opcode, pdu_id, connection->volume_percentage);
1041                     avrcp_target_emit_volume_changed(avrcp_target_context.avrcp_callback, connection->avrcp_cid, connection->volume_percentage);
1042                     // avrcp_target_volume_changed(connection->avrcp_cid, connection->volume_percentage);
1043                     break;
1044                 }
1045                 default:
1046                     log_info("AVRCP target: unhandled pdu id 0x%02x", pdu_id);
1047                     avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND);
1048                     break;
1049             }
1050             break;
1051         default:
1052             log_info("AVRCP target: opcode 0x%02x not implemented", avrcp_cmd_opcode(packet,size));
1053             break;
1054     }
1055 }
1056 
1057 #if 0
1058 static int avrcp_target_send_addressed_player_changed_notification(uint16_t cid, avrcp_connection_t * connection, uint16_t uid, uint16_t uid_counter){
1059     if (!connection){
1060         log_error("avrcp tartget: could not find a connection.");
1061         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1062     }
1063     connection->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
1064     connection->command_type    = AVRCP_CTYPE_RESPONSE_CHANGED_STABLE;
1065     connection->subunit_type    = AVRCP_SUBUNIT_TYPE_PANEL;
1066     connection->subunit_id      = AVRCP_SUBUNIT_ID;
1067 
1068     uint16_t pos = 0;
1069     l2cap_reserve_packet_buffer();
1070     uint8_t * packet = l2cap_get_outgoing_buffer();
1071 
1072     connection->packet_type = AVRCP_SINGLE_PACKET;
1073     packet[pos++] = (connection->transaction_label << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
1074     // Profile IDentifier (PID)
1075     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
1076     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
1077 
1078     // command_type
1079     packet[pos++] = connection->command_type;
1080     // subunit_type | subunit ID
1081     packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
1082     // opcode
1083     packet[pos++] = (uint8_t)connection->command_opcode;
1084 
1085     // company id is 3 bytes long
1086     big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
1087     pos += 3;
1088 
1089     packet[pos++] = AVRCP_PDU_ID_REGISTER_NOTIFICATION;
1090     packet[pos++] = 0;
1091     big_endian_store_16(packet, pos, 5);
1092     pos += 2;
1093     packet[pos++] = AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED;
1094     big_endian_store_16(packet, pos, uid);
1095     pos += 2;
1096     big_endian_store_16(packet, pos, uid_counter);
1097     pos += 2;
1098 
1099     connection->wait_to_send = 0;
1100     return l2cap_send_prepared(cid, pos);
1101 }
1102 #endif
1103 
1104 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){
1105     if (!connection){
1106         log_error("avrcp tartget: could not find a connection.");
1107         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1108     }
1109 
1110     connection->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
1111     connection->command_type    = AVRCP_CTYPE_RESPONSE_CHANGED_STABLE;
1112     connection->subunit_type    = AVRCP_SUBUNIT_TYPE_PANEL;
1113     connection->subunit_id      = AVRCP_SUBUNIT_ID;
1114     connection->transaction_label = avrcp_target_get_transaction_label_for_notification(connection, notification_id);
1115 
1116     uint16_t pos = 0;
1117     l2cap_reserve_packet_buffer();
1118     uint8_t * packet = l2cap_get_outgoing_buffer();
1119     uint16_t  size   = l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid);
1120 
1121     connection->packet_type = AVRCP_SINGLE_PACKET;
1122     packet[pos++] = (connection->transaction_label << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
1123     // Profile IDentifier (PID)
1124     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
1125     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
1126 
1127     // command_type
1128     packet[pos++] = connection->command_type;
1129     // subunit_type | subunit ID
1130     packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
1131     // opcode
1132     packet[pos++] = (uint8_t)connection->command_opcode;
1133 
1134     // company id is 3 bytes long
1135     big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID);
1136     pos += 3;
1137 
1138     packet[pos++] = AVRCP_PDU_ID_REGISTER_NOTIFICATION;
1139     packet[pos++] = 0;
1140     uint16_t remainig_outgoing_buffer_size = size - pos - 2;
1141 
1142     uint16_t caped_value_len = btstack_min(value_len + 1, remainig_outgoing_buffer_size);
1143     big_endian_store_16(packet, pos, caped_value_len);
1144     pos += 2;
1145     packet[pos++] = notification_id;
1146     (void)memcpy(packet + pos, value, caped_value_len - 1);
1147     pos += caped_value_len - 1;
1148     connection->wait_to_send = 0;
1149     return l2cap_send_prepared(cid, pos);
1150 }
1151 
1152 static void avrcp_target_reset_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification_id){
1153     if (!connection){
1154         log_error("avrcp tartget: could not find a connection.");
1155         return;
1156     }
1157     connection->notifications_enabled &= ~(1 << notification_id);
1158     connection->command_opcode  = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
1159     avrcp_target_set_transaction_label_for_notification(connection, notification_id, 0);
1160 }
1161 
1162 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1163     avrcp_connection_t * connection;
1164     switch (packet_type) {
1165         case L2CAP_DATA_PACKET:
1166             connection = get_avrcp_connection_for_l2cap_signaling_cid(AVRCP_TARGET, channel);
1167             if (!connection) break;
1168             avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size);
1169             break;
1170         case HCI_EVENT_PACKET:
1171             switch (hci_event_packet_get_type(packet)){
1172                 case HCI_EVENT_AVRCP_META:
1173                     // forward to app
1174                     (*avrcp_target_context.avrcp_callback)(packet_type, channel, packet, size);
1175                     break;
1176                 case L2CAP_EVENT_CAN_SEND_NOW:{
1177                     connection = get_avrcp_connection_for_l2cap_signaling_cid(AVRCP_TARGET, channel);
1178                     if (!connection) {
1179                         log_error("Connection not found\n");
1180                         break;
1181                     }
1182 
1183                     if (connection->accept_response){
1184                         connection->accept_response = 0;
1185                         avrcp_target_send_response(connection->l2cap_signaling_cid, connection);
1186                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1187                         break;
1188                     }
1189                     if (connection->abort_continue_response){
1190                         connection->abort_continue_response = 0;
1191                         connection->now_playing_info_response = 0;
1192                         avrcp_target_abort_continue_response(connection->l2cap_signaling_cid, connection);
1193                         break;
1194                     }
1195 
1196                     if (connection->now_playing_info_response){
1197                         connection->now_playing_info_response = 0;
1198                         avrcp_target_send_now_playing_info(connection->l2cap_signaling_cid, connection);
1199                         break;
1200                     }
1201 
1202                     if (connection->track_changed){
1203                         connection->track_changed = 0;
1204                         avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, connection->track_id, 8);
1205                         avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED);
1206                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1207                         break;
1208                     }
1209 
1210                     if (connection->playback_status_changed){
1211                         connection->playback_status_changed = 0;
1212                         avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, &connection->playback_status_changed, 1);
1213                         avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED);
1214                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1215                         break;
1216                     }
1217 
1218                     // if (connection->addressed_player_changed){
1219                     //     connection->playback_status_changed = 0;
1220                     //     avrcp_target_send_addressed_player_changed_notification(connection->l2cap_signaling_cid, connection, connection->addressed_player_id, connection->uid_counter);
1221                     //     avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED);
1222                     //     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1223                     //     break;
1224                     // }
1225 
1226                     if (connection->playing_content_changed){
1227                         connection->playing_content_changed = 0;
1228                         avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, NULL, 0);
1229                         avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);
1230                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1231                         break;
1232                     }
1233 
1234                     if (connection->battery_status_changed){
1235                         connection->battery_status_changed = 0;
1236                         avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, (uint8_t *)&connection->battery_status, 1);
1237                         avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED);
1238                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1239                         break;
1240                     }
1241 
1242                     if (connection->notify_volume_percentage_changed){
1243                         // printf("emit new volume %d\n", connection->volume_percentage);
1244                         connection->notify_volume_percentage_changed = 0;
1245                         avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED, &connection->volume_percentage, 1);
1246                         avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
1247                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1248                         break;
1249                     }
1250 
1251                     if (connection->reject_transport_header){
1252                         connection->state = AVCTP_CONNECTION_OPENED;
1253                         connection->reject_transport_header = 0;
1254                         l2cap_reserve_packet_buffer();
1255                         uint8_t * out_buffer = l2cap_get_outgoing_buffer();
1256                         out_buffer[0] = connection->transport_header;
1257                         big_endian_store_16(out_buffer, 1, connection->invalid_pid);
1258                         l2cap_send_prepared(connection->l2cap_signaling_cid, 3);
1259                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1260                         break;
1261                     }
1262 
1263                     switch (connection->state){
1264                         case AVCTP_W2_SEND_RESPONSE:
1265                             connection->state = AVCTP_CONNECTION_OPENED;
1266                             // if (connection->now_playing_info_response){
1267                             //     connection->now_playing_info_response = 0;
1268                             //     avrcp_target_send_now_playing_info(connection->l2cap_signaling_cid, connection);
1269                             //     break;
1270                             // }
1271                             avrcp_target_send_response(connection->l2cap_signaling_cid, connection);
1272                             avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1273                             return;
1274                         default:
1275                             break;
1276                     }
1277 
1278                     break;
1279             }
1280             default:
1281                 break;
1282         }
1283         default:
1284             break;
1285     }
1286 }
1287 
1288 void avrcp_target_init(void){
1289     avrcp_init();
1290     avrcp_target_context.role = AVRCP_TARGET;
1291     avrcp_target_context.packet_handler = avrcp_target_packet_handler;
1292     avrcp_register_target_packet_handler(&avrcp_target_packet_handler);
1293 }
1294 
1295 void avrcp_target_register_packet_handler(btstack_packet_handler_t callback){
1296     if (callback == NULL){
1297         log_error("avrcp_register_packet_handler called with NULL callback");
1298         return;
1299     }
1300     avrcp_target_context.avrcp_callback = callback;
1301 }
1302 
1303 uint8_t avrcp_target_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid){
1304     return avrcp_connect(AVRCP_TARGET, bd_addr, &avrcp_target_context, avrcp_cid);
1305 }
1306 
1307 uint8_t avrcp_target_disconnect(uint16_t avrcp_cid){
1308     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(AVRCP_TARGET, avrcp_cid);
1309     if (!connection){
1310         log_error("avrcp_target_disconnect: could not find a connection.");
1311         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1312     }
1313     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
1314     l2cap_disconnect(connection->l2cap_signaling_cid, 0);
1315     return ERROR_CODE_SUCCESS;
1316 }
1317 
1318