USB系列之一:列出你的USB设备
USB现在已经成为PC机必不可少的接口之一,几乎所有的设备都可以接在USB设备上,USB键盘、鼠标、打印机、摄像头,还有常用的U盘等等,从本篇文章开始,将集中篇幅介绍一下在DOS中使用USB设备的方法,具体会有几篇暂不好定,写到哪里算哪里吧,三、四篇总是少不了的。
本文介绍如何使用我以前文章中介绍过的知识在你的机器中找到USB设备,并判定设备类型。
一个USB系统一般由一个USB主机(HOST)、一个或多个USB集线器(HUB,但不是局域网里的集线器)和一个或多个USB设备节点(NODE)组成,一个系统中只有一个HOST,我们PC机里的USB实际上就是HOST和HUB两部分,你的PC机可能会有4个USB口,其实是一个HOST,一个HUB,HUB为你提供了4个端口,我们插在USB口上的器件,一般是USB设备,比如U盘,USB打印机等,当然我们也可以插一个集线器上去,使你的一个USB口扩展成多个。
实际上我们说在DOS下使用USB,就是对USB系统中的HOST进行编程管理,根据USB的规范,HOST将对连接在上面的HUB和USB设备进行管理,不用我们操心。HOST器件目前有三个规范,OHCI(Open Host Controller Interface)、UHCI(Universal Host Controller Interface)支持USB1.1,EHCI(Enhanced Host Controller Interface)支持USB2.0,以后的文章中,我们将侧重介绍OHCI和EHCI。
学习USB编程,读规范是少不了的,以下是一些应该阅读的规范下载:
OHCI规范:http://blog.hengch.com/specification/usb_ohci_r10a.pdf
EHCI规范:http://blog.hengch.com/specification/usb_ehci_r10.pdf
USB规范1.1:http://blog.hengch.com/specification/usb_spec11.pdf
USB规范2.0:http://blog.hengch.com/specification/usb_spec20.pdf
本文介绍的内容不需要学习规范。
下面进入正题,列出你的USB设备,USB的HOST是挂接在PCI总线上的,所以通过PCI设备的遍历就可以找到你的机器上的所有USB设备,在以前介绍PCI的配置空间时,曾经介绍过在配置空间中有一个占三个字节的分类代码字段(如果不知道,请参阅我以前的博文《遍历PCI设备》),在偏移为0x0B的字节叫基本分类代码,在偏移为0x0A的字节叫子分类代码,在偏移为0x09的字节叫编程接口代码,对于USB设备类说,基本分类代码为0x0C,子分类代码为0x03,对于符合不同规范的HOST器件而言,编程接口代码是不同的,UHCI的编程接口代码是0x00,OHCI的编程接口代码是0x10,EHCI的编程接口代码是0x20,我想了解这些就足够了。
下面列出USB设备的源程序。
#include <stdio.h>
#include <stdlib.h>
#include <dpmi.h>
typedef unsigned long UDWORD;
typedef short int WORD;
typedef unsigned short int UWORD;
typedef unsigned char UBYTE;
typedef union {
struct {
UDWORD edi;
UDWORD esi;
UDWORD ebp;
UDWORD res;
UDWORD ebx;
UDWORD edx;
UDWORD ecx;
UDWORD eax;
} d;
struct {
UWORD di, di_hi;
UWORD si, si_hi;
UWORD bp, bp_hi;
UWORD res, res_hi;
UWORD bx, bx_hi;
UWORD dx, dx_hi;
UWORD cx, cx_hi;
UWORD ax, ax_hi;
UWORD flags;
UWORD es;
UWORD ds;
UWORD fs;
UWORD gs;
UWORD ip;
UWORD cs;
UWORD sp;
UWORD ss;
} x;
struct {
UBYTE edi[];
UBYTE esi[];
UBYTE ebp[];
UBYTE res[];
UBYTE bl, bh, ebx_b2, ebx_b3;
UBYTE dl, dh, edx_b2, edx_b3;
UBYTE cl, ch, ecx_b2, ecx_b3;
UBYTE al, ah, eax_b2, eax_b3;
} h;
} X86_REGS;
/*************************************************************
* Excute soft interrupt in real mode
*************************************************************/
int x86_int(int int_num, X86_REGS *x86_reg) {
__dpmi_regs d_regs;
int return_value;
d_regs.d.edi = x86_reg->d.edi;
d_regs.d.esi = x86_reg->d.esi;
d_regs.d.ebp = x86_reg->d.ebp;
d_regs.d.res = x86_reg->d.res;
d_regs.d.ebx = x86_reg->d.ebx;
d_regs.d.ecx = x86_reg->d.ecx;
d_regs.d.edx = x86_reg->d.edx;
d_regs.d.eax = x86_reg->d.eax;
d_regs.x.flags = x86_reg->x.flags;
d_regs.x.es = x86_reg->x.es;
d_regs.x.ds = x86_reg->x.ds;
d_regs.x.fs = x86_reg->x.fs;
d_regs.x.gs = x86_reg->x.gs;
d_regs.x.ip = x86_reg->x.ip;
d_regs.x.cs = x86_reg->x.cs;
d_regs.x.sp = x86_reg->x.sp;
d_regs.x.ss = x86_reg->x.ss;
return_value = __dpmi_int(int_num, &d_regs);
x86_reg->d.edi = d_regs.d.edi;
x86_reg->d.esi = d_regs.d.esi;
x86_reg->d.ebp = d_regs.d.ebp;
x86_reg->d.res = d_regs.d.res;
x86_reg->d.ebx = d_regs.d.ebx;
x86_reg->d.ecx = d_regs.d.ecx;
x86_reg->d.edx = d_regs.d.edx;
x86_reg->d.eax = d_regs.d.eax;
x86_reg->x.flags = d_regs.x.flags;
x86_reg->x.es = d_regs.x.es;
x86_reg->x.ds = d_regs.x.ds;
x86_reg->x.fs = d_regs.x.fs;
x86_reg->x.gs = d_regs.x.gs;
x86_reg->x.ip = d_regs.x.ip;
x86_reg->x.cs = d_regs.x.cs;
x86_reg->x.sp = d_regs.x.sp;
x86_reg->x.ss = d_regs.x.ss;
return return_value;
}
/**********************************
* Read Configuration WORD if PCI
**********************************/
UWORD ReadConfigWORD(WORD pciAddr, int reg) {
X86_REGS inregs;
inregs.x.ax = 0xB109; // Read Configuration word
inregs.x.bx = pciAddr;
inregs.x.di = reg; // Register number
x86_int(0x1A, &inregs);
return inregs.d.ecx; // the value
}
// main program
int main(void) {
UWORD pciAddr;
UWORD subClass;
, ohciCount = , uhciCount = ;
; pciAddr < 0xffff; pciAddr++) {
) != 0xFFFF) {
// Read Class Code
if (ReadConfigWORD(pciAddr, 0x000a ) == 0x0c03) { // Usb Host Controller
// Read SubClass Code
subClass = ReadConfigWORD(pciAddr, 0x0008);
if ((subClass & 0xff00) == 0x2000) { // uhci
ehciCount++;
} else if ((subClass & 0xff00) == 0x1000) { // ohci
ohciCount++;
} else if ((subClass & 0xff00) == 0x00) { // uhci
uhciCount++;
}
}
}
}
printf("There are %d ohci device(s).\n", ohciCount);
printf("There are %d ehci device(s).\n", ehciCount);
printf("There are %d uhci device(s).\n", uhciCount);
}
程序非常简单,所有概念在以前的博文中均有过介绍,其中的子程序大多是以前程序范例中使用过的,所以在这里就不做更多的解释了,程序中,我们仅仅列出了设备的数量,但很显然,用这种方法,我们可以从配置空间里读出基地址等信息,这些在以后的文章中会用到。
USB系列之一:列出你的USB设备的更多相关文章
- USB系列之二:读取USB设备的描述符
在前面的文章中,我们已经给出了USB协议的链接地址,从这篇文章起,我们会涉及到许多USB 1.1的内容,我们的指导思想是先从熟悉USB 1.1协议入手,先使用现成的HCD和USBD,直接面对客户端驱动 ...
- USB系列之六:基于DOSUSB的简单U盘驱动程序
首先要说明的是,该驱动程序仅实现了部分块设备的功能,如果作为成品软件使用,会感觉性能比较差,而且有些功能(比如FORMAT)是不能完成的,发表此驱动程序的目的旨在说明USB的编程原理以及DOS下驱动程 ...
- USB系列之五:用汇编实现的一些USB功能
前面的USB系列一至四,实现了我们需要的一些USB功能,但都是用C语言的32位代码,之后我们插进了三篇关于DOS下设备驱动程序的文章,我们现在应该清楚,当我们要在DOS下写一个U盘的驱动时,最好使用汇 ...
- USB系列之九:基于ASPI的U盘驱动程序
USB系列之七和之八介绍了ASPI,并通过一些实例说明了基于ASPI的编程方法,本文使用前两篇文章介绍的知识以及以前介绍的有关DOS驱动程序下驱动程序的内容实际完成一个简单的基于ASPI的U盘驱动程序 ...
- USB系列之四:向U盘上写数据
在<USB系列之三>中,我们实现了一系列的SCSI命令,在这个系列中,我们要实现向U盘上写扇区的命令,所以,本文相对比较容易,更多地是给出一个实现的源程序. 在<USB系列之三> ...
- USB系列之八:透过ASPI执行SCSI命令
在<USB系列之七>里我们介绍了ASPI的规范,并对一系列ASPI的命令做了测试,其中的02号命令是执行SCSI命令,我们专门在这篇文章中介绍,在<USB系列七>中,我们已经了 ...
- USB系列之七:ASPI介绍及命令测试
在以前的一篇博文<关于构建DOS下编程平台的总结>中曾经介绍了一种在DOS下驱动U盘的方法,我们大致回顾一下.在config.sys中加入两个驱动程序,就可以驱动U盘:device = a ...
- USB系列之三:从你的U盘里读出更多的内容
U盘是我们最常使用的一种USB设备,本文继续使用DOSUSB做驱动,试图以读取扇区的方式读取你的U盘.本文可能涉及的协议可能会比较多. 一.了解你的U盘 首先我们用上一篇文章介绍的程序usbvi ...
- USB有时adb shell连不上设备
USB有时adb shell连不上设备 图1 下面汇总有效的解决方法 1. 重启 2. 卸载和重新装载驱动 图2 3.
随机推荐
- 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)——引用
在Django视图函数中经常出现类似于'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)的错误. ...
- PowerShell 管道和对象成员
2.1 管道 在各种现代的shell中,均支持管道的概念. 管道的最大特点就是: 前一个命令的输出作为后一个命令的输入.cmd.bash均支持管道的概念,这里我就不多说了,下面我们说说PS中 管道 ...
- HDU4532(组合DP)
题目:安排座位 解析:http://www.douban.com/note/269136472/ #include <iostream> #include <string.h> ...
- Java宝典(三)
--说说ArrayList,Vector,LinkedList的存储性能和特性. --ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,他们都 ...
- 【Python脚本】Eclipse IDE扩展PyDev插件安装
作为一名Python的初学者,其实不用太在意IDE了,我觉得开始的时候用用自带的 IDLE 也挺好的. 还有 DreamPie 也挺好的.都是一些轻量级的IDE. 因为我正好安装有Eclipse,平时 ...
- 《Two Days DIV + CSS》读书笔记——CSS控制页面方式
1.1 你必须知道的知识 (其中包括1.1.1 DIV + CSS的叫法解释:1.1.2 DIV + CSS 名字的误区:以及1.1.3 W3C简介.由于只是背景知识,跳过该章.) 1.2 你必须掌握 ...
- linux文件权限整理
网上对linux文件权限的已经很多,不过还是要自己整理一下,不然每次都要查资料. linux下所有东西都是文件,包括设备,所以这里的文件也包括文件夹. 先是查看文件权限:ls -lh xzc@xzc- ...
- mycat实例(1)
2016二月 22 置原 MyCat - 使用篇(1) 分类:数据库分库分表(Mycat等) (1126) (1) 数据库路由中间件MyCat - 使用篇(1) 基本概念 直接介绍概念太枯燥了,还是拿 ...
- PC-CSS-默认字体样式
字体样式:Arial:字体大小:12px;行高:1.5倍:
- windows 和linux 同步api对比
初始化临界区 (win) InitializeCriticalSection(RTL_CRITICAL_SECTION &rtl_critial_section) (linux) pthrea ...