| M480 BSP V3.05.001 The Board Support Package for M480 Series

uac_core.c
Go to the documentation of this file.
1 /**************************************************************************/
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "NuMicro.h"
14
15 #include "usb.h"
16 #include "usbh_lib.h"
17 #include "usbh_uac.h"
18 #include "uac.h"
19
20
44 int usbh_uac_get_channel_number(UAC_DEV_T *uac, uint8_t target)
45 {
46 AS_FT1_T *ft;
47
48 if (target == UAC_SPEAKER)
49 ft = uac->asif_out.ft;
50 else
51 ft = uac->asif_in.ft;
52
53 if (!ft)
54 return UAC_RET_DEV_NOT_SUPPORTED;
55
56 return ft->bNrChannels;
57 }
58
59
71 int usbh_uac_get_bit_resolution(UAC_DEV_T *uac, uint8_t target, uint8_t *byte_cnt)
72 {
73 AS_FT1_T *ft;
74
75 if (target == UAC_SPEAKER)
76 ft = uac->asif_out.ft;
77 else
78 ft = uac->asif_in.ft;
79
80 if (!ft)
81 return UAC_RET_DEV_NOT_SUPPORTED;
82
83 *byte_cnt = ft->bSubframeSize;
84
85 return ft->bBitResolution;
86 }
87
88
90
91 uint32_t srate_to_u32(uint8_t *srate)
92 {
93 return (srate[2] << 16) | (srate[1] << 8) | srate[0];
94 }
95
97
98
116 int usbh_uac_get_sampling_rate(UAC_DEV_T *uac, uint8_t target, uint32_t *srate_list,
117 int max_cnt, uint8_t *type)
118 {
119 AS_FT1_T *ft;
120 int i;
121
122 if (target == UAC_SPEAKER)
123 ft = uac->asif_out.ft;
124 else
125 ft = uac->asif_in.ft;
126
127 if (!ft)
128 return UAC_RET_DEV_NOT_SUPPORTED;
129
130 *type = ft->bSamFreqType;
131
132 if (*type == 0)
133 {
134 if (max_cnt < 2)
135 return UAC_RET_OUT_OF_MEMORY;
136
137 srate_list[0] = srate_to_u32(&ft->tSamFreq[0][0]);
138 srate_list[1] = srate_to_u32(&ft->tSamFreq[1][0]);
139 }
140 else
141 {
142 for (i = 0; i < *type; i++)
143 srate_list[i] = srate_to_u32(&ft->tSamFreq[i][0]);
144 }
145 return 0;
146 }
147
148
169 int usbh_uac_sampling_rate_control(UAC_DEV_T *uac, uint8_t target, uint8_t req, uint32_t *srate)
170 {
171 EP_INFO_T *ep;
172 uint8_t bmRequestType;
173 uint8_t tSampleFreq[3];
174 uint32_t xfer_len;
175 int ret;
176
177 if (target == UAC_SPEAKER)
178 ep = uac->asif_out.ep;
179 else
180 ep = uac->asif_in.ep;
181
182 if (ep == NULL)
183 return UAC_RET_DEV_NOT_SUPPORTED;
184
185 tSampleFreq[0] = *srate & 0xff;
186 tSampleFreq[1] = (*srate >> 8) & 0xff;
187 tSampleFreq[2] = (*srate >> 16) & 0xff;
188
189 if (req & 0x80)
190 bmRequestType = REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_EP;
191 else
192 bmRequestType = REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_EP;
193
194 /* Audio Class Request - Endpoint Control Requests (5.2.3.2) */
195 ret = usbh_ctrl_xfer(uac->udev, bmRequestType, req,
196 (SAMPLING_FREQ_CONTROL << 8), /* wValue - Control Selector (CS) */
197 ep->bEndpointAddress, /* wIndex - endpoint */
198 3, /* wLength - parameter block length */
199 tSampleFreq, /* parameter block */
200 &xfer_len, UAC_REQ_TIMEOUT);
201 if (ret < 0)
202 return ret;
203
204 if (xfer_len != 3)
205 return UAC_RET_DATA_LEN;
206
207 *srate = srate_to_u32(tSampleFreq);
208 return 0;
209 }
210
211
240 int usbh_uac_mute_control(UAC_DEV_T *uac, uint8_t target, uint8_t req, uint16_t chn, uint8_t *mute)
241 {
242 uint8_t bmRequestType;
243 uint8_t bUnitID;
244 uint32_t xfer_len;
245 int ret;
246
247 if (target == UAC_MICROPHONE)
248 bUnitID = uac->acif.mic_fuid;
249 else
250 bUnitID = uac->acif.speaker_fuid;
251
252 if (req & 0x80)
253 bmRequestType = REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE;
254 else
255 bmRequestType = REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE;
256
257 /* Audio Class Request - Feature Unit Control Request (5.2.2.4) */
258 ret = usbh_ctrl_xfer(uac->udev, bmRequestType, req,
259 (MUTE_CONTROL << 8) | chn, /* wValue - Control Selector (CS) */
260 (bUnitID << 8) | (uac->acif.iface->if_num), /* wIndex - unit ID and interface number */
261 1, /* wLength - parameter block length */
262 mute, /* parameter block */
263 &xfer_len, UAC_REQ_TIMEOUT);
264 if (ret < 0)
265 return ret;
266
267 if (xfer_len != 1)
268 return UAC_RET_DATA_LEN;
269
270 return 0;
271 }
272
273
323 int usbh_uac_vol_control(UAC_DEV_T *uac, uint8_t target, uint8_t req, uint16_t chn, uint16_t *volume)
324 {
325 uint8_t bmRequestType;
326 uint8_t bUnitID;
327 uint32_t xfer_len;
328 int ret;
329
330 if (target == UAC_MICROPHONE)
331 bUnitID = uac->acif.mic_fuid;
332 else
333 bUnitID = uac->acif.speaker_fuid;
334
335 if (req & 0x80)
336 bmRequestType = REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE;
337 else
338 bmRequestType = REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE;
339
340 /* Audio Class Request - Feature Unit Control Request (5.2.2.4) */
341 ret = usbh_ctrl_xfer(uac->udev, bmRequestType, req,
342 (VOLUME_CONTROL << 8) | chn,/* wValue - Control Selector (CS) */
343 (bUnitID << 8) | (uac->acif.iface->if_num), /* wIndex - unit ID and interface number */
344 2, /* wLength - parameter block length */
345 (uint8_t *)volume, /* parameter block */
346 &xfer_len, UAC_REQ_TIMEOUT);
347 if (ret < 0)
348 return ret;
349
350 if (xfer_len != 2)
351 return UAC_RET_DATA_LEN;
352
353 return 0;
354 }
355
356
385 int usbh_uac_auto_gain_control(UAC_DEV_T *uac, uint8_t target, uint8_t req, uint16_t chn, uint8_t *bAGC)
386 {
387 uint8_t bmRequestType;
388 uint8_t bUnitID;
389 uint32_t xfer_len;
390 int ret;
391
392 if (target == UAC_MICROPHONE)
393 bUnitID = uac->acif.mic_fuid;
394 else
395 bUnitID = uac->acif.speaker_fuid;
396
397 if (req & 0x80)
398 bmRequestType = REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE;
399 else
400 bmRequestType = REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE;
401
402 /* Audio Class Request - Feature Unit Control Request (5.2.2.4) */
403 ret = usbh_ctrl_xfer(uac->udev, bmRequestType, req,
404 (AUTOMATIC_GAIN_CONTROL << 8) | chn, /* wValue - Control Selector (CS) */
405 (bUnitID << 8) | (uac->acif.iface->if_num), /* wIndex - unit ID and interface number */
406 1, /* wLength - parameter block length */
407 bAGC, /* parameter block */
408 &xfer_len, UAC_REQ_TIMEOUT);
409 if (ret < 0)
410 return ret;
411
412 if (xfer_len != 1)
413 return UAC_RET_DATA_LEN;
414
415 return 0;
416 }
417
418
420
431 int usbh_uac_find_max_alt(IFACE_T *iface, uint8_t dir, uint8_t attr, uint8_t *bAlternateSetting)
432 {
433 EP_INFO_T *ep;
434 uint8_t i, j;
435 uint16_t wMaxPacketSize = 0;
436
437 for (i = 0; i < iface->num_alt; i++)
438 {
439 for (j = 0; j < iface->alt[i].ifd->bNumEndpoints; j++)
440 {
441 ep = &(iface->alt[i].ep[j]); /* get endpoint */
442
443 if (((ep->bEndpointAddress & EP_ADDR_DIR_MASK) != dir) ||
444 ((ep->bmAttributes & EP_ATTR_TT_MASK) != attr))
445 continue; /* not interested endpoint */
446
447 if (ep->wMaxPacketSize > wMaxPacketSize)
448 {
449 /* a better candidate endpoint found */
450 *bAlternateSetting = i;
451 wMaxPacketSize = ep->wMaxPacketSize;
452 }
453 }
454 }
455 if (wMaxPacketSize == 0)
456 return USBH_ERR_NOT_FOUND;
457
458 return 0;
459 }
460
472 int usbh_uac_find_best_alt(IFACE_T *iface, uint8_t dir, uint8_t attr, int pkt_sz, uint8_t *bAlternateSetting)
473 {
474 EP_INFO_T *ep;
475 uint8_t i, j;
476 uint16_t wMaxPacketSize = 0xFFFF;
477
478 for (i = 0; i < iface->num_alt; i++)
479 {
480 for (j = 0; j < iface->alt[i].ifd->bNumEndpoints; j++)
481 {
482 ep = &(iface->alt[i].ep[j]); /* get endpoint */
483
484 if (((ep->bEndpointAddress & EP_ADDR_DIR_MASK) != dir) ||
485 ((ep->bmAttributes & EP_ATTR_TT_MASK) != attr))
486 continue; /* not interested endpoint */
487
488 if ((ep->wMaxPacketSize >= pkt_sz) && (ep->wMaxPacketSize < wMaxPacketSize))
489 {
490 /* a better candidate endpoint found */
491 *bAlternateSetting = i;
492 wMaxPacketSize = ep->wMaxPacketSize;
493 }
494 }
495 }
496 if (wMaxPacketSize == 0xFFFF)
497 {
498 UAC_DBGMSG("Audio interface %d cannot find endpoint with wMaxPacketSize >= %d!\n", iface->if_num, pkt_sz);
499 return USBH_ERR_NOT_FOUND;
500 }
501 return 0;
502 }
503
504
505 static void iso_in_irq(UTR_T *utr)
506 {
507 UAC_DEV_T *uac = (UAC_DEV_T *)utr->context;
508 int i, ret;
509
510 /* We don't want to do anything if we are about to be removed! */
511 if (!uac || !uac->udev)
512 return;
513
514 if (uac->asif_in.flag_streaming == 0)
515 return;
516
517 //UAC_DBGMSG("SF=%d, 0x%x\n", utr->iso_sf, (int)utr);
518
519 utr->bIsoNewSched = 0;
520
521 for (i = 0; i < IF_PER_UTR; i++)
522 {
523 if (utr->iso_status[i] == 0)
524 {
525 if ((uac->func_au_in != NULL) && (utr->iso_xlen[i] > 0))
526 uac->func_au_in(uac, utr->iso_buff[i], utr->iso_xlen[i]);
527 }
528 else
529 {
530 UAC_DBGMSG("Iso %d err - %d\n", i, utr->iso_status[i]);
531 if ((utr->iso_status[i] == USBH_ERR_NOT_ACCESS0) || (utr->iso_status[i] == USBH_ERR_NOT_ACCESS1))
532 utr->bIsoNewSched = 1;
533 }
534 utr->iso_xlen[i] = utr->ep->wMaxPacketSize;
535 }
536
537 /* schedule the following isochronous transfers */
538 ret = usbh_iso_xfer(utr);
539 if (ret < 0)
540 UAC_DBGMSG("usbh_iso_xfer failed!\n");
541 }
542
544
545
554 int usbh_uac_start_audio_in(UAC_DEV_T *uac, UAC_CB_FUNC *func)
555 {
556 UDEV_T *udev = uac->udev;
557 AS_IF_T *asif = &uac->asif_in;
558 IFACE_T *iface = uac->asif_in.iface;
559 ALT_IFACE_T *aif;
560 EP_INFO_T *ep;
561 UTR_T *utr;
562 uint8_t *buff;
563 uint8_t bAlternateSetting;
564 int i, j, ret;
565
566 if (!uac || !iface)
567 return UAC_RET_DEV_NOT_FOUND;
568
569 if (asif->flag_streaming)
570 return UAC_RET_IS_STREAMING;
571
572 /*------------------------------------------------------------------------------------*/
573 /* Select the maximum packet size alternative interface */
574 /*------------------------------------------------------------------------------------*/
575 if (usbh_uac_find_max_alt(iface, EP_ADDR_DIR_IN, EP_ATTR_TT_ISO, &bAlternateSetting) != 0)
576 return UAC_RET_FUNC_NOT_FOUND;
577
578 uac->func_au_in = func;
579
580 ret = usbh_set_interface(iface, bAlternateSetting);
581 if (ret < 0)
582 {
583 UAC_ERRMSG("Failed to set interface %d, %d! (%d)\n", iface->if_num, bAlternateSetting, ret);
584 return ret;
585 }
586
587 ret = uac_parse_streaming_interface(uac, iface, bAlternateSetting);
588 if (ret < 0)
589 return ret;
590
591 /*------------------------------------------------------------------------------------*/
592 /* Find the endpoint */
593 /*------------------------------------------------------------------------------------*/
594 asif->ep = NULL;
595 aif = asif->iface->aif;
596 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
597 {
598 ep = &(aif->ep[i]);
599
600 if (((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN) &&
601 ((ep->bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_ISO))
602 {
603 asif->ep = ep;
604 UAC_DBGMSG("Audio in endpoint 0x%x found, size: %d\n", ep->bEndpointAddress, ep->wMaxPacketSize);
605 break;
606 }
607 }
608 if (asif->ep == NULL)
609 return UAC_RET_FUNC_NOT_FOUND;
610 ep = asif->ep;
611
612 #ifdef UAC_DEBUG
613 UAC_DBGMSG("Activated isochronous-in endpoint =>");
614 usbh_dump_ep_info(ep);
615 #endif
616
617 /*------------------------------------------------------------------------------------*/
618 /* Allocate isochronous in buffer */
619 /*------------------------------------------------------------------------------------*/
620 for (i = 0; i < NUM_UTR; i++) /* allocate UTRs */
621 {
622 asif->utr[i] = alloc_utr(udev); /* allocate UTR */
623 if (asif->utr[i] == NULL)
624 {
625 ret = USBH_ERR_MEMORY_OUT; /* memory allocate failed */
626 goto err_out; /* abort */
627 }
628 }
629
630 buff = (uint8_t *)usbh_alloc_mem(ep->wMaxPacketSize * IF_PER_UTR * NUM_UTR);
631 if (buff == NULL)
632 {
633 ret = USBH_ERR_MEMORY_OUT; /* memory allocate failed */
634 goto err_out; /* abort */
635 }
636
637 for (i = 0; i < NUM_UTR; i++) /* dispatch buffers */
638 {
639 /* divide buffer equally */
640 utr = asif->utr[i];
641 utr->buff = buff + (ep->wMaxPacketSize * IF_PER_UTR * i);
642 utr->data_len = ep->wMaxPacketSize * IF_PER_UTR;
643 for (j = 0; j < IF_PER_UTR; j++)
644 {
645 utr->iso_xlen[j] = ep->wMaxPacketSize;
646 utr->iso_buff[j] = utr->buff + (ep->wMaxPacketSize * j);
647 }
648 }
649
650 /*------------------------------------------------------------------------------------*/
651 /* Start UTRs */
652 /*------------------------------------------------------------------------------------*/
653
654 asif->utr[0]->bIsoNewSched = 1;
655
656 for (i = 0; i < NUM_UTR; i++)
657 {
658 utr = asif->utr[i];
659 utr->context = uac;
660 utr->ep = ep;
661 utr->func = iso_in_irq;
662 ret = usbh_iso_xfer(utr);
663 if (ret < 0)
664 {
665 UAC_DBGMSG("Error - failed to start UTR %d isochronous-in transfer (%d)", i, ret);
666 goto err_out;
667 }
668 }
669 asif->flag_streaming = 1;
670 uac->state = UAC_STATE_RUNNING;
671
672 return UAC_RET_OK;
673
674 err_out:
675
676 for (i = 0; i < NUM_UTR; i++) /* quit all UTRs */
677 {
678 if (asif->utr[i])
679 usbh_quit_utr(asif->utr[i]);
680 }
681 asif->flag_streaming = 0;
682 /* free USB transfer buffer */
683 if ((asif->utr[0] != NULL) &&
684 (asif->utr[0]->buff != NULL))
685 usbh_free_mem(asif->utr[0]->buff, asif->utr[0]->data_len * NUM_UTR);
686
687 for (i = 0; i < NUM_UTR; i++) /* free all UTRs */
688 {
689 if (asif->utr[i])
690 free_utr(asif->utr[i]);
691 asif->utr[i] = NULL;
692 }
693 return ret;
694 }
695
703 int usbh_uac_stop_audio_in(UAC_DEV_T *uac)
704 {
705 AS_IF_T *asif = &uac->asif_in;
706 int i, ret;
707
708 asif->flag_streaming = 0;
709
710 /* Set interface alternative settings */
711 if (uac->state != UAC_STATE_DISCONNECTING)
712 {
713 ret = usbh_set_interface(asif->iface, 0);
714 if (ret < 0)
715 {
716 UAC_ERRMSG("Failed to set interface %d, %d! (%d)\n", asif->iface->if_num, 0, ret);
717 }
718 }
719
720 for (i = 0; i < NUM_UTR; i++) /* stop all UTRs */
721 {
722 if (asif->utr[i])
723 usbh_quit_utr(asif->utr[i]);
724 }
725
726 if ((asif->utr[0] != NULL) &&
727 (asif->utr[0]->buff != NULL)) /* free audio buffer */
728 usbh_free_mem(asif->utr[0]->buff, asif->utr[0]->data_len * NUM_UTR);
729
730 for (i = 0; i < NUM_UTR; i++) /* free all UTRs */
731 {
732 if (asif->utr[i])
733 free_utr(asif->utr[i]);
734 asif->utr[i] = NULL;
735 }
736
737 if (uac->state != UAC_STATE_DISCONNECTING)
738 {
739 if ((uac->asif_out.iface == NULL) || (uac->asif_out.flag_streaming == 0))
740 {
741 uac->state = UAC_STATE_READY;
742 }
743 }
744
745 return UAC_RET_OK;
746 }
747
748
750
751 static void iso_out_irq(UTR_T *utr)
752 {
753 UAC_DEV_T *uac = (UAC_DEV_T *)utr->context;
754 int i, ret;
755
756 /* We don't want to do anything if we are about to be removed! */
757 if (!uac || !uac->udev)
758 return;
759
760 if (uac->asif_out.flag_streaming == 0)
761 return;
762
763 //UAC_DBGMSG("SF=%d, 0x%x\n", utr->iso_sf, (int)utr);
764
765 utr->bIsoNewSched = 0;
766
767 for (i = 0; i < IF_PER_UTR; i++)
768 {
769 if (utr->iso_status[i] != 0)
770 {
771 // UAC_DBGMSG("Iso %d err - %d\n", i, utr->iso_status[i]);
772 if ((utr->iso_status[i] == USBH_ERR_NOT_ACCESS0) || (utr->iso_status[i] == USBH_ERR_NOT_ACCESS1))
773 utr->bIsoNewSched = 1;
774 }
775 utr->iso_xlen[i] = uac->func_au_out(uac, utr->iso_buff[i], utr->ep->wMaxPacketSize);
776 }
777
778 /* schedule the following isochronous transfers */
779 ret = usbh_iso_xfer(utr);
780 if (ret < 0)
781 UAC_DBGMSG("usbh_iso_xfer failed!\n");
782 }
783
785
786
796 int usbh_uac_start_audio_out(UAC_DEV_T *uac, UAC_CB_FUNC *func)
797 {
798 UDEV_T *udev = uac->udev;
799 AS_IF_T *asif = &uac->asif_out;
800 IFACE_T *iface = uac->asif_out.iface;
801 ALT_IFACE_T *aif;
802 EP_INFO_T *ep;
803 UTR_T *utr;
804 uint8_t *buff;
805 uint8_t bAlternateSetting;
806 int i, j, ret;
807
808 if (!uac || !func || !iface)
809 return UAC_RET_DEV_NOT_FOUND;
810
811 if (asif->flag_streaming)
812 return UAC_RET_IS_STREAMING;
813
814 /*------------------------------------------------------------------------------------*/
815 /* Select the maximum packet size alternative interface */
816 /*------------------------------------------------------------------------------------*/
817 if (usbh_uac_find_max_alt(iface, EP_ADDR_DIR_OUT, EP_ATTR_TT_ISO, &bAlternateSetting) != 0)
818 return UAC_RET_FUNC_NOT_FOUND;
819
820 uac->func_au_out = func;
821
822 ret = usbh_set_interface(iface, bAlternateSetting);
823 if (ret < 0)
824 {
825 UAC_ERRMSG("Failed to set interface %d, %d! (%d)\n", iface->if_num, bAlternateSetting, ret);
826 return ret;
827 }
828
829 ret = uac_parse_streaming_interface(uac, iface, bAlternateSetting);
830 if (ret < 0)
831 return ret;
832
833 /*------------------------------------------------------------------------------------*/
834 /* Find the endpoint */
835 /*------------------------------------------------------------------------------------*/
836 asif->ep = NULL;
837 aif = asif->iface->aif;
838 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
839 {
840 ep = &(aif->ep[i]);
841
842 if (((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT) &&
843 ((ep->bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_ISO))
844 {
845 asif->ep = ep;
846 UAC_DBGMSG("Audio in endpoint 0x%x found, size: %d\n", ep->bEndpointAddress, ep->wMaxPacketSize);
847 break;
848 }
849 }
850 if (asif->ep == NULL)
851 return UAC_RET_FUNC_NOT_FOUND;
852 ep = asif->ep;
853
854 #ifdef UAC_DEBUG
855 UAC_DBGMSG("Activated isochronous-out endpoint =>");
856 usbh_dump_ep_info(ep);
857 #endif
858
859 /*------------------------------------------------------------------------------------*/
860 /* Allocate isochronous in buffer */
861 /*------------------------------------------------------------------------------------*/
862 for (i = 0; i < NUM_UTR; i++) /* allocate UTRs */
863 {
864 asif->utr[i] = alloc_utr(udev); /* allocate UTR */
865 if (asif->utr[i] == NULL)
866 {
867 ret = USBH_ERR_MEMORY_OUT; /* memory allocate failed */
868 goto err_out; /* abort */
869 }
870 }
871
872 buff = (uint8_t *)usbh_alloc_mem(ep->wMaxPacketSize * IF_PER_UTR * NUM_UTR);
873 if (buff == NULL)
874 {
875 ret = USBH_ERR_MEMORY_OUT; /* memory allocate failed */
876 goto err_out; /* abort */
877 }
878
879 for (i = 0; i < NUM_UTR; i++) /* dispatch buffers */
880 {
881 /* divide buffer equally */
882 asif->utr[i]->buff = buff + (ep->wMaxPacketSize * IF_PER_UTR * i);
883 asif->utr[i]->data_len = ep->wMaxPacketSize * IF_PER_UTR;
884 }
885
886 /*------------------------------------------------------------------------------------*/
887 /* Start UTRs */
888 /*------------------------------------------------------------------------------------*/
889
890 asif->utr[0]->bIsoNewSched = 1;
891
892 for (i = 0; i < NUM_UTR; i++)
893 {
894 utr = asif->utr[i];
895 utr->context = uac;
896 utr->ep = ep;
897 utr->func = iso_out_irq;
898
899 for (j = 0; j < IF_PER_UTR; j++) /* get audio out data from user */
900 {
901 utr->iso_buff[j] = utr->buff + (ep->wMaxPacketSize * j);
902 utr->iso_xlen[j] = uac->func_au_out(uac, utr->iso_buff[j], ep->wMaxPacketSize);
903 }
904
905 ret = usbh_iso_xfer(utr);
906 if (ret < 0)
907 {
908 UAC_DBGMSG("Error - failed to start UTR %d isochronous-in transfer (%d)", i, ret);
909 goto err_out;
910 }
911 }
912 asif->flag_streaming = 1;
913 uac->state = UAC_STATE_RUNNING;
914
915 return UAC_RET_OK;
916
917 err_out:
918
919 for (i = 0; i < NUM_UTR; i++) /* quit all UTRs */
920 {
921 if (asif->utr[i])
922 usbh_quit_utr(asif->utr[i]);
923 }
924 asif->flag_streaming = 0;
925
926 if ((asif->utr[0] != NULL) && /* free USB transfer buffer */
927 (asif->utr[0]->buff != NULL))
928 usbh_free_mem(asif->utr[0]->buff, asif->utr[0]->data_len * NUM_UTR);
929
930 for (i = 0; i < NUM_UTR; i++) /* free all UTRs */
931 {
932 if (asif->utr[i])
933 free_utr(asif->utr[i]);
934 asif->utr[i] = NULL;
935 }
936 return ret;
937 }
938
946 int usbh_uac_stop_audio_out(UAC_DEV_T *uac)
947 {
948 AS_IF_T *asif = &uac->asif_out;
949 int i, ret;
950
951 /* Set interface alternative settings */
952 if (uac->state != UAC_STATE_DISCONNECTING)
953 {
954 ret = usbh_set_interface(asif->iface, 0);
955 if (ret < 0)
956 {
957 UAC_ERRMSG("Failed to set interface %d, %d! (%d)\n", asif->iface->if_num, 0, ret);
958 }
959 }
960
961 for (i = 0; i < NUM_UTR; i++) /* stop all UTRs */
962 {
963 if (asif->utr[i])
964 usbh_quit_utr(asif->utr[i]);
965 }
966
967 if ((asif->utr[0] != NULL) &&
968 (asif->utr[0]->buff != NULL)) /* free audio buffer */
969 usbh_free_mem(asif->utr[0]->buff, asif->utr[0]->data_len * NUM_UTR);
970
971 for (i = 0; i < NUM_UTR; i++) /* free all UTRs */
972 {
973 if (asif->utr[i])
974 free_utr(asif->utr[i]);
975 asif->utr[i] = NULL;
976 }
977
978 if (uac->state != UAC_STATE_DISCONNECTING)
979 {
980 if ((uac->asif_in.iface == NULL) || (uac->asif_in.flag_streaming == 0))
981 {
982 uac->state = UAC_STATE_READY;
983 }
984 }
985 asif->flag_streaming = 0;
986
987 return UAC_RET_OK;
988 }
989
997 int usbh_uac_open(UAC_DEV_T *uac)
998 {
999 IFACE_T *iface;
1000 uint8_t bAlternateSetting;
1001 int ret;
1002
1003 /*------------------------------------------------------------------------------------*/
1004 /* Select the maximum packet size alternative interface */
1005 /*------------------------------------------------------------------------------------*/
1006 iface = uac->asif_in.iface;
1007
1008 if (iface != NULL)
1009 {
1010 if (usbh_uac_find_max_alt(iface, EP_ADDR_DIR_IN, EP_ATTR_TT_ISO, &bAlternateSetting) != 0)
1011 return UAC_RET_FUNC_NOT_FOUND;
1012
1013 ret = usbh_set_interface(iface, bAlternateSetting);
1014 if (ret < 0)
1015 {
1016 UAC_ERRMSG("Failed to set interface %d, %d! (%d)\n", iface->if_num, bAlternateSetting, ret);
1017 return ret;
1018 }
1019 }
1020
1021 /*------------------------------------------------------------------------------------*/
1022 /* Select the maximum packet size alternative interface */
1023 /*------------------------------------------------------------------------------------*/
1024 iface = uac->asif_out.iface;
1025
1026 if (iface != NULL)
1027 {
1028 if (usbh_uac_find_max_alt(iface, EP_ADDR_DIR_OUT, EP_ATTR_TT_ISO, &bAlternateSetting) != 0)
1029 return UAC_RET_FUNC_NOT_FOUND;
1030
1031 ret = usbh_set_interface(iface, bAlternateSetting);
1032 if (ret < 0)
1033 {
1034 UAC_ERRMSG("Failed to set interface %d, %d! (%d)\n", iface->if_num, bAlternateSetting, ret);
1035 return ret;
1036 }
1037 }
1038 return 0;
1039 }
1040 /* end of group USBH_EXPORTED_FUNCTIONS */
1042 /* end of group USBH_Library */
1044 /* end of group LIBRARY */
1046
1047 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
1048
uac_dev_t::state
UAC_STATE_E state
Definition: usbh_uac.h:118
USBH_ERR_NOT_FOUND
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
usbh_uac.h
USB Host UAC class driver header file.
UAC_RET_DEV_NOT_FOUND
#define UAC_RET_DEV_NOT_FOUND
Definition: usbh_lib.h:97
UAC_CB_FUNC
int() UAC_CB_FUNC(struct uac_dev_t *dev, uint8_t *data, int len)
Definition: usbh_lib.h:127
UAC_REQ_TIMEOUT
#define UAC_REQ_TIMEOUT
Definition: usbh_uac.h:33
as_if_t::flag_streaming
uint8_t flag_streaming
Definition: usbh_uac.h:102
usbh_uac_get_channel_number
int usbh_uac_get_channel_number(struct uac_dev_t *audev, uint8_t target)
Obtain Audio Class device's channel number.
Definition: uac_core.c:44
usbh_uac_stop_audio_in
int usbh_uac_stop_audio_in(struct uac_dev_t *audev)
Stop UAC device audio in data stream.
Definition: uac_core.c:703
UAC_SPEAKER
#define UAC_SPEAKER
Definition: usbh_uac.h:35
as_if_t::ft
AS_FT1_T * ft
Definition: usbh_uac.h:100
NuMicro.h
NuMicro peripheral access layer header file.
USBH_ERR_NOT_ACCESS0
#define USBH_ERR_NOT_ACCESS0
Definition: usbh_lib.h:68
USBH_ERR_NOT_ACCESS1
#define USBH_ERR_NOT_ACCESS1
Definition: usbh_lib.h:69
ac_if_t::iface
IFACE_T * iface
Definition: usbh_uac.h:82
as_if_t::utr
UTR_T * utr[NUM_UTR]
Definition: usbh_uac.h:96
uac_dev_t
Definition: usbh_uac.h:109
uac_dev_t::func_au_in
UAC_CB_FUNC * func_au_in
Definition: usbh_uac.h:115
uac.h
M480 MCU USB Host Audio Class header file.
usbh_uac_get_sampling_rate
int usbh_uac_get_sampling_rate(struct uac_dev_t *audev, uint8_t target, uint32_t *srate_list, int max_cnt, uint8_t *type)
Get a list of sampling rate frequencies supported by the UAC device.
Definition: uac_core.c:116
usbh_uac_vol_control
int usbh_uac_vol_control(struct uac_dev_t *audev, uint8_t target, uint8_t req, uint16_t chn, uint16_t *volume)
Audio Class device volume control.
Definition: uac_core.c:323
usbh_uac_open
int usbh_uac_open(struct uac_dev_t *audev)
Open an connected UAC device.
Definition: uac_core.c:997
usbh_uac_start_audio_in
int usbh_uac_start_audio_in(struct uac_dev_t *uac, UAC_CB_FUNC *func)
Start to receive audio data from UAC device. (Microphone)
Definition: uac_core.c:554
usbh_lib.h
USB Host library exported header file.
uac_dev_t::asif_in
AS_IF_T asif_in
Definition: usbh_uac.h:113
usbh_uac_mute_control
int usbh_uac_mute_control(struct uac_dev_t *audev, uint8_t target, uint8_t req, uint16_t chn, uint8_t *mute)
Control Audio Class device mute on/off.
Definition: uac_core.c:240
UAC_RET_OUT_OF_MEMORY
#define UAC_RET_OUT_OF_MEMORY
Definition: usbh_lib.h:102
usbh_uac_start_audio_out
int usbh_uac_start_audio_out(struct uac_dev_t *uac, UAC_CB_FUNC *func)
Start to transmit audio data to UAC device. (Speaker)
Definition: uac_core.c:796
uac_dev_t::asif_out
AS_IF_T asif_out
Definition: usbh_uac.h:114
USBH_ERR_MEMORY_OUT
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
UAC_MICROPHONE
#define UAC_MICROPHONE
Definition: usbh_uac.h:36
usbh_uac_stop_audio_out
int usbh_uac_stop_audio_out(struct uac_dev_t *audev)
Stop UAC device audio out data stream.
Definition: uac_core.c:946
UAC_RET_DATA_LEN
#define UAC_RET_DATA_LEN
Definition: usbh_lib.h:100
uac_dev_t::udev
UDEV_T * udev
Definition: usbh_uac.h:111
UAC_RET_IS_STREAMING
#define UAC_RET_IS_STREAMING
Definition: usbh_lib.h:106
ac_if_t::speaker_fuid
uint8_t speaker_fuid
Definition: usbh_uac.h:86
usbh_uac_get_bit_resolution
int usbh_uac_get_bit_resolution(struct uac_dev_t *audev, uint8_t target, uint8_t *byte_cnt)
Obtain Audio Class device subframe bit resolution..
Definition: uac_core.c:71
as_if_t::iface
IFACE_T * iface
Definition: usbh_uac.h:94
usbh_uac_sampling_rate_control
int usbh_uac_sampling_rate_control(struct uac_dev_t *audev, uint8_t target, uint8_t req, uint32_t *srate)
Set sampling rate frequency.
Definition: uac_core.c:169
UAC_RET_FUNC_NOT_FOUND
#define UAC_RET_FUNC_NOT_FOUND
Definition: usbh_lib.h:98
usbh_uac_auto_gain_control
int usbh_uac_auto_gain_control(struct uac_dev_t *audev, uint8_t target, uint8_t req, uint16_t chn, uint8_t *bAGC)
Audio Class device automatic gain control.
Definition: uac_core.c:385
usb.h
USB Host library header file.
UAC_RET_DEV_NOT_SUPPORTED
#define UAC_RET_DEV_NOT_SUPPORTED
Definition: usbh_lib.h:104
uac_dev_t::func_au_out
UAC_CB_FUNC * func_au_out
Definition: usbh_uac.h:116
as_if_t
Definition: usbh_uac.h:92
NULL
#define NULL
NULL pointer.
Definition: M480.h:604
UAC_RET_OK
#define UAC_RET_OK
Definition: usbh_lib.h:96
ac_if_t::mic_fuid
uint8_t mic_fuid
Definition: usbh_uac.h:84
uac_dev_t::acif
AC_IF_T acif
Definition: usbh_uac.h:112
NUM_UTR
#define NUM_UTR
Definition: usbh_uac.h:32
as_if_t::ep
EP_INFO_T * ep
Definition: usbh_uac.h:95