各位高手留步!!!在hid类编程中遇见一个奇怪的问题!!!(100分)

  • 主题发起人 主题发起人 凌未风
  • 开始时间 开始时间

凌未风

Unregistered / Unconfirmed
GUEST, unregistred user!
我在编写hid类器件的编程中遇见一个奇怪的问题,程序在和设备设备建立连接,识别后经检查<br>无误,取得的厂商(vendor id)和产品(product id)的id号和厂家提供的id完全符合.缓冲区的指针<br>和设备的能力也取得了,并且也不是按键型hid类设备。 而且设备里的确是有数据的,但<br>在用readfile函数取数据时取得的数据全是0,我检查了数据类型和前期的连接相信没错。<br>各位高手那位能给我讲讲这是为什么???还有各位能否留下QQ号,我在编程时还有些没解决的<br>问题想请教大家,此外我这里还有WINDOWS下编程的资料(400M)也可以和大家共享的!!!<br>我的QQ:121144437(微尘)!!!我先谢谢大家了!!!<br>下面是我的程序,主要使用的API函数这些函数在DDK中可以找到,此外我的HID设备有两个管道<br>一个是写,一个是读。程序有点乱,大家包含一下吧!!!<br><br><br>unit TranThreadUnit;<br><br>interface<br>&nbsp; Uses Classes,Windows,StdCtrls,SysUtils,SyncObjs,<br>&nbsp; &nbsp;Messages, Variants, Graphics, Controls, Forms,<br>&nbsp; Dialogs, &nbsp;ExtCtrls, Math;<br>&nbsp; var<br>&nbsp; &nbsp;hiddata:array[0..1000000]of byte;//usb数据缓冲区<br>Type<br>&nbsp; TUSBTranThread = Class(TThread) //(TThread):初始化一个多线程的程序<br>&nbsp; private<br>&nbsp; &nbsp; devicehandle,InfoOutPipe,InfoInPipe,MainInPipe:THandle;<br>&nbsp; &nbsp; TotalTimes,NowTime,LastLength:Word;<br>&nbsp; &nbsp; MyOverLapData:OverLapped; &nbsp;// &nbsp;The OVERLAPPED 构造一个信息使用在异步输入或是输入<br>&nbsp; &nbsp; DeviceName:String;<br>&nbsp; &nbsp; FileName:String;<br><br>&nbsp; protected<br>&nbsp; &nbsp; procedure Execute;Override;<br>&nbsp; public<br>&nbsp; &nbsp; Constructor Create(UsbDeviceName, SaveFileName: String);<br><br>&nbsp; end;<br><br>Var<br>&nbsp; BytesTransfered,<br>&nbsp; PackageNum:Cardinal;<br>&nbsp; StartATrans:Boolean;<br>implementation<br><br>uses SetupAPI;<br><br>Constructor TUSBTranThread.Create(UsbDeviceName, SaveFileName: String);<br>begin<br>&nbsp; Inherited Create(False);<br>&nbsp; FreeOnTerminate:=True;<br><br>&nbsp; DeviceName := UsbDeviceName; &nbsp;//主线程传回设备的路径<br>&nbsp; FileName := SaveFileName;//主线程传回存盘文件名<br>end;<br><br>procedure TUSBTranThread.Execute; &nbsp; &nbsp; &nbsp; &nbsp;// 线程开始工作<br>label &nbsp;SkipReadLoop;<br>Const<br>&nbsp; EachBulkSize=1024; //数据缓冲区长度<br>var<br>&nbsp; a:word;<br>&nbsp; l,c:integer;<br>&nbsp; shuzi,getcaps:cardinal;//作为hidp_getcaps函数的返回值<br>&nbsp; ifatt: &nbsp;THIDD_ATTRIBUTES;<br>&nbsp; ifcaps: THIDP_CAPS;<br>&nbsp; ifphid:Pointer;<br>&nbsp; Data:array[0..EachBulkSize-1] of byte; &nbsp; &nbsp; &nbsp; &nbsp;//数据缓冲区<br>&nbsp; DataFile:File;<br>&nbsp; EndEvent:TEvent; &nbsp;//结束事件<br>&nbsp; InfoIn:Array[1..2] of Word;<br>&nbsp; MyCommand:Word;<br>// &nbsp;Len,TranLen,<br>&nbsp; TransLength,i,T:Cardinal; //Cardinal类型 0..4294967295 unsigned(无符号) 32-bit<br>&nbsp; Tr:Boolean;<br>&nbsp; &nbsp;begin<br><br>&nbsp; &nbsp; devicehandle := CreateFile(PChar(DeviceName),Generic_Write,File_Share_Write,Nil,Open_Existing,0,0); //取得设备的代号<br><br>&nbsp; &nbsp; ifatt.size &nbsp; := sizeof(ifatt);<br>&nbsp; &nbsp; HidD_GetAttributes (devicehandle,@ifatt); //取厂商与产品的id<br><br>&nbsp; &nbsp; HidD_GetPreparsedData(devicehandle,@ifphid); //取得包含设备能力的缓冲区指针<br><br>&nbsp;// &nbsp; ifcaps.size &nbsp; := sizeof(ifcaps);<br>&nbsp; &nbsp; getcaps:=HidP_GetCaps(ifphid,@ifcaps); &nbsp; //判断是否取得设备的能力<br><br>{ &nbsp;if (getcaps=hidp_status_invalid_preparsed_data) then //如果上一个函数返回的是错误的信息给出出错提示<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; with Application do<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; NormalizeTopMosts;<br>&nbsp; &nbsp; &nbsp; MessageBox('无法取得USB设备的能力!!!', '提示!!!', MB_OK);<br>&nbsp; &nbsp; &nbsp; RestoreTopMosts;<br>&nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp;end;<br>&nbsp;}<br>// &nbsp; if (ifcaps.NumberInputValueCaps=0) then &nbsp; &nbsp;// 上一个函数返回的结构中说明接口内无数据<br>// &nbsp; &nbsp; begin<br>// &nbsp; &nbsp; &nbsp; &nbsp;with Application do<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NormalizeTopMosts;<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MessageBox('USB设备内无数据!!!', '提示!!!', MB_OK);<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;RestoreTopMosts;<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;application.Terminate;<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br>// &nbsp; &nbsp; &nbsp;end<br>// &nbsp;else<br>// &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp;l:=round(ifcaps.NumberInputValueCaps div ifcaps.InputReportByteLength); //要取多少次数据,并确保除数部为零<br>&nbsp; &nbsp; &nbsp; &nbsp;a:=ifcaps.NumberInputValueCaps mod ifcaps.InputReportByteLength &nbsp;; &nbsp; &nbsp; //最后一次要取多少数据<br>// &nbsp; &nbsp; end;<br>//我觉得以上的程序没有问题的<br>&nbsp;try<br>&nbsp; &nbsp; AssignFile(DataFile,FileName); &nbsp;// &nbsp;(连接的外部文件类型 / 文件名)<br>&nbsp; &nbsp; rewrite(datafile,1);<br>&nbsp; &nbsp; filemode:=2;//datafile类型是可读/写<br>&nbsp; &nbsp; for &nbsp;c:=0 to l-1 do<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ReadFile(devicehandle,hiddata,ifcaps.InputReportByteLength,i,Nil); //读文件<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //ReadFile读回来的数据全时0,问题就在这里<br>// &nbsp; &nbsp; &nbsp; &nbsp;While(WaitForSingleObject(EndEvent.Handle,100)=Wait_TimeOut) do &nbsp; &nbsp; //判定数据是否读完 (或者是度文件完毕/下在文件超时 毫秒)<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //append(datafile);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //write(datafile,ifcaps.InputReportByteLength ); &nbsp; &nbsp; &nbsp; &nbsp;//??????????????????<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; blockwrite(datafile,hiddata,ifcaps.InputReportByteLength);//应该是i还是ifcaps.InputReportByteLength<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//??????????????????<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ReadFile(devicehandle,hiddata,a,i,Nil); //读文件<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //ReadFile读回来的数据全时0,问题就在这里<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; blockwrite(datafile,hiddata,ifcaps.InputReportByteLength);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; closefile(datafile);<br>&nbsp;except<br>&nbsp;// &nbsp; &nbsp; &nbsp; &nbsp;MessageBox(handle,'文件打开失败','错误',MB_OK);<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; with Application do<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NormalizeTopMosts;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MessageBox('文件下载失败!!!', '提示!!!', MB_OK);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RestoreTopMosts;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp;end;<br>end;<br>end.
 
