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