xref: /haiku/src/add-ons/kernel/bus_managers/usb/BusManager.cpp (revision d2e1e872611179c9cfaa43ce11bd58b1e3554e4b)
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, uint8 port, 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 	defaultPipe->SetHubInfo(parent->DeviceAddress(), port);
130 
131 	if (!defaultPipe) {
132 		TRACE_ERROR(("USB BusManager: error getting the default pipe for speed %d\n", (int)speed));
133 		FreeAddress(deviceAddress);
134 		return NULL;
135 	}
136 
137 	status_t result = B_ERROR;
138 	for (int32 i = 0; i < 3; i++) {
139 		// Set the address of the device USB 1.1 spec p202
140 		result = defaultPipe->SendRequest(
141 			USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,	// type
142 			USB_REQUEST_SET_ADDRESS,						// request
143 			deviceAddress,									// value
144 			0,												// index
145 			0,												// length
146 			NULL,											// buffer
147 			0,												// buffer length
148 			NULL);											// actual length
149 
150 		if (result >= B_OK)
151 			break;
152 
153 		snooze(USB_DELAY_SET_ADDRESS_RETRY);
154 	}
155 
156 	if (result < B_OK) {
157 		TRACE_ERROR(("USB BusManager: error while setting device address\n"));
158 		FreeAddress(deviceAddress);
159 		return NULL;
160 	}
161 
162 	// Wait a bit for the device to complete addressing
163 	snooze(USB_DELAY_SET_ADDRESS);
164 
165 	// Create a temporary pipe with the new address
166 	ControlPipe pipe(fRootObject);
167 	pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0,
168 		parent->DeviceAddress(), port);
169 
170 	// Get the device descriptor
171 	// Just retrieve the first 8 bytes of the descriptor -> minimum supported
172 	// size of any device. It is enough because it includes the device type.
173 
174 	size_t actualLength = 0;
175 	usb_device_descriptor deviceDescriptor;
176 
177 	TRACE(("USB BusManager: getting the device descriptor\n"));
178 	pipe.SendRequest(
179 		USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,		// type
180 		USB_REQUEST_GET_DESCRIPTOR,							// request
181 		USB_DESCRIPTOR_DEVICE << 8,							// value
182 		0,													// index
183 		8,													// length
184 		(void *)&deviceDescriptor,							// buffer
185 		8,													// buffer length
186 		&actualLength);										// actual length
187 
188 	if (actualLength != 8) {
189 		TRACE_ERROR(("USB BusManager: error while getting the device descriptor\n"));
190 		FreeAddress(deviceAddress);
191 		return NULL;
192 	}
193 
194 	TRACE(("short device descriptor for device %d:\n", deviceAddress));
195 	TRACE(("\tlength:..............%d\n", deviceDescriptor.length));
196 	TRACE(("\tdescriptor_type:.....0x%04x\n", deviceDescriptor.descriptor_type));
197 	TRACE(("\tusb_version:.........0x%04x\n", deviceDescriptor.usb_version));
198 	TRACE(("\tdevice_class:........0x%02x\n", deviceDescriptor.device_class));
199 	TRACE(("\tdevice_subclass:.....0x%02x\n", deviceDescriptor.device_subclass));
200 	TRACE(("\tdevice_protocol:.....0x%02x\n", deviceDescriptor.device_protocol));
201 	TRACE(("\tmax_packet_size_0:...%d\n", deviceDescriptor.max_packet_size_0));
202 
203 	// Create a new instance based on the type (Hub or Device)
204 	if (deviceDescriptor.device_class == 0x09) {
205 		TRACE(("USB BusManager: creating new hub\n"));
206 		Hub *hub = new(std::nothrow) Hub(parent, port, deviceDescriptor,
207 			deviceAddress, speed, false);
208 		if (!hub) {
209 			TRACE_ERROR(("USB BusManager: no memory to allocate hub\n"));
210 			FreeAddress(deviceAddress);
211 			return NULL;
212 		}
213 
214 		if (hub->InitCheck() < B_OK) {
215 			TRACE_ERROR(("USB BusManager: hub failed init check\n"));
216 			FreeAddress(deviceAddress);
217 			delete hub;
218 			return NULL;
219 		}
220 
221 		return (Device *)hub;
222 	}
223 
224 	TRACE(("USB BusManager: creating new device\n"));
225 	Device *device = new(std::nothrow) Device(parent, port, deviceDescriptor,
226 		deviceAddress, speed, false);
227 	if (!device) {
228 		TRACE_ERROR(("USB BusManager: no memory to allocate device\n"));
229 		FreeAddress(deviceAddress);
230 		return NULL;
231 	}
232 
233 	if (device->InitCheck() < B_OK) {
234 		TRACE_ERROR(("USB BusManager: device failed init check\n"));
235 		FreeAddress(deviceAddress);
236 		delete device;
237 		return NULL;
238 	}
239 
240 	return device;
241 }
242 
243 
244 void
245 BusManager::FreeDevice(Device *device)
246 {
247 	FreeAddress(device->DeviceAddress());
248 	delete device;
249 }
250 
251 
252 status_t
253 BusManager::Start()
254 {
255 	return B_OK;
256 }
257 
258 
259 status_t
260 BusManager::Stop()
261 {
262 	return B_OK;
263 }
264 
265 
266 status_t
267 BusManager::SubmitTransfer(Transfer *transfer)
268 {
269 	// virtual function to be overridden
270 	return B_ERROR;
271 }
272 
273 
274 status_t
275 BusManager::CancelQueuedTransfers(Pipe *pipe, bool force)
276 {
277 	// virtual function to be overridden
278 	return B_ERROR;
279 }
280 
281 
282 status_t
283 BusManager::NotifyPipeChange(Pipe *pipe, usb_change change)
284 {
285 	// virtual function to be overridden
286 	return B_ERROR;
287 }
288 
289 
290 ControlPipe *
291 BusManager::_GetDefaultPipe(usb_speed speed)
292 {
293 	if (!Lock())
294 		return NULL;
295 
296 	if (fDefaultPipes[speed] == NULL) {
297 		fDefaultPipes[speed] = new(std::nothrow) ControlPipe(fRootObject);
298 		fDefaultPipes[speed]->InitCommon(0, 0, speed, Pipe::Default, 8, 0, 0, 0);
299 	}
300 
301 	if (!fDefaultPipes[speed]) {
302 		TRACE_ERROR(("USB BusManager: failed to allocate default pipe for speed %d\n", speed));
303 	}
304 
305 	Unlock();
306 	return fDefaultPipes[speed];
307 }
308