📄 usb.c
字号:
// If the packet we received include more data than we expected, we ignore
// the entire packet and abort the transfer. This is accomplished by
// stalling OEP0 and resetting the bStatusAction condition to "Nothing."
usbStallOEP0;
bStatusAction = STATUS_ACTION_NOTHING;
}
}
/***************************************************************************
* Function: usbSendZeroLengthPacketOnIEP0() *
* Programmer: Lobo Tai (lobotai@ti.com) *
* Description: Sends a 0-lengthg packet back to the host on IEP0. Often *
* called to acknowledge a packet received from the host that requires *
* no data in the reply, just an acknowledgement of receipt. *
***************************************************************************/
void usbSendZeroLengthPacketOnIEP0(void)
{
wBytesRemainingOnIEP0 = NO_MORE_DATA;
bStatusAction = STATUS_ACTION_NOTHING;
tEndPoint0DescriptorBlock.bIEPBCNT = 0x00;
}
/***************************************************************************
* Function: usbSendDataPacketOnEPO / SendNext *
* Programmer: Lobo Tai (lobotai@ti.com) *
* Description: These two functions, together, are responsible for sending *
* data packets back to the host on IEPO. The transfer is initiated by *
* first calling usbSendDataPacketOnEP0 and indicating the address of *
* the buffer to send. This initiates the transfer and sends the first *
* packet of data. If there is more data than can be sent in the first *
* packet, the usbSendNextPacketOnIEP0 function is called to send *
* subsequent packets of data when an interrupt indicates the previous *
* packet has been sent. *
***************************************************************************/
void usbSendDataPacketOnEP0(PBYTE pbBuffer)
{
WORD wTemp;
pbIEP0Buffer = pbBuffer;
wTemp = (WORD)(tSetupPacket.bLengthH << 8) | (WORD)tSetupPacket.bLengthL;
// Limit transfer size to wLength if needed
// this prevent USB device sending 'more than require' data back to host
if(wBytesRemainingOnIEP0 >= wTemp)
{
wBytesRemainingOnIEP0 = wTemp;
bHostAskMoreDataThanAvailable = FALSE;
}
else
{
bHostAskMoreDataThanAvailable = TRUE;
}
usbSendNextPacketOnIEP0();
}
void usbSendNextPacketOnIEP0(void)
{
BYTE bPacketSize,bIndex;
// First check if there are bytes remaining to be transferred
if(wBytesRemainingOnIEP0 != NO_MORE_DATA)
{
if(wBytesRemainingOnIEP0 > EP0_MAX_PACKET_SIZE)
{
// More bytes are remaining than will fit in one packet
// there will be More IN Stage
bPacketSize = EP0_MAX_PACKET_SIZE;
wBytesRemainingOnIEP0 -= EP0_MAX_PACKET_SIZE;
bStatusAction = STATUS_ACTION_DATA_IN;
}
else if (wBytesRemainingOnIEP0 < EP0_MAX_PACKET_SIZE)
{
// The remaining data will fit in one packet.
// This case will properly handle wBytesRemainingOnIEP0 == 0
bPacketSize = (BYTE)wBytesRemainingOnIEP0;
wBytesRemainingOnIEP0 = NO_MORE_DATA; // No more data need to be Txed
bStatusAction = STATUS_ACTION_NOTHING;
}
else
{
// wBytesRemainingOnIEP0 == EP0_MAX_PACKET_SIZE
bPacketSize = EP0_MAX_PACKET_SIZE;
if(bHostAskMoreDataThanAvailable == TRUE)
{
wBytesRemainingOnIEP0 = 0;
bStatusAction = STATUS_ACTION_DATA_IN;
}
else
{
wBytesRemainingOnIEP0 = NO_MORE_DATA;
bStatusAction = STATUS_ACTION_NOTHING;
}
}
for(bIndex=0; bIndex<bPacketSize; bIndex++)
abIEP0Buffer[bIndex] = *pbIEP0Buffer++;
tEndPoint0DescriptorBlock.bIEPBCNT = bPacketSize; // & EPBCT_BYTECNT_MASK;
}
else
{
bStatusAction = STATUS_ACTION_NOTHING;
}
}
/***************************************************************************
* Function: SetupPacketInterruptHandler() *
* Programmer: Lobo Tai (lobotai@ti.com) *
* Description: This function is called by the UsbInterrupt function when *
* a setup packet is received. This function immediately sets both *
* OEP0 and IEP0 to a NAK state, sets the bUSBCTL to send/receive based *
* on the direction of the request, then proceeds to call the *
* usbDecodeAndProcessUsbRequest() function which determines which *
* function should be called to handle the given USB request. *
***************************************************************************/
void SetupPacketInterruptHandler(void)
{
// Hardware clears STALL in both data endpoints once valid setup packet is
// received. NAK both data endpoints.
tEndPoint0DescriptorBlock.bIEPBCNT = EPBCNT_NAK;
tEndPoint0DescriptorBlock.bOEPBCNT = EPBCNT_NAK;
bUSBSTA = USBSTA_SETUP; // from now, hardware will refer NAK bit in I/OEPBCNT
// Copy the MSB of bmRequestType to DIR bit of USBCTL to indicate the
// direction of the transfer.
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_INPUT) == USB_REQ_TYPE_INPUT)
bUSBCTL |= USBCTL_DIR;
else
bUSBCTL &= ~USBCTL_DIR;
// Clear the bStatusAction to indicate that, at this point, nothing is
// happening (it may be set to DATA_OUT by specific functions that
// expect a DATA packet following the setup packet).
bStatusAction = STATUS_ACTION_NOTHING;
// Call the function that determines which function should be called to
// handle the specific USB request.
usbDecodeAndProcessUsbRequest();
}
/***************************************************************************
* Function: OEP0InterruptHandler() *
* Programmer: Lobo Tai (lobotai@ti.com) *
* Description: This function is called by the UsbInterrupt function when *
* a USB interrupt is called by OEP0. This will happen once a data *
* transfer has been initialized by a USB function handler by calling *
* usbReceiveDataPacketOnEP0. *
***************************************************************************/
void OEP0InterruptHandler(void)
{
// We clear the IEP0 byte count since we have nothing to send out.
tEndPoint0DescriptorBlock.bIEPBCNT = 0x00;
// We now handle the interrupt based on the bStatusAction condition.
// If we are in a DATA_OUT condition, we call the usbReceiveNextPacketOnEP0
// function to copy the data payload to its correct buffer. If we are
// not expecting any data on OEP0, we set the stall flag to stall the
// endpoint and abort any additional data that may otherwise be
// sent.
if(bStatusAction == STATUS_ACTION_DATA_OUT)
usbReceiveNextPacketOnOEP0(); // Handle this data packet
else
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL; // We weren't expecting data
}
/***************************************************************************
* Function: IEP0InterruptHandler() *
* Programmer: Lobo Tai (lobotai@ti.com) *
* Description: This function is called by the UsbInterrupt function when *
* a USB interrupt is caused by IEP0. This will happen once the data *
* sent by calling usbSendNextPacketOnIEP0 and means the previous data *
* packet has been sent. At that point, there are two conditions: *
* either there is more data to send or there isn't. If there is, we *
* call usbSendNextPacketOnIEP0 to send the next packet of data. If *
* there isn't anymore data, we stall. However, if the bStatusAction *
* condition indicates that we were changing the devices address, we *
* do so at this point. *
***************************************************************************/
void IEP0InterruptHandler(void)
{
// We clear the OEP0 byte count since we are not expecting any data.
tEndPoint0DescriptorBlock.bOEPBCNT = 0x00;
// We now handle the interrupt based on the bStatusAction condition.
// If we are in a DATA_IN condition, we call the usbSendNextPacketOnIEP0
// function to send the next data payload packet. If we are in a
// Set Address mode, we modify the address. In any other case, we've
// sent all teh data we had to send, so we stall the endpoint to indicate
// there is no more data to send.
if(bStatusAction == STATUS_ACTION_DATA_IN)
usbSendNextPacketOnIEP0(); // Send the next data packet
else if(bStatusAction == STATUS_ACTION_SET_ADDRESS)
bFUNADR = bUsbDeviceAddress; // Set the device's address
else
tEndPoint0DescriptorBlock.bIEPCNFG |= EPCNF_STALL; // No more data to send
}
/***************************************************************************
* Function: USBInterrupt *
* Programmer: Craig Steiner (csteiner@vaultbbs.com) *
* Description: Handles the USB interrupts generated by the USB sectiob of *
* the part. This is actually External 0 interrupt on the 8051 at *
* 0x0003 in memory, but is used exclusively for USB interrupts on the *
* TUSB2136. *
* *
* Note: VECINT is cleared after being handled successfully so that the *
* next USB-related interrupt is made available to the handler. *
***************************************************************************/
interrupt [0x0003] void USBInterrupt(void)
{
// Disable all interrupts because this is critical code
EA = DISABLE;
// Select the appropriate interrupt handler depending on the VECINT value
switch (bVECINT)
{
case VECINT_OUTPUT_ENDPOINT0:
bVECINT = 0x00;
OEP0InterruptHandler();
break;
case VECINT_INPUT_ENDPOINT0:
bVECINT = 0x00;
IEP0InterruptHandler();
break;
case VECINT_INPUT_ENDPOINT1:
case 0x12:
bVECINT = 0x00;
IEP1InterruptHandler();
break;
case VECINT_STPOW_PACKET_RECEIVED:
bVECINT = 0x00;
bUSBSTA = USBSTA_STPOW;
SetupPacketInterruptHandler();
break;
case VECINT_SETUP_PACKET_RECEIVED:
// hardware will NAK data stage, no matter NAK bit in I/OEPBCNT
bVECINT = 0x00;
// bUSBSTA = USBSTA_SETUP; // from now, hardware will refer NAK bit in I/OEPBCNT
SetupPacketInterruptHandler();
break;
case VECINT_RSTR_INTERRUPT:
bVECINT = 0x00;
bUSBSTA = USBSTA_RSTR;
UsbReset();
break;
case VECINT_RESR_INTERRUPT:
bVECINT = 0x00;
bUSBSTA = USBSTA_RESR;
bSuspended = FALSE;
break;
case VECINT_SUSR_INTERRUPT:
bVECINT = 0x00;
bUSBSTA = USBSTA_SUSR;
bSuspended = TRUE;
break;
default:
bVECINT = 0x00;
break;
}
// End of ciritical code section, reenable interrupts
EA = ENABLE;
}
interrupt [0x0013] void P33Interrupt(void)
{
// Disable all interrupts because this is critical code
bUSBCTL |= USBCTL_RWUP;
bSuspended = FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -