学习实例之如何枚举为鼠标_第1页
学习实例之如何枚举为鼠标_第2页
学习实例之如何枚举为鼠标_第3页
学习实例之如何枚举为鼠标_第4页
学习实例之如何枚举为鼠标_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、USB HID 学习实例之如何枚举为鼠标通过上一节的工作,PC 机能成功发现 USB 设备的,但是 PC 要求提供此设置的驱动程序,这是因为原固件驱动定义的设备类型是“测试设备类”,此时要求用户提供自定义的设备驱动程序,如下图所示:USB 主机是通过请求设备的相关描述符来判断设备类型的,所以只需要修改相关描述符就能实现想要设备类型。描述符的配置位于 Descriptor.h 和 Descriptor.c 文件中。来把 Easy USB 51 Programer 改造成一个鼠标。下第一步:修改 Descriptor.c1、找到设备描述结构体/设备描述符code USB_DEVICE_DESCRI

2、PTOR DeviceDescr = 3.sizeof(USB_DEVICE_DESCRIPTOR),/设备描述符长度,= 12HUSB_DEVICE_DESCRIPTOR_TYPE,/设备描述符类型,= 01H 6.0 x00,0 x01,/协议版本,= 1.107.USB_CLASS_CODE_TEST_CLASS_DEVICE,/测试设备类型, = 0DCH将其中的注释掉,并在其后加入下面这行代码同时也将修改为2、找到接口描述符结构体1./接口描述符2.sizeof(USB_ERFACE_DESCRIPTOR),/接口描述符长度,= 09HUSB_ERFACE_DESCRIPTOR_TY

3、PE,/接口描述符类型,= 04H0,/接口数,只有 1 个0,/可选配置,只有 1 个NUM_ENDPOS,/除端点 0 的端点索引数目,= 04HUSB_CLASS_CODE_TEST_CLASS_DEVICE,/测试设备类型,= 0DCHUSB_SUBCLASS_CODE_TEST_CLASS_D12,/子类代码,= 0A0HUSB_PROTOCOL_CODE_TEST_CLASS_D12,/协议代码,= 0B0H0/字符串描述符索引1.0 x66,0 x02,/设备制造商定的产品 ID1.0 x66,0 x01,/设备制造商定的产品 ID1.0,/设备类型由接口描述符提供1.USB_C

4、LASS_CODE_TEST_CLASS_DEVICE,/测试设备类型, = 0DCH0, 0,/设备子类,设备协议EP0_PACKET_SIZE,/端点 0 最大数据包大小,= 10H0 x71,0 x04,/PHILIPS 公司的设备 ID0 x66,0 x01,/设备制造商定的产品 ID12.0 x00,0 x01,/设备系列号13.0, 0, 0,/索引14.1/可能的配置数15.;将其中的注释掉,并在其后加入下面一行代码第二步:编译源程序并写入主控的编程器PC 机,激动人心的时刻到了,工学设备(就是 HID 设备)了:看到 PC 机能成功识别到将设备是的但是接下来却提示:发现学输入设

5、备下面有一个 USB 设备出现了“!”号,这个设备就是打开设备管理器的 Easy USB 51 Programer,但为什么有问题呢?1.0 x03,/人机接口设备(HID)类1.USB_CLASS_CODE_TEST_CLASS_DEVICE,/测试设备类型,= 0DCH12.,对USB 设备的枚举过程不够了解,您可以先看看百合电子USB 的枚举(配置)过程和 USB HID 设备类协议入门。的文章:USB看来开发基础第三步:继续修改USB HID 设备类协议入门一文中提到,除了 HID 的三个特定描述符组成对 HID 设备的解释外,5 个标准描述符中与 HID 设备有关的部分有:设备描述符

