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