📄 d_usb.c
字号:
UBYTE bmRequestType, bRequest;
UWORD wValue, wIndex, wLength, wStatus;
if ( !((*AT91C_UDP_CSR0) & AT91C_UDP_RXSETUP) ) // No setup package available
return;
// Bytes are popped from the FIFO one by one
bmRequestType = *AT91C_UDP_FDR0;
bRequest = *AT91C_UDP_FDR0;
wValue = ((*AT91C_UDP_FDR0) & 0xFF);
wValue |= ((*AT91C_UDP_FDR0) << 8);
wIndex = ((*AT91C_UDP_FDR0) & 0xFF);
wIndex |= ((*AT91C_UDP_FDR0) << 8);
wLength = ((*AT91C_UDP_FDR0) & 0xFF);
wLength |= ((*AT91C_UDP_FDR0) << 8);
if (bmRequestType & 0x80) // If a DEVICE-TO-HOST request
{
*AT91C_UDP_CSR0 |= AT91C_UDP_DIR; // Enables data IN transaction in the control data stage
while ( !((*AT91C_UDP_CSR0) & AT91C_UDP_DIR) ); // Repeat until the DIR bit is set
}
*AT91C_UDP_CSR0 &= ~AT91C_UDP_RXSETUP; // Device firmware has read the setup data in FIFO
while ( ((*AT91C_UDP_CSR0) & AT91C_UDP_RXSETUP) ); // Wait until bit cleared
// Handle supported standard device request from Table 9-3 in USB specification Rev 2.0
switch ((bRequest << 8) | bmRequestType)
{
case STD_GET_DESCRIPTOR:
RequestedData = wLength;
if (wValue == 0x100) // Return Device Descriptor
{
if (sizeof(DeviceDescriptor) > wLength)
{
dUsbSendViaControl(DeviceDescriptor, wLength);
}
else
{
dUsbSendViaControl(DeviceDescriptor, sizeof(DeviceDescriptor));
}
}
else if (wValue == 0x200) // Return Configuration Descriptor
{
if (sizeof(ConfigurationDescriptor) > wLength)
{
dUsbSendViaControl(ConfigurationDescriptor, wLength);
}
else
{
dUsbSendViaControl(ConfigurationDescriptor, sizeof(ConfigurationDescriptor));
}
}
else if ((wValue & 0xF00) == 0x300)
{
switch(wValue & 0xFF)
{
case 0x00:
if ((sizeof(LangIdDescriptor)) > wLength)
{
dUsbSendViaControl(LangIdDescriptor, wLength);
}
else
{
dUsbSendViaControl(LangIdDescriptor, sizeof(LangIdDescriptor));
}
break;
case 0x01:
if ((sizeof(SerialNumberDescriptor)) > wLength)
{
dUsbSendViaControl(SerialNumberDescriptor, wLength);
}
else
{
dUsbSendViaControl(SerialNumberDescriptor, sizeof(SerialNumberDescriptor));
}
break;
default:
dUsbSendStall(); // Illegal request :-(
break;
}
}
else
dUsbSendStall(); // Illegal request :-(
break;
case STD_SET_ADDRESS:
// Status IN transfer
(*AT91C_UDP_CSR0) |= AT91C_UDP_TXPKTRDY;
dUsbStartTimeoutTimer();
while((*AT91C_UDP_CSR0) & AT91C_UDP_TXPKTRDY && !dUsbTimedOut());
*AT91C_UDP_FADDR = (AT91C_UDP_FEN | wValue); // Set device address. No check for invalid address.
// Function endpoint enabled.
*AT91C_UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; // If Device address != 0 then flag device
// in ADDRESS STATE
break;
case STD_SET_CONFIGURATION:
CurrentConfiguration = wValue; // Low byte of wValue = wanted configuration
UsbConnectionStates = USB_CONFIGURED;
dUsbSendZeroLengthPackage(); // Signal request processed OK
*AT91C_UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; // If wanted configuration != 0
*AT91C_UDP_CSR1 = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; // Endpoint 1 enabled and set as BULK OUT
*AT91C_UDP_CSR2 = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; // Endpoint 2 enabled and set as BULK IN
*AT91C_UDP_CSR3 = (wValue) ? (AT91C_UDP_EPTYPE_INT_IN) : 0; // Endpoint 3 disabled and set as INTERRUPT IN
break;
case STD_GET_CONFIGURATION: // The actual configuration value is sent to HOST
RequestedData = sizeof(CurrentConfiguration);
dUsbSendViaControl((UBYTE *) &(CurrentConfiguration), sizeof(CurrentConfiguration));
break;
case STD_GET_STATUS_ZERO:
wStatus = 0x01; // Atmel has a 0x00, but we're not BUS-powered
RequestedData = sizeof(wStatus);
dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_INTERFACE: // Everything reset to zero (reserved)
wStatus = 0;
RequestedData = sizeof(wStatus);
dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_ENDPOINT:
wStatus = 0;
RequestedData = sizeof(wStatus);
wIndex &= 0x0F; // Mask the endpoint #
if (((*AT91C_UDP_GLBSTATE) & AT91C_UDP_CONFG) && (wIndex <= 3)) // If device in CONFIGURED state
{ // and ENDPOINT selected in valid range
switch (wIndex)
{
case 1: wStatus = ((*AT91C_UDP_CSR1) & AT91C_UDP_EPEDS) ? 0 : 1; // If an endpoint is halted, the HALT
// feature is set to 1, else reset
break;
case 2: wStatus = ((*AT91C_UDP_CSR2) & AT91C_UDP_EPEDS) ? 0 : 1;
break;
case 3: wStatus = ((*AT91C_UDP_CSR3) & AT91C_UDP_EPEDS) ? 0 : 1;
break;
default:
// We'll never come here, but we'll never say never.......
break;
}
dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
}
else if (((*AT91C_UDP_GLBSTATE) & AT91C_UDP_FADDEN) && (wIndex == 0))
{
wStatus = ((*AT91C_UDP_CSR0) & AT91C_UDP_EPEDS) ? 0 : 1; // Return 1 if device in ADRESSED state
dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
}
else
dUsbSendStall(); // Illegal request :-(
break;
case STD_SET_FEATURE_ZERO:
dUsbSendStall(); // Illegal request :-(
break;
case STD_SET_FEATURE_INTERFACE:
dUsbSendZeroLengthPackage(); // TextBook
break;
case STD_SET_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex <= 3)) // Feature Selector = 0 ENDPOINT HALT and
{ // endpoint isolated and validated
switch (wIndex)
{
case 1: (*AT91C_UDP_CSR1) = 0;
break;
case 2: (*AT91C_UDP_CSR2) = 0;
break;
case 3: (*AT91C_UDP_CSR3) = 0;
break;
default:
// We'll never come here, but we'll never say never.......
break;
}
dUsbSendZeroLengthPackage();
}
else
dUsbSendStall(); // Illegal request :-(
break;
case STD_CLEAR_FEATURE_ZERO:
dUsbSendStall(); // Illegal request :-(
break;
case STD_CLEAR_FEATURE_INTERFACE:
dUsbSendZeroLengthPackage(); // No special
break;
case STD_CLEAR_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex <= 3)) // Feature Selector = 0 => ENABLE A HALTED endpoint
{ // and endpoint isolated and validated
if (wIndex == 1)
(*AT91C_UDP_CSR1) = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); // On duty again
else if (wIndex == 2)
(*AT91C_UDP_CSR2) = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); // -
else if (wIndex == 3)
(*AT91C_UDP_CSR3) = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN); // -
dUsbSendZeroLengthPackage();
}
else
dUsbSendStall(); // Illegal request :-(
break;
default:
dUsbSendStall(); // Illegal request :-(
break;
}
}
UBYTE dUsbIsConfigured(void)
{
if (*AT91C_UDP_ISR & END_OF_BUS_RESET) // If "End Of Bus Reset Interrupt"
{ // Somebody fallen in the wire? ;-)
*AT91C_UDP_ICR = END_OF_BUS_RESET; // Reset "End Of Bus Reset Interrupt"
*AT91C_UDP_ICR = SUSPEND_RESUME; // State unknown after reset, so we better clear
*AT91C_UDP_ICR = WAKEUP; // As above
CurrentConfiguration = 0; // We're new and ready
UsbConnectionStates = USB_NOT_CONFIGURED;
*AT91C_UDP_RSTEP = 0xFFFFFFFF; // Reset all implemented endpoints "and a few more"
*AT91C_UDP_RSTEP = 0x0; // Restored as zeroes
// Below our main crash thing, if it is missing ;-)
CurrentReceiveBank = AT91C_UDP_RX_DATA_BK0; // Start the PING-PONG buffers at a known state and order
*AT91C_UDP_FADDR = AT91C_UDP_FEN; // Set FEN in the Function Address Register
// USB device is able to receive and transfer data
*AT91C_UDP_CSR0 = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); // Configure endpoint 0
// AT91C_UDP_EPEDS = Endpoint enable
// AT91C_UDP_EPTYPE_CTRL = Endpoint type CONTROL
}
else if (*AT91C_UDP_ISR & SUSPEND_INT)
{
if (UsbConnectionStates == USB_CONFIGURED)
{
UsbConnectionStates = USB_CONFIGURED_BUT_SUSPENDED;
}
else
{
UsbConnectionStates = USB_NOT_CONFIGURED;
}
*AT91C_UDP_ICR = SUSPEND_INT;
CurrentReceiveBank = AT91C_UDP_RX_DATA_BK0; // Start the PING-PONG buffers at a known state and order
}
else if (*AT91C_UDP_ISR & SUSPEND_RESUME)
{
if (UsbConnectionStates == USB_CONFIGURED_BUT_SUSPENDED)
{
UsbConnectionStates = USB_CONFIGURED;
}
else
{
UsbConnectionStates = USB_NOT_CONFIGURED;
}
*AT91C_UDP_ICR = WAKEUP;
*AT91C_UDP_ICR = SUSPEND_RESUME;
}
else if (*AT91C_UDP_ISR & AT91C_UDP_EPINT0) // If "Endpoint 0 Interrupt"
{
*AT91C_UDP_ICR = AT91C_UDP_EPINT0; // Reset "Endpoint 0 Interrupt"
if (BrickNameKnown)
dUsbEnumerate(); // Let's date & exchange "personal data"
}
if (UsbConnectionStates == USB_CONFIGURED)
{
return TRUE;
}
else
{
return FALSE;
}
}
void dUsbInsertHandle(UBYTE Handle)
{
UBYTE Tmp;
Tmp = 0;
while((UsbHandleList[Tmp] != MAX_HANDLES) && (Tmp < MAX_HANDLES))
{
Tmp++;
}
UsbHandleList[Tmp] = Handle;
}
void dUsbRemoveHandle(UBYTE Handle)
{
UBYTE Tmp;
Tmp = 0;
while (Tmp < MAX_HANDLES)
{
if (Handle == UsbHandleList[Tmp])
{
UsbHandleList[Tmp] = MAX_HANDLES;
}
Tmp++;
}
}
UWORD dUsbGetFirstHandle(void)
{
UWORD RtnVal;
UsbHandleCnt = 0;
RtnVal = dUsbGetNextHandle();
return(RtnVal);
}
UWORD dUsbGetNextHandle(void)
{
UBYTE Tmp;
UWORD RtnVal;
RtnVal = 0;
Tmp = UsbHandleCnt;
while((Tmp < MAX_HANDLES) && (MAX_HANDLES == UsbHandleList[Tmp]))
{
Tmp++;
}
UsbHandleCnt = Tmp + 1;
if (Tmp < MAX_HANDLES)
{
RtnVal |= UsbHandleList[Tmp];
}
else
{
RtnVal = 0x8100;
}
return(RtnVal);
}
UWORD dUsbCheckConnection(void)
{
UWORD ADValue;
UWORD Return;
Return = FALSE;
USBReadADCValue(&ADValue);
if (ADValue > 512)
{
Return = TRUE;
}
return(Return);
}
void dUsbInit(void)
{
UBYTE Tmp;
// We could come from a SAMBA session and then we need
// to "introduce ourself in a polite way for the PNP manager
// We will pull the carpet and start a new session by removing
// the pull up of the D+ wire
BrickNameKnown = FALSE;
dUsbStartTimeoutTimer(); // Let H/W settle
dUsbDisconnect(); // Pull the carpet
while(!USBTimedOut); // wait 1 mS.
USBHwInit; // New session
CurrentConfiguration = 0; // We're new born
UsbConnectionStates = USB_NOT_CONFIGURED;
CurrentReceiveBank = AT91C_UDP_RX_DATA_BK0; // Always start from Bank 0
RequestedData = 0;
for(Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
{
UsbHandleList[Tmp] = MAX_HANDLES;
}
}
void dUsbResetConfig(void)
{
CurrentConfiguration = 0; // We've lost the connection
UsbConnectionStates = USB_NOT_CONFIGURED;
}
void dUsbExit(void)
{
// USBExit;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -