xref: /haiku/src/add-ons/kernel/bus_managers/usb/BusManager.cpp (revision 7c18d58f2bdd1fd241d1a8841e3312e5fbc3a764)
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 
BusManager(Stack * stack,device_node * node)13 BusManager::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 
~BusManager()39 BusManager::~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 
49 status_t
InitCheck()50 BusManager::InitCheck()
51 {
52 	if (fInitOK)
53 		return B_OK;
54 
55 	return B_ERROR;
56 }
57 
58 
59 bool
Lock()60 BusManager::Lock()
61 {
62 	return (mutex_lock(&fLock) == B_OK);
63 }
64 
65 
66 void
Unlock()67 BusManager::Unlock()
68 {
69 	mutex_unlock(&fLock);
70 }
71 
72 
73 int8
AllocateAddress()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("the busmanager has run out of device addresses\n");
93 	Unlock();
94 	return -1;
95 }
96 
97 
98 void
FreeAddress(int8 address)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("freeing address %d which was not allocated\n", address);
110 	}
111 
112 	fDeviceMap[address] = false;
113 	Unlock();
114 }
115 
116 
117 Device *
AllocateDevice(Hub * parent,int8 hubAddress,uint8 hubPort,usb_speed speed)118 BusManager::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 
250 void
FreeDevice(Device * device)251 BusManager::FreeDevice(Device *device)
252 {
253 	FreeAddress(device->DeviceAddress());
254 	delete device;
255 }
256 
257 
258 status_t
Start()259 BusManager::Start()
260 {
261 	fStack->AddBusManager(this);
262 	fStackIndex = fStack->IndexOfBusManager(this);
263 	fStack->Explore();
264 	return B_OK;
265 }
266 
267 
268 status_t
Stop()269 BusManager::Stop()
270 {
271 	return B_OK;
272 }
273 
274 
275 status_t
StartDebugTransfer(Transfer * transfer)276 BusManager::StartDebugTransfer(Transfer *transfer)
277 {
278 	// virtual function to be overridden
279 	return B_UNSUPPORTED;
280 }
281 
282 
283 status_t
CheckDebugTransfer(Transfer * transfer)284 BusManager::CheckDebugTransfer(Transfer *transfer)
285 {
286 	// virtual function to be overridden
287 	return B_UNSUPPORTED;
288 }
289 
290 
291 void
CancelDebugTransfer(Transfer * transfer)292 BusManager::CancelDebugTransfer(Transfer *transfer)
293 {
294 	// virtual function to be overridden
295 }
296 
297 
298 status_t
SubmitTransfer(Transfer * transfer)299 BusManager::SubmitTransfer(Transfer *transfer)
300 {
301 	// virtual function to be overridden
302 	return B_ERROR;
303 }
304 
305 
306 status_t
CancelQueuedTransfers(Pipe * pipe,bool force)307 BusManager::CancelQueuedTransfers(Pipe *pipe, bool force)
308 {
309 	// virtual function to be overridden
310 	return B_ERROR;
311 }
312 
313 
314 status_t
NotifyPipeChange(Pipe * pipe,usb_change change)315 BusManager::NotifyPipeChange(Pipe *pipe, usb_change change)
316 {
317 	// virtual function to be overridden
318 	return B_ERROR;
319 }
320 
321 
322 ControlPipe *
_GetDefaultPipe(usb_speed speed)323 BusManager::_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