xref: /haiku/src/add-ons/kernel/bus_managers/usb/usb.cpp (revision 9ecf9d1c1d4888d341a6eac72112c72d1ae3a4cb)
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 <util/kernel_cpp.h>
11 #include "usb_p.h"
12 
13 
14 Stack *gUSBStack = NULL;
15 
16 
17 static int32
18 bus_std_ops(int32 op, ...)
19 {
20 	switch (op) {
21 		case B_MODULE_INIT: {
22 			if (gUSBStack)
23 				return B_OK;
24 
25 #ifdef TRACE_USB
26 			set_dprintf_enabled(true);
27 			load_driver_symbols("usb");
28 			TRACE(("usb_module: init\n"));
29 #endif
30 
31 			Stack *stack = new(std::nothrow) Stack();
32 			if (!stack)
33 				return B_NO_MEMORY;
34 
35 			if (stack->InitCheck() != B_OK) {
36 				delete stack;
37 				return ENODEV;
38 			}
39 
40 			gUSBStack = stack;
41 			break;
42 		}
43 
44 		case B_MODULE_UNINIT:
45 			TRACE(("usb_module: bus module: uninit\n"));
46 			delete gUSBStack;
47 			gUSBStack = NULL;
48 			break;
49 
50 		default:
51 			return EINVAL;
52 	}
53 
54 	return B_OK;
55 }
56 
57 
58 status_t
59 register_driver(const char *driverName,
60 	const usb_support_descriptor *descriptors,
61 	size_t count, const char *optionalRepublishDriverName)
62 {
63 	return gUSBStack->RegisterDriver(driverName, descriptors, count,
64 		optionalRepublishDriverName);
65 }
66 
67 
68 status_t
69 install_notify(const char *driverName, const usb_notify_hooks *hooks)
70 {
71 	return gUSBStack->InstallNotify(driverName, hooks);
72 }
73 
74 
75 status_t
76 uninstall_notify(const char *driverName)
77 {
78 	return gUSBStack->UninstallNotify(driverName);
79 }
80 
81 
82 const usb_device_descriptor *
83 get_device_descriptor(usb_device device)
84 {
85 	TRACE(("usb_module: get_device_descriptor(0x%08x)\n", device));
86 	Object *object = gUSBStack->GetObject(device);
87 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
88 		return NULL;
89 
90 	return ((Device *)object)->DeviceDescriptor();
91 }
92 
93 
94 const usb_configuration_info *
95 get_nth_configuration(usb_device device, uint index)
96 {
97 	TRACE(("usb_module: get_nth_configuration(0x%08x, %d)\n", device, index));
98 	Object *object = gUSBStack->GetObject(device);
99 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
100 		return NULL;
101 
102 	return ((Device *)object)->ConfigurationAt((int32)index);
103 }
104 
105 
106 const usb_configuration_info *
107 get_configuration(usb_device device)
108 {
109 	TRACE(("usb_module: get_configuration(0x%08x)\n", device));
110 	Object *object = gUSBStack->GetObject(device);
111 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
112 		return NULL;
113 
114 	return ((Device *)object)->Configuration();
115 }
116 
117 
118 status_t
119 set_configuration(usb_device device,
120 	const usb_configuration_info *configuration)
121 {
122 	TRACE(("usb_module: set_configuration(0x%08x, 0x%08x)\n", device, configuration));
123 	Object *object = gUSBStack->GetObject(device);
124 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
125 		return B_BAD_VALUE;
126 
127 	return ((Device *)object)->SetConfiguration(configuration);
128 }
129 
130 
131 status_t
132 set_alt_interface(usb_device device, const usb_interface_info *interface)
133 {
134 	TRACE(("usb_module: set_alt_interface(0x%08x, 0x%08x)\n", device, interface));
135 	Object *object = gUSBStack->GetObject(device);
136 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
137 		return B_BAD_VALUE;
138 
139 	return B_ERROR;
140 }
141 
142 
143 status_t
144 set_feature(usb_id handle, uint16 selector)
145 {
146 	TRACE(("usb_module: set_feature(0x%08x, %d)\n", handle, selector));
147 	Object *object = gUSBStack->GetObject(handle);
148 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
149 		return B_BAD_VALUE;
150 
151 	return ((Pipe *)object)->SetFeature(selector);
152 }
153 
154 
155 status_t
156 clear_feature(usb_id handle, uint16 selector)
157 {
158 	TRACE(("usb_module: clear_feature(0x%08x, %d)\n", handle, selector));
159 	Object *object = gUSBStack->GetObject(handle);
160 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
161 		return B_BAD_VALUE;
162 
163 	return ((Pipe *)object)->ClearFeature(selector);
164 }
165 
166 
167 status_t
168 get_status(usb_id handle, uint16 *status)
169 {
170 	TRACE(("usb_module: get_status(0x%08x, 0x%08x)\n", handle, status));
171 	if (!status)
172 		return B_BAD_VALUE;
173 
174 	Object *object = gUSBStack->GetObject(handle);
175 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
176 		return B_BAD_VALUE;
177 
178 	return ((Pipe *)object)->GetStatus(status);
179 }
180 
181 
182 status_t
183 get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
184 	void *data, size_t dataLength, size_t *actualLength)
185 {
186 	TRACE(("usb_module: get_descriptor(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%08x, %d, 0x%08x)\n", device, type, index, languageID, data, dataLength, actualLength));
187 	Object *object = gUSBStack->GetObject(device);
188 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
189 		return B_BAD_VALUE;
190 
191 	return ((Device *)object)->GetDescriptor(type, index, languageID,
192 		data, dataLength, actualLength);
193 }
194 
195 
196 status_t
197 send_request(usb_device device, uint8 requestType, uint8 request,
198 	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
199 {
200 	TRACE(("usb_module: send_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, actualLength));
201 	Object *object = gUSBStack->GetObject(device);
202 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
203 		return B_BAD_VALUE;
204 
205 	return ((Device *)object)->SendRequest(requestType, request, value, index,
206 		length, data, length, actualLength);
207 }
208 
209 
210 status_t
211 queue_request(usb_device device, uint8 requestType, uint8 request,
212 	uint16 value, uint16 index, uint16 length, void *data,
213 	usb_callback_func callback, void *callbackCookie)
214 {
215 	TRACE(("usb_module: queue_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, callback, callbackCookie));
216 	Object *object = gUSBStack->GetObject(device);
217 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
218 		return B_BAD_VALUE;
219 
220 	return ((Device *)object)->QueueRequest(requestType, request, value, index,
221 		length, data, length, callback, callbackCookie);
222 }
223 
224 
225 status_t
226 queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
227 	usb_callback_func callback, void *callbackCookie)
228 {
229 	TRACE(("usb_module: queue_interrupt(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
230 	Object *object = gUSBStack->GetObject(pipe);
231 	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
232 		return B_BAD_VALUE;
233 
234 	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
235 		callbackCookie);
236 }
237 
238 
239 status_t
240 queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
241 	usb_callback_func callback, void *callbackCookie)
242 {
243 	TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
244 	Object *object = gUSBStack->GetObject(pipe);
245 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
246 		return B_BAD_VALUE;
247 
248 	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
249 		callbackCookie);
250 }
251 
252 
253 status_t
254 queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
255 	usb_callback_func callback, void *callbackCookie)
256 {
257 	TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, vector, vectorCount, callback, callbackCookie));
258 	Object *object = gUSBStack->GetObject(pipe);
259 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
260 		return B_BAD_VALUE;
261 
262 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
263 		callbackCookie);
264 }
265 
266 
267 status_t
268 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
269 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
270 	void *callbackCookie)
271 {
272 	TRACE(("usb_module: queue_isochronous(0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, rleArray, bufferDurationMS, callback, callbackCookie));
273 	Object *object = gUSBStack->GetObject(pipe);
274 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
275 		return B_BAD_VALUE;
276 
277 	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
278 		rleArray, bufferDurationMS, callback, callbackCookie);
279 }
280 
281 
282 status_t
283 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
284 	uint16 maxBufferDurationMS, uint16 sampleSize)
285 {
286 	TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize));
287 	Object *object = gUSBStack->GetObject(pipe);
288 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
289 		return B_BAD_VALUE;
290 
291 	return B_ERROR;
292 }
293 
294 
295 status_t
296 cancel_queued_transfers(usb_pipe pipe)
297 {
298 	TRACE(("usb_module: cancel_queued_transfers(0x%08x)\n", pipe));
299 	Object *object = gUSBStack->GetObject(pipe);
300 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
301 		return B_BAD_VALUE;
302 
303 	return ((Pipe *)object)->CancelQueuedTransfers();
304 }
305 
306 
307 status_t
308 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
309 {
310 	TRACE(("usb_module: usb_ioctl(0x%08x, 0x%08x, %d)\n", opcode, buffer, bufferSize));
311 
312 	switch (opcode) {
313 		case 'DNAM': {
314 			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
315 			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
316 				return B_BAD_VALUE;
317 
318 			uint32 index = 0;
319 			return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
320 				bufferSize, NULL);
321 		}
322 	}
323 
324 	return B_DEV_INVALID_IOCTL;
325 }
326 
327 
328 /*
329 	This module exports the USB API v3
330 */
331 struct usb_module_info gModuleInfoV3 = {
332 	// First the bus_manager_info:
333 	{
334 		{
335 			"bus_managers/usb/v3",
336 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
337 			bus_std_ops
338 		},
339 		NULL							// the rescan function
340 	},
341 
342 	register_driver,					// register_driver
343 	install_notify,						// install_notify
344 	uninstall_notify,					// uninstall_notify
345 	get_device_descriptor,				// get_device_descriptor
346 	get_nth_configuration,				// get_nth_configuration
347 	get_configuration,					// get_configuration
348 	set_configuration,					// set_configuration
349 	set_alt_interface,					// set_alt_interface
350 	set_feature,						// set_feature
351 	clear_feature, 						// clear_feature
352 	get_status, 						// get_status
353 	get_descriptor,						// get_descriptor
354 	send_request,						// send_request
355 	queue_interrupt,					// queue_interrupt
356 	queue_bulk,							// queue_bulk
357 	queue_bulk_v,						// queue_bulk_v
358 	queue_isochronous,					// queue_isochronous
359 	queue_request,						// queue_request
360 	set_pipe_policy,					// set_pipe_policy
361 	cancel_queued_transfers,			// cancel_queued_transfers
362 	usb_ioctl							// usb_ioctl
363 };
364 
365 
366 //
367 // #pragma mark -
368 //
369 
370 
371 const usb_device_descriptor *
372 get_device_descriptor_v2(const void *device)
373 {
374 	return get_device_descriptor((usb_id)device);
375 }
376 
377 
378 const usb_configuration_info *
379 get_nth_configuration_v2(const void *device, uint index)
380 {
381 	return get_nth_configuration((usb_id)device, index);
382 }
383 
384 
385 const usb_configuration_info *
386 get_configuration_v2(const void *device)
387 {
388 	return get_configuration((usb_id)device);
389 }
390 
391 
392 status_t
393 set_configuration_v2(const void *device,
394 	const usb_configuration_info *configuration)
395 {
396 	return set_configuration((usb_id)device, configuration);
397 }
398 
399 
400 status_t
401 set_alt_interface_v2(const void *device, const usb_interface_info *interface)
402 {
403 	return set_alt_interface((usb_id)device, interface);
404 }
405 
406 
407 status_t
408 set_feature_v2(const void *object, uint16 selector)
409 {
410 	return set_feature((usb_id)object, selector);
411 }
412 
413 
414 status_t
415 clear_feature_v2(const void *object, uint16 selector)
416 {
417 	return clear_feature((usb_id)object, selector);
418 }
419 
420 
421 status_t
422 get_status_v2(const void *object, uint16 *status)
423 {
424 	return get_status((usb_id)object, status);
425 }
426 
427 
428 status_t
429 get_descriptor_v2(const void *device, uint8 type, uint8 index,
430 	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
431 {
432 	return get_descriptor((usb_id)device, type, index, languageID, data,
433 		dataLength, actualLength);
434 }
435 
436 
437 status_t
438 send_request_v2(const void *device, uint8 requestType, uint8 request,
439 	uint16 value, uint16 index, uint16 length, void *data,
440 	size_t /*dataLength*/, size_t *actualLength)
441 {
442 	return send_request((usb_id)device, requestType, request, value, index,
443 		length, data, actualLength);
444 }
445 
446 
447 status_t
448 queue_request_v2(const void *device, uint8 requestType, uint8 request,
449 	uint16 value, uint16 index, uint16 length, void *data,
450 	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
451 {
452 	return queue_request((usb_id)device, requestType, request, value, index,
453 		length, data, callback, callbackCookie);
454 }
455 
456 
457 status_t
458 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
459 	usb_callback_func callback, void *callbackCookie)
460 {
461 	return queue_interrupt((usb_id)pipe, data, dataLength, callback,
462 		callbackCookie);
463 }
464 
465 
466 status_t
467 queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
468 	usb_callback_func callback, void *callbackCookie)
469 {
470 	return queue_bulk((usb_id)pipe, data, dataLength, callback,
471 		callbackCookie);
472 }
473 
474 
475 status_t
476 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
477 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
478 	void *callbackCookie)
479 {
480 	return queue_isochronous((usb_id)pipe, data, dataLength, rleArray,
481 		bufferDurationMS, callback, callbackCookie);
482 }
483 
484 
485 status_t
486 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
487 	uint16 maxBufferDurationMS, uint16 sampleSize)
488 {
489 	return set_pipe_policy((usb_id)pipe, maxQueuedPackets, maxBufferDurationMS,
490 		sampleSize);
491 }
492 
493 
494 status_t
495 cancel_queued_transfers_v2(const void *pipe)
496 {
497 	return cancel_queued_transfers((usb_id)pipe);
498 }
499 
500 
501 struct usb_module_info_v2 {
502 	bus_manager_info				binfo;
503 	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
504 	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
505 	status_t						(*uninstall_notify)(const char *);
506 	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
507 	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
508 	const usb_configuration_info	*(*get_configuration)(const void *);
509 	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
510 	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
511 	status_t						(*set_feature)(const void *, uint16);
512 	status_t						(*clear_feature)(const void *, uint16);
513 	status_t						(*get_status)(const void *, uint16 *);
514 	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
515 	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
516 	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
517 	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
518 	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
519 	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
520 	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
521 	status_t						(*cancel_queued_transfers)(const void *);
522 	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
523 };
524 
525 
526 /*
527 	This module exports the USB API v2
528 */
529 struct usb_module_info_v2 gModuleInfoV2 = {
530 	// First the bus_manager_info:
531 	{
532 		{
533 			"bus_managers/usb/v2",
534 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
535 			bus_std_ops
536 		},
537 		NULL							// the rescan function
538 	},
539 
540 	register_driver,					// register_driver
541 	install_notify,						// install_notify
542 	uninstall_notify,					// uninstall_notify
543 	get_device_descriptor_v2,			// get_device_descriptor
544 	get_nth_configuration_v2,			// get_nth_configuration
545 	get_configuration_v2,				// get_configuration
546 	set_configuration_v2,				// set_configuration
547 	set_alt_interface_v2,				// set_alt_interface
548 	set_feature_v2,						// set_feature
549 	clear_feature_v2,					// clear_feature
550 	get_status_v2, 						// get_status
551 	get_descriptor_v2,					// get_descriptor
552 	send_request_v2,					// send_request
553 	queue_interrupt_v2,					// queue_interrupt
554 	queue_bulk_v2,						// queue_bulk
555 	queue_isochronous_v2,				// queue_isochronous
556 	queue_request_v2,					// queue_request
557 	set_pipe_policy_v2,					// set_pipe_policy
558 	cancel_queued_transfers_v2,			// cancel_queued_transfers
559 	usb_ioctl							// usb_ioctl
560 };
561 
562 
563 //
564 // #pragma mark -
565 //
566 
567 
568 module_info *modules[] = {
569 	(module_info *)&gModuleInfoV2,
570 	(module_info *)&gModuleInfoV3,
571 	NULL
572 };
573