@@ -189,7 +189,10 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
189
189
struct usb_setup_packet * setup ;
190
190
int ret ;
191
191
uint8_t feature_id = 0xff ;
192
+ uint8_t intf ;
192
193
uint16_t volume_hex ;
194
+ uint16_t volume_max ;
195
+ uint16_t volume_add ;
193
196
194
197
if (!audio_class || !audio_class -> hport ) {
195
198
return - USB_ERR_INVAL ;
@@ -204,20 +207,87 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
204
207
for (uint8_t i = 0 ; i < audio_class -> stream_intf_num ; i ++ ) {
205
208
if (strcmp (name , audio_class -> as_msg_table [i ].stream_name ) == 0 ) {
206
209
feature_id = audio_class -> as_msg_table [i ].feature_terminal_id ;
210
+ intf = audio_class -> as_msg_table [i ].stream_intf ;
207
211
}
208
212
}
209
213
214
+ if (feature_id == 0xff ) {
215
+ return - USB_ERR_NODEV ;
216
+ }
217
+
218
+ setup -> bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE ;
219
+ setup -> bRequest = AUDIO_REQUEST_GET_CUR ;
220
+ setup -> wValue = (AUDIO_FU_CONTROL_VOLUME << 8 ) | ch ;
221
+ setup -> wIndex = (feature_id << 8 ) | audio_class -> ctrl_intf ;
222
+ setup -> wLength = 2 ;
223
+
224
+ ret = usbh_control_transfer (audio_class -> hport , setup , g_audio_buf );
225
+ if (ret < 0 ) {
226
+ return ret ;
227
+ }
228
+
229
+ memcpy (& audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].volume_cur , g_audio_buf , 2 );
230
+
231
+ setup -> bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE ;
232
+ setup -> bRequest = AUDIO_REQUEST_GET_MIN ;
233
+ setup -> wValue = (AUDIO_FU_CONTROL_VOLUME << 8 ) | ch ;
234
+ setup -> wIndex = (feature_id << 8 ) | audio_class -> ctrl_intf ;
235
+ setup -> wLength = 2 ;
236
+
237
+ ret = usbh_control_transfer (audio_class -> hport , setup , g_audio_buf );
238
+ if (ret < 0 ) {
239
+ return ret ;
240
+ }
241
+
242
+ memcpy (& audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].volume_min , g_audio_buf , 2 );
243
+
244
+ setup -> bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE ;
245
+ setup -> bRequest = AUDIO_REQUEST_GET_MAX ;
246
+ setup -> wValue = (AUDIO_FU_CONTROL_VOLUME << 8 ) | ch ;
247
+ setup -> wIndex = (feature_id << 8 ) | audio_class -> ctrl_intf ;
248
+ setup -> wLength = 2 ;
249
+
250
+ ret = usbh_control_transfer (audio_class -> hport , setup , g_audio_buf );
251
+ if (ret < 0 ) {
252
+ return ret ;
253
+ }
254
+ memcpy (& audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].volume_max , g_audio_buf , 2 );
255
+
256
+ setup -> bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE ;
257
+ setup -> bRequest = AUDIO_REQUEST_GET_RES ;
258
+ setup -> wValue = (AUDIO_FU_CONTROL_VOLUME << 8 ) | ch ;
259
+ setup -> wIndex = (feature_id << 8 ) | audio_class -> ctrl_intf ;
260
+ setup -> wLength = 2 ;
261
+
262
+ ret = usbh_control_transfer (audio_class -> hport , setup , g_audio_buf );
263
+ if (ret < 0 ) {
264
+ return ret ;
265
+ }
266
+ memcpy (& audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].volume_res , g_audio_buf , 2 );
267
+
210
268
setup -> bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE ;
211
269
setup -> bRequest = AUDIO_REQUEST_SET_CUR ;
212
270
setup -> wValue = (AUDIO_FU_CONTROL_VOLUME << 8 ) | ch ;
213
271
setup -> wIndex = (feature_id << 8 ) | audio_class -> ctrl_intf ;
214
272
setup -> wLength = 2 ;
215
273
216
- volume_hex = -0xDB00 / 100 * volume + 0xdb00 ;
274
+ /* change volume range start with zero */
275
+ volume_add = 0x10000 - audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].volume_min ;
276
+ volume_max = audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].volume_max + volume_add ;
277
+ volume_hex = volume * volume_max / 100.0 ;
217
278
218
- memcpy (g_audio_buf , & volume_hex , 2 );
219
- ret = usbh_control_transfer (audio_class -> hport , setup , NULL );
279
+ if (volume_hex >= volume_add ) {
280
+ volume_hex = volume_hex - volume_add ;
281
+ } else {
282
+ volume_hex = 0x10000 - (volume_add - volume_hex );
283
+ }
220
284
285
+ memcpy (g_audio_buf , & volume_hex , 2 );
286
+ ret = usbh_control_transfer (audio_class -> hport , setup , g_audio_buf );
287
+ if (ret < 0 ) {
288
+ return ret ;
289
+ }
290
+ audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].volume_cur = volume_hex ;
221
291
return ret ;
222
292
}
223
293
@@ -226,6 +296,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
226
296
struct usb_setup_packet * setup ;
227
297
int ret ;
228
298
uint8_t feature_id = 0xff ;
299
+ uint8_t intf = 0xff ;
229
300
230
301
if (!audio_class || !audio_class -> hport ) {
231
302
return - USB_ERR_INVAL ;
@@ -235,9 +306,14 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
235
306
for (uint8_t i = 0 ; i < audio_class -> stream_intf_num ; i ++ ) {
236
307
if (strcmp (name , audio_class -> as_msg_table [i ].stream_name ) == 0 ) {
237
308
feature_id = audio_class -> as_msg_table [i ].feature_terminal_id ;
309
+ intf = audio_class -> as_msg_table [i ].stream_intf ;
238
310
}
239
311
}
240
312
313
+ if (feature_id == 0xff ) {
314
+ return - USB_ERR_NODEV ;
315
+ }
316
+
241
317
setup -> bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE ;
242
318
setup -> bRequest = AUDIO_REQUEST_SET_CUR ;
243
319
setup -> wValue = (AUDIO_FU_CONTROL_MUTE << 8 ) | ch ;
@@ -246,7 +322,10 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_
246
322
247
323
memcpy (g_audio_buf , & mute , 1 );
248
324
ret = usbh_control_transfer (audio_class -> hport , setup , g_audio_buf );
249
-
325
+ if (ret < 0 ) {
326
+ return ret ;
327
+ }
328
+ audio_class -> as_msg_table [intf - audio_class -> ctrl_intf - 1 ].mute = mute ;
250
329
return ret ;
251
330
}
252
331
@@ -286,13 +365,14 @@ void usbh_audio_list_module(struct usbh_audio *audio_class)
286
365
static int usbh_audio_ctrl_connect (struct usbh_hubport * hport , uint8_t intf )
287
366
{
288
367
int ret ;
289
- uint8_t cur_iface = 0xff ;
290
- uint8_t cur_iface_count = 0xff ;
291
- uint8_t cur_alt_setting = 0xff ;
368
+ uint8_t cur_iface = 0 ;
369
+ uint8_t cur_iface_count = 0 ;
370
+ uint8_t cur_alt_setting = 0 ;
292
371
uint8_t input_offset = 0 ;
293
372
uint8_t output_offset = 0 ;
294
373
uint8_t feature_unit_offset = 0 ;
295
374
uint8_t * p ;
375
+ struct usbh_audio_ac_msg ac_msg_table [CONFIG_USBHOST_AUDIO_MAX_STREAMS ];
296
376
297
377
struct usbh_audio * audio_class = usbh_audio_class_alloc ();
298
378
if (audio_class == NULL ) {
@@ -327,26 +407,24 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
327
407
case AUDIO_CONTROL_INPUT_TERMINAL : {
328
408
struct audio_cs_if_ac_input_terminal_descriptor * desc = (struct audio_cs_if_ac_input_terminal_descriptor * )p ;
329
409
330
- memcpy (& audio_class -> ac_msg_table [input_offset ].ac_input , desc , sizeof (struct audio_cs_if_ac_input_terminal_descriptor ));
410
+ memcpy (& ac_msg_table [input_offset ].ac_input , desc , sizeof (struct audio_cs_if_ac_input_terminal_descriptor ));
331
411
input_offset ++ ;
332
412
} break ;
333
413
case AUDIO_CONTROL_OUTPUT_TERMINAL : {
334
414
struct audio_cs_if_ac_output_terminal_descriptor * desc = (struct audio_cs_if_ac_output_terminal_descriptor * )p ;
335
415
336
- memcpy (& audio_class -> ac_msg_table [output_offset ].ac_output , desc , sizeof (struct audio_cs_if_ac_output_terminal_descriptor ));
416
+ memcpy (& ac_msg_table [output_offset ].ac_output , desc , sizeof (struct audio_cs_if_ac_output_terminal_descriptor ));
337
417
output_offset ++ ;
338
418
} break ;
339
419
case AUDIO_CONTROL_FEATURE_UNIT : {
340
420
struct audio_cs_if_ac_feature_unit_descriptor * desc = (struct audio_cs_if_ac_feature_unit_descriptor * )p ;
341
421
342
- memcpy (& audio_class -> ac_msg_table [feature_unit_offset ].ac_feature_unit , desc , desc -> bLength );
422
+ memcpy (& ac_msg_table [feature_unit_offset ].ac_feature_unit , desc , desc -> bLength );
343
423
feature_unit_offset ++ ;
344
424
} break ;
345
- case AUDIO_CONTROL_PROCESSING_UNIT :
346
-
347
- break ;
348
425
default :
349
- break ;
426
+ USB_LOG_ERR ("Do not support %02x subtype\r\n" , p [DESC_bDescriptorSubType ]);
427
+ return - USB_ERR_NOTSUPP ;
350
428
}
351
429
} else if ((cur_iface > audio_class -> ctrl_intf ) && (cur_iface < (audio_class -> ctrl_intf + cur_iface_count ))) {
352
430
switch (p [DESC_bDescriptorSubType ]) {
@@ -383,7 +461,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
383
461
}
384
462
385
463
if ((input_offset != output_offset ) && (input_offset != feature_unit_offset )) {
386
- USB_LOG_ERR ("Audio descriptor is invalid\r\n" );
464
+ USB_LOG_ERR ("Audio control descriptor is invalid\r\n" );
465
+ return - USB_ERR_INVAL ;
466
+ }
467
+
468
+ if (cur_iface_count == 0xff ) {
469
+ USB_LOG_ERR ("Audio descriptor must have iad descriptor\r\n" );
387
470
return - USB_ERR_INVAL ;
388
471
}
389
472
@@ -392,21 +475,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
392
475
for (uint8_t i = 0 ; i < audio_class -> stream_intf_num ; i ++ ) {
393
476
/* Search 0x0101 in input or output desc */
394
477
for (uint8_t streamidx = 0 ; streamidx < audio_class -> stream_intf_num ; streamidx ++ ) {
395
- if (audio_class -> as_msg_table [i ].as_general .bTerminalLink == audio_class -> ac_msg_table [streamidx ].ac_input .bTerminalID ) {
478
+ if (audio_class -> as_msg_table [i ].as_general .bTerminalLink == ac_msg_table [streamidx ].ac_input .bTerminalID ) {
396
479
/* INPUT --> FEATURE UNIT --> OUTPUT */
397
- audio_class -> as_msg_table [i ].input_terminal_id = audio_class -> ac_msg_table [streamidx ].ac_input .bTerminalID ;
480
+ audio_class -> as_msg_table [i ].input_terminal_id = ac_msg_table [streamidx ].ac_input .bTerminalID ;
398
481
399
482
/* Search input terminal id in feature desc */
400
483
for (uint8_t featureidx = 0 ; featureidx < audio_class -> stream_intf_num ; featureidx ++ ) {
401
- if (audio_class -> ac_msg_table [streamidx ].ac_input .bTerminalID == audio_class -> ac_msg_table [featureidx ].ac_feature_unit .bSourceID ) {
402
- audio_class -> as_msg_table [i ].feature_terminal_id = audio_class -> ac_msg_table [featureidx ].ac_feature_unit .bUnitID ;
484
+ if (ac_msg_table [streamidx ].ac_input .bTerminalID == ac_msg_table [featureidx ].ac_feature_unit .bSourceID ) {
485
+ audio_class -> as_msg_table [i ].feature_terminal_id = ac_msg_table [featureidx ].ac_feature_unit .bUnitID ;
403
486
404
487
/* Search feature unit id in output desc */
405
488
for (uint8_t outputid = 0 ; outputid < audio_class -> stream_intf_num ; outputid ++ ) {
406
- if (audio_class -> ac_msg_table [featureidx ].ac_feature_unit .bUnitID == audio_class -> ac_msg_table [outputid ].ac_output .bSourceID ) {
407
- audio_class -> as_msg_table [i ].output_terminal_id = audio_class -> ac_msg_table [outputid ].ac_output .bTerminalID ;
489
+ if (ac_msg_table [featureidx ].ac_feature_unit .bUnitID == ac_msg_table [outputid ].ac_output .bSourceID ) {
490
+ audio_class -> as_msg_table [i ].output_terminal_id = ac_msg_table [outputid ].ac_output .bTerminalID ;
408
491
409
- switch (audio_class -> ac_msg_table [outputid ].ac_output .wTerminalType ) {
492
+ switch (ac_msg_table [outputid ].ac_output .wTerminalType ) {
410
493
case AUDIO_OUTTERM_SPEAKER :
411
494
audio_class -> as_msg_table [i ].stream_name = "speaker" ;
412
495
break ;
@@ -426,21 +509,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
426
509
break ;
427
510
}
428
511
}
429
- } else if (audio_class -> as_msg_table [i ].as_general .bTerminalLink == audio_class -> ac_msg_table [streamidx ].ac_output .bTerminalID ) {
512
+ } else if (audio_class -> as_msg_table [i ].as_general .bTerminalLink == ac_msg_table [streamidx ].ac_output .bTerminalID ) {
430
513
/* OUTPUT --> FEATURE UNIT --> INPUT */
431
- audio_class -> as_msg_table [i ].output_terminal_id = audio_class -> ac_msg_table [streamidx ].ac_output .bTerminalID ;
514
+ audio_class -> as_msg_table [i ].output_terminal_id = ac_msg_table [streamidx ].ac_output .bTerminalID ;
432
515
433
516
/* Search output terminal id in feature desc */
434
517
for (uint8_t featureidx = 0 ; featureidx < audio_class -> stream_intf_num ; featureidx ++ ) {
435
- if (audio_class -> ac_msg_table [streamidx ].ac_output .bSourceID == audio_class -> ac_msg_table [featureidx ].ac_feature_unit .bUnitID ) {
436
- audio_class -> as_msg_table [i ].feature_terminal_id = audio_class -> ac_msg_table [featureidx ].ac_feature_unit .bUnitID ;
518
+ if (ac_msg_table [streamidx ].ac_output .bSourceID == ac_msg_table [featureidx ].ac_feature_unit .bUnitID ) {
519
+ audio_class -> as_msg_table [i ].feature_terminal_id = ac_msg_table [featureidx ].ac_feature_unit .bUnitID ;
437
520
438
521
/* Search feature unit id in input desc */
439
522
for (uint8_t inputid = 0 ; inputid < audio_class -> stream_intf_num ; inputid ++ ) {
440
- if (audio_class -> ac_msg_table [featureidx ].ac_feature_unit .bSourceID == audio_class -> ac_msg_table [inputid ].ac_input .bTerminalID ) {
441
- audio_class -> as_msg_table [i ].input_terminal_id = audio_class -> ac_msg_table [inputid ].ac_input .bTerminalID ;
523
+ if (ac_msg_table [featureidx ].ac_feature_unit .bSourceID == ac_msg_table [inputid ].ac_input .bTerminalID ) {
524
+ audio_class -> as_msg_table [i ].input_terminal_id = ac_msg_table [inputid ].ac_input .bTerminalID ;
442
525
443
- switch (audio_class -> ac_msg_table [inputid ].ac_input .wTerminalType ) {
526
+ switch (ac_msg_table [inputid ].ac_input .wTerminalType ) {
444
527
case AUDIO_INTERM_MIC :
445
528
audio_class -> as_msg_table [i ].stream_name = "mic" ;
446
529
break ;
@@ -458,6 +541,13 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
458
541
}
459
542
}
460
543
544
+ for (uint8_t i = 0 ; i < audio_class -> stream_intf_num ; i ++ ) {
545
+ if (audio_class -> as_msg_table [i ].stream_name == NULL ) {
546
+ USB_LOG_ERR ("Audio stream search fail\r\n" );
547
+ return - USB_ERR_NODEV ;
548
+ }
549
+ }
550
+
461
551
for (uint8_t i = 0 ; i < audio_class -> stream_intf_num ; i ++ ) {
462
552
ret = usbh_audio_close (audio_class , audio_class -> as_msg_table [i ].stream_name );
463
553
if (ret < 0 ) {
0 commit comments