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

Committer:
dkato
Date:
Wed Apr 01 10:29:31 2015 +0000
Revision:
0:3a3146f89bcc
Child:
1:9ff4cba6524d
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:3a3146f89bcc 1 /*******************************************************************************
dkato 0:3a3146f89bcc 2 * DISCLAIMER
dkato 0:3a3146f89bcc 3 * This software is supplied by Renesas Electronics Corporation and is only
dkato 0:3a3146f89bcc 4 * intended for use with Renesas products. No other uses are authorized. This
dkato 0:3a3146f89bcc 5 * software is owned by Renesas Electronics Corporation and is protected under
dkato 0:3a3146f89bcc 6 * all applicable laws, including copyright laws.
dkato 0:3a3146f89bcc 7 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
dkato 0:3a3146f89bcc 8 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
dkato 0:3a3146f89bcc 9 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
dkato 0:3a3146f89bcc 10 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
dkato 0:3a3146f89bcc 11 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
dkato 0:3a3146f89bcc 12 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
dkato 0:3a3146f89bcc 13 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
dkato 0:3a3146f89bcc 14 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
dkato 0:3a3146f89bcc 15 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
dkato 0:3a3146f89bcc 16 * Renesas reserves the right, without notice, to make changes to this software
dkato 0:3a3146f89bcc 17 * and to discontinue the availability of this software. By using this software,
dkato 0:3a3146f89bcc 18 * you agree to the additional terms and conditions found by accessing the
dkato 0:3a3146f89bcc 19 * following link:
dkato 0:3a3146f89bcc 20 * http://www.renesas.com/disclaimer
dkato 0:3a3146f89bcc 21 * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
dkato 0:3a3146f89bcc 22 *******************************************************************************/
dkato 0:3a3146f89bcc 23
dkato 0:3a3146f89bcc 24 #include "USBHostDac.h"
dkato 0:3a3146f89bcc 25
dkato 0:3a3146f89bcc 26 #define SAMPLING (0x0100)
dkato 0:3a3146f89bcc 27 #define SET_CUR (0x01)
dkato 0:3a3146f89bcc 28 #define FRAME_COUNT (8)
dkato 0:3a3146f89bcc 29 #define PACKET_SIZE (192)
dkato 0:3a3146f89bcc 30 #define QUEUE_NUM (3)
dkato 0:3a3146f89bcc 31
dkato 0:3a3146f89bcc 32 USBHostDac::USBHostDac() {
dkato 0:3a3146f89bcc 33 host = USBHost::getHostInst();
dkato 0:3a3146f89bcc 34 m_isoEp = new IsochronousEp;
dkato 0:3a3146f89bcc 35 p_rest_data = new uint8_t[USBDAC_DATA_SIZE];
dkato 0:3a3146f89bcc 36
dkato 0:3a3146f89bcc 37 init();
dkato 0:3a3146f89bcc 38 }
dkato 0:3a3146f89bcc 39
dkato 0:3a3146f89bcc 40 void USBHostDac::init() {
dkato 0:3a3146f89bcc 41 dev = NULL;
dkato 0:3a3146f89bcc 42 dev_connected = false;
dkato 0:3a3146f89bcc 43 audio_device_found = false;
dkato 0:3a3146f89bcc 44 audio_intf = -1;
dkato 0:3a3146f89bcc 45 audio_intf_cnt = 0;
dkato 0:3a3146f89bcc 46 rest_data_index = 0;
dkato 0:3a3146f89bcc 47
dkato 0:3a3146f89bcc 48 wMaxPacketSize = 0;
dkato 0:3a3146f89bcc 49 bInterfaceNumber = 0;
dkato 0:3a3146f89bcc 50 bAlternateSetting = 0;
dkato 0:3a3146f89bcc 51 bEndpointAddress = 0;
dkato 0:3a3146f89bcc 52 }
dkato 0:3a3146f89bcc 53
dkato 0:3a3146f89bcc 54 bool USBHostDac::connected() {
dkato 0:3a3146f89bcc 55 return dev_connected;
dkato 0:3a3146f89bcc 56 }
dkato 0:3a3146f89bcc 57
dkato 0:3a3146f89bcc 58 bool USBHostDac::connect() {
dkato 0:3a3146f89bcc 59 if (dev_connected) {
dkato 0:3a3146f89bcc 60 return true;
dkato 0:3a3146f89bcc 61 }
dkato 0:3a3146f89bcc 62
dkato 0:3a3146f89bcc 63 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
dkato 0:3a3146f89bcc 64 if ((dev = host->getDevice(i)) != NULL) {
dkato 0:3a3146f89bcc 65
dkato 0:3a3146f89bcc 66 if (host->enumerate(dev, this)) {
dkato 0:3a3146f89bcc 67 break;
dkato 0:3a3146f89bcc 68 }
dkato 0:3a3146f89bcc 69
dkato 0:3a3146f89bcc 70 if (audio_device_found) {
dkato 0:3a3146f89bcc 71 USB_INFO("New UsbDac device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, audio_intf);
dkato 0:3a3146f89bcc 72 dev->setName("UsbDac", audio_intf);
dkato 0:3a3146f89bcc 73 host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect);
dkato 0:3a3146f89bcc 74
dkato 0:3a3146f89bcc 75 int addr = dev->getAddress();
dkato 0:3a3146f89bcc 76 m_isoEp->init(addr, bEndpointAddress, PACKET_SIZE, FRAME_COUNT, QUEUE_NUM);
dkato 0:3a3146f89bcc 77 setInterface(bAlternateSetting, bInterfaceNumber);
dkato 0:3a3146f89bcc 78 setSamplingRate(48000);
dkato 0:3a3146f89bcc 79
dkato 0:3a3146f89bcc 80 dev_connected = true;
dkato 0:3a3146f89bcc 81 return true;
dkato 0:3a3146f89bcc 82 }
dkato 0:3a3146f89bcc 83 }
dkato 0:3a3146f89bcc 84 }
dkato 0:3a3146f89bcc 85 init();
dkato 0:3a3146f89bcc 86 return false;
dkato 0:3a3146f89bcc 87 }
dkato 0:3a3146f89bcc 88
dkato 0:3a3146f89bcc 89 uint32_t USBHostDac::send(uint8_t* buf, uint32_t len, bool flush) {
dkato 0:3a3146f89bcc 90 uint32_t send_index = 0;
dkato 0:3a3146f89bcc 91 uint32_t rest_size = len;
dkato 0:3a3146f89bcc 92 uint32_t send_size;
dkato 0:3a3146f89bcc 93 uint32_t copy_size;
dkato 0:3a3146f89bcc 94 uint32_t def_send_size = PACKET_SIZE * FRAME_COUNT;
dkato 0:3a3146f89bcc 95
dkato 0:3a3146f89bcc 96 if (rest_data_index != 0) {
dkato 0:3a3146f89bcc 97 if (rest_size > (def_send_size - rest_data_index)) {
dkato 0:3a3146f89bcc 98 copy_size = (def_send_size - rest_data_index);
dkato 0:3a3146f89bcc 99 } else {
dkato 0:3a3146f89bcc 100 copy_size = rest_size;
dkato 0:3a3146f89bcc 101 }
dkato 0:3a3146f89bcc 102 memcpy(&p_rest_data[rest_data_index], &buf[send_index], copy_size);
dkato 0:3a3146f89bcc 103 send_index += copy_size;
dkato 0:3a3146f89bcc 104 rest_size -= copy_size;
dkato 0:3a3146f89bcc 105 rest_data_index += copy_size;
dkato 0:3a3146f89bcc 106 if ((flush != false) || (rest_data_index >= def_send_size)) {
dkato 0:3a3146f89bcc 107 m_isoEp->isochronousSend(&p_rest_data[0], rest_data_index, 100);
dkato 0:3a3146f89bcc 108 rest_data_index = 0;
dkato 0:3a3146f89bcc 109 }
dkato 0:3a3146f89bcc 110 }
dkato 0:3a3146f89bcc 111
dkato 0:3a3146f89bcc 112 while ((dev_connected) && (rest_size > 0)) {
dkato 0:3a3146f89bcc 113 if ((flush == false) && (rest_size < def_send_size)) {
dkato 0:3a3146f89bcc 114 memcpy(&p_rest_data[0], &buf[send_index], rest_size);
dkato 0:3a3146f89bcc 115 rest_data_index = rest_size;
dkato 0:3a3146f89bcc 116 break;
dkato 0:3a3146f89bcc 117 } else {
dkato 0:3a3146f89bcc 118 if (rest_size >= def_send_size) {
dkato 0:3a3146f89bcc 119 send_size = def_send_size;
dkato 0:3a3146f89bcc 120 } else {
dkato 0:3a3146f89bcc 121 send_size = rest_size;
dkato 0:3a3146f89bcc 122 }
dkato 0:3a3146f89bcc 123 m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
dkato 0:3a3146f89bcc 124 send_index += send_size;
dkato 0:3a3146f89bcc 125 rest_size -= send_size;
dkato 0:3a3146f89bcc 126 }
dkato 0:3a3146f89bcc 127 }
dkato 0:3a3146f89bcc 128
dkato 0:3a3146f89bcc 129 return send_index;
dkato 0:3a3146f89bcc 130 }
dkato 0:3a3146f89bcc 131
dkato 0:3a3146f89bcc 132 /*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid)
dkato 0:3a3146f89bcc 133 {
dkato 0:3a3146f89bcc 134 // we don't check VID/PID for audio driver
dkato 0:3a3146f89bcc 135 }
dkato 0:3a3146f89bcc 136
dkato 0:3a3146f89bcc 137 /*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
dkato 0:3a3146f89bcc 138 {
dkato 0:3a3146f89bcc 139 bool ret;
dkato 0:3a3146f89bcc 140
dkato 0:3a3146f89bcc 141 if (audio_intf != -1) {
dkato 0:3a3146f89bcc 142 ret = false;
dkato 0:3a3146f89bcc 143 } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) {
dkato 0:3a3146f89bcc 144 // AUDIOSTREAMING Subclass
dkato 0:3a3146f89bcc 145 ret = chkAudioStreaming();
dkato 0:3a3146f89bcc 146 if (ret != false) {
dkato 0:3a3146f89bcc 147 audio_intf = intf_nb;
dkato 0:3a3146f89bcc 148 audio_device_found = true;
dkato 0:3a3146f89bcc 149 }
dkato 0:3a3146f89bcc 150 } else {
dkato 0:3a3146f89bcc 151 ret = false;
dkato 0:3a3146f89bcc 152 }
dkato 0:3a3146f89bcc 153
dkato 0:3a3146f89bcc 154 return false;
dkato 0:3a3146f89bcc 155 }
dkato 0:3a3146f89bcc 156
dkato 0:3a3146f89bcc 157 /*virtual*/ bool USBHostDac::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
dkato 0:3a3146f89bcc 158 {
dkato 0:3a3146f89bcc 159 return false;
dkato 0:3a3146f89bcc 160 }
dkato 0:3a3146f89bcc 161
dkato 0:3a3146f89bcc 162 bool USBHostDac::chkAudioStreaming() {
dkato 0:3a3146f89bcc 163 uint8_t * conf_descr = host->getConfDescrCurPtr();
dkato 0:3a3146f89bcc 164 uint16_t len = host->getConfDescrRestLen();
dkato 0:3a3146f89bcc 165 uint32_t index = 0;
dkato 0:3a3146f89bcc 166 uint32_t len_desc = conf_descr[index];
dkato 0:3a3146f89bcc 167 uint32_t cnt;
dkato 0:3a3146f89bcc 168 uint32_t wk_sampling;
dkato 0:3a3146f89bcc 169 bool smpling_ok = false;
dkato 0:3a3146f89bcc 170 bool loop_end = false;
dkato 0:3a3146f89bcc 171 uint8_t channels = 0;
dkato 0:3a3146f89bcc 172 uint8_t SubframeSize = 0;
dkato 0:3a3146f89bcc 173 uint8_t id;
dkato 0:3a3146f89bcc 174
dkato 0:3a3146f89bcc 175 /* bNumEndpoints */
dkato 0:3a3146f89bcc 176 if (conf_descr[index + 4] >= 1) {
dkato 0:3a3146f89bcc 177 bInterfaceNumber = conf_descr[index + 2];
dkato 0:3a3146f89bcc 178 bAlternateSetting = conf_descr[index + 3];
dkato 0:3a3146f89bcc 179
dkato 0:3a3146f89bcc 180 index += len_desc;
dkato 0:3a3146f89bcc 181 while ((index < len) && (loop_end == false)) {
dkato 0:3a3146f89bcc 182 len_desc = conf_descr[index];
dkato 0:3a3146f89bcc 183 id = conf_descr[index+1];
dkato 0:3a3146f89bcc 184 switch (id) {
dkato 0:3a3146f89bcc 185 case INTERFACE_DESCRIPTOR:
dkato 0:3a3146f89bcc 186 /* next interface descriptor */
dkato 0:3a3146f89bcc 187 loop_end = true;
dkato 0:3a3146f89bcc 188 break;
dkato 0:3a3146f89bcc 189 case ENDPOINT_DESCRIPTOR:
dkato 0:3a3146f89bcc 190 if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) {
dkato 0:3a3146f89bcc 191 bEndpointAddress = conf_descr[index + 2];
dkato 0:3a3146f89bcc 192 wMaxPacketSize = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
dkato 0:3a3146f89bcc 193 loop_end = true;
dkato 0:3a3146f89bcc 194 }
dkato 0:3a3146f89bcc 195 break;
dkato 0:3a3146f89bcc 196 case 0x24: /* Audio Class Specific INTERFACE Descriptor */
dkato 0:3a3146f89bcc 197 if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1)) {
dkato 0:3a3146f89bcc 198 channels = conf_descr[index + 4];
dkato 0:3a3146f89bcc 199 SubframeSize = conf_descr[index + 5];
dkato 0:3a3146f89bcc 200 for (cnt = 8; (cnt + 3) <= len_desc; cnt += 3) {
dkato 0:3a3146f89bcc 201 wk_sampling = ((uint32_t)conf_descr[index + cnt + 0] << 0)
dkato 0:3a3146f89bcc 202 | ((uint32_t)conf_descr[index + cnt + 1] << 8)
dkato 0:3a3146f89bcc 203 | ((uint32_t)conf_descr[index + cnt + 2] << 16);
dkato 0:3a3146f89bcc 204 if (wk_sampling == 48000) {
dkato 0:3a3146f89bcc 205 smpling_ok = true;
dkato 0:3a3146f89bcc 206 }
dkato 0:3a3146f89bcc 207 }
dkato 0:3a3146f89bcc 208 }
dkato 0:3a3146f89bcc 209 break;
dkato 0:3a3146f89bcc 210 default:
dkato 0:3a3146f89bcc 211 break;
dkato 0:3a3146f89bcc 212 }
dkato 0:3a3146f89bcc 213 index += len_desc;
dkato 0:3a3146f89bcc 214 }
dkato 0:3a3146f89bcc 215
dkato 0:3a3146f89bcc 216 if (((bEndpointAddress & 0x80) == 0) && (wMaxPacketSize >= PACKET_SIZE)
dkato 0:3a3146f89bcc 217 && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) {
dkato 0:3a3146f89bcc 218 return true;
dkato 0:3a3146f89bcc 219 }
dkato 0:3a3146f89bcc 220 }
dkato 0:3a3146f89bcc 221
dkato 0:3a3146f89bcc 222 return false;
dkato 0:3a3146f89bcc 223 }
dkato 0:3a3146f89bcc 224
dkato 0:3a3146f89bcc 225 void USBHostDac::onDisconnect() {
dkato 0:3a3146f89bcc 226 if (dev_connected) {
dkato 0:3a3146f89bcc 227 m_isoEp->disconnect();
dkato 0:3a3146f89bcc 228 init();
dkato 0:3a3146f89bcc 229 }
dkato 0:3a3146f89bcc 230 }
dkato 0:3a3146f89bcc 231
dkato 0:3a3146f89bcc 232 USB_TYPE USBHostDac::setInterface(uint16_t alt, uint16_t index) {
dkato 0:3a3146f89bcc 233 return host->controlWrite( dev,
dkato 0:3a3146f89bcc 234 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
dkato 0:3a3146f89bcc 235 SET_INTERFACE,
dkato 0:3a3146f89bcc 236 alt, index, NULL, 0);
dkato 0:3a3146f89bcc 237 }
dkato 0:3a3146f89bcc 238
dkato 0:3a3146f89bcc 239 void USBHostDac::setSamplingRate(uint32_t sampling_rate) {
dkato 0:3a3146f89bcc 240 uint8_t data[3];
dkato 0:3a3146f89bcc 241
dkato 0:3a3146f89bcc 242 data[0] = (uint8_t)((sampling_rate >> 0) & 0xff);
dkato 0:3a3146f89bcc 243 data[1] = (uint8_t)((sampling_rate >> 8) & 0xff);
dkato 0:3a3146f89bcc 244 data[2] = (uint8_t)((sampling_rate >> 16) & 0xff);
dkato 0:3a3146f89bcc 245 host->controlWrite( dev,
dkato 0:3a3146f89bcc 246 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
dkato 0:3a3146f89bcc 247 SET_CUR,
dkato 0:3a3146f89bcc 248 SAMPLING, bEndpointAddress, data, 3);
dkato 0:3a3146f89bcc 249 }
dkato 0:3a3146f89bcc 250