⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rwusb.c

📁 HomePNA的Usb网卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (c) 1999  Microsoft Corporation

Module Name:

   rwusb.c

Abstract:

    USB device driver .
    This module contains code pertaining to IRPS and URBS and USB, but no
    ndis-specific code

Environment:

    kernel mode only

Notes:

  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  PURPOSE.

  Copyright (c) 1999 Microsoft Corporation.  All Rights Reserved.


Revision History:


--*/


#include <ndis.h>
#include <ntdef.h>
#include <windef.h>

#include "usbdi.h"
#include "usbdlib.h"

#include "debug.h"

#include "common.h"
#include "HPNA_2k.h"

/*****************************************************************************
*
*  Function:   InitializeReceive
*
*  Synopsis:   Initialize the receive functionality.
*
*  Arguments:  Deviceice - pointer to current usb device object
*
*  Returns:    NDIS_STATUS_SUCCESS   - if irp is successfully sent to USB
*                                      device object
*              NDIS_STATUS_RESOURCES - if mem can't be alloc'd
*              NDIS_STATUS_FAILURE   - otherwise
*
*  Algorithm:
*              1) Set the receive timeout to READ_INTERVAL_TIMEOUT_MSEC.
*              2) Initialize our rcvInfo and associate info for our
*                 receive state machine.
*              3) Build an IRP_MJ_READ irp to send to the USB device
*                 object, and set the completion(or timeout) routine
*                 to UsbIoCompleteRead.
*  Notes:
*
*  This routine must be called in IRQL PASSIVE_LEVEL.
*
*****************************************************************************/

