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