USB gadget设备驱动解析

USB gadget设备驱动解析
USB gadget设备驱动解析

Linux USB gadget设备驱动解析(1)“功能体验”

利用Linux USB gadget设备驱动可以实现一些比较有意思的功能,举两个例子:

1、一个嵌入式产品中的某个存储设备,或是一个存储设备的某个分区,可以作为一个U盘被PC设别,从而非常方便的完成文件交互,这个功能被广泛的应用于手机、数码相机等产品中。

2、一个嵌入式设备通过USB连接到你的PC后,在你的PC端会出现一个新的网络连接,在嵌入式设备上也会有一个网卡设备,你可以配置它们的IP地址,并进行网络通讯,俗称USBNET。

所有USB通讯的设备端都有usb device程序,通常称它们为usb固件。在一些功能简单的设备里,用一些专用的可编程USB控制器就可以了。而在一些运行了类似linux操作系统的复杂的嵌入式系统中,要完成usb device程序,就会要求你不仅熟悉usb device控制器的操作,还要熟悉操作系统的驱动架构。

我想通过―功能体验‖、―驱动调试‖、―gadget驱动结构分析‖、―编写一个自己的gadget驱动‖这4个方面解析linux usb gadget设备驱动的编写方法。

一、linux模拟U盘功能的实现

在硬件环境为华清远见的fs2410平台,软件环境为linux-2.6.26的linux系统上,实现模拟U盘的功能。

向内核添加代码

#include

#include

#include

修改arch/arm/mach-s3c2410/mach-smdk2410.c

/*USB device上拉电阻处理*/

static void smdk2410_udc_pullup(enum s3c2410_udc_cmd_e cmd)

{

u8 *s3c2410_pullup_info[] = {

" ",

"Pull-up enable",

"Pull-up disable",

"UDC reset, in case of"

};

printk("smdk2410_udc: %s\\n",s3c2410_pullup_info[cmd]);

s3c2410_gpio_cfgpin(S3C2410_GPG9, S3C2410_GPG9_OUTP);

switch (cmd)

{

case S3C2410_UDC_P_ENABLE :

s3c2410_gpio_setpin(S3C2410_GPG9, 1); //set gpg9 output HIGH

break;

case S3C2410_UDC_P_DISABLE :

s3c2410_gpio_setpin(S3C2410_GPG9, 0); //set gpg9 output LOW

break;

case S3C2410_UDC_P_RESET :

//FIXME!!!

break;

default:

break;

}

}

static struct s3c2410_udc_mach_info smdk2410_udc_cfg __initdata = {

.udc_command = smdk2410_udc_pullup,

};

static struct platform_device *smdk2410_devices[] __initdata = {

…,

&s3c_device_usbgadget, /*USB gadget device设备登记*/

};

static void __init sdmk2410_init(void)

{

u32 upll_value;

set_s3c2410fb_info(&smdk2410_lcdcfg);

s3c24xx_udc_set_platdata(&smdk2410_udc_cfg); /* 初始化*/

s3c_device_sdi.dev.platform_data = &smdk2410_mmc_cfg;

/* Turn off suspend on both USB ports, and switch the

* selectable USB port to USB device mode. */

s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |

S3C2410_MISCCR_USBSUSPND0 |

S3C2410_MISCCR_USBSUSPND1, 0x0);

/* 设置USB时钟*/

upll_value = (

0x78 << S3C2410_PLLCON_MDIVSHIFT)

| (0x02 << S3C2410_PLLCON_PDIVSHIFT)

| (0x03 << S3C2410_PLLCON_SDIVSHIFT);

while (upll_value != readl(S3C2410_UPLLCON)) {

writel(upll_value, S3C2410_UPLLCON);

udelay(20);

}

}

修改drivers/usb/gadget/file_storage.c

static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,

struct usb_request *req, int *pbusy,

enum fsg_buffer_state *state)

{

int rc;

udelay(800);

……

}

配置内核支持U盘模拟

<*> USB Gadget Support --->

USB Peripheral Controller (S3C2410 USB Device Controller) --->

S3C2410 USB Device Controller

[*] S3C2410 udc debug messages

USB Gadget Drivers

File-backed Storage Gadget

3、编译内核

#make zImage

#make modules

在目录drivers/usb/gadget下生成g_file_storage.ko

加载驱动,测试功能

利用前面的生成的内核,启动系统后,加载g_file_storage.ko

#insmod g_file_storage.ko

# insmod g_file_storage.ko file=/dev/mtdblock2 stall=0 removable=1

0.03 USB: usb_gadget_register_driver() \'g_file_storage\'

0.04 USB: binding gadget driver \'g_file_storage\'

0.05 USB: s3c2410_set_selfpowered()

g_file_storage gadget: File-backed Storage Gadget, version: 20 October 2004 g_file_storage gadget: Number of LUNs=1

g_file_storage gadget-lun0: ro=0, file: /dev/mtdblock3

0.06 USB: udc_enable called

smdk2410_udc: Pull-up enable

连接设备到windows,windows系统会自动设备到一个新的U盘加入。格式化U 盘,存入文件。卸载U盘后,在目标板上执行如下操作:

# mkdir /mnt/gadget

# mount -t vfat /dev/mtdblock2 /mnt/gadget/

#ls

可以看到windows存入U盘的文件。

二、usbnet功能的实现

配置内核支持usbnet

<*> USB Gadget Support --->

USB Peripheral Controller (S3C2410 USB Device Controller) --->

S3C2410 USB Device Controller

[*] S3C2410 udc debug messages

USB Gadget Drivers

Ethernet Gadget (with CDC Ethernet support)

[*] RNDIS support

2、编译内核

#make zImage

#make modules

在目录drivers/usb/gadget下生成g_ether.ko

3、加载驱动,测试功能

利用前面的生成的内核,启动系统后,加载g_ether.ko

#insmod g_ether.ko

#ifconfig usb0 192.168.1.120

……

usb0 Link encap:Ethernet HWaddr 5E:C5:F6:D4:2B:91

inet addr:192.168.1.120 Bcast:192.168.1.255 Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:253 errors:0 dropped:0 overruns:0 frame:0

TX packets:43 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:1000

RX bytes:35277 (34.4 KiB) TX bytes:10152 (9.9 KiB)

连接设备到windows,windows系统会提示安装驱动,根据提示安装上RNDIS 驱动。这个驱动可以在网络上找到。此时windows会新生成一个网络连接,配置它的ip地址等信息。然后就可以和目标系统通过USB实现网络通讯了。

Linux USB gadget设备驱动解析(2)---驱动调试

作者:刘洪涛, 华清远见嵌入式学院金牌讲师。

这一节主要把在实现―linux模拟U盘功能‖过程中的一些调试过程记录下来,并加以解析。

一、背景知识

1、USB Mass Storage类规范概述

USB 组织在universal Serial Bus Mass Storage Class Spaceification 1.1版本中定义了海量存储设备类(Mass Storage Class)的规范,这个类规范包括四个独立的子类规范,即:

1. USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport

https://www.360docs.net/doc/786019518.html,B Mass Storage Class Bulk-Only Transport

https://www.360docs.net/doc/786019518.html,B Mass Storage Class ATA Command Block

https://www.360docs.net/doc/786019518.html,B Mass Storage Class UFI Command Specification

前两个子规范定义了数据/命令/状态在USB 上的传输方法。Bulk- Only 传输规范仅仅使用Bulk 端点传送数据/命令/状态,CBI 传输规范则使用Control/Bulk/Interrupt 三种类型的端点进行数据/命令/状态传送。后两个子规范则定义了存储介质的操作命令。ATA 命令规范用于硬盘,UFI 命令规范是针对USB 移动存储。

Microsoft Windows 中提供对Mass Storage 协议的支持,因此USB 移动设备只需要遵循Mass Storage 协议来组织数据和处理命令,即可实现与PC 机交换

数据。而Flash 的存储单元组织形式采用FAT16 文件系统,这样,就可以直接在Windows的浏览器中通过可移动磁盘来交换数据了,Windows 负责对FAT16 文件系统的管理,USB 设备不需要干预FAT16 文件系统操作的具体细节。

USB(Host)唯一通过描述符了解设备的有关信息,根据这些信息,建立起通信,在这些描述符中,规定了设备所使用的协议、端点情况等。因此,正确地提供描述符,是USB 设备正常工作的先决条件。

Linux-2.6.26内核中在利用USB gadget驱动实现模拟U盘时主要涉及到file_storage.c、s3c2410_udc.c等驱动文件(这些文件的具体结构,将在下一篇文章中描述)。此时我们想先从这些代码中找到USB描述描述符,从中确定使用的存储类规范,从而确定协议。确定通讯协议是我们调试的基础。

存储类规范是由接口描述符决定的。接口描述符各项的定义义如下:

其中,bInterfaceClass、bInterfaceSubClass、bInterfaceProtocol可以判断出设备是否是存储类,以及属于哪种存储子类和存储介质的操作命令。

在file_storage.c文件中,

/* USB protocol value = the transport method */

#define USB_PR_CBI 0x00 // Control/Bulk/Interrupt

#define USB_PR_CB 0x01 // Control/Bulk w/o interrupt

