2 * Copyright 2003-2006, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
10 #include "usb_private.h"
13 Device::Device(Object
*parent
, int8 hubAddress
, uint8 hubPort
,
14 usb_device_descriptor
&desc
, int8 deviceAddress
, usb_speed speed
,
15 bool isRootHub
, void *controllerCookie
)
17 fDeviceDescriptor(desc
),
20 fIsRootHub(isRootHub
),
21 fConfigurations(NULL
),
22 fCurrentConfiguration(NULL
),
24 fDeviceAddress(deviceAddress
),
25 fHubAddress(hubAddress
),
27 fControllerCookie(controllerCookie
)
29 TRACE("creating device\n");
31 fDefaultPipe
= new(std::nothrow
) ControlPipe(this);
33 TRACE_ERROR("could not allocate default pipe\n");
37 fDefaultPipe
->InitCommon(fDeviceAddress
, 0, fSpeed
, Pipe::Default
,
38 fDeviceDescriptor
.max_packet_size_0
, 0, fHubAddress
, fHubPort
);
40 // Get the device descriptor
41 // We already have a part of it, but we want it all
43 status_t status
= GetDescriptor(USB_DESCRIPTOR_DEVICE
, 0, 0,
44 (void *)&fDeviceDescriptor
, sizeof(fDeviceDescriptor
), &actualLength
);
46 if (status
< B_OK
|| actualLength
!= sizeof(fDeviceDescriptor
)) {
47 TRACE_ERROR("error while getting the device descriptor\n");
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
);
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");
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
),
83 if (status
< B_OK
|| actualLength
!= sizeof(usb_configuration_descriptor
)) {
84 TRACE_ERROR("error fetching configuration %ld\n", i
);
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
);
98 uint8
*configData
= (uint8
*)malloc(configDescriptor
.total_length
);
99 if (configData
== NULL
) {
100 TRACE_ERROR("out of memory when reading config\n");
104 status
= GetDescriptor(USB_DESCRIPTOR_CONFIGURATION
, i
, 0,
105 (void *)configData
, configDescriptor
.total_length
, &actualLength
);
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
);
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");
126 memset(fConfigurations
[i
].interface
, 0,
127 configuration
->number_interfaces
* sizeof(usb_interface_list
));
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
);
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");
152 usb_interface_list
*interfaceList
153 = &fConfigurations
[i
].interface
[interfaceDescriptor
->interface_number
];
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
--;
167 interfaceList
->alt
= newAlternates
;
169 /* Set active interface always to the first one */
170 interfaceList
->active
= interfaceList
->alt
;
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
;
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");
189 interfaceInfo
->handle
= interface
->USBID();
190 currentInterface
= interfaceInfo
;
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
);
205 if (!currentInterface
)
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"
218 currentInterface
->endpoint_count
--;
222 currentInterface
->endpoint
= newEndpoints
;
224 /* setup this endpoint */
225 usb_endpoint_info
*endpointInfo
=
226 ¤tInterface
->endpoint
[currentInterface
->endpoint_count
- 1];
227 endpointInfo
->descr
= endpointDescriptor
;
228 endpointInfo
->handle
= 0;
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
);
239 if (!currentInterface
)
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
--;
255 currentInterface
->generic
= newGenerics
;
257 /* add this descriptor */
258 currentInterface
->generic
[currentInterface
->generic_count
- 1] =
259 (usb_descriptor
*)genericDescriptor
;
263 descriptorStart
+= configData
[descriptorStart
];
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");
282 if (fConfigurations
== NULL
) {
283 // we didn't get far in device setup, so everything below is unneeded
287 // Destroy open endpoints. Do not send a device request to unconfigure
288 // though, since we may be deleted because the device was unplugged
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
)
298 free(configuration
->descr
);
299 if (configuration
->interface
== NULL
)
302 for (size_t j
= 0; j
< configuration
->interface_count
; j
++) {
303 usb_interface_list
*interfaceList
= &configuration
->interface
[j
];
304 if (interfaceList
->alt
== NULL
)
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
);
314 free(interfaceList
->alt
);
317 free(configuration
->interface
);
320 free(fConfigurations
);
335 Device::Changed(change_item
**changeList
, bool added
)
338 change_item
*changeItem
= new(std::nothrow
) change_item
;
342 changeItem
->added
= added
;
343 changeItem
->device
= this;
344 changeItem
->link
= *changeList
;
345 *changeList
= changeItem
;
351 Device::GetDescriptor(uint8 descriptorType
, uint8 index
, uint16 languageID
,
352 void *data
, size_t dataLength
, size_t *actualLength
)
357 return fDefaultPipe
->SendRequest(
358 USB_REQTYPE_DEVICE_IN
| USB_REQTYPE_STANDARD
, // type
359 USB_REQUEST_GET_DESCRIPTOR
, // request
360 (descriptorType
<< 8) | index
, // value
362 dataLength
, // length
364 dataLength
, // buffer length
365 actualLength
); // actual length
369 const usb_configuration_info
*
370 Device::Configuration() const
372 return fCurrentConfiguration
;
376 const usb_configuration_info
*
377 Device::ConfigurationAt(uint8 index
) const
379 if (index
>= fDeviceDescriptor
.num_configurations
)
382 return &fConfigurations
[index
];
387 Device::SetConfiguration(const usb_configuration_info
*configuration
)
390 return Unconfigure(true);
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
);
403 Device::SetConfigurationAt(uint8 index
)
407 if (index
>= fDeviceDescriptor
.num_configurations
)
409 if (&fConfigurations
[index
] == fCurrentConfiguration
)
412 // Destroy our open endpoints
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
424 NULL
); // actual length
429 // Set current configuration
430 fCurrentConfiguration
= &fConfigurations
[index
];
432 // Initialize all the endpoints that are now active
435 // Wait some for the configuration being finished
437 snooze(USB_DELAY_SET_CONFIGURATION
);
443 Device::InitEndpoints(int32 interfaceIndex
)
445 for (size_t j
= 0; j
< fCurrentConfiguration
->interface_count
; j
++) {
446 if (interfaceIndex
>= 0 && j
!= (size_t)interfaceIndex
)
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
];
454 Pipe::pipeDirection direction
= Pipe::Out
;
455 if (endpoint
->descr
->endpoint_address
& 0x80)
456 direction
= Pipe::In
;
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
;
464 case USB_ENDPOINT_ATTR_ISOCHRONOUS
: /* Isochronous Endpoint */
465 pipe
= new(std::nothrow
) IsochronousPipe(this);
468 case USB_ENDPOINT_ATTR_BULK
: /* Bulk Endpoint */
469 pipe
= new(std::nothrow
) BulkPipe(this);
472 case USB_ENDPOINT_ATTR_INTERRUPT
: /* Interrupt Endpoint */
473 pipe
= new(std::nothrow
) InterruptPipe(this);
478 TRACE_ERROR("failed to allocate pipe\n");
479 endpoint
->handle
= 0;
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();
494 Device::Unconfigure(bool atDeviceLevel
)
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
509 NULL
); // actual length
514 snooze(USB_DELAY_SET_CONFIGURATION
);
517 if (!fCurrentConfiguration
)
521 fCurrentConfiguration
= NULL
;
527 Device::ClearEndpoints(int32 interfaceIndex
)
529 if (fCurrentConfiguration
== NULL
|| fCurrentConfiguration
->interface
== NULL
)
532 for (size_t j
= 0; j
< fCurrentConfiguration
->interface_count
; j
++) {
533 if (interfaceIndex
>= 0 && j
!= (size_t)interfaceIndex
)
536 usb_interface_info
*interfaceInfo
= fCurrentConfiguration
->interface
[j
].active
;
537 if (interfaceInfo
== NULL
|| interfaceInfo
->endpoint
== NULL
)
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;
550 Device::SetAltInterface(const usb_interface_info
*interface
)
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
567 // Clear the no longer active endpoints
568 ClearEndpoints(interfaceNumber
);
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
];
576 // Initialize the new endpoints
577 InitEndpoints(interfaceNumber
);
581 const usb_device_descriptor
*
582 Device::DeviceDescriptor() const
584 return &fDeviceDescriptor
;
589 Device::ReportDevice(usb_support_descriptor
*supportDescriptors
,
590 uint32 supportDescriptorCount
, const usb_notify_hooks
*hooks
,
591 usb_driver_cookie
**cookies
, bool added
, bool recursive
)
593 TRACE("reporting device\n");
594 bool supported
= false;
595 if (supportDescriptorCount
== 0 || supportDescriptors
== NULL
)
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
))
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
)) {
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
)) {
633 return B_UNSUPPORTED
;
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
644 usb_driver_cookie
*cookie
= new(std::nothrow
) usb_driver_cookie
;
645 if (hooks
->device_added(id
, &cookie
->cookie
) >= B_OK
) {
647 cookie
->link
= *cookies
;
652 usb_driver_cookie
**pointer
= cookies
;
653 usb_driver_cookie
*cookie
= *cookies
;
655 if (cookie
->device
== id
)
657 pointer
= &cookie
->link
;
658 cookie
= cookie
->link
;
662 // the device is supported, but there is no cookie. this most
663 // probably means that the device_added hook above failed.
667 hooks
->device_removed(cookie
->cookie
);
668 *pointer
= cookie
->link
;
677 Device::BuildDeviceName(char *string
, uint32
*index
, size_t bufferSize
,
680 if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB
) == 0)
683 ((Hub
*)Parent())->BuildDeviceName(string
, index
, bufferSize
, this);
689 Device::SetFeature(uint16 selector
)
694 TRACE("set feature %u\n", selector
);
695 return fDefaultPipe
->SendRequest(
696 USB_REQTYPE_STANDARD
| USB_REQTYPE_DEVICE_OUT
,
697 USB_REQUEST_SET_FEATURE
,
708 Device::ClearFeature(uint16 selector
)
713 TRACE("clear feature %u\n", selector
);
714 return fDefaultPipe
->SendRequest(
715 USB_REQTYPE_STANDARD
| USB_REQTYPE_DEVICE_OUT
,
716 USB_REQUEST_CLEAR_FEATURE
,
727 Device::GetStatus(uint16
*status
)
732 TRACE("get status\n");
733 return fDefaultPipe
->SendRequest(
734 USB_REQTYPE_STANDARD
| USB_REQTYPE_DEVICE_IN
,
735 USB_REQUEST_GET_STATUS
,