阅读:4155回复:18
请教与USB接口通信的问题,能进来帮我看一下吗
使用windows server 2003 ddk 模仿别人的程序自己做了一个打开USB设备的程序。但有问题:
DEFINE_GUID(USB_DRIVER_GUID, 0x0748816c, 0x9b2d, 0x4796, 0x82, 0x4a, 0xc4, 0xa0, 0xdb, 0x48, 0x22, 0xfb); HANDLE OpenOneDevice(HDEVINFO hDvcInfo, PSP_INTERFACE_DEVICE_DATA DvcInfoData, char *sDevNameBuf) { HANDLE hOut = INVALID_HANDLE_VALUE; ULONG iReqLen = 0; //这条语句的执行结果为false //iReqLen=83 //这个函数是干什么的?谁能帮我解释一下?或告诉我在哪能查到 SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, NULL, 0, &iReqLen, NULL); ULONG iDevDataLen = iReqLen; //sizeof(SP_FNCLASS_DEVICE_DATA) + 512; PSP_INTERFACE_DEVICE_DETAIL_DATA pDevData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(iDevDataLen); if(pDevData == NULL) return INVALID_HANDLE_VALUE; //pDevData->cbSize=8 pDevData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); //这句返回为“假”,美景到判断里面 if(SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, pDevData, iDevDataLen, &iReqLen, NULL)) { strcpy(sDevNameBuf, pDevData->DevicePath); hOut = CreateFile(pDevData->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); } free(pDevData); return hOut; } //----------------------------------------------------------HANDLE OpenUsbDevice(const GUID *pGuid, char *sDevNameBuf) { HANDLE hOut = INVALID_HANDLE_VALUE; //查了Setupapi.h,HDEVINFO是一个指针变量,SetupDiGetClassDevs()返回指向一个设备信息集的句柄 //但这个信息集究竟是什么样的呀?能帮我解释一下吗? HDEVINFO hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); SP_INTERFACE_DEVICE_DATA deviceInfoData; deviceInfoData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA); ULONG nGuessCount = MAXLONG; for(ULONG iDevIndex = 0;iDevIndex < nGuessCount;iDevIndex ++) { //这句返回为“真”。iDevIndex=0; //deviceInfoData={cbsize=28, interfaceclassGUID={122192236UL (0x0748816C), 39725U (0x9B2D), 18326U (0x4796), "xFFFFFF82+0x4A+xFFFFFFC4+xFFFFFFA0+xFFFFFFDB+0x48+0x22+0xFFFFFFFB"}, flags=1, reserved=1595112UL} //我查不到deviceInfoData->flags及reserved的帮助,谁能帮我解释一下吗? if(SetupDiEnumDeviceInterfaces(hDevInfo, 0, pGuid, iDevIndex, &deviceInfoData)) { hOut = OpenOneDevice(hDevInfo, &deviceInfoData, sDevNameBuf); if(hOut != INVALID_HANDLE_VALUE) break; } else if(GetLastError() == ERROR_NO_MORE_ITEMS) //No more items { break; } } SetupDiDestroyDeviceInfoList(hDevInfo); return hOut; } //---------------------------------------------------------- HANDLE OpenMyDevice() { char DeviceName[MAXPATH] = ""; return OpenUsbDevice(&USB_DRIVER_GUID, DeviceName); } //---------------------------------------------------------- 我用的GUID是DS开发的驱动中DeviceInterface.h中的GUID,在注册表中也找到了这个设备。使用DS自动生成的Test_Usb.exe程序可以打开设备,为什么我上面的程序却不行呢? [编辑 - 7/19/04 by metalwing] |
|
|
沙发#
发布于:2004-07-19 21:24
这一段是 Retrieve the information from Plug and Play. 你可以用getlasterror()察看错误信息,需要硬件支持 |
|
|
板凳#
发布于:2004-07-20 15:01
谢谢你的回答,分已给了。另外还想请教一下:
我将那句改为: SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, pDevData, iDevDataLen, &iReqLen, NULL); int my_error = GetLastError(); int len = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), //MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); 执行结果为: my_error = 1784 len = 34 一次:lpMsgBuf={0x0, 0x53, 0x18} 二次:lpMsgBuf={0x18, 0x52, 0x18} 三次:lpMsgBuf={0xB0, 0x53, 0x18} 1。不知什么意思。能给解释一下吗? 2。你说的需要硬件支持是指什么?我用USB Monitor看,并为看见相应坚范颂了什么请求呀。 |
|
|
地板#
发布于:2004-07-20 17:43
errcode=1784
表示: 所提供的用户缓冲区对所申请的操作无效。 |
|
|
地下室#
发布于:2004-07-20 19:57
谢谢你的回答。
那该怎么办呢?我用DS自动生成的测试程序为什么可以呀? 你说的“所提供的用户缓存区”是指pDevData的长度吗? 我试一下先 errcode=1784 |
|
|
5楼#
发布于:2004-07-20 20:24
SetupDiGetInterfaceDeviceDetail()中的几个参数是什么意思呀?我把pDevData的长度设到520=512+8
PSP_INTERFACE_DEVICE_DETAIL_DATA pDevData = PSP_INTERFACE_DEVICE_DETAIL_DATA(new char[520]); 可还是不行。我对比了一下我这个程序和Driver Studio自动生成的测试程序(包括他的CDeviceInterfaceClass及CDeviceInterface),基本上差不多呀?只不过我这个程序是在BCB下编译的,DS的程序是在VC下编译的。明天准备把DS的程序展开试一下。 |
|
|
6楼#
发布于:2004-07-21 11:09
刚试完了。在DS+VC环境中,展开CDeviceInterfaceClass和CDeviceInterface(在测试程序中的OpenByInterface函数中),编译通过执行正常。
将整个函数移植到BCB中,编译通过,但执行到 SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, pDevData, iDevDataLen, &iReqLen, NULL); DWORD Error = GetLastError(); 还是Error=1784.不能打开设备。 谁能告诉我为什么呀? |
|
|
7楼#
发布于:2004-07-21 21:56
刚试完了。在DS+VC环境中,展开CDeviceInterfaceClass和CDeviceInterface(在测试程序中的OpenByInterface函数中),编译通过执行正常。 提供的指针有问题,不一定非得是NULL 空间不够或大小部对也可能有问题 |
|
|
8楼#
发布于:2004-07-22 08:11
谢谢。
但为什么在DS+VC编译成的程序就没问题呢?(是相同的语句呀) 另外,snowStart告诉我了 errcode=1784 表示: 所提供的用户缓冲区对所申请的操作无效。 那究竟是那个指针(缓冲区)有问题呢?我估计是pDevData,但pDevData的申请,我原来是: PSP_INTERFACE_DEVICE_DETAIL_DATA pDevData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(iDevDataLen); pDevData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); 也试过 PSP_INTERFACE_DEVICE_DETAIL_DATA pDevData = PSP_INTERFACE_DEVICE_DETAIL_DATA (new char[iDevDataLen]); pDevData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); 都有问题。不知为什么。(iDevDataLen跟踪发现值为83) 是BCB编译器的问题吗? [quote]刚试完了。在DS+VC环境中,展开CDeviceInterfaceClass和CDeviceInterface(在测试程序中的OpenByInterface函数中),编译通过执行正常。 提供的指针有问题,不一定非得是NULL 空间不够或大小部对也可能有问题 [/quote] |
|
|
9楼#
发布于:2004-07-24 17:34
粗略的看了一下,看不出什么问题。随便说两句,希望能给你帮助:
在函数OpenOneDevice中SetupDiGetInterfaceDeviceDetail是需要执行两遍的,你的程序里也是如此。第一次调用你用getlasterror会发现0x7a的错误,别担心,这是正常的,iReqLen参数会包含正确的deviceInterfaceDetailDataSize数值。第二次调用的时候传递此传回值,函数就会执行成功。你可以在第二次调用后用getlasterror看返回值是不是0。这个函数就是区的设备的路径! 然后就可以用creatfile创建句柄了。 ;) |
|
10楼#
发布于:2004-07-25 09:18
谢谢你的帮助。我也是这么考虑的。现在的问题是:前面都跟你说的一样(程序设计、执行效果(iReqLen=83)),但第二次调用SetupDiGetInterfaceDeviceDetail还是不成功(getLastError()=1784所提供的用户缓冲区对所申请的操作无效。并且,不成功仅是在BCB环境中发生,而在VC+DS中不会发生),我估计是pDevData的长度有问题。但究竟是怎么回事,我还不太清楚。分已经给别人了,若能解决,我再开贴给分。谢谢。
粗略的看了一下,看不出什么问题。随便说两句,希望能给你帮助: [编辑 - 7/25/04 by metalwing] |
|
|
11楼#
发布于:2004-07-26 00:23
会不会是系统不支持对设备的访问?
比如说win2k下就不能访问鼠标键盘类的hid设备,但是我换了joystick却可以访问,也是hid的。 分不分的无所谓的,关键是讨论问题嘛,呵呵 |
|
12楼#
发布于:2004-07-26 09:37
谢谢帮助。
系统应该是支持的,我使用两种环境(VC+DDK+DS、BCB,程序一样)编译,两种环境都能编译通过,但只有第一种环境编译的程序执行正确,而使用BCB环境编译的程序执行到第二个SetupDiGetInterfaceDeviceDetail()不成功,用GetLastError(),发现返回错误代码1784。不知为何? 另外,我现在使用另一种方法打开USB设备,倒是能成功。但不知会否有什么问题,请指教。 利用注册表,在HKEY_LOCAL_MACHINE中的SYSTEMCONTROLSET001ControlDeviceClass中查找设备的GUID,打开后,获取键名: RegEnumKey(m_hKey, 0, cKeyName, 255);//cKeyName为char[255] 然后修正cKeyName: cKeyName[0]=''; cKeyName[1]=''; cKeyName[3]=''; 这时,cKeyName就相当于使用传统方法获得的Detail->Devicepath了。应用程序可以使用它来打开Usb设备。 这是我调试程序的时候无意间发现的。也估计到会有问题,因传统方法打不开设备,就先用这个方法。谁能帮我说明一下,这个方法的原因。也说一下这个方法的漏洞。谢谢。 [编辑 - 7/26/04 by metalwing] [编辑 - 7/26/04 by metalwing] |
|
|
13楼#
发布于:2004-07-28 20:25
SetupDi... 是winapi函数你可以在msdn中找到他们,错误代码你可以通过vc tools中的error lookup查到。你可以试一下将pGuid改为
(LPGUID)&pGuid。 |
|
14楼#
发布于:2004-08-01 19:25
非常感谢你的回答,你告诉我的error lookup工具非常有用。
我把pGuid改成(LPGUID)&pGuid了,还是不成。我个人觉得这跟GUID好像没有太大关系。SetupDiGetClassDevs、SetupDiEnumDeviceInterfaces都返回了值(不知道返回值对不对怎么确认呢?)。就是在SetupDiGetInterfaceDeviceDetail那里死活过不去。郁闷中。 我现在已经用另一种办法,通过注册表来获得DevicePath了。 SetupDi... 是winapi函数你可以在msdn中找到他们,错误代码你可以通过vc tools中的error lookup查到。你可以试一下将pGuid改为 |
|
|
15楼#
发布于:2004-08-03 08:18
是GUIDD的事,查查我以前的帖子。
|
|
16楼#
发布于:2004-08-03 10:04
谢谢你的帮助,但我认为应该不是GUID的问题,原因有两点:
1。 我使用该函数在VC+DDK+DS没有问题,可创建设备句柄。只是在BCB+DDK HEADER 的情况下SetDiGetDeviceInterfaceDetail(最后的那个)不正确(第一个也不正确不过是返回了0x7a)。 2。我对可正确执行的函数在争取执行的情况下跟踪,发现DevicePath为\\?\\Usb\....{ GUID },中的GUID就是我使用的GUID(函数中的使用、deviceinterface.h中的定义、注册表中的都是)。 是GUIDD的事,查查我以前的帖子。 |
|
|
17楼#
发布于:2004-09-23 09:21
不知道解决没有,小弟也碰到了同样的问题
|
|
18楼#
发布于:2005-06-22 10:52
我也遇到同样的问题了,我也是直接在注册表里找到符号连接,然后直接打开通讯端口的,不知道楼主有没有解决,能QQ上交流一下:13488339
|
|