source: trunk/kitgen/8.x/libusb-win32/windows.c@ 201

Last change on this file since 201 was 175, checked in by demin, 12 years ago

initial commit

File size: 32.9 KB
Line 
1/* libusb-win32, Generic Windows USB Library
2 * Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
3 * Copyright (c) 2000-2005 Johannes Erdfelt <johannes@erdfelt.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
21#include <stdlib.h>
22#include <string.h>
23#include <stdio.h>
24#include <errno.h>
25#include <ctype.h>
26#include <windows.h>
27#include <winioctl.h>
28#include <setupapi.h>
29
30#include "lusb0_usb.h"
31#include "error.h"
32#include "usbi.h"
33#include "driver_api.h"
34#include "registry.h"
35#include "libusb-win32_version.h"
36
37#define LIBUSB_WIN32_DLL_LARGE_TRANSFER_SUPPORT
38
39#define LIBUSB_DEFAULT_TIMEOUT 5000
40#define LIBUSB_DEVICE_NAME "\\\\.\\libusb0-"
41#define LIBUSB_BUS_NAME "bus-0"
42#define LIBUSB_MAX_DEVICES 256
43
44typedef struct
45{
46 usb_dev_handle *dev;
47 libusb_request req;
48 char *bytes;
49 int size;
50 DWORD control_code;
51 OVERLAPPED ol;
52} usb_context_t;
53
54
55static struct usb_version _usb_version =
56{
57 { VERSION_MAJOR,
58 VERSION_MINOR,
59 VERSION_MICRO,
60 VERSION_NANO },
61 { -1, -1, -1, -1 }
62};
63
64
65static int _usb_setup_async(usb_dev_handle *dev, void **context,
66 DWORD control_code,
67 unsigned char ep, int pktsize);
68static int _usb_transfer_sync(usb_dev_handle *dev, int control_code,
69 int ep, int pktsize, char *bytes, int size,
70 int timeout);
71
72static int usb_get_configuration(usb_dev_handle *dev, bool_t cached);
73static int _usb_cancel_io(usb_context_t *context);
74static int _usb_abort_ep(usb_dev_handle *dev, unsigned int ep);
75
76static int _usb_io_sync(HANDLE dev, unsigned int code, void *in, int in_size,
77 void *out, int out_size, int *ret);
78static int _usb_reap_async(void *context, int timeout, int cancel);
79static int _usb_add_virtual_hub(struct usb_bus *bus);
80
81static void _usb_free_bus_list(struct usb_bus *bus);
82static void _usb_free_dev_list(struct usb_device *dev);
83static void _usb_deinit(void);
84
85/* DLL main entry point */
86BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID reserved)
87{
88 switch (reason)
89 {
90 case DLL_PROCESS_ATTACH:
91 break;
92 case DLL_PROCESS_DETACH:
93 _usb_deinit();
94 break;
95 case DLL_THREAD_ATTACH:
96 break;
97 case DLL_THREAD_DETACH:
98 break;
99 default:
100 break;
101 }
102 return TRUE;
103}
104
105
106static int usb_get_configuration(usb_dev_handle *dev, bool_t cached)
107{
108 int ret;
109 char config;
110 libusb_request request;
111
112 if (cached)
113 {
114 memset(&request, 0, sizeof(request));
115 request.timeout = LIBUSB_DEFAULT_TIMEOUT;
116
117 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_GET_CACHED_CONFIGURATION,
118 &request, sizeof(request), &request, sizeof(request), &ret))
119 {
120 USBERR("sending get cached configuration ioctl failed, win error: %s\n", usb_win_error_to_string());
121 ret = -usb_win_error_to_errno();
122 }
123
124 if (ret < 1)
125 ret = -EINVAL;
126 else
127 config = *((char*)&request);
128 }
129 else
130 {
131 ret = usb_control_msg(dev, USB_RECIP_DEVICE | USB_ENDPOINT_IN,
132 USB_REQ_GET_CONFIGURATION, 0, 0, &config, 1,
133 LIBUSB_DEFAULT_TIMEOUT);
134 }
135
136 if(ret < 0)
137 return ret;
138
139 return config;
140}
141
142int usb_os_open(usb_dev_handle *dev)
143{
144 char dev_name[LIBUSB_PATH_MAX];
145 char *p;
146 int config;
147 if (!dev)
148 {
149 USBERR("invalid device handle %p", dev);
150 return -EINVAL;
151 }
152
153 dev->impl_info = INVALID_HANDLE_VALUE;
154 dev->config = 0;
155 dev->interface = -1;
156 dev->altsetting = -1;
157
158 if (!dev->device->filename)
159 {
160 USBERR0("invalid file name\n");
161 return -ENOENT;
162 }
163
164 /* build the Windows file name from the unique device name */
165 strcpy(dev_name, dev->device->filename);
166
167 p = strstr(dev_name, "--");
168
169 if (!p)
170 {
171 USBERR("invalid file name %s\n", dev->device->filename);
172 return -ENOENT;
173 }
174
175 *p = 0;
176
177 dev->impl_info = CreateFile(dev_name, 0, 0, NULL, OPEN_EXISTING,
178 FILE_FLAG_OVERLAPPED, NULL);
179
180 if (dev->impl_info == INVALID_HANDLE_VALUE)
181 {
182 USBERR("failed to open %s: win error: %s",
183 dev->device->filename, usb_win_error_to_string());
184 return -ENOENT;
185 }
186
187 // get the cached configuration (no device i/o)
188 config = usb_get_configuration(dev, TRUE);
189 if (config > 0)
190 {
191 dev->config = config;
192 dev->interface = -1;
193 dev->altsetting = -1;
194 }
195
196 return 0;
197}
198
199int usb_os_close(usb_dev_handle *dev)
200{
201 if (dev->impl_info != INVALID_HANDLE_VALUE)
202 {
203 if (dev->interface >= 0)
204 {
205 usb_release_interface(dev, dev->interface);
206 }
207
208 CloseHandle(dev->impl_info);
209 dev->impl_info = INVALID_HANDLE_VALUE;
210 dev->interface = -1;
211 dev->altsetting = -1;
212 }
213
214 return 0;
215}
216
217int usb_set_configuration(usb_dev_handle *dev, int configuration)
218{
219 libusb_request req;
220
221 if (dev->impl_info == INVALID_HANDLE_VALUE)
222 {
223 USBERR0("error: device not open\n");
224 return -EINVAL;
225 }
226
227 if (dev->config == configuration)
228 {
229 return 0;
230 }
231
232 if (dev->interface >= 0)
233 {
234 USBERR0("can't change configuration, an interface is still in use (claimed)\n");
235 return -EINVAL;
236 }
237
238 req.configuration.configuration = configuration;
239 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
240
241 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_SET_CONFIGURATION,
242 &req, sizeof(libusb_request), NULL, 0, NULL))
243 {
244 USBERR("could not set config %d: "
245 "win error: %s", configuration, usb_win_error_to_string());
246 return -usb_win_error_to_errno();
247 }
248
249 dev->config = configuration;
250 dev->interface = -1;
251 dev->altsetting = -1;
252
253 return 0;
254}
255
256int usb_claim_interface(usb_dev_handle *dev, int interface)
257{
258 libusb_request req;
259
260 if (dev->impl_info == INVALID_HANDLE_VALUE)
261 {
262 USBERR0("device not open\n");
263 return -EINVAL;
264 }
265
266 if (!dev->config)
267 {
268 USBERR("could not claim interface %d, invalid configuration %d\n", interface, dev->config);
269 return -EINVAL;
270 }
271
272 if (dev->interface == interface)
273 {
274 return 0;
275 }
276
277 req.intf.interface_number = interface;
278
279 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_CLAIM_INTERFACE,
280 &req, sizeof(libusb_request), NULL, 0, NULL))
281 {
282 USBERR("could not claim interface %d, "
283 "win error: %s", interface, usb_win_error_to_string());
284 return -usb_win_error_to_errno();
285 }
286 else
287 {
288 dev->interface = interface;
289 dev->altsetting = 0;
290 return 0;
291 }
292}
293
294int usb_release_interface(usb_dev_handle *dev, int interface)
295{
296 libusb_request req;
297
298 if (dev->impl_info == INVALID_HANDLE_VALUE)
299 {
300 USBERR0("device not open\n");
301 return -EINVAL;
302 }
303
304 if (!dev->config)
305 {
306 USBERR("could not release interface %d, invalid configuration %d\n", interface, dev->config);
307 return -EINVAL;
308 }
309
310 req.intf.interface_number = interface;
311
312 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_RELEASE_INTERFACE,
313 &req, sizeof(libusb_request), NULL, 0, NULL))
314 {
315 USBERR("could not release interface %d, "
316 "win error: %s", interface, usb_win_error_to_string());
317 return -usb_win_error_to_errno();
318 }
319 else
320 {
321 dev->interface = -1;
322 dev->altsetting = -1;
323
324 return 0;
325 }
326}
327
328int usb_set_altinterface(usb_dev_handle *dev, int alternate)
329{
330 libusb_request req;
331
332 if (dev->impl_info == INVALID_HANDLE_VALUE)
333 {
334 USBERR0("device not open\n");
335 return -EINVAL;
336 }
337
338 if (dev->config <= 0)
339 {
340 USBERR("could not set alt interface %d: invalid configuration %d\n", alternate, dev->config);
341 return -EINVAL;
342 }
343
344 if (dev->interface < 0)
345 {
346 USBERR("could not set alt interface %d: no interface claimed\n", alternate);
347 return -EINVAL;
348 }
349
350 req.intf.interface_number = dev->interface;
351 req.intf.altsetting_number = alternate;
352 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
353
354 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_SET_INTERFACE,
355 &req, sizeof(libusb_request),
356 NULL, 0, NULL))
357 {
358 USBERR("could not set alt interface "
359 "%d/%d: win error: %s",
360 dev->interface, alternate, usb_win_error_to_string());
361 return -usb_win_error_to_errno();
362 }
363
364 dev->altsetting = alternate;
365
366 return 0;
367}
368
369static int _usb_setup_async(usb_dev_handle *dev, void **context,
370 DWORD control_code,
371 unsigned char ep, int pktsize)
372{
373 usb_context_t **c = (usb_context_t **)context;
374
375 if (((control_code == LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE)
376 || (control_code == LIBUSB_IOCTL_ISOCHRONOUS_WRITE))
377 && (ep & USB_ENDPOINT_IN))
378 {
379 USBERR("invalid endpoint 0x%02x", ep);
380 return -EINVAL;
381 }
382
383 if (((control_code == LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ)
384 || (control_code == LIBUSB_IOCTL_ISOCHRONOUS_READ))
385 && !(ep & USB_ENDPOINT_IN))
386 {
387 USBERR("invalid endpoint 0x%02x\n", ep);
388 return -EINVAL;
389 }
390
391 *c = malloc(sizeof(usb_context_t));
392
393 if (!*c)
394 {
395 USBERR0("memory allocation error\n");
396 return -ENOMEM;
397 }
398
399 memset(*c, 0, sizeof(usb_context_t));
400
401 (*c)->dev = dev;
402 (*c)->req.endpoint.endpoint = ep;
403 (*c)->req.endpoint.packet_size = pktsize;
404 (*c)->control_code = control_code;
405
406 (*c)->ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
407
408 if (!(*c)->ol.hEvent)
409 {
410 free(*c);
411 *c = NULL;
412 USBERR("creating event failed: win error: %s",
413 usb_win_error_to_string());
414 return -usb_win_error_to_errno();
415 }
416
417 return 0;
418}
419
420int usb_submit_async(void *context, char *bytes, int size)
421{
422 usb_context_t *c = (usb_context_t *)context;
423
424 if (!c)
425 {
426 USBERR0("invalid context");
427 return -EINVAL;
428 }
429
430 if (c->dev->impl_info == INVALID_HANDLE_VALUE)
431 {
432 USBERR0("device not open\n");
433 return -EINVAL;
434 }
435
436 if (c->dev->config <= 0)
437 {
438 USBERR("invalid configuration %d\n", c->dev->config);
439 return -EINVAL;
440 }
441
442 if (c->dev->interface < 0)
443 {
444 USBERR("invalid interface %d\n", c->dev->interface);
445 return -EINVAL;
446 }
447
448
449 c->ol.Offset = 0;
450 c->ol.OffsetHigh = 0;
451 c->bytes = bytes;
452 c->size = size;
453
454 ResetEvent(c->ol.hEvent);
455
456 if (!DeviceIoControl(c->dev->impl_info,
457 c->control_code,
458 &c->req, sizeof(libusb_request),
459 c->bytes,
460 c->size, NULL, &c->ol))
461 {
462 if (GetLastError() != ERROR_IO_PENDING)
463 {
464 USBERR("submitting request failed, "
465 "win error: %s", usb_win_error_to_string());
466 return -usb_win_error_to_errno();
467 }
468 }
469
470 return 0;
471}
472
473static int _usb_reap_async(void *context, int timeout, int cancel)
474{
475 usb_context_t *c = (usb_context_t *)context;
476 ULONG ret = 0;
477
478 if (!c)
479 {
480 USBERR0("invalid context\n");
481 return -EINVAL;
482 }
483
484 if (WaitForSingleObject(c->ol.hEvent, timeout) == WAIT_TIMEOUT)
485 {
486 /* request timed out */
487 if (cancel)
488 {
489 _usb_cancel_io(c);
490 }
491
492 USBERR0("timeout error\n");
493 return -ETRANSFER_TIMEDOUT;
494 }
495
496 if (!GetOverlappedResult(c->dev->impl_info, &c->ol, &ret, TRUE))
497 {
498 USBERR("reaping request failed, win error: %s\n",usb_win_error_to_string());
499 return -usb_win_error_to_errno();
500 }
501
502 return ret;
503}
504
505int usb_reap_async(void *context, int timeout)
506{
507 return _usb_reap_async(context, timeout, TRUE);
508}
509
510int usb_reap_async_nocancel(void *context, int timeout)
511{
512 return _usb_reap_async(context, timeout, FALSE);
513}
514
515
516int usb_cancel_async(void *context)
517{
518 /* NOTE that this function will cancel all pending URBs */
519 /* on the same endpoint as this particular context, or even */
520 /* all pending URBs for this particular device. */
521
522 usb_context_t *c = (usb_context_t *)context;
523
524 if (!c)
525 {
526 USBERR0("invalid context\n");
527 return -EINVAL;
528 }
529
530 if (c->dev->impl_info == INVALID_HANDLE_VALUE)
531 {
532 USBERR0("device not open\n");
533 return -EINVAL;
534 }
535
536 _usb_cancel_io(c);
537
538 return 0;
539}
540
541int usb_free_async(void **context)
542{
543 usb_context_t **c = (usb_context_t **)context;
544
545 if (!*c)
546 {
547 USBERR0("invalid context\n");
548 return -EINVAL;
549 }
550
551 CloseHandle((*c)->ol.hEvent);
552
553 free(*c);
554 *c = NULL;
555
556 return 0;
557}
558
559static int _usb_transfer_sync(usb_dev_handle *dev, int control_code,
560 int ep, int pktsize, char *bytes, int size,
561 int timeout)
562{
563 void *context = NULL;
564 int transmitted = 0;
565 int ret;
566 int requested;
567
568 if (!timeout) timeout=INFINITE;
569 ret = _usb_setup_async(dev, &context, control_code, (unsigned char )ep,
570 pktsize);
571
572 if (ret < 0)
573 {
574 return ret;
575 }
576
577 do
578 {
579#ifdef LIBUSB_WIN32_DLL_LARGE_TRANSFER_SUPPORT
580 requested = size > LIBUSB_MAX_READ_WRITE ? LIBUSB_MAX_READ_WRITE : size;
581#else
582 requested = size;
583#endif
584 ret = usb_submit_async(context, bytes, requested);
585
586 if (ret < 0)
587 {
588 transmitted = ret;
589 break;
590 }
591
592 ret = usb_reap_async(context, timeout);
593
594 if (ret < 0)
595 {
596 transmitted = ret;
597 break;
598 }
599
600 transmitted += ret;
601 bytes += ret;
602 size -= ret;
603 }
604 while (size > 0 && ret == requested);
605
606 usb_free_async(&context);
607
608 return transmitted;
609}
610
611int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
612 int timeout)
613{
614 return _usb_transfer_sync(dev, LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE,
615 ep, 0, bytes, size, timeout);
616}
617
618int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
619 int timeout)
620{
621 return _usb_transfer_sync(dev, LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ,
622 ep, 0, bytes, size, timeout);
623}
624
625int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
626 int timeout)
627{
628 return _usb_transfer_sync(dev, LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE,
629 ep, 0, bytes, size, timeout);
630}
631
632int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
633 int timeout)
634{
635 return _usb_transfer_sync(dev, LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ,
636 ep, 0, bytes, size, timeout);
637}
638
639int usb_isochronous_setup_async(usb_dev_handle *dev, void **context,
640 unsigned char ep, int pktsize)
641{
642 if (ep & 0x80)
643 return _usb_setup_async(dev, context, LIBUSB_IOCTL_ISOCHRONOUS_READ,
644 ep, pktsize);
645 else
646 return _usb_setup_async(dev, context, LIBUSB_IOCTL_ISOCHRONOUS_WRITE,
647 ep, pktsize);
648}
649
650int usb_bulk_setup_async(usb_dev_handle *dev, void **context, unsigned char ep)
651{
652 if (ep & 0x80)
653 return _usb_setup_async(dev, context, LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ,
654 ep, 0);
655 else
656 return _usb_setup_async(dev, context, LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE,
657 ep, 0);
658}
659
660int usb_interrupt_setup_async(usb_dev_handle *dev, void **context,
661 unsigned char ep)
662{
663 if (ep & 0x80)
664 return _usb_setup_async(dev, context, LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ,
665 ep, 0);
666 else
667 return _usb_setup_async(dev, context, LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE,
668 ep, 0);
669}
670
671int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
672 int value, int index, char *bytes, int size, int timeout)
673{
674 int read = 0;
675 libusb_request req;
676 void *out = &req;
677 int out_size = sizeof(libusb_request);
678 void *in = bytes;
679 int in_size = size;
680 int code;
681
682 if (dev->impl_info == INVALID_HANDLE_VALUE)
683 {
684 USBERR0("device not open\n");
685 return -EINVAL;
686 }
687
688 req.timeout = timeout;
689
690 /* windows doesn't support generic control messages, so it needs to be */
691 /* split up */
692 switch (requesttype & (0x03 << 5))
693 {
694 case USB_TYPE_STANDARD:
695 switch (request)
696 {
697 case USB_REQ_GET_STATUS:
698 req.status.recipient = requesttype & 0x1F;
699 req.status.index = index;
700 code = LIBUSB_IOCTL_GET_STATUS;
701 break;
702
703 case USB_REQ_CLEAR_FEATURE:
704 req.feature.recipient = requesttype & 0x1F;
705 req.feature.feature = value;
706 req.feature.index = index;
707 code = LIBUSB_IOCTL_CLEAR_FEATURE;
708 break;
709
710 case USB_REQ_SET_FEATURE:
711 req.feature.recipient = requesttype & 0x1F;
712 req.feature.feature = value;
713 req.feature.index = index;
714 code = LIBUSB_IOCTL_SET_FEATURE;
715 break;
716
717 case USB_REQ_GET_DESCRIPTOR:
718 req.descriptor.recipient = requesttype & 0x1F;
719 req.descriptor.type = (value >> 8) & 0xFF;
720 req.descriptor.index = value & 0xFF;
721 req.descriptor.language_id = index;
722 code = LIBUSB_IOCTL_GET_DESCRIPTOR;
723 break;
724
725 case USB_REQ_SET_DESCRIPTOR:
726 req.descriptor.recipient = requesttype & 0x1F;
727 req.descriptor.type = (value >> 8) & 0xFF;
728 req.descriptor.index = value & 0xFF;
729 req.descriptor.language_id = index;
730 code = LIBUSB_IOCTL_SET_DESCRIPTOR;
731 break;
732
733 case USB_REQ_GET_CONFIGURATION:
734 code = LIBUSB_IOCTL_GET_CONFIGURATION;
735 break;
736
737 case USB_REQ_SET_CONFIGURATION:
738 req.configuration.configuration = value;
739 code = LIBUSB_IOCTL_SET_CONFIGURATION;
740 break;
741
742 case USB_REQ_GET_INTERFACE:
743 req.intf.interface_number = index;
744 code = LIBUSB_IOCTL_GET_INTERFACE;
745 break;
746
747 case USB_REQ_SET_INTERFACE:
748 req.intf.interface_number = index;
749 req.intf.altsetting_number = value;
750 code = LIBUSB_IOCTL_SET_INTERFACE;
751 break;
752
753 default:
754 USBERR("invalid request 0x%x", request);
755 return -EINVAL;
756 }
757 break;
758
759 case USB_TYPE_VENDOR:
760 case USB_TYPE_CLASS:
761
762 req.vendor.type = (requesttype >> 5) & 0x03;
763 req.vendor.recipient = requesttype & 0x1F;
764 req.vendor.request = request;
765 req.vendor.value = value;
766 req.vendor.index = index;
767
768 if (requesttype & 0x80)
769 code = LIBUSB_IOCTL_VENDOR_READ;
770 else
771 code = LIBUSB_IOCTL_VENDOR_WRITE;
772 break;
773
774 case USB_TYPE_RESERVED:
775 default:
776 USBERR("invalid or unsupported request type: %x",
777 requesttype);
778 return -EINVAL;
779 }
780
781 /* out request? */
782 if (!(requesttype & USB_ENDPOINT_IN))
783 {
784 if (!(out = malloc(sizeof(libusb_request) + size)))
785 {
786 USBERR0("memory allocation failed\n");
787 return -ENOMEM;
788 }
789
790 memcpy(out, &req, sizeof(libusb_request));
791 memcpy((char *)out + sizeof(libusb_request), bytes, size);
792 out_size = sizeof(libusb_request) + size;
793 in = NULL;
794 in_size = 0;
795 }
796
797 if (!_usb_io_sync(dev->impl_info, code, out, out_size, in, in_size, &read))
798 {
799 USBERR("sending control message failed, win error: %s\n", usb_win_error_to_string());
800 if (!(requesttype & USB_ENDPOINT_IN))
801 {
802 free(out);
803 }
804 return -usb_win_error_to_errno();
805 }
806
807 /* out request? */
808 if (!(requesttype & USB_ENDPOINT_IN))
809 {
810 free(out);
811 return size;
812 }
813 else
814 return read;
815}
816
817
818int usb_os_find_busses(struct usb_bus **busses)
819{
820 struct usb_bus *bus = NULL;
821
822 /* create one 'virtual' bus */
823
824 bus = malloc(sizeof(struct usb_bus));
825
826 if (!bus)
827 {
828 USBERR0("memory allocation failed\n");
829 return -ENOMEM;
830 }
831
832 memset(bus, 0, sizeof(*bus));
833 strcpy(bus->dirname, LIBUSB_BUS_NAME);
834
835 USBMSG("found %s\n", bus->dirname);
836
837 *busses = bus;
838
839 return 0;
840}
841
842int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
843{
844 int i;
845 struct usb_device *dev, *fdev = NULL;
846 char dev_name[LIBUSB_PATH_MAX];
847 int ret;
848 HANDLE handle;
849 libusb_request req;
850
851 for (i = 1; i < LIBUSB_MAX_DEVICES; i++)
852 {
853 ret = 0;
854
855 _snprintf(dev_name, sizeof(dev_name) - 1,"%s%04d",
856 LIBUSB_DEVICE_NAME, i);
857
858 if (!(dev = malloc(sizeof(*dev))))
859 {
860 USBERR0("memory allocation failed\n");
861 return -ENOMEM;
862 }
863
864 memset(dev, 0, sizeof(*dev));
865 dev->bus = bus;
866 dev->devnum = (unsigned char)i;
867
868 handle = CreateFile(dev_name, 0, 0, NULL, OPEN_EXISTING,
869 FILE_FLAG_OVERLAPPED, NULL);
870
871 if (handle == INVALID_HANDLE_VALUE)
872 {
873 free(dev);
874 continue;
875 }
876
877 /* retrieve device descriptor */
878 req.descriptor.type = USB_DT_DEVICE;
879 req.descriptor.recipient = USB_RECIP_DEVICE;
880 req.descriptor.index = 0;
881 req.descriptor.language_id = 0;
882 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
883
884 _usb_io_sync(handle, LIBUSB_IOCTL_GET_DESCRIPTOR,
885 &req, sizeof(libusb_request),
886 &dev->descriptor, USB_DT_DEVICE_SIZE, &ret);
887
888 if (ret < USB_DT_DEVICE_SIZE)
889 {
890 USBERR0("couldn't read device descriptor\n");
891 free(dev);
892 CloseHandle(handle);
893 continue;
894 }
895
896 _snprintf(dev->filename, LIBUSB_PATH_MAX - 1, "%s--0x%04x-0x%04x",
897 dev_name, dev->descriptor.idVendor, dev->descriptor.idProduct);
898
899 CloseHandle(handle);
900
901 LIST_ADD(fdev, dev);
902
903 USBMSG("found %s on %s\n", dev->filename, bus->dirname);
904 }
905
906 *devices = fdev;
907
908 return 0;
909}
910
911
912void usb_os_init(void)
913{
914 HANDLE dev;
915 libusb_request req;
916 int i;
917 int ret;
918 char dev_name[LIBUSB_PATH_MAX];
919
920 USBMSG("dll version: %d.%d.%d.%d\n",
921 VERSION_MAJOR, VERSION_MINOR,
922 VERSION_MICRO, VERSION_NANO);
923
924
925 for (i = 1; i < LIBUSB_MAX_DEVICES; i++)
926 {
927 /* build the Windows file name */
928 _snprintf(dev_name, sizeof(dev_name) - 1,"%s%04d",
929 LIBUSB_DEVICE_NAME, i);
930
931 dev = CreateFile(dev_name, 0, 0, NULL, OPEN_EXISTING,
932 FILE_FLAG_OVERLAPPED, NULL);
933
934 if (dev == INVALID_HANDLE_VALUE)
935 {
936 continue;
937 }
938
939 if (!_usb_io_sync(dev, LIBUSB_IOCTL_GET_VERSION,
940 &req, sizeof(libusb_request),
941 &req, sizeof(libusb_request), &ret)
942 || (ret < sizeof(libusb_request)))
943 {
944 USBERR0("getting driver version failed\n");
945 CloseHandle(dev);
946 continue;
947 }
948 else
949 {
950 _usb_version.driver.major = req.version.major;
951 _usb_version.driver.minor = req.version.minor;
952 _usb_version.driver.micro = req.version.micro;
953 _usb_version.driver.nano = req.version.nano;
954
955 USBMSG("driver version: %d.%d.%d.%d\n",
956 req.version.major, req.version.minor,
957 req.version.micro, req.version.nano);
958
959 /* set debug level */
960 req.timeout = 0;
961 req.debug.level = usb_log_get_level();
962
963 if (!_usb_io_sync(dev, LIBUSB_IOCTL_SET_DEBUG_LEVEL,
964 &req, sizeof(libusb_request),
965 NULL, 0, NULL))
966 {
967 USBERR0("setting debug level failed");
968 }
969
970 CloseHandle(dev);
971 break;
972 }
973 }
974}
975
976
977int usb_resetep(usb_dev_handle *dev, unsigned int ep)
978{
979 libusb_request req;
980
981 if (dev->impl_info == INVALID_HANDLE_VALUE)
982 {
983 USBERR0("device not open\n");
984 return -EINVAL;
985 }
986
987 req.endpoint.endpoint = (int)ep;
988 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
989
990 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_ABORT_ENDPOINT, &req,
991 sizeof(libusb_request), NULL, 0, NULL))
992 {
993 USBERR("could not abort ep 0x%02x, win error: %s\n", ep, usb_win_error_to_string());
994 return -usb_win_error_to_errno();
995 }
996
997 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_RESET_ENDPOINT, &req,
998 sizeof(libusb_request), NULL, 0, NULL))
999 {
1000 USBERR("could not reset ep 0x%02x, win error: %s\n", ep, usb_win_error_to_string());
1001 return -usb_win_error_to_errno();
1002 }
1003
1004 return 0;
1005}
1006
1007int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
1008{
1009 libusb_request req;
1010
1011 if (dev->impl_info == INVALID_HANDLE_VALUE)
1012 {
1013 USBERR0("device not open\n");
1014 return -EINVAL;
1015 }
1016
1017 req.endpoint.endpoint = (int)ep;
1018 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
1019
1020 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_RESET_ENDPOINT, &req,
1021 sizeof(libusb_request), NULL, 0, NULL))
1022 {
1023 USBERR("could not clear halt, ep 0x%02x, "
1024 "win error: %s", ep, usb_win_error_to_string());
1025 return -usb_win_error_to_errno();
1026 }
1027
1028 return 0;
1029}
1030
1031int usb_reset(usb_dev_handle *dev)
1032{
1033 libusb_request req;
1034
1035 if (dev->impl_info == INVALID_HANDLE_VALUE)
1036 {
1037 USBERR0("device not open\n");
1038 return -EINVAL;
1039 }
1040
1041 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
1042
1043 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_RESET_DEVICE,
1044 &req, sizeof(libusb_request), NULL, 0, NULL))
1045 {
1046 USBERR("could not reset device, win error: %s\n", usb_win_error_to_string());
1047 return -usb_win_error_to_errno();
1048 }
1049
1050 return 0;
1051}
1052
1053int usb_reset_ex(usb_dev_handle *dev, unsigned int reset_type)
1054{
1055 libusb_request req;
1056
1057 if (dev->impl_info == INVALID_HANDLE_VALUE)
1058 {
1059 USBERR0("device not open\n");
1060 return -EINVAL;
1061 }
1062
1063 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
1064 req.reset_ex.reset_type = reset_type;
1065
1066 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_RESET_DEVICE_EX,
1067 &req, sizeof(libusb_request), NULL, 0, NULL))
1068 {
1069 USBERR("could not reset device, win error: %s\n", usb_win_error_to_string());
1070 return -usb_win_error_to_errno();
1071 }
1072
1073 return 0;
1074}
1075
1076const struct usb_version *usb_get_version(void)
1077{
1078 return &_usb_version;
1079}
1080
1081void usb_set_debug(int level)
1082{
1083 HANDLE dev;
1084 libusb_request req;
1085 int i;
1086 char dev_name[LIBUSB_PATH_MAX];
1087
1088 if (usb_log_get_level() || level)
1089 {
1090 USBMSG("setting debugging level to %d (%s)\n",
1091 level, level ? "on" : "off");
1092 }
1093
1094 usb_log_set_level(level);
1095
1096 /* find a valid device */
1097 for (i = 1; i < LIBUSB_MAX_DEVICES; i++)
1098 {
1099 /* build the Windows file name */
1100 _snprintf(dev_name, sizeof(dev_name) - 1,"%s%04d",
1101 LIBUSB_DEVICE_NAME, i);
1102
1103 dev = CreateFile(dev_name, 0, 0, NULL, OPEN_EXISTING,
1104 FILE_FLAG_OVERLAPPED, NULL);
1105
1106 if (dev == INVALID_HANDLE_VALUE)
1107 {
1108 continue;
1109 }
1110
1111 /* set debug level */
1112 req.timeout = 0;
1113 req.debug.level = usb_log_get_level();
1114
1115 if (!_usb_io_sync(dev, LIBUSB_IOCTL_SET_DEBUG_LEVEL,
1116 &req, sizeof(libusb_request),
1117 NULL, 0, NULL))
1118 {
1119 USBERR0("setting debug level failed\n");
1120 }
1121
1122 CloseHandle(dev);
1123
1124 break;
1125 }
1126}
1127
1128int usb_os_determine_children(struct usb_bus *bus)
1129{
1130 struct usb_device *dev;
1131 int i = 0;
1132
1133 /* add a virtual hub to the bus to emulate this feature */
1134 if (_usb_add_virtual_hub(bus))
1135 {
1136 if (bus->root_dev->children)
1137 {
1138 free(bus->root_dev->children);
1139 }
1140
1141 bus->root_dev->num_children = 0;
1142 for (dev = bus->devices; dev; dev = dev->next)
1143 bus->root_dev->num_children++;
1144
1145 bus->root_dev->children
1146 = malloc(sizeof(struct usb_device *) * bus->root_dev->num_children);
1147
1148 for (dev = bus->devices; dev; dev = dev->next)
1149 bus->root_dev->children[i++] = dev;
1150 }
1151
1152 return 0;
1153}
1154
1155static int _usb_cancel_io(usb_context_t *context)
1156{
1157 int ret;
1158 ret = _usb_abort_ep(context->dev, context->req.endpoint.endpoint);
1159 WaitForSingleObject(context->ol.hEvent, 0);
1160 return ret;
1161}
1162
1163static int _usb_abort_ep(usb_dev_handle *dev, unsigned int ep)
1164{
1165 libusb_request req;
1166
1167 if (dev->impl_info == INVALID_HANDLE_VALUE)
1168 {
1169 USBERR0("device not open");
1170 return -EINVAL;
1171 }
1172
1173 req.endpoint.endpoint = (int)ep;
1174 req.timeout = LIBUSB_DEFAULT_TIMEOUT;
1175
1176 if (!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_ABORT_ENDPOINT, &req,
1177 sizeof(libusb_request), NULL, 0, NULL))
1178 {
1179 USBERR("could not abort ep 0x%02x, win error: %s\n", ep, usb_win_error_to_string());
1180 return -usb_win_error_to_errno();
1181 }
1182
1183 return 0;
1184}
1185
1186static int _usb_io_sync(HANDLE dev, unsigned int code, void *out, int out_size,
1187 void *in, int in_size, int *ret)
1188{
1189 OVERLAPPED ol;
1190 DWORD _ret;
1191
1192 memset(&ol, 0, sizeof(ol));
1193
1194 if (ret)
1195 *ret = 0;
1196
1197 ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1198
1199 if (!ol.hEvent)
1200 return FALSE;
1201
1202 if (!DeviceIoControl(dev, code, out, out_size, in, in_size, NULL, &ol))
1203 {
1204 if (GetLastError() != ERROR_IO_PENDING)
1205 {
1206 CloseHandle(ol.hEvent);
1207 return FALSE;
1208 }
1209 }
1210
1211 if (GetOverlappedResult(dev, &ol, &_ret, TRUE))
1212 {
1213 if (ret)
1214 *ret = (int)_ret;
1215 CloseHandle(ol.hEvent);
1216 return TRUE;
1217 }
1218
1219 CloseHandle(ol.hEvent);
1220 return FALSE;
1221}
1222
1223static int _usb_add_virtual_hub(struct usb_bus *bus)
1224{
1225 struct usb_device *dev;
1226
1227 if (!bus->root_dev)
1228 {
1229 if (!(dev = malloc(sizeof(*dev))))
1230 return FALSE;
1231
1232 memset(dev, 0, sizeof(*dev));
1233 strcpy(dev->filename, "virtual-hub");
1234 dev->bus = bus;
1235
1236 dev->descriptor.bLength = USB_DT_DEVICE_SIZE;
1237 dev->descriptor.bDescriptorType = USB_DT_DEVICE;
1238 dev->descriptor.bcdUSB = 0x0200;
1239 dev->descriptor.bDeviceClass = USB_CLASS_HUB;
1240 dev->descriptor.bDeviceSubClass = 0;
1241 dev->descriptor.bDeviceProtocol = 0;
1242 dev->descriptor.bMaxPacketSize0 = 64;
1243 dev->descriptor.idVendor = 0;
1244 dev->descriptor.idProduct = 0;
1245 dev->descriptor.bcdDevice = 0x100;
1246 dev->descriptor.iManufacturer = 0;
1247 dev->descriptor.iProduct = 0;
1248 dev->descriptor.iSerialNumber = 0;
1249 dev->descriptor.bNumConfigurations = 0;
1250
1251 bus->root_dev = dev;
1252 }
1253
1254 return TRUE;
1255}
1256
1257static void _usb_free_bus_list(struct usb_bus *bus)
1258{
1259 if (bus)
1260 {
1261 _usb_free_bus_list(bus->next);
1262 if (bus->root_dev)
1263 usb_free_dev(bus->root_dev);
1264 _usb_free_dev_list(bus->devices);
1265 usb_free_bus(bus);
1266 }
1267}
1268
1269static void _usb_free_dev_list(struct usb_device *dev)
1270{
1271 if (dev)
1272 {
1273 _usb_free_dev_list(dev->next);
1274 usb_free_dev(dev);
1275 }
1276}
1277
1278static void _usb_deinit(void)
1279{
1280 _usb_free_bus_list(usb_get_busses());
1281}
Note: See TracBrowser for help on using the repository browser.