The usb_prop.c file is a very important file because many USB processing functions are defined here. Some processing in the USB establishment phase, data phase or status phase is in this file, and the USB standard function request function is also in this file.
usb_prop.c starts with a series of structures, as follows:
DEVICE Device_Table =
{
EP_NUM, //Number of endpoints used
1 //The number of endpoints that can be used
};
DEVICE_PROP Device_Property = //Register some CustomHID functions
{
CustomHID_init, //CustomHID initialization function
CustomHID_Reset, //CustomHID reset function
CustomHID_Status_In, //CustomHID status input function
CustomHID_Status_Out, //CustomHID status output function
CustomHID_Data_Setup, //CustomHID processing has a special class request function in the data stage
CustomHID_NoData_Setup, //CustomHID processing no data stage special class request function
CustomHID_Get_Interface_Setting, //CustomHID gets the interface and backup interface settings (whether available)
CustomHID_GetDeviceDescriptor, //CustomHID gets the device descriptor
CustomHID_GetConfigDescriptor, //CustomHID gets the configuration descriptor
CustomHID_GetStringDescriptor, //CustomHID gets string descriptor
0, //Current library is not used
0x40 /*MAX PACKET SIZE*/ //The maximum packet length is 64 bytes
};
/*Register USB standard request implementation function*/
USER_STANDARD_REQUESTS User_Standard_Requests =
{
CustomHID_GetConfiguration, //Get configuration request
CustomHID_SetConfiguration, //Set configuration request
CustomHID_GetInterface, //Get interface request
CustomHID_SetInterface, //Set interface request
CustomHID_GetStatus, //Get status request
CustomHID_ClearFeature, //Clear attribute request
CustomHID_SetEndPointFeature, //Set endpoint attribute request
CustomHID_SetDeviceFeature, //Set device attribute request
CustomHID_SetDeviceAddress //Set device address request
};
/*Register device descriptor information*/
ONE_DESCRIPTOR Device_Descriptor =
{
(uint8_t*)CustomHID_DeviceDescriptor, //Register device descriptor array
CUSTOMHID_SIZ_DEVICE_DESC //The length of the device descriptor
};
/*Register device descriptor information*/
ONE_DESCRIPTOR Config_Descriptor =
{
(uint8_t*)CustomHID_ConfigDescriptor, //Register configuration descriptor array
CUSTOMHID_SIZ_CONFIG_DESC //Configuration descriptor length
};
/*Register report descriptor information*/
ONE_DESCRIPTOR CustomHID_Report_Descriptor =
{
(uint8_t *)CustomHID_ReportDescriptor, //Register report descriptor array
CUSTOMHID_SIZ_REPORT_DESC //The length of the report descriptor
};
/*Register HID descriptor information*/
ONE_DESCRIPTOR CustomHID_Descriptor =
{
(uint8_t*)CustomHID_ConfigDescriptor + CUSTOMHID_OFF_HID_DESC, //Register HID descriptor array
CUSTOMHID_SIZ_HID_DESC //The length of the HID array
};
/*Register string descriptors, including language ID, manufacturer, product, and serial number descriptors*/
ONE_DESCRIPTOR String_Descriptor[4] =
{
{(uint8_t*)CustomHID_StringLangID, CUSTOMHID_SIZ_STRING_LANGID}, //Register language string descriptor array
{(uint8_t*)CustomHID_StringVendor, CUSTOMHID_SIZ_STRING_VENDOR}, //Registered vendor string descriptor array
{(uint8_t*)CustomHID_StringProduct, CUSTOMHID_SIZ_STRING_PRODUCT}, //Register product string descriptor array
{(uint8_t*)CustomHID_StringSerial, CUSTOMHID_SIZ_STRING_SERIAL} //Register serial number string descriptor array
};
It should be clear that this series of structures is to register some processing functions. Let's analyze them one by one.
Let's talk about the DEVICE Device_Table structure first. The DEVICE structure type is defined in usb_core.h:
typedef struct _DEVICE
{
uint8_t Total_Endpoint; /*Number of endpoints used*/
uint8_t Total_Configuration;/*Number of endpoints that can be used*/
}
DEVICE;
This structure type is very simple. It defines the endpoints that have been used and the endpoints that have not been used. Putting the two together facilitates query and management.
Next, let’s talk about DEVICE_PROP
Device_Property is a structure of this type. The first 10 elements of this structure are all function pointer types. Some commonly used functions are placed here, and the function definitions are defined after this structure. Do you feel like a key sentence in Chinese? The outline of the entire file is condensed in this structure. Just by looking at this structure, you can understand what the entire file does. This structure is also very convenient to use. For example, if I want to use the CustomHID_init function, I just need to write Device_Property.CustomHID_init. We must learn this method.
The DEVICE_PROP structure type is still defined in usb_core.h:
typedef struct _DEVICE_PROP
{
void (*Init)(void); /*Initialize device*/
void (*Reset)(void); /*Reset the device*/
/* There are three processes in control transmission: 1. Establishment process, 2. Optional data process, 3. Status process*/
/* Device dependent process after the status stage */
void (*Process_Status_IN)(void);/*Processing IN token packet*/
void (*Process_Status_OUT)(void);/*Processing OUT token packet*/
/*During the establishment phase, there will be many special class request data stages */
/*All special class requests in the data phase are handled in the Class_Data_Setup() function
Class_Data_Setup() will respond to all special class requests and fill in the ENDPOINT_INFO structure information according to the request
If the IN token packet is the expected token packet, the wLength and wOffset fields are filled with the total number of bytes to be sent and the position to start the transmission, respectively.
If the OUT token packet is the expected token packet, rLength and rOffser will be filled with the total number of bytes to be received and the starting address of the buffer to receive the data, respectively.
If the request is valid, Class_Data_Setup returns SUCCESS, otherwise it returns UNSUPPORT
Notice:
Because the GET_CONFIGURATION and GET_INTERFACE requests are closely related to individual classes, they will be checked and processed in this function*/
RESULT (*Class_Data_Setup)(uint8_t RequestNo);
/*During the establishment process, there will be many data-free stages for special class requests*/
/*All special requests without data phase are handled in the Class_NoData_Setup function
Class_NoData_Setup()
Will respond to check all special class requests and execute the requests
Notice:
Because the two requests SET_CONFIGURATION and SET_INTERFACE are closely related to individual classes, they will be checked and processed in this function*/
RESULT (*Class_NoData_Setup)(uint8_t RequestNo);
/*Class_Get_Interface_Setting()
This function is called in the usb_core.c file to test whether the application supports the selected interface and the alternate interface.
This function is written by the user. If the application supports the interface and the alternate interface, it must return "SUCCESS", otherwise, it returns "UNSUPPORT"*/
RESULT (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting);
uint8_t* (*GetDeviceDescriptor)(uint16_t Length);
uint8_t* (*GetConfigDescriptor)(uint16_t Length);
uint8_t* (*GetStringDescriptor)(uint16_t Length);
/* This field is not used in the current library version. It is only kept for compatibility with previous versions */
void* RxEP_buffer;
uint8_t MaxPacketSize;
}DEVICE_PROP;
Next is the USER_STANDARD_REQUESTS User_Standard_Requests structure, which mainly registers the implementation functions of USB standard requests. Of course, these functions are also defined after this structure.
The Device_Property structure is similar, so I won’t go into details.
The USER_STANDARD_REQUESTS structure is also defined in usb_core.h:
typedef struct _USER_STANDARD_REQUESTS
{
void (*User_GetConfiguration)(void); /*Get configuration*/
void (*User_SetConfiguration)(void); /*Set configuration*/
void (*User_GetInterface)(void); /*Get interface*/
void (*User_SetInterface)(void); /*Set interface*/
void (*User_GetStatus)(void); /*Get status*/
void (*User_ClearFeature)(void); /*Clear feature*/
void (*User_SetEndPointFeature)(void); /*Set endpoint features*/
void (*User_SetDeviceFeature)(void); /*Set device features*/
void (*User_SetDeviceAddress)(void); /*Set device address*/
}
USER_STANDARD_REQUESTS;
Structures like ONE_DESCRIPTOR Device_Descriptor, ONE_DESCRIPTOR Config_Descriptor, ONE_DESCRIPTOR CustomHID_Report_Descriptor, ONE_DESCRIPTOR CustomHID_Descriptor, and ONE_DESCRIPTOR String_Descriptor[4] are not explained in detail. Here are the definitions of each structure, which are still in usb_core.h:
typedef struct OneDescriptor
{
uint8_t *Descriptor;
uint16_t Descriptor_Size;
}
ONE_DESCRIPTOR, *PONE_DESCRIPTOR;
Next, paste the functions registered by each structure above:
/*******************************************************************************
* Function Name : CustomHID_init.
* Description: CustomHID Mouse init routine. Initialization
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void CustomHID_init(void)
{
/* Update the serial number string descriptor with the data from the unique
ID*/
Get_SerialNum(); //Get the serial number
pInformation->Current_Configuration = 0;
/* Connect the device */
PowerOn(); //Power on
/* Perform basic device initialization operations */
USB_SIL_Init(); //Perform basic initialization operations, such as initialization of device IP and endpoint 0
bDeviceState = UNCONNECTED; //Set the state to unconnected
}
/*******************************************************************************
* Function Name : CustomHID_Reset.
* Description : CustomHID Mouse reset routine.复位
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void CustomHID_Reset(void)
{
/* Set CustomHID_DEVICE as not configured */
pInformation->Current_Configuration = 0; //Set the current configuration to 0, indicating that it has not been configured
pInformation->Current_Interface = 0; //Default interface
/* Current Feature initialization */
pInformation->Current_Feature = CustomHID_ConfigDescriptor[7]; //Current attributes, bmAttributes: some characteristics of the device, 0xc0 means self-powered, does not support remote wake-up
#ifdef STM32F10X_CL
/* EP0 is already configured in DFU_Init() by USB_SIL_Init() function */
/* Init EP1 IN snd EP1 OUT as Interrupt endpoint */
OTG_DEV_EP_Init(EP1_IN, OTG_DEV_EP_TYPE_INT, EP1_SIZE);
OTG_DEV_EP_Init(EP1_OUT, OTG_DEV_EP_TYPE_INT, EP1_SIZE);
#else
SetBTABLE(BTABLE_ADDRESS);
/* Initialize Endpoint 0 */
SetEPType(ENDP0, EP_CONTROL); //Set endpoint 1 as the control endpoint
SetEPTxStatus(ENDP0, EP_TX_STALL); //Set endpoint 0 send delay
SetEPRxAddr(ENDP0, ENDP0_RXADDR); //Set the receive buffer address of endpoint 0
SetEPTxAddr(ENDP0, ENDP0_TXADDR); //Set the send buffer address of endpoint 0
Clear_Status_Out(ENDP0); //Clear the status of endpoint 0
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); //Set the receive count of endpoint 0
SetEPRxValid(ENDP0); //Enable receiving status
/* Initialize Endpoint 1 */
SetEPType(ENDP1, EP_INTERRUPT); //Set endpoint 1 as interrupt control endpoint
SetEPRxAddr(ENDP1, ENDP1_RXADDR); //Set the receive buffer address of endpoint 1
SetEPRxCount(ENDP1, REPORT_COUNT); //Set the receive count of endpoint 1
SetEPRxStatus(ENDP1, EP_RX_VALID); //Set endpoint 1 to receive valid
//SetEPTxStatus(ENDP1, EP_TX_DIS);
/* Initialize Endpoint 2 */
SetEPType(ENDP2, EP_INTERRUPT); //Set endpoint 2 as interrupt control endpoint
SetEPTxAddr(ENDP2, ENDP2_TXADDR); //Set the receive buffer address of endpoint 2
SetEPTxCount(ENDP2, REPORT_COUNT); //Set the receive count of endpoint 2
// SetEPTxStatus(ENDP2, EP_TX_DIS);
SetEPTxStatus(ENDP2, EP_TX_NAK); //Set endpoint 2 to receive no response
bDeviceState = ATTACHED; //Set the device state to ATTACHED state
/* Set this device to response on default address */
SetDeviceAddress(0); //Set the device to the default address
#endif /* STM32F10X_CL */
bDeviceState = ATTACHED;
}
/*******************************************************************************
* Function Name : CustomHID_SetConfiguration.
* Description: Update device configuration status
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void CustomHID_SetConfiguration(void)
{
DEVICE_INFO *pInfo = &Device_Info;
if (pInfo->Current_Configuration != 0)
{
/* Device configured */
bDeviceState = CONFIGURED;
}
}
/*******************************************************************************
* Function Name : CustomHID_SetConfiguration.
* Description: Update the addressing status of the device
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void CustomHID_SetDeviceAddress (void)
{
bDeviceState = ADDRESSED;
}
/*******************************************************************************
* Function Name : CustomHID_Status_In.
* Description: Status input function
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void CustomHID_Status_In(void)
{}
/*******************************************************************************
* Function Name : CustomHID_Status_Out
* Description: Status output function
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void CustomHID_Status_Out(void)
{}
/*******************************************************************************
* Function Name : CustomHID_Data_Setup
* Description: Process special type requests with data phase
* Input : Request Nb.
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
RESULT CustomHID_Data_Setup(uint8_t RequestNo)
{
uint8_t *(*CopyRoutine)(uint16_t); //Define a pointer to a function pointer
CopyRoutine = NULL;
if ((RequestNo == GET_DESCRIPTOR) //It is a GET_DESCRIPTOR request, see circle P75
&& (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) //The request type is a standard request, and the recipient of the request is an interface
&& (pInformation->USBwIndex0 == 0)) //Other descriptors other than language ID string descriptors
{
if (pInformation->USBwValue1 == REPORT_DESCRIPTOR) //It is the report descriptor
{
CopyRoutine = CustomHID_GetReportDescriptor; //CopyRoutine points to the function pointer to get the report descriptor
}
else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE) // is the HID descriptor
{
CopyRoutine = CustomHID_GetHIDDescriptor; //CopyRoutine points to the function pointer to get the HID descriptor
}
} /* End of GET_DESCRIPTOR */
/*** GET_PROTOCOL ***/
else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) //The request type is a class request and the recipient is an interface request
&& RequestNo == GET_PROTOCOL) //Get the protocol
{
CopyRoutine = CustomHID_GetProtocolValue; //Get the value of the protocol
}
if (CopyRoutine == NULL) //If the length is 0, CopyRoutine=NULL
{
return USB_UNSUPPORT; //USB is not connected
}
pInformation->Ctrl_Info.CopyData = CopyRoutine; //注册CopyData函数
pInformation->Ctrl_Info.Usb_wOffset = 0; //Data offset
(*CopyRoutine)(0); //Call CopyData() function
return USB_SUCCESS; //返回 USB_SUCCESS
}
/*******************************************************************************
* Function Name : CustomHID_NoData_Setup
* Description: Handle special class requests without data phase
* Input : Request Nb.
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
RESULT CustomHID_NoData_Setup(uint8_t RequestNo)
{
if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) //Class request, interface reception
&& (RequestNo == SET_PROTOCOL)) //Set the protocol
{
return CustomHID_SetProtocol();
}
else
{
return USB_UNSUPPORT;
}
}
/*******************************************************************************
* Function Name : CustomHID_GetDeviceDescriptor.
* Description: Get device descriptor
* Input : Length
* Output : None.
* Return : The address of the device descriptor.
*******************************************************************************/
uint8_t *CustomHID_GetDeviceDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &Device_Descriptor);
}
/*******************************************************************************
* Function Name : CustomHID_GetConfigDescriptor.
* Description: Get configuration descriptor
* Input : Length
* Output : None.
* Return : The address of the configuration descriptor.
*******************************************************************************/
uint8_t *CustomHID_GetConfigDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &Config_Descriptor);
}
/*******************************************************************************
* Function Name : CustomHID_GetStringDescriptor
* Description: Get the character descriptor according to the index
* Input : Length
* Output : None.
* Return : The address of the string descriptors.
*******************************************************************************/
uint8_t *CustomHID_GetStringDescriptor(uint16_t Length)
{
uint8_t wValue0 = pInformation->USBwValue0;
if (wValue0 > 4)
{
return NULL;
}
else
{
return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]);
}
}
/*******************************************************************************
* Function Name : CustomHID_GetReportDescriptor.
* Description: Get report descriptor
* Input : Length
* Output : None.
* Return : The address of the configuration descriptor.
*******************************************************************************/
uint8_t *CustomHID_GetReportDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &CustomHID_Report_Descriptor);
}
/*******************************************************************************
* Function Name : CustomHID_GetHIDDescriptor.
* Description: Get HID descriptor
* Input : Length
* Output : None.
* Return : The address of the configuration descriptor.
*******************************************************************************/
uint8_t *CustomHID_GetHIDDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &CustomHID_Descriptor);
}
/*******************************************************************************
* Function Name : CustomHID_Get_Interface_Setting.
* Description: Test whether the interface and its backup interface are available
* Input : - Interface : interface number.
* - AlternateSetting : Alternate Setting number.
* Output : None.
* Return : USB_SUCCESS or USB_UNSUPPORT.
*******************************************************************************/
RESULT CustomHID_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting)
{
if (AlternateSetting > 0) //The alternate number is greater than 0
{
return USB_UNSUPPORT;
}
else if (Interface > 0) //The interface number is greater than 0
{
return USB_UNSUPPORT;
}
return USB_SUCCESS;
}
/*******************************************************************************
* Function Name : CustomHID_SetProtocol
* Description: Set the protocol request function used by the interface
* Input : None.
* Output : None.
* Return : USB SUCCESS.
*******************************************************************************/
RESULT CustomHID_SetProtocol(void)
{
uint8_t wValue0 = pInformation->USBwValue0; //Get the USBwValue value in the device information
ProtocolValue = wValue0;
return USB_SUCCESS;
}
/*******************************************************************************
* Function Name : CustomHID_GetProtocolValue
* Description: Get the value of the protocol
* Input : Length.
* Output : None.
* Return : address of the protcol value.
*******************************************************************************/
uint8_t *CustomHID_GetProtocolValue(uint16_t Length)
{
if (Length == 0) //Length is 0
{
pInformation->Ctrl_Info.Usb_wLength = 1; //The length to be sent is 1
return NULL;
}
else
{
return (uint8_t *)(&ProtocolValue); //Return the value of the protocol
}
}
Previous article:STM32 USB related registers
Next article:STM32 usb_pwr.c file analysis
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Why software-defined vehicles transform cars from tools into living spaces
- How Lucid is overtaking Tesla with smaller motors
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Three steps to govern hybrid multicloud environments
- Three steps to govern hybrid multicloud environments
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- TILEBOX battery voltage problem
- Internet of Things Era | Which industries benefit from the application of Internet of Things
- FPGA Deep Analysis.pdf
- C51 uses macro definition to replace printf function
- Understanding the CAN bus from the bottom up
- [STM32WB55 Review] +USB Dongle Bricked
- STM32F429 USB_OTG_FS (PA11, PA12) read USB disk problem
- PoE and PoE+, an article to understand Power over Ethernet
- How to control trace impedance of PCB for signal integrity?
- Disassembling the USB wireless network card, the circuit scheme is very classic