This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED;
This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_CONNECT;
This->m_PortStatus[i].PortChange |= USB_PORT_STATUS_CONNECT;
+ }
+ else
+ {
+ DPRINT1("Device disconnected on port %d\n", i);
//
- // is there a status change callback
+ // update port status flags
//
- if (This->m_SCECallBack != NULL)
- {
- //
- // queue work item for processing
- //
- ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
- }
+ This->m_PortStatus[i].PortStatus &= ~USB_PORT_STATUS_HIGH_SPEED;
+ This->m_PortStatus[i].PortStatus &= ~USB_PORT_STATUS_CONNECT;
+ This->m_PortStatus[i].PortChange |= USB_PORT_STATUS_CONNECT;
}
- else
+
+ //
+ // is there a status change callback
+ //
+ if (This->m_SCECallBack != NULL)
{
- DPRINT1("Device disconnected on port %d\n", i);
+ //
+ // queue work item for processing
+ //
+ ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
}
//
IN LONG PortId,
OUT PDEVICE_OBJECT *UsbChildDeviceObject);
+NTSTATUS
+DestroyUsbChildDeviceObject(
+ IN PDEVICE_OBJECT UsbHubDeviceObject,
+ IN LONG PortId);
+
NTSTATUS
SubmitRequestToRootHub(
IN PDEVICE_OBJECT RootHubDeviceObject,
{
DPRINT1("Device disconnected from port %d\n", PortId);
- //
- // FIXME: Remove the device, and deallocate memory
- //
+ Status = DestroyUsbChildDeviceObject(DeviceObject, PortId);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to delete child device object after disconnect\n");
+ }
}
else
{
return Status;
}
+NTSTATUS
+DestroyUsbChildDeviceObject(
+ IN PDEVICE_OBJECT UsbHubDeviceObject,
+ IN LONG PortId)
+{
+ PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension;
+ PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL;
+ PDEVICE_OBJECT ChildDeviceObject = NULL;
+ ULONG Index = 0;
+
+ DPRINT1("Removing device on port %d (Child index: %d)\n", PortId, Index);
+
+ for (Index = 0; Index < USB_MAXCHILDREN; Index++)
+ {
+ if (HubDeviceExtension->ChildDeviceObject[Index])
+ {
+ UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension;
+
+ /* Check if it matches the port ID */
+ if (UsbChildExtension->PortNumber == PortId)
+ {
+ /* We found it */
+ ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index];
+ break;
+ }
+ }
+ }
+
+ /* Fail the request if the device doesn't exist */
+ if (!ChildDeviceObject)
+ {
+ DPRINT1("Removal request for non-existant device!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Remove the device from the table */
+ HubDeviceExtension->ChildDeviceObject[Index] = NULL;
+
+ /* Invalidate device relations for the root hub */
+ IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations);
+
+ /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
CreateUsbChildDeviceObject(
IN PDEVICE_OBJECT UsbHubDeviceObject,
}
case IRP_MN_REMOVE_DEVICE:
{
- //
- // FIXME
- //
- Status = STATUS_SUCCESS;
- break;
+ PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
+ PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
+
+ DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
+
+ /* Remove the device */
+ HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0);
+
+ /* Complete the IRP */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ /* Delete the device object */
+ IoDeleteDevice(DeviceObject);
+ return STATUS_SUCCESS;
}
default:
{
//
This->m_PortStatus[Index].PortStatus |= USB_PORT_STATUS_LOW_SPEED;
}
-
- //
- // is there a status change callback
- //
- if (This->m_SCECallBack != NULL)
- {
- //
- // queue work item for processing
- //
- ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
- }
}
else
{
// device disconnected
//
DPRINT1("Device disconnected at Port %x\n", Index);
+
+ //
+ // update port status flags
+ //
+ This->m_PortStatus[Index].PortStatus &= ~USB_PORT_STATUS_LOW_SPEED;
+ This->m_PortStatus[Index].PortStatus &= ~USB_PORT_STATUS_CONNECT;
+ This->m_PortStatus[Index].PortChange |= USB_PORT_STATUS_CONNECT;
+ }
+
+ //
+ // is there a status change callback
+ //
+ if (This->m_SCECallBack != NULL)
+ {
+ //
+ // queue work item for processing
+ //
+ ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
}
}
}
return STATUS_SUCCESS;
}
+NTSTATUS
+USBSTOR_FdoHandleRemoveDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension,
+ IN OUT PIRP Irp)
+{
+ NTSTATUS Status;
+
+ DPRINT1("Handling FDO removal\n");
+
+ /* We don't need to request removal of our children here */
+
+ /* Send the IRP down the stack */
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+
+ /* Detach from the device stack */
+ /* IoDetachDevice(DeviceExtension->LowerDeviceObject); */ //This crashes for some reason during unload
+
+ /* Delete the device object */
+ IoDeleteDevice(DeviceObject);
+
+ return Status;
+}
+
NTSTATUS
USBSTOR_FdoHandleStartDevice(
IN PDEVICE_OBJECT DeviceObject,
Status = STATUS_NOT_SUPPORTED;
break;
case IRP_MN_REMOVE_DEVICE:
- DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_REMOVE_DEVICE unimplemented\n");
- Status = STATUS_NOT_SUPPORTED;
- break;
+ {
+ DPRINT1("IRP_MN_REMOVE_DEVICE\n");
+
+ return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
+ }
case IRP_MN_QUERY_CAPABILITIES:
{
//
break;
}
case IRP_MN_REMOVE_DEVICE:
- DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_REMOVE_DEVICE unimplemented\n");
- Status = STATUS_SUCCESS;
- break;
+ {
+ DPRINT1("IRP_MN_REMOVE_DEVICE\n");
+
+ /* Complete the IRP */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ /* Delete the device object */
+ IoDeleteDevice(DeviceObject);
+
+ return STATUS_SUCCESS;
+ }
case IRP_MN_QUERY_CAPABILITIES:
{
//