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

📄 send.c

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

Copyright (c) 1999  Microsoft Corporation

Module Name:

   send.c

Abstract:

    USB device driver - Transmit io code

Environment:

    kernel mode only


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


Revision History:

--*/


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

#include "stdarg.h"
#include "stdio.h"
#include "debug.h"

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

#include "common.h"
#include "HPNA_2K.h"

/*****************************************************************************
*
*  Function:   SendPacket
*
*  Synopsis:   Send a packet to the USB driver and add the sent irp and io context to
*              To the pending send queue; this que is really just needed for possible later error cancellation
*
*
*  Arguments:  MiniportAdapterContext - pointer to current ir device object
*              pPacketToSend          - pointer to packet to send
*              Flags                  - any flags set by protocol
               Type                      - CONTEXT_TYPE enum for whether it's a real NDIS_PACKET
                                         or dummy packet for a SetSpeed/Check Media busy call
*
*  Returns:    NDIS_STATUS_PENDING - This is generally what we should
*                                    return. We will call NdisMSendComplete
*                                    when the USB driver completes the
*                                    send.
*              STATUS_UNSUCCESSFUL - The packet was invalid.
*
*  Unsupported returns:
*              NDIS_STATUS_SUCCESS  - We should never return this since
*                                     results will always be pending from
*                                     the USB driver.
*              NDIS_STATUS_RESOURCES-This indicates to the protocol that the
*                                    device currently has no resources to complete
*                                    the request. The protocol will resend
*                                    the request when it receives either
*                                    NdisMSendResourcesAvailable or
*                                    NdisMSendComplete from the device.
*
*
*
*****************************************************************************/

NTSTATUS
SendPacket(
           IN PUSB_DEVICE   Device,
           IN PVOID           pPacketToSend,
           IN UINT         Flags,
           IN CONTEXT_TYPE Type
           )
{
    PIRP                pIrp;
    UINT                BytesToWrite =0;
    NTSTATUS            status;
    BOOLEAN             fConvertedPacket;
    ULONG siz;
    PURB urb = NULL;
    PDEVICE_OBJECT urbTargetDev;
    PIO_STACK_LOCATION nextStack;
    PMDL    mdl = NULL;
    PUSB_CONTEXT pCur, thisContext;

    ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

    thisContext = (PUSB_CONTEXT) GetFreeContext( Device );

    if ( NULL == thisContext )
    {
        status = STATUS_UNSUCCESSFUL;
        goto done;
    }
    
    thisContext->Packet = pPacketToSend;
    thisContext->Type = Type;

    urb = thisContext->Urb;

    NdisZeroMemory( urb, Device->UrbLen );

    if (  CONTEXT_NDIS_PACKET == Type )
	{
        ASSERT( NULL != pPacketToSend );
        //
        // Get the packet's entire length
        //
        NdisQueryPacket( (PNDIS_PACKET)pPacketToSend, NULL, NULL, NULL, &BytesToWrite);
        
		BytesToWrite += USB_PACKET_LENGTH;

        thisContext->BufLen = BytesToWrite;

        NdisZeroMemory(
                    thisContext->Buffer,
                    thisContext->BufLen
                    );

        //
        // Convert the packet to an usb frame and copy into our buffer
        // and send the irp.
        //
        fConvertedPacket = NdisToUsbPacket(
                                    Device,
                                    pPacketToSend,
                                    (PUCHAR)thisContext->Buffer,
                                  	MAX_PACKET_SIZE+USB_PACKET_LENGTH
                                    );

        if (fConvertedPacket == FALSE)
        {
            status = STATUS_UNSUCCESSFUL;
            goto done;
        }


    } 
/*	else if (  CONTEXT_SETSPEED == Type )
	{
        // set up the single byte required to send to device to change speeds
        BytesToWrite = 1;

        Device->OutBoundHeader = Device->linkSpeedInfo->headerLinkSpeed;

        thisContext->Buffer[0] = Device->OutBoundHeader;

    }*/
	else if (  CONTEXT_TERMINATOR == Type ) 
	{
        // We need to Send a zero-lengh USB ( not NDIS) packet as a terminator
        // when we have  previously sent a packet with a length that is an exact multiple of
        // Device->UsbInterface->Pipes[1]->MaximumPacketSize  (64)
        //
        BytesToWrite = 0;

    }

    thisContext->BufLen = BytesToWrite;

    //
    // 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
    pIrp = IoAllocateIrp( (CCHAR)(Device->pUsbDevObj->StackSize +1), FALSE );


    if ( NULL == pIrp )
    {
        status = STATUS_UNSUCCESSFUL;
        goto done;
    }

    pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; 
    pIrp->IoStatus.Information = 0;

    thisContext->Irp = pIrp;


    // Build our URB for USBD
    urb->UrbBulkOrInterruptTransfer.Hdr.Length =
        (USHORT) sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
    urb->UrbBulkOrInterruptTransfer.Hdr.Function =
                URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
    urb->UrbBulkOrInterruptTransfer.PipeHandle =
               Device->BulkOutPipeHandle;
    urb->UrbBulkOrInterruptTransfer.TransferFlags =
        USBD_TRANSFER_DIRECTION_OUT ;
    // short packet is not treated as an error.
    urb->UrbBulkOrInterruptTransfer.TransferFlags |=
        USBD_SHORT_TRANSFER_OK;
    urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
    urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
    urb->UrbBulkOrInterruptTransfer.TransferBuffer = thisContext->Buffer;
    urb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int) BytesToWrite;


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


    nextStack = IoGetNextIrpStackLocation(pIrp);

    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,                      // irp to use
                UsbIoCompleteWrite,      // routine to call when irp is done
                DEV_TO_CONTEXT(thisContext),  // context to pass routine
                TRUE,                      // call on success
                TRUE,                      // call on error
                TRUE);                     // call on cancel

    //
    // Call IoCallDriver to send the irp to the usb port.
    //

    UsbIncIoCount( Device );

    status =  IoCallDriver( urbTargetDev, pIrp );
    //
    // The USB driver should always return STATUS_PENDING when
    // it receives a write irp
    //

    ASSERT(status == STATUS_PENDING);

    // We need to Send a zero-lengh USB ( not NDIS) packet as a terminator
    // when we have  previously sent a packet with a length that is an exact multiple of
    // ((PUSB_INFO) Device->pUsbInfo)->UsbInterface->Pipes[1]->MaximumPacketSize  (64)
    // BUGBUG? we'll indicate send complete before sending terminator
    
    if ( BytesToWrite && ( BytesToWrite % 64 == 0))
    {   // ((PUSB_INFO) Device->pUsbInfo)->UsbInterface->Pipes[1].MaximumPacketSize ) == 0) {

        SendPacket( Device, NULL, 0, CONTEXT_TERMINATOR );
    }

done:

    return status;

}

/*****************************************************************************
*
*  Function:   UsbIoCompleteWrite
*
*  Synopsis:
*
*  Arguments:  pUsbDevObj - pointer to the USB device object which
*                              completed the irp
*              pIrp          - the irp which was completed by the
*                              device object
*              Context       - the context given to IoSetCompletionRoutine
*                              before calling IoCallDriver on the irp
*                              The Context is a pointer to the ir device object.
*
*  Returns:    STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
*              (IofCompleteRequest) to stop working on the irp.
*
*  Algorithm:
*     1a) Indicate to the protocol the status of the write.
*     1b) Return ownership of the packet to the protocol.
*
*     2)  If any more packets are queue for sending, send another packet
*         to USBD.

⌨️ 快捷键说明

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