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/pdo.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 LPCSTR 18 USBSTOR_GetDeviceType( 19 IN PUFI_INQUIRY_RESPONSE InquiryData, 20 IN UCHAR IsFloppy) 21 { 22 // 23 // check if device type is zero 24 // 25 if (InquiryData->DeviceType == 0) 26 { 27 if (IsFloppy) 28 { 29 // 30 // floppy device 31 // 32 return "SFloppy"; 33 } 34 35 // 36 // direct access device 37 // 38 return "Disk"; 39 } 40 41 // 42 // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type 43 // 44 switch (InquiryData->DeviceType) 45 { 46 case 1: 47 { 48 // 49 // sequential device, i.e magnetic tape 50 // 51 return "Sequential"; 52 } 53 case 4: 54 { 55 // 56 // write once device 57 // 58 return "Worm"; 59 } 60 case 5: 61 { 62 // 63 // CDROM device 64 // 65 return "CdRom"; 66 } 67 case 7: 68 { 69 // 70 // optical memory device 71 // 72 return "Optical"; 73 } 74 case 8: 75 { 76 // 77 // medium change device 78 // 79 return "Changer"; 80 } 81 default: 82 { 83 // 84 // other device 85 // 86 return "Other"; 87 } 88 } 89 } 90 91 LPCSTR 92 USBSTOR_GetGenericType( 93 IN PUFI_INQUIRY_RESPONSE InquiryData, 94 IN UCHAR IsFloppy) 95 { 96 // 97 // check if device type is zero 98 // 99 if (InquiryData->DeviceType == 0) 100 { 101 if (IsFloppy) 102 { 103 // 104 // floppy device 105 // 106 return "GenSFloppy"; 107 } 108 109 // 110 // direct access device 111 // 112 return "GenDisk"; 113 } 114 115 // 116 // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type 117 // 118 switch (InquiryData->DeviceType) 119 { 120 case 1: 121 { 122 // 123 // sequential device, i.e magnetic tape 124 // 125 return "GenSequential"; 126 } 127 case 4: 128 { 129 // 130 // write once device 131 // 132 return "GenWorm"; 133 } 134 case 5: 135 { 136 // 137 // CDROM device 138 // 139 return "GenCdRom"; 140 } 141 case 7: 142 { 143 // 144 // optical memory device 145 // 146 return "GenOptical"; 147 } 148 case 8: 149 { 150 // 151 // medium change device 152 // 153 return "GenChanger"; 154 } 155 default: 156 { 157 // 158 // other device 159 // 160 return "UsbstorOther"; 161 } 162 } 163 } 164 165 166 ULONG 167 CopyField( 168 IN PUCHAR Name, 169 IN PCHAR Buffer, 170 IN ULONG MaxLength) 171 { 172 ULONG Index; 173 174 for(Index = 0; Index < MaxLength; Index++) 175 { 176 if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',') 177 { 178 // 179 // convert to underscore 180 // 181 Buffer[Index] = '_'; 182 } 183 else 184 { 185 // 186 // just copy character 187 // 188 Buffer[Index] = Name[Index]; 189 } 190 } 191 192 return MaxLength; 193 } 194 195 NTSTATUS 196 USBSTOR_PdoHandleQueryDeviceText( 197 IN PDEVICE_OBJECT DeviceObject, 198 IN PIRP Irp) 199 { 200 //PPDO_DEVICE_EXTENSION DeviceExtension; 201 PIO_STACK_LOCATION IoStack; 202 LPWSTR Buffer; 203 static WCHAR DeviceText[] = L"USB Mass Storage Device"; 204 205 // 206 // get current stack location 207 // 208 IoStack = IoGetCurrentIrpStackLocation(Irp); 209 210 if (IoStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) 211 { 212 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextDescription\n"); 213 214 // 215 // allocate item 216 // 217 Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText)); 218 if (!Buffer) 219 { 220 // 221 // no memory 222 // 223 Irp->IoStatus.Information = 0; 224 return STATUS_INSUFFICIENT_RESOURCES; 225 } 226 227 // 228 // copy buffer 229 // 230 wcscpy(Buffer, DeviceText); 231 232 // 233 // save result 234 // 235 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 236 return STATUS_SUCCESS; 237 } 238 else 239 { 240 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextLocationInformation\n"); 241 242 // 243 // allocate item 244 // 245 Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText)); 246 if (!Buffer) 247 { 248 // 249 // no memory 250 // 251 Irp->IoStatus.Information = 0; 252 return STATUS_INSUFFICIENT_RESOURCES; 253 } 254 255 // 256 // copy buffer 257 // 258 wcscpy(Buffer, DeviceText); 259 260 // 261 // save result 262 // 263 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 264 return STATUS_SUCCESS; 265 } 266 267 } 268 269 270 NTSTATUS 271 USBSTOR_PdoHandleQueryDeviceId( 272 IN PDEVICE_OBJECT DeviceObject, 273 IN PIRP Irp) 274 { 275 PPDO_DEVICE_EXTENSION DeviceExtension; 276 NTSTATUS Status; 277 CHAR Buffer[100]; 278 LPCSTR DeviceType; 279 ULONG Offset = 0; 280 PUFI_INQUIRY_RESPONSE InquiryData; 281 ANSI_STRING AnsiString; 282 UNICODE_STRING DeviceId; 283 284 // 285 // get device extension 286 // 287 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 288 289 // 290 // sanity check 291 // 292 ASSERT(DeviceExtension->InquiryData); 293 294 // 295 // get inquiry data 296 // 297 InquiryData = (PUFI_INQUIRY_RESPONSE)DeviceExtension->InquiryData; 298 299 // 300 // get device type 301 // 302 DeviceType = USBSTOR_GetDeviceType(InquiryData, DeviceExtension->IsFloppy); 303 304 // 305 // zero buffer 306 // 307 RtlZeroMemory(Buffer, sizeof(Buffer)); 308 309 // 310 // lets create device string 311 // 312 Offset = sprintf(&Buffer[Offset], "USBSTOR\\"); 313 Offset += sprintf(&Buffer[Offset], DeviceType); 314 Offset += sprintf(&Buffer[Offset], "&Ven_"); 315 Offset += CopyField(InquiryData->Vendor, &Buffer[Offset], 8); 316 Offset += sprintf(&Buffer[Offset], "&Prod_"); 317 Offset += CopyField(InquiryData->Product, &Buffer[Offset], 16); 318 Offset += sprintf(&Buffer[Offset], "&Rev_"); 319 Offset += CopyField(InquiryData->Revision, &Buffer[Offset], 4); 320 321 // 322 // now initialize ansi string 323 // 324 RtlInitAnsiString(&AnsiString, (PCSZ)Buffer); 325 326 // 327 // allocate DeviceId string 328 // 329 DeviceId.Length = 0; 330 DeviceId.MaximumLength = (strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR); 331 DeviceId.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceId.MaximumLength); 332 if (!DeviceId.Buffer) 333 { 334 // 335 // no memory 336 // 337 Irp->IoStatus.Information = 0; 338 return STATUS_INSUFFICIENT_RESOURCES; 339 } 340 341 342 // 343 // convert to unicode 344 // 345 Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, FALSE); 346 347 if (NT_SUCCESS(Status)) 348 { 349 // 350 // store result 351 // 352 Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer; 353 } 354 355 DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status); 356 357 // 358 // done 359 // 360 return Status; 361 } 362 363 VOID 364 USBSTOR_ConvertToUnicodeString( 365 IN CHAR * Buffer, 366 IN ULONG ResultBufferLength, 367 IN ULONG ResultBufferOffset, 368 OUT LPWSTR ResultBuffer, 369 OUT PULONG NewResultBufferOffset) 370 { 371 UNICODE_STRING DeviceString; 372 ANSI_STRING AnsiString; 373 NTSTATUS Status; 374 375 ASSERT(ResultBufferLength); 376 ASSERT(ResultBufferLength > ResultBufferOffset); 377 378 DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer)); 379 380 // 381 // construct destination string 382 // 383 DeviceString.Buffer = &ResultBuffer[ResultBufferOffset]; 384 DeviceString.Length = 0; 385 DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR); 386 387 // 388 // initialize source string 389 // 390 RtlInitAnsiString(&AnsiString, Buffer); 391 392 // 393 // convert to unicode 394 // 395 Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE); 396 ASSERT(Status == STATUS_SUCCESS); 397 398 // 399 // subtract consumed bytes 400 // 401 ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR); 402 ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR); 403 404 // 405 // store new offset 406 // 407 *NewResultBufferOffset = ResultBufferOffset; 408 } 409 410 411 412 NTSTATUS 413 USBSTOR_PdoHandleQueryHardwareId( 414 IN PDEVICE_OBJECT DeviceObject, 415 IN OUT PIRP Irp) 416 { 417 PPDO_DEVICE_EXTENSION PDODeviceExtension; 418 PFDO_DEVICE_EXTENSION FDODeviceExtension; 419 LPCSTR GenericType, DeviceType; 420 LPWSTR Buffer; 421 CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50]; 422 ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length,Id6Length; 423 ULONG Offset, TotalLength, Length; 424 PUFI_INQUIRY_RESPONSE InquiryData; 425 426 // 427 // get PDO device extension 428 // 429 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 430 431 // 432 // get FDO device extension 433 // 434 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; 435 436 // 437 // sanity check 438 // 439 ASSERT(FDODeviceExtension->DeviceDescriptor); 440 441 // 442 // get inquiry data 443 // 444 InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData; 445 446 447 // 448 // get device type and generic type 449 // 450 DeviceType = USBSTOR_GetDeviceType(InquiryData, PDODeviceExtension->IsFloppy); 451 GenericType = USBSTOR_GetGenericType(InquiryData, PDODeviceExtension->IsFloppy); 452 453 ASSERT(GenericType); 454 455 // 456 // generate id 1 457 // USBSTOR\SCSIType_Vendor(8)_Product(16)_Revision(4) 458 // 459 RtlZeroMemory(Id1, sizeof(Id1)); 460 Offset = 0; 461 Offset = sprintf(&Id1[Offset], "USBSTOR\\"); 462 Offset += sprintf(&Id1[Offset], DeviceType); 463 Offset += CopyField(InquiryData->Vendor, &Id1[Offset], 8); 464 Offset += CopyField(InquiryData->Product, &Id1[Offset], 16); 465 Offset += CopyField(InquiryData->Revision, &Id1[Offset], 4); 466 Id1Length = strlen(Id1) + 1; 467 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1); 468 469 // 470 // generate id 2 471 // USBSTOR\SCSIType_VENDOR(8)_Product(16) 472 // 473 RtlZeroMemory(Id2, sizeof(Id2)); 474 Offset = 0; 475 Offset = sprintf(&Id2[Offset], "USBSTOR\\"); 476 Offset += sprintf(&Id2[Offset], DeviceType); 477 Offset += CopyField(InquiryData->Vendor, &Id2[Offset], 8); 478 Offset += CopyField(InquiryData->Product, &Id2[Offset], 16); 479 Id2Length = strlen(Id2) + 1; 480 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2); 481 482 // 483 // generate id 3 484 // USBSTOR\SCSIType_VENDOR(8) 485 // 486 RtlZeroMemory(Id3, sizeof(Id3)); 487 Offset = 0; 488 Offset = sprintf(&Id3[Offset], "USBSTOR\\"); 489 Offset += sprintf(&Id3[Offset], DeviceType); 490 Offset += CopyField(InquiryData->Vendor, &Id3[Offset], 8); 491 Id3Length = strlen(Id3) + 1; 492 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3); 493 494 // 495 // generate id 4 496 // USBSTOR\SCSIType_VENDOR(8)_Product(16)_Revision(1) 497 // 498 RtlZeroMemory(Id4, sizeof(Id4)); 499 Offset = 0; 500 Offset = sprintf(&Id4[Offset], "USBSTOR\\"); 501 Offset += sprintf(&Id4[Offset], DeviceType); 502 Offset += CopyField(InquiryData->Vendor, &Id4[Offset], 8); 503 Offset += CopyField(InquiryData->Product, &Id4[Offset], 16); 504 Offset += CopyField(InquiryData->Revision, &Id4[Offset], 1); 505 Id4Length = strlen(Id4) + 1; 506 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4); 507 508 // 509 // generate id 5 510 // USBSTOR\SCSIType 511 // 512 RtlZeroMemory(Id5, sizeof(Id5)); 513 Offset = 0; 514 Offset = sprintf(&Id5[Offset], "USBSTOR\\"); 515 Offset += sprintf(&Id5[Offset], GenericType); 516 Id5Length = strlen(Id5) + 1; 517 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5); 518 519 // 520 // generate id 6 521 // SCSIType 522 // 523 RtlZeroMemory(Id6, sizeof(Id6)); 524 Offset = 0; 525 Offset = sprintf(&Id6[Offset], GenericType); 526 Id6Length = strlen(Id6) + 1; 527 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6); 528 529 // 530 // compute total length 531 // 532 TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1; 533 534 // 535 // allocate buffer 536 // 537 Buffer = (LPWSTR)AllocateItem(PagedPool, TotalLength * sizeof(WCHAR)); 538 if (!Buffer) 539 { 540 // 541 // no memory 542 // 543 Irp->IoStatus.Information = 0; 544 return STATUS_INSUFFICIENT_RESOURCES; 545 } 546 547 // 548 // reset offset 549 // 550 Offset = 0; 551 Length = TotalLength; 552 553 USBSTOR_ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset); 554 USBSTOR_ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset); 555 USBSTOR_ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset); 556 USBSTOR_ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset); 557 USBSTOR_ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset); 558 USBSTOR_ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset); 559 560 // 561 // sanity check 562 // 563 ASSERT(Offset + 1 == Length); 564 565 // 566 // store result 567 // 568 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 569 570 // 571 // done 572 // 573 return STATUS_SUCCESS; 574 } 575 576 NTSTATUS 577 USBSTOR_PdoHandleQueryCompatibleId( 578 IN PDEVICE_OBJECT DeviceObject, 579 IN OUT PIRP Irp) 580 { 581 PPDO_DEVICE_EXTENSION PDODeviceExtension; 582 PFDO_DEVICE_EXTENSION FDODeviceExtension; 583 CHAR Buffer[100]; 584 ULONG Length, Offset; 585 LPWSTR InstanceId; 586 LPCSTR DeviceType; 587 588 // 589 // get PDO device extension 590 // 591 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 592 593 // 594 // get FDO device extension 595 // 596 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; 597 598 // 599 // sanity check 600 // 601 ASSERT(FDODeviceExtension->DeviceDescriptor); 602 603 // 604 // get target device type 605 // 606 DeviceType = USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData, PDODeviceExtension->IsFloppy); 607 608 // 609 // zero memory 610 // 611 RtlZeroMemory(Buffer, sizeof(Buffer)); 612 613 // 614 // format instance id 615 // 616 Length = sprintf(Buffer, "USBSTOR\\%s", DeviceType) + 1; 617 Length += sprintf(&Buffer[Length], "USBSTOR\\%s", "RAW") + 2; 618 619 // 620 // allocate instance id 621 // 622 InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR)); 623 if (!InstanceId) 624 { 625 // 626 // no memory 627 // 628 Irp->IoStatus.Information = 0; 629 return STATUS_INSUFFICIENT_RESOURCES; 630 } 631 632 USBSTOR_ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset); 633 USBSTOR_ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset); 634 635 DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId); 636 637 // 638 // store result 639 // 640 Irp->IoStatus.Information = (ULONG_PTR)InstanceId; 641 642 // 643 // completed successfully 644 // 645 return STATUS_SUCCESS; 646 } 647 648 NTSTATUS 649 USBSTOR_PdoHandleQueryInstanceId( 650 IN PDEVICE_OBJECT DeviceObject, 651 IN OUT PIRP Irp) 652 { 653 PPDO_DEVICE_EXTENSION PDODeviceExtension; 654 PFDO_DEVICE_EXTENSION FDODeviceExtension; 655 WCHAR Buffer[100]; 656 ULONG Length; 657 LPWSTR InstanceId; 658 659 // 660 // get PDO device extension 661 // 662 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 663 664 // 665 // get FDO device extension 666 // 667 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; 668 669 // 670 // format instance id 671 // 672 if (FDODeviceExtension->SerialNumber) 673 { 674 // 675 // using serial number from device 676 // 677 swprintf(Buffer, L"%s&%c", FDODeviceExtension->SerialNumber->bString, PDODeviceExtension->LUN); 678 } 679 else 680 { 681 // 682 // use instance count and LUN 683 // 684 swprintf(Buffer, L"%04lu&%c", FDODeviceExtension->InstanceCount, PDODeviceExtension->LUN); 685 } 686 687 // 688 // calculate length 689 // 690 Length = wcslen(Buffer) + 1; 691 692 // 693 // allocate instance id 694 // 695 InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR)); 696 if (!InstanceId) 697 { 698 // 699 // no memory 700 // 701 Irp->IoStatus.Information = 0; 702 return STATUS_INSUFFICIENT_RESOURCES; 703 } 704 705 // 706 // copy instance id 707 // 708 wcscpy(InstanceId, Buffer); 709 710 DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId); 711 712 // 713 // store result 714 // 715 Irp->IoStatus.Information = (ULONG_PTR)InstanceId; 716 717 // 718 // completed successfully 719 // 720 return STATUS_SUCCESS; 721 } 722 723 NTSTATUS 724 USBSTOR_PdoHandleDeviceRelations( 725 IN PDEVICE_OBJECT DeviceObject, 726 IN OUT PIRP Irp) 727 { 728 PDEVICE_RELATIONS DeviceRelations; 729 PIO_STACK_LOCATION IoStack; 730 731 DPRINT("USBSTOR_PdoHandleDeviceRelations\n"); 732 733 // 734 // get current irp stack location 735 // 736 IoStack = IoGetCurrentIrpStackLocation(Irp); 737 738 // 739 // check if relation type is BusRelations 740 // 741 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 742 { 743 // 744 // PDO handles only target device relation 745 // 746 return Irp->IoStatus.Status; 747 } 748 749 // 750 // allocate device relations 751 // 752 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); 753 if (!DeviceRelations) 754 { 755 // 756 // no memory 757 // 758 return STATUS_INSUFFICIENT_RESOURCES; 759 } 760 761 // 762 // initialize device relations 763 // 764 DeviceRelations->Count = 1; 765 DeviceRelations->Objects[0] = DeviceObject; 766 ObReferenceObject(DeviceObject); 767 768 // 769 // store result 770 // 771 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 772 773 // 774 // completed successfully 775 // 776 return STATUS_SUCCESS; 777 } 778 779 780 NTSTATUS 781 USBSTOR_PdoHandlePnp( 782 IN PDEVICE_OBJECT DeviceObject, 783 IN OUT PIRP Irp) 784 { 785 PIO_STACK_LOCATION IoStack; 786 PPDO_DEVICE_EXTENSION DeviceExtension; 787 NTSTATUS Status; 788 PDEVICE_CAPABILITIES Caps; 789 ULONG bDelete; 790 791 // 792 // get current stack location 793 // 794 IoStack = IoGetCurrentIrpStackLocation(Irp); 795 796 // 797 // get device extension 798 // 799 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 800 801 // 802 // sanity check 803 // 804 ASSERT(DeviceExtension->Common.IsFDO == FALSE); 805 806 switch(IoStack->MinorFunction) 807 { 808 case IRP_MN_QUERY_DEVICE_RELATIONS: 809 { 810 Status = USBSTOR_PdoHandleDeviceRelations(DeviceObject, Irp); 811 break; 812 } 813 case IRP_MN_QUERY_DEVICE_TEXT: 814 { 815 Status = USBSTOR_PdoHandleQueryDeviceText(DeviceObject, Irp); 816 break; 817 } 818 case IRP_MN_QUERY_ID: 819 { 820 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID) 821 { 822 // 823 // handle query device id 824 // 825 Status = USBSTOR_PdoHandleQueryDeviceId(DeviceObject, Irp); 826 break; 827 } 828 else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) 829 { 830 // 831 // handle instance id 832 // 833 Status = USBSTOR_PdoHandleQueryHardwareId(DeviceObject, Irp); 834 break; 835 } 836 else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID) 837 { 838 // 839 // handle instance id 840 // 841 Status = USBSTOR_PdoHandleQueryInstanceId(DeviceObject, Irp); 842 break; 843 } 844 else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) 845 { 846 // 847 // handle instance id 848 // 849 Status = USBSTOR_PdoHandleQueryCompatibleId(DeviceObject, Irp); 850 break; 851 } 852 853 DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType); 854 Status = STATUS_NOT_SUPPORTED; 855 Irp->IoStatus.Information = 0; 856 break; 857 } 858 case IRP_MN_REMOVE_DEVICE: 859 { 860 DPRINT("IRP_MN_REMOVE_DEVICE\n"); 861 862 if(*DeviceExtension->PDODeviceObject != NULL) 863 { 864 // 865 // clear entry in FDO pdo list 866 // 867 *DeviceExtension->PDODeviceObject = NULL; 868 bDelete = TRUE; 869 } 870 else 871 { 872 // 873 // device object already marked for deletion 874 // 875 bDelete = FALSE; 876 } 877 878 /* Complete the IRP */ 879 Irp->IoStatus.Status = STATUS_SUCCESS; 880 IoCompleteRequest(Irp, IO_NO_INCREMENT); 881 882 if (bDelete) 883 { 884 /* Delete the device object */ 885 IoDeleteDevice(DeviceObject); 886 } 887 return STATUS_SUCCESS; 888 } 889 case IRP_MN_QUERY_CAPABILITIES: 890 { 891 // 892 // just forward irp to lower device 893 // 894 Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp); 895 ASSERT(Status == STATUS_SUCCESS); 896 897 if (NT_SUCCESS(Status)) 898 { 899 // 900 // check if no unique id 901 // 902 Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities; 903 Caps->UniqueID = FALSE; // no unique id is supported 904 Caps->Removable = TRUE; //FIXME 905 } 906 break; 907 } 908 case IRP_MN_QUERY_REMOVE_DEVICE: 909 case IRP_MN_QUERY_STOP_DEVICE: 910 { 911 #if 0 912 // 913 // if we're not claimed it's ok 914 // 915 if (DeviceExtension->Claimed) 916 #else 917 if (TRUE) 918 #endif 919 { 920 Status = STATUS_UNSUCCESSFUL; 921 DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack->MinorFunction); 922 } 923 else 924 Status = STATUS_SUCCESS; 925 break; 926 } 927 case IRP_MN_START_DEVICE: 928 { 929 // 930 // no-op for PDO 931 // 932 Status = STATUS_SUCCESS; 933 break; 934 } 935 case IRP_MN_SURPRISE_REMOVAL: 936 { 937 Status = STATUS_SUCCESS; 938 break; 939 } 940 default: 941 { 942 // 943 // do nothing 944 // 945 Status = Irp->IoStatus.Status; 946 } 947 } 948 949 // 950 // complete request 951 // 952 if (Status != STATUS_PENDING) 953 { 954 // 955 // store result 956 // 957 Irp->IoStatus.Status = Status; 958 959 // 960 // complete request 961 // 962 IoCompleteRequest(Irp, IO_NO_INCREMENT); 963 } 964 965 // 966 // done processing 967 // 968 return Status; 969 } 970 971 NTSTATUS 972 NTAPI 973 USBSTOR_CompletionRoutine( 974 IN PDEVICE_OBJECT DeviceObject, 975 IN PIRP Irp, 976 IN PVOID Ctx) 977 { 978 PKEVENT Event = (PKEVENT)Ctx; 979 980 // 981 // signal event 982 // 983 KeSetEvent(Event, 0, FALSE); 984 return STATUS_MORE_PROCESSING_REQUIRED; 985 } 986 987 NTSTATUS 988 USBSTOR_AllocateIrp( 989 IN PDEVICE_OBJECT DeviceObject, 990 IN ULONG DataTransferLength, 991 IN UCHAR OpCode, 992 IN PKEVENT Event, 993 OUT PSCSI_REQUEST_BLOCK *OutRequest, 994 OUT PIRP *OutIrp) 995 { 996 PIRP Irp; 997 PIO_STACK_LOCATION IoStack; 998 PSCSI_REQUEST_BLOCK Request; 999 PCDB pCDB; 1000 1001 // 1002 // allocate irp 1003 // 1004 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 1005 if (!Irp) 1006 { 1007 // 1008 // no memory 1009 // 1010 return STATUS_INSUFFICIENT_RESOURCES; 1011 } 1012 1013 // 1014 // get next stack location 1015 // 1016 IoStack = IoGetNextIrpStackLocation(Irp); 1017 1018 // 1019 // create scsi block 1020 // 1021 Request = ExAllocatePoolWithTag(NonPagedPool, 1022 sizeof(SCSI_REQUEST_BLOCK), 1023 USB_STOR_TAG); 1024 if (!Request) 1025 { 1026 // 1027 // no memory 1028 // 1029 IoFreeIrp(Irp); 1030 return STATUS_INSUFFICIENT_RESOURCES; 1031 } 1032 1033 // 1034 // init request 1035 // 1036 RtlZeroMemory(Request, sizeof(SCSI_REQUEST_BLOCK)); 1037 1038 // 1039 // allocate data transfer block 1040 // 1041 Request->DataBuffer = ExAllocatePoolWithTag(NonPagedPool, 1042 DataTransferLength, 1043 USB_STOR_TAG); 1044 if (!Request->DataBuffer) 1045 { 1046 // 1047 // no memory 1048 // 1049 IoFreeIrp(Irp); 1050 ExFreePoolWithTag(Request, USB_STOR_TAG); 1051 return STATUS_INSUFFICIENT_RESOURCES; 1052 } 1053 1054 // 1055 // allocate MDL 1056 // 1057 Irp->MdlAddress = IoAllocateMdl(Request->DataBuffer, DataTransferLength, FALSE, FALSE, NULL); 1058 if (!Irp->MdlAddress) 1059 { 1060 // 1061 // no memory 1062 // 1063 IoFreeIrp(Irp); 1064 ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG); 1065 ExFreePoolWithTag(Request, USB_STOR_TAG); 1066 return STATUS_INSUFFICIENT_RESOURCES; 1067 } 1068 1069 // 1070 // non paged pool 1071 // 1072 MmBuildMdlForNonPagedPool(Irp->MdlAddress); 1073 1074 // 1075 // init scsi block 1076 // 1077 Request->DataTransferLength = DataTransferLength; 1078 Request->Function = SRB_FUNCTION_EXECUTE_SCSI; 1079 Request->SrbFlags = SRB_FLAGS_DATA_IN; 1080 1081 RtlZeroMemory(Request->DataBuffer, DataTransferLength); 1082 1083 1084 // 1085 // get SCSI command data block 1086 // 1087 pCDB = (PCDB)Request->Cdb; 1088 1089 // 1090 // set op code 1091 // 1092 pCDB->AsByte[0] = OpCode; 1093 1094 // 1095 // store result 1096 // 1097 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 1098 IoStack->Parameters.Others.Argument1 = Request; 1099 IoStack->DeviceObject = DeviceObject; 1100 1101 // 1102 // init event 1103 // 1104 KeInitializeEvent(Event, NotificationEvent, FALSE); 1105 1106 // 1107 // lets setup a completion routine 1108 // 1109 IoSetCompletionRoutine(Irp, USBSTOR_CompletionRoutine, (PVOID)Event, TRUE, TRUE, TRUE); 1110 1111 // 1112 // output result 1113 // 1114 *OutIrp = Irp; 1115 *OutRequest = Request; 1116 return STATUS_SUCCESS; 1117 } 1118 1119 NTSTATUS 1120 USBSTOR_SendIrp( 1121 IN PDEVICE_OBJECT PDODeviceObject, 1122 IN ULONG DataTransferLength, 1123 IN UCHAR OpCode, 1124 OUT PVOID *OutData) 1125 { 1126 NTSTATUS Status; 1127 PIRP Irp; 1128 KEVENT Event; 1129 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1130 PSCSI_REQUEST_BLOCK Request; 1131 1132 // 1133 // let's allocate an irp 1134 // 1135 Status = USBSTOR_AllocateIrp(PDODeviceObject, DataTransferLength, OpCode, &Event, &Request, &Irp); 1136 if (!NT_SUCCESS(Status)) 1137 { 1138 // 1139 // failed 1140 // 1141 DPRINT1("[USBSTOR] Failed to build irp\n"); 1142 return Status; 1143 } 1144 1145 // 1146 // get device extension 1147 // 1148 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension; 1149 1150 // 1151 // send irp 1152 // 1153 ASSERT(Irp); 1154 ASSERT(PDODeviceExtension->LowerDeviceObject); 1155 Status = IoCallDriver(PDODeviceExtension->Self, Irp); 1156 1157 if (Status == STATUS_PENDING) 1158 { 1159 // 1160 // wait for completion 1161 // 1162 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1163 Status = Irp->IoStatus.Status; 1164 } 1165 1166 if (NT_SUCCESS(Status)) 1167 { 1168 // 1169 // store result 1170 // 1171 *OutData = Request->DataBuffer; 1172 } 1173 else 1174 { 1175 // 1176 // free the data 1177 // 1178 ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG); 1179 *OutData = NULL; 1180 } 1181 1182 // 1183 // free resources 1184 // 1185 ExFreePoolWithTag(Request, USB_STOR_TAG); 1186 IoFreeMdl(Irp->MdlAddress); 1187 IoFreeIrp(Irp); 1188 return Status; 1189 } 1190 1191 NTSTATUS 1192 USBSTOR_SendInquiryIrp( 1193 IN PDEVICE_OBJECT PDODeviceObject) 1194 { 1195 NTSTATUS Status; 1196 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1197 PUFI_INQUIRY_RESPONSE Response; 1198 1199 // 1200 // get device extension 1201 // 1202 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension; 1203 1204 // 1205 // send request 1206 // 1207 Status = USBSTOR_SendIrp(PDODeviceObject, sizeof(UFI_INQUIRY_RESPONSE), SCSIOP_INQUIRY, (PVOID*)&Response); 1208 if (!NT_SUCCESS(Status)) 1209 { 1210 // 1211 // command failed 1212 // 1213 DPRINT1("USBSTOR_SendInquiryIrp Failed with %x\n", Status); 1214 return Status; 1215 } 1216 1217 DPRINT1("Response %p\n", Response); 1218 DPRINT1("DeviceType %x\n", Response->DeviceType); 1219 DPRINT1("RMB %x\n", Response->RMB); 1220 DPRINT1("Version %x\n", Response->Version); 1221 DPRINT1("Format %x\n", Response->Format); 1222 DPRINT1("Length %x\n", Response->Length); 1223 DPRINT1("Reserved %p\n", Response->Reserved); 1224 DPRINT1("Vendor %c%c%c%c%c%c%c%c\n", Response->Vendor[0], Response->Vendor[1], Response->Vendor[2], Response->Vendor[3], Response->Vendor[4], Response->Vendor[5], Response->Vendor[6], Response->Vendor[7]); 1225 DPRINT1("Product %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", Response->Product[0], Response->Product[1], Response->Product[2], Response->Product[3], 1226 Response->Product[4], Response->Product[5], Response->Product[6], Response->Product[7], 1227 Response->Product[8], Response->Product[9], Response->Product[10], Response->Product[11], 1228 Response->Product[12], Response->Product[13], Response->Product[14], Response->Product[15]); 1229 1230 DPRINT1("Revision %c%c%c%c\n", Response->Revision[0], Response->Revision[1], Response->Revision[2], Response->Revision[3]); 1231 1232 // 1233 // store result 1234 // 1235 PDODeviceExtension->InquiryData = (PVOID)Response; 1236 return Status; 1237 } 1238 1239 NTSTATUS 1240 USBSTOR_SendFormatCapacityIrp( 1241 IN PDEVICE_OBJECT PDODeviceObject) 1242 { 1243 NTSTATUS Status; 1244 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1245 PUCHAR Response; 1246 1247 // 1248 // get device extension 1249 // 1250 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension; 1251 1252 // 1253 // send request 1254 // 1255 Status = USBSTOR_SendIrp(PDODeviceObject, 0xFC, SCSIOP_READ_FORMATTED_CAPACITY, (PVOID*)&Response); 1256 if (!NT_SUCCESS(Status)) 1257 { 1258 // 1259 // command failed 1260 // 1261 return Status; 1262 } 1263 1264 // 1265 // check if its a floppy 1266 // 1267 PDODeviceExtension->IsFloppy = USBSTOR_IsFloppy(Response, 0xFC /*FIXME*/, &PDODeviceExtension->MediumTypeCode); 1268 1269 // 1270 // free response 1271 // 1272 ExFreePoolWithTag(Response, USB_STOR_TAG); 1273 return Status; 1274 } 1275 1276 1277 1278 NTSTATUS 1279 USBSTOR_CreatePDO( 1280 IN PDEVICE_OBJECT DeviceObject, 1281 IN UCHAR LUN) 1282 { 1283 PDEVICE_OBJECT PDO; 1284 NTSTATUS Status; 1285 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1286 PUFI_INQUIRY_RESPONSE Response; 1287 PFDO_DEVICE_EXTENSION FDODeviceExtension; 1288 1289 // 1290 // get device extension 1291 // 1292 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 1293 1294 1295 // 1296 // create child device object 1297 // 1298 Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_MASS_STORAGE, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &PDO); 1299 if (!NT_SUCCESS(Status)) 1300 { 1301 // 1302 // failed to create device 1303 // 1304 return Status; 1305 } 1306 1307 // 1308 // patch the stack size 1309 // 1310 PDO->StackSize = DeviceObject->StackSize; 1311 1312 // 1313 // get device extension 1314 // 1315 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDO->DeviceExtension; 1316 1317 // 1318 // initialize device extension 1319 // 1320 RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION)); 1321 PDODeviceExtension->Common.IsFDO = FALSE; 1322 PDODeviceExtension->LowerDeviceObject = DeviceObject; 1323 PDODeviceExtension->PDODeviceObject = &FDODeviceExtension->ChildPDO[LUN]; 1324 PDODeviceExtension->Self = PDO; 1325 PDODeviceExtension->LUN = LUN; 1326 1327 // 1328 // set device flags 1329 // 1330 PDO->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER; 1331 1332 // 1333 // device is initialized 1334 // 1335 PDO->Flags &= ~DO_DEVICE_INITIALIZING; 1336 1337 // 1338 // output device object 1339 // 1340 FDODeviceExtension->ChildPDO[LUN] = PDO; 1341 1342 // 1343 // send inquiry command by irp 1344 // 1345 Status = USBSTOR_SendInquiryIrp(PDO); 1346 ASSERT(Status == STATUS_SUCCESS); 1347 1348 // 1349 // check response data 1350 // 1351 Response = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData; 1352 ASSERT(Response); 1353 1354 if (Response->DeviceType == 0) 1355 { 1356 // 1357 // check if it is a floppy 1358 // 1359 Status = USBSTOR_SendFormatCapacityIrp(PDO); 1360 1361 // 1362 // display result 1363 // 1364 DPRINT1("[USBSTOR] Status %x IsFloppy %x MediumTypeCode %x\n", Status, PDODeviceExtension->IsFloppy, PDODeviceExtension->MediumTypeCode); 1365 1366 // 1367 // failing command is non critical 1368 // 1369 Status = STATUS_SUCCESS; 1370 } 1371 1372 // 1373 // done 1374 // 1375 return Status; 1376 } 1377