1 /* 2 * Copyright 2011 Martin Pieuchot <mpi (at) openbsd.org> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 #include <config.h> 20 21 #include <sys/time.h> 22 #include <sys/types.h> 23 24 #include <errno.h> 25 #include <fcntl.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include <dev/usb/usb.h> 32 33 #include "libusbi.h" 34 35 struct device_priv { 36 char devnode[16]; 37 int fd; 38 39 unsigned char *cdesc; /* active config descriptor */ 40 usb_device_descriptor_t ddesc; /* usb device descriptor */ 41 }; 42 43 struct handle_priv { 44 int endpoints[USB_MAX_ENDPOINTS]; 45 }; 46 47 /* 48 * Backend functions 49 */ 50 static int netbsd_get_device_list(struct libusb_context *, 51 struct discovered_devs **); 52 static int netbsd_open(struct libusb_device_handle *); 53 static void netbsd_close(struct libusb_device_handle *); 54 55 static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *, 56 int *); 57 static int netbsd_get_active_config_descriptor(struct libusb_device *, 58 unsigned char *, size_t, int *); 59 static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t, 60 unsigned char *, size_t, int *); 61 62 static int netbsd_get_configuration(struct libusb_device_handle *, int *); 63 static int netbsd_set_configuration(struct libusb_device_handle *, int); 64 65 static int netbsd_claim_interface(struct libusb_device_handle *, int); 66 static int netbsd_release_interface(struct libusb_device_handle *, int); 67 68 static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int, 69 int); 70 static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char); 71 static int netbsd_reset_device(struct libusb_device_handle *); 72 static void netbsd_destroy_device(struct libusb_device *); 73 74 static int netbsd_submit_transfer(struct usbi_transfer *); 75 static int netbsd_cancel_transfer(struct usbi_transfer *); 76 static void netbsd_clear_transfer_priv(struct usbi_transfer *); 77 static int netbsd_handle_transfer_completion(struct usbi_transfer *); 78 static int netbsd_clock_gettime(int, struct timespec *); 79 80 /* 81 * Private functions 82 */ 83 static int _errno_to_libusb(int); 84 static int _cache_active_config_descriptor(struct libusb_device *, int); 85 static int _sync_control_transfer(struct usbi_transfer *); 86 static int _sync_gen_transfer(struct usbi_transfer *); 87 static int _access_endpoint(struct libusb_transfer *); 88 89 const struct usbi_os_backend netbsd_backend = { 90 "Synchronous NetBSD backend", 91 0, 92 NULL, /* init() */ 93 NULL, /* exit() */ 94 netbsd_get_device_list, 95 NULL, /* hotplug_poll */ 96 netbsd_open, 97 netbsd_close, 98 99 netbsd_get_device_descriptor, 100 netbsd_get_active_config_descriptor, 101 netbsd_get_config_descriptor, 102 NULL, /* get_config_descriptor_by_value() */ 103 104 netbsd_get_configuration, 105 netbsd_set_configuration, 106 107 netbsd_claim_interface, 108 netbsd_release_interface, 109 110 netbsd_set_interface_altsetting, 111 netbsd_clear_halt, 112 netbsd_reset_device, 113 114 NULL, /* alloc_streams */ 115 NULL, /* free_streams */ 116 117 NULL, /* dev_mem_alloc() */ 118 NULL, /* dev_mem_free() */ 119 120 NULL, /* kernel_driver_active() */ 121 NULL, /* detach_kernel_driver() */ 122 NULL, /* attach_kernel_driver() */ 123 124 netbsd_destroy_device, 125 126 netbsd_submit_transfer, 127 netbsd_cancel_transfer, 128 netbsd_clear_transfer_priv, 129 130 NULL, /* handle_events() */ 131 netbsd_handle_transfer_completion, 132 133 netbsd_clock_gettime, 134 sizeof(struct device_priv), 135 sizeof(struct handle_priv), 136 0, /* transfer_priv_size */ 137 }; 138 139 int 140 netbsd_get_device_list(struct libusb_context * ctx, 141 struct discovered_devs **discdevs) 142 { 143 struct libusb_device *dev; 144 struct device_priv *dpriv; 145 struct usb_device_info di; 146 unsigned long session_id; 147 char devnode[16]; 148 int fd, err, i; 149 150 usbi_dbg(""); 151 152 /* Only ugen(4) is supported */ 153 for (i = 0; i < USB_MAX_DEVICES; i++) { 154 /* Control endpoint is always .00 */ 155 snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i); 156 157 if ((fd = open(devnode, O_RDONLY)) < 0) { 158 if (errno != ENOENT && errno != ENXIO) 159 usbi_err(ctx, "could not open %s", devnode); 160 continue; 161 } 162 163 if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0) 164 continue; 165 166 session_id = (di.udi_bus << 8 | di.udi_addr); 167 dev = usbi_get_device_by_session_id(ctx, session_id); 168 169 if (dev == NULL) { 170 dev = usbi_alloc_device(ctx, session_id); 171 if (dev == NULL) 172 return (LIBUSB_ERROR_NO_MEM); 173 174 dev->bus_number = di.udi_bus; 175 dev->device_address = di.udi_addr; 176 dev->speed = di.udi_speed; 177 178 dpriv = (struct device_priv *)dev->os_priv; 179 strlcpy(dpriv->devnode, devnode, sizeof(devnode)); 180 dpriv->fd = -1; 181 182 if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) { 183 err = errno; 184 goto error; 185 } 186 187 dpriv->cdesc = NULL; 188 if (_cache_active_config_descriptor(dev, fd)) { 189 err = errno; 190 goto error; 191 } 192 193 if ((err = usbi_sanitize_device(dev))) 194 goto error; 195 } 196 close(fd); 197 198 if (discovered_devs_append(*discdevs, dev) == NULL) 199 return (LIBUSB_ERROR_NO_MEM); 200 201 libusb_unref_device(dev); 202 } 203 204 return (LIBUSB_SUCCESS); 205 206 error: 207 close(fd); 208 libusb_unref_device(dev); 209 return _errno_to_libusb(err); 210 } 211 212 int 213 netbsd_open(struct libusb_device_handle *handle) 214 { 215 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 216 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 217 218 dpriv->fd = open(dpriv->devnode, O_RDWR); 219 if (dpriv->fd < 0) { 220 dpriv->fd = open(dpriv->devnode, O_RDONLY); 221 if (dpriv->fd < 0) 222 return _errno_to_libusb(errno); 223 } 224 225 usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); 226 227 return (LIBUSB_SUCCESS); 228 } 229 230 void 231 netbsd_close(struct libusb_device_handle *handle) 232 { 233 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 234 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 235 236 usbi_dbg("close: fd %d", dpriv->fd); 237 238 close(dpriv->fd); 239 dpriv->fd = -1; 240 } 241 242 int 243 netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, 244 int *host_endian) 245 { 246 struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 247 248 usbi_dbg(""); 249 250 memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); 251 252 *host_endian = 0; 253 254 return (LIBUSB_SUCCESS); 255 } 256 257 int 258 netbsd_get_active_config_descriptor(struct libusb_device *dev, 259 unsigned char *buf, size_t len, int *host_endian) 260 { 261 struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 262 usb_config_descriptor_t *ucd; 263 264 ucd = (usb_config_descriptor_t *) dpriv->cdesc; 265 len = MIN(len, UGETW(ucd->wTotalLength)); 266 267 usbi_dbg("len %d", len); 268 269 memcpy(buf, dpriv->cdesc, len); 270 271 *host_endian = 0; 272 273 return len; 274 } 275 276 int 277 netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, 278 unsigned char *buf, size_t len, int *host_endian) 279 { 280 struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 281 struct usb_full_desc ufd; 282 int fd, err; 283 284 usbi_dbg("index %d, len %d", idx, len); 285 286 /* A config descriptor may be requested before opening the device */ 287 if (dpriv->fd >= 0) { 288 fd = dpriv->fd; 289 } else { 290 fd = open(dpriv->devnode, O_RDONLY); 291 if (fd < 0) 292 return _errno_to_libusb(errno); 293 } 294 295 ufd.ufd_config_index = idx; 296 ufd.ufd_size = len; 297 ufd.ufd_data = buf; 298 299 if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { 300 err = errno; 301 if (dpriv->fd < 0) 302 close(fd); 303 return _errno_to_libusb(err); 304 } 305 306 if (dpriv->fd < 0) 307 close(fd); 308 309 *host_endian = 0; 310 311 return len; 312 } 313 314 int 315 netbsd_get_configuration(struct libusb_device_handle *handle, int *config) 316 { 317 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 318 319 usbi_dbg(""); 320 321 if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0) 322 return _errno_to_libusb(errno); 323 324 usbi_dbg("configuration %d", *config); 325 326 return (LIBUSB_SUCCESS); 327 } 328 329 int 330 netbsd_set_configuration(struct libusb_device_handle *handle, int config) 331 { 332 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 333 334 usbi_dbg("configuration %d", config); 335 336 if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) 337 return _errno_to_libusb(errno); 338 339 return _cache_active_config_descriptor(handle->dev, dpriv->fd); 340 } 341 342 int 343 netbsd_claim_interface(struct libusb_device_handle *handle, int iface) 344 { 345 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 346 int i; 347 348 for (i = 0; i < USB_MAX_ENDPOINTS; i++) 349 hpriv->endpoints[i] = -1; 350 351 return (LIBUSB_SUCCESS); 352 } 353 354 int 355 netbsd_release_interface(struct libusb_device_handle *handle, int iface) 356 { 357 struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; 358 int i; 359 360 for (i = 0; i < USB_MAX_ENDPOINTS; i++) 361 if (hpriv->endpoints[i] >= 0) 362 close(hpriv->endpoints[i]); 363 364 return (LIBUSB_SUCCESS); 365 } 366 367 int 368 netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, 369 int altsetting) 370 { 371 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 372 struct usb_alt_interface intf; 373 374 usbi_dbg("iface %d, setting %d", iface, altsetting); 375 376 memset(&intf, 0, sizeof(intf)); 377 378 intf.uai_interface_index = iface; 379 intf.uai_alt_no = altsetting; 380 381 if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) 382 return _errno_to_libusb(errno); 383 384 return (LIBUSB_SUCCESS); 385 } 386 387 int 388 netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) 389 { 390 struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; 391 struct usb_ctl_request req; 392 393 usbi_dbg(""); 394 395 req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; 396 req.ucr_request.bRequest = UR_CLEAR_FEATURE; 397 USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); 398 USETW(req.ucr_request.wIndex, endpoint); 399 USETW(req.ucr_request.wLength, 0); 400 401 if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0) 402 return _errno_to_libusb(errno); 403 404 return (LIBUSB_SUCCESS); 405 } 406 407 int 408 netbsd_reset_device(struct libusb_device_handle *handle) 409 { 410 usbi_dbg(""); 411 412 return (LIBUSB_ERROR_NOT_SUPPORTED); 413 } 414 415 void 416 netbsd_destroy_device(struct libusb_device *dev) 417 { 418 struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 419 420 usbi_dbg(""); 421 422 free(dpriv->cdesc); 423 } 424 425 int 426 netbsd_submit_transfer(struct usbi_transfer *itransfer) 427 { 428 struct libusb_transfer *transfer; 429 struct handle_priv *hpriv; 430 int err = 0; 431 432 usbi_dbg(""); 433 434 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 435 hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; 436 437 switch (transfer->type) { 438 case LIBUSB_TRANSFER_TYPE_CONTROL: 439 err = _sync_control_transfer(itransfer); 440 break; 441 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 442 if (IS_XFEROUT(transfer)) { 443 /* Isochronous write is not supported */ 444 err = LIBUSB_ERROR_NOT_SUPPORTED; 445 break; 446 } 447 err = _sync_gen_transfer(itransfer); 448 break; 449 case LIBUSB_TRANSFER_TYPE_BULK: 450 case LIBUSB_TRANSFER_TYPE_INTERRUPT: 451 if (IS_XFEROUT(transfer) && 452 transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { 453 err = LIBUSB_ERROR_NOT_SUPPORTED; 454 break; 455 } 456 err = _sync_gen_transfer(itransfer); 457 break; 458 case LIBUSB_TRANSFER_TYPE_BULK_STREAM: 459 err = LIBUSB_ERROR_NOT_SUPPORTED; 460 break; 461 } 462 463 if (err) 464 return (err); 465 466 usbi_signal_transfer_completion(itransfer); 467 468 return (LIBUSB_SUCCESS); 469 } 470 471 int 472 netbsd_cancel_transfer(struct usbi_transfer *itransfer) 473 { 474 usbi_dbg(""); 475 476 return (LIBUSB_ERROR_NOT_SUPPORTED); 477 } 478 479 void 480 netbsd_clear_transfer_priv(struct usbi_transfer *itransfer) 481 { 482 usbi_dbg(""); 483 484 /* Nothing to do */ 485 } 486 487 int 488 netbsd_handle_transfer_completion(struct usbi_transfer *itransfer) 489 { 490 return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); 491 } 492 493 int 494 netbsd_clock_gettime(int clkid, struct timespec *tp) 495 { 496 usbi_dbg("clock %d", clkid); 497 498 if (clkid == USBI_CLOCK_REALTIME) 499 return clock_gettime(CLOCK_REALTIME, tp); 500 501 if (clkid == USBI_CLOCK_MONOTONIC) 502 return clock_gettime(CLOCK_MONOTONIC, tp); 503 504 return (LIBUSB_ERROR_INVALID_PARAM); 505 } 506 507 int 508 _errno_to_libusb(int err) 509 { 510 switch (err) { 511 case EIO: 512 return (LIBUSB_ERROR_IO); 513 case EACCES: 514 return (LIBUSB_ERROR_ACCESS); 515 case ENOENT: 516 return (LIBUSB_ERROR_NO_DEVICE); 517 case ENOMEM: 518 return (LIBUSB_ERROR_NO_MEM); 519 } 520 521 usbi_dbg("error: %s", strerror(err)); 522 523 return (LIBUSB_ERROR_OTHER); 524 } 525 526 int 527 _cache_active_config_descriptor(struct libusb_device *dev, int fd) 528 { 529 struct device_priv *dpriv = (struct device_priv *)dev->os_priv; 530 struct usb_config_desc ucd; 531 struct usb_full_desc ufd; 532 unsigned char* buf; 533 int len; 534 535 usbi_dbg("fd %d", fd); 536 537 ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX; 538 539 if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0) 540 return _errno_to_libusb(errno); 541 542 usbi_dbg("active bLength %d", ucd.ucd_desc.bLength); 543 544 len = UGETW(ucd.ucd_desc.wTotalLength); 545 buf = malloc(len); 546 if (buf == NULL) 547 return (LIBUSB_ERROR_NO_MEM); 548 549 ufd.ufd_config_index = ucd.ucd_config_index; 550 ufd.ufd_size = len; 551 ufd.ufd_data = buf; 552 553 usbi_dbg("index %d, len %d", ufd.ufd_config_index, len); 554 555 if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { 556 free(buf); 557 return _errno_to_libusb(errno); 558 } 559 560 if (dpriv->cdesc) 561 free(dpriv->cdesc); 562 dpriv->cdesc = buf; 563 564 return (0); 565 } 566 567 int 568 _sync_control_transfer(struct usbi_transfer *itransfer) 569 { 570 struct libusb_transfer *transfer; 571 struct libusb_control_setup *setup; 572 struct device_priv *dpriv; 573 struct usb_ctl_request req; 574 575 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 576 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; 577 setup = (struct libusb_control_setup *)transfer->buffer; 578 579 usbi_dbg("type %d request %d value %d index %d length %d timeout %d", 580 setup->bmRequestType, setup->bRequest, 581 libusb_le16_to_cpu(setup->wValue), 582 libusb_le16_to_cpu(setup->wIndex), 583 libusb_le16_to_cpu(setup->wLength), transfer->timeout); 584 585 req.ucr_request.bmRequestType = setup->bmRequestType; 586 req.ucr_request.bRequest = setup->bRequest; 587 /* Don't use USETW, libusb already deals with the endianness */ 588 (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; 589 (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; 590 (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; 591 req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; 592 593 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) 594 req.ucr_flags = USBD_SHORT_XFER_OK; 595 596 if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) 597 return _errno_to_libusb(errno); 598 599 if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) 600 return _errno_to_libusb(errno); 601 602 itransfer->transferred = req.ucr_actlen; 603 604 usbi_dbg("transferred %d", itransfer->transferred); 605 606 return (0); 607 } 608 609 int 610 _access_endpoint(struct libusb_transfer *transfer) 611 { 612 struct handle_priv *hpriv; 613 struct device_priv *dpriv; 614 char *s, devnode[16]; 615 int fd, endpt; 616 mode_t mode; 617 618 hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; 619 dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; 620 621 endpt = UE_GET_ADDR(transfer->endpoint); 622 mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; 623 624 usbi_dbg("endpoint %d mode %d", endpt, mode); 625 626 if (hpriv->endpoints[endpt] < 0) { 627 /* Pick the right node given the control one */ 628 strlcpy(devnode, dpriv->devnode, sizeof(devnode)); 629 s = strchr(devnode, '.'); 630 snprintf(s, 4, ".%02d", endpt); 631 632 /* We may need to read/write to the same endpoint later. */ 633 if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) 634 if ((fd = open(devnode, mode)) < 0) 635 return (-1); 636 637 hpriv->endpoints[endpt] = fd; 638 } 639 640 return (hpriv->endpoints[endpt]); 641 } 642 643 int 644 _sync_gen_transfer(struct usbi_transfer *itransfer) 645 { 646 struct libusb_transfer *transfer; 647 int fd, nr = 1; 648 649 transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 650 651 /* 652 * Bulk, Interrupt or Isochronous transfer depends on the 653 * endpoint and thus the node to open. 654 */ 655 if ((fd = _access_endpoint(transfer)) < 0) 656 return _errno_to_libusb(errno); 657 658 if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) 659 return _errno_to_libusb(errno); 660 661 if (IS_XFERIN(transfer)) { 662 if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) 663 if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) 664 return _errno_to_libusb(errno); 665 666 nr = read(fd, transfer->buffer, transfer->length); 667 } else { 668 nr = write(fd, transfer->buffer, transfer->length); 669 } 670 671 if (nr < 0) 672 return _errno_to_libusb(errno); 673 674 itransfer->transferred = nr; 675 676 return (0); 677 } 678