精华内容
下载资源
问答
  • usb插入后自动启动程序Portable apps—self-contained executables that can be moved onto flash drives and run without installation—are popular tools for anyone who has to work on multiple Windows ...
    usb插入后自动启动程序

    usb插入后自动启动程序

    Portable apps—self-contained executables that can be moved onto flash drives and run without installation—are popular tools for anyone who has to work on multiple Windows machines. If you want to make your workflow even faster, you can add an “auto-run” file that automatically opens the program as soon as you plug in the drive.

    对于必须在多台Windows机器上工作的任何人来说,便携式应用程序(可以包含到闪存驱动器上并且可以不经安装而运行的自包含可执行文件)是受欢迎的工具。 如果要使工作流程更快,可以添加一个“自动运行”文件,该文件在插入驱动器后立即自动打开程序。

    Unfortunately, starting with Windows 7, Microsoft restricted the autorun function for security purposes. There’s no practical way to get it back on every new machine, but it’s possible to do so on computers you have access to on a regular basis. First, you’ll need a small, third-party tool that monitors new USB drives for the autorun instruction. Then, you’ll need to create a simple autorun script file that sits on the USB drive and designates what program to run when you insert the drive.

    不幸的是,从Windows 7开始,Microsoft出于安全目的限制了自动运行功能。 没有实用的方法可以将其恢复到每台新计算机上,但是可以在可以定期访问的计算机上进行恢复。 首先,您将需要一个小的第三方工具来监视新的USB驱动器的自动运行指令。 然后,您需要创建一个简单的自动运行脚本文件,该文件位于USB驱动器上,并指定在插入驱动器时要运行的程序。

    第一步:在Windows PC上安装APO USB Autorun (Step One: Install APO USB Autorun on Your Windows PC)

    APO USB Autorun is a program that monitors USB drives as they’re plugged in, looking for the legacy autorun.inf script file and launching any programs directed within. Download it from Softpedia here, then double-click the installer file and install it like any other program.

    APO USB Autorun是一个程序,可在插入USB驱动器时对其进行监视,以查找旧版autorun.inf脚本文件并启动其中定向的任何程序。 从此处的Softpedia下载它 ,然后双击安装程序文件,然后像安装其他任何程序一样安装它。

    After installation, whenever you connect a USB drive, you should see a window pop-up like the one below, asking if you want to run the program you’ve designated to run automatically (and we’ll talk more about how to do that part in a bit).

    安装后,无论何时连接USB驱动器,您都应该会看到一个如下所示的弹出窗口,询问您是否要运行指定为自动运行的程序(我们将详细讨论如何执行该操作)部分)。

    Just click the “Run” button to run the program and, optionally, disable the “Always ask before opening this file” option so that you aren’t bothered with this warning the next time you insert the drive.

    只需单击“运行”按钮以运行该程序,然后有选择地禁用“在打开此文件之前始终询问”选项,这样您下次插入驱动器时就不会受到此警告的困扰。

    Unfortunately, you’ll need to install APO USB Autorun on each Windows 7 or later PC that you want to autorun your USB drives. That makes it not so useful for drives you carry around to lots of different PCs, but it can be really helpful if you often work on the same computer.

    不幸的是,您需要在要自动运行USB驱动器的每台Windows 7或更高版本的PC上安装APO USB Autorun。 这使得它对于随身携带到许多不同PC上的驱动器没有太大用处,但是如果您经常在同一台计算机上工作,那么它确实很有用。

    第二步:设置USB驱动器 (Step Two: Set Up the USB Drive)

    In order to autorun a program, the USB drive needs to contain two things: the program you want to run and an autorun script file that points to that program.

    为了自动运行程序,USB驱动器需要包含两件东西:要运行的程序和指向该程序的自动运行脚本文件。

    Go ahead and copy the portable executable for the program to your USB drive. That’s the easy part.

    继续并将该程序的可移植可执行文件复制到USB驱动器。 那是容易的部分。

    To create the autorun script file, open up Notepad (or whatever text editor you prefer). Type (or copy and paste) the following text into the Notepad window, complete with line breaks.

    要创建自动运行脚本文件,请打开记事本(或您喜欢的任何文本编辑器)。 在记事本窗口中键入(或复制并粘贴)以下文本,并带有换行符。

    [autorun]
     ;Open=YOURAPP.exe
     ShellExecute=YOURAPP.exe
     UseAutoPlay=1
    

    Replace the “YOURAPP” text with the file name of the application you’re trying to start. I’m using the portable version of the Lynx browser for this demonstration, so my commands read like this:

    将“ YOURAPP”文本替换为您要启动的应用程序的文件名。 我在此演示中使用的是Lynx浏览器的便携式版本,因此我的命令如下所示:

    [autorun]
     ;Open=LynxPortable.exe
     ShellExecute=LynxPortable.exe
     UseAutoPlay=1
    

    Next, save the file to your USB drive with the name “autorun.inf” and make sure that you select “All Files (*.*)” in the “Save as type” field. That way, Notepad won’t add an additional “.txt” extension to the end of your file name.

    接下来,使用名称“ autorun.inf”将文件保存到USB驱动器,并确保在“另存为类型”字段中选择“所有文件(*。*)”。 这样,记事本就不会在文件名的末尾添加额外的“ .txt”扩展名。

    The root folder of your USB drive should now contain the program’s executable file and the autorun.inf file you just created.

    现在,USB驱动器的根文件夹应包含程序的可执行文件和刚创建的autorun.inf文件。

    You can place other files and folders in the drive, of course, but make sure to keep those two items in the root directory.

    当然,您可以在驱动器中放置其他文件和文件夹,但请确保将这两项保留在根目录中。

    Now, with APO USB Autorun running and your USB drive properly configured, your program should run automatically whenever you connect the USB drive to your PC.

    现在,在运行APO USB Autorun并正确配置USB驱动器的情况下,只要将USB驱动器连接到PC,程序就应该自动运行。

    Image credit: Amazon

    图片来源: 亚马逊

    翻译自: https://www.howtogeek.com/326049/how-to-auto-run-windows-programs-when-you-plug-in-a-usb-drive/

    usb插入后自动启动程序

    展开全文
  • 但是在使用键盘时,小心触碰到触摸板,屏幕鼠标就会乱跑了,影响正常使用,比较烦。当然我们也可以利用笔记本提供的快捷键手动禁止触摸板。使用这个软件后,可以变手动为自动,即计算机检测到你插入了USB鼠标,...
  • 拯救者usb3.0驱动是一款非常好用的usb驱动程序,适合使用英特尔USB3.0的用户进行使用,可以有效的解决主控制器在安装过程中出现的一些异常问题,欢迎有需要的朋友下载使用!USB3.0简介USB3.0是一种USB规范,该规范由...
  • usbserialcontroller驱动是支持WIN7旗舰版64位的USB转串口驱动,需要的朋友欢迎下载!安装说明1.手动安装插入数据线,查找到新硬件,然后将其需要的配置文件定位到这里2.自动安装运行Setup.exe安装成功后重新启动...
  • 手机usb通用驱动程序是一款适合所有手机usb接口与电脑通信的驱动程序,是您手机连接电脑的必要帮手,现在下载驱动安装完成以后,重新起动计算机即可使用!安装说明自动安装:运行Setup.exe。安装成功后重新启动电脑。...
  • 安装USB驱动程序.zip

    2020-05-03 08:52:57
    Usb口插入开发板后电脑会自动识别设备,自动联网安装驱动设备成功。 ③若电脑未自动安装驱动,打开设备管理器,找到插入开发板后弹出的新设备(未安装好驱动的情况下在“其他设备”中,带有黄色感叹号或问号),右键...
  • Linux USB 驱动开发(四)—— 热拔那点事

    万次阅读 多人点赞 2016-04-04 16:08:04
    学习USB拔之前,先学习一些USB的硬件知识: 一、USB基础概念 1、硬件知识(USB插座和插头)  在最初的标准里,USB接头有4条线:电源,D-,D+,地线。我们暂且把这样的叫做标准的USB接头吧。后来OTG出现了,又增加...

          学习USB热插拔之前,先学习一些USB的硬件知识:

    一、USB基础概念

    1、硬件知识(USB插座和插头)

           在最初的标准里,USB接头有4条线:电源,D-,D+,地线。我们暂且把这样的叫做标准的USB接头吧。后来OTG出现了,又增加了miniUSB接头。而miniUSB接头则有5条线,多了一条ID线,用来标识身份用的。标准USB口只有A型和B型。其中每一型又分为插头和插座,例如A型插头,A型插座等。我们平常电脑上用的那种插座叫做A型USB插座,而相应的插头,叫做A型插头,例如U盘上那种。而像打印机上面那个插座,则是B型插座(比较四方的,没电脑上面那种扁),相应的插头,就是B型插头。也许你见过一头方一头扁的USB延长线,没错了,扁的那头就叫做A型插头,而方的那头,就叫做B型插头,而相应的被插的那两个插座,就分别是A型插座和B型插座了。A型插头是插不进B型插座的,反之亦然。

          miniUSB也分为A型,B型,但增加了一个AB型(不是血型呀,别搞错了,没有O型^_^)。既然它叫做miniUSB,那么当然它就是很小的了,主要是给便携式设备用的,例如MP3、手机、数码相机等。USB是一主多从结构,即一个时刻只能有一台主机。像PC机就是一个主机,其它的只能是设备,因而两个设备之间是无法直接进行通信的。而USB OTG(on the go)的出现,则解决了这个矛盾:一个设备可以在某种场合下,改变身份,以主机的形式出现。因而就出现了AB型的miniUSB插座,不管是A型miniUSB插头,还是B型miniUSB插头,都可以插进去,而靠里面多出的那条ID线来识别它的身份:是主机还是从机。这样两个USB设备就可以直接连接起来,进行数据传送了。 像我们MP3上用的那中miniUSB插座,就是B型的miniUSB插座(注意,有一类miniUSB插座,似乎不是USB规范里面的,因为miniUSB接头应该有5条线,而这种插座只有4条线)。由于USB是支持热插拔的,因此它在接头的设计上也有相应的措施。USB插头的地引脚和电源引脚比较长,而两个数据引脚则比较短,这样在插入到插座中时,首先接通电源和地,然后再接通两个数据线。这样就可以保证电源在数据线之前接通,防止闩锁发生。至于USB电缆,通常我们不怎么关心,买现成的就行了,除非你是生产USB线缆的。在全速模式下需要使用带屏蔽的双绞电缆线,而低速模式模式则可以不用屏蔽和双绞。此外,USB协议规定,USB低速电缆长度不得超过3米,而全速电缆长度不得超过5米。这是因为线缆传输有延迟,要保证能够正确响应,就不能延迟太多。USB标准规定了里面信号线的颜色,其中Vbus为红色,D-为白色,D+为绿色,GND为黑色。然而,我见过很多USB线缆并没有遵循标准,所以大家在使用时要小心,用表测量一下比较可靠。


    2、集线器把USB设备的连接报告给USB主控制器

          首先,在USB集线器的每个下游端口的D+和D-上,分别接了一个15K欧姆的下拉电阻到地。这样,在集线器的端口悬空时,就被这两个下拉电阻拉到了低电平。而在USB设备端,在D+或者D-上接了1.5K欧姆上拉电阻。对于全速和高速设备,上拉电阻是接在D+上;而低速设备则是上拉电阻接在D-上。这样,当设备插入到集线器时,由1.5K的上拉电阻和15K的下拉电阻分压,结果就将差分数据线中的一条拉高了集线器检测到这个状态后,它就报告给USB主控制器(或者通过它上一层的集线器报告给USB主控制器),这样就检测到设备的插入了。USB高速设备先是被识别为全速设备,然后通过HOST和DEVICE两者之间的确认,再切换到高速模式的。在高速模式下,是电流传输模式,这时将D+上的上拉电阻断开。


    二、什么是热插拔

    1、基础概念

         热插拔(hot-plugging或Hot Swap)带电插拔,热插拔功能就是允许用户在不关闭系统,不切断电源的情况下取出和更换损坏的硬盘、电源或板卡等部件,从而提高了系统对灾难的及时恢复能力、扩展性和灵活性等,例如一些面向高端应用的磁盘镜像系统都可以提供磁盘的热插拔功能。具体用学术的说法就是:热替换(Hot replacement)、热添加(hot expansion)和热升级(hot upgrade)


    2、热插拔好处

    系统中加入热插拔的好处包括:

    在系统开机情况下将损坏的模块移除,还可以在开机情况下做更新或扩容而不影响系统操作。

    由于热插拔零件的可靠度提升,还可以将它们用做断电器,而且因为热插拔能够自动恢复,有很多热插拔芯片为系统提供线路供电情况的信号,以便系统做故障分析,因此减少了成本。


    三、Linux 下USB热插拔处理

    1、 Linux下USB HUB的驱动的实现和分析:

           在系统初始化的时候在usb_init函数中调用usb_hub_init函数,就进入了hub的初始化

           在usb_hub_init函数中完成了注册hub驱动,并且利用函数kthread_run创建一个内核线程。该线程用来管理监视hub的状态,所有的情况都通过该线程来报告。

          USB设备是热插拔,这就和PCI设备不同,PCI设备是在系统启动的时候都固定了,因此PCI设备只需要初始化进行枚举就可以了,采用递归算法即可。而USB设备需要热插拔,因此在hub_probe函数中调用hub_configure函数来配置hub,在这个函数中主要是利用函数usb_alloc_urb函数来分配一个urb,利用usb_fill_int_urb来初始化这个urb结构,包括hub的中断服务程序hub_irq的,查询的周期等。

           每当有设备连接到USB接口时,USB总线在查询hub状态信息的时候会触发hub的中断服务程序hub_irq,在该函数中利用kick_khubd将hub结构通过event_list添加到khubd的队列hub_event_list,然后唤醒khubd。进入hub_events函数,该函数用来处理khubd事件队列,从khubd的hub_event_list中的每个usb_hub数据结构。该函数中首先判断hub是否出错,然后通过一个for循环来检测每个端口的状态信息。利用usb_port_status获取端口信息,如果发生变化就调用hub_port_connect_change函数来配置端口等。


    2、软件层次分析

    这里我们先讲讲USB热插拔事件的处理工作。---Khubd守护进程。

    -Khubd守护进程它是一个守护进程,来检查usb port的事件通知HCD和usb core,然后做相应的处理。

    驱动目录drivers/usb/*
    usb/serial  usb 串行设备驱动 (例如usb 3G卡、蓝牙等)
    usb/storage  usb 大储量磁盘驱动(u盘)  
    usb/host usb host usb主机控制器驱动(嵌入式otg:dwc_otg)
    usb/core   usb 核心一些处理代码,所有的驱动相关处理都在这里,也都注册到它里面。
    usb/usb-skeleton.c 经典的usb客户驱动框架,可以参考

    当然还有其他这里不再说明。

    下面贴出USB的整体驱动框架:


    这里我们主要分析khub的工作原理: 硬件层次是hub的工作,如何和host及其设备间通信及相应事件

    [usb/core/hub.c ]

    int usb_hub_init(void)
    {
    	if (usb_register(&hub_driver) < 0) {
    		printk(KERN_ERR "%s: can't register hub driver\n",
    			usbcore_name);
    		return -1;
    	}
    
    	khubd_task = kthread_run(hub_thread, NULL, "khubd");
    	if (!IS_ERR(khubd_task))
    		return 0;
    
    	/* Fall through if kernel_thread failed */
    	usb_deregister(&hub_driver);
    	printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);
    
    	return -1;
    }
    这里我们只关心kthread_run(hub_thread, NULL, "khubd"); 然后我们看hub_thread函数
    static int hub_thread(void *__unused)
    {
    	do {
    		hub_events();
    		wait_event_interruptible(khubd_wait,
    				!list_empty(&hub_event_list) ||
    				kthread_should_stop());
    		try_to_freeze();
    	} while (!kthread_should_stop() || !list_empty(&hub_event_list));
    
    	pr_debug("%s: khubd exiting\n", usbcore_name);
    	return 0;
    }

    这里我们看到了hub_events()函数。然后设置运行状态,如果有事件就加入hub_event_list。自此khubd运行起来了。

    这里我们同样贴出它的函数调用流程图(这里懒得自己画了,就剪切了个^^)



    通过流程图我们可以清晰的明白,当usb设备插入usb接口后,khubd运行,它检测到port状态的变化,调用hub_port_connect_change(),如果是新设备那么usb_allco_dev,然后调用usb_new_device来进行配置使usb设备可以正常工作。详细流程请看源码。


    四、USB的枚举过程

           内核辅助线程khubd用来监视与该集线器连接的所有端口,通常情况下,该线程处于休眠状态,当集线器驱动程序检测到USB端口状态变化后,该内核线程立马唤醒

          USB的枚举过程:USB的枚举过程是热插拔USB设备的起始步骤,该过程中,主机控制器获取设备的相关信息并配置好设备,集线器驱动程序负责该枚举过程

    枚举过程主要分如下几步:

    Step1:根集线器报告插入设备导致的端口电流变化,集线器驱动程序检测到这一状态变化后,唤醒khubd线程。

    Step2:khubd识别出电流变化的那个端口

    Step3:khubd通过给控制端点0发送控制URB来实现从1-127中选出一个数作为插入设备的批量端点

    Step4:khubd利用端口0使用的控制URB从插入的设备那里获得设备描述符,然后获得配置描述符,并选择一个合适的。

    Step5:khubd请求USB核心把对应的客户驱动程序和该USB设备挂钩



    展开全文
  • Linux驱动开发: USB驱动开发

    千次阅读 多人点赞 2021-08-24 22:03:05
    一、USB简介 1.1 什么是USB? USB是连接计算机系统与外部设备的一种串口总线标准,也是一种输入输出接口的技术规范,被广泛地应用于个人电脑和移动设备等信息通讯产品,USB就是简写,中文叫通用串行总线。最早出现...

    一、USB简介

    1.1  什么是USB?

          USB是连接计算机系统与外部设备的一种串口总线标准,也是一种输入输出接口的技术规范,被广泛地应用于个人电脑和移动设备等信息通讯产品,USB就是简写,中文叫通用串行总线。最早出现在1995年,伴随着奔腾机发展而来。自微软在Windows 98中加入对USB接口的支持后,USB接口才推广开来,USB设备也日渐增多,如数码相机、摄像头、扫描仪、游戏杆、打印机、键盘、鼠标等等,其中应用最广的就是摄像头和U盘了。

         USB包括老旧的USB 1.1标准和时下正流行的USB 2.0标准。传统的USB 1.1最高传输速率为12Mbps,一般厂商将其符合USB 1.1标准的产品称为“全速USB”。而高速USB 2.0最初推出时最高传输速率仅为240Mbps,后来USB2.0推广组(USB Promoter Group)在1999年10月将该速率提高到480Mbps,比传统的USB 1.1快40倍。

          USB2.0向下兼容USB 1.1,当然USB1.1设备也“向上兼容”USB 2.0,但是无法实现USB2.0的传输能力,并自动以低速传输。USB 2.0连接线的最大长度为5米,但如果用五个USB适配器,则最大长度可达30米。

          最新一代是USB 3.1,传输速度为10Gbit/s,三段式电压5V/12V/20V,最大供电100W ,新型Type C插型不再分正反。

     

          USB采用四线电缆,其中两根是用来传送数据的串行通道,另两根为下游(Downstream)设备提供电源,对于高速且需要高带宽的外设,USB以全速12Mbps的传输数据;对于低速外设,USB则以1.5Mbps的传输速率来传输数据。USB总线会根据外设情况在两种传输模式中自动地动态转换。USB是基于令牌的总线。类似于令牌环网络或FDDI基于令牌的总线。USB主控制器广播令牌,总线上设备检测令牌中的地址是否与自身相符,通过接收或发送数据给主机来响应。USB通过支持悬挂/恢复操作来管理USB总线电源。USB系统采用级联星型拓扑,该拓扑由三个基本部分组成:主机(Host),集线器(Hub)和功能设备。

          主机,也称为根,根结或根Hub,它做在主板上或作为适配卡安装在计算机上,主机包含有主控制器和根集线器(Root Hub),控制着USB总线上的数据和控制信息的流动,每个USB系统只能有一个根集线器,它连接在主控制器上。

         集线器是USB结构中的特定成分,它提供叫做端口(Port)的点将设备连接到USB总线上,同时检测连接在总线上的设备,并为这些设备提供电源管理,负责总线的故障检测和恢复。集线可为总线提供能源,亦可为自身提供能源(从外部得到电源),自身提供能源的设备可插入总线提供能源的集线器中,但总线提供能源的设备不能插入自身提供能源的集线器或支持超过四个的下游端口中,如总线提供能源设备的需要超过100mA电源时,不能同总线提供电源的集线器连接。

    USB介绍: http://www.usb.org/home

    1.2 USB设备主要优点总结

    1. 可以热插拔

    用户在使用外接设备时,不需要关机再开机等动作,而是在电脑工作时,直接将USB插上使用。

    2. 携带方便

    USB设备大多以“小、轻、薄”见长,对用户来说,随身携带大量数据时,很方便。当然USB硬盘是首要之选了。

    3. 标准统一

    大家常见的是IDE接口的硬盘,串口的鼠标键盘,并口的打印机扫描仪,可是有了USB之后,这些应用外设统统可以用同样的标准与个人电脑连接,这时就有了USB硬盘、USB鼠标、USB打印机等等。

    4. 可以连接多个设备

    USB在个人电脑上往往具有多个接口,可以同时连接几个设备,如果接上一个有四个端口的USB HUB时,就可以再连上四个USB设备,以此类推 (注:最高可连接至127个设备,扩展到一定数量时需要外加电源)

    1.3  USB电器接口定义

    一般的排列方式是:红白绿黑从左到右

    定义:

    1. 红色-USB电源: 标有-VCC、Power、5V、5VSB字样
    2. 白色-USB数据线:(负)-DATA-、USBD-、PD-、USBDT-
    3. 绿色-USB数据线:(正)-DATA+、USBD+、PD+、USBDT+
    4. 黑色-地线: GND、Ground

     

    1. 4 USB的插入检测机制

            USB端口的D+和D-均用一个15k的电阻接地,当无设备接入时,均处于低电平;在设备端在D+(表示高速设备或者全速设备)或者D-(表示低速设备)接了一个1.5k的上拉电阻到+3.3v,一旦将设备接入,USB端口的D+或者D-其中一个被拉高为3v,系统识别到外部设备接入。

           注意:高速设备首先会被识别为全速设备,然后再通过集线器和设备二者的确认最后切换到高速模式下。

         在高速模式下,采用的是电流传输模式,这个时候上拉电阻需要从D+上断开。

         usb主机检测到USB设备插入后,就要对设备进行枚举了。枚举的作用就是从设备是那个读取一些信息,知道设备是什么样的设备,如果通信,这样主机就可以根据这些信息选择合适的驱动程序。调试USB设备,很重要的一点就是USB枚举过程,只要枚举成功了,那就成功一大半了。

          当设备没有枚举成功时(可以通过一个10K的电阻将USB的电源端和D+或者D-连接起来,电脑会发现一个无法识别的设备,这个设备的PID和VID都是0,根据每个特性可以简单的判定设备的枚举是否成功。 

    二、 USB标准描述符

            USB协议为USB设备定义了一套描述设备功能和属性的有固定结构的描述符,包括标准的描述符即设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符。USB设备通过这些描述符向USB主机汇报设备的各种各样属性,主机通过对这些描述符的访问对设备进行类型识别、配置并为其提供相应的客户端驱动程序。

            USB设备通过描述符反映自己的设备特性。USB描述符是由特定格式排列的一组数据结构组成。

         在USB设备枚举过程中,主机端的协义软件需要解析从USB设备读取的所有描述符信息。在USB主向设备发送读取描述符的请求后,USB设备将所有的描述符以连续的数据流方式传输给USB主机。主机从第一个读到的字符开始,根据双方规定好的数据格式,顺序地解析读到的数据流。

         USB描述符包含标准描述符类描述符厂商特定描述3种形式。任何一种设备必须遵循USB标准描述符(除了字符串描述符可选外)。

         在USB1.X中,规定了5种标准描述符:设备描述符(Device Descriptor)、配置描述符(Configuration Descriptor)、接口描述符(Interface Descriptor)、端点描述符(Endpoint Descriptor)和字符串描述符(String Descriptor)。

        每个USB设备只有一个设备描述符,而一个设备中可包含一个或多个配置描述符,即USB设备可以有多种配置。设备的每一个配置中又可以包含一个或多个接口描述符,即USB设备可以支持多种功能(接口),接口的特性通过描述符提供。

        在USB主机访问USB设备的描述符时,USB设备依照设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符顺序将所有描述符传给主机。一设备至少要包含设备描述符、配置描述符和接口描述符,如果USB设备没有端点描述符,则它仅仅用默认管道与主机进行数据传输。

    2. 1 设备描述符

    30.2.1 设备描述符
    /* USB_DT_DEVICE: Device descriptor */
    struct usb_device_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;
    
        __le16 bcdUSB;
        __u8  bDeviceClass;
        __u8  bDeviceSubClass;
        __u8  bDeviceProtocol;
        __u8  bMaxPacketSize0;
        __le16 idVendor;
        __le16 idProduct;
        __le16 bcdDevice;
        __u8  iManufacturer;
        __u8  iProduct;
        __u8  iSerialNumber;
        __u8  bNumConfigurations;
    } __attribute__ ((packed));
    
    
    //USB设备信息与驱动端匹配成功的时候调用。
    static int test_probe(struct usb_interface *intf,const struct usb_device_id *id)  //资源探索函数
    {
        printk("识别到USB光谱仪设备,正在进行设备初始化.\n");
        printk("该设备的厂商ID=%#x,设备ID:%#x\n",id->idVendor,id->idProduct);
    
        /*通过接口获取设备信息*/	
        struct usb_device *dev = interface_to_usbdev(intf);
        printk("bcdUSB = %#x\n",dev->descriptor.bcdUSB);   //从USB设备描述符中获取USB版本
        printk("vidUSB = %#x\n",dev->descriptor.idVendor); //从USB设备描述符中获取厂商ID
        printk("pidUSB = %#x\n",dev->descriptor.idProduct);//从USB设备描述符中获取产品ID
    
        /*-------------------------------*/
    }
    

    设备描述符给出了USB设备的一般信息,包括对设备及在设备配置中起全程作用的信息,包括制造商标识号ID、产品序列号、所属设备类号、默认端点的最大包长度和配置描述符的个数等。一个USB设备必须有且仅有一个设备描述符。设备描述符是设备连接到总线上时USB主机所读取的第一个描述符,它包含了14个字段,结构如下

    USB设备描述符的结构

    偏移量

    大小

    描述

    0

    bLength

    1

    数字

    此描述表的字节数

    1

    bDecriptorType

    1

    常量

    描述符的类型(此处应为0x01,即设备描述符)

    2

    bcdUSB

    2

    BCD

    此设备与描述表兼容的USB设备说明版本号(BCD 码)

    4

    bDeviceClass

    1

    设备类码:

    如果此域的值为0则一个设置下每个接口指出它自己的类,各个接口各自独立工作。
    如果此域的值处于1~FEH之间,则设备在不同的接口上支持不同的类。并这些接口可能不能独立工作。此值指出了这些接口集体的类定义。
    如果此域设为FFH,则此设备的类由厂商定义。

    5

    bDeviceSubClass

    1

    子类

    子类码

    这些码值的具体含义根据bDeviceClass 域来看。
    bDeviceClass 域为零,此域也须为零
    bDeviceClass 域为FFH,此域的所有值保留。

    6

    bDevicePortocol

    1

    协议

    协议码

    这些码的值视bDeviceClass bDeviceSubClass 的值而定。 如果设备支持设备类相关的协议,此码标志了设备类的值。如果此域的值为零,则此设备不支持设备类相关的协议,然而,可能它的接口支持设备类相关的协议。如果此域的值为FFH,此设备使用厂商定义的协议。

    7

    bMaxPacketSize0

    1

    数字

    端点0的最大包大小(仅8,16,32,64为合法值)

    8

    idVendor

    2

    ID

    厂商标志(由USB-IF组织赋值)

    10

    idProduct

    2

    ID

    产品标志(由厂商赋值)

    12

    bcdDevice

    2

    BCD

    设备发行号(BCD 码)

    14

    iManufacturer

    1

    索引

    描述厂商信息的字符串描述符的索引值。

    15

    iProduct

    1

    索引

    描述产品信息的字串描述符的索引值。

    16

    iSerialNumber

    1

    索引

    描述设备序列号信息的字串描述符的索引值。

    17

    bNumConfigurations

    1

    数字

    可能的配置描述符数目

    其中bDescriptorType为描述符的类型,其含义可查下表(此表也适用于标准命令Get_Descriptor中wValue域高字节的取值含义):

     

    USB描述符的类型值

    类型

    描述符

    描述符值

    标准描述符

    设备描述符(Device Descriptor)

    0x01

    配置描述符(Configuration Descriptor

    0x02

    字符串描述符(String Descriptor

    0x03

    接口描述符(Interface Descriptor

    0x04

    端点描述符(EndPont Descriptor

    0x05

    类描述符

    集线器类描述符(Hub Descriptor

    0x29

    人机接口类描述符(HID

    0x21

    厂商定义的描述符

    0xFF

    设备类代码bDeviceClass可查下表:

    设备的类别(bDeviceClass)

    值(十进制)

    值(十六进制)

    说明

    0

    0x00

    接口描述符中提供类的值

    2

    0x02

    通信类

    9

    0x09

    集线器类

    220

    0xDC

    用于诊断用途的设备类

    224

    0xE0

    无线通信设备类

    255

    0xFF

    厂商定义的设备类

    下表列出了一个USB鼠标的设备描述符的例子,供大家分析一下:

    一种鼠标的设备描述符示例

    字段

    描述符值(十六制)

    bLength

    0x12

    bDecriptorType

    0x01

    bcdUSB

    0x110

    bDeviceClass

    0x00

    bDeviceSubClass

    0x00

    bDevicePortocol

    0x00

    bMaxPacketSize0

    0x08

    idVendor

    0x045E(Microsoft Corporation

    idProduct

    0x0047

    bcdDevice

    0x300

    iManufacturer

    0x01

    iProduct

    0x03

    iSerialNumber

    0x00

    bNumConfigurations

    0x01

    Linux内核中定义的设备描述符结构:

    struct usb_device_descriptor  
    {  
        _ _u8 bLength; //描述符长度  
        _ _u8 bDescriptorType; //描述符类型编号  
        _ _le16 bcdUSB; //USB版本号  
        _ _u8 bDeviceClass; //USB分配的设备类code  
        _ _u8 bDeviceSubClass;// USB分配的子类code  
        _ _u8 bDeviceProtocol; //USB分配的协议code  
        _ _u8 bMaxPacketSize0; //endpoint0最大包大小  
        _ _le16 idVendor; //厂商编号  
        _ _le16 idProduct; //产品编号  
        _ _le16 bcdDevice; //设备出厂编号  
        _ _u8 iManufacturer; //描述厂商字符串的索引  
        _ _u8 iProduct; //描述产品字符串的索引  
        _ _u8 iSerialNumber; //描述设备序列号字符串的索引  
        _ _u8 bNumConfigurations; //可能的配置数量  
    } _ _attribute_ _ ((packed));
    

    2.2 配置描述符

          配置描述符中包括了描述符的长度(属于此描述符的所有接口描述符和端点描述符的长度的和)、供电方式(自供电/总线供电)、最大耗电量等。主果主机发出USB标准命令Get_Descriptor要求得到设备的某个配置描述符,那么除了此配置描述符以外,此配置包含的所有接口描述符与端点描述符都将提供给USB主机。

    USB配置描述符的结构

    偏移量

    大小

    描述

    0

    bLength

    1

    数字

    此描述表的字节数长度。

    1

    bDescriptorType

    1

    常量

    配置描述表类型(此处为0x02)

    2

    wTotalLength

    2

    数字

    此配置信息的总长(包括配置,接口,端点和设备类及厂商定义的描述符)

    4

    bNumInterfaces

    1

    数字

    此配置所支持的接口个数

    5

    bCongfigurationValue

    1

    数字

    在SetConfiguration()请求中用作参数来选定此配置。

    6

    iConfiguration

    1

    索引

    描述此配置的字串描述表索引

    7

    bmAttributes

    1

    位图

    配置特性:

    D7: 保留(设为一)
    D6: 自给电源
    D5: 远程唤醒
    D4..0:保留(设为一)
    一个既用总线电源又有自给电源的设备会在MaxPower域指出需要从总线取的电量。并设置D6为一。运行时期的实际电源模式可由GetStatus(DEVICE) 请求得到。

    8

    MaxPower

    1

    mA

    在此配置下的总线电源耗费量。以 2mA 为一个单位。

    下面是一种硬盘的配置描述符示例:

    一种硬盘的配置描述符示例

    字段

    描述符值(十六进制)

    bLength

    0x09

    bDescriptorType

    0x02

    wTotalLength

    0x01F

    bNumInterfaces

    0x01

    bCongfigurationValue

    0x01

    iConfiguration

    0x00

    bmAttributes

    0x0C

    MaxPower

    0x32

     Linux内核中定义的配置描述符结构

    {  
        _ _u8 bLength; //描述符长度  
        _ _u8 bDescriptorType; //描述符类型编号  
          
        _ _le16 wTotalLength; //配置所返回的所有数据的大小  
        _ _u8 bNumInterfaces; // 配置所支持的接口数  
        _ _u8 bConfigurationValue; //Set_Configuration命令需要的参数值  
        _ _u8 iConfiguration; //描述该配置的字符串的索引值  
        _ _u8 bmAttributes; //供电模式的选择  
        _ _u8 bMaxPower; //设备从总线提取的最大电流  
    } _ _attribute_ _ ((packed));
    

    2.3 接口描述符

        配置描述符中包含了一个或多个接口描述符,这里的“接口”并不是指物理存在的接口,在这里把它称之为“功能”更易理解些,例如一个设备既有录音的功能又有扬声器的功能,则这个设备至少就有两个“接口”。

        如果一个配置描述符不止支持一个接口描述符,并且每个接口描述符都有一个或多个端点描述符,那么在响应USB主机的配置描述符命令时,USB设备的端点描述符总是紧跟着相关的接口描述符后面,作为配置描述符的一部分被返回。接口描述符不可直接用Set_DescriptorGet_Descriptor来存取。

        如果一个接口仅使用端点0,则接口描述符以后就不再返回端点描述符,并且此接口表现的是一个控制接口的特性,它使用与端点0相关联的默认管道进行数据传输。在这种情况下bNumberEndpoints域应被设置成0。接口描述符在说明端点个数并不把端点0计算在内。

    USB接口描述符的结构

    偏移量

    大小

    说明

    0

    bLength

    1

    数字

    此表的字节数

    1

    bDescriptorType

    1

    常量

    接口描述表类(此处应为0x04

    2

    bInterfaceNumber

    1

    数字

    接口号,当前配置支持的接口数组索引(从零开始)。

    3

    bAlternateSetting

    1

    数字

    可选设置的索引值。

    4

    bNumEndpoints

    1

    数字

    此接口用的端点数量,如果是零则说明此接口只用缺省控制管道。

    5

    bInterfaceClass

    1

    接口所属的类值: 零值为将来的标准保留。 如果此域的值设为FFH,则此接口类由厂商说明。 所有其它的值由USB 说明保留。

    6

    bInterfaceSubClass

    1

    子类

    子类:这些值的定义视bInterfaceClass域而定。 如果bInterfaceClass域的值为零则此域的值必须为零。 bInterfaceClass域不为FFH则所有值由USB 所保留。

    7

    bInterfaceProtocol

    1

    协议

    协议码:bInterfaceClass bInterfaceSubClass 域的值而定.如果一个接口支持设备类相关的请求此域的值指出了设备类说明中所定义的协议.

    8

    iInterface

    1

    索引

    描述此接口的字串描述表的索引值。

    对于bInterfaceClass字段,表示接口所属的类别,USB协议根据功能将不同的接口划分成不的类,其具体含义如下表所示:

    USB协议定义的接口类别(bInterfaceClass)

    值(十六进制)

    类别

    0x01

    音频类

    0x02

    CDC控制类

    0x03

    人机接口类(HID

    0x05

    物理类

    0x06

    图像类

    0x07

    打印机类

    0x08

    大数据存储类

    0x09

    集线器类

    0x0A

    CDC数据类

    0x0B

    智能卡类

    0x0D

    安全类

    0xDC

    诊断设备类

    0xE0

    无线控制器类

    0xFE

    特定应用类(包括红外的桥接器等)

    0xFF

    厂商定义的设备

     Linux内核中定义的接口描述符结构

    struct usb_interface_descriptor  
    {  
        _ _u8 bLength;           //描述符长度  
        _ _u8 bDescriptorType;    //描述符类型  
        _ _u8 bInterfaceNumber;   // 接口的编号  
        _ _u8 bAlternateSetting;    //备用的接口描述符编号  
        _ _u8 bNumEndpoints;     //该接口使用的端点数,不包括端点0  
        _ _u8 bInterfaceClass;      //接口类型  
        _ _u8 bInterfaceSubClass;   //接口子类型  
        _ _u8 bInterfaceProtocol;    //接口所遵循的协议  
        _ _u8 iInterface;           //描述该接口的字符串索引值  
    } _ _attribute_ _ ((packed));
    

    2.4 端点描述符

          端点是设备与主机之间进行数据传输的逻辑接口,除配置使用的端点0(控制端点,一般一个设备只有一个控制端点)为双向端口外,其它均为单向。端点描述符描述了数据的传输类型、传输方向、数据包大小和端点号(也可称为端点地址)等。

         除了描述符中描述的端点外,每个设备必须要有一个默认的控制型端点,地址为0,它的数据传输为双向,而且没有专门的描述符,只是在设备描述符中定义了它的最大包长度。主机通过此端点向设备发送命令,获得设备的各种描述符的信息,并通过它来配置设备。

    static int test_probe(struct usb_interface *intf,const struct usb_device_id *id)  //资源探索函数
    {
        /*获取端点描述符*/
        struct usb_endpoint_descriptor *endpoint = &interface->endpoint[0].desc;
        switch(endpoint->bmAttributes)
        {
            case 0:printk("设备支持控制传输.\n");break;
            case 1:printk("设备支持同步传输.\n");break;
            case 2:printk("设备支持批量传输.\n");break;
            case 3:printk("设备支持中断传输.\n");break;
        }
    }
    struct usb_endpoint_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;
        __u8  bEndpointAddress;
        __u8  bmAttributes;
        __le16 wMaxPacketSize;
        __u8  bInterval;
        __u8  bRefresh;
        __u8  bSynchAddress;
    } __attribute__ ((packed));
    

    USB端点描述符的结构

    偏移量

    大小

    说明

    0

    bLength

    1

    数字

    此描述表的字节数长度

    1

    bDescriptorType

    1

    常量

    端点描述表类(此处应为0x05

    2

    bEndpointAddress

    1

    端点

    此描述表所描述的端点的地址、方向:
    Bit 3..0 : 端点号.
    Bit 6..4 :
    保留,为零
    Bit 7:    方向,如果控制端点则略。
    0:输出端点(主机到设备)
    1:输入端点(设备到主机)

    3

    bmAttributes

    1

    位图

    此域的值描述的是在bConfigurationValue域所指的配置下端点的特性。
    Bit 1..0 :传送类型

    00=控制传送

    01=同步传送

    10=批传送

    11=中断传送

    所有其它的位都保留。

    4

    wMaxPacketSize

    2

    数字

    当前配置下此端点能够接收或发送的最大数据包的大小。 对于实进传输,此值用于为每帧的数据净负荷预留时间。在实际运行时,管道可能不完全需要预留的带宽,实际带宽可由设备通过一种非USB定义的机制汇报给主机。对于中断传输,批量传输和控制传输,端点可能发送比之短的数据包

    6

    bInterval

    1

    数字

    周期数据传输端点的时间间隙。 此域的值对于批传送的端点及控制传送的端点无意义。对于同步传送的端点此域必需为1,表示周期为1ms。对于中断传送的端点此域值的范围为1ms255ms

    下表是一种鼠标的端点描述符的示例,该端点是一个中断端点:

    一种鼠标的端点描述符示例

    值(十六进制)

    bLength

    0x07

    bDescriptorType

    0x05

    bEndpointAddress

    0x81

    bmAttributes

    0x03

    wMaxPacketSize

    0x04

    bInterval

    0x0A

    一个 USB 端点有 4 种不同类型, 分别具有不同的数据传送方式:

    控制CONTROL

    控制端点被用来控制对 USB 设备的不同部分访问. 通常用作配置设备、获取设备信息、发送命令到设备或获取设备状态报告。这些端点通常较小。每个 USB 设备都有一个控制端点称为"端点 0", 被 USB 核心用来在插入时配置设备。USB协议保证总有足够的带宽留给控制端点传送数据到设备.

    中断INTERRUPT

    每当 USB 主机向设备请求数据时,中断端点以固定的速率传送小量的数据。此为USB 键盘和鼠标的主要的数据传送方法。它还用以传送数据到 USB 设备来控制设备。通常不用来传送大量数据。USB协议保证总有足够的带宽留给中断端点传送数据到设备.

    批量BULK

    批量端点用以传送大量数据。这些端点常比中断端点大得多. 它们普遍用于不能有任何数据丢失的数据。USB 协议不保证传输在特定时间范围内完成。如果总线上没有足够的空间来发送整个BULK包,它被分为多个包进行传输。这些端点普遍用于打印机、USB Mass StorageUSB网络设备上

    等时ISOCHRONOUS

    等时端点也批量传送大量数据, 但是这个数据不被保证能送达。这些端点用在可以处理数据丢失的设备中,并且更多依赖于保持持续的数据流。如音频和视频设备等等。

    控制和批量端点用于异步数据传送,而中断和同步端点是周期性的。这意味着这些端点被设置来在固定的时间连续传送数据,USB 核心为它们保留了相应的带宽。

    端点在linux内核中使用结构 struct usb_host_endpoint 来描述,它所包含的真实端点信息在另一个结构中:struct usb_endpoint_descriptor(端点描述符,包含所有的USB特定数据)。

    Linux内核中定义的端点描述符结构

    struct usb_endpoint_descriptor  
    {  
        _ _u8 bLength; //描述符长度  
        _ _u8 bDescriptorType; //描述符类型  
        _ _u8 bEndpointAddress; //端点地址:0~3位是端点号,第7位是方向(0-OUT,1-IN)  
        _ _u8 bmAttributes; //端点属性:bit[0:1] 的值为00表示控制,为01表示同步,为02表示批量,为03表示中断  
        _ _le16 wMaxPacketSize;  本端点接收或发送的最大信息包的大小  
        _ _u8 bInterval;//轮询数据传送端点的时间间隔  
                               //对于批量传送的端点以及控制传送的端点,此域忽略  
                               //对于同步传送的端点,此域必须为1  
        _ _u8 bRefresh;  
        _ _u8 bSynchAddress;  
    } _ _attribute_ _ ((packed));
    

    2.5 字符串描述符

         字符串描述符是一种可选的USB标准描述符,描述了如制商、设备名称或序列号等信息。如果一个设备无字符串描述符,则其它描述符中与字符串有关的索引值都必须为0。字符串使用的是Unicode编码。

        主机请示得到某个字符串描述符时一般分成两步:首先主机向设备发出USB标准命令Get_Descriptor,其中所使用的字符串的索引值为0,设备返回一个字符串描述符,此描述符的结构如下:

    USB字符串描述符(响应主机请求时返回的表示语言ID的字符串描述符)

    偏移量

    大小

    描述

    0

    bLength

    1

    N+2

    此描述表的字节数

    1

    bDescriptorType

    1

    常量

    字串描述表类型(此处应为0x03

    2

    wLANGID[0]

    2

    数字

    语言标识(LANGID 0

    N

    wLANGID[x]

    2

    数字

    语言标识(LANGID)码X

        该字符串描述符双字节的语言ID的数组,wLANGID[0]~wLANGID[x]指明了设备支持的语言,具体含义可查看USB_LANGIDs.pdf

         主机根据自己需要的语言,再次向设备发出USB标准命令Get_Descriptor,指明所要求得到的字符串的索引值和语言。这次设备所返回的是Unicode编号的字符串描述符,其结构如下:

    Unicode字符串描述符(响应主机请求时真正表示字符串编码的字符串描述符)

    偏移量

    大小

    描述

    0

    bLength

    1

    数字

    此描述表的字节数(bString域的数值N2

    1

    bDescriptorType

    1

    常量

    字串描述表类型(此处应为0x03

    2

    bString

    N

    数字

    UNICODE 编码的字串

         bString域为设备实际返回的以UNICODE编码的字符串流,我们在编写设备端硬件驱动的时候需要将字符串转换为UNICODE编码,可以通过一些UNICODE转换工具进行转换。这里推荐一款USB描述符生成工具“USB Unicode 字符串描述符生成器”,它专门为编写设备端驱动程序的需要而定制,可以非常方便将需要的字符串转换成UNICODE格式,进而导入C或汇编程序代码中。

    Linux内核中定义的字符串描述符结构

    struct usb_string_descriptor  
    {  
        _ _u8 bLength; //描述符长度  
        _ _u8 bDescriptorType; //描述符类型
        _ _le16 wData[1];  
    } _ _attribute_ _ ((packed));  
    

    三、HID描述符

    3.1 HID描述符介绍

           USB 设备中有一大类就是 HID 设备,即 Human Interface Devices,人机接口设备。这类设备包括鼠标、键盘等,主要用于人与计算机进行交互。 它是 USB 协议最早支持的一种设备类。 HID 设备可以作为低速、全速、高速设备用。由于 HID 设备要求用户输入能得到及时响应,故其传输方式通常采用中断方式。

         在 USB 协议中, HID 设备的定义放置在接口描述符中, USB 的设备描述符和配置描述符中不包含 HID 设备的信息。因此,对于某些特定的 HID 设备,可以定义多个接口,只有其中一个接口为 HID 设备类即可。

        当定义一个设备为 HID 设备时,其设备描述符应为:          

    bDeviceClass=0

    bDeviceSubClass=0

    bDeviceProtocol=0

    其接口描述符应该:

    bInterfaceClass=0x03

    另外(接口描述符)

    对无引导的 HID 设备,子类代码 bInterfaceSubClass 应置 0,此时 bInterfaceProtocol 无效,置零即可。即为:

    bInterfaceClass=0x03

    bInterfaceSubClass=0

    bInterfaceProtocol=0

          对支持引导的 USB 设备,子类代码 bInterfaceSubClass 应置 1,此时 bInterfaceProtocol 可以为 1 或 2, 1 表示键盘接口, 3 表示鼠标接口。其参考设置如下:

    bInterfaceClass=0x03

    bInterfaceSubClass=1

    bInterfaceProtocol=1 或 2

           HID 设备支持 USB 标准描述符中的五个:设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符。除此之外, HID 设备还有三种特殊的描述符: HID 描述符、报告描述符、物理描述符。一个 USB 设备只能支持一个 HID 描述符,但可以支持多个报告描述符,而物理描述符则可以有也可以没有。

    3.2 HID 描述符

    HID 描述符用于识别 HID 设备中所包含的额外描述符,例如报告描述符或物理描述符等。

    其格式如下:

    字段名

    长度/字节

    地址偏移量

    说明

    bLength

    1

    0

    报告描述符长度(字节)

    bDescriptorType

    1

    1

    描述符类型: 0x21

    bcdHID

    2

    2

    HID版本号(BCD 码)

    bCountryCode

    1

    4

    国家/地区代码

    bNumDescriptor

    1

    5

    支持的其他类型描述符数量

    bDescriptorType

    1

    6

    类别描述符的类型

    wDescriptorLength

    2

    7

    报告描述符的总长度

    bDescriptorType

    1

    9

    用于识别描述符类型的常数

    wDescriptorLength

    2

    10

    描述符的总长度

    各字段含义如下:

    1. bLength: HID 描述符长度。
    2. bDescriptorType: HID 描述符类型,值为 0x21。
    3. bcdHID: HID 设备所遵循的 HID 版本号,为 4 位 16 进制的 BCD 码数据。 1.0 即 0x0100, 1.1 即 0x01
    4. bCountryCode: HID 设备国家/地区代码。
    5. bNumDescriptor: HID 设备支持的其01, 2.0即 0x0200。他设备描述符的数量。由于 HID 设备至少需要包括一个报告描述符,故其值至小为 0x01。
    6. bDescriptorType: HID 描述符附属的类别描述符长度。
    7. bDescriptorType/wDescriptorLength:可选字段,用于表示 HID 描述符附属的类别描述符类型及长度。

    3.3 报告描述符

           HID 设备的报告描述符是一种数据报表,主要用于定义 HID 设备和 USB 主机之间的数据交换格式, HID 设备报告描述符的类型值为 0x22。 

         报告描述符使用自定义的数据结构,用于传输特定的数据包。

        例如: 对于键盘,需要在数据包中指明按键的值,报告描述符把这些数据打包发给主机,主机对发来的数据进行处理。 它有四个组成部分, 其格式如下:

    0 ~1     2~ 3     4 5 6 7      8~ 23          (共24位,占4个字节)

    bSize    bType     bTag      [data]

    各字段含义:

    1. bSize:占用两个位, 指示数据部分,即[data]字段的长度, 00b表没有数据字节, 01b表只有一个数据字节, 10b 表示有两个数据字节, 11b 表有 4 个数据字节。
    2. bType:数据项类型,用于指明数据项的类型。 00b主数据类型, 01b全局数据类型, 10b局部数据类型, 11b保留。
    3. bTag:数据项标签,用于指明数据项的功能。报告描述符需要包含的数据项标签有:输入输出数据项标签、用法数据项标签、用法页数据项标签、逻辑最小和最大值数据项标签、报告大小数据项标签以及报告计数数据项标签。
    4. [data]:数据字节,随着前面 bSize 定义的大小而变化。

    3.4 物理描述符

         HID 设备的物理描述符主要用于报告物理设备的激活信息,其类型值为 0x23,它是可选的,对大部分设备不需要使用此描述符。

    四、 linux内核下USB相关的API函数与数据结构

            前面介绍了USB相关一些基础概念与重要的数据结构,接下来就分析在linux内核中如何编写一个USB 驱动程序,编写与一个USB设备驱动程序的方法和其他总线驱动方式类似,驱动程序把驱动程序对象注册到USB子系统中,稍后再使用制造商和设备标识来判断是否安装了硬件。当然,这些制造商和设备标识需要我们编写进USB 驱动程序中。

         USB 驱动程序依然遵循设备模型 —— 总线、设备、驱动。和I2C 总线设备驱动编写一样,所有的USB驱动程序都必须创建的主要结构体是 struct usb_driver,它们向USB 核心代码描述了USB 驱动程序。但这是个外壳,只是实现设备和总线的挂接,具体的USB 设备是什么样的,如何实现的,比如一个字符设备,我们还需填写相应的文件操作接口。

    USB构成框图:

     4.1 USB设备注册与注销

    //注册USB设备
    #define usb_register(driver) \
    	usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
    
    //注销USB设备
    void usb_deregister(struct usb_driver *driver)
    
    //需要添加的头文件
    #include <linux/usb.h>
    

    4.2 USB设备注册框架示例

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/usb.h>
    //定义USB的IDTAB
    static const struct usb_device_id usbtest[] = {
    	{//148f:760b
    		USB_DEVICE(0x148f, 0x760b),	/*360WIFI的制造商ID和产品ID */
    	},
    };
    
    //USB设备信息与驱动端匹配成功的时候调用。
    static int test_probe(struct usb_interface *intf,const struct usb_device_id *id)  //资源探索函数
    {
    		printk("USB 驱动匹配成功!\n");
    		return 0;
    }
    
    //USB断开的时候调用
    static void test_disconnect(struct usb_interface *intf)
    {
    		printk("USB 设备释放成功!\n"); 
    }
    //定义USB驱动结构体 
    static struct usb_driver usbtest_driver = {
    	.name = "linux_usb_drv",
    	.id_table = usbtest,
    	.probe = test_probe,
    	.disconnect = test_disconnect
    };
    
    static int __init usbtest_init(void)
    {
    	//注册USB设备驱动
    	usb_register(&usbtest_driver);
    	return 0;
    }
    module_init(usbtest_init);
    static void __exit usbtest_exit(void)
    {
    	//注销USB设备驱动
    	usb_deregister(&usbtest_driver);
    }
    module_exit(usbtest_exit);
    MODULE_AUTHOR("xiaolong");
    MODULE_LICENSE("GPL");
    

    4.3 struct usb_driver数据结构

    struct usb_driver {
    	const char *name;   //USB设备的名字,名称可以随便填写。
    	int (*probe) (struct usb_interface *intf, const struct usb_device_id *id);   //资源探索函数,当usB驱动端与设备端匹配成功的时候调用。
    	void (*disconnect) (struct usb_interface *intf);  //USB设备断开时调用。
    	const struct usb_device_id *id_table;  //USB设备的匹配ID列表
    ……………..
    };
    

    列出的为必填成员。

    struct usb_device_id 设备ID结构原型如下:

    struct usb_device_id {
    	/* 确定设备信息去和结构体中哪几个字段匹配来判断驱动的适用性,比如是否是HID协议等*/
    	__u16		match_flags;
    
    	/*用于特定于产品的匹配 */
    	__u16		idVendor;  /*USB设备的制造商ID,须向www.usb.org申请*/
    	__u16		idProduct;  // USB设备的产品ID,有制造商自定
    	__u16		bcdDevice_lo; /* USB设备的产品版本号最低值*/
    	__u16		bcdDevice_hi; /* 和最高值,以BCD码来表示。*/
    
    	/* 分别定义设备的类,子类和协议,他们由 USB 论坛分配并定义在 USB 规范中. 
    这些值指定这个设备的行为, 包括设备上所有的接口 */ 
    	__u8		bDeviceClass;
    	__u8		bDeviceSubClass;
    	__u8		bDeviceProtocol;
    
    	/*  分别定义单个接口的类,子类和协议,他们由 USB 论坛分配并定义在 USB 规范中 */
    	__u8		bInterfaceClass;
    	__u8		bInterfaceSubClass;
    	__u8		bInterfaceProtocol;
    
    	/* 这个值不用来匹配驱动的, 驱动用它来在 USB 驱动的探测回调函数中区分不同的设备 
          该成员一般来保存一个结构体指针,存放该设备特殊的数据
    */
    	kernel_ulong_t	driver_info;
    

     填充struct usb_device_id结构体中的__u16  match_flags成员用到的宏定义:

    #define USB_DEVICE_ID_MATCH_VENDOR		   0x0001    /*供应商厂家ID*/
    #define USB_DEVICE_ID_MATCH_PRODUCT		0x0002    /*产品ID*/
    

     快速填充usb_device_id结构体的相关宏:

    USB_DEVICE_ID_MATCH_INT_INFO            --根据接口信息
    USB_DEVICE_ID_MATCH_DEV_INFO           --根据设备的信息
    USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION --根据设备制造信息和版本
    USB_DEVICE_ID_MATCH_DEV_RANGE         --根据设备版本
    USB_DEVICE_ID_MATCH_DEVICE             --根据设备制造信息
    

     struct usb_device_id结构体填充示例1—(摘自DM9620-USB网卡)

    static const struct usb_device_id products[] = {
    	{
    		USB_DEVICE(0x07aa, 0x9601),	/* Corega FEther USB-TXC */
    		.driver_info = (unsigned long)&dm9620_info,
    	}, {
    		USB_DEVICE(0x0a46, 0x9601),	/* Davicom USB-100 */
    		.driver_info = (unsigned long)&dm9620_info,
    	},
    }
    

     struct usb_device_id结构体填充示例2------->(摘自内核自带的鼠标驱动)

    static struct usb_device_id usb_mouse_id_table [] = {
    	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
    		USB_INTERFACE_PROTOCOL_MOUSE) },
    	{ }	/* 结束 */
    };
    

    USB鼠标USB驱动端结构体填充示例:

    static struct usb_driver usb_mouse_driver = {
    	.name		= "usbmouse",         /*鼠标的名称-不是匹配使用*/
    	.probe		= usb_mouse_probe,    /*资源探测函数-匹配成功调用*/
    	.disconnect	= usb_mouse_disconnect,/*当鼠标断开连接调用*/
    	.id_table	= usb_mouse_id_table,       /*匹配驱动使用*/
    };
    

    4.4 获取当前设备信息

    struct usb_device *interface_to_usbdev(struct usb_interface *intf)

    用法示例:

    static int usb_driver_probe(struct usb_interface *intf, const struct usb_device_id *id)
    {
    	struct usb_device *dev = interface_to_usbdev(intf);  /*设备与驱动匹配成功时,在_probe 函数里获取设备的信息*/
    }
    

    4.5 创建数据传输管道

         管道是USB设备通信的通道,内核中提供了创建管道的宏,从以下内核定义宏中我们可以分析出,管道是一个 int 型的变量,由设备号、端点地址、端点类型组合而成。

    //控制CONTROL 
    #define usb_sndctrlpipe(dev, endpoint)	\
    	((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint))  //默认输出
    #define usb_rcvctrlpipe(dev, endpoint)	\
    	((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN) //输入
    
    //中断INTERRUPT 
    #define usb_sndisocpipe(dev, endpoint)	\
    	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint))//默认输出
    #define usb_rcvisocpipe(dev, endpoint)	\
    	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)//输入
    
    //批量BULK
    #define usb_sndbulkpipe(dev, endpoint)	\
    	((PIPE_BULK << 30) | __create_pipe(dev, endpoint))//默认输出
    #define usb_rcvbulkpipe(dev, endpoint)	\
    	((PIPE_BULK << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)//输入
    
    //等时ISOCHRONOUS 
    #define usb_sndintpipe(dev, endpoint)	\
    	((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint))//默认输出
    #define usb_rcvintpipe(dev, endpoint)	\
    	((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)//输入
    
    static inline unsigned int __create_pipe(struct usb_device *dev,unsigned int endpoint)
    {
    	return (dev->devnum << 8) | (endpoint << 15);
    }
    

         端点是有四种的,对应着管道也就有四种,同时端点是有IN也有OUT,相应的管道也就有两个方向,于是二四得八,上面就出现了八个创建管道的宏。有了struct usb_device结构体,也就是说知道了设备地址,再加上端点号,就可以根据需要创建指定的管道。__create_pipe宏只是一个幕后的角色,用来将设备地址和端点号放在管道正确的位置上。

    示例:

    struct usb_device *dev = interface_to_usbdev(intf);
    struct usb_host_interface *interface;
    struct usb_endpoint_descriptor *endpoint;	/* 定义端点描述符 */
    interface = intf->cur_altsetting;
    endpoint = &interface->endpoint[0].desc;
    int pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);  /*创建管道*/
    

    4.6 动态分配urb

         urb(USB Request Block)Linux内核中USB驱动实现上的一个数据结构,用于组织每一次的USB设备驱动的数据传输请求。

    struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
     @iso_packets:这个urb的iso包的数量
    @mem_flags:要分配的内存类型,请参阅kmalloc()以获取列表
    

    示例:

    static struct urb *myurb= usb_alloc_urb(0, GFP_KERNEL);

    4.7 urb数据结构初始化(控制) 

    static inline void usb_fill_control_urb(struct urb *urb,
    					struct usb_device *dev,
    					unsigned int pipe,
    					unsigned char *setup_packet,
    					void *transfer_buffer,
    					int buffer_length,
    					usb_complete_t complete_fn,
    					void *context)
    

    4.8 urb数据结构初始化(中断) 

    static inline void usb_fill_int_urb(struct urb *urb,
    				    struct usb_device *dev,
    				    unsigned int pipe,
    				    void *transfer_buffer,
    				    int buffer_length,
    				    usb_complete_t complete_fn,
    				    void *context,
    				    int interval)
    

    4.9 urb数据结构初始化(批量)

    static inline void usb_fill_bulk_urb(struct urb *urb,
    				     struct usb_device *dev,
    				     unsigned int pipe,
    				     void *transfer_buffer,
    				     int buffer_length,
    				     usb_complete_t complete_fn,
    				     void *context)
    

    4.10 urb数据结构初始化(等时)

     等时urb 没有和中断、控制、批量urb 类似的初始化函数,因此它们在提交到USB核心之前,需要在驱动程序中手动的初始化。例如:

    urb->dev = dev;
    urb->context = uvd;
    urb->pipe = usb_rcvisocpipe(dev,uvd->video_endp-1);
    urb->interval = 1;
    urb->transfer_flags = URB_IOS_ASAP;
    urb->transfer_buffer = can->sts_buf[i];
    urb_complete = konicawc_isoc_irq;
    urb->number_of_packets = FRAMES_PRE_DESC;
    urb->transfer_buffer_lenth = FRAMES_PRE_DESC;
    for (j=0; j < FRAMES_PRE_DESC; j++){
        urb->ios_frame_desc[j].offset  = j;
        urb->ios_frame_desc[j].length  = 1;
    }
    

    五、编写USB鼠标驱动(中断传输方式)

    5.1 USB驱动注册框架代码

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/usb.h>
    
    /*
    [   25.845000] usb 1-2.2: new high-speed USB device number 6 using s5p-ehci
    [   25.950000] usb 1-2.2: New USB device found, idVendor=0661, idProduct=294b
    [   25.950000] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [   25.950000] usb 1-2.2: Product: EZ-USB
    [   25.950000] usb 1-2.2: Manufacturer: Cypress
    
    [  726.360000] usb 1-2.2: new high-speed USB device number 7 using s5p-ehci
    [  726.475000] usb 1-2.2: config 1 interface 0 altsetting 0 has 7 endpoint descriptors, different from the interface descriptor's value: 5
    [  726.480000] usb 1-2.2: New USB device found, idVendor=148f, idProduct=5370
    [  726.480000] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [  726.480000] usb 1-2.2: Product: 802.11 n WLAN
    [  726.480000] usb 1-2.2: Manufacturer: Ralink
    [  726.485000] usb 1-2.2: SerialNumber: 1.0
    */
    
    //定义USB的IDTAB
    static const struct usb_device_id tiny4412_usb_id[] = 
    {
        {USB_DEVICE(0x148f,0x5370)},
        {USB_DEVICE(0x0661,0x294b)},
        {}
    };
    
    /*
    MODULE_DEVICE_TABLE 有两个功能。
    一是:将设备加入到外设队列中,
    二是告诉程序阅读者该设备是热插拔设备或是说该设备支持热插拔功能。
    该宏定义在<linux/module.h>下
    这个宏有两个参数,第一个参数设备名,第二个参数该设备加入到模块中时对应产生的设备搜索符号,这个宏生成了一个名为__mod_pci_device_table
    局部变量,这个变量指向第二个参数
    */
    MODULE_DEVICE_TABLE (usb,tiny4412_usb_id);
    
    //USB设备信息与驱动端匹配成功的时候调用。
    static int test_probe(struct usb_interface *intf,const struct usb_device_id *id)  //资源探索函数
    {
        printk("tiny4412 probe success .\n");
        return 0;
    }
    
    //USB断开的时候调用
    static void test_disconnect(struct usb_interface *intf)
    {
        printk("tiny4412 usb drv disconnect success.\n"); 
    }
    
    //定义USB驱动结构体 
    static struct usb_driver tiny4412_usb_driver = {
        .name = "tiny4412_usb_drv",
        .id_table = tiny4412_usb_id,
        .probe = test_probe,
        .disconnect = test_disconnect
    };
    
    static int __init tiny4412_usb_init(void)
    {
        //注册USB设备驱动
        usb_register(&tiny4412_usb_driver);
        printk("tiny4412 usb drv install success.\n"); 
        return 0;
    }
    
    static void __exit tiny4412_usb_exit(void)
    {
         //注销USB设备驱动
         usb_deregister(&tiny4412_usb_driver);
         printk("tiny4412 usb drv exit success.\n"); 
    }
    
    module_init(tiny4412_usb_init);
    module_exit(tiny4412_usb_exit);
    MODULE_AUTHOR("xiaolong");
    MODULE_LICENSE("GPL");
    

    运行示例: 拔插USB WIFI 弹出的提示信息。

    [root@wbyq code]# insmod linux_usb_drv.ko 
    [   19.160000] usbcore: registered new interface driver tiny4412_usb_drv
    [   19.160000] tiny4412 usb drv install success.
    [root@wbyq code]# [   25.430000] usb 1-2.2: new high-speed USB device number 5 using s5p-ehci
    [   25.545000] usb 1-2.2: config 1 interface 0 altsetting 0 has 7 endpoint descriptors, different from the interface descriptor's value: 5
    [   25.550000] usb 1-2.2: New USB device found, idVendor=148f, idProduct=5370
    [   25.550000] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [   25.550000] usb 1-2.2: Product: 802.11 n WLAN
    [   25.550000] usb 1-2.2: Manufacturer: Ralink
    [   25.555000] usb 1-2.2: SerialNumber: 1.0
    [   25.570000] tiny4412 probe success .
    

    5.2 编写USB鼠标驱动

    [root@wbyq linux-3.5]# make menuconfig

    由于内核自带了usb鼠标驱动,所以需要去除:

    Device Drivers  ---> 
    	  HID support  --->
    	  	 USB HID support  --->	
    	  	 		<> USB HID transport layer    //HID传输层
    

    去掉之后,再重新编译内核,烧写内核。

    鼠标驱动代码: 该模板适用于键盘驱动。

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/usb.h>
    #include <linux/usb/input.h>
    #include <linux/hid.h>
    
    /*
    本程序为USB鼠标驱动程序,要安装本驱动,需要先将内核自带的USB驱动程序卸载掉
    */
    
    //定义USB的IDTAB 24ae:2002
    static const struct usb_device_id tiny4412_usb_id[] = {
    	{//148f:7601
    		USB_DEVICE(0x148f,0x7601),/*360WIFI的制造商ID和产品ID */
    		USB_DEVICE(0x24ae,0x2002),/*当前鼠标的ID*/
    	},
    };
    
    //USB鼠标的ID
    static struct usb_device_id usb_mouse_id[] = {
    	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
    		USB_INTERFACE_PROTOCOL_MOUSE) },
    	{ }	/* 终止进入 */
    };
    
    int size;
    static unsigned char *buf =NULL;
    static struct urb *myurb=NULL;
    dma_addr_t buf_phy;
    
    /*USB中断处理程序*/
    static void usb_complete(struct urb *urb)
    {
    	int i;
    	for(i=0;i<size;i++)
    	{
    		printk("0x%x ",buf[i]);
    	}
    	printk("\n");
    	
    	/* 重新提交异步请求*/
    	usb_submit_urb(myurb, GFP_KERNEL);
    }
    
    //USB设备信息与驱动端匹配成功的时候调用。
    static int usb_probe(struct usb_interface *intf,const struct usb_device_id *id)
    {
    	printk("USB驱动匹配成功! ID: 0x%X,0x%X\n",id->idVendor,id->idProduct);
    
    	/*通过接口获取设备信息*/
    	struct usb_device *dev = interface_to_usbdev(intf);
    	/*获取当前接口设置*/
    	struct usb_host_interface *interface=intf->cur_altsetting;
    	/*获取端点描述符*/
    	struct usb_endpoint_descriptor *endpoint = &interface->endpoint[0].desc;
    	/*中断传输:创建输入管道*/
    	int pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
    	/*从端点描述符中获取传输的数据大小 */
    	size = endpoint->wMaxPacketSize;
    	printk("设备传输数据包大小:%d\n",size);
    	/*分配数据传输缓冲区*/
    	buf = usb_alloc_coherent(dev,size,GFP_ATOMIC,&buf_phy);
    	/*分配新的urb,urb是usb设备驱动中用来描述与usb设备通信所用的基本载体和核心数据结构*/
    	myurb = usb_alloc_urb(0,GFP_KERNEL);
    	/*中断方式初始化urb*/
    	usb_fill_int_urb(myurb,dev,pipe,buf,size,usb_complete,NULL,endpoint->bInterval);
    	myurb->transfer_dma = buf_phy;
    	myurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    	/*为端点提交异步传输请求*/
    	usb_submit_urb(myurb, GFP_KERNEL);	
    	return 0;
    }
    
    //USB断开的时候调用
    static void usb_disconnect(struct usb_interface *intf)
    {
    	struct usb_device *dev = interface_to_usbdev(intf);
    	usb_kill_urb(myurb);
    	usb_free_urb(myurb);
    	usb_free_coherent(dev,size,buf, buf_phy);
    	printk("USB 设备释放成功!\n"); 
    }
    
    //定义USB驱动结构体 
    static struct usb_driver tiny4412_usb_driver = {
    	.name = "tiny4412_usb",
    	.id_table = usb_mouse_id,
    	.probe = usb_probe,
    	.disconnect = usb_disconnect
    };
    
    static int __init tiny4412_usb_init(void)
    {
    	//注册USB设备驱动
    	usb_register(&tiny4412_usb_driver);
    	return 0;
    }
    
    static void __exit tiny4412_usb_exit(void)
    {
    	 //注销USB设备驱动
    	 usb_deregister(&tiny4412_usb_driver);
    }
    
    module_init(tiny4412_usb_init);
    module_exit(tiny4412_usb_exit);
    MODULE_AUTHOR("xiaolong");
    MODULE_LICENSE("GPL");
    

     

    六、编写USB光谱仪驱动(批量传输方式)

          USB光谱仪的USB接口支持使用批量方式传输数据,当前程序里使用的是同步方式提交请求。

    整体驱动思路:

    (1). 在驱动层里先定义光谱仪设备的设备ID和厂商ID,当设备插入时,ID匹配成功,就会调用probe函数,在probe函数里完成设备信息探测,比如: 端点数据传输方向,数据传输大小,传输方式等等。

    探测成功后,就注册一个字符设备,创建设备节点,方便应用程序调用驱动完成设备控制。

    (2).  驱动层向应用层提供了read和write接口函数,方便根据预先定义的结构体进行数据通信。

       具体情况可以参考 –下面的应用层程序示例代码。

    6.1 头文件定义支持的命令

    #ifndef SPECTROMETER_H
    #define SPECTROMETER_H
    #define Get_Module_Information  0x01000000UL
    #define Get_Spectrometer_Information    0x02000000UL
    #define Get_Module_Property 0x03000000UL
    #define Get_Data_Position_Property  0x04000000UL
    #define Get_Data_Count_Property 0x05000000UL
    #define Get_Data_Transmit_Property  0x06000000UL
    #define Get_Data_Trigger_Offset_Property    0x07000000UL
    #define Get_Exposure_Property   0x08000000UL
    #define Get_Gain_Property   0x08000000UL
    #define Get_Ad_Offset_Property  0x0A000000UL
    #define Get_Wavelength_Property 0x0C000000UL
    #define Get_Image_Size  0x0D000000UL
    #define Get_Capture_Mode    0x0F000000UL
    #define Set_Capture_Mode    0x10000000UL
    #define Get_Data_Position   0x11000000UL
    #define Set_Data_Position   0x12000000UL
    #define Get_Data_Count  0x13000000UL
    #define Set_Data_Count  0x14000000UL
    #define Get_Data_Transmit   0x15000000UL
    #define Set_Data_Transmit   0x16000000UL
    #define Get_Data_TriggerOffset  0x17000000UL
    #define Set_Data_TriggerOffset  0x18000000UL
    #define Get_Exposure_Time   0x19000000UL
    #define Set_Exposure_Time   0x1A000000UL
    #define Get_Exposure_Cycle  0x1B000000UL
    #define Set_Exposure_Cycle  0x1C000000UL
    #define Get_Trigger_Mode    0x1D000000UL
    #define Set_Trigger_Mode    0x1E000000UL
    #define Get_Trigger_Polarity    0x1F000000UL
    #define Set_Trigger_Polarity    0x20000000UL
    #define Get_Trigger_Output  0x21000000UL
    #define Set_Trigger_Output  0x22000000UL
    #define Get_Gain    0x25000000UL
    #define Set_ain 0x26000000UL
    #define Get_Ad_Offset   0x27000000UL
    #define Set_Ad_OffSet   0x28000000UL
    #define Get_Calibration_Coefficient 0x29000000UL
    #define Set_Calibration_Coefficient 0x3B000000UL
    #define Get_Cooling_Temperature 0x2A000000UL
    #define Capture_Start   0x2F000000UL
    #define Fire_Trigger    0x30000000UL
    #define Capture_Stop    0x31000000UL
    #define Read_Eeprom_User_Area   0x33000000UL
    #define Write_Eeprom_User_Area  0x34000000UL
    #define Get_Status_Request  0x3D000000UL
    #define Get_Defective_Pixel 0x3E000000UL
    
    #pragma pack(1)
    struct DEV_CMD
    {
        unsigned char buff[500];  //读写数据缓冲区
        unsigned int write_len;  //写数据长度
        unsigned int read_len;   //读数据长度
    };
    
    #define IOCTL_CMD_RW 0x39654128
    #endif
    

    6.2 应用层程序示例

    打开光谱仪设备节点,获取设备的信息或者设置设备信息。

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/ioctl.h>
    #include <stdlib.h>
    #include "spectrometer_cmd_list.h"
    #include <string.h>
     #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #define DEV_NAME "/dev/spectrometer_usb_drv"
    
    int main(int argc,char **argv)
    {
        /*1. 打开设备文件*/
        int fd=open(DEV_NAME,2);
        if(fd<0)
        {
            printf("%s 设备文件打开失败.\n",DEV_NAME);
            return 0;
        }
        
        /*2. 读写光谱仪设备*/
        struct DEV_CMD dev_cmd;
        memset(&dev_cmd,0,sizeof(struct DEV_CMD));
        dev_cmd.write_len=8;  //写数据长度
        dev_cmd.read_len=500; //读数据长度,如果只想写不想读. 这里长度填0即可.
        //写入的命令.赋值  01 00 00 00
        dev_cmd.buff[0]=0x01;
        dev_cmd.buff[1]=0x00;
        dev_cmd.buff[2]=0x00;
        dev_cmd.buff[3]=0x00;
        dev_cmd.buff[4]=0x00;
        dev_cmd.buff[5]=0x00;
        dev_cmd.buff[6]=0x00;
        dev_cmd.buff[7]=0x00;
        //提交数据
        if(ioctl(fd,IOCTL_CMD_RW,&dev_cmd))
        {
            printf("ioctl执行失败.\n");
        }
        else
        {
            printf("写成功: %d 字节.\n",dev_cmd.write_len);
            if(dev_cmd.read_len>0)
            {
                printf("读成功: %d 字节.\n",dev_cmd.read_len);
                printf("读取数据如下:\n");
                int i;
                for (i = 0; i < dev_cmd.read_len; i++)
                {
                    printf("%#x ",dev_cmd.buff[i]);
                }
                printf("\n");
            }
        }
        
        //关闭设备
        close(fd);
        return 0;
    }
    

    6.3 支持的命令详情

    Contents

    RequestCommand
    (4Byte)

    DataSize
    (4Byte)

    Data

    Note

    Get Module Information

    0x00000001

    0x00000000

     

     

     

     

     

     

     

     

    Get Spectrometer Information

    0x00000002

    0x00000000

     

     

     

     

     

     

     

     

    Get Module Property

    0x00000003

    0x00000000

     

     

     

     

     

     

     

     

    Get Data Position Property

    0x00000004

    0x00000000

     

     

     

     

     

     

     

     

    Get Data Count Property

    0x00000005

    0x00000000

     

     

     

     

     

     

     

     

    Get Data Transmit Property

    0x00000006

    0x00000000

     

     

     

     

     

     

     

     

    Get Data Trigger Offset Property

    0x00000007

    0x00000000

     

     

     

     

     

     

     

     

    Get Exposure Property

    0x00000008

    0x00000000

     

     

     

     

     

     

     

     

    Get Gain Property

    0x00000009

    0x00000000

     

     

     

     

     

     

     

     

    Get Ad Offset Property

    0x0000000A

    0x00000000

     

     

     

     

     

     

     

     

    Get Wavelength Property

    0x0000000C

    0x00000000

     

     

     

     

     

     

     

     

    Get Image Size

    0x0000000D

    0x00000000

     

     

     

     

     

     

     

     

    Get Capture Mode

    0x0000000F

    0x00000000

     

     

     

     

     

     

     

     

    Set Capture Mode

    0x00000010

    0x00000002

    Capture Mode
    (2Byte)

     

     

     

     

     

     

    Capture Mode
    0x0000 : Specified number of measurement mode
    0x0001 : Continuous measurement mode
    0x0002 : Trigger mode

    Get Data Position

    0x00000011

    0x00000000

     

     

     

     

     

     

     

     

    Set Data Position

    0x00000012

    0x00000004

    Data Position
    (4Byte)

     

     

     

     

     

     

     

    Get Data Count

    0x00000013

    0x00000000

     

     

     

     

     

     

     

     

    Set Data Count

    0x00000014

    0x00000004

    Data Count
    (4Byte)

     

     

     

     

     

     

     

    Get Data Transmit

    0x00000015

    0x00000000

     

     

     

     

     

     

     

     

    Set Data Transmit

    0x00000016

    0x00000004

    Data Transmit
    (4Byte)

     

     

     

     

     

     

     

    Get Data TriggerOffset

    0x00000017

    0x00000000

     

     

     

     

     

     

     

     

    Set Data TriggerOffset

    0x00000018

    0x00000004

    Trigger Offset
    (4Byte)

     

     

     

     

     

     

     

    Get Exposure Time

    0x00000019

    0x00000000

     

     

     

     

     

     

     

     

    Set Exposure Time

    0x0000001A

    0x00000008

    Exposure Time
    (8Byte)

     

     

     

     

     

     

     

    Get Exposure Cycle

    0x0000001B

    0x00000000

     

     

     

     

     

     

     

     

    Set Exposure Cycle

    0x0000001C

    0x00000008

    Exposure Cycle
    (8Byte)

     

     

     

     

     

     

     

    Get Trigger Mode

    0x0000001D

    0x00000000

     

     

     

     

     

     

     

     

    Set Trigger Mode

    0x0000001E

    0x00000004

    Trigger Mode
    (4Byte)

     

     

     

     

     

     

    Trigger Mode
    0x00000000 : Internal synchronous mode
    0x00000001 : software asynchronous mode
    0x00000002 : software synchronous mode
    0x00000003 : External asynchronous edge sense mode
    0x00000004 : External asynchronous level sense mode
    0x00000005 : External synchronous edge sense mode
    0x00000006 : External synchronous level sense mode
    0x00000007 : External synchronous pulse mode

    Get Trigger Polarity

    0x0000001F

    0x00000000

     

     

     

     

     

     

     

     

    Set Trigger Polarity

    0x00000020

    0x00000004

    Trigger Polarity
    (4Byte)

     

     

     

     

     

     

    Trigger Polarity
    0x00000001 : Falling edge or Low level
    0x00000003 : Rising edge or High level

    Get Trigger Output

    0x00000021

    0x00000000

     

     

     

     

     

     

     

     

    Set Trigger Output

    0x00000022

    0x00000004

    Trigger Output
    (4Byte)

     

     

     

     

     

     

    Trigger Output
    0x00000001 : OFF
    0x00000003 : ON

    Get Gain

    0x00000025

    0x00000004

    Gain Mode
    (4Byte)

     

     

     

     

     

     

    Gain Mode
    0x00000000 : Sensor gain mode
    0x00000001 : Circuit gain mode

    Set Gain

    0x00000026

    0x00000008

    Gain Mode
    (4Byte)

    Gain
    (4Byte)

     

     

     

     

     

    Gain Mode
    0x00000000 : Sensor gain mode
    0x00000001 : Circuit gain mode

    Gain
    0x00000000 : Low gain
    0x00000001 : High gain

    Get Ad Offset

    0x00000027

    0x00000000

     

     

     

     

     

     

     

     

    Set Ad OffSet

    0x00000028

    0x00000004

    Ad Offset
    (4Byte)

     

     

     

     

     

     

     

    Get Calibration Coefficient

    0x00000029

    0x00000004

    Index
    (4Byte)

     

     

     

     

     

     

    Index
    0x00000000 : Wavelength calibration coefficient
    0x00000001 : Sensitivity calibration coefficient

    Set Calibration Coefficient

    0x0000003B

    0x00000034

    Index
    (4Byte)

    Coefficient A0
    (8Byte)

    Coefficient B1
    (8Byte)

    Coefficient B2
    (8Byte)

    Coefficient B3
    (8Byte)

    Coefficient B4
    (8Byte)

    Coefficient B5
    (8Byte)

    Index
    0x00000000 : Wavelength calibration coefficient
    0x00000001 : Sensitivity calibration coefficient

    Get Cooling Temperature

    0x0000002A

    0x00000000

     

     

     

     

     

     

     

     

    Capture Start

    0x0000002F

    0x00000002

    Capture Mode
    (2Byte)

     

     

     

     

     

     

     

    Fire Trigger

    0x00000030

    0x00000000

     

     

     

     

     

     

     

     

    Capture Stop

    0x00000031

    0x00000000

     

     

     

     

     

     

     

     

    Read Eeprom User Area

    0x00000033

    0x00000004

    Address
    (2Byte)

    Length
    (2Byte)

     

     

     

     

     

     

    Write Eeprom User Area

    0x00000034

    0x00000008

    Address
    (2Byte)

    Length
    (2Byte)

    Data
    (2Byte)

     

     

     

     

    The address that can be specified is 0-511.
    Please specify 384 henceforth, when you use it.
    Spectroscope may stop operating correctly.

    Address will be specified in word.

    Get Status Request

    0x0000003D

    0x00000000

     

     

     

     

     

     

     

    Cooled only

    Get Defective Pixel

    0x0000003E

    0x00000000

     

     

     

     

     

     

     

     

    6.4 驱动层程序示例

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/usb.h>
    #include <linux/sched.h>
    #include <linux/slab.h>
    #include <linux/miscdevice.h>
    #include <linux/fs.h>
    #include <linux/io.h>
    #include "spectrometer_cmd_list.h"
    #include <asm/uaccess.h>
    #include <linux/bcd.h>
    #include <linux/uaccess.h>
    
    /*容纳所有设备特定内容的结构 */
    struct usb_spectrometer
    {
        struct usb_device   *udev;          /* 此设备的USB设备 */
        struct usb_interface    *interface; /*该设备的接口*/
        struct usb_anchor   submitted;      /* 万一需要撤回提交*/
        struct urb      *bulk_in_urb;       /*用urb读取数据*/
        unsigned char           *bulk_in_buffer;    /* 接收数据的缓冲区 */
        size_t          bulk_in_size;       /*接收缓冲区的大小 */
        size_t          bulk_in_filled;     /* 缓冲区中的字节数 */
        size_t          bulk_in_copied;     /* 已经复制到用户空间 */
        __u8            bulk_in_endpointAddr;   /* 端点中的批量地址 */
        __u8            bulk_out_endpointAddr;  /*批量输出端点的地址 */
        int             errors;         /* 最后一个请求被取消 */
        bool            ongoing_read;       /* 读正在进行*/
        bool            processed_urb;      /* 表示尚未处理 */
    };
    static struct usb_spectrometer *dev;
        
    /*
    [   25.845000] usb 1-2.2: new high-speed USB device number 6 using s5p-ehci
    [   25.950000] usb 1-2.2: New USB device found, idVendor=0661, idProduct=294b
    [   25.950000] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [   25.950000] usb 1-2.2: Product: EZ-USB
    [   25.950000] usb 1-2.2: Manufacturer: Cypress
    
    [  726.360000] usb 1-2.2: new high-speed USB device number 7 using s5p-ehci
    [  726.475000] usb 1-2.2: config 1 interface 0 altsetting 0 has 7 endpoint descriptors, different from the interface descriptor's value: 5
    [  726.480000] usb 1-2.2: New USB device found, idVendor=148f, idProduct=5370
    [  726.480000] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [  726.480000] usb 1-2.2: Product: 802.11 n WLAN
    [  726.480000] usb 1-2.2: Manufacturer: Ralink
    [  726.485000] usb 1-2.2: SerialNumber: 1.0
    */
    
    //定义USB的IDTAB
    static const struct usb_device_id tiny4412_usb_id[] = 
    {
        {USB_DEVICE(0x148f,0x5370)},
        {USB_DEVICE(0x0661,0x294b)},
        {}
    };
    
    /*
    MODULE_DEVICE_TABLE 有两个功能。
    一是:将设备加入到外设队列中,
    二是告诉程序阅读者该设备是热插拔设备或是说该设备支持热插拔功能。
    该宏定义在<linux/module.h>下
    这个宏有两个参数,第一个参数设备名,第二个参数该设备加入到模块中时对应产生的设备搜索符号,这个宏生成了一个名为__mod_pci_device_table
    局部变量,这个变量指向第二个参数
    */
    
    MODULE_DEVICE_TABLE (usb,tiny4412_usb_id);
    
    static int usb_dev_open(struct inode *inode, struct file *file)
    {
        printk("open:USB光谱仪设备.\n");
        printk("命令结构大小_drv:%lu\n",sizeof(struct DEV_CMD));
        return 0;
    }
    
    //读写命令
    static long usb_dev_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long argv)
    {
        //转换指针类型
        struct DEV_CMD *buff=(struct DEV_CMD *)argv;
        struct DEV_CMD dev_cmd;
        int ret=0;
        int actual_length=0;
        int err=0;
        printk("读写:USB光谱仪设备.\n");
    
        //命令符合要求
        if(IOCTL_CMD_RW==cmd)
        {
            //拷贝应用层的数据到本地
            if(copy_from_user(&dev_cmd,buff,sizeof(struct DEV_CMD)))
            {
                printk("write: copy_from_user error...\n");
                return -2;
            }
    
            /*同步提交写请求*/
            ret=usb_bulk_msg(dev->udev,
                        usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
                        dev_cmd.buff,dev_cmd.write_len,&actual_length,HZ*20);
            if(ret<0)
            {
                printk("同步提交写请求错误.错误值:%d\n",ret);
                return -3;
            }
            dev_cmd.write_len=actual_length; //成功写入的长度
            printk("write:len=%d\n",actual_length);
    
            //读取的长度大于0.就表示需要读取数据
            if(dev_cmd.read_len>0)
            {
                    //buff清0
                memset(dev_cmd.buff,0,sizeof(dev_cmd.buff));
                /*同步提交读请求*/
                ret = usb_bulk_msg(dev->udev, 
                                usb_rcvbulkpipe(dev->udev,dev->bulk_in_endpointAddr),
                                dev_cmd.buff,dev_cmd.read_len, &actual_length,HZ*20);
                if(ret<0)
                {
                    printk("同步提交读请求错误.错误值:%d\n",ret);
                    return -4;
                }
                //实际读取的长度
                dev_cmd.read_len=actual_length;
                printk("read:len=%d\n",actual_length);
                
                //将数据拷贝到应用层
                err=copy_to_user(buff,&dev_cmd,sizeof(struct DEV_CMD));
                if(err)
                {
                    printk("read:read cmd error!!!\n");
                    return err;
                }
            }
        }
        return 0;
    }
    
    static int usb_dev_release(struct inode *inode, struct file *file)
    {
        printk("release:USB光谱仪设备.\n");
        return 0;
    }
    
    static const struct file_operations usb_dev_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl=usb_dev_unlocked_ioctl,
        .open  = usb_dev_open,
        .release = usb_dev_release,
    };
    
    static struct miscdevice usb_dev_miscdev = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = "spectrometer_usb_drv",
        .fops = &usb_dev_fops,
    };
    
    //USB设备信息与驱动端匹配成功的时候调用。
    static int test_probe(struct usb_interface *interface,const struct usb_device_id *id)  //资源探索函数
    {
        int i=0;
        size_t buffer_size;
        struct usb_device *dev_info;
        unsigned char *bcdUSB_p;
        struct usb_host_interface *host_inter;
        struct usb_endpoint_descriptor *endpoint;
        int size;
        
        dev=kzalloc(sizeof(*dev), GFP_KERNEL);
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
    
        printk("识别到USB光谱仪设备,正在进行设备初始化.\n");
    
        /*通过接口获取设备信息*/
        dev_info = interface_to_usbdev(interface);
        bcdUSB_p=(unsigned char *)&dev_info->descriptor.bcdUSB;
        printk("设备与描述表兼容的USB设备说明版本号=0x%x%x\n", bcd2bin(*bcdUSB_p),bcd2bin(*(bcdUSB_p+1)));   //从USB设备描述符中获取USB版本
        printk("厂商ID = %#x\n",dev_info->descriptor.idVendor); //从USB设备描述符中获取厂商ID
        printk("设备ID = %#x\n",dev_info->descriptor.idProduct);//从USB设备描述符中获取产品ID
    
        printk("设备类 = %#x\n",interface->cur_altsetting->desc.bInterfaceClass);   //从USB设备获取设备类
        printk("设备从类 = %#x\n",interface->cur_altsetting->desc.bInterfaceSubClass);//从USB设备获取设备从类
        printk("设备协议 = %#x\n",interface->cur_altsetting->desc.bInterfaceProtocol);//从USB设备获取设备协议
        printk("驱动名称:%s\n",interface->dev.driver->name);
        printk("总线名称:%s\n",interface->dev.driver->bus->name);
        
        /*获取当前接口设置*/
        host_inter=interface->cur_altsetting;
        /*获取端点描述符*/
        for(i=0;i<host_inter->desc.bNumEndpoints;i++) 
        {
            endpoint = &host_inter->endpoint[i].desc;
            printk("端点号[%d]:%d\n",i,endpoint->bEndpointAddress&0xFF);
            if(endpoint->bEndpointAddress&1<<7)
            {
                printk("端点[%d] 输入端点(设备到主机)\n",i);
            }
            else
            {
                printk("端点[%d] 输出端点(主机到设备)\n",i);
            }
            switch(endpoint->bmAttributes)
            {
                case 0:printk("端点[%d] 设备支持控制传输.\n",i);break;
                case 1:printk("端点[%d] 设备支持同步传输.\n",i);break;
                case 2:printk("端点[%d] 设备支持批量传输.\n",i);break;
                case 3:printk("端点[%d] 设备支持中断传输.\n",i);break;
            }
            /*从端点描述符中获取传输的数据大小 */
            size = usb_endpoint_maxp(endpoint);
            printk("端点[%d] 传输的数据大小:%d\n",i,size);
    
            //输入端点
            if(!dev->bulk_in_endpointAddr &&usb_endpoint_is_bulk_in(endpoint)) 
            {
                /* 批量输入端点 */
                buffer_size = usb_endpoint_maxp(endpoint);
                dev->bulk_in_size = buffer_size;
                dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
                printk("probe:dev->bulk_in_size=%lu\n",dev->bulk_in_size);
                printk("probe:dev->bulk_in_endpointAddr=%d\n",dev->bulk_in_endpointAddr);
                dev->bulk_in_buffer = kmalloc(buffer_size,GFP_KERNEL);
                if(!dev->bulk_in_buffer)
                {
                    printk("无法分配bulk_in_buffer");
                    break;
                }
                dev->bulk_in_urb = usb_alloc_urb(0,GFP_KERNEL);
                if(!dev->bulk_in_urb)
                {
                    printk("无法分配bulk_in_urb");
                    break;
                }
            }
            
            //输出端点
            if(!dev->bulk_out_endpointAddr &&usb_endpoint_is_bulk_out(endpoint))
            {
                /*  批量输出端点 */
                dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
                printk("probe:dev->bulk_out_endpointAddr=%d\n",dev->bulk_out_endpointAddr);
            }
        }
        
        /*向内核注册一个杂项字符设备*/
        if(misc_register(&usb_dev_miscdev)==0)
        {
            printk("USB光谱仪设备节点注册成功:/dev/%s ,主设备号:10,次设备号:%d\n",
                usb_dev_miscdev.name,usb_dev_miscdev.minor);    
        }
        return 0;
    }
    
    //USB断开的时候调用
    static void test_disconnect(struct usb_interface *intf)
    {
        printk("USB光谱仪设备已断开.\n"); 
        /*从内核注销一个杂项字符设备*/
        misc_deregister(&usb_dev_miscdev);
    }
    
    //定义USB驱动结构体 
    static struct usb_driver tiny4412_usb_driver = {
        .name = "spectrometer_usb_drv",
        .id_table = tiny4412_usb_id,
        .probe = test_probe,
        .disconnect = test_disconnect
    };
    
    static int __init tiny4412_usb_init(void)
    {
        printk("正在安装USB光谱仪驱动.\n"); 
        //注册USB设备驱动
        usb_register(&tiny4412_usb_driver);
        return 0;
    }
    
    static void __exit tiny4412_usb_exit(void)
    {
         //注销USB设备驱动
         usb_deregister(&tiny4412_usb_driver);
         printk("USB光谱仪驱动卸载成功.\n"); 
    }
    
    module_init(tiny4412_usb_init);
    module_exit(tiny4412_usb_exit);
    MODULE_AUTHOR("xiaolong");
    MODULE_LICENSE("GPL");
    

    展开全文
  • 虽然知道问题出在驱动上,用各种软件检测驱动也都是正常,一般USB驱动都是在系统自带的。 计算机 –> 右键 –> 管理 –> 设备管理器,发现USB Optical Mouse(有线鼠标)驱动、USB Reciver(无线鼠标接收器)驱动异常...
    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接: https://blog.csdn.net/Form_/article/details/79456646

    系统: Win 10(x64)
    把手机通过数据线插在电脑USB口上读取数据正常(说明USB口没有坏)


    问题

    昨天电脑还好好的,今天起来鼠标就没用了,不管是有线还是无线鼠标都用不了。
    鼠标插电脑上,不停的有USB连接和断开的声音重复。


    检查

    虽然知道问题出在驱动上,用各种软件检测驱动也都是正常,一般USB驱动都是在系统自带的。
    计算机 –> 右键 –> 管理 –> 设备管理器,发现USB Optical Mouse(有线鼠标)驱动、USB Reciver(无线鼠标接收器)驱动异常,一个黄色的感叹号。


    解决方案

    操作步骤如下:
    双击异常驱动 –> 更新驱动程序 –> 浏览我的计算机以查找驱动程序软件 –> 在以下位置搜索驱动程序C:\Windows\WinSxS –> 下一步 –> 关闭(驱动完成安装)

    • 浏览我的计算机以查找驱动程序软件
      浏览我的计算机以查找驱动程序软件

    • 在以下位置搜索驱动程序
      在以下位置搜索驱动程序

    • 正在C:\Windows\WinSxS中搜索驱动程序
      3

    • 完成
      4

    USB鼠标可以正常使用。

    展开全文
  • 小编提供的这款为64位安装系统,用户下载后解压打开驱动程序,插入网卡后,可自动识别设备!欢迎下载使用。驱动软件介绍RD9700USB2.0ToFastEthernetAdapterrd9700usb网卡驱动程序支持硬件ID:USB\VID_0FE6,欢迎下载...
  • usb转串口万能驱动.rar

    2019-07-14 21:51:16
    USB转通用串口线及其驱动程式使得的USB需要改变固件就可以直接和周边设备连接,只需要做最小的修改就使得串口和周边设备之间可以通过的USB埠通讯。 UT-810 USB 1.1 TO RS232 Cable驱动程序USB转串口 ...
  • 在进行usb设备通信时候,通常需要对usb设备授权,会弹出系统申请权限框,这样显得特别麻烦,如下图: 今天研究了一下,解决了这个问题 1.AndroidManifest.xml中的配置 <activity android:name=".MainActivity"&...
  • xilinx 自动安装USB 驱动

    万次阅读 2014-07-24 14:52:05
    大部分情况下可以自动安装驱动,但有的可以就
  • 设备驱动程序是操作系统内核和机器硬件之间的接口,由一组函数和一些私有数据组成,是应用程序和硬件设备之间的桥梁。在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作...
  • usb设备:usb-serialusb驱动:ftdi_sio 1.原有内容luther@gliethttp:~$ ls /sys/bus/usb-serial/drivers/generic2.插入usb-serail之后内容luther@gliethttp:~$ ls /sys/bus/usb-serial/drivers/ftdi_sio gene
  • 找了N久找到的笔记本电脑 插入鼠标禁用触摸板的驱动,真的
  • win7每次一个新的鼠标或者键盘时,都提示找驱动程序,非得去设备管理器下手动去c:/Windows/winsys手动更新驱动,而且有时候驱动更新好了键盘或者鼠标还是用了,有时候又能用,已确认不是键盘或者鼠标或者usb...
  • 插上USB鼠标自动禁用触摸板,拔掉鼠标触摸板恢复。注意:需要先装触摸板驱动
  • 这才是真正的MPLAB ICD2/2.5 USB 在Win7系统安装驱动的方法。在电脑安装好IDE之后,IDE的安装目录里会自动生成一个存放ICD驱动程序的文件夹,无需自己下载驱动安装程序。 在Win7系统,第一次插入ICD后,系统...
  • 1、首先到网上下载一个Synaptics触摸板驱动并安装,安装完后重启计算机;(已安装Synaptics触摸板驱动忽略此步骤) 2、然后WIN+R,打开运行对话框,输入“regedit”,回车打开注册表→依次展开HKEY_CURRENT_USER/...
  • USB转232驱动

    2015-02-28 10:02:25
    必须通过CONSOLE口进行 但我的本本没有COM口 怎么办呢 没关系 来个USB转串口RS232 插上之后来配置吧 问题又出现啦 提示:找到COM口 哎 这又是怎么回事呢 原来是没有安装USB TO RS232的驱动 赶紧下一个装吧 ...
  • USB

    千次阅读 2018-10-12 11:13:21
    学习USB拔之前,先学习一些USB的硬件知识: 一、USB基础概念 1、硬件知识(USB插座和插头) &nbsp; &nbsp; &nbsp; &nbsp;在最初的标准里,USB接头有4条线:电源,D-,D+,地线。我们暂且把这样的...
  • 本人电脑USB接口除了之前过的USB设备可以用,其他的USB设备都不好使!难受,想当的难受!由于也不是很常用这些设备就没太在意,最近有时间,外加一个计算机专业的学生连这个问题都解决了,实在有点对不起自己了...
  • 此贴一定能解决从物理机到...1、关闭虚拟机系统 ,然后打开Windows系统里的运行 输入 services.msc,查看Windows服务2、将所有关于Vmware的服务设置启动,自动(当然只为了解决USB的问题话,只设VM ware USB Arbitrat...
  • USB-to-Serial-串口驱动

    热门讨论 2013-08-06 16:14:45
    安装Y340 USB转串口驱动,里面有两个文件,先试HL-340,安装后插入usb-toserial线,自动安装应该可以正常运行,如果不行,再试另一个文件,同样的安装方法。。。行不行?多试几次就可以应该可以。。。。。 ========...
  • 西门子usb-ppi驱动程序

    2019-08-08 01:26:12
    本款西门子usb ppi驱动程序是西门子200PLC通讯线USB转PPI驱动程序,本站提供该驱动程序的软件下载,看到很多朋友都找到,所以给大家分享一下。需要的朋友们可以前来下载使用。 使用方法 下载解压,在文件夹中...
  • USB驱动下载失败的解决

    千次阅读 2018-11-14 20:58:39
    Xilinx-ZYNQ7000系列-学习笔记(1):对USB驱动下载失败的解决 背景 在进行某个项目或是某个工程时,我们在编辑完代码或者是文件之后,需要将其下载到板卡或者一些其他设备中使其工作,这就需要一根下载线,又名...
  • Xilinx Platform Cable USB II Firmware Loader,如下两图所示,这都表明下载器驱动没有正确安装。 此时在ISE iMPACT中 点击Initialize Chain,会有如下报错信息: ISE iMPACT报错如下: … Connecting to cable ...
  • USB-232线驱动程序

    2010-10-01 18:12:02
    直接手动安装本文件夹中的HL341中的驱动即可,如果更换另外的USB口,自动搜索安装即可。 安装成功的标志是:在电脑设备管理器中可以看到虚拟的com口,端口号为com3或着com4 注意,此驱动必须要放在桌面安装!!!!!
  • USB GPS驱动

    热门讨论 2009-05-07 16:20:12
    将文件解压后 直接插上GPS设备,然后安装的时候选择解压后的文件夹进行安装

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,550
精华内容 10,220
关键字:

usb插上不自动驱动