6、中 bDeviceClass、bDevi须为零。ubClass 和 bDeviceProtocol 三个字段的值必接口描述符中 berfaceClass 的值必须为 0 x03,berfaubClass 的值为 0 或 1,为 1 表示 HID 设备符是一个启动设备(Boot Device,一般对 PC 机而言才有意义,意思是BIOS 启动时能识别并使用您的HID 设备,且只有标准鼠标或键盘类设备才能成为 BootDevice。 berfaceProtocol 的取值含义如下表所示:HID 接口描述符中 berfaceProtocol 的含义berfaceProtocol 的取值(十进制)含义

7、0NONE所以还有两处没有修改到:A、找到:将其注释掉并在其后加入以下代码:B、找到:将其注释掉,并在其后加入以下代码:接口描述符中的berfaceProtocol 设为1(代表鼠标),但这只是针对启动设备(Boot虽然Device)而言有才有效果(即 PC 机的 BIOS 加载后能识别和使用),但真正对 HID 设备的数据流格式进行描述的是描述符,所以 berfaceProtocol 的取值实际意义不大。的 HID 设备运行起来,因为描述符和实体描述符,其中对标准描述符的修改已经完成了,但是到目前为止还不能让HID 设备类还有 3 个特定的描述符,它们分别是:HID 描述符、实体描述符是可选

8、描述符。USB 主机在请求 HID 设备的配置描述符时,设备返回的描述符为:配置描述符、接口描述符、HID 描述符、端点描述符。HID 描述符里包含了其附属的描述的类型和长度(如描述符),然后主机再根据 HID 描述符的信息请求其相关的描述符。所以现在来完成 HID 设备类的两必须的类特定描述符:HID 描述符和描述符。1、修改 Descriptor.c1.1,/berfaceProtocol 为 1 代表鼠标1.USB_PROTOCOL_CODE_TEST_CLASS_D12,/协议代码,= 0B0H1.1,/使用的子类:(支持 boot)1.USB_SUBCLASS_CODE_TEST_C

9、LASS_D12,/子类代码,= 0A0H1鼠标2键盘3255保留A、将以下代码修改为B、在以下代码前面加入代码:其中 USB_HID_DESCRIPTOR 为 HID 描述符结构体,在 Descriptor 中定义;SWAP16 为宏定义,作用是交换双字节数据的高字节和低字节,在 Descriptor.h 中定义;MouseReportDescriptor 为 HID描述符,可利用 HID Descriptor tool 来生成,这是一个标准鼠标的描述符。1./hid_descriptor 2.sizeof(USB_HID_DESCRIPTOR),/HID 描述符的字节数大小 0 x09US

10、B_HID_DESCRIPTOR_TYPE,/HID 描述符类型0 x215.SWAP16(0 x0110),/协议版本,= 1.100 x21,/固件的国家地区代号,0 x21 为NUM_SUB_DESCRIPTORS,/下级描述符的数量USB_REPORT_DESCRIPTOR_TYPE,/下级描述符为描述符SWAP16(sizeof(MouseReportDescriptor),/下级描述符的长度 10.,1./端点描述符,端点 1 输入2.sizeof(USB_ENDPO_DESCRIPTOR),/端点描述符长度,= 07HUSB_ENDPO_DESCRIPTOR_TYPE,/端点描述

11、符类型,= 05H5.0 x81,/端点 1 INUSB_ENDPO_TYPE_ERRUPT,/中断传输, = 03HEP1_PACKET_SIZE,0 x00,/端点最大包的大小,= 0010H10/传输间隔时间,= 10ms9.,1.0 x80,/总线供电1.0 x60,/自供电,支持唤醒C、在代码后面加入以下代码:/该描述符号由 HID Descriptor tool 生成code char MouseReportDescriptor63 = 0 x05, 0 x01,/ USAGE_PAGE (Generic Desktop)0 x09, 0 x06,/ USAGE (Keyboard

12、)0 xa1, 0 x01,/ COLLECTION (Application)0 x05, 0 x07,/USAGE_PAGE (Keyboard)0 x19, 0 xe0,/USAGE_MINIMUM (Keyboard LeftControl)0 x29, 0 xe7,/USAGE_UM (Keyboard Right GUI)0 x15, 0 x00,/LOGICAL_MINIMUM (0)10.0 x25, 0 x01,/LOGICAL_UM (1)11.0 x75, 0 x01,/REPORT_SIZE (1)12.0 x95, 0 x08,/REPORT_COUNT (8)13.

13、0 x81, 0 x02,/INPUT (Data,Var,Abs)14.0 x95, 0 x01,/REPORT_COUNT (1)15.0 x75, 0 x08,/REPORT_SIZE (8)16.0 x81, 0 x03,/INPUT (Cnst,Var,Abs)17.0 x95, 0 x05,/REPORT_COUNT (5)18.0 x75, 0 x01,/REPORT_SIZE (1)0 x05, 0 x08,/USAGE_PAGE (LEDs)0 x19, 0 x01,/USAGE_MINIMUM (Num Lock)0 x29, 0 x05,/USAGE_UM (Kana)0

14、 x91, 0 x02,/OUTPUT (Data,Var,Abs)23.0 x95, 0 x01,/REPORT_COUNT (1)24.0 x75, 0 x03,/REPORT_SIZE (3)25.0 x91, 0 x03,/OUTPUT (Cnst,Var,Abs)26.0 x95, 0 x06,/REPORT_COUNT (6)27.0 x75, 0 x08,/REPORT_SIZE (8)28.0 x15, 0 x00,/LOGICAL_MINIMUM (0)29.0 x25, 0 xFF,/LOGICAL_UM (255)0 x05, 0 x07,/USAGE_PAGE (Key

15、board)0 x19, 0 x00,/USAGE_MINIMUM (no event indicated)0 x29, 0 x65,/USAGE_UM (Keyboard Application)0 x81, 0 x00,/INPUT (Data,Ary,Abs)0 xc0/ END_COLLECTION 35.;/* 接口描述符: 协议代码 */#define USB_PROTOCOL_CODE_TEST_CLASS_D120 xB0D、将以下代码注释掉E、将以下代码1./端点 2 输入2.sizeof(USB_ENDPO_DESCRIPTOR),/端点描述符长度,= 07HUSB_END

16、PO_DESCRIPTOR_TYPE,/端点描述符类型,= 05H5.0 x82,/端点 2 OUTUSB_ENDPO_TYPE_BULK,/批量传输,= 02HEP2_PACKET_SIZE,0 x00,/端点最大包的大小,= 0040H10/批量传输时该设备无效9.,10./端点 2 输出11.sizeof(USB_ENDPO_DESCRIPTOR),/端点描述符长度,= 07HUSB_ENDPO_DESCRIPTOR_TYPE,/端点描述符类型,= 05H14.0 x2,/端点 2 INUSB_ENDPO_TYPE_BULK,/批量传输,= 02HEP2_PACKET_SIZE,0 x0

17、0,/端点最大包的大小,= 0040H10/批量传输时该设备无效18.1./端点描述符,端点 1 输入2.sizeof(USB_ENDPO_DESCRIPTOR),/端点描述符长度,= 07HUSB_ENDPO_DESCRIPTOR_TYPE,/端点描述符类型,= 05H5.0 x81,/端点 1 INUSB_ENDPO_TYPE_ERRUPT,/中断传输, = 03HEP1_PACKET_SIZE,0 x00,/端点最大包的大小,= 0010H10/传输间隔时间,= 10ms9.,10./端点描述符,端点 1 输出11.sizeof(USB_ENDPO_DESCRIPTOR),/端点描述符长

18、度,= 07HUSB_ENDPO_DESCRIPTOR_TYPE,/端点描述符类型,= 05H0 x1,/端点 1 OUTUSB_ENDPO_TYPE_ERRUPT,/中断传输,= 03HEP1_PACKET_SIZE,0 x00,/端点最大包的大小,= 0010H10/传输间隔时间,= 10ms18.,修改为2、修改 Descriptor.hA、将以下代码修改为1./* D12 USB 各种描述符结构体 */2.typedef struct _USB_DESCRIPTOR 1./* D12 USB 各种描述符结构体 */typedef struct _USB_DESCRIPTOR USB_C

19、ONFIGURATION_DESCRIPTOR ConfigDescr;/配置描述符USB_ERFACE_DESCRIPTORerfaceDescr;/接口描述符USB_ENDPO_DESCRIPTOR EP1_TXDescr;/端点 1 输入描述符USB_ENDPO_DESCRIPTOR EP1_RXDescr;/端点 1 输出描述符USB_ENDPO_DESCRIPTOR EP2_TXDescr;/端点 2 输入描述符USB_ENDPO_DESCRIPTOR EP2_RXDescr;/端点 2 输出描述符 USB_DESCRIPTOR, *PUSB_DESCRIPTOR;1./端点 2 输

20、入2.sizeof(USB_ENDPO_DESCRIPTOR),/端点描述符长度,= 07HUSB_ENDPO_DESCRIPTOR_TYPE,/端点描述符类型,= 05H 5.0 x82,/端点 2 OUTUSB_ENDPO_TYPE_ERRUPT,/中断传输,= 03HEP2_PACKET_SIZE,0 x00,/端点最大包的大小,= 0040H0 x01/中断扫描时间:设置为1ms9.,10./端点 2 输出11.sizeof(USB_ENDPO_DESCRIPTOR),/端点描述符长度,= 07HUSB_ENDPO_DESCRIPTOR_TYPE,/端点描述符类型,= 05H 14.0

21、 x02,/端点 2 INUSB_ENDPO_TYPE_ERRUPT,/中断传输,= 03HEP2_PACKET_SIZE,0 x00,/端点最大包的大小,= 0040H0 x01/中断扫描时间:设置为1ms18.B、找到以下代码段:在其后加入代码:C、找到以下代码:1.#define NUM_SUB_DESCRIPTORS 12.3./* 定义 HID 描述符结构 */4.typedef struct _HID_DESCRIPTOR 5.8U bLength;8U bDescriptorType;16U bcdHID;8U bCountryCode;8U bNumDescriptors;/

22、USB_HID_SUB_DESCRIPTOR HidSubDescriptorsNUM_SUB_DESCRIPTORS;8U bSubDescriptorType;/下级描述符的类型16U wDescriptorLength; /下级描述符的长度USB_HID_DESCRIPTOR,*PUSB_HID_DESCRIPTOR;1./* USB HUB 描述符结构体 */typedef struct _USB_HUB_DESCRIPTOR 8UbDescriptorLength;/ Length of this descriptor8UbDescriptorType;/ Hub configura

23、tion type8UbNumberOfPorts;/ number of ports on this hub16UwHubCharacteristics;/ Hub Charateristics8UberOnToerGood;/ porter on tiller good in 2ms8UbHubControlCurrent;/ max currentA 9./ room for 255 portser control and removabitmask8UbRemoveAnderMask64; USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;USB_CON

24、FIGURATION_DESCRIPTOR ConfigDescr;/配置描述符USB_ERFACE_DESCRIPTORerfaceDescr;/接口描述符USB_HID_DESCRIPTOR HidDescr;/HID 描述符/ USB_ENDPO_DESCRIPTOR EP1_TXDescr;/端点 1 输入描述符/ USB_ENDPO_DESCRIPTOR EP1_RXDescr;/端点 1 输出描述符USB_ENDPO_DESCRIPTOR EP2_TXDescr;/端点 2 输入描述符USB_ENDPO_DESCRIPTOR EP2_RXDescr;/端点 2 输出描述符 USB_

25、DESCRIPTOR, *PUSB_DESCRIPTOR;在其后加入D、找到以下代码:在其后加入E、将以下代码修改为F、将以下代码修改为1.#define CONFIG_DESCRIPTOR_LENGTHsizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_ERFACE_DESCRIPTOR) + sizeof(USB_HID_DESCRIPTOR) + (NUM_ENDPOS * sizeof(USB_ENDPO_DESCRIPTOR)1.#define CONFIG_DESCRIPTOR_LENGTHsizeof(USB_CONFIGURATI

26、ON_DESCRIPTOR) 2.+ sizeof(USB_ERFACE_DESCRIPTOR) 3.+ (NUM_ENDPOS * sizeof(USB_ENDPO_DESCRIPTOR)1.#define NUM_ENDPOS21.#define NUM_ENDPOS41.#define SWAP16(x) (16U)(x)8)2.3.extern code char MouseReportDescriptor63;1.#define HIDDESCRIPTOR_H #define USB_HID_DESCRIPTOR_TYPE0 x21/HID 描述符类型#define USB_REPO

27、RT_DESCRIPTOR_TYPE0 x22 /描述符1.#define USB_ER_DESCRIPTOR_TYPE0 x063、修改 Chap_9.c以下修改内容主要与实现与 HID 类相关请求有关。A、将 get_descriptor 函数注释掉,并修改为1.void get_descriptor(void) 2.8U bDescriptor = MSB(ControlData.DeviceRequest.wValue);/请求的描述符类型/wValue 的高字节表示描述符的类型,低字节表示描述符的索引值5.6.7.if (bDescriptor = USB_DEVICE_DESCRI

28、PTOR_TYPE) /获取设备描述符 8.9.code_transmit(8U *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR);10.11.else if (bDescriptor = USB_CONFIGURATION_DESCRIPTOR_TYPE) /获取配置描述符12.13.if (ControlData.DeviceRequest.wLength CONFIG_DESCRIPTOR_LENGTH)14.15.ControlData.DeviceRequest.wLength = CONFIG_DESCRIPTOR_LENGTH;16.17

29、.code_transmit(8U *)&(usb_descr.ConfigDescr), ControlData.DeviceRequest.wLength); 18.19.20./发送描述符内容21.22./(added by BH.)23.24.else if(bDescriptor = USB_REPORT_DESCRIPTOR_TYPE) /获取描述符25.26./ControlData.wCount=SWAP16(sizeof(KeyBoardReportDescriptor);ControlData.pData=(8U *)(MouseReportDescriptor);/if(

30、ControlData.wLengthControlData.wCount)/ControlData.wCount = ControlData.wLength; 31./code_transmit(8U *)(KeyBoardReportDescriptor),ControlData.wCount);code_transmit(8U *)(MouseReportDescriptor),sizeof(MouseReportDescriptor);34.35.36.else37.B、将 control_handler 函数中被注销掉的以下语句取消注释以复原C、找到以下代码在后面加入1./*2./U

31、SB HID 设备类请求地址指针表1./*2./USB 标准设备请求地址指针表3./*4.code void (*StandardDeviceRequest)(void) = 5.get_sus,clear_feature, 8.,9.set_feature,10.,set_address,get_descriptor,13.,get_configuration,set_configuration,get_erface,set_erface,18.,19.,20.,21.22.;/else if(type = USB_CLASS_REQUEST)/ (*ClassDeviceRequestre

32、q)();/类请求,如大容量类38.39.stall_ep0();/没有该请求,返回 STALL 40.41.42./43.D、增加以下代码/定义 USB 事件标志变量EPPFLAGS bEPPflags;后加入unsigned char idle;/空闲状态 5.6./* 函数名称: void get_report(void)* 功能描述:描述符9.*/10.void get_report(void)11. 12.13. 14.15./* 函数名称: void set_report(void)* 功能描述: 获取空闲18.*/19.void set_report(void)20.21. 22

33、.3./*4.code void (*ClassDeviceRequest)(void) = 5.6.,get_report,get_idle,/ get_protocol,10.,11.,12.,13.,14.,15.,set_report,set_idle,/ setprotocol 19.20.;4、修改 Chap_9.h加入以下代码第四步、再次编译程序,将程序写入主控再次怀着激动和不安的心情将的 Easy USB 51 Programer电脑,这次终于实现了的 USB 鼠标了!针设备”中多了一项“,“USB学输入设备”已经没有“!”了,而且在“鼠标和其它指pliant mouse”,这

34、就是“设计”的鼠标了。1.#define LSB(x)(8U)(x)2.extern void get_idle(void);extern void set_idle(void);extern void set_report(void);extern void get_report(void);23./* 函数名称: void get_idle(void)* 功能描述: 获取空闲26.*/27.void get_idle(void)28.29.code_transmit(&idle,1);30. 31.32./* 函数名称: void set_idle(void)* 功能描述: 设置空闲35.

35、*/36.void set_idle(void)37. 38.while(D12_SelectEndpo(1)&0 x01);single_transmit(0, 0);/发送一个空的数据表示执行完毕idle=ControlData.DeviceRequest.wValue;42.源程序但是这个实例还不够生动,因为它并没有鼠标的一点功能,现在就来实现部分鼠标的功能。可以利用扩展板 EXT-BOARD-A 上的两个按键来模拟鼠标指针的和右移,当 K1 按下鼠标指针、K2 按下时鼠标指针右移(当然您也可以用它来模拟鼠标左键和鼠标右键)。实现这个功能非常简单,只需修改 main 函数,其内容如下:1.main()2.unsigned char i = 0;signed char cKeyIn4; 5.6.if (Init_D12()!=0)/初始化 D127.return;/如果初始化不成功,返回 8.9.IT0 = 0;/外部中断 0 为电平触发方式10.11.12.13.14.15.EX0 = 1;PX0 = 0;EA = 1;/开外部中断 0/设置外部中断 0 中断优先级/开 80C51 总

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论