Beispiel #1
0
VOID GFilterIOCallback(	IN	WDFDEVICE	Device,
						IN	WDFREQUEST	Request)
{
	NTSTATUS 				status;
	WDF_REQUEST_PARAMETERS 	params;
	char 					*buf;
	size_t					bufLength;	

	// Filter the desired information
	WDF_REQUEST_PARAMETERS_INIT(&params);
	WdfRequestGetParameters(Request,
							&params);
	switch (params.Type)
	{
		//!todo - Record the IRP contents
		case WdfRequestTypeRead:
			DEBUG("Intercepted Read IRP");
			// We must register a callback for when the read completes (in case it is asynchronous) so the buffers will contain something from
			// the device (or what ever driver is below us).
			WdfRequestSetCompletionRoutine(	Request,
											GFilterReadCompleteionRoutine,
											WDF_NO_CONTEXT); // This should be the filter|device context so we can pass the results to the PDO
			break;
		case WdfRequestTypeWrite:
			DEBUG("Intercepted Write IRP");
			status = WdfRequestRetrieveInputBuffer(	Request,	//!todo This should work for BUFFERED and DIRECT, but I think it will break for Neither !!
													1,
													(PVOID)&buf,
													&bufLength);
			CHECKSTATUS(status, ERROR("Failed to retrieve intercepted write buffer. 0x%0.4", status); break;);
			DEBUG("Intercepted Write of %d bytes: %#0.2x ...", bufLength, (unsigned char)buf[0]);			
			//!todo place the buf into the RAW PDO context
			break;
		// All else can just be passed on...
	}
//读操作
VOID RamDiskEvtIoRead(IN WDFQUEUE Queue,IN WDFREQUEST Request,IN size_t Length)
{
    PDEVICE_EXTENSION      devExt = QueueGetExtension(Queue)->DeviceExtension;
    //从队列对象获得设备扩展
    NTSTATUS               Status = STATUS_INVALID_PARAMETER;
    WDF_REQUEST_PARAMETERS Parameters;
    LARGE_INTEGER          ByteOffset;
    WDFMEMORY              hMemory;

    //__analysis_assume(Length > 0);
    //参数清0
    WDF_REQUEST_PARAMETERS_INIT(&Parameters);
    //从请求中获取信息
    WdfRequestGetParameters(Request, &Parameters);
    //读取偏移
    ByteOffset.QuadPart = Parameters.Parameters.Read.DeviceOffset;
    //检测读取是否合法
    if (RamDiskCheckParameters(devExt, ByteOffset, Length))
    {
        //获得内存状态
        Status = WdfRequestRetrieveOutputMemory(Request, &hMemory);
        if(NT_SUCCESS(Status))
        {
            // Destination # Offset into the destination # source
            Status = WdfMemoryCopyFromBuffer(hMemory,0, devExt->DiskImage + ByteOffset.LowPart, Length);
        }
    }

    WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length);
}
// 写操作
VOID RamDiskEvtIoWrite(IN WDFQUEUE Queue,IN WDFREQUEST Request,IN size_t Length)
{
    PDEVICE_EXTENSION      devExt = QueueGetExtension(Queue)->DeviceExtension;
    //从队列对象获得设备扩展
    NTSTATUS               Status = STATUS_INVALID_PARAMETER;
    WDF_REQUEST_PARAMETERS Parameters;
    LARGE_INTEGER          ByteOffset;
    WDFMEMORY              hMemory;

    //__analysis_assume(Length > 0);
    //参数清0
    WDF_REQUEST_PARAMETERS_INIT(&Parameters);
    //从请求中获取信息
    WdfRequestGetParameters(Request, &Parameters);
    //写入偏移
    ByteOffset.QuadPart = Parameters.Parameters.Write.DeviceOffset;
    //检测写入是否合法
    if (RamDiskCheckParameters(devExt, ByteOffset, Length))
    {
        // from output to input
        Status = WdfRequestRetrieveInputMemory(Request, &hMemory);
        //获得内存状态
        if(NT_SUCCESS(Status))
        {
            // Source # offset in Source memory where the copy has to start # destination
            Status = WdfMemoryCopyToBuffer(hMemory, 0,devExt->DiskImage + ByteOffset.LowPart, Length);
            // from "from" to "to"
        }

    }

    WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length);
}
Beispiel #4
0
VOID
RamDiskEvtIoWrite(
    IN WDFQUEUE Queue,
    IN WDFREQUEST Request,
    IN size_t Length
    )

/*++

Routine Description:

    This event is invoked when the framework receives IRP_MJ_WRITE request.

Arguments:

    Queue -  Handle to the framework queue object that is associated with the
             I/O request.

    Request - Handle to a framework request object.

    Length - Length of the data buffer associated with the request.
             The default property of the queue is to not dispatch
             zero length read & write requests to the driver and
             complete is with status success. So we will never get
             a zero length request.

Return Value:

    VOID

--*/
{
    PDEVICE_EXTENSION      devExt = QueueGetExtension(Queue)->DeviceExtension;
    NTSTATUS               Status = STATUS_INVALID_PARAMETER;
    WDF_REQUEST_PARAMETERS Parameters;
    LARGE_INTEGER          ByteOffset;
    WDFMEMORY              hMemory;

    _Analysis_assume_(Length > 0);

    WDF_REQUEST_PARAMETERS_INIT(&Parameters);
    WdfRequestGetParameters(Request, &Parameters);

    ByteOffset.QuadPart = Parameters.Parameters.Write.DeviceOffset;

    if (RamDiskCheckParameters(devExt, ByteOffset, Length)) {

        Status = WdfRequestRetrieveInputMemory(Request, &hMemory);
        if(NT_SUCCESS(Status)){

            Status = WdfMemoryCopyToBuffer(hMemory, // Source
                                    0,              // offset in Source memory where the copy has to start
                                    devExt->DiskImage + ByteOffset.LowPart, // destination
                                    Length);
        }

    }

    WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length);
}
VOID
XenUsb_EvtRequestCancelPvUrb(WDFREQUEST request) {
  WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request));
  PXENUSB_DEVICE_DATA xudd = GetXudd(device);
  WDF_REQUEST_PARAMETERS wrp;
  partial_pvurb_t *partial_pvurb;
  pvurb_t *pvurb;
  KIRQL old_irql;

  FUNCTION_ENTER();
  FUNCTION_MSG("cancelling request %p\n", request);

  WDF_REQUEST_PARAMETERS_INIT(&wrp);
  KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);

  WdfRequestGetParameters(request, &wrp);
  pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
  FUNCTION_MSG("pvurb = %p\n", pvurb);
  ASSERT(pvurb);

  partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_queue.Flink;
  while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
    partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
    ASSERT(!partial_pvurb->on_ring);
    FUNCTION_MSG("partial_pvurb = %p is not yet on ring\n", partial_pvurb);
    RemoveEntryList(&partial_pvurb->entry);
    ExFreePoolWithTag(partial_pvurb, XENUSB_POOL_TAG);
    pvurb->ref--;
    partial_pvurb = next_partial_pvurb;
  }
  partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_ring.Flink;
  while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_ring) {
    partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
    partial_pvurb_t *partial_pvurb_cancel;
    FUNCTION_MSG("partial_pvurb = %p is on ring\n", partial_pvurb);
    ASSERT(partial_pvurb->on_ring);
    partial_pvurb_cancel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb_cancel), XENUSB_POOL_TAG); /* todo - use lookaside */
    ASSERT(partial_pvurb_cancel); /* what would we do if this failed? */
    partial_pvurb_cancel->req = partial_pvurb->req;
    partial_pvurb_cancel->req.pipe = usbif_setunlink_pipe(partial_pvurb_cancel->req.pipe);
    partial_pvurb_cancel->req.u.unlink.unlink_id = partial_pvurb->req.id;
    partial_pvurb_cancel->pvurb = pvurb;
    partial_pvurb_cancel->mdl = NULL;
    partial_pvurb_cancel->other_partial_pvurb = partial_pvurb;
    partial_pvurb->other_partial_pvurb = partial_pvurb_cancel;
    partial_pvurb_cancel->on_ring = FALSE;
    pvurb->ref++;
    InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb_cancel->entry);
    partial_pvurb = next_partial_pvurb;
  }
  if (pvurb->ref) {
    PutRequestsOnRing(xudd);
    KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
  } else {
    KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
    WdfRequestComplete(request, STATUS_CANCELLED);
  }
  FUNCTION_EXIT();
}
Beispiel #6
0
NTSTATUS
SerialCompleteIfError(
    PSERIAL_DEVICE_EXTENSION extension,
    WDFREQUEST Request
    )

/*++

Routine Description:

    If the current request is not an IOCTL_SERIAL_GET_COMMSTATUS request and
    there is an error and the application requested abort on errors,
    then cancel the request.

Arguments:

    extension - Pointer to the device context

    Request - Pointer to the WDFREQUEST to test.

Return Value:

    STATUS_SUCCESS or STATUS_CANCELLED.

--*/

{

    WDF_REQUEST_PARAMETERS  params;
    NTSTATUS status = STATUS_SUCCESS;

    if ((extension->HandFlow.ControlHandShake &
         SERIAL_ERROR_ABORT) && extension->ErrorWord) {

        WDF_REQUEST_PARAMETERS_INIT(&params);

        WdfRequestGetParameters(
            Request,
            &params
            );


        //
        // There is a current error in the driver.  No requests should
        // come through except for the GET_COMMSTATUS.
        //

        if ((params.Type != WdfRequestTypeDeviceControl) ||
                    (params.Parameters.DeviceIoControl.IoControlCode !=  IOCTL_SERIAL_GET_COMMSTATUS)) {
            status = STATUS_CANCELLED;
            SerialCompleteRequest(Request, status, 0);
        }

    }

    return status;

}
Beispiel #7
0
VOID
OnTopLevelIoDefault(
    _In_  WDFQUEUE    FxQueue,
    _In_  WDFREQUEST  FxRequest
    )
/*++

  Routine Description:

    Accepts all incoming requests and pends or forwards appropriately.

  Arguments:

    FxQueue -  Handle to the framework queue object that is associated with the
        I/O request.
    FxRequest - Handle to a framework request object.

  Return Value:

    None.

--*/
{
    FuncEntry(TRACE_FLAG_SPBAPI);
    
    UNREFERENCED_PARAMETER(FxQueue);

    WDFDEVICE device;
    PDEVICE_CONTEXT pDevice;
    WDF_REQUEST_PARAMETERS params;
    NTSTATUS status;

    device = WdfIoQueueGetDevice(FxQueue);
    pDevice = GetDeviceContext(device);

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(FxRequest, &params);

	status = WdfRequestForwardToIoQueue(FxRequest, pDevice->SpbQueue);

	if (!NT_SUCCESS(status))
	{
		CyapaPrint(
			DEBUG_LEVEL_ERROR,
			DBG_IOCTL,
			"Failed to forward WDFREQUEST %p to SPB queue %p - %!STATUS!",
			FxRequest,
			pDevice->SpbQueue,
			status);
		
		WdfRequestComplete(FxRequest, status);
	}

    FuncExit(TRACE_FLAG_SPBAPI);
}
static VOID
XenPci_IoWatch(char *path, PVOID context)
{
  NTSTATUS status;
  watch_context_t *watch_context = context;
  WDFFILEOBJECT file_object = watch_context->file_object;
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;
  struct xsd_sockmsg *rep;
  xenbus_read_queue_item_t *list_entry;
  size_t remaining;
  WDFREQUEST request;

  FUNCTION_ENTER();
  
  KeAcquireSpinLock(&xpdid->lock, &old_irql);
  
  remaining = sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1;
  rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1, XENPCI_POOL_TAG);
  rep->type = XS_WATCH_EVENT;
  rep->req_id = 0;
  rep->tx_id = 0;
  rep->len = (ULONG)(strlen(path) + 1 + strlen(watch_context->token) + 1);
  remaining -= sizeof(struct xsd_sockmsg);
  RtlStringCbCopyA((PCHAR)(rep + 1), remaining, path);
  remaining -= strlen(path) + 1;
  RtlStringCbCopyA((PCHAR)(rep + 1) + strlen(path) + 1, remaining, watch_context->token);
  
  list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
  list_entry->data = rep;
  list_entry->length = sizeof(*rep) + rep->len;
  list_entry->offset = 0;
  InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry);
    
  status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &request);
  if (NT_SUCCESS(status))
  {
    WDF_REQUEST_PARAMETERS parameters;
    WDF_REQUEST_PARAMETERS_INIT(&parameters);
    WdfRequestGetParameters(request, &parameters);
    
    KdPrint((__DRIVER_NAME "     found pending read - MinorFunction = %d, length = %d\n", (ULONG)parameters.MinorFunction, (ULONG)parameters.Parameters.Read.Length));
    XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, request, parameters.Parameters.Read.Length);
    KeReleaseSpinLock(&xpdid->lock, old_irql);
    WdfRequestComplete(request, STATUS_SUCCESS);
  }
  else
  {
    KdPrint((__DRIVER_NAME "     no pending read (%08x)\n", status));
    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  
  FUNCTION_EXIT();
}
static VOID
XenUsb_EvtIoDefault(
  WDFQUEUE queue,
  WDFREQUEST request)
{
  NTSTATUS status;
  WDF_REQUEST_PARAMETERS parameters;

  FUNCTION_ENTER();

  UNREFERENCED_PARAMETER(queue);

  status = STATUS_BAD_INITIAL_PC;

  WDF_REQUEST_PARAMETERS_INIT(&parameters);
  WdfRequestGetParameters(request, &parameters);

  switch (parameters.Type)
  {
  case WdfRequestTypeCreate:
    FUNCTION_MSG("WdfRequestTypeCreate\n");
    break;
  case WdfRequestTypeClose:
    FUNCTION_MSG("WdfRequestTypeClose\n");
    break;
  case WdfRequestTypeRead:
    FUNCTION_MSG("WdfRequestTypeRead\n");
    break;
  case WdfRequestTypeWrite:
    FUNCTION_MSG("WdfRequestTypeWrite\n");
    break;
  case WdfRequestTypeDeviceControl:
    FUNCTION_MSG("WdfRequestTypeDeviceControl\n");
    break;
  case WdfRequestTypeDeviceControlInternal:
    FUNCTION_MSG("WdfRequestTypeDeviceControlInternal\n");
    break;
  default:
    FUNCTION_MSG("Unknown type %x\n", parameters.Type);
    break;
  }
  WdfRequestComplete(request, status);  

  FUNCTION_EXIT();
}
__forceinline
void
PwmCreateRequestGetAccess(
    _In_ WDFREQUEST WdfRequest,
    _Out_ ACCESS_MASK* DesiredAccessPtr,
    _Out_ ULONG* ShareAccessPtr
    )
{
    NT_ASSERT(ARGUMENT_PRESENT(DesiredAccessPtr));
    NT_ASSERT(ARGUMENT_PRESENT(ShareAccessPtr));

    WDF_REQUEST_PARAMETERS wdfRequestParameters;
    WDF_REQUEST_PARAMETERS_INIT(&wdfRequestParameters);
    WdfRequestGetParameters(WdfRequest, &wdfRequestParameters);

    NT_ASSERTMSG(
        "Expected create request",
        wdfRequestParameters.Type == WdfRequestTypeCreate);

    *DesiredAccessPtr =
        wdfRequestParameters.Parameters.Create.SecurityContext->DesiredAccess;
    *ShareAccessPtr = wdfRequestParameters.Parameters.Create.ShareAccess;
}
Beispiel #11
0
///////////////////////////////////////////////////////////////////////////////
// SmplFilterEvtIoDefault
///////////////////////////////////////////////////////////////////////////////
VOID SmplFilterEvtIoDefault(
  __in  WDFQUEUE Queue,
  __in  WDFREQUEST Request
)
{
    WDF_REQUEST_PARAMETERS RequestParameters;
    BOOLEAN bResult;

    WDF_REQUEST_PARAMETERS_INIT(&RequestParameters);
    WdfRequestGetParameters(Request, &RequestParameters);
    if(WdfRequestTypeRead == RequestParameters.Type)
    {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault WdfRequestTypeRead\n");
        WdfRequestFormatRequestUsingCurrentType(Request);
        WdfRequestSetCompletionRoutine(Request, SmplFilterCompletionRoutineRead, NULL);
        bResult = WdfRequestSend(Request,
                                WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)),
                                NULL);
    }
    else
    {
        WDF_REQUEST_SEND_OPTIONS Options;
        WDF_REQUEST_SEND_OPTIONS_INIT(&Options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);

        DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault other Request type\n");

        bResult = WdfRequestSend(Request,
                                WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)),
                                &Options);
    }

    if(FALSE == bResult)
    {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "WdfRequestSend failed!\n");
        WdfRequestComplete(Request, WdfRequestGetStatus(Request));
    }
} // end SmplFilterEvtIoDefault
Beispiel #12
0
VOID
tgwinkEvtIoRead(
    WDFQUEUE Queue,
    WDFREQUEST Request,
    size_t Length
    )
{
    NTSTATUS status;
    WDFMEMORY mem;
    WDF_REQUEST_PARAMETERS params;
    ULONG offset;
    ULONG result;
    PDEVICE_CONTEXT context;
    WDFDEVICE device;
    
    device = WdfIoQueueGetDevice(Queue);
    context = DeviceGetContext(device);

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(Request, &params);

    offset = (ULONG)params.Parameters.Read.DeviceOffset;

    status = WdfRequestRetrieveOutputMemory(Request, &mem);
    if (!NT_SUCCESS(status)) {
        KdPrint("tgwinkEvtIoRead could not get request memory buffer, status 0x%x\n", status);
        WdfVerifierDbgBreakPoint();
        WdfRequestCompleteWithInformation(Request, status, 0);
        return;
    }

    result = context->busInterface.GetBusData(context->busInterface.Context, PCI_WHICHSPACE_CONFIG, WdfMemoryGetBuffer(mem, NULL), offset, (ULONG)Length);

    WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)result);
}
Beispiel #13
0
VOID
SerialStartOrQueue(
    IN PSERIAL_DEVICE_EXTENSION Extension,
    IN WDFREQUEST Request,
    IN WDFQUEUE QueueToExamine,
    IN WDFREQUEST *CurrentOpRequest,
    IN PSERIAL_START_ROUTINE Starter
    )

/*++

Routine Description:

    This routine is used to either start or queue any requst
    that can be queued in the driver.

Arguments:

    Extension - Points to the serial device extension.

    Request - The request to either queue or start.  In either
          case the request will be marked pending.

    QueueToExamine - The queue the request will be place on if there
                     is already an operation in progress.

    CurrentOpRequest - Pointer to a pointer to the request the is current
                   for the queue.  The pointer pointed to will be
                   set with to Request if what CurrentOpRequest points to
                   is NULL.

    Starter - The routine to call if the queue is empty.

Return Value:


--*/

{

    NTSTATUS status;
    PREQUEST_CONTEXT reqContext;
    WDF_REQUEST_PARAMETERS  params;

    reqContext = SerialGetRequestContext(Request);

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(
             Request,
             &params);

    //
    // If this is a write request then take the amount of characters
    // to write and add it to the count of characters to write.
    //

    if (params.Type == WdfRequestTypeWrite) {

        Extension->TotalCharsQueued += reqContext->Length;

    } else if ((params.Type == WdfRequestTypeDeviceControl) &&
               ((params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR) ||
                (params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER))) {

        reqContext->IoctlCode = params.Parameters.DeviceIoControl.IoControlCode; // We need this in the destroy callback

        Extension->TotalCharsQueued++;

    }

    if (IsQueueEmpty(QueueToExamine) &&  !(*CurrentOpRequest)) {

        //
        // There were no current operation.  Mark this one as
        // current and start it up.
        //

        *CurrentOpRequest = Request;

        Starter(Extension);

        return;

    } else {

        //
        // We don't know how long the request will be in the
        // queue.  If it gets cancelled while waiting in the queue, we will
        // be notified by EvtCanceledOnQueue callback so that we can readjust
        // the lenght or free the buffer.
        //
        reqContext->Extension = Extension; // We need this in the destroy callback

        status = WdfRequestForwardToIoQueue(Request,  QueueToExamine);
        if(!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestForwardToIoQueue failed%X\n", status);
            ASSERTMSG("WdfRequestForwardToIoQueue failed ", FALSE);
            SerialCompleteRequest(Request, status, 0);
        }

        return;
    }
}
Beispiel #14
0
NTSTATUS HidFx2SetOutput(_In_ WDFREQUEST hRequest)
{
    NTSTATUS                    status = STATUS_SUCCESS;
    PHID_XFER_PACKET            pTransferPacket = NULL;
    WDF_REQUEST_PARAMETERS      params;
    PHIDFX2_IO_REPORT           pOutputReport = NULL;
    WDFDEVICE                   hDevice;

    PAGED_CODE();

    TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n");

    hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest));

    WDF_REQUEST_PARAMETERS_INIT(&params);
    WdfRequestGetParameters(hRequest, &params);

    if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET))
    {
        status = STATUS_BUFFER_TOO_SMALL;
        TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status);
        return status;
    }

    pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer;
    if (pTransferPacket == NULL)
    {
        status = STATUS_INVALID_DEVICE_REQUEST;
        TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status);
        return status;
    }

    if (pTransferPacket->reportBufferLen == 0)
    {
        status = STATUS_BUFFER_TOO_SMALL;
        TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status);
        return status;
    }

    if (pTransferPacket->reportBufferLen < sizeof(UCHAR))
    {
        status = STATUS_BUFFER_TOO_SMALL;
        TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status);
        return status;
    }

    if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID)
    {
        status = STATUS_INVALID_DEVICE_REQUEST;
        TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status);
        return status;
    }

    pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer;

    if (pOutputReport->bData == 0)
    {
        status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_OFF);
    }
    else
    {
        status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_ON);
    }

    TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status);
    return status;
}
Beispiel #15
0
NTSTATUS HidFx2GetInput(_In_ WDFREQUEST hRequest)
{
    NTSTATUS                    status = STATUS_SUCCESS;
    WDF_REQUEST_PARAMETERS      params;
    WDFDEVICE                   hDevice;
    PHID_XFER_PACKET            pTransferPacket = NULL;
    PHIDFX2_IO_REPORT           pOutputReport = NULL;
    unsigned char               bSwitchState = 0;

    PAGED_CODE();

    TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n");

    hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest));

    WDF_REQUEST_PARAMETERS_INIT(&params);
    WdfRequestGetParameters(hRequest, &params);


    if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET))
    {
        status = STATUS_BUFFER_TOO_SMALL;
        TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status);
        return status;
    }

    pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer;
    if (pTransferPacket == NULL)
    {
        status = STATUS_INVALID_DEVICE_REQUEST;
        TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status);
        return status;
    }

    if (pTransferPacket->reportBufferLen == 0)
    {
        status = STATUS_BUFFER_TOO_SMALL;
        TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status);
        return status;
    }

    if (pTransferPacket->reportBufferLen < sizeof(UCHAR))
    {
        status = STATUS_BUFFER_TOO_SMALL;
        TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status);
        return status;
    }

    if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID)
    {
        status = STATUS_INVALID_DEVICE_REQUEST;
        TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status);
        return status;
    }

    pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer;

    // Get the switch state directly from the hardware
    status = HidFx2GetSwitchState(hDevice, &bSwitchState);
    TraceVerbose(DBG_IOCTL, "(%!FUNC!) switch state 0x%x\n", bSwitchState);

    //Mask off everything except the actual switch bit
    bSwitchState &= RADIO_SWITCH_BUTTONS_BIT_MASK;
    TraceVerbose(DBG_IOCTL, "(%!FUNC!) maskedswitch state 0x%x\n", bSwitchState);

    pOutputReport->bReportId = GENERIC_DESKTOP_REPORT_ID;
    pOutputReport->bData = bSwitchState;

    TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status);
    return status;
}
Beispiel #16
0
VOID
AmccPciEvtIoDefault(
    __in WDFQUEUE       Queue,
    __in WDFREQUEST     Request
    )
/*++

Routine Description:

    Start the IRP on the device.  This driver allows only one I/O to
    be active on the adapter at any one time.  If multiple I/Os are sent
    to the driver, they will be queued and completed as they complete on
    the adapter (one IRP per interrupt).

Arguments:

    Queue - Default queue handle
    Request - Handle to the write request
    Parameters - Contains current stack location information from the IRP

Return Value:

    None

--*/
{
    PAMCC_DEVICE_EXTENSION    devExt;
    REQUEST_CONTEXT         * transfer;
    NTSTATUS                  status;
    size_t                    length;
    WDF_DMA_DIRECTION         direction;
    WDFDMATRANSACTION         dmaTransaction;
    WDF_REQUEST_PARAMETERS    params;

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(
        Request,
        &params
        );

    //
    // Get the device extension.
    //
    devExt = AmccPciGetDevExt(WdfIoQueueGetDevice( Queue ));

    //
    // Validate and gather parameters.
    //
    switch (params.Type) {

        case WdfRequestTypeRead:
            length    = params.Parameters.Read.Length;
            direction = WdfDmaDirectionReadFromDevice;
            break;

        case WdfRequestTypeWrite:
            length    = params.Parameters.Write.Length;
            direction = WdfDmaDirectionWriteToDevice;
            break;

        default:
            TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO,
                        "Request type not Read or Write\n");
            WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
            return;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO,
                "Request %p: %s %d bytes",
                Request, (direction)?"Write":"Read", (ULONG)length);

    //
    // The length must be non-zero.
    //
    if (length == 0) {
        TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO,
                    "Zero transfer length input to read/write");
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;
    }

    transfer = GetRequestContext(Request);

    //
    // Create new DmaRequst to conduct this DMA transaction.
    //
    status = WdfDmaTransactionCreate( devExt->DmaEnabler,
                                      WDF_NO_OBJECT_ATTRIBUTES,
                                      &dmaTransaction );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaRequestCreate failed: %X", status);
        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Create new DmaTransaction.
    //
    status = WdfDmaTransactionInitializeUsingRequest( dmaTransaction,
                                                      Request,
                                                      AmccPciProgramDma,
                                                      direction );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaRequestInitializeWithRequest failed: %X",
                    status);

        WdfObjectDelete(dmaTransaction);

        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Fill transfer context structure
    //
    transfer->Request        = Request;
    transfer->DmaTransaction = dmaTransaction;

    //
    // Save the current Request as the "in-progress" request.
    //
    devExt->CurrentRequest = Request;

    //
    // Execute this dmaTransaction transaction.
    //
    status = WdfDmaTransactionExecute( dmaTransaction, WDF_NO_CONTEXT);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaTransactionExecute failed: %X",
                    status);

        WdfObjectDelete(dmaTransaction);
        WdfRequestComplete(Request, status);
        return;
    }

    return;
}
VOID
XenUsb_EvtIoInternalDeviceControl_ROOTHUB_SUBMIT_URB(
  WDFQUEUE queue,
  WDFREQUEST request,
  size_t output_buffer_length,
  size_t input_buffer_length,
  ULONG io_control_code)
{
  //NTSTATUS status;
  WDFDEVICE device = WdfIoQueueGetDevice(queue);
  PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
  PXENUSB_DEVICE_DATA xudd = GetXudd(xupdd->wdf_device_bus_fdo);
  WDF_REQUEST_PARAMETERS wrp;
  PURB urb;
  PUSBD_INTERFACE_INFORMATION interface_information;
  ULONG i, j;
  xenusb_device_t *usb_device;
  xenusb_endpoint_t *endpoint;
  //USB_DEFAULT_PIPE_SETUP_PACKET setup_packet;
  urb_decode_t decode_data;
  ULONG decode_retval;

  UNREFERENCED_PARAMETER(input_buffer_length);
  UNREFERENCED_PARAMETER(output_buffer_length);
  UNREFERENCED_PARAMETER(io_control_code);

  //FUNCTION_ENTER();

  WDF_REQUEST_PARAMETERS_INIT(&wrp);
  WdfRequestGetParameters(request, &wrp);

  urb = (PURB)wrp.Parameters.Others.Arg1;
  ASSERT(urb);
#if 0
  FUNCTION_MSG("urb = %p\n", urb);
  FUNCTION_MSG(" Length = %d\n", urb->UrbHeader.Length);
  FUNCTION_MSG(" Function = %d\n", urb->UrbHeader.Function);
  FUNCTION_MSG(" Status = %d\n", urb->UrbHeader.Status);
  FUNCTION_MSG(" UsbdDeviceHandle = %p\n", urb->UrbHeader.UsbdDeviceHandle);
  FUNCTION_MSG(" UsbdFlags = %08x\n", urb->UrbHeader.UsbdFlags);
#endif
  usb_device = urb->UrbHeader.UsbdDeviceHandle;

  if (!usb_device)
    usb_device = xupdd->usb_device;

  decode_retval = XenUsb_DecodeControlUrb(urb, &decode_data);
  if (decode_retval == URB_DECODE_UNKNOWN)
  {
    FUNCTION_MSG("Unknown URB - Calling WdfRequestCompletestatus with status = %08x\n", STATUS_UNSUCCESSFUL); //STATUS_UNSUCCESSFUL);
    urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
    WdfRequestComplete(request, STATUS_UNSUCCESSFUL);
    return;
  }

  urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
  
  if (decode_retval != URB_DECODE_NOT_CONTROL)
  {
    FUNCTION_MSG("bmRequestType = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.B);
    FUNCTION_MSG(" Recipient = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
    FUNCTION_MSG(" Type = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type);
    FUNCTION_MSG(" Dir = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Dir);
    FUNCTION_MSG("bRequest = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bRequest);
    FUNCTION_MSG("wValue = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W);
    FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.LowByte);
    FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte);
    FUNCTION_MSG("wIndex = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex);
    FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte);
    FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.HiByte);
    FUNCTION_MSG("wLength = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wLength);
  }
  
  switch(urb->UrbHeader.Function)
  {
  case URB_FUNCTION_SELECT_CONFIGURATION:
    FUNCTION_MSG("URB_FUNCTION_SELECT_CONFIGURATION\n");
    FUNCTION_MSG(" ConfigurationDescriptor = %p\n", urb->UrbSelectConfiguration.ConfigurationDescriptor);
    if (urb->UrbSelectConfiguration.ConfigurationDescriptor)
    {
      FUNCTION_MSG("  bLength = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bLength);
      FUNCTION_MSG("  bDescriptorType = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bDescriptorType);
      FUNCTION_MSG("  wTotalLength = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->wTotalLength);
      FUNCTION_MSG("  bNumInterfaces = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces);
      FUNCTION_MSG("  bConfigurationValue = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue);
      FUNCTION_MSG("  iConfiguration = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->iConfiguration);
      FUNCTION_MSG("  bmAttributes = %04x\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bmAttributes);
      FUNCTION_MSG("  MaxPower = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->MaxPower);
    }
    FUNCTION_MSG(" ConfigurationHandle = %p\n", urb->UrbSelectConfiguration.ConfigurationHandle);
    if (urb->UrbSelectConfiguration.ConfigurationDescriptor)
    {
      urb->UrbSelectConfiguration.ConfigurationHandle = xupdd->usb_device->configs[0];
      interface_information = &urb->UrbSelectConfiguration.Interface;
      for (i = 0; i < urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces; i++)
      {
        FUNCTION_MSG("InterfaceInformation[%d]\n", i);
        FUNCTION_MSG(" Length = %d\n", interface_information->Length);
        FUNCTION_MSG(" InterfaceNumber = %d\n", interface_information->InterfaceNumber);
        FUNCTION_MSG(" AlternateSetting = %d\n", interface_information->AlternateSetting);
        FUNCTION_MSG(" Class = %02x\n", (ULONG)interface_information->Class);
        FUNCTION_MSG(" SubClass = %02x\n", (ULONG)interface_information->SubClass);
        FUNCTION_MSG(" Protocol = %02x\n", (ULONG)interface_information->Protocol);
        FUNCTION_MSG(" Reserved = %02x\n", (ULONG)interface_information->Reserved);
        FUNCTION_MSG(" InterfaceHandle = %p\n", interface_information->InterfaceHandle);
        FUNCTION_MSG(" NumberOfPipes = %d\n", interface_information->NumberOfPipes);
        interface_information->InterfaceHandle = xupdd->usb_device->configs[0]->interfaces[0];
        interface_information->Class = 0x09;
        interface_information->SubClass = 0x00;
        interface_information->SubClass = 0x00;
        for (j = 0; j < interface_information->NumberOfPipes; j++)
        {
          FUNCTION_MSG(" Pipe[%d]\n", i);
          FUNCTION_MSG("  MaximumPacketSize = %d\n", interface_information->Pipes[j].MaximumPacketSize);
          FUNCTION_MSG("  EndpointAddress = %d\n", interface_information->Pipes[j].EndpointAddress);
          FUNCTION_MSG("  Interval = %d\n", interface_information->Pipes[j].Interval);
          FUNCTION_MSG("  PipeType = %d\n", interface_information->Pipes[j].PipeType);
          FUNCTION_MSG("  PipeHandle = %d\n", interface_information->Pipes[j].PipeHandle);
          FUNCTION_MSG("  MaximumTransferSize = %d\n", interface_information->Pipes[j].MaximumTransferSize);
          FUNCTION_MSG("  PipeFlags = %08x\n", interface_information->Pipes[j].PipeFlags);
          interface_information->Pipes[j].MaximumPacketSize = 2;
          interface_information->Pipes[j].EndpointAddress = 0x81;
          interface_information->Pipes[j].Interval = 12;
          interface_information->Pipes[j].PipeType = UsbdPipeTypeInterrupt;
          interface_information->Pipes[j].PipeHandle = xupdd->usb_device->configs[0]->interfaces[0]->endpoints[j];
          interface_information->Pipes[j].MaximumTransferSize = 4096; /* made up number - possibly not used */
          // this is input actually interface_information->Pipes[j].PipeFlags = 0;
        }
        interface_information = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)interface_information + interface_information->Length);
      }
    }
    urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
    break;
  case URB_FUNCTION_SELECT_INTERFACE:
    FUNCTION_MSG("URB_FUNCTION_SELECT_INTERFACE\n");
    interface_information = &urb->UrbSelectInterface.Interface;
    FUNCTION_MSG("InterfaceInformation\n");
    FUNCTION_MSG(" Length = %d\n", interface_information->Length);
    FUNCTION_MSG(" InterfaceNumber = %d\n", interface_information->InterfaceNumber);
    FUNCTION_MSG(" AlternateSetting = %d\n", interface_information->AlternateSetting);
    FUNCTION_MSG(" Class = %02x\n", (ULONG)interface_information->Class);
    FUNCTION_MSG(" SubClass = %02x\n", (ULONG)interface_information->SubClass);
    FUNCTION_MSG(" Protocol = %02x\n", (ULONG)interface_information->Protocol);
    FUNCTION_MSG(" Reserved = %02x\n", (ULONG)interface_information->Reserved);
    FUNCTION_MSG(" InterfaceHandle = %p\n", interface_information->InterfaceHandle);
    FUNCTION_MSG(" NumberOfPipes = %d\n", interface_information->NumberOfPipes);
    for (i = 0; i < interface_information->NumberOfPipes; i++)
    {
      FUNCTION_MSG(" Pipe[%d]\n", i);
      FUNCTION_MSG("  MaximumPacketSize = %d\n", interface_information->Pipes[i].MaximumPacketSize);
      FUNCTION_MSG("  EndpointAddress = %d\n", interface_information->Pipes[i].EndpointAddress);
      FUNCTION_MSG("  Interval = %d\n", interface_information->Pipes[i].Interval);
      FUNCTION_MSG("  PipeType = %d\n", interface_information->Pipes[i].PipeType);
      FUNCTION_MSG("  PipeHandle = %d\n", interface_information->Pipes[i].PipeHandle);
      FUNCTION_MSG("  MaximumTransferSize = %d\n", interface_information->Pipes[i].MaximumTransferSize);
      FUNCTION_MSG("  PipeFlags = %08x\n", interface_information->Pipes[i].PipeFlags);
    }
    urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
    break;
#if (NTDDI_VERSION >= NTDDI_VISTA)  
  case URB_FUNCTION_CONTROL_TRANSFER_EX:
#endif
  case URB_FUNCTION_CONTROL_TRANSFER:
  case URB_FUNCTION_CLASS_DEVICE:
  case URB_FUNCTION_CLASS_OTHER:
  case URB_FUNCTION_CLASS_INTERFACE:
  case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
  case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
  case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
    switch(decode_data.setup_packet.default_pipe_setup_packet.bRequest)
    {
    case USB_REQUEST_GET_STATUS:
      // switch device, interface, endpoint
      switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type)
      {
      case BMREQUEST_STANDARD:
        FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n");
        FUNCTION_MSG(" Type=Standard\n");
        switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient)
        {
        case BMREQUEST_TO_DEVICE:
          FUNCTION_MSG("  Recipient=Device\n");
          ((PUSHORT)decode_data.buffer)[0] = 0x0001; /* self powered */
          urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
          break;
        default:
          FUNCTION_MSG(" Recipient=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
          break;
        }
        break;
      case BMREQUEST_CLASS:
        switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient)
        {
        case BMREQUEST_TO_DEVICE:
          ((PUSHORT)decode_data.buffer)[0] = 0x0000;
          ((PUSHORT)decode_data.buffer)[1] = 0x0000;
          urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
          break;
        case BMREQUEST_TO_OTHER:
          FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n");
          FUNCTION_MSG(" Type=Class\n");
          FUNCTION_MSG("  Recipient=Other (port = %d)\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte);
          ((PUSHORT)decode_data.buffer)[0] = xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status;
          ((PUSHORT)decode_data.buffer)[1] = xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change;
          urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
          FUNCTION_MSG(" status = %04x, change = %04x\n",
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status,
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change);
          break;
        default:
          FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n");
          FUNCTION_MSG(" Type=Class\n");
          FUNCTION_MSG(" Recipient=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
          break;
        }
        break;
      default:
        FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n");
        FUNCTION_MSG(" Type=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type);
        break;
      }
      break;      
    case USB_REQUEST_GET_DESCRIPTOR:
      FUNCTION_MSG(" USB_REQUEST_GET_DESCRIPTOR\n");
      // should separate into Standard and Class
      switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte)
      {
      case USB_DEVICE_DESCRIPTOR_TYPE:
        FUNCTION_MSG(" USB_DEVICE_DESCRIPTOR_TYPE\n");
        FUNCTION_MSG(" length = %d\n", *decode_data.length);
        memcpy(decode_data.buffer, &usb_device->device_descriptor, sizeof(USB_DEVICE_DESCRIPTOR));
        *decode_data.length = sizeof(USB_DEVICE_DESCRIPTOR);
        urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
        break;
      case USB_CONFIGURATION_DESCRIPTOR_TYPE:
      {
        xenusb_config_t *usb_config;
        PUCHAR ptr;

        FUNCTION_MSG(" USB_CONFIGURATION_DESCRIPTOR_TYPE\n");
        FUNCTION_MSG(" length = %d\n", *decode_data.length);
        usb_config = usb_device->active_config;
        ptr = (PUCHAR)decode_data.buffer;
        memcpy(ptr, &usb_config->config_descriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
        ptr += sizeof(USB_CONFIGURATION_DESCRIPTOR);
        ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
        if (*decode_data.length > 9)
        {
          for (i = 0; i < usb_config->config_descriptor.bNumInterfaces; i++)
          {
            memcpy(ptr, &usb_config->interfaces[i]->interface_descriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
            ptr += sizeof(USB_INTERFACE_DESCRIPTOR);
            ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength += sizeof(USB_INTERFACE_DESCRIPTOR);
            for (j = 0; j < usb_config->interfaces[i]->interface_descriptor.bNumEndpoints; j++)
            {
              memcpy(ptr, &usb_config->interfaces[i]->endpoints[j]->endpoint_descriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
              ptr += sizeof(USB_ENDPOINT_DESCRIPTOR);
              ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength += sizeof(USB_ENDPOINT_DESCRIPTOR);
            }
          }
        }
        *decode_data.length = ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength;
        //if (urb->UrbControlDescriptorRequest.TransferBufferLength == 9)
        //  ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength = 32;
        urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
        break;
      } 
      case 0x00: // unknown... doing the same as 0x29 seems to work
        FUNCTION_MSG(" USB_00_DESCRIPTOR_TYPE (doesn't exist)\n");
        urb->UrbHeader.Status = USBD_STATUS_BAD_DESCRIPTOR;
        break;
      case 0x29: // Hub Descriptor
      {
        PUSB_HUB_DESCRIPTOR uhd;
        
        FUNCTION_MSG(" USB_HUB_DESCRIPTOR_TYPE\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte);
        FUNCTION_MSG(" length = %d\n", *decode_data.length);
        uhd = decode_data.buffer;
        // TODO adjust for real number of ports
        *decode_data.length = FIELD_OFFSET(USB_HUB_DESCRIPTOR, bRemoveAndPowerMask[0]) + 2 + 1;
        uhd->bDescriptorLength = (UCHAR)*decode_data.length;
        uhd->bDescriptorType = 0x29;
        uhd->bNumberOfPorts = (UCHAR)xudd->num_ports;
        uhd->wHubCharacteristics = 0x0012; // no power switching no overcurrent protection
        uhd->bPowerOnToPowerGood = 1; // 2ms units
        uhd->bHubControlCurrent = 0;
        // DeviceRemovable bits (includes an extra bit at the start)
        uhd->bRemoveAndPowerMask[0] = 0;
        uhd->bRemoveAndPowerMask[1] = 0;
        // PortPwrCtrlMask
        uhd->bRemoveAndPowerMask[2] = 0xFF;
        urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
        break;
      }
      default:
        FUNCTION_MSG(" USB_%02x_DESCRIPTOR_TYPE\n", (ULONG)decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte);
        FUNCTION_MSG("bmRequestType = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.B);
        FUNCTION_MSG(" Recipient = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
        FUNCTION_MSG(" Type = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type);
        FUNCTION_MSG(" Dir = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Dir);
        FUNCTION_MSG("bRequest = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bRequest);
        FUNCTION_MSG("wValue = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W);
        FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.LowByte);
        FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte);
        FUNCTION_MSG("wIndex = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex);
        FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte);
        FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.HiByte);
        FUNCTION_MSG("wLength = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wLength);
        break;
      }
      break;
    case USB_REQUEST_CLEAR_FEATURE:
      FUNCTION_MSG(" USB_REQUEST_CLEAR_FEATURE\n");
      switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type)
      {
      case BMREQUEST_STANDARD: /* Standard */
        FUNCTION_MSG("  Type=Standard\n");
        switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient)
        {
        case BMREQUEST_TO_DEVICE:
          FUNCTION_MSG("  Recipient=Device\n");
          switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.W)
          {
          case 1: /* DEVICE_REMOTE_WAKEUP */
            FUNCTION_MSG("  Feature=DEVICE_REMOTE_WAKEUP\n");
            /* fake this */
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          default:
            FUNCTION_MSG(__DRIVER_NAME "       Feature=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W);
            break;
          }
          break;
        default:
          FUNCTION_MSG(__DRIVER_NAME "       Recipient=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
          break;
        }
        break;
        break;
      case BMREQUEST_CLASS: /* Class */
        FUNCTION_MSG("  Type=Class\n");
        switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient)
        {
        case BMREQUEST_TO_OTHER:
          FUNCTION_MSG("  Recipient=Other (port = %d)\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte);
          switch (urb->UrbControlVendorClassRequest.Value)
          {
          case PORT_ENABLE:
            FUNCTION_MSG("   PORT_ENABLE\n");
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status &= ~(1 << PORT_ENABLE);
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          case PORT_SUSPEND:
            FUNCTION_MSG("   PORT_SUSPEND (NOOP)\n");
            /* do something here */
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          case C_PORT_CONNECTION:
            FUNCTION_MSG("   C_PORT_CONNECTION\n");
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change &= ~(1 << PORT_CONNECTION);
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          case C_PORT_ENABLE:
            FUNCTION_MSG("   C_PORT_ENABLE\n");
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change &= ~(1 << PORT_ENABLE);
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          case C_PORT_RESET:
            FUNCTION_MSG("   C_PORT_RESET\n");
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change &= ~(1 << PORT_RESET);
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          default:
            FUNCTION_MSG("   Unknown Value %04X\n", urb->UrbControlVendorClassRequest.Value);
            break;
          }
          FUNCTION_MSG("   status = %04x, change = %04x\n",
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status,
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change);
          break;
        default:
          FUNCTION_MSG(" Recipient=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
          break;
        }
        break;
      default:
        FUNCTION_MSG("  Type=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type);
        break;
      }
      break;
    case USB_REQUEST_SET_FEATURE:
      FUNCTION_MSG(" USB_REQUEST_SET_FEATURE\n");
      FUNCTION_MSG("  SetPortFeature\n");
      switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type)
      {
      case 0: /* Standard */
        FUNCTION_MSG("  Type=Standard\n");
        switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient)
        {
        case BMREQUEST_TO_DEVICE:
          FUNCTION_MSG("  Recipient=Device\n");
          switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.W)
          {
          case 1: /* DEVICE_REMOTE_WAKEUP */
            FUNCTION_MSG("  Feature=DEVICE_REMOTE_WAKEUP\n");
            /* fake this */
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          default:
            FUNCTION_MSG(__DRIVER_NAME "       Feature=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W);
            break;
          }
          break;
        default:
          FUNCTION_MSG(__DRIVER_NAME "       Recipient=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
          break;
        }
        break;
      case 1: /* Class */
        FUNCTION_MSG("  Type=Class\n");
        switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient)
        {
        case BMREQUEST_TO_OTHER:
          FUNCTION_MSG("  Recipient=Other (port = %d)\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte);
          switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.W)
          {
          case PORT_ENABLE:
            FUNCTION_MSG("   PORT_ENABLE (NOOP)\n");
            /* do something here */
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          case PORT_SUSPEND:
            FUNCTION_MSG("   PORT_SUSPEND (NOOP)\n");
            /* do something here */
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          case PORT_RESET:
            FUNCTION_MSG("   PORT_RESET\n");
            /* just fake the reset by setting the status bit to indicate that the reset is complete*/
            //xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status |= (1 << PORT_RESET);
            //xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].reset_counter = 10;
            // TODO: maybe fake a 10ms time here...
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status &= ~(1 << PORT_RESET);
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status |= (1 << PORT_ENABLE);
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change |= (1 << PORT_RESET);
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            endpoint = xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0];
            XenUsbHub_ProcessHubInterruptEvent(endpoint);
            break;
          case PORT_POWER:
            FUNCTION_MSG("   PORT_POWER\n");
            xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status |= (1 << PORT_POWER);
            urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
            break;
          default:
            FUNCTION_MSG("   PORT_%04X\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W);
            break;
          }
          FUNCTION_MSG("   status = %04x, change = %04x\n",
            xudd->ports[urb->UrbControlVendorClassRequest.Index - 1].port_status,
            xudd->ports[urb->UrbControlVendorClassRequest.Index - 1].port_change);
          break;
        default:
          FUNCTION_MSG(__DRIVER_NAME "       Recipient=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
          break;
        }
        break;
      }
      break;
    default:
      FUNCTION_MSG(" USB_REQUEST_%02x\n", (ULONG)decode_data.setup_packet.default_pipe_setup_packet.bRequest);
      FUNCTION_MSG(" TransferBufferLength returned = %d\n", urb->UrbControlDescriptorRequest.TransferBufferLength);
      break;
    }
    break;
  case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
    FUNCTION_MSG("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL\n");
    FUNCTION_MSG(" PipeHandle = %p\n", urb->UrbPipeRequest.PipeHandle);
    urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
    break;
  case URB_FUNCTION_ABORT_PIPE:
    FUNCTION_MSG("URB_FUNCTION_ABORT_PIPE\n");
    FUNCTION_MSG(" PipeHandle = %p\n", urb->UrbPipeRequest.PipeHandle);
    urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
    break;
  case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: /* 11.12.4 */
#if 0
    FUNCTION_MSG("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n");
    FUNCTION_MSG(" PipeHandle = %p\n", urb->UrbBulkOrInterruptTransfer.PipeHandle);
    FUNCTION_MSG(" TransferFlags = %08x\n", urb->UrbBulkOrInterruptTransfer.TransferFlags);
    FUNCTION_MSG(" TransferBufferLength = %d\n", urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
    FUNCTION_MSG(" TransferBuffer = %p\n", urb->UrbBulkOrInterruptTransfer.TransferBuffer);
    FUNCTION_MSG(" TransferBufferMdl = %p\n", urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
#endif
    endpoint = urb->UrbBulkOrInterruptTransfer.PipeHandle;
    //WdfSpinLockAcquire(endpoint->lock);
    WdfRequestForwardToIoQueue(request, endpoint->queue);
    XenUsbHub_ProcessHubInterruptEvent(endpoint);
    //WdfSpinLockRelease(endpoint->lock);
    //FUNCTION_EXIT();
    return;
    
  default:
    FUNCTION_MSG("URB_FUNCTION_%04x\n", urb->UrbHeader.Function);
    if (decode_retval != URB_DECODE_NOT_CONTROL)
    {
      FUNCTION_MSG("bmRequestType = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.B);
      FUNCTION_MSG(" Recipient = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient);
      FUNCTION_MSG(" Type = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type);
      FUNCTION_MSG(" Dir = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Dir);
      FUNCTION_MSG("bRequest = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bRequest);
      FUNCTION_MSG("wValue = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W);
      FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.LowByte);
      FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte);
      FUNCTION_MSG("wIndex = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex);
      FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte);
      FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.HiByte);
      FUNCTION_MSG("wLength = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wLength);
    }
    urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
    break;
  }
  if (urb->UrbHeader.Status == USBD_STATUS_SUCCESS)
  {
    //FUNCTION_MSG("Calling WdfRequestCompletestatus with status = %08x\n", STATUS_SUCCESS);
    WdfRequestComplete(request, STATUS_SUCCESS);
  }
  else
  {
    FUNCTION_MSG("Calling WdfRequestCompletestatus with status = %08x\n", STATUS_UNSUCCESSFUL);
    WdfRequestComplete(request, STATUS_UNSUCCESSFUL);
  }

  //FUNCTION_EXIT();
  return;
}
Beispiel #18
0
VOID
NonPnpEvtDeviceIoInCallerContext(
    IN WDFDEVICE  Device,
    IN WDFREQUEST Request
    )
/*++
Routine Description:

    This I/O in-process callback is called in the calling threads context/address
    space before the request is subjected to any framework locking or queueing
    scheme based on the device pnp/power or locking attributes set by the
    driver. The process context of the calling app is guaranteed as long as
    this driver is a top-level driver and no other filter driver is attached
    to it.

    This callback is only required if you are handling method-neither IOCTLs,
    or want to process requests in the context of the calling process.

    Driver developers should avoid defining neither IOCTLs and access user
    buffers, and use much safer I/O tranfer methods such as buffered I/O
    or direct I/O.

Arguments:

    Device - Handle to a framework device object.

    Request - Handle to a framework request object. Framework calls
              PreProcess callback only for Read/Write/ioctls and internal
              ioctl requests.

Return Value:

    VOID

--*/
{
    NTSTATUS                   status = STATUS_SUCCESS;
    PREQUEST_CONTEXT            reqContext = NULL;
    WDF_OBJECT_ATTRIBUTES           attributes;
    WDF_REQUEST_PARAMETERS  params;
    size_t              inBufLen, outBufLen;
    PVOID              inBuf, outBuf;

    PAGED_CODE();

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(Request,  &params );

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Entered NonPnpEvtDeviceIoInCallerContext %p \n",
                            Request);

    //
    // Check to see whether we have recevied a METHOD_NEITHER IOCTL. if not
    // just send the request back to framework because we aren't doing
    // any pre-processing in the context of the calling thread process.
    //
    if(!(params.Type == WdfRequestTypeDeviceControl &&
            params.Parameters.DeviceIoControl.IoControlCode ==
                                    IOCTL_NONPNP_METHOD_NEITHER)) {
        //
        // Forward it for processing by the I/O package
        //
        status = WdfDeviceEnqueueRequest(Device, Request);
        if( !NT_SUCCESS(status) ) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                                        "Error forwarding Request 0x%x",  status);
            goto End;
        }

        return;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess: received METHOD_NEITHER ioctl \n");

    //
    // In this type of transfer, the I/O manager assigns the user input
    // to Type3InputBuffer and the output buffer to UserBuffer of the Irp.
    // The I/O manager doesn't copy or map the buffers to the kernel
    // buffers.
    //
    status = WdfRequestRetrieveUnsafeUserInputBuffer(Request, 0, &inBuf, &inBufLen);
    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                                    "Error WdfRequestRetrieveUnsafeUserInputBuffer failed 0x%x",  status);
        goto End;
    }

    status = WdfRequestRetrieveUnsafeUserOutputBuffer(Request, 0, &outBuf, &outBufLen);
    if(!NT_SUCCESS(status)) {
       TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                                    "Error WdfRequestRetrieveUnsafeUserOutputBuffer failed 0x%x",  status);
       goto End;
    }

    //
    // Allocate a context for this request so that we can store the memory
    // objects created for input and output buffer.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);

    status = WdfObjectAllocateContext(Request, &attributes, &reqContext);
    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                                    "Error WdfObjectAllocateContext failed 0x%x",  status);
        goto End;
    }

    //
    // WdfRequestProbleAndLockForRead/Write function checks to see
    // whether the caller in the right thread context, creates an MDL,
    // probe and locks the pages, and map the MDL to system address
    // space and finally creates a WDFMEMORY object representing this
    // system buffer address. This memory object is associated with the
    // request. So it will be freed when the request is completed. If we
    // are accessing this memory buffer else where, we should store these
    // pointers in the request context.
    //

    #pragma prefast(suppress:6387, "If inBuf==NULL at this point, then inBufLen==0")    
    status = WdfRequestProbeAndLockUserBufferForRead(Request,
                            inBuf,
                            inBufLen,
                            &reqContext->InputMemoryBuffer);

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                                    "Error WdfRequestProbeAndLockUserBufferForRead failed 0x%x",  status);
        goto End;
    }

    #pragma prefast(suppress:6387, "If outBuf==NULL at this point, then outBufLen==0") 
    status = WdfRequestProbeAndLockUserBufferForWrite(Request,
                            outBuf,
                            outBufLen,
                            &reqContext->OutputMemoryBuffer);
    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                                    "Error WdfRequestProbeAndLockUserBufferForWrite failed 0x%x",  status);
        goto End;
    }

    //
    // Finally forward it for processing by the I/O package
    //
    status = WdfDeviceEnqueueRequest(Device, Request);
    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                                    "Error WdfDeviceEnqueueRequest failed 0x%x",  status);
        goto End;
    }

    return;

End:

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess failed %x \n", status);
    WdfRequestComplete(Request, status);
    return;
}
static VOID
XenUsb_EvtIoInternalDeviceControl_PVURB(
  WDFQUEUE queue,
  WDFREQUEST request,
  size_t output_buffer_length,
  size_t input_buffer_length,
  ULONG io_control_code)
{
  NTSTATUS status;
  WDFDEVICE device = WdfIoQueueGetDevice(queue);
  PXENUSB_DEVICE_DATA xudd = GetXudd(device);
  WDF_REQUEST_PARAMETERS wrp;
  pvurb_t *pvurb;
  partial_pvurb_t *partial_pvurb;
  KIRQL old_irql;
  
  UNREFERENCED_PARAMETER(input_buffer_length);
  UNREFERENCED_PARAMETER(output_buffer_length);
  UNREFERENCED_PARAMETER(io_control_code);

  FUNCTION_ENTER();

  ASSERT(io_control_code == IOCTL_INTERNAL_PVUSB_SUBMIT_URB);

  WDF_REQUEST_PARAMETERS_INIT(&wrp);
  WdfRequestGetParameters(request, &wrp);
  pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
  ASSERT(pvurb);
  RtlZeroMemory(&pvurb->rsp, sizeof(pvurb->rsp));
  pvurb->status = STATUS_SUCCESS;
  pvurb->request = request;
  pvurb->ref = 1;
  pvurb->total_length = 0;
  partial_pvurb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb), XENUSB_POOL_TAG); /* todo - use lookaside */
  if (!partial_pvurb) {
    WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
    FUNCTION_EXIT();
    return;
  }
  KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);
  status = WdfRequestMarkCancelableEx(request, XenUsb_EvtRequestCancelPvUrb);
  if (!NT_SUCCESS(status)) {
    KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);  
    FUNCTION_MSG("WdfRequestMarkCancelableEx returned %08x\n", status);
    WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
    FUNCTION_EXIT();
    return;
  }  
  
  partial_pvurb->req = pvurb->req;
  partial_pvurb->mdl = pvurb->mdl; /* 1:1 right now, but may need to split up large pvurb into smaller partial_pvurb's */
  partial_pvurb->pvurb = pvurb;
  partial_pvurb->other_partial_pvurb = NULL;
  partial_pvurb->on_ring = FALSE;
  if (!partial_pvurb->mdl) {
    partial_pvurb->req.nr_buffer_segs = 0;
    partial_pvurb->req.buffer_length = 0;
  } else {
    ULONG remaining = MmGetMdlByteCount(partial_pvurb->mdl);
    USHORT offset = (USHORT)MmGetMdlByteOffset(partial_pvurb->mdl);
    int i;
    partial_pvurb->req.buffer_length = (USHORT)MmGetMdlByteCount(partial_pvurb->mdl);
    partial_pvurb->req.nr_buffer_segs = (USHORT)ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(partial_pvurb->mdl), MmGetMdlByteCount(partial_pvurb->mdl));
    for (i = 0; i < partial_pvurb->req.nr_buffer_segs; i++) {
      partial_pvurb->req.seg[i].gref = XnGrantAccess(xudd->handle, (ULONG)MmGetMdlPfnArray(partial_pvurb->mdl)[i], FALSE, INVALID_GRANT_REF, (ULONG)'XUSB');
      partial_pvurb->req.seg[i].offset = (USHORT)offset;
      partial_pvurb->req.seg[i].length = (USHORT)min((USHORT)remaining, (USHORT)PAGE_SIZE - offset);
      offset = 0;
      remaining -= partial_pvurb->req.seg[i].length;
      FUNCTION_MSG("seg = %d\n", i);
      FUNCTION_MSG(" gref = %d\n", partial_pvurb->req.seg[i].gref);
      FUNCTION_MSG(" offset = %d\n", partial_pvurb->req.seg[i].offset);
      FUNCTION_MSG(" length = %d\n", partial_pvurb->req.seg[i].length);
    }
    FUNCTION_MSG("buffer_length = %d\n", partial_pvurb->req.buffer_length);
    FUNCTION_MSG("nr_buffer_segs = %d\n", partial_pvurb->req.nr_buffer_segs);
  }
  InsertTailList(&xudd->partial_pvurb_queue, &partial_pvurb->entry);
  PutRequestsOnRing(xudd);
  KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);  
  
  FUNCTION_EXIT();
}
VOID
NICServiceReadIrps(
    PFDO_DATA   FdoData,
    PMP_RFD     *PacketArray,
    ULONG       PacketArrayCount
    )
/*++
Routine Description:

    Copy the data from the recv buffers to pending read IRP buffers
    and complete the IRP. When used as network driver, copy operation
    can be avoided by devising a private interface between us and the
    NDIS-WDM filter and have the NDIS-WDM edge to indicate our buffers
    directly to NDIS.

    Called at DISPATCH_LEVEL. Take advantage of that fact while
     acquiring spinlocks.

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

     None

--*/
{
    PMP_RFD             pMpRfd = NULL;
    ULONG               index;
    NTSTATUS            status;
    PVOID               buffer;
    WDFREQUEST          request;
    size_t              bufLength=0;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> NICServiceReadIrps\n");


    for(index=0; index < PacketArrayCount; index++)
    {
        pMpRfd = PacketArray[index];
        ASSERT(pMpRfd);

        status = WdfIoQueueRetrieveNextRequest( FdoData->PendingReadQueue,
                                                &request );

        if(NT_SUCCESS(status)){

            WDF_REQUEST_PARAMETERS  params;
            ULONG                   length = 0;

            WDF_REQUEST_PARAMETERS_INIT(&params);

            WdfRequestGetParameters(
                request,
                &params
                 );

            ASSERT(status == STATUS_SUCCESS);

            bufLength = params.Parameters.Read.Length;

            status = WdfRequestRetrieveOutputBuffer(request,
                                                    bufLength,
                                                    &buffer,
                                                    &bufLength);
            if(NT_SUCCESS(status) ) {

                length = min((ULONG)bufLength, pMpRfd->PacketSize);

                RtlCopyMemory(buffer, pMpRfd->Buffer, length);

                Hexdump((TRACE_LEVEL_VERBOSE, DBG_READ,
                         "Received Packet Data: %!HEXDUMP!\n",
                         log_xstr(buffer, (USHORT)length)));
                FdoData->BytesReceived += length;
            }

            WdfRequestCompleteWithInformation(request, status, length);
        }else {
            ASSERTMSG("WdfIoQueueRetrieveNextRequest failed",
                      (status == STATUS_NO_MORE_ENTRIES ||
                       status == STATUS_WDF_PAUSED));
        }

        WdfSpinLockAcquire(FdoData->RcvLock);

        ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_PEND));
        MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_PEND);


        if (FdoData->RfdShrinkCount < NIC_RFD_SHRINK_THRESHOLD)
        {
            NICReturnRFD(FdoData, pMpRfd);
        }
        else
        {
            ASSERT(FdoData->CurrNumRfd > FdoData->NumRfd);
            status = PciDrvQueuePassiveLevelCallback(FdoData,
                                    NICFreeRfdWorkItem, (PVOID)pMpRfd,
                                    NULL);
            if(NT_SUCCESS(status)){

                FdoData->RfdShrinkCount = 0;
                FdoData->CurrNumRfd--;
                TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Shrink... CurrNumRfd = %d\n",
                                                    FdoData->CurrNumRfd);
            } else {
                //
                // We couldn't queue a workitem to free memory, so let us
                // put that back in the main pool and try again next time.
                //
                NICReturnRFD(FdoData, pMpRfd);
            }
        }


        WdfSpinLockRelease(FdoData->RcvLock);

    }// end of loop

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- NICServiceReadIrps\n");

    return;

}
Beispiel #21
0
VOID
MarsEvtIoRead (
              WDFQUEUE      Queue,
              WDFREQUEST    Request,
              size_t         Length
              )
/*++

Routine Description:

    This event is called when the framework receives IRP_MJ_READ requests.

Arguments:

    Queue -  Handle to the framework queue object that is associated with the
            I/O request.
    Request - Handle to a framework request object.

    Lenght - Length of the data buffer associated with the request.
             The default property of the queue is to not dispatch
             zero lenght read & write requests to the driver and
             complete is with status success. So we will never get
             a zero length request.

Return Value:

  None.

--*/
{
    WDFDEVICE        device;
    PFDO_DATA        fdoData;
    PMDL            mdlAddress;
    WDF_REQUEST_PARAMETERS  parameters;
    NTSTATUS        status;
    ULONG            bytesRead;

    device = WdfIoQueueGetDevice(Queue);
    fdoData = MarsFdoGetData(device);

    status = WdfRequestRetrieveOutputWdmMdl(Request,&mdlAddress);
    if (!NT_SUCCESS(status)) {
        WdfRequestComplete(Request, status);
        return;
    }

    WDF_REQUEST_PARAMETERS_INIT(&parameters);
    WdfRequestGetParameters(Request, &parameters);

    status = SdioReadWriteBuffer(device,
                                 fdoData->FunctionFocus,
                                 mdlAddress,
                                 (ULONG)parameters.Parameters.Read.DeviceOffset,
                                 (ULONG)parameters.Parameters.Read.Length,
                                 FALSE,
                                 &bytesRead);

    WdfRequestCompleteWithInformation(Request, status, bytesRead);

    return;
}
static VOID
XenBus_EvtIoWrite(WDFQUEUE queue, WDFREQUEST request, size_t length)
{
  NTSTATUS status;
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfIoQueueGetDevice(queue));
  WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;
  WDFREQUEST read_request;

  PUCHAR buffer;
  PUCHAR src_ptr;
  ULONG src_len;
  PUCHAR dst_ptr;
  ULONG copy_len;
  struct xsd_sockmsg *rep;
  xenbus_read_queue_item_t *list_entry;
  watch_context_t *watch_context;
  PCHAR watch_path;
  PCHAR watch_token;
  PCHAR msg;
  
  FUNCTION_ENTER();
  
  status = WdfRequestRetrieveInputBuffer(request, length, &buffer, NULL);
  ASSERT(NT_SUCCESS(status));
  
  src_ptr = (PUCHAR)buffer;
  src_len = (ULONG)length;
  dst_ptr = xpdid->xenbus.u.buffer + xpdid->xenbus.len;
  while (src_len != 0)
  {
    KdPrint((__DRIVER_NAME "     %d bytes of write buffer remaining\n", src_len));
    /* get a complete msg header */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
      continue;
    /* get a complete msg body */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      continue;
    }
    
    switch (xpdid->xenbus.u.msg.type)
    {
    case XS_WATCH:
    case XS_UNWATCH:
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      watch_context = (watch_context_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(watch_context_t), XENPCI_POOL_TAG);
      watch_path = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg));
      watch_token = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg) + strlen(watch_path) + 1);
      RtlStringCbCopyA(watch_context->path, ARRAY_SIZE(watch_context->path), watch_path);
      RtlStringCbCopyA(watch_context->token, ARRAY_SIZE(watch_context->path), watch_token);
      watch_context->file_object = file_object;
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        InsertTailList(&xpdid->xenbus.watch_list_head, &watch_context->entry);
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        msg = XenBus_AddWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      else
        msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      if (msg != NULL)
      {
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(msg) + 1, XENPCI_POOL_TAG);
        rep->type = XS_ERROR;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = (ULONG)(strlen(msg) + 0);
        RtlStringCbCopyA((PCHAR)(rep + 1), strlen(msg) + 1, msg);
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
          RemoveEntryList(&watch_context->entry);
      }
      else
      {
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
        {
          WdfObjectReference(file_object);
        }
        else
        {
          RemoveEntryList(&watch_context->entry);
          WdfObjectDereference(file_object);
        }
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg), XENPCI_POOL_TAG);
        rep->type = xpdid->xenbus.u.msg.type;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = 0;
      }
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      break;
    default:
      rep = XenBus_Raw(xpdd, &xpdid->xenbus.u.msg);
      break;
    }
    xpdid->xenbus.len = 0;
    
    KeAcquireSpinLock(&xpdid->lock, &old_irql);
    list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
    list_entry->data = rep;
    list_entry->length = sizeof(*rep) + rep->len;
    list_entry->offset = 0;
    InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry);

	// Check if someone was waiting for the answer already
	status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &read_request);
    if (NT_SUCCESS(status))
    {
		WDF_REQUEST_PARAMETERS parameters;
		KdPrint((__DRIVER_NAME "     post-write: found pending read\n"));
		WDF_REQUEST_PARAMETERS_INIT(&parameters);
		WdfRequestGetParameters(read_request, &parameters);
		XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, read_request, parameters.Parameters.Read.Length);
		WdfRequestComplete(read_request, STATUS_SUCCESS);
    }
    else
    {
		KdPrint((__DRIVER_NAME "     post-write: no pending read (%08x)\n", status));
    }

    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  KdPrint((__DRIVER_NAME "     completing request with length %d\n", length));
  WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, length);

  FUNCTION_EXIT();
}
Beispiel #23
0
VCHIQ_PAGED_SEGMENT_BEGIN

/*++

Routine Description:

     VchiqIoDeviceControl handles VCHIQ IOCTL.

Arguments:

     DeviceContextPtr - Pointer to device context

     WdfRequest - A handle to a framework request object.

     OutputBufferLength - The length, in bytes, of the request's output buffer,
          if an output buffer is available.

     InputBufferLength - The length, in bytes, of the request's input buffer,
          if an input buffer is available.

     IoControlCode - The driver-defined or system-defined I/O control code
          (IOCTL) that is associated with the request.

Return Value:

     None

--*/
_Use_decl_annotations_
VOID VchiqIoDeviceControl (
    WDFQUEUE Queue,
    WDFREQUEST WdfRequest,
    size_t OutputBufferLength,
    size_t InputBufferLength,
    ULONG IoControlCode
    )
{
    NTSTATUS status;
    VCHIQ_FILE_CONTEXT* vchiqFileContextPtr;
    WDFDEVICE device = WdfIoQueueGetDevice(Queue);
    DEVICE_CONTEXT* deviceContextPtr = VchiqGetDeviceContext(device);

    PAGED_CODE();

    if (deviceContextPtr->VCConnected == FALSE) {
        VCHIQ_LOG_WARNING("VCHIQ interface not ready");
        status = STATUS_DEVICE_NOT_READY;
        goto CompleteRequest;
    }

    // First process IOCTL that does not require a file context
    switch (IoControlCode)
    {
    case IOCTL_VCHIQ_CONNECT:
        {
            // Connect is a simple ioctl to ensure that we have establish 
            // connection with VC firmware. Connection is establish by 
            // initiating the slots which if we reach this point has 
            // already been initialize. We just send a message to notify
            // the firmware too
            WDFFILEOBJECT wdfFileObject = WdfRequestGetFileObject(WdfRequest);
            if (wdfFileObject == NULL) {
                WDF_REQUEST_PARAMETERS wdfRequestParameters;
                WdfRequestGetParameters(WdfRequest, &wdfRequestParameters);
                VCHIQ_LOG_ERROR(
                    "Fail to retrieve file object. \
                         (WdfRequest = 0x%p, Type = 0x%lx)",
                    WdfRequest,
                    (ULONG)wdfRequestParameters.Type);
                status = STATUS_INTERNAL_ERROR;
                goto CompleteRequest;
            }

            // Create a file context here as vchiq_arm would immediately begin
            // to send IOCTL to wait for completion message
            vchiqFileContextPtr = VchiqGetFileContext(wdfFileObject);
            if (vchiqFileContextPtr != NULL) {
                VCHIQ_LOG_ERROR(
                    "Caller has already connected to a service");
                status = STATUS_UNSUCCESSFUL;
                goto CompleteRequest;
            }

            status = VchiqAllocateFileObjContext(
                deviceContextPtr,
                wdfFileObject,
                &vchiqFileContextPtr);
            if (!NT_SUCCESS (status)) {
                VCHIQ_LOG_ERROR(
                    "VchiqAllocateFileObjContext failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            status = VchiqQueueMessageAsync(
                deviceContextPtr,
                vchiqFileContextPtr,
                VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0),
                NULL,
                0);
            if (!NT_SUCCESS (status)) {
                VCHIQ_LOG_ERROR(
                    "VchiqQueueMessageAsync failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            goto CompleteRequest;
        }
    case IOCTL_VCHIQ_GET_CONFIG:
        {
            VCHIQ_CONFIG vchiqCurrentConfig =
                {
                    VCHIQ_MAX_MSG_SIZE,
                    VCHIQ_MAX_MSG_SIZE,
                    VCHIQ_NUM_SERVICE_BULKS,
                    VCHIQ_MAX_SERVICES,
                    VCHIQ_VERSION,
                    VCHIQ_VERSION_MIN
                };

            VCHIQ_GET_CONFIG* clientConfigPtr;
            status = WdfRequestRetrieveInputBuffer(
                WdfRequest,
                sizeof(*clientConfigPtr),
                &clientConfigPtr,
                NULL);
            if (!NT_SUCCESS(status)) {
                VCHIQ_LOG_ERROR(
                    "WdfRequestRetrieveInputBuffer failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            // Ensure that the buffer provided is not too big.
            if (clientConfigPtr->ConfigSize > sizeof(VCHIQ_CONFIG)) {
                VCHIQ_LOG_WARNING("Config buffer too big");
                status = STATUS_INVALID_PARAMETER;
                goto CompleteRequest;
            }

            VCHIQ_CONFIG* configurationPtr;
            size_t bufferSize;
            configurationPtr = WdfMemoryGetBuffer(
                clientConfigPtr->WdfMemoryConfiguration,
                &bufferSize);
            if ((configurationPtr == NULL) ||
                (bufferSize != sizeof(*configurationPtr))) {
                VCHIQ_LOG_ERROR(
                    "Caller provided invalid VCHIQ_CONFIG buffer 0x%08x %d",
                    (ULONG)configurationPtr,
                    bufferSize);
                status = STATUS_INVALID_PARAMETER;
                goto CompleteRequest;
            }

            RtlCopyMemory(
                configurationPtr,
                &vchiqCurrentConfig, 
                sizeof(*clientConfigPtr->PConfig));

            status = STATUS_SUCCESS;
        }
        goto CompleteRequest;
    case IOCTL_VCHIQ_LIB_VERSION:
        {
            ULONG* libVersion;
            status = WdfRequestRetrieveInputBuffer(
                WdfRequest,
                sizeof(*libVersion),
                &libVersion,
                NULL);
            if (!NT_SUCCESS(status)) {
                VCHIQ_LOG_ERROR(
                    "WdfRequestRetrieveInputBuffer failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            if (*libVersion < VCHIQ_VERSION_MIN) {
                VCHIQ_LOG_ERROR(
                    "Library version %d unsupported",
                    *libVersion);
                status = STATUS_NOT_SUPPORTED;
                goto CompleteRequest;
            }
            status = STATUS_SUCCESS;
        }
        goto CompleteRequest;
    case IOCTL_VCHIQ_CREATE_SERVICE:
    default:
        {
            WDFFILEOBJECT wdfFileObject = WdfRequestGetFileObject(WdfRequest);
            if (wdfFileObject == NULL) {
                WDF_REQUEST_PARAMETERS wdfRequestParameters;
                WdfRequestGetParameters(WdfRequest, &wdfRequestParameters);
                VCHIQ_LOG_ERROR(
                    "Fail to retrieve file object. \
                         (WdfRequest = 0x%p, Type = 0x%lx)",
                    WdfRequest,
                    (ULONG)wdfRequestParameters.Type);
                status = STATUS_INTERNAL_ERROR;
                goto CompleteRequest;
            }

            vchiqFileContextPtr = VchiqGetFileContext(wdfFileObject);
            if ((vchiqFileContextPtr == NULL) &&
                (IoControlCode == IOCTL_VCHIQ_CREATE_SERVICE)) {

                // Functional test does not call connect prior to a create
                // service call, so we allocate a file context here instead
                status = VchiqAllocateFileObjContext(
                    deviceContextPtr,
                    wdfFileObject,
                    &vchiqFileContextPtr);
                if (!NT_SUCCESS (status)) {
                    VCHIQ_LOG_ERROR(
                        "VchiqAllocateFileObjContext failed (%!STATUS!)",
                        status);
                    goto CompleteRequest;
                }
            } else if (vchiqFileContextPtr == NULL) {
                VCHIQ_LOG_ERROR(
                    "Caller has not connected to a service %d",
                    ((IoControlCode >> 2) & 0x0FFF));
                status = STATUS_UNSUCCESSFUL;
                goto CompleteRequest;
            }
        }
    }
Beispiel #24
0
VOID
MarsEvtIoWrite (
               WDFQUEUE      Queue,
               WDFREQUEST    Request,
               size_t         Length
               )
/*++

Routine Description:

    Called by the framework as soon as it receive a write IRP.
    If the device is not ready, fail the request. Otherwise
    get scatter-gather list for this request and send the
    packet to the hardware for DMA.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    Length - Length of the IO operation
                 The default property of the queue is to not dispatch
                 zero lenght read & write requests to the driver and
                 complete is with status success. So we will never get
                 a zero length request.

Return Value:


--*/
{
    WDFDEVICE        device;
    PFDO_DATA        fdoData;
    PMDL            mdlAddress;
    WDF_REQUEST_PARAMETERS  parameters;
    NTSTATUS        status;
    ULONG            bytesRead;

    device = WdfIoQueueGetDevice(Queue);
    fdoData = MarsFdoGetData(device);

    status = WdfRequestRetrieveInputWdmMdl(Request,&mdlAddress);
    if (!NT_SUCCESS(status)) {
        WdfRequestComplete(Request, status);
        return;
    }

    WDF_REQUEST_PARAMETERS_INIT(&parameters);
    WdfRequestGetParameters(Request, &parameters);

    status = SdioReadWriteBuffer(device,
                                 fdoData->FunctionFocus,
                                 mdlAddress,
                                 (ULONG)parameters.Parameters.Read.DeviceOffset,
                                 (ULONG)parameters.Parameters.Read.Length,
                                 TRUE,
                                 &bytesRead);

    WdfRequestCompleteWithInformation(Request, status, bytesRead);
    return;
}
_Use_decl_annotations_
VOID
TreeSampleProcessOtherDeviceIo(
    WDFDEVICE MasterDevice,
    WDFREQUEST Request
    )

/*++

    Routine Description:

        This routine is called when an unrecognized IO request is made to the
        device. This can be used to process private calls directly to the
        secure device.

    Arguments:

        MasterDevice - Supplies a handle to the master device object.

        DeviceContext - Supplies a pointer to the context.

        Request - Supplies a pointer to the WDF request object.

    Return Value:

        NTSTATUS code.

--*/

{

    PWCHAR Buffer;
    size_t BufferSize;
    ULONG BytesWritten;
    WDF_REQUEST_PARAMETERS Parameters;
    NTSTATUS Status;

    PAGED_CODE();

    UNREFERENCED_PARAMETER(MasterDevice);

    WDF_REQUEST_PARAMETERS_INIT(&Parameters);
    WdfRequestGetParameters(Request, &Parameters);
    BytesWritten = 0;
    switch (Parameters.Parameters.DeviceIoControl.IoControlCode) {
    case IOCTL_SAMPLE_DBGPRINT:
        Status = WdfRequestRetrieveInputBuffer(Request,
                                               0,
                                               (PVOID*)&Buffer,
                                               &BufferSize);

        if (!NT_SUCCESS(Status)) {
            goto TreeSampleProcessOtherDeviceIoEnd;
        }

        //
        // Must be NULL-terminated
        //
        if (Buffer[BufferSize / sizeof(WCHAR) - 1] != L'\0') {
            Status = STATUS_INVALID_PARAMETER;
            goto TreeSampleProcessOtherDeviceIoEnd;
        }

        DbgPrintEx(DPFLTR_DEFAULT_ID,
                   DPFLTR_ERROR_LEVEL,
                   "[TrEEMiniportSample] %ws\n",
                   (PWSTR)Buffer);

        break;

    default:
        Status = STATUS_INVALID_DEVICE_REQUEST;
    }

TreeSampleProcessOtherDeviceIoEnd:
    WdfRequestCompleteWithInformation(Request, Status, BytesWritten);
}
Beispiel #26
0
VOID
EvtIoDeviceControl(
    WDFQUEUE   Queue,
    WDFREQUEST Request,
    size_t     OutputBufferLength,
    size_t     InputBufferLength,
    ULONG      IoControlCode)
{
    NTSTATUS        status;
    BOOLEAN         completeRequest = TRUE;
    WDFDEVICE       device = WdfIoQueueGetDevice(Queue);
    PINPUT_DEVICE   pContext = GetDeviceContext(device);
    ULONG           uReportSize;
    HID_XFER_PACKET Packet;
    WDF_REQUEST_PARAMETERS params;
    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS,
                "--> %s, code = %d\n", __FUNCTION__, IoControlCode);

    switch (IoControlCode)
    {
    case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_DEVICE_DESCRIPTOR\n");
        //
        // Return the device's HID descriptor.
        //
        ASSERT(pContext->HidDescriptor.bLength != 0);
        status = RequestCopyFromBuffer(Request,
            &pContext->HidDescriptor,
            pContext->HidDescriptor.bLength);
        break;

    case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_DEVICE_ATTRIBUTES\n");
        //
        // Return the device's attributes in a HID_DEVICE_ATTRIBUTES structure.
        //
        status = RequestCopyFromBuffer(Request,
            &pContext->HidDeviceAttributes,
            sizeof(HID_DEVICE_ATTRIBUTES));
        break;

    case IOCTL_HID_GET_REPORT_DESCRIPTOR:
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_REPORT_DESCRIPTOR\n");
        //
        // Return the report descriptor for the HID device.
        //
        status = RequestCopyFromBuffer(Request,
            pContext->HidReportDescriptor,
            pContext->HidDescriptor.DescriptorList[0].wReportLength);
        break;

    case IOCTL_HID_READ_REPORT:
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_READ_REPORT\n");
        //
        // Queue up a report request. We'll complete it when we actually
        // receive data from the device.
        //

        status = WdfRequestForwardToIoQueue(
            Request,
            pContext->HidQueue);
        if (NT_SUCCESS(status))
        {
            completeRequest = FALSE;
        }
        else
        {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                        "WdfRequestForwardToIoQueue failed with 0x%x\n", status);
        }
        break;

    case IOCTL_HID_WRITE_REPORT:
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_WRITE_REPORT\n");
        //
        // Write a report to the device, commonly used for controlling keyboard
        // LEDs. We'll complete the request after the host processes all virtio
        // buffers we add to the status queue.
        //

        WDF_REQUEST_PARAMETERS_INIT(&params);
        WdfRequestGetParameters(Request, &params);

        if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET))
        {
            status = STATUS_BUFFER_TOO_SMALL;
        }
        else
        {
            RtlCopyMemory(&Packet, WdfRequestWdmGetIrp(Request)->UserBuffer,
                          sizeof(HID_XFER_PACKET));
            WdfRequestSetInformation(Request, Packet.reportBufferLen);

            status = ProcessOutputReport(pContext, Request, &Packet);
            if (NT_SUCCESS(status))
            {
                completeRequest = FALSE;
            }
        }
        break;

    default:
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS,
                    "Unrecognized IOCTL %d\n", IoControlCode);
        status = STATUS_NOT_IMPLEMENTED;
        break;
    }

    if (completeRequest)
    {
        WdfRequestComplete(Request, status);
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %s\n", __FUNCTION__);
}
Beispiel #27
0
VOID
vJoy_EvtIoDeviceControlForRawPdo(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
/*++

Routine Description:

    This routine is the dispatch routine for device control requests.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.

Return Value:

   VOID

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    WDFDEVICE parent;
    WDF_REQUEST_FORWARD_OPTIONS forwardOptions;
    PDEVICE_EXTENSION    pDevContext = NULL;
	WDFMEMORY  inMemory, outMemory;
    PVOID  buffer;
    size_t  bufSize;
    WDFDEVICE            hRawDevice = WdfIoQueueGetDevice(Queue);
	PRPDO_DEVICE_DATA pdoData = PdoGetData(hRawDevice);
	WDF_REQUEST_SEND_OPTIONS RequestOptions;
	WDFIOTARGET TargetOnParent;

	JOYSTICK_POSITION_V2 * iReport;
	WDFFILEOBJECT FileObj;
	USHORT id=0;
	PFILEOBJECT_EXTENSION pExtension=NULL;

    WDFREQUEST				requestForceFeedback;
	PHID_XFER_PACKET		transferPacket = NULL;
	PVOID					ForceFeedbackBuffer = NULL;
	PVOID					GenBuffer = NULL;
	size_t					bytesReturned = 0;
	WDF_REQUEST_PARAMETERS	Params;
	BOOLEAN					FfbStat = FALSE;
	ULONG					bytesToCopy = 0;
	BYTE					Byte_tmp;




    
    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

	TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_EvtIoDeviceControlForRawPdo\n");

    //
    // Process the ioctl and complete it when you are done.
    // Since the queue is configured for serial dispatch, you will
    // not receive another ioctl request until you complete this one.
    //

	  switch (IoControlCode) {
 	case 1234: // TODO: Remove for production
		//RequestOptions.Flags =	WDF_REQUEST_SEND_OPTION_TIMEOUT;
		//RequestOptions.Size =	sizeof(WDF_REQUEST_SEND_OPTIONS);
		//WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&RequestOptions,  WDF_REL_TIMEOUT_IN_SEC(1));
		//status = WdfIoTargetSendInternalIoctlSynchronously(pdoData->IoTargetToParent, Request, IoControlCode , NULL, NULL, &RequestOptions, NULL);
		break; // Testing 

	case GET_DEV_STAT:
		// Get information for a device by device ID
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DEV_STAT\n");

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		if (bytesToCopy<5)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed - bytesToCopy=%d\n", bytesToCopy);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the buffer
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (bytesReturned<5)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed - bytesReturned=%d\n", bytesReturned);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the id number from input buffer
		status = WdfRequestRetrieveInputBuffer(Request, sizeof(BYTE), &buffer, &bufSize);
		if (!NT_SUCCESS(status) || (bufSize!=1))
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed to retrieve input buffer\n");
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get target ID
		id = *(BYTE *)buffer;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: id=%d\n", id);

		// Put data into output buffer
		// Byte 1:
		// Bit 0: Implemented?
		// Bit 1: FFB Device Enabled?
		// Bit 2: File Object associated with this device?
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		Byte_tmp = 0;

		// Implemented mask
		if (pDevContext->DeviceImplemented[id - 1])
			Byte_tmp |= 1;
		else
			Byte_tmp &= 0xFE;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Dev Implemented=%x\n", pDevContext->DeviceImplemented[id - 1]);

		// FFB mask
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Dev Enabled=%x\n", pDevContext->FfbEnable[id - 1]);
		if (pDevContext->FfbEnable[id - 1])
			Byte_tmp |= 2;
		else
			Byte_tmp &= 0xFD;

		// File Object
		if (pDevContext->DeviceFileObject[id - 1])
			Byte_tmp |= 4;
		else
			Byte_tmp &= 0xFB;

		((BYTE *)GenBuffer)[0] = Byte_tmp;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Buffer[0]=%x\n", ((BYTE *)GenBuffer)[0]);

		// Byte2-5: Process ID
		// Get the context
		FileObj = pDevContext->DeviceFileObject[id - 1];
		if (FileObj)
			*(DWORD *)(&((BYTE *)GenBuffer)[1]) = GetFileObjectContext(FileObj)->CallingProcessId;
		else
			*(DWORD *)(&((BYTE *)GenBuffer)[1]) = 0;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: ProcessID=%x\n", *(DWORD *)(&((BYTE *)GenBuffer)[1]));

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;



	case GET_DRV_INFO:
		// Get information for this driver
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO]\n");
		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);

		// Number of bytes to copy must be at least one byte
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		if (bytesToCopy <1 )
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - bytesToCopy <1\n");
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};


		// Output buffer must be at least one byte
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (bytesReturned<1)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - bytesReturned <1\n");
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		pDevContext = GetDeviceContext(pdoData->hParentDevice);

		// Return the data in the output buffer
		// BYTE 0 //////////////////////////////
		// Bit 0	: Supports FFB?
		// Bit 1	: Reserved
		// Bit 2	: Mode: Multi-device 
		// Bit 3	: Mode: FFB 
		// BYTE 1 //////////////////////////////
		// Bits 0-7	: Maximum number of possible devices (16 ==> 255)  not regarding to mode
		// BYTE 2 //////////////////////////////
		// Bits 0-7	: Number of existing devices
		// BYTE 3 //////////////////////////////
		// Bits 0-7	: Number of devices that can still be implemented (This is the number of possible devices for the current mode minus the number of already existing devices).

		//////////////////////////////////
		// Byte 0
		Byte_tmp = 0;
		Byte_tmp |= 0x01; // FFB Supported
		Byte_tmp |= 0x00; // Default Mode (TODO: Change to real mode when Implemented) Multi-Device=0x04; FFB=0x80
		((BYTE *)GenBuffer)[0] = Byte_tmp;

		// Byte 1
		if (bytesToCopy >= 2 && bytesReturned >= 2)
		{
			((BYTE *)GenBuffer)[1] = MAX_N_DEVICES;
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[1]=%02x\n", ((BYTE *)GenBuffer)[1]);
		}

		// Byte 2
		if (bytesToCopy >= 3 && bytesReturned >= 3)
		{
			((BYTE *)GenBuffer)[2] = (BYTE)(pDevContext->nDevices);
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[2]=%02x\n", ((BYTE *)GenBuffer)[2]);
		}

		// Byte 3 - TODO: Change according to mode
		if (bytesToCopy >= 4 && bytesReturned >= 4)
		{
			((BYTE *)GenBuffer)[3] = MAX_N_DEVICES - (BYTE)(pDevContext->nDevices);
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[3]=%02x\n", ((BYTE *)GenBuffer)[3]);
		}
		//////////////////////////////////

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;


	case GET_DEV_INFO:
		// Get information for this device (and for the driver)

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		if (bytesToCopy<6)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (bytesReturned<6)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the context, id and the status
		id = GetIdFromRawPdoRequest(Request, pExtension);

		// Illegal ID
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Copy the state to the buffer
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		((BYTE *)GenBuffer)[0] = (BYTE)id;
		((BYTE *)GenBuffer)[1] = (BYTE)(pDevContext->nDevices);
		((BYTE *)GenBuffer)[2] = pDevContext->DeviceImplemented ? 1:0;
		((BYTE *)GenBuffer)[3] = MAX_N_DEVICES; 
 		((BYTE *)GenBuffer)[4] = 1; // Driver does support FFB
		((BYTE *)GenBuffer)[5] = pDevContext->FfbEnable[id - 1]; // Device support FFB

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;

	case 0x910: // Backward compatibility value of 	LOAD_POSITIONS
	case LOAD_POSITIONS:
		// KdBreakPoint(); Break When loading position
		status = WdfRequestRetrieveInputBuffer( Request, sizeof(JOYSTICK_POSITION), &buffer, &bufSize);
		if(!NT_SUCCESS(status))
			break;

		// Get interface that this IRP came from,
		// then get the implicated id of the top-level collection
		id = GetIdFromRawPdoRequest(Request, pExtension);


		// Illegal ID
		if (id==0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the incoming report and compare the id in the report
		// to the implicated id of the top-level collection
		// They should match
		iReport = buffer;
		if (iReport->bDevice != id)
		{
			WdfRequestComplete(Request, STATUS_CANCELLED);
			return;
		};

		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		LoadPositions(iReport, pDevContext, bufSize);
		status = vJoyCompleteReadReport(pdoData->hParentDevice, (BYTE)id);
		break;   

	case GET_FFB_STAT:
		/* Get the status of the FFB mechanism */

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (!bytesReturned)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the context, id and the status
		id = GetIdFromRawPdoRequest(Request, pExtension);


		// Illegal ID
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Copy the state to the buffer
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		((BYTE *)GenBuffer)[0] =  pDevContext->FfbEnable[id-1];

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;

	case SET_FFB_STAT:
		/*Set the status of the FFB mechanism - Obsolete*/

		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);

		// Get interface that this IRP came from,
		// then get the implicated id of the top-level collection
		// Get the context, id and the status
		id = GetIdFromRawPdoRequest(Request, pExtension);
		// Illegal ID
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};


		// Get the data, process the data and complete the transaction
		//pDevContext = GetDeviceContext(pdoData->hParentDevice);	   - Obsolete
		//FfbActiveSet(*(BOOLEAN *)Params.Parameters.DeviceIoControl.Type3InputBuffer, id, pDevContext);   - Obsolete
		WdfRequestComplete(Request, status);
		return;

	case GET_FFB_DATA:
		// Get interface that this IRP came from,
		// then get the implicated id of the top-level collection
		id = GetIdFromRawPdoRequest(Request, pExtension);


		// If FFB is not active then just reject this request
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		if (id == 0xFFFF || !pDevContext->FfbEnable[id - 1])
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// If FFB is active then forward this request to the ReadQ and return
		status = WdfRequestForwardToIoQueue(Request, pDevContext->FfbReadQ[id - 1]);
        if(!NT_SUCCESS(status)){
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
				"WdfRequestForwardToIoQueue (FfbWriteQ[%d]) failed with status: 0x%x\n", id - 1, status);
            WdfRequestComplete(Request, status);
        }
        return;

	case GET_DRV_DEV_EN:
		// Get the number of devices that are currently enabled
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DRV_DEV_EN\n");

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy);
		if (bytesToCopy<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned);
		if (bytesReturned<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		if (!pdoData) break;
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		if (!pDevContext) break;
		// The number of the max supported devices
		((BYTE *)GenBuffer)[0] = (BYTE)(pDevContext->nDevices);

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]);
		return;

	case GET_DRV_DEV_MAX:
		// Get the max possible number of devices that this driver supports
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DRV_DEV_MAX\n");

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy);
		if (bytesToCopy<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned);
		if (bytesReturned<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// The number of the max supported devices
		((BYTE *)GenBuffer)[0] = MAX_N_DEVICES;

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]);
		return;


	case IS_DRV_FFB_CAP:
		// Test is this version of vJoy driver supports FFB
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case IS_DRV_FFB_CAP\n");

		// Get the data from the request (Bytes to copy)
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy);
		if (bytesToCopy<1)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d (Failed)\n", bytesToCopy);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the buffer from the request
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned);
		if (bytesReturned<1)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d (Failed)\n", bytesReturned);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Yes, this driver supports FFB
		((BYTE *)GenBuffer)[0] = 1;

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]);
		return;
	case RESET_DEV:
		/* Resets device(s) to predefined values */
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case RESET_DEV\n");

		// then get the implicated id of the top-level collection
		id = GetIdFromRawPdoRequest(Request, pExtension);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: ID=%d\n", id);

		// Sanity check
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the context of vJoy device
		pDevContext = GetDeviceContext(pdoData->hParentDevice);		
		
		// Reset device(s)
		status = ResetDevice(id, pDevContext);
		WdfRequestCompleteWithInformation(Request, status, 0);
		return;

	default:
        break;
    }
	  WdfRequestComplete(Request, status);

    return;
}
Beispiel #28
0
/*++

Routine Description:

    This is the dispatch routine for write.  It validates the parameters
    for the write request and if all is ok then it places the request
    on the work queue.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Pointer to the WDFREQUEST for the current request

    Length - Length of the IO operation
                 The default property of the queue is to not dispatch
                 zero lenght read & write requests to the driver and
                 complete is with status success. So we will never get
                 a zero length request.

Return Value:

--*/
_Use_decl_annotations_
VOID
SerialEvtIoWrite(
    WDFQUEUE Queue,
    WDFREQUEST Request,
    size_t Length
    )
{
    PSERIAL_DEVICE_EXTENSION extension;
    NTSTATUS status;
    WDFDEVICE hDevice;
    WDF_REQUEST_PARAMETERS params;
    PREQUEST_CONTEXT reqContext;
    size_t bufLen;
    UCHAR tempIER=0x00;

    hDevice = WdfIoQueueGetDevice(Queue);
    extension = SerialGetDeviceExtension(hDevice);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                "++SerialEvtIoWrite(%p, 0x%I64x)\r\n", 
                Request,
                Length);

    if (SerialCompleteIfError(extension, Request) != STATUS_SUCCESS) {

        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                    "--SerialEvtIoWrite 1 %Xh\r\n",
                    (ULONG)STATUS_CANCELLED);
        return;
    }

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(Request, &params);

    // Initialize the scratch area of the request.

    reqContext = SerialGetRequestContext(Request);
    reqContext->MajorFunction = params.Type;
    reqContext->Length = (ULONG) Length;

    status = WdfRequestRetrieveInputBuffer (Request,
                                            Length,
                                            &reqContext->SystemBuffer,
                                            &bufLen);

    if (!NT_SUCCESS (status)) {

        SerialCompleteRequest(Request , status, 0);
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                    "--SerialEvtIoWrite 2 %Xh\r\n", 
                    status);
        return;
    }

   SerialStartOrQueue(extension,
                        Request,
                        extension->WriteQueue,
                        &extension->CurrentWriteRequest,
                        SerialStartWrite);

    // enable mini Uart Tx interrupt

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "SerialEvtIoWrite() - enable Tx interrupt\r\n");

    tempIER=READ_INTERRUPT_ENABLE(extension, extension->Controller);
    WRITE_INTERRUPT_ENABLE(extension, extension->Controller, (tempIER | SERIAL_IER_THR));

   TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "--SerialEvtIoWrite()=%X\r\n", status);
   return;
}