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, ¬ifyHooks);
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