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)
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)
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)
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)
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 
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 
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 
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 
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 
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_STATE_E state
Definition: usbh_uac.h:118
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
USB Host UAC class driver header file.
#define UAC_RET_DEV_NOT_FOUND
Definition: usbh_lib.h:97
int() UAC_CB_FUNC(struct uac_dev_t *dev, uint8_t *data, int len)
Definition: usbh_lib.h:127
#define UAC_REQ_TIMEOUT
Definition: usbh_uac.h:33
uint8_t flag_streaming
Definition: usbh_uac.h:102
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
int usbh_uac_stop_audio_in(struct uac_dev_t *audev)
Stop UAC device audio in data stream.
Definition: uac_core.c:703
#define UAC_SPEAKER
Definition: usbh_uac.h:35
AS_FT1_T * ft
Definition: usbh_uac.h:100
NuMicro peripheral access layer header file.
#define USBH_ERR_NOT_ACCESS0
Definition: usbh_lib.h:68
#define USBH_ERR_NOT_ACCESS1
Definition: usbh_lib.h:69
IFACE_T * iface
Definition: usbh_uac.h:82
UTR_T * utr[NUM_UTR]
Definition: usbh_uac.h:96
UAC_CB_FUNC * func_au_in
Definition: usbh_uac.h:115
M480 MCU USB Host Audio Class header file.
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
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
int usbh_uac_open(struct uac_dev_t *audev)
Open an connected UAC device.
Definition: uac_core.c:997
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
USB Host library exported header file.
AS_IF_T asif_in
Definition: usbh_uac.h:113
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
#define UAC_RET_OUT_OF_MEMORY
Definition: usbh_lib.h:102
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
AS_IF_T asif_out
Definition: usbh_uac.h:114
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
#define UAC_MICROPHONE
Definition: usbh_uac.h:36
int usbh_uac_stop_audio_out(struct uac_dev_t *audev)
Stop UAC device audio out data stream.
Definition: uac_core.c:946
#define UAC_RET_DATA_LEN
Definition: usbh_lib.h:100
UDEV_T * udev
Definition: usbh_uac.h:111
#define UAC_RET_IS_STREAMING
Definition: usbh_lib.h:106
uint8_t speaker_fuid
Definition: usbh_uac.h:86
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
IFACE_T * iface
Definition: usbh_uac.h:94
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
#define UAC_RET_FUNC_NOT_FOUND
Definition: usbh_lib.h:98
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 Host library header file.
#define UAC_RET_DEV_NOT_SUPPORTED
Definition: usbh_lib.h:104
UAC_CB_FUNC * func_au_out
Definition: usbh_uac.h:116
#define NULL
NULL pointer.
Definition: M480.h:604
#define UAC_RET_OK
Definition: usbh_lib.h:96
uint8_t mic_fuid
Definition: usbh_uac.h:84
AC_IF_T acif
Definition: usbh_uac.h:112
#define NUM_UTR
Definition: usbh_uac.h:32
EP_INFO_T * ep
Definition: usbh_uac.h:95