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/misc.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 // 18 // driver verifier 19 // 20 IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine; 21 22 NTSTATUS 23 NTAPI 24 USBSTOR_SyncForwardIrpCompletionRoutine( 25 PDEVICE_OBJECT DeviceObject, 26 PIRP Irp, 27 PVOID Context) 28 { 29 if (Irp->PendingReturned) 30 { 31 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); 32 } 33 return STATUS_MORE_PROCESSING_REQUIRED; 34 } 35 36 NTSTATUS 37 NTAPI 38 USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp) 39 { 40 KEVENT Event; 41 NTSTATUS Status; 42 43 // 44 // initialize event 45 // 46 KeInitializeEvent(&Event, NotificationEvent, FALSE); 47 48 // 49 // copy irp stack location 50 // 51 IoCopyCurrentIrpStackLocationToNext(Irp); 52 53 // 54 // set completion routine 55 // 56 IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); 57 58 59 // 60 // call driver 61 // 62 Status = IoCallDriver(DeviceObject, Irp); 63 64 // 65 // check if pending 66 // 67 if (Status == STATUS_PENDING) 68 { 69 // 70 // wait for the request to finish 71 // 72 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 73 74 // 75 // copy status code 76 // 77 Status = Irp->IoStatus.Status; 78 } 79 80 // 81 // done 82 // 83 return Status; 84 } 85 86 NTSTATUS 87 NTAPI 88 USBSTOR_GetBusInterface( 89 IN PDEVICE_OBJECT DeviceObject, 90 OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface) 91 { 92 KEVENT Event; 93 NTSTATUS Status; 94 PIRP Irp; 95 IO_STATUS_BLOCK IoStatus; 96 PIO_STACK_LOCATION Stack; 97 98 // 99 // sanity checks 100 // 101 ASSERT(DeviceObject); 102 ASSERT(BusInterface); 103 104 105 // 106 // initialize event 107 // 108 KeInitializeEvent(&Event, NotificationEvent, FALSE); 109 110 111 // 112 // create irp 113 // 114 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, 115 DeviceObject, 116 NULL, 117 0, 118 NULL, 119 &Event, 120 &IoStatus); 121 122 // 123 // was irp built 124 // 125 if (Irp == NULL) 126 { 127 // 128 // no memory 129 // 130 return STATUS_INSUFFICIENT_RESOURCES; 131 } 132 133 // 134 // initialize request 135 // 136 Stack=IoGetNextIrpStackLocation(Irp); 137 Stack->MajorFunction = IRP_MJ_PNP; 138 Stack->MinorFunction = IRP_MN_QUERY_INTERFACE; 139 Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD); 140 Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBDI_GUID; 141 Stack->Parameters.QueryInterface.Version = 2; 142 Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface; 143 Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL; 144 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 145 146 // 147 // call driver 148 // 149 Status= IoCallDriver(DeviceObject, Irp); 150 151 // 152 // did operation complete 153 // 154 if (Status == STATUS_PENDING) 155 { 156 // 157 // wait for completion 158 // 159 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 160 161 // 162 // collect status 163 // 164 Status=IoStatus.Status; 165 } 166 167 return Status; 168 } 169 170 NTSTATUS 171 USBSTOR_SyncUrbRequest( 172 IN PDEVICE_OBJECT DeviceObject, 173 OUT PURB UrbRequest) 174 { 175 PIRP Irp; 176 PIO_STACK_LOCATION IoStack; 177 KEVENT Event; 178 NTSTATUS Status; 179 180 // 181 // allocate irp 182 // 183 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 184 if (!Irp) 185 { 186 // 187 // no memory 188 // 189 return STATUS_INSUFFICIENT_RESOURCES; 190 } 191 192 // 193 // initialize event 194 // 195 KeInitializeEvent(&Event, NotificationEvent, FALSE); 196 197 198 // 199 // get next stack location 200 // 201 IoStack = IoGetNextIrpStackLocation(Irp); 202 203 // 204 // initialize stack location 205 // 206 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 207 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; 208 IoStack->Parameters.Others.Argument1 = (PVOID)UrbRequest; 209 IoStack->Parameters.DeviceIoControl.InputBufferLength = UrbRequest->UrbHeader.Length; 210 Irp->IoStatus.Status = STATUS_SUCCESS; 211 212 // 213 // setup completion routine 214 // 215 IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); 216 217 // 218 // call driver 219 // 220 Status = IoCallDriver(DeviceObject, Irp); 221 222 // 223 // check if request is pending 224 // 225 if (Status == STATUS_PENDING) 226 { 227 // 228 // wait for completion 229 // 230 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 231 232 // 233 // update status 234 // 235 Status = Irp->IoStatus.Status; 236 } 237 238 // 239 // free irp 240 // 241 IoFreeIrp(Irp); 242 243 // 244 // done 245 // 246 return Status; 247 } 248 249 PVOID 250 AllocateItem( 251 IN POOL_TYPE PoolType, 252 IN ULONG ItemSize) 253 { 254 // 255 // allocate item 256 // 257 PVOID Item = ExAllocatePoolWithTag(PoolType, ItemSize, USB_STOR_TAG); 258 259 if (Item) 260 { 261 // 262 // zero item 263 // 264 RtlZeroMemory(Item, ItemSize); 265 } 266 267 // 268 // return element 269 // 270 return Item; 271 } 272 273 VOID 274 FreeItem( 275 IN PVOID Item) 276 { 277 // 278 // free item 279 // 280 ExFreePoolWithTag(Item, USB_STOR_TAG); 281 } 282 283 NTSTATUS 284 USBSTOR_ClassRequest( 285 IN PDEVICE_OBJECT DeviceObject, 286 IN PFDO_DEVICE_EXTENSION DeviceExtension, 287 IN UCHAR RequestType, 288 IN USHORT Index, 289 IN ULONG TransferFlags, 290 IN ULONG TransferBufferLength, 291 IN PVOID TransferBuffer) 292 293 { 294 PURB Urb; 295 NTSTATUS Status; 296 297 // 298 // first allocate urb 299 // 300 Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST)); 301 if (!Urb) 302 { 303 // 304 // no memory 305 // 306 return STATUS_INSUFFICIENT_RESOURCES; 307 } 308 309 // 310 // initialize vendor request 311 // 312 Urb->UrbControlVendorClassRequest.Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); 313 Urb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_CLASS_INTERFACE; 314 Urb->UrbControlVendorClassRequest.TransferFlags = TransferFlags; 315 Urb->UrbControlVendorClassRequest.TransferBufferLength = TransferBufferLength; 316 Urb->UrbControlVendorClassRequest.TransferBuffer = TransferBuffer; 317 Urb->UrbControlVendorClassRequest.Request = RequestType; 318 Urb->UrbControlVendorClassRequest.Index = Index; 319 320 // 321 // submit request 322 // 323 Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb); 324 325 // 326 // free urb 327 // 328 FreeItem(Urb); 329 330 // 331 // done 332 // 333 return Status; 334 } 335 336 337 NTSTATUS 338 USBSTOR_GetMaxLUN( 339 IN PDEVICE_OBJECT DeviceObject, 340 IN PFDO_DEVICE_EXTENSION DeviceExtension) 341 { 342 PUCHAR Buffer; 343 NTSTATUS Status; 344 345 // 346 // allocate 1-byte buffer 347 // 348 Buffer = (PUCHAR)AllocateItem(NonPagedPool, sizeof(UCHAR)); 349 if (!Buffer) 350 { 351 // 352 // no memory 353 // 354 FreeItem(Buffer); 355 return STATUS_INSUFFICIENT_RESOURCES; 356 } 357 358 // 359 // execute request 360 // 361 Status = USBSTOR_ClassRequest(DeviceObject, DeviceExtension, USB_BULK_GET_MAX_LUN, DeviceExtension->InterfaceInformation->InterfaceNumber, USBD_TRANSFER_DIRECTION_IN, sizeof(UCHAR), Buffer); 362 363 DPRINT("MaxLUN: %x\n", *Buffer); 364 365 if (NT_SUCCESS(Status)) 366 { 367 if (*Buffer > 0xF) 368 { 369 // 370 // invalid response documented in usb mass storage specification 371 // 372 Status = STATUS_DEVICE_DATA_ERROR; 373 } 374 else 375 { 376 // 377 // store maxlun 378 // 379 DeviceExtension->MaxLUN = *Buffer; 380 } 381 } 382 else 383 { 384 // 385 // "USB Mass Storage Class. Bulk-Only Transport. Revision 1.0" 386 // 3.2 Get Max LUN (class-specific request) : 387 // Devices that do not support multiple LUNs may STALL this command. 388 // 389 USBSTOR_ResetDevice(DeviceExtension->LowerDeviceObject, DeviceExtension); 390 391 DeviceExtension->MaxLUN = 0; 392 Status = STATUS_SUCCESS; 393 } 394 395 // 396 // free buffer 397 // 398 FreeItem(Buffer); 399 400 // 401 // done 402 // 403 return Status; 404 405 } 406 407 NTSTATUS 408 USBSTOR_ResetDevice( 409 IN PDEVICE_OBJECT DeviceObject, 410 IN PFDO_DEVICE_EXTENSION DeviceExtension) 411 { 412 NTSTATUS Status; 413 414 // 415 // execute request 416 // 417 Status = USBSTOR_ClassRequest(DeviceObject, DeviceExtension, USB_BULK_RESET_DEVICE, DeviceExtension->InterfaceInformation->InterfaceNumber, USBD_TRANSFER_DIRECTION_OUT, 0, NULL); 418 419 // 420 // done 421 // 422 return Status; 423 424 } 425 426 BOOLEAN 427 USBSTOR_IsFloppy( 428 IN PUCHAR Buffer, 429 IN ULONG BufferLength, 430 OUT PUCHAR MediumTypeCode) 431 { 432 PUFI_CAPACITY_FORMAT_HEADER FormatHeader; 433 PUFI_CAPACITY_DESCRIPTOR Descriptor; 434 ULONG Length, Index, BlockCount, BlockLength; 435 436 // 437 // get format header 438 // 439 FormatHeader = (PUFI_CAPACITY_FORMAT_HEADER)Buffer; 440 441 // 442 // sanity checks 443 // 444 ASSERT(FormatHeader->Reserved1 == 0x00); 445 ASSERT(FormatHeader->Reserved2 == 0x00); 446 ASSERT(FormatHeader->Reserved3 == 0x00); 447 448 // 449 // is there capacity data 450 // 451 if (!FormatHeader->CapacityLength) 452 { 453 // 454 // no data provided 455 // 456 DPRINT1("[USBSTOR] No capacity length\n"); 457 return FALSE; 458 } 459 460 // 461 // the format header are always 8 bytes in length 462 // 463 ASSERT((FormatHeader->CapacityLength & 0x7) == 0); 464 DPRINT1("CapacityLength %x\n", FormatHeader->CapacityLength); 465 466 // 467 // grab length and locate first descriptor 468 // 469 Length = FormatHeader->CapacityLength; 470 Descriptor = (PUFI_CAPACITY_DESCRIPTOR)(FormatHeader + 1); 471 for(Index = 0; Index < Length / sizeof(UFI_CAPACITY_DESCRIPTOR); Index++) 472 { 473 // 474 // blocks are little endian format 475 // 476 BlockCount = NTOHL(Descriptor->BlockCount); 477 478 // 479 // get block length 480 // 481 BlockLength = NTOHL((Descriptor->BlockLengthByte0 << 24 | Descriptor->BlockLengthByte1 << 16 | Descriptor->BlockLengthByte2 << 8)); 482 483 DPRINT1("BlockCount %x BlockLength %x Code %x\n", BlockCount, BlockLength, Descriptor->Code); 484 485 if (BlockLength == 512 && BlockCount == 1440) 486 { 487 // 488 // 720 KB DD 489 // 490 *MediumTypeCode = 0x1E; 491 return TRUE; 492 } 493 else if (BlockLength == 1024 && BlockCount == 1232) 494 { 495 // 496 // 1,25 MB 497 // 498 *MediumTypeCode = 0x93; 499 return TRUE; 500 } 501 else if (BlockLength == 512 && BlockCount == 2880) 502 { 503 // 504 // 1,44MB KB DD 505 // 506 *MediumTypeCode = 0x94; 507 return TRUE; 508 } 509 510 // 511 // move to next descriptor 512 // 513 Descriptor = (Descriptor + 1); 514 } 515 516 // 517 // no floppy detected 518 // 519 return FALSE; 520 } 521