⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 HID 设备测试程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*===============================================================================//
//== 文 件 名:USB.c
//== author	 :gnsusn
//== 说    明:对 USB 协议的处理
//== 修改日志:2008.8.20 创建文件
//== 
//===============================================================================*/
#include <reg52.h>
#include "USB.h"
#include "PDIUSBD12.h"
#include "functions.h"
#include "hid_report.h"

//***************************************************************************************
//=======================================================================================

EPPFLAGS 				bEPPflags;				//== 程序运行状态标志
CONTROL_DATA_BUFF 		Control_Data;			//== setup 包

unsigned char usb_transmit_buf[8];				//== 用于给USB发送数据的缓冲区
unsigned char hid_idle;							//== HID 设备的idle状态
unsigned char hid_protocol;						//== HID 当前协议

//*********************************************************************************
//== 协议中用到的数据
code unsigned char LANGUAGE_ID[4] = {0x04,0x03,0x09,0x04};		//== 字符串描述符所用的语言种类
									
code unsigned char device_serial_number[] =						//== 设备序列号	
{
	22,STRING_DESCRIPTOR,'2',0,'0',0,'0',0,
	'8',0,'-',0,'0',0,'8',0,'-',0,'2',0,'3',0
};

code unsigned char ManufacturerString[28] =						//== 厂商字符串
{
	28,STRING_DESCRIPTOR,0x3F,0x80,0x11,0x68,0x7E,0x67,0x84,
	0x76,'U',0x00,'S',0x00,'B',0x00,'-',0x00,'H',0x00,'I',
	0x00,'D',0x00,0xBE,0x8B,0x07,0x59
};

code unsigned char ProducterString[30] =						//== 产品字符串
{
	30,STRING_DESCRIPTOR,0x3F,0x80,0x11,0x68,0x7E,0x67,0x84,
	0x76,'U',0x00,'S',0x00,'B',0x00,'-',0x00,'-',0x00,'H',
	0x00,'I',0x00,'D',0x00,0xBE,0x8B,0x07,0x59
};

code DEVICE_DESCRIPTOR_STRUCT device_descriptor =				//== 设备描述符
{
	sizeof(DEVICE_DESCRIPTOR_STRUCT),							//== 设备描述符的字节数大小
	DEVICE_DESCRIPTOR,											//== 设备描述符类型编号
	SWAP16(0x0110),												//== USB版本号
	0x03,														//== USB分配的设备类代码
	0x00,														//== USB分配的子类代码
	0x00,														//== USB分配的设备协议代码
	0x10,														//== 端点0的最大包大小
	SWAP16(0x0471),												//== 厂商编号VID,这里只是作为测试用,请使用自己的VID
	SWAP16(0x1234),												//== 产品编号PID,这里只是作为测试用,请使用自己的PID
	SWAP16(0x0001),												//== 设备出厂编号
	0x01,														//== 设备厂商字符串的索引
	0x02,														//== 描述产品字符串的索引
	0x03,														//== 描述设备序列号字符串的索引
	0x01														//== 可能的配置数量
};

//== 定义配置,接口,端点等描述符结构体,因为它们是随配置描述符一起返回的
typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
{
	CONFIGURATION_DESCRIPTOR_STRUCT	configuration_descriptor;
	INTERFACE_DESCRIPTOR_STRUCT		interface_descriptor;
	HID_DESCRIPTOR_STRUCT			hid_descriptor;
	ENDPOINT_DESCRIPTOR_STRUCT		endpoint_descriptor[ENDPOINT_NUMBER];
}CON_INT_ENDP_DESCRIPTOR_STRUCT;

