STM32 usb_prop.c文件分析与usb_core.h一些数据定义分析
扫描二维码
随时随地手机看文章
usb_prop.c文件可以说是一个蛮重要的文件,因为USB的许多处理函数都在这里定义。在无论是在USB的建立阶段、数据阶段还是状态阶段的一些处理都在这个文件,USB标准函数请求的函数也在这个文件里。
usb_prop.c一开始就是一连串的结构体,如下:
DEVICE Device_Table =
{
EP_NUM, //被使用的端点数
1 //可以使用的端点数
};
DEVICE_PROP Device_Property =//注册一些CustomHID函数
{
CustomHID_init,//CustomHID的初始化函数
CustomHID_Reset,//CustomHID的复位函数
CustomHID_Status_In,//CustomHID状态输入函数
CustomHID_Status_Out,//CustomHID状态输出函数
CustomHID_Data_Setup,//CustomHID的处理有数据阶段的特殊类请求函数
CustomHID_NoData_Setup,//CustomHID的处理没有数据阶段特殊类请求函数
CustomHID_Get_Interface_Setting,//CustomHID获取接口及备用接口设置(是否可用)
CustomHID_GetDeviceDescriptor,//CustomHID获取设备描述符
CustomHID_GetConfigDescriptor,//CustomHID获取配置描述符
CustomHID_GetStringDescriptor,//CustomHID获取字符串描述符
0,//当前库未使用
0x40 /*MAX PACKET SIZE*/ //最大的包长度为64字节
};
/*注册USB标准请求的实现函数*/
USER_STANDARD_REQUESTS User_Standard_Requests =
{
CustomHID_GetConfiguration,//获取配置请求
CustomHID_SetConfiguration,//设置配置请求
CustomHID_GetInterface,//获取接口请求
CustomHID_SetInterface,//设置接口请求
CustomHID_GetStatus,//获取状态请求
CustomHID_ClearFeature,//清除属性请求
CustomHID_SetEndPointFeature,//设置端点属性请求
CustomHID_SetDeviceFeature,//设置设备属性请求
CustomHID_SetDeviceAddress//设置设备地址请求
};
/*注册设备描述符信息*/
ONE_DESCRIPTOR Device_Descriptor =
{
(uint8_t*)CustomHID_DeviceDescriptor, //注册设备描述符数组
CUSTOMHID_SIZ_DEVICE_DESC //设备描述符的长度
};
/*注册设备描述符信息*/
ONE_DESCRIPTOR Config_Descriptor =
{
(uint8_t*)CustomHID_ConfigDescriptor, //注册配置描述符数组
CUSTOMHID_SIZ_CONFIG_DESC //配置描述符的长度
};
/*注册报告描述符信息*/
ONE_DESCRIPTOR CustomHID_Report_Descriptor =
{
(uint8_t *)CustomHID_ReportDescriptor, //注册报告描述符数组
CUSTOMHID_SIZ_REPORT_DESC //报告描述符的长度
};
/*注册HID描述符信息*/
ONE_DESCRIPTOR CustomHID_Descriptor =
{
(uint8_t*)CustomHID_ConfigDescriptor + CUSTOMHID_OFF_HID_DESC, //注册HID描述符数组
CUSTOMHID_SIZ_HID_DESC //HID数组的长度
};
/*注册字符串描述符,包括语言ID、厂商、产品、序列号描述符*/
ONE_DESCRIPTOR String_Descriptor[4] =
{
{(uint8_t*)CustomHID_StringLangID, CUSTOMHID_SIZ_STRING_LANGID},//注册语言字符串描述符数组
{(uint8_t*)CustomHID_StringVendor, CUSTOMHID_SIZ_STRING_VENDOR},//注册厂商字符串描述符数组
{(uint8_t*)CustomHID_StringProduct, CUSTOMHID_SIZ_STRING_PRODUCT},//注册产品字符串描述符数组
{(uint8_t*)CustomHID_StringSerial, CUSTOMHID_SIZ_STRING_SERIAL}//注册序列号字符串描述符数组
};
应该看了很明白,这一系列的结构体就是注册一些处理函数。我们一个个分析。
先来说下 DEVICE Device_Table这个结构体,DEVICE这个结构体类型在usb_core.h中定义:
typedef struct _DEVICE
{
uint8_t Total_Endpoint; /*被使用的端点数*/
uint8_t Total_Configuration;/*还可以用的端点数*/
}
DEVICE;
这个结构体类型很简单,在结构体中定义了已经被使用的端点和没有被使用的端点,把他们两个放在一起方便查询和管理。
接下去的说说DEVICE_PROP
Device_Property 这个类型的结构体。这个结构体的前10个元素都是函数指针类型的,把一些常用的函数放在这里,而函数定义都在该结构体之后定义,有没有觉得像是语文中的关键句,把整个文件的概要全部浓缩在这个结构体中了,只要看这个结构体就可以把整个文件做什么了解个七七八八了。这样的结构使用起来也非常方便,比如说我想要使用CustomHID_init函数,只要写Device_Property.CustomHID_init不就可以了。我们必须学会这种方法。
DEVICE_PROP这个结构体类型还是在usb_core.h中定义:
typedef struct _DEVICE_PROP
{
void (*Init)(void); /*初始化设备*/
void (*Reset)(void); /*复位该设备*/
/*在控制传输中分三个过程:1.建立过程,2、可选的数据过程,3、状态过程*/
/* Device dependent process after the status stage */
void (*Process_Status_IN)(void);/*状态过程中,处理IN令牌包*/
void (*Process_Status_OUT)(void);/*状态过程中,处理OUT令牌包*/
/*在建立阶段的过程中,会有很多特殊类请求的数据阶段stage */
/*所有在数据阶段的特殊类请求都在Class_Data_Setup()函数中处理
Class_Data_Setup() 会响应去检查所有的特殊类请求,同时根据请求填充ENDPOINT_INFO结构信息
如果IN令牌包是期望的令牌包,则wLength和wOffset两个域会分别被填充成要发送的总字节数和要开始传输的位置
如果OUT令牌包是期盼的令牌包,则rLength和rOffser将会分别被填充成要接收的总字节数和要接收数据的缓冲区起始地址
如果请求有效,Class_Data_Setup返回SUCCESS,否则返回UNSUPPORT
注意:
因为GET_CONFIGURATION和GET_INTERFACE两个请求跟个别的类联系密切,所以他们会在该函数中检查和处理*/
RESULT (*Class_Data_Setup)(uint8_t RequestNo);
/*在建立过程中,会有很多特殊类请求的无数据阶段*/
/*所有的没有数据阶段的特殊请求都在Class_NoData_Setup这个函数中处理
Class_NoData_Setup()
会响应去检查所有特殊类请求,并且执行请求
注意:
因为SET_CONFIGURATION和SET_INTERFACE这两个请求跟个别的类联系密切,他们都会在该函数中被检查和处理*/
RESULT (*Class_NoData_Setup)(uint8_t RequestNo);
/*Class_Get_Interface_Setting()
这个函数时在usb_core.c文件中被调用来测试应用程序是否支持被选中的接口和备用接口
这个函数时由用户写的。如果应用程序支持接口和备用接口,则必须返回"SUCCESS",否则,返回"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);
/* 这个字段不是用于当前库版本。它是只保持兼容以前的版本*/
void* RxEP_buffer;
uint8_t MaxPacketSize;
}DEVICE_PROP;
接下去是USER_STANDARD_REQUESTS User_Standard_Requests这个结构体,在这个结构体中主要注册了USB标准请求的实现函数,当然这些函数也实在该结构体后面定义的。跟上面的DEVICE_PROP
Device_Property结构体类似,就不多讲了。
USER_STANDARD_REQUESTS 结构体也是在usb_core.h中定义:
typedef struct _USER_STANDARD_REQUESTS
{
void (*User_GetConfiguration)(void); /*获取配置*/
void (*User_SetConfiguration)(void); /*设置配置*/
void (*User_GetInterface)(void); /*获取接口*/
void (*User_SetInterface)(void); /*设置接口*/
void (*User_GetStatus)(void); /*获取状态*/
void (*User_ClearFeature)(void); /*清除特性*/
void (*User_SetEndPointFeature)(void); /*设置端点特性*/
void (*User_SetDeviceFeature)(void); /*设置设备特性*/
void (*User_SetDeviceAddress)(void); /*设置设备地址*/
}
USER_STANDARD_REQUESTS;
像ONE_DESCRIPTOR Device_Descriptor、ONE_DESCRIPTOR Config_Descriptor、ONE_DESCRIPTOR CustomHID_Report_Descriptor、ONE_DESCRIPTOR CustomHID_Descriptor、ONE_DESCRIPTOR String_Descriptor[4]这些结构体都不仔细讲了。贴出各个结构体的定义,依旧在usb_core.h中:
typedef struct OneDescriptor
{
uint8_t *Descriptor;
uint16_t Descriptor_Size;
}
ONE_DESCRIPTOR, *PONE_DESCRIPTOR;
接下去上面各个结构体注册的函数贴出来:
/*******************************************************************************
* Function Name : CustomHID_init.
* Description : CustomHID Mouse init routine.初始化
* 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();//获取序列号
pInformation->Current_Configuration = 0;
/* Connect the device */
PowerOn();//上电
/* Perform basic device initialization operations */
USB_SIL_Init();//执行基本的初始化操作,比如说设备IP和端点0的初始化
bDeviceState =