doku newon / DokuUSBHost
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost6ChDac.cpp Source File

USBHost6ChDac.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 "USBHost6ChDac.h"
00025 
00026 #define FUCS_CH0                    (0x00)
00027 #define FUCS_CH1                    (0x01)
00028 #define FUCS_CH2                    (0x02)
00029 #define FUCS_CH3                    (0x03)
00030 #define FUCS_MUTE                   (0x0100)
00031 #define FUCS_VOLUME                 (0x0200)
00032 
00033 #define SAMPLING                    (0x0100)
00034 #define SET_CUR                     (0x01)
00035 #define FRAME_COUNT                 (8)
00036 #define PACKET_SIZE                 (192)
00037 #define PACKET_SIZE_6CH             (192 * 3)
00038 //doku #define QUEUE_NUM            (3)
00039 #define QUEUE_NUM                   (11)
00040 
00041 //#define DESC_REP printf
00042 #define DESC_REP(...) while(0);
00043 
00044 USBHostDac::USBHostDac() {
00045     host = USBHost::getHostInst();
00046     iso_send.m_isoEp = new IsochronousEp;
00047     iso_send.p_rest_data = NULL;
00048 
00049     iso_recv.m_isoEp = new IsochronousEp;
00050     iso_recv.p_rest_data = NULL;
00051 
00052     init();
00053 }
00054 
00055 USBHostDac::~USBHostDac() {
00056     delete iso_send.m_isoEp;
00057     delete iso_recv.m_isoEp;
00058 }
00059 
00060 void USBHostDac::init() {
00061     dev = NULL;
00062     dev_connected = false;
00063     audio_device_found = false;
00064     audio_intf = -1;
00065     audio_intf_cnt = 0;
00066     iso_send.bEndpointAddress = 0;
00067     iso_send.rest_data_index = 0;
00068     iso_send.rest_data_size = 0;
00069     if (iso_send.p_rest_data != NULL) {
00070         delete iso_send.p_rest_data;
00071         iso_send.p_rest_data = NULL;
00072     }
00073     iso_recv.bEndpointAddress = 0;
00074     iso_recv.rest_data_index = 0;
00075     iso_recv.rest_data_size = 0;
00076     if (iso_recv.p_rest_data != NULL) {
00077         delete iso_recv.p_rest_data;
00078         iso_recv.p_rest_data = NULL;
00079     }
00080 }
00081 
00082 bool USBHostDac::connected() {
00083     return dev_connected;
00084 }
00085 
00086 bool USBHostDac::connect() {
00087     if (dev_connected) {
00088         return true;
00089     }
00090 
00091     for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
00092         if ((dev = host->getDevice(i)) != NULL) {
00093 
00094             if (host->enumerate(dev, this)) {
00095                 break;
00096             }
00097 
00098             if (audio_device_found) {
00099                 USB_INFO("New UsbDac device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, audio_intf);
00100                 dev->setName("UsbDac", audio_intf);
00101                 host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect);
00102 
00103                 int addr = dev->getAddress();
00104 
00105                 if (iso_send.bEndpointAddress != 0) {
00106                     iso_send.p_rest_data = new uint8_t[PACKET_SIZE_6CH * FRAME_COUNT];
00107                     iso_send.m_isoEp->init(addr, iso_send.bEndpointAddress, PACKET_SIZE_6CH, FRAME_COUNT, QUEUE_NUM);
00108                     setInterface(iso_send.bAlternateSetting, iso_send.bInterfaceNumber);
00109                     setSamplingRate(iso_send.bEndpointAddress, 48000);
00110                 }
00111 
00112                 if (iso_recv.bEndpointAddress != 0) {
00113                     iso_recv.p_rest_data = new uint8_t[iso_recv.wMaxPacketSize * FRAME_COUNT];
00114                     iso_recv.m_isoEp->init(addr, iso_recv.bEndpointAddress, iso_recv.wMaxPacketSize, FRAME_COUNT, QUEUE_NUM);
00115                     setInterface(iso_recv.bAlternateSetting, iso_recv.bInterfaceNumber);
00116                     setSamplingRate(iso_recv.bEndpointAddress, 48000);
00117                 }
00118 
00119                 setMuteAndVolume();
00120 
00121                 dev_connected = true;
00122                 return true;
00123             }
00124         }
00125     }
00126     init();
00127     return false;
00128 }
00129 
00130 uint32_t USBHostDac::send(uint8_t* buf, uint32_t len, bool flush) {
00131     uint32_t send_index = 0;
00132     uint32_t rest_size = len;
00133     uint32_t send_size;
00134     uint32_t copy_size;
00135     int      result;
00136 
00137     if (iso_send.bEndpointAddress == 0) {
00138         return 0;
00139     }
00140 
00141     if (iso_send.rest_data_index != 0) {
00142         if (rest_size > iso_send.rest_data_size) {
00143             copy_size = iso_send.rest_data_size;
00144         } else {
00145             copy_size = rest_size;
00146         }
00147         memcpy(&iso_send.p_rest_data[iso_send.rest_data_index], &buf[send_index], copy_size);
00148         send_index      += copy_size;
00149         rest_size       -= copy_size;
00150         iso_send.rest_data_index += copy_size;
00151         if ((flush != false) || (iso_send.rest_data_index >= (PACKET_SIZE_6CH * FRAME_COUNT))) {
00152             if (iso_send.m_isoEp->getQueueNum() == 0) {
00153                 iso_send.m_isoEp->reset(4);
00154             }
00155             result = iso_send.m_isoEp->isochronousSend(&iso_send.p_rest_data[0], iso_send.rest_data_index, 100);
00156             iso_send.rest_data_index = 0;
00157         }
00158     }
00159 
00160     while ((dev_connected) && (rest_size > 0)) {
00161         if ((flush == false) && (rest_size < (PACKET_SIZE_6CH * FRAME_COUNT))) {
00162             memcpy(&iso_send.p_rest_data[0], &buf[send_index], rest_size);
00163             iso_send.rest_data_index = rest_size;
00164             iso_send.rest_data_size  = (PACKET_SIZE_6CH * FRAME_COUNT) - rest_size;
00165             break;
00166         } else {
00167             if (rest_size >= (PACKET_SIZE_6CH * FRAME_COUNT)) {
00168                 send_size = (PACKET_SIZE_6CH * FRAME_COUNT);
00169             } else {
00170                 send_size = rest_size;
00171             }
00172             if (iso_send.m_isoEp->getQueueNum() == 0) {
00173                 iso_send.m_isoEp->reset(4);
00174             }
00175             result = iso_send.m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
00176             send_index += result;
00177             rest_size  -= result;
00178         }
00179     }
00180 
00181     return send_index;
00182 }
00183 
00184 uint32_t USBHostDac::receive(uint8_t* buf, uint32_t len) {
00185     uint32_t recv_index = 0;
00186     uint32_t rest_size = len;
00187     uint32_t copy_size;
00188 
00189     if (iso_recv.bEndpointAddress == 0) {
00190         return 0;
00191     }
00192 
00193     if (iso_recv.rest_data_size != 0) {
00194         if (rest_size > iso_recv.rest_data_size) {
00195             copy_size = iso_recv.rest_data_size;
00196         } else {
00197             copy_size = rest_size;
00198         }
00199         memcpy(&buf[recv_index], &iso_recv.p_rest_data[iso_recv.rest_data_index], copy_size);
00200         recv_index      += copy_size;
00201         rest_size       -= copy_size;
00202         iso_recv.rest_data_index += copy_size; 
00203         iso_recv.rest_data_size  -= copy_size;
00204     }
00205 
00206     while ((dev_connected) && (rest_size > 0)) {
00207         iso_recv.rest_data_index = 0;
00208         iso_recv.rest_data_size  = 0;
00209 
00210         if (iso_recv.m_isoEp->getQueueNum() == 0) {
00211             iso_recv.m_isoEp->reset(4);
00212         }
00213         HCITD* itd = iso_recv.m_isoEp->isochronousReceive(100);
00214         if (itd) {
00215             uint8_t cc = itd->ConditionCode();
00216             if (cc == 0) {
00217                 int fc = itd->FrameCount();
00218                 uint8_t* wk_buf = const_cast<uint8_t*>(itd->buf); 
00219                 int mps = iso_recv.m_isoEp->m_PacketSize;
00220                 for (int i = 0; i < fc; i++) {
00221                     uint16_t psw = itd->OffsetPSW[i];
00222                     cc = psw>>12;
00223                     if (cc == 0 || cc == 9) {
00224                         int wk_len = psw & 0x7ff;
00225                         if (rest_size > 0) {
00226                             if (rest_size > wk_len) {
00227                                 copy_size = wk_len;
00228                             } else {
00229                                 copy_size = rest_size;
00230                             }
00231                             memcpy(&buf[recv_index], wk_buf, copy_size);
00232                             recv_index += copy_size;
00233                             rest_size  -= copy_size;
00234                             if (copy_size < wk_len) {
00235                                 memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[copy_size], (wk_len - copy_size));
00236                                 iso_recv.rest_data_size += (wk_len - copy_size);
00237                             }
00238                         } else {
00239                             memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[0], wk_len);
00240                             iso_recv.rest_data_size += wk_len;
00241                         }
00242                     }
00243                     wk_buf += mps;
00244                 }
00245             }
00246             delete itd;
00247         }
00248     }
00249 
00250     return recv_index;
00251 }
00252 
00253 /*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid)
00254 {
00255     // we don't check VID/PID for audio driver
00256 }
00257 
00258 /*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
00259 {
00260     bool ret;
00261 
00262     if (audio_intf_cnt >= 2) {
00263         ret = false;
00264     } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) {
00265         // AUDIOSTREAMING Subclass
00266         ret = chkAudioStreaming();
00267         if (ret != false) {
00268             audio_intf = intf_nb;
00269             audio_device_found = true;
00270             audio_intf_cnt++;
00271         }
00272     } else {
00273         ret = false;
00274     }
00275 
00276     return false;
00277 }
00278 
00279 /*virtual*/ bool USBHostDac::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
00280 {
00281     return false;
00282 }
00283 
00284 bool USBHostDac::chkAudioStreaming() {
00285     uint8_t * conf_descr  = host->getConfDescrCurPtr();
00286     uint16_t len          = host->getConfDescrRestLen();
00287     uint32_t index        = 0;
00288     uint32_t len_desc     = conf_descr[index];
00289     uint32_t cnt;
00290     uint32_t wk_sampling;
00291     bool     smpling_ok   = false;
00292     bool     loop_end     = false;
00293     uint8_t  channels     = 0;
00294     uint8_t  SubframeSize = 0;
00295     uint8_t  id;
00296     uint16_t wk_wMaxPacketSize;
00297     uint8_t  wk_bEndpointAddress;
00298     uint8_t  wk_bInterfaceNumber;
00299     uint8_t  wk_bAlternateSetting;
00300 
00301     DESC_REP("audio streaming interface:%d alt:%d found\n",conf_descr[index + 2],conf_descr[index + 3]);
00302     /* bNumEndpoints */
00303     if (conf_descr[index + 4] >= 1) {
00304         wk_bInterfaceNumber  = conf_descr[index + 2];
00305         wk_bAlternateSetting = conf_descr[index + 3];
00306         wk_wMaxPacketSize    = 0;
00307         wk_bEndpointAddress  = 0;
00308 
00309         index += len_desc;
00310         while ((index < len) && (loop_end == false)) {
00311             len_desc = conf_descr[index];
00312             id = conf_descr[index+1];
00313             switch (id) {
00314                 case INTERFACE_DESCRIPTOR:
00315                     DESC_REP("interface descriptor found\n");
00316                     /* next interface descriptor */
00317                     loop_end = true;
00318                     break;
00319                 case ENDPOINT_DESCRIPTOR:
00320                     DESC_REP("endpoint descriptor found\n");
00321                     if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) {
00322                         wk_bEndpointAddress = conf_descr[index + 2];
00323                         wk_wMaxPacketSize   = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
00324                         loop_end = true;
00325                     }
00326                     break;
00327                 case 0x24: /* Audio Class Specific INTERFACE Descriptor */
00328                     DESC_REP("audio specific descriptor found\n");
00329 //doku                    if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1)) {
00330                     if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1 && (wk_bAlternateSetting != 5))) {
00331                         channels     = conf_descr[index + 4];
00332                         SubframeSize = conf_descr[index + 5];
00333                         for (cnt = 8; (cnt + 3) <= len_desc; cnt += 3) {
00334                             wk_sampling = ((uint32_t)conf_descr[index + cnt + 0] << 0)
00335                                         | ((uint32_t)conf_descr[index + cnt + 1] << 8)
00336                                         | ((uint32_t)conf_descr[index + cnt + 2] << 16);
00337                             DESC_REP("interface:%d alt:%d found channels:%d subframe size:%d sampling:%d\n",wk_bInterfaceNumber,wk_bAlternateSetting,channels,SubframeSize,wk_sampling);
00338                             if (wk_sampling == 48000) {
00339                                 smpling_ok = true;
00340                             }
00341                         }
00342                     }
00343                     break;
00344                 default:
00345                     break;
00346             }
00347             index += len_desc;
00348         }
00349 
00350         DESC_REP("interface:%d alt:%d endpoint:%02x found\n",wk_bInterfaceNumber,wk_bAlternateSetting,wk_bEndpointAddress);
00351 
00352         if (((wk_bEndpointAddress & 0x80) == 0) && (wk_wMaxPacketSize >= PACKET_SIZE_6CH)
00353          && (channels == 6) && (SubframeSize == 2) && (smpling_ok != false)) {
00354             DESC_REP("****** fit for send ******\n");
00355             iso_send.wMaxPacketSize    = wk_wMaxPacketSize;
00356             iso_send.bEndpointAddress  = wk_bEndpointAddress;
00357             iso_send.bInterfaceNumber  = wk_bInterfaceNumber;
00358             iso_send.bAlternateSetting = wk_bAlternateSetting;
00359             return true;
00360         }
00361 
00362         DESC_REP("end point:%d packet size:%d channels:%d subflame:%d ampling ok:%d\n",wk_bEndpointAddress,wk_wMaxPacketSize,channels,SubframeSize,smpling_ok);
00363 //doku  if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE/2))
00364         if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE))
00365          && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) {
00366             DESC_REP("****** fit for receive ******\n");
00367             iso_recv.wMaxPacketSize    = wk_wMaxPacketSize;
00368             iso_recv.bEndpointAddress  = wk_bEndpointAddress;
00369             iso_recv.bInterfaceNumber  = wk_bInterfaceNumber;
00370             iso_recv.bAlternateSetting = wk_bAlternateSetting;
00371             return true;
00372         }
00373     }
00374 
00375     return false;
00376 }
00377 
00378 void USBHostDac::onDisconnect() {
00379     if (dev_connected) {
00380         if (iso_send.bEndpointAddress != 0) {
00381             iso_send.m_isoEp->disconnect();
00382         }
00383         if (iso_recv.bEndpointAddress != 0) {
00384             iso_recv.m_isoEp->disconnect();
00385         }
00386         init();
00387     }
00388 }
00389 
00390 USB_TYPE USBHostDac::setInterface(uint16_t alt, uint16_t index) {
00391     DESC_REP("set interface:%d alt:%d\n",index,alt);
00392     return host->controlWrite(   dev,
00393                                  USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
00394                                  SET_INTERFACE,
00395                                  alt, index, NULL, 0);
00396 }
00397 
00398 void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) {
00399     uint8_t  data[3];
00400     DESC_REP("set sampling rate endpoint:%02x rate:%d\n",endpoint_adder,sampling_rate);
00401 
00402     data[0] = (uint8_t)((sampling_rate >>  0) & 0xff);
00403     data[1] = (uint8_t)((sampling_rate >>  8) & 0xff);
00404     data[2] = (uint8_t)((sampling_rate >> 16) & 0xff);
00405     host->controlWrite(   dev,
00406                           USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
00407                           SET_CUR,
00408                           SAMPLING, endpoint_adder, data, 3);
00409 }
00410 
00411 void USBHostDac::FUMute(int unit, int ch, int mute) 
00412 {
00413 //    DESC_REP("mute:%d\n",mute);
00414     uint8_t data[1];
00415 
00416     unit <<= 8;
00417     data[0] = 0xff & mute;
00418 
00419     host->controlWrite(   dev,
00420                           USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
00421                           SET_CUR,
00422                           FUCS_MUTE | ch, unit, data, 1);
00423 }
00424 
00425 void USBHostDac::FUVolume(int unit, int ch,int volume) 
00426 {
00427 //    DESC_REP("volume:%d\n",volume);
00428     uint8_t data[2];
00429     
00430     unit <<= 8;
00431     data[0] = volume & 0xFF;
00432     data[1] = (volume>>8) & 0xFF;
00433 
00434     host->controlWrite(   dev,
00435                           USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
00436                           SET_CUR,
00437                           FUCS_VOLUME | ch, unit, data, 2);
00438 }
00439 
00440 void USBHostDac::FUSelect(int unit, int sel) 
00441 {
00442 //    DESC_REP("volume:%d\n",volume);
00443     uint8_t data[1];
00444     
00445     unit <<= 8;
00446     data[0] = sel & 0xFF;
00447 
00448     host->controlWrite(   dev,
00449                           USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
00450                           SET_CUR,
00451                           0 , unit, data, 1);
00452 }
00453 
00454 void USBHostDac::setMuteAndVolume(void)
00455 {
00456     //off playback mute
00457 //    FUMute(13, 0, 0);
00458     //front volume
00459 //    FUVolume(13, 1, -256 * 0);
00460 //    FUVolume(13, 2, -256 * 0); 
00461 
00462     //recoding volume
00463 //    FUMute(15, 0, 0);
00464 //    FUVolume(15, 1, -256 * 0);
00465 
00466     //recoding selector
00467     FUSelect(7, 2);
00468 }
00469