关于上位机通过USB与DSP通信的问题

litongo 2014-09-12 11:03:40
最近在做相关的项目,了解到USB通信的基本过程是先通过枚举找到所需的设备,然后打开设备,进行通信。做到现在遇到一些问题,有点疑惑,请大神指导!
1、关于如何通信
一、查了一些资料,无非都是通过SetupDiGetClassDevs,SetupDiEnumDeviceInterfaces,SetupDiGetDeviceInterfaceDetail等方式枚举设备,找到自己的设备,然后通过CreateFile打开,用WriteFile和ReadFile或者DeviceIoControl来读写。
二、还有一种枚举方式如下:
连接了设备的 HUB 在 HOST 查询其状态改变端点 时返回对应的 bitmap,告知HOST 某个PORT状态发生了改变。
• 主机向 HUB 查询该PORT的状态,得知有设备连接,并知道了该设备的基本特性。
• 主机等待(至少 100mS)设备上电稳定,然后向 HUB 发送请求,复位并使能该PORT。
• HUB执行PORT复位操作,复位完成后该PORT就使能了。现在设备进入到defalut状态,可以从Vbus获取不超过 100mA 的电流。主机可以通过 0地址与其通讯。
• 主机通过0地址向该设备发送get_device_descriptor标准请求,获取设备的描述符。
• 主机再次向 HUB 发送请求,复位该PORT。
• 主机通过标准请求 set_address给设备分配地址。
• 主机通过新地址向设备发送 get_device_descriptor标准请求,获取设备的描述符。
• 主机通过新地址向设备发送其他 get_configuration请求,获取设备的配置描述符。
• 根据配置信息,主机选择合适配置,通过 set_configuration请求对设备而进行配置。这时设备方可正常使用。
我现在很疑问,第二种方法是在USB协议里看到的,个人理解第一种是上位机软件对USB设备的操作,第二种是开发USB驱动程序时严格定义的,不知道理解的对不对,还有就是,我现在在上位机对USB接口操作,即第一种方法,请问打开设备后就可以直接读写了吗?还要做哪些配置?需要对端点(endpoint)指定吗?
...全文
952 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
litongo 2014-09-29
  • 打赏
  • 举报
回复
引用 22 楼 Huntercao 的回复:
[quote=引用 21 楼 litongo 的回复:] 就是说驱动程序里面没有相应的操作是吗?
是的。控制设备都是由驱动程序来完成。应用程序不能直接控制设备。 [/quote] 非常感谢,已实现通信,收获颇多!
曹大夯 2014-09-19
  • 打赏
  • 举报
回复
引用 21 楼 litongo 的回复:
就是说驱动程序里面没有相应的操作是吗?
是的。控制设备都是由驱动程序来完成。应用程序不能直接控制设备。
litongo 2014-09-19
  • 打赏
  • 举报
回复
引用 19 楼 Huntercao 的回复:
[quote=引用 18 楼 litongo 的回复:] 太谢谢了,现在思路清晰了很多,还有一个问题,我用createfile打开设备后,在BUSHOUND中看不到设备被打开的迹象,就停在SET CONFIG,似乎我用createfile打开的只是上位机的USB接口,驱动层好像并没有收到IRP_MJ_CREATE ?
既然CreateFile成功了,那么IRP_MJ_CREATE已经被驱动程序处理完成了。 但是驱动程序不一定在处理IRP_MJ_CREATE的时候往USB设备发送USB控制命令。[/quote] 就是说驱动程序里面没有相应的操作是吗?还要用DeviceIoControl发控制命令,如果没有相应的控制命令,我还得自己修改驱动程序让驱动发URB包给硬件?昨天看了一些资料说打开设备不等于启动设备,在打开设备之前要先CreateService,是这样的吗?
曹大夯 2014-09-18
  • 打赏
  • 举报
回复
引用 16 楼 litongo 的回复:
没有,现在正在跟厂商协商,如果没有驱动程序源码是不是就没法实现通信了?
不一定要源码。但是厂商必须告诉你怎么设置是正确的。因为只有他们自己清楚他们是怎么处理读写IRP。 很多厂商会提供一些可以工作的例子,你照着例子来写你的应用程序。
天冰天降 2014-09-18
  • 打赏
  • 举报