code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor =
{
	//configuration_descriptor									//配置描述符
	{
		sizeof(CONFIGURATION_DESCRIPTOR_STRUCT),				//== 配置描述符的字节数大小
		CONFIGURATION_DESCRIPTOR,								//== 配置描述符类型编号
		SWAP16(sizeof(CON_INT_ENDP_DESCRIPTOR_STRUCT)),
		0x01,													//== 只包含一个接口
		0x01,													//== 该配置的编号
		0x00,													//== iConfiguration字段
		0x80,													//== 采用总线供电
		0xC8													//== 从总线获取最大电流400mA
	},
	//interface_descritor										//== 接口描述符
	{
		sizeof(INTERFACE_DESCRIPTOR_STRUCT),					//== 接口描述符的字节数大小
		INTERFACE_DESCRIPTOR,									//== 接口描述符类型编号
		0x00,													//== 接口编号为0
		0x00,													//== 该接口描述符的编号
		ENDPOINT_NUMBER,										//== 该接口使用的端点数量,非0端点数量为4,只使用端点主端点输入和输出
		0x03,													//== 人机接口设备(HID)类
		0x00,													//== 使用的子类:未定义
		0x00,													//== 使用的协议:未定义
		0x00													//== 接口描述符字符串索引
	},
	//hid_descriptor
	{
		sizeof(HID_DESCRIPTOR_STRUCT),							//== HID描述符的字节数大小
		HID_DESCRIPTOR,											//== HID描述符类型编号
		0x1001,													//== HID类协议版本号,为1.1
		0x00,													//== 固件的国家地区代号,0x21为美国
		NUM_SUB_DESCRIPTORS,									//== 下级描述符的数量
		{
			{
				REPORT_DESCRIPTOR,								//== 下级描述符为报告描述符
				SWAP16(sizeof(DataReportDescriptor))			//== 下级描述符的长度
			}
		},
	},
	//endpoint_descriptor[]
	{
		{														//== 主端点输入描述
			sizeof(ENDPOINT_DESCRIPTOR_STRUCT),					//== 端点描述符的字节数大小
			ENDPOINT_DESCRIPTOR,								//== 端点描述符类型编号
			POINT_1_IN,											//== 控制输入端点
			ENDPOINT_TYPE_INTERRUPT,							//== 使用的传输类型:中断传输
			SWAP16(0x0010),										//== 该端点支持的最大包尺寸,16字节
			0x0A												//== 中断扫描时间:设置为10ms
		},
  
		{														//== 主端点输出描述
			sizeof(ENDPOINT_DESCRIPTOR_STRUCT),					//== 端点描述符的字节数大小
			ENDPOINT_DESCRIPTOR,								//== 端点描述符类型编号
			POINT_1_OUT,										//== 控制输出端点
			ENDPOINT_TYPE_INTERRUPT,							//== 使用的传输类型:中断传输
			SWAP16(0x0010),										//== 该端点支持的最大包尺寸,16字节
			0x0A												//== 中断扫描时间:设置为10ms
		},

		{														//== 主端点输出描述
			sizeof(ENDPOINT_DESCRIPTOR_STRUCT),					//== 端点描述符的字节数大小
			ENDPOINT_DESCRIPTOR,								//== 端点描述符类型编号
			MAIN_POINT_IN,										//== 端点号,主输入端点
			ENDPOINT_TYPE_INTERRUPT,							//== 使用的传输类型:批量传输
			SWAP16(0x0040),										//== 该端点支持的最大包尺寸,64字节
			0x0A												//== 中断扫描时间:设置为10ms
		},

		{														//== 主端点输出描述
			sizeof(ENDPOINT_DESCRIPTOR_STRUCT),					//== 端点描述符的字节数大小
			ENDPOINT_DESCRIPTOR,								//== 端点描述符类型编号
			MAIN_POINT_OUT,										//== 端点号,主输出端点
			ENDPOINT_TYPE_INTERRUPT,							//== 使用的传输类型:中断传输
			SWAP16(0x0040),										//== 该端点支持的最大包尺寸,64字节
			0x0A												//== 中断扫描时间:设置为10ms
		},
	},
};
 
//*********************************************************************************

//===============================================================================//
//== 函 数 名:usb_bus_reset
//== 功    能:USB 总线复位处理
//== 说    明:
//== 时    间:2008.8.13 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char usb_bus_reset(void)
{
	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("Runing usb_bus_reset()!\r\n");
	#endif

	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("USB总线复位................................\r\n");
	#endif

	bEPPflags.bits.bus_reset = 1;

	return 0;
}

//===============================================================================//
//== 函 数 名:usb_bus_suspend
//== 功    能:USB 总线挂起处理
//== 说    明:
//== 时    间:2008.8.13 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char usb_bus_suspend(void)
{
	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("Runing usb_bus_suspend()!\r\n");
	#endif

	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("USB总线挂起................................\r\n");
	#endif

	bEPPflags.bits.suspend = 1;

	return 0;
}

//===============================================================================//
//== 函 数 名:set_usb_address
//== 功    能:设置D12的地址
//== 说    明:主机请求设置地址时被调用
//== 时    间:2008.8.22 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char set_usb_address(void)
{
	set_usb_addr((unsigned char)(Control_Data.DeviceRequest.wValue & DEVICE_ADDRESS_MASK));
	Control_Data.wLength = 0;										//== 发送0字节长度数据到主机做回答
	Control_Data.wCount = 0;
	bEPPflags.bits.control_state = USB_TRANSMIT;					//== 设置为发送状态,等待in端点中断
	return 0;
}
//===============================================================================//
//== 函 数 名:stall_ep0
//== 功    能:停止端点0
//== 说    明:
//== 时    间:
//== 入口参数:
//== 返 回 值:0
//===============================================================================//
unsigned char stall_ep0(void)
{
	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("Runing stall_ep0()!\r\n");
	#endif
	set_endpoint_status(0, 1);
	set_endpoint_status(1, 1);
	return 0;
}

//===============================================================================//
//== 函 数 名:reserved
//== 功    能:备用函数
//== 说    明:
//== 时    间:
//== 入口参数:
//== 返 回 值:0
//===============================================================================//
unsigned char reserved(void)
{
	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("Runing reserved()!\r\n");
	#endif
	stall_ep0();
	return 0;
}
//===============================================================================//
//== 函 数 名:control_handler
//== 功    能:得到状态
//== 说    明:
//== 时    间:2008.8.20 创建函数
//== 入口参数:receiver: 要得到状态的对象
//== 返 回 值:0
//===============================================================================//
unsigned char get_status(unsigned char receiver)
{
	unsigned char status[2];
	unsigned char endp, endp_state;

	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("Runing get_status()!\r\n");
	#endif

	switch (receiver)
	{
		case USB_RECIPIENT_DEVICE:					//== 获取设备状态
		{
			if (bEPPflags.bits.remote_wakeup == 1)	//== 自给供电+远程唤醒
			{
				status[0] = 0x03;
			}
			else									//== 自给供电
			{
				status[0] = 0x01;
			}
			status[1] = 0x00;
		} break;

		case USB_RECIPIENT_INTERFACE:				//== 获取接口状态
		{
			status[0] = 0x00;
			status[1] = 0x00;
		} break;

		case USB_RECIPIENT_ENDPOINT:				//== 获取端点状态
		{
			endp = (unsigned char)(Control_Data.DeviceRequest.wIndex & MAX_ENDPOINTS);	//== 得到端点号

			if (Control_Data.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
				endp_state = select_endpoint(endp*2 + 1);	//== Control-in
			else
				endp_state = select_endpoint(endp*2);		//== Control-out

			if (endp_state & D12_STALL)
				status[0] = 0x01;
			else
				status[0] = 0;

			status[1] = 0;
		} break;

		default:stall_ep0(); break;
	}

	usb_transmit_buf[0] = status[0];
	usb_transmit_buf[1] = status[1];
	Control_Data.pData = usb_transmit_buf;
	Control_Data.wLength = 2;
	Control_Data.wCount = 0;
	bEPPflags.bits.control_state = USB_TRANSMIT;		//== 设置为发送状态,等待in端点中断
	return 0;
}

//===============================================================================//
//== 函 数 名:get_descriptor
//== 功    能:得到描述符
//== 说    明:
//== 时    间:2008.8.20 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char get_descriptor(void)
{
	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("Runing get_descriptor()!\r\n");
	#endif

	#ifdef __DEBUG__ 	//== 打印调试信息
		Print_Msg("获取描述符................................\r\n");
	#endif
	switch(MSB(Control_Data.DeviceRequest.wValue))
	{
		case DEVICE_DESCRIPTOR:
		{
			#ifdef __DEBUG__ 	//== 打印调试信息
				Print_Msg("	获取设备描述符................................\r\n");
			#endif
			Control_Data.wCount = sizeof(DEVICE_DESCRIPTOR_STRUCT);
			Control_Data.pData = (unsigned char *)(&device_descriptor);
			if (Control_Data.DeviceRequest.wLength == 0x40)	//== 第一次获取描述符
			{
				bEPPflags.bits.first_get_descriptor = 1;
			}
		} break;

		case CONFIGURATION_DESCRIPTOR:
		{
			#ifdef __DEBUG__ 	//== 打印调试信息
				Print_Msg("	获取配置描述符................................\r\n");
			#endif
			Control_Data.wCount = SWAP16(con_int_endp_descriptor.configuration_descriptor.wTotalLength);
			Control_Data.pData = (unsigned char *)(&con_int_endp_descriptor);
			if (Control_Data.wLength<Control_Data.wCount) Control_Data.wCount = Control_Data.wLength;
		} break;

		case STRING_DESCRIPTOR:
		{
			#ifdef __DEBUG__ 	//== 打印调试信息
				Print_Msg("	获取字符串描述符................................\r\n");
			#endif
			switch(LSB(Control_Data.DeviceRequest.wValue))
			{
				case 0x00:
				{
					#ifdef __DEBUG__ 	//== 打印调试信息
						Print_Msg("		获取语言ID................................\r\n");
					#endif
					Control_Data.wCount = LANGUAGE_ID[0];
					Control_Data.pData = LANGUAGE_ID;
				} break;

				case 0x01:
				{
					#ifdef __DEBUG__ 	//== 打印调试信息
						Print_Msg("		获取厂商字符串................................\r\n");
					#endif
					Control_Data.wCount = ManufacturerString[0];
					Control_Data.pData = ManufacturerString;
				} break;

				case 0x02:
				{
					#ifdef __DEBUG__ 	//== 打印调试信息
						Print_Msg("		获取产品字符串................................\r\n");
					#endif
					Control_Data.wCount = ProducterString[0];
					Control_Data.pData = ProducterString;
				} break;

				case 0x03:
				{
					#ifdef __DEBUG__ 	//== 打印调试信息
						Print_Msg("		获取设备序列号................................\r\n");
					#endif
					Control_Data.wCount = device_serial_number[0];
					Control_Data.pData = device_serial_number;
				} break;

				default: break;
			}
		} break;

		case INTERFACE_DESCRIPTOR: break;
		case ENDPOINT_DESCRIPTOR: break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -