Increase ITD queue count.
USBHost6ChDac.cpp@3:5006f79eb589, 2015-10-18 (annotated)
- Committer:
- dokunewon
- Date:
- Sun Oct 18 08:16:39 2015 +0000
- Revision:
- 3:5006f79eb589
Change a little.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dokunewon | 3:5006f79eb589 | 1 | /******************************************************************************* |
dokunewon | 3:5006f79eb589 | 2 | * DISCLAIMER |
dokunewon | 3:5006f79eb589 | 3 | * This software is supplied by Renesas Electronics Corporation and is only |
dokunewon | 3:5006f79eb589 | 4 | * intended for use with Renesas products. No other uses are authorized. This |
dokunewon | 3:5006f79eb589 | 5 | * software is owned by Renesas Electronics Corporation and is protected under |
dokunewon | 3:5006f79eb589 | 6 | * all applicable laws, including copyright laws. |
dokunewon | 3:5006f79eb589 | 7 | * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING |
dokunewon | 3:5006f79eb589 | 8 | * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT |
dokunewon | 3:5006f79eb589 | 9 | * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE |
dokunewon | 3:5006f79eb589 | 10 | * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. |
dokunewon | 3:5006f79eb589 | 11 | * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS |
dokunewon | 3:5006f79eb589 | 12 | * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE |
dokunewon | 3:5006f79eb589 | 13 | * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR |
dokunewon | 3:5006f79eb589 | 14 | * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE |
dokunewon | 3:5006f79eb589 | 15 | * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. |
dokunewon | 3:5006f79eb589 | 16 | * Renesas reserves the right, without notice, to make changes to this software |
dokunewon | 3:5006f79eb589 | 17 | * and to discontinue the availability of this software. By using this software, |
dokunewon | 3:5006f79eb589 | 18 | * you agree to the additional terms and conditions found by accessing the |
dokunewon | 3:5006f79eb589 | 19 | * following link: |
dokunewon | 3:5006f79eb589 | 20 | * http://www.renesas.com/disclaimer |
dokunewon | 3:5006f79eb589 | 21 | * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved. |
dokunewon | 3:5006f79eb589 | 22 | *******************************************************************************/ |
dokunewon | 3:5006f79eb589 | 23 | |
dokunewon | 3:5006f79eb589 | 24 | #include "USBHost6ChDac.h" |
dokunewon | 3:5006f79eb589 | 25 | |
dokunewon | 3:5006f79eb589 | 26 | #define FUCS_CH0 (0x00) |
dokunewon | 3:5006f79eb589 | 27 | #define FUCS_CH1 (0x01) |
dokunewon | 3:5006f79eb589 | 28 | #define FUCS_CH2 (0x02) |
dokunewon | 3:5006f79eb589 | 29 | #define FUCS_CH3 (0x03) |
dokunewon | 3:5006f79eb589 | 30 | #define FUCS_MUTE (0x0100) |
dokunewon | 3:5006f79eb589 | 31 | #define FUCS_VOLUME (0x0200) |
dokunewon | 3:5006f79eb589 | 32 | |
dokunewon | 3:5006f79eb589 | 33 | #define SAMPLING (0x0100) |
dokunewon | 3:5006f79eb589 | 34 | #define SET_CUR (0x01) |
dokunewon | 3:5006f79eb589 | 35 | #define FRAME_COUNT (8) |
dokunewon | 3:5006f79eb589 | 36 | #define PACKET_SIZE (192) |
dokunewon | 3:5006f79eb589 | 37 | #define PACKET_SIZE_6CH (192 * 3) |
dokunewon | 3:5006f79eb589 | 38 | //doku #define QUEUE_NUM (3) |
dokunewon | 3:5006f79eb589 | 39 | #define QUEUE_NUM (11) |
dokunewon | 3:5006f79eb589 | 40 | |
dokunewon | 3:5006f79eb589 | 41 | //#define DESC_REP printf |
dokunewon | 3:5006f79eb589 | 42 | #define DESC_REP(...) while(0); |
dokunewon | 3:5006f79eb589 | 43 | |
dokunewon | 3:5006f79eb589 | 44 | USBHostDac::USBHostDac() { |
dokunewon | 3:5006f79eb589 | 45 | host = USBHost::getHostInst(); |
dokunewon | 3:5006f79eb589 | 46 | iso_send.m_isoEp = new IsochronousEp; |
dokunewon | 3:5006f79eb589 | 47 | iso_send.p_rest_data = NULL; |
dokunewon | 3:5006f79eb589 | 48 | |
dokunewon | 3:5006f79eb589 | 49 | iso_recv.m_isoEp = new IsochronousEp; |
dokunewon | 3:5006f79eb589 | 50 | iso_recv.p_rest_data = NULL; |
dokunewon | 3:5006f79eb589 | 51 | |
dokunewon | 3:5006f79eb589 | 52 | init(); |
dokunewon | 3:5006f79eb589 | 53 | } |
dokunewon | 3:5006f79eb589 | 54 | |
dokunewon | 3:5006f79eb589 | 55 | USBHostDac::~USBHostDac() { |
dokunewon | 3:5006f79eb589 | 56 | delete iso_send.m_isoEp; |
dokunewon | 3:5006f79eb589 | 57 | delete iso_recv.m_isoEp; |
dokunewon | 3:5006f79eb589 | 58 | } |
dokunewon | 3:5006f79eb589 | 59 | |
dokunewon | 3:5006f79eb589 | 60 | void USBHostDac::init() { |
dokunewon | 3:5006f79eb589 | 61 | dev = NULL; |
dokunewon | 3:5006f79eb589 | 62 | dev_connected = false; |
dokunewon | 3:5006f79eb589 | 63 | audio_device_found = false; |
dokunewon | 3:5006f79eb589 | 64 | audio_intf = -1; |
dokunewon | 3:5006f79eb589 | 65 | audio_intf_cnt = 0; |
dokunewon | 3:5006f79eb589 | 66 | iso_send.bEndpointAddress = 0; |
dokunewon | 3:5006f79eb589 | 67 | iso_send.rest_data_index = 0; |
dokunewon | 3:5006f79eb589 | 68 | iso_send.rest_data_size = 0; |
dokunewon | 3:5006f79eb589 | 69 | if (iso_send.p_rest_data != NULL) { |
dokunewon | 3:5006f79eb589 | 70 | delete iso_send.p_rest_data; |
dokunewon | 3:5006f79eb589 | 71 | iso_send.p_rest_data = NULL; |
dokunewon | 3:5006f79eb589 | 72 | } |
dokunewon | 3:5006f79eb589 | 73 | iso_recv.bEndpointAddress = 0; |
dokunewon | 3:5006f79eb589 | 74 | iso_recv.rest_data_index = 0; |
dokunewon | 3:5006f79eb589 | 75 | iso_recv.rest_data_size = 0; |
dokunewon | 3:5006f79eb589 | 76 | if (iso_recv.p_rest_data != NULL) { |
dokunewon | 3:5006f79eb589 | 77 | delete iso_recv.p_rest_data; |
dokunewon | 3:5006f79eb589 | 78 | iso_recv.p_rest_data = NULL; |
dokunewon | 3:5006f79eb589 | 79 | } |
dokunewon | 3:5006f79eb589 | 80 | } |
dokunewon | 3:5006f79eb589 | 81 | |
dokunewon | 3:5006f79eb589 | 82 | bool USBHostDac::connected() { |
dokunewon | 3:5006f79eb589 | 83 | return dev_connected; |
dokunewon | 3:5006f79eb589 | 84 | } |
dokunewon | 3:5006f79eb589 | 85 | |
dokunewon | 3:5006f79eb589 | 86 | bool USBHostDac::connect() { |
dokunewon | 3:5006f79eb589 | 87 | if (dev_connected) { |
dokunewon | 3:5006f79eb589 | 88 | return true; |
dokunewon | 3:5006f79eb589 | 89 | } |
dokunewon | 3:5006f79eb589 | 90 | |
dokunewon | 3:5006f79eb589 | 91 | for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { |
dokunewon | 3:5006f79eb589 | 92 | if ((dev = host->getDevice(i)) != NULL) { |
dokunewon | 3:5006f79eb589 | 93 | |
dokunewon | 3:5006f79eb589 | 94 | if (host->enumerate(dev, this)) { |
dokunewon | 3:5006f79eb589 | 95 | break; |
dokunewon | 3:5006f79eb589 | 96 | } |
dokunewon | 3:5006f79eb589 | 97 | |
dokunewon | 3:5006f79eb589 | 98 | if (audio_device_found) { |
dokunewon | 3:5006f79eb589 | 99 | USB_INFO("New UsbDac device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, audio_intf); |
dokunewon | 3:5006f79eb589 | 100 | dev->setName("UsbDac", audio_intf); |
dokunewon | 3:5006f79eb589 | 101 | host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect); |
dokunewon | 3:5006f79eb589 | 102 | |
dokunewon | 3:5006f79eb589 | 103 | int addr = dev->getAddress(); |
dokunewon | 3:5006f79eb589 | 104 | |
dokunewon | 3:5006f79eb589 | 105 | if (iso_send.bEndpointAddress != 0) { |
dokunewon | 3:5006f79eb589 | 106 | iso_send.p_rest_data = new uint8_t[PACKET_SIZE_6CH * FRAME_COUNT]; |
dokunewon | 3:5006f79eb589 | 107 | iso_send.m_isoEp->init(addr, iso_send.bEndpointAddress, PACKET_SIZE_6CH, FRAME_COUNT, QUEUE_NUM); |
dokunewon | 3:5006f79eb589 | 108 | setInterface(iso_send.bAlternateSetting, iso_send.bInterfaceNumber); |
dokunewon | 3:5006f79eb589 | 109 | setSamplingRate(iso_send.bEndpointAddress, 48000); |
dokunewon | 3:5006f79eb589 | 110 | } |
dokunewon | 3:5006f79eb589 | 111 | |
dokunewon | 3:5006f79eb589 | 112 | if (iso_recv.bEndpointAddress != 0) { |
dokunewon | 3:5006f79eb589 | 113 | iso_recv.p_rest_data = new uint8_t[iso_recv.wMaxPacketSize * FRAME_COUNT]; |
dokunewon | 3:5006f79eb589 | 114 | iso_recv.m_isoEp->init(addr, iso_recv.bEndpointAddress, iso_recv.wMaxPacketSize, FRAME_COUNT, QUEUE_NUM); |
dokunewon | 3:5006f79eb589 | 115 | setInterface(iso_recv.bAlternateSetting, iso_recv.bInterfaceNumber); |
dokunewon | 3:5006f79eb589 | 116 | setSamplingRate(iso_recv.bEndpointAddress, 48000); |
dokunewon | 3:5006f79eb589 | 117 | } |
dokunewon | 3:5006f79eb589 | 118 | |
dokunewon | 3:5006f79eb589 | 119 | setMuteAndVolume(); |
dokunewon | 3:5006f79eb589 | 120 | |
dokunewon | 3:5006f79eb589 | 121 | dev_connected = true; |
dokunewon | 3:5006f79eb589 | 122 | return true; |
dokunewon | 3:5006f79eb589 | 123 | } |
dokunewon | 3:5006f79eb589 | 124 | } |
dokunewon | 3:5006f79eb589 | 125 | } |
dokunewon | 3:5006f79eb589 | 126 | init(); |
dokunewon | 3:5006f79eb589 | 127 | return false; |
dokunewon | 3:5006f79eb589 | 128 | } |
dokunewon | 3:5006f79eb589 | 129 | |
dokunewon | 3:5006f79eb589 | 130 | uint32_t USBHostDac::send(uint8_t* buf, uint32_t len, bool flush) { |
dokunewon | 3:5006f79eb589 | 131 | uint32_t send_index = 0; |
dokunewon | 3:5006f79eb589 | 132 | uint32_t rest_size = len; |
dokunewon | 3:5006f79eb589 | 133 | uint32_t send_size; |
dokunewon | 3:5006f79eb589 | 134 | uint32_t copy_size; |
dokunewon | 3:5006f79eb589 | 135 | int result; |
dokunewon | 3:5006f79eb589 | 136 | |
dokunewon | 3:5006f79eb589 | 137 | if (iso_send.bEndpointAddress == 0) { |
dokunewon | 3:5006f79eb589 | 138 | return 0; |
dokunewon | 3:5006f79eb589 | 139 | } |
dokunewon | 3:5006f79eb589 | 140 | |
dokunewon | 3:5006f79eb589 | 141 | if (iso_send.rest_data_index != 0) { |
dokunewon | 3:5006f79eb589 | 142 | if (rest_size > iso_send.rest_data_size) { |
dokunewon | 3:5006f79eb589 | 143 | copy_size = iso_send.rest_data_size; |
dokunewon | 3:5006f79eb589 | 144 | } else { |
dokunewon | 3:5006f79eb589 | 145 | copy_size = rest_size; |
dokunewon | 3:5006f79eb589 | 146 | } |
dokunewon | 3:5006f79eb589 | 147 | memcpy(&iso_send.p_rest_data[iso_send.rest_data_index], &buf[send_index], copy_size); |
dokunewon | 3:5006f79eb589 | 148 | send_index += copy_size; |
dokunewon | 3:5006f79eb589 | 149 | rest_size -= copy_size; |
dokunewon | 3:5006f79eb589 | 150 | iso_send.rest_data_index += copy_size; |
dokunewon | 3:5006f79eb589 | 151 | if ((flush != false) || (iso_send.rest_data_index >= (PACKET_SIZE_6CH * FRAME_COUNT))) { |
dokunewon | 3:5006f79eb589 | 152 | if (iso_send.m_isoEp->getQueueNum() == 0) { |
dokunewon | 3:5006f79eb589 | 153 | iso_send.m_isoEp->reset(4); |
dokunewon | 3:5006f79eb589 | 154 | } |
dokunewon | 3:5006f79eb589 | 155 | result = iso_send.m_isoEp->isochronousSend(&iso_send.p_rest_data[0], iso_send.rest_data_index, 100); |
dokunewon | 3:5006f79eb589 | 156 | iso_send.rest_data_index = 0; |
dokunewon | 3:5006f79eb589 | 157 | } |
dokunewon | 3:5006f79eb589 | 158 | } |
dokunewon | 3:5006f79eb589 | 159 | |
dokunewon | 3:5006f79eb589 | 160 | while ((dev_connected) && (rest_size > 0)) { |
dokunewon | 3:5006f79eb589 | 161 | if ((flush == false) && (rest_size < (PACKET_SIZE_6CH * FRAME_COUNT))) { |
dokunewon | 3:5006f79eb589 | 162 | memcpy(&iso_send.p_rest_data[0], &buf[send_index], rest_size); |
dokunewon | 3:5006f79eb589 | 163 | iso_send.rest_data_index = rest_size; |
dokunewon | 3:5006f79eb589 | 164 | iso_send.rest_data_size = (PACKET_SIZE_6CH * FRAME_COUNT) - rest_size; |
dokunewon | 3:5006f79eb589 | 165 | break; |
dokunewon | 3:5006f79eb589 | 166 | } else { |
dokunewon | 3:5006f79eb589 | 167 | if (rest_size >= (PACKET_SIZE_6CH * FRAME_COUNT)) { |
dokunewon | 3:5006f79eb589 | 168 | send_size = (PACKET_SIZE_6CH * FRAME_COUNT); |
dokunewon | 3:5006f79eb589 | 169 | } else { |
dokunewon | 3:5006f79eb589 | 170 | send_size = rest_size; |
dokunewon | 3:5006f79eb589 | 171 | } |
dokunewon | 3:5006f79eb589 | 172 | if (iso_send.m_isoEp->getQueueNum() == 0) { |
dokunewon | 3:5006f79eb589 | 173 | iso_send.m_isoEp->reset(4); |
dokunewon | 3:5006f79eb589 | 174 | } |
dokunewon | 3:5006f79eb589 | 175 | result = iso_send.m_isoEp->isochronousSend(&buf[send_index], send_size, 100); |
dokunewon | 3:5006f79eb589 | 176 | send_index += result; |
dokunewon | 3:5006f79eb589 | 177 | rest_size -= result; |
dokunewon | 3:5006f79eb589 | 178 | } |
dokunewon | 3:5006f79eb589 | 179 | } |
dokunewon | 3:5006f79eb589 | 180 | |
dokunewon | 3:5006f79eb589 | 181 | return send_index; |
dokunewon | 3:5006f79eb589 | 182 | } |
dokunewon | 3:5006f79eb589 | 183 | |
dokunewon | 3:5006f79eb589 | 184 | uint32_t USBHostDac::receive(uint8_t* buf, uint32_t len) { |
dokunewon | 3:5006f79eb589 | 185 | uint32_t recv_index = 0; |
dokunewon | 3:5006f79eb589 | 186 | uint32_t rest_size = len; |
dokunewon | 3:5006f79eb589 | 187 | uint32_t copy_size; |
dokunewon | 3:5006f79eb589 | 188 | |
dokunewon | 3:5006f79eb589 | 189 | if (iso_recv.bEndpointAddress == 0) { |
dokunewon | 3:5006f79eb589 | 190 | return 0; |
dokunewon | 3:5006f79eb589 | 191 | } |
dokunewon | 3:5006f79eb589 | 192 | |
dokunewon | 3:5006f79eb589 | 193 | if (iso_recv.rest_data_size != 0) { |
dokunewon | 3:5006f79eb589 | 194 | if (rest_size > iso_recv.rest_data_size) { |
dokunewon | 3:5006f79eb589 | 195 | copy_size = iso_recv.rest_data_size; |
dokunewon | 3:5006f79eb589 | 196 | } else { |
dokunewon | 3:5006f79eb589 | 197 | copy_size = rest_size; |
dokunewon | 3:5006f79eb589 | 198 | } |
dokunewon | 3:5006f79eb589 | 199 | memcpy(&buf[recv_index], &iso_recv.p_rest_data[iso_recv.rest_data_index], copy_size); |
dokunewon | 3:5006f79eb589 | 200 | recv_index += copy_size; |
dokunewon | 3:5006f79eb589 | 201 | rest_size -= copy_size; |
dokunewon | 3:5006f79eb589 | 202 | iso_recv.rest_data_index += copy_size; |
dokunewon | 3:5006f79eb589 | 203 | iso_recv.rest_data_size -= copy_size; |
dokunewon | 3:5006f79eb589 | 204 | } |
dokunewon | 3:5006f79eb589 | 205 | |
dokunewon | 3:5006f79eb589 | 206 | while ((dev_connected) && (rest_size > 0)) { |
dokunewon | 3:5006f79eb589 | 207 | iso_recv.rest_data_index = 0; |
dokunewon | 3:5006f79eb589 | 208 | iso_recv.rest_data_size = 0; |
dokunewon | 3:5006f79eb589 | 209 | |
dokunewon | 3:5006f79eb589 | 210 | if (iso_recv.m_isoEp->getQueueNum() == 0) { |
dokunewon | 3:5006f79eb589 | 211 | iso_recv.m_isoEp->reset(4); |
dokunewon | 3:5006f79eb589 | 212 | } |
dokunewon | 3:5006f79eb589 | 213 | HCITD* itd = iso_recv.m_isoEp->isochronousReceive(100); |
dokunewon | 3:5006f79eb589 | 214 | if (itd) { |
dokunewon | 3:5006f79eb589 | 215 | uint8_t cc = itd->ConditionCode(); |
dokunewon | 3:5006f79eb589 | 216 | if (cc == 0) { |
dokunewon | 3:5006f79eb589 | 217 | int fc = itd->FrameCount(); |
dokunewon | 3:5006f79eb589 | 218 | uint8_t* wk_buf = const_cast<uint8_t*>(itd->buf); |
dokunewon | 3:5006f79eb589 | 219 | int mps = iso_recv.m_isoEp->m_PacketSize; |
dokunewon | 3:5006f79eb589 | 220 | for (int i = 0; i < fc; i++) { |
dokunewon | 3:5006f79eb589 | 221 | uint16_t psw = itd->OffsetPSW[i]; |
dokunewon | 3:5006f79eb589 | 222 | cc = psw>>12; |
dokunewon | 3:5006f79eb589 | 223 | if (cc == 0 || cc == 9) { |
dokunewon | 3:5006f79eb589 | 224 | int wk_len = psw & 0x7ff; |
dokunewon | 3:5006f79eb589 | 225 | if (rest_size > 0) { |
dokunewon | 3:5006f79eb589 | 226 | if (rest_size > wk_len) { |
dokunewon | 3:5006f79eb589 | 227 | copy_size = wk_len; |
dokunewon | 3:5006f79eb589 | 228 | } else { |
dokunewon | 3:5006f79eb589 | 229 | copy_size = rest_size; |
dokunewon | 3:5006f79eb589 | 230 | } |
dokunewon | 3:5006f79eb589 | 231 | memcpy(&buf[recv_index], wk_buf, copy_size); |
dokunewon | 3:5006f79eb589 | 232 | recv_index += copy_size; |
dokunewon | 3:5006f79eb589 | 233 | rest_size -= copy_size; |
dokunewon | 3:5006f79eb589 | 234 | if (copy_size < wk_len) { |
dokunewon | 3:5006f79eb589 | 235 | memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[copy_size], (wk_len - copy_size)); |
dokunewon | 3:5006f79eb589 | 236 | iso_recv.rest_data_size += (wk_len - copy_size); |
dokunewon | 3:5006f79eb589 | 237 | } |
dokunewon | 3:5006f79eb589 | 238 | } else { |
dokunewon | 3:5006f79eb589 | 239 | memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[0], wk_len); |
dokunewon | 3:5006f79eb589 | 240 | iso_recv.rest_data_size += wk_len; |
dokunewon | 3:5006f79eb589 | 241 | } |
dokunewon | 3:5006f79eb589 | 242 | } |
dokunewon | 3:5006f79eb589 | 243 | wk_buf += mps; |
dokunewon | 3:5006f79eb589 | 244 | } |
dokunewon | 3:5006f79eb589 | 245 | } |
dokunewon | 3:5006f79eb589 | 246 | delete itd; |
dokunewon | 3:5006f79eb589 | 247 | } |
dokunewon | 3:5006f79eb589 | 248 | } |
dokunewon | 3:5006f79eb589 | 249 | |
dokunewon | 3:5006f79eb589 | 250 | return recv_index; |
dokunewon | 3:5006f79eb589 | 251 | } |
dokunewon | 3:5006f79eb589 | 252 | |
dokunewon | 3:5006f79eb589 | 253 | /*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid) |
dokunewon | 3:5006f79eb589 | 254 | { |
dokunewon | 3:5006f79eb589 | 255 | // we don't check VID/PID for audio driver |
dokunewon | 3:5006f79eb589 | 256 | } |
dokunewon | 3:5006f79eb589 | 257 | |
dokunewon | 3:5006f79eb589 | 258 | /*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 |
dokunewon | 3:5006f79eb589 | 259 | { |
dokunewon | 3:5006f79eb589 | 260 | bool ret; |
dokunewon | 3:5006f79eb589 | 261 | |
dokunewon | 3:5006f79eb589 | 262 | if (audio_intf_cnt >= 2) { |
dokunewon | 3:5006f79eb589 | 263 | ret = false; |
dokunewon | 3:5006f79eb589 | 264 | } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) { |
dokunewon | 3:5006f79eb589 | 265 | // AUDIOSTREAMING Subclass |
dokunewon | 3:5006f79eb589 | 266 | ret = chkAudioStreaming(); |
dokunewon | 3:5006f79eb589 | 267 | if (ret != false) { |
dokunewon | 3:5006f79eb589 | 268 | audio_intf = intf_nb; |
dokunewon | 3:5006f79eb589 | 269 | audio_device_found = true; |
dokunewon | 3:5006f79eb589 | 270 | audio_intf_cnt++; |
dokunewon | 3:5006f79eb589 | 271 | } |
dokunewon | 3:5006f79eb589 | 272 | } else { |
dokunewon | 3:5006f79eb589 | 273 | ret = false; |
dokunewon | 3:5006f79eb589 | 274 | } |
dokunewon | 3:5006f79eb589 | 275 | |
dokunewon | 3:5006f79eb589 | 276 | return false; |
dokunewon | 3:5006f79eb589 | 277 | } |
dokunewon | 3:5006f79eb589 | 278 | |
dokunewon | 3:5006f79eb589 | 279 | /*virtual*/ bool USBHostDac::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used |
dokunewon | 3:5006f79eb589 | 280 | { |
dokunewon | 3:5006f79eb589 | 281 | return false; |
dokunewon | 3:5006f79eb589 | 282 | } |
dokunewon | 3:5006f79eb589 | 283 | |
dokunewon | 3:5006f79eb589 | 284 | bool USBHostDac::chkAudioStreaming() { |
dokunewon | 3:5006f79eb589 | 285 | uint8_t * conf_descr = host->getConfDescrCurPtr(); |
dokunewon | 3:5006f79eb589 | 286 | uint16_t len = host->getConfDescrRestLen(); |
dokunewon | 3:5006f79eb589 | 287 | uint32_t index = 0; |
dokunewon | 3:5006f79eb589 | 288 | uint32_t len_desc = conf_descr[index]; |
dokunewon | 3:5006f79eb589 | 289 | uint32_t cnt; |
dokunewon | 3:5006f79eb589 | 290 | uint32_t wk_sampling; |
dokunewon | 3:5006f79eb589 | 291 | bool smpling_ok = false; |
dokunewon | 3:5006f79eb589 | 292 | bool loop_end = false; |
dokunewon | 3:5006f79eb589 | 293 | uint8_t channels = 0; |
dokunewon | 3:5006f79eb589 | 294 | uint8_t SubframeSize = 0; |
dokunewon | 3:5006f79eb589 | 295 | uint8_t id; |
dokunewon | 3:5006f79eb589 | 296 | uint16_t wk_wMaxPacketSize; |
dokunewon | 3:5006f79eb589 | 297 | uint8_t wk_bEndpointAddress; |
dokunewon | 3:5006f79eb589 | 298 | uint8_t wk_bInterfaceNumber; |
dokunewon | 3:5006f79eb589 | 299 | uint8_t wk_bAlternateSetting; |
dokunewon | 3:5006f79eb589 | 300 | |
dokunewon | 3:5006f79eb589 | 301 | DESC_REP("audio streaming interface:%d alt:%d found\n",conf_descr[index + 2],conf_descr[index + 3]); |
dokunewon | 3:5006f79eb589 | 302 | /* bNumEndpoints */ |
dokunewon | 3:5006f79eb589 | 303 | if (conf_descr[index + 4] >= 1) { |
dokunewon | 3:5006f79eb589 | 304 | wk_bInterfaceNumber = conf_descr[index + 2]; |
dokunewon | 3:5006f79eb589 | 305 | wk_bAlternateSetting = conf_descr[index + 3]; |
dokunewon | 3:5006f79eb589 | 306 | wk_wMaxPacketSize = 0; |
dokunewon | 3:5006f79eb589 | 307 | wk_bEndpointAddress = 0; |
dokunewon | 3:5006f79eb589 | 308 | |
dokunewon | 3:5006f79eb589 | 309 | index += len_desc; |
dokunewon | 3:5006f79eb589 | 310 | while ((index < len) && (loop_end == false)) { |
dokunewon | 3:5006f79eb589 | 311 | len_desc = conf_descr[index]; |
dokunewon | 3:5006f79eb589 | 312 | id = conf_descr[index+1]; |
dokunewon | 3:5006f79eb589 | 313 | switch (id) { |
dokunewon | 3:5006f79eb589 | 314 | case INTERFACE_DESCRIPTOR: |
dokunewon | 3:5006f79eb589 | 315 | DESC_REP("interface descriptor found\n"); |
dokunewon | 3:5006f79eb589 | 316 | /* next interface descriptor */ |
dokunewon | 3:5006f79eb589 | 317 | loop_end = true; |
dokunewon | 3:5006f79eb589 | 318 | break; |
dokunewon | 3:5006f79eb589 | 319 | case ENDPOINT_DESCRIPTOR: |
dokunewon | 3:5006f79eb589 | 320 | DESC_REP("endpoint descriptor found\n"); |
dokunewon | 3:5006f79eb589 | 321 | if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) { |
dokunewon | 3:5006f79eb589 | 322 | wk_bEndpointAddress = conf_descr[index + 2]; |
dokunewon | 3:5006f79eb589 | 323 | wk_wMaxPacketSize = (conf_descr[index + 5] << 8) + conf_descr[index + 4]; |
dokunewon | 3:5006f79eb589 | 324 | loop_end = true; |
dokunewon | 3:5006f79eb589 | 325 | } |
dokunewon | 3:5006f79eb589 | 326 | break; |
dokunewon | 3:5006f79eb589 | 327 | case 0x24: /* Audio Class Specific INTERFACE Descriptor */ |
dokunewon | 3:5006f79eb589 | 328 | DESC_REP("audio specific descriptor found\n"); |
dokunewon | 3:5006f79eb589 | 329 | //doku if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1)) { |
dokunewon | 3:5006f79eb589 | 330 | if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1 && (wk_bAlternateSetting != 5))) { |
dokunewon | 3:5006f79eb589 | 331 | channels = conf_descr[index + 4]; |
dokunewon | 3:5006f79eb589 | 332 | SubframeSize = conf_descr[index + 5]; |
dokunewon | 3:5006f79eb589 | 333 | for (cnt = 8; (cnt + 3) <= len_desc; cnt += 3) { |
dokunewon | 3:5006f79eb589 | 334 | wk_sampling = ((uint32_t)conf_descr[index + cnt + 0] << 0) |
dokunewon | 3:5006f79eb589 | 335 | | ((uint32_t)conf_descr[index + cnt + 1] << 8) |
dokunewon | 3:5006f79eb589 | 336 | | ((uint32_t)conf_descr[index + cnt + 2] << 16); |
dokunewon | 3:5006f79eb589 | 337 | DESC_REP("interface:%d alt:%d found channels:%d subframe size:%d sampling:%d\n",wk_bInterfaceNumber,wk_bAlternateSetting,channels,SubframeSize,wk_sampling); |
dokunewon | 3:5006f79eb589 | 338 | if (wk_sampling == 48000) { |
dokunewon | 3:5006f79eb589 | 339 | smpling_ok = true; |
dokunewon | 3:5006f79eb589 | 340 | } |
dokunewon | 3:5006f79eb589 | 341 | } |
dokunewon | 3:5006f79eb589 | 342 | } |
dokunewon | 3:5006f79eb589 | 343 | break; |
dokunewon | 3:5006f79eb589 | 344 | default: |
dokunewon | 3:5006f79eb589 | 345 | break; |
dokunewon | 3:5006f79eb589 | 346 | } |
dokunewon | 3:5006f79eb589 | 347 | index += len_desc; |
dokunewon | 3:5006f79eb589 | 348 | } |
dokunewon | 3:5006f79eb589 | 349 | |
dokunewon | 3:5006f79eb589 | 350 | DESC_REP("interface:%d alt:%d endpoint:%02x found\n",wk_bInterfaceNumber,wk_bAlternateSetting,wk_bEndpointAddress); |
dokunewon | 3:5006f79eb589 | 351 | |
dokunewon | 3:5006f79eb589 | 352 | if (((wk_bEndpointAddress & 0x80) == 0) && (wk_wMaxPacketSize >= PACKET_SIZE_6CH) |
dokunewon | 3:5006f79eb589 | 353 | && (channels == 6) && (SubframeSize == 2) && (smpling_ok != false)) { |
dokunewon | 3:5006f79eb589 | 354 | DESC_REP("****** fit for send ******\n"); |
dokunewon | 3:5006f79eb589 | 355 | iso_send.wMaxPacketSize = wk_wMaxPacketSize; |
dokunewon | 3:5006f79eb589 | 356 | iso_send.bEndpointAddress = wk_bEndpointAddress; |
dokunewon | 3:5006f79eb589 | 357 | iso_send.bInterfaceNumber = wk_bInterfaceNumber; |
dokunewon | 3:5006f79eb589 | 358 | iso_send.bAlternateSetting = wk_bAlternateSetting; |
dokunewon | 3:5006f79eb589 | 359 | return true; |
dokunewon | 3:5006f79eb589 | 360 | } |
dokunewon | 3:5006f79eb589 | 361 | |
dokunewon | 3:5006f79eb589 | 362 | DESC_REP("end point:%d packet size:%d channels:%d subflame:%d ampling ok:%d\n",wk_bEndpointAddress,wk_wMaxPacketSize,channels,SubframeSize,smpling_ok); |
dokunewon | 3:5006f79eb589 | 363 | //doku if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE/2)) |
dokunewon | 3:5006f79eb589 | 364 | if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE)) |
dokunewon | 3:5006f79eb589 | 365 | && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) { |
dokunewon | 3:5006f79eb589 | 366 | DESC_REP("****** fit for receive ******\n"); |
dokunewon | 3:5006f79eb589 | 367 | iso_recv.wMaxPacketSize = wk_wMaxPacketSize; |
dokunewon | 3:5006f79eb589 | 368 | iso_recv.bEndpointAddress = wk_bEndpointAddress; |
dokunewon | 3:5006f79eb589 | 369 | iso_recv.bInterfaceNumber = wk_bInterfaceNumber; |
dokunewon | 3:5006f79eb589 | 370 | iso_recv.bAlternateSetting = wk_bAlternateSetting; |
dokunewon | 3:5006f79eb589 | 371 | return true; |
dokunewon | 3:5006f79eb589 | 372 | } |
dokunewon | 3:5006f79eb589 | 373 | } |
dokunewon | 3:5006f79eb589 | 374 | |
dokunewon | 3:5006f79eb589 | 375 | return false; |
dokunewon | 3:5006f79eb589 | 376 | } |
dokunewon | 3:5006f79eb589 | 377 | |
dokunewon | 3:5006f79eb589 | 378 | void USBHostDac::onDisconnect() { |
dokunewon | 3:5006f79eb589 | 379 | if (dev_connected) { |
dokunewon | 3:5006f79eb589 | 380 | if (iso_send.bEndpointAddress != 0) { |
dokunewon | 3:5006f79eb589 | 381 | iso_send.m_isoEp->disconnect(); |
dokunewon | 3:5006f79eb589 | 382 | } |
dokunewon | 3:5006f79eb589 | 383 | if (iso_recv.bEndpointAddress != 0) { |
dokunewon | 3:5006f79eb589 | 384 | iso_recv.m_isoEp->disconnect(); |
dokunewon | 3:5006f79eb589 | 385 | } |
dokunewon | 3:5006f79eb589 | 386 | init(); |
dokunewon | 3:5006f79eb589 | 387 | } |
dokunewon | 3:5006f79eb589 | 388 | } |
dokunewon | 3:5006f79eb589 | 389 | |
dokunewon | 3:5006f79eb589 | 390 | USB_TYPE USBHostDac::setInterface(uint16_t alt, uint16_t index) { |
dokunewon | 3:5006f79eb589 | 391 | DESC_REP("set interface:%d alt:%d\n",index,alt); |
dokunewon | 3:5006f79eb589 | 392 | return host->controlWrite( dev, |
dokunewon | 3:5006f79eb589 | 393 | USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, |
dokunewon | 3:5006f79eb589 | 394 | SET_INTERFACE, |
dokunewon | 3:5006f79eb589 | 395 | alt, index, NULL, 0); |
dokunewon | 3:5006f79eb589 | 396 | } |
dokunewon | 3:5006f79eb589 | 397 | |
dokunewon | 3:5006f79eb589 | 398 | void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) { |
dokunewon | 3:5006f79eb589 | 399 | uint8_t data[3]; |
dokunewon | 3:5006f79eb589 | 400 | DESC_REP("set sampling rate endpoint:%02x rate:%d\n",endpoint_adder,sampling_rate); |
dokunewon | 3:5006f79eb589 | 401 | |
dokunewon | 3:5006f79eb589 | 402 | data[0] = (uint8_t)((sampling_rate >> 0) & 0xff); |
dokunewon | 3:5006f79eb589 | 403 | data[1] = (uint8_t)((sampling_rate >> 8) & 0xff); |
dokunewon | 3:5006f79eb589 | 404 | data[2] = (uint8_t)((sampling_rate >> 16) & 0xff); |
dokunewon | 3:5006f79eb589 | 405 | host->controlWrite( dev, |
dokunewon | 3:5006f79eb589 | 406 | USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, |
dokunewon | 3:5006f79eb589 | 407 | SET_CUR, |
dokunewon | 3:5006f79eb589 | 408 | SAMPLING, endpoint_adder, data, 3); |
dokunewon | 3:5006f79eb589 | 409 | } |
dokunewon | 3:5006f79eb589 | 410 | |
dokunewon | 3:5006f79eb589 | 411 | void USBHostDac::FUMute(int unit, int ch, int mute) |
dokunewon | 3:5006f79eb589 | 412 | { |
dokunewon | 3:5006f79eb589 | 413 | // DESC_REP("mute:%d\n",mute); |
dokunewon | 3:5006f79eb589 | 414 | uint8_t data[1]; |
dokunewon | 3:5006f79eb589 | 415 | |
dokunewon | 3:5006f79eb589 | 416 | unit <<= 8; |
dokunewon | 3:5006f79eb589 | 417 | data[0] = 0xff & mute; |
dokunewon | 3:5006f79eb589 | 418 | |
dokunewon | 3:5006f79eb589 | 419 | host->controlWrite( dev, |
dokunewon | 3:5006f79eb589 | 420 | USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, |
dokunewon | 3:5006f79eb589 | 421 | SET_CUR, |
dokunewon | 3:5006f79eb589 | 422 | FUCS_MUTE | ch, unit, data, 1); |
dokunewon | 3:5006f79eb589 | 423 | } |
dokunewon | 3:5006f79eb589 | 424 | |
dokunewon | 3:5006f79eb589 | 425 | void USBHostDac::FUVolume(int unit, int ch,int volume) |
dokunewon | 3:5006f79eb589 | 426 | { |
dokunewon | 3:5006f79eb589 | 427 | // DESC_REP("volume:%d\n",volume); |
dokunewon | 3:5006f79eb589 | 428 | uint8_t data[2]; |
dokunewon | 3:5006f79eb589 | 429 | |
dokunewon | 3:5006f79eb589 | 430 | unit <<= 8; |
dokunewon | 3:5006f79eb589 | 431 | data[0] = volume & 0xFF; |
dokunewon | 3:5006f79eb589 | 432 | data[1] = (volume>>8) & 0xFF; |
dokunewon | 3:5006f79eb589 | 433 | |
dokunewon | 3:5006f79eb589 | 434 | host->controlWrite( dev, |
dokunewon | 3:5006f79eb589 | 435 | USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, |
dokunewon | 3:5006f79eb589 | 436 | SET_CUR, |
dokunewon | 3:5006f79eb589 | 437 | FUCS_VOLUME | ch, unit, data, 2); |
dokunewon | 3:5006f79eb589 | 438 | } |
dokunewon | 3:5006f79eb589 | 439 | |
dokunewon | 3:5006f79eb589 | 440 | void USBHostDac::FUSelect(int unit, int sel) |
dokunewon | 3:5006f79eb589 | 441 | { |
dokunewon | 3:5006f79eb589 | 442 | // DESC_REP("volume:%d\n",volume); |
dokunewon | 3:5006f79eb589 | 443 | uint8_t data[1]; |
dokunewon | 3:5006f79eb589 | 444 | |
dokunewon | 3:5006f79eb589 | 445 | unit <<= 8; |
dokunewon | 3:5006f79eb589 | 446 | data[0] = sel & 0xFF; |
dokunewon | 3:5006f79eb589 | 447 | |
dokunewon | 3:5006f79eb589 | 448 | host->controlWrite( dev, |
dokunewon | 3:5006f79eb589 | 449 | USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, |
dokunewon | 3:5006f79eb589 | 450 | SET_CUR, |
dokunewon | 3:5006f79eb589 | 451 | 0 , unit, data, 1); |
dokunewon | 3:5006f79eb589 | 452 | } |
dokunewon | 3:5006f79eb589 | 453 | |
dokunewon | 3:5006f79eb589 | 454 | void USBHostDac::setMuteAndVolume(void) |
dokunewon | 3:5006f79eb589 | 455 | { |
dokunewon | 3:5006f79eb589 | 456 | //off playback mute |
dokunewon | 3:5006f79eb589 | 457 | // FUMute(13, 0, 0); |
dokunewon | 3:5006f79eb589 | 458 | //front volume |
dokunewon | 3:5006f79eb589 | 459 | // FUVolume(13, 1, -256 * 0); |
dokunewon | 3:5006f79eb589 | 460 | // FUVolume(13, 2, -256 * 0); |
dokunewon | 3:5006f79eb589 | 461 | |
dokunewon | 3:5006f79eb589 | 462 | //recoding volume |
dokunewon | 3:5006f79eb589 | 463 | // FUMute(15, 0, 0); |
dokunewon | 3:5006f79eb589 | 464 | // FUVolume(15, 1, -256 * 0); |
dokunewon | 3:5006f79eb589 | 465 | |
dokunewon | 3:5006f79eb589 | 466 | //recoding selector |
dokunewon | 3:5006f79eb589 | 467 | FUSelect(7, 2); |
dokunewon | 3:5006f79eb589 | 468 | } |
dokunewon | 3:5006f79eb589 | 469 |