[175] | 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 |
|
---|
| 44 | typedef 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 |
|
---|
| 55 | static 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 |
|
---|
| 65 | static int _usb_setup_async(usb_dev_handle *dev, void **context,
|
---|
| 66 | DWORD control_code,
|
---|
| 67 | unsigned char ep, int pktsize);
|
---|
| 68 | static int _usb_transfer_sync(usb_dev_handle *dev, int control_code,
|
---|
| 69 | int ep, int pktsize, char *bytes, int size,
|
---|
| 70 | int timeout);
|
---|
| 71 |
|
---|
| 72 | static int usb_get_configuration(usb_dev_handle *dev, bool_t cached);
|
---|
| 73 | static int _usb_cancel_io(usb_context_t *context);
|
---|
| 74 | static int _usb_abort_ep(usb_dev_handle *dev, unsigned int ep);
|
---|
| 75 |
|
---|
| 76 | static int _usb_io_sync(HANDLE dev, unsigned int code, void *in, int in_size,
|
---|
| 77 | void *out, int out_size, int *ret);
|
---|
| 78 | static int _usb_reap_async(void *context, int timeout, int cancel);
|
---|
| 79 | static int _usb_add_virtual_hub(struct usb_bus *bus);
|
---|
| 80 |
|
---|
| 81 | static void _usb_free_bus_list(struct usb_bus *bus);
|
---|
| 82 | static void _usb_free_dev_list(struct usb_device *dev);
|
---|
| 83 | static void _usb_deinit(void);
|
---|
| 84 |
|
---|
| 85 | /* DLL main entry point */
|
---|
| 86 | BOOL 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 |
|
---|
| 106 | static 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 |
|
---|
| 142 | int 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 |
|
---|
| 199 | int 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 |
|
---|
| 217 | int 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 |
|
---|
| 256 | int 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 |
|
---|
| 294 | int 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 |
|
---|
| 328 | int 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 |
|
---|
| 369 | static 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 |
|
---|
| 420 | int 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 |
|
---|
| 473 | static 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 |
|
---|
| 505 | int usb_reap_async(void *context, int timeout)
|
---|
| 506 | {
|
---|
| 507 | return _usb_reap_async(context, timeout, TRUE);
|
---|
| 508 | }
|
---|
| 509 |
|
---|
| 510 | int usb_reap_async_nocancel(void *context, int timeout)
|
---|
| 511 | {
|
---|
| 512 | return _usb_reap_async(context, timeout, FALSE);
|
---|
| 513 | }
|
---|
| 514 |
|
---|
| 515 |
|
---|
| 516 | int 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 |
|
---|
| 541 | int 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 |
|
---|
| 559 | static 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 |
|
---|
| 611 | int 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 |
|
---|
| 618 | int 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 |
|
---|
| 625 | int 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 |
|
---|
| 632 | int 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 |
|
---|
| 639 | int 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 |
|
---|
| 650 | int 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 |
|
---|
| 660 | int 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 |
|
---|
| 671 | int 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 |
|
---|
| 818 | int 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 |
|
---|
| 842 | int 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 |
|
---|
| 912 | void 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 |
|
---|
| 977 | int 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 |
|
---|
| 1007 | int 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 |
|
---|
| 1031 | int 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 |
|
---|
| 1053 | int 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 |
|
---|
| 1076 | const struct usb_version *usb_get_version(void)
|
---|
| 1077 | {
|
---|
| 1078 | return &_usb_version;
|
---|
| 1079 | }
|
---|
| 1080 |
|
---|
| 1081 | void 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 |
|
---|
| 1128 | int 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 |
|
---|
| 1155 | static 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 |
|
---|
| 1163 | static 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 |
|
---|
| 1186 | static 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 |
|
---|
| 1223 | static 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 |
|
---|
| 1257 | static 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 |
|
---|
| 1269 | static 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 |
|
---|
| 1278 | static void _usb_deinit(void)
|
---|
| 1279 | {
|
---|
| 1280 | _usb_free_bus_list(usb_get_busses());
|
---|
| 1281 | }
|
---|