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 #include <StackOrHeapArray.h>
14
15
Device(Object * parent,int8 hubAddress,uint8 hubPort,usb_device_descriptor & desc,int8 deviceAddress,usb_speed speed,bool isRootHub,void * controllerCookie)16 Device::Device(Object* parent, int8 hubAddress, uint8 hubPort,
17 usb_device_descriptor& desc, int8 deviceAddress, usb_speed speed,
18 bool isRootHub, void* controllerCookie)
19 :
20 Object(parent),
21 fDeviceDescriptor(desc),
22 fInitOK(false),
23 fAvailable(true),
24 fIsRootHub(isRootHub),
25 fConfigurations(NULL),
26 fCurrentConfiguration(NULL),
27 fSpeed(speed),
28 fDeviceAddress(deviceAddress),
29 fHubAddress(hubAddress),
30 fHubPort(hubPort),
31 fControllerCookie(controllerCookie),
32 fNode(NULL)
33 {
34 TRACE("creating device\n");
35
36 fDefaultPipe = new(std::nothrow) ControlPipe(this);
37 if (fDefaultPipe == NULL) {
38 TRACE_ERROR("could not allocate default pipe\n");
39 return;
40 }
41
42 fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default,
43 fDeviceDescriptor.max_packet_size_0, 0, fHubAddress, fHubPort);
44
45 // Get the device descriptor
46 // We already have a part of it, but we want it all
47 size_t actualLength;
48 status_t status = GetDescriptor(USB_DESCRIPTOR_DEVICE, 0, 0,
49 (void*)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength);
50
51 if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) {
52 TRACE_ERROR("error while getting the device descriptor\n");
53 return;
54 }
55
56 TRACE("full device descriptor for device %d:\n", fDeviceAddress);
57 TRACE("\tlength:..............%d\n", fDeviceDescriptor.length);
58 TRACE("\tdescriptor_type:.....0x%04x\n", fDeviceDescriptor.descriptor_type);
59 TRACE("\tusb_version:.........0x%04x\n", fDeviceDescriptor.usb_version);
60 TRACE("\tdevice_class:........0x%02x\n", fDeviceDescriptor.device_class);
61 TRACE("\tdevice_subclass:.....0x%02x\n", fDeviceDescriptor.device_subclass);
62 TRACE("\tdevice_protocol:.....0x%02x\n", fDeviceDescriptor.device_protocol);
63 TRACE("\tmax_packet_size_0:...%d\n", fDeviceDescriptor.max_packet_size_0);
64 TRACE("\tvendor_id:...........0x%04x\n", fDeviceDescriptor.vendor_id);
65 TRACE("\tproduct_id:..........0x%04x\n", fDeviceDescriptor.product_id);
66 TRACE("\tdevice_version:......0x%04x\n", fDeviceDescriptor.device_version);
67 TRACE("\tmanufacturer:........0x%02x\n", fDeviceDescriptor.manufacturer);
68 TRACE("\tproduct:.............0x%02x\n", fDeviceDescriptor.product);
69 TRACE("\tserial_number:.......0x%02x\n", fDeviceDescriptor.serial_number);
70 TRACE("\tnum_configurations:..%d\n", fDeviceDescriptor.num_configurations);
71
72 // Get the configurations
73 fConfigurations = (usb_configuration_info*)malloc(
74 fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info));
75 if (fConfigurations == NULL) {
76 TRACE_ERROR("out of memory during config creations!\n");
77 return;
78 }
79
80 memset(fConfigurations, 0, fDeviceDescriptor.num_configurations
81 * sizeof(usb_configuration_info));
82 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
83 usb_configuration_descriptor configDescriptor;
84 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
85 (void*)&configDescriptor, sizeof(usb_configuration_descriptor),
86 &actualLength);
87
88 if (status < B_OK
89 || actualLength != sizeof(usb_configuration_descriptor)) {
90 TRACE_ERROR("error fetching configuration %" B_PRId32 "\n", i);
91 return;
92 }
93
94 TRACE("configuration %" B_PRId32 "\n", i);
95 TRACE("\tlength:..............%d\n", configDescriptor.length);
96 TRACE("\tdescriptor_type:.....0x%02x\n",
97 configDescriptor.descriptor_type);
98 TRACE("\ttotal_length:........%d\n", configDescriptor.total_length);
99 TRACE("\tnumber_interfaces:...%d\n",
100 configDescriptor.number_interfaces);
101 TRACE("\tconfiguration_value:.0x%02x\n",
102 configDescriptor.configuration_value);
103 TRACE("\tconfiguration:.......0x%02x\n",
104 configDescriptor.configuration);
105 TRACE("\tattributes:..........0x%02x\n", configDescriptor.attributes);
106 TRACE("\tmax_power:...........%d\n", configDescriptor.max_power);
107
108 uint8* configData = (uint8*)malloc(configDescriptor.total_length);
109 if (configData == NULL) {
110 TRACE_ERROR("out of memory when reading config\n");
111 return;
112 }
113
114 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
115 (void*)configData, configDescriptor.total_length, &actualLength);
116
117 if (status < B_OK || actualLength != configDescriptor.total_length) {
118 TRACE_ERROR("error fetching full configuration"
119 " descriptor %" B_PRId32 " got %" B_PRIuSIZE " expected %"
120 B_PRIu16 "\n", i, actualLength, configDescriptor.total_length);
121 free(configData);
122 return;
123 }
124
125 usb_configuration_descriptor* configuration
126 = (usb_configuration_descriptor*)configData;
127 fConfigurations[i].descr = configuration;
128 fConfigurations[i].interface_count = configuration->number_interfaces;
129 fConfigurations[i].interface = (usb_interface_list*)malloc(
130 configuration->number_interfaces * sizeof(usb_interface_list));
131 if (fConfigurations[i].interface == NULL) {
132 TRACE_ERROR("out of memory when creating interfaces\n");
133 return;
134 }
135
136 memset(fConfigurations[i].interface, 0,
137 configuration->number_interfaces * sizeof(usb_interface_list));
138
139 usb_interface_info* currentInterface = NULL;
140 uint32 descriptorStart = sizeof(usb_configuration_descriptor);
141 while (descriptorStart < actualLength) {
142 switch (configData[descriptorStart + 1]) {
143 case USB_DESCRIPTOR_INTERFACE:
144 {
145 TRACE("got interface descriptor\n");
146 usb_interface_descriptor* interfaceDescriptor
147 = (usb_interface_descriptor*)&configData[
148 descriptorStart];
149 TRACE("\tlength:.............%d\n",
150 interfaceDescriptor->length);
151 TRACE("\tdescriptor_type:....0x%02x\n",
152 interfaceDescriptor->descriptor_type);
153 TRACE("\tinterface_number:...%d\n",
154 interfaceDescriptor->interface_number);
155 TRACE("\talternate_setting:..%d\n",
156 interfaceDescriptor->alternate_setting);
157 TRACE("\tnum_endpoints:......%d\n",
158 interfaceDescriptor->num_endpoints);
159 TRACE("\tinterface_class:....0x%02x\n",
160 interfaceDescriptor->interface_class);
161 TRACE("\tinterface_subclass:.0x%02x\n",
162 interfaceDescriptor->interface_subclass);
163 TRACE("\tinterface_protocol:.0x%02x\n",
164 interfaceDescriptor->interface_protocol);
165 TRACE("\tinterface:..........%d\n",
166 interfaceDescriptor->interface);
167
168 if (interfaceDescriptor->interface_number
169 >= fConfigurations[i].interface_count) {
170 interfaceDescriptor->interface_number
171 = fConfigurations[i].interface_count - 1;
172 TRACE_ERROR("Corrected invalid interface_number!\n");
173 }
174
175 usb_interface_list* interfaceList = &fConfigurations[i]
176 .interface[interfaceDescriptor->interface_number];
177
178 // Allocate this alternate
179 interfaceList->alt_count++;
180 usb_interface_info* newAlternates
181 = (usb_interface_info*)realloc(interfaceList->alt,
182 interfaceList->alt_count * sizeof(usb_interface_info));
183 if (newAlternates == NULL) {
184 TRACE_ERROR("out of memory allocating"
185 " alternate interface\n");
186 interfaceList->alt_count--;
187 return;
188 }
189
190 interfaceList->alt = newAlternates;
191
192 // Set active interface always to the first one
193 interfaceList->active = interfaceList->alt;
194
195 // Setup this alternate
196 usb_interface_info* interfaceInfo
197 = &interfaceList->alt[interfaceList->alt_count - 1];
198 interfaceInfo->descr = interfaceDescriptor;
199 interfaceInfo->endpoint_count = 0;
200 interfaceInfo->endpoint = NULL;
201 interfaceInfo->generic_count = 0;
202 interfaceInfo->generic = NULL;
203
204 Interface* interface = new(std::nothrow) Interface(this,
205 interfaceDescriptor->interface_number);
206 if (interface == NULL) {
207 TRACE_ERROR("failed to allocate"
208 " interface object\n");
209 return;
210 }
211
212 interfaceInfo->handle = interface->USBID();
213 currentInterface = interfaceInfo;
214 break;
215 }
216
217 case USB_DESCRIPTOR_ENDPOINT:
218 {
219 TRACE("got endpoint descriptor\n");
220 usb_endpoint_descriptor* endpointDescriptor
221 = (usb_endpoint_descriptor*)&configData[descriptorStart];
222 TRACE("\tlength:.............%d\n",
223 endpointDescriptor->length);
224 TRACE("\tdescriptor_type:....0x%02x\n",
225 endpointDescriptor->descriptor_type);
226 TRACE("\tendpoint_address:...0x%02x\n",
227 endpointDescriptor->endpoint_address);
228 TRACE("\tattributes:.........0x%02x\n",
229 endpointDescriptor->attributes);
230 TRACE("\tmax_packet_size:....%d\n",
231 endpointDescriptor->max_packet_size);
232 TRACE("\tinterval:...........%d\n",
233 endpointDescriptor->interval);
234
235 if (currentInterface == NULL)
236 break;
237
238 // Allocate this endpoint
239 currentInterface->endpoint_count++;
240 usb_endpoint_info* newEndpoints = (usb_endpoint_info*)
241 realloc(currentInterface->endpoint,
242 currentInterface->endpoint_count
243 * sizeof(usb_endpoint_info));
244 if (newEndpoints == NULL) {
245 TRACE_ERROR("out of memory allocating new endpoint\n");
246 currentInterface->endpoint_count--;
247 return;
248 }
249
250 currentInterface->endpoint = newEndpoints;
251
252 // Setup this endpoint
253 usb_endpoint_info* endpointInfo = ¤tInterface
254 ->endpoint[currentInterface->endpoint_count - 1];
255 endpointInfo->descr = endpointDescriptor;
256 endpointInfo->handle = 0;
257 break;
258 }
259
260 case USB_DESCRIPTOR_ENDPOINT_SS_COMPANION: {
261 if (currentInterface != NULL) {
262 usb_endpoint_descriptor* desc
263 = currentInterface->endpoint[
264 currentInterface->endpoint_count - 1].descr;
265 if ((uint8*)desc != (&configData[descriptorStart
266 - desc->length])) {
267 TRACE_ERROR("found endpoint companion descriptor "
268 "not immediately following endpoint "
269 "descriptor, ignoring!\n");
270 break;
271 }
272 // TODO: It'd be nicer if we could store the endpoint
273 // companion descriptor along with the endpoint
274 // descriptor, but as the interface struct is public
275 // API, that would be an ABI break.
276 }
277
278 // fall through
279 }
280
281 default:
282 TRACE("got generic descriptor\n");
283 usb_generic_descriptor* genericDescriptor
284 = (usb_generic_descriptor*)&configData[descriptorStart];
285 TRACE("\tlength:.............%d\n",
286 genericDescriptor->length);
287 TRACE("\tdescriptor_type:....0x%02x\n",
288 genericDescriptor->descriptor_type);
289
290 if (currentInterface == NULL)
291 break;
292
293 // Allocate this descriptor
294 currentInterface->generic_count++;
295 usb_descriptor** newGenerics = (usb_descriptor**)realloc(
296 currentInterface->generic,
297 currentInterface->generic_count
298 * sizeof(usb_descriptor*));
299 if (newGenerics == NULL) {
300 TRACE_ERROR("out of memory allocating"
301 " generic descriptor\n");
302 currentInterface->generic_count--;
303 return;
304 }
305
306 currentInterface->generic = newGenerics;
307
308 // Add this descriptor
309 currentInterface->generic[
310 currentInterface->generic_count - 1]
311 = (usb_descriptor*)genericDescriptor;
312 break;
313 }
314
315 descriptorStart += configData[descriptorStart];
316 }
317 }
318
319 // Set default configuration
320 TRACE("setting default configuration\n");
321 if (SetConfigurationAt(0) != B_OK) {
322 TRACE_ERROR("failed to set default configuration\n");
323 return;
324 }
325
326 fInitOK = true;
327 }
328
329
~Device()330 Device::~Device()
331 {
332 if (fNode != NULL) {
333 status_t error = gDeviceManager->unregister_node(fNode);
334 if (error != B_OK && error != B_BUSY)
335 TRACE_ERROR("failed to unregister device node\n");
336 fNode = NULL;
337 }
338
339 // Destroy open endpoints. Do not send a device request to unconfigure
340 // though, since we may be deleted because the device was unplugged already.
341 Unconfigure(false);
342
343 // Destroy all Interfaces in the Configurations hierarchy.
344 for (int32 i = 0; fConfigurations != NULL
345 && i < fDeviceDescriptor.num_configurations; i++) {
346 usb_configuration_info* configuration = &fConfigurations[i];
347 if (configuration == NULL || configuration->interface == NULL)
348 continue;
349
350 for (size_t j = 0; j < configuration->interface_count; j++) {
351 usb_interface_list* interfaceList = &configuration->interface[j];
352 if (interfaceList->alt == NULL)
353 continue;
354
355 for (size_t k = 0; k < interfaceList->alt_count; k++) {
356 usb_interface_info* interface = &interfaceList->alt[k];
357 Interface* interfaceObject =
358 (Interface*)GetStack()->GetObject(interface->handle);
359 interface->handle = 0;
360 if (interfaceObject != NULL)
361 interfaceObject->ReleaseReference();
362 delete interfaceObject;
363 }
364 }
365 }
366
367 if (fDefaultPipe != NULL) {
368 fDefaultPipe->PutUSBID(false);
369
370 // Also put our ID to prevent further transfers on the default pipe
371 // from being queued. (We have to do this after putting the pipe's ID,
372 // since we are its parent.)
373 PutUSBID(false);
374
375 fDefaultPipe->CancelQueuedTransfers(true);
376 fDefaultPipe->WaitForIdle();
377 }
378
379 // Ensure we are gone from the stack before deleting public structures.
380 PutUSBID(true);
381 delete fDefaultPipe;
382
383 if (fConfigurations == NULL) {
384 // we didn't get far in device setup, so everything below is unneeded
385 return;
386 }
387
388 // Free the Configurations hierarchy.
389 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
390 usb_configuration_info* configuration = &fConfigurations[i];
391 if (configuration == NULL)
392 continue;
393
394 free(configuration->descr);
395 if (configuration->interface == NULL)
396 continue;
397
398 for (size_t j = 0; j < configuration->interface_count; j++) {
399 usb_interface_list* interfaceList = &configuration->interface[j];
400 if (interfaceList->alt == NULL)
401 continue;
402
403 for (size_t k = 0; k < interfaceList->alt_count; k++) {
404 usb_interface_info* interface = &interfaceList->alt[k];
405 free(interface->endpoint);
406 free(interface->generic);
407 }
408
409 free(interfaceList->alt);
410 }
411
412 free(configuration->interface);
413 }
414
415 free(fConfigurations);
416 }
417
418
419 status_t
InitCheck()420 Device::InitCheck()
421 {
422 if (fInitOK)
423 return B_OK;
424
425 return B_ERROR;
426 }
427
428
429 status_t
Changed(change_item ** changeList,bool added)430 Device::Changed(change_item** changeList, bool added)
431 {
432 fAvailable = added;
433 change_item* changeItem = new(std::nothrow) change_item;
434 if (changeItem == NULL)
435 return B_NO_MEMORY;
436
437 changeItem->added = added;
438 changeItem->device = this;
439 changeItem->link = *changeList;
440 *changeList = changeItem;
441 return B_OK;
442 }
443
444
445 status_t
GetDescriptor(uint8 descriptorType,uint8 index,uint16 languageID,void * data,size_t dataLength,size_t * actualLength)446 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
447 void* data, size_t dataLength, size_t* actualLength)
448 {
449 if (!fAvailable)
450 return B_ERROR;
451
452 return fDefaultPipe->SendRequest(
453 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,
454 USB_REQUEST_GET_DESCRIPTOR, (descriptorType << 8) | index,
455 languageID, dataLength, data, dataLength, actualLength);
456 }
457
458
459 const usb_configuration_info*
Configuration() const460 Device::Configuration() const
461 {
462 return fCurrentConfiguration;
463 }
464
465
466 const usb_configuration_info*
ConfigurationAt(uint8 index) const467 Device::ConfigurationAt(uint8 index) const
468 {
469 if (index >= fDeviceDescriptor.num_configurations)
470 return NULL;
471
472 return &fConfigurations[index];
473 }
474
475
476 status_t
SetConfiguration(const usb_configuration_info * configuration)477 Device::SetConfiguration(const usb_configuration_info* configuration)
478 {
479 if (!configuration)
480 return Unconfigure(true);
481
482 for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
483 if (configuration->descr->configuration_value
484 == fConfigurations[i].descr->configuration_value)
485 return SetConfigurationAt(i);
486 }
487
488 return B_BAD_VALUE;
489 }
490
491
492 status_t
SetConfigurationAt(uint8 index)493 Device::SetConfigurationAt(uint8 index)
494 {
495 if (!fAvailable)
496 return B_ERROR;
497 if (index >= fDeviceDescriptor.num_configurations)
498 return B_BAD_VALUE;
499 if (&fConfigurations[index] == fCurrentConfiguration)
500 return B_OK;
501
502 // Destroy our open endpoints
503 Unconfigure(false);
504
505 // Tell the device to set the configuration
506 status_t result = fDefaultPipe->SendRequest(
507 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
508 USB_REQUEST_SET_CONFIGURATION,
509 fConfigurations[index].descr->configuration_value, 0, 0, NULL, 0, NULL);
510 if (result < B_OK)
511 return result;
512
513 // Set current configuration
514 fCurrentConfiguration = &fConfigurations[index];
515
516 // Initialize all the endpoints that are now active
517 InitEndpoints(-1);
518
519 // Wait some for the configuration being finished
520 if (!fIsRootHub)
521 snooze(USB_DELAY_SET_CONFIGURATION);
522 return B_OK;
523 }
524
525
526 void
InitEndpoints(int32 interfaceIndex)527 Device::InitEndpoints(int32 interfaceIndex)
528 {
529 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
530 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
531 continue;
532
533 usb_interface_info* interfaceInfo
534 = fCurrentConfiguration->interface[j].active;
535 if (interfaceInfo == NULL)
536 continue;
537
538 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
539 usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
540 Pipe* pipe = NULL;
541
542 usb_endpoint_ss_companion_descriptor* comp_descr = NULL;
543 if (fSpeed >= USB_SPEED_SUPERSPEED) {
544 // We should have a companion descriptor for this device.
545 // Let's find it: it'll be the "i"th one.
546 size_t k = 0;
547 for (size_t j = 0; j < interfaceInfo->generic_count; j++) {
548 usb_descriptor* desc = interfaceInfo->generic[j];
549 if (desc->endpoint.descriptor_type
550 != USB_DESCRIPTOR_ENDPOINT_SS_COMPANION) {
551 continue;
552 }
553 if (k == i) {
554 comp_descr =
555 (usb_endpoint_ss_companion_descriptor*)desc;
556 break;
557 }
558 k++;
559 }
560 if (comp_descr == NULL) {
561 TRACE_ERROR("SuperSpeed device without an endpoint companion "
562 "descriptor!");
563 }
564 }
565
566 Pipe::pipeDirection direction = Pipe::Out;
567 if ((endpoint->descr->endpoint_address & 0x80) != 0)
568 direction = Pipe::In;
569
570 switch (endpoint->descr->attributes & 0x03) {
571 case USB_ENDPOINT_ATTR_CONTROL: // Control Endpoint
572 pipe = new(std::nothrow) ControlPipe(this);
573 direction = Pipe::Default;
574 break;
575
576 case USB_ENDPOINT_ATTR_ISOCHRONOUS: // Isochronous Endpoint
577 pipe = new(std::nothrow) IsochronousPipe(this);
578 break;
579
580 case USB_ENDPOINT_ATTR_BULK: // Bulk Endpoint
581 pipe = new(std::nothrow) BulkPipe(this);
582 break;
583
584 case USB_ENDPOINT_ATTR_INTERRUPT: // Interrupt Endpoint
585 pipe = new(std::nothrow) InterruptPipe(this);
586 break;
587 }
588
589 if (pipe == NULL) {
590 TRACE_ERROR("failed to allocate pipe\n");
591 endpoint->handle = 0;
592 continue;
593 }
594
595 pipe->InitCommon(fDeviceAddress,
596 endpoint->descr->endpoint_address & 0x0f,
597 fSpeed, direction, endpoint->descr->max_packet_size,
598 endpoint->descr->interval, fHubAddress, fHubPort);
599 if (comp_descr != NULL) {
600 pipe->InitSuperSpeed(comp_descr->max_burst,
601 comp_descr->bytes_per_interval);
602 }
603 endpoint->handle = pipe->USBID();
604 }
605 }
606 }
607
608
609 status_t
Unconfigure(bool atDeviceLevel)610 Device::Unconfigure(bool atDeviceLevel)
611 {
612 // If we only want to destroy our open pipes before setting
613 // another configuration unconfigure will be called with
614 // atDevice = false. otherwise we explicitly want to unconfigure
615 // the device and have to send it the corresponding request.
616 if (atDeviceLevel && fAvailable) {
617 status_t result = fDefaultPipe->SendRequest(
618 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
619 USB_REQUEST_SET_CONFIGURATION, 0, 0, 0, NULL, 0, NULL);
620 if (result < B_OK)
621 return result;
622
623 snooze(USB_DELAY_SET_CONFIGURATION);
624 }
625
626 if (!fCurrentConfiguration)
627 return B_OK;
628
629 ClearEndpoints(-1);
630 fCurrentConfiguration = NULL;
631 return B_OK;
632 }
633
634
635 void
ClearEndpoints(int32 interfaceIndex)636 Device::ClearEndpoints(int32 interfaceIndex)
637 {
638 if (fCurrentConfiguration == NULL
639 || fCurrentConfiguration->interface == NULL)
640 return;
641
642 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
643 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
644 continue;
645
646 usb_interface_info* interfaceInfo
647 = fCurrentConfiguration->interface[j].active;
648 if (interfaceInfo == NULL || interfaceInfo->endpoint == NULL)
649 continue;
650
651 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
652 usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
653 Pipe* pipe = (Pipe*)GetStack()->GetObject(endpoint->handle);
654 if (pipe != NULL)
655 pipe->ReleaseReference();
656 delete pipe;
657 endpoint->handle = 0;
658 }
659 }
660 }
661
662
663 status_t
SetAltInterface(const usb_interface_info * interface)664 Device::SetAltInterface(const usb_interface_info* interface)
665 {
666 uint8 interfaceNumber = interface->descr->interface_number;
667 // Tell the device to set the alternate settings
668 status_t result = fDefaultPipe->SendRequest(
669 USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD,
670 USB_REQUEST_SET_INTERFACE,
671 interface->descr->alternate_setting, interfaceNumber, 0, NULL, 0, NULL);
672 if (result < B_OK)
673 return result;
674
675 // Clear the no longer active endpoints
676 ClearEndpoints(interfaceNumber);
677
678 // Update the active pointer of the interface list
679 usb_interface_list* interfaceList
680 = &fCurrentConfiguration->interface[interfaceNumber];
681 interfaceList->active
682 = &interfaceList->alt[interface->descr->alternate_setting];
683
684 // Initialize the new endpoints
685 InitEndpoints(interfaceNumber);
686 return result;
687 }
688
689
690 const usb_device_descriptor*
DeviceDescriptor() const691 Device::DeviceDescriptor() const
692 {
693 return &fDeviceDescriptor;
694 }
695
696
697 status_t
ReportDevice(usb_support_descriptor * supportDescriptors,uint32 supportDescriptorCount,const usb_notify_hooks * hooks,usb_driver_cookie ** cookies,bool added,bool recursive)698 Device::ReportDevice(usb_support_descriptor* supportDescriptors,
699 uint32 supportDescriptorCount, const usb_notify_hooks* hooks,
700 usb_driver_cookie** cookies, bool added, bool recursive)
701 {
702 TRACE("reporting device\n");
703 bool supported = false;
704 if (supportDescriptorCount == 0 || supportDescriptors == NULL)
705 supported = true;
706
707 for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) {
708 if ((supportDescriptors[i].vendor != 0
709 && fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
710 || (supportDescriptors[i].product != 0
711 && fDeviceDescriptor.product_id
712 != supportDescriptors[i].product))
713 continue;
714
715 if ((supportDescriptors[i].dev_class == 0
716 || fDeviceDescriptor.device_class
717 == supportDescriptors[i].dev_class)
718 && (supportDescriptors[i].dev_subclass == 0
719 || fDeviceDescriptor.device_subclass
720 == supportDescriptors[i].dev_subclass)
721 && (supportDescriptors[i].dev_protocol == 0
722 || fDeviceDescriptor.device_protocol
723 == supportDescriptors[i].dev_protocol)) {
724 supported = true;
725 }
726
727 // we have to check all interfaces for matching class/subclass/protocol
728 for (uint32 j = 0;
729 !supported && j < fDeviceDescriptor.num_configurations; j++) {
730 for (uint32 k = 0;
731 !supported && k < fConfigurations[j].interface_count; k++) {
732 for (uint32 l = 0; !supported
733 && l < fConfigurations[j].interface[k].alt_count; l++) {
734 usb_interface_descriptor* descriptor
735 = fConfigurations[j].interface[k].alt[l].descr;
736 if ((supportDescriptors[i].dev_class == 0
737 || descriptor->interface_class
738 == supportDescriptors[i].dev_class)
739 && (supportDescriptors[i].dev_subclass == 0
740 || descriptor->interface_subclass
741 == supportDescriptors[i].dev_subclass)
742 && (supportDescriptors[i].dev_protocol == 0
743 || descriptor->interface_protocol
744 == supportDescriptors[i].dev_protocol)) {
745 supported = true;
746 }
747 }
748 }
749 }
750 }
751
752 if (!supported)
753 return B_UNSUPPORTED;
754
755 if ((added && hooks->device_added == NULL)
756 || (!added && hooks->device_removed == NULL)) {
757 // hooks are not installed, but report success to indicate that
758 // the driver supports the device
759 return B_OK;
760 }
761
762 usb_id id = USBID();
763 if (added) {
764 usb_driver_cookie* cookie = new(std::nothrow) usb_driver_cookie;
765 if (hooks->device_added(id, &cookie->cookie) >= B_OK) {
766 cookie->device = id;
767 cookie->link = *cookies;
768 *cookies = cookie;
769 } else
770 delete cookie;
771 } else {
772 usb_driver_cookie** pointer = cookies;
773 usb_driver_cookie* cookie = *cookies;
774 while (cookie != NULL) {
775 if (cookie->device == id)
776 break;
777 pointer = &cookie->link;
778 cookie = cookie->link;
779 }
780
781 if (cookie == NULL) {
782 // the device is supported, but there is no cookie. this most
783 // probably means that the device_added hook above failed.
784 return B_OK;
785 }
786
787 hooks->device_removed(cookie->cookie);
788 *pointer = cookie->link;
789 delete cookie;
790 }
791
792 return B_OK;
793 }
794
795
796 status_t
BuildDeviceName(char * string,uint32 * index,size_t bufferSize,Device * device)797 Device::BuildDeviceName(char* string, uint32* index, size_t bufferSize,
798 Device* device)
799 {
800 if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB) == 0)
801 return B_ERROR;
802
803 ((Hub*)Parent())->BuildDeviceName(string, index, bufferSize, this);
804 return B_OK;
805 }
806
807
808 status_t
SetFeature(uint16 selector)809 Device::SetFeature(uint16 selector)
810 {
811 if (!fAvailable)
812 return B_ERROR;
813
814 TRACE("set feature %u\n", selector);
815 return fDefaultPipe->SendRequest(
816 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
817 USB_REQUEST_SET_FEATURE, selector, 0, 0, NULL, 0, NULL);
818 }
819
820
821 status_t
ClearFeature(uint16 selector)822 Device::ClearFeature(uint16 selector)
823 {
824 if (!fAvailable)
825 return B_ERROR;
826
827 TRACE("clear feature %u\n", selector);
828 return fDefaultPipe->SendRequest(
829 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
830 USB_REQUEST_CLEAR_FEATURE, selector, 0, 0, NULL, 0, NULL);
831 }
832
833
834 status_t
GetStatus(uint16 * status)835 Device::GetStatus(uint16* status)
836 {
837 if (!fAvailable)
838 return B_ERROR;
839
840 TRACE("get status\n");
841 return fDefaultPipe->SendRequest(
842 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
843 USB_REQUEST_GET_STATUS, 0, 0, 2, (void*)status, 2, NULL);
844 }
845
846
847 device_node*
RegisterNode(device_node * parent)848 Device::RegisterNode(device_node *parent)
849 {
850 usb_id id = USBID();
851 if (parent == NULL)
852 parent = ((Device*)Parent())->Node();
853
854 // determine how many attributes we will need
855 uint32 deviceAttrTotal = 1;
856 for (uint32 j = 0; j < fDeviceDescriptor.num_configurations; j++) {
857 for (uint32 k = 0; k < fConfigurations[j].interface_count; k++) {
858 for (uint32 l = 0; l < fConfigurations[j].interface[k].alt_count; l++) {
859 deviceAttrTotal += 3;
860 }
861 }
862 }
863
864 BStackOrHeapArray<device_attr, 16> attrs(deviceAttrTotal + 4 + 5);
865 attrs[0] = { B_DEVICE_BUS, B_STRING_TYPE, { .string = "usb" } };
866
867 // location
868 attrs[1] = { USB_DEVICE_ID_ITEM, B_UINT32_TYPE, { .ui32 = id } };
869 attrs[2] = { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN } };
870 attrs[3] = { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "USB device" } };
871
872 uint32 attrCount = 4;
873
874 if (fDeviceDescriptor.vendor_id != 0) {
875 attrs[attrCount].name = B_DEVICE_VENDOR_ID;
876 attrs[attrCount].type = B_UINT16_TYPE;
877 attrs[attrCount].value.ui16 = fDeviceDescriptor.vendor_id;
878 attrCount++;
879
880 attrs[attrCount].name = B_DEVICE_ID;
881 attrs[attrCount].type = B_UINT16_TYPE;
882 attrs[attrCount].value.ui16 = fDeviceDescriptor.product_id;
883 attrCount++;
884 }
885
886 uint32 attrClassesIndex = attrCount;
887
888 if (fDeviceDescriptor.device_class != 0) {
889 attrs[attrCount].name = USB_DEVICE_CLASS;
890 attrs[attrCount].type = B_UINT8_TYPE;
891 attrs[attrCount].value.ui8 = fDeviceDescriptor.device_class;
892 attrCount++;
893
894 attrs[attrCount].name = USB_DEVICE_SUBCLASS;
895 attrs[attrCount].type = B_UINT8_TYPE;
896 attrs[attrCount].value.ui8 = fDeviceDescriptor.device_subclass;
897 attrCount++;
898
899 attrs[attrCount].name = USB_DEVICE_PROTOCOL;
900 attrs[attrCount].type = B_UINT8_TYPE;
901 attrs[attrCount].value.ui8 = fDeviceDescriptor.device_protocol;
902 attrCount++;
903 }
904
905 for (uint32 j = 0; j < fDeviceDescriptor.num_configurations; j++) {
906 for (uint32 k = 0; k < fConfigurations[j].interface_count; k++) {
907 for (uint32 l = 0; l < fConfigurations[j].interface[k].alt_count; l++) {
908 usb_interface_descriptor* descriptor
909 = fConfigurations[j].interface[k].alt[l].descr;
910 bool found = false;
911 for (uint32 i = attrClassesIndex; i < attrCount;) {
912 if (attrs[i++].value.ui8 != descriptor->interface_class)
913 continue;
914 if (attrs[i++].value.ui8 != descriptor->interface_subclass)
915 continue;
916 if (attrs[i++].value.ui8 != descriptor->interface_protocol)
917 continue;
918 found = true;
919 break;
920 }
921 if (found)
922 continue;
923
924 attrs[attrCount].name = USB_DEVICE_CLASS;
925 attrs[attrCount].type = B_UINT8_TYPE;
926 attrs[attrCount].value.ui8 = descriptor->interface_class;
927 attrCount++;
928
929 attrs[attrCount].name = USB_DEVICE_SUBCLASS;
930 attrs[attrCount].type = B_UINT8_TYPE;
931 attrs[attrCount].value.ui8 = descriptor->interface_subclass;
932 attrCount++;
933
934 attrs[attrCount].name = USB_DEVICE_PROTOCOL;
935 attrs[attrCount].type = B_UINT8_TYPE;
936 attrs[attrCount].value.ui8 = descriptor->interface_protocol;
937 attrCount++;
938 }
939 }
940 }
941
942 attrs[attrCount].name = NULL;
943 attrs[attrCount].type = 0;
944 attrs[attrCount].value.string = NULL;
945 attrCount++;
946
947 device_node* node = NULL;
948 if (gDeviceManager->register_node(parent, USB_DEVICE_MODULE_NAME, attrs,
949 NULL, &node) != B_OK) {
950 TRACE_ERROR("failed to register device node\n");
951 } else
952 fNode = node;
953 return node;
954 }
955