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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHostDac.cpp Source File

USBHostDac.cpp

00001 /*******************************************************************************
00002 * DISCLAIMER
00003 * This software is supplied by Renesas Electronics Corporation and is only
00004 * intended for use with Renesas products. No other uses are authorized. This
00005 * software is owned by Renesas Electronics Corporation and is protected under
00006 * all applicable laws, including copyright laws.
00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
00016 * Renesas reserves the right, without notice, to make changes to this software
00017 * and to discontinue the availability of this software. By using this software,
00018 * you agree to the additional terms and conditions found by accessing the
00019 * following link:
00020 * http://www.renesas.com/disclaimer
00021 * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
00022 *******************************************************************************/
00023 
00024 #include "USBHostDac.h"
00025 
00026 #define SAMPLING                    (0x0100)
00027 #define SET_CUR                     (0x01)
00028 #define FRAME_COUNT                 (8)
00029 #define PACKET_SIZE                 (192)
00030 #define QUEUE_NUM                   (3)
00031 
00032 USBHostDac::USBHostDac() {
00033     host = USBHost::getHostInst();
00034     iso_send.m_isoEp = new IsochronousEp;
00035     iso_send.p_rest_data = NULL;
00036 
00037     iso_recv.m_isoEp = new IsochronousEp;
00038     iso_recv.p_rest_data = NULL;
00039 
00040     init();
00041 }
00042 
00043 USBHostDac::~USBHostDac() {
00044     delete iso_send.m_isoEp;
00045     delete iso_recv.m_isoEp;
00046 }
00047 
00048 void USBHostDac::init() {
00049     dev = NULL;
00050     dev_connected = false;
00051     audio_device_found = false;
00052     audio_intf = -1;
00053     audio_intf_cnt = 0;
00054     iso_send.bEndpointAddress = 0;
00055     iso_send.rest_data_index = 0;
00056     iso_send.rest_data_size = 0;
00057     if (iso_send.p_rest_data != NULL) {
00058         delete iso_send.p_rest_data;
00059         iso_send.p_rest_data = NULL;
00060     }
00061     iso_recv.bEndpointAddress = 0;
00062     iso_recv.rest_data_index = 0;
00063     iso_recv.rest_data_size = 0;
00064     if (iso_recv.p_rest_data != NULL) {
00065         delete iso_recv.p_rest_data;
00066         iso_recv.p_rest_data = NULL;
00067     }
00068 }
00069 
00070 bool USBHostDac::connected() {
00071     return dev_connected;
00072 }
00073 
00074 bool USBHostDac::connect() {
00075     if (dev_connected) {
00076         return true;
00077     }
00078 
00079     for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
00080         if ((dev = host->getDevice(i)) != NULL) {
00081 
00082             if (host->enumerate(dev, this)) {
00083                 break;
00084             }
00085 
00086             if (audio_device_found) {
00087                 USB_INFO("New UsbDac device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, audio_intf);
00088                 dev->setName("UsbDac", audio_intf);
00089                 host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect);
00090 
00091                 int addr = dev->getAddress();
00092 
00093                 if (iso_send.bEndpointAddress != 0) {
00094                     iso_send.p_rest_data = new uint8_t[PACKET_SIZE * FRAME_COUNT];
00095                     iso_send.m_isoEp->init(addr, iso_send.bEndpointAddress, PACKET_SIZE, FRAME_COUNT, QUEUE_NUM);
00096                     setInterface(iso_send.bAlternateSetting, iso_send.bInterfaceNumber);
00097                     setSamplingRate(iso_send.bEndpointAddress, 48000);
00098                 }
00099 
00100                 if (iso_recv.bEndpointAddress != 0) {
00101                     iso_recv.p_rest_data = new uint8_t[iso_recv.wMaxPacketSize * FRAME_COUNT];
00102                     iso_recv.m_isoEp->init(addr, iso_recv.bEndpointAddress, iso_recv.wMaxPacketSize, FRAME_COUNT, QUEUE_NUM);
00103                     setInterface(iso_recv.bAlternateSetting, iso_recv.bInterfaceNumber);
00104                     setSamplingRate(iso_recv.bEndpointAddress, 48000);
00105                 }
00106 
00107                 dev_connected = true;
00108                 return true;
00109             }
00110         }
00111     }
00112     init();
00113     return false;
00114 }
00115 
00116 uint32_t USBHostDac::send(uint8_t* buf, uint32_t len, bool flush) {
00117     uint32_t send_index = 0;
00118     uint32_t rest_size = len;
00119     uint32_t send_size;
00120     uint32_t copy_size;
00121     int      result;
00122 
00123     if (iso_send.bEndpointAddress == 0) {
00124         return 0;
00125     }
00126 
00127     if (iso_send.rest_data_index != 0) {
00128         if (rest_size > iso_send.rest_data_size) {
00129             copy_size = iso_send.rest_data_size;
00130         } else {
00131             copy_size = rest_size;
00132         }
00133         memcpy(&iso_send.p_rest_data[iso_send.rest_data_index], &buf[send_index], copy_size);
00134         send_index      += copy_size;
00135         rest_size       -= copy_size;
00136         iso_send.rest_data_index += copy_size;
00137         if ((flush != false) || (iso_send.rest_data_index >= (PACKET_SIZE * FRAME_COUNT))) {
00138             if (iso_send.m_isoEp->getQueueNum() == 0) {
00139                 iso_send.m_isoEp->reset(4);
00140             }
00141             result = iso_send.m_isoEp->isochronousSend(&iso_send.p_rest_data[0], iso_send.rest_data_index, 100);
00142             iso_send.rest_data_index = 0;
00143         }
00144     }
00145 
00146     while ((dev_connected) && (rest_size > 0)) {
00147         if ((flush == false) && (rest_size < (PACKET_SIZE * FRAME_COUNT))) {
00148             memcpy(&iso_send.p_rest_data[0], &buf[send_index], rest_size);
00149             iso_send.rest_data_index = rest_size;
00150             iso_send.rest_data_size  = (PACKET_SIZE * FRAME_COUNT) - rest_size;
00151             break;
00152         } else {
00153             if (rest_size >= (PACKET_SIZE * FRAME_COUNT)) {
00154                 send_size = (PACKET_SIZE * FRAME_COUNT);
00155             } else {
00156                 send_size = rest_size;
00157             }
00158             if (iso_send.m_isoEp->getQueueNum() == 0) {
00159                 iso_send.m_isoEp->reset(4);
00160             }
00161             result = iso_send.m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
00162             send_index += result;
00163             rest_size  -= result;
00164         }
00165     }
00166 
00167     return send_index;
00168 }
00169 
00170 uint32_t USBHostDac::receive(uint8_t* buf, uint32_t len) {
00171     uint32_t recv_index = 0;
00172     uint32_t rest_size = len;
00173     uint32_t copy_size;
00174 
00175     if (iso_recv.bEndpointAddress == 0) {
00176         return 0;
00177     }
00178 
00179     if (iso_recv.rest_data_size != 0) {
00180         if (rest_size > iso_recv.rest_data_size) {
00181             copy_size = iso_recv.rest_data_size;
00182         } else {
00183             copy_size = rest_size;
00184         }
00185         memcpy(&buf[recv_index], &iso_recv.p_rest_data[iso_recv.rest_data_index], copy_size);
00186         recv_index      += copy_size;
00187         rest_size       -= copy_size;
00188         iso_recv.rest_data_index += copy_size; 
00189         iso_recv.rest_data_size  -= copy_size;
00190     }
00191 
00192     while ((dev_connected) && (rest_size > 0)) {
00193         iso_recv.rest_data_index = 0;
00194         iso_recv.rest_data_size  = 0;
00195 
00196         if (iso_recv.m_isoEp->getQueueNum() == 0) {
00197             iso_recv.m_isoEp->reset(4);
00198         }
00199         HCITD* itd = iso_recv.m_isoEp->isochronousReceive(100);
00200         if (itd) {
00201             uint8_t cc = itd->ConditionCode();
00202             if (cc == 0) {
00203                 int fc = itd->FrameCount();
00204                 uint8_t* wk_buf = const_cast<uint8_t*>(itd->buf); 
00205                 int mps = iso_recv.m_isoEp->m_PacketSize;
00206                 for (int i = 0; i < fc; i++) {
00207                     uint16_t psw = itd->OffsetPSW[i];
00208                     cc = psw>>12;
00209                     if (cc == 0 || cc == 9) {
00210                         int wk_len = psw & 0x7ff;
00211                         if (rest_size > 0) {
00212                             if (rest_size > wk_len) {
00213                                 copy_size = wk_len;
00214                             } else {
00215                                 copy_size = rest_size;
00216                             }
00217                             memcpy(&buf[recv_index], wk_buf, copy_size);
00218                             recv_index += copy_size;
00219                             rest_size  -= copy_size;
00220                             if (copy_size < wk_len) {
00221                                 memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[copy_size], (wk_len - copy_size));
00222                                 iso_recv.rest_data_size += (wk_len - copy_size);
00223                             }
00224                         } else {
00225                             memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[0], wk_len);
00226                             iso_recv.rest_data_size += wk_len;
00227                         }
00228                     }
00229                     wk_buf += mps;
00230                 }
00231             }
00232             delete itd;
00233         }
00234     }
00235 
00236     return recv_index;
00237 }
00238 
00239 /*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid)
00240 {
00241     // we don't check VID/PID for audio driver
00242 }
00243 
00244 /*virtual*/ bool USBHostDac::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
00245 {
00246     bool ret;
00247 
00248     if (audio_intf_cnt >= 2) {
00249         ret = false;
00250     } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) {
00251         // AUDIOSTREAMING Subclass
00252         ret = chkAudioStreaming();
00253         if (ret != false) {
00254             audio_intf = intf_nb;
00255             audio_device_found = true;
00256             audio_intf_cnt++;
00257         }
00258     } else {
00259         ret = false;
00260     }
00261 
00262     return false;
00263 }
00264 
00265 /*virtual*/ bool USBHostDac::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
00266 {
00267     return false;
00268 }
00269 
00270 bool USBHostDac::chkAudioStreaming() {
00271     uint8_t * conf_descr  = host->getConfDescrCurPtr();
00272     uint16_t len          = host->getConfDescrRestLen();
00273     uint32_t index        = 0;
00274     uint32_t len_desc     = conf_descr[index];
00275     uint32_t cnt;
00276     uint32_t wk_sampling;
00277     bool     smpling_ok   = false;
00278     bool     loop_end     = false;
00279     uint8_t  channels     = 0;
00280     uint8_t  SubframeSize = 0;
00281     uint8_t  id;
00282     uint16_t wk_wMaxPacketSize;
00283     uint8_t  wk_bEndpointAddress;
00284     uint8_t  wk_bInterfaceNumber;
00285     uint8_t  wk_bAlternateSetting;
00286 
00287     /* bNumEndpoints */
00288     if (conf_descr[index + 4] >= 1) {
00289         wk_bInterfaceNumber  = conf_descr[index + 2];
00290         wk_bAlternateSetting = conf_descr[index + 3];
00291         wk_wMaxPacketSize    = 0;
00292         wk_bEndpointAddress  = 0;
00293 
00294         index += len_desc;
00295         while ((index < len) && (loop_end == false)) {
00296             len_desc = conf_descr[index];
00297             id = conf_descr[index+1];
00298             switch (id) {
00299                 case INTERFACE_DESCRIPTOR:
00300                     /* next interface descriptor */
00301                     loop_end = true;
00302                     break;
00303                 case ENDPOINT_DESCRIPTOR:
00304                     if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) {
00305                         wk_bEndpointAddress = conf_descr[index + 2];
00306                         wk_wMaxPacketSize   = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
00307                         loop_end = true;
00308                     }
00309                     break;
00310                 case 0x24: /* Audio Class Specific INTERFACE Descriptor */
00311                     if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1)) {
00312                         channels     = conf_descr[index + 4];
00313                         SubframeSize = conf_descr[index + 5];
00314                         for (cnt = 8; (cnt + 3) <= len_desc; cnt += 3) {
00315                             wk_sampling = ((uint32_t)conf_descr[index + cnt + 0] << 0)
00316                                         | ((uint32_t)conf_descr[index + cnt + 1] << 8)
00317                                         | ((uint32_t)conf_descr[index + cnt + 2] << 16);
00318                             if (wk_sampling == 48000) {
00319                                 smpling_ok = true;
00320                             }
00321                         }
00322                     }
00323                     break;
00324                 default:
00325                     break;
00326             }
00327             index += len_desc;
00328         }
00329 
00330         if (((wk_bEndpointAddress & 0x80) == 0) && (wk_wMaxPacketSize >= PACKET_SIZE)
00331          && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) {
00332             iso_send.wMaxPacketSize    = wk_wMaxPacketSize;
00333             iso_send.bEndpointAddress  = wk_bEndpointAddress;
00334             iso_send.bInterfaceNumber  = wk_bInterfaceNumber;
00335             iso_send.bAlternateSetting = wk_bAlternateSetting;
00336             return true;
00337         }
00338 
00339         if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE/2))
00340          && (channels == 1) && (SubframeSize == 2) && (smpling_ok != false)) {
00341             iso_recv.wMaxPacketSize    = wk_wMaxPacketSize;
00342             iso_recv.bEndpointAddress  = wk_bEndpointAddress;
00343             iso_recv.bInterfaceNumber  = wk_bInterfaceNumber;
00344             iso_recv.bAlternateSetting = wk_bAlternateSetting;
00345             return true;
00346         }
00347     }
00348 
00349     return false;
00350 }
00351 
00352 void USBHostDac::onDisconnect() {
00353     if (dev_connected) {
00354         if (iso_send.bEndpointAddress != 0) {
00355             iso_send.m_isoEp->disconnect();
00356         }
00357         if (iso_recv.bEndpointAddress != 0) {
00358             iso_recv.m_isoEp->disconnect();
00359         }
00360         init();
00361     }
00362 }
00363 
00364 USB_TYPE USBHostDac::setInterface(uint16_t alt, uint16_t index) {
00365     return host->controlWrite(   dev,
00366                                  USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
00367                                  SET_INTERFACE,
00368                                  alt, index, NULL, 0);
00369 }
00370 
00371 void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) {
00372     uint8_t  data[3];
00373 
00374     data[0] = (uint8_t)((sampling_rate >>  0) & 0xff);
00375     data[1] = (uint8_t)((sampling_rate >>  8) & 0xff);
00376     data[2] = (uint8_t)((sampling_rate >> 16) & 0xff);
00377     host->controlWrite(   dev,
00378                           USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
00379                           SET_CUR,
00380                           SAMPLING, endpoint_adder, data, 3);
00381 }
00382