Exemplo n.º 1
0
void remove_lock_release_and_wait(libusb_device_t *dev)
{
  dev->remove_lock.remove_pending = TRUE;
  remove_lock_release(dev);
  remove_lock_release(dev);
  KeWaitForSingleObject(&dev->remove_lock.event, Executive, KernelMode,
                        FALSE, NULL);
}
static NTSTATUS DDKAPI 
on_query_capabilities_complete(DEVICE_OBJECT *device_object,
                               IRP *irp, void *context)
{
  libusb_device_t *dev = device_object->DeviceExtension;
  IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);

  if(irp->PendingReturned)
    {
      IoMarkIrpPending(irp);
    }

  if(NT_SUCCESS(irp->IoStatus.Status))
    {
      if(!dev->is_filter)
        {
          /* apply registry setting */
          stack_location->Parameters.DeviceCapabilities.Capabilities
            ->SurpriseRemovalOK = dev->surprise_removal_ok;
        }

      /* save supported device power states */
      memcpy(dev->device_power_states, stack_location
             ->Parameters.DeviceCapabilities.Capabilities->DeviceState,
             sizeof(dev->device_power_states));
    }

  remove_lock_release(dev);

  return STATUS_SUCCESS;
}
Exemplo n.º 3
0
static NTSTATUS DDKAPI
on_power_state_complete(DEVICE_OBJECT *device_object,
                        IRP           *irp,
                        void          *context)
{
    libusb_device_t *dev = context;
    IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
    POWER_STATE power_state = stack_location->Parameters.Power.State;
    DEVICE_POWER_STATE dev_power_state;

    if (irp->PendingReturned)
    {
        IoMarkIrpPending(irp);
    }

    if (NT_SUCCESS(irp->IoStatus.Status))
    {
        if (stack_location->Parameters.Power.Type == SystemPowerState)
        {
            USBMSG("S%d %s\n",
				power_state.SystemState - PowerSystemWorking, dev->device_id);

            /* save current system state */
            dev->power_state.SystemState = power_state.SystemState;

            /* get supported device power state from the array reported by */
            /* IRP_MN_QUERY_CAPABILITIES */
            dev_power_state = dev->device_power_states[power_state.SystemState];

            /* set the device power state, but don't block the thread */
            power_set_device_state(dev, dev_power_state, FALSE);
        }
        else /* DevicePowerState */
        {
            USBMSG("D%d %s\n",
				power_state.DeviceState - PowerDeviceD0, dev->device_id);

            if (power_state.DeviceState <= dev->power_state.DeviceState)
            {
                /* device is powered up, */
                /* report device state to Power Manager */
                PoSetPowerState(dev->self, DevicePowerState, power_state);
            }
            /* save current device state */
            dev->power_state.DeviceState = power_state.DeviceState;
        }
    }
    else
    {
        USBMSG0("failed\n");
    }

    remove_lock_release(dev);

    return STATUS_SUCCESS;
}
Exemplo n.º 4
0
NTSTATUS DDKAPI transfer_complete(DEVICE_OBJECT *device_object, IRP *irp, 
                                  void *context)
{
  context_t *c = (context_t *)context;
  int transmitted = 0;
  libusb_device_t *dev = device_object->DeviceExtension;

  if(irp->PendingReturned)
    {
      IoMarkIrpPending(irp);
    }

  if(NT_SUCCESS(irp->IoStatus.Status) 
     && USBD_SUCCESS(c->urb->UrbHeader.Status))
    {
      if(c->urb->UrbHeader.Function == URB_FUNCTION_ISOCH_TRANSFER)
        {
          transmitted = c->urb->UrbIsochronousTransfer.TransferBufferLength;
        }
      if(c->urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER)
        {
          transmitted 
            = c->urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
        }
      
      DEBUG_MESSAGE("transfer_complete(): sequence %d: %d bytes transmitted", 
                    c->sequence, transmitted);
    }
  else
    {
      if(irp->IoStatus.Status == STATUS_CANCELLED)
        {
          DEBUG_ERROR("transfer_complete(): sequence %d: timeout error",
                      c->sequence);
        }
      else
        {
          DEBUG_ERROR("transfer_complete(): sequence %d: transfer failed: "
                      "status: 0x%x, urb-status: 0x%x", 
                      c->sequence, irp->IoStatus.Status, 
                      c->urb->UrbHeader.Status);
        }
    }

  ExFreePool(c->urb);
  ExFreePool(c);

  irp->IoStatus.Information = transmitted;

  remove_lock_release(dev);

  return STATUS_SUCCESS;
}
Exemplo n.º 5
0
static NTSTATUS DDKAPI
on_filter_power_state_complete(DEVICE_OBJECT *device_object,
                               IRP           *irp,
                               void          *context)
{
    libusb_device_t *dev = context;
    IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
    POWER_STATE power_state = stack_location->Parameters.Power.State;

    if (NT_SUCCESS(irp->IoStatus.Status))
    {
        if (stack_location->Parameters.Power.Type == SystemPowerState)
        {
            USBMSG("S%d\n",
				power_state.SystemState - PowerSystemWorking);

            /* save current system state */
            dev->power_state.SystemState = power_state.SystemState;


        }
        else /* DevicePowerState */
        {
            USBMSG("D%d\n",
				power_state.DeviceState - PowerDeviceD0);

            if (power_state.DeviceState <= dev->power_state.DeviceState)
            {
                /* device is powered up, */
                /* report device state to Power Manager */
                PoSetPowerState(dev->self, DevicePowerState, power_state);
            }

            /* save current device state */
            dev->power_state.DeviceState = power_state.DeviceState;
        }
    }
    else
    {
        USBMSG0("failed\n");
    }

    remove_lock_release(dev);

    return STATUS_SUCCESS;
}
static NTSTATUS DDKAPI 
on_device_usage_notification_complete(DEVICE_OBJECT *device_object,
                                      IRP *irp, void *context)
{
  libusb_device_t *dev = device_object->DeviceExtension;

  if(irp->PendingReturned)
    {
      IoMarkIrpPending(irp);
    }

  if(!(dev->next_stack_device->Flags & DO_POWER_PAGABLE))
    {
      device_object->Flags &= ~DO_POWER_PAGABLE;
    }

  remove_lock_release(dev);

  return STATUS_SUCCESS;
}
static NTSTATUS DDKAPI 
on_start_complete(DEVICE_OBJECT *device_object, IRP *irp, void *context)
{
  libusb_device_t *dev = device_object->DeviceExtension;

  if(irp->PendingReturned)
    {
      IoMarkIrpPending(irp);
    }
  
  if(dev->next_stack_device->Characteristics & FILE_REMOVABLE_MEDIA) 
    {
      device_object->Characteristics |= FILE_REMOVABLE_MEDIA;
    }
  
  dev->is_started = TRUE;

  remove_lock_release(dev);

  return STATUS_SUCCESS;
}
Exemplo n.º 8
0
/* [trobinso MOD 4/16/2010]
 * If running as a filter, do not act as power policy owner.
 */
