A class to communicate a USB dac (send:only 48kHz,16bit,2ch , receive:only 48kHz,16bit,1ch). Need "USBHost_AddIso" library.

Dependents:   USBHostDac_Audio_in_out

Fork of USBHostDac by GR-PEACH_producer_meeting

Files at this revision

API Documentation at this revision

Comitter:
dkato
Date:
Wed Sep 30 06:04:31 2015 +0000
Parent:
0:3a3146f89bcc
Child:
2:4afe26b3d48b
Commit message:
Supports data receive.

Changed in this revision

USBHostDac.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostDac.h Show annotated file Show diff for this revision Revisions of this file
--- a/USBHostDac.cpp	Wed Apr 01 10:29:31 2015 +0000
+++ b/USBHostDac.cpp	Wed Sep 30 06:04:31 2015 +0000
@@ -31,24 +31,40 @@
 
 USBHostDac::USBHostDac() {
     host = USBHost::getHostInst();
-    m_isoEp = new IsochronousEp;
-    p_rest_data = new uint8_t[USBDAC_DATA_SIZE];
+    iso_send.m_isoEp = new IsochronousEp;
+    iso_send.p_rest_data = NULL;
+
+    iso_recv.m_isoEp = new IsochronousEp;
+    iso_recv.p_rest_data = NULL;
 
     init();
 }
 
+USBHostDac::~USBHostDac() {
+    delete iso_send.m_isoEp;
+    delete iso_recv.m_isoEp;
+}
+
 void USBHostDac::init() {
     dev = NULL;
     dev_connected = false;
     audio_device_found = false;
     audio_intf = -1;
     audio_intf_cnt = 0;
-    rest_data_index = 0;
-
-    wMaxPacketSize    = 0;
-    bInterfaceNumber  = 0;
-    bAlternateSetting = 0;
-    bEndpointAddress  = 0;
+    iso_send.bEndpointAddress = 0;
+    iso_send.rest_data_index = 0;
+    iso_send.rest_data_size = 0;
+    if (iso_send.p_rest_data != NULL) {
+        delete iso_send.p_rest_data;
+        iso_send.p_rest_data = NULL;
+    }
+    iso_recv.bEndpointAddress = 0;
+    iso_recv.rest_data_index = 0;
+    iso_recv.rest_data_size = 0;
+    if (iso_recv.p_rest_data != NULL) {
+        delete iso_recv.p_rest_data;
+        iso_recv.p_rest_data = NULL;
+    }
 }
 
 bool USBHostDac::connected() {
@@ -73,9 +89,20 @@
                 host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect);
 
                 int addr = dev->getAddress();
-                m_isoEp->init(addr, bEndpointAddress, PACKET_SIZE, FRAME_COUNT, QUEUE_NUM);
-                setInterface(bAlternateSetting, bInterfaceNumber);
-                setSamplingRate(48000);
+
+                if (iso_send.bEndpointAddress != 0) {
+                    iso_send.p_rest_data = new uint8_t[PACKET_SIZE * FRAME_COUNT];
+                    iso_send.m_isoEp->init(addr, iso_send.bEndpointAddress, PACKET_SIZE, FRAME_COUNT, QUEUE_NUM);
+                    setInterface(iso_send.bAlternateSetting, iso_send.bInterfaceNumber);
+                    setSamplingRate(iso_send.bEndpointAddress, 48000);
+                }
+
+                if (iso_recv.bEndpointAddress != 0) {
+                    iso_recv.p_rest_data = new uint8_t[iso_recv.wMaxPacketSize * FRAME_COUNT];
+                    iso_recv.m_isoEp->init(addr, iso_recv.bEndpointAddress, iso_recv.wMaxPacketSize, FRAME_COUNT, QUEUE_NUM);
+                    setInterface(iso_recv.bAlternateSetting, iso_recv.bInterfaceNumber);
+                    setSamplingRate(iso_recv.bEndpointAddress, 48000);
+                }
 
                 dev_connected = true;
                 return true;
@@ -91,44 +118,124 @@
     uint32_t rest_size = len;
     uint32_t send_size;
     uint32_t copy_size;
-    uint32_t def_send_size = PACKET_SIZE * FRAME_COUNT;
+    int      result;
 
-    if (rest_data_index != 0) {
-        if (rest_size > (def_send_size - rest_data_index)) {
-            copy_size = (def_send_size - rest_data_index);
+    if (iso_send.bEndpointAddress == 0) {
+        return 0;
+    }
+
+    if (iso_send.rest_data_index != 0) {
+        if (rest_size > iso_send.rest_data_size) {
+            copy_size = iso_send.rest_data_size;
         } else {
             copy_size = rest_size;
         }
-        memcpy(&p_rest_data[rest_data_index], &buf[send_index], copy_size);
+        memcpy(&iso_send.p_rest_data[iso_send.rest_data_index], &buf[send_index], copy_size);
         send_index      += copy_size;
         rest_size       -= copy_size;
-        rest_data_index += copy_size;
-        if ((flush != false) || (rest_data_index >= def_send_size)) {
-            m_isoEp->isochronousSend(&p_rest_data[0], rest_data_index, 100);
-            rest_data_index = 0;
+        iso_send.rest_data_index += copy_size;
+        if ((flush != false) || (iso_send.rest_data_index >= (PACKET_SIZE * FRAME_COUNT))) {
+            if (iso_send.m_isoEp->getQueueNum() == 0) {
+                iso_send.m_isoEp->reset(4);
+            }
+            result = iso_send.m_isoEp->isochronousSend(&iso_send.p_rest_data[0], iso_send.rest_data_index, 100);
+            iso_send.rest_data_index = 0;
         }
     }
 
     while ((dev_connected) && (rest_size > 0)) {
-        if ((flush == false) && (rest_size < def_send_size)) {
-            memcpy(&p_rest_data[0], &buf[send_index], rest_size);
-            rest_data_index = rest_size;
+        if ((flush == false) && (rest_size < (PACKET_SIZE * FRAME_COUNT))) {
+            memcpy(&iso_send.p_rest_data[0], &buf[send_index], rest_size);
+            iso_send.rest_data_index = rest_size;
+            iso_send.rest_data_size  = (PACKET_SIZE * FRAME_COUNT) - rest_size;
             break;
         } else {
-            if (rest_size >= def_send_size) {
-                send_size = def_send_size;
+            if (rest_size >= (PACKET_SIZE * FRAME_COUNT)) {
+                send_size = (PACKET_SIZE * FRAME_COUNT);
             } else {
                 send_size = rest_size;
             }
-            m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
-            send_index += send_size;
-            rest_size  -= send_size;
+            if (iso_send.m_isoEp->getQueueNum() == 0) {
+                iso_send.m_isoEp->reset(4);
+            }
+            result = iso_send.m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
+            send_index += result;
+            rest_size  -= result;
         }
     }
 
     return send_index;
 }
 
+uint32_t USBHostDac::receive(uint8_t* buf, uint32_t len) {
+    uint32_t recv_index = 0;
+    uint32_t rest_size = len;
+    uint32_t copy_size;
+
+    if (iso_recv.bEndpointAddress == 0) {
+        return 0;
+    }
+
+    if (iso_recv.rest_data_size != 0) {
+        if (rest_size > iso_recv.rest_data_size) {
+            copy_size = iso_recv.rest_data_size;
+        } else {
+            copy_size = rest_size;
+        }
+        memcpy(&buf[recv_index], &iso_recv.p_rest_data[iso_recv.rest_data_index], copy_size);
+        recv_index      += copy_size;
+        rest_size       -= copy_size;
+        iso_recv.rest_data_index += copy_size; 
+        iso_recv.rest_data_size  -= copy_size;
+    }
+
+    while ((dev_connected) && (rest_size > 0)) {
+        iso_recv.rest_data_index = 0;
+        iso_recv.rest_data_size  = 0;
+
+        if (iso_recv.m_isoEp->getQueueNum() == 0) {
+            iso_recv.m_isoEp->reset(4);
+        }
+        HCITD* itd = iso_recv.m_isoEp->isochronousReceive(100);
+        if (itd) {
+            uint8_t cc = itd->ConditionCode();
+            if (cc == 0) {
+                int fc = itd->FrameCount();
+                uint8_t* wk_buf = const_cast<uint8_t*>(itd->buf); 
+                int mps = iso_recv.m_isoEp->m_PacketSize;
+                for (int i = 0; i < fc; i++) {
+                    uint16_t psw = itd->OffsetPSW[i];
+                    cc = psw>>12;
+                    if (cc == 0 || cc == 9) {
+                        int wk_len = psw & 0x7ff;
+                        if (rest_size > 0) {
+                            if (rest_size > wk_len) {
+                                copy_size = wk_len;
+                            } else {
+                                copy_size = rest_size;
+                            }
+                            memcpy(&buf[recv_index], wk_buf, copy_size);
+                            recv_index += copy_size;
+                            rest_size  -= copy_size;
+                            if (copy_size < wk_len) {
+                                memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[copy_size], (wk_len - copy_size));
+                                iso_recv.rest_data_size += (wk_len - copy_size);
+                            }
+                        } else {
+                            memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[0], wk_len);
+                            iso_recv.rest_data_size += wk_len;
+                        }
+                    }
+                    wk_buf += mps;
+                }
+            }
+            delete itd;
+        }
+    }
+
+    return recv_index;
+}
+
 /*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid)
 {
     // we don't check VID/PID for audio driver
@@ -138,7 +245,7 @@
 {
     bool ret;
 
-    if (audio_intf != -1) {
+    if (audio_intf_cnt >= 2) {
         ret = false;
     } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) {
         // AUDIOSTREAMING Subclass
@@ -146,6 +253,7 @@
         if (ret != false) {
             audio_intf = intf_nb;
             audio_device_found = true;
+            audio_intf_cnt++;
         }
     } else {
         ret = false;
@@ -171,11 +279,17 @@
     uint8_t  channels     = 0;
     uint8_t  SubframeSize = 0;
     uint8_t  id;
+    uint16_t wk_wMaxPacketSize;
+    uint8_t  wk_bEndpointAddress;
+    uint8_t  wk_bInterfaceNumber;
+    uint8_t  wk_bAlternateSetting;
 
     /* bNumEndpoints */
     if (conf_descr[index + 4] >= 1) {
-        bInterfaceNumber  = conf_descr[index + 2];
-        bAlternateSetting = conf_descr[index + 3];
+        wk_bInterfaceNumber  = conf_descr[index + 2];
+        wk_bAlternateSetting = conf_descr[index + 3];
+        wk_wMaxPacketSize    = 0;
+        wk_bEndpointAddress  = 0;
 
         index += len_desc;
         while ((index < len) && (loop_end == false)) {
@@ -188,8 +302,8 @@
                     break;
                 case ENDPOINT_DESCRIPTOR:
                     if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) {
-                        bEndpointAddress = conf_descr[index + 2];
-                        wMaxPacketSize   = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
+                        wk_bEndpointAddress = conf_descr[index + 2];
+                        wk_wMaxPacketSize   = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
                         loop_end = true;
                     }
                     break;
@@ -213,8 +327,21 @@
             index += len_desc;
         }
 
-        if (((bEndpointAddress & 0x80) == 0) && (wMaxPacketSize >= PACKET_SIZE)
+        if (((wk_bEndpointAddress & 0x80) == 0) && (wk_wMaxPacketSize >= PACKET_SIZE)
          && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) {
+            iso_send.wMaxPacketSize    = wk_wMaxPacketSize;
+            iso_send.bEndpointAddress  = wk_bEndpointAddress;
+            iso_send.bInterfaceNumber  = wk_bInterfaceNumber;
+            iso_send.bAlternateSetting = wk_bAlternateSetting;
+            return true;
+        }
+
+        if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE/2))
+         && (channels == 1) && (SubframeSize == 2) && (smpling_ok != false)) {
+            iso_recv.wMaxPacketSize    = wk_wMaxPacketSize;
+            iso_recv.bEndpointAddress  = wk_bEndpointAddress;
+            iso_recv.bInterfaceNumber  = wk_bInterfaceNumber;
+            iso_recv.bAlternateSetting = wk_bAlternateSetting;
             return true;
         }
     }
