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/descriptor.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 NTSTATUS 18 NTAPI 19 USBSTOR_GetDescriptor( 20 IN PDEVICE_OBJECT DeviceObject, 21 IN UCHAR DescriptorType, 22 IN ULONG DescriptorLength, 23 IN UCHAR DescriptorIndex, 24 IN LANGID LanguageId, 25 OUT PVOID *OutDescriptor) 26 { 27 PURB Urb; 28 NTSTATUS Status; 29 PVOID Descriptor; 30 31 // 32 // sanity checks 33 // 34 ASSERT(DeviceObject); 35 ASSERT(OutDescriptor); 36 ASSERT(DescriptorLength); 37 38 // 39 // first allocate descriptor buffer 40 // 41 Descriptor = AllocateItem(NonPagedPool, DescriptorLength); 42 if (!Descriptor) 43 { 44 // 45 // no memory 46 // 47 return STATUS_INSUFFICIENT_RESOURCES; 48 } 49 50 // 51 // allocate urb 52 // 53 Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB)); 54 if (!Urb) 55 { 56 // 57 // no memory 58 // 59 FreeItem(Descriptor); 60 return STATUS_INSUFFICIENT_RESOURCES; 61 } 62 63 // 64 // initialize urb 65 // 66 UsbBuildGetDescriptorRequest(Urb, 67 sizeof(Urb->UrbControlDescriptorRequest), 68 DescriptorType, 69 DescriptorIndex, 70 LanguageId, 71 Descriptor, 72 NULL, 73 DescriptorLength, 74 NULL); 75 76 // 77 // submit urb 78 // 79 Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb); 80 81 // 82 // free urb 83 // 84 FreeItem(Urb); 85 86 if (NT_SUCCESS(Status)) 87 { 88 // 89 // store result 90 // 91 *OutDescriptor = Descriptor; 92 } 93 94 // 95 // done 96 // 97 return Status; 98 } 99 100 101 NTSTATUS 102 USBSTOR_GetDescriptors( 103 IN PDEVICE_OBJECT DeviceObject) 104 { 105 NTSTATUS Status; 106 PFDO_DEVICE_EXTENSION DeviceExtension; 107 USHORT DescriptorLength; 108 109 // 110 // get device extension 111 // 112 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 113 114 // 115 // first get device descriptor 116 // 117 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor); 118 if (!NT_SUCCESS(Status)) 119 { 120 // 121 // failed to get device descriptor 122 // 123 DeviceExtension->DeviceDescriptor = NULL; 124 return Status; 125 } 126 127 // 128 // now get basic configuration descriptor 129 // 130 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor); 131 if (!NT_SUCCESS(Status)) 132 { 133 // 134 // failed to get configuration descriptor 135 // 136 FreeItem(DeviceExtension->DeviceDescriptor); 137 DeviceExtension->DeviceDescriptor = NULL; 138 return Status; 139 } 140 141 // 142 // backup length 143 // 144 DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength; 145 146 // 147 // release basic descriptor 148 // 149 FreeItem(DeviceExtension->ConfigurationDescriptor); 150 DeviceExtension->ConfigurationDescriptor = NULL; 151 152 // 153 // allocate full descriptor 154 // 155 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor); 156 if (!NT_SUCCESS(Status)) 157 { 158 // 159 // failed to get configuration descriptor 160 // 161 FreeItem(DeviceExtension->DeviceDescriptor); 162 DeviceExtension->DeviceDescriptor = NULL; 163 return Status; 164 } 165 166 // 167 // check if there is a serial number provided 168 // 169 if (DeviceExtension->DeviceDescriptor->iSerialNumber) 170 { 171 // 172 // get serial number 173 // 174 Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_STRING_DESCRIPTOR_TYPE, 100 * sizeof(WCHAR), DeviceExtension->DeviceDescriptor->iSerialNumber, 0x0409, (PVOID*)&DeviceExtension->SerialNumber); 175 if (!NT_SUCCESS(Status)) 176 { 177 // 178 // failed to get serial number descriptor, free device descriptor 179 // 180 FreeItem(DeviceExtension->DeviceDescriptor); 181 DeviceExtension->DeviceDescriptor = NULL; 182 183 // 184 // free configuration descriptor 185 // 186 FreeItem(DeviceExtension->ConfigurationDescriptor); 187 DeviceExtension->ConfigurationDescriptor = NULL; 188 189 // 190 // set serial number to zero 191 // 192 DeviceExtension->SerialNumber = NULL; 193 return Status; 194 } 195 } 196 197 return Status; 198 } 199 200 NTSTATUS 201 NTAPI 202 USBSTOR_ScanConfigurationDescriptor( 203 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, 204 OUT PUSB_INTERFACE_DESCRIPTOR * OutInterfaceDescriptor, 205 OUT PUSB_ENDPOINT_DESCRIPTOR * InEndpointDescriptor, 206 OUT PUSB_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor) 207 { 208 PUSB_CONFIGURATION_DESCRIPTOR CurrentDescriptor; 209 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; 210 211 // 212 // sanity checks 213 // 214 ASSERT(ConfigurationDescriptor); 215 ASSERT(OutInterfaceDescriptor); 216 ASSERT(InEndpointDescriptor); 217 ASSERT(OutEndpointDescriptor); 218 219 // 220 // nullify pointers 221 // 222 *OutInterfaceDescriptor = NULL; 223 *InEndpointDescriptor = NULL; 224 *OutEndpointDescriptor = NULL; 225 226 // 227 // start scanning 228 // 229 CurrentDescriptor = ConfigurationDescriptor; 230 231 do 232 { 233 // 234 // check current descriptor type 235 // 236 if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) 237 { 238 // 239 // found interface descriptor 240 // 241 if (*OutInterfaceDescriptor) 242 { 243 // 244 // we only process the first interface descriptor as ms does -> see documentation 245 // 246 break; 247 } 248 249 // 250 // store interface descriptor 251 // 252 *OutInterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)CurrentDescriptor; 253 } 254 else if (CurrentDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) 255 { 256 // 257 // convert to endpoint descriptor 258 // 259 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)CurrentDescriptor; 260 261 // 262 // sanity check 263 // 264 ASSERT(*OutInterfaceDescriptor); 265 266 // 267 // get endpoint type 268 // 269 if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK) 270 { 271 // 272 // bulk endpoint type 273 // 274 if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor->bEndpointAddress)) 275 { 276 // 277 // bulk in 278 // 279 *InEndpointDescriptor = EndpointDescriptor; 280 } 281 else 282 { 283 // 284 // bulk out 285 // 286 *OutEndpointDescriptor = EndpointDescriptor; 287 } 288 } 289 else if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT) 290 { 291 // 292 // interrupt endpoint type 293 // 294 UNIMPLEMENTED; 295 } 296 } 297 298 // 299 // move to next descriptor 300 // 301 CurrentDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)CurrentDescriptor + CurrentDescriptor->bLength); 302 303 // 304 // was it the last descriptor 305 // 306 if ((ULONG_PTR)CurrentDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength)) 307 { 308 // 309 // reached last descriptor 310 // 311 break; 312 } 313 314 }while(TRUE); 315 316 // 317 // check if everything has been found 318 // 319 if (*OutInterfaceDescriptor == NULL || *InEndpointDescriptor == NULL || *OutEndpointDescriptor == NULL) 320 { 321 // 322 // failed to find interface / endpoint descriptor 323 // 324 DPRINT1("USBSTOR_ScanConfigurationDescriptor: Failed to find InterfaceDescriptor %p InEndpointDescriptor %p OutEndpointDescriptor %p\n", *OutInterfaceDescriptor, *InEndpointDescriptor, *OutEndpointDescriptor); 325 return STATUS_UNSUCCESSFUL; 326 } 327 328 // 329 // completed successfully 330 // 331 return STATUS_SUCCESS; 332 } 333 334 VOID 335 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) 336 { 337 DPRINT1("Dumping ConfigurationDescriptor %p\n", ConfigurationDescriptor); 338 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength); 339 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType); 340 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength); 341 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces); 342 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue); 343 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration); 344 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes); 345 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower); 346 } 347 348 NTSTATUS 349 USBSTOR_SelectConfigurationAndInterface( 350 IN PDEVICE_OBJECT DeviceObject, 351 IN PFDO_DEVICE_EXTENSION DeviceExtension) 352 { 353 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; 354 PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor, OutEndpointDescriptor; 355 NTSTATUS Status; 356 PURB Urb; 357 PUSBD_INTERFACE_LIST_ENTRY InterfaceList; 358 359 // 360 // now scan configuration descriptors 361 // 362 Status = USBSTOR_ScanConfigurationDescriptor(DeviceExtension->ConfigurationDescriptor, &InterfaceDescriptor, &InEndpointDescriptor, &OutEndpointDescriptor); 363 if (!NT_SUCCESS(Status)) 364 { 365 // 366 // failed to scan 367 // 368 return Status; 369 } 370 371 // 372 // now allocate one interface entry and terminating null entry 373 // 374 InterfaceList = (PUSBD_INTERFACE_LIST_ENTRY)AllocateItem(PagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * 2); 375 if (!InterfaceList) 376 { 377 // 378 // no memory 379 // 380 return STATUS_INSUFFICIENT_RESOURCES; 381 } 382 383 // 384 // initialize interface list entry 385 // 386 InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor; 387 388 // 389 // now allocate the urb 390 // 391 Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, InterfaceList); 392 if (!Urb) 393 { 394 // 395 // no memory 396 // 397 FreeItem(InterfaceList); 398 return STATUS_INSUFFICIENT_RESOURCES; 399 } 400 401 // 402 // sanity check 403 // 404 ASSERT(InterfaceList[0].Interface); 405 406 // 407 // submit urb 408 // 409 Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb); 410 if (!NT_SUCCESS(Status)) 411 { 412 // 413 // failed to set configuration 414 // 415 DPRINT1("USBSTOR_SelectConfiguration failed to set interface %x\n", Status); 416 FreeItem(InterfaceList); 417 ExFreePoolWithTag(Urb, 0); 418 return Status; 419 } 420 421 // 422 // backup interface information 423 // 424 DeviceExtension->InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)AllocateItem(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length); 425 if (!DeviceExtension->InterfaceInformation) 426 { 427 // 428 // failed to allocate interface information structure 429 // 430 FreeItem(InterfaceList); 431 ExFreePoolWithTag(Urb, 0); 432 return STATUS_INSUFFICIENT_RESOURCES; 433 } 434 435 // 436 // copy interface information 437 // 438 RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length); 439 440 // 441 // store pipe handle 442 // 443 DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle; 444 445 // 446 // now prepare interface urb 447 // 448 UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting); 449 450 // 451 // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ 452 // 453 RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceInformation, DeviceExtension->InterfaceInformation->Length); 454 455 // 456 // now select the interface 457 // 458 Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb); 459 460 // 461 // did it succeed 462 // 463 if (NT_SUCCESS(Status)) 464 { 465 // 466 // update configuration info 467 // 468 ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceInformation->Length); 469 RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length); 470 } 471 472 // 473 // free interface list & urb 474 // 475 FreeItem(InterfaceList); 476 ExFreePoolWithTag(Urb, 0); 477 478 // 479 // done 480 // 481 return Status; 482 } 483 484 NTSTATUS 485 USBSTOR_GetPipeHandles( 486 IN PFDO_DEVICE_EXTENSION DeviceExtension) 487 { 488 ULONG Index; 489 BOOLEAN BulkInFound = FALSE, BulkOutFound = FALSE; 490 491 // 492 // no enumerate all pipes and extract bulk-in / bulk-out pipe handle 493 // 494 for(Index = 0; Index < DeviceExtension->InterfaceInformation->NumberOfPipes; Index++) 495 { 496 // 497 // check pipe type 498 // 499 if (DeviceExtension->InterfaceInformation->Pipes[Index].PipeType == UsbdPipeTypeBulk) 500 { 501 // 502 // check direction 503 // 504 if (USB_ENDPOINT_DIRECTION_IN(DeviceExtension->InterfaceInformation->Pipes[Index].EndpointAddress)) 505 { 506 // 507 // bulk in pipe 508 // 509 DeviceExtension->BulkInPipeIndex = Index; 510 511 // 512 // there should not be another bulk in pipe 513 // 514 ASSERT(BulkInFound == FALSE); 515 BulkInFound = TRUE; 516 } 517 else 518 { 519 // 520 // bulk out pipe 521 // 522 DeviceExtension->BulkOutPipeIndex = Index; 523 524 // 525 // there should not be another bulk out pipe 526 // 527 ASSERT(BulkOutFound == FALSE); 528 BulkOutFound = TRUE; 529 } 530 } 531 } 532 533 // 534 // check if both bulk pipes have been found 535 // 536 if (!BulkInFound || !BulkOutFound) 537 { 538 // 539 // WTF? usb port driver does not give us bulk pipe access 540 // 541 DPRINT1("USBSTOR_GetPipeHandles> BulkInFound %c BulkOutFound %c missing!!!\n", BulkInFound, BulkOutFound); 542 return STATUS_DEVICE_CONFIGURATION_ERROR; 543 } 544 545 // 546 // device is configured 547 // 548 return STATUS_SUCCESS; 549 } 550