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