xref: /haiku/src/add-ons/kernel/bus_managers/usb/BusManager.cpp (revision 652f187eee454506a61c85631eb5d8415f3e22d4)
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