1 /* 2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: USB block storage device driver. 5 * COPYRIGHT: 2005-2006 James Tabor 6 * 2011-2012 Michael Martin (michael.martin@reactos.org) 7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org) 8 * 2019 Victor Perevertkin (victor.perevertkin@reactos.org) 9 */ 10 11 #include "usbstor.h" 12 13 #define NDEBUG 14 #include <debug.h> 15 16 17 #if DBG 18 static 19 VOID 20 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) 21 { 22 DPRINT("Dumping Device Descriptor %p\n", DeviceDescriptor); 23 DPRINT("bLength %x\n", DeviceDescriptor->bLength); 24 DPRINT("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType); 25 DPRINT("bcdUSB %x\n", DeviceDescriptor->bcdUSB); 26 DPRINT("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass); 27 DPRINT("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass); 28 DPRINT("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol); 29 DPRINT("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0); 30 DPRINT("idVendor %x\n", DeviceDescriptor->idVendor); 31 DPRINT("idProduct %x\n", DeviceDescriptor->idProduct); 32 DPRINT("bcdDevice %x\n", DeviceDescriptor->bcdDevice); 33 DPRINT("iManufacturer %x\n", DeviceDescriptor->iManufacturer); 34 DPRINT("iProduct %x\n", DeviceDescriptor->iProduct); 35 DPRINT("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber); 36 DPRINT("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations); 37 } 38 #endif 39 40 NTSTATUS 41 USBSTOR_FdoHandleDeviceRelations( 42 IN PFDO_DEVICE_EXTENSION DeviceExtension, 43 IN OUT PIRP Irp) 44 { 45 INT32 DeviceCount = 0; 46 LONG Index; 47 PDEVICE_RELATIONS DeviceRelations; 48 PIO_STACK_LOCATION IoStack; 49 50 IoStack = IoGetCurrentIrpStackLocation(Irp); 51 52 // FDO always only handles bus relations 53 if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations) 54 { 55 // go through array and count device objects 56 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++) 57 { 58 if (DeviceExtension->ChildPDO[Index]) 59 { 60 DeviceCount++; 61 } 62 } 63 64 DeviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount - 1) * sizeof(PDEVICE_OBJECT), USB_STOR_TAG); 65 if (!DeviceRelations) 66 { 67 Irp->IoStatus.Information = 0; 68 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 69 IoCompleteRequest(Irp, IO_NO_INCREMENT); 70 return STATUS_INSUFFICIENT_RESOURCES; 71 } 72 73 DeviceRelations->Count = 0; 74 75 // add device objects 76 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++) 77 { 78 if (DeviceExtension->ChildPDO[Index]) 79 { 80 // store child pdo 81 DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index]; 82 83 // add reference 84 ObReferenceObject(DeviceExtension->ChildPDO[Index]); 85 86 DeviceRelations->Count++; 87 } 88 } 89 90 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 91 Irp->IoStatus.Status = STATUS_SUCCESS; 92 } 93 94 IoCopyCurrentIrpStackLocationToNext(Irp); 95 96 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 97 } 98 99 NTSTATUS 100 USBSTOR_FdoHandleRemoveDevice( 101 IN PDEVICE_OBJECT DeviceObject, 102 IN PFDO_DEVICE_EXTENSION DeviceExtension, 103 IN OUT PIRP Irp) 104 { 105 NTSTATUS Status; 106 ULONG Index; 107 108 DPRINT("Handling FDO removal %p\n", DeviceObject); 109 110 // FIXME: wait for devices finished processing 111 for (Index = 0; Index < USB_MAXCHILDREN; Index++) 112 { 113 if (DeviceExtension->ChildPDO[Index] != NULL) 114 { 115 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension->ChildPDO[Index], DeviceExtension->ChildPDO[Index]->ReferenceCount, DeviceExtension->ChildPDO[Index]->AttachedDevice); 116 IoDeleteDevice(DeviceExtension->ChildPDO[Index]); 117 } 118 } 119 120 // Freeing everything in DeviceExtension 121 ASSERT( 122 DeviceExtension->DeviceDescriptor && 123 DeviceExtension->ConfigurationDescriptor && 124 DeviceExtension->InterfaceInformation && 125 DeviceExtension->ResetDeviceWorkItem 126 ); 127 128 ExFreePoolWithTag(DeviceExtension->DeviceDescriptor, USB_STOR_TAG); 129 ExFreePoolWithTag(DeviceExtension->ConfigurationDescriptor, USB_STOR_TAG); 130 ExFreePoolWithTag(DeviceExtension->InterfaceInformation, USB_STOR_TAG); 131 IoFreeWorkItem(DeviceExtension->ResetDeviceWorkItem); 132 133 if (DeviceExtension->SerialNumber) 134 { 135 ExFreePoolWithTag(DeviceExtension->SerialNumber, USB_STOR_TAG); 136 } 137 138 // Send the IRP down the stack 139 IoSkipCurrentIrpStackLocation(Irp); 140 Irp->IoStatus.Status = STATUS_SUCCESS; 141 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 142 143 // Detach from the device stack 144 IoDetachDevice(DeviceExtension->LowerDeviceObject); 145 146 IoDeleteDevice(DeviceObject); 147 148 return Status; 149 } 150 151 NTSTATUS 152 USBSTOR_FdoHandleStartDevice( 153 IN PDEVICE_OBJECT DeviceObject, 154 IN PFDO_DEVICE_EXTENSION DeviceExtension, 155 IN OUT PIRP Irp) 156 { 157 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc; 158 NTSTATUS Status; 159 UCHAR Index = 0; 160 PIO_WORKITEM WorkItem; 161 162 // forward irp to lower device 163 if (!IoForwardIrpSynchronously(DeviceExtension->LowerDeviceObject, Irp)) 164 { 165 return STATUS_UNSUCCESSFUL; 166 } 167 168 Status = Irp->IoStatus.Status; 169 if (!NT_SUCCESS(Status)) 170 { 171 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status); 172 return Status; 173 } 174 175 if (!DeviceExtension->ResetDeviceWorkItem) 176 { 177 WorkItem = IoAllocateWorkItem(DeviceObject); 178 DeviceExtension->ResetDeviceWorkItem = WorkItem; 179 180 if (!WorkItem) 181 { 182 return STATUS_INSUFFICIENT_RESOURCES; 183 } 184 } 185 186 // initialize irp queue 187 USBSTOR_QueueInitialize(DeviceExtension); 188 189 // first get device & configuration & string descriptor 190 Status = USBSTOR_GetDescriptors(DeviceObject); 191 if (!NT_SUCCESS(Status)) 192 { 193 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status); 194 return Status; 195 } 196 197 #if DBG 198 USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor); 199 #endif 200 201 // Check that this device uses bulk transfers and is SCSI 202 203 InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR)); 204 ASSERT(InterfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE); 205 ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); 206 207 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc->bInterfaceSubClass); 208 if (InterfaceDesc->bInterfaceProtocol != USB_PROTOCOL_BULK) 209 { 210 DPRINT1("USB Device is not a bulk only device and is not currently supported\n"); 211 return STATUS_NOT_SUPPORTED; 212 } 213 214 if (InterfaceDesc->bInterfaceSubClass == USB_SUBCLASS_UFI) 215 { 216 DPRINT1("USB Floppy devices are not supported\n"); 217 return STATUS_NOT_SUPPORTED; 218 } 219 220 // now select an interface 221 Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension); 222 if (!NT_SUCCESS(Status)) 223 { 224 // failed to get device descriptor 225 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status); 226 return Status; 227 } 228 229 // check if we got a bulk in + bulk out endpoint 230 Status = USBSTOR_GetPipeHandles(DeviceExtension); 231 if (!NT_SUCCESS(Status)) 232 { 233 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status); 234 return Status; 235 } 236 237 Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension); 238 if (!NT_SUCCESS(Status)) 239 { 240 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status); 241 return Status; 242 } 243 244 // now create for each LUN a device object, 1 minimum 245 do 246 { 247 Status = USBSTOR_CreatePDO(DeviceObject, Index); 248 249 if (!NT_SUCCESS(Status)) 250 { 251 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status); 252 return Status; 253 } 254 255 Index++; 256 DeviceExtension->InstanceCount++; 257 258 } while(Index < DeviceExtension->MaxLUN); 259 260 #if 0 261 // 262 // finally get usb device interface 263 // 264 Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface); 265 if (!NT_SUCCESS(Status)) 266 { 267 // 268 // failed to device interface 269 // 270 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status); 271 return Status; 272 } 273 #endif 274 275 //IoStartTimer(DeviceObject); 276 277 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n"); 278 return STATUS_SUCCESS; 279 } 280 281 NTSTATUS 282 USBSTOR_FdoHandlePnp( 283 IN PDEVICE_OBJECT DeviceObject, 284 IN OUT PIRP Irp) 285 { 286 PIO_STACK_LOCATION IoStack; 287 PFDO_DEVICE_EXTENSION DeviceExtension; 288 NTSTATUS Status; 289 290 IoStack = IoGetCurrentIrpStackLocation(Irp); 291 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 292 ASSERT(DeviceExtension->Common.IsFDO); 293 294 switch(IoStack->MinorFunction) 295 { 296 case IRP_MN_SURPRISE_REMOVAL: 297 { 298 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject); 299 Irp->IoStatus.Status = STATUS_SUCCESS; 300 301 // forward irp to next device object 302 IoSkipCurrentIrpStackLocation(Irp); 303 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 304 } 305 case IRP_MN_QUERY_DEVICE_RELATIONS: 306 { 307 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p Type: %u\n", DeviceObject, IoStack->Parameters.QueryDeviceRelations.Type); 308 return USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp); 309 } 310 case IRP_MN_STOP_DEVICE: 311 { 312 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n"); 313 IoStopTimer(DeviceObject); 314 Irp->IoStatus.Status = STATUS_SUCCESS; 315 316 // forward irp to next device object 317 IoSkipCurrentIrpStackLocation(Irp); 318 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 319 } 320 case IRP_MN_REMOVE_DEVICE: 321 { 322 DPRINT("IRP_MN_REMOVE_DEVICE\n"); 323 324 return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp); 325 } 326 case IRP_MN_QUERY_CAPABILITIES: 327 { 328 // FIXME: set custom capabilities 329 IoSkipCurrentIrpStackLocation(Irp); 330 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 331 } 332 case IRP_MN_QUERY_STOP_DEVICE: 333 case IRP_MN_QUERY_REMOVE_DEVICE: 334 { 335 if (DeviceExtension->IrpPendingCount != 0 || DeviceExtension->ActiveSrb != NULL) 336 { 337 /* We have pending requests */ 338 DPRINT1("Failing removal/stop request due to pending requests present\n"); 339 Status = STATUS_UNSUCCESSFUL; 340 } 341 else 342 { 343 /* We're all clear */ 344 Irp->IoStatus.Status = STATUS_SUCCESS; 345 346 IoSkipCurrentIrpStackLocation(Irp); 347 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 348 } 349 break; 350 } 351 case IRP_MN_START_DEVICE: 352 { 353 Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp); 354 break; 355 } 356 default: 357 { 358 // forward irp to next device object 359 IoSkipCurrentIrpStackLocation(Irp); 360 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 361 } 362 } 363 364 if (Status != STATUS_PENDING) 365 { 366 Irp->IoStatus.Status = Status; 367 IoCompleteRequest(Irp, IO_NO_INCREMENT); 368 } 369 370 return Status; 371 } 372