📄 fw.c
字号:
default: // Invalid request
EZUSB_STALL_EP0(); // Stall End Point 0
} // switch
break;
case SC_GET_INTERFACE: // *** Get Interface
EP0BUF[0] = AlternateSetting;
EP0BCH = 0;
EP0BCL = 1;
break;
case SC_SET_INTERFACE: // *** Set Interface
TOGCTL = 0x2; // Reset data toggle for EP2
TOGCTL = 0x22;
TOGCTL = 0x18; // Reset data toggle for EP8
TOGCTL = 0x38;
AlternateSetting = SETUPDAT[2];
break;
case SC_SET_CONFIGURATION: // *** Set Configuration
Configuration = SETUPDAT[2];
#if BUS_POWERED
// The following section of code allows us to enumerate with less than
// 100mA of current draw. The USB spec limits current draw to 100mA
// until a device is configured. The current draw of the high-speed
// phy exceeds this limit. Our workaround for this is to initially
// enumerate in full-speed only mode (by setting the full-speed only bit
// in the eeprom config byte). Our config descriptor reports us as
// bus-powered with a 500mA requirement. Therefore, if we receive a
// Set Configuration, we know we are plugged into a high-power capable
// port. When we receive the set configuration, we check to see if we
// have enabled high-speed mode. If not, we enable high-speed and
// renumerate. To enable this workaround BUS_POWERED must be set to
// 1 in both the C51 and A51 options of the project file. The full
// speed only bit (bit 7 in the eeprom config byte) must also be set.
// check to see if we have enabled high-speed. Configuration = zero says
// that high-speed is currently disabled
if (!bHighSpeedEnabled)
{
if (Configuration == 1)
bSwitchToHighSpeed = 1;
}
#endif // BUS_POWERED
break;
case SC_GET_CONFIGURATION: // *** Get Configuration
EP0BUF[0] = Configuration;
EP0BCH = 0;
EP0BCL = 1;
break;
case SC_GET_STATUS: // *** Get Status
switch(SETUPDAT[0])
{
case GS_DEVICE: // Device
#if BUS_POWERED
EP0BUF[0] = 0x00; // Bit 0 -- 1 = self-power, 0 = bus power
EP0BUF[1] = 0; // Bit 1 -- remote wakeup enabled (0 for us)
#else
EP0BUF[0] = 0x01; // Bit 0 -- 1 = self-power, 0 = bus power
EP0BUF[1] = 0; // Bit 1 -- remote wakeup enabled (0 for us)
#endif
EP0BCH = 0;
EP0BCL = 2;
break;
case GS_INTERFACE: // Interface
EP0BUF[0] = 0;
EP0BUF[1] = 0;
EP0BCH = 0;
EP0BCL = 2;
break;
case GS_ENDPOINT: // End Point
if (SETUPDAT[4] == 0x2)
{
EP0BUF[0] = (EP2CS & bmEPSTALL);
}
else if (SETUPDAT[4] == 0x88)
{
EP0BUF[0] = (EP8CS & bmEPSTALL);
}
else if (SETUPDAT[4] == 0x00)
{
EP0BUF[0] = 0x00;
}
else
{
EZUSB_STALL_EP0(); // Stall End Point 0
break;
}
EP0BUF[1] = 0;
EP0BCH = 0;
EP0BCL = 2;
break;
default: // Invalid Command
EZUSB_STALL_EP0(); // Stall End Point 0
}
break;
case SC_CLEAR_FEATURE: // *** Clear Feature
switch(SETUPDAT[0])
{
case FT_DEVICE: // Device
if(SETUPDAT[2] == 1)
{
// Disable Remote Wakeup. don't need to do anything here
}
else
EZUSB_STALL_EP0(); // Stall End Point 0
break;
case FT_ENDPOINT: // End Point
if(SETUPDAT[2] == 0)
{
// do not clear endpoint STALLs if we received an invalid CBW.
// The BOT MSC Spec says we must stay STALL'd until we get reset
if (!phaseErrorState)
{
if (SETUPDAT[4] == 0x2)
{
ResetAndArmEp2();
TOGCTL = 0x2;
TOGCTL = 0x22; // reset data toggle
EP2CS = 0; // Clear stall bit
}
else if (SETUPDAT[4] == 0x88)
{
TOGCTL = 0x18;
TOGCTL = 0x38; // reset data toggle
EP8CS = 0; // Clear stall bit
}
else if (SETUPDAT[4] == 0x0)
{
// EP0 STALLs are auto-clear
}
else
EZUSB_STALL_EP0(); // Stall End Point 0
}
}
else
EZUSB_STALL_EP0(); // Stall End Point 0
break;
default:
EZUSB_STALL_EP0(); // Stall End Point 0
}
break;
case SC_SET_FEATURE: // *** Set Feature
switch(SETUPDAT[0])
{
case FT_DEVICE: // Device
if(SETUPDAT[2] == 1)
{
// Enable Remote Wakeup. don't need to do anything here
}
else if(SETUPDAT[2] == 2)
// Set Feature Test Mode. The core handles this request. However, it is
// necessary for the firmware to complete the handshake phase of the
// control transfer before the chip will enter test mode. It is also
// necessary for FX2 to be physically disconnected (D+ and D-)
// from the host before it will enter test mode.
break;
else
EZUSB_STALL_EP0(); // Stall End Point 0
break;
case FT_ENDPOINT: // End Point
if(SETUPDAT[2] == 0)
{
if (SETUPDAT[4] == 0x2)
EP2CS = bmEPSTALL; // Set stall bit
else if (SETUPDAT[4] == 0x88)
EP8CS = bmEPSTALL; // Set stall bit
else
EZUSB_STALL_EP0(); // Stall End Point 0
}
else
EZUSB_STALL_EP0(); // Stall End Point 0
break;
default:
EZUSB_STALL_EP0(); // Stall End Point 0
}
break;
default: // *** Invalid Command
EZUSB_STALL_EP0(); // Stall End Point 0
}
}
else if ((SETUPDAT[0] & SETUP_MASK) == SETUP_CLASS_REQUEST)
{
switch(SETUPDAT[1])
{
case SC_MASS_STORAGE_RESET:
// Verify that the command is actually a MS reset command sent to the proper interface
if (SETUPDAT[0] == 0x21 && SETUPDAT[4] == 0) // Our interface number is hard coded (0) in DSCR.A51
{
// All we really need to do in response to a MSC Reset is restart using
// a soft reset (jump to 0x00). This will re-initialize the drive and
// endpoints.
EZUSB_IRQ_CLEAR();
INT2CLR = bmSUDAV; // Clear SUDAV IRQ
// force a soft reset after the iret.
EA = 0;
softReset();
}
else
EZUSB_STALL_EP0(); // Stall End Point 0
break;
case SC_GET_MAX_LUN:
if (SETUPDAT[0] == 0xa1 && SETUPDAT[4] == 0) // Our interface number is hard coded (0) in DSCR.A51
{
EP0BUF[0] = deviceCount - 1;
EP0BCH = 0;
EP0BCL = 1;
}
else
EZUSB_STALL_EP0(); // Stall End Point 0
break;
default: // *** Invalid Command
EZUSB_STALL_EP0(); // Stall End Point 0
} // End Switch
} // end elseif
else
EZUSB_STALL_EP0(); // Stall End Point 0
// Acknowledge handshake phase of device request
EP0CS |= bmHSNAK;
}
// Wake-up interrupt handler
void resume_isr(void) interrupt WKUP_VECT
{
EZUSB_CLEAR_RSMIRQ();
}
STRINGDSCR xdata * EZUSB_GetStringDscr(BYTE StrIdx)
{
// explanation. String indexes are calculated. The index is
// the offset of the string in the eeprom divided by two.
// The first 16 bytes of the eeprom are config bytes. So, to
// get the actual address of the string descriptor in memory,
// you double the string indes subtract 16 (to account for the
// config bytes in the eeprom) and add that to the address of
// the device descriptor. simple.
if (StrIdx)
return(pDeviceDscr + (StrIdx * 2) - 16);
else
return(pStringDscr);
}
void EZUSB_Discon(BOOL renum)
{
if(renum) // If renumerate (i.e. 8051 will handle SETUP commands)
USBCS |= (bmDISCON | bmRENUM); // disconnect from USB and set the renumerate bit
else
USBCS |= bmDISCON; // just disconnect from USB
EZUSB_Delay(2500); // Wait 2500 ms
USBIRQ = 0xff; // Clear any pending USB interrupt requests. They're for our old life.
EPIRQ = 0xff;
EZUSB_IRQ_CLEAR();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -