#ifndef _USB_DRIVER_H__
#define _USB_DRIVER_H__

/*
Time:2007 - 10 -23
Author:ShenZhen FirSail Company.
Function:about Usb Driver

//http://hengch.blog.163.com/blog/static/1078006720086141327970
//http://blog.ednchina.com/jiereliyi/73957/message.aspx
//http://www.cn-dos.net/forum/viewthread.php?tid=41668

*/

//There are usb's token command in the following                             
#define USB_COMMAND_OUT      0x1
#define USB_COMMAND_IN       0x9
#define USB_COMMAND_SOF      0x5
#define USB_COMMAND_SETUP    0xd

//There are usb's data command in the following                             
#define USB_COMMAND_DATA0    0x3
#define USB_COMMAND_DATA1    0xb
#define USB_COMMAND_DATA2    0x7
#define USB_COMMAND_MDATA    0xf

//There are usb's handshake command in the following                             
#define USB_COMMAND_ACK      0x2
#define USB_COMMAND_NAK      0xa
#define USB_COMMAND_STALL    0xe
#define USB_COMMAND_NYET     0x6


//There are usb's Special command in the following                             
#define USB_COMMAND_PRE      0xc
#define USB_COMMAND_ERR      0xc
#define USB_COMMAND_SPLIT    0x8
#define USB_COMMAND_PING     0x4
#define USB_COMMAND_RESERVED 0x0

typedef struct tagUSB_TOKEN1 //for SOF
{
        BYTE bySync;    //00000001
        BYTE byPID;

        WORD wFrameNum:11;
        WORD wCrc::5;
}USB_TOKEN1, *LPUSB_TOKEN1;

typedef struct tagUSB_TOKEN2 //fo IN, OUT, SETUP
{
        BYTE bySync;    //00000001
        BYTE byPID;

        WORD wAddr:7;
        WORD wEndP:4;
        WORD wCrc::5;
}USB_TOKEN2, *LPUSB_TOKEN2;

typedef struct tagUSB_DATA //Data Package
{
        BYTE bySync;    //00000001
        BYTE byPID;
        //B0~B1023      //for USB1.0, G(x)=x^5+x^2+1
        //B0~B8192      //for USB2.0, G(x)=x^16+x^15+x^2+1
        //WORD wCrc; 
}USB_DATA, *LPUSB_DATA;

typedef struct tagUSB_HANDSHAKE //Handshake Package
{
        BYTE bySync;    //00000001
        BYTE byPID;
}USB_HANDSHAKE, *LPUSB_HANDSHAKE;

//http://www.cn-dos.net/forum/viewthread.php?tid=41668
//DOSUSB通过一个叫做URB(USB Request Block)的数据结构与客户端驱动程序进行通讯，
//这一点和linux非常相似，估计作者参考了linux下的源代码，在DOSUSB文档里给出了
//这个结构的定义
typedef struct tagUSBURB //32Byte
{
   BYTE transaction_type  ;//事务类型  2Dh---控制传输, 69H = 输入事务  E1H = 输出事务
   BYTE chain_end_flag    ;//保留
   BYTE dev_add           ;//USB设备地址
   BYTE end_point         ;//端点号
   BYTE error_code        ;//错误代码
   BYTE status            ;//设备状态
   WORD transaction_flags ;//保留
   WORD buffer_off        ;//缓冲区的偏移地址
   WORD buffer_seg        ;//缓冲区的段地址
   WORD buffer_length     ;//缓冲区的长度
   WORD actual_length     ;//每个包的实际长度
   WORD setup_buffer_off  ;//setup_request结构的偏移地址
   WORD setup_buffer_seg  ;//setup_request结构的段地址
   WORD start_frame       ;//保留
   WORD nr_of_packets     ;//>0时会启动实时传输
   BYTE int_interval      ;//保留
   BYTE error_count       ;//重试的次数
   WORD timeout           ;//保留
   WORD next_urb_off      ;//保留
   WORD next_urb_seg      ;//保留
}USBURB, *LPUSBURB;


//http://www.cn-dos.net/forum/viewthread.php?tid=41668
//http://blog.ednchina.com/jiereliyi/73957/message.aspx
//设备描述符
typedef struct tagUSB_DEVICEDESCRIPTOR
{
	BYTE byLength;           //设备描述符的字节数大小，为0x12
	BYTE byDescriptorType;   //描述符类型编号，为0x01
	WORD wUSB;               //USB版本号
	BYTE byDeviceClass;      //USB分配的设备类代码，0x01~0xfe为标准设备类，0xff为厂商自定义类型

	//0x00不是在设备描述符中定义的，如HID
	BYTE byDeviceSubClass;   //usb分配的子类代码，同上，值由USB规定和分配的
	BYTE byDeviceProtocl;    //USB分配的设备协议代码，同上
	BYTE byMaxPacketSize0;   //端点0的最大包的大小
	WORD wVendor;            //厂商编号
	WORD wProduct;           //产品编号
	WORD wDevice;            //设备出厂编号
	BYTE byManufacturer;     //描述厂商字符串的索引
	BYTE byProduct;          //描述产品字符串的索引
	BYTE bySerialNumber;     //描述设备序列号字符串的索引
	BYTE byNumConfiguration; //可能的配置数量
}USB_DEVICEDESCRIPTOR, *LPUSB_DEVICEDESCRIPTOR;

//配置描述符
typedef struct tagUSB_CONFIGURATIONDESCRIPTOR
{
	BYTE byLength;            //设备描述符的字节数大小，为0x12
	BYTE byDescriptorType;    //描述符类型编号，为0x01
	WORD wTotalLength;        //配置所返回的所有数量的大小
	BYTE byNumInterface;      //此配置所支持的接口数量
	BYTE byConfigurationVale; //Set_Configuration命令需要的参数值
	BYTE byConfiguration;     //描述该配置的字符串的索引值
	BYTE byAttribute;         //供电模式的选择
	                          //b7：备用，b6：自供电，b5：远程唤醒，b4--b0：备用
	BYTE byMaxPower;          //设备从总线提取的最大电流
}USB_CONFIGURATIONDESCRIPTOR, *LPUSB_CONFIGURATIONDESCRIPTOR;

//接口描述符
typedef struct tagUSB_INTERFACEDESCRIPTOR
{
	BYTE byLength;           //设备描述符的字节数大小，为0x12
	BYTE byDescriptorType;   //描述符类型编号，为0x01
	BYTE byInterfaceNunber;  //接口的编号
	BYTE byAlternateSetting; //备用的接口描述符编号
	BYTE byNumEndpoints;     //该接口使用端点数，不包括端点0
	BYTE byInterfaceClass;   //接口类型
                             //1：音频类，2：CDC控制类，3：人机接口类（HID），5：物理类
                             //6：图像类，7：打印机类，8：大数据存储类，9：集线器类10：CDC数据类
                             //11：智能卡类，13：安全类，220：诊断设备类，224：无线控制类
                             //254：特定应用类，255厂商定义的设备。
	BYTE byInterfaceSubClass;//接口子类型
	BYTE byInterfaceProtocol;//接口所遵循的协议
	BYTE byInterface;        //描述该接口的字符串索引值
}USB_INTERFACEDESCRIPTOR, *LPUSB_INTERFACEDESCRIPTOR;

//端点描述符
typedef struct tagUSB_ENDPOINTDESCRIPTOR
{
	BYTE byLength;          //设备描述符的字节数大小，为0x12
	BYTE byDescriptorType;  //描述符类型编号，为0x01
	BYTE byEndpointAddress; //端点地址及输入输出属性
	BYTE byAttribute;       //端点的传输类型属性
                            //bit1,Bit0--传送类型，00=控制传输，01=实时传输
                            //10=批量传输，11=中断传输；所有其他位均保留。
	WORD wMaxPacketSize;    //端点收、发的最大包的大小
	BYTE byInterval;        //主机查询端点的时间间隔
}USB_ENDPOINTDESCRIPTOR, *LPUSB_ENDPOINTDESCRIPTOR;


/*
//字符串描述符(String Descriptor)：
typedef struct _STRING_Descriptor_Struct
{
      BYTE    bLength;            // 描述符的长度，以字节为单位
      BYTE    bDescriptorType;    // 字符串描述符类型，0x03
      char    bString[];          // UNICODE编码的字符串
}string_descriptor;
*/

//字符描述符
typedef struct tagUSB_STRINGDESCRIPTOR
{
	BYTE byLength;             //设备描述符的字节数大小，为0x12
	BYTE byDescriptorType;     //描述符类型编号，为0x01
	BYTE bySomeDescriptor[36]; //UNICODE编码的字符串
}USB_STRINGDESCRIPTOR, *LPUSB_STRINGDESCRIPTOR;


//命令请求
//http://www.cn-dos.net/forum/viewthread.php?tid=41668
//为了更好地协调USB主机与设备之间的数据通信，USB规范定义了一套命令请求，
//用于完成主机对总线上所有USB设备的统一控制，USB命令请求由统一的格式，其结构如下：

typedef struct tagUSB_SETUPREQUEST
{
      BYTE  bmRequestType;  // 请求类型
							//b7--数据传输方向，0=主机到设备，1=设备到主机；
							//b6:5--命令的类型，0=标准命令，1=类命令，2=厂商提供的命令，3=保留；
							//b4:0--接收对象，0=设备，1=接口，2=端点，3=其他。
							//数据传输方向为设备到主机，标准命令，接收对象为设备，所以该字段填0x80。
      BYTE  bRequest;       // 命令请求的编码
							//GET_STATUS=0;
							//CLEAR_FEATURE=1;
							//SET_FEATURE=3;
							//SET_ADDRESS=5；
							//GET_DESCRIPTOR=6;
							//SET_DESCRIPTOR=7;
							//GET_CONFIGURATION=8;
							//SET_CONFIGURATION=9;
							//GET_INTERFACE=10;
							//SET_INTERFACE=11;
							//SYNCH_FRAME=12。	 
      WORD  wValue;         //高字节表示描述符的类型,低字节表示表示描述符的索引值
							//高字节 = 0x01=设备描述符，
							//高字节 = 0x02=配置描述符，
							//高字节 = 0x03=字符串描述符，
							//高字节 = 0x04=接口描述符，
							//高字节 = 0x05=端点描述符，
							//高字节 = 0x29=集线器类描述符，
							//高字节 = 0x21=人机接口类描述符，
							//高字节 = 0xFF=厂商定义的描述符
							//低字节 = 描述符的索引值
      WORD  wIndex;         //当读取字符串描述符时，填0x0409，表示希望获得英文字符串，其他情况下填0。
      WORD  wLength;        //数据长度
							//一般应该填写，描述符的第一个字节，bLength。
			/*由于我们在读描述符时，并不知道其实际长度，通常的做法是先读取8个字节，
			然后根据第一个字节bLength的值在重新读取一次完整的描述符；注意，当读取
			配置描述符的钱8个字节后，应该使用wTotalLength字段的值作为长度读取与该
			配置有关的所有描述符。*/

}USB_SETUPREQUEST, *LPUSB_SETUPREQUEST;


#endif
