打印

USB驱动开发的例程问题

[复制链接]
1826|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhuhuis|  楼主 | 2012-7-10 19:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人使用Cy7c68013A进行开发,其它例程都已经完成,控制传输找资料已经完成.
只是剩下       DriverObject-> MajorFunction[IRP_MJ_WRITE]   =   Ezusb_Write;       //写入数据
      DriverObject-> MajorFunction[IRP_MJ_READ]   =   Ezusb_Read;           //读取数据


这两个例程没有完成,本人没有写过此类例程,不知如何下手,有知道的朋友告知一下相关的消息也行,谢谢了
沙发
tian111| | 2012-7-10 19:46 | 只看该作者
贴个程序吧

使用特权

评论回复
板凳
zhuhuis|  楼主 | 2012-7-10 20:10 | 只看该作者
NTSTATUS
Ezusb_Read(
        IN   PDEVICE_OBJECT   DeviceObject,
        IN   PIRP                       Irp
        )
{
        PMDL                                       mdl;
        PURB                                       urb;
        ULONG                                     totalLength;
        ULONG                                     stageLength;
        ULONG                                     urbFlags;
        BOOLEAN                                 read;
        NTSTATUS                               ntStatus;
        ULONG_PTR                             virtualAddress;
        PFILE_OBJECT                       fileObject;
        PDEVICE_EXTENSION             deviceExtension;
        PIO_STACK_LOCATION           irpStack;
        PIO_STACK_LOCATION           nextStack;
        PBULKUSB_RW_CONTEXT         rwContext;
        PUSBD_PIPE_INFORMATION   pipeInformation;
PVOID   IoBuffer;


        //
        //   initialize   variables
        //
        urb   =   NULL;
        mdl   =   NULL;
        rwContext   =   NULL;
        totalLength   =   0;
        irpStack   =   IoGetCurrentIrpStackLocation(Irp);
        fileObject   =   irpStack-> FileObject;
        read   =   (irpStack-> MajorFunction   ==   IRP_MJ_READ)   ?   TRUE   :   FALSE;
        deviceExtension   =   (PDEVICE_EXTENSION)   DeviceObject-> DeviceExtension;
        IoBuffer                       =   Irp-> AssociatedIrp.SystemBuffer;

        if(fileObject   &&   fileObject-> FsContext)   {

                pipeInformation   =   fileObject-> FsContext;

                if((UsbdPipeTypeBulk   !=   pipeInformation-> PipeType)   &&
                      (UsbdPipeTypeInterrupt   !=   pipeInformation-> PipeType))   {
                        
                        ntStatus   =   STATUS_INVALID_HANDLE;
                        goto   BulkUsb_DispatchRead_Exit;
                }
        }
        else   {

                ntStatus   =   STATUS_INVALID_HANDLE;
                goto   BulkUsb_DispatchRead_Exit;
        }

        rwContext   =   (PBULKUSB_RW_CONTEXT)
                                ExAllocatePool(NonPagedPool,
                                                              sizeof(BULKUSB_RW_CONTEXT));

        if(rwContext   ==   NULL)   {
               

                ntStatus   =   STATUS_INSUFFICIENT_RESOURCES;
                goto   BulkUsb_DispatchRead_Exit;
        }

        if(Irp-> MdlAddress)   {

                totalLength   =   MmGetMdlByteCount(Irp-> MdlAddress);
        }

        if(totalLength   >   BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE)   {


                ntStatus   =   STATUS_INVALID_PARAMETER;

                ExFreePool(rwContext);

                goto   BulkUsb_DispatchRead_Exit;
        }

        if(totalLength   ==   0)   {


                ntStatus   =   STATUS_SUCCESS;

                ExFreePool(rwContext);

                goto   BulkUsb_DispatchRead_Exit;
        }

        urbFlags   =   USBD_SHORT_TRANSFER_OK;
        virtualAddress   =   (ULONG_PTR)   MmGetMdlVirtualAddress(Irp-> MdlAddress);

        if(read)   {

                urbFlags   |=   USBD_TRANSFER_DIRECTION_IN;
        }
        else   {

                urbFlags   |=   USBD_TRANSFER_DIRECTION_OUT;
        }

        //
        //   the   transfer   request   is   for   totalLength.
        //   we   can   perform   a   max   of   BULKUSB_MAX_TRANSFER_SIZE
        //   in   each   stage.
        //
        if(totalLength   >   BULKUSB_MAX_TRANSFER_SIZE)   {

                stageLength   =   BULKUSB_MAX_TRANSFER_SIZE;
        }
        else   {

                stageLength   =   totalLength;
        }

        mdl   =   IoAllocateMdl((PVOID)   virtualAddress,
                                                totalLength,
                                                FALSE,
                                                FALSE,
                                                NULL);

        if(mdl   ==   NULL)   {
        

                ntStatus   =   STATUS_INSUFFICIENT_RESOURCES;

                ExFreePool(rwContext);

                goto   BulkUsb_DispatchRead_Exit;
        }

        //
        //   map   the   portion   of   user-buffer   described   by   an   mdl   to   another   mdl
        //
        IoBuildPartialMdl(Irp-> MdlAddress,
                                            mdl,
                                            (PVOID)   virtualAddress,
                                            stageLength);

        urb   =   ExAllocatePool(NonPagedPool,
                                                  sizeof(struct   _URB_BULK_OR_INTERRUPT_TRANSFER));

        if(urb   ==   NULL)   {


                ntStatus   =   STATUS_INSUFFICIENT_RESOURCES;

                ExFreePool(rwContext);
                IoFreeMdl(mdl);

                goto   BulkUsb_DispatchRead_Exit;
        }

        UsbBuildInterruptOrBulkTransferRequest(
                                                        urb,
                                                        sizeof(struct   _URB_BULK_OR_INTERRUPT_TRANSFER),
                                                        pipeInformation-> PipeHandle,
                                                        NULL,
                                                        mdl,
                                                        stageLength,
                                                        urbFlags,
                                                        NULL);

        //
        //   set   BULKUSB_RW_CONTEXT   parameters.
        //
        
        rwContext-> Urb                           =   urb;
        rwContext-> Mdl                           =   mdl;
        rwContext-> Length                     =   totalLength   -   stageLength;
        rwContext-> Numxfer                   =   0;
        rwContext-> VirtualAddress     =   virtualAddress   +   stageLength;
        rwContext-> DeviceExtension   =   deviceExtension;

        //
        //   use   the   original   read/write   irp   as   an   internal   device   control   irp
        //

        nextStack   =   IoGetNextIrpStackLocation(Irp);
        nextStack-> MajorFunction   =   IRP_MJ_INTERNAL_DEVICE_CONTROL;
        nextStack-> Parameters.Others.Argument1   =   (PVOID)   urb;
        nextStack-> Parameters.DeviceIoControl.IoControlCode   =   
                                                                                          IOCTL_INTERNAL_USB_SUBMIT_URB;

        IoSetCompletionRoutine(Irp,   
                                                      (PIO_COMPLETION_ROUTINE)Ezusb_ReadWriteCompletion,
                                                      rwContext,
                                                      TRUE,
                                                      TRUE,
                                                      TRUE);

        //
        //   since   we   return   STATUS_PENDING   call   IoMarkIrpPending.
        //   This   is   the   boiler   plate   code.
        //   This   may   cause   extra   overhead   of   an   APC   for   the   Irp   completion
        //   but   this   is   the   correct   thing   to   do.
        //

        IoMarkIrpPending(Irp);

        //BulkUsb_IoIncrement(deviceExtension);

        ntStatus   =   IoCallDriver(deviceExtension-> StackDeviceObject,
                                                        Irp);

        if(!NT_SUCCESS(ntStatus))   {


                //
                //   if   the   device   was   yanked   out,   then   the   pipeInformation   
                //   field   is   invalid.
                //   similarly   if   the   request   was   cancelled,   then   we   need   not
                //   invoked   reset   pipe/device.
                //
                if((ntStatus   !=   STATUS_CANCELLED)   &&   
                      (ntStatus   !=   STATUS_DEVICE_NOT_CONNECTED))   {
                        ULONG   pipenum   =   *((PULONG)   irpStack);
                        /*ntStatus   =   UsbResetPipe(DeviceObject,
                                                                          pipeInformation);*/
                        ntStatus   =   UsbResetPipe(DeviceObject,
                                                                          pipenum);
        
                        if(!NT_SUCCESS(ntStatus))   {


                                //ntStatus   =   BulkUsb_ResetDevice(DeviceObject);
                        }
                }
                else   {

                }
        }

        //
        //   we   return   STATUS_PENDING   and   not   the   status   returned   by   the   lower   layer.
        //
        return   STATUS_PENDING;

BulkUsb_DispatchRead_Exit:

        Irp-> IoStatus.Status   =   ntStatus;
        Irp-> IoStatus.Information   =   0;

        IoCompleteRequest(Irp,   IO_NO_INCREMENT);


        return   ntStatus;
}   

