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
BusManager(Stack * stack,device_node * node)13 BusManager::BusManager(Stack *stack, device_node* node)
14 : fInitOK(false),
15 fStack(stack),
16 fRootHub(NULL),
17 fStackIndex((uint32)-1),
18 fNode(node)
19 {
20 mutex_init(&fLock, "usb busmanager lock");
21
22 fRootObject = new(std::nothrow) Object(stack, this);
23 if (!fRootObject)
24 return;
25
26 // Clear the device map
27 for (int32 i = 0; i < 128; i++)
28 fDeviceMap[i] = false;
29 fDeviceIndex = 0;
30
31 // Set the default pipes to NULL (these will be created when needed)
32 for (int32 i = 0; i <= USB_SPEED_MAX; i++)
33 fDefaultPipes[i] = NULL;
34
35 fInitOK = true;
36 }
37
38
~BusManager()39 BusManager::~BusManager()
40 {
41 Lock();
42 mutex_destroy(&fLock);
43 for (int32 i = 0; i <= USB_SPEED_MAX; i++)
44 delete fDefaultPipes[i];
45 delete fRootObject;
46 }
47
48
49 status_t
InitCheck()50 BusManager::InitCheck()
51 {
52 if (fInitOK)
53 return B_OK;
54
55 return B_ERROR;
56 }
57
58
59 bool
Lock()60 BusManager::Lock()
61 {
62 return (mutex_lock(&fLock) == B_OK);
63 }
64
65
66 void
Unlock()67 BusManager::Unlock()
68 {
69 mutex_unlock(&fLock);
70 }
71
72
73 int8
AllocateAddress()74 BusManager::AllocateAddress()
75 {
76 if (!Lock())
77 return -1;
78
79 int8 tries = 127;
80 int8 address = fDeviceIndex;
81 while (tries-- > 0) {
82 if (fDeviceMap[address] == false) {
83 fDeviceIndex = (address + 1) % 127;
84 fDeviceMap[address] = true;
85 Unlock();
86 return address + 1;
87 }
88
89 address = (address + 1) % 127;
90 }
91
92 TRACE_ERROR("the busmanager has run out of device addresses\n");
93 Unlock();
94 return -1;
95 }
96
97
98 void
FreeAddress(int8 address)99 BusManager::FreeAddress(int8 address)
100 {
101 address--;
102 if (address < 0)
103 return;
104
105 if (!Lock())
106 return;
107
108 if (!fDeviceMap[address]) {
109 TRACE_ERROR("freeing address %d which was not allocated\n", address);
110 }
111
112 fDeviceMap[address] = false;
113 Unlock();
114 }
115
116
117 Device *
AllocateDevice(Hub * parent,int8 hubAddress,uint8 hubPort,usb_speed speed)118 BusManager::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
119 usb_speed speed)
120 {
121 // Check if there is a free entry in the device map (for the device number)
122 int8 deviceAddress = AllocateAddress();
123 if (deviceAddress < 0) {
124 TRACE_ERROR("could not allocate an address\n");
125 return NULL;
126 }
127
128 TRACE("setting device address to %d\n", deviceAddress);
129 ControlPipe *defaultPipe = _GetDefaultPipe(speed);
130
131 if (!defaultPipe) {
132 TRACE_ERROR("error getting the default pipe for speed %d\n", speed);
133 FreeAddress(deviceAddress);
134 return NULL;
135 }
136
137 defaultPipe->SetHubInfo(hubAddress, hubPort);
138
139 status_t result = B_ERROR;
140 for (int32 i = 0; i < 3; i++) {
141 // Set the address of the device USB 1.1 spec p202
142 result = defaultPipe->SendRequest(
143 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, // type
144 USB_REQUEST_SET_ADDRESS, // request
145 deviceAddress, // value
146 0, // index
147 0, // length
148 NULL, // buffer
149 0, // buffer length
150 NULL); // actual length
151
152 if (result >= B_OK)
153 break;
154
155 snooze(USB_DELAY_SET_ADDRESS_RETRY);
156 }
157
158 if (result < B_OK) {
159 TRACE_ERROR("error while setting device address\n");
160 FreeAddress(deviceAddress);
161 return NULL;
162 }
163
164 // Wait a bit for the device to complete addressing
165 snooze(USB_DELAY_SET_ADDRESS);
166
167 // Create a temporary pipe with the new address
168 ControlPipe pipe(fRootObject);
169 pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0, hubAddress,
170 hubPort);
171
172 // Get the device descriptor
173 // Just retrieve the first 8 bytes of the descriptor -> minimum supported
174 // size of any device. It is enough because it includes the device type.
175
176 size_t actualLength = 0;
177 usb_device_descriptor deviceDescriptor;
178
179 TRACE("getting the device descriptor\n");
180 pipe.SendRequest(
181 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
182 USB_REQUEST_GET_DESCRIPTOR, // request
183 USB_DESCRIPTOR_DEVICE << 8, // value
184 0, // index
185 8, // length
186 (void *)&deviceDescriptor, // buffer
187 8, // buffer length
188 &actualLength); // actual length
189
190 if (actualLength != 8) {
191 TRACE_ERROR("error while getting the device descriptor\n");
192 FreeAddress(deviceAddress);
193 return NULL;
194 }
195
196 TRACE("short device descriptor for device %d:\n", deviceAddress);
197 TRACE("\tlength:..............%d\n", deviceDescriptor.length);
198 TRACE("\tdescriptor_type:.....0x%04x\n", deviceDescriptor.descriptor_type);
199 TRACE("\tusb_version:.........0x%04x\n", deviceDescriptor.usb_version);
200 TRACE("\tdevice_class:........0x%02x\n", deviceDescriptor.device_class);
201 TRACE("\tdevice_subclass:.....0x%02x\n", deviceDescriptor.device_subclass);
202 TRACE("\tdevice_protocol:.....0x%02x\n", deviceDescriptor.device_protocol);
203 TRACE("\tmax_packet_size_0:...%d\n", deviceDescriptor.max_packet_size_0);
204
205 // Create a new instance based on the type (Hub or Device)
206 if (deviceDescriptor.device_class == 0x09) {
207 TRACE("creating new hub\n");
208 Hub *hub = new(std::nothrow) Hub(parent, hubAddress, hubPort,
209 deviceDescriptor, deviceAddress, speed, false);
210 if (!hub) {
211 TRACE_ERROR("no memory to allocate hub\n");
212 FreeAddress(deviceAddress);
213 return NULL;
214 }
215
216 if (hub->InitCheck() < B_OK) {
217 TRACE_ERROR("hub failed init check\n");
218 FreeAddress(deviceAddress);
219 delete hub;
220 return NULL;
221 }
222
223 hub->RegisterNode();
224
225 return (Device *)hub;
226 }
227
228 TRACE("creating new device\n");
229 Device *device = new(std::nothrow) Device(parent, hubAddress, hubPort,
230 deviceDescriptor, deviceAddress, speed, false);
231 if (!device) {
232 TRACE_ERROR("no memory to allocate device\n");
233 FreeAddress(deviceAddress);
234 return NULL;
235 }
236
237 if (device->InitCheck() < B_OK) {
238 TRACE_ERROR("device failed init check\n");
239 FreeAddress(deviceAddress);
240 delete device;
241 return NULL;
242 }
243
244 device->RegisterNode();
245
246 return device;
247 }
248
249
250 void
FreeDevice(Device * device)251 BusManager::FreeDevice(Device *device)
252 {
253 FreeAddress(device->DeviceAddress());
254 delete device;
255 }
256
257
258 status_t
Start()259 BusManager::Start()
260 {
261 fStack->AddBusManager(this);
262 fStackIndex = fStack->IndexOfBusManager(this);
263 fStack->Explore();
264 return B_OK;
265 }
266
267
268 status_t
Stop()269 BusManager::Stop()
270 {
271 return B_OK;
272 }
273
274
275 status_t
StartDebugTransfer(Transfer * transfer)276 BusManager::StartDebugTransfer(Transfer *transfer)
277 {
278 // virtual function to be overridden
279 return B_UNSUPPORTED;
280 }
281
282
283 status_t
CheckDebugTransfer(Transfer * transfer)284 BusManager::CheckDebugTransfer(Transfer *transfer)
285 {
286 // virtual function to be overridden
287 return B_UNSUPPORTED;
288 }
289
290
291 void
CancelDebugTransfer(Transfer * transfer)292 BusManager::CancelDebugTransfer(Transfer *transfer)
293 {
294 // virtual function to be overridden
295 }
296
297
298 status_t
SubmitTransfer(Transfer * transfer)299 BusManager::SubmitTransfer(Transfer *transfer)
300 {
301 // virtual function to be overridden
302 return B_ERROR;
303 }
304
305
306 status_t
CancelQueuedTransfers(Pipe * pipe,bool force)307 BusManager::CancelQueuedTransfers(Pipe *pipe, bool force)
308 {
309 // virtual function to be overridden
310 return B_ERROR;
311 }
312
313
314 status_t
NotifyPipeChange(Pipe * pipe,usb_change change)315 BusManager::NotifyPipeChange(Pipe *pipe, usb_change change)
316 {
317 // virtual function to be overridden
318 return B_ERROR;
319 }
320
321
322 ControlPipe *
_GetDefaultPipe(usb_speed speed)323 BusManager::_GetDefaultPipe(usb_speed speed)
324 {
325 if (!Lock())
326 return NULL;
327
328 if (fDefaultPipes[speed] == NULL) {
329 fDefaultPipes[speed] = new(std::nothrow) ControlPipe(fRootObject);
330 fDefaultPipes[speed]->InitCommon(0, 0, speed, Pipe::Default, 8, 0, 0, 0);
331 }
332
333 if (!fDefaultPipes[speed]) {
334 TRACE_ERROR("failed to allocate default pipe for speed %d\n", speed);
335 }
336
337 Unlock();
338 return fDefaultPipes[speed];
339 }
340
341