This commit is contained in:
Ross Owen
2013-05-08 14:24:34 +01:00
parent f36a1afe23
commit e7d23603a4
13 changed files with 909 additions and 1281 deletions

View File

@@ -55,7 +55,7 @@ unsigned char DFUdevDesc[] = {
unsigned char DFUcfgDesc[] = { unsigned char DFUcfgDesc[] = {
/* Standard USB device descriptor */ /* Standard USB device descriptor */
0x09, /* 0 bLength */ 0x09, /* 0 bLength */
CONFIGURATION, /* 1 bDescriptorType */ USB_CONFIGURATION, /* 1 bDescriptorType */
0x1b, /* 2 wTotalLength */ 0x1b, /* 2 wTotalLength */
0x00, /* 3 wTotalLength */ 0x00, /* 3 wTotalLength */
1, /* 4 bNumInterface: Number of interfaces*/ 1, /* 4 bNumInterface: Number of interfaces*/
@@ -100,58 +100,8 @@ unsigned char DFUcfgDesc[] = {
}; };
unsigned char DFUoSpeedCfgDesc[] =
{
/* Standard USB device descriptor */
0x09, /* 0 bLength */
OTHER_SPEED_CONFIGURATION, /* 1 bDescriptorType */
0x1b, /* 2 wTotalLength */
0x00, /* 3 wTotalLength */
1, /* 4 bNumInterface: Number of interfaces*/
0x01, /* 5 bConfigurationValue */
0x00, /* 6 iConfiguration */
0xC0, /* 7 bmAttributes */
0x32, /* 8 bMaxPower */
/* Standard DFU class interface descriptor */
0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */
0x04, /* 1 bDescriptorType : INTERFACE descriptor. (field size 1 bytes) */
0x00, /* 2 bInterfaceNumber : Index of this interface. (field size 1 bytes) */
0x00, /* 3 bAlternateSetting : Index of this setting. (field size 1 bytes) */
0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */
0xFE, /* 5 bInterfaceClass : AUDIO. (field size 1 bytes) */
0x01, /* 6 bInterfaceSubclass : AUDIO_CONTROL. (field size 1 bytes) */
0x02, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */
0x00, /* 8 iInterface : Unused. (field size 1 bytes) */
/* DFU 1.1 Run-Time DFU Functional Descriptor */
0x09, /* 0 Size */
0x21, /* 1 bDescriptorType : DFU FUNCTIONAL */
0x07, /* 2 bmAttributes */
0xFA, /* 3 wDetachTimeOut */
0x00, /* 4 wDetachTimeOut */
0x40, /* 5 wTransferSize */
0x00, /* 6 wTransferSize */
0x10, /* 7 bcdDFUVersion */
0x01, /* 7 bcdDFUVersion */
};
unsigned char DFUdevQualDesc[] =
{
10, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */
DEVICE_QUALIFIER, /* 1 bdescriptorType */
0, /* 2 bcdUSB */
2, /* 3 bcdUSB */
0xfe, /* 4 bDeviceClass */
1, /* 5 bDeviceSubClass */
0, /* 6 bDeviceProtocol */
64, /* 7 bMaxPacketSize */
0x01, /* 8 bNumConfigurations : Number of possible configs */ \
0x00 /* 9 bReserved (must be zero) */ \
};
int DFUReportResetState(chanend ?c_user_cmd); int DFUReportResetState(chanend ?c_user_cmd);
int DFUDeviceRequests(XUD_ep c_ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend ?c_user_cmd, unsigned int altInterface, unsigned int user_reset); int DFUDeviceRequests(XUD_ep c_ep0_out, XUD_ep &?ep0_in, USB_SetupPacket_t &sp, chanend ?c_user_cmd, unsigned int altInterface, unsigned int user_reset);

View File

@@ -390,14 +390,14 @@ int XMOS_DFU_LoadState()
return 0; return 0;
} }
int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend ?c_user_cmd, unsigned int altInterface, unsigned int user_reset) int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, USB_SetupPacket_t &sp, chanend ?c_user_cmd, unsigned int altInterface, unsigned int user_reset)
{ {
unsigned int return_data_len = 0; unsigned int return_data_len = 0;
unsigned int data_buffer_len = 0; unsigned int data_buffer_len = 0;
unsigned int data_buffer[17]; unsigned int data_buffer[17];
unsigned int reset_device_after_ack = 0; unsigned int reset_device_after_ack = 0;
if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT) if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
{ {
// Host to device // Host to device
if (sp.wLength) if (sp.wLength)
@@ -465,7 +465,7 @@ int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend
break; break;
} }
if (sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_IN && sp.wLength != 0) if (sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_D2H && sp.wLength != 0)
{ {
// Device to host // Device to host
#ifdef ARCH_G #ifdef ARCH_G
@@ -477,9 +477,9 @@ int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend
else else
{ {
#ifdef ARCH_G #ifdef ARCH_G
XUD_DoSetRequestStatus(ep0_out, 0); XUD_DoSetRequestStatus(ep0_out);
#else #else
XUD_DoSetRequestStatus(ep0_in, 0); XUD_DoSetRequestStatus(ep0_in);
#endif #endif
} }

View File

@@ -14,12 +14,14 @@
#include <print.h> #include <print.h>
#include <xs1_su.h> #include <xs1_su.h>
#include "clocking.h"
#include "audioports.h" #include "audioports.h"
#include "codec.h" #include "audiohw.h"
#include "devicedefines.h" #include "devicedefines.h"
#include "SpdifTransmit.h" #include "SpdifTransmit.h"
//#define DSD_OUTPUT 1
unsigned g_adcVal = 0; unsigned g_adcVal = 0;
//#define RAMP_CHECK 1 //#define RAMP_CHECK 1
@@ -30,18 +32,6 @@ unsigned g_adcVal = 0;
//#pragma xta command "analyse path i2s_output_r i2s_output_l" //#pragma xta command "analyse path i2s_output_r i2s_output_l"
//#pragma xta command "set required - 2000 ns" //#pragma xta command "set required - 2000 ns"
#define DSD_OVER_PCM 1
#ifdef DSD_OVER_PCM
unsigned dopMarkerCount = 0;
#define DOP_MARKER_1 0x05
#define DOP_MARKER_2 0xFA
#define DOP_MARKER_XOR 0xFF
#define DOP_MARKER_THRESH 32 /* How many DSD markers we must see before switching to DSD mode */
#define DSD_MASK_IN(x) ((x & 0xFF000000) >> 24)
unsigned dopMarker = DOP_MARKER_1;
#endif
/* I2S Data I/O*/ /* I2S Data I/O*/
#if (I2S_CHANS_DAC != 0) #if (I2S_CHANS_DAC != 0)
extern buffered out port:32 p_i2s_dac[I2S_WIRES_DAC]; extern buffered out port:32 p_i2s_dac[I2S_WIRES_DAC];
@@ -60,26 +50,35 @@ extern in port p_lrclk;
extern in port p_bclk; extern in port p_bclk;
#endif #endif
unsigned dsdMode = 0;
#ifdef DSD_OUTPUT
#define p_dsd_clk p_i2s_dac[1]
#define p_dsd_left p_i2s_dac[0]
#define p_dsd_right p_lrclk
#define DSD_MARKER_1 0xFA
#define DSD_MARKER_2 0x05
#define DSD_MARKER_XOR 0xFF
#define DSD_EN_THRESH 32 /* Number of consecutive DSD markers before switching to DSD mode */
#define DSD_MASK(x) ((x >> 24) & 0xff)
#endif
/* Master clock input */ /* Master clock input */
extern port p_mclk; extern port p_mclk;
#ifdef SPDIF #ifdef SPDIF
extern buffered out port:32 p_spdif_tx; extern buffered out port:32 p_spdif_tx;
extern clock clk_mst_spd;
#endif #endif
extern clock clk_audio_mclk; extern clock clk_audio_mclk;
extern clock clk_audio_bclk; extern clock clk_audio_bclk;
extern clock clk_mst_spd;
extern void device_reboot(void); extern void device_reboot(void);
/* I2S delivery thread */ /* I2S delivery thread */
#pragma unsafe arrays #pragma unsafe arrays
unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_dig_rx, chanend ?c_adc unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_dig_rx, chanend ?c_adc)
#ifdef DSD_OVER_PCM
, int dop
#endif
)
{ {
unsigned sample; unsigned sample;
#if NUM_USB_CHAN_OUT > 0 #if NUM_USB_CHAN_OUT > 0
@@ -98,7 +97,13 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_
int started = 0; int started = 0;
#endif #endif
int dsdmode = 0; #ifdef DSD_OUTPUT
unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */
int dsdCount = 0;
int everyOther = 0;
unsigned dsdSample_l = 0;
unsigned dsdSample_r = 0;
#endif
#if NUM_USB_CHAN_IN > 0 #if NUM_USB_CHAN_IN > 0
@@ -218,7 +223,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_
#endif #endif
p_lrclk <: 0x7FFFFFFF; p_lrclk <: 0x7FFFFFFF;
p_bclk <: 0xAAAAAAAA; p_bclk <: 0xAAAAAAAA;//32clks
p_bclk <: 0xAAAAAAAA; p_bclk <: 0xAAAAAAAA;
} }
#else #else
@@ -322,57 +327,101 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_
asm("ldw %0, dp[g_digData+36]":"=r"(samplesIn[ADAT_RX_INDEX + 7])); asm("ldw %0, dp[g_digData+36]":"=r"(samplesIn[ADAT_RX_INDEX + 7]));
#endif #endif
#ifdef DSD_OVER_PCM
/* Inspect for DSD markers */
if((DSD_MASK_IN(samplesOut[0]) == dopMarker) && (DSD_MASK_IN(samplesOut[1]) == dopMarker))
{
dopMarker ^= DOP_MARKER_XOR;
dopMarkerCount++;
if(!dsdmode)
{
if(dopMarkerCount >= DOP_MARKER_THRESH)
{
dopMarkerCount=0;
dopMarker ^= DOP_MARKER_XOR;
printstr("DSD\n");
dsdmode = 1;
//return 0;
}
}
}
else
{
/* Reset DOP detect state */
dopMarkerCount = 0;
if(dsdmode)
{
//if(samplesOut[0] == 0)
//else
if(DSD_MASK_IN(samplesOut[0]) == (dopMarker ^ 0xff))
{
printstr("almost stopped");
//dopMarker ^= 0xff;
}
else
{
/* We were running in DOP mode, but it stopped... */
//return 0;
dsdmode = 0;
printstr("PCM\n");
}
}
}
#endif
#if defined(SPDIF_RX) || defined(ADAT_RX) #if defined(SPDIF_RX) || defined(ADAT_RX)
/* Request digital data (with prefill) */ /* Request digital data (with prefill) */
outuint(c_dig_rx, 0); outuint(c_dig_rx, 0);
#endif #endif
tmp = 0; tmp = 0;
#ifdef DSD_OUTPUT
#error
if(dsdMode)
{
//while(1)
{
if(!everyOther)
{
dsdSample_l = ((samplesOut[0] & 0xffff00) << 8);
dsdSample_r = ((samplesOut[1] & 0xffff00) << 8);
everyOther = 1;
switch (divide*4)
{
case 8:
p_bclk <: 0xF0F0F0F0;
p_bclk <: 0xF0F0F0F0;
p_bclk <: 0xF0F0F0F0;
p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
break;
case 4:
p_bclk <: 0xCCCCCCCC;
p_bclk <: 0xCCCCCCCC;
//p_bclk <: 0xCCCCCCCC;
//p_bclk <: 0xCCCCCCCC;
break;
case 2:
//p_bclk <: 0xAAAAAAAA;
p_bclk <: 0xAAAAAAAA;
break;
case 1:
break;
}
}
else if(everyOther)
{
everyOther = 0;
dsdSample_l = dsdSample_l | ((samplesOut[0] & 0xffff00) >> 8);
dsdSample_r = dsdSample_r | ((samplesOut[1] & 0xffff00) >> 8);
// Output 16 clocks DSD to all
p_dsd_left <: bitrev(dsdSample_l);
p_dsd_right <: bitrev(dsdSample_r);
switch (divide*4)
{
case 8:
p_bclk <: 0xF0F0F0F0;
p_bclk <: 0xF0F0F0F0;
p_bclk <: 0xF0F0F0F0;
p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
//p_bclk <: 0xF0F0F0F0;
break;
case 4:
p_bclk <: 0xCCCCCCCC;
p_bclk <: 0xCCCCCCCC;
//p_bclk <: 0xCCCCCCCC;
//p_bclk <: 0xCCCCCCCC;
break;
case 2:
//p_bclk <: 0xAAAAAAAA;
p_bclk <: 0xAAAAAAAA;
break;
case 1:
break;
}
}
}
}
else
#endif
{
#pragma xta endpoint "i2s_output_l" #pragma xta endpoint "i2s_output_l"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < I2S_CHANS_DAC; i+=2) for(int i = 0; i < I2S_CHANS_DAC; i+=2)
@@ -440,12 +489,10 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_
} }
#endif #endif
#if defined(SPDIF) && (NUM_USB_CHAN_OUT > 0) #if defined(SPDIF) && (NUM_USB_CHAN_OUT > 0)
if(!dop) outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to SPDIF txt thread */
{ outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to SPDIF txt thread */
sample = samplesOut[SPDIF_TX_INDEX + 1]; sample = samplesOut[SPDIF_TX_INDEX + 1];
outuint(c_spd_out, sample); /* Forward sample to SPDIF txt thread */ outuint(c_spd_out, sample); /* Forward sample to SPDIF txt thread */
}
#ifdef RAMP_CHECK #ifdef RAMP_CHECK
sample >>= 8; sample >>= 8;
if (started<10000) { if (started<10000) {
@@ -462,7 +509,6 @@ if(!dop)
#endif #endif
#endif #endif
tmp = 0; tmp = 0;
#pragma xta endpoint "i2s_output_r" #pragma xta endpoint "i2s_output_r"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
@@ -513,8 +559,6 @@ if(!dop)
#endif #endif
#if (I2S_CHANS_ADC != 0) #if (I2S_CHANS_ADC != 0)
/* Input previous L ADC sample */ /* Input previous L ADC sample */
index = 0; index = 0;
@@ -538,6 +582,48 @@ if(!dop)
} }
#endif #endif
#endif #endif
} // !dsdMode
#if defined (DSD_OUTPUT) && (NUM_USB_CHAN_OUT > 0)
#error
/* Check for DSD */
/* Currently we only check on channel 0 - we get all 0's on channels without data */
if(!dsdMode)
{
if((DSD_MASK(samplesOut[0]) == dsdMarker) && (DSD_MASK(samplesOut[1]) == dsdMarker))
{
dsdCount++;
dsdMarker ^= DSD_MARKER_XOR;
if(dsdCount == DSD_EN_THRESH)
{
dsdMode = 1;
dsdCount = 0;
dsdMarker = DSD_MARKER_2;
return 0;
}
}
else
{
dsdCount = 0;
dsdMarker = DSD_MARKER_2;
}
}
else // DSD Mode
{
if((DSD_MASK(samplesOut[0]) != dsdMarker) && (DSD_MASK(samplesOut[1]) != dsdMarker))
{
if(!((dsdCount == 0) && (DSD_MASK(samplesOut[0]) == (dsdMarker ^DSD_MARKER_XOR))
&& (DSD_MASK(samplesOut[1]) == (dsdMarker ^ DSD_MARKER_XOR))))
{
dsdCount = 0;
dsdMode = 0;
return 0;
}
}
}
#endif
} }
return 0; return 0;
} }
@@ -601,12 +687,10 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
chan c_spdif_out; chan c_spdif_out;
#endif #endif
unsigned curSamFreq = DEFAULT_FREQ; unsigned curSamFreq = DEFAULT_FREQ;
unsigned retVal;
unsigned mClk; unsigned mClk;
unsigned divide; unsigned divide;
unsigned firstRun = 1; unsigned firstRun = 1;
#ifdef DSD_OVER_PCM
unsigned dop = 0;
#endif
#ifdef SU1_ADC_ENABLE #ifdef SU1_ADC_ENABLE
/* Setup galaxian ADC */ /* Setup galaxian ADC */
@@ -646,17 +730,13 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
#endif #endif
/* Initialise master clock generation */ /* Initialise master clock generation */
ClockingInit(c_config); //ClockingInit(c_config);
/* Perform required CODEC/ADC/DAC initialisation */ /* Perform required CODEC/ADC/DAC initialisation */
CodecInit(c_config); AudioHwInit(c_config);
while(1) while(1)
{ {
if(curSamFreq)
{
/* Calculate what master clock we should be using */ /* Calculate what master clock we should be using */
if ((curSamFreq % 22050) == 0) if ((curSamFreq % 22050) == 0)
{ {
@@ -671,13 +751,19 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
divide = mClk / ( curSamFreq * 64 ); divide = mClk / ( curSamFreq * 64 );
/* Configure clocking for required master clock */ /* Configure clocking for required master clock */
ClockingConfig(mClk, c_config); //ClockingConfig(mClk, c_config);
/* Configure CODEC/DAC/ADC for SampleFreq/MClk */
AudioHwConfig(curSamFreq, mClk, c_config, dsdMode);
/* Configure audio ports */
ConfigAudioPorts(divide);
if(!firstRun) if(!firstRun)
{ {
/* TODO wait for good mclk instead of delay */ /* TODO wait for good mclk instead of delay */
/* No delay for DFU modes */ /* No delay for DFU modes */
if ((curSamFreq != AUDIO_REBOOT_FROM_DFU) && (curSamFreq != AUDIO_STOP_FOR_DFU)) if ((curSamFreq != AUDIO_REBOOT_FROM_DFU) && (curSamFreq != AUDIO_STOP_FOR_DFU) && retVal)
{ {
timer t; timer t;
unsigned time; unsigned time;
@@ -690,68 +776,46 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
} }
firstRun = 0; firstRun = 0;
/* Configure CODEC/DAC/ADC for SampleFreq/MClk */
CodecConfig(curSamFreq, mClk, c_config);
/* Configure audio ports */
ConfigAudioPorts(divide);
}
else
{
if(!dop)
{
/* DOP detected! */
printstrln("DOP Detect");
dop = 1;
/* TODO:
* Config ports for DSD
* Config CODEC for DSD
*/
}
else
{
/* DOP mode end */
printstrln("DOP end");
dop = 0;
}
}
par par
{ {
#ifdef SPDIF #ifdef SPDIF
{
if(!dop)
{ {
set_thread_fast_mode_on(); set_thread_fast_mode_on();
SpdifTransmit(p_spdif_tx, c_spdif_out); SpdifTransmit(p_spdif_tx, c_spdif_out);
} }
}
#endif #endif
{ {
#ifdef SPDIF #ifdef SPDIF
if(!dop)
{
/* Communicate master clock and sample freq to S/PDIF thread */ /* Communicate master clock and sample freq to S/PDIF thread */
outuint(c_spdif_out, curSamFreq); outuint(c_spdif_out, curSamFreq);
outuint(c_spdif_out, mClk); outuint(c_spdif_out, mClk);
}
#endif #endif
curSamFreq = deliver(c_mix_out, retVal = deliver(c_mix_out,
#ifdef SPDIF #ifdef SPDIF
c_spdif_out, c_spdif_out,
#else #else
null, null,
#endif #endif
divide, c_dig_rx, c divide, c_dig_rx, c);
#ifdef DSD_OVER_PCM
, dop #ifdef DSD_OUTPUT
if(retVal == 0)
{
// Check DSD mode here..
}
else
{
curSamFreq = retVal;
}
#else
curSamFreq = retVal;
#endif #endif
);
// Currently no more audio will happen after this point // Currently no more audio will happen after this point
if (curSamFreq == AUDIO_STOP_FOR_DFU) if (curSamFreq == AUDIO_STOP_FOR_DFU)
@@ -773,7 +837,6 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
#ifdef SPDIF #ifdef SPDIF
/* Notify S/PDIF thread of impending new freq... */ /* Notify S/PDIF thread of impending new freq... */
if(!dop)
outct(c_spdif_out, XS1_CT_END); outct(c_spdif_out, XS1_CT_END);
#endif #endif
} }

View File

@@ -0,0 +1,14 @@
#ifndef _CODEC_H_
#define _CODEC_H_
/* These functions must be implemented for the CODEC/ADC/DAC arrangement of a specific design */
/* TODO Are the channel args required? */
/* Any required clocking and CODEC initialisation - run once at start up */
void AudioHwInit(chanend ?c_codec);
/* Configure audio hardware (clocking, CODECs etc) for a specific mClk/Sample frquency - run on every sample frequency change */
void AudioHwConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec, int dsdMode);
#endif

View File

@@ -8,10 +8,10 @@
* */ * */
/* Any actions required for stream start e.g. DAC un-mute - run every stream start */ /* Any actions required for stream start e.g. DAC un-mute - run every stream start */
void AudioStreamStart(void); void UserAudioStreamStart(void);
/* Any actions required on stream stop e.g. DAC mute - run every steam stop */ /* Any actions required on stream stop e.g. DAC mute - run every steam stop */
void AudioStreamStop(void); void UserAudioStreamStop(void);
#endif #endif

View File

@@ -2,15 +2,6 @@
#ifndef _CLOCKING_H_ #ifndef _CLOCKING_H_
#define _CLOCKING_H_ #define _CLOCKING_H_
/* Functions that handle master clock generation. These need modifying for an existing design */
/* Any initialisation required for master clock generation - run once at start up */
void ClockingInit(chanend ?c);
/* Configuration for a specific master clock frequency - run every sample frequency change */
void ClockingConfig(unsigned mClkFreq, chanend ?c);
/** Clock generation and digital audio I/O handling. /** Clock generation and digital audio I/O handling.
* *
* \param c_spdif_rx channel connected to S/PDIF receive thread * \param c_spdif_rx channel connected to S/PDIF receive thread

View File

@@ -1,14 +0,0 @@
#ifndef _CODEC_H_
#define _CODEC_H_
/* These functions must be implemented for the CODEC/ADC/DAC arrangement of a specific design */
/* TODO Are the channel args required? */
/* Any required CODEC initialisation - run once at start up */
void CodecInit(chanend ?c_codec);
/* Configure condec for a specific mClk/Sample frquency - run on every sample frequency change */
void CodecConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec);
#endif

View File

@@ -1,5 +1,4 @@
/** /**
* @file internaldefines.h
* @brief Defines relating to device configuration and customisation. * @brief Defines relating to device configuration and customisation.
* @author Ross Owen, XMOS Limited * @author Ross Owen, XMOS Limited
*/ */

View File

@@ -7,6 +7,7 @@
#include "xud.h" #include "xud.h"
#include "usb.h" #include "usb.h"
#include "usbaudio20.h" #include "usbaudio20.h"
#include "usbaudio10.h"
#include "dbcalc.h" #include "dbcalc.h"
#include "devicedefines.h" #include "devicedefines.h"
#include "clockcmds.h" #include "clockcmds.h"
@@ -185,7 +186,8 @@ void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
{ {
switch( unitID ) switch( unitID )
{ {
case FU_USBOUT: { case FU_USBOUT:
{
/* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */ /* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */
/* 0x8000 is a special value representing -inf (i.e. mute) */ /* 0x8000 is a special value representing -inf (i.e. mute) */
unsigned master_vol = volsOut[0] == 0x8000 ? 0 : db_to_mult(volsOut[0], 8, 29); unsigned master_vol = volsOut[0] == 0x8000 ? 0 : db_to_mult(volsOut[0], 8, 29);
@@ -196,28 +198,18 @@ void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
#ifdef OUT_VOLUME_IN_MIXER #ifdef OUT_VOLUME_IN_MIXER
if (!isnull(c_mix_ctl)) if (!isnull(c_mix_ctl))
{ {
//master {
// c_mix_ctl <: SET_MIX_OUT_VOL;
// c_mix_ctl <: channel-1;
// /c_mix_ctl <: x;
//}
outuint(c_mix_ctl, SET_MIX_OUT_VOL); outuint(c_mix_ctl, SET_MIX_OUT_VOL);
outuint(c_mix_ctl, channel-1); outuint(c_mix_ctl, channel-1);
outuint(c_mix_ctl, x); outuint(c_mix_ctl, x);
outct(c_mix_ctl, XS1_CT_END); outct(c_mix_ctl, XS1_CT_END);
} }
#else #else
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multOut),"r"(channel-1)); asm("stw %0, %1[%2]"::"r"(x),"r"(p_multOut),"r"(channel-1));
#endif #endif
break; break;
} }
case FU_USBIN: { case FU_USBIN:
{
/* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */ /* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */
/* 0x8000 is a special value representing -inf (i.e. mute) */ /* 0x8000 is a special value representing -inf (i.e. mute) */
unsigned master_vol = volsIn[0] == 0x8000 ? 0 : db_to_mult(volsIn[0], 8, 29); unsigned master_vol = volsIn[0] == 0x8000 ? 0 : db_to_mult(volsIn[0], 8, 29);
@@ -226,35 +218,25 @@ void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[channel]; x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[channel];
#ifdef IN_VOLUME_IN_MIXER #ifdef IN_VOLUME_IN_MIXER
if (!isnull(c_mix_ctl)) { if (!isnull(c_mix_ctl))
//master { {
// c_mix_ctl <: SET_MIX_IN_VOL;
// c_mix_ctl <: channel-1;
// c_mix_ctl <: x;
//}
outuint(c_mix_ctl, SET_MIX_IN_VOL); outuint(c_mix_ctl, SET_MIX_IN_VOL);
outuint(c_mix_ctl, channel-1); outuint(c_mix_ctl, channel-1);
outuint(c_mix_ctl, x); outuint(c_mix_ctl, x);
outct(c_mix_ctl, XS1_CT_END); outct(c_mix_ctl, XS1_CT_END);
} }
#else #else
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multIn),"r"(channel-1)); asm("stw %0, %1[%2]"::"r"(x),"r"(p_multIn),"r"(channel-1));
#endif #endif
break; break;
} }
default:
/* Don't hit - We hope */
//"Vol: No such unit: unitID;
break;
} }
} }
} }
/* Handles the audio class specific requests /* Handles the audio class specific requests
* returns: 0 if request delt with successfully without error, * returns: 0 if request dealt with successfully without error,
* <0 for device reset suspend * <0 for device reset
* else 1 * else 1
*/ */
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
@@ -290,7 +272,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
case CS_SAM_FREQ_CONTROL: case CS_SAM_FREQ_CONTROL:
{ {
/* Direction: Host-to-device */ /* Direction: Host-to-device */
if( sp.bmRequestType.Direction == 0 ) if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
{ {
/* Get OUT data with Sample Rate into buffer*/ /* Get OUT data with Sample Rate into buffer*/
datalength = XUD_GetBuffer(ep0_out, buffer); datalength = XUD_GetBuffer(ep0_out, buffer);
@@ -303,7 +285,6 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
if(datalength == 4) if(datalength == 4)
{ {
/* Re-construct Sample Freq */ /* Re-construct Sample Freq */
i_tmp = buffer[0] | (buffer[1] << 8) | buffer[2] << 16 | buffer[3] << 24; i_tmp = buffer[0] | (buffer[1] << 8) | buffer[2] << 16 | buffer[3] << 24;
@@ -342,8 +323,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
} }
/* Send 0 Length as status stage */ /* Send 0 Length as status stage */
return XUD_SetBuffer(ep0_in, buffer, 0); XUD_DoSetRequestStatus(ep0_in);
} }
/* Direction: Device-to-host: Send Current Sample Freq */ /* Direction: Device-to-host: Send Current Sample Freq */
else else
@@ -352,7 +332,6 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
{ {
case ID_CLKSRC_EXT: case ID_CLKSRC_EXT:
case ID_CLKSRC_ADAT: case ID_CLKSRC_ADAT:
#ifdef REPORT_SPDIF_FREQ #ifdef REPORT_SPDIF_FREQ
/* Interogate clockgen thread for SPDIF freq */ /* Interogate clockgen thread for SPDIF freq */
if (!isnull(c_clk_ctl)) if (!isnull(c_clk_ctl))
@@ -360,30 +339,29 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
outuint(c_clk_ctl, GET_FREQ); outuint(c_clk_ctl, GET_FREQ);
outuint(c_clk_ctl, CLOCK_SPDIF_INDEX); outuint(c_clk_ctl, CLOCK_SPDIF_INDEX);
outct(c_clk_ctl, XS1_CT_END); outct(c_clk_ctl, XS1_CT_END);
(buffer, unsigned[])[0] = inuint(c_clk_ctl); (buffer, unsigned[])[0] = inuint(c_clk_ctl);
chkct(c_clk_ctl, XS1_CT_END); chkct(c_clk_ctl, XS1_CT_END);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 4, sp.wLength );
} }
else else
{ {
(buffer, unsigned[])[0] = g_curSamFreq; (buffer, unsigned[])[0] = g_curSamFreq;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 4, sp.wLength );
} }
break; break;
#endif #endif
case ID_CLKSRC_INT: case ID_CLKSRC_INT:
/* Always report our current operating frequency */ /* Always report our current operating frequency */
(buffer, unsigned[])[0] = g_curSamFreq; (buffer, unsigned[])[0] = g_curSamFreq;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 4, sp.wLength );
break; break;
default: default:
// XUD_Error_hex("Unknown Unit ID in Sample Frequency Control Request", unitID); /* Unknown Unit ID in Sample Frequency Control Request: unitID */
break; break;
} }
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength );
} }
break; break;
} }
@@ -397,6 +375,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
/* Internal clock always valid */ /* Internal clock always valid */
buffer[0] = 1; buffer[0] = 1;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
break; break;
case ID_CLKSRC_EXT: case ID_CLKSRC_EXT:
@@ -409,6 +388,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
outct(c_clk_ctl, XS1_CT_END); outct(c_clk_ctl, XS1_CT_END);
buffer[0] = inuint(c_clk_ctl); buffer[0] = inuint(c_clk_ctl);
chkct(c_clk_ctl, XS1_CT_END); chkct(c_clk_ctl, XS1_CT_END);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
} }
break; break;
@@ -422,23 +402,19 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
outct(c_clk_ctl, XS1_CT_END); outct(c_clk_ctl, XS1_CT_END);
buffer[0] = inuint(c_clk_ctl); buffer[0] = inuint(c_clk_ctl);
chkct(c_clk_ctl, XS1_CT_END); chkct(c_clk_ctl, XS1_CT_END);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
} }
break; break;
default: default:
//XUD_Error_hex("Unknown Unit ID in Clock Valid Control Request: ", unitID); //Unknown Unit ID in Clock Valid Control Request
break; break;
} }
return XUD_DoGetRequest( ep0_out, ep0_in, buffer, sp.wLength, sp.wLength );
break; break;
} }
default: default:
//XUD_Error_hex("Unknown Control Selector for Clock Unit: ", sp.wValue >> 8 ); //Unknown Control Selector for Clock Unit: sp.wValue >> 8
break; break;
} }
@@ -449,10 +425,10 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
case ID_CLKSEL: case ID_CLKSEL:
{ {
if ((sp.wValue >> 8) == CX_CLOCK_SELECTOR_CONTROL) if ((sp.wValue >> 8) == CX_CLOCK_SELECTOR_CONTROL)
{
if( sp.bmRequestType.Direction == 0 )
{ {
/* Direction: Host-to-device */ /* Direction: Host-to-device */
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D )
{
datalength = XUD_GetBuffer(ep0_out, buffer); datalength = XUD_GetBuffer(ep0_out, buffer);
if(datalength < 0) if(datalength < 0)
@@ -461,24 +437,21 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
/* Check for correct datalength for clock sel */ /* Check for correct datalength for clock sel */
if(datalength == 1) if(datalength == 1)
{ {
if (!isnull(c_clk_ctl)) if (!isnull(c_clk_ctl))
{ {
outuint(c_clk_ctl, SET_SEL); outuint(c_clk_ctl, SET_SEL);
outuint(c_clk_ctl, buffer[0]); outuint(c_clk_ctl, buffer[0]);
outct(c_clk_ctl, XS1_CT_END); outct(c_clk_ctl, XS1_CT_END);
} }
}
/* Send 0 Length as status stage */ /* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in); return XUD_DoSetRequestStatus(ep0_in);
} }
}
else else
{ {
buffer[0] = 1;
/* Direction: Device-to-host: Send Current Selection */ /* Direction: Device-to-host: Send Current Selection */
buffer[0] = 1;
if (!isnull(c_clk_ctl)) if (!isnull(c_clk_ctl))
{ {
outuint(c_clk_ctl, GET_SEL); outuint(c_clk_ctl, GET_SEL);
@@ -486,14 +459,10 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
buffer[0] = inuint(c_clk_ctl); buffer[0] = inuint(c_clk_ctl);
chkct(c_clk_ctl, XS1_CT_END); chkct(c_clk_ctl, XS1_CT_END);
} }
return XUD_DoGetRequest( ep0_out, ep0_in, buffer, 1, sp.wLength ); return XUD_DoGetRequest( ep0_out, ep0_in, buffer, 1, sp.wLength );
} }
} }
else
{
//Unknown control on clock selector: sp.wValue
}
break; break;
} }
@@ -506,79 +475,61 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
{ {
case FU_VOLUME_CONTROL: case FU_VOLUME_CONTROL:
if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT) /* Direction: Host-to-device */ if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
{ {
/* Expect OUT here (with volume) */
/* Expect OUT here (with v2yyolume) */
loop = XUD_GetBuffer(ep0_out, buffer); loop = XUD_GetBuffer(ep0_out, buffer);
/* Check for rst/suspend */ /* Check for reset */
if(loop < 0) if(loop < 0)
{
printintln(loop);
return loop; return loop;
}
#if 1
if(unitID == FU_USBOUT) if(unitID == FU_USBOUT)
{ {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT) { if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
{
volsOut[ sp.wValue&0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8); volsOut[ sp.wValue&0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl ); updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
} }
} }
else else
{ {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN) { if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{
volsIn[ sp.wValue&0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8); volsIn[ sp.wValue&0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl ); updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
}
}
#endif
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in); return XUD_DoSetRequestStatus(ep0_in);
} }
}
}
else /* Direction: Device-to-host */ else /* Direction: Device-to-host */
{ {
if(unitID == FU_USBOUT) if(unitID == FU_USBOUT)
{ {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT) { if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
{
buffer[0] = volsOut[ sp.wValue&0xff ]; buffer[0] = volsOut[ sp.wValue&0xff ];
buffer[1] = volsOut[ sp.wValue&0xff ] >> 8; buffer[1] = volsOut[ sp.wValue&0xff ] >> 8;
} return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
else {
buffer[0] = buffer[1] = 0;
} }
} }
else else
{ {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN) { if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{
buffer[0] = volsIn[ sp.wValue&0xff ]; buffer[0] = volsIn[ sp.wValue&0xff ];
buffer[1] = volsIn[ sp.wValue&0xff ] >> 8; buffer[1] = volsIn[ sp.wValue&0xff ] >> 8;
} return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
else {
buffer[0] = buffer[1] = 0;
} }
} }
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
} }
break; /* FU_VOLUME_CONTROL */ break; /* FU_VOLUME_CONTROL */
case FU_MUTE_CONTROL: case FU_MUTE_CONTROL:
if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT) // Direction: Host-to-device if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
{ {
{
unsigned time;
timer t;
t :> time;
t when timerafter(time+10000000):> void;
}
/* Expect OUT here with mute */ /* Expect OUT here with mute */
loop = XUD_GetBuffer(ep0_out, buffer); loop = XUD_GetBuffer(ep0_out, buffer);
@@ -587,37 +538,42 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
if (unitID == FU_USBOUT) if (unitID == FU_USBOUT)
{ {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT) { if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
{
mutesOut[sp.wValue & 0xff] = buffer[0]; mutesOut[sp.wValue & 0xff] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl); updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
return XUD_DoSetRequestStatus(ep0_in);
} }
} }
else else
{
if((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{ {
mutesIn[ sp.wValue&0xff ] = buffer[0]; mutesIn[ sp.wValue&0xff ] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl); updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in); return XUD_DoSetRequestStatus(ep0_in);
} }
}
}
else // Direction: Device-to-host else // Direction: Device-to-host
{ {
if(unitID == FU_USBOUT) if(unitID == FU_USBOUT)
{ {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT) { if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
{
buffer[0] = mutesOut[sp.wValue&0xff]; buffer[0] = mutesOut[sp.wValue&0xff];
} return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
else {
buffer[0] = 0;
} }
} }
else else
{
if((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{ {
buffer[0] = mutesIn[ sp.wValue&0xff ]; buffer[0] = mutesIn[ sp.wValue&0xff ];
}
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength); return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
} }
}
}
break; break;
default: default:
@@ -630,7 +586,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
#ifdef MIXER #ifdef MIXER
case ID_XU_OUT: case ID_XU_OUT:
{ {
if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT) /* Direction: Host-to-device */ if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
{ {
unsigned volume = 0; unsigned volume = 0;
int c = sp.wValue & 0xff; int c = sp.wValue & 0xff;
@@ -646,22 +602,16 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
{ {
if (c < NUM_USB_CHAN_OUT) if (c < NUM_USB_CHAN_OUT)
{ {
//master {
// c_mix_ctl <: SET_SAMPLES_TO_DEVICE_MAP;
// c_mix_ctl <: c;
// c_mix_ctl <: (int) channelMapAud[c];
//}
outuint(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP); outuint(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP);
outuint(c_mix_ctl, c); outuint(c_mix_ctl, c);
outuint(c_mix_ctl, channelMapAud[c]); outuint(c_mix_ctl, channelMapAud[c]);
outct(c_mix_ctl, XS1_CT_END); outct(c_mix_ctl, XS1_CT_END);
}
}
/* Send 0 Length as status stage */ /* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in); return XUD_DoSetRequestStatus(ep0_in);
} }
}
}
else else
{ {
buffer[0] = channelMapAud[sp.wValue & 0xff]; buffer[0] = channelMapAud[sp.wValue & 0xff];
@@ -674,8 +624,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
break; break;
case ID_XU_IN: case ID_XU_IN:
{ if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT) /* Direction: Host-to-device */
{ {
unsigned volume = 0; unsigned volume = 0;
int c = sp.wValue & 0xff; int c = sp.wValue & 0xff;
@@ -687,38 +636,27 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
channelMapUsb[c] = buffer[0] | buffer[1] << 8; channelMapUsb[c] = buffer[0] | buffer[1] << 8;
if (!isnull(c_mix_ctl))
{
if (c < NUM_USB_CHAN_IN) if (c < NUM_USB_CHAN_IN)
{ {
//master { if (!isnull(c_mix_ctl))
// c_mix_ctl <: SET_SAMPLES_TO_HOST_MAP; {
// c_mix_ctl <: c;
// c_mix_ctl <: (int) channelMapUsb[c];
//}
outuint(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP); outuint(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP);
outuint(c_mix_ctl, c); outuint(c_mix_ctl, c);
outuint(c_mix_ctl, channelMapUsb[c]); outuint(c_mix_ctl, channelMapUsb[c]);
outct(c_mix_ctl, XS1_CT_END); outct(c_mix_ctl, XS1_CT_END);
}
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in); return XUD_DoSetRequestStatus(ep0_in);
} }
}
}
else else
{ {
/* Direction: Device-to-host */
buffer[0] = channelMapUsb[sp.wValue & 0xff]; buffer[0] = channelMapUsb[sp.wValue & 0xff];
buffer[1] = 0; buffer[1] = 0;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength); return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
} }
}
break; break;
case ID_XU_MIXSEL: case ID_XU_MIXSEL:
{ {
int cs = sp.wValue >> 8; /* Control Selector */ int cs = sp.wValue >> 8; /* Control Selector */
@@ -730,11 +668,9 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
/* Direction: Host-to-device */ /* Host-to-device */ /* Direction: Host-to-device */ /* Host-to-device */
datalength = XUD_GetBuffer(ep0_out, buffer); datalength = XUD_GetBuffer(ep0_out, buffer);
/* Check for reset/suspend */ /* Check for reset */
if(datalength < 0) if(datalength < 0)
{
return datalength; return datalength;
}
if(datalength > 0) if(datalength > 0)
{ {
@@ -758,15 +694,10 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
outuint(c_mix_ctl, (int) mixSel[cn]); /* Source */ outuint(c_mix_ctl, (int) mixSel[cn]); /* Source */
outct(c_mix_ctl, XS1_CT_END); outct(c_mix_ctl, XS1_CT_END);
} }
}
}
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in); return XUD_DoSetRequestStatus(ep0_in);
}
}
}
} }
else else
{ {
@@ -780,12 +711,9 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
if(cs == CS_XU_MIXSEL) if(cs == CS_XU_MIXSEL)
{ {
buffer[0] = mixSel[cn]; buffer[0] = mixSel[cn];
}
}
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, 1 ); return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, 1 );
}
}
} }
break; break;
} }
@@ -795,34 +723,29 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT) /* Direction: Host-to-device */ if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT) /* Direction: Host-to-device */
{ {
unsigned volume = 0; unsigned volume = 0;
/* Expect OUT here with mute */ /* Expect OUT here with mute */
loop = XUD_GetBuffer(ep0_out, buffer); loop = XUD_GetBuffer(ep0_out, buffer);
if(loop < 0) if(loop < 0)
return loop; return loop;
mixer1Weights[sp.wValue & 0xff] = buffer[0] | buffer[1] << 8; mixer1Weights[sp.wValue & 0xff] = buffer[0] | buffer[1] << 8;
if (mixer1Weights[sp.wValue & 0xff] == 0x8000) { if (mixer1Weights[sp.wValue & 0xff] == 0x8000)
{
volume = 0; volume = 0;
} }
else { else
{
volume = db_to_mult(mixer1Weights[sp.wValue & 0xff], 8, 25); volume = db_to_mult(mixer1Weights[sp.wValue & 0xff], 8, 25);
} }
if (!isnull(c_mix_ctl)) if (!isnull(c_mix_ctl))
{ {
//master {
// c_mix_ctl <: SET_MIX_MULT;
//c_mix_ctl <: (sp.wValue & 0xff) % 8;
//c_mix_ctl <: (sp.wValue & 0xff) / 8;
///c_mix_ctl <: volume;
//}/
outuint(c_mix_ctl, SET_MIX_MULT); outuint(c_mix_ctl, SET_MIX_MULT);
outuint(c_mix_ctl, (sp.wValue & 0xff) % 8); outuint(c_mix_ctl, (sp.wValue & 0xff) % 8);
outuint(c_mix_ctl, (sp.wValue & 0xff) / 8); outuint(c_mix_ctl, (sp.wValue & 0xff) / 8);
outuint(c_mix_ctl, volume); outuint(c_mix_ctl, volume);
outct(c_mix_ctl, XS1_CT_END); outct(c_mix_ctl, XS1_CT_END);
} }
/* Send 0 Length as status stage */ /* Send 0 Length as status stage */
@@ -839,11 +762,9 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
break; break;
#endif #endif
//default: default:
/* We dont have a unit with this ID! */
///* We dont have a unit with this ID! */ break;
//XUD_Error_hex("ERR: Unknown control unit: ", sp.wIndex);
//break;
} /* switch(sp.wIndex >> 8) i.e Unit ID */ } /* switch(sp.wIndex >> 8) i.e Unit ID */
break; break;
@@ -936,13 +857,11 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
storeShort(buffer, 2, MIN_VOLUME); storeShort(buffer, 2, MIN_VOLUME);
storeShort(buffer, 4, MAX_VOLUME); storeShort(buffer, 4, MAX_VOLUME);
storeShort(buffer, 6, VOLUME_RES); storeShort(buffer, 6, VOLUME_RES);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength); return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
break; break;
default: default:
//Unknown control selector for FU: ", sp.wValue); /* Unknown control selector for FU */
break; break;
} }
@@ -951,25 +870,21 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
#ifdef MIXER #ifdef MIXER
/* Mixer Unit */ /* Mixer Unit */
case ID_MIXER_1: case ID_MIXER_1:
storeShort(buffer, 0, 1); storeShort(buffer, 0, 1);
storeShort(buffer, 2, MIN_MIXER_VOLUME); storeShort(buffer, 2, MIN_MIXER_VOLUME);
storeShort(buffer, 4, MAX_MIXER_VOLUME); storeShort(buffer, 4, MAX_MIXER_VOLUME);
storeShort(buffer, 6, VOLUME_RES_MIXER); storeShort(buffer, 6, VOLUME_RES_MIXER);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength); return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
break; break;
#endif #endif
default: default:
//XUD_Error_hex("Unknown Unit ID in Range Request selector for FU: ", sp.wIndex >> 8); /* Unknown Unit ID in Range Request selector for FU */
break; break;
} }
break; break; /* case: RANGE */
} }
#ifdef MIXER #ifdef MIXER
@@ -1033,7 +948,8 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
for(int i = 0; i < MAX_MIX_COUNT; i++) for(int i = 0; i < MAX_MIX_COUNT; i++)
{ {
if (!isnull(c_mix_ctl)) { if (!isnull(c_mix_ctl))
{
outuint(c_mix_ctl, GET_OUTPUT_LEVELS); outuint(c_mix_ctl, GET_OUTPUT_LEVELS);
outuint(c_mix_ctl, i); outuint(c_mix_ctl, i);
outct(c_mix_ctl, XS1_CT_END); outct(c_mix_ctl, XS1_CT_END);
@@ -1050,31 +966,10 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
} }
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, length, sp.wLength); return XUD_DoGetRequest(ep0_out, ep0_in, buffer, length, sp.wLength);
} }
else
{
/* Host-to-device (SET) */
/* Currently no action for set mem request for any offset */
datalength = XUD_GetBuffer(ep0_out, buffer);
/* Check for reset/suspend */
if(datalength < 0)
{
return datalength;
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in);
}
break; break;
} }
break; break;
#endif #endif
} }
/* Didn't deal with request, return 1 */ /* Didn't deal with request, return 1 */
@@ -1083,79 +978,43 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
} }
#if defined (AUDIO_CLASS_FALLBACK) || (AUDIO_CLASS==1) #if defined (AUDIO_CLASS_FALLBACK) || (AUDIO_CLASS==1)
/* Handles the Audio Class 1.0 specific requests */
int AudioClassRequests_1(XUD_ep c_ep0_out, XUD_ep c_ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl)
)
{ {
/* At this point we know:
* bmRequestType.Recipient = Endpoint
* bmRequestType.Type = Class
* endpoint (wIndex & 0xff) is 0x01 or 0x82
*/
int retVal = 1;
unsigned char buffer[1024]; unsigned char buffer[1024];
int unitID;
int loop = 1;
int i_tmp;
/* Inspect request, NOTE: these are class specific requests */ /* Host to Device */
switch( sp.bRequest ) if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
{ {
case SET_INTERFACE: /* Inspect for request */
switch(sp.bRequest)
{ {
return XUD_SetBuffer(c_ep0_in, buffer, 0); case UAC_B_REQ_SET_CUR:
{
/* Check Control Selector */
unsigned short controlSelector = sp.wValue>>8;
break; retVal = XUD_GetBuffer(ep0_out, buffer);
}
case B_REQ_SET_CUR: /* Inspect for reset */
if(retVal < 0)
return retVal;
if(controlSelector == SAMPLING_FREQ_CONTROL)
{
/* Expect length 3 for sample rate */
if((sp.wLength == 3)&&(retVal == 3))
{ {
loop = XUD_GetBuffer(c_ep0_out, buffer); /* Recontruct sample-freq */
int i_tmp = buffer[0] | (buffer [1] << 8) | (buffer[2] << 16);
/* Inspect for rst/suspend */
if(loop < 0)
return loop;
unitID = sp.wIndex >> 8;
if (unitID == FU_USBOUT)
{
switch ((sp.wValue>>8) & 0xff)
{
case FU_VOLUME_CONTROL:
{
volsOut[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
break;
}
case FU_MUTE_CONTROL:
{
mutesOut[ sp.wValue & 0xff ] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
break;
}
}
}
else if (unitID == FU_USBIN)
{
switch ((sp.wValue>>8) & 0xff)
{
case FU_VOLUME_CONTROL:
{
volsIn[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
break;
}
case FU_MUTE_CONTROL:
{
mutesIn[ sp.wValue & 0xff ] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
break;
}
}
}
else if (unitID == 0) // sample freq
{
i_tmp = buffer[0] | (buffer [1] << 8) | (buffer[2] << 16);
if(i_tmp != g_curSamFreq) if(i_tmp != g_curSamFreq)
{ {
@@ -1198,13 +1057,83 @@ int AudioClassRequests_1(XUD_ep c_ep0_out, XUD_ep c_ep0_in, USB_SetupPacket_t &s
} }
} }
} }
return XUD_SetBuffer(ep0_in, buffer, 0);
}
}
} }
return XUD_SetBuffer(c_ep0_in, buffer, 0);
break; break;
} }
case B_REQ_GET_CUR: }
else // sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_D2H
{
switch(sp.bRequest)
{
case UAC_B_REQ_GET_CUR:
(buffer, unsigned[])[0] = g_curSamFreq;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 3, sp.wLength);
break;
}
}
/* Return 1 for not handled */
return 1;
}
/* Handles the Audio Class 1.0 specific requests */
int AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
)
{
unsigned char buffer[1024];
int unitID;
int loop = 1;
int i_tmp;
/* Inspect request */
/* Note we could check sp.bmRequestType.Direction if we wanted to be really careful */
switch(sp.bRequest)
{
case UAC_B_REQ_SET_CUR:
{
loop = XUD_GetBuffer(ep0_out, buffer);
/* Inspect for reset */
if(loop < 0)
return loop;
unitID = sp.wIndex >> 8;
if (unitID == FU_USBOUT)
{
switch ((sp.wValue>>8) & 0xff)
{
case FU_VOLUME_CONTROL:
volsOut[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
case FU_MUTE_CONTROL:
mutesOut[ sp.wValue & 0xff ] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
}
}
else if (unitID == FU_USBIN)
{
switch ((sp.wValue>>8) & 0xff)
{
case FU_VOLUME_CONTROL:
volsIn[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
case FU_MUTE_CONTROL:
mutesIn[ sp.wValue & 0xff ] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
}
}
break;
}
case UAC_B_REQ_GET_CUR:
{ {
unitID = sp.wIndex >> 8; unitID = sp.wIndex >> 8;
if (unitID == FU_USBOUT) if (unitID == FU_USBOUT)
@@ -1215,11 +1144,13 @@ int AudioClassRequests_1(XUD_ep c_ep0_out, XUD_ep c_ep0_in, USB_SetupPacket_t &s
{ {
buffer[0] = volsOut[ sp.wValue&0xff ]; buffer[0] = volsOut[ sp.wValue&0xff ];
buffer[1] = volsOut[ sp.wValue&0xff ] >> 8; buffer[1] = volsOut[ sp.wValue&0xff ] >> 8;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
break; break;
} }
case FU_MUTE_CONTROL: case FU_MUTE_CONTROL:
{ {
buffer[0] = mutesOut[ sp.wValue & 0xff ]; buffer[0] = mutesOut[ sp.wValue & 0xff ];
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
break; break;
} }
} }
@@ -1232,74 +1163,34 @@ int AudioClassRequests_1(XUD_ep c_ep0_out, XUD_ep c_ep0_in, USB_SetupPacket_t &s
{ {
buffer[0] = volsIn[ sp.wValue&0xff ]; buffer[0] = volsIn[ sp.wValue&0xff ];
buffer[1] = volsIn[ sp.wValue&0xff ] >> 8; buffer[1] = volsIn[ sp.wValue&0xff ] >> 8;
break; return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
} }
case FU_MUTE_CONTROL: case FU_MUTE_CONTROL:
{ {
buffer[0] = mutesIn[ sp.wValue & 0xff ]; buffer[0] = mutesIn[ sp.wValue & 0xff ];
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
}
}
}
break; break;
} }
} case UAC_B_REQ_GET_MIN:
}
else if(unitID == 0)
{
//printintln(unitID);
}
loop = XUD_SetBuffer(c_ep0_in, buffer, sp.wLength);
if(loop < 0)
return loop;
/* Status stage (0 length OUT) */
return XUD_GetBuffer(c_ep0_out,buffer);
break;
}
case B_REQ_GET_MIN:
{
buffer[0] = (MIN_MIXER_VOLUME & 0xff); buffer[0] = (MIN_MIXER_VOLUME & 0xff);
buffer[1] = (MIN_MIXER_VOLUME >> 8); buffer[1] = (MIN_MIXER_VOLUME >> 8);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
loop = XUD_SetBuffer(c_ep0_in, buffer, sp.wLength); case UAC_B_REQ_GET_MAX:
if(loop < 0)
return loop;
// Status stage (0 length OUT)
return XUD_GetBuffer(c_ep0_out, buffer);
break;
}
case B_REQ_GET_MAX:
{
buffer[0] = (MAX_MIXER_VOLUME & 0xff); buffer[0] = (MAX_MIXER_VOLUME & 0xff);
buffer[1] = (MAX_MIXER_VOLUME >> 8); buffer[1] = (MAX_MIXER_VOLUME >> 8);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
loop = XUD_SetBuffer(c_ep0_in, buffer, sp.wLength); case UAC_B_REQ_GET_RES:
if(loop < 0)
return 0;
// Status stage (0 length OUT)
return XUD_GetBuffer(c_ep0_out, buffer);
break;
}
case B_REQ_GET_RES:
{
buffer[0] = (VOLUME_RES_MIXER & 0xff); buffer[0] = (VOLUME_RES_MIXER & 0xff);
buffer[1] = (VOLUME_RES_MIXER >> 8); buffer[1] = (VOLUME_RES_MIXER >> 8);
loop = XUD_SetBuffer(c_ep0_in, buffer, sp.wLength); return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
if(loop < 0)
return loop;
// Status stage (0 length OUT)
return XUD_GetBuffer(c_ep0_out, buffer);
break;
}
} }
return 1; return 1;
} }
#endif #endif