NTSTATUS dispatch_power(libusb_device_t *dev, IRP *irp)
{
    IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
    POWER_STATE power_state;
    NTSTATUS status;

    status = remove_lock_acquire(dev);

    if (!NT_SUCCESS(status))
    {
        irp->IoStatus.Status = status;
        PoStartNextPowerIrp(irp);
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        return status;
    }

    if (stack_location->MinorFunction == IRP_MN_SET_POWER)
    {
        power_state = stack_location->Parameters.Power.State;

        if (stack_location->Parameters.Power.Type == SystemPowerState)
        {
            USBMSG("IRP_MN_SET_POWER: S%d %s\n",
				power_state.SystemState - PowerSystemWorking, dev->device_id);
        }
        else
        {
            USBMSG("IRP_MN_SET_POWER: D%d %s\n",
				power_state.DeviceState - PowerDeviceD0, dev->device_id);

            if (power_state.DeviceState > dev->power_state.DeviceState)
            {
                /* device is powered down, report device state to the */
                /* Power Manager before sending the IRP down */
                /* (power up is handled by the completion routine) */
                PoSetPowerState(dev->self, DevicePowerState, power_state);
            }
        }

        /* TODO: should PoStartNextPowerIrp() be called here or from the */
        /* completion routine? */
        PoStartNextPowerIrp(irp);

        IoCopyCurrentIrpStackLocationToNext(irp);
        if (!dev->is_filter && !dev->disallow_power_control)
        {
            IoSetCompletionRoutine(irp,
                                   on_power_state_complete,
                                   dev,
                                   TRUE, /* on success */
                                   TRUE, /* on error   */
                                   TRUE);/* on cancel  */
        }
        else
        {
            IoSetCompletionRoutine(irp,
                                   on_filter_power_state_complete,
                                   dev,
                                   TRUE, /* on success */
                                   TRUE, /* on error   */
                                   TRUE);/* on cancel  */
        }

        return PoCallDriver(dev->next_stack_device, irp);
    }
    else
    {
		/* pass all other power IRPs down without setting a completion routine */
        PoStartNextPowerIrp(irp);
        IoSkipCurrentIrpStackLocation(irp);
        status = PoCallDriver(dev->next_stack_device, irp);
        remove_lock_release(dev);

        return status;
    }
}
NTSTATUS dispatch_pnp(libusb_device_t *dev, IRP *irp)
{
  NTSTATUS status = STATUS_SUCCESS;
  IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
  UNICODE_STRING symbolic_link_name;
  WCHAR tmp_name[128];

  status = remove_lock_acquire(dev);
  
  if(!NT_SUCCESS(status))
    { 
      return complete_irp(irp, status, 0);
    }

  DEBUG_PRINT_NL();

  switch(stack_location->MinorFunction) 
    {     
    case IRP_MN_REMOVE_DEVICE:

      DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_REMOVE_DEVICE");

      dev->is_started = FALSE;
      
      /* wait until all outstanding requests are finished */
      remove_lock_release_and_wait(dev);

      status = pass_irp_down(dev, irp, NULL, NULL); 

      DEBUG_MESSAGE("dispatch_pnp(): deleting device #%d", dev->id);
      
      _snwprintf(tmp_name, sizeof(tmp_name)/sizeof(WCHAR), L"%s%04d", 
                 LIBUSB_SYMBOLIC_LINK_NAME, dev->id);
      
      /* delete the symbolic link */
      RtlInitUnicodeString(&symbolic_link_name, tmp_name);
      IoDeleteSymbolicLink(&symbolic_link_name);

      /* delete the device object */
      IoDetachDevice(dev->next_stack_device);
      IoDeleteDevice(dev->self);

      return status;

    case IRP_MN_SURPRISE_REMOVAL:

      DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_SURPRISE_REMOVAL");
      dev->is_started = FALSE;
      break;

    case IRP_MN_START_DEVICE:

      DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_START_DEVICE");

/*       if(!NT_SUCCESS(set_configuration(dev, 1, 1000))) */
/*         { */
/*           DEBUG_ERROR("dispatch_pnp(): IRP_MN_START_DEVICE: selecting " */
/*                       "configuration failed"); */
/*         } */

      /* report device state to Power Manager */
      /* power_state.DeviceState has been set to D0 by add_device() */
      PoSetPowerState(dev->self, DevicePowerState, dev->power_state);

      return pass_irp_down(dev, irp, on_start_complete, NULL);

    case IRP_MN_STOP_DEVICE:

      dev->is_started = FALSE;
      DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_STOP_DEVICE");
      break;

    case IRP_MN_DEVICE_USAGE_NOTIFICATION:

      DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_DEVICE_USAGE_NOTIFICATION");

      if(!dev->self->AttachedDevice
         || (dev->self->AttachedDevice->Flags & DO_POWER_PAGABLE))
        {
          dev->self->Flags |= DO_POWER_PAGABLE;
        }

      return pass_irp_down(dev, irp, on_device_usage_notification_complete,
                           NULL);

    case IRP_MN_QUERY_CAPABILITIES: 

      DEBUG_MESSAGE("dispatch_pnp(): IRP_MN_QUERY_CAPABILITIES");

      if(!dev->is_filter)
        {
          /* apply registry setting */
          stack_location->Parameters.DeviceCapabilities.Capabilities
            ->SurpriseRemovalOK = dev->surprise_removal_ok;
        }

      return pass_irp_down(dev, irp, on_query_capabilities_complete,  NULL);

    default:
      ;
    }

  remove_lock_release(dev);
  return pass_irp_down(dev, irp, NULL, NULL);
}
Exemplo n.º 10
0
NTSTATUS transfer(libusb_device_t *dev, IRP *irp,
                  int direction, int urb_function, int endpoint, 
                  int packet_size, MDL *buffer, int size)
{
  IO_STACK_LOCATION *stack_location = NULL;
  context_t *context;
  NTSTATUS status = STATUS_SUCCESS;
 
  DEBUG_PRINT_NL();

  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
    DEBUG_MESSAGE("transfer(): isochronous transfer");
  else
    DEBUG_MESSAGE("transfer(): bulk or interrupt transfer");

  if(direction == USBD_TRANSFER_DIRECTION_IN)
    DEBUG_MESSAGE("transfer(): direction in");
  else
    DEBUG_MESSAGE("transfer(): direction out");

  DEBUG_MESSAGE("transfer(): endpoint 0x%02x", endpoint);

  if(urb_function == URB_FUNCTION_ISOCH_TRANSFER)
    DEBUG_MESSAGE("transfer(): packet_size 0x%x", packet_size);

  DEBUG_MESSAGE("transfer(): size %d", size);
  DEBUG_MESSAGE("transfer(): sequence %d", sequence);
  DEBUG_PRINT_NL();

  if(!dev->config.value)
    {
      DEBUG_ERROR("transfer(): invalid configuration 0");
      remove_lock_release(dev);
      return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0);
    }
  
  context = ExAllocatePool(NonPagedPool, sizeof(context_t));

  if(!context)
    {
      remove_lock_release(dev);
      return complete_irp(irp, STATUS_NO_MEMORY, 0);
    }

  status = create_urb(dev, &context->urb, direction, urb_function, 
                      endpoint, packet_size, buffer, size);
    
  if(!NT_SUCCESS(status))
    {
      ExFreePool(context);
      remove_lock_release(dev);
      return complete_irp(irp, status, 0);
    }

  context->sequence = sequence++;

  stack_location = IoGetNextIrpStackLocation(irp);
    
  stack_location->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  stack_location->Parameters.Others.Argument1 = context->urb;
  stack_location->Parameters.DeviceIoControl.IoControlCode 
    = IOCTL_INTERNAL_USB_SUBMIT_URB;
    
  IoSetCompletionRoutine(irp, transfer_complete, context,
                         TRUE, TRUE, TRUE);
    
  return IoCallDriver(dev->target_device, irp);
}