📄 usb.c
字号:
}
}
//-----------------------------------------------------------------------------
// Send a zero-length packet on EP0. This blocks until the packet has been
// transmitted and an ACK from the host has been received.
//-----------------------------------------------------------------------------
static void UsbSendZeroLength(void)
{
UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;
while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED))
;
UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;
while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)
;
}
//-----------------------------------------------------------------------------
// Handle a received SETUP DATA packet. These are the packets used to
// configure the link (e.g. request various descriptors, and assign our
// address).
//-----------------------------------------------------------------------------
static void HandleRxdSetupData(void)
{
int i;
UsbSetupData usd;
for(i = 0; i < sizeof(usd); i++) {
((BYTE *)&usd)[i] = UDP_ENDPOINT_FIFO(0);
}
if(usd.bmRequestType & 0x80) {
UDP_ENDPOINT_CSR(0) |= UDP_CSR_CONTROL_DATA_DIR;
while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_CONTROL_DATA_DIR))
;
}
UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_HAVE_READ_SETUP_DATA;
while(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA)
;
switch(usd.bRequest) {
case USB_REQUEST_GET_DESCRIPTOR:
if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) {
UsbSendEp0((BYTE *)&DeviceDescriptor,
min(sizeof(DeviceDescriptor), usd.wLength));
} else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) {
UsbSendEp0((BYTE *)&ConfigurationDescriptor,
min(sizeof(ConfigurationDescriptor), usd.wLength));
} else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) {
const BYTE *s = StringDescriptors[usd.wValue & 0xff];
UsbSendEp0(s, min(s[0], usd.wLength));
} else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) {
UsbSendEp0((BYTE *)&HidReportDescriptor,
min(sizeof(HidReportDescriptor), usd.wLength));
}
break;
case USB_REQUEST_SET_ADDRESS:
UsbSendZeroLength();
UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED | usd.wValue ;
if(usd.wValue != 0) {
UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;
} else {
UDP_GLOBAL_STATE = 0;
}
break;
case USB_REQUEST_GET_CONFIGURATION:
UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration));
break;
case USB_REQUEST_GET_STATUS: {
if(usd.bmRequestType & 0x80) {
WORD w = 0;
UsbSendEp0((BYTE *)&w, sizeof(w));
}
break;
}
case USB_REQUEST_SET_CONFIGURATION:
CurrentConfiguration = usd.wValue;
if(CurrentConfiguration) {
UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_CONFIGURED;
UDP_ENDPOINT_CSR(1) = UDP_CSR_ENABLE_EP |
UDP_CSR_EPTYPE_INTERRUPT_OUT;
UDP_ENDPOINT_CSR(2) = UDP_CSR_ENABLE_EP |
UDP_CSR_EPTYPE_INTERRUPT_IN;
} else {
UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;
UDP_ENDPOINT_CSR(1) = 0;
UDP_ENDPOINT_CSR(2) = 0;
}
UsbSendZeroLength();
break;
case USB_REQUEST_GET_INTERFACE: {
BYTE b = 0;
UsbSendEp0(&b, sizeof(b));
break;
}
case USB_REQUEST_SET_INTERFACE:
UsbSendZeroLength();
break;
case USB_REQUEST_CLEAR_FEATURE:
case USB_REQUEST_SET_FEATURE:
case USB_REQUEST_SET_DESCRIPTOR:
case USB_REQUEST_SYNC_FRAME:
default:
break;
}
}
//-----------------------------------------------------------------------------
// Send a data packet. This packet should be exactly USB_REPORT_PACKET_SIZE
// long. This function blocks until the packet has been transmitted, and
// an ACK has been received from the host.
//-----------------------------------------------------------------------------
void UsbSendPacket(BYTE *packet, int len)
{
int i, thisTime;
while(len > 0) {
thisTime = min(len, 8);
for(i = 0; i < thisTime; i++) {
UDP_ENDPOINT_FIFO(2) = packet[i];
}
UDP_ENDPOINT_CSR(2) |= UDP_CSR_TX_PACKET;
while(!(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED))
;
UDP_ENDPOINT_CSR(2) &= ~UDP_CSR_TX_PACKET_ACKED;
while(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED)
;
len -= thisTime;
packet += thisTime;
}
}
//-----------------------------------------------------------------------------
// Handle a received packet. This handles only those packets received on
// EP1 (i.e. the HID reports that we use as our data packets).
//-----------------------------------------------------------------------------
static void HandleRxdData(void)
{
int i, len;
if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {
len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));
for(i = 0; i < len; i++) {
UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);
UsbSoFarCount++;
}
UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;
while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0)
;
if(UsbSoFarCount >= 64) {
UsbPacketReceived(UsbBuffer, UsbSoFarCount);
UsbSoFarCount = 0;
}
}
if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1) {
len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));
for(i = 0; i < len; i++) {
UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);
UsbSoFarCount++;
}
UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_1;
while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1)
;
if(UsbSoFarCount >= 64) {
UsbPacketReceived(UsbBuffer, UsbSoFarCount);
UsbSoFarCount = 0;
}
}
}
//-----------------------------------------------------------------------------
// Initialize the USB driver. To be thorough, disconnect the pull-up on
// D+ (to make the host think that we have been unplugged, resetting all
// of its state) before reconnecting it and resetting the AT91's USB
// peripheral.
//-----------------------------------------------------------------------------
void UsbStart(void)
{
volatile int i;
UsbSoFarCount = 0;
USB_D_PLUS_PULLUP_OFF();
for(i = 0; i < 1000000; i++)
;
USB_D_PLUS_PULLUP_ON();
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {
UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;
}
}
//-----------------------------------------------------------------------------
// This must be called periodically in order for USB to work. UsbPoll may
// call UsbPacketReceived if a non-control packet has been received, and
// UsbPoll should not be called from UsbPacketReceived.
//
// Returns TRUE if we `did something' (received either a control or data
// packet, or a piece of one at least), FALSE otherwise.
//-----------------------------------------------------------------------------
BOOL UsbPoll(void)
{
BOOL ret = FALSE;
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {
UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;
// following a reset we should be ready to receive a setup packet
UDP_RESET_ENDPOINT = 0xf;
UDP_RESET_ENDPOINT = 0;
UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED;
UDP_ENDPOINT_CSR(0) = UDP_CSR_EPTYPE_CONTROL | UDP_CSR_ENABLE_EP;
CurrentConfiguration = 0;
ret = TRUE;
}
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(0)) {
if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA) {
HandleRxdSetupData();
ret = TRUE;
}
}
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(1)) {
HandleRxdData();
ret = TRUE;
}
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -