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_BUSMANAGER 13 #ifdef TRACE_BUSMANAGER 14 #define TRACE(x) dprintf x 15 #else 16 #define TRACE(x) /* nothing */ 17 #endif 18 19 20 BusManager::BusManager() 21 { 22 fInitOK = false; 23 fRootHub = NULL; 24 25 // Set up the semaphore 26 fLock = create_sem(1, "bus manager lock"); 27 if (fLock < B_OK) 28 return; 29 30 set_sem_owner(B_SYSTEM_TEAM, fLock); 31 32 // Clear the device map 33 for (int32 i = 0; i < 128; i++) 34 fDeviceMap[i] = false; 35 36 // Set up the default pipes 37 fDefaultPipe = new ControlPipe(this, 0, Pipe::Default, Pipe::NormalSpeed, 38 0, 8); 39 fDefaultPipeLowSpeed = new ControlPipe(this, 0, Pipe::Default, 40 Pipe::LowSpeed, 0, 8); 41 42 fExploreThread = -1; 43 fInitOK = true; 44 } 45 46 47 BusManager::~BusManager() 48 { 49 } 50 51 52 status_t 53 BusManager::InitCheck() 54 { 55 if (fInitOK) 56 return B_OK; 57 58 return B_ERROR; 59 } 60 61 62 /* 63 This is the 'main' function of the explore thread, which keeps track of 64 the hub states. 65 */ 66 int32 67 BusManager::ExploreThread(void *data) 68 { 69 Hub *rootHub = (Hub *)data; 70 if (!rootHub) 71 return B_ERROR; 72 73 snooze(3000000); 74 while (true) { 75 rootHub->Explore(); 76 snooze(1000000); 77 } 78 79 return B_OK; 80 } 81 82 83 Device * 84 BusManager::AllocateNewDevice(Device *parent, bool lowSpeed) 85 { 86 // Check if there is a free entry in the device map (for the device number) 87 int8 deviceAddress = AllocateAddress(); 88 if (deviceAddress < 0) { 89 TRACE(("usb BusManager::AllocateNewDevice(): could not get a new address\n")); 90 return NULL; 91 } 92 93 TRACE(("usb BusManager::AllocateNewDevice(): setting device address to %d\n", deviceAddress)); 94 95 ControlPipe *defaultPipe = (lowSpeed ? fDefaultPipeLowSpeed : fDefaultPipe); 96 97 // Set the address of the device USB 1.1 spec p202 98 status_t result = defaultPipe->SendRequest( 99 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type 100 USB_REQUEST_SET_ADDRESS, // request 101 deviceAddress, // value 102 0, // index 103 0, // length 104 NULL, // buffer 105 0, // buffer length 106 NULL); // actual length 107 108 if (result < B_OK) { 109 TRACE(("usb BusManager::AllocateNewDevice(): error while setting device address\n")); 110 return NULL; 111 } 112 113 // Wait a bit for the device to complete addressing 114 snooze(10000); 115 116 // Create a temporary pipe with the new address 117 ControlPipe pipe(this, deviceAddress, Pipe::Default, 118 lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 0, 8); 119 120 // Get the device descriptor 121 // Just retrieve the first 8 bytes of the descriptor -> minimum supported 122 // size of any device. It is enough because it includes the device type. 123 124 size_t actualLength = 0; 125 usb_device_descriptor deviceDescriptor; 126 127 TRACE(("usb BusManager::AllocateNewDevice(): getting the device descriptor\n")); 128 pipe.SendRequest( 129 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type 130 USB_REQUEST_GET_DESCRIPTOR, // request 131 USB_DESCRIPTOR_DEVICE << 8, // value 132 0, // index 133 8, // length 134 (void *)&deviceDescriptor, // buffer 135 8, // buffer length 136 &actualLength); // actual length 137 138 if (actualLength != 8) { 139 TRACE(("usb BusManager::AllocateNewDevice(): error while getting the device descriptor\n")); 140 return NULL; 141 } 142 143 TRACE(("short device descriptor for device %d:\n", deviceAddress)); 144 TRACE(("\tlength:..............%d\n", deviceDescriptor.length)); 145 TRACE(("\tdescriptor_type:.....0x%04x\n", deviceDescriptor.descriptor_type)); 146 TRACE(("\tusb_version:.........0x%04x\n", deviceDescriptor.usb_version)); 147 TRACE(("\tdevice_class:........0x%02x\n", deviceDescriptor.device_class)); 148 TRACE(("\tdevice_subclass:.....0x%02x\n", deviceDescriptor.device_subclass)); 149 TRACE(("\tdevice_protocol:.....0x%02x\n", deviceDescriptor.device_protocol)); 150 TRACE(("\tmax_packet_size_0:...%d\n", deviceDescriptor.max_packet_size_0)); 151 152 // Create a new instance based on the type (Hub or Device) 153 if (deviceDescriptor.device_class == 0x09) { 154 TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n")); 155 Device *ret = new Hub(this, parent, deviceDescriptor, deviceAddress, 156 lowSpeed); 157 158 if (parent == NULL) { 159 // root hub 160 fRootHub = ret; 161 } 162 163 return ret; 164 } 165 166 TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n")); 167 return new Device(this, parent, deviceDescriptor, deviceAddress, lowSpeed); 168 } 169 170 171 int8 172 BusManager::AllocateAddress() 173 { 174 acquire_sem_etc(fLock, 1, B_CAN_INTERRUPT, 0); 175 176 int8 deviceAddress = -1; 177 for (int32 i = 1; i < 128; i++) { 178 if (fDeviceMap[i] == false) { 179 deviceAddress = i; 180 fDeviceMap[i] = true; 181 break; 182 } 183 } 184 185 release_sem(fLock); 186 return deviceAddress; 187 } 188 189 190 status_t 191 BusManager::Start() 192 { 193 TRACE(("usb BusManager::Start()\n")); 194 if (InitCheck() != B_OK) 195 return InitCheck(); 196 197 if (fExploreThread < 0) { 198 fExploreThread = spawn_kernel_thread(ExploreThread, 199 "usb busmanager explore", B_LOW_PRIORITY, (void *)fRootHub); 200 } 201 202 return resume_thread(fExploreThread); 203 } 204 205 206 status_t 207 BusManager::Stop() 208 { 209 // ToDo: implement (should end the explore thread) 210 return B_OK; 211 } 212 213 214 status_t 215 BusManager::SubmitTransfer(Transfer *transfer, bigtime_t timeout) 216 { 217 // virtual function to be overridden 218 return B_ERROR; 219 } 220