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.
Revision 3:5006f79eb589, committed 2015-10-18
- Comitter:
- dokunewon
- Date:
- Sun Oct 18 08:16:39 2015 +0000
- Parent:
- 2:4afe26b3d48b
- Commit message:
- Change a little.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost6ChDac.cpp Sun Oct 18 08:16:39 2015 +0000
@@ -0,0 +1,469 @@
+/*******************************************************************************
+* DISCLAIMER
+* This software is supplied by Renesas Electronics Corporation and is only
+* intended for use with Renesas products. No other uses are authorized. This
+* software is owned by Renesas Electronics Corporation and is protected under
+* all applicable laws, including copyright laws.
+* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
+* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
+* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
+* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
+* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
+* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
+* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
+* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+* Renesas reserves the right, without notice, to make changes to this software
+* and to discontinue the availability of this software. By using this software,
+* you agree to the additional terms and conditions found by accessing the
+* following link:
+* http://www.renesas.com/disclaimer
+* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
+*******************************************************************************/
+
+#include "USBHost6ChDac.h"
+
+#define FUCS_CH0 (0x00)
+#define FUCS_CH1 (0x01)
+#define FUCS_CH2 (0x02)
+#define FUCS_CH3 (0x03)
+#define FUCS_MUTE (0x0100)
+#define FUCS_VOLUME (0x0200)
+
+#define SAMPLING (0x0100)
+#define SET_CUR (0x01)
+#define FRAME_COUNT (8)
+#define PACKET_SIZE (192)
+#define PACKET_SIZE_6CH (192 * 3)
+//doku #define QUEUE_NUM (3)
+#define QUEUE_NUM (11)
+
+//#define DESC_REP printf
+#define DESC_REP(...) while(0);
+
+USBHostDac::USBHostDac() {
+ host = USBHost::getHostInst();
+ iso_send.m_isoEp = new IsochronousEp;
+ iso_send.p_rest_data = NULL;
+
+ iso_recv.m_isoEp = new IsochronousEp;
+ iso_recv.p_rest_data = NULL;
+
+ init();
+}
+
+USBHostDac::~USBHostDac() {
+ delete iso_send.m_isoEp;
+ delete iso_recv.m_isoEp;
+}
+
+void USBHostDac::init() {
+ dev = NULL;
+ dev_connected = false;
+ audio_device_found = false;
+ audio_intf = -1;
+ audio_intf_cnt = 0;
+ iso_send.bEndpointAddress = 0;
+ iso_send.rest_data_index = 0;
+ iso_send.rest_data_size = 0;
+ if (iso_send.p_rest_data != NULL) {
+ delete iso_send.p_rest_data;
+ iso_send.p_rest_data = NULL;
+ }
+ iso_recv.bEndpointAddress = 0;
+ iso_recv.rest_data_index = 0;
+ iso_recv.rest_data_size = 0;
+ if (iso_recv.p_rest_data != NULL) {
+ delete iso_recv.p_rest_data;
+ iso_recv.p_rest_data = NULL;
+ }
+}
+
+bool USBHostDac::connected() {
+ return dev_connected;
+}
+
+bool USBHostDac::connect() {
+ if (dev_connected) {
+ return true;
+ }
+
+ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+ if ((dev = host->getDevice(i)) != NULL) {
+
+ if (host->enumerate(dev, this)) {
+ break;
+ }
+
+ if (audio_device_found) {
+ USB_INFO("New UsbDac device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, audio_intf);
+ dev->setName("UsbDac", audio_intf);
+ host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect);
+
+ int addr = dev->getAddress();
+
+ if (iso_send.bEndpointAddress != 0) {
+ iso_send.p_rest_data = new uint8_t[PACKET_SIZE_6CH * FRAME_COUNT];
+ iso_send.m_isoEp->init(addr, iso_send.bEndpointAddress, PACKET_SIZE_6CH, FRAME_COUNT, QUEUE_NUM);
+ setInterface(iso_send.bAlternateSetting, iso_send.bInterfaceNumber);
+ setSamplingRate(iso_send.bEndpointAddress, 48000);
+ }
+
+ if (iso_recv.bEndpointAddress != 0) {
+ iso_recv.p_rest_data = new uint8_t[iso_recv.wMaxPacketSize * FRAME_COUNT];
+ iso_recv.m_isoEp->init(addr, iso_recv.bEndpointAddress, iso_recv.wMaxPacketSize, FRAME_COUNT, QUEUE_NUM);
+ setInterface(iso_recv.bAlternateSetting, iso_recv.bInterfaceNumber);
+ setSamplingRate(iso_recv.bEndpointAddress, 48000);
+ }
+
+ setMuteAndVolume();
+
+ dev_connected = true;
+ return true;
+ }
+ }
+ }
+ init();
+ return false;
+}
+
+uint32_t USBHostDac::send(uint8_t* buf, uint32_t len, bool flush) {
+ uint32_t send_index = 0;
+ uint32_t rest_size = len;
+ uint32_t send_size;
+ uint32_t copy_size;
+ int result;
+
+ if (iso_send.bEndpointAddress == 0) {
+ return 0;
+ }
+
+ if (iso_send.rest_data_index != 0) {
+ if (rest_size > iso_send.rest_data_size) {
+ copy_size = iso_send.rest_data_size;
+ } else {
+ copy_size = rest_size;
+ }
+ memcpy(&iso_send.p_rest_data[iso_send.rest_data_index], &buf[send_index], copy_size);
+ send_index += copy_size;
+ rest_size -= copy_size;
+ iso_send.rest_data_index += copy_size;
+ if ((flush != false) || (iso_send.rest_data_index >= (PACKET_SIZE_6CH * FRAME_COUNT))) {
+ if (iso_send.m_isoEp->getQueueNum() == 0) {
+ iso_send.m_isoEp->reset(4);
+ }
+ result = iso_send.m_isoEp->isochronousSend(&iso_send.p_rest_data[0], iso_send.rest_data_index, 100);
+ iso_send.rest_data_index = 0;
+ }
+ }
+
+ while ((dev_connected) && (rest_size > 0)) {
+ if ((flush == false) && (rest_size < (PACKET_SIZE_6CH * FRAME_COUNT))) {
+ memcpy(&iso_send.p_rest_data[0], &buf[send_index], rest_size);
+ iso_send.rest_data_index = rest_size;
+ iso_send.rest_data_size = (PACKET_SIZE_6CH * FRAME_COUNT) - rest_size;
+ break;
+ } else {
+ if (rest_size >= (PACKET_SIZE_6CH * FRAME_COUNT)) {
+ send_size = (PACKET_SIZE_6CH * FRAME_COUNT);
+ } else {
+ send_size = rest_size;
+ }
+ if (iso_send.m_isoEp->getQueueNum() == 0) {
+ iso_send.m_isoEp->reset(4);
+ }
+ result = iso_send.m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
+ send_index += result;
+ rest_size -= result;
+ }
+ }
+
+ return send_index;
+}
+
+uint32_t USBHostDac::receive(uint8_t* buf, uint32_t len) {
+ uint32_t recv_index = 0;
+ uint32_t rest_size = len;
+ uint32_t copy_size;
+
+ if (iso_recv.bEndpointAddress == 0) {
+ return 0;
+ }
+
+ if (iso_recv.rest_data_size != 0) {
+ if (rest_size > iso_recv.rest_data_size) {
+ copy_size = iso_recv.rest_data_size;
+ } else {
+ copy_size = rest_size;
+ }
+ memcpy(&buf[recv_index], &iso_recv.p_rest_data[iso_recv.rest_data_index], copy_size);
+ recv_index += copy_size;
+ rest_size -= copy_size;
+ iso_recv.rest_data_index += copy_size;
+ iso_recv.rest_data_size -= copy_size;
+ }
+
+ while ((dev_connected) && (rest_size > 0)) {
+ iso_recv.rest_data_index = 0;
+ iso_recv.rest_data_size = 0;
+
+ if (iso_recv.m_isoEp->getQueueNum() == 0) {
+ iso_recv.m_isoEp->reset(4);
+ }
+ HCITD* itd = iso_recv.m_isoEp->isochronousReceive(100);
+ if (itd) {
+ uint8_t cc = itd->ConditionCode();
+ if (cc == 0) {
+ int fc = itd->FrameCount();
+ uint8_t* wk_buf = const_cast<uint8_t*>(itd->buf);
+ int mps = iso_recv.m_isoEp->m_PacketSize;
+ for (int i = 0; i < fc; i++) {
+ uint16_t psw = itd->OffsetPSW[i];
+ cc = psw>>12;
+ if (cc == 0 || cc == 9) {
+ int wk_len = psw & 0x7ff;
+ if (rest_size > 0) {
+ if (rest_size > wk_len) {
+ copy_size = wk_len;
+ } else {
+ copy_size = rest_size;
+ }
+ memcpy(&buf[recv_index], wk_buf, copy_size);
+ recv_index += copy_size;
+ rest_size -= copy_size;
+ if (copy_size < wk_len) {
+ memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[copy_size], (wk_len - copy_size));
+ iso_recv.rest_data_size += (wk_len - copy_size);
+ }
+ } else {
+ memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[0], wk_len);
+ iso_recv.rest_data_size += wk_len;
+ }
+ }
+ wk_buf += mps;
+ }
+ }
+ delete itd;
+ }
+ }
+
+ return recv_index;
+}
+
+/*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid)
+{
+ // we don't check VID/PID for audio driver
+}
+
+/*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
+{
+ bool ret;
+
+ if (audio_intf_cnt >= 2) {
+ ret = false;
+ } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) {
+ // AUDIOSTREAMING Subclass
+ ret = chkAudioStreaming();
+ if (ret != false) {
+ audio_intf = intf_nb;
+ audio_device_found = true;
+ audio_intf_cnt++;
+ }
+ } else {
+ ret = false;
+ }
+
+ return false;
+}
+
+/*virtual*/ bool USBHostDac::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ return false;
+}
+
+bool USBHostDac::chkAudioStreaming() {
+ uint8_t * conf_descr = host->getConfDescrCurPtr();
+ uint16_t len = host->getConfDescrRestLen();
+ uint32_t index = 0;
+ uint32_t len_desc = conf_descr[index];
+ uint32_t cnt;
+ uint32_t wk_sampling;
+ bool smpling_ok = false;
+ bool loop_end = false;
+ uint8_t channels = 0;
+ uint8_t SubframeSize = 0;
+ uint8_t id;
+ uint16_t wk_wMaxPacketSize;
+ uint8_t wk_bEndpointAddress;
+ uint8_t wk_bInterfaceNumber;
+ uint8_t wk_bAlternateSetting;
+
+ DESC_REP("audio streaming interface:%d alt:%d found\n",conf_descr[index + 2],conf_descr[index + 3]);
+ /* bNumEndpoints */
+ if (conf_descr[index + 4] >= 1) {
+ wk_bInterfaceNumber = conf_descr[index + 2];
+ wk_bAlternateSetting = conf_descr[index + 3];
+ wk_wMaxPacketSize = 0;
+ wk_bEndpointAddress = 0;
+
+ index += len_desc;
+ while ((index < len) && (loop_end == false)) {
+ len_desc = conf_descr[index];
+ id = conf_descr[index+1];
+ switch (id) {
+ case INTERFACE_DESCRIPTOR:
+ DESC_REP("interface descriptor found\n");
+ /* next interface descriptor */
+ loop_end = true;
+ break;
+ case ENDPOINT_DESCRIPTOR:
+ DESC_REP("endpoint descriptor found\n");
+ if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) {
+ wk_bEndpointAddress = conf_descr[index + 2];
+ wk_wMaxPacketSize = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
+ loop_end = true;
+ }
+ break;
+ case 0x24: /* Audio Class Specific INTERFACE Descriptor */
+ DESC_REP("audio specific descriptor found\n");
+//doku if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1)) {
+ if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1 && (wk_bAlternateSetting != 5))) {
+ channels = conf_descr[index + 4];
+ SubframeSize = conf_descr[index + 5];
+ for (cnt = 8; (cnt + 3) <= len_desc; cnt += 3) {
+ wk_sampling = ((uint32_t)conf_descr[index + cnt + 0] << 0)
+ | ((uint32_t)conf_descr[index + cnt + 1] << 8)
+ | ((uint32_t)conf_descr[index + cnt + 2] << 16);
+ DESC_REP("interface:%d alt:%d found channels:%d subframe size:%d sampling:%d\n",wk_bInterfaceNumber,wk_bAlternateSetting,channels,SubframeSize,wk_sampling);
+ if (wk_sampling == 48000) {
+ smpling_ok = true;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ index += len_desc;
+ }
+
+ DESC_REP("interface:%d alt:%d endpoint:%02x found\n",wk_bInterfaceNumber,wk_bAlternateSetting,wk_bEndpointAddress);
+
+ if (((wk_bEndpointAddress & 0x80) == 0) && (wk_wMaxPacketSize >= PACKET_SIZE_6CH)
+ && (channels == 6) && (SubframeSize == 2) && (smpling_ok != false)) {
+ DESC_REP("****** fit for send ******\n");
+ iso_send.wMaxPacketSize = wk_wMaxPacketSize;
+ iso_send.bEndpointAddress = wk_bEndpointAddress;
+ iso_send.bInterfaceNumber = wk_bInterfaceNumber;
+ iso_send.bAlternateSetting = wk_bAlternateSetting;
+ return true;
+ }
+
+ DESC_REP("end point:%d packet size:%d channels:%d subflame:%d ampling ok:%d\n",wk_bEndpointAddress,wk_wMaxPacketSize,channels,SubframeSize,smpling_ok);
+//doku if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE/2))
+ if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE))
+ && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) {
+ DESC_REP("****** fit for receive ******\n");
+ iso_recv.wMaxPacketSize = wk_wMaxPacketSize;
+ iso_recv.bEndpointAddress = wk_bEndpointAddress;
+ iso_recv.bInterfaceNumber = wk_bInterfaceNumber;
+ iso_recv.bAlternateSetting = wk_bAlternateSetting;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void USBHostDac::onDisconnect() {
+ if (dev_connected) {
+ if (iso_send.bEndpointAddress != 0) {
+ iso_send.m_isoEp->disconnect();
+ }
+ if (iso_recv.bEndpointAddress != 0) {
+ iso_recv.m_isoEp->disconnect();
+ }
+ init();
+ }
+}
+
+USB_TYPE USBHostDac::setInterface(uint16_t alt, uint16_t index) {
+ DESC_REP("set interface:%d alt:%d\n",index,alt);
+ return host->controlWrite( dev,
+ USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
+ SET_INTERFACE,
+ alt, index, NULL, 0);
+}
+
+void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) {
+ uint8_t data[3];
+ DESC_REP("set sampling rate endpoint:%02x rate:%d\n",endpoint_adder,sampling_rate);
+
+ data[0] = (uint8_t)((sampling_rate >> 0) & 0xff);
+ data[1] = (uint8_t)((sampling_rate >> 8) & 0xff);
+ data[2] = (uint8_t)((sampling_rate >> 16) & 0xff);
+ host->controlWrite( dev,
+ USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
+ SET_CUR,
+ SAMPLING, endpoint_adder, data, 3);
+}
+
+void USBHostDac::FUMute(int unit, int ch, int mute)
+{
+// DESC_REP("mute:%d\n",mute);
+ uint8_t data[1];
+
+ unit <<= 8;
+ data[0] = 0xff & mute;
+
+ host->controlWrite( dev,
+ USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
+ SET_CUR,
+ FUCS_MUTE | ch, unit, data, 1);
+}
+
+void USBHostDac::FUVolume(int unit, int ch,int volume)
+{
+// DESC_REP("volume:%d\n",volume);
+ uint8_t data[2];
+
+ unit <<= 8;
+ data[0] = volume & 0xFF;
+ data[1] = (volume>>8) & 0xFF;
+
+ host->controlWrite( dev,
+ USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
+ SET_CUR,
+ FUCS_VOLUME | ch, unit, data, 2);
+}
+
+void USBHostDac::FUSelect(int unit, int sel)
+{
+// DESC_REP("volume:%d\n",volume);
+ uint8_t data[1];
+
+ unit <<= 8;
+ data[0] = sel & 0xFF;
+
+ host->controlWrite( dev,
+ USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
+ SET_CUR,
+ 0 , unit, data, 1);
+}
+
+void USBHostDac::setMuteAndVolume(void)
+{
+ //off playback mute
+// FUMute(13, 0, 0);
+ //front volume
+// FUVolume(13, 1, -256 * 0);
+// FUVolume(13, 2, -256 * 0);
+
+ //recoding volume
+// FUMute(15, 0, 0);
+// FUVolume(15, 1, -256 * 0);
+
+ //recoding selector
+ FUSelect(7, 2);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost6ChDac.h Sun Oct 18 08:16:39 2015 +0000
@@ -0,0 +1,128 @@
+/*******************************************************************************
+* DISCLAIMER
+* This software is supplied by Renesas Electronics Corporation and is only
+* intended for use with Renesas products. No other uses are authorized. This
+* software is owned by Renesas Electronics Corporation and is protected under
+* all applicable laws, including copyright laws.
+* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
+* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
+* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
+* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
+* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
+* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
+* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
+* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+* Renesas reserves the right, without notice, to make changes to this software
+* and to discontinue the availability of this software. By using this software,
+* you agree to the additional terms and conditions found by accessing the
+* following link:
+* http://www.renesas.com/disclaimer
+* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
+*******************************************************************************/
+
+#ifndef USBHOSTAUDIO_H
+#define USBHOSTAUDIO_H
+
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "USBIsochronous.h"
+
+#define USBDAC_DATA_SIZE (192 * 8)
+#define USBDAC_DATA_SIZE_6CH (192 * 8 * 3) //doku
+
+#define USBDAC_
+
+/**
+ * A class to communicate a USB dac (send:only 48kHz,16bit,2ch , receive:only 48kHz,16bit,1ch)
+ */
+class USBHostDac : public IUSBEnumerator {
+public:
+
+ /**
+ * Constructor
+ */
+ USBHostDac();
+
+ /** Destructor
+ *
+ */
+ virtual ~USBHostDac();
+
+ /**
+ * Try to connect a audio device
+ *
+ * @return true if connection was successful
+ */
+ bool connect();
+
+ /**
+ * Check if a audio is connected
+ *
+ * @returns true if a audio is connected
+ */
+ bool connected();
+
+ /**
+ * Data send : only 48kHz,16bit,2ch. It's sent by the 1536byte unit.
+ *
+ * @param buf pointer on a buffer which will be written
+ * @param len length of the transfer
+ * @param flush if true, less than 1536 bytes of data is sent
+ *
+ * @returns the number of bytes written is returned
+ */
+ uint32_t send(uint8_t* buf, uint32_t len, bool flush = true);
+
+
+ /**
+ * Data receive : only 48kHz,16bit,1ch
+ *
+ * @param buf pointer on a buffer which will be read
+ * @param len length of the transfer
+ *
+ * @returns the number of bytes read is returned
+ */
+ uint32_t receive(uint8_t* buf, uint32_t len);
+
+ void FUMute(int unit, int ch, int mute); //doku
+ void FUVolume(int unit, int ch, int mute); //doku
+ void USBHostDac::FUSelect(int unit, int sel); //doku
+ void USBHostDac::setMuteAndVolume(void); //doku
+
+protected:
+ //From IUSBEnumerator
+ virtual void setVidPid(uint16_t vid, uint16_t pid);
+ virtual bool 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
+ virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+private:
+ typedef struct {
+ IsochronousEp* m_isoEp;
+ uint16_t wMaxPacketSize;
+ uint8_t bEndpointAddress;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t* p_rest_data;
+ uint32_t rest_data_index;
+ uint32_t rest_data_size;
+ } iso_if_t;
+
+ USBHost * host;
+ USBDeviceConnected * dev;
+
+ bool dev_connected;
+ bool audio_device_found;
+ int audio_intf;
+ int audio_intf_cnt;
+
+ iso_if_t iso_send;
+ iso_if_t iso_recv;
+
+ void init();
+ void onDisconnect();
+ bool chkAudioStreaming();
+ USB_TYPE setInterface(uint16_t alt, uint16_t index);
+ void setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate);
+};
+#endif
--- a/USBHostDac.cpp Wed Sep 30 06:08:15 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-/*******************************************************************************
-* DISCLAIMER
-* This software is supplied by Renesas Electronics Corporation and is only
-* intended for use with Renesas products. No other uses are authorized. This
-* software is owned by Renesas Electronics Corporation and is protected under
-* all applicable laws, including copyright laws.
-* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
-* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
-* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
-* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
-* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
-* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
-* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
-* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
-* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-* Renesas reserves the right, without notice, to make changes to this software
-* and to discontinue the availability of this software. By using this software,
-* you agree to the additional terms and conditions found by accessing the
-* following link:
-* http://www.renesas.com/disclaimer
-* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
-*******************************************************************************/
-
-#include "USBHostDac.h"
-
-#define SAMPLING (0x0100)
-#define SET_CUR (0x01)
-#define FRAME_COUNT (8)
-#define PACKET_SIZE (192)
-#define QUEUE_NUM (3)
-
-USBHostDac::USBHostDac() {
- host = USBHost::getHostInst();
- iso_send.m_isoEp = new IsochronousEp;
- iso_send.p_rest_data = NULL;
-
- iso_recv.m_isoEp = new IsochronousEp;
- iso_recv.p_rest_data = NULL;
-
- init();
-}
-
-USBHostDac::~USBHostDac() {
- delete iso_send.m_isoEp;
- delete iso_recv.m_isoEp;
-}
-
-void USBHostDac::init() {
- dev = NULL;
- dev_connected = false;
- audio_device_found = false;
- audio_intf = -1;
- audio_intf_cnt = 0;
- iso_send.bEndpointAddress = 0;
- iso_send.rest_data_index = 0;
- iso_send.rest_data_size = 0;
- if (iso_send.p_rest_data != NULL) {
- delete iso_send.p_rest_data;
- iso_send.p_rest_data = NULL;
- }
- iso_recv.bEndpointAddress = 0;
- iso_recv.rest_data_index = 0;
- iso_recv.rest_data_size = 0;
- if (iso_recv.p_rest_data != NULL) {
- delete iso_recv.p_rest_data;
- iso_recv.p_rest_data = NULL;
- }
-}
-
-bool USBHostDac::connected() {
- return dev_connected;
-}
-
-bool USBHostDac::connect() {
- if (dev_connected) {
- return true;
- }
-
- for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
- if ((dev = host->getDevice(i)) != NULL) {
-
- if (host->enumerate(dev, this)) {
- break;
- }
-
- if (audio_device_found) {
- USB_INFO("New UsbDac device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, audio_intf);
- dev->setName("UsbDac", audio_intf);
- host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect);
-
- int addr = dev->getAddress();
-
- if (iso_send.bEndpointAddress != 0) {
- iso_send.p_rest_data = new uint8_t[PACKET_SIZE * FRAME_COUNT];
- iso_send.m_isoEp->init(addr, iso_send.bEndpointAddress, PACKET_SIZE, FRAME_COUNT, QUEUE_NUM);
- setInterface(iso_send.bAlternateSetting, iso_send.bInterfaceNumber);
- setSamplingRate(iso_send.bEndpointAddress, 48000);
- }
-
- if (iso_recv.bEndpointAddress != 0) {
- iso_recv.p_rest_data = new uint8_t[iso_recv.wMaxPacketSize * FRAME_COUNT];
- iso_recv.m_isoEp->init(addr, iso_recv.bEndpointAddress, iso_recv.wMaxPacketSize, FRAME_COUNT, QUEUE_NUM);
- setInterface(iso_recv.bAlternateSetting, iso_recv.bInterfaceNumber);
- setSamplingRate(iso_recv.bEndpointAddress, 48000);
- }
-
- dev_connected = true;
- return true;
- }
- }
- }
- init();
- return false;
-}
-
-uint32_t USBHostDac::send(uint8_t* buf, uint32_t len, bool flush) {
- uint32_t send_index = 0;
- uint32_t rest_size = len;
- uint32_t send_size;
- uint32_t copy_size;
- int result;
-
- if (iso_send.bEndpointAddress == 0) {
- return 0;
- }
-
- if (iso_send.rest_data_index != 0) {
- if (rest_size > iso_send.rest_data_size) {
- copy_size = iso_send.rest_data_size;
- } else {
- copy_size = rest_size;
- }
- memcpy(&iso_send.p_rest_data[iso_send.rest_data_index], &buf[send_index], copy_size);
- send_index += copy_size;
- rest_size -= copy_size;
- iso_send.rest_data_index += copy_size;
- if ((flush != false) || (iso_send.rest_data_index >= (PACKET_SIZE * FRAME_COUNT))) {
- if (iso_send.m_isoEp->getQueueNum() == 0) {
- iso_send.m_isoEp->reset(4);
- }
- result = iso_send.m_isoEp->isochronousSend(&iso_send.p_rest_data[0], iso_send.rest_data_index, 100);
- iso_send.rest_data_index = 0;
- }
- }
-
- while ((dev_connected) && (rest_size > 0)) {
- if ((flush == false) && (rest_size < (PACKET_SIZE * FRAME_COUNT))) {
- memcpy(&iso_send.p_rest_data[0], &buf[send_index], rest_size);
- iso_send.rest_data_index = rest_size;
- iso_send.rest_data_size = (PACKET_SIZE * FRAME_COUNT) - rest_size;
- break;
- } else {
- if (rest_size >= (PACKET_SIZE * FRAME_COUNT)) {
- send_size = (PACKET_SIZE * FRAME_COUNT);
- } else {
- send_size = rest_size;
- }
- if (iso_send.m_isoEp->getQueueNum() == 0) {
- iso_send.m_isoEp->reset(4);
- }
- result = iso_send.m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
- send_index += result;
- rest_size -= result;
- }
- }
-
- return send_index;
-}
-
-uint32_t USBHostDac::receive(uint8_t* buf, uint32_t len) {
- uint32_t recv_index = 0;
- uint32_t rest_size = len;
- uint32_t copy_size;
-
- if (iso_recv.bEndpointAddress == 0) {
- return 0;
- }
-
- if (iso_recv.rest_data_size != 0) {
- if (rest_size > iso_recv.rest_data_size) {
- copy_size = iso_recv.rest_data_size;
- } else {
- copy_size = rest_size;
- }
- memcpy(&buf[recv_index], &iso_recv.p_rest_data[iso_recv.rest_data_index], copy_size);
- recv_index += copy_size;
- rest_size -= copy_size;
- iso_recv.rest_data_index += copy_size;
- iso_recv.rest_data_size -= copy_size;
- }
-
- while ((dev_connected) && (rest_size > 0)) {
- iso_recv.rest_data_index = 0;
- iso_recv.rest_data_size = 0;
-
- if (iso_recv.m_isoEp->getQueueNum() == 0) {
- iso_recv.m_isoEp->reset(4);
- }
- HCITD* itd = iso_recv.m_isoEp->isochronousReceive(100);
- if (itd) {
- uint8_t cc = itd->ConditionCode();
- if (cc == 0) {
- int fc = itd->FrameCount();
- uint8_t* wk_buf = const_cast<uint8_t*>(itd->buf);
- int mps = iso_recv.m_isoEp->m_PacketSize;
- for (int i = 0; i < fc; i++) {
- uint16_t psw = itd->OffsetPSW[i];
- cc = psw>>12;
- if (cc == 0 || cc == 9) {
- int wk_len = psw & 0x7ff;
- if (rest_size > 0) {
- if (rest_size > wk_len) {
- copy_size = wk_len;
- } else {
- copy_size = rest_size;
- }
- memcpy(&buf[recv_index], wk_buf, copy_size);
- recv_index += copy_size;
- rest_size -= copy_size;
- if (copy_size < wk_len) {
- memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[copy_size], (wk_len - copy_size));
- iso_recv.rest_data_size += (wk_len - copy_size);
- }
- } else {
- memcpy(&iso_recv.p_rest_data[iso_recv.rest_data_size], &wk_buf[0], wk_len);
- iso_recv.rest_data_size += wk_len;
- }
- }
- wk_buf += mps;
- }
- }
- delete itd;
- }
- }
-
- return recv_index;
-}
-
-/*virtual*/ void USBHostDac::setVidPid(uint16_t vid, uint16_t pid)
-{
- // we don't check VID/PID for audio driver
-}
-
-/*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
-{
- bool ret;
-
- if (audio_intf_cnt >= 2) {
- ret = false;
- } else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) {
- // AUDIOSTREAMING Subclass
- ret = chkAudioStreaming();
- if (ret != false) {
- audio_intf = intf_nb;
- audio_device_found = true;
- audio_intf_cnt++;
- }
- } else {
- ret = false;
- }
-
- return false;
-}
-
-/*virtual*/ bool USBHostDac::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
-{
- return false;
-}
-
-bool USBHostDac::chkAudioStreaming() {
- uint8_t * conf_descr = host->getConfDescrCurPtr();
- uint16_t len = host->getConfDescrRestLen();
- uint32_t index = 0;
- uint32_t len_desc = conf_descr[index];
- uint32_t cnt;
- uint32_t wk_sampling;
- bool smpling_ok = false;
- bool loop_end = false;
- uint8_t channels = 0;
- uint8_t SubframeSize = 0;
- uint8_t id;
- uint16_t wk_wMaxPacketSize;
- uint8_t wk_bEndpointAddress;
- uint8_t wk_bInterfaceNumber;
- uint8_t wk_bAlternateSetting;
-
- /* bNumEndpoints */
- if (conf_descr[index + 4] >= 1) {
- wk_bInterfaceNumber = conf_descr[index + 2];
- wk_bAlternateSetting = conf_descr[index + 3];
- wk_wMaxPacketSize = 0;
- wk_bEndpointAddress = 0;
-
- index += len_desc;
- while ((index < len) && (loop_end == false)) {
- len_desc = conf_descr[index];
- id = conf_descr[index+1];
- switch (id) {
- case INTERFACE_DESCRIPTOR:
- /* next interface descriptor */
- loop_end = true;
- break;
- case ENDPOINT_DESCRIPTOR:
- if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) {
- wk_bEndpointAddress = conf_descr[index + 2];
- wk_wMaxPacketSize = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
- loop_end = true;
- }
- break;
- case 0x24: /* Audio Class Specific INTERFACE Descriptor */
- if ((conf_descr[index + 2] == 2) && (conf_descr[index + 3] == 1)) {
- channels = conf_descr[index + 4];
- SubframeSize = conf_descr[index + 5];
- for (cnt = 8; (cnt + 3) <= len_desc; cnt += 3) {
- wk_sampling = ((uint32_t)conf_descr[index + cnt + 0] << 0)
- | ((uint32_t)conf_descr[index + cnt + 1] << 8)
- | ((uint32_t)conf_descr[index + cnt + 2] << 16);
- if (wk_sampling == 48000) {
- smpling_ok = true;
- }
- }
- }
- break;
- default:
- break;
- }
- index += len_desc;
- }
-
- if (((wk_bEndpointAddress & 0x80) == 0) && (wk_wMaxPacketSize >= PACKET_SIZE)
- && (channels == 2) && (SubframeSize == 2) && (smpling_ok != false)) {
- iso_send.wMaxPacketSize = wk_wMaxPacketSize;
- iso_send.bEndpointAddress = wk_bEndpointAddress;
- iso_send.bInterfaceNumber = wk_bInterfaceNumber;
- iso_send.bAlternateSetting = wk_bAlternateSetting;
- return true;
- }
-
- if (((wk_bEndpointAddress & 0x80) != 0) && (wk_wMaxPacketSize >= (PACKET_SIZE/2))
- && (channels == 1) && (SubframeSize == 2) && (smpling_ok != false)) {
- iso_recv.wMaxPacketSize = wk_wMaxPacketSize;
- iso_recv.bEndpointAddress = wk_bEndpointAddress;
- iso_recv.bInterfaceNumber = wk_bInterfaceNumber;
- iso_recv.bAlternateSetting = wk_bAlternateSetting;
- return true;
- }
- }
-
- return false;
-}
-
-void USBHostDac::onDisconnect() {
- if (dev_connected) {
- if (iso_send.bEndpointAddress != 0) {
- iso_send.m_isoEp->disconnect();
- }
- if (iso_recv.bEndpointAddress != 0) {
- iso_recv.m_isoEp->disconnect();
- }
- init();
- }
-}
-
-USB_TYPE USBHostDac::setInterface(uint16_t alt, uint16_t index) {
- return host->controlWrite( dev,
- USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
- SET_INTERFACE,
- alt, index, NULL, 0);
-}
-
-void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) {
- uint8_t data[3];
-
- data[0] = (uint8_t)((sampling_rate >> 0) & 0xff);
- data[1] = (uint8_t)((sampling_rate >> 8) & 0xff);
- data[2] = (uint8_t)((sampling_rate >> 16) & 0xff);
- host->controlWrite( dev,
- USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
- SET_CUR,
- SAMPLING, endpoint_adder, data, 3);
-}
-
--- a/USBHostDac.h Wed Sep 30 06:08:15 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*******************************************************************************
-* DISCLAIMER
-* This software is supplied by Renesas Electronics Corporation and is only
-* intended for use with Renesas products. No other uses are authorized. This
-* software is owned by Renesas Electronics Corporation and is protected under
-* all applicable laws, including copyright laws.
-* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
-* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
-* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
-* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
-* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
-* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
-* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
-* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
-* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-* Renesas reserves the right, without notice, to make changes to this software
-* and to discontinue the availability of this software. By using this software,
-* you agree to the additional terms and conditions found by accessing the
-* following link:
-* http://www.renesas.com/disclaimer
-* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
-*******************************************************************************/
-
-#ifndef USBHOSTAUDIO_H
-#define USBHOSTAUDIO_H
-
-#include "USBHostConf.h"
-#include "USBHost.h"
-#include "USBIsochronous.h"
-
-#define USBDAC_DATA_SIZE (192 * 8)
-
-#define USBDAC_
-
-/**
- * A class to communicate a USB dac (send:only 48kHz,16bit,2ch , receive:only 48kHz,16bit,1ch)
- */
-class USBHostDac : public IUSBEnumerator {
-public:
-
- /**
- * Constructor
- */
- USBHostDac();
-
- /** Destructor
- *
- */
- virtual ~USBHostDac();
-
- /**
- * Try to connect a audio device
- *
- * @return true if connection was successful
- */
- bool connect();
-
- /**
- * Check if a audio is connected
- *
- * @returns true if a audio is connected
- */
- bool connected();
-
- /**
- * Data send : only 48kHz,16bit,2ch. It's sent by the 1536byte unit.
- *
- * @param buf pointer on a buffer which will be written
- * @param len length of the transfer
- * @param flush if true, less than 1536 bytes of data is sent
- *
- * @returns the number of bytes written is returned
- */
- uint32_t send(uint8_t* buf, uint32_t len, bool flush = true);
-
- /**
- * Data receive : only 48kHz,16bit,1ch
- *
- * @param buf pointer on a buffer which will be read
- * @param len length of the transfer
- *
- * @returns the number of bytes read is returned
- */
- uint32_t receive(uint8_t* buf, uint32_t len);
-
-protected:
- //From IUSBEnumerator
- virtual void setVidPid(uint16_t vid, uint16_t pid);
- virtual bool 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
- virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
-
-private:
- typedef struct {
- IsochronousEp* m_isoEp;
- uint16_t wMaxPacketSize;
- uint8_t bEndpointAddress;
- uint8_t bInterfaceNumber;
- uint8_t bAlternateSetting;
- uint8_t* p_rest_data;
- uint32_t rest_data_index;
- uint32_t rest_data_size;
- } iso_if_t;
-
- USBHost * host;
- USBDeviceConnected * dev;
-
- bool dev_connected;
- bool audio_device_found;
- int audio_intf;
- int audio_intf_cnt;
-
- iso_if_t iso_send;
- iso_if_t iso_recv;
-
- void init();
- void onDisconnect();
- bool chkAudioStreaming();
- USB_TYPE setInterface(uint16_t alt, uint16_t index);
- void setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate);
-};
-#endif