📄 usb_lib.c
字号:
Non_Standard_Request;
}
}
else if (sUSB_vSetup.USBwValue1 == 0x03 // String Descriptor
&& sUSB_vSetup.USBwIndex == 0x0409 // US english only
&& sUSB_vSetup.USBwValue0 < UI.Num_Strings) { // Valid index
vUSB_DataToSend = StringDescriptor[sUSB_vSetup.USBwValue0].Descriptor;
vUSB_length = StringDescriptor[sUSB_vSetup.USBwValue0].Size;
}
if (vUSB_DataToSend == NULL)
goto Req_Error;
if (vUSB_length > sUSB_vSetup.USBwLength)
vUSB_length = sUSB_vSetup.USBwLength;
return;
case GET_STATUS:
if (DADDR == 0) // On default state, to stall the request
goto Req_Error;
if (sUSB_vSetup.Flag != (TWO_wLength | NON0_wLength0)) // (wValue | wIndex) != 0 || wLength != 2
goto Req_Error;
// Request of Get Device Status
_vUSB_Report[0] = vUSB_Current_Feature & 0x03; // Remote wakeup and self power feature
_vUSB_Report[1] = 0;
vUSB_length = 2;
vUSB_DataToSend = _vUSB_Report;
return;
default:
goto Req_Error;
}
} // Device->Host, Standard, Device-Recipient
/*****************************************************************************
ROUTINE NAME : RequestType_0x01
DESCRIPTION : Standard process for request of (H->D, Standard, Interface)
*****************************************************************************/
void RequestType_0x01(void) // Host->Device, Standard, Interface-Recipient
{
// _vUSB_StateMachine = WAIT_STATUS_IN; // Expect Status IN stage follow the Setup Stage
if (DADDR == 0 || vUSB_Configuration == 0) // Not on configured state
goto Req_Error;
if (sUSB_vSetup.Flag & NON0_wLength)
goto Req_Error; // wLength != 0
if (sUSB_vSetup.USBbRequest == CLEAR_FEATURE) {
USER(USER_Clear_Feature_Int);
return;
}
else if (sUSB_vSetup.USBbRequest == SET_FEATURE) {
USER(USER_Set_Feature_Int);
return;
}
else if (sUSB_vSetup.USBbRequest == SET_INTERFACE) {
if (sUSB_vSetup.Flag & (NON0_wIndex1 | NON0_wValue1))
goto Req_Error; // (wIndex1 | wValue1) != 0
USER(USER_Set_Interface); // if (USER_Set_Interface == REQ_SUCCESS) return;
asm { // Check the return status of USER_Set_Interface
CP A, #REQ_SUCCESS
JRNE bad_setting
RET
bad_setting:
}
}
Req_Error:
Non_Standard_Request;
} // End of "Host->Device, Standard, Interface-Recipient"
/*****************************************************************************
ROUTINE NAME : RequestType_0x81
DESCRIPTION : Standard process for request of (D->H, Standard, Interface)
*****************************************************************************/
void RequestType_0x81(void) // Device->Host, Standard, Interface-Recipient
{
// _vUSB_StateMachine = IN_DATA; // Expect Data IN stage follow the Setup Stage
if (DADDR == 0 || vUSB_Configuration == 0) // Not on configured state
goto Req_Error;
if (sUSB_vSetup.Flag & (NON0_wValue | NON0_wIndex1))
goto Req_Error; // (wValue | wIndex1) != 0
if (sUSB_vSetup.USBbRequest == GET_STATUS) {
if (!(sUSB_vSetup.Flag & TWO_wLength))
goto Req_Error; // wLength != 2
// Check range of the interface number
if (sUSB_vSetup.USBwIndex0 >= UI.Num_Interface)
goto Req_Error;
_vUSB_Report[0] = 0; // Send a 0 Word according to spec.
_vUSB_Report[1] = 0; // Send a 0 Word according to spec.
vUSB_length = 2;
vUSB_DataToSend = _vUSB_Report;
return;
}
else if (sUSB_vSetup.USBbRequest == GET_INTERFACE) {
if (!(sUSB_vSetup.Flag & ONE_wLength))
goto Req_Error; // wLength != 1
USER(USER_Get_Interface);
asm LD _vUSB_Report[0], A; // _vUSB_Report[0] = USER_Get_Interface();
vUSB_length = 1;
vUSB_DataToSend = _vUSB_Report;
return;
}
Req_Error:
Non_Standard_Request;
} // End of "Device->Host, Standard, Interface-Recipient"
/*****************************************************************************
ROUTINE NAME : RequestType_0x02
DESCRIPTION : Standard process for request of (H->D, Standard, Endpoint)
*****************************************************************************/
void RequestType_0x02(void) // Host->Device, Standard, Endpoint-Recipient
{
if (DADDR == 0 || vUSB_Configuration == 0) // Not on configured state
goto Req_Error;
if ((sUSB_vSetup.Flag & (NON0_wValue | NON0_wLength | NON0_wIndex)) != NON0_wIndex0)
goto Req_Error; // (wValue | wIndex1 | wLength) != 0 || wIndex0 == 0
if (sUSB_vSetup.USBbRequest == CLEAR_FEATURE) {
_USB_Clr_Feature_EP();
USER(USER_Clear_Feature_EP);
return;
}
else if (sUSB_vSetup.USBbRequest == SET_FEATURE) {
_USB_Set_Feature_EP();
USER(USER_Set_Feature_EP);
return;
}
Req_Error:
Non_Standard_Request;
} // End of "Host->Device, Standard, Endpoint-Recipient"
/*****************************************************************************
ROUTINE NAME : RequestType_0x82
DESCRIPTION : Standard process for request of (D->H, Standard, Endpoint)
*****************************************************************************/
void RequestType_0x82(void) // Device->Host, Standard, Endpoint-Recipient
{
char EP_State;
// _vUSB_StateMachine = IN_DATA; // Expect Data IN stage follow the Setup Stage
if (sUSB_vSetup.USBbRequest != GET_STATUS)
goto Req_Error;
if (DADDR == 0)
goto Req_Error; // Error on default state
if ((sUSB_vSetup.Flag & (NON0_wValue | TWO_wLength)) != TWO_wLength)
goto Req_Error; // wValue != 0 || wLength != 2
if (vUSB_Configuration == 0 && (sUSB_vSetup.USBwIndex & ~0x80))
goto Req_Error; // Error on address state if it is not EP0
EP_State = _USB_GetEPStatus(sUSB_vSetup.USBwIndex0);
if (EP_State == EP_DISABLE || EP_State == REQ_UNSUPPORT)
Req_Error:
Non_Standard_Request;
_vUSB_Report[0] = (EP_State == EP_STALL);
_vUSB_Report[1] = 0;
vUSB_length = 2;
vUSB_DataToSend = _vUSB_Report;
} // End of "Device->Host, Standard, Endpoint-Recipient"
/*****************************************************************************
ROUTINE NAME : _USB_CopydataIN
DESCRIPTION : Copy data to endpoint transmit buffer
Adjust the pointer and counter
*****************************************************************************/
void _USB_CopydataIN(void)
{
unsigned char TransferLength;
if (vUSB_length >= MAX_PACKET_SIZE) {
if (vUSB_length == MAX_PACKET_SIZE)
_vUSB_StateMachine = ONE_MORE_IN;
TransferLength = MAX_PACKET_SIZE;
}
else
TransferLength = vUSB_length;
CNT0TXR = TransferLength;
vUSB_length -= TransferLength;
if (vUSB_DataToSend) { // Data from the library
asm {
LD X, TransferLength
DEC X
_Copy_Byte:
LD A, ([vUSB_DataToSend.w],X)
LD (EP0_IN,X), A
DEC X
JRPL _Copy_Byte
}
vUSB_DataToSend += TransferLength;
}
else { // Data from user space
asm LD A, TransferLength;
USER(USER_CopydataIN);
}
vUSB_offset += CNT0TXR;
}
/*****************************************************************************
ROUTINE NAME : _USB_CopydataOUT
DESCRIPTION : Copy data from endpoint receive buffer to user space
Adjust the pointer and counter
Return error if the received data length is too long
*****************************************************************************/
char _USB_CopydataOUT(void)
{
if (_vUSB_Data_OUT_Len > vUSB_length)
return REQ_ERROR;
asm LD A, _vUSB_Data_OUT_Len;
USER(USER_CopydataOUT);
vUSB_offset += _vUSB_Data_OUT_Len;
vUSB_length -= _vUSB_Data_OUT_Len;
if (vUSB_length == 0)
_vUSB_StateMachine = ONE_MORE_OUT;
return (REQ_SUCCESS);
}
/*****************************************************************************
ROUTINE NAME : Init_USB
DESCRIPTION : Initialize the USB Macrocell
*****************************************************************************/
void Init_USB(void)
{
_vUSB_StateMachine = 0;
vUSB_Current_Feature = 0;
vUSB_Configuration = 0;
_EP_RxTx_Flag = 0; // Clear flag for non-control EPs
#ifdef USB_POLLING_MODEL
// In polling model, set USB as highest interrupt level 3
// All the other interrupt source are set as level 1
// ITSPR0 = 0x5D;
#else
// In interrupt model, set USB as highest interrupt level 2
// All the other interrupt source are set as level 1
ITSPR0 = 0x51;
#endif
ITSPR0 = 0x15; // DTC interrupt is in level 2@jin0823
ITSPR1 = 0x57; // USB interrupt is in level 3
// ITSPR2 = 0x55;
ITSPR2 = 0x5f; // PC interrupt & timer interrupt is level 3 @jin0823
ITSPR3 = 0xF5;
USBCTLR = 0x00; // No-force USB reset and Power on 3.3V regulator
USBISTR = 0; // Clear pending flags
USBIMR = IMR_RESET; // Enable USB reset interrupt only
}
/*****************************************************************************
ROUTINE NAME : USB_Reset
DESCRIPTION : Called when USB cell is reset
*****************************************************************************/
void USB_Reset(void)
{
Init_USB();
DADDR = 0x00; // Enable this device at USB address zero
CNT0RXR = MAX_PACKET_SIZE; // Receive data on endpoint 0
CNT0TXR = 0;
EP0R = 0x01; // TX disable, RX Stall (only SETUP token will be ACKed)
USBIMR = UI.Interrupt_Mask;
USERIT(USER_Reset);
}
/*****************************************************************************/
// EP_RXR_Adr has the address of all EP?RXR register.
// The value is 0x00 if the EP?RXR is not exist.
#pragma CONST_SEG USB_CONST
const unsigned char *const near EP_RXR_Adr[6] = {
&EP0R,
#ifdef MCU_ST7265
&EP1RXR,
#else
0x00,
#endif
&EP2RXR,
0x00,
0x00,
0x00
};
// EP_TXR_Adr has the address of all EP?TXR register.
// The value is 0x00 if the EP?TXR is not exist.
const unsigned char *const near EP_TXR_Adr[6] = {
0x00,
&EP1TXR,
&EP2TXR,
#ifdef MCU_ST7265
0x00,
0x00,
0x00
#else
&EP3TXR,
&EP4TXR,
&EP5TXR
#endif
};
/*****************************************************************************
ROUTINE NAME : _USB_GetEPStatus
INPUT/OUTPUT :
Endpoint: The endpoint number which the status is going to return
Rx status is returned if bit7 = 0
Tx status is returned if bit7 = 1
DESCRIPTION : Used to get the current Status of Endpoint
*****************************************************************************/
#pragma NO_ENTRY
char _USB_GetEPStatus(char Endpoint)
{
asm {
TNZ A
JRMI Tx_Status
// JRNE Non_rEP0
// LD A, EP0R
// JRT EP_Status
//Non_rEP0:
CP A, #5
JRUGT No_EPs
LD X, A
LD X, (EP_RXR_Adr,X)
JREQ No_EPs
gEP_Status:
LD A, (X)
EP_Status:
AND A, #0x03
RET
Tx_Status:
AND A, #0x7F
JRNE Non_tEP0
LD A, EP0R
SWAP A
JRT EP_Status
Non_tEP0:
CP A, #5
JRUGT No_EPs
LD X, A
LD X, (EP_TXR_Adr,X)
JRNE gEP_Status
No_EPs:
}
return REQ_UNSUPPORT;
}
/*****************************************************************************
ROUTINE NAME : _USB_Clr_Feature_EP
DESCRIPTION : Clear STALL condition of the specified EP if it is not DISABLED
The specified EP is given in sUSB_vSetup.USBwIndex0
*****************************************************************************/
void _USB_Clr_Feature_EP(void)
{
asm {
LD A, sUSB_vSetup.USBwIndex0
AND A, #0x7F
CP A, #6
JRUGE EP_Error
LD X, A
LD A, sUSB_vSetup.USBwIndex0
JRMI Clear_Feature_Tx
LD X, (EP_RXR_Adr, X)
JRT Set_Feature
EP_Error:
JP RequestError
Clear_Feature_Tx:
LD X, (EP_TXR_Adr, X)
Set_Feature:
JREQ EP_Error // Error: if the EP is not exist
LD A, (X)
AND A, #0x03
JREQ EP_Error // Error: if the EP is EP_DISABLE
CP A, #EP_STALL
JRNE End_Clear // Return if the EP is not in STALL
LD A, (X)
AND A, #0xF8
OR A, #EP_NAK // Change the endpoint state to NAK
LD (X), A
End_Clear:
}
}
/*****************************************************************************
ROUTINE NAME : USB_Set_Feature_EP
INPUT/OUTPUT : None
DESCRIPTION : Set STALL condition of the specified EP if it is not DISABLED
The specified EP is given in sUSB_vSetup.USBwIndex0
*****************************************************************************/
void _USB_Set_Feature_EP(void)
{
asm {
LD A, sUSB_vSetup.USBwIndex0
AND A, #0x7F
CP A, #6
JRUGE EP_Error
LD X, A
LD A, sUSB_vSetup.USBwIndex0
JRMI Set_Feature_Tx
LD X, (EP_RXR_Adr, X)
JRT Set_Feature
EP_Error:
JP RequestError
Set_Feature_Tx:
LD X, (EP_TXR_Adr, X)
Set_Feature:
JREQ EP_Error // Error: if the EP is not exist
LD A, (X)
BCP A, #0x03
JREQ EP_Error // Error: if the EP is EP_DISABLE
AND A, #0xFC
OR A, #EP_STALL
LD (X), A
}
}
/*****************************************************************************
ROUTINE NAME : USB_Remote_Wakeup
INPUT/OUTPUT : return SUCCESS if device is in suspend state, ERROR instead
DESCRIPTION : Send a resume signal within 3ms for 8MHz CPU clock, 6ms for 4MHz
12ms for 2MHz. At least the resume signal must be longer
than 1ms and lower than 15ms
*****************************************************************************/
char USB_Remote_Wakeup(void)
{
unsigned int loop;
if ((USBCTLR & 0x02) && (vUSB_Current_Feature & 0x02)) { // SUSPEND MODE and RWU enabled
USBCTLR &= ~0x02; // Exit from SUSPEND mode
USBCTLR |= 0x08; // Force RESUME signal
// CPU frequency = 8MHz => Resume signal active for 3ms
// CPU frequency = 4MHz => Resume signal active for 6ms
// CPU frequency = 2MHz => Resume signal active for 12ms
for (loop = 3 * 340; loop; loop--) // loop to keep the Resume signal for at least 3ms
asm nop;
USBCTLR &= ~0x08; // stop RESUME signal
return REQ_SUCCESS;
}
else
return REQ_ERROR;
};
/**************** (c) 2000 STMicroelectronics *******************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -