Chinaunix首页 | 论坛 | 博客
  • 博客访问: 963612
  • 博文数量: 173
  • 博客积分: 3436
  • 博客等级: 中校
  • 技术积分: 1886
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-07 09:29
文章分类

全部博文(173)

文章存档

2016年(6)

2015年(10)

2014年(14)

2013年(8)

2012年(36)

2011年(63)

2010年(19)

2009年(17)

分类: WINDOWS

2011-09-12 20:06:54

在做一个USB设备驱动开发过程中,遇到一个问题:

U盘+PC 如果正在读写U盘时,将U盘拔出,是不影响系统稳定的。顶多是读写文件没有完成。
但我自己做的一个USB设备驱动,如果有数据通信的时候,将USB设备拔出来,结果造成PC蓝屏。在驱动中,如何修改,才可以实现这样的效果?
之后:详细的测试了一番,蓝屏与驱动无关。如果正在读写USB设备时,忽然将设备拔出。在驱动层的函数超时机制,也可以返回正确的操作码。
但是遇到另外一个问题: 我改写的一个USB 设备驱动。在某些windows系统中,关机时刻会导致蓝屏死机,并报出:Driver_Power_State_Failure。
后来找了一DDK下面的usb driver example。详细的研究了一番,发现那个驱动中,对pnp和电源管理做的工作才叫到位。文件目录在在wdm下面。

另外小记一下,自己在做这个事情上面走的弯路:
1. cpp文件中包含c库的头文件,一定要加extern限定一番,
    在vc下面编译源码时,如果引用了c库,在link那一栏中,也要加入适当的api.dll
2 通过inf文件进行驱动安装时,对于驱动中用到的全局变量,是可以通过inf文件对其进行赋初值的。

  1. HKLM,"System\Currentcontrolset\services\EncSdRead\Parameters","BulkUsbEnable",0x10001,1
这样加了一句话,要保证变量“BulkUsbEnable”在驱动中有声明,定义。否则驱动安装时,将会提示驱动损坏等错误。
3 USB bulk设备是可以注册Read, Write函数的。可以通过 create USB设备名称+端点名称的方式,打开一个文件。当然,通过这种方式打开一个文件时,也不是那么容易轻松了,通过若干函数实现它,DDK中也给了相应的例子。可以从中看到。

注意:
EP0 对应的"PIPE00", EP1 对应的"PIPE01"。像这样的语句,也就只能从源码中琢磨。
 
  1. HANDLE
  2. OpenOneDevice (
  3.     IN HDEVINFO HardwareDeviceInfo,
  4.     IN PSP_DEVICE_INTERFACE_DATA DeviceInfoData,
  5.         IN char *devName
  6.     )


  7. HANDLE
  8. OpenUsbDevice( LPGUID pGuid, char *outNameBuf)


  9. BOOL
  10. GetUsbDeviceFileName( LPGUID pGuid, char *outNameBuf)
对pnp和电源管理其实相当复杂,我还需要仔细的研究。
5 对于通过GUID打开设备的方式打开文件,这个时候,文件名称是怎样的?如果在一台设备中,连接了多个这样的器件,怎么支持这个打开多个设备?

在基于DDK的windows驱动中,

   DriverObject->MajorFunction[IRP_MJ_PNP] = TestPnpIrp;
TestPnpIrp函数负责处理PNP相关操作。这个函数中有如下语句:
  1. case IRP_MN_REMOVE_DEVICE:
  2.          ntStatus = PnpHandleRemoveDevice(fdo,Irp);
  3.           break;
负责设备拔出时的操作。

如果 PnpPrepareHardware 执行错误导致函数返回失败,我们就会在设备管理器中看到对应的设备那一栏中被标上一个黄色感叹号,表示此设备不可用。如 PnpPrepareHardware 返回错误,系统会调用 DeviceReleaseHardware 释放系统资源。

DeviceReleaseHardware 有点类似WDM框架下,IRP_MN_STOP_DEVICE所对应的子分发函数。

如果设备被异常拔除,回调函数 PnpSurpriseRemove 函数会被调用。值得注意的是,如果 PnpSurpriseRemove 被调用的话,紧接着 DeviceReleaseHardware 也一定会被调用。所以虽然我们也可以在 PnpSurpriseRemove 中释放系统资源,但如果把它们都统一到 DeviceReleaseHardware 中的话会更好。如果没有特殊需求,一般可忽略这个回调。同样,这个回调函数,对应于WDM框架下的IRP_MN_SURPRISE_REMOVE子分发ID所对应的处理函数。

PwrD0Entry PwrD0 Exit 两个回调比较重要。前者当设备电源状态进入D0时被调用,后者当设备电源状态离开D0时被调用。这两个回调函数合在一起,恰可对于WDM框架下 IRP_MN_SET_POWER子分发所对应的处理函数。联系到我们为CY001注册的两个电源策略:休眠和唤醒。我们就可以这样来说:当设备休眠的时 候,PwrD0Exit将被调用;当设备唤醒的时候, PwrD0Entry 将被调用。





阅读(1281) | 评论(0) | 转发(0) |
0

上一篇:做一个爱国的工程师

下一篇:vi + makefile

给主人留下些什么吧!~~