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
Diff: USBHostDac.cpp
- Revision:
- 1:9ff4cba6524d
- Parent:
- 0:3a3146f89bcc
--- a/USBHostDac.cpp Wed Apr 01 10:29:31 2015 +0000
+++ b/USBHostDac.cpp Wed Sep 30 06:04:31 2015 +0000
@@ -31,24 +31,40 @@
USBHostDac::USBHostDac() {
host = USBHost::getHostInst();
- m_isoEp = new IsochronousEp;
- p_rest_data = new uint8_t[USBDAC_DATA_SIZE];
+ 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;
- rest_data_index = 0;
-
- wMaxPacketSize = 0;
- bInterfaceNumber = 0;
- bAlternateSetting = 0;
- bEndpointAddress = 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() {
@@ -73,9 +89,20 @@
host->registerDriver(dev, audio_intf, this, &USBHostDac::onDisconnect);
int addr = dev->getAddress();
- m_isoEp->init(addr, bEndpointAddress, PACKET_SIZE, FRAME_COUNT, QUEUE_NUM);
- setInterface(bAlternateSetting, bInterfaceNumber);
- setSamplingRate(48000);
+
+ 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;
@@ -91,44 +118,124 @@
uint32_t rest_size = len;
uint32_t send_size;
uint32_t copy_size;
- uint32_t def_send_size = PACKET_SIZE * FRAME_COUNT;
+ int result;
- if (rest_data_index != 0) {
- if (rest_size > (def_send_size - rest_data_index)) {
- copy_size = (def_send_size - rest_data_index);
+ 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(&p_rest_data[rest_data_index], &buf[send_index], copy_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;
- rest_data_index += copy_size;
- if ((flush != false) || (rest_data_index >= def_send_size)) {
- m_isoEp->isochronousSend(&p_rest_data[0], rest_data_index, 100);
- rest_data_index = 0;
+ 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 < def_send_size)) {
- memcpy(&p_rest_data[0], &buf[send_index], rest_size);
- rest_data_index = rest_size;
+ 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 >= def_send_size) {
- send_size = def_send_size;
+ if (rest_size >= (PACKET_SIZE * FRAME_COUNT)) {
+ send_size = (PACKET_SIZE * FRAME_COUNT);
} else {
send_size = rest_size;
}
- m_isoEp->isochronousSend(&buf[send_index], send_size, 100);
- send_index += send_size;
- rest_size -= send_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
@@ -138,7 +245,7 @@
{
bool ret;
- if (audio_intf != -1) {
+ if (audio_intf_cnt >= 2) {
ret = false;
} else if ((intf_class == AUDIO_CLASS) && (intf_subclass == 2) && (intf_protocol == 0)) {
// AUDIOSTREAMING Subclass
@@ -146,6 +253,7 @@
if (ret != false) {
audio_intf = intf_nb;
audio_device_found = true;
+ audio_intf_cnt++;
}
} else {
ret = false;
@@ -171,11 +279,17 @@
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) {
- bInterfaceNumber = conf_descr[index + 2];
- bAlternateSetting = conf_descr[index + 3];
+ 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)) {
@@ -188,8 +302,8 @@
break;
case ENDPOINT_DESCRIPTOR:
if ((conf_descr[index + 3] & 0x03) == ISOCHRONOUS_ENDPOINT) {
- bEndpointAddress = conf_descr[index + 2];
- wMaxPacketSize = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
+ wk_bEndpointAddress = conf_descr[index + 2];
+ wk_wMaxPacketSize = (conf_descr[index + 5] << 8) + conf_descr[index + 4];
loop_end = true;
}
break;
@@ -213,8 +327,21 @@
index += len_desc;
}
- if (((bEndpointAddress & 0x80) == 0) && (wMaxPacketSize >= PACKET_SIZE)
+ 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;
}
}
@@ -224,7 +351,12 @@
void USBHostDac::onDisconnect() {
if (dev_connected) {
- m_isoEp->disconnect();
+ if (iso_send.bEndpointAddress != 0) {
+ iso_send.m_isoEp->disconnect();
+ }
+ if (iso_recv.bEndpointAddress != 0) {
+ iso_recv.m_isoEp->disconnect();
+ }
init();
}
}
@@ -236,7 +368,7 @@
alt, index, NULL, 0);
}
-void USBHostDac::setSamplingRate(uint32_t sampling_rate) {
+void USBHostDac::setSamplingRate(uint8_t endpoint_adder, uint32_t sampling_rate) {
uint8_t data[3];
data[0] = (uint8_t)((sampling_rate >> 0) & 0xff);
@@ -245,6 +377,6 @@
host->controlWrite( dev,
USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
SET_CUR,
- SAMPLING, bEndpointAddress, data, 3);
+ SAMPLING, endpoint_adder, data, 3);
}
