xref: /haiku/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp (revision cda5b8808fd0262f0fac472f6cfa809f846a83cf)
1 /*
2  * Copyright 2006-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 "BeOSCompatibility.h"
10 #include "usb_raw.h"
11 
12 #include <KernelExport.h>
13 #include <Drivers.h>
14 #include <lock.h>
15 #include <malloc.h>
16 #include <stdio.h>
17 #include <string.h>
18 
19 //#define TRACE_USB_RAW
20 #ifdef TRACE_USB_RAW
21 #define TRACE(x)	dprintf x
22 #else
23 #define TRACE(x)	/* nothing */
24 #endif
25 
26 #define DRIVER_NAME		"usb_raw"
27 #define DEVICE_NAME		"bus/usb/raw"
28 
29 typedef struct {
30 	usb_device			device;
31 	benaphore			lock;
32 	uint32				reference_count;
33 
34 	char				name[32];
35 	void				*link;
36 
37 	sem_id				notify;
38 	status_t			status;
39 	size_t				actual_length;
40 } raw_device;
41 
42 int32 api_version = B_CUR_DRIVER_API_VERSION;
43 static usb_module_info *gUSBModule = NULL;
44 static raw_device *gDeviceList = NULL;
45 static uint32 gDeviceCount = 0;
46 static benaphore gDeviceListLock;
47 static char **gDeviceNames = NULL;
48 
49 static status_t
50 usb_raw_device_added(usb_device newDevice, void **cookie)
51 {
52 	TRACE((DRIVER_NAME": device_added(0x%08lx)\n", newDevice));
53 	raw_device *device = (raw_device *)malloc(sizeof(raw_device));
54 
55 	status_t result = benaphore_init(&device->lock, "usb_raw device lock");
56 	if (result < B_OK) {
57 		free(device);
58 		return result;
59 	}
60 
61 	device->notify = create_sem(0, "usb_raw callback notify");
62 	if (device->notify < B_OK) {
63 		benaphore_destroy(&device->lock);
64 		free(device);
65 		return B_NO_MORE_SEMS;
66 	}
67 
68 	char deviceName[32];
69 	memcpy(deviceName, &newDevice, sizeof(usb_device));
70 	if (gUSBModule->usb_ioctl('DNAM', deviceName, sizeof(deviceName)) >= B_OK) {
71 		sprintf(device->name, "bus/usb/%s", deviceName);
72 	} else {
73 		sprintf(device->name, "bus/usb/%08lx", newDevice);
74 	}
75 
76 	device->device = newDevice;
77 	device->reference_count = 0;
78 
79 	benaphore_lock(&gDeviceListLock);
80 	device->link = (void *)gDeviceList;
81 	gDeviceList = device;
82 	gDeviceCount++;
83 	benaphore_unlock(&gDeviceListLock);
84 
85 	TRACE((DRIVER_NAME": new device: 0x%08lx\n", (uint32)device));
86 	*cookie = (void *)device;
87 	return B_OK;
88 }
89 
90 
91 static status_t
92 usb_raw_device_removed(void *cookie)
93 {
94 	TRACE((DRIVER_NAME": device_removed(0x%08lx)\n", (uint32)cookie));
95 	raw_device *device = (raw_device *)cookie;
96 
97 	benaphore_lock(&gDeviceListLock);
98 	if (gDeviceList == device) {
99 		gDeviceList = (raw_device *)device->link;
100 	} else {
101 		raw_device *element = gDeviceList;
102 		while (element) {
103 			if (element->link == device) {
104 				element->link = device->link;
105 				break;
106 			}
107 
108 			element = (raw_device *)element->link;
109 		}
110 	}
111 	gDeviceCount--;
112 	benaphore_unlock(&gDeviceListLock);
113 
114 	device->device = 0;
115 	if (device->reference_count == 0) {
116 		benaphore_lock(&device->lock);
117 		benaphore_destroy(&device->lock);
118 		delete_sem(device->notify);
119 		free(device);
120 	}
121 
122 	return B_OK;
123 }
124 
125 
126 //
127 //#pragma mark -
128 //
129 
130 
131 static status_t
132 usb_raw_open(const char *name, uint32 flags, void **cookie)
133 {
134 	TRACE((DRIVER_NAME": open()\n"));
135 	benaphore_lock(&gDeviceListLock);
136 	raw_device *element = gDeviceList;
137 	while (element) {
138 		if (strcmp(name, element->name) == 0) {
139 			element->reference_count++;
140 			*cookie = element;
141 			benaphore_unlock(&gDeviceListLock);
142 			return B_OK;
143 		}
144 
145 		element = (raw_device *)element->link;
146 	}
147 
148 	benaphore_unlock(&gDeviceListLock);
149 	return B_NAME_NOT_FOUND;
150 }
151 
152 
153 static status_t
154 usb_raw_close(void *cookie)
155 {
156 	TRACE((DRIVER_NAME": close()\n"));
157 	return B_OK;
158 }
159 
160 
161 static status_t
162 usb_raw_free(void *cookie)
163 {
164 	TRACE((DRIVER_NAME": free()\n"));
165 	benaphore_lock(&gDeviceListLock);
166 
167 	raw_device *device = (raw_device *)cookie;
168 	device->reference_count--;
169 	if (device->device == 0) {
170 		benaphore_lock(&device->lock);
171 		benaphore_destroy(&device->lock);
172 		delete_sem(device->notify);
173 		free(device);
174 	}
175 
176 	benaphore_unlock(&gDeviceListLock);
177 	return B_OK;
178 }
179 
180 
181 static void
182 usb_raw_callback(void *cookie, status_t status, void *data, size_t actualLength)
183 {
184 	TRACE((DRIVER_NAME": callback()\n"));
185 	raw_device *device = (raw_device *)cookie;
186 
187 	switch (status) {
188 		case B_OK:
189 			device->status = B_USB_RAW_STATUS_SUCCESS;
190 			break;
191 		case B_TIMED_OUT:
192 			device->status = B_USB_RAW_STATUS_TIMEOUT;
193 			break;
194 		case B_CANCELED:
195 			device->status = B_USB_RAW_STATUS_ABORTED;
196 			break;
197 		case B_DEV_CRC_ERROR:
198 			device->status = B_USB_RAW_STATUS_CRC_ERROR;
199 			break;
200 		case B_DEV_STALLED:
201 			device->status = B_USB_RAW_STATUS_STALLED;
202 			break;
203 		default:
204 			device->status = B_USB_RAW_STATUS_FAILED;
205 			break;
206 	}
207 
208 	device->actual_length = actualLength;
209 	release_sem(device->notify);
210 }
211 
212 
213 static status_t
214 usb_raw_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
215 {
216 	TRACE((DRIVER_NAME": ioctl\n"));
217 	raw_device *device = (raw_device *)cookie;
218 	usb_raw_command *command = (usb_raw_command *)buffer;
219 
220 	if (device->device == 0)
221 		return B_DEV_NOT_READY;
222 
223 	switch (op) {
224 		case B_USB_RAW_COMMAND_GET_VERSION: {
225 			command->version.status = B_USB_RAW_PROTOCOL_VERSION;
226 			return B_OK;
227 		}
228 
229 		case B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR: {
230 			const usb_device_descriptor *deviceDescriptor =
231 				gUSBModule->get_device_descriptor(device->device);
232 			if (!deviceDescriptor) {
233 				command->device.status = B_USB_RAW_STATUS_ABORTED;
234 				return B_OK;
235 			}
236 
237 			memcpy(command->device.descriptor, deviceDescriptor,
238 				sizeof(usb_device_descriptor));
239 			command->device.status = B_USB_RAW_STATUS_SUCCESS;
240 			return B_OK;
241 		}
242 
243 		case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR: {
244 			const usb_configuration_info *configurationInfo =
245 				gUSBModule->get_nth_configuration(device->device,
246 				command->config.config_index);
247 			if (!configurationInfo) {
248 				command->config.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
249 				return B_OK;
250 			}
251 
252 			memcpy(command->config.descriptor, configurationInfo->descr,
253 				sizeof(usb_configuration_descriptor));
254 			command->config.status = B_USB_RAW_STATUS_SUCCESS;
255 			return B_OK;
256 		}
257 
258 		case B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR: {
259 			const usb_configuration_info *configurationInfo =
260 				gUSBModule->get_nth_configuration(device->device,
261 				command->interface.config_index);
262 			if (!configurationInfo) {
263 				command->interface.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
264 				return B_OK;
265 			}
266 
267 			if (command->interface.interface_index >= configurationInfo->interface_count) {
268 				command->interface.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
269 				return B_OK;
270 			}
271 
272 			const usb_interface_info *interfaceInfo =
273 				configurationInfo->interface[command->interface.interface_index].active;
274 			if (!interfaceInfo) {
275 				command->interface.status = B_USB_RAW_STATUS_ABORTED;
276 				return B_OK;
277 			}
278 
279 			memcpy(command->interface.descriptor, interfaceInfo->descr,
280 				sizeof(usb_interface_descriptor));
281 			command->interface.status = B_USB_RAW_STATUS_SUCCESS;
282 			return B_OK;
283 		}
284 
285 		case B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT: {
286 			const usb_configuration_info *configurationInfo =
287 				gUSBModule->get_nth_configuration(device->device,
288 				command->alternate.config_index);
289 			if (!configurationInfo) {
290 				command->alternate.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
291 				return B_OK;
292 			}
293 
294 			if (command->alternate.interface_index >= configurationInfo->interface_count) {
295 				command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
296 				return B_OK;
297 			}
298 
299 			*command->alternate.alternate_count
300 				= configurationInfo->interface[command->alternate.interface_index].alt_count;
301 			command->alternate.status = B_USB_RAW_STATUS_SUCCESS;
302 			return B_OK;
303 		}
304 
305 		case B_USB_RAW_COMMAND_GET_ALT_INTERFACE_DESCRIPTOR: {
306 			const usb_configuration_info *configurationInfo =
307 				gUSBModule->get_nth_configuration(device->device,
308 				command->alternate.config_index);
309 			if (!configurationInfo) {
310 				command->alternate.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
311 				return B_OK;
312 			}
313 
314 			if (command->alternate.interface_index >= configurationInfo->interface_count) {
315 				command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
316 				return B_OK;
317 			}
318 
319 			const usb_interface_list *interfaceList =
320 				&configurationInfo->interface[command->alternate.interface_index];
321 			if (command->alternate.alternate_index >= interfaceList->alt_count) {
322 				command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
323 				return B_OK;
324 			}
325 
326 			memcpy(command->alternate.descriptor,
327 				&interfaceList->alt[command->alternate.alternate_index],
328 				sizeof(usb_interface_descriptor));
329 			command->alternate.status = B_USB_RAW_STATUS_SUCCESS;
330 			return B_OK;
331 		}
332 
333 		case B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR: {
334 			const usb_configuration_info *configurationInfo =
335 				gUSBModule->get_nth_configuration(device->device,
336 				command->endpoint.config_index);
337 			if (!configurationInfo) {
338 				command->endpoint.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
339 				return B_OK;
340 			}
341 
342 			if (command->endpoint.interface_index >= configurationInfo->interface_count) {
343 				command->endpoint.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
344 				return B_OK;
345 			}
346 
347 			const usb_interface_info *interfaceInfo =
348 				configurationInfo->interface[command->endpoint.interface_index].active;
349 			if (!interfaceInfo) {
350 				command->endpoint.status = B_USB_RAW_STATUS_ABORTED;
351 				return B_OK;
352 			}
353 
354 			if (command->endpoint.endpoint_index >= interfaceInfo->endpoint_count) {
355 				command->endpoint.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
356 				return B_OK;
357 			}
358 
359 			memcpy(command->endpoint.descriptor,
360 				interfaceInfo->endpoint[command->endpoint.endpoint_index].descr,
361 				sizeof(usb_endpoint_descriptor));
362 			command->endpoint.status = B_USB_RAW_STATUS_SUCCESS;
363 			return B_OK;
364 		}
365 
366 		case B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR: {
367 			const usb_configuration_info *configurationInfo =
368 				gUSBModule->get_nth_configuration(device->device,
369 				command->generic.config_index);
370 			if (!configurationInfo) {
371 				command->generic.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
372 				return B_OK;
373 			}
374 
375 			if (command->generic.interface_index >= configurationInfo->interface_count) {
376 				command->generic.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
377 				return B_OK;
378 			}
379 
380 			const usb_interface_info *interfaceInfo =
381 				configurationInfo->interface[command->generic.interface_index].active;
382 			if (!interfaceInfo) {
383 				command->generic.status = B_USB_RAW_STATUS_ABORTED;
384 				return B_OK;
385 			}
386 
387 			if (command->generic.generic_index >= interfaceInfo->generic_count) {
388 				// ToDo: add B_USB_RAW_STATUS_INVALID_GENERIC
389 				command->generic.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
390 				return B_OK;
391 			}
392 
393 			usb_descriptor *descriptor = interfaceInfo->generic[command->generic.generic_index];
394 			if (!descriptor) {
395 				command->generic.status = B_USB_RAW_STATUS_ABORTED;
396 				return B_OK;
397 			}
398 
399 			if (descriptor->generic.length > command->generic.length) {
400 				command->generic.status = B_USB_RAW_STATUS_NO_MEMORY;
401 				return B_OK;
402 			}
403 
404 			memcpy(command->generic.descriptor, descriptor,
405 				descriptor->generic.length);
406 			command->generic.status = B_USB_RAW_STATUS_SUCCESS;
407 			return B_OK;
408 		}
409 
410 		case B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR: {
411 			size_t actualLength = 0;
412 			uint8 firstTwoBytes[2];
413 
414 			if (gUSBModule->get_descriptor(device->device,
415 				USB_DESCRIPTOR_STRING, command->string.string_index, 0,
416 				firstTwoBytes, 2, &actualLength) < B_OK
417 				|| actualLength != 2
418 				|| firstTwoBytes[1] != USB_DESCRIPTOR_STRING) {
419 				command->string.status = B_USB_RAW_STATUS_ABORTED;
420 				command->string.length = 0;
421 				return B_OK;
422 			}
423 
424 			uint8 stringLength = MIN(firstTwoBytes[0], command->string.length);
425 			char *string = (char *)malloc(stringLength);
426 			if (!string) {
427 				command->string.status = B_USB_RAW_STATUS_ABORTED;
428 				command->string.length = 0;
429 				return B_NO_MEMORY;
430 			}
431 
432 			if (gUSBModule->get_descriptor(device->device,
433 				USB_DESCRIPTOR_STRING, command->string.string_index, 0,
434 				string, stringLength, &actualLength) < B_OK
435 				|| actualLength != stringLength) {
436 				command->string.status = B_USB_RAW_STATUS_ABORTED;
437 				command->string.length = 0;
438 				free(string);
439 				return B_OK;
440 			}
441 
442 			memcpy(command->string.descriptor, string, stringLength);
443 			command->string.status = B_USB_RAW_STATUS_SUCCESS;
444 			command->string.length = stringLength;
445 			free(string);
446 			return B_OK;
447 		}
448 
449 		case B_USB_RAW_COMMAND_GET_DESCRIPTOR: {
450 			size_t actualLength = 0;
451 			uint8 firstTwoBytes[2];
452 
453 			if (gUSBModule->get_descriptor(device->device,
454 				command->descriptor.type, command->descriptor.index,
455 				command->descriptor.language_id, firstTwoBytes, 2,
456 				&actualLength) < B_OK
457 				|| actualLength != 2
458 				|| firstTwoBytes[1] != command->descriptor.type) {
459 				command->descriptor.status = B_USB_RAW_STATUS_ABORTED;
460 				command->descriptor.length = 0;
461 				return B_OK;
462 			}
463 
464 			uint8 length = MIN(firstTwoBytes[0], command->descriptor.length);
465 			uint8 *buffer = (uint8 *)malloc(length);
466 			if (!buffer) {
467 				command->descriptor.status = B_USB_RAW_STATUS_ABORTED;
468 				command->descriptor.length = 0;
469 				return B_NO_MEMORY;
470 			}
471 
472 			if (gUSBModule->get_descriptor(device->device,
473 				command->descriptor.type, command->descriptor.index,
474 				command->descriptor.language_id, buffer, length,
475 				&actualLength) < B_OK
476 				|| actualLength != length) {
477 				command->descriptor.status = B_USB_RAW_STATUS_ABORTED;
478 				command->descriptor.length = 0;
479 				free(buffer);
480 				return B_OK;
481 			}
482 
483 			memcpy(command->descriptor.data, buffer, length);
484 			command->descriptor.status = B_USB_RAW_STATUS_SUCCESS;
485 			command->descriptor.length = length;
486 			free(buffer);
487 			return B_OK;
488 		}
489 
490 		case B_USB_RAW_COMMAND_SET_CONFIGURATION: {
491 			const usb_configuration_info *configurationInfo =
492 				gUSBModule->get_nth_configuration(device->device,
493 				command->config.config_index);
494 			if (!configurationInfo) {
495 				command->config.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
496 				return B_OK;
497 			}
498 
499 			if (gUSBModule->set_configuration(device->device,
500 				configurationInfo) < B_OK) {
501 				command->config.status = B_USB_RAW_STATUS_FAILED;
502 				return B_OK;
503 			}
504 
505 			command->config.status = B_USB_RAW_STATUS_SUCCESS;
506 			return B_OK;
507 		}
508 
509 		case B_USB_RAW_COMMAND_SET_ALT_INTERFACE: {
510 			const usb_configuration_info *configurationInfo =
511 				gUSBModule->get_nth_configuration(device->device,
512 				command->alternate.config_index);
513 			if (!configurationInfo) {
514 				command->alternate.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
515 				return B_OK;
516 			}
517 
518 			if (command->alternate.interface_index >= configurationInfo->interface_count) {
519 				command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
520 				return B_OK;
521 			}
522 
523 			const usb_interface_list *interfaceList =
524 				&configurationInfo->interface[command->alternate.interface_index];
525 			if (command->alternate.alternate_index >= interfaceList->alt_count) {
526 				command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
527 				return B_OK;
528 			}
529 
530 			if (gUSBModule->set_alt_interface(device->device,
531 				&interfaceList->alt[command->alternate.alternate_index]) < B_OK) {
532 				command->alternate.status = B_USB_RAW_STATUS_FAILED;
533 				return B_OK;
534 			}
535 
536 			command->alternate.status = B_USB_RAW_STATUS_SUCCESS;
537 			return B_OK;
538 		}
539 
540 		case B_USB_RAW_COMMAND_CONTROL_TRANSFER: {
541 			benaphore_lock(&device->lock);
542 			if (gUSBModule->queue_request(device->device,
543 				command->control.request_type, command->control.request,
544 				command->control.value, command->control.index,
545 				command->control.length, command->control.data,
546 				usb_raw_callback, device) < B_OK) {
547 				command->control.status = B_USB_RAW_STATUS_FAILED;
548 				command->control.length = 0;
549 				benaphore_unlock(&device->lock);
550 				return B_OK;
551 			}
552 
553 			acquire_sem(device->notify);
554 			command->control.status = device->status;
555 			command->control.length = device->actual_length;
556 			benaphore_unlock(&device->lock);
557 			return B_OK;
558 		}
559 
560 		case B_USB_RAW_COMMAND_INTERRUPT_TRANSFER:
561 		case B_USB_RAW_COMMAND_BULK_TRANSFER:
562 		case B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER: {
563 			const usb_configuration_info *configurationInfo =
564 				gUSBModule->get_configuration(device->device);
565 			if (!configurationInfo) {
566 				command->transfer.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
567 				return B_OK;
568 			}
569 
570 			if (command->transfer.interface >= configurationInfo->interface_count) {
571 				command->transfer.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
572 				return B_OK;
573 			}
574 
575 			const usb_interface_info *interfaceInfo =
576 				configurationInfo->interface[command->transfer.interface].active;
577 			if (!interfaceInfo) {
578 				command->transfer.status = B_USB_RAW_STATUS_ABORTED;
579 				return B_OK;
580 			}
581 
582 			if (command->transfer.endpoint >= interfaceInfo->endpoint_count) {
583 				command->transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
584 				return B_OK;
585 			}
586 
587 			const usb_endpoint_info *endpointInfo =
588 				&interfaceInfo->endpoint[command->transfer.endpoint];
589 			if (!endpointInfo->handle) {
590 				command->transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
591 				return B_OK;
592 			}
593 
594 			size_t descriptorsSize = 0;
595 			usb_iso_packet_descriptor *packetDescriptors = NULL;
596 			if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) {
597 				descriptorsSize = sizeof(usb_iso_packet_descriptor)
598 					* command->isochronous.packet_count;
599 				packetDescriptors
600 					= (usb_iso_packet_descriptor *)malloc(descriptorsSize);
601 				if (!packetDescriptors) {
602 					command->transfer.status = B_USB_RAW_STATUS_NO_MEMORY;
603 					command->transfer.length = 0;
604 					return B_OK;
605 				}
606 
607 				memcpy(packetDescriptors,
608 					command->isochronous.packet_descriptors, descriptorsSize);
609 			}
610 
611 			status_t status;
612 			benaphore_lock(&device->lock);
613 			if (op == B_USB_RAW_COMMAND_INTERRUPT_TRANSFER) {
614 				status = gUSBModule->queue_interrupt(endpointInfo->handle,
615 					command->transfer.data, command->transfer.length,
616 					usb_raw_callback, device);
617 			} else if (op == B_USB_RAW_COMMAND_BULK_TRANSFER) {
618 				status = gUSBModule->queue_bulk(endpointInfo->handle,
619 					command->transfer.data, command->transfer.length,
620 					usb_raw_callback, device);
621 			} else {
622 				status = gUSBModule->queue_isochronous(endpointInfo->handle,
623 					command->isochronous.data, command->isochronous.length,
624 					packetDescriptors, command->isochronous.packet_count, NULL,
625 					0, usb_raw_callback, device);
626 			}
627 
628 			if (status < B_OK) {
629 				command->transfer.status = B_USB_RAW_STATUS_FAILED;
630 				command->transfer.length = 0;
631 				free(packetDescriptors);
632 				benaphore_unlock(&device->lock);
633 				return B_OK;
634 			}
635 
636 			acquire_sem(device->notify);
637 			command->transfer.status = device->status;
638 			command->transfer.length = device->actual_length;
639 			benaphore_unlock(&device->lock);
640 
641 			if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) {
642 				memcpy(command->isochronous.packet_descriptors,
643 					packetDescriptors, descriptorsSize);
644 				free(packetDescriptors);
645 			}
646 
647 			return B_OK;
648 		}
649 	}
650 
651 	return B_DEV_INVALID_IOCTL;
652 }
653 
654 
655 static status_t
656 usb_raw_read(void *cookie, off_t position, void *buffer, size_t *length)
657 {
658 	TRACE((DRIVER_NAME": read()\n"));
659 	*length = 0;
660 	return B_OK;
661 }
662 
663 
664 static status_t
665 usb_raw_write(void *cookie, off_t position, const void *buffer, size_t *length)
666 {
667 	TRACE((DRIVER_NAME": write()\n"));
668 	*length = 0;
669 	return B_OK;
670 }
671 
672 
673 //
674 //#pragma mark -
675 //
676 
677 
678 status_t
679 init_hardware()
680 {
681 	TRACE((DRIVER_NAME": init_hardware()\n"));
682 	return B_OK;
683 }
684 
685 
686 status_t
687 init_driver()
688 {
689 	TRACE((DRIVER_NAME": init_driver()\n"));
690 	static usb_notify_hooks notifyHooks = {
691 		&usb_raw_device_added,
692 		&usb_raw_device_removed
693 	};
694 
695 	gDeviceList = NULL;
696 	gDeviceCount = 0;
697 	status_t result = benaphore_init(&gDeviceListLock, "usb_raw device list lock");
698 	if (result < B_OK) {
699 		TRACE((DRIVER_NAME": failed to create device list lock\n"));
700 		return result;
701 	}
702 
703 	TRACE((DRIVER_NAME": trying module %s\n", B_USB_MODULE_NAME));
704 	result = get_module(B_USB_MODULE_NAME, (module_info **)&gUSBModule);
705 	if (result < B_OK) {
706 		TRACE((DRIVER_NAME": getting module failed 0x%08lx\n", result));
707 		benaphore_destroy(&gDeviceListLock);
708 		return result;
709 	}
710 
711 	gUSBModule->register_driver(DRIVER_NAME, NULL, 0, NULL);
712 	gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
713 	return B_OK;
714 }
715 
716 
717 void
718 uninit_driver()
719 {
720 	TRACE((DRIVER_NAME": uninit_driver()\n"));
721 	gUSBModule->uninstall_notify(DRIVER_NAME);
722 	benaphore_lock(&gDeviceListLock);
723 
724 	if (gDeviceNames) {
725 		for (int32 i = 1; gDeviceNames[i]; i++)
726 			free(gDeviceNames[i]);
727 		free(gDeviceNames);
728 		gDeviceNames = NULL;
729 	}
730 
731 	benaphore_destroy(&gDeviceListLock);
732 	put_module(B_USB_MODULE_NAME);
733 }
734 
735 
736 const char **
737 publish_devices()
738 {
739 	TRACE((DRIVER_NAME": publish_devices()\n"));
740 	if (gDeviceNames) {
741 		for (int32 i = 1; gDeviceNames[i]; i++)
742 			free(gDeviceNames[i]);
743 		free(gDeviceNames);
744 		gDeviceNames = NULL;
745 	}
746 
747 	int32 index = 0;
748 	gDeviceNames = (char **)malloc(sizeof(char *) * (gDeviceCount + 2));
749 	if (!gDeviceNames)
750 		return NULL;
751 
752 	gDeviceNames[index++] = DEVICE_NAME;
753 
754 	benaphore_lock(&gDeviceListLock);
755 	raw_device *element = gDeviceList;
756 	while (element) {
757 		gDeviceNames[index++] = strdup(element->name);
758 		element = (raw_device *)element->link;
759 	}
760 
761 	gDeviceNames[index++] = NULL;
762 	benaphore_unlock(&gDeviceListLock);
763 	return (const char **)gDeviceNames;
764 }
765 
766 
767 device_hooks *
768 find_device(const char *name)
769 {
770 	TRACE((DRIVER_NAME": find_device()\n"));
771 	static device_hooks hooks = {
772 		&usb_raw_open,
773 		&usb_raw_close,
774 		&usb_raw_free,
775 		&usb_raw_ioctl,
776 		&usb_raw_read,
777 		&usb_raw_write,
778 		NULL,
779 		NULL,
780 		NULL,
781 		NULL
782 	};
783 
784 	return &hooks;
785 }
786