阅读:1236回复:0
USB 摄像机驱动开发瓶颈问题请教大家
瓶颈问题:重要!需求:
我现在做的是摄像机的驱动程序,现在我的驱动程序设置了2个函数,一个用于传输控制命令(对应于端点0),一个用于从端点6读取数据:相机USB有2个端点,端点0和端点6,端点0用于传输命令,端点6用来传输数据,端点0的缓冲区大小为64个字节,端点6的缓冲区的大小为2k,当应用程序向相机发送F1 xx xx xx xx xx xx xx 命令,命令为8个字节,xx表示为任意值,应用程序发送F1后,相机通过端点6给应用程序发送数据,但是每次只发512个字节,所以需要开辟一个线程不断的监听端点6,然后不断的把数据取走,摄像机会不断的往端点6发送数据,当取出的数据的大小为一幅图像的大小时(1.4M)就将图像显示在界面上,然后继续监听端点6,重新开始读数据。 问题(1) 怎么使用线程去监听端点6,有没有读取端点6的API,以流的形式读(StreamRead) 我是这样考虑的,可以用2种方法去读数据,第一种方法是驱动程序分配一个缓冲区,大小为一幅图像的大小,然后不断的从端点6读取数据,一次读512个字节,然后移动缓冲区的指针,接着读,直到缓冲区满,说明一幅图像已经读出来了,显示在界面上,清空缓冲区,然后继续读端点6. 第2种方法是采用Stream的方式读,不知道有这样的API吗,(win driver )里面就有这样的API,我现在不知道driver studio 或windows 提供这样的API吗? 问题(2):我在应用程序中想用这个函数传输控制命令, DeviceIoControl(m_hDevice, Camera_IOCTL_Control, bufInput, IOCTL_INBUF_SIZE, bufOutput, IOCTL_OUTBUF_SIZE, &nOutput, NULL) ) BufInput 是不是传输的就是我们的令牌还是我们的控制命令,我的令牌为0x40 0xF1 0x00 0x00 0x00 0x00 0x08 0x00,而我的控制命令是0xF10x00 0x00 0x00 0x00 0x00 0x08 0x00,我现在搞不懂了到底命令怎么传输。我将bufInput 初始化为 0xF10x00 0x00 0x00 0x00 0x00 0x08 0x00,使用bus hound 抓图如下:没有弄明白,我没有发送令牌,CTL 0x40 0xF1 0x00 0x00 0x00 0x00 0x08 0x00 是怎么加上去的 问题(3): 我想用NTSTATUS CameraDevice::Camera_IOCTL_Read_Handler(KIrp I)函数去读取端点6中的数据,这个里面调用了2个函数EndPoint6In.BuildBulkTransfer和EndPoint6In.SubmitUrb: PURB pUrb=EndPoint6In.BuildBulkTransfer((unsigned char *)I.IoctlBuffer(), //接收数据的缓冲区 dwTotalSize, //读数据的数据字节数 TRUE, //TURE表示读数据 NULL, //连接下一个传输的URB,这里没有,置为NULL TRUE, //TRUE表示设备传输的字节数可以少于指定的字节数 NULL); //指向一个已经存在的URB。置为NULL,分配一个新的URB 但是我没有弄明白:BuildBulkTransfer函数中,I.IoctlBuffer()就是我的相机传输的512字节吗,那么在调用Camera_IOCTL_Read_Handler(KIrp I)的应用程序DeviceIoControl中,bufInput=512吗,还有bufOutput的大小就是我分配的一幅图片的缓冲区的大小吗? 那么我怎么在Camera_IOCTL_Read_Handler(KIrp I)中不断的读数据呢? DeviceIoControl(m_hDevice, Camera_IOCTL_Control, bufInput, IOCTL_INBUF_SIZE, bufOutput, IOCTL_OUTBUF_SIZE, &nOutput, NULL) ) 问题(4)我不知道怎么去开辟一个线程去监听端口,我那个应用程序和驱动程序中的读数据函数还没有完全写好,大家提供能提供一点方法吗?我的读图像的理路如下: 驱动程序和应用程序如下: NTSTATUS CameraDevice::DeviceControl(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; switch (I.IoctlCode()) { case Camera_IOCTL_Control: status = Camera_IOCTL_Control_Handler(I);//设置控制参数; break; case Camera_IOCTL_Read: status = Camera_IOCTL_Read_Handler(I);//读端口6中的数据; break; case Camera_IOCTL_Write: status = Camera_IOCTL_Write_Handler(I); break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } if (status != STATUS_PENDING) { I.PnpComplete(this, status); } T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } //下面是接收端点0控制命令的函数 NTSTATUS CameraDevice::Camera_IOCTL_Control_Handler(KIrp I)//发送控制命令的脚本 { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; //ULONG inputSize = I.IoctlInputBufferSize(); //ULONG outputSize = I.IoctlOutputBufferSize(); //PVOID inputBuffer = I.IoctlBuffer(); // PVOID outputBuffer = I.IoctlBuffer(); if(FALSE) { status=STATUS_INVALID_PARAMETER; I.Information()=0; } else { PURB pUrb=m_Lower.BuildVendorRequest( (unsigned char *)I.IoctlBuffer(),//transfer buffer 为驱动程序传输数据的内存区 I.IoctlInputBufferSize(),//transfer buffer size 为传输的字节数 0, //request reserved bits 0xF1,//具体请求的数值,可以为F1 F2 F4 F5 F6 0, //value FALSE, //FALSE 表示输出,数据从主机到设备 TRUE, // NULL, //Link 0 //Index ); if ( pUrb == NULL ) { status = STATUS_INSUFFICIENT_RESOURCES; } else { // submit the URB to USBD status = m_Lower.SubmitUrb(pUrb);//SubmitUrb(pUrb,NULL,NULL,1500L); if(NT_SUCCESS(status)) { I.Information() = pUrb->UrbControlVendorClassRequest.TransferBufferLength; } delete pUrb;//删除分配的Urb } }//end else I.Status() = status; T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } NTSTATUS CameraDevice::Camera_IOCTL_Read_Handler(KIrp I)//这里是往端点6读数据的程序 { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // ULONG inputSize = I.IoctlInputBufferSize(); // ULONG outputSize = I.IoctlOutputBufferSize(); // Buffered ioctl - using the same buffer so read the buffer before writing the buffer // PVOID inputBuffer = I.IoctlBuffer(); // PVOID outputBuffer = I.IoctlBuffer(); // TODO: Validate the parameters of the IRP. Replace "FALSE" //in the following line with error checking code that //evaulates to TRUE if the request is not valid. if(FALSE)//如果缓冲区为无效地址 { status = STATUS_INVALID_PARAMETER; I.Information() = 0; } else { if(I.IoctlOutputBufferSize()==0) //如果读数据长度为0,则不用传输数据 { I.Information() = 0; return I.PnpComplete(this,STATUS_SUCCESS); } else //长度不为0 { ULONG dwTotalSize=I.IoctlOutputBufferSize(CURRENT);// ULONG dwMaxSize=EndPoint6In.MaximumTransferSize(); if(dwTotalSize>dwMaxSize) { ASSERT(dwMaxSize); dwTotalSize=dwMaxSize; } //创建一个批量传输的URB,用来从端点6读取数据 PURB pUrb=EndPoint6In.BuildBulkTransfer((unsigned char *)I.IoctlBuffer(), //接收数据的缓冲区 dwTotalSize, //读数据的数据字节数 TRUE, //TURE表示读数据 NULL, //连接下一个传输的URB,这里没有,置为NULL TRUE, //TRUE表示设备传输的字节数可以少于指定的字节数 NULL); //指向一个已经存在的URB。置为NULL,分配一个新的URB if(pUrb==NULL) //如果分配失败 { status=STATUS_INSUFFICIENT_RESOURCES; //设置状态为资源不足 I.Information()=0; //数据传输为0 } else { //提交URB,并设置等待3秒后就超时 status=EndPoint6In.SubmitUrb(pUrb,NULL,NULL,3000);// //获取实际读到的数据字节数 if(NT_SUCCESS(status)) { I.Information()=pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength; } delete pUrb; //删除刚刚分配的URB } } } T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } 对应的测试应用程序如下: void CTest_CameraDlg::OnOK() { // TODO: Add extra validation here TestControlParam();//传输控制命令 TestReadParam();//从端点6读取数据 } void CTest_CameraDlg::TestControlParam() { UCHAR bufInput[IOCTL_INBUF_SIZE]={0xF1,0x00,0x00,0x00,0x00,0x00,0x08,0x00};// //Input to device UCHAR bufOutput[IOCTL_OUTBUF_SIZE]; // Output from device ULONG nOutput; // Count written to bufOutput if (!DeviceIoControl(m_hDevice, Camera_IOCTL_Control, bufInput, IOCTL_INBUF_SIZE, bufOutput, IOCTL_OUTBUF_SIZE, &nOutput, NULL) ) { MessageBox("Camera_IOCTL_Control", "错误", MB_OK | MB_ICONHAND); } } #define IOCTL_INBUF_SIZE1 512 #define IOCTL_OUTBUF_SIZE1 512 void CTest_CameraDlg::TestReadParam() { UCHAR bufInput[IOCTL_INBUF_SIZE1]; UCHAR bufOutput[IOCTL_OUTBUF_SIZE1]; ULONG nOutput;// if (!DeviceIoControl(m_hDevice, Camera_IOCTL_Read, bufInput, IOCTL_INBUF_SIZE, bufOutput, IOCTL_OUTBUF_SIZE, &nOutput, NULL) ) { MessageBox("Camera_IOCTL_Read", "错误", MB_OK | MB_ICONHAND); } else { CString str; str.Format("0x%x",bufOutput); SetDlgItemText(IDC_OutputEndpoint,str); } } |
|