NTSTATUS
InitializeReceive(
            IN PUSB_DEVICE Device
            )
{
    NTSTATUS        status = STATUS_SUCCESS;

    DEBUGMSG(DBG_FUNC, ("+InitializeReceive\n"));

    //
    // Create a thread to run at IRQL PASSIVE_LEVEL.
    //
    status =  PsCreateSystemThread(
                            &Device->hPassiveThread,
                            (ACCESS_MASK) 0L,
                            NULL,
                            NULL,
                            NULL,
                            PassiveLevelThread,
                            Device
                            );
    if (status != STATUS_SUCCESS)
    {
        DEBUGMSG(DBG_ERROR, ("PsCreateSystemThread PassiveLevelThread failed. Returned 0x%.8x\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;

        goto done;
    }
    //
    // Create a thread to run at IRQL PASSIVE_LEVEL to be always receiving.

    status =  PsCreateSystemThread(
                    &Device->hPollingThread,
                    (ACCESS_MASK) 0L,
                    NULL,
                    NULL,
                    NULL,
                    PollingThread,
                    Device
                    );

    if (status != STATUS_SUCCESS)
    {
        DEBUGMSG(DBG_ERROR, ("PsCreateSystemThread PollingThread failed. Returned 0x%.8x\n", status));

        status = STATUS_INSUFFICIENT_RESOURCES;
        goto done;

    }


    Device->fReceiving = TRUE;

done:
        return status;
}

NTSTATUS StartUsbRead(IN PUSB_DEVICE Device)
/*++

Routine Description:

    Allocates an irp and calls USBD.

Arguments:

    Device - Current usb device.

Return Value:

    STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver

--*/
{
    ULONG siz;
    ULONG length;
    PURB urb = NULL;
    PDEVICE_OBJECT urbTargetDev;
    PIO_STACK_LOCATION nextStack;
    NTSTATUS timeStat = STATUS_UNSUCCESSFUL;
    PMDL    mdl;
    PRCV_BUFFER pRecBuf;
    UINT Index;


    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
    length = MAX_PACKET_SIZE;

    // Find a free buffer and set the state to PENDING;
    pRecBuf = GetRcvBuf( Device, &Index, STATE_PENDING );
    if ( !pRecBuf)
    {
        //
        // no buffers available; drop it
        //
        timeStat = STATUS_UNSUCCESSFUL;

        goto done;
    }

    if( TRUE == Device->fPendingReadClearStall ) {

        timeStat = STATUS_UNSUCCESSFUL;
        goto done;
    }

    urb =  ((PURB) pRecBuf->Urb);


    // Build our URB for USBD

    NdisZeroMemory(urb, siz);

    ASSERT(Device->BulkInPipeHandle);

    //
    // Now that we have created the urb, we will send a
    // request to the USB device object.
    //

    KeClearEvent(&pRecBuf->Event);

    urbTargetDev = Device->pUsbDevObj;

    ASSERT(urbTargetDev);


    //
    // Now that we have created the urb, we will send a
    // request to the USB device object.
    //

    urbTargetDev = Device->pUsbDevObj;


    // make an irp sending to usbhub
    pRecBuf->Irp = IoAllocateIrp( (CCHAR)(Device->pUsbDevObj->StackSize +1), FALSE );


    if ( NULL == pRecBuf->Irp )
    {
        timeStat = STATUS_INSUFFICIENT_RESOURCES;
        goto done;
    }


    ((PIRP) pRecBuf->Irp)->IoStatus.Status = STATUS_NOT_SUPPORTED;
    ((PIRP) pRecBuf->Irp)->IoStatus.Information = 0;


    // Build our URB for USBD

    urb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT) siz;
    urb->UrbBulkOrInterruptTransfer.Hdr.Function =
                URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
    urb->UrbBulkOrInterruptTransfer.PipeHandle =
               Device->BulkInPipeHandle;
    urb->UrbBulkOrInterruptTransfer.TransferFlags =
        USBD_TRANSFER_DIRECTION_IN ;

    // short packet is not treated as an error.
    urb->UrbBulkOrInterruptTransfer.TransferFlags |=
        USBD_SHORT_TRANSFER_OK;

    //
    // not using linked urb's
    //
    urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;

    urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;

    urb->UrbBulkOrInterruptTransfer.TransferBuffer = pRecBuf->dataBuf;

    urb->UrbBulkOrInterruptTransfer.TransferBufferLength =length;


    //
    // Call the class driver to perform the operation.


    nextStack = IoGetNextIrpStackLocation( (PIRP) pRecBuf->Irp );

    ASSERT(nextStack != NULL);

    //
    // pass the URB to the USB driver stack
    //


    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    nextStack->Parameters.Others.Argument1 = urb;
    nextStack->Parameters.DeviceIoControl.IoControlCode =
        IOCTL_INTERNAL_USB_SUBMIT_URB;


    IoSetCompletionRoutine(
                ((PIRP) pRecBuf->Irp),     // irp to use
                UsbIoCompleteRead,      // routine to call when irp is done
                pRecBuf,  // context to pass routine is the RCV_BUFFER
                TRUE,                      // call on success
                TRUE,                      // call on error
                TRUE);                     // call on cancel


    //
    // Call IoCallDriver to send the irp to the usb port.
    //
    UsbIncIoCount( Device ) ;
    
    timeStat = IoCallDriver(urbTargetDev, (PIRP) pRecBuf->Irp ); // Start UsbRead()

    DEBUGMSG(DBG_FUNC, (" StartUsbRead() after IoCallDriver () status = 0x%x\n", timeStat));

    ASSERT( STATUS_SUCCESS != timeStat );

    while ( timeStat != STATUS_SUCCESS ) { //we will always get to our completion routine, even if cancelled

        timeStat = MyKeWaitForSingleObject(
                       Device,
                       &pRecBuf->Event, //event to wait on
                       NULL,  //irp to cancel on halt/reset or timeout
                       10000 * 1000 * 1 );//1秒
    }

    ASSERT( NULL == pRecBuf->Irp ); // WIll be nulled by completion routine
done:
    if ( !pRecBuf || ( Device->RcvBuffersInUse >= (NUM_RCV_BUFS -2) ) )
	{
        /*if ( FALSE == Device->fIndicatedMediaBusy ) 
		{

            InterlockedExchange( &Device->fMediaBusy, TRUE );
            InterlockedExchange( &Device->fIndicatedMediaBusy, TRUE );
            IndicateMediaBusy( Device ); // indicate to Ndis  BUGBUG? NOT NEEDED HERE?
        }*/
       IndicateMediaBusy( Device ); // indicate to Ndis  BUGBUG? NOT NEEDED HERE?
	}

    return timeStat;
}



/*****************************************************************************
*
*  Function:   UsbIoCompleteRead
*
*  Synopsis:
*
*  Arguments:  pUsbDevObj - pointer to the  device object which
*                              completed the irp
*              pIrp          - the irp which was completed by the  device
*                              object
*              Context       - dev ext
*
*  Returns:    STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
*              (IofCompleteRequest) to stop working on the irp.
*
*  Algorithm:
*              This is the completion routine for all pending IRP_MJ_READ irps
*              sent to the  device object.
*
*              If there is a pending halt or reset, we exit the completion
*              routine without sending another irp to the USBl device object.
*
*
*              If the IRP_MJ_READ irp returned either STATUS_SUCCESS or
*              STATUS_TIMEOUT, we must process any data (stripping BOFs, ESC
*              sequences, and EOF) into an NDIS_BUFFER and NDIS_PACKET.
*
*              Another irp is then built (we just re-use the incoming irp) and
*              sent to the USB object with another IRP_MJ_READ
*              request.
*  Notes:
*
*  This routine is called (by the io manager) in IRQL DISPATCH_LEVEL.
*
*****************************************************************************/

NTSTATUS
UsbIoCompleteRead(
            IN PDEVICE_OBJECT pUsbDevObj,
            IN PIRP           pIrp,
            IN PVOID          Context
            )
{
    PUSB_DEVICE  device;
    NTSTATUS    status;
    ULONG_PTR    BytesRead;
    PRCV_BUFFER  pRecBuf;
    LARGE_INTEGER tat;

    DEBUGMSG(DBG_FUNC, ("+UsbIoCompleteRead\n"));

    //
    // The context given to IoSetCompletionRoutine is the receive buffer object
    //

    pRecBuf = (PRCV_BUFFER) Context;

    device = (PUSB_DEVICE) pRecBuf->device;

    ASSERT( pRecBuf->Irp == pIrp );

    ASSERT( NULL != device );



    if ((device->fPendingHalt  == TRUE) ||
        (device->fPendingReset == TRUE))
    {
        //
        // Set the fReceiving boolean so that the halt and reset routines
        // know when it is okay to continue.
        //
                    // change the below back to DBG_FUNC later?
        DEBUGMSG(DBG_FUNC, ("UsbIoCompleteRead  halt or reset pending setting fReceiving FALSE\n"));
        device->fReceiving = FALSE;


    }

    //
    // We have a number of cases:
    //      1) The USB read timed out and we received no data.
    //      2) The USB read timed out and we received some data.
    //      3) The USB read was successful and fully filled our irp buffer.
    //      4) The irp was cancelled.
    //      5) Some other failure from the USB device object.
    //


    status = pIrp->IoStatus.Status;

    //
    // IoCallDriver has been called on this Irp;
    // Set the length based on the TransferBufferLength
    // value in the URB
    //
    pIrp->IoStatus.Information =
         ((PURB) pRecBuf->Urb)->UrbBulkOrInterruptTransfer.TransferBufferLength;

    BytesRead = pIrp->IoStatus.Information;

    device->pCurrentRcvBuf = NULL;


    switch (status)
    {
        case STATUS_SUCCESS:

            if (BytesRead > 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -