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