程序大体我看了,程序中的 i 怎么没有定义,还有ifcaps.InputReportByteLength应该<br>是 i ,因为 i 返回的是实际接收到的字节数,而blockwrite 的第三个参数也是字节数,<br>但是,为什么readfile读出的总是0,就不太清楚了,你确认你的板子没有问题么?
 
你说的i我试过。但好象问题不是出在这里,我用其他的测试软件得到以下的结果:<br>usage page: 0xff00<br>usage:0x01<br>inputreportbytelength:0x05<br>outputreportbytelength:0x00<br>featurereportbytelength:0x00<br>numberinputbuttoncaps:0x00<br>numberinputvaluecaps:0x00<br>numberoutputbuttoncaps:0x00<br>numberoutputvaluecaps:0x00<br>numberfeaturebuttoncaps:0x00<br>numberfeaturevaluecaps:0x00<br><br>我觉得现在可能程序没有问题,有可能出现的问题:<br>(1)取数据的时候需要什么函数去通知设备发送数据,然后才能用readfile函数去数据<br>这是因为我的程序返回的上述函数结构体中numberinputbuttoncaps返回值是2(十进制),<br>而测试软件的结果是0x00。所以我觉得设备要不是按键型的就是缺了标志,然后才能<br>readfile你觉得呢???如果要是你知道这个函数的话请告诉我!!!谢谢了!!!<br>(2)使用测试软件时它第一次取得的数据全是5(五位),然后才是12345(五位),而<br>我的设备里存的数据是12345。这也让我很奇怪!!!不知你有何看法???
 
