xref: /haiku/src/add-ons/kernel/bus_managers/usb/BusManager.cpp (revision 93a78ecaa45114d68952d08c4778f073515102f2)
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_p.h"
11 
12 
13 BusManager::BusManager(Stack *stack)
14 	:	fInitOK(false),
15 		fRootHub(NULL)
16 {
17 	if (benaphore_init(&fLock, "usb busmanager lock") < B_OK) {
18 		TRACE_ERROR(("USB BusManager: failed to create busmanager lock\n"));
19 		return;
20 	}
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 
39 BusManager::~BusManager()
40 {
41 	Lock();
42 	benaphore_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
50 BusManager::InitCheck()
51 {
52 	if (fInitOK)
53 		return B_OK;
54 
55 	return B_ERROR;
56 }
57 
58 
59 bool
60 BusManager::Lock()
61 {
62 	return (benaphore_lock(&fLock) == B_OK);
63 }
64 
65 
66 void
67 BusManager::Unlock()
68 {
69 	benaphore_unlock(&fLock);
70 }
71 
72 
73 int8
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(("USB BusManager: the busmanager has run out of device addresses\n"));
93 	Unlock();
94 	return -1;
95 }
96 
97 
98 void
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(("USB BusManager: freeing address %d which was not allocated\n", address));
110 	}
111 
112 	fDeviceMap[address] = false;
113 	Unlock();
114 }
115 
116 
117 Device *
118 BusManager::AllocateDevice(Hub *parent, usb_speed speed)
119 {
120 	// Check if there is a free entry in the device map (for the device number)
121 	int8 deviceAddress = AllocateAddress();
122 	if (deviceAddress < 0) {
123 		TRACE_ERROR(("USB BusManager: could not allocate an address\n"));
124 		return NULL;
125 	}
126 
127 	TRACE(("USB BusManager: setting device address to %d\n", deviceAddress));
128 	ControlPipe *defaultPipe = _GetDefaultPipe(speed);
129 
130 	if (!defaultPipe) {
131 		TRACE_ERROR(("USB BusManager: error getting the default pipe for speed %d\n", (int)speed));
132 		FreeAddress(deviceAddress);
133 		return NULL;
134 	}
135 
136 	status_t result = B_ERROR;
137 	for (int32 i = 0; i < 15; i++) {
138 		// Set the address of the device USB 1.1 spec p202
139 		result = defaultPipe->SendRequest(
140 			USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,	// type
141 			USB_REQUEST_SET_ADDRESS,						// request
142 			deviceAddress,									// value
143 			0,												// index
144 			0,												// length
145 			NULL,											// buffer
146 			0,												// buffer length
147 			NULL);											// actual length
148 
149 		if (result >= B_OK)
150 			break;
151 
152 		snooze(USB_DELAY_SET_ADDRESS_RETRY);
153 	}
154 
155 	if (result < B_OK) {
156 		TRACE_ERROR(("USB BusManager: error while setting device address\n"));
157 		FreeAddress(deviceAddress);
158 		return NULL;
159 	}
160 
161 	// Wait a bit for the device to complete addressing
162 	snooze(USB_DELAY_SET_ADDRESS);
163 
164 	// Create a temporary pipe with the new address
165 	ControlPipe pipe(parent, deviceAddress, 0, speed, 8);
166 
167 	// Get the device descriptor
168 	// Just retrieve the first 8 bytes of the descriptor -> minimum supported
169 	// size of any device. It is enough because it includes the device type.
170 
171 	size_t actualLength = 0;
172 	usb_device_descriptor deviceDescriptor;
173 
174 	TRACE(("USB BusManager: getting the device descriptor\n"));
175 	pipe.SendRequest(
176 		USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,		// type
177 		USB_REQUEST_GET_DESCRIPTOR,							// request
178 		USB_DESCRIPTOR_DEVICE << 8,							// value
179 		0,													// index
180 		8,													// length
181 		(void *)&deviceDescriptor,							// buffer
182 		8,													// buffer length
183 		&actualLength);										// actual length
184 
185 	if (actualLength != 8) {
186 		TRACE_ERROR(("USB BusManager: error while getting the device descriptor\n"));
187 		FreeAddress(deviceAddress);
188 		return NULL;
189 	}
190 
191 	TRACE(("short device descriptor for device %d:\n", deviceAddress));
192 	TRACE(("\tlength:..............%d\n", deviceDescriptor.length));
193 	TRACE(("\tdescriptor_type:.....0x%04x\n", deviceDescriptor.descriptor_type));
194 	TRACE(("\tusb_version:.........0x%04x\n", deviceDescriptor.usb_version));
195 	TRACE(("\tdevice_class:........0x%02x\n", deviceDescriptor.device_class));
196 	TRACE(("\tdevice_subclass:.....0x%02x\n", deviceDescriptor.device_subclass));
197 	TRACE(("\tdevice_protocol:.....0x%02x\n", deviceDescriptor.device_protocol));
198 	TRACE(("\tmax_packet_size_0:...%d\n", deviceDescriptor.max_packet_size_0));
199 
200 	// Create a new instance based on the type (Hub or Device)
201 	if (deviceDescriptor.device_class == 0x09) {
202 		TRACE(("USB BusManager: creating new hub\n"));
203 		Hub *hub = new(std::nothrow) Hub(parent, deviceDescriptor,
204 			deviceAddress, speed);
205 		if (!hub) {
206 			TRACE_ERROR(("USB BusManager: no memory to allocate hub\n"));
207 			FreeAddress(deviceAddress);
208 			return NULL;
209 		}
210 
211 		if (hub->InitCheck() < B_OK) {
212 			TRACE_ERROR(("USB BusManager: hub failed init check\n"));
213 			FreeAddress(deviceAddress);
214 			delete hub;
215 			return NULL;
216 		}
217 
218 		return (Device *)hub;
219 	}
220 
221 	TRACE(("USB BusManager: creating new device\n"));
222 	Device *device = new(std::nothrow) Device(parent, deviceDescriptor,
223 		deviceAddress, speed);
224 	if (!device) {
225 		TRACE_ERROR(("USB BusManager: no memory to allocate device\n"));
226 		FreeAddress(deviceAddress);
227 		return NULL;
228 	}
229 
230 	if (device->InitCheck() < B_OK) {
231 		TRACE_ERROR(("USB BusManager: device failed init check\n"));
232 		FreeAddress(deviceAddress);
233 		delete device;
234 		return NULL;
235 	}
236 
237 	return device;
238 }
239 
240 
241 void
242 BusManager::FreeDevice(Device *device)
243 {
244 	FreeAddress(device->DeviceAddress());
245 	delete device;
246 }
247 
248 
249 status_t
250 BusManager::Start()
251 {
252 	return B_OK;
253 }
254 
255 
256 status_t
257 BusManager::Stop()
258 {
259 	return B_OK;
260 }
261 
262 
263 status_t
264 BusManager::SubmitTransfer(Transfer *transfer)
265 {
266 	// virtual function to be overridden
267 	return B_ERROR;
268 }
269 
270 
271 status_t
272 BusManager::CancelQueuedTransfers(Pipe *pipe)
273 {
274 	// virtual function to be overridden
275 	return B_ERROR;
276 }
277 
278 
279 status_t
280 BusManager::NotifyPipeChange(Pipe *pipe, usb_change change)
281 {
282 	// virtual function to be overridden
283 	return B_ERROR;
284 }
285 
286 
287 ControlPipe *
288 BusManager::_GetDefaultPipe(usb_speed speed)
289 {
290 	if (!Lock())
291 		return NULL;
292 
293 	if (fDefaultPipes[speed] == NULL) {
294 		fDefaultPipes[speed] = new(std::nothrow) ControlPipe(fRootObject,
295 			0, 0, speed, 8);
296 	}
297 
298 	if (!fDefaultPipes[speed]) {
299 		TRACE_ERROR(("USB BusManager: failed to allocate default pipe for speed %d\n", speed));
300 	}
301 
302 	Unlock();
303 	return fDefaultPipes[speed];
304 }
305