xref: /haiku/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp (revision c2e8b3177bb0f9d499a052ff61d76d92222833ab)
1 /*
2  * Copyright 2006-2018, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  *		Adrien Destugues <pulkomandy@pulkomandy.tk>
8  */
9 
10 #include "usb_raw.h"
11 
12 #include <util/AutoLock.h>
13 #include <AutoDeleter.h>
14 #include <KernelExport.h>
15 #include <Drivers.h>
16 #include <algorithm>
17 #include <lock.h>
18 #include <malloc.h>
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include <kernel.h>
23 
24 
25 //#define TRACE_USB_RAW
26 #ifdef TRACE_USB_RAW
27 #define TRACE(x)	dprintf x
28 #else
29 #define TRACE(x)	/* nothing */
30 #endif
31 
32 #define DRIVER_NAME		"usb_raw"
33 #define DEVICE_NAME		"bus/usb/raw"
34 
35 typedef struct {
36 	usb_device			device;
37 	mutex				lock;
38 	uint32				reference_count;
39 
40 	char				name[64];
41 	void				*link;
42 
43 	sem_id				notify;
44 	status_t			status;
45 	size_t				actual_length;
46 } raw_device;
47 
48 int32 api_version = B_CUR_DRIVER_API_VERSION;
49 static usb_module_info *gUSBModule = NULL;
50 static raw_device *gDeviceList = NULL;
51 static uint32 gDeviceCount = 0;
52 static mutex gDeviceListLock;
53 static char **gDeviceNames = NULL;
54 
55 static status_t
usb_raw_device_added(usb_device newDevice,void ** cookie)56 usb_raw_device_added(usb_device newDevice, void **cookie)
57 {
58 	TRACE((DRIVER_NAME": device_added(0x%08" B_PRIx32 ")\n", newDevice));
59 	raw_device *device = (raw_device *)malloc(sizeof(raw_device));
60 
61 	mutex_init(&device->lock, "usb_raw device lock");
62 
63 	device->notify = create_sem(0, "usb_raw callback notify");
64 	if (device->notify < B_OK) {
65 		mutex_destroy(&device->lock);
66 		free(device);
67 		return B_NO_MORE_SEMS;
68 	}
69 
70 	char deviceName[64];
71 	memcpy(deviceName, &newDevice, sizeof(usb_device));
72 	if (gUSBModule->usb_ioctl('DNAM', deviceName, sizeof(deviceName)) >= B_OK) {
73 		snprintf(device->name, sizeof(device->name), "bus/usb/%s", deviceName);
74 	} else {
75 		snprintf(device->name, sizeof(device->name), "bus/usb/%08" B_PRIx32,
76 			newDevice);
77 	}
78 
79 	device->device = newDevice;
80 	device->reference_count = 0;
81 
82 	mutex_lock(&gDeviceListLock);
83 	device->link = (void *)gDeviceList;
84 	gDeviceList = device;
85 	gDeviceCount++;
86 	mutex_unlock(&gDeviceListLock);
87 
88 	TRACE((DRIVER_NAME": new device: 0x%p\n", device));
89 	*cookie = (void *)device;
90 	return B_OK;
91 }
92 
93 
94 static status_t
usb_raw_device_removed(void * cookie)95 usb_raw_device_removed(void *cookie)
96 {
97 	TRACE((DRIVER_NAME": device_removed(0x%p)\n", cookie));
98 	raw_device *device = (raw_device *)cookie;
99 
100 	// cancel all pending transfers to make sure no one keeps waiting forever
101 	// in syscalls.
102 	const usb_configuration_info *configurationInfo =
103 		gUSBModule->get_configuration(device->device);
104 	if (configurationInfo != NULL) {
105 		struct usb_interface_info* interface
106 			= configurationInfo->interface->active;
107 		for (unsigned int i = 0; i < interface->endpoint_count; i++)
108 			gUSBModule->cancel_queued_transfers(interface->endpoint[i].handle);
109 	}
110 
111 	mutex_lock(&gDeviceListLock);
112 	if (gDeviceList == device) {
113 		gDeviceList = (raw_device *)device->link;
114 	} else {
115 		raw_device *element = gDeviceList;
116 		while (element) {
117 			if (element->link == device) {
118 				element->link = device->link;
119 				break;
120 			}
121 
122 			element = (raw_device *)element->link;
123 		}
124 	}
125 	gDeviceCount--;
126 	mutex_unlock(&gDeviceListLock);
127 
128 	device->device = 0;
129 	if (device->reference_count == 0) {
130 		mutex_lock(&device->lock);
131 		mutex_destroy(&device->lock);
132 		delete_sem(device->notify);
133 		free(device);
134 	}
135 
136 	return B_OK;
137 }
138 
139 
140 //
141 //#pragma mark -
142 //
143 
144 
145 static const usb_configuration_info *
usb_raw_get_configuration(raw_device * device,uint32 configIndex,status_t * status)146 usb_raw_get_configuration(raw_device *device, uint32 configIndex,
147 	status_t *status)
148 {
149 	const usb_configuration_info *result = gUSBModule->get_nth_configuration(
150 		device->device, configIndex);
151 	if (result == NULL) {
152 		*status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
153 		return NULL;
154 	}
155 
156 	return result;
157 }
158 
159 
160 static const usb_interface_info *
usb_raw_get_interface(raw_device * device,uint32 configIndex,uint32 interfaceIndex,uint32 alternateIndex,status_t * status)161 usb_raw_get_interface(raw_device *device, uint32 configIndex,
162 	uint32 interfaceIndex, uint32 alternateIndex, status_t *status)
163 {
164 	const usb_configuration_info *configurationInfo
165 		= usb_raw_get_configuration(device, configIndex, status);
166 	if (configurationInfo == NULL)
167 		return NULL;
168 
169 	if (interfaceIndex >= configurationInfo->interface_count) {
170 		*status = B_USB_RAW_STATUS_INVALID_INTERFACE;
171 		return NULL;
172 	}
173 
174 	const usb_interface_info *result = NULL;
175 	if (alternateIndex == B_USB_RAW_ACTIVE_ALTERNATE)
176 		result = configurationInfo->interface[interfaceIndex].active;
177 	else {
178 		const usb_interface_list *interfaceList =
179 			&configurationInfo->interface[interfaceIndex];
180 		if (alternateIndex >= interfaceList->alt_count) {
181 			*status = B_USB_RAW_STATUS_INVALID_INTERFACE;
182 			return NULL;
183 		}
184 
185 		result = &interfaceList->alt[alternateIndex];
186 	}
187 
188 	return result;
189 }
190 
191 
192 //
193 //#pragma mark -
194 //
195 
196 
197 static status_t
usb_raw_open(const char * name,uint32 flags,void ** cookie)198 usb_raw_open(const char *name, uint32 flags, void **cookie)
199 {
200 	TRACE((DRIVER_NAME": open()\n"));
201 	mutex_lock(&gDeviceListLock);
202 	raw_device *element = gDeviceList;
203 	while (element) {
204 		if (strcmp(name, element->name) == 0) {
205 			element->reference_count++;
206 			*cookie = element;
207 			mutex_unlock(&gDeviceListLock);
208 			return B_OK;
209 		}
210 
211 		element = (raw_device *)element->link;
212 	}
213 
214 	mutex_unlock(&gDeviceListLock);
215 	return B_NAME_NOT_FOUND;
216 }
217 
218 
219 static status_t
usb_raw_close(void * cookie)220 usb_raw_close(void *cookie)
221 {
222 	TRACE((DRIVER_NAME": close()\n"));
223 	return B_OK;
224 }
225 
226 
227 static status_t
usb_raw_free(void * cookie)228 usb_raw_free(void *cookie)
229 {
230 	TRACE((DRIVER_NAME": free()\n"));
231 	mutex_lock(&gDeviceListLock);
232 
233 	raw_device *device = (raw_device *)cookie;
234 	device->reference_count--;
235 	if (device->device == 0) {
236 		mutex_lock(&device->lock);
237 		mutex_destroy(&device->lock);
238 		delete_sem(device->notify);
239 		free(device);
240 	}
241 
242 	mutex_unlock(&gDeviceListLock);
243 	return B_OK;
244 }
245 
246 
247 static void
usb_raw_callback(void * cookie,status_t status,void * data,size_t actualLength)248 usb_raw_callback(void *cookie, status_t status, void *data, size_t actualLength)
249 {
250 	TRACE((DRIVER_NAME": callback()\n"));
251 	raw_device *device = (raw_device *)cookie;
252 
253 	switch (status) {
254 		case B_OK:
255 			device->status = B_USB_RAW_STATUS_SUCCESS;
256 			break;
257 		case B_TIMED_OUT:
258 			device->status = B_USB_RAW_STATUS_TIMEOUT;
259 			break;
260 		case B_CANCELED:
261 			device->status = B_USB_RAW_STATUS_ABORTED;
262 			break;
263 		case B_DEV_CRC_ERROR:
264 			device->status = B_USB_RAW_STATUS_CRC_ERROR;
265 			break;
266 		case B_DEV_STALLED:
267 			device->status = B_USB_RAW_STATUS_STALLED;
268 			break;
269 		default:
270 			device->status = B_USB_RAW_STATUS_FAILED;
271 			break;
272 	}
273 
274 	device->actual_length = actualLength;
275 	release_sem(device->notify);
276 }
277 
278 
279 static status_t
usb_raw_ioctl(void * cookie,uint32 op,void * buffer,size_t length)280 usb_raw_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
281 {
282 	TRACE((DRIVER_NAME": ioctl\n"));
283 	raw_device *device = (raw_device *)cookie;
284 	if (device->device == 0)
285 		return B_DEV_NOT_READY;
286 
287 	usb_raw_command command;
288 	if (length < sizeof(command.version.status))
289 		return B_BUFFER_OVERFLOW;
290 	if (!IS_USER_ADDRESS(buffer)
291 		|| user_memcpy(&command, buffer, min_c(length, sizeof(command)))
292 			!= B_OK) {
293 		return B_BAD_ADDRESS;
294 	}
295 
296 	command.version.status = B_USB_RAW_STATUS_ABORTED;
297 	status_t status = B_DEV_INVALID_IOCTL;
298 
299 	switch (op) {
300 		case B_USB_RAW_COMMAND_GET_VERSION:
301 		{
302 			command.version.status = B_USB_RAW_PROTOCOL_VERSION;
303 			status = B_OK;
304 			break;
305 		}
306 
307 		case B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR:
308 		{
309 			if (length < sizeof(command.device))
310 				return B_BUFFER_OVERFLOW;
311 
312 			status = B_OK;
313 			const usb_device_descriptor *deviceDescriptor =
314 				gUSBModule->get_device_descriptor(device->device);
315 			if (deviceDescriptor == NULL)
316 				return B_OK;
317 
318 			if (!IS_USER_ADDRESS(command.device.descriptor)
319 				|| user_memcpy(command.device.descriptor, deviceDescriptor,
320 					sizeof(usb_device_descriptor)) != B_OK) {
321 				return B_BAD_ADDRESS;
322 			}
323 
324 			command.device.status = B_USB_RAW_STATUS_SUCCESS;
325 			break;
326 		}
327 
328 		case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR:
329 		case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC:
330 		{
331 			if (op == B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC
332 					&& length < sizeof(command.config_etc))
333 				return B_BUFFER_OVERFLOW;
334 
335 			if (length < sizeof(command.config))
336 				return B_BUFFER_OVERFLOW;
337 
338 			status = B_OK;
339 			const usb_configuration_info *configurationInfo =
340 				usb_raw_get_configuration(device, command.config.config_index,
341 					&command.config.status);
342 			if (configurationInfo == NULL)
343 				break;
344 
345 			size_t sizeToCopy = sizeof(usb_configuration_descriptor);
346 			if (op == B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC) {
347 				sizeToCopy = std::min(command.config_etc.length,
348 					(size_t)configurationInfo->descr->total_length);
349 			}
350 
351 			if (!IS_USER_ADDRESS(command.config.descriptor)
352 				|| user_memcpy(command.config.descriptor,
353 					configurationInfo->descr, sizeToCopy) != B_OK) {
354 				return B_BAD_ADDRESS;
355 			}
356 
357 			command.config.status = B_USB_RAW_STATUS_SUCCESS;
358 			break;
359 		}
360 
361 		case B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT:
362 		case B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX:
363 		{
364 			if (length < sizeof(command.alternate))
365 				return B_BUFFER_OVERFLOW;
366 
367 			status = B_OK;
368 			const usb_configuration_info *configurationInfo =
369 				usb_raw_get_configuration(device,
370 					command.alternate.config_index,
371 					&command.alternate.status);
372 			if (configurationInfo == NULL)
373 				break;
374 
375 			if (command.alternate.interface_index
376 				>= configurationInfo->interface_count) {
377 				command.alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
378 				break;
379 			}
380 
381 			const usb_interface_list *interfaceList
382 				= &configurationInfo->interface[
383 					command.alternate.interface_index];
384 			if (op == B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT) {
385 				command.alternate.alternate_info = interfaceList->alt_count;
386 			} else {
387 				for (size_t i = 0; i < interfaceList->alt_count; i++) {
388 					if (&interfaceList->alt[i] == interfaceList->active) {
389 						command.alternate.alternate_info = i;
390 						break;
391 					}
392 				}
393 			}
394 
395 			command.alternate.status = B_USB_RAW_STATUS_SUCCESS;
396 			break;
397 		}
398 
399 		case B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR:
400 		case B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC:
401 		{
402 			const usb_interface_info *interfaceInfo = NULL;
403 			status = B_OK;
404 			if (op == B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR) {
405 				if (length < sizeof(command.interface))
406 					return B_BUFFER_OVERFLOW;
407 
408 				interfaceInfo = usb_raw_get_interface(device,
409 					command.interface.config_index,
410 					command.interface.interface_index,
411 					B_USB_RAW_ACTIVE_ALTERNATE,
412 					&command.interface.status);
413 			} else {
414 				if (length < sizeof(command.interface_etc))
415 					return B_BUFFER_OVERFLOW;
416 
417 				interfaceInfo = usb_raw_get_interface(device,
418 					command.interface_etc.config_index,
419 					command.interface_etc.interface_index,
420 					command.interface_etc.alternate_index,
421 					&command.interface_etc.status);
422 			}
423 
424 			if (interfaceInfo == NULL)
425 				break;
426 
427 			if (!IS_USER_ADDRESS(command.interface.descriptor)
428 				|| user_memcpy(command.interface.descriptor, interfaceInfo->descr,
429 					sizeof(usb_interface_descriptor)) != B_OK) {
430 				return B_BAD_ADDRESS;
431 			}
432 
433 			command.interface.status = B_USB_RAW_STATUS_SUCCESS;
434 			break;
435 		}
436 
437 		case B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR:
438 		case B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC:
439 		{
440 			uint32 endpointIndex = 0;
441 			const usb_interface_info *interfaceInfo = NULL;
442 			status = B_OK;
443 			if (op == B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR) {
444 				if (length < sizeof(command.endpoint))
445 					return B_BUFFER_OVERFLOW;
446 
447 				interfaceInfo = usb_raw_get_interface(device,
448 					command.endpoint.config_index,
449 					command.endpoint.interface_index,
450 					B_USB_RAW_ACTIVE_ALTERNATE,
451 					&command.endpoint.status);
452 				endpointIndex = command.endpoint.endpoint_index;
453 			} else {
454 				if (length < sizeof(command.endpoint_etc))
455 					return B_BUFFER_OVERFLOW;
456 
457 				interfaceInfo = usb_raw_get_interface(device,
458 					command.endpoint_etc.config_index,
459 					command.endpoint_etc.interface_index,
460 					command.endpoint_etc.alternate_index,
461 					&command.endpoint_etc.status);
462 				endpointIndex = command.endpoint_etc.endpoint_index;
463 			}
464 
465 			if (interfaceInfo == NULL)
466 				break;
467 
468 			if (endpointIndex >= interfaceInfo->endpoint_count) {
469 				command.endpoint.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
470 				break;
471 			}
472 
473 			if (!IS_USER_ADDRESS(command.endpoint.descriptor)
474 				|| user_memcpy(command.endpoint.descriptor,
475 					interfaceInfo->endpoint[endpointIndex].descr,
476 					sizeof(usb_endpoint_descriptor)) != B_OK) {
477 				return B_BAD_ADDRESS;
478 			}
479 
480 			command.endpoint.status = B_USB_RAW_STATUS_SUCCESS;
481 			break;
482 		}
483 
484 		case B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR:
485 		case B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC:
486 		{
487 			uint32 genericIndex = 0;
488 			size_t genericLength = 0;
489 			const usb_interface_info *interfaceInfo = NULL;
490 			status = B_OK;
491 			if (op == B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR) {
492 				if (length < sizeof(command.generic))
493 					return B_BUFFER_OVERFLOW;
494 
495 				interfaceInfo = usb_raw_get_interface(device,
496 					command.generic.config_index,
497 					command.generic.interface_index,
498 					B_USB_RAW_ACTIVE_ALTERNATE,
499 					&command.generic.status);
500 				genericIndex = command.generic.generic_index;
501 				genericLength = command.generic.length;
502 			} else {
503 				if (length < sizeof(command.generic_etc))
504 					return B_BUFFER_OVERFLOW;
505 
506 				interfaceInfo = usb_raw_get_interface(device,
507 					command.generic_etc.config_index,
508 					command.generic_etc.interface_index,
509 					command.generic_etc.alternate_index,
510 					&command.generic_etc.status);
511 				genericIndex = command.generic_etc.generic_index;
512 				genericLength = command.generic_etc.length;
513 			}
514 
515 			if (interfaceInfo == NULL)
516 				break;
517 
518 			if (genericIndex >= interfaceInfo->generic_count) {
519 				command.endpoint.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
520 				break;
521 			}
522 
523 			usb_descriptor *descriptor = interfaceInfo->generic[genericIndex];
524 			if (descriptor == NULL)
525 				break;
526 
527 			if (!IS_USER_ADDRESS(command.generic.descriptor)
528 				|| user_memcpy(command.generic.descriptor, descriptor,
529 					min_c(genericLength, descriptor->generic.length)) != B_OK) {
530 				return B_BAD_ADDRESS;
531 			}
532 
533 			if (descriptor->generic.length > genericLength)
534 				command.generic.status = B_USB_RAW_STATUS_NO_MEMORY;
535 			else
536 				command.generic.status = B_USB_RAW_STATUS_SUCCESS;
537 			break;
538 		}
539 
540 		case B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR:
541 		{
542 			if (length < sizeof(command.string))
543 				return B_BUFFER_OVERFLOW;
544 
545 			size_t actualLength = 0;
546 			uint8 temp[4];
547 			status = B_OK;
548 
549 			// We need to fetch the default language code, first.
550 			if (gUSBModule->get_descriptor(device->device,
551 				USB_DESCRIPTOR_STRING, 0, 0,
552 				temp, 4, &actualLength) < B_OK
553 				|| actualLength != 4
554 				|| temp[1] != USB_DESCRIPTOR_STRING) {
555 				command.string.status = B_USB_RAW_STATUS_ABORTED;
556 				command.string.length = 0;
557 				break;
558 			}
559 			const uint16 langid = (temp[2] | (temp[3] << 8));
560 
561 			// Now fetch the string length.
562 			if (gUSBModule->get_descriptor(device->device,
563 				USB_DESCRIPTOR_STRING, command.string.string_index, langid,
564 				temp, 2, &actualLength) < B_OK
565 				|| actualLength != 2
566 				|| temp[1] != USB_DESCRIPTOR_STRING) {
567 				command.string.status = B_USB_RAW_STATUS_ABORTED;
568 				command.string.length = 0;
569 				break;
570 			}
571 
572 			uint8 stringLength = MIN(temp[0], command.string.length);
573 			char *string = (char *)malloc(stringLength);
574 			if (string == NULL) {
575 				command.string.status = B_USB_RAW_STATUS_ABORTED;
576 				command.string.length = 0;
577 				status = B_NO_MEMORY;
578 				break;
579 			}
580 
581 			if (gUSBModule->get_descriptor(device->device,
582 				USB_DESCRIPTOR_STRING, command.string.string_index, langid,
583 				string, stringLength, &actualLength) < B_OK
584 				|| actualLength != stringLength) {
585 				command.string.status = B_USB_RAW_STATUS_ABORTED;
586 				command.string.length = 0;
587 				free(string);
588 				break;
589 			}
590 
591 			if (!IS_USER_ADDRESS(command.string.descriptor)
592 				|| user_memcpy(command.string.descriptor, string,
593 					stringLength) != B_OK) {
594 				free(string);
595 				return B_BAD_ADDRESS;
596 			}
597 
598 			command.string.status = B_USB_RAW_STATUS_SUCCESS;
599 			command.string.length = stringLength;
600 			free(string);
601 			break;
602 		}
603 
604 		case B_USB_RAW_COMMAND_GET_DESCRIPTOR:
605 		{
606 			if (length < sizeof(command.descriptor))
607 				return B_BUFFER_OVERFLOW;
608 
609 			size_t actualLength = 0;
610 			uint8 firstTwoBytes[2];
611 			status = B_OK;
612 
613 			if (gUSBModule->get_descriptor(device->device,
614 				command.descriptor.type, command.descriptor.index,
615 				command.descriptor.language_id, firstTwoBytes, 2,
616 				&actualLength) < B_OK
617 				|| actualLength != 2
618 				|| firstTwoBytes[1] != command.descriptor.type) {
619 				command.descriptor.status = B_USB_RAW_STATUS_ABORTED;
620 				command.descriptor.length = 0;
621 				break;
622 			}
623 
624 			uint8 descriptorLength = MIN(firstTwoBytes[0],
625 				command.descriptor.length);
626 			uint8 *descriptorBuffer = (uint8 *)malloc(descriptorLength);
627 			if (descriptorBuffer == NULL) {
628 				command.descriptor.status = B_USB_RAW_STATUS_ABORTED;
629 				command.descriptor.length = 0;
630 				status = B_NO_MEMORY;
631 				break;
632 			}
633 
634 			if (gUSBModule->get_descriptor(device->device,
635 				command.descriptor.type, command.descriptor.index,
636 				command.descriptor.language_id, descriptorBuffer,
637 				descriptorLength, &actualLength) < B_OK
638 				|| actualLength != descriptorLength) {
639 				command.descriptor.status = B_USB_RAW_STATUS_ABORTED;
640 				command.descriptor.length = 0;
641 				free(descriptorBuffer);
642 				break;
643 			}
644 
645 			if (!IS_USER_ADDRESS(command.descriptor.data)
646 				|| user_memcpy(command.descriptor.data, descriptorBuffer,
647 					descriptorLength) != B_OK) {
648 				free(descriptorBuffer);
649 				return B_BAD_ADDRESS;
650 			}
651 
652 			command.descriptor.status = B_USB_RAW_STATUS_SUCCESS;
653 			command.descriptor.length = descriptorLength;
654 			free(descriptorBuffer);
655 			break;
656 		}
657 
658 		case B_USB_RAW_COMMAND_SET_CONFIGURATION:
659 		{
660 			if (length < sizeof(command.config))
661 				return B_BUFFER_OVERFLOW;
662 
663 			status = B_OK;
664 			const usb_configuration_info *configurationInfo =
665 				usb_raw_get_configuration(device, command.config.config_index,
666 					&command.config.status);
667 			if (configurationInfo == NULL)
668 				break;
669 
670 			if (gUSBModule->set_configuration(device->device,
671 				configurationInfo) < B_OK) {
672 				command.config.status = B_USB_RAW_STATUS_FAILED;
673 				break;
674 			}
675 
676 			command.config.status = B_USB_RAW_STATUS_SUCCESS;
677 			break;
678 		}
679 
680 		case B_USB_RAW_COMMAND_SET_ALT_INTERFACE:
681 		{
682 			if (length < sizeof(command.alternate))
683 				return B_BUFFER_OVERFLOW;
684 
685 			status = B_OK;
686 			const usb_configuration_info *configurationInfo =
687 				usb_raw_get_configuration(device,
688 					command.alternate.config_index,
689 					&command.alternate.status);
690 			if (configurationInfo == NULL)
691 				break;
692 
693 			if (command.alternate.interface_index
694 				>= configurationInfo->interface_count) {
695 				command.alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
696 				break;
697 			}
698 
699 			const usb_interface_list *interfaceList =
700 				&configurationInfo->interface[command.alternate.interface_index];
701 			if (command.alternate.alternate_info >= interfaceList->alt_count) {
702 				command.alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
703 				break;
704 			}
705 
706 			if (gUSBModule->set_alt_interface(device->device,
707 				&interfaceList->alt[command.alternate.alternate_info]) < B_OK) {
708 				command.alternate.status = B_USB_RAW_STATUS_FAILED;
709 				break;
710 			}
711 
712 			command.alternate.status = B_USB_RAW_STATUS_SUCCESS;
713 			break;
714 		}
715 
716 		case B_USB_RAW_COMMAND_CONTROL_TRANSFER:
717 		{
718 			if (length < sizeof(command.control))
719 				return B_BUFFER_OVERFLOW;
720 
721 			void *controlData = malloc(command.control.length);
722 			if (controlData == NULL)
723 				return B_NO_MEMORY;
724 			MemoryDeleter dataDeleter(controlData);
725 
726 			bool inTransfer = (command.control.request_type
727 				& USB_ENDPOINT_ADDR_DIR_IN) != 0;
728 			if (!IS_USER_ADDRESS(command.control.data)
729 				|| (!inTransfer && user_memcpy(controlData,
730 					command.control.data, command.control.length) != B_OK)) {
731 				return B_BAD_ADDRESS;
732 			}
733 
734 			MutexLocker deviceLocker(device->lock);
735 			if (gUSBModule->queue_request(device->device,
736 				command.control.request_type, command.control.request,
737 				command.control.value, command.control.index,
738 				command.control.length, controlData,
739 				usb_raw_callback, device) < B_OK) {
740 				command.control.status = B_USB_RAW_STATUS_FAILED;
741 				command.control.length = 0;
742 				status = B_OK;
743 				break;
744 			}
745 
746 			status = acquire_sem_etc(device->notify, 1, B_KILL_CAN_INTERRUPT, 0);
747 			if (status != B_OK) {
748 				gUSBModule->cancel_queued_requests(device->device);
749 				acquire_sem(device->notify);
750 			}
751 
752 			command.control.status = device->status;
753 			command.control.length = device->actual_length;
754 			deviceLocker.Unlock();
755 
756 			if (command.control.status == B_OK)
757 				status = B_OK;
758 			if (inTransfer && user_memcpy(command.control.data, controlData,
759 				command.control.length) != B_OK) {
760 				status = B_BAD_ADDRESS;
761 			}
762 			break;
763 		}
764 
765 		case B_USB_RAW_COMMAND_INTERRUPT_TRANSFER:
766 		case B_USB_RAW_COMMAND_BULK_TRANSFER:
767 		case B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER:
768 		{
769 			if (length < sizeof(command.transfer))
770 				return B_BUFFER_OVERFLOW;
771 
772 			status = B_OK;
773 			const usb_configuration_info *configurationInfo =
774 				gUSBModule->get_configuration(device->device);
775 			if (configurationInfo == NULL) {
776 				command.transfer.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION;
777 				break;
778 			}
779 
780 			if (command.transfer.interface >= configurationInfo->interface_count) {
781 				command.transfer.status = B_USB_RAW_STATUS_INVALID_INTERFACE;
782 				break;
783 			}
784 
785 			const usb_interface_info *interfaceInfo =
786 				configurationInfo->interface[command.transfer.interface].active;
787 			if (interfaceInfo == NULL) {
788 				command.transfer.status = B_USB_RAW_STATUS_ABORTED;
789 				break;
790 			}
791 
792 			if (command.transfer.endpoint >= interfaceInfo->endpoint_count) {
793 				command.transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
794 				break;
795 			}
796 
797 			const usb_endpoint_info *endpointInfo =
798 				&interfaceInfo->endpoint[command.transfer.endpoint];
799 			if (!endpointInfo->handle) {
800 				command.transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT;
801 				break;
802 			}
803 
804 			size_t descriptorsSize = 0;
805 			usb_iso_packet_descriptor *packetDescriptors = NULL;
806 			void *transferData = NULL;
807 			MemoryDeleter descriptorsDeleter, dataDeleter;
808 
809 			bool inTransfer = (endpointInfo->descr->endpoint_address
810 				& USB_ENDPOINT_ADDR_DIR_IN) != 0;
811 			if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) {
812 				if (length < sizeof(command.isochronous))
813 					return B_BUFFER_OVERFLOW;
814 
815 				descriptorsSize = sizeof(usb_iso_packet_descriptor)
816 					* command.isochronous.packet_count;
817 				packetDescriptors
818 					= (usb_iso_packet_descriptor *)malloc(descriptorsSize);
819 				if (packetDescriptors == NULL) {
820 					command.transfer.status = B_USB_RAW_STATUS_NO_MEMORY;
821 					command.transfer.length = 0;
822 					break;
823 				}
824 				descriptorsDeleter.SetTo(packetDescriptors);
825 
826 				if (!IS_USER_ADDRESS(command.isochronous.data)
827 					|| !IS_USER_ADDRESS(command.isochronous.packet_descriptors)
828 					|| user_memcpy(packetDescriptors,
829 						command.isochronous.packet_descriptors,
830 						descriptorsSize) != B_OK) {
831 					return B_BAD_ADDRESS;
832 				}
833 			} else {
834 				transferData = malloc(command.transfer.length);
835 				if (transferData == NULL) {
836 					command.transfer.status = B_USB_RAW_STATUS_NO_MEMORY;
837 					command.transfer.length = 0;
838 					break;
839 				}
840 				dataDeleter.SetTo(transferData);
841 
842 				if (!IS_USER_ADDRESS(command.transfer.data) || (!inTransfer
843 						&& user_memcpy(transferData, command.transfer.data,
844 							command.transfer.length) != B_OK)) {
845 					return B_BAD_ADDRESS;
846 				}
847 			}
848 
849 			status_t status;
850 			MutexLocker deviceLocker(device->lock);
851 			if (op == B_USB_RAW_COMMAND_INTERRUPT_TRANSFER) {
852 				status = gUSBModule->queue_interrupt(endpointInfo->handle,
853 					transferData, command.transfer.length,
854 					usb_raw_callback, device);
855 			} else if (op == B_USB_RAW_COMMAND_BULK_TRANSFER) {
856 				status = gUSBModule->queue_bulk(endpointInfo->handle,
857 					transferData, command.transfer.length,
858 					usb_raw_callback, device);
859 			} else {
860 				status = gUSBModule->queue_isochronous(endpointInfo->handle,
861 					command.isochronous.data, command.isochronous.length,
862 					packetDescriptors, command.isochronous.packet_count, NULL,
863 					0, usb_raw_callback, device);
864 			}
865 
866 			if (status < B_OK) {
867 				command.transfer.status = B_USB_RAW_STATUS_FAILED;
868 				command.transfer.length = 0;
869 				status = B_OK;
870 				break;
871 			}
872 
873 			status = acquire_sem_etc(device->notify, 1, B_KILL_CAN_INTERRUPT, 0);
874 			if (status != B_OK) {
875 				gUSBModule->cancel_queued_transfers(endpointInfo->handle);
876 				acquire_sem(device->notify);
877 			}
878 
879 			command.transfer.status = device->status;
880 			command.transfer.length = device->actual_length;
881 			deviceLocker.Unlock();
882 
883 			if (command.transfer.status == B_OK)
884 				status = B_OK;
885 			if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) {
886 				if (user_memcpy(command.isochronous.packet_descriptors,
887 						packetDescriptors, descriptorsSize) != B_OK) {
888 					status = B_BAD_ADDRESS;
889 				}
890 			} else {
891 				if (inTransfer && user_memcpy(command.transfer.data,
892 					transferData, command.transfer.length) != B_OK) {
893 					status = B_BAD_ADDRESS;
894 				}
895 			}
896 
897 			break;
898 		}
899 	}
900 
901 	if (user_memcpy(buffer, &command, min_c(length, sizeof(command))) != B_OK)
902 		return B_BAD_ADDRESS;
903 
904 	return status;
905 }
906 
907 
908 static status_t
usb_raw_read(void * cookie,off_t position,void * buffer,size_t * length)909 usb_raw_read(void *cookie, off_t position, void *buffer, size_t *length)
910 {
911 	TRACE((DRIVER_NAME": read()\n"));
912 	*length = 0;
913 	return B_OK;
914 }
915 
916 
917 static status_t
usb_raw_write(void * cookie,off_t position,const void * buffer,size_t * length)918 usb_raw_write(void *cookie, off_t position, const void *buffer, size_t *length)
919 {
920 	TRACE((DRIVER_NAME": write()\n"));
921 	*length = 0;
922 	return B_OK;
923 }
924 
925 
926 //
927 //#pragma mark -
928 //
929 
930 
931 status_t
init_hardware()932 init_hardware()
933 {
934 	TRACE((DRIVER_NAME": init_hardware()\n"));
935 	return B_OK;
936 }
937 
938 
939 status_t
init_driver()940 init_driver()
941 {
942 	TRACE((DRIVER_NAME": init_driver()\n"));
943 	static usb_notify_hooks notifyHooks = {
944 		&usb_raw_device_added,
945 		&usb_raw_device_removed
946 	};
947 
948 	gDeviceList = NULL;
949 	gDeviceCount = 0;
950 	mutex_init(&gDeviceListLock, "usb_raw device list lock");
951 
952 	TRACE((DRIVER_NAME": trying module %s\n", B_USB_MODULE_NAME));
953 	status_t result = get_module(B_USB_MODULE_NAME,
954 		(module_info **)&gUSBModule);
955 	if (result < B_OK) {
956 		TRACE((DRIVER_NAME": getting module failed 0x%08" B_PRIx32 "\n",
957 			result));
958 		mutex_destroy(&gDeviceListLock);
959 		return result;
960 	}
961 
962 	gUSBModule->register_driver(DRIVER_NAME, NULL, 0, NULL);
963 	gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
964 	return B_OK;
965 }
966 
967 
968 void
uninit_driver()969 uninit_driver()
970 {
971 	TRACE((DRIVER_NAME": uninit_driver()\n"));
972 	gUSBModule->uninstall_notify(DRIVER_NAME);
973 	mutex_lock(&gDeviceListLock);
974 
975 	if (gDeviceNames) {
976 		for (int32 i = 1; gDeviceNames[i]; i++)
977 			free(gDeviceNames[i]);
978 		free(gDeviceNames);
979 		gDeviceNames = NULL;
980 	}
981 
982 	mutex_destroy(&gDeviceListLock);
983 	put_module(B_USB_MODULE_NAME);
984 }
985 
986 
987 const char **
publish_devices()988 publish_devices()
989 {
990 	TRACE((DRIVER_NAME": publish_devices()\n"));
991 	if (gDeviceNames) {
992 		for (int32 i = 0; gDeviceNames[i]; i++)
993 			free(gDeviceNames[i]);
994 		free(gDeviceNames);
995 		gDeviceNames = NULL;
996 	}
997 
998 	int32 index = 0;
999 	gDeviceNames = (char **)malloc(sizeof(char *) * (gDeviceCount + 2));
1000 	if (gDeviceNames == NULL)
1001 		return NULL;
1002 
1003 	gDeviceNames[index++] = strdup(DEVICE_NAME);
1004 
1005 	mutex_lock(&gDeviceListLock);
1006 	raw_device *element = gDeviceList;
1007 	while (element) {
1008 		gDeviceNames[index++] = strdup(element->name);
1009 		element = (raw_device *)element->link;
1010 	}
1011 
1012 	gDeviceNames[index++] = NULL;
1013 	mutex_unlock(&gDeviceListLock);
1014 	return (const char **)gDeviceNames;
1015 }
1016 
1017 
1018 device_hooks *
find_device(const char * name)1019 find_device(const char *name)
1020 {
1021 	TRACE((DRIVER_NAME": find_device()\n"));
1022 	static device_hooks hooks = {
1023 		&usb_raw_open,
1024 		&usb_raw_close,
1025 		&usb_raw_free,
1026 		&usb_raw_ioctl,
1027 		&usb_raw_read,
1028 		&usb_raw_write,
1029 		NULL,
1030 		NULL,
1031 		NULL,
1032 		NULL
1033 	};
1034 
1035 	return &hooks;
1036 }
1037