当你执行readfile()后,先看一下函数返回值,如果为非零,则调用成功,再看i ,如果<br>i等于你要读的数,则说明读取成功。还有就是readfile这个函数是阻塞调用,如果你的设备<br>的固件没有要发送的数据,则应用程序就会挂起,除非你结束任务或者设备从总线上拔下来。<br>所以,你应该保证你的设备在你调用readfile()时,设备有数据发送,或者把它放在一个<br>独立的进程里。这里你应该先用writefile()函数来发送一个报告,告诉设备准备发送数据。<br>还有就是hiddata的第0个字节是报告ID,后面的才是从设备中读取的数据。<br>
 
至于第二个问题,我不知道你的固件是怎么写的,有人设计的固件的思路是如果执行了<br>readfile函数而设备又没有数据要发送的话,就重复发送上一次最后发送的数据,不知<br>道说的对不对,仅供参考!
 
我注意到您说的这样一句话:这里你应该先用writefile()函数来发送一个报告,告诉<br>设备准备发送数据。我觉得有道理,我也觉得应该是这样的,但我却不知道应该用<br>writefile()函数来发送一个什么报告,告诉设备准备发送数据.(是否用writefile()告诉设备<br>准备发送数据后就可以使用readfile()来读数据呢???),能给我说说吗???<br>还有我试着把readfile()放在了一个for循环里,因为我一开始觉得是我取数据她没发,她发<br>我有没取,后来也不行.您是否需要看一下全部的代码?<br>还有就是一开始我给程序的设备号是一个标准的hid类的guid号是从注册表里查到的就是下面的<br>{745A17A0-74D3-11D0-B6FE-00A0C90F57DA},但是我觉得这个好象不应改由问题,要不设备号和<br>厂商号就不应该是正确的,不知道我说的对不对,请帮我看看!!!谢谢!!!
 
设备号和厂商号对就说明你的guid应该没有问题,也就是说设备你已经找到,问题肯定就是<br>后面的读写代码,要不你把你的全部代码给我看一下,不知道能不能找到错误,我得信箱<br>zuofeng@183.ha.cn &nbsp;, 我得qq号 9793367 ,不过我的qq 不常用。
 
你好!!!<br>我今天又查了一下设备,有些问题我想问你以下!!!<br>(1)我的设备不是模拟的鼠标或者是键盘,就是说不需要判断是否还样是否有键按下的情<br>况才能去取数据。设备里面有数据。<br>(2)我的程序里面如果用ifcaps.InputReportByteLength取回来的数据就是5各字节大小的<br>文件(但我觉得是5个字节大小的0)但用i取回来的就是0字节的文件<br>(3)我想请教一下如果是我的设备模拟的是鼠标或者是键盘,那样的话我在取数据的数据的<br>时候不就得还判断是否有键按下吗???请问我怎么判断呢???<br>(4)我觉得你说的这句话:这里你应该先用writefile()函数来发送一个报告,告诉设备<br>准备发送数据。给我有些启示,但我还不知道你说的用writefile()函数来发送一个报告到<br>底是该发一个什么报告,你能告诉我吗???<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;谢谢!!!<br>
 
接受答案了.
 

Similar threads

后退
顶部