1 /* 2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: drivers/usb/usbstor/fdo.c 5 * PURPOSE: USB block storage device driver. 6 * PROGRAMMERS: 7 * James Tabor 8 * Michael Martin (michael.martin@reactos.org) 9 * Johannes Anderwald (johannes.anderwald@reactos.org) 10 */ 11 12 #include "usbstor.h" 13 14 #define NDEBUG 15 #include <debug.h> 16 17 VOID 18 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) 19 { 20 DPRINT1("Dumping Device Descriptor %p\n", DeviceDescriptor); 21 DPRINT1("bLength %x\n", DeviceDescriptor->bLength); 22 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType); 23 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB); 24 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass); 25 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass); 26 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol); 27 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0); 28 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor); 29 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct); 30 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice); 31 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer); 32 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct); 33 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber); 34 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations); 35 } 36 37 NTSTATUS 38 USBSTOR_FdoHandleDeviceRelations( 39 IN PFDO_DEVICE_EXTENSION DeviceExtension, 40 IN OUT PIRP Irp) 41 { 42 ULONG DeviceCount = 0; 43 LONG Index; 44 PDEVICE_RELATIONS DeviceRelations; 45 PIO_STACK_LOCATION IoStack; 46 47 // 48 // get current irp stack location 49 // 50 IoStack = IoGetCurrentIrpStackLocation(Irp); 51 52 // 53 // check if relation type is BusRelations 54 // 55 if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations) 56 { 57 // 58 // FDO always only handles bus relations 59 // 60 return USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp); 61 } 62 63 // 64 // go through array and count device objects 65 // 66 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++) 67 { 68 if (DeviceExtension->ChildPDO[Index]) 69 { 70 // 71 // child pdo 72 // 73 DeviceCount++; 74 } 75 } 76 77 // 78 // allocate device relations 79 // 80 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0)); 81 if (!DeviceRelations) 82 { 83 // 84 // no memory 85 // 86 return STATUS_INSUFFICIENT_RESOURCES; 87 } 88 89 // 90 // add device objects 91 // 92 for(Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++) 93 { 94 if (DeviceExtension->ChildPDO[Index]) 95 { 96 // 97 // store child pdo 98 // 99 DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index]; 100 101 // 102 // add reference 103 // 104 ObReferenceObject(DeviceExtension->ChildPDO[Index]); 105 106 // 107 // increment count 108 // 109 DeviceRelations->Count++; 110 } 111 } 112 113 // 114 // store result 115 // 116 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 117 118 // 119 // request completed successfully 120 // 121 return STATUS_SUCCESS; 122 } 123 124 NTSTATUS 125 USBSTOR_FdoHandleRemoveDevice( 126 IN PDEVICE_OBJECT DeviceObject, 127 IN PFDO_DEVICE_EXTENSION DeviceExtension, 128 IN OUT PIRP Irp) 129 { 130 NTSTATUS Status; 131 ULONG Index; 132 133 DPRINT("Handling FDO removal %p\n", DeviceObject); 134 135 /* FIXME: wait for devices finished processing */ 136 for(Index = 0; Index < 16; Index++) 137 { 138 if (DeviceExtension->ChildPDO[Index] != NULL) 139 { 140 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension->ChildPDO[Index], DeviceExtension->ChildPDO[Index]->ReferenceCount, DeviceExtension->ChildPDO[Index]->AttachedDevice); 141 IoDeleteDevice(DeviceExtension->ChildPDO[Index]); 142 } 143 } 144 145 /* Send the IRP down the stack */ 146 IoSkipCurrentIrpStackLocation(Irp); 147 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 148 149 /* Detach from the device stack */ 150 IoDetachDevice(DeviceExtension->LowerDeviceObject); 151 152 /* Delete the device object */ 153 IoDeleteDevice(DeviceObject); 154 155 return Status; 156 } 157 158 NTSTATUS 159 USBSTOR_FdoHandleStartDevice( 160 IN PDEVICE_OBJECT DeviceObject, 161 IN PFDO_DEVICE_EXTENSION DeviceExtension, 162 IN OUT PIRP Irp) 163 { 164 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc; 165 NTSTATUS Status; 166 UCHAR Index = 0; 167 168 // 169 // forward irp to lower device 170 // 171 Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp); 172 if (!NT_SUCCESS(Status)) 173 { 174 // 175 // failed to start 176 // 177 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status); 178 return Status; 179 } 180 181 // 182 // initialize irp queue 183 // 184 USBSTOR_QueueInitialize(DeviceExtension); 185 186 // 187 // first get device & configuration & string descriptor 188 // 189 Status = USBSTOR_GetDescriptors(DeviceObject); 190 if (!NT_SUCCESS(Status)) 191 { 192 // 193 // failed to get device descriptor 194 // 195 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status); 196 return Status; 197 } 198 199 // 200 // dump device descriptor 201 // 202 USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor); 203 204 // 205 // Check that this device uses bulk transfers and is SCSI 206 // 207 InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR)); 208 209 // 210 // sanity check 211 // 212 ASSERT(InterfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE); 213 ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); 214 215 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc->bInterfaceSubClass); 216 if (InterfaceDesc->bInterfaceProtocol != 0x50) 217 { 218 DPRINT1("USB Device is not a bulk only device and is not currently supported\n"); 219 return STATUS_NOT_SUPPORTED; 220 } 221 222 if (InterfaceDesc->bInterfaceSubClass != 0x06) 223 { 224 // 225 // FIXME: need to pad CDBs to 12 byte 226 // mode select commands must be translated from 1AH / 15h to 5AH / 55h 227 // 228 DPRINT1("[USBSTOR] Error: need to pad CDBs\n"); 229 return STATUS_NOT_IMPLEMENTED; 230 } 231 232 // 233 // now select an interface 234 // 235 Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension); 236 if (!NT_SUCCESS(Status)) 237 { 238 // 239 // failed to get device descriptor 240 // 241 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status); 242 return Status; 243 } 244 245 // 246 // check if we got a bulk in + bulk out endpoint 247 // 248 Status = USBSTOR_GetPipeHandles(DeviceExtension); 249 if (!NT_SUCCESS(Status)) 250 { 251 // 252 // failed to get pipe handles descriptor 253 // 254 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status); 255 return Status; 256 } 257 258 // 259 // get num of lun which are supported 260 // 261 Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension); 262 if (!NT_SUCCESS(Status)) 263 { 264 // 265 // failed to get max LUN 266 // 267 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status); 268 return Status; 269 } 270 271 // 272 // now create for each LUN a device object, 1 minimum 273 // 274 do 275 { 276 // 277 // create pdo 278 // 279 Status = USBSTOR_CreatePDO(DeviceObject, Index); 280 281 // 282 // check for failure 283 // 284 if (!NT_SUCCESS(Status)) 285 { 286 // 287 // failed to create child pdo 288 // 289 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status); 290 return Status; 291 } 292 293 // 294 // increment pdo index 295 // 296 Index++; 297 DeviceExtension->InstanceCount++; 298 299 }while(Index < DeviceExtension->MaxLUN); 300 301 #if 0 302 // 303 // finally get usb device interface 304 // 305 Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface); 306 if (!NT_SUCCESS(Status)) 307 { 308 // 309 // failed to device interface 310 // 311 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status); 312 return Status; 313 } 314 #endif 315 316 317 // 318 // start the timer 319 // 320 //IoStartTimer(DeviceObject); 321 322 323 // 324 // fdo is now initialized 325 // 326 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n"); 327 return STATUS_SUCCESS; 328 } 329 330 NTSTATUS 331 USBSTOR_FdoHandlePnp( 332 IN PDEVICE_OBJECT DeviceObject, 333 IN OUT PIRP Irp) 334 { 335 PIO_STACK_LOCATION IoStack; 336 PFDO_DEVICE_EXTENSION DeviceExtension; 337 NTSTATUS Status; 338 339 // 340 // get current stack location 341 // 342 IoStack = IoGetCurrentIrpStackLocation(Irp); 343 344 // 345 // get device extension 346 // 347 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 348 349 // 350 // sanity check 351 // 352 ASSERT(DeviceExtension->Common.IsFDO); 353 354 switch(IoStack->MinorFunction) 355 { 356 case IRP_MN_SURPRISE_REMOVAL: 357 { 358 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject); 359 Irp->IoStatus.Status = STATUS_SUCCESS; 360 361 // 362 // forward irp to next device object 363 // 364 IoSkipCurrentIrpStackLocation(Irp); 365 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 366 } 367 case IRP_MN_QUERY_DEVICE_RELATIONS: 368 { 369 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject); 370 Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp); 371 break; 372 } 373 case IRP_MN_STOP_DEVICE: 374 { 375 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n"); 376 IoStopTimer(DeviceObject); 377 Irp->IoStatus.Status = STATUS_SUCCESS; 378 379 // 380 // forward irp to next device object 381 // 382 IoSkipCurrentIrpStackLocation(Irp); 383 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 384 } 385 case IRP_MN_REMOVE_DEVICE: 386 { 387 DPRINT("IRP_MN_REMOVE_DEVICE\n"); 388 389 return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp); 390 } 391 case IRP_MN_QUERY_CAPABILITIES: 392 { 393 // 394 // FIXME: set custom capabilities 395 // 396 IoSkipCurrentIrpStackLocation(Irp); 397 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 398 } 399 case IRP_MN_QUERY_STOP_DEVICE: 400 case IRP_MN_QUERY_REMOVE_DEVICE: 401 { 402 #if 0 403 // 404 // we can if nothing is pending 405 // 406 if (DeviceExtension->IrpPendingCount != 0 || 407 DeviceExtension->ActiveSrb != NULL) 408 #else 409 if (TRUE) 410 #endif 411 { 412 /* We have pending requests */ 413 DPRINT1("Failing removal/stop request due to pending requests present\n"); 414 Status = STATUS_UNSUCCESSFUL; 415 } 416 else 417 { 418 /* We're all clear */ 419 Irp->IoStatus.Status = STATUS_SUCCESS; 420 421 IoSkipCurrentIrpStackLocation(Irp); 422 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 423 } 424 break; 425 } 426 case IRP_MN_START_DEVICE: 427 { 428 Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp); 429 break; 430 } 431 default: 432 { 433 // 434 // forward irp to next device object 435 // 436 IoSkipCurrentIrpStackLocation(Irp); 437 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 438 } 439 } 440 441 // 442 // complete request 443 // 444 if (Status != STATUS_PENDING) 445 { 446 // 447 // store result 448 // 449 Irp->IoStatus.Status = Status; 450 451 // 452 // complete request 453 // 454 IoCompleteRequest(Irp, IO_NO_INCREMENT); 455 } 456 457 // 458 // done processing 459 // 460 return Status; 461 } 462