View File

@@ -20,7 +20,7 @@
unsigned char devDesc_Audio1[] = unsigned char devDesc_Audio1[] =
{ {
18, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */ 18, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */
DEVICE, /* 1 bdescriptorType */ USB_DEVICE, /* 1 bdescriptorType */
0x0, /* 2 bcd USB */ 0x0, /* 2 bcd USB */
0x1, /* 3 bcdUSB */ 0x1, /* 3 bcdUSB */
0, /* 4 bDeviceClass */ 0, /* 4 bDeviceClass */
@@ -34,7 +34,7 @@ unsigned char devDesc_Audio1[] =
(BCD_DEVICE & 0xFF), /* 12 bcdDevice : Device release number */ (BCD_DEVICE & 0xFF), /* 12 bcdDevice : Device release number */
(BCD_DEVICE >> 8), /* 13 bcdDevice : Device release number */ (BCD_DEVICE >> 8), /* 13 bcdDevice : Device release number */
MANUFACTURER_STR_INDEX, /* 14 iManufacturer : Index of manufacturer string */ MANUFACTURER_STR_INDEX, /* 14 iManufacturer : Index of manufacturer string */
PRODUCT_STR_INDEX, /* 15 iProduct : Index of product string descriptor */ 8, /* 15 iProduct : Index of product string descriptor */
0,//SERIAL_STR_INDEX, /* 16 iSerialNumber : Index of serial number decriptor */ 0,//SERIAL_STR_INDEX, /* 16 iSerialNumber : Index of serial number decriptor */
0x01 /* 17 bNumConfigurations : Number of possible configs. */ 0x01 /* 17 bNumConfigurations : Number of possible configs. */
}; };
@@ -44,7 +44,7 @@ unsigned char devDesc_Audio1[] =
unsigned char devDesc_Audio2[] = unsigned char devDesc_Audio2[] =
{ {
18, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */ 18, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */
DEVICE, /* 1 bdescriptorType */ USB_DEVICE, /* 1 bdescriptorType */
0, /* 2 bcdUSB */ 0, /* 2 bcdUSB */
2, /* 3 bcdUSB */ 2, /* 3 bcdUSB */
0xEF, /* 4 bDeviceClass (See Audio Class Spec page 45) */ 0xEF, /* 4 bDeviceClass (See Audio Class Spec page 45) */
@@ -68,7 +68,7 @@ unsigned char devDesc_Audio2[] =
unsigned char devDesc_Null[] = unsigned char devDesc_Null[] =
{ {
18, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */ 18, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */
DEVICE, /* 1 bdescriptorType */ USB_DEVICE, /* 1 bdescriptorType */
0, /* 2 bcdUSB */ 0, /* 2 bcdUSB */
2, /* 3 bcdUSB */ 2, /* 3 bcdUSB */
0x0, /* 4 bDeviceClass */ 0x0, /* 4 bDeviceClass */
@@ -94,7 +94,7 @@ unsigned char devDesc_Null[] =
unsigned char devQualDesc_Audio2[] = unsigned char devQualDesc_Audio2[] =
{ {
10, /* 0 bLength (10 Bytes) */ 10, /* 0 bLength (10 Bytes) */
DEVICE_QUALIFIER, /* 1 bDescriptorType */ USB_DEVICE_QUALIFIER, /* 1 bDescriptorType */
0x00, /* 2 bcdUSB (Binary Coded Decimal of usb version) */ 0x00, /* 2 bcdUSB (Binary Coded Decimal of usb version) */
0x02, /* 3 bcdUSB */ 0x02, /* 3 bcdUSB */
0xEF, /* 4 bDeviceClass */ 0xEF, /* 4 bDeviceClass */
@@ -110,7 +110,7 @@ unsigned char devQualDesc_Audio2[] =
unsigned char devQualDesc_Audio1[] = unsigned char devQualDesc_Audio1[] =
{ {
10, /* 0 bLength (10 Bytes) */ 10, /* 0 bLength (10 Bytes) */
DEVICE_QUALIFIER, /* 1 bDescriptorType */ USB_DEVICE_QUALIFIER, /* 1 bDescriptorType */
0x00, /* 2 bcdUSB (Binary Coded Decimal of usb version) */ 0x00, /* 2 bcdUSB (Binary Coded Decimal of usb version) */
0x02, /* 3 bcdUSB */ 0x02, /* 3 bcdUSB */
0x00, /* 4 bDeviceClass */ 0x00, /* 4 bDeviceClass */
@@ -126,7 +126,7 @@ unsigned char devQualDesc_Audio1[] =
unsigned char devQualDesc_Null[] = unsigned char devQualDesc_Null[] =
{ {
10, /* 0 bLength (10 Bytes) */ 10, /* 0 bLength (10 Bytes) */
DEVICE_QUALIFIER, /* 1 bDescriptorType */ USB_DEVICE_QUALIFIER, /* 1 bDescriptorType */
0x00, /* 2 bcdUSB (Binary Coded Decimal of usb version) */ 0x00, /* 2 bcdUSB (Binary Coded Decimal of usb version) */
0x02, /* 3 bcdUSB */ 0x02, /* 3 bcdUSB */
0x00, /* 4 bDeviceClass */ 0x00, /* 4 bDeviceClass */
@@ -228,8 +228,8 @@ unsigned char devQualDesc_Null[] =
#endif #endif
// Positions in strDescs_Audio2 // Positions in strDescs_Audio2
#define INTERNAL_CLOCK_STRING_INDEX 9 #define INTERNAL_CLOCK_STRING_INDEX 14
#define SPDIF_CLOCK_STRING_INDEX 10 #define SPDIF_CLOCK_STRING_INDEX 15
#ifdef SPDIF_RX #ifdef SPDIF_RX
#define ADAT_CLOCK_STRING_INDEX (SPDIF_CLOCK_STRING_INDEX + 1) #define ADAT_CLOCK_STRING_INDEX (SPDIF_CLOCK_STRING_INDEX + 1)
@@ -299,7 +299,7 @@ unsigned char hidReportDescriptor[] = {
unsigned char cfgDesc_Audio2[] = unsigned char cfgDesc_Audio2[] =
{ {
0x09, /* 0 bLength */ 0x09, /* 0 bLength */
CONFIGURATION, /* 1 bDescriptorType */ USB_CONFIGURATION, /* 1 bDescriptorType */
(CFG_TOTAL_LENGTH_A2 & 0xFF), /* 2 wTotalLength */ (CFG_TOTAL_LENGTH_A2 & 0xFF), /* 2 wTotalLength */
(CFG_TOTAL_LENGTH_A2 >> 8), /* 3 wTotalLength */ (CFG_TOTAL_LENGTH_A2 >> 8), /* 3 wTotalLength */
NUM_INTERFACES, /* 4 bNumInterface: Number of interfaces*/ NUM_INTERFACES, /* 4 bNumInterface: Number of interfaces*/
@@ -325,7 +325,7 @@ unsigned char cfgDesc_Audio2[] =
/* Standard Audio Control Interface Descriptor (Note: Must be first with lowest interface number)r */ /* Standard Audio Control Interface Descriptor (Note: Must be first with lowest interface number)r */
0x09, /* 0 bLength: 9 */ 0x09, /* 0 bLength: 9 */
INTERFACE, /* 1 bDescriptorType: INTERFACE */ USB_INTERFACE, /* 1 bDescriptorType: INTERFACE */
0x00, /* 2 bInterfaceNumber */ 0x00, /* 2 bInterfaceNumber */
0x00, /* 3 bAlternateSetting: Must be 0 */ 0x00, /* 3 bAlternateSetting: Must be 0 */
#if defined(SPDIF_RX) || defined(ADAT_RX) #if defined(SPDIF_RX) || defined(ADAT_RX)
@@ -780,7 +780,7 @@ unsigned char cfgDesc_Audio2[] =
#ifdef OUTPUT #ifdef OUTPUT
/* Standard AS Interface Descriptor (4.9.1) */ /* Standard AS Interface Descriptor (4.9.1) */
0x09, /* 0 bLength: (in bytes, 9) */ 0x09, /* 0 bLength: (in bytes, 9) */
INTERFACE, /* 1 bDescriptorType: INTERFACE */ USB_INTERFACE, /* 1 bDescriptorType: INTERFACE */
1, /* 2 bInterfaceNumber: Number of interface */ 1, /* 2 bInterfaceNumber: Number of interface */
0, /* 3 bAlternateSetting */ 0, /* 3 bAlternateSetting */
0, /* 4 bNumEndpoints */ 0, /* 4 bNumEndpoints */
@@ -791,7 +791,7 @@ unsigned char cfgDesc_Audio2[] =
/* Standard AS Interface Descriptor (4.9.1) (Alt) */ /* Standard AS Interface Descriptor (4.9.1) (Alt) */
0x09, /* 0 bLength: (in bytes, 9) */ 0x09, /* 0 bLength: (in bytes, 9) */
INTERFACE, /* 1 bDescriptorType: INTERFACE */ USB_INTERFACE, /* 1 bDescriptorType: INTERFACE */
1, /* 2 bInterfaceNumber: Number of interface */ 1, /* 2 bInterfaceNumber: Number of interface */
1, /* 3 bAlternateSetting */ 1, /* 3 bAlternateSetting */
2, /* 4 bNumEndpoints */ 2, /* 4 bNumEndpoints */
@@ -822,7 +822,7 @@ unsigned char cfgDesc_Audio2[] =
/* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */ /* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */
0x07, /* 0 bLength: 7 */ 0x07, /* 0 bLength: 7 */
ENDPOINT, /* 1 bDescriptorType: ENDPOINT */ USB_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x01, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 0x01, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
0x05, /* 3 bmAttributes (bitmap) */ 0x05, /* 3 bmAttributes (bitmap) */
0,4, /* 4 wMaxPacketSize */ 0,4, /* 4 wMaxPacketSize */
@@ -839,7 +839,7 @@ unsigned char cfgDesc_Audio2[] =
/* Feedback EP */ /* Feedback EP */
0x07, /* 0 bLength: 7 */ 0x07, /* 0 bLength: 7 */
ENDPOINT, /* 1 bDescriptorType: ENDPOINT */ USB_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
17, /* 3 bmAttributes (bitmap) */ 17, /* 3 bmAttributes (bitmap) */
4,0, /* 4 wMaxPacketSize */ 4,0, /* 4 wMaxPacketSize */
@@ -848,7 +848,7 @@ unsigned char cfgDesc_Audio2[] =
#ifdef ADAT_TX #ifdef ADAT_TX
/* Standard AS Interface Descriptor (4.9.1) (Alt) */ /* Standard AS Interface Descriptor (4.9.1) (Alt) */
0x09, /* 0 bLength: (in bytes, 9) */ 0x09, /* 0 bLength: (in bytes, 9) */
INTERFACE, /* 1 bDescriptorType: INTERFACE */ USB_INTERFACE, /* 1 bDescriptorType: INTERFACE */
1, /* 2 bInterfaceNumber: Number of interface */ 1, /* 2 bInterfaceNumber: Number of interface */
2, /* 3 bAlternateSetting */ 2, /* 3 bAlternateSetting */
2, /* 4 bNumEndpoints */ 2, /* 4 bNumEndpoints */
@@ -879,7 +879,7 @@ unsigned char cfgDesc_Audio2[] =
/* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */ /* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */
0x07, /* 0 bLength: 7 */ 0x07, /* 0 bLength: 7 */
ENDPOINT, /* 1 bDescriptorType: ENDPOINT */ USB_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x01, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 0x01, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
0x05, /* 3 bmAttributes (bitmap) */ 0x05, /* 3 bmAttributes (bitmap) */
0,4, /* 4 wMaxPacketSize */ 0,4, /* 4 wMaxPacketSize */
@@ -896,7 +896,7 @@ unsigned char cfgDesc_Audio2[] =
/* Feedback EP */ /* Feedback EP */
0x07, /* 0 bLength: 7 */ 0x07, /* 0 bLength: 7 */
ENDPOINT, /* 1 bDescriptorType: ENDPOINT */ USB_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
17, /* 3 bmAttributes (bitmap) */ 17, /* 3 bmAttributes (bitmap) */
4,0, /* 4 wMaxPacketSize */ 4,0, /* 4 wMaxPacketSize */
@@ -908,7 +908,7 @@ unsigned char cfgDesc_Audio2[] =
#ifdef INPUT #ifdef INPUT
/* Standard AS Interface Descriptor (4.9.1) */ /* Standard AS Interface Descriptor (4.9.1) */
0x09, /* 0 bLength: (in bytes, 9) */ 0x09, /* 0 bLength: (in bytes, 9) */
INTERFACE, /* 1 bDescriptorType: INTERFACE */ USB_INTERFACE, /* 1 bDescriptorType: INTERFACE */
(OUTPUT_INTERFACES + 1), /* 2 bInterfaceNumber: Number of interface */ (OUTPUT_INTERFACES + 1), /* 2 bInterfaceNumber: Number of interface */
0, /* 3 bAlternateSetting */ 0, /* 3 bAlternateSetting */
0, /* 4 bNumEndpoints */ 0, /* 4 bNumEndpoints */
@@ -919,7 +919,7 @@ unsigned char cfgDesc_Audio2[] =
/* Standard AS Interface Descriptor (4.9.1) (Alt) */ /* Standard AS Interface Descriptor (4.9.1) (Alt) */
0x09, /* 0 bLength: (in bytes, 9) */ 0x09, /* 0 bLength: (in bytes, 9) */
INTERFACE, /* 1 bDescriptorType: INTERFACE */ USB_INTERFACE, /* 1 bDescriptorType: INTERFACE */
(OUTPUT_INTERFACES + 1), /* 2 bInterfaceNumber: Number of interface */ (OUTPUT_INTERFACES + 1), /* 2 bInterfaceNumber: Number of interface */
1, /* 3 bAlternateSetting */ 1, /* 3 bAlternateSetting */
1, /* 4 bNumEndpoints */ 1, /* 4 bNumEndpoints */
@@ -950,7 +950,7 @@ unsigned char cfgDesc_Audio2[] =
/* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */ /* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */
0x07, /* 0 bLength: 7 */ 0x07, /* 0 bLength: 7 */
ENDPOINT, /* 1 bDescriptorType: ENDPOINT */ USB_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x82, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 0x82, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
5, /* 3 bmAttributes (bitmap) */ 5, /* 3 bmAttributes (bitmap) */
0,4, /* 4 wMaxPacketSize */ 0,4, /* 4 wMaxPacketSize */
@@ -968,7 +968,7 @@ unsigned char cfgDesc_Audio2[] =
#ifdef ADAT_RX #ifdef ADAT_RX
/* Standard AS Interface Descriptor (4.9.1) (Alt) */ /* Standard AS Interface Descriptor (4.9.1) (Alt) */
0x09, /* 0 bLength: (in bytes, 9) */ 0x09, /* 0 bLength: (in bytes, 9) */
INTERFACE, /* 1 bDescriptorType: INTERFACE */ USB_INTERFACE, /* 1 bDescriptorType: INTERFACE */
(OUTPUT_INTERFACES + 1), /* 2 bInterfaceNumber: Number of interface */ (OUTPUT_INTERFACES + 1), /* 2 bInterfaceNumber: Number of interface */
2, /* 3 bAlternateSetting */ 2, /* 3 bAlternateSetting */
1, /* 4 bNumEndpoints */ 1, /* 4 bNumEndpoints */
@@ -999,7 +999,7 @@ unsigned char cfgDesc_Audio2[] =
/* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */ /* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */
0x07, /* 0 bLength: 7 */ 0x07, /* 0 bLength: 7 */
ENDPOINT, /* 1 bDescriptorType: ENDPOINT */ USB_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x82, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 0x82, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
5, /* 3 bmAttributes (bitmap) */ 5, /* 3 bmAttributes (bitmap) */
0,4, /* 4 wMaxPacketSize */ 0,4, /* 4 wMaxPacketSize */
@@ -1342,10 +1342,12 @@ unsigned char cfgDesc_Audio2[] =
#define STR_INDEX_OUT_CHAN (10 + SPDIF_RX_NUM_STRS + ADAT_RX_NUM_STRS + MIDI_NUM_STRS + DFU_NUM_STRS) #define STR_INDEX_OUT_CHAN (10 + SPDIF_RX_NUM_STRS + ADAT_RX_NUM_STRS + MIDI_NUM_STRS + DFU_NUM_STRS)
#define STR_INDEX_IN_CHAN (STR_INDEX_OUT_CHAN + NUM_USB_CHAN_OUT) #define STR_INDEX_IN_CHAN (STR_INDEX_OUT_CHAN + NUM_USB_CHAN_OUT)
static unsigned char strDescs_Audio2[][40] = static unsigned char strDescs[][40] =
{ {
"Langids", /* String 0 (LangIDs) place holder */ "Langids", /* String 0 (LangIDs) place holder */
APPEND_VENDOR_STR( ), // 1 iManufacturer (at MANUFACTURER_STRING_INDEX) APPEND_VENDOR_STR( ), // 1 iManufacturer (at MANUFACTURER_STRING_INDEX)
/* Audio 2.0 Strings */
APPEND_VENDOR_STR(USB Audio 2.0), // 2 iProduct and iInterface for control interface (at PRODUCT_STR_INDEX) APPEND_VENDOR_STR(USB Audio 2.0), // 2 iProduct and iInterface for control interface (at PRODUCT_STR_INDEX)
"",//SERIAL_STR, // 3 iSerialNumber (at SERIAL_STR_INDEX) "",//SERIAL_STR, // 3 iSerialNumber (at SERIAL_STR_INDEX)
APPEND_VENDOR_STR(USB 2.0 Audio Out), // 4 iInterface for Streaming interaces APPEND_VENDOR_STR(USB 2.0 Audio Out), // 4 iInterface for Streaming interaces
@@ -1354,8 +1356,15 @@ static unsigned char strDescs_Audio2[][40] =
APPEND_VENDOR_STR(Audio 2.0 Output), // 6 "USB Input Terminal" (User sees as output from host) APPEND_VENDOR_STR(Audio 2.0 Output), // 6 "USB Input Terminal" (User sees as output from host)
APPEND_VENDOR_STR(Audio 2.0 Input), // 7 "USB Output Terminal" (User sees as input to host) APPEND_VENDOR_STR(Audio 2.0 Input), // 7 "USB Output Terminal" (User sees as input to host)
APPEND_VENDOR_STR(Clock Selector), // 8 iClockSel /* Audio 1.0 Strings */
APPEND_VENDOR_STR(Internal Clock), // 9 iClockSource APPEND_VENDOR_STR(USB Audio 1.0), // 8 iProduct and iInterface for control interface
APPEND_VENDOR_STR(USB 1.0 Audio Out), // 9 iInterface for Streaming interaces
APPEND_VENDOR_STR(USB 1.0 Audio In), // 10
APPEND_VENDOR_STR(Audio 1.0 Output), // 11 "USB Input Terminal" (User sees as output from host)
APPEND_VENDOR_STR(Audio 1.0 Input), // 12 "USB Output Terminal" (User sees as input to host)
APPEND_VENDOR_STR(Clock Selector), // 13 iClockSel
APPEND_VENDOR_STR(Internal Clock), // 14 iClockSource
#ifdef SPDIF_RX #ifdef SPDIF_RX
APPEND_VENDOR_STR(S/PDIF Clock), // iClockSource APPEND_VENDOR_STR(S/PDIF Clock), // iClockSource
#endif #endif
@@ -1526,7 +1535,7 @@ static unsigned char strDescs_Audio2[][40] =
unsigned char cfgDesc_Null[] = unsigned char cfgDesc_Null[] =
{ {
0x09, /* 0 bLength */ 0x09, /* 0 bLength */
CONFIGURATION, /* 1 bDescriptorType */ USB_CONFIGURATION, /* 1 bDescriptorType */
0x12, /* 2 wTotalLength */ 0x12, /* 2 wTotalLength */
0x00, /* 3 wTotalLength */ 0x00, /* 3 wTotalLength */
0x01, /* 4 bNumInterface: Number of interfaces*/ 0x01, /* 4 bNumInterface: Number of interfaces*/
@@ -1589,8 +1598,9 @@ unsigned char oSpeedCfgDesc[] =
#ifdef AUDIO_CLASS_FALLBACK #ifdef AUDIO_CLASS_FALLBACK
unsigned char cfgDesc_Audio1[] = unsigned char cfgDesc_Audio1[] =
{ {
/* Configuration descriptor */ 0x09, /* Configuration descriptor */
CONFIGURATION, 0x09,
USB_CONFIGURATION,
(CFG_TOTAL_LENGTH_A1 & 0xFF), /* wTotalLength */ (CFG_TOTAL_LENGTH_A1 & 0xFF), /* wTotalLength */
(CFG_TOTAL_LENGTH_A1 >> 8), /* wTotalLength */ (CFG_TOTAL_LENGTH_A1 >> 8), /* wTotalLength */
NUM_INTERFACES_A1, /* numInterfaces - we dont support MIDI in audio 1.0 mode*/ NUM_INTERFACES_A1, /* numInterfaces - we dont support MIDI in audio 1.0 mode*/
@@ -1606,14 +1616,14 @@ unsigned char cfgDesc_Audio1[] =
/* Standard AC interface descriptor */ /* Standard AC interface descriptor */
0x09, 0x09,
INTERFACE, USB_INTERFACE,
0x00, /* Interface No */ 0x00, /* Interface No */
0x00, /* Alternate setting*/ 0x00, /* Alternate setting*/
0x00, /* Num endpoints */ 0x00, /* Num endpoints */
AUDIO, AUDIO,
AUDIOCONTROL, AUDIOCONTROL,
0x00, /* Unused */ 0x00, /* Unused */
PRODUCT_STR_INDEX, /* iInterface - re-use iProduct */ 8, /* iInterface - re-use iProduct */
/* CS (Class Specific) AudioControl interface header descriptor (4.3.2) */ /* CS (Class Specific) AudioControl interface header descriptor (4.3.2) */
AC_LENGTH, AC_LENGTH,
@@ -1641,7 +1651,7 @@ unsigned char cfgDesc_Audio1[] =
2, /* bNrChannels */ 2, /* bNrChannels */
0x03, 0x00, /* wChannelConfig */ 0x03, 0x00, /* wChannelConfig */
0x00, /* iChannelNames - Unused */ 0x00, /* iChannelNames - Unused */
0x06, /* iTerminal */ 11, /* iTerminal */
/* CS_Interface class specific AC interface feature unit descriptor - mute & volume for dac */ /* CS_Interface class specific AC interface feature unit descriptor - mute & volume for dac */
0x0A, 0x0A,
@@ -1678,7 +1688,7 @@ unsigned char cfgDesc_Audio1[] =
2, /* bNrChannels */ 2, /* bNrChannels */
0x03, 0x00, /* wChannelConfigs */ 0x03, 0x00, /* wChannelConfigs */
0x00, /* iChannelNames */ 0x00, /* iChannelNames */
0x07, /* iTerminal */ 12, /* iTerminal */
/* CS_Interface Output Terminal Descriptor - USB Streaming Device to Host*/ /* CS_Interface Output Terminal Descriptor - USB Streaming Device to Host*/
0x09, 0x09,
@@ -1713,7 +1723,7 @@ unsigned char cfgDesc_Audio1[] =
0x01, /* bInterfaceClass - AUDIO */ 0x01, /* bInterfaceClass - AUDIO */
0x02, /* bInterfaceSubclass - AUDIO_STREAMING */ 0x02, /* bInterfaceSubclass - AUDIO_STREAMING */
0x00, /* bInterfaceProtocol - Not used */ 0x00, /* bInterfaceProtocol - Not used */
0x04, /* iInterface */ 0x09, /* iInterface */
/* Standard As Interface Descriptor (4.5.1) */ /* Standard As Interface Descriptor (4.5.1) */
0x09, 0x09,
@@ -1807,7 +1817,7 @@ unsigned char cfgDesc_Audio1[] =
0x01, /* Interface class - AUDIO */ 0x01, /* Interface class - AUDIO */
0x02, /* Subclass - AUDIO_STREAMING */ 0x02, /* Subclass - AUDIO_STREAMING */
0x00, /* Unused */ 0x00, /* Unused */
0x05, /* String table index */ 0x0A, /* String table index */
/* CS_Interface AC interface header descriptor */ /* CS_Interface AC interface header descriptor */
0x07, 0x07,
@@ -1900,7 +1910,7 @@ unsigned char cfgDesc_Audio1[] =
#endif #endif
#define APPEND_VENDOR_STR(x) VENDOR_STR#x #define APPEND_VENDOR_STR(x) VENDOR_STR#x
#if 0
static unsigned char strDescs_Audio1[][40] = static unsigned char strDescs_Audio1[][40] =
{ {
"Langids", /* String 0 (LangIDs) place holder */ "Langids", /* String 0 (LangIDs) place holder */
@@ -1916,5 +1926,5 @@ static unsigned char strDescs_Audio1[][40] =
APPEND_VENDOR_STR(DFU) // 8 iInterface for DFU interface APPEND_VENDOR_STR(DFU) // 8 iInterface for DFU interface
}; };
#endif
#endif #endif

View File

@@ -13,10 +13,11 @@
#include "usbaudio20.h" /* Defines from USB Audio 2.0 spec */ #include "usbaudio20.h" /* Defines from USB Audio 2.0 spec */
#include "devicedefines.h" #include "devicedefines.h"
#include "DescriptorRequests.h" /* Standard descriptor requests */ #include "usb_device.h" /* Standard descriptor requests */
#include "descriptors_2.h" /* This devices descriptors */ #include "descriptors_2.h" /* This devices descriptors */
#include "clockcmds.h" #include "clockcmds.h"
#include "audiostream.h" #include "audiostream.h"
#include "hostactive.h"
#include "vendorrequests.h" #include "vendorrequests.h"
#include "dfu_types.h" #include "dfu_types.h"
#include "xc_ptr.h" #include "xc_ptr.h"
@@ -50,8 +51,9 @@ extern void device_reboot(chanend);
#endif #endif
/* Handles Audio Class requests */ /* Handles Audio Class requests */
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, SetupPacket &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl); int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl);
int AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, SetupPacket &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl); int AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl);
int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl);
/* Global var for current frequency, set to default freq */ /* Global var for current frequency, set to default freq */
unsigned int g_curSamFreq = DEFAULT_FREQ; unsigned int g_curSamFreq = DEFAULT_FREQ;
@@ -84,50 +86,21 @@ unsigned char mixSel[MIX_INPUTS];
int min(int x, int y); int min(int x, int y);
/* Records alt setting for each interface */
int interfaceAlt[NUM_INTERFACES];
/* Global current device config var*/ /* Global current device config var*/
unsigned g_config = 0; extern unsigned char g_currentConfig;
/* Global endpoint status arrays */ /* Global endpoint status arrays - declared in usb_device.xc */
unsigned g_epStatusOut[EP_CNT_OUT]; extern unsigned char g_interfaceAlt[];
unsigned g_epStatusIn[EP_CNT_IN];
/* Global variable for current USB bus speed (i.e. FS/HS) */ /* Global variable for current USB bus speed (i.e. FS/HS) */
unsigned g_curUsbSpeed = 0; unsigned g_curUsbSpeed = 0;
#ifdef HOST_ACTIVE_CALL
void VendorHostActive(int active);
#endif
/* Global used for signalling reset to decouple */ /* Global used for signalling reset to decouple */
#ifdef IAP #ifdef IAP
extern unsigned g_iap_reset; extern unsigned g_iap_reset;
#endif #endif
/* Used when setting/clearing EP halt */
void SetEndpointStatus(unsigned epNum, unsigned status)
{
/* Inspect for IN bit */
if( epNum & 0x80 )
{
epNum &= 0x7f;
/* Range check */
if(epNum < EP_CNT_IN)
{
g_epStatusIn[ epNum & 0x7F ] = status;
}
}
else
{
if(epNum < EP_CNT_OUT)
{
g_epStatusOut[ epNum ] = status;
}
}
}
#define STR_USENG 0x0409 #define STR_USENG 0x0409
@@ -148,16 +121,9 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
chanend ?c_mix_ctl, chanend ?c_clk_ctl, chanend ?c_usb_test) chanend ?c_mix_ctl, chanend ?c_clk_ctl, chanend ?c_usb_test)
{ {
unsigned char buffer[2]; unsigned char buffer[2];
SetupPacket sp; USB_SetupPacket_t sp;
XUD_ep ep0_out = XUD_Init_Ep(c_ep0_out); XUD_ep ep0_out = XUD_InitEp(c_ep0_out);
XUD_ep ep0_in = XUD_Init_Ep(c_ep0_in); XUD_ep ep0_in = XUD_InitEp(c_ep0_in);
/* Init endpoint status tables */
for (int i = 0; i++; i < EP_CNT_OUT)
g_epStatusOut[i] = 0;
for (int i = 0; i++; i < EP_CNT_IN)
g_epStatusIn[i] = 0;
/* Init tables for volumes (+ 1 for master) */ /* Init tables for volumes (+ 1 for master) */
for(int i = 0; i < NUM_USB_CHAN_OUT + 1; i++) for(int i = 0; i < NUM_USB_CHAN_OUT + 1; i++)
@@ -227,40 +193,40 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
/* Copy langIDs string desc into string[0] */ /* Copy langIDs string desc into string[0] */
/* TODO: Macro? */ /* TODO: Macro? */
#if defined(AUDIO_CLASS_FALLBACK) || (AUDIO_CLASS == 1) #if defined(AUDIO_CLASS_FALLBACK) || (AUDIO_CLASS == 1)
safememcpy(strDescs_Audio1[0], strDesc_langIDs, sizeof(strDesc_langIDs)); //safememcpy(strDescs_Audio1[0], strDesc_langIDs, sizeof(strDesc_langIDs));
#endif #endif
safememcpy(strDescs_Audio2[0], strDesc_langIDs, sizeof(strDesc_langIDs)); safememcpy(strDescs[0], strDesc_langIDs, sizeof(strDesc_langIDs));
/* Build up channel string table - By default all channels are marked as analogue /* Build up channel string table - By default all channels are marked as analogue
* TODO We really want to do this an build time... */ * TODO We really want to do this an build time... */
#if defined(SPDIF_RX) && (SPDIF_RX_INDEX != 0) #if defined(SPDIF_RX) && (SPDIF_RX_INDEX != 0)
safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + STR_INDEX_IN_CHAN], "S/PDIF 1"); safestrcpy(strDescs[SPDIF_RX_INDEX + STR_INDEX_IN_CHAN], "S/PDIF 1");
safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + STR_INDEX_IN_CHAN + 1], "S/PDIF 2"); safestrcpy(strDescs[SPDIF_RX_INDEX + STR_INDEX_IN_CHAN + 1], "S/PDIF 2");
#endif #endif
#if defined(ADAT_RX) && (ADAT_RX_INDEX != 0) #if defined(ADAT_RX) && (ADAT_RX_INDEX != 0)
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN], "ADAT 1"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN], "ADAT 1");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 1], "ADAT 2"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 1], "ADAT 2");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 2], "ADAT 3"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 2], "ADAT 3");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 3], "ADAT 4"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 3], "ADAT 4");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 4], "ADAT 5"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 4], "ADAT 5");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 5], "ADAT 6"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 5], "ADAT 6");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 6], "ADAT 7"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 6], "ADAT 7");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 7], "ADAT 8"); safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 7], "ADAT 8");
#endif #endif
#if defined(SPDIF) && (SPDIF_TX_INDEX != 0) /* "Analogue naming gets priority */ #if defined(SPDIF) && (SPDIF_TX_INDEX != 0) /* "Analogue naming gets priority */
safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + STR_INDEX_OUT_CHAN], "S/PDIF 1"); safestrcpy(strDescs[SPDIF_TX_INDEX + STR_INDEX_OUT_CHAN], "S/PDIF 1");
safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + STR_INDEX_OUT_CHAN + 1], "S/PDIF 2"); safestrcpy(strDescs[SPDIF_TX_INDEX + STR_INDEX_OUT_CHAN + 1], "S/PDIF 2");
#endif #endif
#if defined(ADAT_TX) && (ADAT_TX_INDEX != 0) #if defined(ADAT_TX) && (ADAT_TX_INDEX != 0)
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN], "ADAT 1"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN], "ADAT 1");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 1], "ADAT 2"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 1], "ADAT 2");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 2], "ADAT 3"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 2], "ADAT 3");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 3], "ADAT 4"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 3], "ADAT 4");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 4], "ADAT 5"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 4], "ADAT 5");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 5], "ADAT 6"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 5], "ADAT 6");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 6], "ADAT 7"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 6], "ADAT 7");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 7], "ADAT 8"); safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 7], "ADAT 8");
#endif #endif
#ifdef VENDOR_AUDIO_REQS #ifdef VENDOR_AUDIO_REQS
@@ -282,182 +248,53 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
while(1) while(1)
{ {
int retVal = 1; /* Returns 0 for success, -1 for bus reset */
int retVal = USB_GetSetupPacket(ep0_out, ep0_in, sp);
/* Do standard enumeration requests */ if (!retVal)
#ifndef DFU
if(g_curUsbSpeed == XUD_SPEED_HS)
{ {
retVal = 1;
#ifdef AUDIO_CLASS_FALLBACK /* Inspect Request type and Receipient and direction */
/* Return Audio 2.0 Descriptors with Audio 1.0 as fallback */ switch( (sp.bmRequestType.Direction << 7) | (sp.bmRequestType.Recipient ) | (sp.bmRequestType.Type << 5) )
cfgDesc_Audio2[1] = CONFIGURATION;
cfgDesc_Audio1[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in,
devDesc_Audio2, sizeof(devDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
devQualDesc_Audio1, sizeof(devQualDesc_Audio1),
cfgDesc_Audio1, sizeof(cfgDesc_Audio1),
strDescs_Audio2, sp, c_usb_test);
#else
/* Return Audio 2.0 Descriptors */
cfgDesc_Audio2[1] = CONFIGURATION;
cfgDesc_Null[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in,
devDesc_Audio2, sizeof(devDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
devQualDesc_Null, sizeof(devQualDesc_Null),
cfgDesc_Null, sizeof(cfgDesc_Null),
strDescs_Audio2, sp, c_usb_test);
#endif
}
else
{ {
/* Return descriptors for full-speed - Audio 1.0? */ case USB_BMREQ_H2D_STANDARD_INT:
#ifdef AUDIO_CLASS_FALLBACK
cfgDesc_Audio1[1] = CONFIGURATION;
cfgDesc_Audio2[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in, /* Over-riding USB_StandardRequests implementation */
devDesc_Audio1, sizeof(devDesc_Audio1), if(sp.bRequest == USB_SET_INTERFACE)
cfgDesc_Audio1, sizeof(cfgDesc_Audio1),
devQualDesc_Audio2, sizeof(devQualDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
strDescs_Audio1, sp, c_usb_test);
#else
cfgDesc_Null[1] = CONFIGURATION;
cfgDesc_Audio2[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in,
devDesc_Null, sizeof(devDesc_Null),
cfgDesc_Null, sizeof(cfgDesc_Null),
devQualDesc_Audio2, sizeof(devQualDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
strDescs_Audio2, sp, c_usb_test);
#endif
}
#else /* ifndef DFU */
if (!DFU_mode_active)
{ {
if(g_curUsbSpeed == XUD_SPEED_HS)
{
#ifdef AUDIO_CLASS_FALLBACK
/* Return Audio 2.0 Descriptors with Audio 1.0 as fallback */
cfgDesc_Audio2[1] = CONFIGURATION;
cfgDesc_Audio1[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in,
devDesc_Audio2, sizeof(devDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
devQualDesc_Audio1, sizeof(devQualDesc_Audio1),
cfgDesc_Audio1, sizeof(cfgDesc_Audio1),
strDescs_Audio2, sp, c_usb_test);
#else
/* Return Audio 2.0 Descriptors with Null device as fallback */
cfgDesc_Audio2[1] = CONFIGURATION;
cfgDesc_Null[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in,
devDesc_Audio2, sizeof(devDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
devQualDesc_Null, sizeof(devQualDesc_Null),
cfgDesc_Null, sizeof(cfgDesc_Null),
strDescs_Audio2, sp, c_usb_test);
#endif
}
else
{
/* Return descriptors for full-speed - Audio 1.0? */
#ifdef AUDIO_CLASS_FALLBACK
cfgDesc_Audio1[1] = CONFIGURATION;
cfgDesc_Audio2[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in,
devDesc_Audio1, sizeof(devDesc_Audio1),
cfgDesc_Audio1, sizeof(cfgDesc_Audio1),
devQualDesc_Audio2, sizeof(devQualDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
strDescs_Audio1, sp, c_usb_test);
#else
cfgDesc_Null[1] = CONFIGURATION;
cfgDesc_Audio2[1] = OTHER_SPEED_CONFIGURATION;
retVal = DescriptorRequests(ep0_out, ep0_in,
devDesc_Null, sizeof(devDesc_Null),
cfgDesc_Null, sizeof(cfgDesc_Null),
devQualDesc_Audio2, sizeof(devQualDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
strDescs_Audio2, sp, c_usb_test);
#endif
}
}
else
{
/* Running in DFU mode - always return same descs for DFU whether HS or FS */
retVal = DescriptorRequests(ep0_out, ep0_in,
DFUdevDesc, sizeof(DFUdevDesc),
DFUcfgDesc, sizeof(DFUcfgDesc),
DFUdevQualDesc, sizeof(DFUdevQualDesc),
DFUoSpeedCfgDesc, sizeof(DFUoSpeedCfgDesc),
strDescs_Audio2, sp, c_usb_test);
}
#endif
if (retVal == 1)
{
/* Request not covered by XUD_DoEnumReqs() so decode ourselves */
/* Inspect Request type and Receipient */
switch( (sp.bmRequestType.Recipient ) | (sp.bmRequestType.Type << 5) )
{
case STANDARD_INTERFACE_REQUEST:
switch(sp.bRequest)
{
/* Set Interface */
case SET_INTERFACE:
#if defined(OUTPUT) && defined(INPUT) #if defined(OUTPUT) && defined(INPUT)
/* Check for stream start stop on output and input audio interfaces */ /* Check for stream start stop on output and input audio interfaces */
if(sp.wValue && !interfaceAlt[1] && !interfaceAlt[2]) if(sp.wValue && !g_interfaceAlt[1] && !g_interfaceAlt[2])
{ {
/* If start and input AND output not currently running */ /* If start and input AND output not currently running */
AudioStreamStart(); UserAudioStreamStart();
} }
else if(((sp.wIndex == 1)&& (!sp.wValue)) && interfaceAlt[1] && (!interfaceAlt[2])) else if(((sp.wIndex == 1) && (!sp.wValue)) && g_interfaceAlt[1] && (!g_interfaceAlt[2]))
{ {
/* if output stop and output running and input not running */ /* if output stop and output running and input not running */
AudioStreamStop(); UserAudioStreamStop();
} }
else if(((sp.wIndex == 2) && (!sp.wValue)) && interfaceAlt[2] && (!interfaceAlt[1])) else if(((sp.wIndex == 2) && (!sp.wValue)) && g_interfaceAlt[2] && (!g_interfaceAlt[1]))
{ {
/* if input stop and input running and output not running */ /* if input stop and input running and output not running */
AudioStreamStop(); UserAudioStreamStop();
} }
#elif defined(OUTPUT) || defined(INPUT) #elif defined(OUTPUT) || defined(INPUT)
if(sp.wValue && (!interfaceAlt[1])) if(sp.wValue && (!g_interfaceAlt[1]))
{ {
/* if start and not currently running */ /* if start and not currently running */
AudioStreamStart(); UserAudioStreamStart();
} }
else if (!sp.wValue && interfaceAlt[1]) else if (!sp.wValue && g_interfaceAlt[1])
{ {
/* if stop and currently running */ /* if stop and currently running */
AudioStreamStop(); UserAudioStreamStop();
} }
#endif #endif
/* Record interface change */ /* Record interface change */
if( sp.wIndex < NUM_INTERFACES ) if(sp.wIndex < NUM_INTERFACES)
interfaceAlt[sp.wIndex] = sp.wValue; g_interfaceAlt[sp.wIndex] = sp.wValue;
#if 1
/* Check for audio stream from host start/stop */ /* Check for audio stream from host start/stop */
if(sp.wIndex == 1) // Ouput interface if(sp.wIndex == 1) // Ouput interface
@@ -465,9 +302,7 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
switch(sp.wValue) switch(sp.wValue)
{ {
case 0: case 0:
break; break;
case 1: case 1:
/* Stream active + 0 chans */ /* Stream active + 0 chans */
/* NOTE there could be a difference between HS/UAC1 and FS/UAC1 channel count */ /* NOTE there could be a difference between HS/UAC1 and FS/UAC1 channel count */
@@ -484,16 +319,13 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
} }
break; break;
} }
} }
else if(sp.wIndex == 2) // Input interface else if(sp.wIndex == 2) // Input interface
{ {
switch(sp.wValue) switch(sp.wValue)
{ {
case 0: case 0:
break; break;
case 1: case 1:
/* Stream active + 0 chans */ /* Stream active + 0 chans */
/* NOTE there could be a difference between HS/UAC1 and FS/UAC1 channel count */ /* NOTE there could be a difference between HS/UAC1 and FS/UAC1 channel count */
@@ -513,16 +345,13 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
outuint(c_clk_ctl, 0); outuint(c_clk_ctl, 0);
outct(c_clk_ctl, XS1_CT_END); outct(c_clk_ctl, XS1_CT_END);
#endif #endif
break; break;
#ifdef ADAT_RX #ifdef ADAT_RX
case 2: case 2:
/* Stream active + 8 chans */ /* Stream active + 8 chans */
outuint(c_audioControl, SET_CHAN_COUNT_IN); outuint(c_audioControl, SET_CHAN_COUNT_IN);
outuint(c_audioControl, NUM_USB_CHAN_IN-4); outuint(c_audioControl, NUM_USB_CHAN_IN-4);
outuint(c_clk_ctl, SET_SMUX); outuint(c_clk_ctl, SET_SMUX);
outuint(c_clk_ctl, 1); outuint(c_clk_ctl, 1);
outct(c_clk_ctl, XS1_CT_END); outct(c_clk_ctl, XS1_CT_END);
@@ -531,107 +360,65 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
case 3: case 3:
outuint(c_audioControl, SET_CHAN_COUNT_IN); outuint(c_audioControl, SET_CHAN_COUNT_IN);
outuint(c_audioControl, NUM_USB_CHAN_IN-6); outuint(c_audioControl, NUM_USB_CHAN_IN-6);
outuint(c_clk_ctl, SET_SMUX); outuint(c_clk_ctl, SET_SMUX);
outuint(c_clk_ctl, 1); outuint(c_clk_ctl, 1);
outct(c_clk_ctl, XS1_CT_END); outct(c_clk_ctl, XS1_CT_END);
/* Stream active + 8 chans */
//outuint(c_audioControl, 8);
// Handshake
//chkct(c_audioControl, XS1_CT_END);
break; break;
#endif #endif
} }
} }
#endif
/* No data stage for this request, just do data stage */ /* No data stage for this request, just do data stage */
retVal = XUD_DoSetRequestStatus(ep0_in, 0); retVal = XUD_DoSetRequestStatus(ep0_in);
break; } /* if(sp.bRequest == SET_INTERFACE) */
/* A device must support the GetInterface request if it has alternate setting for that interface */ break; /* BMREQ_H2D_STANDARD_INT */
case GET_INTERFACE:
buffer[0] = 0; case USB_BMREQ_D2H_STANDARD_INT:
/* Bounds check */ switch(sp.bRequest)
if( sp.wIndex < NUM_INTERFACES ) {
buffer[0] = interfaceAlt[sp.wIndex];
retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
break;
#ifdef HID_CONTROLS #ifdef HID_CONTROLS
case GET_DESCRIPTOR: case GET_DESCRIPTOR:
/* Check what inteface request is for */
if(sp.wIndex == INTERFACE_NUM_HID) if(sp.wIndex == INTERFACE_NUM_HID)
{ {
switch (sp.wValue>>8) /* High byte of wValue is descriptor type */
unsigned descriptorType = sp.wValue & 0xff00;
switch (descriptorType)
{ {
case REPORT: case REPORT:
/* Return HID report descriptor */ /* Return HID report descriptor */
retVal = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptor, retVal = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptor,
min(sizeof(hidReportDescriptor),sp.wLength), sp.wLength); sizeof(hidReportDescriptor), sp.wLength);
break; break;
} }
} }
break; break;
#endif #endif
default: default:
//printstr("Unknown Standard Interface Request: ");
//printhexln(sp.bRequest);
//printhexln(sp.bmRequestType.Type);
//printhexln(sp.bmRequestType.Recipient);
//printhexln(sp.bmRequestType.Recipient | (sp.bmRequestType.Type << 5));
break; break;
} }
break; break;
/* Recipient: Device */ /* Recipient: Device */
case STANDARD_DEVICE_REQUEST: case USB_BMREQ_H2D_STANDARD_DEV:
/* Standard Device requests (8) */ /* Inspect for actual request */
switch( sp.bRequest ) switch( sp.bRequest )
{ {
/* Set Device Address: This is a unique set request. */
case SET_ADDRESS:
/* Status stage: Send a zero length packet */
retVal = XUD_SetBuffer(ep0_in, buffer, 0);
/* TODO We should wait until ACK is received for status stage before changing address */
//XUD_Sup_Delay(50000);
{
timer t;
unsigned time;
t :> time;
t when timerafter(time+50000) :> void;
}
/* Set device address in XUD */
XUD_SetDevAddr(sp.wValue);
break;
/* TODO Check direction */
/* Standard request: SetConfiguration */ /* Standard request: SetConfiguration */
case SET_CONFIGURATION: /* Overriding implementation in USB_StandardRequests */
case USB_SET_CONFIGURATION:
g_config = sp.wValue; g_currentConfig = sp.wValue;
//if(g_current_config == 1)
#ifdef HOST_ACTIVE_CALL
if(g_config == 1)
{ {
/* Consider host active with valid driver at this point */ /* Consider host active with valid driver at this point */
VendorHostActive(1); UserHostActive(1);
} }
#endif
#ifdef IAP #ifdef IAP
{ {
int iap_reset = 1; int iap_reset = 1;
@@ -639,132 +426,42 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
} }
#endif #endif
/* No data stage for this request, just do status stage */ /* No data stage for this request, just do status stage */
retVal = XUD_DoSetRequestStatus(ep0_in, 0); retVal = XUD_DoSetRequestStatus(ep0_in);
break; break;
case GET_CONFIGURATION: default:
buffer[0] = g_config; //Unknown device request"
retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength); break;
}
break; break;
/* Get Status request */ /* Audio Class 1.0 Sampling Freqency Requests go to Endpoint */
case GET_STATUS: case USB_BMREQ_H2D_CLASS_EP:
case USB_BMREQ_D2H_CLASS_EP:
{
unsigned epNum = sp.wIndex & 0xff;
#ifdef SELF_POWERED if ((epNum == 0x82) || (epNum == 0x01))
buffer[0] = 1; // self powered {
#else #if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK)
buffer[0] = 0; // bus powered if(g_curUsbSpeed == XUD_SPEED_FS)
{
retVal = AudioEndpointRequests_1(ep0_out, ep0_in, sp, c_audioControl, c_mix_ctl, c_clk_ctl);
}
#elif (AUDIO_CLASS==1)
retVal = AudioEndpointRequests_1(ep0_out, ep0_in, sp, c_audioControl, c_mix_ctl, c_clk_ctl);
#endif #endif
buffer[1] = 0; // remote wakeup not supported }
retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
break;
default:
XUD_Error("Unknown device request");
break;
} }
break; break;
/* Receipient: Endpoint */ case USB_BMREQ_H2D_CLASS_INT:
case STANDARD_ENDPOINT_REQUEST: case USB_BMREQ_D2H_CLASS_INT:
/* Standard endpoint requests */
switch ( sp.bRequest )
{
/* ClearFeature */
case CLEAR_FEATURE:
switch ( sp.wValue )
{
case ENDPOINT_HALT:
/* Mark the endpoint status */
SetEndpointStatus(sp.wIndex, 0);
/* No data stage for this request, just do status stage */
retVal = XUD_DoSetRequestStatus(ep0_in, 0);
break;
default:
XUD_Error( "Unknown request in Endpoint ClearFeature" );
break;
}
break; /* B_REQ_CLRFEAR */
/* SetFeature */
case SET_FEATURE:
switch( sp.wValue )
{
case ENDPOINT_HALT:
/* Check request is in range */
SetEndpointStatus(sp.wIndex, 1);
break;
default:
XUD_Error("Unknown feature in SetFeature Request");
break;
}
retVal = XUD_DoSetRequestStatus(ep0_in, 0);
break;
/* Endpoint GetStatus Request */
case GET_STATUS:
buffer[0] = 0;
buffer[1] = 0;
if( sp.wIndex & 0x80 )
{
/* IN Endpoint */
if((sp.wIndex&0x7f) < EP_CNT_IN)
{
buffer[0] = ( g_epStatusIn[ sp.wIndex & 0x7F ] & 0xff );
buffer[1] = ( g_epStatusIn[ sp.wIndex & 0x7F ] >> 8 );
}
}
else
{
/* OUT Endpoint */
if(sp.wIndex < EP_CNT_OUT)
{
buffer[0] = ( g_epStatusOut[ sp.wIndex ] & 0xff );
buffer[1] = ( g_epStatusOut[ sp.wIndex ] >> 8 );
}
}
retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
break;
default:
//printstrln("Unknown Standard Endpoint Request");
break;
}
break;
case CLASS_INTERFACE_REQUEST:
case CLASS_ENDPOINT_REQUEST:
{ {
unsigned interfaceNum = sp.wIndex & 0xff; unsigned interfaceNum = sp.wIndex & 0xff;
unsigned request = (sp.bmRequestType.Recipient ) | (sp.bmRequestType.Type << 5); //unsigned request = (sp.bmRequestType.Recipient ) | (sp.bmRequestType.Type << 5);
/* TODO Check interface number */
/* TODO Check on return value retval = */ /* TODO Check on return value retval = */
#ifdef DFU #ifdef DFU
unsigned DFU_IF = DFU_IF_NUM; unsigned DFU_IF = DFU_IF_NUM;
@@ -777,22 +474,20 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
if (interfaceNum == DFU_IF) if (interfaceNum == DFU_IF)
{ {
/* If running in application mode stop audio */ /* If running in application mode stop audio */
/* Don't interupt audio for save and restore cmds */ /* Don't interupt audio for save and restore cmds */
if ((DFU_IF == DFU_IF_NUM) && (sp.bRequest != XMOS_DFU_SAVESTATE) && (sp.bRequest != XMOS_DFU_RESTORESTATE)) if ((DFU_IF == DFU_IF_NUM) && (sp.bRequest != XMOS_DFU_SAVESTATE) &&
(sp.bRequest != XMOS_DFU_RESTORESTATE))
{ {
// Stop audio // Stop audio
outuint(c_audioControl, SET_SAMPLE_FREQ); outuint(c_audioControl, SET_SAMPLE_FREQ);
outuint(c_audioControl, AUDIO_STOP_FOR_DFU); outuint(c_audioControl, AUDIO_STOP_FOR_DFU);
// Handshake // Handshake
chkct(c_audioControl, XS1_CT_END); chkct(c_audioControl, XS1_CT_END);
} }
/* This will return 1 if reset requested */ /* This will return 1 if reset requested */
if (DFUDeviceRequests(ep0_out, ep0_in, sp, null, interfaceAlt[sp.wIndex], 1)) if (DFUDeviceRequests(ep0_out, ep0_in, sp, null, g_interfaceAlt[sp.wIndex], 1))
{ {
timer tmr; timer tmr;
unsigned s; unsigned s;
@@ -804,16 +499,13 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
/* TODO we should not make the assumption that all DFU requests are handled */ /* TODO we should not make the assumption that all DFU requests are handled */
retVal = 0; retVal = 0;
} }
/* Check for: - Audio CONTROL interface request - always 0, note we check for DFU first
* - Audio STREAMING interface request
* - Audio endpoint request
*/
else if(((request == CLASS_INTERFACE_REQUEST) && (interfaceNum == 0))
|| ((request == CLASS_INTERFACE_REQUEST) && (interfaceNum == 1 || interfaceNum == 2))
|| (request == CLASS_ENDPOINT_REQUEST && ((interfaceNum == 0x82) || (interfaceNum == 0x01))))
{
#endif #endif
/* Check for: - Audio CONTROL interface request - always 0, note we check for DFU first
* - Audio STREAMING interface request (In or Out)
* - Audio endpoint request (Audio 1.0 Sampling freq requests are sent to the endpoint)
*/
if((interfaceNum == 0) || (interfaceNum == 1) || (interfaceNum == 2))
{
#if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK) #if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK)
if(g_curUsbSpeed == XUD_SPEED_HS) if(g_curUsbSpeed == XUD_SPEED_HS)
{ {
@@ -846,36 +538,78 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
break; break;
default: default:
//printstr("unrecognised request\n");
//printhexln(sp.bRequest);
//printhexln(sp.bmRequestType.Type);
//printhexln(sp.bmRequestType.Recipient);
//printhexln(sp.bmRequestType.Recipient | (sp.bmRequestType.Type << 5));
break; break;
} }
} /* if(retVal == 0) */ } /* if(retVal == 0) */
if(retVal == 1) if(retVal > 0)
{ {
/* Did not handle request - Protocol Stall Secion 8.4.5 of USB 2.0 spec #ifndef DFU
* Detailed in Section 8.5.3. Protocol stall is unique to control pipes.
Protocol stall differs from functional stall in meaning and duration. #ifdef AUDIO_CLASS_FALLBACK
A protocol STALL is returned during the Data or Status stage of a control /* Return Audio 2.0 Descriptors with Audio 1.0 as fallback */
transfer, and the STALL condition terminates at the beginning of the retVal = USB_StandardRequests(ep0_out, ep0_in,
next control transfer (Setup). The remainder of this section refers to devDesc_Audio2, sizeof(devDesc_Audio2),
the general case of a functional stall */ cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
XUD_SetStall_Out(0); devDesc_Audio1, sizeof(devDesc_Audio1),
XUD_SetStall_In(0); cfgDesc_Audio1, sizeof(cfgDesc_Audio1),
strDescs,
sp, c_usb_test, g_curUsbSpeed);
#else
/* Return Audio 2.0 Descriptors */
cfgDesc_Audio2[1] = CONFIGURATION;
cfgDesc_Null[1] = OTHER_SPEED_CONFIGURATION;
retVal = USB_StandardRequests(ep0_out, ep0_in,
devDesc_Audio2, sizeof(devDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
devDesc_Null, sizeof(devDesc_Null),
cfgDesc_Null, sizeof(cfgDesc_Null),
strDescs,
sp, c_usb_test, g_curUsbSpeed);
#endif
#else /* ifndef DFU */
if (!DFU_mode_active)
{
#ifdef AUDIO_CLASS_FALLBACK
/* Return Audio 2.0 Descriptors with Audio 1.0 as fallback */
retVal = USB_StandardRequests(ep0_out, ep0_in,
devDesc_Audio2, sizeof(devDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
devDesc_Audio1, sizeof(devDesc_Audio1),
cfgDesc_Audio1, sizeof(cfgDesc_Audio1),
strDescs, sp, c_usb_test, g_curUsbSpeed);
#else
/* Return Audio 2.0 Descriptors with Null device as fallback */
retVal = USB_StandardRequests(ep0_out, ep0_in,
devDesc_Audio2, sizeof(devDesc_Audio2),
cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
devDesc_Null, sizeof(devDesc_Null),
cfgDesc_Null, sizeof(cfgDesc_Null),
strDescs, sp, c_usb_test, g_curUsbSpeed);
#endif
}
else
{
/* Running in DFU mode - always return same descs for DFU whether HS or FS */
retVal = USB_StandardRequests(ep0_out, ep0_in,
DFUdevDesc, sizeof(DFUdevDesc),
DFUcfgDesc, sizeof(DFUcfgDesc),
null, 0, /* Used same descriptors for full and high-speed */
null, 0,
strDescs, sp, c_usb_test, g_curUsbSpeed);
}
#endif /* ifndef DFU else */
} }
if (retVal < 0) if (retVal < 0)
{ {
g_curUsbSpeed = XUD_ResetEndpoint(ep0_out, ep0_in); g_curUsbSpeed = XUD_ResetEndpoint(ep0_out, ep0_in);
g_config = 0; g_currentConfig = 0;
#ifdef DFU #ifdef DFU
if (DFUReportResetState(null)) if (DFUReportResetState(null))
@@ -900,9 +634,6 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
DFU_mode_active = 0; DFU_mode_active = 0;
// Send reboot command // Send reboot command
//outuint(c_audioControl, SET_SAMPLE_FREQ);
//outuint(c_audioControl, AUDIO_REBOOT_FROM_DFU);
// No handshake on reboot
tmr :> s; tmr :> s;
tmr when timerafter(s + 5000000) :> s; tmr when timerafter(s + 5000000) :> s;
device_reboot(c_audioControl); device_reboot(c_audioControl);

View File

@@ -2,12 +2,6 @@
#include <xs1.h> #include <xs1.h>
#include <print.h> #include <print.h>
//In this file xud.h is not included since we are interpreting the
//assembly functions GetData/SetData as taking xc_ptrs
//#include "xud.h"
#define XUD_SPEED_HS 2
#include "usb.h" #include "usb.h"
#include "devicedefines.h" #include "devicedefines.h"
#include "usb_midi.h" #include "usb_midi.h"
@@ -98,24 +92,24 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
#endif #endif
) )
{ {
XUD_ep ep_aud_out = XUD_Init_Ep(c_aud_out); XUD_ep ep_aud_out = XUD_InitEp(c_aud_out);
XUD_ep ep_aud_in = XUD_Init_Ep(c_aud_in); XUD_ep ep_aud_in = XUD_InitEp(c_aud_in);
XUD_ep ep_aud_fb = XUD_Init_Ep(c_aud_fb); XUD_ep ep_aud_fb = XUD_InitEp(c_aud_fb);
#ifdef MIDI #ifdef MIDI
XUD_ep ep_midi_from_host = XUD_Init_Ep(c_midi_from_host); XUD_ep ep_midi_from_host = XUD_InitEp(c_midi_from_host);
XUD_ep ep_midi_to_host = XUD_Init_Ep(c_midi_to_host); XUD_ep ep_midi_to_host = XUD_InitEp(c_midi_to_host);
#endif #endif
#ifdef IAP #ifdef IAP
XUD_ep ep_iap_from_host = XUD_Init_Ep(c_iap_from_host); XUD_ep ep_iap_from_host = XUD_InitEp(c_iap_from_host);
XUD_ep ep_iap_to_host = XUD_Init_Ep(c_iap_to_host); XUD_ep ep_iap_to_host = XUD_InitEp(c_iap_to_host);
XUD_ep ep_iap_to_host_int = XUD_Init_Ep(c_iap_to_host_int); XUD_ep ep_iap_to_host_int = XUD_InitEp(c_iap_to_host_int);
#endif #endif
#if defined(SPDIF_RX) || defined(ADAT_RX) #if defined(SPDIF_RX) || defined(ADAT_RX)
XUD_ep ep_int = XUD_Init_Ep(c_int); XUD_ep ep_int = XUD_InitEp(c_int);
#endif #endif
#ifdef HID_CONTROLS #ifdef HID_CONTROLS
XUD_ep ep_hid = XUD_Init_Ep(c_hid); XUD_ep ep_hid = XUD_InitEp(c_hid);
#endif #endif
@@ -699,7 +693,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
else else
{ {
// Too many events from device - drop // Too many events from device - drop
printstr("DROP"); //printstr("DROP");
} }
/* Once we have the whole message, sent it to host */ /* Once we have the whole message, sent it to host */

View File

@@ -1,23 +1,22 @@
#include "devicedefines.h" #include "devicedefines.h"
#include "hostactive.h"
#ifdef HOST_ACTIVE_CALL #include "audiostream.h"
void VendorHostActive(int valid);
void XUD_UserSuspend(void) void XUD_UserSuspend(void)
{ {
VendorHostActive(0); UserAudioStreamStop();
UserHostActive(0);
} }
void XUD_UserResume(void) void XUD_UserResume(void)
{ {
unsigned config; unsigned config;
asm("ldw %0, dp[g_config]" : "=r" (config):); asm("ldw %0, dp[g_currentConfig]" : "=r" (config):);
if(config == 1) if(config == 1)
{ {
VendorHostActive(1); UserHostActive(1);
} }
} }
#endif