xref: /haiku/src/kits/device/USBDevice.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2007-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  */
8 
9 #include <USBKit.h>
10 #include <usb_raw.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <new>
15 
16 
17 BUSBDevice::BUSBDevice(const char *path)
18 	:	fPath(NULL),
19 		fRawFD(-1),
20 		fConfigurations(NULL),
21 		fActiveConfiguration(0),
22 		fManufacturerString(NULL),
23 		fProductString(NULL),
24 		fSerialNumberString(NULL)
25 {
26 	memset(&fDescriptor, 0, sizeof(fDescriptor));
27 
28 	if (path)
29 		SetTo(path);
30 }
31 
32 
33 BUSBDevice::~BUSBDevice()
34 {
35 	Unset();
36 }
37 
38 
39 status_t
40 BUSBDevice::InitCheck()
41 {
42 	return (fRawFD >= 0 ? B_OK : B_ERROR);
43 }
44 
45 
46 status_t
47 BUSBDevice::SetTo(const char *path)
48 {
49 	if (!path)
50 		return B_BAD_VALUE;
51 
52 	fPath = strdup(path);
53 	fRawFD = open(path, O_RDWR | O_CLOEXEC);
54 	if (fRawFD < 0) {
55 		Unset();
56 		return B_ERROR;
57 	}
58 
59 	usb_raw_command command;
60 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_VERSION, &command, sizeof(command))
61 		|| command.version.status != B_USB_RAW_PROTOCOL_VERSION) {
62 		Unset();
63 		return B_ERROR;
64 	}
65 
66 	command.device.descriptor = &fDescriptor;
67 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command,
68 		sizeof(command)) || command.device.status != B_USB_RAW_STATUS_SUCCESS) {
69 		Unset();
70 		return B_ERROR;
71 	}
72 
73 	fConfigurations = new(std::nothrow) BUSBConfiguration *[
74 		fDescriptor.num_configurations];
75 	if (fConfigurations == NULL)
76 		return B_NO_MEMORY;
77 
78 	for (uint32 i = 0; i < fDescriptor.num_configurations; i++) {
79 		fConfigurations[i] = new(std::nothrow) BUSBConfiguration(this, i,
80 			fRawFD);
81 	}
82 
83 	return B_OK;
84 }
85 
86 
87 void
88 BUSBDevice::Unset()
89 {
90 	if (fRawFD >= 0)
91 		close(fRawFD);
92 	fRawFD = -1;
93 
94 	free(fPath);
95 	fPath = NULL;
96 
97 	delete[] fManufacturerString;
98 	delete[] fProductString;
99 	delete[] fSerialNumberString;
100 	fManufacturerString = fProductString = fSerialNumberString = NULL;
101 
102 	if (fConfigurations != NULL) {
103 		for (int32 i = 0; i < fDescriptor.num_configurations; i++)
104 			delete fConfigurations[i];
105 
106 		delete[] fConfigurations;
107 		fConfigurations = NULL;
108 	}
109 
110 	memset(&fDescriptor, 0, sizeof(fDescriptor));
111 }
112 
113 
114 const char *
115 BUSBDevice::Location() const
116 {
117 	if (!fPath || strlen(fPath) < 12)
118 		return NULL;
119 
120 	return &fPath[12];
121 }
122 
123 
124 bool
125 BUSBDevice::IsHub() const
126 {
127 	return fDescriptor.device_class == 0x09;
128 }
129 
130 
131 uint16
132 BUSBDevice::USBVersion() const
133 {
134 	return fDescriptor.usb_version;
135 }
136 
137 
138 uint8
139 BUSBDevice::Class() const
140 {
141 	return fDescriptor.device_class;
142 }
143 
144 
145 uint8
146 BUSBDevice::Subclass() const
147 {
148 	return fDescriptor.device_subclass;
149 }
150 
151 
152 uint8
153 BUSBDevice::Protocol() const
154 {
155 	return fDescriptor.device_protocol;
156 }
157 
158 
159 uint8
160 BUSBDevice::MaxEndpoint0PacketSize() const
161 {
162 	return fDescriptor.max_packet_size_0;
163 }
164 
165 
166 uint16
167 BUSBDevice::VendorID() const
168 {
169 	return fDescriptor.vendor_id;
170 }
171 
172 
173 uint16
174 BUSBDevice::ProductID() const
175 {
176 	return fDescriptor.product_id;
177 }
178 
179 
180 uint16
181 BUSBDevice::Version() const
182 {
183 	return fDescriptor.device_version;
184 }
185 
186 
187 const char *
188 BUSBDevice::ManufacturerString() const
189 {
190 	if (fDescriptor.manufacturer == 0)
191 		return "";
192 
193 	if (fManufacturerString)
194 		return fManufacturerString;
195 
196 	fManufacturerString = DecodeStringDescriptor(fDescriptor.manufacturer);
197 	if (fManufacturerString == NULL)
198 		return "";
199 
200 	return fManufacturerString;
201 }
202 
203 
204 const char *
205 BUSBDevice::ProductString() const
206 {
207 	if (fDescriptor.product == 0)
208 		return "";
209 
210 	if (fProductString)
211 		return fProductString;
212 
213 	fProductString = DecodeStringDescriptor(fDescriptor.product);
214 	if (fProductString == NULL)
215 		return "";
216 
217 	return fProductString;
218 }
219 
220 
221 const char *
222 BUSBDevice::SerialNumberString() const
223 {
224 	if (fDescriptor.serial_number == 0)
225 		return "";
226 
227 	if (fSerialNumberString)
228 		return fSerialNumberString;
229 
230 	fSerialNumberString = DecodeStringDescriptor(fDescriptor.serial_number);
231 	if (fSerialNumberString == NULL)
232 		return "";
233 
234 	return fSerialNumberString;
235 }
236 
237 
238 const usb_device_descriptor *
239 BUSBDevice::Descriptor() const
240 {
241 	return &fDescriptor;
242 }
243 
244 
245 size_t
246 BUSBDevice::GetStringDescriptor(uint32 index,
247 	usb_string_descriptor *descriptor, size_t length) const
248 {
249 	if (!descriptor)
250 		return B_BAD_VALUE;
251 
252 	usb_raw_command command;
253 	command.string.descriptor = descriptor;
254 	command.string.string_index = index;
255 	command.string.length = length;
256 
257 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR, &command,
258 		sizeof(command)) || command.string.status != B_USB_RAW_STATUS_SUCCESS)
259 		return 0;
260 
261 	return command.string.length;
262 }
263 
264 
265 char *
266 BUSBDevice::DecodeStringDescriptor(uint32 index) const
267 {
268 	char buffer[300];
269 	usb_string_descriptor *stringDescriptor;
270 	stringDescriptor = (usb_string_descriptor *)&buffer;
271 
272 	size_t stringLength = GetStringDescriptor(index, stringDescriptor,
273 		sizeof(buffer) - sizeof(usb_string_descriptor));
274 
275 	if (stringLength < 3)
276 		return NULL;
277 
278 	// pseudo convert unicode string
279 	stringLength = (stringLength - 2) / 2;
280 	char *result = new(std::nothrow) char[stringLength + 1];
281 	if (result == NULL)
282 		return NULL;
283 
284 	for (size_t i = 0; i < stringLength; i++)
285 		result[i] = stringDescriptor->string[i * 2];
286 	result[stringLength] = 0;
287 	return result;
288 }
289 
290 
291 size_t
292 BUSBDevice::GetDescriptor(uint8 type, uint8 index, uint16 languageID,
293 	void *data, size_t length) const
294 {
295 	if (length > 0 && data == NULL)
296 		return B_BAD_VALUE;
297 
298 	usb_raw_command command;
299 	command.descriptor.type = type;
300 	command.descriptor.index = index;
301 	command.descriptor.language_id = languageID;
302 	command.descriptor.data = data;
303 	command.descriptor.length = length;
304 
305 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DESCRIPTOR, &command,
306 		sizeof(command)) || command.descriptor.status != B_USB_RAW_STATUS_SUCCESS)
307 		return 0;
308 
309 	return command.descriptor.length;
310 }
311 
312 
313 uint32
314 BUSBDevice::CountConfigurations() const
315 {
316 	return fDescriptor.num_configurations;
317 }
318 
319 
320 const BUSBConfiguration *
321 BUSBDevice::ConfigurationAt(uint32 index) const
322 {
323 	if (index >= fDescriptor.num_configurations || fConfigurations == NULL)
324 		return NULL;
325 
326 	return fConfigurations[index];
327 }
328 
329 
330 const BUSBConfiguration *
331 BUSBDevice::ActiveConfiguration() const
332 {
333 	if (fConfigurations == NULL)
334 		return NULL;
335 
336 	return fConfigurations[fActiveConfiguration];
337 }
338 
339 
340 status_t
341 BUSBDevice::SetConfiguration(const BUSBConfiguration *configuration)
342 {
343 	if (!configuration || configuration->Index() >= fDescriptor.num_configurations)
344 		return B_BAD_VALUE;
345 
346 	usb_raw_command command;
347 	command.config.config_index = configuration->Index();
348 
349 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command,
350 		sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS)
351 		return B_ERROR;
352 
353 	fActiveConfiguration = configuration->Index();
354 	return B_OK;
355 }
356 
357 
358 ssize_t
359 BUSBDevice::ControlTransfer(uint8 requestType, uint8 request, uint16 value,
360 	uint16 index, uint16 length, void *data) const
361 {
362 	if (length > 0 && data == NULL)
363 		return B_BAD_VALUE;
364 
365 	usb_raw_command command;
366 	command.control.request_type = requestType;
367 	command.control.request = request;
368 	command.control.value = value;
369 	command.control.index = index;
370 	command.control.length = length;
371 	command.control.data = data;
372 
373 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command,
374 		sizeof(command)) || command.control.status != B_USB_RAW_STATUS_SUCCESS)
375 		return B_ERROR;
376 
377 	return command.control.length;
378 }
379 
380 
381 // definition of reserved virtual functions
382 void BUSBDevice::_ReservedUSBDevice1() {};
383 void BUSBDevice::_ReservedUSBDevice2() {};
384 void BUSBDevice::_ReservedUSBDevice3() {};
385 void BUSBDevice::_ReservedUSBDevice4() {};
386 void BUSBDevice::_ReservedUSBDevice5() {};
387