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[] = {
/* Standard USB device descriptor */
0x09, /* 0 bLength */
CONFIGURATION, /* 1 bDescriptorType */
USB_CONFIGURATION, /* 1 bDescriptorType */
0x1b, /* 2 wTotalLength */
0x00, /* 3 wTotalLength */
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 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;
}
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 data_buffer_len = 0;
unsigned int data_buffer[17];
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
if (sp.wLength)
@@ -465,7 +465,7 @@ int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend
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
#ifdef ARCH_G
@@ -477,9 +477,9 @@ int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend
else
{
#ifdef ARCH_G
XUD_DoSetRequestStatus(ep0_out, 0);
XUD_DoSetRequestStatus(ep0_out);
#else
XUD_DoSetRequestStatus(ep0_in, 0);
XUD_DoSetRequestStatus(ep0_in);
#endif
}

View File

@@ -14,12 +14,14 @@
#include <print.h>
#include <xs1_su.h>
#include "clocking.h"
#include "audioports.h"
#include "codec.h"
#include "audiohw.h"
#include "devicedefines.h"
#include "SpdifTransmit.h"
//#define DSD_OUTPUT 1
unsigned g_adcVal = 0;
//#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 "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*/
#if (I2S_CHANS_DAC != 0)
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;
#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 */
extern port p_mclk;
#ifdef SPDIF
extern buffered out port:32 p_spdif_tx;
extern clock clk_mst_spd;
#endif
extern clock clk_audio_mclk;
extern clock clk_audio_bclk;
extern clock clk_mst_spd;
extern void device_reboot(void);
/* I2S delivery thread */
#pragma unsafe arrays
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 deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_dig_rx, chanend ?c_adc)
{
unsigned sample;
#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;
#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
@@ -218,7 +223,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_
#endif
p_lrclk <: 0x7FFFFFFF;
p_bclk <: 0xAAAAAAAA;
p_bclk <: 0xAAAAAAAA;//32clks
p_bclk <: 0xAAAAAAAA;
}
#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]));
#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)
/* Request digital data (with prefill) */
outuint(c_dig_rx, 0);
#endif
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"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
#pragma loop unroll
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
#if defined(SPDIF) && (NUM_USB_CHAN_OUT > 0)
if(!dop)
{ outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to SPDIF txt thread */
#if defined(SPDIF) && (NUM_USB_CHAN_OUT > 0)
outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to SPDIF txt thread */
sample = samplesOut[SPDIF_TX_INDEX + 1];
outuint(c_spd_out, sample); /* Forward sample to SPDIF txt thread */
}
#ifdef RAMP_CHECK
sample >>= 8;
if (started<10000) {
@@ -462,7 +509,6 @@ if(!dop)
#endif
#endif
tmp = 0;
#pragma xta endpoint "i2s_output_r"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
@@ -513,8 +559,6 @@ if(!dop)
#endif
#if (I2S_CHANS_ADC != 0)
/* Input previous L ADC sample */
index = 0;
@@ -538,6 +582,48 @@ if(!dop)
}
#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;
}
@@ -601,12 +687,10 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
chan c_spdif_out;
#endif
unsigned curSamFreq = DEFAULT_FREQ;
unsigned retVal;
unsigned mClk;
unsigned divide;
unsigned firstRun = 1;
#ifdef DSD_OVER_PCM
unsigned dop = 0;
#endif
#ifdef SU1_ADC_ENABLE
/* Setup galaxian ADC */
@@ -646,17 +730,13 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
#endif
/* Initialise master clock generation */
ClockingInit(c_config);
//ClockingInit(c_config);
/* Perform required CODEC/ADC/DAC initialisation */
CodecInit(c_config);
AudioHwInit(c_config);
while(1)
{
if(curSamFreq)
{
/* Calculate what master clock we should be using */
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 );
/* 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)
{
/* TODO wait for good mclk instead of delay */
/* 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;
unsigned time;
@@ -690,68 +776,46 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c)
}
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
{
#ifdef SPDIF
{
if(!dop)
{
set_thread_fast_mode_on();
SpdifTransmit(p_spdif_tx, c_spdif_out);
}
}
#endif
{
#ifdef SPDIF
if(!dop)
{
/* Communicate master clock and sample freq to S/PDIF thread */
outuint(c_spdif_out, curSamFreq);
outuint(c_spdif_out, mClk);
}
#endif
curSamFreq = deliver(c_mix_out,
retVal = deliver(c_mix_out,
#ifdef SPDIF
c_spdif_out,
#else
null,
#endif
divide, c_dig_rx, c
#ifdef DSD_OVER_PCM
, dop
divide, c_dig_rx, c);
#ifdef DSD_OUTPUT
if(retVal == 0)
{
// Check DSD mode here..
}
else
{
curSamFreq = retVal;
}
#else
curSamFreq = retVal;
#endif
);
// Currently no more audio will happen after this point
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
/* Notify S/PDIF thread of impending new freq... */
if(!dop)
outct(c_spdif_out, XS1_CT_END);
#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 */
void AudioStreamStart(void);
void UserAudioStreamStart(void);
/* Any actions required on stream stop e.g. DAC mute - run every steam stop */
void AudioStreamStop(void);
void UserAudioStreamStop(void);
#endif

View File

@@ -2,15 +2,6 @@
#ifndef _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.
*
* \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.
* @author Ross Owen, XMOS Limited
*/

View File

@@ -7,6 +7,7 @@
#include "xud.h"
#include "usb.h"
#include "usbaudio20.h"
#include "usbaudio10.h"
#include "dbcalc.h"
#include "devicedefines.h"
#include "clockcmds.h"
@@ -185,7 +186,8 @@ void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
{
switch( unitID )
{
case FU_USBOUT: {
case FU_USBOUT:
{
/* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */
/* 0x8000 is a special value representing -inf (i.e. mute) */
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
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, channel-1);
outuint(c_mix_ctl, x);
outct(c_mix_ctl, XS1_CT_END);
}
#else
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multOut),"r"(channel-1));
#endif
break;
}
case FU_USBIN: {
case FU_USBIN:
{
/* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */
/* 0x8000 is a special value representing -inf (i.e. mute) */
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];
#ifdef IN_VOLUME_IN_MIXER
if (!isnull(c_mix_ctl)) {
//master {
// c_mix_ctl <: SET_MIX_IN_VOL;
// c_mix_ctl <: channel-1;
// c_mix_ctl <: x;
//}
if (!isnull(c_mix_ctl))
{
outuint(c_mix_ctl, SET_MIX_IN_VOL);
outuint(c_mix_ctl, channel-1);
outuint(c_mix_ctl, x);
outct(c_mix_ctl, XS1_CT_END);
}
#else
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multIn),"r"(channel-1));
#endif
break;
}
default:
/* Don't hit - We hope */
//"Vol: No such unit: unitID;
break;
}
}
}
/* Handles the audio class specific requests
* returns: 0 if request delt with successfully without error,
* <0 for device reset suspend
* returns: 0 if request dealt with successfully without error,
* <0 for device reset
* 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
@@ -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:
{
/* 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*/
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)
{
/* Re-construct Sample Freq */
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 */
return XUD_SetBuffer(ep0_in, buffer, 0);
XUD_DoSetRequestStatus(ep0_in);
}
/* Direction: Device-to-host: Send Current Sample Freq */
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_ADAT:
#ifdef REPORT_SPDIF_FREQ
/* Interogate clockgen thread for SPDIF freq */
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, CLOCK_SPDIF_INDEX);
outct(c_clk_ctl, XS1_CT_END);
(buffer, unsigned[])[0] = inuint(c_clk_ctl);
chkct(c_clk_ctl, XS1_CT_END);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 4, sp.wLength );
}
else
{
(buffer, unsigned[])[0] = g_curSamFreq;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 4, sp.wLength );
}
break;
#endif
case ID_CLKSRC_INT:
/* Always report our current operating frequency */
(buffer, unsigned[])[0] = g_curSamFreq;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 4, sp.wLength );
break;
default:
// XUD_Error_hex("Unknown Unit ID in Sample Frequency Control Request", unitID);
/* Unknown Unit ID in Sample Frequency Control Request: unitID */
break;
}
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength );
}
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 */
buffer[0] = 1;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
break;
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);
buffer[0] = inuint(c_clk_ctl);
chkct(c_clk_ctl, XS1_CT_END);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
}
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);
buffer[0] = inuint(c_clk_ctl);
chkct(c_clk_ctl, XS1_CT_END);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
}
break;
default:
//XUD_Error_hex("Unknown Unit ID in Clock Valid Control Request: ", unitID);
//Unknown Unit ID in Clock Valid Control Request
break;
}
return XUD_DoGetRequest( ep0_out, ep0_in, buffer, sp.wLength, sp.wLength );
break;
}
default:
//XUD_Error_hex("Unknown Control Selector for Clock Unit: ", sp.wValue >> 8 );
//Unknown Control Selector for Clock Unit: sp.wValue >> 8
break;
}
@@ -449,10 +425,10 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
case ID_CLKSEL:
{
if ((sp.wValue >> 8) == CX_CLOCK_SELECTOR_CONTROL)
{
if( sp.bmRequestType.Direction == 0 )
{
/* Direction: Host-to-device */
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D )
{
datalength = XUD_GetBuffer(ep0_out, buffer);
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 */
if(datalength == 1)
{
if (!isnull(c_clk_ctl))
{
outuint(c_clk_ctl, SET_SEL);
outuint(c_clk_ctl, buffer[0]);
outct(c_clk_ctl, XS1_CT_END);
}
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in);
}
}
else
{
buffer[0] = 1;
/* Direction: Device-to-host: Send Current Selection */
buffer[0] = 1;
if (!isnull(c_clk_ctl))
{
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);
chkct(c_clk_ctl, XS1_CT_END);
}
return XUD_DoGetRequest( ep0_out, ep0_in, buffer, 1, sp.wLength );
}
}
else
{
//Unknown control on clock selector: sp.wValue
}
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:
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 v2yyolume) */
/* Expect OUT here (with volume) */
loop = XUD_GetBuffer(ep0_out, buffer);
/* Check for rst/suspend */
/* Check for reset */
if(loop < 0)
{
printintln(loop);
return loop;
}
#if 1
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);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
}
}
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);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
}
}
#endif
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in);
}
}
}
else /* Direction: Device-to-host */
{
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[1] = volsOut[ sp.wValue&0xff ] >> 8;
}
else {
buffer[0] = buffer[1] = 0;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
}
}
else
{
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN) {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{
buffer[0] = volsIn[ sp.wValue&0xff ];
buffer[1] = volsIn[ sp.wValue&0xff ] >> 8;
}
else {
buffer[0] = buffer[1] = 0;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
}
}
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
}
break; /* FU_VOLUME_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 */
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 ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT) {
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
{
mutesOut[sp.wValue & 0xff] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
return XUD_DoSetRequestStatus(ep0_in);
}
}
else
{
if((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{
mutesIn[ sp.wValue&0xff ] = buffer[0];
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in);
}
}
}
else // Direction: Device-to-host
{
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];
}
else {
buffer[0] = 0;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
}
}
else
{
if((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{
buffer[0] = mutesIn[ sp.wValue&0xff ];
}
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
}
}
}
break;
default:
@@ -630,7 +586,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
#ifdef MIXER
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;
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)
{
//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, c);
outuint(c_mix_ctl, channelMapAud[c]);
outct(c_mix_ctl, XS1_CT_END);
}
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in);
}
}
}
else
{
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;
case ID_XU_IN:
{
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;
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;
if (!isnull(c_mix_ctl))
{
if (c < NUM_USB_CHAN_IN)
{
//master {
// c_mix_ctl <: SET_SAMPLES_TO_HOST_MAP;
// c_mix_ctl <: c;
// c_mix_ctl <: (int) channelMapUsb[c];
//}
if (!isnull(c_mix_ctl))
{
outuint(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP);
outuint(c_mix_ctl, c);
outuint(c_mix_ctl, channelMapUsb[c]);
outct(c_mix_ctl, XS1_CT_END);
}
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in);
}
}
}
else
{
/* Direction: Device-to-host */
buffer[0] = channelMapUsb[sp.wValue & 0xff];
buffer[1] = 0;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
}
}
break;
case ID_XU_MIXSEL:
{
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 */
datalength = XUD_GetBuffer(ep0_out, buffer);
/* Check for reset/suspend */
/* Check for reset */
if(datalength < 0)
{
return datalength;
}
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 */
outct(c_mix_ctl, XS1_CT_END);
}
}
}
}
/* Send 0 Length as status stage */
return XUD_DoSetRequestStatus(ep0_in);
}
}
}
}
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)
{
buffer[0] = mixSel[cn];
}
}
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, 1 );
}
}
}
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 */
{
unsigned volume = 0;
/* Expect OUT here with mute */
loop = XUD_GetBuffer(ep0_out, buffer);
if(loop < 0)
return loop;
mixer1Weights[sp.wValue & 0xff] = buffer[0] | buffer[1] << 8;
if (mixer1Weights[sp.wValue & 0xff] == 0x8000) {
if (mixer1Weights[sp.wValue & 0xff] == 0x8000)
{
volume = 0;
}
else {
else
{
volume = db_to_mult(mixer1Weights[sp.wValue & 0xff], 8, 25);
}
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, (sp.wValue & 0xff) % 8);
outuint(c_mix_ctl, (sp.wValue & 0xff) / 8);
outuint(c_mix_ctl, volume);
outct(c_mix_ctl, XS1_CT_END);
}
/* 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;
#endif
//default:
///* We dont have a unit with this ID! */
//XUD_Error_hex("ERR: Unknown control unit: ", sp.wIndex);
//break;
default:
/* We dont have a unit with this ID! */
break;
} /* switch(sp.wIndex >> 8) i.e Unit ID */
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, 4, MAX_VOLUME);
storeShort(buffer, 6, VOLUME_RES);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
break;
default:
//Unknown control selector for FU: ", sp.wValue);
/* Unknown control selector for FU */
break;
}
@@ -951,25 +870,21 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
#ifdef MIXER
/* Mixer Unit */
case ID_MIXER_1:
storeShort(buffer, 0, 1);
storeShort(buffer, 2, MIN_MIXER_VOLUME);
storeShort(buffer, 4, MAX_MIXER_VOLUME);
storeShort(buffer, 6, VOLUME_RES_MIXER);
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, sp.wLength, sp.wLength);
break;
#endif
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; /* case: RANGE */
}
#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++)
{
if (!isnull(c_mix_ctl)) {
if (!isnull(c_mix_ctl))
{
outuint(c_mix_ctl, GET_OUTPUT_LEVELS);
outuint(c_mix_ctl, i);
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);
}
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;
#endif
}
/* 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)
/* 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];
int unitID;
int loop = 1;
int i_tmp;
/* Inspect request, NOTE: these are class specific requests */
switch( sp.bRequest )
/* Host to Device */
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);
/* 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);
/* Recontruct sample-freq */
int i_tmp = buffer[0] | (buffer [1] << 8) | (buffer[2] << 16);
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;
}
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;
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[1] = volsOut[ sp.wValue&0xff ] >> 8;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
break;
}
case FU_MUTE_CONTROL:
{
buffer[0] = mutesOut[ sp.wValue & 0xff ];
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
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[1] = volsIn[ sp.wValue&0xff ] >> 8;
break;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
}
case FU_MUTE_CONTROL:
{
buffer[0] = mutesIn[ sp.wValue & 0xff ];
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
}
}
}
break;
}
}
}
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:
{
case UAC_B_REQ_GET_MIN:
buffer[0] = (MIN_MIXER_VOLUME & 0xff);
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);
if(loop < 0)
return loop;
// Status stage (0 length OUT)
return XUD_GetBuffer(c_ep0_out, buffer);
break;
}
case B_REQ_GET_MAX:
{
case UAC_B_REQ_GET_MAX:
buffer[0] = (MAX_MIXER_VOLUME & 0xff);
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);
if(loop < 0)
return 0;
// Status stage (0 length OUT)
return XUD_GetBuffer(c_ep0_out, buffer);
break;
}
case B_REQ_GET_RES:
{
case UAC_B_REQ_GET_RES:
buffer[0] = (VOLUME_RES_MIXER & 0xff);
buffer[1] = (VOLUME_RES_MIXER >> 8);
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;
}
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
}
return 1;
}
#endif

