Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Wed Jul 13 2022 04:57:20 by
1.7.2