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
13BusManager::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
39BusManager::~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
49status_t
50BusManager::InitCheck()
51{
52	if (fInitOK)
53		return B_OK;
54
55	return B_ERROR;
56}
57
58
59bool
60BusManager::Lock()
61{
62	return (mutex_lock(&fLock) == B_OK);
63}
64
65
66void
67BusManager::Unlock()
68{
69	mutex_unlock(&fLock);
70}
71
72
73int8
74BusManager::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
98void
99BusManager::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
117Device *
118BusManager::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
250void
251BusManager::FreeDevice(Device *device)
252{
253	FreeAddress(device->DeviceAddress());
254	delete device;
255}
256
257
258status_t
259BusManager::Start()
260{
261	fStack->AddBusManager(this);
262	fStackIndex = fStack->IndexOfBusManager(this);
263	fStack->Explore();
264	return B_OK;
265}
266
267
268status_t
269BusManager::Stop()
270{
271	return B_OK;
272}
273
274
275status_t
276BusManager::StartDebugTransfer(Transfer *transfer)
277{
278	// virtual function to be overridden
279	return B_UNSUPPORTED;
280}
281
282
283status_t
284BusManager::CheckDebugTransfer(Transfer *transfer)
285{
286	// virtual function to be overridden
287	return B_UNSUPPORTED;
288}
289
290
291void
292BusManager::CancelDebugTransfer(Transfer *transfer)
293{
294	// virtual function to be overridden
295}
296
297
298status_t
299BusManager::SubmitTransfer(Transfer *transfer)
300{
301	// virtual function to be overridden
302	return B_ERROR;
303}
304
305
306status_t
307BusManager::CancelQueuedTransfers(Pipe *pipe, bool force)
308{
309	// virtual function to be overridden
310	return B_ERROR;
311}
312
313
314status_t
315BusManager::NotifyPipeChange(Pipe *pipe, usb_change change)
316{
317	// virtual function to be overridden
318	return B_ERROR;
319}
320
321
322ControlPipe *
323BusManager::_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