USB驱动程序源代码

合集下载

USB转串口驱动代码分析

USB转串口驱动代码分析

USB转串口驱动代码分析分类:window xp 驱动(USB)/FireFox插件/汇编2012-08-09 15:55 3467人阅读评论(1) 收藏举报代码分析extensioninterfacebufferresourcesio/chenyujing1234/article/details/7843836目录(?)[+]1、USB插入时,创建设备[plain]view plaincopy1.DriverObject->DriverExtension->AddDevice = USB2COM_PnPAddDevice;步一、调用USB2COM_CreateDeviceObject创建功能设备对象(FDO)(1)IoCreateDevice系统API的原理为:[plain]view plaincopy1.NTKERNELAPI2.NTSTATUS3.IoCreateDevice(4. IN PDRIVER_OBJECT DriverObject,5. IN ULONG DeviceExtensionSize,6. IN PUNICODE_STRING DeviceName OPTIONAL,7. IN DEVICE_TYPE DeviceType,8. IN ULONG DeviceCharacteristics,9. IN BOOLEAN Reserved,10. OUT PDEVICE_OBJECT *DeviceObject11. );在之前真实的USB驱动中我们是这样创建的:[cpp]view plaincopy1.ntStatus = IoCreateDevice(2. DriverObject, // our driver object3.sizeof(DEVICE_EXTENSION), // extension size for us4. NULL, // name for this device5. FILE_DEVICE_UNKNOWN,6. FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics7. FALSE, // Not exclusive8. &deviceObject); // Our device object就是第三个参数为NULL,第四个参数为FILE_DEVICE_UNKNOWN,意味着我们驱动想附加的设备是空的,且未知。

USB驱动程序编写

USB驱动程序编写

USB驱动程序编写linux‎下usb驱动编写(内核2.4)—‎—2.6与此接口有区别2006-‎09-15 14:57我们知道了‎在Linux下如何去使用一些最常‎见的USB设备。

但对于做系统设计‎的程序员来说,这是远远不够的,我‎们还需要具有驱动程序的阅读、修改‎和开发能力。

在此下篇中,就是要通‎过简单的USB驱动的例子,随您一‎起进入USB驱动开发的世界。

‎USB骨架程序(usb-ske‎l eton),是USB驱动程序的‎基础,通过对它源码的学习和理解,‎可以使我们迅速地了解USB驱动架‎构,迅速地开发我们自己的USB硬‎件的驱动。

USB驱动开发‎在掌握了USB设备的配置后,‎对于程序员,我们就可以尝试进行一‎些简单的USB驱动的修改和开发了‎。

这一段落,我们会讲解一个最基础‎U SB框架的基础上,做两个小的U‎S B驱动的例子。

USB骨架‎在Linux kernel‎源码目录中driver/usb/‎u sb-skeleton.c为我‎们提供了一个最基础的USB驱动程‎序。

我们称为USB骨架。

通过它我‎们仅需要修改极少的部分,就可以完‎成一个USB设备的驱动。

我们的U‎S B驱动开发也是从她开始的。

‎那些linux下不支持的USB‎设备几乎都是生产厂商特定的产品。

‎如果生产厂商在他们的产品中使用自‎己定义的协议,他们就需要为此设备‎创建特定的驱动程序。

当然我们知道‎,有些生产厂商公开他们的USB协‎议,并帮助Linux驱动程序的开‎发,然而有些生产厂商却根本不公开‎他们的USB协议。

因为每一个不同‎的协议都会产生一个新的驱动程序,‎所以就有了这个通用的USB驱动骨‎架程序,它是以pci 骨架为模‎板的。

如果你准备写一个li‎n ux驱动程序,首先要熟悉USB‎协议规范。

USB主页上有它的帮助‎。

一些比较典型的驱动可以在上面发‎现,同时还介绍了USB urbs‎的概念,而这个是usb驱动程序中‎最基本的。

单片机USB模拟U盘源码

单片机USB模拟U盘源码

单片机USB模拟U盘源码虽然现在成品U盘的成本已经非常低,但是单片机系统中模拟U盘还是有些场景会应用到,比如:①代替传统光盘,为用户提供说明书、驱动软件等(直接存储在产品中)②U盘数据监控、截取和加密等(定制U盘)③采集数据暂存,方便传输给主机下文是根据masstorage和Bulk-Only传输协议,使用CH559实现模拟U盘的功能(容量大小由选择的外部存储芯片决定),用以实现数据转存或定制U盘功能。

关键点在于USB 设备模式初始化、扇区读写和外部存储芯片的操作。

一、总体概述模拟U盘关键功能部件包括以下几点:(1)、具有USB设备功能的MCU或接口芯片,此例中CH559有2个USB主机接口和1个USB设备接口。

(2)、根据实际需要或者接口选择合适的外部存储来作为U盘的存储空间,比如SPI的串行Flash、E2PROM,甚至是Nand Flash等。

以上准备完毕整体的操作流程如下所示:二、硬件电路CH559模拟U盘使用的SPI接口的串行Flash,硬件如下图:CH559是增强型51内核的单片机,内置晶振,所以芯片外围也足够简洁。

芯片资源如下图:三、软件编写软件主要包括以下方面:(1)、USB设备模式初始化(2)、存储芯片接口初始化(3)Bulk_Only传输CBW包:CSW包:四、可拓展功能(1)、其他存储介质:除了以上提到的SPI接口的串行Flash,也可以替换成E2PROM或者Nand falsh等。

(2)、数据来源可以随意指定,比如串口数据流,并口数据流,甚至其他温湿度传感器设备等。

(3)、CH559+SPI串行Flash模拟U盘测试参数CH563模拟U盘源码.rar559模拟U盘源码.rar五、源码分享CH559模拟U 盘的源代码(C 语言):CH563模拟U 盘的源代码(C 语言):。

WindowsCE下USB摄像头驱动开发以OV511为例附带全部源代码以及讲解

WindowsCE下USB摄像头驱动开发以OV511为例附带全部源代码以及讲解

Windows 下 USB设备接口的枚举和保存
USB主设备身很复杂,但方便在提供了统一的接口方式,使得驱动程序在使 用设备的时候,工作简化到了类似操作串行接口。 USB设备可以看作提供了多个串口的设备,依据USB的规范,我们将每个串 口称作端点(Endpoint),要和这个端点通信,我们就要打开到这个端点的连接, 这个连接就是管道(Pipe)。
驱动加载完成后,用户程序再用CreateFile打开设备的 时候,将返回驱动程序上下文给用户程序,这样用户程序和 驱动就可以交互了,并且这个驱动程序上下文是含有该USB 设备相关信息的,所以,可以使用USBD函数来操作USB设 备,并且将USB设备的数据返回给应用程序。
Windows 下 流接口USB驱动程序卸载的流程
Windows 下 USB设备接口的枚举和保存
OV511+这8个Interface设置见Datasheet USBDeviceAttach函数中,通过ParseStreamInterfaces函数来保 存这些Interface。详细内容的参见代码。 主要结构如下:
for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++) { lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i]; if ((lpIF->Descriptor.bInterfaceClass == bIFStrm) && (lpIF->Descriptor.bInterfaceSubClass == bIFSubStrm)) { //保存接口 } }
OV511通过端点0来控制其寄存器。 Linux中,写寄存器函数如下:

USB驱动开发实例

USB驱动开发实例

USB驱动开发实例本节具体介绍如何进行USB驱动的开发,本节采用的源码来源自DDK的源程序,其位置在DDK子目录的src\wdm\usb\bulkusb目录下。

该示例很全面地支持了即插即用IRP的处理,也很全面地支持了电源管理,同时很好地支持了USB设备的bulk读写。

如果从头开发USB驱动,往往很难达到USB驱动的稳定性,所以强烈建议读者在此驱动修改的基础上进行USB驱动开发。

1 功能驱动与物理总线驱动DDK已经为USB驱动开发人员提供了功能强大的USB物理总线驱动(PDO),程序员需要做的事情是完成功能驱动(FDO)的开发。

驱动开发人员不需要了解USB如何将请求转化成数据包等细节,程序员只需要指定何种管道,发送何种数据即可。

当功能驱动想向某个管道发出读写请求时,首先构造请求发给USB总线驱动。

这种请求是标准的USB请求,被称为URB(USB Request Block),即USB请求块。

这种URB被发送到USB物理总线驱动以后,被USB总线驱动所解释,进而转化成请求发往USB HOST 驱动或者USB HUB驱动,如图17-21所示。

图17-21 总线驱动与功能驱动的关系可以看出,USB总线驱动完成了大部分工作,并留给USB功能驱动标准的接口,即URB请求。

USB驱动开发人员只需要根据不同的USB设备的设计要求,在相应的管道中发起URB 请求即可。

2. 构造USB请求包USB驱动在与USB设备通信的时候,如在控制管道中获取设备描述符、配置描述符、端点描述符,或者在Bulk管道中获取大量数据,都是通过创建USB 请求包(URB)来完成的。

URB中填充需要对USB的请求,然后将URB作为IRP的一个参数传递给底层的USB总线驱动。

在USB总线驱动中,能够解释不同URB,并将其转化为USB总线上的相应数据包。

DDK提供了构造URB的内核函数UsbBuildGetDescriptorRequest,其声明如下:VOID UsbBuildGetDescriptorRequest(IN OUT PURB Urb,IN USHORT Length,IN UCHAR DescriptorType,IN UCHAR Index,IN USHORT LanguageId,IN PVOID TransferBuffer OPTIONAL,IN PMDL TransferBufferMDL OPTIONAL,IN ULONG TransferBufferLength,IN PURB Link OPTIONAL);z Urb:用来输出的URB结构的指针。

USB驱动开发

USB驱动开发

第17章USB设备驱动USB设备驱动和PCI设备驱动是PC中最主要的两种设备驱动程序。

与PCI协议相比,USB协议更复杂,涉及面较多。

本章将介绍USB设备驱动开发。

首先介绍USB协议,使读者对USB协议有个整体认识。

然后介绍USB设备在WDM中的开发框架。

由于操作系统的USB总线驱动程序提供了丰富的功能调用,因此开发USB驱动开发变得相对简单,只需要调用USB总线驱动接口。

17.1 USB总线协议USB总线协议比PCI协议复杂的多,涉及USB物理层协议,又涉及USB传输层协议等。

对于USB驱动程序开发者来说,不需要对USB协议的每个细节都很清楚。

本节概要地介绍USB总线协议,并对驱动开发者需要了解的地方进行详细介绍。

17.1.1 USB设备简介USB即通用串行总线(Universal Serial Bus),是一种支持即插即用的新型串行接口。

也有人称之为“菊链(daisy-chaining)”,是因为在一条“线缆”上有链接127 个设备的能力。

USB要比标准串行口快得多,其数据传输率可达每秒4Mb~12Mb(而老式的串行口最多是每秒115Kb)。

除了具有较高的传输率外,它还能给外围设备提供支持。

需要注意的是,这不是一种新的总线标准,而是计算机系统连接外围设备(如键盘、鼠标、打印机等)的输入/输出接口标准。

到现在为止,计算机系统连接外围设备的接口还没有统一的标准,例如,键盘的插口是圆的、连接打印机要用9针或25针的并行接口、鼠标则要用9针或25针的串行接口。

USB能把这些不同的接口统一起来,仅用一个4针插头作为标准插头,如图17-1所示。

通过这个标准插头,采用菊花链形式可以把所有的外设连接起来,并且不会损失带宽。

USB正在取代当前PC上的串口和并口。

第17章 USB 设备驱动431图17-1 USB 的四条传输线以USB 方式连接设备时,所有的外设都在机箱外连接,连接外设不必再打开机箱;允许外设热插拔,而不必关闭主机电源。

WINCE下USB驱动程序

WINCE下USB驱动程序

如何编写WINDOWS 的USB驱动程序发表:不详阅读:226次关键字:字体:[大中小]随着USB设备的普及,摆在开发人员面前的驱动开发任务也是越来越繁重了,特别是对于一些嵌入式开发厂商来讲,由于设备所采用的操作系统不同,相应的硬件接口也是不一样的,开发相关的USB驱动程序更是难上加难。

Windows 是微软推出的功能强大的嵌入式操作系统,国内采用此操作系统的厂商已经很多了,本文就以windows 为例,简单介绍一下如何开发windows 下的USB驱动程序。

首先要熟悉一些USB的基本概念,当然最好把USB 1.1的协议看一遍,(当然现在2。

0的协议都已经有了) 上可以下载,我记得好像有个中文版的,翻译的还可以,上有的,具体位置记不太清楚了,中文版的协议可以快速翻一边,了解一些基本的概念,但是设计到一些关键性的东西最好还是看英文版的心里比较清楚些。

这里我就不介绍USB的基本协议了,假设用户已经熟悉了USB设备的一些基本的概念,并且对Winows 的开发有一定的了解。

下面简略介绍一下Windows 中USB设备驱动开发的一些基础知识。

Windows 的USB系统软件分为两层: USB Client设备驱动程序和底层的Windows CE 实现的函数层。

USB设备驱动程序主要负责利用系统提供的底层接口配置设备,和设备进行通讯。

底层的函数提本身又由两部分组成,通用串行总线驱动程序(USBD)模块和较低的主控制器驱动程序(HCD)模块。

HCD负责最最底层的处理,USBD模块实现较高的USBD函数接口。

USB设备驱动主要利用USBD接口函数和他们的外围设备打交道。

USB设备驱动程序主要和USBD打交道,所以我们必须详细的了解USBD提供的函数。

主要的传输函数有:AbourtTransfer IssueControlTransferCloseTransfer IssueInterrupTransferGetIsochResult IssueIsochTransferGetTransferStatus IstransferCompleteIssueBulkTransfer IssueVendorTransfer主要的用于打开和关闭USBD和USB设备之间的通信通道的函数有:AbortPipeTransfers ClosePipeIsDefaultPipeHalted IsPipeHaltedOpenPipe ResetDefaultPipeResetPipe相应的打包函数接口有:GetFrameLength GetFrameNumber ReleaseFrameLengthControl SetFrameLength TakeFrameLengthControl取得设置设备配置函数:ClearFeature SetDescriptorGetDescriptor SetFeatureGetInterface SetInterfaceGetStatus SyncFrame与USB进行交互的实现方法相关的多任务函数:FindInterface RegisterClientDeviceIdGetDeviceInfo RegisterClientSettingsGetUSBDVersion RegisterNotificationRoutine LoadGenericInterfaceDriver TranslateStringDescrOpenClientRegisterKey UnRegisterNotificationRoutine常见的Windows 下USB的设备驱动程序的编写有以下几种方法:● 流式接口函数这种驱动程序主要呈现流式函数接口,主要输出XXX_Init,XXX_Deinit,XXX_Open,XXX_Close,XXX_Open,XXX_Close,XXX_Read,XXX_Write, XXX_Seek,XXX_IOControl,XXX_PowerUp,XXX_PowerDown等流式接口,注意上述的几个接口一定都要输出,另外XXX必须为三个字符,否则会出错。

USB源代码

USB源代码
//该用途是未定义的,如果使用该用途来开集合,那么系统将不会把它
//当作标准系统设备,从而就成了一个用户自定义的HID设备。
0x09, 0x00, // USAGE (0)
//这是一个主条目(bType为0)条目,开集合,后面跟的数据0x01表示
//该集合是一个应用集合。它的性质在前面由用途页和用途定义为
//这是一个全局条目,说明逻辑值最大为255。
0x25, 0xff, // LOGICAL_MAXIMUM (255)
//这是一个局部条目,说明用途的最小值为1。
0x19, 0x01, // USAGE_MINIMUM (1)
//这是一个局部条目,说明用途的最大值8。
//注意小端模式,低字节应该在前。
0xE1,
0x05,
//bcdDevice字段。设备版本号,取1.0版,即0x0100。
//小端模式,低字节在先。
0x00,
0x01,
//iManufacturer字段。厂商字符串的索引值,为了方便记忆和管理,
//字符串索引就从1开始吧。
0x10,
//idVender字段。厂商ID号,我们这里取0x8888,仅供实验用。
//实际产品不能随便使用厂商ID号,必须跟USB协会申请厂商ID号。
//注意小端模式,低字节在先。
0xC0,
0x16,
//idProduct字段。产品ID号,由于是第六个实验,我们这里取0x0006。
0x29, 0x08, // USAGE_MAXIMUM (8)
//这是一个全局条目,说明数据域的数量为八个。
0x95, 0x08, // REPORT_COUNT (8)
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

项目报告7USB驱动程序源代码作者:罗仕波一.头文件go7007sb.h/**go7007sb.h - this file includes all relative header files that*will be used in go7007sb vedio usb interface driver, and it*also defines all relative driver private data structures and*it's io control commands.*/#ifndef _GO7007SB_H#define _GO7007SB_H#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <asm/uaccess.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/ioctl.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/fs.h>#include <linux/devfs_fs_kernel.h>//#define DEBUG#define DRIVER_VERSION "1.0.0"#define DRIVER_DESC "USB GO7007SB Driver"#include <linux/usb.h>MODULE_AUTHOR("Luo Shibo");MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);MODULE_LICENSE("GPL");/**io control commands definition,these commands will be*used to control the device in function iocntl_go7007sb*/#define GO7007SB_IOC_MAGIC 'U' //command magic number#define GO7007SB_IOC_RESET _IO(GO7007SB_IOC_MAGIC,0) //software reset the device#define GO7007SB_IOC_SHUTDOWN _IO(GO7007SB_IOC_MAGIC,1) //shutdown the device#define GO7007SB_IOC_PAUSE _IO(GO7007SB_IOC_MAGIC,2) //pause compression#define GO7007SB_IOC_RESUME _IO(GO7007SB_IOC_MAGIC,3) //resume from pause status#define GO7007SB_IOC_GETSTATE _IOR(GO7007SB_IOC_MAGIC,4,unsigned int)//get state of dev/**go7007sb device file number,the major of all USB devices have been defined as 180,*we just need to define minors here,currently,we accept only 4 devices*their minors start from 64,so minors:64,65,66,67 should be ok.*/#ifdef __KERNEL__ /*__KERNEL__*/#define GO7007SB_MAX_MNR 4#define GO7007SB_BASE_MNR 64#define USB_GO7007SB_MINOR(inode) MINOR((inode)->i_rdev)-GO7007SB_BASE_MNR/**go7007sb video interface number*/#define GO7007SB_VIDEO_IFNUM 0/**endpoints definition*/#define GO7007SB_MAX_EP_NUM 4 //maximum endpoint number#define GO7007SB_EP_BULK_IN 1 //in endpoint for stream#define GO7007SB_EP_CTRL 2 //out endpoint for control#define GO7007SB_EP_BULK_OUT 3 //out endpoint for initialization#define GO7007SB_EP_INTR 4 //in endpoint for interrupt#define IS_EP_BULK(ep) ((ep).bmAttributes==USB_ENDPOINT_XFER_BULK ? 1 : 0)#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep)&& \((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN)#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep)&& \((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_OUT)#define IS_EP_INTR(ep) ((ep).bmAttributes==USB_ENDPOINT_XFER_INT ? 1 : 0)#define IS_EP_CTRL(ep) ((ep).bmAttributes==USB_ENDPOINT_XFER_CONTROL ? 1 : 0)#define USB_ENDPOINT_NUM(ep) ((ep).bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)#define USB_EP_DIR_IN 0#define USB_EP_DIR_OUT 1/**buffer sizes*/#define GO7007SB_STRM_BUF_SZ 128 //streaming buffer#define GO7007SB_INIT_BUF_SZ 64 //initial buffer#define IN_URB_BUF_SZ 1024 //buffer for in urb#define OUT_URB_BUF_SZ 4*GO7007SB_INIT_BUF_SZ //buffer for out urb/**times*/#define GO7007SB_INT_INTERVAL 5 //interrupt interval:5ms#define GO7007SB_RD_TIMEOUT 3*HZ //timeout per read:3s#define GO7007SB_RD_EXPIRE 3 //expires after 3 read timeouts#define GO7007SB_WR_TIMEOUT 3*HZ#define GO7007SB_WR_EXPIRE 10/**interrupts and command values:values with REQ are requests sent from go7007sb*values with CMD are commands sent from host to control go7007sb*/#define GO7007SB_IRQ_VALUE_MASK 0xFFFF0000#define go7007sb_irq_value(u32_data) (((u32_data) & GO7007SB_IRQ_VALUE_MASK) >> 16)#define GO7007SB_IRQ_BOOT 0x55AA //boota : go7007sb request to boot#define GO7007SB_IRQ_INIT 0x5A5A //bootb2: boot done, request to init#define GO7007SB_IRQ_RUN 0x0000 //initz : init done, request to run#define GO7007SB_IRQ_PAUSE 0x0020 //the ack of PAUSE command#define GO7007SB_IRQ_SHUTDOWN 0xA55A //fatal error,request to shutdown#define GO7007SB_CMD_BOOT 0x55AA //boot go7007sb,write it into init buffer#define GO7007SB_CMD_INIT_BICP 0x1000 //use Block-Init-Config-Package to init#define GO7007SB_CMD_INIT_RICP 0x2000 //use Register-Init_Config-Package to init#define GO7007SB_CMD_INIT_DICP 0x4000 //use DRAM-Init-Config-Packet to init#define GO7007SB_CMD_START 0x8000 //start encoding#define GO7007SB_CMD_PAUSE 0x0020 //pause encoding#define GO7007SB_CMD_SHUTDOWN 0x0081 //shutdown the device#define GO7007SB_CMD_SOFTRESET 0x0082 //software reset the device#define XRISC_EXCODE_START_ADDR 0x0200 //xrisc executable code starting address#define NUM_OF_FIRMWARE_PKT 1 //number of firmware packet downloaded/**file paths*/#define PKT_TYPE_FIRMWARE 0#define PKT_TYPE_INITPKT 1#define DEFAULT_FIRMWARE_PATH "/etc/go7007sb/go7007fw.bin"#define DEFAULT_INITPKT_PATH "/etc/go7007sb/go7007in.bin"#define DEFAULT_CONF_FILE_PATH "/etc/go7007sb.conf"/**go7007sb device id:this will be used for system to*find the driver for a hotpluged go7007sb vedio device*here we only need to match vendor and productor id.*/static struct usb_device_id go7007sb_device_id={match_flags: USB_DEVICE_ID_MATCH_DEVICE |USB_DEVICE_ID_MATCH_INT_CLASS |USB_DEVICE_ID_MATCH_INT_SUBCLASS,idVendor: 0x0EB1,idProduct: 0x7007,bInterfaceClass: 0xFF,bInterfaceSubClass: 0x00,};#endif /*__KERNEL__*//**go7007sb device private data:this struct descripts the*relative info about this device.*/#define GO7007SB_STATE_NOTBOOTED 0 //before bootA state#define GO7007SB_STATE_BOOTFAILED 1 //failed to bootup the device#define GO7007SB_STATE_BOOTDONE 2 //succeeded to boot the device#define GO7007SB_STATE_INITFAILED 3 //failed to initialize the device #define GO7007SB_STATE_PAUSED 4 //paused#define GO7007SB_STATE_HALTED 5 //device halted#define GO7007SB_STATE_RUNNING 6 //device is running#define GO7007SB_STATE_READY 7 //start-coding command sent#ifdef __KERNEL__ /*__KERNEL__*/struct go7007sb_usb_data{struct usb_device *go7007sb_dev; //the usb device structstruct urb go7007sb_irq;//the interrupt urb of this deviceunsigned int ifnum; //interface number of the vedio interface kdev_t go7007sb_minor; //the device minor number of go7007sb char isopen; //not zero if the device is openchar present; //not zero if the device is presentunsigned int state; //device state__u32 irq; //buffer for interrupt endpoint,4 bytes__u64 ctrl; //buffer for control endpoint,8 byteschar *out_buf,*in_buf;//the io buffers used to transferchar bulk_in_ep; //data in endpoint,should be 1char ctrl_ep; //control out endpoint num,should be 2char bulk_out_ep; //init out endpoint,should be 3char intr_ep; //interrupt listening endpoint,should be 4 wait_queue_head_t rd_wait_q; //wait queue on read requestwait_queue_head_t wr_wait_q; //wait queue on write requeststruct semaphore sem; //semphore to prevent concurrent operation unsigned int rd_nak_timeout; //seconds to wait before timeoutunsigned int wr_nak_timeout; //seconds to wait before timeout};#endif /*__KERNEL__*/#endif二.源代码go7007sb.c/**go7007sb.c - defines all the global varibales and functions of the driver*/#ifndef MODULE#define MODULE#endif#ifndef __KERNEL__#define __KERNEL__#endif#include "go7007sb.h"/**global variables*/struct go7007sb_usb_data *p_go7007sb_data_table[GO7007SB_MAX_MNR]={NULL,/*...*/};static DECLARE_MUTEX(go7007sb_mutex);/**macroes to get/set the device state*/#define set_state(go_data,s) \do{ \(go_data)->state=(s); \}while(0)#define get_state(go_data) ((go_data)->state)/**function to build the initial buffer to send command to the device */static inline int build_cmd_buffer(char *buf,__u16 cmd){__u16 *u16_buf=(__u16 *)buf;if(!u16_buf)return -ENOMEM;switch(cmd){case GO7007SB_CMD_BOOT :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_BOOT);u16_buf[1]=cpu_to_le16(XRISC_EXCODE_START_ADDR);u16_buf[3]=cpu_to_le16(NUM_OF_FIRMWARE_PKT);break;case GO7007SB_CMD_START :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_START);/*note:buffer[1]-buffer[31]should reffer to*//*the vendor sdk and to be handled later */break;case GO7007SB_CMD_PAUSE :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_PAUSE);break;case GO7007SB_CMD_SHUTDOWN :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_SHUTDOWN);break;case GO7007SB_CMD_SOFTRESET :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_SOFTRESET);break;default:return -EINVAL;}return 0;}/**function to locate the paths of firmware and config packet*/static struct file *locate_vendor_image(int type){struct file *filp;switch(type){case PKT_TYPE_FIRMWARE :filp=filp_open(DEFAULT_FIRMWARE_PATH,O_RDONLY,0644);if(IS_ERR(filp))goto error;break;case PKT_TYPE_INITPKT :filp=filp_open(DEFAULT_INITPKT_PATH,O_RDONLY,0644);if(IS_ERR(filp))goto error;break;default:goto error;}return filp;error:return NULL;}/**function to send command to device through bulk out endpoint*/static int send_command(struct go7007sb_usb_data *go_data,__u16 cmd) {int retval;int bytes;int wr_expires=GO7007SB_WR_EXPIRE;struct usb_device *dev;char *cmd_buf=go_data->out_buf;kdev_t go_minor=go_data->go7007sb_minor;if(!cmd_buf)return -ENOMEM;/**build the initial buffer*/if((retval=build_cmd_buffer(cmd_buf,cmd))!=0)return retval;/**fill the urb and then submit it*/dev=go_data->go7007sb_dev;try_again:retval=usb_bulk_msg(dev,usb_sndbulkpipe(dev,go_data->bulk_out_ep),cmd_buf,GO7007SB_INIT_BUF_SZ,&bytes,GO7007SB_WR_TIMEOUT);/**check the result*/if(retval==USB_ST_TIMEOUT && !bytes){//timeout and no data sentif(--wr_expires<=0){err("send_command(%d):sending command timed out!",go_minor);}elsegoto try_again;;}else if(retval==-EPIPE){ //endpoint haltedif(usb_clear_halt(dev,go_data->bulk_out_ep)){err("send_command(%d):endpoint halted!",go_minor);}goto try_again;}else if(retval<0){ //other errorserr("send_command(%d):sending command failed!",go_minor);}return retval;}/**function to download file to initial buffer*/static int download_file(struct go7007sb_usb_data *go_data,struct file *fp){char *buf;int count;int partial;int this_write;int result;int wr_expires;struct usb_device *dev;kdev_t go_minor=go_data->go7007sb_minor;buf=go_data->out_buf;if(!buf){return -ENOMEM;}dev=go_data->go7007sb_dev;result=0;wr_expires=GO7007SB_WR_EXPIRE;while((count=kernel_read(fp,fp->f_pos,buf,OUT_URB_BUF_SZ))>0){this_write=(count < OUT_URB_BUF_SZ) ? count : OUT_URB_BUF_SZ;result=usb_bulk_msg(dev,usb_sndbulkpipe(dev,go_data->bulk_out_ep),buf,this_write,&partial,GO7007SB_WR_TIMEOUT);if(result==USB_ST_TIMEOUT && !partial){ //timed out and no data writen if(--wr_expires<=0){err("download_file(%d):downloading file timed out!",go_minor);break;}elsecontinue;}else if(result==-EPIPE){ //endpoint halted, try to repare itif(usb_clear_halt(dev,go_data->bulk_out_ep)){err("download_file(%d):bulk out endpoint halted!",go_minor);break;}continue; //if halt condition cleared}else if(result<0){ //we can not torrent any error in downloadingerr("download_file(%d):downloading file failed!",go_minor);break;}fp->f_pos+=partial;}return result;}///////////////////////////////////////////////////////////////////// go7007sb device file operations definition block////////////////////////////////////////////////////////////////////**function:open_go7007sb - to open the device*/static int open_go7007sb(struct inode *inode,struct file *file){struct go7007sb_usb_data *go_data;struct usb_device *dev;kdev_t go_minor;int err=0;down(&go7007sb_mutex);go_minor=USB_GO7007SB_MINOR(inode);dbg("open_go7007sb(%d): try to open device",go_minor);go_data=p_go7007sb_data_table[go_minor];if(!go_data){printk("<1>open_go7007sb(%d):unable to get private data of devide\n",go_minor);err=-ENODEV;goto out_error;}dev=go_data->go7007sb_dev;if(!dev){printk("<1>open_go7007sb(%d):device is not present!\n",go_minor);err=-ENODEV;goto out_error;}if(!go_data->present){printk("<1>open_go7007sb(%d):device is not present!\n",go_minor);err=-ENODEV;goto out_error;}if(go_data->isopen){printk("<1>open_go7007sb(%d):device is already opened!\n",go_minor);err=-EBUSY;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_READY){printk("<1>open_go7007sb(%d):device is not ready!\n",go_minor);err=-ENODEV;goto out_error;}down(&go_data->sem);/**then send the "start coding" command*/if((err=send_command(go_data,GO7007SB_CMD_START))!=0){printk("<1>open_go7007sb(%d):send \"start\" command failed!\n",go_minor);up(&go_data->sem);goto out_error;}up(&go_data->sem); //release the mutex before sleeping/**wait for the processing of command*/interruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain the mutexif(signal_pending(current)){up(&go_data->sem);err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_RUNNING){printk("<1>open_go7007sb(%d):process \"start\" command failed!\n",go_minor);up(&go_data->sem);err=-EAGAIN;goto out_error;}dbg("open_go7007sb(%d):device opened!",go_minor);go_data->isopen=1;up(&go_data->sem);file->private_data=go_data;MOD_INC_USE_COUNT;out_error:up(&go7007sb_mutex );return err;}/**function:close_go7007sb - to close the device*/static int close_go7007sb(struct inode *inode,struct file *file){struct go7007sb_usb_data *go_data;kdev_t go_minor;int err=0;down(&go7007sb_mutex);go_minor=USB_GO7007SB_MINOR(inode);dbg("close_go7007sb(%d):try to close device",go_minor);go_data=p_go7007sb_data_table[go_minor];if(!go_data){printk("<1>close_go7007sb(%d):invalid device minor\n",go_minor);err=-ENODEV;goto out_error;}down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_PAUSE))!=0){printk("<1>close_go7007sb(%d):send \"pause\" command failed!\n",go_minor);up(&go_data->sem);goto out_error;}up(&go_data->sem);interruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem);if(signal_pending(current)){up(&go_data->sem);err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_READY){printk("<1>close_go7007sb(%d):send \"pause\" command failed!\n",go_minor);err=-EAGAIN;up(&go_data->sem);goto out_error;}dbg("close_go7007sb:device(%d):device closed!\n",go_minor);go_data->isopen=0;up(&go_data->sem);file->private_data=NULL;MOD_DEC_USE_COUNT;out_error:up(&go7007sb_mutex);return err;}/**function:read_go7007sb - to read data from go7007sb device*/static ssize_t read_go7007sb(struct file *file,char *buffer,size_t count,loff_t *ppos){struct go7007sb_usb_data *go_data;struct usb_device *dev;ssize_t ret; //return valuessize_t bytes_read; //totally bytes readkdev_t go_minor;int result; //function statusint partial; //actually bytes per readint this_read; //bytes wanted per readint rd_expire; //how many timeouts will drive us mad char *urb_buf;go_data=file->private_data;down(&go_data->sem); //enter the critical sectiondev=go_data->go7007sb_dev;go_minor=go_data->go7007sb_minor;urb_buf=go_data->in_buf;bytes_read=0;ret=0;rd_expire=GO7007SB_RD_EXPIRE;/**update the access time*/file->f_dentry->d_inode->i_atime=CURRENT_TIME;while(count>0){this_read=(count > IN_URB_BUF_SZ) ? IN_URB_BUF_SZ : count;result=usb_bulk_msg(dev,usb_rcvbulkpipe(dev,go_data->bulk_in_ep),urb_buf,this_read,&partial,GO7007SB_RD_TIMEOUT);/**now check the return status of submited urb*/if(result==-ETIMEDOUT){ //timed outif(!partial){ //no data readif(--rd_expire<=0){warn("read_go7007sb(%d):excessive NAKs received!",go_minor);ret=result;break;}else //keep trying to read datacontinue;}else //timed out,but did receive some datagoto data_rcvd;if(result==-EPIPE){ //endpoint halted, try to recover itif(usb_clear_halt(dev,go_data->bulk_in_ep))err("read_go7007sb(%d):failed to clear endpoint halt condition!",go_minor);ret=result;break;}}else if(result<0 && result!=USB_ST_DATAUNDERRUN){//funky packetwarn("read_scanner(%d):funky result!",go_minor);ret=-EIO;break;}data_rcvd:if(partial){ //there received some dataif(copy_to_user(buffer,urb_buf,partial)){//copy data to user's bufferret=-EFAULT;break;}count-=partial; //update bytes leftbytes_read+=partial; //update bytes have been readbuffer+=partial; //adjust buffer pointer}else{ //no error or data-underrun,but read 0 byte ret=0;break;}}//whileup(&go_data->sem);return ret ? ret : bytes_read;}/**function:write_go7007sb - to write data to go7007sb device,*commonly,this happens when trying to initialize the device*/static ssize_t write_go7007sb(struct file *file,const char *buffer,size_t count,loff_t *ppos){/**write operation is not allowed*/return -EOPNOTSUPP;}/**function:ioctl_go7007sb - to control the device*/static int reset_go7007sb(struct go7007sb_usb_data *go_data){kdev_t go_minor=go_data->go7007sb_minor;int err=0;down(&go_data->sem);*reset the state*/set_state(go_data,GO7007SB_STATE_NOTBOOTED);/**this command has no response,if succeeded,*go7007sb will send BootA irq to the host*/if((err=send_command(go_data,GO7007SB_CMD_SOFTRESET))!=0){printk("<1>reset_go7007sb(%d):send \"reset\" command failed!\n",go_minor);goto out_error;}/**then we must wait for the boot and initial procedure done*so sleep and wait for the state is set to "standby", and*then send the start-coding command to the device*/up(&go_data->sem); //release mutex before sleepingerr=wait_event_interruptible(go_data->wr_wait_q,get_state(go_data)==GO7007SB_STATE_READY);if(!err) //interrupted by signalsreturn err;down(&go_data->sem); //regain the mutexif((err=send_command(go_data,GO7007SB_CMD_START))!=0){printk("<1>reset_go7007sb(%d):send \"start\" command failed!\n",go_minor);goto out_error;}/**wait for the device to start coding*/up(&go_data->sem);interruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem);if(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_RUNNING){printk("<1>reset_go7007sb(%d):process \"start\" command failed!\n",go_minor);err=-EAGAIN;goto out_error;}dbg("reset_go7007sb(%d):reset device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int shutdown_go7007sb(struct go7007sb_usb_data *go_data){int err=0;kdev_t go_minor=go_data->go7007sb_minor;down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_SHUTDOWN))!=0){printk("<1>shutdown_go7007sb(%d):send \"shutdown\" command failed!\n",go_minor);goto out_error;}up(&go_data->sem); //release mutex before sleepinginterruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain mutexif(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_HALTED){printk("<1>shutdown_go7007sb(%d):process \"shutdown\" command failed\n",go_minor);err=-EAGAIN;goto out_error;}dbg("shutdown_go7007sb(%d):shutdown device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int pause_go7007sb(struct go7007sb_usb_data *go_data){int err=0;kdev_t go_minor=go_data->go7007sb_minor;down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_PAUSE))!=0){printk("<1>pause_go7007sb(%d):send \"pause\" command failed!\n",go_minor);goto out_error;}up(&go_data->sem); //release mutex before sleepinginterruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain mutexif(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_PAUSED){printk("<1>pause_go7007sb(%d):process \"pause\" command failed\n",go_minor);err=-EAGAIN;goto out_error;}dbg("pause_go7007sb(%d):pause device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int resume_go7007sb(struct go7007sb_usb_data *go_data){int err=0;kdev_t go_minor=go_data->go7007sb_minor;down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_START))!=0){printk("<1>resume_go7007sb(%d):send \"resume\" command failed!\n",go_minor);goto out_error;}up(&go_data->sem); //release mutex before sleepinginterruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain mutexif(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_RUNNING){printk("<1>resume_go7007sb(%d):process \"resume\" command failed\n",go_minor);err=-EAGAIN;goto out_error;}dbg("resume_go7007sb(%d):resume device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int ioctl_go7007sb(struct inode *inode,struct file *file, unsigned int cmd,unsigned long arg) {struct usb_device *dev;struct go7007sb_usb_data *go_data;int result;kdev_t go_minor;go_data=(struct go7007sb_usb_data *)file->private_data;dev=go_data->go7007sb_dev;go_minor=USB_GO7007SB_MINOR(inode);switch(cmd){case GO7007SB_IOC_GETSTATE :down(&go_data->sem);result=put_user(get_state(go_data),(int *)arg);up(&go_data->sem);break;case GO7007SB_IOC_RESET :result=reset_go7007sb(go_data);break;case GO7007SB_IOC_SHUTDOWN :result=shutdown_go7007sb(go_data);break;case GO7007SB_IOC_PAUSE :result=pause_go7007sb(go_data);break;case GO7007SB_IOC_RESUME :result=resume_go7007sb(go_data);default:result=-ENOIOCTLCMD;}return result;}/**global variable:usb_go7007sb_fops - this variable*defines the operations of go7007sb,the functions*in the struct will be called when access the device*/static struct file_operations usb_go7007sb_fops={owner: THIS_MODULE,read: read_go7007sb,write: write_go7007sb,ioctl: ioctl_go7007sb,open: open_go7007sb,release: close_go7007sb,};/////////////////////////////////////////////////////////////////////// //// go7007sb device driver definition block///////////////////////////////////////////////////////////////////////// /**functions to handle interrupts from go7007sb,*if succeed,return 0, otherwise, return a nonzero number*/static int handle_go7007sb_boot(struct go7007sb_usb_data *go_data){struct file *fm_fp;int retval;kdev_t go_minor=go_data->go7007sb_minor;/**get the file-pointers of firmware and init config packet files*if failed, boot procedure will abort*/if(!(fm_fp=locate_vendor_image(PKT_TYPE_FIRMWARE))){printk("<1>handle_go7007sb_boot(%d):could not locate firmware file!\n",go_minor);return retval;}down(&go_data->sem);/**now send the "start boot" command to the device through bulk out endpoint*this command notify the device we will begin to download firmware data.*/if((retval=send_command(go_data,GO7007SB_CMD_BOOT))<0){printk("<1>handle_go7007sb_boo(%d)t:send \"boot\" command failed!\n",go_minor);goto failed;}/**the begin download the data*/if((retval=download_file(go_data,fm_fp))!=0){printk("<1>handle_go7007sb_boot(%d):download firmware failed!\n",go_minor);goto failed;}set_state(go_data,GO7007SB_STATE_BOOTDONE);goto out;failed:set_state(go_data,GO7007SB_STATE_BOOTFAILED);out:up(&go_data->sem);wake_up_interruptible(&go_data->wr_wait_q);return retval;}static int handle_go7007sb_init(struct go7007sb_usb_data *go_data){struct file *cfg_fp;int retval;kdev_t go_minor=go_data->go7007sb_minor;/**get the file pointer of init configuration packet*/retval=-EINVAL;if(!(cfg_fp=locate_vendor_image(PKT_TYPE_INITPKT))){printk("<1>handle_go7007sb_init(%d):could not locate init packet file!\n",go_minor);return retval;}down(&go_data->sem);/**then download the file*/if((retval=download_file(go_data,cfg_fp))!=0){printk("<1>handle_go7007sb_init(%d):download init packet failed!\n",go_minor);goto failed;}set_state(go_data,GO7007SB_STATE_READY);dbg("handle_go7007sb_init(%d):device is now ready!",go_minor);goto out;failed:set_state(go_data,GO7007SB_STATE_INITFAILED);out:up(&go_data->sem);wake_up_interruptible(&go_data->wr_wait_q);return retval;}static int handle_go7007sb_run(struct go7007sb_usb_data *go_data){down(&go_data->sem);/**just need to change the state*/set_state(go_data,GO7007SB_STATE_RUNNING);up(&go_data->sem);/**wakeup the process in the wr_wait_q*it slept after sending the command*/wake_up_interruptible(&go_data->wr_wait_q);return 0;}static int handle_go7007sb_pause(struct go7007sb_usb_data *go_data) {down(&go_data->sem);/**just need to change the state*/set_state(go_data,GO7007SB_STATE_READY);up(&go_data->sem);wake_up_interruptible(&go_data->wr_wait_q);return 0;}static int handle_go7007sb_shutdown(struct go7007sb_usb_data *go_data) {down(&go_data->sem);/**just need to change the state*/。

相关文档
最新文档