@@ -148,11 +148,34 @@ static void avrcp_subunit_info_req(struct bt_avrcp_tg *tg, uint8_t tid)
148
148
tg_tid = tid ;
149
149
}
150
150
151
+ static void avrcp_passthrough_cmd_req (struct bt_avrcp_tg * tg , uint8_t tid , bt_avrcp_opid_t opid ,
152
+ bt_avrcp_button_state_t state , const uint8_t * data ,
153
+ uint8_t len )
154
+ {
155
+ const char * state_str ;
156
+
157
+ /* Convert button state to string */
158
+ state_str = (state == BT_AVRCP_BUTTON_PRESSED ) ? "PRESSED" : "RELEASED" ;
159
+
160
+ bt_shell_print ("AVRCP passthrough command received: opid = 0x%02x (%s), tid=0x%02x, len=%u" ,
161
+ opid , state_str , tid , len );
162
+
163
+ if (len > 0U && data != NULL ) {
164
+ bt_shell_print ("Payload:" );
165
+ for (uint8_t i = 0U ; i < len ; i ++ ) {
166
+ bt_shell_print (" [%u]: 0x%02x" , i , data [i ]);
167
+ }
168
+ }
169
+
170
+ tg_tid = tid ;
171
+ }
172
+
151
173
static struct bt_avrcp_tg_cb app_avrcp_tg_cb = {
152
174
.connected = avrcp_tg_connected ,
153
175
.disconnected = avrcp_tg_disconnected ,
154
176
.unit_info_req = avrcp_unit_info_req ,
155
177
.subunit_info_req = avrcp_subunit_info_req ,
178
+ .passthrough_cmd_req = avrcp_passthrough_cmd_req ,
156
179
};
157
180
158
181
static int register_ct_cb (const struct shell * sh )
@@ -331,6 +354,93 @@ static int cmd_send_subunit_info_rsp(const struct shell *sh, int32_t argc, char
331
354
return 0 ;
332
355
}
333
356
357
+ static int cmd_send_passthrough_rsp (const struct shell * sh , int32_t argc , char * argv [])
358
+ {
359
+ bt_avrcp_opid_t opid ;
360
+ bt_avrcp_button_state_t state ;
361
+ uint16_t vu_opid = 0 ;
362
+ uint8_t is_op_vu = 0 ;
363
+ struct bt_avrcp_passthrough_opvu_data payload ;
364
+ char * endptr ;
365
+ unsigned long val ;
366
+ int err ;
367
+
368
+ if (!avrcp_tg_registered && register_tg_cb (sh ) != 0 ) {
369
+ return - ENOEXEC ;
370
+ }
371
+
372
+ if (default_tg == NULL ) {
373
+ shell_error (sh , "AVRCP TG is not connected" );
374
+ return - ENOEXEC ;
375
+ }
376
+
377
+ if (argc < 4 ) {
378
+ shell_print (sh , "Usage: send_passthrough_rsp <response> <op/opvu> <opid> <state>\n"
379
+ " op/opvu: passthrough command (normal/passthrough VENDOR UNIQUE)\n"
380
+ " opid: operation identifier (e.g., play/pause or hex value)\n"
381
+ " state: [pressed|released]" );
382
+ return - EINVAL ;
383
+ }
384
+
385
+ memset (& payload , 0 , sizeof (payload ));
386
+
387
+ if (!strcmp (argv [1 ], "op" )) {
388
+ is_op_vu = 0 ;
389
+ } else if (!strcmp (argv [1 ], "opvu" )) {
390
+ opid = BT_AVRCP_OPID_VENDOR_UNIQUE ;
391
+ is_op_vu = 1 ;
392
+ } else {
393
+ shell_error (sh , "Invalid response: %s" , argv [2 ]);
394
+ return - EINVAL ;
395
+ }
396
+
397
+ if (!strcmp (argv [2 ], "play" )) {
398
+ opid = BT_AVRCP_OPID_PLAY ;
399
+ vu_opid = (uint16_t )opid ;
400
+ } else if (!strcmp (argv [2 ], "pause" )) {
401
+ opid = BT_AVRCP_OPID_PAUSE ;
402
+ vu_opid = (uint16_t )opid ;
403
+ } else {
404
+ /* Try to parse as hex value */
405
+ val = strtoul (argv [2 ], & endptr , 16 );
406
+ if (* endptr != '\0' || val > 0xFFFFU ) {
407
+ shell_error (sh , "Invalid opid: %s" , argv [2 ]);
408
+ return - EINVAL ;
409
+ }
410
+ if (is_op_vu == 1 ) {
411
+ vu_opid = (uint16_t )val ;
412
+ } else {
413
+ opid = (bt_avrcp_opid_t )val ;
414
+ }
415
+ }
416
+
417
+ if (!strcmp (argv [3 ], "pressed" )) {
418
+ state = BT_AVRCP_BUTTON_PRESSED ;
419
+ } else if (!strcmp (argv [3 ], "released" )) {
420
+ state = BT_AVRCP_BUTTON_RELEASED ;
421
+ } else {
422
+ shell_error (sh , "Invalid state: %s" , argv [3 ]);
423
+ return - EINVAL ;
424
+ }
425
+
426
+ if (is_op_vu == 1 ) {
427
+ sys_put_be24 (BT_AVRCP_COMPANY_ID_BLUETOOTH_SIG , payload .company_id );
428
+ payload .op_len = 5U ;
429
+ payload .opid_vu = vu_opid ;
430
+ }
431
+
432
+ err = bt_avrcp_tg_send_passthrough_rsp (default_tg , tg_tid , BT_AVRCP_RSP_ACCEPTED , opid , state ,
433
+ payload .op_len ? (const uint8_t * )& payload : NULL ,
434
+ payload .op_len );
435
+ if (err ) {
436
+ shell_error (sh , "Failed to send passthrough response: %d" , err );
437
+ } else {
438
+ shell_print (sh , "Passthrough opid=0x%02x, state=%s" , opid , argv [2 ]);
439
+ }
440
+
441
+ return err ;
442
+ }
443
+
334
444
static int cmd_get_subunit_info (const struct shell * sh , int32_t argc , char * argv [])
335
445
{
336
446
if (!avrcp_ct_registered && register_ct_cb (sh ) != 0 ) {
@@ -415,6 +525,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
415
525
SHELL_CMD_ARG (send_unit_rsp , NULL , "send unit info response" , cmd_send_unit_info_rsp , 1 , 0 ),
416
526
SHELL_CMD_ARG (send_subunit_rsp , NULL , "send subunit info response" ,
417
527
cmd_send_subunit_info_rsp , 1 , 0 ),
528
+ SHELL_CMD_ARG (send_passthrough_rsp , NULL ,
529
+ "send_passthrough_rsp <response> <op/opvu> <opid> <state>" ,
530
+ cmd_send_passthrough_rsp , 4 , 0 ),
418
531
SHELL_SUBCMD_SET_END );
419
532
420
533
static int cmd_avrcp (const struct shell * sh , size_t argc , char * * argv )
0 commit comments