Esempio n. 1
0
NTSTATUS get_status(libusb_device_t *dev, int recipient,
                    int index, char *status, int *ret, int timeout)
{
  NTSTATUS _status = STATUS_SUCCESS;
  URB urb;

  DEBUG_PRINT_NL();
  DEBUG_MESSAGE("get_status(): recipient %02d", recipient);
  DEBUG_MESSAGE("get_status(): index %04d", index);
  DEBUG_MESSAGE("get_status(): timeout %d", timeout);

  memset(&urb, 0, sizeof(URB));

  switch(recipient)
    {
    case USB_RECIP_DEVICE:
      urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_DEVICE;
      break;
    case USB_RECIP_INTERFACE:
      urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_INTERFACE;
      break;
    case USB_RECIP_ENDPOINT:
      urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_ENDPOINT;
      break;
    case USB_RECIP_OTHER:
      urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_OTHER;
      break;
    default:
      DEBUG_ERROR("get_status(): invalid recipient");
      return STATUS_INVALID_PARAMETER;
    }

  urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST);
  urb.UrbControlGetStatusRequest.TransferBufferLength = 2;
  urb.UrbControlGetStatusRequest.TransferBuffer = status; 
  urb.UrbControlGetStatusRequest.Index = (USHORT)index; 
	
  _status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
      
  if(!NT_SUCCESS(_status) || !USBD_SUCCESS(urb.UrbHeader.Status))
    {
      DEBUG_ERROR("get_status(): getting status failed: "
                   "status: 0x%x, urb-status: 0x%x", 
                   _status, urb.UrbHeader.Status);
      *ret = 0;
    }
  else
    {
      *ret = urb.UrbControlGetStatusRequest.TransferBufferLength;
    }

  return _status;
}
NTSTATUS get_interface(libusb_device_t *dev,
                       int interface, unsigned char *altsetting, 
                       int *ret, int timeout)
{
  NTSTATUS status = STATUS_SUCCESS;
  URB urb;

  DEBUG_PRINT_NL();
  DEBUG_MESSAGE("get_interface(): interface %d", interface);
  DEBUG_MESSAGE("get_interface(): timeout %d", timeout);

  if(!dev->config.value)
    {
      DEBUG_ERROR("get_interface(): invalid configuration 0"); 
      return STATUS_INVALID_DEVICE_STATE;
    }

  memset(&urb, 0, sizeof(URB));

  urb.UrbHeader.Function = URB_FUNCTION_GET_INTERFACE;
  urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_GET_INTERFACE_REQUEST);
  urb.UrbControlGetInterfaceRequest.TransferBufferLength = 1;
  urb.UrbControlGetInterfaceRequest.TransferBuffer = altsetting;
  urb.UrbControlGetInterfaceRequest.Interface = (USHORT)interface;
  
  status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
  
  if(!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
    {
      DEBUG_ERROR("get_interface(): getting interface "
                  "failed: status: 0x%x, urb-status: 0x%x", 
                  status, urb.UrbHeader.Status);
      *ret = 0;
    }
  else
    {
      *ret = urb.UrbControlGetInterfaceRequest.TransferBufferLength;
      DEBUG_MESSAGE("get_interface(): current altsetting is %d", *altsetting); 
    }

  return status;
}
NTSTATUS abort_endpoint(libusb_device_t *dev, int endpoint, int timeout)
{
  NTSTATUS status = STATUS_SUCCESS;
  URB urb;

  DEBUG_PRINT_NL();
  DEBUG_MESSAGE("abort_endpoint(): endpoint 0x%02x\n", endpoint);
  DEBUG_MESSAGE("abort_endpoint(): timeout %d\n", timeout);

  memset(&urb, 0, sizeof(struct _URB_PIPE_REQUEST));

  if(!dev->config.value)
    {
      DEBUG_ERROR("abort_endpoint(): invalid configuration 0");
      return STATUS_INVALID_DEVICE_STATE;
    }

  if(!get_pipe_handle(dev, endpoint, &urb.UrbPipeRequest.PipeHandle))
    {
      DEBUG_ERROR("abort_endpoint(): getting endpoint pipe failed");
      return STATUS_INVALID_PARAMETER;
    }

  urb.UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
  urb.UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;

  status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
  
  if(!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
    {
      DEBUG_ERROR("abort_endpoint(): request failed: status: 0x%x, "
                  "urb-status: 0x%x", status, urb.UrbHeader.Status);
    }
  
  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);
}
Esempio n. 5
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);
}
NTSTATUS set_interface(libusb_device_t *dev, int interface, int altsetting,
                       int timeout)
{
  NTSTATUS status = STATUS_SUCCESS;
  URB *urb;
  int i, config_size, tmp_size;

  USB_CONFIGURATION_DESCRIPTOR *configuration_descriptor = NULL;
  USB_INTERFACE_DESCRIPTOR *interface_descriptor = NULL;
  USBD_INTERFACE_INFORMATION *interface_information = NULL;

  DEBUG_PRINT_NL();
  DEBUG_MESSAGE("set_interface(): interface %d", interface);
  DEBUG_MESSAGE("set_interface(): altsetting %d", altsetting);
  DEBUG_MESSAGE("set_interface(): timeout %d", timeout);

  if(!dev->config.value)
    {
      DEBUG_ERROR("release_interface(): device is not configured"); 
      return STATUS_INVALID_DEVICE_STATE;
    }

  configuration_descriptor = get_config_descriptor(dev, dev->config.value, 
                                                   &config_size);
  if(!configuration_descriptor)
    {
      DEBUG_ERROR("set_interface(): memory_allocation error");
      return STATUS_NO_MEMORY;
    }

  interface_descriptor =
    find_interface_desc(configuration_descriptor, config_size, 
                        interface, altsetting);

  if(!interface_descriptor)
    {
      DEBUG_ERROR("set_interface(): interface %d or altsetting %d invalid", 
                  interface, altsetting);
      ExFreePool(configuration_descriptor);
      return STATUS_UNSUCCESSFUL;
    }
  
  tmp_size = sizeof(struct _URB_SELECT_INTERFACE)
    + interface_descriptor->bNumEndpoints
    * sizeof(USBD_PIPE_INFORMATION);


  urb = ExAllocatePool(NonPagedPool, tmp_size);

  if(!urb)
    {
      DEBUG_ERROR("set_interface(): memory_allocation error");
      ExFreePool(configuration_descriptor);
      return STATUS_NO_MEMORY;
    }

  memset(urb, 0, tmp_size);

  urb->UrbHeader.Function = URB_FUNCTION_SELECT_INTERFACE;
  urb->UrbHeader.Length = (USHORT)tmp_size;

  urb->UrbSelectInterface.ConfigurationHandle = dev->config.handle;
  urb->UrbSelectInterface.Interface.Length =
    sizeof(struct _USBD_INTERFACE_INFORMATION);
  urb->UrbSelectInterface.Interface.NumberOfPipes = 
    interface_descriptor->bNumEndpoints;
  urb->UrbSelectInterface.Interface.Length +=
    interface_descriptor->bNumEndpoints 
    * sizeof(struct _USBD_PIPE_INFORMATION);

  urb->UrbSelectInterface.Interface.InterfaceNumber = (UCHAR)interface;
  urb->UrbSelectInterface.Interface.AlternateSetting = (UCHAR)altsetting;

  interface_information = &urb->UrbSelectInterface.Interface;

  for(i = 0; i < interface_descriptor->bNumEndpoints; i++)
    {
      interface_information->Pipes[i].MaximumTransferSize 
        = LIBUSB_MAX_READ_WRITE;
    }

  status = call_usbd(dev, urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);


  if(!NT_SUCCESS(status) || !USBD_SUCCESS(urb->UrbHeader.Status))
    {
      DEBUG_ERROR("set_interface(): setting interface failed: status: 0x%x, "
                  "urb-status: 0x%x", status, urb->UrbHeader.Status);
      ExFreePool(configuration_descriptor);
      ExFreePool(urb);
      return STATUS_UNSUCCESSFUL;
    }

  update_pipe_info(dev, interface_information);

  ExFreePool(configuration_descriptor);
  ExFreePool(urb);

  return status;
}