#define USB_PR_BULK 0x50 // Bulk-only

/* USB subclass value = the protocol encapsulation */

#define USB_SC_RBC 0x01 // Reduced Block Commands (flash)

#define USB_SC_8020 0x02 // SFF-8020i, MMC-2, ATAPI (CD-ROM) #define USB_SC_QIC 0x03 // QIC-157 (tape)

#define USB_SC_UFI 0x04 // UFI (floppy)

#define USB_SC_8070 0x05 // SFF-8070i (removable)

#define USB_SC_SCSI 0x06 // Transparent SCSI

默认的情况是:

mod_data = { // Default values

.transport_parm = "BBB",

.protocol_parm = "SCSI",

……

默认的赋值如下:

bInterfaceClass=08 表示:存储类

bInterfaceSubClass=0x06 表示:透明的SCSI指令

bInterfaceProtocol=0x50 表示:bulk-only 传输

2、Bulk-Only 传输协议

下面看看Bulk-Only 传输协议:(详细的规范请阅读《Universal Serial BusMass Storage ClassBulk-Only Transport》)

设备插入到USB 后,USB 即对设备进行搜索,并要求设备提供相应的描述符。在USBHost 得到上述描述符后,即完成了设备的配置,识别出为Bulk-Only 的Mass Storage 设备,然后即进入Bulk-Only 传输方式。在此方式下,USB 与设备间的所有数据均通过Bulk-In和Bulk-Out 来进行传输,不再通过控制端点传输任何数据。

在这种传输方式下,有三种类型的数据在USB 和设备之间传送,CBW、CSW 和普通数据。CBW(Command Block Wrapper,即命令块包)是从USB Host 发送到设备的命令,命令格式遵从接口中的bInterfaceSubClass 所指定的命令块,这里为SCSI 传输命令集。USB设备需要将SCSI 命令从CBW 中提取出来,执行相应的命令,完成以后,向Host 发出反映当前命令执行状态的CSW (Command Status Wrapper),Host 根据CSW 来决定是否继续发送下一个CBW 或是数据。Host 要求USB 设备执行的命令可能为发送数据,则此时需要将特定数据传送出去,完毕后发出CSW,以使Host 进行下一步的操作。USB 设备所执行的操作可用下图描述:

CBW的格式如下:

dCBWSignature:

CBW的标识,固定值:43425355h (little endian)。

dCBWTag:

主机发送的一个命令块标识,设备需要原样作为dCSWTag(CSW中的一部分)再发送给Host;主要用于关联CSW到对应的CBW。

dCBWDataTransferLength:

本次CBW命令要求在命令与回应之间传输的字节数。如果为0,则不传输数据。

bmCBWFlags:

反映数据传输的方向,0 表示来自Host,1 表示发至Host;

bCBWLUN:

对于有多个LUN逻辑单元的设备,用来选择具体目标。如果没有多个LUN,则写0。

bCBWCBLength:

命令的长度,范围在0~16.

CBWCB:

传输的具体命令,符合bInterfaceSubClass.中定义的命令规范,此处是SCSI

CSW命令格式如下:

dCSWSignature:

CSW的标识,固定值:53425355h (little endian)

dCSWTag:

设置这个标识和CBW中的dCBWTag一致,参照上面关于dCBWTag 的解释

dCSWDataResidue:

还需要传送的数据,此数据根据dCBWDataTransferLength-本次已经传送的数据得到

bCSWStatus:

指示命令的执行状态。如果命令正确执行,bCSWStatus 返回0 即可。

3、SCSI指令集

Bulk-Only 的CBW 中的CBWCB 中的内容即为如下格式的命令块描述符(Command Block Descriptor)。SCSI-2 有三种字长的命令,6 字节、10字节和12字节,Microsoft Windows 环境下支持12 字节长的命令。

Operation Code:

操作代码,表示特定的命令。高3 位为Group Code,共有8 种组合,即8 个组,低5 五位为Command Code,可以有32 种命令。

Logicol unit Number:

为了兼容SCSI-1 而设的,此处可以不必关心。

Logical block address:

为高位在前,低位在后的逻辑块地址,即扇区地址。第2 位为高位,第3、4、5 依次为低位。

Transfer length:

为需要从逻辑块地址处开始传输的扇区数(比如在Write 命令中)。

Parameter list length:

为需要传输的数据长度(比如在Mode Sense 命令中);

Allocation length:

为初始程序为返回数据所分配的最大字节数,此值可以为零,表示不需要传送数据。

SCSI指令集的Direct Accesss 类型存储介质的传输命令有许多,Mass Storage协议只用到了其中的一些。更多的SCSI指令参见:https://www.360docs.net/doc/786019518.html,/wiki/SCSI_command

指令代码指令名称说明

04h Format Unit 格式化存储单元

12h Inquiry 索取器件信息

1Bh Start/Stop load/unload

55h Mode select 允许Host对外部设备设置参数。

5Ah Mode Sense 向host传输参数

Eh Prevent/Allow Medium Removal 写保护

>28h Read(10)Host读存储介质中的二进制数据

A8h Read(12)同上,不过比较详细一点

25h Read Capacity 要求设备返回当前容量

23h Read Format Capacity 查询当前容量及可用空间

03h Request Sense 请求设备向主机返回执行结果,及状态数据

01h Rexero Unit 返回零轨道

2Bh Seek(10)为设备分配到特定地址

1Dh Send Diagnostic 执行固件复位并执行诊断

00h Test Unit Ready 请求设备报告是否处于Ready状态

2Fh Verify 在存储中验证数据

2Ah Write(10)从主机向介质写二进制数据

AAh Write(12)同上,不过比较详细

2Eh Write and Verify 写二进制数据并验证

对于不同的命令,其命令块描述符略有不同,其要求的返回内容也有所不同,根据相应的文档,可以对每种请求作出适当的回应。比如,下面是INQUIRY 请求的命令块描述符和其返回内容的数据格式:如:INQUIRY

命令描述符:

返回数据格式

Host 会依次发出INQUIRY、Read Capacity、UFI Mode Sense 请求,如果上述请求的返回结果都正确,则Host 会发出READ 命令,读取文件系统0 簇0 扇区的MBR 数据,进入文件系统识别阶段。

4、利用USB View观察结果

可通过USB View软件查看到USB设置阶段获取到的信息。

二、出现的主要问题

在调试过程中遇到了一个问题。现象是:在目标板加载完驱动后,即执行完:

# insmod g_file_storage.ko file=/dev/mtdblock2 stall=0 removable=1 后,接好USB线。此时在windows端设备出有usb storage设备加入,但出现不了盘符。

下面记录下调试过程。

三、调试过程

根据规范,当完成SCSI指令集中Inquiry 命令时,可以出现盘符。所以可以通过bushound软件查看通讯过程,找出原因。

下面是利用bushound工具在出现问题时采集到的数据。

Dev Phase Data

Info Time Cmd.Phase. Ofs

--- ----- --------------------------------- ---------- ----- -----------

26 CTL 80 06 00 01 - 00 00 12 00 GET DESCRIPTR 0us 1.1.0

26 DI 12 01 10 01 - 00 00 00 10 - 25 05 a5 a4 - 12 03 01

02 ........%....... 4.8ms 1.2.0

03 01 ..

1.2.16

26 CTL 80 06 00 02 - 00 00 09 00 GET DESCRIPTR 14us 2.1.0

26 DI 09 02 20 00 - 01 01 04 c0 -

01 .. ...... 3.9ms

2.2.0

26 CTL 80 06 00 02 - 00 00 20 00 GET DESCRIPTR 16us 3.1.0

26 DI 09 02 20 00 - 01 01 04 c0 - 01 09 04 00 - 00 02 08 06 .. ............. 4.9ms 3.2.0

50 05 07 05 - 81 02 40 00 - 00 07 05 02 - 02 40 00 00 P.....@......@.. 3.2.16

26 CTL 80 06 00 03 - 00 00 02 00 GET DESCRIPTR 60us 4.1.0

26 DI 09 02 20 00 - 01 01 04 c0 -

01 .. ...... 3.9ms

2.2.0

26 DI 04 03 ..

3.9ms 3.1.0

26 CTL 80 06 00 03 - 00 00 04 00 GET DESCRIPTR 15us 5.1.0

26 DI 04 03 09 04 ....

3.9ms 6.1.0

26 CTL 80 06 03 03 - 09 04 02 00 GET DESCRIPTR 10us 1.2.16

26 DI 1a 03

.... 4.0ms 6.2.0

26 CTL 80 06 03 03 - 09 04 1a 00 GET DESCRIPTR 18us 7.1.0

26 DI 1a 03 33 00 - 37 00 32 00 - 30 00 34 00 - 31 00 37 00 ..3.7.2.0.4.1.7. 4.9ms 7.2.0

35 00 36 00 - 37 00 37 00 - 35 00 5.6.7.7.5. 7.2.16

26 CTL 00 09 01 00 - 00 00 00 00 SET CONFIG 16us 8.1.0

26 CTL 01 0b 00 00 - 00 00 00 00 SET INTERFACE 60ms 9.1.0

26 CTL a1 fe 00 00 - 00 00 01 00 CLASS 62ms 10.1.0

26 DI 00 .

3.9ms 10.2.0

26 DO 55 53 42 43 - 08 60 e0 86 - 24 00 00 00 - 80 00 06 12 USBC.`..$....... 985us 11.1.0

00 00 00 24 - 00 00 00 00 - 00 00 00 00 - 00 00 00 ...$........... 11.1.16

26 DI 00 80 02 02 - 1f 00 00 00 - 4c 69 6e 75 - 78 20 20 20 ........Linux 1.0ms 12.1.0

46 69 6c 65 - 2d 53 74 6f - 72 20 47 61 - 64 67 65 74 File-Stor Gadget 12.1.16

30 33 31 32 0312 12.1.32

26 CTL 80 06 00 02 - 00 00 20 00 GET DESCRIPTR 893ms 13.1.0

26 DI 09 02 20 00 - 01 01 04 c0 - 01 09 04 00 - 00 02 08 06 .. ............. 4.1ms 13.2.0

50 05 07 05 - 81 02 40 00 - 00 07 05 02 - 02 40 00 00 P.....@......@.. 13.2.16

26 CTL 80 06 00 02 - 00 00 20 00 GET DESCRIPTR 2.7sc 14.1.0

26 DI 09 02 20 00 - 01 01 04 c0 - 01 09 04 00 - 00 02 08 06 .. ............. 4.4ms 14.2.0

50 05 07 05 - 81 02 40 00 - 00 07 05 02 - 02 40 00 00 P.....@......@.. 14.2.16

26 USTS 05 00 00 c0 no response 2.8sc 15.1.0

注意上面红色部分的代码,DO发出了55 53 42 43开始的CBW命令块,命令码是12,即Inquiry命令。要求目标返回Inquiry命令要求的数据,长度是0x24。接下来设备端通过DI返回了设备信息。按照规范,在返回完了数据后,设备端还应该通过DI向系统返回CSW的值。但实际的捕获内容并没有。所以导致不能正确出现盘符。

在file_storage.c中,发送数据时都会调用到start_transfer()函数。在此函数中加入printk调试语句,观察现象。发现只要加入的调试语句,windows端就能够正常设别设备了。于是,可以猜测是因为需要在连续两次发送之间加上一些延时。在函数中加入udelay(800)后,windows系统可以正常发现设备了。具体的代码架构,将在下一遍文章中解析。

下面是程序正常后,用bushound捕获到的数据。

红色部分,可以看出设备正确的按照规范在发送完数据后,返回CSW信息。

四、总结做好USB gadget驱动、或者USB host驱动调试需要:

·掌握一定的知识基础

包括:USB协议、具体的类设备规范、USB驱动程序架构、USB设备端控制器操作等。

·合理利用调试工具。

包括:USB view 、bushound 、及一些硬件USB信号分析仪。

作者:刘洪涛,华清远见嵌入式学院讲师。

Linux USB 设备端驱动有两部分组成。一部分是USB 设备控制器(USB Device Controller, UDC)驱动、另一部分是硬件无关的功能驱动(如:鼠标、u盘、usb 串口、usb网络等);也可以分为3层的,分别是:Controller Drivers、Gadget Drivers、Upper Layers,大概意思都差不多。

一、控制器(USB Device Controller, UDC)驱动

Gadget 框架提出了一套标准API, 在底层,USB 设备控制器驱动则实现这一套API, 不同的UDC需要不同的驱动,甚至基于同样的UDC 的不同板子也需要进行代码修改。这一层是硬件相关层。

Linux 标准内核里支持各种主流SOC 的udc 驱动,如:S3C2410、PXA270等。你可以通过内核直接配置支持。你也可以通过修改它们获取更高的效率。如:s3c2410_uda.c 中并没有利用到控制器的dma功能,你可以根据需要修改它。

要理解UDC驱动代码就必须对相应的硬件控制器熟悉。当然,如果你对此不感兴趣,或没时间熟悉,也可以暂时跳过对硬件相关部分。本文也侧重于对软件结构的描述,不关心硬件细节。

下面给出在UDC驱动中涉及到的一些关键数据结构及API,参考s3c2410_uda.c

1.关键的数据结构及API

gadget api 提供了usb device controller 驱动和上层gadget驱动交互的接口。下面列出一些关键的数据结构。

struct usb_gadget {//代表一个UDC设备

/* readonly to gadget driver */

const struct usb_gadget_ops *ops; //设备的操作集

struct usb_ep *ep0; //ep0(USB协议中的端点0), 处理setup()请求

struct list_head ep_list; /* of usb_ep */本设备支持的端点链表

enum usb_device_speed speed; //如:USB_SPEED_LOW、USB_SPEED_FULL等

unsigned is_dualspeed:1; //支持full/high speed

unsigned is_otg:1; //OTG的特性

unsigned is_a_peripheral:1; //当前是A-peripheral,而不是A-host

unsigned b_hnp_enable:1;

unsigned a_hnp_support:1;

unsigned a_alt_hnp_support:1;

const char *name;

struct device dev;

};

struct usb_gadget_driver {//代表一个gadget设备driver,如:file_storage.c中的fsg_driver

//又如:如zero.c中的zero_driver

char *function; //一个字符串,如"Gadget Zero"

enum usb_device_speed speed;

int (*bind)(struct usb_gadget *);

void (*unbind)(struct usb_gadget *);

int (*setup)(struct usb_gadget *,

const struct usb_ctrlrequest *);

void (*disconnect)(struct usb_gadget *);

void (*suspend)(struct usb_gadget *);

void (*resume)(struct usb_gadget *)

/* FIXME support safe rmmod */

struct device_driver driver;

};

struct usb_gadget_ops {//代表设备的操作集

int (*get_frame)(struct usb_gadget *);

int (*wakeup)(struct usb_gadget *);

int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);

nt (*vbus_session) (struct usb_gadget *, int is_active);

int (*vbus_draw) (struct usb_gadget *, unsigned mA);

int (*pullup) (struct usb_gadget *, int is_on);

int (*ioctl)(struct usb_gadget *,

unsigned code, unsigned long param);

};

struct usb_ep {//代表一个端点

void *driver_data //

...

const struct usb_ep_ops *ops; //端点的操作集,如上

struct list_head ep_list; //gadget的所有ep的list

...

};

struct usb_ep_ops {//表示端点的操作集

...

int (*queue) (struct usb_ep *ep, struct usb_request *req,

gfp_t gfp_flags); //将一个usb_request提交给endpoint

//是数据传输的关键函数

...

};

struct usb_request {//表示一个传输的请求,这与usb host端的urb类似

void *buf;

unsigned length;

dma_addr_t dma;

unsigned no_interrupt:1;

unsigned zero:1;

unsigned short_not_ok:1;

void (*complete)(struct usb_ep *ep,

struct usb_request *req);

void *context;

struct list_head list;

int status;

unsigned actual;

};

上述结构中具体每项的含义可以参考https://www.360docs.net/doc/786019518.html,/linux-docbook/gadget/

如:struct usb_request

在https://www.360docs.net/doc/786019518.html,/linux-docbook/gadget/re02.html中

Name

struct usb_request — describes one i/o request

Synopsis

struct usb_request {

void * buf;

unsigned length;

dma_addr_t dma;

unsigned no_interrupt:1;

unsigned zero:1;

unsigned short_not_ok:1;

void (* complete) (struct usb_ep *ep,struct usb_request *req);

void * context;

struct list_head list;

int status;

unsigned actual;

};

Members

buf

Buffer used for data. Always provide this; some controllers only use PIO, or don't use DMA for some endpoints.

length

Length of that data

dma

DMA address corresponding to 'buf'. If you don't set this field, and the usb controller needs one, it is responsible for mapping and unmapping the buffer.

no_interrupt

If true, hints that no completion irq is needed. Helpful sometimes with deep request queues that are handled directly by DMA controllers.

zero

If true, when writing data, makes the last packet be ―short‖ by adding a zero length packet as needed;

short_not_ok

When reading data, makes short packets be treated as errors (queue stops advancing till cleanup).

complete

Function called when request completes, so this request and its buffer may be re-used. Reads terminate with a short packet, or when the buffer fills, whichever comes first. When writes terminate, some data bytes will usually still be in flight (often in a hardware fifo). Errors (for reads or writes) stop the queue from advancing until the completion function returns, so that any transfers invalidated by the error may first be dequeued.

context

For use by the completion callback

list

For use by the gadget driver.

status

Reports completion code, zero or a negative errno. Normally, faults block the transfer queue from advancing until the completion callback returns. Code ―-ESHUTDOWN‖ indicates completion caused by device disconnect, or when the driver disabled the endpoint.

actual

Reports bytes transferred to/from the buffer. For reads (OUT transfers) this

may be less than the requested length. If the short_not_ok flag is set, short reads are treated as errors even when status otherwise indicates successful completion. Note that for writes (IN transfers) some data bytes may still reside in a device-side FIFO when the request is reported as complete.

Description

These are allocated/freed through the endpoint they're used with. The hardware's driver can add extra per-request data to the memory it returns,whichoften avoids separate memory allocations (potential failures), later when the request is queued.

Request flags affect request handling, such as whether a zero length packet is written (the ―zero‖ flag), whether a short read should be treated as anerror (blocking request queue advance, the ―short_not_ok‖ flag), or hinting that an interrupt is not required (the ―no_interrupt‖ flag, for use with deeprequest queues).

Bulk endpoints can use any size buffers, and can also be used for interrupt transfers. interrupt-only endpoints can be much less functional.

2、为USB gadget功能驱动提供的注册、注销函数

EXPORT_SYMBOL(usb_gadget_unregister_driver); //注销一个USB gadget功能驱动

EXPORT_SYMBOL(usb_gadget_register_driver);//注册一个USB gadget功能驱动

二、USB gadget功能驱动

如果内核已经支持了SOC的UDC驱动,很多时候,我们可以只关心这部分代码的编写。那么我们如何编写出一个类似usb 功能驱动呢?

usb 功能驱动应该至少要实现如下功能:

.实现USB协议中端点0部分和具体功能相关的部分(UDC驱动无法帮我们完成的部分)。如:USB_REQ_GET_DESCRIPTOR、USB_REQ_GET_CONFIGURATION等;

完成了这个功能以后,USB主机端系统就会设别出我们是一个什么样的设备。

实现数据交互功能

即如何实现向硬件控制器的端点发出读、写请求来完成数据交互;

具体功能的实现如:如何实现一个usb net驱动,或是一个usb storage驱动。

接下来以zero.c为例,说明这3个方面是如何实现的。

1、zero设备介绍

作为一个简单的gadget 驱动,zero 的功能基于两个BULK 端点实现了简单的输入输出功能,它可以用作写新的gadget 驱动的一个实例。

两个BULK 端点为一个IN 端点, 一个OUT端点。基于这两个(由底层提供的)端点,g_zero 驱动实现了两个configuration。第一个configuration 提供了sink/source功能:两个端点一个负责输入,一个负责输出,其中输出的内容根据设置可以是全0,也可以是按照某种算法生成的数据。另一个configuration 提供了loopback 接口,IN 端点负责把从OUT 端点收到的数据反馈给Host. 2、zero设备注册、注销

static int __init init(void)

{

return usb_gadget_register_driver(&zero_driver);

}

module_init(init);

static struct usb_gadget_driver zero_driver = {

#ifdef CONFIG_USB_GADGET_DUALSPEE

.speed = USB_SPEED_HIGH,

#else

.speed = USB_SPEED_FULL,

#endif

.function = (char *) longname,

.bind = zero_bind,

.unbind = __exit_p(zero_unbind),

.setup = zero_setup,

.disconnect = zero_disconnect,

.suspend = zero_suspend,

.resume = zero_resume,

.driver = {

.name = (char *) shortname,

.owner = THIS_MODULE,

},

};

构建一个usb_gadget_driver,调用usb_gadget_register_driver注册函数即可注册一个usb gadget驱动。需要注意的是,目前S3C2410主机控制器只能注册一个gadget功能驱动。这主要是由协议决定的。参考s3c2410_udc.c中的这段代码

int usb_gadget_register_driver(struct usb_gadget_driver *driver)

{……

if (udc->driver)//如果已经注册过了

return -EBUSY;

……

}

3、usb_gadget_driver结构

事实上我们的工作就是构建这个usb_gadget_driver结构。那么这个结构这样和我们上面要实现的3个目标联系起来呢。

. Setup (zero_setup)

处理host端发来的request,如:处理host端发来的get_descriptor请求。在这实现了前面提到的必须要实现的第一个功能。

. bind (zero_bind)

绑定dev与driver,在gadget driver,注册驱动时被usb_gadget_register_driver 调用,绑定之后driver才能处理setup请求

另外,通过usb_ep_autoconfig函数,可以分配到名为EP_IN_NAME、EP_OUT_NAME两个端点。后面可以对两个端点发起数据传输请求,和USB 主机端的urb请求非常相似,大家可以和urb对照一些。

发起数据请求大致有以下几步:

struct usb_request *req;

req = alloc_ep_req(ep, buflen);//分配请求,数据传输的方向由ep 本身决定

req->complete = source_sink_complete; //请求完成后的处理函数

status = usb_ep_queue(ep, req, GFP_ATOMIC);//递交请求

free_ep_req(ep, req);//释放请求,通常在请求处理函数complete 中调用

. 通常在bind和unbind函数中注册具体的功能驱动

如果为了实现某个特定功能需要在设备端注册字符、块、网络设备驱动的话,选择的场

合通常是bind中注册,unbind中卸载。如ether.c文件中:

static int __init

eth_bind (struct usb_gadget *gadget)

{

……

status = register_netdev (dev->net); //注册网卡驱动

……

}

static void /* __init_or_exit */

eth_unbind (struct usb_gadget *gadget)

{

……

unregister_netdev (dev->net); //注销网卡驱动

……

}

这也让我们对在设备端实现一个字符、块、网络驱动的结构有了一些了解。总结

本文对gadget的驱动结构做了简要的介绍。下一篇将介绍如何编写一个简单的gadget驱动及应用测试程序。

一、编写计划

通过前面几节的基础,本节计划编写一个简单的gadget驱动。重在让大家快速了解gadget驱动结构。

上节中简单介绍了zero.c程序。这个程序考虑到了多配置、高速传输、USB OTG 等因素。应该说写的比较清楚,是我们了解gadget驱动架构的一个非常好的途径。但把这些东西都放在一起,对很多初学人员来说还是不能快速理解。那就再把它简化一些,针对S3C2410平台,只实现一个配置、一个接口、一个端点,不考虑高速及OTG的情况。只完成单向从host端接收数据的功能,但要把字符设备驱动结合在里面。这需要有一个host端的驱动,来完成向device端发送数据。关于在主机端编写一个简单的USB设备驱动程序,有很多的资料。相信大家很快就会完成的。

二、功能展示

字符设备驱动程序课程设计报告

中南大学 字符设备驱动程序 课程设计报告 姓名:王学彬 专业班级:信安1002班 学号:0909103108 课程:操作系统安全课程设计 指导老师:张士庚 一、课程设计目的 1.了解Linux字符设备驱动程序的结构; 2.掌握Linux字符设备驱动程序常用结构体和操作函数的使用方法; 3.初步掌握Linux字符设备驱动程序的编写方法及过程; 4.掌握Linux字符设备驱动程序的加载方法及测试方法。 二、课程设计内容 5.设计Windows XP或者Linux操作系统下的设备驱动程序; 6.掌握虚拟字符设备的设计方法和测试方法;

7.编写测试应用程序,测试对该设备的读写等操作。 三、需求分析 3.1驱动程序介绍 驱动程序负责将应用程序如读、写等操作正确无误的传递给相关的硬件,并使硬件能够做出正确反应的代码。驱动程序像一个黑盒子,它隐藏了硬件的工作细节,应用程序只需要通过一组标准化的接口实现对硬件的操作。 3.2 Linux设备驱动程序分类 Linux设备驱动程序在Linux的内核源代码中占有很大的比例,源代码的长度日益增加,主要是驱动程序的增加。虽然Linux内核的不断升级,但驱动程序的结构还是相对稳定。 Linux系统的设备分为字符设备(char device),块设备(block device)和网络设备(network device)三种。字符设备是指在存取时没有缓存的设备,而块设备的读写都有缓存来支持,并且块设备必须能够随机存取(random access)。典型的字符设备包括鼠标,键盘,串行口等。块设备主要包括硬盘软盘设备,CD-ROM等。 网络设备在Linux里做专门的处理。Linux的网络系统主要是基于BSD unix的socket 机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据传递。系统有支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。 3.3驱动程序的结构 驱动程序的结构如图3.1所示,应用程序经过系统调用,进入核心层,内核要控制硬件需要通过驱动程序实现,驱动程序相当于内核与硬件之间的“系统调用”。

虚拟声卡驱动程序VirtualAudioCable使用方法

一:安装软件 点击 选择是(Y) 选择I accept 选择Install 安装成功,点击“确定”按钮即完成安装。 二、软件的设置 点击桌面开始按钮所有程序---Virtual Audio Cable —Control panel 进入软件初始化 设置。 在Cables 中选择1(即首次设置一个虚拟通道),点击旁边的Set 按钮生成通道Cable1. 在参数设置区将Line 、Mic (可选可不选)、S/PDIF (可选可不选)三个选项后面的方框打钩,选中之后点击参数设置区内的设置按钮Set ,即完成了,对虚拟声卡通道1 的设置。 鼠标右键点击桌面右下角的喇叭------ 调整音频属性---- < 或者点击开始—控制面板--- 声音、 语音和音频设备--- 声音和音频设备>弹出: 选择语音 此时语音部分的设置为原系统默认的设备,保持不变。 选择音频: 改变声音播放、录音的选项内容:

如上图将声音播放、录音的默认设备全部改为Virtual Cable 1 。点击应用--- 确定即可。 三、打开录音机录音--- 录制电脑里播放出来的音频(不包含麦克风 里的声音) - 即“内录” 开始--- 所有程序—附件--- 娱乐--- 录音机 点击确定即可开始录音(注:此时可在电脑中打开相应的音频文件,开始录音) 此时音频波段显示有声音输入,但是电脑的耳机听不到正在播放的音频文件(属正常现象)。若想同时听到音频文件的内容点击桌面开始按钮所有程序---Virtual Audio Cable —Audio Repeater 。 修改为 点击Start 即可听到正在录制的音频文件。此时的录音即是通过虚拟声卡通道录制电脑里的声音的。 四、同时录电脑里播放的声音和麦克风收集的外部声音----- 即混录 <通过这种方法解决现有笔记本无“立体声混音”或“波形音”选项的问题> 在《三打开录音机录音--- 录制电脑里播放出来的音频(不包含麦克风里的声音)------------ 即“内录”》的同时,在打开一个irtual Audio Cable —Audio Repeater 窗口将其设置为: 即将外部麦克风收集的声音转移到虚拟声卡通道Cable1 中,同电脑里播放的声音一起被录音软件收录为音频文件。

未能成功安装设备驱动程序MTPUSB设备安装失败的解决办法

未能成功安装设备驱动程序M T P U S B设备安装失败的解决办法 文件编码(GHTU-UITID-GGBKT-POIU-WUUI-8968)

M T P U S B设备安装失败未能成功安装设备驱动程序 终极解决方法 环境介绍:电脑系统win7(32位)已安装摩托罗拉手机驱动版本(其他版本应该也行,不行的话去摩托罗拉官网下载最新驱动) 手机型号:摩托罗拉defy mb525(系统) 备注:其他电脑操作系统和不同型号手机可参考此方法,找到相应设置项即可。 问题简介: 1.当我们把手机连接至电脑,把模式调制成“摩托罗拉手机门户”时,出现下列情况 2.过一会之后便会弹出提示说:未能成功安装设备驱动程序

3.单击查看详情便弹出窗口如下图所示: 4.此时桌面右下角图标出现黄色三角号,如图所示: 5.于是我们就开始不淡定了,怎么看怎么别扭、抓狂、按耐不住。下面介绍问题解决方案 解决方法: 1.我的电脑——右键单击——管理——设别管理器,之后会看到如图所示:在便携设备下有黄色三角号提示,即是我们纠结的MTP USB设备安装不成功的展示。

MIUI手机操作系统为例,其他手机操作系统需将USB绑定服务开启即可)。选择设置——系统——共享手机网络——USB绑定,将该选项设置为“开”,这是你会发现如图所示变化,在设备管理器面板中没有了便携设备选项及黄色三角号提醒,如图所示:(但桌面右下角的黄色三角警示还在)

3.在完成以上步骤后,用手机打开WIFI并登录无线WLAN,手机打开网页检验连接是否正常,若正常则如下图所示,黄色三角号警示消失,问题解决;若以上步骤没有解决问题,请先连接WIFI并登录WLAN之后,再按步骤操作。 4.完成以上步骤并解决问题后,选择电脑桌面网络——右键单击——属性,如下图所示:此时不仅手机能上网,而且电脑也能正常连接网络,正常上网。(我的体验是连接数据不稳定,时不时的要手机重新登陆WIFI,才有数据传输,可能是高校WLAN的问题,在家网速快的可以尝试一下) 5.通过这个问题的解决,我才知道原来MTP USB设备安装失败,未能成 功安装设备驱动程序的原因是我们手机里面没有启用该设备服务。今天 才知道MTP USB设备是与手机里的共享手机网络中“USB绑定”服务相关 联的,是电脑用来使用手机WIFI网络连接进行上网的工具。

usb驱动程序教程

编写Windows https://www.360docs.net/doc/786019518.html,的usb驱动程序教程 Windows https://www.360docs.net/doc/786019518.html, 是微软推出的功能强大的嵌入式操作系统,国内采用此操作系统的厂商已经很多了,本文就以windows https://www.360docs.net/doc/786019518.html,为例,简单介绍一下如何开发windows https://www.360docs.net/doc/786019518.html, 下的USB驱动程序。 Windows https://www.360docs.net/doc/786019518.html, 的USB系统软件分为两层: USB Client设备驱动程序和底层的Windows CE实现的函数层。USB设备驱动程序主要负责利用系统提供的底层接口配置设备,和设备进行通讯。底层的函数提本身又由两部分组成,通用串行总线驱动程序(USBD)模块和较低的主控制器驱动程序(HCD)模块。HCD负责最最底层的处理,USBD模块实现较高的USBD函数接口。USB设备驱动主要利用 USBD接口函数和他们的外围设备打交道。 USB设备驱动程序主要和USBD打交道,所以我们必须详细的了解USBD提供的函数。 主要的传输函数有: abourttransfer issuecontroltransfer closetransfer issuein te rruptransfer getisochresult issueisochtransfer gettransferstatus istransfercomplete issuebulktransfer issuevendortransfer 主要的用于打开和关闭usbd和usb设备之间的通信通道的函数有: abortpipetransfers closepipe isdefaultpipehalted ispipehalted openpipe resetdefaultpipe resetpipe 相应的打包函数接口有: getframelength getframenumber releaseframelengthcontrol setframelength takeframelengthcontrol 取得设置设备配置函数: clearfeature setdescriptor getdescriptor setfeature

Linux的LCD驱动源码分析及移植

Linux的LCD驱动源码分析及移植(三部曲) 第一部分: 基于ARM9处理器的linux-2.6.32.2操作系统内核移植手记part5.1(LCD驱动源码分析及移植之platform device) 1.与LCD控制器硬件相关的寄存器内容请参照三星S3C2440A技术手册中的第15章。 2. LCD Controller的平台设备定义如下(文件位于linux/arch/arm/plat-s3c24xx/devs.c):

1./* LCD Controller */ 2. 3.static struct resource s3c_lcd_resource[] = { 4. [0] = { 5. .start = S3C24XX_PA_LCD, 6. .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1, 7. .flags = IORESOURCE_MEM, 8. }, 9. [1] = { 10. .start = IRQ_LCD, 11. .end = IRQ_LCD, 12. .flags = IORESOURCE_IRQ, 13. } 14. 15.}; 16. 17.static u64 s3c_device_lcd_dmamask = 0xffffffffUL; 18. 19.struct platform_device s3c_device_lcd = { 20. .name = "s3c2410-lcd", 21. .id = -1, 22. .num_resources = ARRAY_SIZE(s3c_lcd_resource), 23. .resource = s3c_lcd_resource, 24. .dev = { 25. .dma_mask = &s3c_device_lcd_dmamask, 26. .coherent_dma_mask = 0xffffffffUL 27. } 28.}; 29. 30.EXPORT_SYMBOL(s3c_device_lcd); 平台设备的结构体定义为s3c_device_lcd,该设备在平台总线中的名字取为s3c2410-lcd,该平台设备申请的两个板级资源为以S3C24XX_PA_LCD为起始的IORESOURCE_MEM资源和一个定义为IRQ_LCD的IORESOURCE_IRQ资源。 其中, 1.#define S3C24XX_PA_LCD S3C2410_PA_LCD 1./* LCD controller */ 2.#define S3C2410_PA_LCD (0x4D000000) 3.#define S3C24XX_SZ_LCD SZ_1M 0x4D000000为LCDCON1寄存器的地址。

编译hello设备驱动程序详细过程

编译hello world设备驱动程序详细过程 1、安装与你的开发板相同的内核版本的虚拟机,我的板子内核是2.6.8.1,虚拟机是2.6.9, 一般是虚拟机的内核只能比板子内核新,不能旧 #uanme –a [1](在任何目录下,输入此命令,查看虚拟机的内核版本,我的内核版本是2.6.9) 2、在虚拟机上设置共享目录,我的共享目录在linux下的/mnt/hgfs/share [2]share是自己命名的,我的物理机上,即Windows下的目录是G:/share, 3、在Windows下,把开发板的的交叉开发工具链[3],内核源码包[4],复制到物理机的共享目录下[5] 即Windows下的目录是G:/share, 4、#cp /mnt/hgfs/share/cross-3.3.2.tar.bz2 /usr/local/arm [6] 在Linux下,把交叉工具链,复制到/usr/local/arm目录下 5、#cd /usr/local/arm 6、#tar jxvf cross-3.3.2.tar.bz2 [7] 并在当前目录/usr/local/arm下解压它cross-2.95.3.tar.bz2和gec2410-linux-2.6.8.tar.bz2也是用同样的命令去解压 7、#export PATH=/usr/local/arm/3.3.2/bin:$PATH [8] 安装交叉工具链,在需要使用交叉编译时,只要在终端输入如下命令 #export PATH=/usr/local/arm/版本/bin:$PATH 即可,在需要更改不同版本的工具链时,重新启动一个终端,然后再一次输入上面的命令即可,使用哪个版本的交叉工具链,视你要编译的内核版本决定,编译2.4版本的内核,则用2.95.3版本的交叉工具链,而2.6版本内核的,则要用3.3.2版本的交叉工具链。 8、#cp gec2410-linux-2.6.8.tar.bz2 /root [9]把内核拷贝到/root目录下, 9、#cd /root 10、#tar gec2410-linux-2.6.8.tar.bz2 [10] 在/root解压开发板的内核源码压缩包gec2410-linux-2.6.8.tar.bz2,得到gec2410-linux-2.6.8.1文件夹 11、#cd /root/ gec2410-linux-2.6.8.1 12、#cp gec2410.cfg .config [11] gec2410.cfg文件是广嵌开发板提供的默认内核配置文件,在这里首先把内核配置成默认配置,然后在此基础上用make menuconfig进一步配置,但在这里,不进行进一步的配置,对于内核配置,还需要看更多的知识,在这里先存疑。 13、#make [12]在内核源代码的根目录gec2410-linux-2.6.8.1下用make命令编译内核,注意,先安装交叉工具链,再编译内核,因为这里编译的hello.ko驱动模块最终是下载到开发板上运行的,而不是在虚拟机的Linux系统运行的,如果是为了在虚拟机的Linux系统运行的,则不用安装交叉编译工具链arm-linux-gcc,而直接用gcc,用命令#arm-linux-gcc –v 可以查看当前已经安装的交叉编译工具链的版本。这里编译内核不是为了得到内核的映象文件zImage(虽然会得到内核的映象文件zImage),而是为了得到编译hello.o模块需要相关联,相依赖(depends on)的模块。 14、#cd /root 12、#mkdir hello [13]在/root目录下建立hello文件夹, 13、#cd hel 14 、#vi hello.c [12]编辑hello.c文件,内容是《Linux设备驱动程序》第三版22页的hello world程序。 15、#vi Makefile [13]在hello文件夹下编辑Makefile文件, 16、obj-m := module.o [14] 这是Makefile的内容,为obj-m := module.omodule.o视你编辑的.c文件而定,这里则要写成hello.o,写完后,保存退出。 17、cd /root/hello

设备驱动程序

驱动程序 驱动程序一般指的是设备驱动程序(Device Driver),是一种可以使计算机和设备通信的特殊程序。相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。 因此,驱动程序被比作“硬件的灵魂”、“硬件的主宰”、和“硬件和系统之间的桥梁”等。 中文名 驱动程序 外文名 Device Driver 全称 设备驱动程序 性质 可使计算机和设备通信的特殊程序 目录 1定义 2作用 3界定 ?正式版 ?认证版 ?第三方 ?修改版 ?测试版 4驱动程序的开发 ?微软平台 ?Unix平台 5安装顺序 6inf文件 1定义 驱动程序(Device Driver)全称为“设备驱动程序”,是一种可以使计算机和设备通信的特殊程序,可以说相当于硬件的接口,操作系统只能通过这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。 惠普显卡驱动安装 正因为这个原因,驱动程序在系统中的所占的地位十分重要,一般当操作系统安装完毕后,首要的便是安装硬件设备的驱动程序。不过,大多数情况下,我们并不需要安装所有硬件设备的驱动程序,例如硬盘、显示器、光驱等就不需要安装驱动程序,而显卡、声卡、扫描仪、摄像头、Modem等就需要安装驱动程序。另外,不同版本的操作系统对硬件设

备的支持也是不同的,一般情况下版本越高所支持的硬件设备也越多,例如笔者使用了Windows XP,装好系统后一个驱动程序也不用安装。 设备驱动程序用来将硬件本身的功能告诉操作系统,完成硬件设备电子信号与操作系统及软件的高级编程语言之间的互相翻译。当操作系统需要使用某个硬件时,比如:让声卡播放音乐,它会先发送相应指令到声卡驱动程序,声卡驱动程序接收到后,马上将其翻译成声卡才能听懂的电子信号命令,从而让声卡播放音乐。 所以简单的说,驱动程序提供了硬件到操作系统的一个接口以及协调二者之间的关系,而因为驱动程序有如此重要的作用,所以人们都称“驱动程序是硬件的灵魂”、“硬件的主宰”,同时驱动程序也被形象的称为“硬件和系统之间的桥梁”。 戴尔电脑驱动盘 驱动程序即添加到操作系统中的一小块代码,其中包含有关硬件设备的信息。有了此信息,计算机就可以与设备进行通信。驱动程序是硬件厂商根据操作系统编写的配置文件,可以说没有驱动程序,计算机中的硬件就无法工作。操作系统不同,硬件的驱动程序也不同,各个硬件厂商为了保证硬件的兼容性及增强硬件的功能会不断地升级驱动程序。如:Nvidia显卡芯片公司平均每个月会升级显卡驱动程序2-3次。驱动程序是硬件的一部分,当你安装新硬件时,驱动程序是一项不可或缺的重要元件。凡是安装一个原本不属于你电脑中的硬件设备时,系统就会要求你安装驱动程序,将新的硬件与电脑系统连接起来。驱动程序扮演沟通的角色,把硬件的功能告诉电脑系统,并且也将系统的指令传达给硬件,让它开始工作。 当你在安装新硬件时总会被要求放入“这种硬件的驱动程序”,很多人这时就开始头痛。不是找不到驱动程序的盘片,就是找不到文件的位置,或是根本不知道什么是驱动程序。比如安装打印机这类的硬件外设,并不是把连接线接上就算完成,如果你这时候开始使用,系统会告诉你,找不到驱动程序。怎么办呢参照说明书也未必就能顺利安装。其实在安装方面还是有一定的惯例与通则可寻的,这些都可以帮你做到无障碍安装。 在Windows系统中,需要安装主板、光驱、显卡、声卡等一套完整的驱动程序。如果你需要外接别的硬件设备,则还要安装相应的驱动程序,如:外接游戏硬件要安装手柄、方向盘、摇杆、跳舞毯等的驱动程序,外接打印机要安装打印机驱动程序,上网或接入局域网要安装网卡、Modem甚至ISDN、ADSL的驱动程序。说了这么多的驱动程序,你是否有一点头痛了。下面就介绍Windows系统中各种的不同硬件设备的驱动程序,希望能让你拨云见日。 在Windows 9x下,驱动程序按照其提供的硬件支持可以分为:声卡驱动程序、显卡驱动程序、鼠标驱动程序、主板驱动程序、网络设备驱动程序、打印机驱动程序、扫描仪驱动程序等等。为什么没有CPU、内存驱动程序呢因为CPU和内存无需驱动程序便可使用,不仅如此,绝大多数键盘、鼠标、硬盘、软驱、显示器和主板上的标准设备都可以用Windows 自带的标准驱动程序来驱动,当然其它特定功能除外。如果你需要在Windows系统中的DOS 模式下使用光驱,那么还需要在DOS模式下安装光驱驱动程序。多数显卡、声卡、网卡等内置扩展卡和打印机、扫描仪、外置Modem等外设都需要安装与设备型号相符的驱动程序,否则无法发挥其部分或全部功能。驱动程序一般可通过三种途径得到,一是购买的硬件附

最新开发usb驱动程序的方法连载一

最新开发usb驱动程序的方法连载一 开发usb驱动程序的方法(连载二) NT还有更多其他的对象,例如中断对象、Controller对象、定时器对象等等,但在我们开发的驱动程序中并没有用到,因此在这里不做介绍。 I/O缓冲策略 很明显的,驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,因此操作系统必须解决两者之间的数据交换。这就就设计到设备的I/O缓冲策略。 读写请求的I/O缓冲策略 前面说到通过设置Device对象的Flag可以选择控制处理读写请求的I/O缓冲策略。下面对这些缓冲策略分别做一介绍。 1、缓冲I/O(DO_BUFFERED_IO) 在读写请求的一开始,I/O管理器检查用户缓冲区的可访问性,然后分配与调用者的缓冲区一样大的非分页池,并把它的地址放在IRP的AssociatedIrp.SystemBuffer域中。驱动程序就利用这个域来进行实际数据的传输。 对于IRP_MJ_READ读请求,I/O管理器还把IRP的UserBuffer域设置成调用者缓冲区的用户空间地址。当请求完成时,I/O管理器利用这个地址将数据从驱动程序的系统空间拷贝回调用者的缓冲区。对于IRP_MJ_WRITE写请求,UserBuffer被设置为NULL,并把用户缓冲区的数据拷贝到系统缓冲区中。 2、直接I/O(DO_DIRECT_IO) I/O管理器首先检查用户缓冲区的可访问性,并在物理内存中锁定它。然后它为该缓冲区创建一个内存描述表(MDL),并把MDL的地址存放在IRP的MdlAddress域中。AssociatedIrp.SystemBuffer和 UserBuffer 都被设置为NULL。驱动程序可以调用函数 MmGetSystemAddressForMdl得到用户缓冲区的系统空间地址,从而进行数据操作。这个函数将调用者的缓冲区映射到非份页的地址空间。驱动程序完成I/O请求后,系统自动从系统空间解除缓冲区的映射。 3、这两种方法都不是 这种情况比较少用,因为这需要驱动程序自己来处理缓冲问题。 I/O管理器仅把调用者缓冲区的用户空间地址放到IRP的UserBuffer 域中。我们并不推荐这种方式。 IOCTL缓冲区的缓冲策略 IOCTL请求涉及来自调用者的输入缓冲区和返回到调用者的输出缓冲区。为了理解IOCTL请求,我们先来看看WIN32 API DeviceIoControl函数的原型。 BOOL DeviceIoControl ( HANDLE hDevice, // 设备句柄 DWORD dwIoControlCode, // IOCTL请求操作代码 LPVOID lpInBuffer, // 输入缓冲区地址 DWORD nInBufferSize, // 输入缓冲区大小 LPVOID lpOutBuffer, // 输出缓冲区地址 DWORD nOutBufferSize, // 输出缓冲区大小 LPDWORD lpBytesReturned, // 存放返回字节数的指针

Linux网络设备驱动

嵌入式培训专家
Linux网络设备驱动
主讲:宋宝华
https://www.360docs.net/doc/786019518.html,

华清远见
今天的内容
vLinux网络设备驱动架构 vLinux网络设备驱动数据流程
? NON-NAPI模式数据接收流程 ? NAPI模式数据接收流程 ? 数据发送流程
vLinux网络协议栈的实现
? TCP/UDP/IP/MAC各层数据传递 ? 网络系统调用与socket

华清远见
Linux网络设备驱动架构

华清远见
net_device
struct net_device_ops { int (*ndo_open)(struct net_device *dev); int (*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev); int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); void (*ndo_tx_timeout) (struct net_device *dev); ... }
struct net_device { struct net_device_stats stats; const struct net_device_ops *netdev_ops; const struct ethtool_ops *ethtool_ops; ... }
struct ethtool_ops { int (*get_settings)(struct net_device *, struct ethtool_cmd *); int (*set_settings)(struct net_device *, struct ethtool_cmd *); void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); int (*get_regs_len)(struct net_device *); ... }

安装WIN7时提示缺少所需的CDDVD驱动器设备驱动程序的解决办法

安装WIN7时提示 “缺少所需的CD/DVD驱动器设备驱动程序” 的解决办法 问题描述:安装win7时提示:“缺少所需的CD/DVD驱动器设备驱动程序。…………”然后找遍整个硬盘/光盘也找不到合适的驱动,安装无法继续。 ————————————————————————————————————————————————————————————— 现在安装系统肯定用光驱的人不多,一般最简单的方法就是通过U盘来安装WINDOWS7这个操作系统,实际操作过程中我们用到最多的工具要数UltraISO这个软件了,现在的最新版本应该是9.5。通过插入U盘,之后在UltraISO的启动标签中,我们选择写入硬盘就可以制作我们想要的U盘WINDOWS7安装盘。 但实际操作过程中,我们会碰到一个比较麻烦的问题就是出现:缺少所需的CD/DVD驱动器设备驱动程序,这时我们的安装是没有办法继续的如下图:

其实从表面看,好像真像他提示的一样,可能是缺少驱动了,其实不然,这是微软的提示误导了我们,我们可以看一下下图 我们点击浏览按扭之后会出现如上的图片,在上图中我们可以清楚地看到硬盘的分区情况,那证明不是驱动的问题,但就是在这个窗口其实细心的朋友应该可以看出情况来,先买一个关子。这时我们没有办法继续安装,那怎么办呢?这时我们关掉上图中要我们找驱动的界面,我们回到开始安装界面,然后同时按下Shift+F10键,这时会弹出命令窗口,如下图: 在这个界面同时按下Shift+F10,出现如下窗口

我们用WINDODWS 7提供的硬盘分区命令:diskpart 来查看我们的驱动器情况,先在默认窗口中输入:diskpart 回车,提到下图 再输入:list disk 回车,图如下

USB驱动程序的编写采用WDM驱动程序

U S B驱动程序的编写采用W D M驱动程序 Document serial number【UU89WT-UU98YT-UU8CB-UUUT-UUT108】

USB驱动程序的编写采用WDM 驱动程序。WDM 驱动程序是一些例程的集合,它们被动地存在,等待主机系 统软件(PnP 管理器、I/O 管理器、电源管理器等)来调用或激活它们。具体驱动程序不同,其所包含 的例程也不同。一个WDM 驱动程序的基本组成包括以下5个例程:(1)驱动程序入口例程:处理驱动程序的初始化。 (2)即插即用例程:处理PnP 设备的添加、删除和停止。 (3)分发例程:处理用户应用程序发出的各种 I/O 请求。 (4)电源管理例程:处理电源管理请求。 (5)卸载例程:处理驱动程序的卸载。 包含文件: , , , , , makefile,sources) 在文件中,包含了上述五个例程: 中定义了各种数据结构还有各种IOCTL控制码,用于不同数据的读写。

中实现了各种驱动例程。包含了上述五个所说例程外还包含了其他例程,课程从下面的驱动 程序入口例程得出一些信息。 驱动程序入口例程: NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; DriverObject->MajorFunction[IRP_MJ_CREATE] = Ezusb_Create; DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ezusb_Close; ources. If you want to add a new source # file to this

USB设备驱动程序设计

USB设备驱动程序设计 引言 USB 总线是1995 年微软、IBM 等公司推出的一种新型通信标准总线, 特点是速度快、价格低、独立供电、支持热插拔等,其版本从早期的1.0、1.1 已经发展到目前的2.0 版本,2.0 版本的最高数据传输速度达到480Mbit/s,能 满足包括视频在内的多种高速外部设备的数据传输要求,由于其众多的优点,USB 总线越来越多的被应用到计算机与外设的接口中,芯片厂家也提供了多种USB 接口芯片供设计者使用,为了开发出功能强大的USB 设备,设计者往往 需要自己开发USB 设备驱动程序,驱动程序开发一直是Windows 开发中较难 的一个方面,但是通过使用专门的驱动程序开发包能减小开发的难度,提高工 作效率,本文使用Compuware Numega 公司的DriverStudio3.2 开发包,开发了基于NXP 公司USB2.0 控制芯片ISP1581 的USB 设备驱动程序。 USB 设备驱动程序的模型 USB 设备驱动程序是一种典型的WDM(Windows Driver Model)驱动程序,其程序模型如图1 所示。用户应用程序工作在Windows 操作系统的用户模式层,它不能直接访问USB 设备,当需要访问时,通过调用操作系统的 API(Application programming interface)函数生成I/O 请求信息包(IRP),IRP 被传输到工作于内核模式层的设备驱动程序,并通过驱动程序完成与UBS 外设通 信。设备驱动程序包括两层:函数驱动程序层和总线驱动程序层,函数驱动程 序一方面通过IRP 及API 函数与应用程序通信,另一方面调用相应的总线驱动 程序,总线驱动程序完成和外设硬件通信。USB 总线驱动程序已经由操作系统 提供,驱动程序开发的重点是函数驱动程序。 USB 设备驱动程序的设计

LCD驱动分析_LCD控制器设置及代码详解

LCD驱动分析_LCD控制器设置及代码详解 1. LCD工作的硬件需求: 要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD 控制器。在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等。通过LCD控制器就可以产生LCD驱动器所需要的控制信号来控制STN/TFT屏了。 2. S3C2440内部LCD控制器结构图: 我们根据数据手册来描述一下这个集成在S3C2440内部的LCD控制器: a:LCD控制器由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS寄存器组成; b:REGBANK由17个可编程的寄存器组和一块256*16的调色板内存组成,它们用来配置LCD控制器的; c:LCDCDMA是一个专用的DMA,它能自动地把在侦内存中的视频数据传送到LCD驱动器,通过使用这个DMA通道,视频数据在不需要CPU的干预的情况下显示在LCD屏上; d:VIDPRCS接收来自LCDCDMA的数据,将数据转换为合适的数据格式,比如说4/8位单扫,4位双扫显示模式,然后通过数据端口VD[23:0]传送视频数据到LCD驱动器;e:TIMEGEN由可编程的逻辑组成,他生成LCD驱动器需要的控制信号,比如VSYNC、HSYNC、VCLK和LEND等等,而这些控制信号又与REGBANK寄存器组中的LCDCON1/2/3/4/5的配置密切相关,通过不同的配置,TIMEGEN就能产生这些信号的不同形态,从而支持不同的LCD驱动器(即不同的STN/TFT屏)。 3. 常见TFT屏工作时序分析: LCD提供的外部接口信号:

常用网络设备设备

物理层设备 1.调制解调器 调制解调器的英文名称为modem,来源于Modulator/Demodulator,即调制器/解调器。 ⑴工作原理 调制解调器是由调制器与解调器组合而成的,故称为调制解调器。调制器的基本职能就是把从终端设备和计算机送出的数字信号转变成适合在电话线、有线电视线等模拟信道上传输的模拟信号;解调器的基本职能是将从模拟信道上接收到的模拟信号恢复成数字信号,交给终端计算机处理。 ⑵调制与解调方式 调制,有模拟调制和数字调制之分。模拟调制是对载波信号的参量进行连续地估值;而数字调制使用载波信号的某些离散状态来表征所传送的信息,在接收端对载波信号的离散参量进行检测。调制是指利用载波信号的一个或几个参数的变化来表示数字信号的一种过程。 调制方式相应的有:调幅、调频和调相三种基本方式。 调幅:振幅调制其载波信号将随着调制信号的振幅而变化。 调频:载波信号的频率随着调制信号而改变。 调相:相位调制有两相调制、四相调制和八相调制几种方式。 ⑶调制解调器的分类 按安装位置:调解解调器可以分为内置式和外置式 按传输速率分类:低速调制解调器,其传输速率在9600bps以下;中速调制解调器,其传输速率在9.6~19.2kbps之间;高速调制解调器,传输速率达到19.2~56kbps。 ⑷调制解调器的功能 ?差错控制功能:差错控制为了克服线路传输中出现的数据差错,实现调制解调器至远端调制解调器的无差错数据传送。 ?数据压缩功能:数据压缩功能是为了提高线路传输中的数据吞吐率,使数据更快地传送至对方。 ⑸调制解调器的安装 调制解调器的安装由两部分组成,线路的连接和驱动程序的安装。 线路连接: ?将电话线引线的一端插头插入调制解调器后面LINE端口。

虚拟设备驱动程序的设计与实现

虚拟设备驱动程序的设计与实现 由于Windows对系统底层操作采取了屏蔽的策略,因而对用户而言,系统变得 更为安全,但这却给众多的硬件或者系统软件开发人员带来了不小的困难,因为只要应用中涉及到底层的操作,开发人员就不得不深入到Windows的内核去编写属 于系统级的虚拟设备驱动程序。Win 98与Win 95设备驱动程序的机理不尽相同,Win 98不仅支持与Windows NT 5.0兼容的WDM(Win32 Driver Mode)模式驱动程序 ,而且还支持与Win 95兼容的虚拟设备驱动程序VxD(Virtual Device Driver)。下面介绍了基于Windows 9x平台的虚拟环境、虚拟设备驱动程序VxD的基本原理和 设计方法,并结合开发工具VToolsD给出了一个为可视电话音频卡配套的虚拟设备 驱动程序VxD的设计实例。 1.Windows 9x的虚拟环境 Windows 9x作为一个完整的32位多任务操作系统,它不像Window 3.x那样依 赖于MS-DOS,但为了保证软件的兼容性,Windows 9x除了支持Win16应用程序和 Win32应用程序之外,还得支持MS-DOS应用程序的运行。Windows 9x是通过虚拟机 VM(Virtual Machine)环境来确保其兼容和多任务特性的。 所谓Windows虚拟机(通常简称为Windows VM)就是指执行应用程序的虚拟环 境,它包括MS-DOS VM和System VM两种虚拟机环境。在每一个MS-DOS VM中都只运 行一个MS-DOS进程,而System VM能为所有的Windows应用程序和动态链接库DLL(Dynamic Link Libraries)提供运行环境。每个虚拟机都有独立的地址空间、寄存器状态、堆栈、局部描述符表、中断表状态和执行优先权。虽然Win16、Win32应用程序都运行在System VM环境下,但Win16应用程序共享同一地址空间, 而Win32应用程序却有自己独立的地址空间。 在编写应用程序时,编程人员经常忽略虚拟环境和实环境之间的差异,一般认为虚拟环境也就是实环境。但是,在编写虚拟设备驱动程序VxD时却不能这样做 ,因为VxD的工作是向应用程序代码提供一个与硬件接口的环境,为每一个客户虚 拟机管理虚设备的状态,透明地仲裁多个应用程序,同时对底层硬件进行访问。这就是所谓虚拟化的概念。 VxD在虚拟机管理器VMM(Virtual Machine Manager)的监控下运行,而VMM 实 际上是一个特殊的VxD。VMM执行与系统资源有关的工作,提供虚拟机环境(能产

驱动程序安装方法

驱动程序安装方法 初识电脑的人,可能为安装驱动程序而头疼。因为对驱动程序了解得不多就会在安装过程中走不少弯路,下面就给大家介绍一下安装驱动程序的两种常用方法和一些实用技巧。 一、安装即插即用设备的驱动程序 安装前的准备工作很重要,一般我们拿到要安装的新硬件时,首先要查看外包装盒,了解产品的型号、盒内部件及产品对系统的最低要求等信息。紧接着就要打开包装盒,取出硬件产品、说明书和驱动盘(光盘或软盘),认真阅读说明书或驱动盘上的ReadMe 文件,一般说明书上写有安装方法和步骤,以及安装注意事项。除了阅读说明书外,还应记得硬件产品上印刷的各种信息以及板卡产品使用的主要芯片的型号。这些信息就是确定产品型号及厂家的重要依据,只有知道这些,才能在网上查找最新的驱动程序。最后按照说明书上介绍的方法来安装硬件。通常安装内置板卡、内置驱动器,使用串口或PS /2接口的设备都应关机断电后再操作,而安装USB设备、笔记本电脑的PC卡时可以带电热插拔。当然,如果是Win2000系统则均可热插拔。完成前面的准备工作之后,就可以启动Windows 来安装驱动程序了。通常情况下,Windows 能够自动检测到PCI 卡、AGP卡、ISA卡、USB设备以及多数打印机和扫描仪等外设,并提示用户插入安装盘。以YAMAHA724声卡为例,其在Win98下安装驱动程序的详细步骤如下。 1.Win98在启动过程中会自动检测即插即用设备,一旦发现了新设备,并且在INF目录下有该设备的.inf 文件,系统将自动安装驱动程序;如果这是一个新设备,INF目录下没有相应的.inf 文件,那么系统就会启动硬件向导。我们单击“下一步”让安装向导自动搜索设备驱动程序,然后再单击“下一步”。 2.在图3中只选中“指定位置”,插入驱动光盘,并单击“浏览”,根据说明书的介绍,选择简体中文版驱动程序所在的目录“E:\Lx_so u n d /Yamaha /Win9X”,点“确定”后单击“下一步”。需要注意的是:Win95的安装向导没有自动搜索功能,我们必须选择“从磁盘安装”,并指定驱动程序所在的位置。驱动程序所在的目录通常是驱动盘上的“Win95”、“Win9X”或“Windows98”目录。 3.硬件安装向导会在指定目录下查找与设备相符的.inf 文件,此例中,硬件向导将在指定目录下找到并向作户报告发现YAMAHA724声卡驱动程序,继续按“下一步”。 4.硬件安装向导显示Windows 准备安装的驱动程序的信息,单击“下一步”后,硬件向导便会根据.inf 文件的内容把指定的文件拷贝到相应的目录下,并在注册表中写入相应的信息,安装成功后显示出对话框。 5.对多数设备而言,到这里驱动程序就算安装完毕了。但如果你安装的是声卡那就还未结束,因为刚才的步骤只能装完声卡的主体部分。单击“完成”后,Windows 又会报告发现了两个新硬件,分别是声卡的DOS 仿真部件和声卡上的游戏控制端口。由于此时SBPCI9X.inf 文件已经被拷到“Windows /INF /Other”子目录下,所以Windows 能够自动安装好这两种设备的驱动程序。 6.驱动程序安装完毕后,我们需要检查设备能否正常工作。检查前还要进行额外的设置,例如使用网卡之前必须先安装和设置网络协议,用调制解调器上网之前要先“新建连接”等。此例中,在“控制面板”里打开“系统”→“设备管理器”→“声音、视频和游戏控制器”,可以看见下面多了三个设备,只要设备的小图标上没有黄色惊叹号,就表示驱动程序运行正常。 二、安装非即插即用设备的驱动程序

安装Windows7时电脑提示缺少所需的CDDVD驱动器设备驱动程序的原因

安装Windows7时电脑提示缺少所需的CD/DVD驱动器设备驱动程序的原因 以及解决方案 来源:互联网作者:佚名时间:09-03 15:16:35【大中小】问题描述:安装win7时提示:“缺少所需的CD/DVD驱动器设备驱动程序。…………”然后找遍整个硬盘/光盘也找不到合适的驱动,安装无法继续。 现在安装系统肯定用光驱的人不多,一般最简单的方法就是通过U盘来安装WINDOWS7这个操作系统,实际操作过程中我们用到最多的工具要数UltraISO这个软件了,现在的最新版本应该是9.5。通过插入U盘,之后在UltraISO的启动标签中,我们选择写入硬盘就可以制作我们想要的U盘WINDOWS7安装盘。 但实际操作过程中,我们会碰到一个比较麻烦的问题就是出现:缺少所需的CD/DVD驱动器设备驱动程序,这时我们的安装是没有办法继续的如下图:

其实从表面看,好像真像他提示的一样,可能是缺少驱动了,其实不然,这是微软的提示误导了我们,我们可以看一下下图 我们点击浏览按扭之后会出现如上的图片,在上图中我们可以清楚地看到硬盘的分区情况,那证明不是驱动的问题,但就是在这个窗口其实细心的朋友应该可以看出情况来,先买一个关子。这时我们没有办法继续安装,那怎么办呢?这时我们关掉上图中要我们找驱动的界面,我们回到开始安装界面,然后同时按下Shift+F10键,这时会弹出命令窗口,如下图:

在这个界面同时按下Shift+F10,出现如下窗口 我们用WINDODWS 7提供的硬盘分区命令:diskpart 来查看我们的驱动器情况,先在默认窗口中输入:diskpart 回车,提到下图

相关文档
最新文档