回复
引用 14 楼 litongo 的回复:
[quote=引用 12 楼 w110223 的回复:] [quote=引用 11 楼 litongo 的回复:] [quote=引用 10 楼 w110223 的回复:] 最简单的还是libusb做驱动,下位机找一下固件程序
什么意思?[/quote] 下位机一般还是能找到固件的例程,麻烦的是usb驱动。 libusb能做inf,把你的设备vid,pid和驱动做个接口,而后就是链接lib,就可以查找设备,读写,就通讯了。[/quote] libusb是基于Linux平台的吧?对这个不是很了解,我的最终目的是要从DSP接受图像数据,可在VC环境下利用OpenCV进行处理[/quote] LibUsb-Win32是32位的,现在还有适合64位的。当然一般的就是32位的就可以了。
曹大夯 2014-09-18
  • 打赏
  • 举报
回复
引用 18 楼 litongo 的回复:
太谢谢了,现在思路清晰了很多,还有一个问题,我用createfile打开设备后,在BUSHOUND中看不到设备被打开的迹象,就停在SET CONFIG,似乎我用createfile打开的只是上位机的USB接口,驱动层好像并没有收到IRP_MJ_CREATE ?
既然CreateFile成功了,那么IRP_MJ_CREATE已经被驱动程序处理完成了。 但是驱动程序不一定在处理IRP_MJ_CREATE的时候往USB设备发送USB控制命令。
litongo 2014-09-18
  • 打赏
  • 举报
回复
引用 17 楼 Huntercao 的回复:
[quote=引用 16 楼 litongo 的回复:] 没有,现在正在跟厂商协商,如果没有驱动程序源码是不是就没法实现通信了?
不一定要源码。但是厂商必须告诉你怎么设置是正确的。因为只有他们自己清楚他们是怎么处理读写IRP。 很多厂商会提供一些可以工作的例子,你照着例子来写你的应用程序。[/quote] 太谢谢了,现在思路清晰了很多,还有一个问题,我用createfile打开设备后,在BUSHOUND中看不到设备被打开的迹象,就停在SET CONFIG,似乎我用createfile打开的只是上位机的USB接口,驱动层好像并没有收到IRP_MJ_CREATE ?
天冰天降 2014-09-17
  • 打赏
  • 举报
回复
引用 11 楼 litongo 的回复:
[quote=引用 10 楼 w110223 的回复:] 最简单的还是libusb做驱动,下位机找一下固件程序
什么意思?[/quote] 下位机一般还是能找到固件的例程,麻烦的是usb驱动。 libusb能做inf,把你的设备vid,pid和驱动做个接口,而后就是链接lib,就可以查找设备,读写,就通讯了。
litongo 2014-09-17
  • 打赏
  • 举报
回复
引用 10 楼 w110223 的回复:
最简单的还是libusb做驱动,下位机找一下固件程序
什么意思?
天冰天降 2014-09-17
  • 打赏
  • 举报
回复
最简单的还是libusb做驱动,下位机找一下固件程序
litongo 2014-09-17
  • 打赏
  • 举报
回复
引用 15 楼 Huntercao 的回复:
[quote=引用 13 楼 litongo 的回复:] 可能是我的参数不对吧,ReadFile的第二个参数是接受缓冲区的指针,这个指针指向的地址是驱动程序定义的,还是应用层定义的?看了一些资料说发出读写命令后,驱动程序直接从总线上取数据放到缓冲区,那readfile是不是再从缓冲区读数据,如果是这样,这个缓冲区的地址是怎么获得的呢?
该指针应该是应用程序分配好的buffer指针。你有驱动程序源码么?只有驱动程序知道发生了什么错误。[/quote] 没有,现在正在跟厂商协商,如果没有驱动程序源码是不是就没法实现通信了?
曹大夯 2014-09-17
  • 打赏
  • 举报
回复
引用 13 楼 litongo 的回复:
可能是我的参数不对吧,ReadFile的第二个参数是接受缓冲区的指针,这个指针指向的地址是驱动程序定义的,还是应用层定义的?看了一些资料说发出读写命令后,驱动程序直接从总线上取数据放到缓冲区,那readfile是不是再从缓冲区读数据,如果是这样,这个缓冲区的地址是怎么获得的呢?
该指针应该是应用程序分配好的buffer指针。你有驱动程序源码么?只有驱动程序知道发生了什么错误。
litongo 2014-09-17
  • 打赏
  • 举报
回复
引用 12 楼 w110223 的回复:
[quote=引用 11 楼 litongo 的回复:] [quote=引用 10 楼 w110223 的回复:] 最简单的还是libusb做驱动,下位机找一下固件程序
什么意思?[/quote] 下位机一般还是能找到固件的例程,麻烦的是usb驱动。 libusb能做inf,把你的设备vid,pid和驱动做个接口,而后就是链接lib,就可以查找设备,读写,就通讯了。[/quote] libusb是基于Linux平台的吧?对这个不是很了解,我的最终目的是要从DSP接受图像数据,可在VC环境下利用OpenCV进行处理
litongo 2014-09-17
  • 打赏
  • 举报