这是我找资料写的一个写例程.我用softIce进行调试时if(fileObject   &&   fileObject-> FsContext)   这里就没有往下执行,直接跳到
        else   {

                ntStatus   =   STATUS_INVALID_HANDLE;
                goto   BulkUsb_DispatchRead_Exit;
        }

使用特权

评论回复
地板
zhuhuis|  楼主 | 2012-7-10 20:13 | 只看该作者
我也只是从别的地方抄来的,肯定不对,请高手指正.

使用特权

评论回复
5
gongche| | 2012-7-10 20:15 | 只看该作者
FsContext这个具体内容不太清楚,最有可能这个东西没有搞好。

使用特权

评论回复
6
huwr| | 2012-7-10 20:17 | 只看该作者
先确认68013A的firmware好了没有?

使用特权

评论回复
7
huanghuac| | 2012-7-10 20:20 | 只看该作者
cypress没有提供driver sample code么?好像《usb原理与工程开发》有提供实例。

使用特权

评论回复
8
zhuhuis|  楼主 | 2012-7-10 20:23 | 只看该作者
这个是没有提供实例的,没实现IRP_MJ_READ的例程的,他们都是使用IRP_MJ_DEVICE_CONTROL这个例程来传输数据的

使用特权

评论回复
9
happy_10| | 2012-7-10 20:25 | 只看该作者
那最终是firmware的问题,还是driver的问题?

