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
USBHostDac.cpp@2:4afe26b3d48b, 2015-09-30 (annotated)
- Committer:
- dkato
- Date:
- Wed Sep 30 06:08:15 2015 +0000
- Revision:
- 2:4afe26b3d48b
- Parent:
- 1:9ff4cba6524d
Comments update.
Who changed what in which revision?
User | Revision | Line number | New 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 | 1:9ff4cba6524d | 34 | iso_send.m_isoEp = new IsochronousEp; |
dkato | 1:9ff4cba6524d | 35 | iso_send.p_rest_data = NULL; |
dkato | 1:9ff4cba6524d | 36 | |
dkato | 1:9ff4cba6524d | 37 | iso_recv.m_isoEp = new IsochronousEp; |
dkato | 1:9ff4cba6524d | 38 | iso_recv.p_rest_data = NULL; |
dkato | 0:3a3146f89bcc | 39 | |
dkato | 0:3a3146f89bcc | 40 | init(); |
dkato | 0:3a3146f89bcc | 41 | } |
dkato | 0:3a3146f89bcc | 42 | |
dkato | 1:9ff4cba6524d | 43 | USBHostDac::~USBHostDac() { |
dkato | 1:9ff4cba6524d | 44 | delete iso_send.m_isoEp; |
dkato | 1:9ff4cba6524d | 45 | delete iso_recv.m_isoEp; |
dkato | 1:9ff4cba6524d | 46 | } |
dkato | 1:9ff4cba6524d | 47 | |
dkato | 0:3a3146f89bcc | 48 | void USBHostDac::init() { |
dkato | 0:3a3146f89bcc | 49 | dev = NULL; |
dkato | 0:3a3146f89bcc | 50 | dev_connected = false; |
dkato | 0:3a3146f89bcc | 51 | audio_device_found = false; |
dkato | 0:3a3146f89bcc | 52 | audio_intf = -1; |
dkato | 0:3a3146f89bcc | 53 | audio_intf_cnt = 0; |
dkato | 1:9ff4cba6524d | 54 | iso_send.bEndpointAddress = 0; |
dkato | 1:9ff4cba6524d | 55 | iso_send.rest_data_index = 0; |
dkato | 1:9ff4cba6524d | 56 | iso_send.rest_data_size = 0; |
dkato | 1:9ff4cba6524d | 57 | if (iso_send.p_rest_data != NULL) { |
dkato | 1:9ff4cba6524d | 58 | delete iso_send.p_rest_data; |
dkato | 1:9ff4cba6524d | 59 | iso_send.p_rest_data = NULL; |
dkato | 1:9ff4cba6524d | 60 | } |
dkato | 1:9ff4cba6524d | 61 | iso_recv.bEndpointAddress = 0; |
dkato | 1:9ff4cba6524d | 62 | iso_recv.rest_data_index = 0; |
dkato | 1:9ff4cba6524d | 63 | iso_recv.rest_data_size = 0; |
dkato | 1:9ff4cba6524d | 64 | if (iso_recv.p_rest_data != NULL) { |
dkato | 1:9ff4cba6524d | 65 | delete iso_recv.p_rest_data; |
dkato | 1:9ff4cba6524d | 66 | iso_recv.p_rest_data = NULL; |
dkato | 1:9ff4cba6524d | 67 | } |
dkato | 0:3a3146f89bcc | 68 | } |
dkato | 0:3a3146f89bcc | 69 | |
dkato | 0:3a3146f89bcc | 70 | bool USBHostDac::connected() { |
dkato | 0:3a3146f89bcc | 71 | return dev_connected; |
dkato | 0:3a3146f89bcc | 72 | } |
dkato | 0:3a3146f89bcc | 73 | |
dkato | 0:3a3146f89bcc | 74 | bool USBHostDac::connect() { |
dkato | 0:3a3146f89bcc | 75 | if (dev_connected) { |
dkato | 0:3a3146f89bcc | 76 | return true; |
dkato | 0:3a3146f89bcc | 77 | } |
dkato | 0:3a3146f89bcc | 78 | |
dkato | 0:3a3146f89bcc | 79 | for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { |
dkato | 0:3a3146f89bcc | 80 | if ((dev = host->getDevice(i)) != NULL) { |
dkato | 0:3a3146f89bcc | 81 | |
dkato | 0:3a3146f89bcc | 82 | if (host->enumerate(dev, this)) { |
dkato | 0:3a3146f89bcc | 83 | break; |
dkato | 0:3a3146f89bcc | 84 | } |
dkato | 0:3a3146f89bcc | 85 | |
dkato | 0:3a3146f89bcc | 86 | if (audio_device_found) { |
dkato | 0:3a3146f89bcc | 87 | USB_INFO("New UsbDac device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, audio_intf); |
dkato | 0:3a3146f89bcc | 88 | dev->setName("UsbDac", audio_intf); |
dkato | 0:3a3146f89bcc | 89 | host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect); |
dkato | 0:3a3146f89bcc | 90 | |
dkato | 0:3a3146f89bcc | 91 | int addr = dev->getAddress(); |
dkato | 1:9ff4cba6524d | 92 | |
dkato | 1:9ff4cba6524d | 93 | if (iso_send.bEndpointAddress != 0) { |
dkato | 1:9ff4cba6524d | 94 | iso_send.p_rest_data = new uint8_t[PACKET_SIZE * FRAME_COUNT]; |
dkato | 1:9ff4cba6524d | 95 | iso_send.m_isoEp->init(addr, iso_send.bEndpointAddress, PACKET_SIZE, FRAME_COUNT, QUEUE_NUM); |
dkato | 1:9ff4cba6524d | 96 | setInterface(iso_send.bAlternateSetting, iso_send.bInterfaceNumber); |
dkato | 1:9ff4cba6524d | 97 | setSamplingRate(iso_send.bEndpointAddress, 48000); |
dkato | 1:9ff4cba6524d | 98 | } |
dkato | 1:9ff4cba6524d | 99 | |
dkato | 1:9ff4cba6524d | 100 | if (iso_recv.bEndpointAddress != 0) { |
dkato | 1:9ff4cba6524d | 101 | iso_recv.p_rest_data = new uint8_t[iso_recv.wMaxPacketSize * FRAME_COUNT]; |
dkato | 1:9ff4cba6524d | 102 | iso_recv.m_isoEp->init(addr, iso_recv.bEndpointAddress, iso_recv.wMaxPacketSize, FRAME_COUNT, QUEUE_NUM); |
dkato | 1:9ff4cba6524d | 103 | setInterface(iso_recv.bAlternateSetting, iso_recv.bInterfaceNumber); |
dkato | 1:9ff4cba6524d | 104 | setSamplingRate(iso_recv.bEndpointAddress, 48000); |
dkato | 1:9ff4cba6524d | 105 | } |
dkato | 0:3a3146f89bcc | 106 | |
dkato | 0:3a3146f89bcc | 107 | dev_connected = true; |
dkato | 0:3a3146f89bcc | 108 | return true; |
dkato | 0:3a3146f89bcc | 109 | } |
dkato | 0:3a3146f89bcc | 110 | } |
dkato | 0:3a3146f89bcc | 111 | } |
dkato | 0:3a3146f89bcc | 112 | init(); |
dkato | 0:3a3146f89bcc | 113 | return false; |
dkato | 0:3a3146f89bcc | 114 | } |
dkato | 0:3a3146f89bcc | 115 | |
dkato | 0:3a3146f89bcc | 116 | uint32_t USBHostDac::send(uint8_t* buf, uint32_t len, bool flush) { |
dkato | 0:3a3146f89bcc | 117 | uint32_t send_index = 0; |
dkato | 0:3a3146f89bcc | 118 | uint32_t rest_size = len; |
dkato | 0:3a3146f89bcc | 119 | uint32_t send_size; |
dkato | 0:3a3146f89bcc | 120 | uint32_t copy_size; |
dkato | 1:9ff4cba6524d | 121 | int result; |
dkato | 0:3a3146f89bcc | 122 | |
dkato | 1:9ff4cba6524d | 123 | if (iso_send.bEndpointAddress == 0) { |
dkato | 1:9ff4cba6524d | 124 | return 0; |
dkato | 1:9ff4cba6524d | 125 | } |
dkato | 1:9ff4cba6524d | 126 | |
dkato | 1:9ff4cba6524d | 127 | if (iso_send.rest_data_index != 0) { |
dkato | 1:9ff4cba6524d | 128 | if (rest_size > iso_send.rest_data_size) { |
dkato | 1:9ff4cba6524d | 129 | copy_size = iso_send.rest_data_size; |
dkato | 0:3a3146f89bcc | 130 | } else { |
dkato | 0:3a3146f89bcc | 131 | copy_size = rest_size; |
dkato | 0:3a3146f89bcc | 132 | } |
dkato | 1:9ff4cba6524d | 133 | memcpy(&iso_send.p_rest_data[iso_send.rest_data_index], &buf[send_index], copy_size); |
dkato | 0:3a3146f89bcc | 134 | send_index += copy_size; |
dkato | 0:3a3146f89bcc | 135 | rest_size -= copy_size; |
dkato | 1:9ff4cba6524d | 136 | iso_send.rest_data_index += copy_size; |
dkato | 1:9ff4cba6524d | 137 | if ((flush != false) || (iso_send.rest_data_index >= (PACKET_SIZE * FRAME_COUNT))) { |
dkato | 1:9ff4cba6524d | 138 | if (iso_send.m_isoEp->getQueueNum() == 0) { |
dkato | 1:9ff4cba6524d | 139 | iso_send.m_isoEp->reset(4); |
dkato | 1:9ff4cba6524d | 140 | } |
dkato | 1:9ff4cba6524d | 141 | result = iso_send.m_isoEp->isochronousSend(&iso_send.p_rest_data[0], iso_send.rest_data_index, 100); |
dkato | 1:9ff4cba6524d | 142 | iso_send.rest_data_index = 0; |
dkato | 0:3a3146f89bcc | 143 | } |
dkato | 0:3a3146f89bcc | 144 | } |
dkato | 0:3a3146f89bcc | 145 | |
dkato | 0:3a3146f89bcc | 146 | while ((dev_connected) && (rest_size > 0)) { |
dkato | 1:9ff4cba6524d | 147 | if ((flush == false) && (rest_size < (PACKET_SIZE * FRAME_COUNT))) { |
dkato | 1:9ff4cba6524d | 148 | memcpy(&iso_send.p_rest_data[0], &buf[send_index], rest_size); |
dkato | 1:9ff4cba6524d | 149 | iso_send.rest_data_index = rest_size; |
dkato | 1:9ff4cba6524d | 150 | iso_send.rest_data_size = (PACKET_SIZE * FRAME_COUNT) - rest_size; |
dkato | 0:3a3146f89bcc | 151 | break; |
dkato | 0:3a3146f89bcc | 152 | } else { |
dkato | 1:9ff4cba6524d | 153 | if (rest_size >= (PACKET_SIZE * FRAME_COUNT)) { |
dkato | 1:9ff4cba6524d | 154 | send_size = (PACKET_SIZE * FRAME_COUNT); |
dkato | 0:3a3146f89bcc | 155 | } else { |
dkato | 0:3a3146f89bcc | 156 | send_size = rest_size; |
dkato | 0:3a3146f89bcc | 157 | } |
dkato | 1:9ff4cba6524d | 158 | if (iso_send.m_isoEp->getQueueNum() == 0) { |
dkato | 1:9ff4cba6524d | 159 | iso_send.m_isoEp->reset(4); |
dkato | 1:9ff4cba6524d | 160 | } |
dkato | 1:9ff4cba6524d | 161 | result = iso_send.m_isoEp->isochronousSend(&buf[send_index], send_size, 100); |
dkato | 1:9ff4cba6524d | 162 | send_index += result; |
dkato | 1:9ff4cba6524d | 163 | rest_size -= result; |
dkato | 0:3a3146f89bcc | 164 | } |
dkato | 0:3a3146f89bcc | 165 | } |
dkato | 0:3a3146f89bcc | 166 | |
dkato | 0:3a3146f89bcc | 167 | return send_index; |
dkato | 0:3a3146f89bcc | 168 | } |
dkato | 0:3a3146f89bcc | 169 | |
dkato | 1:9ff4cba6524d | 170 | uint32_t USBHostDac::receive(uint8_t* buf, uint32_t len) { |
dkato | 1:9ff4cba6524d | 171 | uint32_t recv_index = 0; |
dkato | 1:9ff4cba6524d | 172 | uint32_t rest_size = len; |
dkato | 1:9ff4cba6524d | 173 | uint32_t copy_size; |
dkato | 1:9ff4cba6524d | 174 | |
dkato | 1:9ff4cba6524d | 175 | if (iso_recv.bEndpointAddress == 0) { |
dkato | 1:9ff4cba6524d | 176 | return 0; |
dkato | 1:9ff4cba6524d | 177 | } |
dkato | 1:9ff4cba6524d | 178 | |
dkato | 1:9ff4cba6524d | 179 | if (iso_recv.rest_data_size != 0) { |
dkato | 1:9ff4cba6524d | 180 | if (rest_size > iso_recv.rest_data_size) { |
dkato | 1:9ff4cba6524d | 181 | copy_size = iso_recv.rest_data_size; |
dkato | 1:9ff4cba6524d | 182 | } else { |
dkato | 1:9ff4cba6524d | 183 | copy_size = rest_size; |
dkato | 1:9ff4cba6524d | 184 | } |
dkato | 1:9ff4cba6524d | 185 | memcpy(&buf[recv_index], &iso_recv.p_rest_data[iso_recv.rest_data_index], copy_size); |
dkato | 1:9ff4cba6524d | 186 | recv_index += copy_size; |
dkato | 1:9ff4cba6524d | 187 | rest_size -= copy_size; |
dkato | 1:9ff4cba6524d | 188 | iso_recv.rest_data_index += copy_size; |
dkato | 1:9ff4cba6524d | 189 | iso_recv.rest_data_size -= copy_size; |
dkato | 1:9ff4cba6524d | 190 | } |
dkato | 1:9ff4cba6524d | 191 | |
dkato | 1:9ff4cba6524d | 192 | while ((dev_connected) && (rest_size > 0)) { |
dkato | 1:9ff4cba6524d | 193 | iso_recv.rest_data_index = 0; |
dkato | 1:9ff4cba6524d | 194 | iso_recv.rest_data_size = 0; |
dkato | 1:9ff4cba6524d | 195 | |
dkato | 1:9ff4cba6524d | 196 | if (iso_recv.m_isoEp->getQueueNum() == 0) { |
dkato | 1:9ff4cba6524d | 197 | iso_recv.m_isoEp->reset(4); |
dkato | 1:9ff4cba6524d | 198 | } |
dkato | 1:9ff4cba6524d | 199 | HCITD* itd = iso_recv.m_isoEp->isochronousReceive(100); |
dkato | 1:9ff4cba6524d | 200 | if (itd) { |
dkato | 1:9ff4cba6524d | 201 | uint8_t cc = itd->ConditionCode(); |
dkato | 1:9ff4cba6524d | 202 | if (cc == 0) { |
dkato | 1:9ff4cba6524d | 203 | int fc = itd->FrameCount(); |
dkato | 1:9ff4cba6524d | 204 | uint8_t* wk_buf = const_cast<uint8_t*>(itd->buf); |
dkato | 1:9ff4cba6524d | 205 | int mps = iso_recv.m_isoEp->m_PacketSize; |
dkato | 1:9ff4cba6524d | 206 | for (int i = 0; i < fc; i++) { |
dkato | 1:9ff4cba6524d | 207 | uint16_t psw = itd->OffsetPSW[i]; |
dkato | 1:9ff4cba6524d | 208 | cc = psw>>12; |
dkato | 1:9ff4cba6524d | 209 | if (cc == 0 || cc == 9) { |
dkato | 1:9ff4cba6524d | 210 | int wk_len = psw & 0x7ff; |
dkato | 1:9ff4cba6524d | 211 | if (rest_size > 0) { |
dkato | 1:9ff4cba6524d | 212 | if (rest_size > wk_len) { |
dkato | 1:9ff4cba6524d | 213 | copy_size = wk_len; |
dkato | 1:9ff4cba6524d | 214 | } else { |
dkato | 1:9ff4cba6524d | 215 | copy_size = rest_size; |
dkato | 1:9ff4cba6524d | 216 | } |
dkato | 1:9ff4cba6524d | 217 | memcpy(&buf[recv_index], wk_buf, copy_size); |
dkato | 1:9ff4cba6524d | 218 | recv_index += copy_size; |
dkato | 1:9ff4cba6524d | 219 | rest_size -= copy_size; |
dkato | 1:9ff4cba6524d | 220 | if (copy_size < wk_len) { |
dkato | 1:9ff4cba6524d | 221 | memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[copy_size], (wk_len - copy_size)); |
dkato | 1:9ff4cba6524d | 222 | iso_recv.rest_data_size += (wk_len - copy_size); |
dkato | 1:9ff4cba6524d | 223 | } |
dkato | 1:9ff4cba6524d | 224 | } else { |
dkato | 1:9ff4cba6524d | 225 | memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[0], wk_len); |
dkato | 1:9ff4cba6524d | 226 | iso_recv.rest_data_size += wk_len; |
dkato | 1:9ff4cba6524d | 227 | } |
dkato | 1:9ff4cba6524d | 228 | } |
dkato | 1:9ff4cba6524d | 229 | wk_buf += mps; |
dkato | 1:9ff4cba6524d | 230 | } |
dkato | 1:9ff4cba6524d | 231 | } |
dkato | 1:9ff4cba6524d | 232 | delete itd; |
dkato | 1:9ff4cba6524d | 233 | } |
dkato | 1:9ff4cba6524d | 234 | } |
dkato | 1:9ff4cba6524d | 235 | |
dkato | 1:9ff4cba6524d | 236 | return recv_index; |
dkato | 1:9ff4cba6524d | 237 | } |
dkato | 1:9ff4cba6524d | 238 | |
dkato | 0:3a3146f89bcc | 239 | /*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid) |
dkato | 0:3a3146f89bcc | 240 | { |
dkato | 0:3a3146f89bcc | 241 | // we don't check VID/PID for audio driver |
dkato | 0:3a3146f89bcc | 242 | } |
dkato | 0:3a3146f89bcc | 243 | |
dkato | 0:3a3146f89bcc | 244 | /*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 | 245 | { |
dkato | 0:3a3146f89bcc | 246 | bool ret; |
dkato | 0:3a3146f89bcc | 247 | |
dkato | 1:9ff4cba6524d | 248 | if (audio_intf_cnt >= 2) { |
dkato | 0:3a3146f89bcc | 249 | ret = false; |
dkato | 0:3a3146f89bcc | 250 | } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) { |
dkato | 0:3a3146f89bcc | 251 | // AUDIOSTREAMING Subclass |
dkato | 0:3a3146f89bcc | 252 | ret = chkAudioStreaming(); |
dkato | 0:3a3146f89bcc | 253 | if (ret != false) { |
dkato | 0:3a3146f89bcc | 254 | audio_intf = intf_nb; |
dkato | 0:3a3146f89bcc | 255 | audio_device_found = true; |
dkato | 1:9ff4cba6524d | 256 | audio_intf_cnt++; |
dkato | 0:3a3146f89bcc | 257 | } |
dkato | 0:3a3146f89bcc | 258 | } else { |
dkato | 0:3a3146f89bcc | 259 | ret = false; |
dkato | 0:3a3146f89bcc | 260 | } |
dkato | 0:3a3146f89bcc | 261 | |
dkato | 0:3a3146f89bcc | 262 | return false; |
dkato | 0:3a3146f89bcc | 263 | } |
dkato | 0:3a3146f89bcc | 264 | |
dkato | 0:3a3146f89bcc | 265 | /*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 | 266 | { |
dkato | 0:3a3146f89bcc | 267 | return false; |
dkato | 0:3a3146f89bcc | 268 | } |
dkato | 0:3a3146f89bcc | 269 | |
dkato | 0:3a3146f89bcc | 270 | bool USBHostDac::chkAudioStreaming() { |
dkato | 0:3a3146f89bcc | 271 | uint8_t * conf_descr = host->getConfDescrCurPtr(); |
dkato | 0:3a3146f89bcc | 272 | uint16_t len = host->getConfDescrRestLen(); |
dkato | 0:3a3146f89bcc | 273 | uint32_t index = 0; |
dkato | 0:3a3146f89bcc | 274 | uint32_t len_desc = conf_descr[index]; |
dkato | 0:3a3146f89bcc | 275 | uint32_t cnt; |
dkato | 0:3a3146f89bcc | 276 | uint32_t wk_sampling; |
dkato | 0:3a3146f89bcc | 277 | bool smpling_ok = false; |
dkato | 0:3a3146f89bcc | 278 | bool loop_end = false; |
dkato | 0:3a3146f89bcc | 279 | uint8_t channels = 0; |
dkato | 0:3a3146f89bcc | 280 | uint8_t SubframeSize = 0; |
dkato | 0:3a3146f89bcc | 281 | uint8_t id; |
dkato | 1:9ff4cba6524d | 282 | uint16_t wk_wMaxPacketSize; |
dkato | 1:9ff4cba6524d | 283 | uint8_t wk_bEndpointAddress; |
dkato | 1:9ff4cba6524d | 284 | uint8_t wk_bInterfaceNumber; |
dkato | 1:9ff4cba6524d | 285 | uint8_t wk_bAlternateSetting; |
dkato | 0:3a3146f89bcc | 286 | |
dkato | 0:3a3146f89bcc | 287 | /* bNumEndpoints */ |
dkato | 0:3a3146f89bcc | 288 | if (conf_descr[index + 4] >= 1) { |
dkato | 1:9ff4cba6524d | 289 | wk_bInterfaceNumber = conf_descr[index + 2]; |
dkato | 1:9ff4cba6524d | 290 | wk_bAlternateSetting = conf_descr[index + 3]; |
dkato | 1:9ff4cba6524d | 291 | wk_wMaxPacketSize = 0; |
dkato | 1:9ff4cba6524d | 292 | wk_bEndpointAddress = 0; |
dkato | 0:3a3146f89bcc | 293 | |
dkato | 0:3a3146f89bcc | 294 | index += len_desc; |
dkato | 0:3a3146f89bcc | 295 | while ((index < len) && (loop_end == false)) { |
dkato | 0:3a3146f89bcc | 296 | len_desc = conf_descr[index]; |
dkato | 0:3a3146f89bcc | 297 | id = conf_descr[index+1]; |
dkato | 0:3a3146f89bcc | 298 | switch (id) { |
dkato | 0:3a3146f89bcc | 299 | case INTERFACE_DESCRIPTOR: |
dkato | 0:3a3146f89bcc | 300 | /* next interface descriptor */ |
dkato | 0:3a3146f89bcc | 301 | loop_end = true; |
dkato | 0:3a3146f89bcc | 302 | break; |
dkato | 0:3a3146f89bcc | 303 | case ENDPOINT_DESCRIPTOR: |
dkato | 0:3a3146f89bcc | 304 | if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) { |
dkato | 1:9ff4cba6524d | 305 | wk_bEndpointAddress = conf_descr[index + 2]; |
dkato | 1:9ff4cba6524d | 306 | wk_wMaxPacketSize = (conf_descr[index + 5] << 8) + conf_descr[index + 4]; |
dkato | 0:3a3146f89bcc | 307 | loop_end = true; |
dkato | 0:3a3146f89bcc | 308 | } |
dkato | 0:3a3146f89bcc | 309 | break; |
dkato | 0:3a3146f89bcc | 310 | case 0x24: /* Audio Class Specific INTERFACE Descriptor */ |
dkato | 0:3a3146f89bcc | 311 | if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1)) { |
dkato | 0:3a3146f89bcc | 312 | channels = conf_descr[index + 4]; |
dkato | 0:3a3146f89bcc | 313 | SubframeSize = conf_descr[index + 5]; |
dkato | 0:3a3146f89bcc | 314 | for (cnt = 8; (cnt + 3) <= len_desc; cnt += 3) { |
dkato | 0:3a3146f89bcc | 315 | wk_sampling = ((uint32_t)conf_descr[index + cnt + 0] << 0) |
dkato | 0:3a3146f89bcc | 316 | | ((uint32_t)conf_descr[index + cnt + 1] << 8) |
dkato | 0:3a3146f89bcc | 317 | | ((uint32_t)conf_descr[index + cnt + 2] << 16); |
dkato | 0:3a3146f89bcc | 318 | if (wk_sampling == 48000) { |
dkato | 0:3a3146f89bcc | 319 | smpling_ok = true; |
dkato | 0:3a3146f89bcc | 320 | } |
dkato | 0:3a3146f89bcc | 321 | } |
dkato | 0:3a3146f89bcc | 322 | } |
dkato | 0:3a3146f89bcc | 323 | break; |
dkato | 0:3a3146f89bcc | 324 | default: |
dkato | 0:3a3146f89bcc | 325 | break; |
dkato | 0:3a3146f89bcc | 326 | } |
dkato | 0:3a3146f89bcc | 327 | index += len_desc; |
dkato | 0:3a3146f89bcc | 328 | } |
dkato | 0:3a3146f89bcc | 329 | |
dkato | 1:9ff4cba6524d | 330 | if (((wk_bEndpointAddress & 0x80) == 0) && (wk_wMaxPacketSize >= PACKET_SIZE) |
dkato | 0:3a3146f89bcc | 331 | && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) { |
dkato | 1:9ff4cba6524d | 332 | iso_send.wMaxPacketSize = wk_wMaxPacketSize; |
dkato | 1:9ff4cba6524d | 333 | iso_send.bEndpointAddress = wk_bEndpointAddress; |
dkato | 1:9ff4cba6524d | 334 | iso_send.bInterfaceNumber = wk_bInterfaceNumber; |
dkato | 1:9ff4cba6524d | 335 | iso_send.bAlternateSetting = wk_bAlternateSetting; |
dkato | 1:9ff4cba6524d | 336 | return true; |
dkato | 1:9ff4cba6524d | 337 | } |
dkato | 1:9ff4cba6524d | 338 | |
dkato | 1:9ff4cba6524d | 339 | if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE/2)) |
dkato | 1:9ff4cba6524d | 340 | && (channels == 1) && (SubframeSize == 2) && (smpling_ok != false)) { |
dkato | 1:9ff4cba6524d | 341 | iso_recv.wMaxPacketSize = wk_wMaxPacketSize; |
dkato | 1:9ff4cba6524d | 342 | iso_recv.bEndpointAddress = wk_bEndpointAddress; |
dkato | 1:9ff4cba6524d | 343 | iso_recv.bInterfaceNumber = wk_bInterfaceNumber; |
dkato | 1:9ff4cba6524d | 344 | iso_recv.bAlternateSetting = wk_bAlternateSetting; |
dkato | 0:3a3146f89bcc | 345 | return true; |
dkato | 0:3a3146f89bcc | 346 | } |
dkato | 0:3a3146f89bcc | 347 | } |
dkato | 0:3a3146f89bcc | 348 | |
dkato | 0:3a3146f89bcc | 349 | return false; |
dkato | 0:3a3146f89bcc | 350 | } |
dkato | 0:3a3146f89bcc | 351 | |
dkato | 0:3a3146f89bcc | 352 | void USBHostDac::onDisconnect() { |
dkato | 0:3a3146f89bcc | 353 | if (dev_connected) { |
dkato | 1:9ff4cba6524d | 354 | if (iso_send.bEndpointAddress != 0) { |
dkato | 1:9ff4cba6524d | 355 | iso_send.m_isoEp->disconnect(); |
dkato | 1:9ff4cba6524d | 356 | } |
dkato | 1:9ff4cba6524d | 357 | if (iso_recv.bEndpointAddress != 0) { |
dkato | 1:9ff4cba6524d | 358 | iso_recv.m_isoEp->disconnect(); |
dkato | 1:9ff4cba6524d | 359 | } |
dkato | 0:3a3146f89bcc | 360 | init(); |
dkato | 0:3a3146f89bcc | 361 | } |
dkato | 0:3a3146f89bcc | 362 | } |
dkato | 0:3a3146f89bcc | 363 | |
dkato | 0:3a3146f89bcc | 364 | USB_TYPE USBHostDac::setInterface(uint16_t alt, uint16_t index) { |
dkato | 0:3a3146f89bcc | 365 | return host->controlWrite( dev, |
dkato | 0:3a3146f89bcc | 366 | USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, |
dkato | 0:3a3146f89bcc | 367 | SET_INTERFACE, |
dkato | 0:3a3146f89bcc | 368 | alt, index, NULL, 0); |
dkato | 0:3a3146f89bcc | 369 | } |
dkato | 0:3a3146f89bcc | 370 | |
dkato | 1:9ff4cba6524d | 371 | void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) { |
dkato | 0:3a3146f89bcc | 372 | uint8_t data[3]; |
dkato | 0:3a3146f89bcc | 373 | |
dkato | 0:3a3146f89bcc | 374 | data[0] = (uint8_t)((sampling_rate >> 0) & 0xff); |
dkato | 0:3a3146f89bcc | 375 | data[1] = (uint8_t)((sampling_rate >> 8) & 0xff); |
dkato | 0:3a3146f89bcc | 376 | data[2] = (uint8_t)((sampling_rate >> 16) & 0xff); |
dkato | 0:3a3146f89bcc | 377 | host->controlWrite( dev, |
dkato | 0:3a3146f89bcc | 378 | USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, |
dkato | 0:3a3146f89bcc | 379 | SET_CUR, |
dkato | 1:9ff4cba6524d | 380 | SAMPLING, endpoint_adder, data, 3); |
dkato | 0:3a3146f89bcc | 381 | } |
dkato | 0:3a3146f89bcc | 382 |