xref: /btstack/src/classic/avrcp_controller.c (revision 6983e65e8fc2d4d8998d4365fc3aeee49461fe5d)
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.c"
39 
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 #include "btstack.h"
46 #include "classic/avrcp.h"
47 #include "classic/avrcp_controller.h"
48 
49 
50 /*
51 Category 1: Player/Recorder
52 Category 2: Monitor/Amplifier
53 Category 3: Tuner
54 Category 4: Menu
55 */
56 
57 /* controller supported features
58 Bit 0 = Category 1
59 Bit 1 = Category 2
60 Bit 2 = Category 3
61 Bit 3 = Category 4
62 Bit 4-5 = RFA
63 Bit 6 = Supports browsing
64 Bit 7-15 = RFA
65 The bits for supported categories are set to 1. Others are set to 0.
66 */
67 
68 /* target supported features
69 Bit 0 = Category 1
70 Bit 1 = Category 2
71 Bit 2 = Category 3
72 Bit 3 = Category 4
73 Bit 4 = Player Application Settings. Bit 0 should be set for this bit to be set.
74 Bit 5 = Group Navigation. Bit 0 should be set for this bit to be set.
75 Bit 6 = Supports browsing*4
76 Bit 7 = Supports multiple media player applications
77 Bit 8-15 = RFA
78 The bits for supported categories are set to 1. Others are set to 0.
79 */
80 
81 static avrcp_context_t avrcp_controller_context;
82 
83 void avrcp_controller_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){
84     avrcp_create_sdp_record(1, service, service_record_handle, browsing, supported_features, service_name, service_provider_name);
85 }
86 
87 static void avrcp_emit_repeat_and_shuffle_mode(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t ctype, avrcp_repeat_mode_t repeat_mode, avrcp_shuffle_mode_t shuffle_mode){
88     if (!callback) return;
89     uint8_t event[8];
90     int pos = 0;
91     event[pos++] = HCI_EVENT_AVRCP_META;
92     event[pos++] = sizeof(event) - 2;
93     event[pos++] = AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE;
94     little_endian_store_16(event, pos, avrcp_cid);
95     pos += 2;
96     event[pos++] = ctype;
97     event[pos++] = repeat_mode;
98     event[pos++] = shuffle_mode;
99     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
100 }
101 
102 static void avrcp_emit_operation_status(btstack_packet_handler_t callback, uint8_t subevent, uint16_t avrcp_cid, uint8_t ctype, uint8_t operation_id){
103     if (!callback) return;
104     uint8_t event[7];
105     int pos = 0;
106     event[pos++] = HCI_EVENT_AVRCP_META;
107     event[pos++] = sizeof(event) - 2;
108     event[pos++] = subevent;
109     little_endian_store_16(event, pos, avrcp_cid);
110     pos += 2;
111     event[pos++] = ctype;
112     event[pos++] = operation_id;
113     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
114 }
115 
116 static void avrcp_press_and_hold_timeout_handler(btstack_timer_source_t * timer){
117     UNUSED(timer);
118     avrcp_connection_t * connection = btstack_run_loop_get_timer_context(timer);
119     btstack_run_loop_set_timer(&connection->press_and_hold_cmd_timer, 2000); // 2 seconds timeout
120     btstack_run_loop_add_timer(&connection->press_and_hold_cmd_timer);
121     connection->state = AVCTP_W2_SEND_PRESS_COMMAND;
122     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
123 }
124 
125 static void avrcp_press_and_hold_timer_start(avrcp_connection_t * connection){
126     btstack_run_loop_remove_timer(&connection->press_and_hold_cmd_timer);
127     btstack_run_loop_set_timer_handler(&connection->press_and_hold_cmd_timer, avrcp_press_and_hold_timeout_handler);
128     btstack_run_loop_set_timer_context(&connection->press_and_hold_cmd_timer, connection);
129     btstack_run_loop_set_timer(&connection->press_and_hold_cmd_timer, 2000); // 2 seconds timeout
130     btstack_run_loop_add_timer(&connection->press_and_hold_cmd_timer);
131 }
132 
133 static void avrcp_press_and_hold_timer_stop(avrcp_connection_t * connection){
134     connection->continuous_fast_forward_cmd = 0;
135     btstack_run_loop_remove_timer(&connection->press_and_hold_cmd_timer);
136 }
137 
138 static uint8_t request_pass_through_release_control_cmd(avrcp_connection_t * connection){
139     connection->state = AVCTP_W2_SEND_RELEASE_COMMAND;
140     if (connection->continuous_fast_forward_cmd){
141         avrcp_press_and_hold_timer_stop(connection);
142     }
143     connection->cmd_operands[0] = 0x80 | connection->cmd_operands[0];
144     connection->transaction_label++;
145     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
146     return ERROR_CODE_SUCCESS;
147 }
148 
149 static inline uint8_t request_pass_through_press_control_cmd(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint16_t playback_speed, uint8_t continuous_fast_forward_cmd, avrcp_context_t * context){
150     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, context);
151     if (!connection){
152         log_error("avrcp: could not find a connection.");
153         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
154     }
155     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
156     connection->state = AVCTP_W2_SEND_PRESS_COMMAND;
157     connection->command_opcode =  AVRCP_CMD_OPCODE_PASS_THROUGH;
158     connection->command_type = AVRCP_CTYPE_CONTROL;
159     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
160     connection->subunit_id =   AVRCP_SUBUNIT_ID;
161     connection->cmd_operands_length = 0;
162 
163     connection->continuous_fast_forward_cmd = continuous_fast_forward_cmd;
164     connection->cmd_operands_length = 2;
165     connection->cmd_operands[0] = opid;
166     if (playback_speed > 0){
167         connection->cmd_operands[2] = playback_speed;
168         connection->cmd_operands_length++;
169     }
170     connection->cmd_operands[1] = connection->cmd_operands_length - 2;
171 
172     if (connection->continuous_fast_forward_cmd){
173         avrcp_press_and_hold_timer_start(connection);
174     }
175 
176     connection->transaction_label++;
177     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
178     return ERROR_CODE_SUCCESS;
179 }
180 
181 static uint8_t request_single_pass_through_press_control_cmd(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint16_t playback_speed){
182     return request_pass_through_press_control_cmd(avrcp_cid, opid, playback_speed, 0, &avrcp_controller_context);
183 }
184 
185 static uint8_t request_continuous_pass_through_press_control_cmd(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint16_t playback_speed){
186     return request_pass_through_press_control_cmd(avrcp_cid, opid, playback_speed, 1, &avrcp_controller_context);
187 }
188 
189 static int avrcp_send_cmd(uint16_t cid, avrcp_connection_t * connection){
190     uint8_t command[30];
191     int pos = 0;
192     // transport header
193     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
194     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
195     // Profile IDentifier (PID)
196     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
197     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
198 
199     // command_type
200     command[pos++] = connection->command_type;
201     // subunit_type | subunit ID
202     command[pos++] = (connection->subunit_type << 3) | connection->subunit_id;
203     // opcode
204     command[pos++] = (uint8_t)connection->command_opcode;
205     // operands
206     memcpy(command+pos, connection->cmd_operands, connection->cmd_operands_length);
207     pos += connection->cmd_operands_length;
208 
209     return l2cap_send(cid, command, pos);
210 }
211 
212 static int avrcp_register_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t event_id){
213     if (connection->notifications_to_deregister & (1 << event_id)) return 0;
214     if (connection->notifications_enabled & (1 << event_id)) return 0;
215     if (connection->notifications_to_register & (1 << event_id)) return 0;
216     connection->notifications_to_register |= (1 << event_id);
217     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
218     return 1;
219 }
220 
221 static void avrcp_prepare_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t event_id){
222     connection->transaction_label++;
223     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
224     connection->command_type = AVRCP_CTYPE_NOTIFY;
225     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
226     connection->subunit_id = AVRCP_SUBUNIT_ID;
227     int pos = 0;
228     big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID);
229     pos += 3;
230     connection->cmd_operands[pos++] = AVRCP_PDU_ID_REGISTER_NOTIFICATION;
231     connection->cmd_operands[pos++] = 0;                     // reserved(upper 6) | packet_type -> 0
232     big_endian_store_16(connection->cmd_operands, pos, 5);     // parameter length
233     pos += 2;
234     connection->cmd_operands[pos++] = event_id;
235     big_endian_store_32(connection->cmd_operands, pos, 0);
236     pos += 4;
237     connection->cmd_operands_length = pos;
238     // AVRCP_SPEC_V14.pdf 166
239     // answer page 61
240 }
241 
242 static uint8_t avrcp_cmd_opcode(uint8_t *packet, uint16_t size){
243     uint8_t cmd_opcode_index = 5;
244     if (cmd_opcode_index > size) return AVRCP_CMD_OPCODE_UNDEFINED;
245     return packet[cmd_opcode_index];
246 }
247 
248 
249 static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){
250     uint8_t operands[20];
251     uint8_t opcode;
252     int     pos = 3;
253     // uint8_t transport_header = packet[0];
254     // uint8_t transaction_label = transport_header >> 4;
255     // uint8_t packet_type = (transport_header & 0x0F) >> 2;
256     // uint8_t frame_type = (transport_header & 0x03) >> 1;
257     // uint8_t ipid = transport_header & 0x01;
258     // uint8_t byte_value = packet[2];
259     // uint16_t pid = (byte_value << 8) | packet[2];
260 
261     avrcp_command_type_t ctype = (avrcp_command_type_t) packet[pos++];
262     uint8_t byte_value = packet[pos++];
263     avrcp_subunit_type_t subunit_type = (avrcp_subunit_type_t) (byte_value >> 3);
264     avrcp_subunit_type_t subunit_id = (avrcp_subunit_type_t)   (byte_value & 0x07);
265     opcode = packet[pos++];
266 
267     // printf("    Transport header 0x%02x (transaction_label %d, packet_type %d, frame_type %d, ipid %d), pid 0x%4x\n",
268     //     transport_header, transaction_label, packet_type, frame_type, ipid, pid);
269     // // printf_hexdump(packet+pos, size-pos);
270 
271     uint8_t pdu_id;
272     uint16_t param_length;
273     switch (avrcp_cmd_opcode(packet,size)){
274         case AVRCP_CMD_OPCODE_UNIT_INFO:{
275             if (connection->state != AVCTP_W2_RECEIVE_RESPONSE) return;
276             connection->state = AVCTP_CONNECTION_OPENED;
277 
278             // operands:
279             memcpy(operands, packet+pos, 5);
280             uint8_t unit_type = operands[1] >> 3;
281             uint8_t unit = operands[1] & 0x07;
282             uint32_t company_id = operands[2] << 16 | operands[3] << 8 | operands[4];
283             log_info("    UNIT INFO response: ctype 0x%02x (0C), subunit_type 0x%02x (1F), subunit_id 0x%02x (07), opcode 0x%02x (30), unit_type 0x%02x, unit %d, company_id 0x%06x",
284                 ctype, subunit_type, subunit_id, opcode, unit_type, unit, company_id );
285             break;
286         }
287         case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT:
288             if (size - pos < 7) {
289                 log_error("avrcp: wrong packet size");
290                 return;
291             };
292             // operands:
293             memcpy(operands, packet+pos, 7);
294             pos += 7;
295             // uint32_t company_id = operands[0] << 16 | operands[1] << 8 | operands[2];
296             pdu_id = operands[3];
297 
298             if (connection->state != AVCTP_W2_RECEIVE_RESPONSE && pdu_id != AVRCP_PDU_ID_REGISTER_NOTIFICATION){
299                 log_info("AVRCP_CMD_OPCODE_VENDOR_DEPENDENT state %d", connection->state);
300                 return;
301             }
302             connection->state = AVCTP_CONNECTION_OPENED;
303 
304 
305             // uint8_t unit_type = operands[4] >> 3;
306             // uint8_t unit = operands[4] & 0x07;
307             param_length = big_endian_read_16(operands, 5);
308 
309             // printf("    VENDOR DEPENDENT response: ctype 0x%02x (0C), subunit_type 0x%02x (1F), subunit_id 0x%02x (07), opcode 0x%02x (30), unit_type 0x%02x, unit %d, company_id 0x%06x\n",
310             //     ctype, subunit_type, subunit_id, opcode, unit_type, unit, company_id );
311 
312             // if (ctype == AVRCP_CTYPE_RESPONSE_INTERIM) return;
313             log_info("        VENDOR DEPENDENT response: pdu id 0x%02x, param_length %d, status %s", pdu_id, param_length, avrcp_ctype2str(ctype));
314             switch (pdu_id){
315                 case AVRCP_PDU_ID_GetCurrentPlayerApplicationSettingValue:{
316                     uint8_t num_attributes = packet[pos++];
317                     int i;
318                     avrcp_repeat_mode_t  repeat_mode =  AVRCP_REPEAT_MODE_INVALID;
319                     avrcp_shuffle_mode_t shuffle_mode = AVRCP_SHUFFLE_MODE_INVALID;
320                     for (i = 0; i < num_attributes; i++){
321                         uint8_t attribute_id    = packet[pos++];
322                         uint8_t value = packet[pos++];
323                         switch (attribute_id){
324                             case 0x02:
325                                 repeat_mode = (avrcp_repeat_mode_t) value;
326                                 break;
327                             case 0x03:
328                                 shuffle_mode = (avrcp_shuffle_mode_t) value;
329                                 break;
330                             default:
331                                 break;
332                         }
333                     }
334                     avrcp_emit_repeat_and_shuffle_mode(avrcp_controller_context.avrcp_callback, connection->avrcp_cid, ctype, repeat_mode, shuffle_mode);
335                     break;
336                 }
337                 case AVRCP_PDU_ID_SetPlayerApplicationSettingValue:{
338                     uint8_t event[6];
339                     int offset = 0;
340                     event[offset++] = HCI_EVENT_AVRCP_META;
341                     event[offset++] = sizeof(event) - 2;
342                     event[offset++] = AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE;
343                     little_endian_store_16(event, offset, connection->avrcp_cid);
344                     offset += 2;
345                     event[offset++] = ctype;
346                     (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
347                     break;
348                 }
349                 case AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME:{
350                     uint8_t event[7];
351                     int offset = 0;
352                     event[offset++] = HCI_EVENT_AVRCP_META;
353                     event[offset++] = sizeof(event) - 2;
354                     event[offset++] = AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE;
355                     little_endian_store_16(event, offset, connection->avrcp_cid);
356                     offset += 2;
357                     event[offset++] = ctype;
358                     event[offset++] = packet[pos++];
359                     (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
360                     break;
361                 }
362                 case AVRCP_PDU_ID_GET_CAPABILITIES:{
363                     avrcp_capability_id_t capability_id = (avrcp_capability_id_t) packet[pos++];
364                     uint8_t capability_count = packet[pos++];
365                     int i;
366                     switch (capability_id){
367                         case AVRCP_CAPABILITY_ID_COMPANY:
368                             // log_info("Supported companies %d: ", capability_count);
369                             for (i = 0; i < capability_count; i++){
370                                 uint32_t company_id = big_endian_read_24(packet, pos);
371                                 pos += 3;
372                                 log_info("  0x%06x, ", company_id);
373                             }
374                             break;
375                         case AVRCP_CAPABILITY_ID_EVENT:
376                             // log_info("Supported events %d: ", capability_count);
377                             for (i = 0; i < capability_count; i++){
378                                 uint8_t event_id = packet[pos++];
379                                 log_info("  0x%02x %s", event_id, avrcp_event2str(event_id));
380                             }
381                             break;
382                     }
383                     break;
384                 }
385                 case AVRCP_PDU_ID_GET_PLAY_STATUS:{
386                     uint32_t song_length = big_endian_read_32(packet, pos);
387                     pos += 4;
388                     uint32_t song_position = big_endian_read_32(packet, pos);
389                     pos += 4;
390                     uint8_t play_status = packet[pos];
391                     // log_info("        GET_PLAY_STATUS length 0x%04X, position 0x%04X, status %s", song_length, song_position, avrcp_play_status2str(play_status));
392 
393                     uint8_t event[15];
394                     int offset = 0;
395                     event[offset++] = HCI_EVENT_AVRCP_META;
396                     event[offset++] = sizeof(event) - 2;
397                     event[offset++] = AVRCP_SUBEVENT_PLAY_STATUS;
398                     little_endian_store_16(event, offset, connection->avrcp_cid);
399                     offset += 2;
400                     event[offset++] = ctype;
401                     little_endian_store_32(event, offset, song_length);
402                     offset += 4;
403                     little_endian_store_32(event, offset, song_position);
404                     offset += 4;
405                     event[offset++] = play_status;
406                     (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
407                     break;
408                 }
409                 case AVRCP_PDU_ID_REGISTER_NOTIFICATION:{
410                     avrcp_notification_event_id_t  event_id = (avrcp_notification_event_id_t) packet[pos++];
411                     uint16_t event_mask = (1 << event_id);
412                     uint16_t reset_event_mask = ~event_mask;
413                     switch (ctype){
414                         case AVRCP_CTYPE_RESPONSE_INTERIM:
415                             // register as enabled
416                             connection->notifications_enabled |= event_mask;
417                             // printf("INTERIM notifications_enabled 0x%2x, notifications_to_register 0x%2x\n", connection->notifications_enabled,  connection->notifications_to_register);
418                             break;
419                         case AVRCP_CTYPE_RESPONSE_CHANGED_STABLE:
420                             // received change, event is considered deregistered
421                             // we are re-enabling it automatically, if it is not
422                             // explicitly disabled
423                             connection->notifications_enabled &= reset_event_mask;
424                             if (! (connection->notifications_to_deregister & event_mask)){
425                                 avrcp_register_notification(connection, event_id);
426                                 // printf("CHANGED_STABLE notifications_enabled 0x%2x, notifications_to_register 0x%2x\n", connection->notifications_enabled,  connection->notifications_to_register);
427                             } else {
428                                 connection->notifications_to_deregister &= reset_event_mask;
429                             }
430                             break;
431                         default:
432                             connection->notifications_to_register &= reset_event_mask;
433                             connection->notifications_enabled &= reset_event_mask;
434                             connection->notifications_to_deregister &= reset_event_mask;
435                             break;
436                     }
437 
438                     switch (event_id){
439                         case AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED:{
440                             uint8_t event[7];
441                             int offset = 0;
442                             event[offset++] = HCI_EVENT_AVRCP_META;
443                             event[offset++] = sizeof(event) - 2;
444                             event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED;
445                             little_endian_store_16(event, offset, connection->avrcp_cid);
446                             offset += 2;
447                             event[offset++] = ctype;
448                             event[offset++] = packet[pos];
449                             (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
450                             break;
451                         }
452                         case AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED:{
453                             uint8_t event[6];
454                             int offset = 0;
455                             event[offset++] = HCI_EVENT_AVRCP_META;
456                             event[offset++] = sizeof(event) - 2;
457                             event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED;
458                             little_endian_store_16(event, offset, connection->avrcp_cid);
459                             offset += 2;
460                             event[offset++] = ctype;
461                             (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
462                             break;
463                         }
464                         case AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED:{
465                             uint8_t event[6];
466                             int offset = 0;
467                             event[offset++] = HCI_EVENT_AVRCP_META;
468                             event[offset++] = sizeof(event) - 2;
469                             event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED;
470                             little_endian_store_16(event, offset, connection->avrcp_cid);
471                             offset += 2;
472                             event[offset++] = ctype;
473                             (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
474                             break;
475                         }
476                         case AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED:{
477                             uint8_t event[6];
478                             int offset = 0;
479                             event[offset++] = HCI_EVENT_AVRCP_META;
480                             event[offset++] = sizeof(event) - 2;
481                             event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED;
482                             little_endian_store_16(event, offset, connection->avrcp_cid);
483                             offset += 2;
484                             event[offset++] = ctype;
485                             (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
486                             break;
487                         }
488                         case AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED:{
489                             uint8_t event[7];
490                             int offset = 0;
491                             event[offset++] = HCI_EVENT_AVRCP_META;
492                             event[offset++] = sizeof(event) - 2;
493                             event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED;
494                             little_endian_store_16(event, offset, connection->avrcp_cid);
495                             offset += 2;
496                             event[offset++] = ctype;
497                             event[offset++] = packet[pos++] & 0x7F;
498                             (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
499                             break;
500                         }
501                         // case AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:{
502                         //     uint8_t num_PlayerApplicationSettingAttributes = packet[pos++];
503                         //     int i;
504                         //     for (i = 0; i < num_PlayerApplicationSettingAttributes; i++){
505                         //         uint8_t PlayerApplicationSetting_AttributeID = packet[pos++];
506                         //         uint8_t PlayerApplicationSettingValueID = packet[pos++];
507                         //     }
508                         //     break;
509                         // }
510                         // case AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED:
511                         //     uint16_t player_id = big_endian_read_16(packet, pos);
512                         //     pos += 2;
513                         //     uint16_t uid_counter = big_endian_read_16(packet, pos);
514                         //     pos += 2;
515                         //     break;
516                         // case AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED:
517                         //     uint16_t uid_counter = big_endian_read_16(packet, pos);
518                         //     pos += 2;
519                         //     break;
520                         default:
521                             log_info("avrcp: not implemented");
522                             break;
523                     }
524                     if (connection->notifications_to_register != 0){
525                         avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
526                     }
527                     break;
528                 }
529 
530                 case AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES:{
531                     uint8_t num_attributes = packet[pos++];
532                     int i;
533                     struct item {
534                         uint16_t len;
535                         uint8_t  * value;
536                     } items[AVRCP_MEDIA_ATTR_COUNT];
537                     memset(items, 0, sizeof(items));
538 
539                     uint16_t string_attributes_len = 0;
540                     uint8_t  num_string_attributes = 0;
541                     uint16_t total_event_payload_for_string_attributes = HCI_EVENT_PAYLOAD_SIZE-2;
542                     uint16_t max_string_attribute_value_len = 0;
543                     if (ctype == AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE || ctype == AVRCP_CTYPE_RESPONSE_CHANGED_STABLE){
544                         for (i = 0; i < num_attributes; i++){
545                             avrcp_media_attribute_id_t attr_id = (avrcp_media_attribute_id_t) big_endian_read_32(packet, pos);
546                             pos += 4;
547                             // uint16_t character_set = big_endian_read_16(packet, pos);
548                             pos += 2;
549                             uint16_t attr_value_length = big_endian_read_16(packet, pos);
550                             pos += 2;
551 
552                             // debug - to remove later
553                             uint8_t  value[100];
554                             uint16_t value_len = sizeof(value) <= attr_value_length? sizeof(value) - 1 : attr_value_length;
555                             memcpy(value, packet+pos, value_len);
556                             value[value_len] = 0;
557                             // printf("Now Playing Info %s: %s \n", attribute2str(attr_id), value);
558                             // end debug
559 
560                             if ((attr_id >= 1) || (attr_id <= AVRCP_MEDIA_ATTR_COUNT)) {
561                                 items[attr_id-1].len = attr_value_length;
562                                 items[attr_id-1].value = &packet[pos];
563                                 switch (attr_id){
564                                     case AVRCP_MEDIA_ATTR_TITLE:
565                                     case AVRCP_MEDIA_ATTR_ARTIST:
566                                     case AVRCP_MEDIA_ATTR_ALBUM:
567                                     case AVRCP_MEDIA_ATTR_GENRE:
568                                         num_string_attributes++;
569                                         string_attributes_len += attr_value_length;
570                                         if (max_string_attribute_value_len < attr_value_length){
571                                             max_string_attribute_value_len = attr_value_length;
572                                         }
573                                         break;
574                                     default:
575                                         break;
576                                 }
577                             }
578                             pos += attr_value_length;
579                         }
580                     }
581 
582                     // subtract space for fixed fields
583                     total_event_payload_for_string_attributes -= 14 + 4;    // 4 for '\0'
584 
585                     // @TODO optimize space by repeatedly decreasing max_string_attribute_value_len until it fits into buffer instead of crude divion
586                     uint16_t max_value_len = total_event_payload_for_string_attributes > string_attributes_len? max_string_attribute_value_len : total_event_payload_for_string_attributes/(string_attributes_len+1) - 1;
587                     // printf("num_string_attributes %d, string_attributes_len %d, total_event_payload_for_string_attributes %d, max_value_len %d \n", num_string_attributes, string_attributes_len, total_event_payload_for_string_attributes, max_value_len);
588 
589                     const uint8_t attribute_order[] = {
590                         AVRCP_MEDIA_ATTR_TRACK,
591                         AVRCP_MEDIA_ATTR_TOTAL_TRACKS,
592                         AVRCP_MEDIA_ATTR_SONG_LENGTH,
593                         AVRCP_MEDIA_ATTR_TITLE,
594                         AVRCP_MEDIA_ATTR_ARTIST,
595                         AVRCP_MEDIA_ATTR_ALBUM,
596                         AVRCP_MEDIA_ATTR_GENRE
597                     };
598 
599                     uint8_t event[HCI_EVENT_BUFFER_SIZE];
600                     event[0] = HCI_EVENT_AVRCP_META;
601                     pos = 2;
602                     event[pos++] = AVRCP_SUBEVENT_NOW_PLAYING_INFO;
603                     little_endian_store_16(event, pos, connection->avrcp_cid);
604                     pos += 2;
605                     event[pos++] = ctype;
606                     for (i = 0; i < sizeof(attribute_order); i++){
607                         avrcp_media_attribute_id_t attr_id = (avrcp_media_attribute_id_t) attribute_order[i];
608                         uint16_t value_len = 0;
609                         switch (attr_id){
610                             case AVRCP_MEDIA_ATTR_TITLE:
611                             case AVRCP_MEDIA_ATTR_ARTIST:
612                             case AVRCP_MEDIA_ATTR_ALBUM:
613                             case AVRCP_MEDIA_ATTR_GENRE:
614                                 if (items[attr_id-1].value){
615                                     value_len = items[attr_id-1].len <= max_value_len ? items[attr_id-1].len : max_value_len;
616                                 }
617                                 event[pos++] = value_len + 1;
618                                 if (value_len){
619                                     memcpy(event+pos, items[attr_id-1].value, value_len);
620                                     pos += value_len;
621                                 }
622                                 event[pos++] = 0;
623                                 break;
624                             case AVRCP_MEDIA_ATTR_SONG_LENGTH:
625                                 if (items[attr_id-1].value){
626                                     little_endian_store_32(event, pos, btstack_atoi((char *)items[attr_id-1].value));
627                                 } else {
628                                     little_endian_store_32(event, pos, 0);
629                                 }
630                                 pos += 4;
631                                 break;
632                             case AVRCP_MEDIA_ATTR_TRACK:
633                             case AVRCP_MEDIA_ATTR_TOTAL_TRACKS:
634                                 if (items[attr_id-1].value){
635                                     event[pos++] = btstack_atoi((char *)items[attr_id-1].value);
636                                 } else {
637                                     event[pos++] = 0;
638                                 }
639                                 break;
640                         }
641                     }
642                     event[1] = pos - 2;
643                     // printf_hexdump(event, pos);
644                     (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, pos);
645                     break;
646                 }
647                 default:
648                     break;
649             }
650             break;
651         case AVRCP_CMD_OPCODE_PASS_THROUGH:{
652             // 0x80 | connection->cmd_operands[0]
653             uint8_t operation_id = packet[pos++];
654             switch (connection->state){
655                 case AVCTP_W2_RECEIVE_PRESS_RESPONSE:
656                     if (connection->continuous_fast_forward_cmd){
657                         connection->state = AVCTP_W4_STOP;
658                     } else {
659                         connection->state = AVCTP_W2_SEND_RELEASE_COMMAND;
660                     }
661                     break;
662                 case AVCTP_W2_RECEIVE_RESPONSE:
663                     connection->state = AVCTP_CONNECTION_OPENED;
664                     break;
665                 default:
666                     // check for notifications? move state transition down
667                     // log_info("AVRCP_CMD_OPCODE_PASS_THROUGH state %d\n", connection->state);
668                     break;
669             }
670             if (connection->state == AVCTP_W4_STOP){
671                 avrcp_emit_operation_status(avrcp_controller_context.avrcp_callback, AVRCP_SUBEVENT_OPERATION_START, connection->avrcp_cid, ctype, operation_id);
672             }
673             if (connection->state == AVCTP_CONNECTION_OPENED) {
674                 // RELEASE response
675                 operation_id = operation_id & 0x7F;
676                 avrcp_emit_operation_status(avrcp_controller_context.avrcp_callback, AVRCP_SUBEVENT_OPERATION_COMPLETE, connection->avrcp_cid, ctype, operation_id);
677             }
678             if (connection->state == AVCTP_W2_SEND_RELEASE_COMMAND){
679                 // PRESS response
680                 request_pass_through_release_control_cmd(connection);
681             }
682             break;
683         }
684         default:
685             break;
686     }
687 }
688 
689 static void avrcp_controller_handle_can_send_now(avrcp_connection_t * connection){
690     int i;
691     switch (connection->state){
692         case AVCTP_W2_SEND_PRESS_COMMAND:
693             connection->state = AVCTP_W2_RECEIVE_PRESS_RESPONSE;
694             avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
695             break;
696         case AVCTP_W2_SEND_COMMAND:
697         case AVCTP_W2_SEND_RELEASE_COMMAND:
698             connection->state = AVCTP_W2_RECEIVE_RESPONSE;
699             avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
700             break;
701         case AVCTP_CONNECTION_OPENED:
702             if (connection->notifications_to_register != 0){
703                 for (i = 1; i <= AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED; i++){
704                     if (connection->notifications_to_register & (1<<i)){
705                         connection->notifications_to_register &= ~ (1 << i);
706                         avrcp_prepare_notification(connection, (avrcp_notification_event_id_t) i);
707                         connection->state = AVCTP_W2_RECEIVE_RESPONSE;
708                         avrcp_send_cmd(connection->l2cap_signaling_cid, connection);
709                         return;
710                     }
711                 }
712             }
713             return;
714         default:
715             return;
716     }
717 }
718 
719 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
720     avrcp_connection_t * connection;
721 
722     switch (packet_type) {
723         case L2CAP_DATA_PACKET:
724             connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_controller_context);
725             if (!connection) break;
726             avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size);
727             break;
728         case HCI_EVENT_PACKET:
729             switch (hci_event_packet_get_type(packet)){
730                 case L2CAP_EVENT_CAN_SEND_NOW:
731                     connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_controller_context);
732                     if (!connection) break;
733                     avrcp_controller_handle_can_send_now(connection);
734                     break;
735             default:
736                 avrcp_packet_handler(packet_type, channel, packet, size, &avrcp_controller_context);
737                 break;
738         }
739         default:
740             break;
741     }
742 }
743 
744 void avrcp_controller_init(void){
745     avrcp_controller_context.role = AVRCP_CONTROLLER;
746     avrcp_controller_context.connections = NULL;
747     avrcp_controller_context.packet_handler = avrcp_controller_packet_handler;
748     l2cap_register_service(&avrcp_controller_packet_handler, BLUETOOTH_PROTOCOL_AVCTP, 0xffff, LEVEL_0);
749 }
750 
751 void avrcp_controller_register_packet_handler(btstack_packet_handler_t callback){
752     if (callback == NULL){
753         log_error("avrcp_register_packet_handler called with NULL callback");
754         return;
755     }
756     avrcp_controller_context.avrcp_callback = callback;
757 }
758 
759 uint8_t avrcp_controller_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid){
760     return avrcp_connect(bd_addr, &avrcp_controller_context, avrcp_cid);
761 }
762 
763 uint8_t avrcp_controller_unit_info(uint16_t avrcp_cid){
764     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
765     if (!connection){
766         log_error("avrcp_unit_info: could not find a connection.");
767         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
768     }
769     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
770     connection->state = AVCTP_W2_SEND_COMMAND;
771 
772     connection->transaction_label++;
773     connection->command_opcode = AVRCP_CMD_OPCODE_UNIT_INFO;
774     connection->command_type = AVRCP_CTYPE_STATUS;
775     connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique
776     connection->subunit_id =   AVRCP_SUBUNIT_ID_IGNORE;
777     memset(connection->cmd_operands, 0xFF, connection->cmd_operands_length);
778     connection->cmd_operands_length = 5;
779     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
780     return ERROR_CODE_SUCCESS;
781 }
782 
783 static uint8_t avrcp_controller_get_capabilities(uint16_t avrcp_cid, uint8_t capability_id){
784     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
785     if (!connection){
786         log_error("avrcp_get_capabilities: could not find a connection.");
787         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
788     }
789     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
790     connection->state = AVCTP_W2_SEND_COMMAND;
791 
792     connection->transaction_label++;
793     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
794     connection->command_type = AVRCP_CTYPE_STATUS;
795     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
796     connection->subunit_id = AVRCP_SUBUNIT_ID;
797     big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID);
798     connection->cmd_operands[3] = AVRCP_PDU_ID_GET_CAPABILITIES; // PDU ID
799     connection->cmd_operands[4] = 0;
800     big_endian_store_16(connection->cmd_operands, 5, 1); // parameter length
801     connection->cmd_operands[7] = capability_id;                  // capability ID
802     connection->cmd_operands_length = 8;
803     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
804     return ERROR_CODE_SUCCESS;
805 }
806 
807 uint8_t avrcp_controller_get_supported_company_ids(uint16_t avrcp_cid){
808     return avrcp_controller_get_capabilities(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY);
809 }
810 
811 uint8_t avrcp_controller_get_supported_events(uint16_t avrcp_cid){
812     return avrcp_controller_get_capabilities(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT);
813 }
814 
815 
816 uint8_t avrcp_controller_play(uint16_t avrcp_cid){
817     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_PLAY, 0);
818 }
819 
820 uint8_t avrcp_controller_stop(uint16_t avrcp_cid){
821     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_STOP, 0);
822 }
823 
824 uint8_t avrcp_controller_pause(uint16_t avrcp_cid){
825     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_PAUSE, 0);
826 }
827 
828 uint8_t avrcp_controller_forward(uint16_t avrcp_cid){
829     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FORWARD, 0);
830 }
831 
832 uint8_t avrcp_controller_backward(uint16_t avrcp_cid){
833     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_BACKWARD, 0);
834 }
835 
836 uint8_t avrcp_controller_start_rewind(uint16_t avrcp_cid){
837     return request_continuous_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_REWIND, 0);
838 }
839 
840 uint8_t avrcp_controller_volume_up(uint16_t avrcp_cid){
841     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_VOLUME_UP, 0);
842 }
843 
844 uint8_t avrcp_controller_volume_down(uint16_t avrcp_cid){
845     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_VOLUME_DOWN, 0);
846 }
847 
848 uint8_t avrcp_controller_mute(uint16_t avrcp_cid){
849     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_MUTE, 0);
850 }
851 
852 uint8_t avrcp_controller_skip(uint16_t avrcp_cid){
853     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_SKIP, 0);
854 }
855 
856 uint8_t avrcp_controller_stop_rewind(uint16_t avrcp_cid){
857     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
858     if (!connection){
859         log_error("avrcp_stop_rewind: could not find a connection.");
860         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
861     }
862     if (connection->state != AVCTP_W4_STOP) return ERROR_CODE_COMMAND_DISALLOWED;
863     return request_pass_through_release_control_cmd(connection);
864 }
865 
866 uint8_t avrcp_controller_start_fast_forward(uint16_t avrcp_cid){
867     return request_continuous_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FAST_FORWARD, 0);
868 }
869 
870 uint8_t avrcp_controller_fast_forward(uint16_t avrcp_cid){
871     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FAST_FORWARD, 0);
872 }
873 
874 uint8_t avrcp_controller_rewind(uint16_t avrcp_cid){
875     return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_REWIND, 0);
876 }
877 
878 
879 uint8_t avrcp_controller_stop_fast_forward(uint16_t avrcp_cid){
880     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
881     if (!connection){
882         log_error("avrcp_stop_fast_forward: could not find a connection.");
883         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
884     }
885     if (connection->state != AVCTP_W4_STOP) return ERROR_CODE_COMMAND_DISALLOWED;
886     return request_pass_through_release_control_cmd(connection);
887 }
888 
889 uint8_t avrcp_controller_get_play_status(uint16_t avrcp_cid){
890     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
891     if (!connection){
892         log_error("avrcp_get_play_status: could not find a connection.");
893         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
894     }
895     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
896     connection->state = AVCTP_W2_SEND_COMMAND;
897     connection->transaction_label++;
898     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
899     connection->command_type = AVRCP_CTYPE_STATUS;
900     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
901     connection->subunit_id = AVRCP_SUBUNIT_ID;
902     big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID);
903     connection->cmd_operands[3] = AVRCP_PDU_ID_GET_PLAY_STATUS;
904     connection->cmd_operands[4] = 0;                     // reserved(upper 6) | packet_type -> 0
905     big_endian_store_16(connection->cmd_operands, 5, 0); // parameter length
906     connection->cmd_operands_length = 7;
907     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
908     return ERROR_CODE_SUCCESS;
909 }
910 
911 uint8_t avrcp_controller_enable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id){
912     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
913     if (!connection){
914         log_error("avrcp_get_play_status: could not find a connection.");
915         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
916     }
917     avrcp_register_notification(connection, event_id);
918     return ERROR_CODE_SUCCESS;
919 }
920 
921 uint8_t avrcp_controller_disable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id){
922     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
923     if (!connection){
924         log_error("avrcp_get_play_status: could not find a connection.");
925         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
926     }
927     connection->notifications_to_deregister |= (1 << event_id);
928     return ERROR_CODE_SUCCESS;
929 }
930 
931 uint8_t avrcp_controller_get_now_playing_info(uint16_t avrcp_cid){
932     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
933     if (!connection){
934         log_error("avrcp_get_capabilities: could not find a connection.");
935         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
936     }
937     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
938     connection->state = AVCTP_W2_SEND_COMMAND;
939 
940     connection->transaction_label++;
941     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
942     connection->command_type = AVRCP_CTYPE_STATUS;
943     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
944     connection->subunit_id = AVRCP_SUBUNIT_ID;
945     int pos = 0;
946     big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID);
947     pos += 3;
948     connection->cmd_operands[pos++] = AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES; // PDU ID
949     connection->cmd_operands[pos++] = 0;
950 
951     // Parameter Length
952     big_endian_store_16(connection->cmd_operands, pos, 9);
953     pos += 2;
954 
955     // write 8 bytes value
956     memset(connection->cmd_operands + pos, 0, 8); // identifier: PLAYING
957     pos += 8;
958 
959     connection->cmd_operands[pos++] = 0; // attribute count, if 0 get all attributes
960     // every attribute is 4 bytes long
961 
962     connection->cmd_operands_length = pos;
963     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
964     return ERROR_CODE_SUCCESS;
965 }
966 
967 uint8_t avrcp_controller_set_absolute_volume(uint16_t avrcp_cid, uint8_t volume){
968      avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
969     if (!connection){
970         log_error("avrcp_get_capabilities: could not find a connection.");
971         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
972     }
973     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
974     connection->state = AVCTP_W2_SEND_COMMAND;
975 
976     connection->transaction_label++;
977     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
978     connection->command_type = AVRCP_CTYPE_CONTROL;
979     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
980     connection->subunit_id = AVRCP_SUBUNIT_ID;
981     int pos = 0;
982     big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID);
983     pos += 3;
984     connection->cmd_operands[pos++] = AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME; // PDU ID
985     connection->cmd_operands[pos++] = 0;
986 
987     // Parameter Length
988     big_endian_store_16(connection->cmd_operands, pos, 1);
989     pos += 2;
990     connection->cmd_operands[pos++] = volume;
991 
992     connection->cmd_operands_length = pos;
993     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
994     return ERROR_CODE_SUCCESS;
995 }
996 
997 uint8_t avrcp_controller_query_shuffle_and_repeat_modes(uint16_t avrcp_cid){
998     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
999     if (!connection){
1000         log_error("avrcp_get_capabilities: could not find a connection.");
1001         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1002     }
1003     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
1004     connection->state = AVCTP_W2_SEND_COMMAND;
1005 
1006     connection->transaction_label++;
1007     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
1008     connection->command_type = AVRCP_CTYPE_STATUS;
1009     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
1010     connection->subunit_id = AVRCP_SUBUNIT_ID;
1011     big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID);
1012     connection->cmd_operands[3] = AVRCP_PDU_ID_GetCurrentPlayerApplicationSettingValue; // PDU ID
1013     connection->cmd_operands[4] = 0;
1014     big_endian_store_16(connection->cmd_operands, 5, 5); // parameter length
1015     connection->cmd_operands[7] = 4;                     // NumPlayerApplicationSettingAttributeID
1016     // PlayerApplicationSettingAttributeID1 AVRCP Spec, Appendix F, 133
1017     connection->cmd_operands[8]  = 0x01;    // equalizer  (1-OFF, 2-ON)
1018     connection->cmd_operands[9]  = 0x02;    // repeat     (1-off, 2-single track, 3-all tracks, 4-group repeat)
1019     connection->cmd_operands[10] = 0x03;    // shuffle    (1-off, 2-all tracks, 3-group shuffle)
1020     connection->cmd_operands[11] = 0x04;    // scan       (1-off, 2-all tracks, 3-group scan)
1021     connection->cmd_operands_length = 12;
1022     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1023     return ERROR_CODE_SUCCESS;
1024 }
1025 
1026 static uint8_t avrcp_controller_set_current_player_application_setting_value(uint16_t avrcp_cid, uint8_t attr_id, uint8_t attr_value){
1027     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
1028     if (!connection){
1029         log_error("avrcp_get_capabilities: could not find a connection.");
1030         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1031     }
1032     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
1033     connection->state = AVCTP_W2_SEND_COMMAND;
1034 
1035     connection->transaction_label++;
1036     connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
1037     connection->command_type = AVRCP_CTYPE_CONTROL;
1038     connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
1039     connection->subunit_id = AVRCP_SUBUNIT_ID;
1040     int pos = 0;
1041     big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID);
1042     pos += 3;
1043     connection->cmd_operands[pos++] = AVRCP_PDU_ID_SetPlayerApplicationSettingValue; // PDU ID
1044     connection->cmd_operands[pos++] = 0;
1045     // Parameter Length
1046     big_endian_store_16(connection->cmd_operands, pos, 3);
1047     pos += 2;
1048     connection->cmd_operands[pos++] = 2;
1049     connection->cmd_operands_length = pos;
1050     connection->cmd_operands[pos++]  = attr_id;
1051     connection->cmd_operands[pos++]  = attr_value;
1052     connection->cmd_operands_length = pos;
1053     avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
1054     return ERROR_CODE_SUCCESS;
1055 }
1056 
1057 uint8_t avrcp_controller_set_shuffle_mode(uint16_t avrcp_cid, avrcp_shuffle_mode_t mode){
1058     if (mode < AVRCP_SHUFFLE_MODE_OFF || mode > AVRCP_SHUFFLE_MODE_GROUP) return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
1059     return avrcp_controller_set_current_player_application_setting_value(avrcp_cid, 0x03, mode);
1060 }
1061 
1062 uint8_t avrcp_controller_set_repeat_mode(uint16_t avrcp_cid, avrcp_repeat_mode_t mode){
1063     if (mode < AVRCP_REPEAT_MODE_OFF || mode > AVRCP_REPEAT_MODE_GROUP) return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
1064     return avrcp_controller_set_current_player_application_setting_value(avrcp_cid, 0x02, mode);
1065 }
1066 
1067 uint8_t avrcp_controller_disconnect(uint16_t avrcp_cid){
1068     avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
1069     if (!connection){
1070         log_error("avrcp_get_capabilities: could not find a connection.");
1071         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
1072     }
1073     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
1074     l2cap_disconnect(connection->l2cap_signaling_cid, 0);
1075     return ERROR_CODE_SUCCESS;
1076 }