Sample Code

Windows Driver Samples/ Usbsamp Generic USB Driver/ C++/ sys/ stream.c/

 /*++

Copyright (c) Microsoft Corporation.  All rights reserved.

    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.

Module Name:

    stream.c

Abstract:

    This files contain routines for Streams.

Environment:

    Kernel mode only

Notes:


--*/

#include "private.h"


#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, GetStackCapability)
#if (NTDDI_VERSION >= NTDDI_WIN8)
#pragma alloc_text(PAGE, InitializePipeContextForSuperSpeedBulkPipe)
#endif
#endif

NTSTATUS
GetStackCapability(
    _In_  WDFDEVICE   Device,
    _In_  const GUID* CapabilityType,
    _In_ ULONG       OutputBufferLength,
    _When_(OutputBufferLength == 0, _Pre_null_)
    _When_(OutputBufferLength != 0, _Out_writes_bytes_(OutputBufferLength))
         PUCHAR      OutputBuffer
    )
/*++

Routine Description:

    The helper routine gets stack's capability.

Arguments:

    Device - WDF Device Object

    CapabilityType - Pointer to capability type GUID

    OutputBufferLength - Length of output buffer

    OutPutBuffer - Output buffer

Return Value:

    NTSTATUS

--*/

{
    PDEVICE_CONTEXT  pDevContext;
    NTSTATUS status;

    PAGED_CODE();

    pDevContext = GetDeviceContext(Device);

    //
    // Note: All super speed bulk stream I/O transfers use USBD Handle obtained in
    //       UsbSamp_EvtDeviceAdd. If you call WdfUsbTargetDeviceQueryUsbCapability
    //       method instead of USBD_QueryUsbCapability here, it will not set stream 
    //       capabilites for USBD Handle used by stream transfer in which case 
    //       the open streams request will fail in this example.
    //
    status = USBD_QueryUsbCapability(pDevContext->UsbdHandle,
                                      CapabilityType,
                                      OutputBufferLength,
                                      OutputBuffer,
                                      NULL);
    if (NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("USBD_QueryUsbCapability %x\n", status));
    }

    return status;    
}

#if (NTDDI_VERSION >= NTDDI_WIN8)
                     
NTSTATUS
InitializePipeContextForSuperSpeedBulkPipe(
    _In_ PDEVICE_CONTEXT            DeviceContext,
    _In_ UCHAR                      InterfaceNumber,
    _In_ WDFUSBPIPE                 Pipe
    )
/*++

Routine Description:

    This routine initialize pipe's streams context.

Arguments:

    DeviceContext - pointer to device context

    InterfaceNumber - InterfaceNumber of selected interface

    Pipe - Bullk Pipe

Return Value:

    NTSTATUS

--*/

{
    WDF_USB_PIPE_INFORMATION    pipeInfo;
    PPIPE_CONTEXT               pipeContext;
    PUSB_ENDPOINT_DESCRIPTOR    pEndpointDescriptor;
    PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR pEndpointCompanionDescriptor;

    UCHAR               endpointAddress;
    ULONG               maxStreams;
    ULONG               supportedStreams;
    PUSBSAMP_STREAM_INFO pStreamInfo;
    NTSTATUS            status;
    PURB                pUrb = NULL;
    ULONG               i;

    PAGED_CODE();

    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(Pipe, &pipeInfo);
    pipeContext = GetPipeContext(Pipe);
    pStreamInfo = &pipeContext->StreamInfo;
    
    pStreamInfo->NumberOfStreams = 0;
    pStreamInfo->StreamList = NULL;
 
    pipeContext->StreamConfigured = FALSE;
    
    //
    // Validate that the endpoint/pipe is of type BULK.
    // Streams are only allowed on a SS BULK endpoint.
    // Also ensure that the bus actually supports streams
    // before proceeding
    //
    if (pipeInfo.PipeType != WdfUsbPipeTypeBulk ||
        DeviceContext->NumberOfStreamsSupportedByController == 0) {
        status = STATUS_SUCCESS;
        goto End;
    }

    endpointAddress = pipeInfo.EndpointAddress;

    pEndpointDescriptor = GetEndpointDescriptorForEndpointAddress(
                                DeviceContext,
                                InterfaceNumber,
                                endpointAddress,
                                &pEndpointCompanionDescriptor);

    if (pEndpointDescriptor != NULL &&
        pEndpointCompanionDescriptor != NULL) {
        
        maxStreams = pEndpointCompanionDescriptor->bmAttributes.Bulk.MaxStreams;

        if (maxStreams == 0) {

            supportedStreams = 0;
        
        } else {
        
            supportedStreams = 1 << maxStreams;
        }

    } else {
    
        UsbSamp_DbgPrint(1, ("Endpoint Descriptor or Endpoint Companion Descriptor is NULL.\n"));
        status = STATUS_INVALID_PARAMETER;
        goto End;
    
    }

    if (supportedStreams == 0) {
        status = STATUS_SUCCESS;
        goto End;
    }

    if (supportedStreams > DeviceContext->NumberOfStreamsSupportedByController) {
        supportedStreams = DeviceContext->NumberOfStreamsSupportedByController;
    }

    pStreamInfo->NumberOfStreams = supportedStreams;

    pStreamInfo->StreamList = ExAllocatePoolWithTag(
                                    NonPagedPool,
                                    supportedStreams * sizeof(USBD_STREAM_INFORMATION),
                                    POOL_TAG);

    if (pStreamInfo->StreamList == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto End;
    }

    for(i = 0; i < supportedStreams; i++)
    {
        pStreamInfo->StreamList[i].StreamID = i + 1;
    }

    status = USBD_UrbAllocate(DeviceContext->UsbdHandle, &pUrb);

    if (!NT_SUCCESS(status)){
        pUrb = NULL;
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto End;
    }

    pUrb->UrbOpenStaticStreams.Hdr.Length = sizeof(struct _URB_OPEN_STATIC_STREAMS);
    pUrb->UrbOpenStaticStreams.Hdr.Function = URB_FUNCTION_OPEN_STATIC_STREAMS;
    pUrb->UrbOpenStaticStreams.PipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(Pipe);
    pUrb->UrbOpenStaticStreams.NumberOfStreams = pStreamInfo->NumberOfStreams;
    pUrb->UrbOpenStaticStreams.StreamInfoSize = sizeof(USBD_STREAM_INFORMATION);
    pUrb->UrbOpenStaticStreams.Streams = pStreamInfo->StreamList;

    // Send the URB down the stack
    status = WdfUsbTargetPipeSendUrbSynchronously(
                                                  Pipe,
                                                  NULL,
                                                  NULL,
                                                  pUrb                           
                                                  );

    if (NT_SUCCESS(status)) {

         pipeContext->StreamConfigured = TRUE;
  
    }
End:
    if (!NT_SUCCESS(status)) {

        pipeContext->StreamConfigured = FALSE;
        pStreamInfo->NumberOfStreams = 0;

        if (pStreamInfo->StreamList != NULL) {
            ExFreePool(pStreamInfo->StreamList);
            pStreamInfo->StreamList = NULL;
        }

    }

    if(pUrb != NULL) {
        USBD_UrbFree(DeviceContext->UsbdHandle, pUrb);
    }

    return status;
}


USBD_PIPE_HANDLE
GetStreamPipeHandleFromBulkPipe(
    _In_ WDFUSBPIPE                 Pipe
    )
/*++

Routine Description:

    This routine gets a stream USBD_PIPE_HANDLE from a super speed bulk pipe

Arguments:

    Pipe - Bullk Pipe

Return Value:

    A stream's USBD_PIPE_HANDLE

--*/
{
    PPIPE_CONTEXT               pipeContext;

    PUSBSAMP_STREAM_INFO        pStreamInfo;
    USBD_PIPE_HANDLE            streamPipeHandle;
    ULONG                       index;

    pipeContext = GetPipeContext(Pipe);

    if (pipeContext->StreamConfigured == FALSE) 
    {
        streamPipeHandle = NULL;
        goto End;
    }

    pStreamInfo = &pipeContext->StreamInfo;

    if (pStreamInfo->NumberOfStreams == 0 ||
        pStreamInfo->StreamList == NULL)
    {
         streamPipeHandle = NULL;
         goto End;
    }

    //
    // Specify one associate stream's PipeHandle as the super speed bulk endpoint's PipeHandle
    //
    index = 1;

    streamPipeHandle = pStreamInfo->StreamList[index].PipeHandle;

End:
    return streamPipeHandle;

}

VOID
ConfigureStreamPipeHandleForRequest(
    _In_ WDFREQUEST       Request,
    _In_ WDFUSBPIPE       Pipe
    )
/*++

Routine Description:

    The framework has formated request for super speed bulk pipe. 
    For stream transfer, use the associated stream's PipeHandle for transfer.

Arguments:
    
    Request - Read/Write Request.

    Pipe - Bullk Pipe

Return Value:

    NULL

--*/
{
    PIRP                irp;
    PIO_STACK_LOCATION  irpSp;
    PURB                urb;

    //
    // Get the IRP that is associated with the framework request object.
    //
    irp = WdfRequestWdmGetIrp(Request);

    //
    // Obtain the next-lower driver's I/O stack location in the IRP
    //
    irpSp = IoGetNextIrpStackLocation(irp);

    //
    // The framework uses pipe's Pipehandle for data transfer by default.
    // For stream transfer, we should use the associated stream's PipeHandle of 
    // the super speed bulk pipe for transfer. Replace the PipeHandle with 
    // its associated stream's PipeHandle .
    //
    urb = irpSp->Parameters.Others.Argument1;
    urb->UrbBulkOrInterruptTransfer.PipeHandle = GetStreamPipeHandleFromBulkPipe(Pipe);

}


#endif

ULONG
GetMaxTransferSize(
    _In_ WDFUSBPIPE         Pipe,
    _In_ PDEVICE_CONTEXT    DeviceContext
)
/*++

Routine Description:

    This routine returns maximum packet size of a bulk pipe

Arguments:
    
    Pipe - Bullk Pipe

Return Value:

    Maximum Packet Size

--*/
{
    ULONG           maxTransferSize;
    PPIPE_CONTEXT   pipeContext;
    
    pipeContext = GetPipeContext(Pipe);

    if (pipeContext->StreamConfigured == TRUE) {

        //
        // For super speed bulk stream pipe, the max transfer size is
        // MAX_STREAM_VALID_PACKET_SIZE which depends on the implementation
        // of super speed bulk stream endpoint
        //
        maxTransferSize = MAX_STREAM_VALID_PACKET_SIZE;

    }
    else{
        if (DeviceContext->IsDeviceSuperSpeed == TRUE)
        {
            maxTransferSize = MAX_SUPER_SPEED_TRANSFER_SIZE;
        } 
        else if (DeviceContext->IsDeviceHighSpeed == TRUE)
        {
            maxTransferSize = MAX_HIGH_SPEED_TRANSFER_SIZE;
        }
        else
        {         
            maxTransferSize = MAX_FULL_SPEED_TRANSFER_SIZE;
        }
            
    }

    return maxTransferSize;
}




  


Our Services

  • What our customers say about us?

© 2011-2024 All Rights Reserved. Joya Systems. 4425 South Mopac Building II Suite 101 Austin, TX 78735 Tel: 800-DEV-KERNEL

Privacy Policy. Terms of use. Valid XHTML & CSS