使用特权

评论回复
10
zhuhuis|  楼主 | 2012-7-10 20:27 | 只看该作者
如果是driver的问题,if(fileObject && fileObject- >FsContext) 判断为false的原因是什么?

使用特权

评论回复
11
zhuhuis|  楼主 | 2012-7-10 20:29 | 只看该作者
if(fileObject && fileObject- >FsContext)

这个文件对象是需要创建的,在驱动加载时,这个不好控制, 我没有采用此方法,这种方法是DDK的例子的方法.

使用特权

评论回复
12
wenfen| | 2012-7-10 20:30 | 只看该作者
是因为你fileObject- >FsContext为null,fileObject- >FsContext可以记录任意信息,但从这里可以看出是记录PUSBD_PIPE_INFORMATION pipeInformation信息的。
Ezusb驱动我没用过,但大体应该和ddk中的例子bulkusb差不多,fileObject- >FsContext应该在IRP_CREATE中就被赋值了,但你的程序没有成功赋值。
下面摘抄一段bulkusb中的代码
C/C++ code
NTSTATUS
BulkUsb_DispatchCreate(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
。。。。
    for(i=0; i<interface->NumberOfPipes; i++) {

        if(pipeContext == &deviceExtension->PipeContext[i]) {

            //
            // found a match
            //
            BulkUsb_DbgPrint(3, ("open pipe %d\n", i));

            fileObject->FsContext = &interface->Pipes[i];
            
            ASSERT(fileObject->FsContext);

            pipeContext->PipeOpen = TRUE;

            ntStatus = STATUS_SUCCESS;

            //
            // increment OpenHandleCounts
            //
            InterlockedIncrement(&deviceExtension->OpenHandleCount);

            //
            // the device is idle if it has no open handles or pending PnP Irps
            // since we just received an open handle request, cancel idle req.
            //
            if(deviceExtension->SSEnable) {

                CancelSelectSuspend(deviceExtension);
            }
        }
    }
}

使用特权

评论回复
13
冰清玉洁| | 2012-7-10 20:32 | 只看该作者
摘抄的代码貌似\WINDDK\2600.1106\src\wdm\usb\bulkusb\sys\bulkdev.c中的。这个是用pipe的方式。
处理irp,也可以将scsi指令放在urb中,传给下一层的设备栈。

使用特权

评论回复
14
zhuhuis|  楼主 | 2012-7-10 20:35 | 只看该作者
是抄的咯,呵呵
对于驱动的读写,直接I/O方式,大伙有没有好的代码.

使用特权

评论回复
15
huwr| | 2012-7-10 20:37 | 只看该作者
实际上,在XP下也有问题的。只是屏幕没有显示而已!
试着My computer->property->Advanced->Startup and Recovery auto restart选项勾掉,看看是否能重现问题?

使用特权

评论回复
16
zhuhuis|  楼主 | 2012-7-10 20:39 | 只看该作者
好,多谢了

使用特权

评论回复
17
zhuhuis|  楼主 | 2012-7-10 20:40 | 只看该作者
那就结贴了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

728

主题

8464

帖子

6

粉丝