View File

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

View File

@@ -13,10 +13,11 @@
#include "usbaudio20.h" /* Defines from USB Audio 2.0 spec */
#include "devicedefines.h"
#include "DescriptorRequests.h" /* Standard descriptor requests */
#include "usb_device.h" /* Standard descriptor requests */
#include "descriptors_2.h" /* This devices descriptors */
#include "clockcmds.h"
#include "audiostream.h"
#include "hostactive.h"
#include "vendorrequests.h"
#include "dfu_types.h"
#include "xc_ptr.h"
@@ -50,8 +51,9 @@ extern void device_reboot(chanend);
#endif
/* 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_1(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, 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 */
unsigned int g_curSamFreq = DEFAULT_FREQ;
@@ -84,50 +86,21 @@ unsigned char mixSel[MIX_INPUTS];
int min(int x, int y);
/* Records alt setting for each interface */
int interfaceAlt[NUM_INTERFACES];
/* Global current device config var*/
unsigned g_config = 0;
extern unsigned char g_currentConfig;
/* Global endpoint status arrays */
unsigned g_epStatusOut[EP_CNT_OUT];
unsigned g_epStatusIn[EP_CNT_IN];
/* Global endpoint status arrays - declared in usb_device.xc */
extern unsigned char g_interfaceAlt[];
/* Global variable for current USB bus speed (i.e. FS/HS) */
unsigned g_curUsbSpeed = 0;
#ifdef HOST_ACTIVE_CALL
void VendorHostActive(int active);
#endif
/* Global used for signalling reset to decouple */
#ifdef IAP
extern unsigned g_iap_reset;
#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
@@ -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)
{
unsigned char buffer[2];
SetupPacket sp;
XUD_ep ep0_out = XUD_Init_Ep(c_ep0_out);
XUD_ep ep0_in = XUD_Init_Ep(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;
USB_SetupPacket_t sp;
XUD_ep ep0_out = XUD_InitEp(c_ep0_out);
XUD_ep ep0_in = XUD_InitEp(c_ep0_in);
/* Init tables for volumes (+ 1 for master) */
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] */
/* TODO: Macro? */
#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
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
* TODO We really want to do this an build time... */
#if defined(SPDIF_RX) && (SPDIF_RX_INDEX != 0)
safestrcpy(strDescs_Audio2[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], "S/PDIF 1");
safestrcpy(strDescs[SPDIF_RX_INDEX + STR_INDEX_IN_CHAN + 1], "S/PDIF 2");
#endif
#if defined(ADAT_RX) && (ADAT_RX_INDEX != 0)
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN], "ADAT 1");
safestrcpy(strDescs_Audio2[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_Audio2[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_Audio2[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_Audio2[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 7], "ADAT 8");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN], "ADAT 1");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 1], "ADAT 2");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 2], "ADAT 3");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 3], "ADAT 4");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 4], "ADAT 5");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 5], "ADAT 6");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 6], "ADAT 7");
safestrcpy(strDescs[ADAT_RX_INDEX + STR_INDEX_IN_CHAN + 7], "ADAT 8");
#endif
#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_Audio2[SPDIF_TX_INDEX + STR_INDEX_OUT_CHAN + 1], "S/PDIF 2");
safestrcpy(strDescs[SPDIF_TX_INDEX + STR_INDEX_OUT_CHAN], "S/PDIF 1");
safestrcpy(strDescs[SPDIF_TX_INDEX + STR_INDEX_OUT_CHAN + 1], "S/PDIF 2");
#endif
#if defined(ADAT_TX) && (ADAT_TX_INDEX != 0)
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN], "ADAT 1");
safestrcpy(strDescs_Audio2[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_Audio2[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_Audio2[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_Audio2[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 7], "ADAT 8");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN], "ADAT 1");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 1], "ADAT 2");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 2], "ADAT 3");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 3], "ADAT 4");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 4], "ADAT 5");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 5], "ADAT 6");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 6], "ADAT 7");
safestrcpy(strDescs[ADAT_TX_INDEX + STR_INDEX_OUT_CHAN + 7], "ADAT 8");
#endif
#ifdef VENDOR_AUDIO_REQS
@@ -282,182 +248,53 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
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 */
#ifndef DFU
if(g_curUsbSpeed == XUD_SPEED_HS)
if (!retVal)
{
retVal = 1;
#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 */
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
/* Inspect Request type and Receipient and direction */
switch( (sp.bmRequestType.Direction << 7) | (sp.bmRequestType.Recipient ) | (sp.bmRequestType.Type << 5) )
{
/* Return descriptors for full-speed - Audio 1.0? */
#ifdef AUDIO_CLASS_FALLBACK
cfgDesc_Audio1[1] = CONFIGURATION;
cfgDesc_Audio2[1] = OTHER_SPEED_CONFIGURATION;
case USB_BMREQ_H2D_STANDARD_INT:
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 /* ifndef DFU */
if (!DFU_mode_active)
/* Over-riding USB_StandardRequests implementation */
if(sp.bRequest == USB_SET_INTERFACE)
{
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)
/* 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 */
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 */
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 */
AudioStreamStop();
UserAudioStreamStop();
}
#elif defined(OUTPUT) || defined(INPUT)
if(sp.wValue && (!interfaceAlt[1]))
if(sp.wValue && (!g_interfaceAlt[1]))
{
/* 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 */
AudioStreamStop();
UserAudioStreamStop();
}
#endif
/* Record interface change */
if( sp.wIndex < NUM_INTERFACES )
interfaceAlt[sp.wIndex] = sp.wValue;
#if 1
if(sp.wIndex < NUM_INTERFACES)
g_interfaceAlt[sp.wIndex] = sp.wValue;
/* Check for audio stream from host start/stop */
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)
{
case 0:
break;
case 1:
/* Stream active + 0 chans */
/* 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;
}
}
else if(sp.wIndex == 2) // Input interface
{
switch(sp.wValue)
{
case 0:
break;
case 1:
/* Stream active + 0 chans */
/* 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);
outct(c_clk_ctl, XS1_CT_END);
#endif
break;
#ifdef ADAT_RX
case 2:
/* Stream active + 8 chans */
outuint(c_audioControl, SET_CHAN_COUNT_IN);
outuint(c_audioControl, NUM_USB_CHAN_IN-4);
outuint(c_clk_ctl, SET_SMUX);
outuint(c_clk_ctl, 1);
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:
outuint(c_audioControl, SET_CHAN_COUNT_IN);
outuint(c_audioControl, NUM_USB_CHAN_IN-6);
outuint(c_clk_ctl, SET_SMUX);
outuint(c_clk_ctl, 1);
outct(c_clk_ctl, XS1_CT_END);
/* Stream active + 8 chans */
//outuint(c_audioControl, 8);
// Handshake
//chkct(c_audioControl, XS1_CT_END);
break;
#endif
}
}
#endif
/* No data stage for this request, just do data stage */
retVal = XUD_DoSetRequestStatus(ep0_in, 0);
break;
retVal = XUD_DoSetRequestStatus(ep0_in);
} /* if(sp.bRequest == SET_INTERFACE) */
/* A device must support the GetInterface request if it has alternate setting for that interface */
case GET_INTERFACE:
break; /* BMREQ_H2D_STANDARD_INT */
buffer[0] = 0;
case USB_BMREQ_D2H_STANDARD_INT:
/* Bounds check */
if( sp.wIndex < NUM_INTERFACES )
buffer[0] = interfaceAlt[sp.wIndex];
switch(sp.bRequest)
{
retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
break;
#ifdef HID_CONTROLS
case GET_DESCRIPTOR:
/* Check what inteface request is for */
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:
/* Return HID report descriptor */
retVal = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptor,
min(sizeof(hidReportDescriptor),sp.wLength), sp.wLength);
sizeof(hidReportDescriptor), sp.wLength);
break;
}
}
break;
#endif
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;
/* Recipient: Device */
case STANDARD_DEVICE_REQUEST:
case USB_BMREQ_H2D_STANDARD_DEV:
/* Standard Device requests (8) */
/* Inspect for actual request */
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 */
case SET_CONFIGURATION:
/* Overriding implementation in USB_StandardRequests */
case USB_SET_CONFIGURATION:
g_config = sp.wValue;
#ifdef HOST_ACTIVE_CALL
if(g_config == 1)
g_currentConfig = sp.wValue;
//if(g_current_config == 1)
{
/* Consider host active with valid driver at this point */
VendorHostActive(1);
UserHostActive(1);
}
#endif
#ifdef IAP
{
int iap_reset = 1;
@@ -639,132 +426,42 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
}
#endif
/* No data stage for this request, just do status stage */
retVal = XUD_DoSetRequestStatus(ep0_in, 0);
retVal = XUD_DoSetRequestStatus(ep0_in);
break;
case GET_CONFIGURATION:
buffer[0] = g_config;
retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
default:
//Unknown device request"
break;
}
break;
/* Get Status request */
case GET_STATUS:
/* Audio Class 1.0 Sampling Freqency Requests go to Endpoint */
case USB_BMREQ_H2D_CLASS_EP:
case USB_BMREQ_D2H_CLASS_EP:
{
unsigned epNum = sp.wIndex & 0xff;
#ifdef SELF_POWERED
buffer[0] = 1; // self powered
#else
buffer[0] = 0; // bus powered
if ((epNum == 0x82) || (epNum == 0x01))
{
#if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK)
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
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;
/* Receipient: Endpoint */
case STANDARD_ENDPOINT_REQUEST:
/* 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:
case USB_BMREQ_H2D_CLASS_INT:
case USB_BMREQ_D2H_CLASS_INT:
{
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 = */
#ifdef DFU
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 running in application mode stop audio */
/* 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
outuint(c_audioControl, SET_SAMPLE_FREQ);
outuint(c_audioControl, AUDIO_STOP_FOR_DFU);
// Handshake
chkct(c_audioControl, XS1_CT_END);
}
/* 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;
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 */
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
/* 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(g_curUsbSpeed == XUD_SPEED_HS)
{
@@ -846,36 +538,78 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
break;
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;
}
} /* if(retVal == 0) */
if(retVal == 1)
if(retVal > 0)
{
/* Did not handle request - Protocol Stall Secion 8.4.5 of USB 2.0 spec
* Detailed in Section 8.5.3. Protocol stall is unique to control pipes.
Protocol stall differs from functional stall in meaning and duration.
A protocol STALL is returned during the Data or Status stage of a control
transfer, and the STALL condition terminates at the beginning of the
next control transfer (Setup). The remainder of this section refers to
the general case of a functional stall */
XUD_SetStall_Out(0);
XUD_SetStall_In(0);
#ifndef DFU
#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 */
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)
{
g_curUsbSpeed = XUD_ResetEndpoint(ep0_out, ep0_in);
g_config = 0;
g_currentConfig = 0;
#ifdef DFU
if (DFUReportResetState(null))
@@ -900,9 +634,6 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
DFU_mode_active = 0;
// Send reboot command
//outuint(c_audioControl, SET_SAMPLE_FREQ);
//outuint(c_audioControl, AUDIO_REBOOT_FROM_DFU);
// No handshake on reboot
tmr :> s;
tmr when timerafter(s + 5000000) :> s;
device_reboot(c_audioControl);

View File

@@ -2,12 +2,6 @@
#include <xs1.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 "devicedefines.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
)
{
XUD_ep ep_aud_out = XUD_Init_Ep(c_aud_out);
XUD_ep ep_aud_in = XUD_Init_Ep(c_aud_in);
XUD_ep ep_aud_fb = XUD_Init_Ep(c_aud_fb);
XUD_ep ep_aud_out = XUD_InitEp(c_aud_out);
XUD_ep ep_aud_in = XUD_InitEp(c_aud_in);
XUD_ep ep_aud_fb = XUD_InitEp(c_aud_fb);
#ifdef MIDI
XUD_ep ep_midi_from_host = XUD_Init_Ep(c_midi_from_host);
XUD_ep ep_midi_to_host = XUD_Init_Ep(c_midi_to_host);
XUD_ep ep_midi_from_host = XUD_InitEp(c_midi_from_host);
XUD_ep ep_midi_to_host = XUD_InitEp(c_midi_to_host);
#endif
#ifdef IAP
XUD_ep ep_iap_from_host = XUD_Init_Ep(c_iap_from_host);
XUD_ep ep_iap_to_host = XUD_Init_Ep(c_iap_to_host);
XUD_ep ep_iap_to_host_int = XUD_Init_Ep(c_iap_to_host_int);
XUD_ep ep_iap_from_host = XUD_InitEp(c_iap_from_host);
XUD_ep ep_iap_to_host = XUD_InitEp(c_iap_to_host);
XUD_ep ep_iap_to_host_int = XUD_InitEp(c_iap_to_host_int);
#endif
#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
#ifdef HID_CONTROLS
XUD_ep ep_hid = XUD_Init_Ep(c_hid);
XUD_ep ep_hid = XUD_InitEp(c_hid);
#endif
@@ -699,7 +693,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
else
{
// Too many events from device - drop
printstr("DROP");
//printstr("DROP");
}
/* Once we have the whole message, sent it to host */

View File

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