回复
引用 9 楼 Huntercao 的回复:
[quote=引用 7 楼 litongo 的回复:] 我是用CreateFile以异步方式打开设备,然后调用readfile和writefile对设备读写,我没有驱动程序cpp,驱动程序是厂家提供的一个安装程序,也没有用DeviceIoControl,因为无法获得设备驱动程序的控制码,无法确认设备端有没有收到请求,读写返回的是ERROR_PRENDING
这种情况应该是设备的驱动程序没有响应你的WriteFile请求,WriteFile对应的IRP被驱动程序Pending了,并且可能是参数设置不对或者什么其他原因,驱动程序没有把IRP转换成对应的USB Control命令发给设备。 对设备进行控制离不开驱动程序的支持。[/quote] 可能是我的参数不对吧,ReadFile的第二个参数是接受缓冲区的指针,这个指针指向的地址是驱动程序定义的,还是应用层定义的?看了一些资料说发出读写命令后,驱动程序直接从总线上取数据放到缓冲区,那readfile是不是再从缓冲区读数据,如果是这样,这个缓冲区的地址是怎么获得的呢?
曹大夯 2014-09-16
  • 打赏
  • 举报
回复
引用 7 楼 litongo 的回复:
我是用CreateFile以异步方式打开设备,然后调用readfile和writefile对设备读写,我没有驱动程序cpp,驱动程序是厂家提供的一个安装程序,也没有用DeviceIoControl,因为无法获得设备驱动程序的控制码,无法确认设备端有没有收到请求,读写返回的是ERROR_PRENDING
这种情况应该是设备的驱动程序没有响应你的WriteFile请求,WriteFile对应的IRP被驱动程序Pending了,并且可能是参数设置不对或者什么其他原因,驱动程序没有把IRP转换成对应的USB Control命令发给设备。 对设备进行控制离不开驱动程序的支持。
litongo 2014-09-16
  • 打赏
  • 举报
回复
引用 6 楼 Huntercao 的回复:
[quote=引用 5 楼 litongo 的回复:] 我现在采用异步方式收发数据,每次向USB设备写数据是总显示IO挂起是为什么呢?
是驱动程序往设备发USB命令挂起还是应用程序的写请求被挂起? 设备端有收到对应的USB写请求并且正确相应么? 有代码可以介绍一下你做了什么么?[/quote] 打开设备就是通过一些列的SetDi函数找到设备,用CREATEFILE打开,打开成功后,就开始读写 读线程: UINT ReadReportThread(LPVOID pParam) { CUsbDlg *pAppDlg; DWORD Length; UINT i; CString Str; DWORD RReadReportBuffer; //将参数pParam取出,并转换为CMyUsbHidTestAppDlg型指针, //以供下面调用其成员函数。 pAppDlg=(CUsbDlg*)pParam; //该线程是个死循环,直到程序退出时,它才退出 while(1) { //设置事件为无效状态 ResetEvent(ReadOverlapped.hEvent); //如果设备已经找到 if(MyDevFound==TRUE) { if(hReadHandle==INVALID_HANDLE_VALUE) //如果读句柄无效 { pAppDlg->AddToInfOut("无效的读报告句柄,可能是打开设备时失败"); } else //否则,句柄有效 { ReadFile(hReadHandle, ReadReportBuffer, 9, &RReadReportBuffer, &ReadOverlapped); } //等待事件触发 WaitForSingleObject(ReadOverlapped.hEvent,INFINITE); //如果等待过程中设备被拔出,也会导致事件触发,但此时MyDevFound //被设置为假,因此在这里判断MyDevFound为假的话就进入下一轮循环。 if(MyDevFound==FALSE) continue; GetOverlappedResult(hReadHandle,&ReadOverlapped,&Length,TRUE); //如果字节数不为0,则将读到的数据显示到信息框中 if(Length!=0) { pAppDlg->AddToInfOut("读取报告"+pAppDlg->itos(Length)+"字节"); Str=""; for(i=0;i<Length;i++) { Str+=pAppDlg->itos(ReadReportBuffer[i],16).Right(2)+" "; } pAppDlg->AddToInfOut(Str, FALSE); } } else { //阻塞线程,直到下次事件被触发 WaitForSingleObject(ReadOverlapped.hEvent,INFINITE); } } return 0; } 写线程中的动作比较简单,实际的写操作是按下发送按钮后执行的 UINT WriteReportThread(LPVOID pParam) { while(1) { ResetEvent(WriteOverlapped.hEvent); WaitForSingleObject(WriteOverlapped.hEvent,INFINITE); DataInSending=FALSE; } return 0; } oid CUsbDlg::OnBUTTONSend() { // TODO: Add your control notification handler code here BOOL Result; UINT LastError; UINT i; CString Str,str_send; DWORD WWriteReportBuffer; SetEvent(WriteOverlapped.hEvent); GetDlgItemText(IDC_SEND,str_send);//从窗口获得要写入的数据 //如果设备没有找到,则返回失败 if(MyDevFound==FALSE) { AddToInfOut("设备未找到"); //return FALSE; } //如果句柄无效,则说明打开设备失败 if(hWriteHandle==INVALID_HANDLE_VALUE) { AddToInfOut("无效的写报告句柄,可能是打开设备时失败"); //return FALSE; } //如果数据仍在发送中,则返回失败 if(DataInSending==TRUE) { AddToInfOut("数据正在发送中,暂时不能发送"); //return FALSE; } //设置要发送报告的数据 WriteReportBuffer[0]=0x00; //报告ID为0 for(int ii=0;ii<256;ii++) { WriteReportBuffer[ii]=ii; } //设置正在发送标志 DataInSending=TRUE; //调用WriteFile函数发送数据 Result=WriteFile(hWriteHandle, WriteReportBuffer, 9, &WWriteReportBuffer, &WriteOverlapped); //如果函数返回失败,则可能是真的失败,也可能是IO挂起了 if(Result==FALSE) { //获取最后错误代码 LastError=GetLastError(); //看是否是真的IO挂起 if((LastError==ERROR_IO_PENDING)||(LastError==ERROR_SUCCESS)) { //return TRUE; AddToInfOut("IO挂起"); } //否则,是函数调用时发生错误,显示错误代码 else { DataInSending=FALSE; AddToInfOut("发送失败,错误代码:"+itos(LastError)); //如果最后错误为1,说明该设备不支持该函数。 if(LastError==1) { AddToInfOut("该设备不支持WriteFile函数。", FALSE); } Result=FALSE; } } //否则,函数返回成功 else { DataInSending=FALSE; Result=TRUE; }
litongo 2014-09-16
  • 打赏
  • 举报
回复
引用 6 楼 Huntercao 的回复:
[quote=引用 5 楼 litongo 的回复:]
我现在采用异步方式收发数据,每次向USB设备写数据是总显示IO挂起是为什么呢?

是驱动程序往设备发USB命令挂起还是应用程序的写请求被挂起?
设备端有收到对应的USB写请求并且正确相应么?

有代码可以介绍一下你做了什么么?[/quote]
应用程序往设备发写请求被挂起,从设备读也是挂起,我用BusHound看不到数据交换,如下图:

是不是我还没有对端口设置呀
我是用CreateFile以异步方式打开设备,然后调用readfile和writefile对设备读写,我没有驱动程序cpp,驱动程序是厂家提供的一个安装程序,也没有用DeviceIoControl,因为无法获得设备驱动程序的控制码,无法确认设备端有没有收到请求,读写返回的是ERROR_PRENDING
曹大夯 2014-09-16
  • 打赏
  • 举报
回复
引用 5 楼 litongo 的回复:
我现在采用异步方式收发数据,每次向USB设备写数据是总显示IO挂起是为什么呢?
是驱动程序往设备发USB命令挂起还是应用程序的写请求被挂起? 设备端有收到对应的USB写请求并且正确相应么? 有代码可以介绍一下你做了什么么?
litongo 2014-09-15
  • 打赏
  • 举报
回复
引用 4 楼 Huntercao 的回复:
[quote=引用 2 楼 litongo 的回复:] 那请问用writefile和readfile读写数据时,控制请求怎么发?也是通过deviceiocontrol吗?
WriteFile/ReadFile/DeviceIoControl是应用程序可用的API,应用程序调用这些API将请求发给设备的驱动程序。设备的驱动程序会根据USB规范来跟USB设备打交道。[/quote] 了解。我现在采用异步方式收发数据,每次向USB设备写数据是总显示IO挂起是为什么呢?
曹大夯 2014-09-15
  • 打赏
  • 举报
回复
引用 2 楼 litongo 的回复:
那请问用writefile和readfile读写数据时,控制请求怎么发?也是通过deviceiocontrol吗?
WriteFile/ReadFile/DeviceIoControl是应用程序可用的API,应用程序调用这些API将请求发给设备的驱动程序。设备的驱动程序会根据USB规范来跟USB设备打交道。
加载更多回复(3)

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