1 /* 2 * Copyright 2003-2006, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Niels S. Reedijk 7 */ 8 9 #include "usb_p.h" 10 11 12 #define TRACE_HUB 13 #ifdef TRACE_HUB 14 #define TRACE(x) dprintf x 15 #else 16 #define TRACE(x) /* nothing */ 17 #endif 18 19 20 Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc, 21 int8 deviceAddress, bool lowSpeed) 22 : Device(bus, parent, desc, deviceAddress, lowSpeed) 23 { 24 TRACE(("USB Hub is being initialised\n")); 25 26 if (!fInitOK) { 27 TRACE(("USB Hub: Device failed to initialize\n")); 28 return; 29 } 30 31 // Set to false again for the hub init. 32 fInitOK = false; 33 34 if (fDeviceDescriptor.device_subclass != 0 35 || fDeviceDescriptor.device_protocol != 0) { 36 TRACE(("USB Hub: wrong class/subclass/protocol! Bailing out\n")); 37 return; 38 } 39 40 if (fCurrentConfiguration->number_interfaces > 1) { 41 TRACE(("USB Hub: too many interfaces\n")); 42 return; 43 } 44 45 size_t actualLength; 46 if (GetDescriptor(USB_DESCRIPTOR_INTERFACE, 0, (void *)&fInterruptInterface, 47 sizeof(usb_interface_descriptor)) != sizeof(usb_interface_descriptor)) { 48 TRACE(("USB Hub: error getting the interrupt interface\n")); 49 return; 50 } 51 52 if (fInterruptInterface.num_endpoints > 1) { 53 TRACE(("USB Hub: too many endpoints\n")); 54 return; 55 } 56 57 if (GetDescriptor(USB_DESCRIPTOR_ENDPOINT, 0, (void *)&fInterruptEndpoint, 58 sizeof(usb_endpoint_descriptor)) != sizeof(usb_endpoint_descriptor)) { 59 TRACE(("USB Hub: Error getting the endpoint\n")); 60 return; 61 } 62 63 if (fInterruptEndpoint.attributes != 0x03) { // interrupt transfer 64 TRACE(("USB Hub: Not an interrupt endpoint\n")); 65 return; 66 } 67 68 TRACE(("USB Hub: Getting hub descriptor...\n")); 69 if (GetDescriptor(USB_DESCRIPTOR_HUB, 0, (void *)&fHubDescriptor, 70 sizeof(usb_hub_descriptor)) != sizeof(usb_hub_descriptor)) { 71 TRACE(("USB Hub: Error getting hub descriptor\n")); 72 return; 73 } 74 75 // Enable port power on all ports 76 for (int32 i = 0; i < fHubDescriptor.bNbrPorts; i++) { 77 fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, 78 USB_REQUEST_SET_FEATURE, 79 PORT_POWER, 80 i + 1, 81 0, 82 NULL, 83 0, 84 &actualLength); 85 } 86 87 // Wait for power to stabilize 88 snooze(fHubDescriptor.bPwrOn2PwrGood * 2); 89 90 fInitOK = true; 91 TRACE(("USB Hub: initialised ok\n")); 92 } 93 94 95 void 96 Hub::Explore() 97 { 98 for (int32 i = 0; i < fHubDescriptor.bNbrPorts; i++) { 99 size_t actualLength; 100 101 // Get the current port status 102 fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN, 103 USB_REQUEST_GET_STATUS, 104 0, 105 i + 1, 106 4, 107 (void *)&fPortStatus[i], 108 4, 109 &actualLength); 110 111 if (actualLength < 4) { 112 TRACE(("USB Hub: error getting port status\n")); 113 return; 114 } 115 116 //TRACE(("status: 0x%04x; change: 0x%04x\n", fPortStatus[i].status, fPortStatus[i].change)); 117 118 // We need to test the port change against a number of things 119 if (fPortStatus[i].status & PORT_RESET) { 120 fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, 121 USB_REQUEST_CLEAR_FEATURE, 122 PORT_RESET, 123 i + 1, 124 0, 125 NULL, 126 0, 127 &actualLength); 128 } 129 130 if (fPortStatus[i].change & PORT_STATUS_CONNECTION) { 131 if (fPortStatus[i].status & PORT_STATUS_CONNECTION) { 132 // New device attached! 133 134 if ((fPortStatus[i].status & PORT_STATUS_ENABLE) == 0) { 135 // enable the port if it isn't 136 fDefaultPipe->SendRequest( 137 USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, 138 USB_REQUEST_SET_FEATURE, 139 PORT_ENABLE, 140 i + 1, 141 0, 142 NULL, 143 0, 144 NULL); 145 } 146 147 TRACE(("USB Hub: Explore(): New device connected\n")); 148 149 Device *newDevice; 150 if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED) 151 newDevice = fBus->AllocateNewDevice(this, true); 152 else 153 newDevice = fBus->AllocateNewDevice(this, false); 154 155 if (newDevice) 156 fChildren[i] = newDevice; 157 } else { 158 // Device removed... 159 // ToDo: do something 160 TRACE(("USB Hub Explore(): Device removed\n")); 161 } 162 163 // Clear status change 164 fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, 165 USB_REQUEST_CLEAR_FEATURE, 166 C_PORT_CONNECTION, 167 i + 1, 168 0, 169 NULL, 170 0, 171 NULL); 172 } 173 } 174 } 175