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
35typedef 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
48int32 api_version = B_CUR_DRIVER_API_VERSION;
49static usb_module_info *gUSBModule = NULL;
50static raw_device *gDeviceList = NULL;
51static uint32 gDeviceCount = 0;
52static mutex gDeviceListLock;
53static char **gDeviceNames = NULL;
54
55static status_t
56usb_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
94static status_t
95usb_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
145static const usb_configuration_info *
146usb_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
160static const usb_interface_info *
161usb_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
197static status_t
198usb_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
219static status_t
220usb_raw_close(void *cookie)
221{
222	TRACE((DRIVER_NAME": close()\n"));
223	return B_OK;
224}
225
226
227static status_t
228usb_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
247static void
248usb_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
279static status_t
280usb_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
908static status_t
909usb_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
917static status_t
918usb_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
931status_t
932init_hardware()
933{
934	TRACE((DRIVER_NAME": init_hardware()\n"));
935	return B_OK;
936}
937
938
939status_t
940init_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
968void
969uninit_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
987const char **
988publish_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
1018device_hooks *
1019find_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