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; }
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; }
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; }
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; }
/* [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); }
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); }