1 /* 2 * Copyright 2003-2014, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 * Niels S. Reedijk 8 */ 9 10 11 #include "usb_private.h" 12 13 14 Device::Device(Object* parent, int8 hubAddress, uint8 hubPort, 15 usb_device_descriptor& desc, int8 deviceAddress, usb_speed speed, 16 bool isRootHub, void* controllerCookie) 17 : 18 Object(parent), 19 fDeviceDescriptor(desc), 20 fInitOK(false), 21 fAvailable(true), 22 fIsRootHub(isRootHub), 23 fConfigurations(NULL), 24 fCurrentConfiguration(NULL), 25 fSpeed(speed), 26 fDeviceAddress(deviceAddress), 27 fHubAddress(hubAddress), 28 fHubPort(hubPort), 29 fControllerCookie(controllerCookie) 30 { 31 TRACE("creating device\n"); 32 33 fDefaultPipe = new(std::nothrow) ControlPipe(this); 34 if (fDefaultPipe == NULL) { 35 TRACE_ERROR("could not allocate default pipe\n"); 36 return; 37 } 38 39 fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default, 40 fDeviceDescriptor.max_packet_size_0, 0, fHubAddress, fHubPort); 41 42 // Get the device descriptor 43 // We already have a part of it, but we want it all 44 size_t actualLength; 45 status_t status = GetDescriptor(USB_DESCRIPTOR_DEVICE, 0, 0, 46 (void*)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength); 47 48 if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) { 49 TRACE_ERROR("error while getting the device descriptor\n"); 50 return; 51 } 52 53 TRACE("full device descriptor for device %d:\n", fDeviceAddress); 54 TRACE("\tlength:..............%d\n", fDeviceDescriptor.length); 55 TRACE("\tdescriptor_type:.....0x%04x\n", fDeviceDescriptor.descriptor_type); 56 TRACE("\tusb_version:.........0x%04x\n", fDeviceDescriptor.usb_version); 57 TRACE("\tdevice_class:........0x%02x\n", fDeviceDescriptor.device_class); 58 TRACE("\tdevice_subclass:.....0x%02x\n", fDeviceDescriptor.device_subclass); 59 TRACE("\tdevice_protocol:.....0x%02x\n", fDeviceDescriptor.device_protocol); 60 TRACE("\tmax_packet_size_0:...%d\n", fDeviceDescriptor.max_packet_size_0); 61 TRACE("\tvendor_id:...........0x%04x\n", fDeviceDescriptor.vendor_id); 62 TRACE("\tproduct_id:..........0x%04x\n", fDeviceDescriptor.product_id); 63 TRACE("\tdevice_version:......0x%04x\n", fDeviceDescriptor.device_version); 64 TRACE("\tmanufacturer:........0x%02x\n", fDeviceDescriptor.manufacturer); 65 TRACE("\tproduct:.............0x%02x\n", fDeviceDescriptor.product); 66 TRACE("\tserial_number:.......0x%02x\n", fDeviceDescriptor.serial_number); 67 TRACE("\tnum_configurations:..%d\n", fDeviceDescriptor.num_configurations); 68 69 // Get the configurations 70 fConfigurations = (usb_configuration_info*)malloc( 71 fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info)); 72 if (fConfigurations == NULL) { 73 TRACE_ERROR("out of memory during config creations!\n"); 74 return; 75 } 76 77 memset(fConfigurations, 0, fDeviceDescriptor.num_configurations 78 * sizeof(usb_configuration_info)); 79 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) { 80 usb_configuration_descriptor configDescriptor; 81 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0, 82 (void*)&configDescriptor, sizeof(usb_configuration_descriptor), 83 &actualLength); 84 85 if (status < B_OK 86 || actualLength != sizeof(usb_configuration_descriptor)) { 87 TRACE_ERROR("error fetching configuration %" B_PRId32 "\n", i); 88 return; 89 } 90 91 TRACE("configuration %" B_PRId32 "\n", i); 92 TRACE("\tlength:..............%d\n", configDescriptor.length); 93 TRACE("\tdescriptor_type:.....0x%02x\n", 94 configDescriptor.descriptor_type); 95 TRACE("\ttotal_length:........%d\n", configDescriptor.total_length); 96 TRACE("\tnumber_interfaces:...%d\n", 97 configDescriptor.number_interfaces); 98 TRACE("\tconfiguration_value:.0x%02x\n", 99 configDescriptor.configuration_value); 100 TRACE("\tconfiguration:.......0x%02x\n", 101 configDescriptor.configuration); 102 TRACE("\tattributes:..........0x%02x\n", configDescriptor.attributes); 103 TRACE("\tmax_power:...........%d\n", configDescriptor.max_power); 104 105 uint8* configData = (uint8*)malloc(configDescriptor.total_length); 106 if (configData == NULL) { 107 TRACE_ERROR("out of memory when reading config\n"); 108 return; 109 } 110 111 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0, 112 (void*)configData, configDescriptor.total_length, &actualLength); 113 114 if (status < B_OK || actualLength != configDescriptor.total_length) { 115 TRACE_ERROR("error fetching full configuration" 116 " descriptor %" B_PRId32 " got %" B_PRIuSIZE " expected %" 117 B_PRIu16 "\n", i, actualLength, configDescriptor.total_length); 118 free(configData); 119 return; 120 } 121 122 usb_configuration_descriptor* configuration 123 = (usb_configuration_descriptor*)configData; 124 fConfigurations[i].descr = configuration; 125 fConfigurations[i].interface_count = configuration->number_interfaces; 126 fConfigurations[i].interface = (usb_interface_list*)malloc( 127 configuration->number_interfaces * sizeof(usb_interface_list)); 128 if (fConfigurations[i].interface == NULL) { 129 TRACE_ERROR("out of memory when creating interfaces\n"); 130 return; 131 } 132 133 memset(fConfigurations[i].interface, 0, 134 configuration->number_interfaces * sizeof(usb_interface_list)); 135 136 usb_interface_info* currentInterface = NULL; 137 uint32 descriptorStart = sizeof(usb_configuration_descriptor); 138 while (descriptorStart < actualLength) { 139 switch (configData[descriptorStart + 1]) { 140 case USB_DESCRIPTOR_INTERFACE: 141 { 142 TRACE("got interface descriptor\n"); 143 usb_interface_descriptor* interfaceDescriptor 144 = (usb_interface_descriptor*)&configData[ 145 descriptorStart]; 146 TRACE("\tlength:.............%d\n", 147 interfaceDescriptor->length); 148 TRACE("\tdescriptor_type:....0x%02x\n", 149 interfaceDescriptor->descriptor_type); 150 TRACE("\tinterface_number:...%d\n", 151 interfaceDescriptor->interface_number); 152 TRACE("\talternate_setting:..%d\n", 153 interfaceDescriptor->alternate_setting); 154 TRACE("\tnum_endpoints:......%d\n", 155 interfaceDescriptor->num_endpoints); 156 TRACE("\tinterface_class:....0x%02x\n", 157 interfaceDescriptor->interface_class); 158 TRACE("\tinterface_subclass:.0x%02x\n", 159 interfaceDescriptor->interface_subclass); 160 TRACE("\tinterface_protocol:.0x%02x\n", 161 interfaceDescriptor->interface_protocol); 162 TRACE("\tinterface:..........%d\n", 163 interfaceDescriptor->interface); 164 165 if (interfaceDescriptor->interface_number 166 >= fConfigurations[i].interface_count) { 167 interfaceDescriptor->interface_number 168 = fConfigurations[i].interface_count - 1; 169 TRACE_ERROR("Corrected invalid interface_number!\n"); 170 } 171 172 usb_interface_list* interfaceList = &fConfigurations[i] 173 .interface[interfaceDescriptor->interface_number]; 174 175 // Allocate this alternate 176 interfaceList->alt_count++; 177 usb_interface_info* newAlternates 178 = (usb_interface_info*)realloc(interfaceList->alt, 179 interfaceList->alt_count * sizeof(usb_interface_info)); 180 if (newAlternates == NULL) { 181 TRACE_ERROR("out of memory allocating" 182 " alternate interface\n"); 183 interfaceList->alt_count--; 184 return; 185 } 186 187 interfaceList->alt = newAlternates; 188 189 // Set active interface always to the first one 190 interfaceList->active = interfaceList->alt; 191 192 // Setup this alternate 193 usb_interface_info* interfaceInfo 194 = &interfaceList->alt[interfaceList->alt_count - 1]; 195 interfaceInfo->descr = interfaceDescriptor; 196 interfaceInfo->endpoint_count = 0; 197 interfaceInfo->endpoint = NULL; 198 interfaceInfo->generic_count = 0; 199 interfaceInfo->generic = NULL; 200 201 Interface* interface = new(std::nothrow) Interface(this, 202 interfaceDescriptor->interface_number); 203 if (interface == NULL) { 204 TRACE_ERROR("failed to allocate" 205 " interface object\n"); 206 return; 207 } 208 209 interfaceInfo->handle = interface->USBID(); 210 currentInterface = interfaceInfo; 211 break; 212 } 213 214 case USB_DESCRIPTOR_ENDPOINT: 215 { 216 TRACE("got endpoint descriptor\n"); 217 usb_endpoint_descriptor* endpointDescriptor 218 = (usb_endpoint_descriptor*)&configData[descriptorStart]; 219 TRACE("\tlength:.............%d\n", 220 endpointDescriptor->length); 221 TRACE("\tdescriptor_type:....0x%02x\n", 222 endpointDescriptor->descriptor_type); 223 TRACE("\tendpoint_address:...0x%02x\n", 224 endpointDescriptor->endpoint_address); 225 TRACE("\tattributes:.........0x%02x\n", 226 endpointDescriptor->attributes); 227 TRACE("\tmax_packet_size:....%d\n", 228 endpointDescriptor->max_packet_size); 229 TRACE("\tinterval:...........%d\n", 230 endpointDescriptor->interval); 231 232 if (currentInterface == NULL) 233 break; 234 235 // Allocate this endpoint 236 currentInterface->endpoint_count++; 237 usb_endpoint_info* newEndpoints = (usb_endpoint_info*) 238 realloc(currentInterface->endpoint, 239 currentInterface->endpoint_count 240 * sizeof(usb_endpoint_info)); 241 if (newEndpoints == NULL) { 242 TRACE_ERROR("out of memory allocating new endpoint\n"); 243 currentInterface->endpoint_count--; 244 return; 245 } 246 247 currentInterface->endpoint = newEndpoints; 248 249 // Setup this endpoint 250 usb_endpoint_info* endpointInfo = ¤tInterface 251 ->endpoint[currentInterface->endpoint_count - 1]; 252 endpointInfo->descr = endpointDescriptor; 253 endpointInfo->handle = 0; 254 break; 255 } 256 257 default: 258 TRACE("got generic descriptor\n"); 259 usb_generic_descriptor* genericDescriptor 260 = (usb_generic_descriptor*)&configData[descriptorStart]; 261 TRACE("\tlength:.............%d\n", 262 genericDescriptor->length); 263 TRACE("\tdescriptor_type:....0x%02x\n", 264 genericDescriptor->descriptor_type); 265 266 if (currentInterface == NULL) 267 break; 268 269 // Allocate this descriptor 270 currentInterface->generic_count++; 271 usb_descriptor** newGenerics = (usb_descriptor**)realloc( 272 currentInterface->generic, 273 currentInterface->generic_count 274 * sizeof(usb_descriptor*)); 275 if (newGenerics == NULL) { 276 TRACE_ERROR("out of memory allocating" 277 " generic descriptor\n"); 278 currentInterface->generic_count--; 279 return; 280 } 281 282 currentInterface->generic = newGenerics; 283 284 // Add this descriptor 285 currentInterface->generic[ 286 currentInterface->generic_count - 1] 287 = (usb_descriptor*)genericDescriptor; 288 break; 289 } 290 291 descriptorStart += configData[descriptorStart]; 292 } 293 } 294 295 // Set default configuration 296 TRACE("setting default configuration\n"); 297 if (SetConfigurationAt(0) != B_OK) { 298 TRACE_ERROR("failed to set default configuration\n"); 299 return; 300 } 301 302 fInitOK = true; 303 } 304 305 306 Device::~Device() 307 { 308 delete fDefaultPipe; 309 310 if (fConfigurations == NULL) { 311 // we didn't get far in device setup, so everything below is unneeded 312 return; 313 } 314 315 // Destroy open endpoints. Do not send a device request to unconfigure 316 // though, since we may be deleted because the device was unplugged 317 // already. 318 Unconfigure(false); 319 320 // Free all allocated resources 321 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) { 322 usb_configuration_info* configuration = &fConfigurations[i]; 323 if (configuration == NULL) 324 continue; 325 326 free(configuration->descr); 327 if (configuration->interface == NULL) 328 continue; 329 330 for (size_t j = 0; j < configuration->interface_count; j++) { 331 usb_interface_list* interfaceList = &configuration->interface[j]; 332 if (interfaceList->alt == NULL) 333 continue; 334 335 for (size_t k = 0; k < interfaceList->alt_count; k++) { 336 usb_interface_info* interface = &interfaceList->alt[k]; 337 delete (Interface*)GetStack()->GetObject(interface->handle); 338 free(interface->endpoint); 339 free(interface->generic); 340 } 341 342 free(interfaceList->alt); 343 } 344 345 free(configuration->interface); 346 } 347 348 free(fConfigurations); 349 } 350 351 352 status_t 353 Device::InitCheck() 354 { 355 if (fInitOK) 356 return B_OK; 357 358 return B_ERROR; 359 } 360 361 362 status_t 363 Device::Changed(change_item** changeList, bool added) 364 { 365 fAvailable = added; 366 change_item* changeItem = new(std::nothrow) change_item; 367 if (changeItem == NULL) 368 return B_NO_MEMORY; 369 370 changeItem->added = added; 371 changeItem->device = this; 372 changeItem->link = *changeList; 373 *changeList = changeItem; 374 return B_OK; 375 } 376 377 378 status_t 379 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID, 380 void* data, size_t dataLength, size_t* actualLength) 381 { 382 if (!fAvailable) 383 return B_ERROR; 384 385 return fDefaultPipe->SendRequest( 386 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, 387 USB_REQUEST_GET_DESCRIPTOR, (descriptorType << 8) | index, 388 languageID, dataLength, data, dataLength, actualLength); 389 } 390 391 392 const usb_configuration_info* 393 Device::Configuration() const 394 { 395 return fCurrentConfiguration; 396 } 397 398 399 const usb_configuration_info* 400 Device::ConfigurationAt(uint8 index) const 401 { 402 if (index >= fDeviceDescriptor.num_configurations) 403 return NULL; 404 405 return &fConfigurations[index]; 406 } 407 408 409 status_t 410 Device::SetConfiguration(const usb_configuration_info* configuration) 411 { 412 if (!configuration) 413 return Unconfigure(true); 414 415 for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) { 416 if (configuration->descr->configuration_value 417 == fConfigurations[i].descr->configuration_value) 418 return SetConfigurationAt(i); 419 } 420 421 return B_BAD_VALUE; 422 } 423 424 425 status_t 426 Device::SetConfigurationAt(uint8 index) 427 { 428 if (!fAvailable) 429 return B_ERROR; 430 if (index >= fDeviceDescriptor.num_configurations) 431 return B_BAD_VALUE; 432 if (&fConfigurations[index] == fCurrentConfiguration) 433 return B_OK; 434 435 // Destroy our open endpoints 436 Unconfigure(false); 437 438 // Tell the device to set the configuration 439 status_t result = fDefaultPipe->SendRequest( 440 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, 441 USB_REQUEST_SET_CONFIGURATION, 442 fConfigurations[index].descr->configuration_value, 0, 0, NULL, 0, NULL); 443 if (result < B_OK) 444 return result; 445 446 // Set current configuration 447 fCurrentConfiguration = &fConfigurations[index]; 448 449 // Initialize all the endpoints that are now active 450 InitEndpoints(-1); 451 452 // Wait some for the configuration being finished 453 if (!fIsRootHub) 454 snooze(USB_DELAY_SET_CONFIGURATION); 455 return B_OK; 456 } 457 458 459 void 460 Device::InitEndpoints(int32 interfaceIndex) 461 { 462 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) { 463 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex) 464 continue; 465 466 usb_interface_info* interfaceInfo 467 = fCurrentConfiguration->interface[j].active; 468 if (interfaceInfo == NULL) 469 continue; 470 471 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) { 472 usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i]; 473 Pipe* pipe = NULL; 474 475 Pipe::pipeDirection direction = Pipe::Out; 476 if ((endpoint->descr->endpoint_address & 0x80) != 0) 477 direction = Pipe::In; 478 479 switch (endpoint->descr->attributes & 0x03) { 480 case USB_ENDPOINT_ATTR_CONTROL: // Control Endpoint 481 pipe = new(std::nothrow) ControlPipe(this); 482 direction = Pipe::Default; 483 break; 484 485 case USB_ENDPOINT_ATTR_ISOCHRONOUS: // Isochronous Endpoint 486 pipe = new(std::nothrow) IsochronousPipe(this); 487 break; 488 489 case USB_ENDPOINT_ATTR_BULK: // Bulk Endpoint 490 pipe = new(std::nothrow) BulkPipe(this); 491 break; 492 493 case USB_ENDPOINT_ATTR_INTERRUPT: // Interrupt Endpoint 494 pipe = new(std::nothrow) InterruptPipe(this); 495 break; 496 } 497 498 if (pipe == NULL) { 499 TRACE_ERROR("failed to allocate pipe\n"); 500 endpoint->handle = 0; 501 continue; 502 } 503 504 pipe->InitCommon(fDeviceAddress, 505 endpoint->descr->endpoint_address & 0x0f, 506 fSpeed, direction, endpoint->descr->max_packet_size, 507 endpoint->descr->interval, fHubAddress, fHubPort); 508 endpoint->handle = pipe->USBID(); 509 } 510 } 511 } 512 513 514 status_t 515 Device::Unconfigure(bool atDeviceLevel) 516 { 517 // If we only want to destroy our open pipes before setting 518 // another configuration unconfigure will be called with 519 // atDevice = false. otherwise we explicitly want to unconfigure 520 // the device and have to send it the corresponding request. 521 if (atDeviceLevel && fAvailable) { 522 status_t result = fDefaultPipe->SendRequest( 523 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, 524 USB_REQUEST_SET_CONFIGURATION, 0, 0, 0, NULL, 0, NULL); 525 if (result < B_OK) 526 return result; 527 528 snooze(USB_DELAY_SET_CONFIGURATION); 529 } 530 531 if (!fCurrentConfiguration) 532 return B_OK; 533 534 ClearEndpoints(-1); 535 fCurrentConfiguration = NULL; 536 return B_OK; 537 } 538 539 540 void 541 Device::ClearEndpoints(int32 interfaceIndex) 542 { 543 if (fCurrentConfiguration == NULL 544 || fCurrentConfiguration->interface == NULL) 545 return; 546 547 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) { 548 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex) 549 continue; 550 551 usb_interface_info* interfaceInfo 552 = fCurrentConfiguration->interface[j].active; 553 if (interfaceInfo == NULL || interfaceInfo->endpoint == NULL) 554 continue; 555 556 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) { 557 usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i]; 558 delete (Pipe*)GetStack()->GetObject(endpoint->handle); 559 endpoint->handle = 0; 560 } 561 } 562 } 563 564 565 status_t 566 Device::SetAltInterface(const usb_interface_info* interface) 567 { 568 uint8 interfaceNumber = interface->descr->interface_number; 569 // Tell the device to set the alternate settings 570 status_t result = fDefaultPipe->SendRequest( 571 USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD, 572 USB_REQUEST_SET_INTERFACE, 573 interface->descr->alternate_setting, interfaceNumber, 0, NULL, 0, NULL); 574 if (result < B_OK) 575 return result; 576 577 // Clear the no longer active endpoints 578 ClearEndpoints(interfaceNumber); 579 580 // Update the active pointer of the interface list 581 usb_interface_list* interfaceList 582 = &fCurrentConfiguration->interface[interfaceNumber]; 583 interfaceList->active 584 = &interfaceList->alt[interface->descr->alternate_setting]; 585 586 // Initialize the new endpoints 587 InitEndpoints(interfaceNumber); 588 return result; 589 } 590 591 592 const usb_device_descriptor* 593 Device::DeviceDescriptor() const 594 { 595 return &fDeviceDescriptor; 596 } 597 598 599 status_t 600 Device::ReportDevice(usb_support_descriptor* supportDescriptors, 601 uint32 supportDescriptorCount, const usb_notify_hooks* hooks, 602 usb_driver_cookie** cookies, bool added, bool recursive) 603 { 604 TRACE("reporting device\n"); 605 bool supported = false; 606 if (supportDescriptorCount == 0 || supportDescriptors == NULL) 607 supported = true; 608 609 for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) { 610 if ((supportDescriptors[i].vendor != 0 611 && fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor) 612 || (supportDescriptors[i].product != 0 613 && fDeviceDescriptor.product_id 614 != supportDescriptors[i].product)) 615 continue; 616 617 if ((supportDescriptors[i].dev_class == 0 618 || fDeviceDescriptor.device_class 619 == supportDescriptors[i].dev_class) 620 && (supportDescriptors[i].dev_subclass == 0 621 || fDeviceDescriptor.device_subclass 622 == supportDescriptors[i].dev_subclass) 623 && (supportDescriptors[i].dev_protocol == 0 624 || fDeviceDescriptor.device_protocol 625 == supportDescriptors[i].dev_protocol)) { 626 supported = true; 627 } 628 629 // we have to check all interfaces for matching class/subclass/protocol 630 for (uint32 j = 0; 631 !supported && j < fDeviceDescriptor.num_configurations; j++) { 632 for (uint32 k = 0; 633 !supported && k < fConfigurations[j].interface_count; k++) { 634 for (uint32 l = 0; !supported 635 && l < fConfigurations[j].interface[k].alt_count; l++) { 636 usb_interface_descriptor* descriptor 637 = fConfigurations[j].interface[k].alt[l].descr; 638 if ((supportDescriptors[i].dev_class == 0 639 || descriptor->interface_class 640 == supportDescriptors[i].dev_class) 641 && (supportDescriptors[i].dev_subclass == 0 642 || descriptor->interface_subclass 643 == supportDescriptors[i].dev_subclass) 644 && (supportDescriptors[i].dev_protocol == 0 645 || descriptor->interface_protocol 646 == supportDescriptors[i].dev_protocol)) { 647 supported = true; 648 } 649 } 650 } 651 } 652 } 653 654 if (!supported) 655 return B_UNSUPPORTED; 656 657 if ((added && hooks->device_added == NULL) 658 || (!added && hooks->device_removed == NULL)) { 659 // hooks are not installed, but report success to indicate that 660 // the driver supports the device 661 return B_OK; 662 } 663 664 usb_id id = USBID(); 665 if (added) { 666 usb_driver_cookie* cookie = new(std::nothrow) usb_driver_cookie; 667 if (hooks->device_added(id, &cookie->cookie) >= B_OK) { 668 cookie->device = id; 669 cookie->link = *cookies; 670 *cookies = cookie; 671 } else 672 delete cookie; 673 } else { 674 usb_driver_cookie** pointer = cookies; 675 usb_driver_cookie* cookie = *cookies; 676 while (cookie != NULL) { 677 if (cookie->device == id) 678 break; 679 pointer = &cookie->link; 680 cookie = cookie->link; 681 } 682 683 if (cookie == NULL) { 684 // the device is supported, but there is no cookie. this most 685 // probably means that the device_added hook above failed. 686 return B_OK; 687 } 688 689 hooks->device_removed(cookie->cookie); 690 *pointer = cookie->link; 691 delete cookie; 692 } 693 694 return B_OK; 695 } 696 697 698 status_t 699 Device::BuildDeviceName(char* string, uint32* index, size_t bufferSize, 700 Device* device) 701 { 702 if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB) == 0) 703 return B_ERROR; 704 705 ((Hub*)Parent())->BuildDeviceName(string, index, bufferSize, this); 706 return B_OK; 707 } 708 709 710 status_t 711 Device::SetFeature(uint16 selector) 712 { 713 if (!fAvailable) 714 return B_ERROR; 715 716 TRACE("set feature %u\n", selector); 717 return fDefaultPipe->SendRequest( 718 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, 719 USB_REQUEST_SET_FEATURE, selector, 0, 0, NULL, 0, NULL); 720 } 721 722 723 status_t 724 Device::ClearFeature(uint16 selector) 725 { 726 if (!fAvailable) 727 return B_ERROR; 728 729 TRACE("clear feature %u\n", selector); 730 return fDefaultPipe->SendRequest( 731 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, 732 USB_REQUEST_CLEAR_FEATURE, selector, 0, 0, NULL, 0, NULL); 733 } 734 735 736 status_t 737 Device::GetStatus(uint16* status) 738 { 739 if (!fAvailable) 740 return B_ERROR; 741 742 TRACE("get status\n"); 743 return fDefaultPipe->SendRequest( 744 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN, 745 USB_REQUEST_GET_STATUS, 0, 0, 2, (void*)status, 2, NULL); 746 } 747