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