




已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Vxworks usb mouse 驱动分析概述:最近在做嵌入式vxworks下usb触摸屏设计,参考了vxworks里面的usb mouse驱动的代码,分析了usb mouse驱动,根据自己的理解,写这个文档。如有任何问题请联系yxj_5421163.com,转载请标明出处。系统资源:Vxworks6.71、USB主机驱动栈模型原理 USB主机驱动栈模型下图所示: 1.1硬件层 在USB主机驱动栈的最底部是USB主控制器(USB HC,即USB Host Controller)。目前,USB主控制器可分为三类:通用型主控制器接口(UHCI)、开放型主控制器接口(OHCI)和增强型主控制接口和增强型主控制接口(EHCI)。其中,UHCI和OHCl支持USBl1低速接口,EHCl支持USB20高速接口。1.2主控制器驱动层对予每一类型的主控制器都有一个与硬件独立的USB主控制器驱动(Host Controller Driver,简称 HCD)。WindRiver提供了两个驱动:usbHedUheiLib (UHCI主控制器库)和usbHcdohciLib(OHCl主控制器库)。该模块向下直接与USB主控制器硬件进行交互操作,向上与USBD层的功能接口,提供各种功能函数的调用,支持对上层模块封装具体的HCD驱动的实现。1.3 USB核心驱动层USB核心驱动(USB host driver,简称USBD)模块实现USB的核心驱动,包括USB总线的枚举、总线带宽分配、传输控制等操作。该模块向下调用HCD接口模块,实现与HCD层的通信,将设备驱动的功能请求转化为相应功能模块的调用。USBD管理每一个与主机相连的USB设备,还负责自动处理USB电力管理和带宽管理及USB hub和设备的动态插拔。1.4 USB设备驱动层USB设备驱动层负责管理连接到USB上的不同类型的设备,它们依靠USBD来提供与每个设备的通信路径,主要实现USB设备的一些特定初始化工作,并将上层用户应用程序的请求转化为对相应的USBD驱动程序的调用。该层通过对应用层提供API函数,从而屏蔽USB实现的细节。1.5应用层应用层为用户编写的对USB设备进行读、写控制等指定功能的应用程序,应用层通过设备驱动程序和USB主机驱动程序完成指定的功能。2、USB mouse 驱动分析Usb mouse驱动属于设备驱动层,在vxworks里面,把usb mouse驱动设计成两层,即文件层+驱动层,文件层对上提供read、write、ioctl等接口,对下调用驱动层提供函数进行硬件初始化,对应的源代码是usrUsbMseInit.c (targetconfigcompssrc)。驱动层则针对具体usb设备初始化,获取数据等。2.1 文件层usrUsbMseInit.c分析在usrRoot (usrConfig.c (targetconfigall))调用#ifdef INCLUDE_USB_MOUSE_INIT usrUsbMseInit (); /* Mouse Driver Initialization */#endifusrUsbMseInit (usrUsbMseInit.c (targetconfigcompssrc))驱动程序入口点,首先检查driver是否已经安装,如果安装就退出if (usbMseDrvNum 0)printf (Mouse already initilaized.n); return ERROR;接着调用usbMseDrvNum = iosDrvInstall (FUNCPTR) NULL, (FUNCPTR) usbMseDevDelete, (FUNCPTR) usbMseOpen, (FUNCPTR) usbMseClose, (FUNCPTR) usbMseRead, (FUNCPTR) usbMseWrite, (FUNCPTR) usbMseIoctl);安装驱动的I/O函数,添加驱动到驱动表里面接着调用驱动层初始化函数if (usbMouseDevInit () = OK) usbMouseLib.c (targetsrcdrvusb) printf (usbMouseDevInit() returned OKn);这个函数如果成功,会输出打印上面的信息表明驱动已经加载,并且和usb设备已经匹配上。接着调用驱动层动态注册函数if (usbMouseDynamicAttachRegister (usbMseDrvAttachCallback, (void *) NULL) != OK) usbMouseLib.c (targetsrcdrvusb)这个函数会把usbMseDrvAttachCallback保存在驱动层创建的一个队列里面,当usb设备热插拔时,都会调用这个函数。如果已经插入了usb mouse,就会马上调用usbMseDrvAttachCallback,参数为USB_MSE_ATTACH, 如果没有插入,那么驱动加载已经完成了。看usbMseDrvAttachCallback (usrUsbMseInit.c (targetconfigcompssrc))因为第一次参数是USB_MSE_ATTACH,就会进入if (attachCode = USB_MSE_ATTACH)这个分支:首先调用驱动层的if (usbMouseSioChanLock (pChan) != OK),标记SIO_CHAN structure已经在使用接着调用sprintf (mseName, %s%d, USB_MSE_NAME, mseCount); if (usbMseDevCreate (mseName, pChan) != OK)创建设备文件,即创建/usbMo/X,X由mseCount决定,同时创建文件层设备结构,并放在链表里面,调用iosDevAdd将设备添加到系统设备列表里面接着调用if (usbMseDevFind (pChan, &pUsbMseDev) != OK)printf(usbMseDevFind() returned ERRORn);return;根据pchan在链表里面找到这个usb设备的文件层设备结构接着调用if (*pChan-pDrvFuncs-callbackInstall) (pChan, SIO_CALLBACK_PUT_MOUSE_REPORT,(STATUS (*) (void *, .) usbMseRptCallback, (void *) pUsbMseDev) != OK)pChan-pDrvFuncs-callbackInstall是usbMouseLib.c里面的usbMouseCallbackInstall函数,它安装回调函数,当usb接受到数据后就会调用usbMseRptCallback这个函数。如果上面都执行成功,会输出打印下面信息printf(USB Mouse attached as %sn, mseName);至此,驱动加载完成,并且设备文件也已经创建好了。2.2 驱动层usbMouseLib.c分析在文件层usrUsbMseInit会调用usbMouseDevInit-驱动层初始化入口if (initCount = 0) 表明还没有进行初始化,初始化内部结构体,并链接在usbd上if (usbdClientRegister (MSE_CLIENT_NAME, &usbdHandle) != OK |usbdDynamicAttachRegister (usbdHandle, USB_CLASS_HID,USB_SUBCLASS_HID_BOOT, USB_PROTOCOL_HID_BOOT_MOUSE,FALSE,usbMouseAttachCallback) != OK)return doShutdown (S_usbMouseLib_USBD_FAULT);usbdClientRegister (usbTransUnitInit.c (targetsrcusb))生成usb设备驱动的usbdHandleif ( !usbtuInitCount) /* usbdInitialize() not called */ USBTU_LOG(usbdClientRegister returns ERROR:usbdInitialize not calledn); return ERROR; 检查usbd是否初始化了,如果没有就出错退出。/* allocate structure for client */ if ( !(pDriver = OSS_CALLOC ( sizeof (USBTU_DEVICE_DRIVER) USBTU_LOG ( usbdClientRegister returns ERROR : malloc failed n); return ERROR; 创建client driver结构体if (pClientHandle != NULL) *pClientHandle = pDriver;将client driver赋给usbdHandle usbdDynamicAttachRegister (usbTransUnitInit.c (targetsrcusb))填充usb设备驱动的usbdHandle,并且注册usbMouseAttachCallback函数,当有热插拔发生时,会调用这个函数,并且将usb设备client注册到usbd上。这三个参数USB_CLASS_HID,USB_SUBCLASS_HID_BOOT, USB_PROTOCOL_HID_BOOT_MOUSE是类代码、子类代码和协议代码,会被填充在usbdHandle上,后面usb驱动就会根据这三个参数把驱动和相应的设备联系起来。pDriverData-bFlagVendorSpecific = vendorSpecific; pDriverData-uVendorIDorClass = deviceClass; pDriverData-uProductIDorSubClass = deviceSubClass;pDriverData-uBCDUSBorProtocol = deviceProtocol;pDriverData-addDevice = usbtuInitDeviceAdd;pDriverData-removeDevice = usbtuInitDeviceRemove;pDriverData-suspendDevice = usbtuInitDeviceSuspend;pDriverData-resumeDevice = usbtuInitDeviceResume;我在网上看到好多人不想用这三个参数来识别usb硬件设备,想用vid和pid来设备,那也可以,秘密就在bFlagVendorSpecific这个标志上,上面函数调用时传入的vendorSpecific参数为false,意思就是不用vid和pid,如果传入是TRUE,就是要用vid和pid来识别,看看uVendorIDorClass和uProductIDorSubClass名字就知道意思了,可能是vid或者类代码,另一个可能是pid或者子类代码,都是由bFlagVendorSpecific决定接着调用usbHstDriverRegister (Usbd.c (targetsrchwifusb))将usb设备client注册到usbd上if (NULL = pDeviceDriverInfo) | (NULL = pDeviceDriverInfo-addDevice) | (NULL = pDeviceDriverInfo-removeDevice) | (NULL = pDeviceDriverInfo-resumeDevice) | (NULL = pDeviceDriverInfo-suspendDevice) OS_LOG_MESSAGE_MEDIUM( USBD, usbHstRegisterDriver() Failed: Invalid parameter Driver info.n, 0, 0, 0, 0); return USBHST_INVALID_PARAMETER; 判断pDeviceDriverInfo里面一些处理函数是否存在,如果没有就出错返回,从上面看到调用这个函数的函数已经把这些变量赋值了。下面是一段处理usb hub的代码,就不分析了/* Store the global driver list in pOldDriverList*/ pOldDriverList = gpDeviceDriverList; while (NULL != pOldDriverList) /* * Check if the bFlagVendorSpecific, VendorIDorClass, * uProductIDorSubClass are same. */ if (pOldDriverList-pDriver-bFlagVendorSpecific = pDeviceDriverInfo-bFlagVendorSpecific) & (pOldDriverList-pDriver-uVendorIDorClass = pDeviceDriverInfo-uVendorIDorClass) & (pOldDriverList-pDriver-uProductIDorSubClass = pDeviceDriverInfo-uProductIDorSubClass) & (pOldDriverList-pDriver-uBCDUSBorProtocol = pDeviceDriverInfo-uBCDUSBorProtocol) OS_LOG_MESSAGE_HIGH( USBD, usbHstRegisterDriver() Failed: Driver is already registered.n, 0, 0, 0, 0); return USBHST_FAILURE; /* Get the driver in the list */ pOldDriverList = pOldDriverList-pNextDriver; 遍历整个gpDeviceDriverList 链表,检查pDeviceDriverInfo是否已经存在,如果存在就错误返回。pNewDriverList = (pUSBD_DEVICE_DRIVER_LIST)OS_MALLOC(sizeof(USBD_DEVICE_DRIVER_LIST);如果不存在,新创建一个pNewDriverListpNewDriverList-pDriver = pDeviceDriverInfo;将pDeviceDriverInfo放在pNewDriverList里面/* make pVxbDriverInfo point to the pDeviceDriverInfo : vxbDriverInfo */ pVxbDriverInfo = &(pDeviceDriverInfo-vxbDriverInfo); memset (pVxbDriverInfo, 0, sizeof (DRIVER_REGISTRATION); /* populate struct vxbDevRegInfo. The devId should be VXB_DEVID_BUSCTRL for * hub driver and VXB_DEVID_DEVICE for all other class drivers. * The vxbDevRegInfo : drvName should be determined for the class code */ /* parent bus ID. Should always be hub bus type. */ pVxbDriverInfo-busID = VXB_BUSID_USB_HUB; if (USBHST_HUB_CLASS = pDeviceDriverInfo-uVendorIDorClass) pVxbDriverInfo-devID = VXB_DEVID_BUSCTRL; else pVxbDriverInfo-devID = VXB_DEVID_DEVICE; /* version number */ pVxbDriverInfo-vxbVersion = VXB_VER_4_0_0; /* driver name. The name of the driver should not be greater than * MAX_DRV_NAME_LEN */ for (size = 0; pDrvNamesize!= 0; size+) pVxbDriverInfo-drvNamesize = pDrvNamesize; pVxbDriverInfo-drvNamesize = 0; /* function pointer to add device */ pVxbDriverInfo-pDrvBusFuncs = &usbVxbDeviceDriverInitFuncs; /* methods */pVxbDriverInfo-pMethods = &usbVxbDeviceDriverMethods0;填充pVxbDriverInfo/* register the driver with vxBus */ if (vxbDevRegister (pVxbDriverInfo) = ERROR) OS_LOG_MESSAGE_HIGH( USBD, usbHstRegisterDriver() Failed: vxBus Registration failedn,0,0, 0,0); /* free allocated memory */ OS_FREE (pNewDriverList); return USBHST_FAILURE; 调用vxbDevRegister将usb驱动注册在vxBus上pNewDriverList-pNextDriver = gpDeviceDriverList; /* Assign the new driver to global driver list */ gpDeviceDriverList = pNewDriverList;将pNewDriverList放在gpDeviceDriverList链表的头部。至此usbdDynamicAttachRegister执行完成,返回到usbMouseDevInit里面,这个函数也执行完成。驱动加载完成。再看vxbDevRegister(vxBus.c (targetsrchwifvxbus))函数调用if ( vxbDrvVerCheck(pDevInfo) != OK ) return(ERROR);先检查vxbus drv版本,vxbus drv版本上面填充VXB_VER_4_0_0pListEnd-pNext = pDriverListHead; pDriverListHead = pDevInfo;将pDevInfo放在链表头部/* Check existing devices, to see if this driver matches */ pCurrent = pDevInfo; while ( pCurrent != pListEnd ) VXB_DEBUG_MSG(2,vxbDevRegister() checking for orphans on %sn, (int)vxbBusTypeString(pCurrent-busID), 2,3,4,5,6); vxbDevIterate(vxbNewDriver, pCurrent, VXB_ITERATE_ORPHANS); pCurrent = pCurrent-pNext; 这里就检查存在的usb device,看看这个驱动是否匹配。看vxbDevIterate函数pBusPres = pPlbBus; /* start with PLB controller */ (*func)(pBusPres-pCtlr, pArg);Func就是vxbNewDriver,pArg就是上面的pDevInfo,而pBusPres-pCtlr就是vxbus上usb设备的信息结构体看vxbNewDriver函数先检查dev和drv一些相关的变量/* get bus type of current device */ pBusEntry = pDev-pParentBus-pBusType; /* check bus-specific match routine */ drvFound = (*(pBusEntry-vxbDevMatch)(pDriver, pDev); if ( drvFound = FALSE ) return(ERROR);调用vxbus上的dev匹配函数去匹配dev和drv,vxbDevMatch 这个是vxbus注册时用usbVxbRegHubBusType结构体填充的,这个函数就是usbdFindDriver,如果匹配不成功,就停止匹配,驱动返回。看usbdFindDriver函数pUSBD_DEVICE_INFO pUSBDeviceInfo = (pUSBD_DEVICE_INFO) pDev-pBusSpecificDevInfo; /* extract the device information from vxBus */ /* device information */ pUSBHST_DEVICE_DRIVER pDriverInfo = (pUSBHST_DEVICE_DRIVER)pDriver;得到pUSBD_DEVICE_INFO结构体,这是usb设备信息,这个结构体在usbHstDeviceNew里面创建,并且赋值。/* * Check if the device has multiple configurations and is vendor * specific. If so, return error */ if (1 uNumConfigurations) & (USBHST_VENDOR_SPECIFIC = pUSBDeviceInfo-uDeviceClass) OS_LOG_MESSAGE_HIGH( USBD, usbdFindDriver() Failed: Vendor specific device with multiple configurations not supported.n, 0, 0, 0, 0); return FALSE; 检查如果这个设备有多个配置,但是又指明vid,这是不支持的,出错返回。if (USBHST_VENDOR_SPECIFIC = pUSBDeviceInfo-uDeviceClass) if (0 = pUSBDeviceInfo-uVendorID) OS_LOG_MESSAGE_MEDIUM( USBD, usbdFindDriver() Failed: Invalid parameter Device Info.n, 0, 0, 0, 0); return FALSE; /* Find the matching driver for the device */ if (usbdMatchDriver (TRUE, pUSBDeviceInfo-uVendorID, pUSBDeviceInfo-uDeviceID, pUSBDeviceInfo-uBCDDevice, pDriverInfo) = TRUE) /* Store the driver info in the device info*/ pUSBDeviceInfo-pDriver = pDriverInfo; return TRUE; if (0 != pUSBDeviceInfo-uDeviceClass) /* Find the matching driver for the device */ if (usbdMatchDriver (FALSE, pUSBDeviceInfo-uDeviceClass, pUSBDeviceInfo-uDeviceSubClass, pUSBDeviceInfo-uDeviceProtocol, pDriverInfo) = TRUE) /* Store the driver info in the device info*/ pUSBDeviceInfo-pDriver = pDriverInfo; return TRUE; 如果usb 设备类代码是0xff,就必须有vid,如果vid为0,出错返回,如果不为0,调用usbdMatchDriver用设备的vid和pid去匹配driver,driver也得提供vid和pid,如果类代码不是0xff,也不为0,调用usbdMatchDriver用设备的类代码和子类代码,协议代码去匹配driver,driver也得提供相应的代码,如果类代码等于0,接着判断interface描述符的类代码是否为0xff,如果是0xff,调用usbdMatchDriver用设备的vid和pid去匹配driver,driver也得提供vid和pid,如果不是0xff,调用usbdMatchDriver用设备的类代码和子类代码,协议代码去匹配driver,driver也得提供相应的代码。前面讲到有网友不想用类代码来进行设备和驱动的匹配,那就要满足两个条件:usb硬件满足类代码为0xff,vid不为0,或者类代码为0,接口描述符类代码为0xff,vid不为0usb驱动调用usbdDynamicAttachRegister时,第五个参数为true,第二个参数为usb硬件的vid,第三个参数为usb硬件的pid看usbdMatchDriver这个函数就是根据dev和drv的类代码或者id进行匹配,如果匹配成功,就返回true,同时把drv结构体放在pUSBDeviceInfo-pDriver或者pInterfaceInfo-pDriver里面。if ( pDriver-devProbe = NULL ) drvFound = TRUE; else drvFound = (*(pDriver-devProbe)(pDev); if ( drvFound = FALSE ) return(ERROR); 执行drv的probe函数,这也是个空函数/* attach driver */ pDev-pDriver = pDriver; /* adjust name */ pDev-pName = &pDriver-drvName0;把drv赋给dev/* perform initialization */ vxbDevInitRun(pDev, pDriver);执行usb dev的初始化看vxbDevInitRun函数/* first pass */ if (!(devID-flags & VXB_INST_INIT_DONE) if ( pDrv-pDrvBusFuncs-devInstanceInit != NULL ) (*(pDrv-pDrvBusFuncs-devInstanceInit)(devID); devID-flags |= VXB_INST_INIT_DONE; /* second pass */ if (vxbInitPhase = 2 & !(devID-flags & VXB_INST_INIT2_DONE) if ( pDrv-pDrvBusFuncs-devInstanceInit2 != NULL ) (*(pDrv-pDrvBusFuncs-devInstanceInit2)(devID); devID-flags |= VXB_INST_INIT2_DONE; /* third pass */ if (vxbInitPhase = 3 & !(devID-flags & VXB_INST_CONNECT_DONE) if ( pDrv-pDrvBusFuncs-devInstanceConnect != NULL ) (*(pDrv-pDrvBusFuncs-devInstanceConnect)(devID); devID-flags |= VXB_INST_CONNECT_DONE; 分三个阶段初始化,我们只看第三阶段链接,pDrv-pDrvBusFuncs-devInstanceConnect,这个pDrv就是usbHstDriverRegister函数传进去的pVxbDriverInfo,在这个函数里面有pVxbDriverInfo-pDrvBusFuncs = &usbVxbDeviceDriverInitFuncs;LOCAL DRIVER_INITIALIZATION usbVxbDeviceDriverInitFuncs = usbVxbDeviceDriverInstInit, /* init 1 */ usbVxbNullFunction, /* init 2 */ usbVxbDeviceAdd /* device connect */ ;因此pDrv-pDrvBusFuncs-devInstanceConnect就是调用usbVxbDeviceAdd函数,参数是dev,即usb设备信息看usbVxbDeviceAdd函数pUSBD_DEVICE_INFO pDeviceInfo = (pUSBD_DEVICE_INFO)pDevInfo-pBusSpecificDevInfo; /* call the addDevice routine for the device */ if (pDeviceInfo-pDriver != NULL) status = pDeviceInfo-pDriver-addDevice (pDeviceInfo-hDevice, 0, pDeviceInfo-uDeviceSpeed, &(pDeviceInfo-pDriverData) );这个pDeviceInfo-pDriver就是在函数usbdFindDriver里面pDriverInfo,也就是函数usbdDynamicAttachRegister里面pDriverData这个结构体。因此pDeviceInfo-pDriver-addDevice就是usbtuInitDeviceAdd函数看usbtuInitDeviceAdd函数/* initialize message structure */ tuMessage.eventCode = ADDDEVICE; tuMessage.hDevice = hDevice; tuMerface = interfaceNumber; tuMessage.ppDriverData = ppDriverData; /* handle the message event */ usbtuInitHandleDeviceEvent(&tuMessage);发送usb设备add的消息看usbtuInitHandleDeviceEvent函数在case ADDDEVICE:分支里面,得到usb设备的设备描述符和interface描述符,调用pDriver = usbtuInitFindDriverInfo(pDevDescr, pIfDescr, &vendorOrClass , &deviceOrSubclass, &bcdOrProtocol );通过类代码或者id在usbtuClientList寻找符合的pDriver,如果找到,创建新的pNodeInfo结构体,接着创建client的message并发送/* initialize message structure */ clientMessage.eventCode = ADDDEVICE; clientMessage.hDevice = pMessage-hDevice; clientMerface = pMessage-interface; clientMessage.class = vendorOrClass; clientMessage.subclass = deviceOrSubclass; clientMtocol = bcdOrProtocol;/* send the message to client thread */ usbtuInitHandleClientEvent (pDriver, &clientMessage);看usbtuInitHandleClientEvent函数在case ADDDEVICE:分支里面/* call the user supplied callback */ (*pDriver-attachCallback) ( (USBD_NODE_ID) pClientMessage-hDevic
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年变化点管理考试题及答案
- 混凝土防水施工技术方案
- 钢结构连接节点设计优化方案
- 呼兰河传阅读测试题及答案
- 机械设备采购合同范本【三篇】
- 体育业务考试试题及答案
- 小学三级知识竞赛题及答案
- 济南市前期物业管理委托合同
- 广告学原理学习心得范例五篇
- 保障性住房项目可行性分析与风险评估方案
- 人才服务合同书
- 2025年工会财务大赛理论题库(附答案)
- 2025-2026学年统编版八年级上册道德与法治教学计划含教学进度表
- 矿井顶板事故防治课件
- 2025年工会入职考试试题及答案
- 2025年中国电力投资集团校园招聘笔试题型分析及备考策略
- 旅游服务安全知识培训课件
- 抗生素课件教学课件
- 通信光缆线路工程安全技术交底大全
- 综合实践活动:我们身边的一次性物品PPT通用课件
- 圆木桩护岸施工组织设计
评论
0/150
提交评论