@@ -224,7 +351,12 @@
 
 void USBHostDac::onDisconnect() {
     if (dev_connected) {
-        m_isoEp->disconnect();
+        if (iso_send.bEndpointAddress != 0) {
+            iso_send.m_isoEp->disconnect();
+        }
+        if (iso_recv.bEndpointAddress != 0) {
+            iso_recv.m_isoEp->disconnect();
+        }
         init();
     }
 }
@@ -236,7 +368,7 @@
                                  alt, index, NULL, 0);
 }
 
-void USBHostDac::setSamplingRate(uint32_t sampling_rate) {
+void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) {
     uint8_t  data[3];
 
     data[0] = (uint8_t)((sampling_rate >>  0) & 0xff);
@@ -245,6 +377,6 @@
     host->controlWrite(   dev,
                           USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
                           SET_CUR,
-                          SAMPLING, bEndpointAddress, data, 3);
+                          SAMPLING, endpoint_adder, data, 3);
 }
 
--- a/USBHostDac.h	Wed Apr 01 10:29:31 2015 +0000
+++ b/USBHostDac.h	Wed Sep 30 06:04:31 2015 +0000
@@ -30,6 +30,8 @@
 
 #define USBDAC_DATA_SIZE       (192 * 8)
 
+#define USBDAC_
+
 /**
  * A class to communicate a USB dac (only 48kHz,16bit,2ch)
  */
