xref: /haiku/src/add-ons/kernel/bus_managers/usb/BusManager.cpp (revision cd552c7a15cc10c36dae8d7439ba1d6c0bb168c5)
1 /*
2  * Copyright 2003-2006, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Niels S. Reedijk
7  */
8 
9 #include "usb_p.h"
10 
11 
12 #define TRACE_BUSMANAGER
13 #ifdef TRACE_BUSMANAGER
14 #define TRACE(x)	dprintf x
15 #else
16 #define TRACE(x)	/* nothing */
17 #endif
18 
19 
20 BusManager::BusManager()
21 {
22 	fInitOK = false;
23 	fRootHub = NULL;
24 
25 	// Set up the semaphore
26 	fLock = create_sem(1, "bus manager lock");
27 	if (fLock < B_OK)
28 		return;
29 
30 	set_sem_owner(B_SYSTEM_TEAM, fLock);
31 
32 	// Clear the device map
33 	for (int32 i = 0; i < 128; i++)
34 		fDeviceMap[i] = false;
35 
36 	// Set up the default pipes
37 	fDefaultPipe = new ControlPipe(this, 0, Pipe::Default, Pipe::NormalSpeed,
38 		0, 8);
39 	fDefaultPipeLowSpeed = new ControlPipe(this, 0, Pipe::Default,
40 		Pipe::LowSpeed, 0, 8);
41 
42 	fExploreThread = -1;
43 	fInitOK = true;
44 }
45 
46 
47 BusManager::~BusManager()
48 {
49 }
50 
51 
52 status_t
53 BusManager::InitCheck()
54 {
55 	if (fInitOK)
56 		return B_OK;
57 
58 	return B_ERROR;
59 }
60 
61 
62 /*
63 	This is the 'main' function of the explore thread, which keeps track of
64 	the hub states.
65 */
66 int32
67 BusManager::ExploreThread(void *data)
68 {
69 	Hub *rootHub = (Hub *)data;
70 	if (!rootHub)
71 		return B_ERROR;
72 
73 	snooze(3000000);
74 	while (true) {
75 		rootHub->Explore();
76 		snooze(1000000);
77 	}
78 
79 	return B_OK;
80 }
81 
82 
83 Device *
84 BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
85 {
86 	// Check if there is a free entry in the device map (for the device number)
87 	int8 deviceAddress = AllocateAddress();
88 	if (deviceAddress < 0) {
89 		TRACE(("usb BusManager::AllocateNewDevice(): could not get a new address\n"));
90 		return NULL;
91 	}
92 
93 	TRACE(("usb BusManager::AllocateNewDevice(): setting device address to %d\n", deviceAddress));
94 
95 	ControlPipe *defaultPipe = (lowSpeed ? fDefaultPipeLowSpeed : fDefaultPipe);
96 
97 	// Set the address of the device USB 1.1 spec p202
98 	status_t result = defaultPipe->SendRequest(
99 		USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,		// type
100 		USB_REQUEST_SET_ADDRESS,							// request
101 		deviceAddress,										// value
102 		0,													// index
103 		0,													// length
104 		NULL,												// buffer
105 		0,													// buffer length
106 		NULL);												// actual length
107 
108 	if (result < B_OK) {
109 		TRACE(("usb BusManager::AllocateNewDevice(): error while setting device address\n"));
110 		return NULL;
111 	}
112 
113 	// Wait a bit for the device to complete addressing
114 	snooze(10000);
115 
116 	// Create a temporary pipe with the new address
117 	ControlPipe pipe(this, deviceAddress, Pipe::Default,
118 		lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 0, 8);
119 
120 	// Get the device descriptor
121 	// Just retrieve the first 8 bytes of the descriptor -> minimum supported
122 	// size of any device. It is enough because it includes the device type.
123 
124 	size_t actualLength = 0;
125 	usb_device_descriptor deviceDescriptor;
126 
127 	TRACE(("usb BusManager::AllocateNewDevice(): getting the device descriptor\n"));
128 	pipe.SendRequest(
129 		USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,		// type
130 		USB_REQUEST_GET_DESCRIPTOR,							// request
131 		USB_DESCRIPTOR_DEVICE << 8,							// value
132 		0,													// index
133 		8,													// length
134 		(void *)&deviceDescriptor,							// buffer
135 		8,													// buffer length
136 		&actualLength);										// actual length
137 
138 	if (actualLength != 8) {
139 		TRACE(("usb BusManager::AllocateNewDevice(): error while getting the device descriptor\n"));
140 		return NULL;
141 	}
142 
143 	TRACE(("short device descriptor for device %d:\n", deviceAddress));
144 	TRACE(("\tlength:..............%d\n", deviceDescriptor.length));
145 	TRACE(("\tdescriptor_type:.....0x%04x\n", deviceDescriptor.descriptor_type));
146 	TRACE(("\tusb_version:.........0x%04x\n", deviceDescriptor.usb_version));
147 	TRACE(("\tdevice_class:........0x%02x\n", deviceDescriptor.device_class));
148 	TRACE(("\tdevice_subclass:.....0x%02x\n", deviceDescriptor.device_subclass));
149 	TRACE(("\tdevice_protocol:.....0x%02x\n", deviceDescriptor.device_protocol));
150 	TRACE(("\tmax_packet_size_0:...%d\n", deviceDescriptor.max_packet_size_0));
151 
152 	// Create a new instance based on the type (Hub or Device)
153 	if (deviceDescriptor.device_class == 0x09) {
154 		TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n"));
155 		Device *ret = new Hub(this, parent, deviceDescriptor, deviceAddress,
156 			lowSpeed);
157 
158 		if (parent == NULL) {
159 			// root hub
160 			fRootHub = ret;
161 		}
162 
163 		return ret;
164 	}
165 
166 	TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n"));
167 	return new Device(this, parent, deviceDescriptor, deviceAddress, lowSpeed);
168 }
169 
170 
171 int8
172 BusManager::AllocateAddress()
173 {
174 	acquire_sem_etc(fLock, 1, B_CAN_INTERRUPT, 0);
175 
176 	int8 deviceAddress = -1;
177 	for (int32 i = 1; i < 128; i++) {
178 		if (fDeviceMap[i] == false) {
179 			deviceAddress = i;
180 			fDeviceMap[i] = true;
181 			break;
182 		}
183 	}
184 
185 	release_sem(fLock);
186 	return deviceAddress;
187 }
188 
189 
190 status_t
191 BusManager::Start()
192 {
193 	TRACE(("usb BusManager::Start()\n"));
194 	if (InitCheck() != B_OK)
195 		return InitCheck();
196 
197 	if (fExploreThread < 0) {
198 		fExploreThread = spawn_kernel_thread(ExploreThread,
199 			"usb busmanager explore", B_LOW_PRIORITY, (void *)fRootHub);
200 	}
201 
202 	return resume_thread(fExploreThread);
203 }
204 
205 
206 status_t
207 BusManager::Stop()
208 {
209 	// ToDo: implement (should end the explore thread)
210 	return B_OK;
211 }
212 
213 
214 status_t
215 BusManager::SubmitTransfer(Transfer *transfer, bigtime_t timeout)
216 {
217 	// virtual function to be overridden
218 	return B_ERROR;
219 }
220