libusb01.c revision 188678
1184610Salfred/* $FreeBSD: head/lib/libusb20/libusb20_compat01.c 188678 2009-02-16 15:32:12Z thompsa $ */ 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 31184610Salfred#include <sys/queue.h> 32184610Salfred 33184610Salfred#include <stdlib.h> 34184610Salfred#include <stdio.h> 35188678Sthompsa#include <errno.h> 36184610Salfred 37184610Salfred#include "libusb20.h" 38184610Salfred#include "libusb20_desc.h" 39184610Salfred#include "libusb20_int.h" 40184610Salfred#include "libusb20_compat01.h" 41184610Salfred 42184610Salfred/* 43184610Salfred * The two following macros were taken from the original LibUSB v0.1 44184610Salfred * for sake of compatibility: 45184610Salfred */ 46184610Salfred#define LIST_ADD(begin, ent) \ 47184610Salfred do { \ 48184610Salfred if (begin) { \ 49184610Salfred ent->next = begin; \ 50184610Salfred ent->next->prev = ent; \ 51184610Salfred } else { \ 52184610Salfred ent->next = NULL; \ 53184610Salfred } \ 54184610Salfred ent->prev = NULL; \ 55184610Salfred begin = ent; \ 56184610Salfred } while(0) 57184610Salfred 58184610Salfred#define LIST_DEL(begin, ent) \ 59184610Salfred do { \ 60184610Salfred if (ent->prev) { \ 61184610Salfred ent->prev->next = ent->next; \ 62184610Salfred } else { \ 63184610Salfred begin = ent->next; \ 64184610Salfred } \ 65184610Salfred if (ent->next) { \ 66184610Salfred ent->next->prev = ent->prev; \ 67184610Salfred } \ 68184610Salfred ent->prev = NULL; \ 69184610Salfred ent->next = NULL; \ 70184610Salfred } while (0) 71184610Salfred 72184610Salfredstruct usb_bus *usb_busses = NULL; 73184610Salfred 74184610Salfredstatic struct usb_bus usb_global_bus = { 75184610Salfred .dirname = {"/dev/usb"}, 76184610Salfred .root_dev = NULL, 77184610Salfred .devices = NULL, 78184610Salfred}; 79184610Salfred 80184610Salfredstatic struct libusb20_backend *usb_backend = NULL; 81184610Salfred 82184610Salfredstruct usb_parse_state { 83184610Salfred 84184610Salfred struct { 85184610Salfred struct libusb20_endpoint *currep; 86184610Salfred struct libusb20_interface *currifc; 87184610Salfred struct libusb20_config *currcfg; 88184610Salfred struct libusb20_me_struct *currextra; 89184610Salfred } a; 90184610Salfred 91184610Salfred struct { 92184610Salfred struct usb_config_descriptor *currcfg; 93184610Salfred struct usb_interface_descriptor *currifc; 94184610Salfred struct usb_endpoint_descriptor *currep; 95184610Salfred struct usb_interface *currifcw; 96184610Salfred uint8_t *currextra; 97184610Salfred } b; 98184610Salfred 99184610Salfred uint8_t preparse; 100184610Salfred}; 101184610Salfred 102184610Salfredstatic uint8_t 103184610Salfredusb_get_first_claimed_interface(usb_dev_handle * dev) 104184610Salfred{ 105184610Salfred struct libusb20_device *pdev = (void *)dev; 106184610Salfred uint32_t x; 107184610Salfred uint8_t y; 108184610Salfred 109184610Salfred x = pdev->claimed_interfaces; 110184610Salfred 111184610Salfred for (y = 0; y != 32; y++) { 112184610Salfred if (x & (1 << y)) 113184610Salfred break; 114184610Salfred } 115184610Salfred 116184610Salfred if (y == 32) 117184610Salfred y = 0xFF; /* dummy */ 118184610Salfred 119184610Salfred return (y); 120184610Salfred} 121184610Salfred 122184610Salfredstatic struct libusb20_transfer * 123184610Salfredusb_get_transfer_by_ep_no(usb_dev_handle * dev, uint8_t ep_no) 124184610Salfred{ 125184610Salfred struct libusb20_device *pdev = (void *)dev; 126184610Salfred struct libusb20_transfer *xfer; 127184610Salfred int err; 128184610Salfred uint32_t bufsize; 129184610Salfred uint8_t x; 130184610Salfred uint8_t speed; 131184610Salfred 132184610Salfred x = (ep_no & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 2; 133184610Salfred 134184610Salfred if (ep_no & LIBUSB20_ENDPOINT_DIR_MASK) { 135185087Salfred /* this is an IN endpoint */ 136184610Salfred x |= 1; 137184610Salfred } 138184610Salfred speed = libusb20_dev_get_speed(pdev); 139184610Salfred 140184610Salfred /* select a sensible buffer size */ 141184610Salfred if (speed == LIBUSB20_SPEED_LOW) { 142184610Salfred bufsize = 256; 143184610Salfred } else if (speed == LIBUSB20_SPEED_FULL) { 144184610Salfred bufsize = 4096; 145184610Salfred } else { 146184610Salfred bufsize = 16384; 147184610Salfred } 148184610Salfred 149184610Salfred xfer = libusb20_tr_get_pointer(pdev, x); 150184610Salfred 151184610Salfred if (xfer == NULL) 152184610Salfred return (xfer); 153184610Salfred 154184610Salfred err = libusb20_tr_open(xfer, bufsize, 1, ep_no); 155184610Salfred if (err == LIBUSB20_ERROR_BUSY) { 156184610Salfred /* already opened */ 157184610Salfred return (xfer); 158184610Salfred } else if (err) { 159184610Salfred return (NULL); 160184610Salfred } 161184610Salfred /* success */ 162184610Salfred return (xfer); 163184610Salfred} 164184610Salfred 165184610Salfredusb_dev_handle * 166184610Salfredusb_open(struct usb_device *dev) 167184610Salfred{ 168184610Salfred int err; 169184610Salfred 170184610Salfred err = libusb20_dev_open(dev->dev, 16 * 2); 171184610Salfred if (err == LIBUSB20_ERROR_BUSY) { 172184610Salfred /* 173184610Salfred * Workaround buggy USB applications which open the USB 174184610Salfred * device multiple times: 175184610Salfred */ 176184610Salfred return (dev->dev); 177184610Salfred } 178184610Salfred if (err) 179184610Salfred return (NULL); 180184610Salfred 181185290Salfred /* 182185290Salfred * Dequeue USB device from backend queue so that it does not get 183185290Salfred * freed when the backend is re-scanned: 184185290Salfred */ 185185290Salfred libusb20_be_dequeue_device(usb_backend, dev->dev); 186185290Salfred 187184610Salfred return (dev->dev); 188184610Salfred} 189184610Salfred 190184610Salfredint 191185290Salfredusb_close(usb_dev_handle * udev) 192184610Salfred{ 193185290Salfred struct usb_device *dev; 194184610Salfred int err; 195184610Salfred 196185290Salfred err = libusb20_dev_close((void *)udev); 197184610Salfred 198184610Salfred if (err) 199184610Salfred return (-1); 200184610Salfred 201185290Salfred if (usb_backend != NULL) { 202185290Salfred /* 203185290Salfred * Enqueue USB device to backend queue so that it gets freed 204185290Salfred * when the backend is re-scanned: 205185290Salfred */ 206185290Salfred libusb20_be_enqueue_device(usb_backend, (void *)udev); 207185290Salfred } else { 208185290Salfred /* 209185290Salfred * The backend is gone. Free device data so that we 210185290Salfred * don't start leaking memory! 211185290Salfred */ 212185290Salfred dev = usb_device(udev); 213185290Salfred libusb20_dev_free((void *)udev); 214185290Salfred LIST_DEL(usb_global_bus.devices, dev); 215185290Salfred free(dev); 216185290Salfred } 217184610Salfred return (0); 218184610Salfred} 219184610Salfred 220184610Salfredint 221185087Salfredusb_get_string(usb_dev_handle * dev, int strindex, 222184610Salfred int langid, char *buf, size_t buflen) 223184610Salfred{ 224184610Salfred int err; 225184610Salfred 226184610Salfred err = libusb20_dev_req_string_sync((void *)dev, 227185087Salfred strindex, langid, buf, buflen); 228184610Salfred 229184610Salfred if (err) 230184610Salfred return (-1); 231184610Salfred 232184610Salfred return (0); 233184610Salfred} 234184610Salfred 235184610Salfredint 236185087Salfredusb_get_string_simple(usb_dev_handle * dev, int strindex, 237184610Salfred char *buf, size_t buflen) 238184610Salfred{ 239184610Salfred int err; 240184610Salfred 241184610Salfred err = libusb20_dev_req_string_simple_sync((void *)dev, 242185087Salfred strindex, buf, buflen); 243184610Salfred 244184610Salfred if (err) 245184610Salfred return (-1); 246184610Salfred 247184610Salfred return (strlen(buf)); 248184610Salfred} 249184610Salfred 250184610Salfredint 251184610Salfredusb_get_descriptor_by_endpoint(usb_dev_handle * udev, int ep, uint8_t type, 252185087Salfred uint8_t ep_index, void *buf, int size) 253184610Salfred{ 254184610Salfred memset(buf, 0, size); 255184610Salfred 256184610Salfred return (usb_control_msg(udev, ep | USB_ENDPOINT_IN, 257185087Salfred USB_REQ_GET_DESCRIPTOR, (type << 8) + ep_index, 0, 258184610Salfred buf, size, 1000)); 259184610Salfred} 260184610Salfred 261184610Salfredint 262185087Salfredusb_get_descriptor(usb_dev_handle * udev, uint8_t type, uint8_t desc_index, 263184610Salfred void *buf, int size) 264184610Salfred{ 265184610Salfred memset(buf, 0, size); 266184610Salfred 267184610Salfred return (usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, 268185087Salfred (type << 8) + desc_index, 0, buf, size, 1000)); 269184610Salfred} 270184610Salfred 271184610Salfredint 272184610Salfredusb_parse_descriptor(uint8_t *source, char *description, void *dest) 273184610Salfred{ 274184610Salfred uint8_t *sp = source; 275184610Salfred uint8_t *dp = dest; 276184610Salfred uint16_t w; 277184610Salfred uint32_t d; 278184610Salfred char *cp; 279184610Salfred 280184610Salfred for (cp = description; *cp; cp++) { 281184610Salfred switch (*cp) { 282184610Salfred case 'b': /* 8-bit byte */ 283184610Salfred *dp++ = *sp++; 284184610Salfred break; 285184610Salfred /* 286184610Salfred * 16-bit word, convert from little endian to CPU 287184610Salfred */ 288184610Salfred case 'w': 289184610Salfred w = (sp[1] << 8) | sp[0]; 290184610Salfred sp += 2; 291184610Salfred /* Align to word boundary */ 292184610Salfred dp += ((dp - (uint8_t *)0) & 1); 293184610Salfred *((uint16_t *)dp) = w; 294184610Salfred dp += 2; 295184610Salfred break; 296184610Salfred /* 297184610Salfred * 32-bit dword, convert from little endian to CPU 298184610Salfred */ 299184610Salfred case 'd': 300184610Salfred d = (sp[3] << 24) | (sp[2] << 16) | 301184610Salfred (sp[1] << 8) | sp[0]; 302184610Salfred sp += 4; 303184610Salfred /* Align to word boundary */ 304184610Salfred dp += ((dp - (uint8_t *)0) & 1); 305184610Salfred /* Align to double word boundary */ 306184610Salfred dp += ((dp - (uint8_t *)0) & 2); 307184610Salfred *((uint32_t *)dp) = d; 308184610Salfred dp += 4; 309184610Salfred break; 310184610Salfred } 311184610Salfred } 312184610Salfred return (sp - source); 313184610Salfred} 314184610Salfred 315184610Salfredstatic void 316184610Salfredusb_parse_extra(struct usb_parse_state *ps, uint8_t **pptr, int *plen) 317184610Salfred{ 318184610Salfred void *ptr; 319184610Salfred uint16_t len; 320184610Salfred 321184610Salfred ptr = ps->a.currextra->ptr; 322184610Salfred len = ps->a.currextra->len; 323184610Salfred 324184610Salfred if (ps->preparse == 0) { 325184610Salfred memcpy(ps->b.currextra, ptr, len); 326184610Salfred *pptr = ps->b.currextra; 327184610Salfred *plen = len; 328184610Salfred } 329184610Salfred ps->b.currextra += len; 330184610Salfred return; 331184610Salfred} 332184610Salfred 333184610Salfredstatic void 334184610Salfredusb_parse_endpoint(struct usb_parse_state *ps) 335184610Salfred{ 336184610Salfred struct usb_endpoint_descriptor *bep; 337184610Salfred struct libusb20_endpoint *aep; 338184610Salfred 339184610Salfred aep = ps->a.currep; 340184610Salfred bep = ps->b.currep++; 341184610Salfred 342184610Salfred if (ps->preparse == 0) { 343184610Salfred /* copy descriptor fields */ 344184610Salfred bep->bLength = aep->desc.bLength; 345184610Salfred bep->bDescriptorType = aep->desc.bDescriptorType; 346184610Salfred bep->bEndpointAddress = aep->desc.bEndpointAddress; 347184610Salfred bep->bmAttributes = aep->desc.bmAttributes; 348184610Salfred bep->wMaxPacketSize = aep->desc.wMaxPacketSize; 349184610Salfred bep->bInterval = aep->desc.bInterval; 350184610Salfred bep->bRefresh = aep->desc.bRefresh; 351184610Salfred bep->bSynchAddress = aep->desc.bSynchAddress; 352184610Salfred } 353184610Salfred ps->a.currextra = &aep->extra; 354184610Salfred usb_parse_extra(ps, &bep->extra, &bep->extralen); 355184610Salfred return; 356184610Salfred} 357184610Salfred 358184610Salfredstatic void 359184610Salfredusb_parse_iface_sub(struct usb_parse_state *ps) 360184610Salfred{ 361184610Salfred struct libusb20_interface *aifc; 362184610Salfred struct usb_interface_descriptor *bifc; 363184610Salfred uint8_t x; 364184610Salfred 365184610Salfred aifc = ps->a.currifc; 366184610Salfred bifc = ps->b.currifc++; 367184610Salfred 368184610Salfred if (ps->preparse == 0) { 369184610Salfred /* copy descriptor fields */ 370184610Salfred bifc->bLength = aifc->desc.bLength; 371184610Salfred bifc->bDescriptorType = aifc->desc.bDescriptorType; 372184610Salfred bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber; 373184610Salfred bifc->bAlternateSetting = aifc->desc.bAlternateSetting; 374184610Salfred bifc->bNumEndpoints = aifc->num_endpoints; 375184610Salfred bifc->bInterfaceClass = aifc->desc.bInterfaceClass; 376184610Salfred bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass; 377184610Salfred bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol; 378184610Salfred bifc->iInterface = aifc->desc.iInterface; 379184610Salfred bifc->endpoint = ps->b.currep; 380184610Salfred } 381184610Salfred for (x = 0; x != aifc->num_endpoints; x++) { 382184610Salfred ps->a.currep = aifc->endpoints + x; 383184610Salfred usb_parse_endpoint(ps); 384184610Salfred } 385184610Salfred 386184610Salfred ps->a.currextra = &aifc->extra; 387184610Salfred usb_parse_extra(ps, &bifc->extra, &bifc->extralen); 388184610Salfred return; 389184610Salfred} 390184610Salfred 391184610Salfredstatic void 392184610Salfredusb_parse_iface(struct usb_parse_state *ps) 393184610Salfred{ 394184610Salfred struct libusb20_interface *aifc; 395184610Salfred struct usb_interface *bifc; 396184610Salfred uint8_t x; 397184610Salfred 398184610Salfred aifc = ps->a.currifc; 399184610Salfred bifc = ps->b.currifcw++; 400184610Salfred 401184610Salfred if (ps->preparse == 0) { 402184610Salfred /* initialise interface wrapper */ 403184610Salfred bifc->altsetting = ps->b.currifc; 404184610Salfred bifc->num_altsetting = aifc->num_altsetting + 1; 405184610Salfred } 406184610Salfred usb_parse_iface_sub(ps); 407184610Salfred 408184610Salfred for (x = 0; x != aifc->num_altsetting; x++) { 409184610Salfred ps->a.currifc = aifc->altsetting + x; 410184610Salfred usb_parse_iface_sub(ps); 411184610Salfred } 412184610Salfred return; 413184610Salfred} 414184610Salfred 415184610Salfredstatic void 416184610Salfredusb_parse_config(struct usb_parse_state *ps) 417184610Salfred{ 418184610Salfred struct libusb20_config *acfg; 419184610Salfred struct usb_config_descriptor *bcfg; 420184610Salfred uint8_t x; 421184610Salfred 422184610Salfred acfg = ps->a.currcfg; 423184610Salfred bcfg = ps->b.currcfg; 424184610Salfred 425184610Salfred if (ps->preparse == 0) { 426184610Salfred /* initialise config wrapper */ 427184610Salfred bcfg->bLength = acfg->desc.bLength; 428184610Salfred bcfg->bDescriptorType = acfg->desc.bDescriptorType; 429184610Salfred bcfg->wTotalLength = acfg->desc.wTotalLength; 430184610Salfred bcfg->bNumInterfaces = acfg->num_interface; 431184610Salfred bcfg->bConfigurationValue = acfg->desc.bConfigurationValue; 432184610Salfred bcfg->iConfiguration = acfg->desc.iConfiguration; 433184610Salfred bcfg->bmAttributes = acfg->desc.bmAttributes; 434184610Salfred bcfg->MaxPower = acfg->desc.bMaxPower; 435184610Salfred bcfg->interface = ps->b.currifcw; 436184610Salfred } 437184610Salfred for (x = 0; x != acfg->num_interface; x++) { 438184610Salfred ps->a.currifc = acfg->interface + x; 439184610Salfred usb_parse_iface(ps); 440184610Salfred } 441184610Salfred 442184610Salfred ps->a.currextra = &acfg->extra; 443184610Salfred usb_parse_extra(ps, &bcfg->extra, &bcfg->extralen); 444184610Salfred return; 445184610Salfred} 446184610Salfred 447184610Salfredint 448184610Salfredusb_parse_configuration(struct usb_config_descriptor *config, 449184610Salfred uint8_t *buffer) 450184610Salfred{ 451184610Salfred struct usb_parse_state ps; 452184610Salfred uint8_t *ptr; 453184610Salfred uint32_t a; 454184610Salfred uint32_t b; 455184610Salfred uint32_t c; 456184610Salfred uint32_t d; 457184610Salfred 458184610Salfred if ((buffer == NULL) || (config == NULL)) { 459184610Salfred return (-1); 460184610Salfred } 461184610Salfred memset(&ps, 0, sizeof(ps)); 462184610Salfred 463184610Salfred ps.a.currcfg = libusb20_parse_config_desc(buffer); 464184610Salfred ps.b.currcfg = config; 465184610Salfred if (ps.a.currcfg == NULL) { 466184610Salfred /* could not parse config or out of memory */ 467184610Salfred return (-1); 468184610Salfred } 469184610Salfred /* do the pre-parse */ 470184610Salfred ps.preparse = 1; 471184610Salfred usb_parse_config(&ps); 472184610Salfred 473184610Salfred a = ((uint8_t *)(ps.b.currifcw) - ((uint8_t *)0)); 474184610Salfred b = ((uint8_t *)(ps.b.currifc) - ((uint8_t *)0)); 475184610Salfred c = ((uint8_t *)(ps.b.currep) - ((uint8_t *)0)); 476184610Salfred d = ((uint8_t *)(ps.b.currextra) - ((uint8_t *)0)); 477184610Salfred 478184610Salfred /* allocate memory for our configuration */ 479184610Salfred ptr = malloc(a + b + c + d); 480184610Salfred 481184610Salfred /* "currifcw" must be first, hence this pointer is freed */ 482184610Salfred ps.b.currifcw = (void *)(ptr); 483184610Salfred ps.b.currifc = (void *)(ptr + a); 484184610Salfred ps.b.currep = (void *)(ptr + a + b); 485184610Salfred ps.b.currextra = (void *)(ptr + a + b + c); 486184610Salfred 487184610Salfred /* generate a libusb v0.1 compatible structure */ 488184610Salfred ps.preparse = 0; 489184610Salfred usb_parse_config(&ps); 490184610Salfred 491184610Salfred /* free config structure */ 492184610Salfred free(ps.a.currcfg); 493184610Salfred 494184610Salfred return (0); /* success */ 495184610Salfred} 496184610Salfred 497184610Salfredvoid 498184610Salfredusb_destroy_configuration(struct usb_device *dev) 499184610Salfred{ 500184610Salfred uint8_t c; 501184610Salfred 502184610Salfred if (dev->config == NULL) { 503184610Salfred return; 504184610Salfred } 505184610Salfred for (c = 0; c != dev->descriptor.bNumConfigurations; c++) { 506184610Salfred struct usb_config_descriptor *cf = &dev->config[c]; 507184610Salfred 508184610Salfred if (cf->interface != NULL) { 509184610Salfred free(cf->interface); 510184610Salfred cf->interface = NULL; 511184610Salfred } 512184610Salfred } 513184610Salfred 514184610Salfred free(dev->config); 515184610Salfred dev->config = NULL; 516184610Salfred return; 517184610Salfred} 518184610Salfred 519184610Salfredvoid 520184610Salfredusb_fetch_and_parse_descriptors(usb_dev_handle * udev) 521184610Salfred{ 522184610Salfred struct usb_device *dev; 523184610Salfred struct libusb20_device *pdev; 524184610Salfred uint8_t *ptr; 525184610Salfred int error; 526184610Salfred uint32_t size; 527184610Salfred uint16_t len; 528184610Salfred uint8_t x; 529184610Salfred 530184610Salfred if (udev == NULL) { 531184610Salfred /* be NULL safe */ 532184610Salfred return; 533184610Salfred } 534184610Salfred dev = usb_device(udev); 535184610Salfred pdev = (void *)udev; 536184610Salfred 537184610Salfred if (dev->descriptor.bNumConfigurations == 0) { 538184610Salfred /* invalid device */ 539184610Salfred return; 540184610Salfred } 541184610Salfred size = dev->descriptor.bNumConfigurations * 542184610Salfred sizeof(struct usb_config_descriptor); 543184610Salfred 544184610Salfred dev->config = malloc(size); 545184610Salfred if (dev->config == NULL) { 546184610Salfred /* out of memory */ 547184610Salfred return; 548184610Salfred } 549184610Salfred memset(dev->config, 0, size); 550184610Salfred 551184610Salfred for (x = 0; x != dev->descriptor.bNumConfigurations; x++) { 552184610Salfred 553184610Salfred error = (pdev->methods->get_config_desc_full) ( 554184610Salfred pdev, &ptr, &len, x); 555184610Salfred 556184610Salfred if (error) { 557184610Salfred usb_destroy_configuration(dev); 558184610Salfred return; 559184610Salfred } 560184610Salfred usb_parse_configuration(dev->config + x, ptr); 561184610Salfred 562184610Salfred /* free config buffer */ 563184610Salfred free(ptr); 564184610Salfred } 565184610Salfred return; 566184610Salfred} 567184610Salfred 568184610Salfredstatic int 569184610Salfredusb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size, 570184610Salfred int timeout, int is_intr) 571184610Salfred{ 572184610Salfred struct libusb20_transfer *xfer; 573184610Salfred uint32_t temp; 574184610Salfred uint32_t maxsize; 575184610Salfred uint32_t actlen; 576184610Salfred char *oldbytes; 577184610Salfred 578184610Salfred xfer = usb_get_transfer_by_ep_no(dev, ep); 579184610Salfred if (xfer == NULL) 580184610Salfred return (-1); 581184610Salfred 582184610Salfred if (libusb20_tr_pending(xfer)) { 583184610Salfred /* there is already a transfer ongoing */ 584184610Salfred return (-1); 585184610Salfred } 586184610Salfred maxsize = libusb20_tr_get_max_total_length(xfer); 587184610Salfred oldbytes = bytes; 588184610Salfred 589184610Salfred /* 590184610Salfred * We allow transferring zero bytes which is the same 591184610Salfred * equivalent to a zero length USB packet. 592184610Salfred */ 593184610Salfred do { 594184610Salfred 595184610Salfred temp = size; 596184610Salfred if (temp > maxsize) { 597184610Salfred /* find maximum possible length */ 598184610Salfred temp = maxsize; 599184610Salfred } 600184610Salfred if (is_intr) 601184610Salfred libusb20_tr_setup_intr(xfer, bytes, temp, timeout); 602184610Salfred else 603184610Salfred libusb20_tr_setup_bulk(xfer, bytes, temp, timeout); 604184610Salfred 605184610Salfred libusb20_tr_start(xfer); 606184610Salfred 607184610Salfred while (1) { 608184610Salfred 609184610Salfred if (libusb20_dev_process((void *)dev) != 0) { 610184610Salfred /* device detached */ 611184610Salfred return (-1); 612184610Salfred } 613184610Salfred if (libusb20_tr_pending(xfer) == 0) { 614184610Salfred /* transfer complete */ 615184610Salfred break; 616184610Salfred } 617184610Salfred /* wait for USB event from kernel */ 618184610Salfred libusb20_dev_wait_process((void *)dev, -1); 619184610Salfred } 620184610Salfred 621188678Sthompsa switch (libusb20_tr_get_status(xfer)) { 622188678Sthompsa case 0: 623188678Sthompsa /* success */ 624188678Sthompsa break; 625188678Sthompsa case LIBUSB20_TRANSFER_TIMED_OUT: 626188678Sthompsa /* transfer timeout */ 627188678Sthompsa return (-ETIMEDOUT); 628188678Sthompsa default: 629188678Sthompsa /* other transfer error */ 630188678Sthompsa return (-ENXIO); 631184610Salfred } 632184610Salfred actlen = libusb20_tr_get_actual_length(xfer); 633184610Salfred 634184610Salfred bytes += actlen; 635184610Salfred size -= actlen; 636184610Salfred 637184610Salfred if (actlen != temp) { 638184610Salfred /* short transfer */ 639184610Salfred break; 640184610Salfred } 641184610Salfred } while (size > 0); 642184610Salfred 643184610Salfred return (bytes - oldbytes); 644184610Salfred} 645184610Salfred 646184610Salfredint 647184610Salfredusb_bulk_write(usb_dev_handle * dev, int ep, char *bytes, 648184610Salfred int size, int timeout) 649184610Salfred{ 650185087Salfred return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, 651185087Salfred bytes, size, timeout, 0)); 652184610Salfred} 653184610Salfred 654184610Salfredint 655184610Salfredusb_bulk_read(usb_dev_handle * dev, int ep, char *bytes, 656184610Salfred int size, int timeout) 657184610Salfred{ 658185087Salfred return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, 659185087Salfred bytes, size, timeout, 0)); 660184610Salfred} 661184610Salfred 662184610Salfredint 663184610Salfredusb_interrupt_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, 1)); 668184610Salfred} 669184610Salfred 670184610Salfredint 671184610Salfredusb_interrupt_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, 1)); 676184610Salfred} 677184610Salfred 678184610Salfredint 679184610Salfredusb_control_msg(usb_dev_handle * dev, int requesttype, int request, 680185087Salfred int value, int wIndex, char *bytes, int size, int timeout) 681184610Salfred{ 682184610Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 683184610Salfred int err; 684184610Salfred uint16_t actlen; 685184610Salfred 686184610Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 687184610Salfred 688184610Salfred req.bmRequestType = requesttype; 689184610Salfred req.bRequest = request; 690184610Salfred req.wValue = value; 691185087Salfred req.wIndex = wIndex; 692184610Salfred req.wLength = size; 693184610Salfred 694184610Salfred err = libusb20_dev_request_sync((void *)dev, &req, bytes, 695184610Salfred &actlen, timeout, 0); 696184610Salfred 697184610Salfred if (err) 698184610Salfred return (-1); 699184610Salfred 700184610Salfred return (actlen); 701184610Salfred} 702184610Salfred 703184610Salfredint 704185087Salfredusb_set_configuration(usb_dev_handle * udev, int bConfigurationValue) 705184610Salfred{ 706185087Salfred struct usb_device *dev; 707184610Salfred int err; 708185087Salfred uint8_t i; 709184610Salfred 710185087Salfred /* 711185087Salfred * Need to translate from "bConfigurationValue" to 712185087Salfred * configuration index: 713185087Salfred */ 714184610Salfred 715185087Salfred if (bConfigurationValue == 0) { 716185087Salfred /* unconfigure */ 717185087Salfred i = 255; 718185087Salfred } else { 719185087Salfred /* lookup configuration index */ 720185087Salfred dev = usb_device(udev); 721185087Salfred 722185087Salfred /* check if the configuration array is not there */ 723185087Salfred if (dev->config == NULL) { 724185087Salfred return (-1); 725185087Salfred } 726185087Salfred for (i = 0;; i++) { 727185087Salfred if (i == dev->descriptor.bNumConfigurations) { 728185087Salfred /* "bConfigurationValue" not found */ 729185087Salfred return (-1); 730185087Salfred } 731185290Salfred if ((dev->config + i)->bConfigurationValue == 732185290Salfred bConfigurationValue) { 733185087Salfred break; 734185087Salfred } 735185087Salfred } 736185087Salfred } 737185087Salfred 738185087Salfred err = libusb20_dev_set_config_index((void *)udev, i); 739185087Salfred 740184610Salfred if (err) 741184610Salfred return (-1); 742184610Salfred 743184610Salfred return (0); 744184610Salfred} 745184610Salfred 746184610Salfredint 747184610Salfredusb_claim_interface(usb_dev_handle * dev, int interface) 748184610Salfred{ 749184610Salfred int err; 750184610Salfred 751184610Salfred err = libusb20_dev_claim_interface((void *)dev, interface); 752184610Salfred 753184610Salfred if (err) 754184610Salfred return (-1); 755184610Salfred 756184610Salfred return (0); 757184610Salfred} 758184610Salfred 759184610Salfredint 760184610Salfredusb_release_interface(usb_dev_handle * dev, int interface) 761184610Salfred{ 762184610Salfred int err; 763184610Salfred 764184610Salfred err = libusb20_dev_release_interface((void *)dev, interface); 765184610Salfred 766184610Salfred if (err) 767184610Salfred return (-1); 768184610Salfred 769184610Salfred return (0); 770184610Salfred} 771184610Salfred 772184610Salfredint 773184610Salfredusb_set_altinterface(usb_dev_handle * dev, int alternate) 774184610Salfred{ 775184610Salfred int err; 776184610Salfred uint8_t iface; 777184610Salfred 778184610Salfred iface = usb_get_first_claimed_interface(dev); 779184610Salfred 780184610Salfred err = libusb20_dev_set_alt_index((void *)dev, iface, alternate); 781184610Salfred 782184610Salfred if (err) 783184610Salfred return (-1); 784184610Salfred 785184610Salfred return (0); 786184610Salfred} 787184610Salfred 788184610Salfredint 789184610Salfredusb_resetep(usb_dev_handle * dev, unsigned int ep) 790184610Salfred{ 791184610Salfred /* emulate an endpoint reset through clear-STALL */ 792184610Salfred return (usb_clear_halt(dev, ep)); 793184610Salfred} 794184610Salfred 795184610Salfredint 796184610Salfredusb_clear_halt(usb_dev_handle * dev, unsigned int ep) 797184610Salfred{ 798184610Salfred struct libusb20_transfer *xfer; 799184610Salfred 800184610Salfred xfer = usb_get_transfer_by_ep_no(dev, ep); 801184610Salfred if (xfer == NULL) 802184610Salfred return (-1); 803184610Salfred 804184610Salfred libusb20_tr_clear_stall_sync(xfer); 805184610Salfred 806184610Salfred return (0); 807184610Salfred} 808184610Salfred 809184610Salfredint 810184610Salfredusb_reset(usb_dev_handle * dev) 811184610Salfred{ 812184610Salfred int err; 813184610Salfred 814184610Salfred err = libusb20_dev_reset((void *)dev); 815184610Salfred 816184610Salfred if (err) 817184610Salfred return (-1); 818184610Salfred 819184610Salfred return (0); 820184610Salfred} 821184610Salfred 822185087Salfredconst char * 823184610Salfredusb_strerror(void) 824184610Salfred{ 825184610Salfred /* TODO */ 826184610Salfred return ("Unknown error"); 827184610Salfred} 828184610Salfred 829184610Salfredvoid 830184610Salfredusb_init(void) 831184610Salfred{ 832184610Salfred /* nothing to do */ 833184610Salfred return; 834184610Salfred} 835184610Salfred 836184610Salfredvoid 837184610Salfredusb_set_debug(int level) 838184610Salfred{ 839184610Salfred /* use kernel UGEN debugging if you need to see what is going on */ 840184610Salfred return; 841184610Salfred} 842184610Salfred 843184610Salfredint 844184610Salfredusb_find_busses(void) 845184610Salfred{ 846184610Salfred usb_busses = &usb_global_bus; 847184610Salfred return (0); 848184610Salfred} 849184610Salfred 850184610Salfredint 851184610Salfredusb_find_devices(void) 852184610Salfred{ 853184610Salfred struct libusb20_device *pdev; 854184610Salfred struct usb_device *udev; 855184610Salfred struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; 856184610Salfred int err; 857184610Salfred 858184610Salfred /* cleanup after last device search */ 859185290Salfred /* close all opened devices, if any */ 860184610Salfred 861185290Salfred while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 862185290Salfred udev = pdev->priv01Data; 863185290Salfred libusb20_be_dequeue_device(usb_backend, pdev); 864185290Salfred libusb20_dev_free(pdev); 865185290Salfred if (udev != NULL) { 866185290Salfred LIST_DEL(usb_global_bus.devices, udev); 867185290Salfred free(udev); 868184610Salfred } 869184610Salfred } 870184610Salfred 871185290Salfred /* free old USB backend, if any */ 872185290Salfred 873185290Salfred libusb20_be_free(usb_backend); 874185290Salfred 875184610Salfred /* do a new backend device search */ 876184610Salfred usb_backend = libusb20_be_alloc_default(); 877184610Salfred if (usb_backend == NULL) { 878184610Salfred return (-1); 879184610Salfred } 880184610Salfred /* iterate all devices */ 881184610Salfred 882184610Salfred pdev = NULL; 883184610Salfred while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) { 884184610Salfred udev = malloc(sizeof(*udev)); 885184610Salfred if (udev == NULL) 886184610Salfred break; 887184610Salfred 888184610Salfred memset(udev, 0, sizeof(*udev)); 889184610Salfred 890184610Salfred udev->bus = &usb_global_bus; 891184610Salfred 892184610Salfred snprintf(udev->filename, sizeof(udev->filename), 893184610Salfred "/dev/ugen%u.%u", 894184610Salfred libusb20_dev_get_bus_number(pdev), 895184610Salfred libusb20_dev_get_address(pdev)); 896184610Salfred 897184610Salfred ddesc = libusb20_dev_get_device_desc(pdev); 898184610Salfred 899184610Salfred udev->descriptor.bLength = sizeof(udev->descriptor); 900184610Salfred udev->descriptor.bDescriptorType = ddesc->bDescriptorType; 901184610Salfred udev->descriptor.bcdUSB = ddesc->bcdUSB; 902184610Salfred udev->descriptor.bDeviceClass = ddesc->bDeviceClass; 903184610Salfred udev->descriptor.bDeviceSubClass = ddesc->bDeviceSubClass; 904184610Salfred udev->descriptor.bDeviceProtocol = ddesc->bDeviceProtocol; 905184610Salfred udev->descriptor.bMaxPacketSize0 = ddesc->bMaxPacketSize0; 906184610Salfred udev->descriptor.idVendor = ddesc->idVendor; 907184610Salfred udev->descriptor.idProduct = ddesc->idProduct; 908184610Salfred udev->descriptor.bcdDevice = ddesc->bcdDevice; 909184610Salfred udev->descriptor.iManufacturer = ddesc->iManufacturer; 910184610Salfred udev->descriptor.iProduct = ddesc->iProduct; 911184610Salfred udev->descriptor.iSerialNumber = ddesc->iSerialNumber; 912184610Salfred udev->descriptor.bNumConfigurations = 913184610Salfred ddesc->bNumConfigurations; 914184610Salfred if (udev->descriptor.bNumConfigurations > USB_MAXCONFIG) { 915184610Salfred /* truncate number of configurations */ 916184610Salfred udev->descriptor.bNumConfigurations = USB_MAXCONFIG; 917184610Salfred } 918184610Salfred /* link together the two structures */ 919184610Salfred udev->dev = pdev; 920184610Salfred pdev->priv01Data = udev; 921184610Salfred 922184610Salfred err = libusb20_dev_open(pdev, 0); 923184610Salfred if (err == 0) { 924184610Salfred /* XXX get all config descriptors by default */ 925184610Salfred usb_fetch_and_parse_descriptors((void *)pdev); 926184610Salfred libusb20_dev_close(pdev); 927184610Salfred } 928184610Salfred LIST_ADD(usb_global_bus.devices, udev); 929184610Salfred } 930184610Salfred 931184610Salfred return (0); /* success */ 932184610Salfred} 933184610Salfred 934184610Salfredstruct usb_device * 935184610Salfredusb_device(usb_dev_handle * dev) 936184610Salfred{ 937184610Salfred struct libusb20_device *pdev; 938184610Salfred 939184610Salfred pdev = (void *)dev; 940184610Salfred 941184610Salfred return (pdev->priv01Data); 942184610Salfred} 943184610Salfred 944184610Salfredstruct usb_bus * 945184610Salfredusb_get_busses(void) 946184610Salfred{ 947184610Salfred return (usb_busses); 948184610Salfred} 949