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 ULONG 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 = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0)); 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 // add device objects 74 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++) 75 { 76 if (DeviceExtension->ChildPDO[Index]) 77 { 78 // store child pdo 79 DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index]; 80 81 // add reference 82 ObReferenceObject(DeviceExtension->ChildPDO[Index]); 83 84 DeviceRelations->Count++; 85 } 86 } 87 88 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 89 Irp->IoStatus.Status = STATUS_SUCCESS; 90 } 91 92 IoCopyCurrentIrpStackLocationToNext(Irp); 93 94 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 95 } 96 97 NTSTATUS 98 USBSTOR_FdoHandleRemoveDevice( 99 IN PDEVICE_OBJECT DeviceObject, 100 IN PFDO_DEVICE_EXTENSION DeviceExtension, 101 IN OUT PIRP Irp) 102 { 103 NTSTATUS Status; 104 ULONG Index; 105 106 DPRINT("Handling FDO removal %p\n", DeviceObject); 107 108 // FIXME: wait for devices finished processing 109 for (Index = 0; Index < 16; Index++) 110 { 111 if (DeviceExtension->ChildPDO[Index] != NULL) 112 { 113 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension->ChildPDO[Index], DeviceExtension->ChildPDO[Index]->ReferenceCount, DeviceExtension->ChildPDO[Index]->AttachedDevice); 114 IoDeleteDevice(DeviceExtension->ChildPDO[Index]); 115 } 116 } 117 118 // Freeing everything in DeviceExtension 119 ASSERT( 120 DeviceExtension->DeviceDescriptor && 121 DeviceExtension->ConfigurationDescriptor && 122 DeviceExtension->InterfaceInformation && 123 DeviceExtension->ResetDeviceWorkItem 124 ); 125 126 ExFreePoolWithTag(DeviceExtension->DeviceDescriptor, USB_STOR_TAG); 127 ExFreePoolWithTag(DeviceExtension->ConfigurationDescriptor, USB_STOR_TAG); 128 ExFreePoolWithTag(DeviceExtension->InterfaceInformation, USB_STOR_TAG); 129 IoFreeWorkItem(DeviceExtension->ResetDeviceWorkItem); 130 131 if (DeviceExtension->SerialNumber) 132 { 133 ExFreePoolWithTag(DeviceExtension->SerialNumber, USB_STOR_TAG); 134 } 135 136 // Send the IRP down the stack 137 IoSkipCurrentIrpStackLocation(Irp); 138 Irp->IoStatus.Status = STATUS_SUCCESS; 139 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 140 141 // Detach from the device stack 142 IoDetachDevice(DeviceExtension->LowerDeviceObject); 143 144 IoDeleteDevice(DeviceObject); 145 146 return Status; 147 } 148 149 NTSTATUS 150 USBSTOR_FdoHandleStartDevice( 151 IN PDEVICE_OBJECT DeviceObject, 152 IN PFDO_DEVICE_EXTENSION DeviceExtension, 153 IN OUT PIRP Irp) 154 { 155 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc; 156 NTSTATUS Status; 157 UCHAR Index = 0; 158 PIO_WORKITEM WorkItem; 159 160 // forward irp to lower device 161 Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp); 162 if (!NT_SUCCESS(Status)) 163 { 164 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status); 165 return Status; 166 } 167 168 if (!DeviceExtension->ResetDeviceWorkItem) 169 { 170 WorkItem = IoAllocateWorkItem(DeviceObject); 171 DeviceExtension->ResetDeviceWorkItem = WorkItem; 172 173 if (!WorkItem) 174 { 175 return STATUS_INSUFFICIENT_RESOURCES; 176 } 177 } 178 179 // initialize irp queue 180 USBSTOR_QueueInitialize(DeviceExtension); 181 182 // first get device & configuration & string descriptor 183 Status = USBSTOR_GetDescriptors(DeviceObject); 184 if (!NT_SUCCESS(Status)) 185 { 186 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status); 187 return Status; 188 } 189 190 #if DBG 191 USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor); 192 #endif 193 194 // Check that this device uses bulk transfers and is SCSI 195 196 InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR)); 197 ASSERT(InterfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE); 198 ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); 199 200 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc->bInterfaceSubClass); 201 if (InterfaceDesc->bInterfaceProtocol != 0x50) 202 { 203 DPRINT1("USB Device is not a bulk only device and is not currently supported\n"); 204 return STATUS_NOT_SUPPORTED; 205 } 206 207 if (InterfaceDesc->bInterfaceSubClass == 0x04) // UFI subclass 208 { 209 // FIXME: need to pad CDBs to 12 byte 210 // mode select commands must be translated from 1AH / 15h to 5AH / 55h 211 DPRINT1("[USBSTOR] Error: need to pad CDBs\n"); 212 return STATUS_NOT_SUPPORTED; 213 } 214 215 // now select an interface 216 Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension); 217 if (!NT_SUCCESS(Status)) 218 { 219 // failed to get device descriptor 220 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status); 221 return Status; 222 } 223 224 // check if we got a bulk in + bulk out endpoint 225 Status = USBSTOR_GetPipeHandles(DeviceExtension); 226 if (!NT_SUCCESS(Status)) 227 { 228 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status); 229 return Status; 230 } 231 232 Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension); 233 if (!NT_SUCCESS(Status)) 234 { 235 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status); 236 return Status; 237 } 238 239 // now create for each LUN a device object, 1 minimum 240 do 241 { 242 Status = USBSTOR_CreatePDO(DeviceObject, Index); 243 244 if (!NT_SUCCESS(Status)) 245 { 246 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status); 247 return Status; 248 } 249 250 Index++; 251 DeviceExtension->InstanceCount++; 252 253 } while(Index < DeviceExtension->MaxLUN); 254 255 #if 0 256 // 257 // finally get usb device interface 258 // 259 Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface); 260 if (!NT_SUCCESS(Status)) 261 { 262 // 263 // failed to device interface 264 // 265 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status); 266 return Status; 267 } 268 #endif 269 270 //IoStartTimer(DeviceObject); 271 272 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n"); 273 return STATUS_SUCCESS; 274 } 275 276 NTSTATUS 277 USBSTOR_FdoHandlePnp( 278 IN PDEVICE_OBJECT DeviceObject, 279 IN OUT PIRP Irp) 280 { 281 PIO_STACK_LOCATION IoStack; 282 PFDO_DEVICE_EXTENSION DeviceExtension; 283 NTSTATUS Status; 284 285 IoStack = IoGetCurrentIrpStackLocation(Irp); 286 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 287 ASSERT(DeviceExtension->Common.IsFDO); 288 289 switch(IoStack->MinorFunction) 290 { 291 case IRP_MN_SURPRISE_REMOVAL: 292 { 293 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject); 294 Irp->IoStatus.Status = STATUS_SUCCESS; 295 296 // forward irp to next device object 297 IoSkipCurrentIrpStackLocation(Irp); 298 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 299 } 300 case IRP_MN_QUERY_DEVICE_RELATIONS: 301 { 302 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p Type: %u\n", DeviceObject, IoStack->Parameters.QueryDeviceRelations.Type); 303 return USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp); 304 } 305 case IRP_MN_STOP_DEVICE: 306 { 307 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n"); 308 IoStopTimer(DeviceObject); 309 Irp->IoStatus.Status = STATUS_SUCCESS; 310 311 // forward irp to next device object 312 IoSkipCurrentIrpStackLocation(Irp); 313 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 314 } 315 case IRP_MN_REMOVE_DEVICE: 316 { 317 DPRINT("IRP_MN_REMOVE_DEVICE\n"); 318 319 return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp); 320 } 321 case IRP_MN_QUERY_CAPABILITIES: 322 { 323 // FIXME: set custom capabilities 324 IoSkipCurrentIrpStackLocation(Irp); 325 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 326 } 327 case IRP_MN_QUERY_STOP_DEVICE: 328 case IRP_MN_QUERY_REMOVE_DEVICE: 329 { 330 #if 0 331 // 332 // we can if nothing is pending 333 // 334 if (DeviceExtension->IrpPendingCount != 0 || 335 DeviceExtension->ActiveSrb != NULL) 336 #else 337 if (TRUE) 338 #endif 339 { 340 /* We have pending requests */ 341 DPRINT1("Failing removal/stop request due to pending requests present\n"); 342 Status = STATUS_UNSUCCESSFUL; 343 } 344 else 345 { 346 /* We're all clear */ 347 Irp->IoStatus.Status = STATUS_SUCCESS; 348 349 IoSkipCurrentIrpStackLocation(Irp); 350 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 351 } 352 break; 353 } 354 case IRP_MN_START_DEVICE: 355 { 356 Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp); 357 break; 358 } 359 default: 360 { 361 // forward irp to next device object 362 IoSkipCurrentIrpStackLocation(Irp); 363 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 364 } 365 } 366 367 if (Status != STATUS_PENDING) 368 { 369 Irp->IoStatus.Status = Status; 370 IoCompleteRequest(Irp, IO_NO_INCREMENT); 371 } 372 373 return Status; 374 } 375