@@ -41,6 +43,11 @@
     */
     USBHostDac();
 
+    /** Destructor
+     *
+     */
+    virtual ~USBHostDac();
+
     /**
      * Try to connect a audio device
      *
@@ -66,6 +73,16 @@
     */
     uint32_t send(uint8_t* buf, uint32_t len, bool flush = true);
 
+    /**
+    * Data receive
+    *
+    * @param buf pointer on a buffer which will be read
+    * @param len length of the transfer
+    *
+    * @returns the number of bytes read is returned
+    */
+    uint32_t receive(uint8_t* buf, uint32_t len);
+
 protected:
     //From IUSBEnumerator
     virtual void setVidPid(uint16_t vid, uint16_t pid);
@@ -73,6 +90,17 @@
     virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
 
 private:
+    typedef struct {
+        IsochronousEp* m_isoEp;
+        uint16_t wMaxPacketSize;
+        uint8_t  bEndpointAddress;
+        uint8_t  bInterfaceNumber;
+        uint8_t  bAlternateSetting;
+        uint8_t* p_rest_data;
+        uint32_t rest_data_index;
+        uint32_t rest_data_size;
+    } iso_if_t;
+
     USBHost * host;
     USBDeviceConnected * dev;
 
@@ -81,18 +109,13 @@
     int audio_intf;
     int audio_intf_cnt;
 
-    IsochronousEp* m_isoEp;
-    uint16_t wMaxPacketSize;
-    uint8_t  bEndpointAddress;
-    uint8_t  bInterfaceNumber;
-    uint8_t  bAlternateSetting;
-    uint8_t* p_rest_data;
-    uint32_t rest_data_index;
+    iso_if_t iso_send;
+    iso_if_t iso_recv;
 
     void init();
     void onDisconnect();
     bool chkAudioStreaming();
     USB_TYPE setInterface(uint16_t alt, uint16_t index);
-    void setSamplingRate(uint32_t sampling_rate);
+    void setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate);
 };
 #endif