1184610Salfred/* $FreeBSD$ */ 2184610Salfred/*- 3184610Salfred * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4184610Salfred * 5184610Salfred * Redistribution and use in source and binary forms, with or without 6184610Salfred * modification, are permitted provided that the following conditions 7184610Salfred * are met: 8184610Salfred * 1. Redistributions of source code must retain the above copyright 9184610Salfred * notice, this list of conditions and the following disclaimer. 10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer in the 12184610Salfred * documentation and/or other materials provided with the distribution. 13184610Salfred * 14184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184610Salfred * SUCH DAMAGE. 25184610Salfred */ 26184610Salfred 27184610Salfred/* 28184610Salfred * This file contains the emulation layer for LibUSB v0.1 from sourceforge. 29184610Salfred */ 30184610Salfred 31248236Shselasky#ifdef LIBUSB_GLOBAL_INCLUDE_FILE 32248236Shselasky#include LIBUSB_GLOBAL_INCLUDE_FILE 33248236Shselasky#else 34203815Swkoszek#include <errno.h> 35203815Swkoszek#include <stdio.h> 36184610Salfred#include <stdlib.h> 37248236Shselasky#include <string.h> 38248236Shselasky#include <time.h> 39248236Shselasky#include <sys/queue.h> 40248236Shselasky#endif 41184610Salfred 42184610Salfred#include "libusb20.h" 43184610Salfred#include "libusb20_desc.h" 44184610Salfred#include "libusb20_int.h" 45189585Sthompsa#include "usb.h" 46184610Salfred 47184610Salfred/* 48184610Salfred * The two following macros were taken from the original LibUSB v0.1 49184610Salfred * for sake of compatibility: 50184610Salfred */ 51184610Salfred#define LIST_ADD(begin, ent) \ 52184610Salfred do { \ 53184610Salfred if (begin) { \ 54184610Salfred ent->next = begin; \ 55184610Salfred ent->next->prev = ent; \ 56184610Salfred } else { \ 57184610Salfred ent->next = NULL; \ 58184610Salfred } \ 59184610Salfred ent->prev = NULL; \ 60184610Salfred begin = ent; \ 61184610Salfred } while(0) 62184610Salfred 63184610Salfred#define LIST_DEL(begin, ent) \ 64184610Salfred do { \ 65184610Salfred if (ent->prev) { \ 66184610Salfred ent->prev->next = ent->next; \ 67184610Salfred } else { \ 68184610Salfred begin = ent->next; \ 69184610Salfred } \ 70184610Salfred if (ent->next) { \ 71184610Salfred ent->next->prev = ent->prev; \ 72184610Salfred } \ 73184610Salfred ent->prev = NULL; \ 74184610Salfred ent->next = NULL; \ 75184610Salfred } while (0) 76184610Salfred 77184610Salfredstruct usb_bus *usb_busses = NULL; 78184610Salfred 79184610Salfredstatic struct usb_bus usb_global_bus = { 80184610Salfred .dirname = {"/dev/usb"}, 81184610Salfred .root_dev = NULL, 82184610Salfred .devices = NULL, 83184610Salfred}; 84184610Salfred 85184610Salfredstatic struct libusb20_backend *usb_backend = NULL; 86184610Salfred 87184610Salfredstruct usb_parse_state { 88184610Salfred 89184610Salfred struct { 90184610Salfred struct libusb20_endpoint *currep; 91184610Salfred struct libusb20_interface *currifc; 92184610Salfred struct libusb20_config *currcfg; 93184610Salfred struct libusb20_me_struct *currextra; 94184610Salfred } a; 95184610Salfred 96184610Salfred struct { 97184610Salfred struct usb_config_descriptor *currcfg; 98184610Salfred struct usb_interface_descriptor *currifc; 99184610Salfred struct usb_endpoint_descriptor *currep; 100184610Salfred struct usb_interface *currifcw; 101184610Salfred uint8_t *currextra; 102184610Salfred } b; 103184610Salfred 104184610Salfred uint8_t preparse; 105184610Salfred}; 106184610Salfred 107184610Salfredstatic struct libusb20_transfer * 108184610Salfredusb_get_transfer_by_ep_no(usb_dev_handle * dev, uint8_t ep_no) 109184610Salfred{ 110184610Salfred struct libusb20_device *pdev = (void *)dev; 111184610Salfred struct libusb20_transfer *xfer; 112184610Salfred int err; 113184610Salfred uint32_t bufsize; 114184610Salfred uint8_t x; 115184610Salfred uint8_t speed; 116184610Salfred 117184610Salfred x = (ep_no & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 2; 118184610Salfred 119184610Salfred if (ep_no & LIBUSB20_ENDPOINT_DIR_MASK) { 120185087Salfred /* this is an IN endpoint */ 121184610Salfred x |= 1; 122184610Salfred } 123184610Salfred speed = libusb20_dev_get_speed(pdev); 124184610Salfred 125184610Salfred /* select a sensible buffer size */ 126184610Salfred if (speed == LIBUSB20_SPEED_LOW) { 127184610Salfred bufsize = 256; 128184610Salfred } else if (speed == LIBUSB20_SPEED_FULL) { 129184610Salfred bufsize = 4096; 130264344Shselasky } else if (speed == LIBUSB20_SPEED_SUPER) { 131264344Shselasky bufsize = 65536; 132184610Salfred } else { 133184610Salfred bufsize = 16384; 134184610Salfred } 135184610Salfred 136184610Salfred xfer = libusb20_tr_get_pointer(pdev, x); 137184610Salfred 138184610Salfred if (xfer == NULL) 139184610Salfred return (xfer); 140184610Salfred 141184610Salfred err = libusb20_tr_open(xfer, bufsize, 1, ep_no); 142184610Salfred if (err == LIBUSB20_ERROR_BUSY) { 143184610Salfred /* already opened */ 144184610Salfred return (xfer); 145184610Salfred } else if (err) { 146184610Salfred return (NULL); 147184610Salfred } 148184610Salfred /* success */ 149184610Salfred return (xfer); 150184610Salfred} 151184610Salfred 152184610Salfredusb_dev_handle * 153184610Salfredusb_open(struct usb_device *dev) 154184610Salfred{ 155184610Salfred int err; 156184610Salfred 157184610Salfred err = libusb20_dev_open(dev->dev, 16 * 2); 158184610Salfred if (err == LIBUSB20_ERROR_BUSY) { 159184610Salfred /* 160184610Salfred * Workaround buggy USB applications which open the USB 161184610Salfred * device multiple times: 162184610Salfred */ 163184610Salfred return (dev->dev); 164184610Salfred } 165184610Salfred if (err) 166184610Salfred return (NULL); 167184610Salfred 168185290Salfred /* 169185290Salfred * Dequeue USB device from backend queue so that it does not get 170185290Salfred * freed when the backend is re-scanned: 171185290Salfred */ 172185290Salfred libusb20_be_dequeue_device(usb_backend, dev->dev); 173185290Salfred 174184610Salfred return (dev->dev); 175184610Salfred} 176184610Salfred 177184610Salfredint 178185290Salfredusb_close(usb_dev_handle * udev) 179184610Salfred{ 180185290Salfred struct usb_device *dev; 181184610Salfred int err; 182184610Salfred 183185290Salfred err = libusb20_dev_close((void *)udev); 184184610Salfred 185184610Salfred if (err) 186184610Salfred return (-1); 187184610Salfred 188185290Salfred if (usb_backend != NULL) { 189185290Salfred /* 190185290Salfred * Enqueue USB device to backend queue so that it gets freed 191185290Salfred * when the backend is re-scanned: 192185290Salfred */ 193185290Salfred libusb20_be_enqueue_device(usb_backend, (void *)udev); 194185290Salfred } else { 195185290Salfred /* 196185290Salfred * The backend is gone. Free device data so that we 197185290Salfred * don't start leaking memory! 198185290Salfred */ 199185290Salfred dev = usb_device(udev); 200185290Salfred libusb20_dev_free((void *)udev); 201185290Salfred LIST_DEL(usb_global_bus.devices, dev); 202185290Salfred free(dev); 203185290Salfred } 204184610Salfred return (0); 205184610Salfred} 206184610Salfred 207184610Salfredint 208185087Salfredusb_get_string(usb_dev_handle * dev, int strindex, 209184610Salfred int langid, char *buf, size_t buflen) 210184610Salfred{ 211184610Salfred int err; 212184610Salfred 213224085Shselasky if (dev == NULL) 214224085Shselasky return (-1); 215224085Shselasky 216224085Shselasky if (buflen > 65535) 217224085Shselasky buflen = 65535; 218224085Shselasky 219184610Salfred err = libusb20_dev_req_string_sync((void *)dev, 220185087Salfred strindex, langid, buf, buflen); 221184610Salfred 222184610Salfred if (err) 223184610Salfred return (-1); 224184610Salfred 225184610Salfred return (0); 226184610Salfred} 227184610Salfred 228184610Salfredint 229185087Salfredusb_get_string_simple(usb_dev_handle * dev, int strindex, 230184610Salfred char *buf, size_t buflen) 231184610Salfred{ 232184610Salfred int err; 233184610Salfred 234224085Shselasky if (dev == NULL) 235224085Shselasky return (-1); 236224085Shselasky 237224085Shselasky if (buflen > 65535) 238224085Shselasky buflen = 65535; 239224085Shselasky 240184610Salfred err = libusb20_dev_req_string_simple_sync((void *)dev, 241185087Salfred strindex, buf, buflen); 242184610Salfred 243184610Salfred if (err) 244184610Salfred return (-1); 245184610Salfred 246184610Salfred return (strlen(buf)); 247184610Salfred} 248184610Salfred 249184610Salfredint 250184610Salfredusb_get_descriptor_by_endpoint(usb_dev_handle * udev, int ep, uint8_t type, 251185087Salfred uint8_t ep_index, void *buf, int size) 252184610Salfred{ 253184610Salfred memset(buf, 0, size); 254184610Salfred 255224085Shselasky if (udev == NULL) 256224085Shselasky return (-1); 257224085Shselasky 258224085Shselasky if (size > 65535) 259224085Shselasky size = 65535; 260224085Shselasky 261184610Salfred return (usb_control_msg(udev, ep | USB_ENDPOINT_IN, 262185087Salfred USB_REQ_GET_DESCRIPTOR, (type << 8) + ep_index, 0, 263184610Salfred buf, size, 1000)); 264184610Salfred} 265184610Salfred 266184610Salfredint 267185087Salfredusb_get_descriptor(usb_dev_handle * udev, uint8_t type, uint8_t desc_index, 268184610Salfred void *buf, int size) 269184610Salfred{ 270184610Salfred memset(buf, 0, size); 271184610Salfred 272224085Shselasky if (udev == NULL) 273224085Shselasky return (-1); 274224085Shselasky 275224085Shselasky if (size > 65535) 276224085Shselasky size = 65535; 277224085Shselasky 278184610Salfred return (usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, 279185087Salfred (type << 8) + desc_index, 0, buf, size, 1000)); 280184610Salfred} 281184610Salfred 282184610Salfredint 283184610Salfredusb_parse_descriptor(uint8_t *source, char *description, void *dest) 284184610Salfred{ 285184610Salfred uint8_t *sp = source; 286184610Salfred uint8_t *dp = dest; 287184610Salfred uint16_t w; 288184610Salfred uint32_t d; 289184610Salfred char *cp; 290184610Salfred 291184610Salfred for (cp = description; *cp; cp++) { 292184610Salfred switch (*cp) { 293184610Salfred case 'b': /* 8-bit byte */ 294184610Salfred *dp++ = *sp++; 295184610Salfred break; 296184610Salfred /* 297184610Salfred * 16-bit word, convert from little endian to CPU 298184610Salfred */ 299184610Salfred case 'w': 300184610Salfred w = (sp[1] << 8) | sp[0]; 301184610Salfred sp += 2; 302184610Salfred /* Align to word boundary */ 303184610Salfred dp += ((dp - (uint8_t *)0) & 1); 304184610Salfred *((uint16_t *)dp) = w; 305184610Salfred dp += 2; 306184610Salfred break; 307184610Salfred /* 308184610Salfred * 32-bit dword, convert from little endian to CPU 309184610Salfred */ 310184610Salfred case 'd': 311184610Salfred d = (sp[3] << 24) | (sp[2] << 16) | 312184610Salfred (sp[1] << 8) | sp[0]; 313184610Salfred sp += 4; 314184610Salfred /* Align to word boundary */ 315184610Salfred dp += ((dp - (uint8_t *)0) & 1); 316184610Salfred /* Align to double word boundary */ 317184610Salfred dp += ((dp - (uint8_t *)0) & 2); 318184610Salfred *((uint32_t *)dp) = d; 319184610Salfred dp += 4; 320184610Salfred break; 321184610Salfred } 322184610Salfred } 323184610Salfred return (sp - source); 324184610Salfred} 325184610Salfred 326184610Salfredstatic void 327184610Salfredusb_parse_extra(struct usb_parse_state *ps, uint8_t **pptr, int *plen) 328184610Salfred{ 329184610Salfred void *ptr; 330184610Salfred uint16_t len; 331184610Salfred 332184610Salfred ptr = ps->a.currextra->ptr; 333184610Salfred len = ps->a.currextra->len; 334184610Salfred 335184610Salfred if (ps->preparse == 0) { 336184610Salfred memcpy(ps->b.currextra, ptr, len); 337184610Salfred *pptr = ps->b.currextra; 338184610Salfred *plen = len; 339184610Salfred } 340184610Salfred ps->b.currextra += len; 341184610Salfred return; 342184610Salfred} 343184610Salfred 344184610Salfredstatic void 345184610Salfredusb_parse_endpoint(struct usb_parse_state *ps) 346184610Salfred{ 347184610Salfred struct usb_endpoint_descriptor *bep; 348184610Salfred struct libusb20_endpoint *aep; 349184610Salfred 350184610Salfred aep = ps->a.currep; 351184610Salfred bep = ps->b.currep++; 352184610Salfred 353184610Salfred if (ps->preparse == 0) { 354184610Salfred /* copy descriptor fields */ 355184610Salfred bep->bLength = aep->desc.bLength; 356184610Salfred bep->bDescriptorType = aep->desc.bDescriptorType; 357184610Salfred bep->bEndpointAddress = aep->desc.bEndpointAddress; 358184610Salfred bep->bmAttributes = aep->desc.bmAttributes; 359184610Salfred bep->wMaxPacketSize = aep->desc.wMaxPacketSize; 360184610Salfred bep->bInterval = aep->desc.bInterval; 361184610Salfred bep->bRefresh = aep->desc.bRefresh; 362184610Salfred bep->bSynchAddress = aep->desc.bSynchAddress; 363184610Salfred } 364184610Salfred ps->a.currextra = &aep->extra; 365184610Salfred usb_parse_extra(ps, &bep->extra, &bep->extralen); 366184610Salfred return; 367184610Salfred} 368184610Salfred 369184610Salfredstatic void 370184610Salfredusb_parse_iface_sub(struct usb_parse_state *ps) 371184610Salfred{ 372184610Salfred struct libusb20_interface *aifc; 373184610Salfred struct usb_interface_descriptor *bifc; 374184610Salfred uint8_t x; 375184610Salfred 376184610Salfred aifc = ps->a.currifc; 377184610Salfred bifc = ps->b.currifc++; 378184610Salfred 379184610Salfred if (ps->preparse == 0) { 380184610Salfred /* copy descriptor fields */ 381184610Salfred bifc->bLength = aifc->desc.bLength; 382184610Salfred bifc->bDescriptorType = aifc->desc.bDescriptorType; 383184610Salfred bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber; 384184610Salfred bifc->bAlternateSetting = aifc->desc.bAlternateSetting; 385184610Salfred bifc->bNumEndpoints = aifc->num_endpoints; 386184610Salfred bifc->bInterfaceClass = aifc->desc.bInterfaceClass; 387184610Salfred bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass; 388184610Salfred bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol; 389184610Salfred bifc->iInterface = aifc->desc.iInterface; 390184610Salfred bifc->endpoint = ps->b.currep; 391184610Salfred } 392184610Salfred for (x = 0; x != aifc->num_endpoints; x++) { 393184610Salfred ps->a.currep = aifc->endpoints + x; 394184610Salfred usb_parse_endpoint(ps); 395184610Salfred } 396184610Salfred 397184610Salfred ps->a.currextra = &aifc->extra; 398184610Salfred usb_parse_extra(ps, &bifc->extra, &bifc->extralen); 399184610Salfred return; 400184610Salfred} 401184610Salfred 402184610Salfredstatic void 403184610Salfredusb_parse_iface(struct usb_parse_state *ps) 404184610Salfred{ 405184610Salfred struct libusb20_interface *aifc; 406184610Salfred struct usb_interface *bifc; 407184610Salfred uint8_t x; 408184610Salfred 409184610Salfred aifc = ps->a.currifc; 410184610Salfred bifc = ps->b.currifcw++; 411184610Salfred 412184610Salfred if (ps->preparse == 0) { 413184610Salfred /* initialise interface wrapper */ 414184610Salfred bifc->altsetting = ps->b.currifc; 415184610Salfred bifc->num_altsetting = aifc->num_altsetting + 1; 416184610Salfred } 417184610Salfred usb_parse_iface_sub(ps); 418184610Salfred 419184610Salfred for (x = 0; x != aifc->num_altsetting; x++) { 420184610Salfred ps->a.currifc = aifc->altsetting + x; 421184610Salfred usb_parse_iface_sub(ps); 422184610Salfred } 423184610Salfred return; 424184610Salfred} 425184610Salfred 426184610Salfredstatic void 427184610Salfredusb_parse_config(struct usb_parse_state *ps) 428184610Salfred{ 429184610Salfred struct libusb20_config *acfg; 430184610Salfred struct usb_config_descriptor *bcfg; 431184610Salfred uint8_t x; 432184610Salfred 433184610Salfred acfg = ps->a.currcfg; 434184610Salfred bcfg = ps->b.currcfg; 435184610Salfred 436184610Salfred if (ps->preparse == 0) { 437184610Salfred /* initialise config wrapper */ 438184610Salfred bcfg->bLength = acfg->desc.bLength; 439184610Salfred bcfg->bDescriptorType = acfg->desc.bDescriptorType; 440184610Salfred bcfg->wTotalLength = acfg->desc.wTotalLength; 441184610Salfred bcfg->bNumInterfaces = acfg->num_interface; 442184610Salfred bcfg->bConfigurationValue = acfg->desc.bConfigurationValue; 443184610Salfred bcfg->iConfiguration = acfg->desc.iConfiguration; 444184610Salfred bcfg->bmAttributes = acfg->desc.bmAttributes; 445184610Salfred bcfg->MaxPower = acfg->desc.bMaxPower; 446184610Salfred bcfg->interface = ps->b.currifcw; 447184610Salfred } 448184610Salfred for (x = 0; x != acfg->num_interface; x++) { 449184610Salfred ps->a.currifc = acfg->interface + x; 450184610Salfred usb_parse_iface(ps); 451184610Salfred } 452184610Salfred 453184610Salfred ps->a.currextra = &acfg->extra; 454184610Salfred usb_parse_extra(ps, &bcfg->extra, &bcfg->extralen); 455184610Salfred return; 456184610Salfred} 457184610Salfred 458184610Salfredint 459184610Salfredusb_parse_configuration(struct usb_config_descriptor *config, 460184610Salfred uint8_t *buffer) 461184610Salfred{ 462184610Salfred struct usb_parse_state ps; 463184610Salfred uint8_t *ptr; 464184610Salfred uint32_t a; 465184610Salfred uint32_t b; 466184610Salfred uint32_t c; 467184610Salfred uint32_t d; 468184610Salfred 469184610Salfred if ((buffer == NULL) || (config == NULL)) { 470184610Salfred return (-1); 471184610Salfred } 472184610Salfred memset(&ps, 0, sizeof(ps)); 473184610Salfred 474184610Salfred ps.a.currcfg = libusb20_parse_config_desc(buffer); 475184610Salfred ps.b.currcfg = config; 476184610Salfred if (ps.a.currcfg == NULL) { 477184610Salfred /* could not parse config or out of memory */ 478184610Salfred return (-1); 479184610Salfred } 480184610Salfred /* do the pre-parse */ 481184610Salfred ps.preparse = 1; 482184610Salfred usb_parse_config(&ps); 483184610Salfred 484184610Salfred a = ((uint8_t *)(ps.b.currifcw) - ((uint8_t *)0)); 485184610Salfred b = ((uint8_t *)(ps.b.currifc) - ((uint8_t *)0)); 486184610Salfred c = ((uint8_t *)(ps.b.currep) - ((uint8_t *)0)); 487184610Salfred d = ((uint8_t *)(ps.b.currextra) - ((uint8_t *)0)); 488184610Salfred 489184610Salfred /* allocate memory for our configuration */ 490184610Salfred ptr = malloc(a + b + c + d); 491216431Skevlo if (ptr == NULL) { 492216431Skevlo /* free config structure */ 493216431Skevlo free(ps.a.currcfg); 494216431Skevlo return (-1); 495216431Skevlo } 496184610Salfred 497184610Salfred /* "currifcw" must be first, hence this pointer is freed */ 498184610Salfred ps.b.currifcw = (void *)(ptr); 499184610Salfred ps.b.currifc = (void *)(ptr + a); 500184610Salfred ps.b.currep = (void *)(ptr + a + b); 501184610Salfred ps.b.currextra = (void *)(ptr + a + b + c); 502184610Salfred 503184610Salfred /* generate a libusb v0.1 compatible structure */ 504184610Salfred ps.preparse = 0; 505184610Salfred usb_parse_config(&ps); 506184610Salfred 507184610Salfred /* free config structure */ 508184610Salfred free(ps.a.currcfg); 509184610Salfred 510184610Salfred return (0); /* success */ 511184610Salfred} 512184610Salfred 513184610Salfredvoid 514184610Salfredusb_destroy_configuration(struct usb_device *dev) 515184610Salfred{ 516184610Salfred uint8_t c; 517184610Salfred 518184610Salfred if (dev->config == NULL) { 519184610Salfred return; 520184610Salfred } 521184610Salfred for (c = 0; c != dev->descriptor.bNumConfigurations; c++) { 522184610Salfred struct usb_config_descriptor *cf = &dev->config[c]; 523184610Salfred 524184610Salfred if (cf->interface != NULL) { 525184610Salfred free(cf->interface); 526184610Salfred cf->interface = NULL; 527184610Salfred } 528184610Salfred } 529184610Salfred 530184610Salfred free(dev->config); 531184610Salfred dev->config = NULL; 532184610Salfred return; 533184610Salfred} 534184610Salfred 535184610Salfredvoid 536184610Salfredusb_fetch_and_parse_descriptors(usb_dev_handle * udev) 537184610Salfred{ 538184610Salfred struct usb_device *dev; 539184610Salfred struct libusb20_device *pdev; 540184610Salfred uint8_t *ptr; 541184610Salfred int error; 542184610Salfred uint32_t size; 543184610Salfred uint16_t len; 544184610Salfred uint8_t x; 545184610Salfred 546184610Salfred if (udev == NULL) { 547184610Salfred /* be NULL safe */ 548184610Salfred return; 549184610Salfred } 550184610Salfred dev = usb_device(udev); 551184610Salfred pdev = (void *)udev; 552184610Salfred 553184610Salfred if (dev->descriptor.bNumConfigurations == 0) { 554184610Salfred /* invalid device */ 555184610Salfred return; 556184610Salfred } 557184610Salfred size = dev->descriptor.bNumConfigurations * 558184610Salfred sizeof(struct usb_config_descriptor); 559184610Salfred 560184610Salfred dev->config = malloc(size); 561184610Salfred if (dev->config == NULL) { 562184610Salfred /* out of memory */ 563184610Salfred return; 564184610Salfred } 565184610Salfred memset(dev->config, 0, size); 566184610Salfred 567184610Salfred for (x = 0; x != dev->descriptor.bNumConfigurations; x++) { 568184610Salfred 569184610Salfred error = (pdev->methods->get_config_desc_full) ( 570184610Salfred pdev, &ptr, &len, x); 571184610Salfred 572184610Salfred if (error) { 573184610Salfred usb_destroy_configuration(dev); 574184610Salfred return; 575184610Salfred } 576184610Salfred usb_parse_configuration(dev->config + x, ptr); 577184610Salfred 578184610Salfred /* free config buffer */ 579184610Salfred free(ptr); 580184610Salfred } 581184610Salfred return; 582184610Salfred} 583184610Salfred 584184610Salfredstatic int 585184610Salfredusb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size, 586184610Salfred int timeout, int is_intr) 587184610Salfred{ 588184610Salfred struct libusb20_transfer *xfer; 589184610Salfred uint32_t temp; 590184610Salfred uint32_t maxsize; 591184610Salfred uint32_t actlen; 592184610Salfred char *oldbytes; 593184610Salfred 594184610Salfred xfer = usb_get_transfer_by_ep_no(dev, ep); 595184610Salfred if (xfer == NULL) 596184610Salfred return (-1); 597184610Salfred 598184610Salfred if (libusb20_tr_pending(xfer)) { 599184610Salfred /* there is already a transfer ongoing */ 600184610Salfred return (-1); 601184610Salfred } 602184610Salfred maxsize = libusb20_tr_get_max_total_length(xfer); 603184610Salfred oldbytes = bytes; 604184610Salfred 605184610Salfred /* 606184610Salfred * We allow transferring zero bytes which is the same 607184610Salfred * equivalent to a zero length USB packet. 608184610Salfred */ 609184610Salfred do { 610184610Salfred 611184610Salfred temp = size; 612184610Salfred if (temp > maxsize) { 613184610Salfred /* find maximum possible length */ 614184610Salfred temp = maxsize; 615184610Salfred } 616184610Salfred if (is_intr) 617184610Salfred libusb20_tr_setup_intr(xfer, bytes, temp, timeout); 618184610Salfred else 619184610Salfred libusb20_tr_setup_bulk(xfer, bytes, temp, timeout); 620184610Salfred 621184610Salfred libusb20_tr_start(xfer); 622184610Salfred 623184610Salfred while (1) { 624184610Salfred 625184610Salfred if (libusb20_dev_process((void *)dev) != 0) { 626184610Salfred /* device detached */ 627184610Salfred return (-1); 628184610Salfred } 629184610Salfred if (libusb20_tr_pending(xfer) == 0) { 630184610Salfred /* transfer complete */ 631184610Salfred break; 632184610Salfred } 633184610Salfred /* wait for USB event from kernel */ 634184610Salfred libusb20_dev_wait_process((void *)dev, -1); 635184610Salfred } 636184610Salfred 637188678Sthompsa switch (libusb20_tr_get_status(xfer)) { 638188678Sthompsa case 0: 639188678Sthompsa /* success */ 640188678Sthompsa break; 641188678Sthompsa case LIBUSB20_TRANSFER_TIMED_OUT: 642188678Sthompsa /* transfer timeout */ 643188678Sthompsa return (-ETIMEDOUT); 644188678Sthompsa default: 645188678Sthompsa /* other transfer error */ 646188678Sthompsa return (-ENXIO); 647184610Salfred } 648184610Salfred actlen = libusb20_tr_get_actual_length(xfer); 649184610Salfred 650184610Salfred bytes += actlen; 651184610Salfred size -= actlen; 652184610Salfred 653184610Salfred if (actlen != temp) { 654184610Salfred /* short transfer */ 655184610Salfred break; 656184610Salfred } 657184610Salfred } while (size > 0); 658184610Salfred 659184610Salfred return (bytes - oldbytes); 660184610Salfred} 661184610Salfred 662184610Salfredint 663184610Salfredusb_bulk_write(usb_dev_handle * dev, int ep, char *bytes, 664184610Salfred int size, int timeout) 665184610Salfred{ 666185087Salfred return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, 667185087Salfred bytes, size, timeout, 0)); 668184610Salfred} 669184610Salfred 670184610Salfredint 671184610Salfredusb_bulk_read(usb_dev_handle * dev, int ep, char *bytes, 672184610Salfred int size, int timeout) 673184610Salfred{ 674185087Salfred return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, 675185087Salfred bytes, size, timeout, 0)); 676184610Salfred} 677184610Salfred 678184610Salfredint 679184610Salfredusb_interrupt_write(usb_dev_handle * dev, int ep, char *bytes, 680184610Salfred int size, int timeout) 681184610Salfred{ 682185087Salfred return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, 683185087Salfred bytes, size, timeout, 1)); 684184610Salfred} 685184610Salfred 686184610Salfredint 687184610Salfredusb_interrupt_read(usb_dev_handle * dev, int ep, char *bytes, 688184610Salfred int size, int timeout) 689184610Salfred{ 690185087Salfred return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, 691185087Salfred bytes, size, timeout, 1)); 692184610Salfred} 693184610Salfred 694184610Salfredint 695184610Salfredusb_control_msg(usb_dev_handle * dev, int requesttype, int request, 696185087Salfred int value, int wIndex, char *bytes, int size, int timeout) 697184610Salfred{ 698184610Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 699184610Salfred int err; 700184610Salfred uint16_t actlen; 701184610Salfred 702184610Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 703184610Salfred 704184610Salfred req.bmRequestType = requesttype; 705184610Salfred req.bRequest = request; 706184610Salfred req.wValue = value; 707185087Salfred req.wIndex = wIndex; 708184610Salfred req.wLength = size; 709184610Salfred 710184610Salfred err = libusb20_dev_request_sync((void *)dev, &req, bytes, 711184610Salfred &actlen, timeout, 0); 712184610Salfred 713184610Salfred if (err) 714184610Salfred return (-1); 715184610Salfred 716184610Salfred return (actlen); 717184610Salfred} 718184610Salfred 719184610Salfredint 720185087Salfredusb_set_configuration(usb_dev_handle * udev, int bConfigurationValue) 721184610Salfred{ 722185087Salfred struct usb_device *dev; 723184610Salfred int err; 724185087Salfred uint8_t i; 725184610Salfred 726185087Salfred /* 727185087Salfred * Need to translate from "bConfigurationValue" to 728185087Salfred * configuration index: 729185087Salfred */ 730184610Salfred 731185087Salfred if (bConfigurationValue == 0) { 732185087Salfred /* unconfigure */ 733185087Salfred i = 255; 734185087Salfred } else { 735185087Salfred /* lookup configuration index */ 736185087Salfred dev = usb_device(udev); 737185087Salfred 738185087Salfred /* check if the configuration array is not there */ 739185087Salfred if (dev->config == NULL) { 740185087Salfred return (-1); 741185087Salfred } 742185087Salfred for (i = 0;; i++) { 743185087Salfred if (i == dev->descriptor.bNumConfigurations) { 744185087Salfred /* "bConfigurationValue" not found */ 745185087Salfred return (-1); 746185087Salfred } 747185290Salfred if ((dev->config + i)->bConfigurationValue == 748185290Salfred bConfigurationValue) { 749185087Salfred break; 750185087Salfred } 751185087Salfred } 752185087Salfred } 753185087Salfred 754185087Salfred err = libusb20_dev_set_config_index((void *)udev, i); 755185087Salfred 756184610Salfred if (err) 757184610Salfred return (-1); 758184610Salfred 759184610Salfred return (0); 760184610Salfred} 761184610Salfred 762184610Salfredint 763184610Salfredusb_claim_interface(usb_dev_handle * dev, int interface) 764184610Salfred{ 765194069Sthompsa struct libusb20_device *pdev = (void *)dev; 766184610Salfred 767194069Sthompsa pdev->claimed_interface = interface; 768184610Salfred 769184610Salfred return (0); 770184610Salfred} 771184610Salfred 772184610Salfredint 773184610Salfredusb_release_interface(usb_dev_handle * dev, int interface) 774184610Salfred{ 775194069Sthompsa /* do nothing */ 776184610Salfred return (0); 777184610Salfred} 778184610Salfred 779184610Salfredint 780184610Salfredusb_set_altinterface(usb_dev_handle * dev, int alternate) 781184610Salfred{ 782194069Sthompsa struct libusb20_device *pdev = (void *)dev; 783184610Salfred int err; 784184610Salfred uint8_t iface; 785184610Salfred 786194069Sthompsa iface = pdev->claimed_interface; 787184610Salfred 788184610Salfred err = libusb20_dev_set_alt_index((void *)dev, iface, alternate); 789184610Salfred 790184610Salfred if (err) 791184610Salfred return (-1); 792184610Salfred 793184610Salfred return (0); 794184610Salfred} 795184610Salfred 796184610Salfredint 797184610Salfredusb_resetep(usb_dev_handle * dev, unsigned int ep) 798184610Salfred{ 799184610Salfred /* emulate an endpoint reset through clear-STALL */ 800184610Salfred return (usb_clear_halt(dev, ep)); 801184610Salfred} 802184610Salfred 803184610Salfredint 804184610Salfredusb_clear_halt(usb_dev_handle * dev, unsigned int ep) 805184610Salfred{ 806184610Salfred struct libusb20_transfer *xfer; 807184610Salfred 808184610Salfred xfer = usb_get_transfer_by_ep_no(dev, ep); 809184610Salfred if (xfer == NULL) 810184610Salfred return (-1); 811184610Salfred 812184610Salfred libusb20_tr_clear_stall_sync(xfer); 813184610Salfred 814184610Salfred return (0); 815184610Salfred} 816184610Salfred 817184610Salfredint 818184610Salfredusb_reset(usb_dev_handle * dev) 819184610Salfred{ 820184610Salfred int err; 821184610Salfred 822184610Salfred err = libusb20_dev_reset((void *)dev); 823184610Salfred 824184610Salfred if (err) 825184610Salfred return (-1); 826184610Salfred 827189621Sthompsa /* 828189621Sthompsa * Be compatible with LibUSB from sourceforge and close the 829189621Sthompsa * handle after reset! 830189621Sthompsa */ 831189621Sthompsa return (usb_close(dev)); 832184610Salfred} 833184610Salfred 834213848Shselaskyint 835213848Shselaskyusb_check_connected(usb_dev_handle * dev) 836213848Shselasky{ 837213848Shselasky int err; 838213848Shselasky 839213848Shselasky err = libusb20_dev_check_connected((void *)dev); 840213848Shselasky 841213848Shselasky if (err) 842213848Shselasky return (-1); 843213848Shselasky 844213848Shselasky return (0); 845213848Shselasky} 846213848Shselasky 847185087Salfredconst char * 848184610Salfredusb_strerror(void) 849184610Salfred{ 850184610Salfred /* TODO */ 851184610Salfred return ("Unknown error"); 852184610Salfred} 853184610Salfred 854184610Salfredvoid 855184610Salfredusb_init(void) 856184610Salfred{ 857184610Salfred /* nothing to do */ 858184610Salfred return; 859184610Salfred} 860184610Salfred 861184610Salfredvoid 862184610Salfredusb_set_debug(int level) 863184610Salfred{ 864184610Salfred /* use kernel UGEN debugging if you need to see what is going on */ 865184610Salfred return; 866184610Salfred} 867184610Salfred 868184610Salfredint 869184610Salfredusb_find_busses(void) 870184610Salfred{ 871184610Salfred usb_busses = &usb_global_bus; 872208021Sthompsa return (1); 873184610Salfred} 874184610Salfred 875184610Salfredint 876184610Salfredusb_find_devices(void) 877184610Salfred{ 878184610Salfred struct libusb20_device *pdev; 879184610Salfred struct usb_device *udev; 880184610Salfred struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; 881203773Swkoszek int devnum; 882184610Salfred int err; 883184610Salfred 884184610Salfred /* cleanup after last device search */ 885185290Salfred /* close all opened devices, if any */ 886184610Salfred 887185290Salfred while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 888195957Salfred udev = pdev->privLuData; 889185290Salfred libusb20_be_dequeue_device(usb_backend, pdev); 890185290Salfred libusb20_dev_free(pdev); 891185290Salfred if (udev != NULL) { 892185290Salfred LIST_DEL(usb_global_bus.devices, udev); 893185290Salfred free(udev); 894184610Salfred } 895184610Salfred } 896184610Salfred 897185290Salfred /* free old USB backend, if any */ 898185290Salfred 899185290Salfred libusb20_be_free(usb_backend); 900185290Salfred 901184610Salfred /* do a new backend device search */ 902184610Salfred usb_backend = libusb20_be_alloc_default(); 903184610Salfred if (usb_backend == NULL) { 904184610Salfred return (-1); 905184610Salfred } 906184610Salfred /* iterate all devices */ 907184610Salfred 908203773Swkoszek devnum = 1; 909184610Salfred pdev = NULL; 910184610Salfred while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) { 911184610Salfred udev = malloc(sizeof(*udev)); 912184610Salfred if (udev == NULL) 913184610Salfred break; 914184610Salfred 915184610Salfred memset(udev, 0, sizeof(*udev)); 916184610Salfred 917184610Salfred udev->bus = &usb_global_bus; 918184610Salfred 919184610Salfred snprintf(udev->filename, sizeof(udev->filename), 920184610Salfred "/dev/ugen%u.%u", 921184610Salfred libusb20_dev_get_bus_number(pdev), 922184610Salfred libusb20_dev_get_address(pdev)); 923184610Salfred 924184610Salfred ddesc = libusb20_dev_get_device_desc(pdev); 925184610Salfred 926184610Salfred udev->descriptor.bLength = sizeof(udev->descriptor); 927184610Salfred udev->descriptor.bDescriptorType = ddesc->bDescriptorType; 928184610Salfred udev->descriptor.bcdUSB = ddesc->bcdUSB; 929184610Salfred udev->descriptor.bDeviceClass = ddesc->bDeviceClass; 930184610Salfred udev->descriptor.bDeviceSubClass = ddesc->bDeviceSubClass; 931184610Salfred udev->descriptor.bDeviceProtocol = ddesc->bDeviceProtocol; 932184610Salfred udev->descriptor.bMaxPacketSize0 = ddesc->bMaxPacketSize0; 933184610Salfred udev->descriptor.idVendor = ddesc->idVendor; 934184610Salfred udev->descriptor.idProduct = ddesc->idProduct; 935184610Salfred udev->descriptor.bcdDevice = ddesc->bcdDevice; 936184610Salfred udev->descriptor.iManufacturer = ddesc->iManufacturer; 937184610Salfred udev->descriptor.iProduct = ddesc->iProduct; 938184610Salfred udev->descriptor.iSerialNumber = ddesc->iSerialNumber; 939184610Salfred udev->descriptor.bNumConfigurations = 940184610Salfred ddesc->bNumConfigurations; 941184610Salfred if (udev->descriptor.bNumConfigurations > USB_MAXCONFIG) { 942184610Salfred /* truncate number of configurations */ 943184610Salfred udev->descriptor.bNumConfigurations = USB_MAXCONFIG; 944184610Salfred } 945203773Swkoszek udev->devnum = devnum++; 946184610Salfred /* link together the two structures */ 947184610Salfred udev->dev = pdev; 948195957Salfred pdev->privLuData = udev; 949184610Salfred 950184610Salfred err = libusb20_dev_open(pdev, 0); 951184610Salfred if (err == 0) { 952184610Salfred /* XXX get all config descriptors by default */ 953184610Salfred usb_fetch_and_parse_descriptors((void *)pdev); 954184610Salfred libusb20_dev_close(pdev); 955184610Salfred } 956184610Salfred LIST_ADD(usb_global_bus.devices, udev); 957184610Salfred } 958184610Salfred 959208021Sthompsa return (devnum - 1); /* success */ 960184610Salfred} 961184610Salfred 962184610Salfredstruct usb_device * 963184610Salfredusb_device(usb_dev_handle * dev) 964184610Salfred{ 965184610Salfred struct libusb20_device *pdev; 966184610Salfred 967184610Salfred pdev = (void *)dev; 968184610Salfred 969195957Salfred return (pdev->privLuData); 970184610Salfred} 971184610Salfred 972184610Salfredstruct usb_bus * 973184610Salfredusb_get_busses(void) 974184610Salfred{ 975184610Salfred return (usb_busses); 976184610Salfred} 977224085Shselasky 978224085Shselaskyint 979224085Shselaskyusb_get_driver_np(usb_dev_handle * dev, int interface, char *name, int namelen) 980224085Shselasky{ 981224085Shselasky struct libusb20_device *pdev; 982224085Shselasky char *ptr; 983224085Shselasky int err; 984224085Shselasky 985224085Shselasky pdev = (void *)dev; 986224085Shselasky 987224085Shselasky if (pdev == NULL) 988224085Shselasky return (-1); 989224085Shselasky if (namelen < 1) 990224085Shselasky return (-1); 991224085Shselasky if (namelen > 255) 992224085Shselasky namelen = 255; 993224085Shselasky 994224085Shselasky err = libusb20_dev_get_iface_desc(pdev, interface, name, namelen); 995224085Shselasky if (err != 0) 996224085Shselasky return (-1); 997224085Shselasky 998224085Shselasky /* we only want the driver name */ 999224085Shselasky ptr = strstr(name, ":"); 1000224085Shselasky if (ptr != NULL) 1001224085Shselasky *ptr = 0; 1002224085Shselasky 1003224085Shselasky return (0); 1004224085Shselasky} 1005224085Shselasky 1006224085Shselaskyint 1007224085Shselaskyusb_detach_kernel_driver_np(usb_dev_handle * dev, int interface) 1008224085Shselasky{ 1009224085Shselasky struct libusb20_device *pdev; 1010224085Shselasky int err; 1011224085Shselasky 1012224085Shselasky pdev = (void *)dev; 1013224085Shselasky 1014224085Shselasky if (pdev == NULL) 1015224085Shselasky return (-1); 1016224085Shselasky 1017224085Shselasky err = libusb20_dev_detach_kernel_driver(pdev, interface); 1018224085Shselasky if (err != 0) 1019224085Shselasky return (-1); 1020224085Shselasky 1021224085Shselasky return (0); 1022224085Shselasky} 1023