libusb01.c revision 203815
1184610Salfred/* $FreeBSD: head/lib/libusb/libusb20_compat01.c 203815 2010-02-13 09:45:50Z wkoszek $ */ 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 33203815Swkoszek#include <errno.h> 34203815Swkoszek#include <stdio.h> 35184610Salfred#include <stdlib.h> 36184610Salfred 37184610Salfred#include "libusb20.h" 38184610Salfred#include "libusb20_desc.h" 39184610Salfred#include "libusb20_int.h" 40189585Sthompsa#include "usb.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 struct libusb20_transfer * 103184610Salfredusb_get_transfer_by_ep_no(usb_dev_handle * dev, uint8_t ep_no) 104184610Salfred{ 105184610Salfred struct libusb20_device *pdev = (void *)dev; 106184610Salfred struct libusb20_transfer *xfer; 107184610Salfred int err; 108184610Salfred uint32_t bufsize; 109184610Salfred uint8_t x; 110184610Salfred uint8_t speed; 111184610Salfred 112184610Salfred x = (ep_no & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 2; 113184610Salfred 114184610Salfred if (ep_no & LIBUSB20_ENDPOINT_DIR_MASK) { 115185087Salfred /* this is an IN endpoint */ 116184610Salfred x |= 1; 117184610Salfred } 118184610Salfred speed = libusb20_dev_get_speed(pdev); 119184610Salfred 120184610Salfred /* select a sensible buffer size */ 121184610Salfred if (speed == LIBUSB20_SPEED_LOW) { 122184610Salfred bufsize = 256; 123184610Salfred } else if (speed == LIBUSB20_SPEED_FULL) { 124184610Salfred bufsize = 4096; 125184610Salfred } else { 126184610Salfred bufsize = 16384; 127184610Salfred } 128184610Salfred 129184610Salfred xfer = libusb20_tr_get_pointer(pdev, x); 130184610Salfred 131184610Salfred if (xfer == NULL) 132184610Salfred return (xfer); 133184610Salfred 134184610Salfred err = libusb20_tr_open(xfer, bufsize, 1, ep_no); 135184610Salfred if (err == LIBUSB20_ERROR_BUSY) { 136184610Salfred /* already opened */ 137184610Salfred return (xfer); 138184610Salfred } else if (err) { 139184610Salfred return (NULL); 140184610Salfred } 141184610Salfred /* success */ 142184610Salfred return (xfer); 143184610Salfred} 144184610Salfred 145184610Salfredusb_dev_handle * 146184610Salfredusb_open(struct usb_device *dev) 147184610Salfred{ 148184610Salfred int err; 149184610Salfred 150184610Salfred err = libusb20_dev_open(dev->dev, 16 * 2); 151184610Salfred if (err == LIBUSB20_ERROR_BUSY) { 152184610Salfred /* 153184610Salfred * Workaround buggy USB applications which open the USB 154184610Salfred * device multiple times: 155184610Salfred */ 156184610Salfred return (dev->dev); 157184610Salfred } 158184610Salfred if (err) 159184610Salfred return (NULL); 160184610Salfred 161185290Salfred /* 162185290Salfred * Dequeue USB device from backend queue so that it does not get 163185290Salfred * freed when the backend is re-scanned: 164185290Salfred */ 165185290Salfred libusb20_be_dequeue_device(usb_backend, dev->dev); 166185290Salfred 167184610Salfred return (dev->dev); 168184610Salfred} 169184610Salfred 170184610Salfredint 171185290Salfredusb_close(usb_dev_handle * udev) 172184610Salfred{ 173185290Salfred struct usb_device *dev; 174184610Salfred int err; 175184610Salfred 176185290Salfred err = libusb20_dev_close((void *)udev); 177184610Salfred 178184610Salfred if (err) 179184610Salfred return (-1); 180184610Salfred 181185290Salfred if (usb_backend != NULL) { 182185290Salfred /* 183185290Salfred * Enqueue USB device to backend queue so that it gets freed 184185290Salfred * when the backend is re-scanned: 185185290Salfred */ 186185290Salfred libusb20_be_enqueue_device(usb_backend, (void *)udev); 187185290Salfred } else { 188185290Salfred /* 189185290Salfred * The backend is gone. Free device data so that we 190185290Salfred * don't start leaking memory! 191185290Salfred */ 192185290Salfred dev = usb_device(udev); 193185290Salfred libusb20_dev_free((void *)udev); 194185290Salfred LIST_DEL(usb_global_bus.devices, dev); 195185290Salfred free(dev); 196185290Salfred } 197184610Salfred return (0); 198184610Salfred} 199184610Salfred 200184610Salfredint 201185087Salfredusb_get_string(usb_dev_handle * dev, int strindex, 202184610Salfred int langid, char *buf, size_t buflen) 203184610Salfred{ 204184610Salfred int err; 205184610Salfred 206184610Salfred err = libusb20_dev_req_string_sync((void *)dev, 207185087Salfred strindex, langid, buf, buflen); 208184610Salfred 209184610Salfred if (err) 210184610Salfred return (-1); 211184610Salfred 212184610Salfred return (0); 213184610Salfred} 214184610Salfred 215184610Salfredint 216185087Salfredusb_get_string_simple(usb_dev_handle * dev, int strindex, 217184610Salfred char *buf, size_t buflen) 218184610Salfred{ 219184610Salfred int err; 220184610Salfred 221184610Salfred err = libusb20_dev_req_string_simple_sync((void *)dev, 222185087Salfred strindex, buf, buflen); 223184610Salfred 224184610Salfred if (err) 225184610Salfred return (-1); 226184610Salfred 227184610Salfred return (strlen(buf)); 228184610Salfred} 229184610Salfred 230184610Salfredint 231184610Salfredusb_get_descriptor_by_endpoint(usb_dev_handle * udev, int ep, uint8_t type, 232185087Salfred uint8_t ep_index, void *buf, int size) 233184610Salfred{ 234184610Salfred memset(buf, 0, size); 235184610Salfred 236184610Salfred return (usb_control_msg(udev, ep | USB_ENDPOINT_IN, 237185087Salfred USB_REQ_GET_DESCRIPTOR, (type << 8) + ep_index, 0, 238184610Salfred buf, size, 1000)); 239184610Salfred} 240184610Salfred 241184610Salfredint 242185087Salfredusb_get_descriptor(usb_dev_handle * udev, uint8_t type, uint8_t desc_index, 243184610Salfred void *buf, int size) 244184610Salfred{ 245184610Salfred memset(buf, 0, size); 246184610Salfred 247184610Salfred return (usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, 248185087Salfred (type << 8) + desc_index, 0, buf, size, 1000)); 249184610Salfred} 250184610Salfred 251184610Salfredint 252184610Salfredusb_parse_descriptor(uint8_t *source, char *description, void *dest) 253184610Salfred{ 254184610Salfred uint8_t *sp = source; 255184610Salfred uint8_t *dp = dest; 256184610Salfred uint16_t w; 257184610Salfred uint32_t d; 258184610Salfred char *cp; 259184610Salfred 260184610Salfred for (cp = description; *cp; cp++) { 261184610Salfred switch (*cp) { 262184610Salfred case 'b': /* 8-bit byte */ 263184610Salfred *dp++ = *sp++; 264184610Salfred break; 265184610Salfred /* 266184610Salfred * 16-bit word, convert from little endian to CPU 267184610Salfred */ 268184610Salfred case 'w': 269184610Salfred w = (sp[1] << 8) | sp[0]; 270184610Salfred sp += 2; 271184610Salfred /* Align to word boundary */ 272184610Salfred dp += ((dp - (uint8_t *)0) & 1); 273184610Salfred *((uint16_t *)dp) = w; 274184610Salfred dp += 2; 275184610Salfred break; 276184610Salfred /* 277184610Salfred * 32-bit dword, convert from little endian to CPU 278184610Salfred */ 279184610Salfred case 'd': 280184610Salfred d = (sp[3] << 24) | (sp[2] << 16) | 281184610Salfred (sp[1] << 8) | sp[0]; 282184610Salfred sp += 4; 283184610Salfred /* Align to word boundary */ 284184610Salfred dp += ((dp - (uint8_t *)0) & 1); 285184610Salfred /* Align to double word boundary */ 286184610Salfred dp += ((dp - (uint8_t *)0) & 2); 287184610Salfred *((uint32_t *)dp) = d; 288184610Salfred dp += 4; 289184610Salfred break; 290184610Salfred } 291184610Salfred } 292184610Salfred return (sp - source); 293184610Salfred} 294184610Salfred 295184610Salfredstatic void 296184610Salfredusb_parse_extra(struct usb_parse_state *ps, uint8_t **pptr, int *plen) 297184610Salfred{ 298184610Salfred void *ptr; 299184610Salfred uint16_t len; 300184610Salfred 301184610Salfred ptr = ps->a.currextra->ptr; 302184610Salfred len = ps->a.currextra->len; 303184610Salfred 304184610Salfred if (ps->preparse == 0) { 305184610Salfred memcpy(ps->b.currextra, ptr, len); 306184610Salfred *pptr = ps->b.currextra; 307184610Salfred *plen = len; 308184610Salfred } 309184610Salfred ps->b.currextra += len; 310184610Salfred return; 311184610Salfred} 312184610Salfred 313184610Salfredstatic void 314184610Salfredusb_parse_endpoint(struct usb_parse_state *ps) 315184610Salfred{ 316184610Salfred struct usb_endpoint_descriptor *bep; 317184610Salfred struct libusb20_endpoint *aep; 318184610Salfred 319184610Salfred aep = ps->a.currep; 320184610Salfred bep = ps->b.currep++; 321184610Salfred 322184610Salfred if (ps->preparse == 0) { 323184610Salfred /* copy descriptor fields */ 324184610Salfred bep->bLength = aep->desc.bLength; 325184610Salfred bep->bDescriptorType = aep->desc.bDescriptorType; 326184610Salfred bep->bEndpointAddress = aep->desc.bEndpointAddress; 327184610Salfred bep->bmAttributes = aep->desc.bmAttributes; 328184610Salfred bep->wMaxPacketSize = aep->desc.wMaxPacketSize; 329184610Salfred bep->bInterval = aep->desc.bInterval; 330184610Salfred bep->bRefresh = aep->desc.bRefresh; 331184610Salfred bep->bSynchAddress = aep->desc.bSynchAddress; 332184610Salfred } 333184610Salfred ps->a.currextra = &aep->extra; 334184610Salfred usb_parse_extra(ps, &bep->extra, &bep->extralen); 335184610Salfred return; 336184610Salfred} 337184610Salfred 338184610Salfredstatic void 339184610Salfredusb_parse_iface_sub(struct usb_parse_state *ps) 340184610Salfred{ 341184610Salfred struct libusb20_interface *aifc; 342184610Salfred struct usb_interface_descriptor *bifc; 343184610Salfred uint8_t x; 344184610Salfred 345184610Salfred aifc = ps->a.currifc; 346184610Salfred bifc = ps->b.currifc++; 347184610Salfred 348184610Salfred if (ps->preparse == 0) { 349184610Salfred /* copy descriptor fields */ 350184610Salfred bifc->bLength = aifc->desc.bLength; 351184610Salfred bifc->bDescriptorType = aifc->desc.bDescriptorType; 352184610Salfred bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber; 353184610Salfred bifc->bAlternateSetting = aifc->desc.bAlternateSetting; 354184610Salfred bifc->bNumEndpoints = aifc->num_endpoints; 355184610Salfred bifc->bInterfaceClass = aifc->desc.bInterfaceClass; 356184610Salfred bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass; 357184610Salfred bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol; 358184610Salfred bifc->iInterface = aifc->desc.iInterface; 359184610Salfred bifc->endpoint = ps->b.currep; 360184610Salfred } 361184610Salfred for (x = 0; x != aifc->num_endpoints; x++) { 362184610Salfred ps->a.currep = aifc->endpoints + x; 363184610Salfred usb_parse_endpoint(ps); 364184610Salfred } 365184610Salfred 366184610Salfred ps->a.currextra = &aifc->extra; 367184610Salfred usb_parse_extra(ps, &bifc->extra, &bifc->extralen); 368184610Salfred return; 369184610Salfred} 370184610Salfred 371184610Salfredstatic void 372184610Salfredusb_parse_iface(struct usb_parse_state *ps) 373184610Salfred{ 374184610Salfred struct libusb20_interface *aifc; 375184610Salfred struct usb_interface *bifc; 376184610Salfred uint8_t x; 377184610Salfred 378184610Salfred aifc = ps->a.currifc; 379184610Salfred bifc = ps->b.currifcw++; 380184610Salfred 381184610Salfred if (ps->preparse == 0) { 382184610Salfred /* initialise interface wrapper */ 383184610Salfred bifc->altsetting = ps->b.currifc; 384184610Salfred bifc->num_altsetting = aifc->num_altsetting + 1; 385184610Salfred } 386184610Salfred usb_parse_iface_sub(ps); 387184610Salfred 388184610Salfred for (x = 0; x != aifc->num_altsetting; x++) { 389184610Salfred ps->a.currifc = aifc->altsetting + x; 390184610Salfred usb_parse_iface_sub(ps); 391184610Salfred } 392184610Salfred return; 393184610Salfred} 394184610Salfred 395184610Salfredstatic void 396184610Salfredusb_parse_config(struct usb_parse_state *ps) 397184610Salfred{ 398184610Salfred struct libusb20_config *acfg; 399184610Salfred struct usb_config_descriptor *bcfg; 400184610Salfred uint8_t x; 401184610Salfred 402184610Salfred acfg = ps->a.currcfg; 403184610Salfred bcfg = ps->b.currcfg; 404184610Salfred 405184610Salfred if (ps->preparse == 0) { 406184610Salfred /* initialise config wrapper */ 407184610Salfred bcfg->bLength = acfg->desc.bLength; 408184610Salfred bcfg->bDescriptorType = acfg->desc.bDescriptorType; 409184610Salfred bcfg->wTotalLength = acfg->desc.wTotalLength; 410184610Salfred bcfg->bNumInterfaces = acfg->num_interface; 411184610Salfred bcfg->bConfigurationValue = acfg->desc.bConfigurationValue; 412184610Salfred bcfg->iConfiguration = acfg->desc.iConfiguration; 413184610Salfred bcfg->bmAttributes = acfg->desc.bmAttributes; 414184610Salfred bcfg->MaxPower = acfg->desc.bMaxPower; 415184610Salfred bcfg->interface = ps->b.currifcw; 416184610Salfred } 417184610Salfred for (x = 0; x != acfg->num_interface; x++) { 418184610Salfred ps->a.currifc = acfg->interface + x; 419184610Salfred usb_parse_iface(ps); 420184610Salfred } 421184610Salfred 422184610Salfred ps->a.currextra = &acfg->extra; 423184610Salfred usb_parse_extra(ps, &bcfg->extra, &bcfg->extralen); 424184610Salfred return; 425184610Salfred} 426184610Salfred 427184610Salfredint 428184610Salfredusb_parse_configuration(struct usb_config_descriptor *config, 429184610Salfred uint8_t *buffer) 430184610Salfred{ 431184610Salfred struct usb_parse_state ps; 432184610Salfred uint8_t *ptr; 433184610Salfred uint32_t a; 434184610Salfred uint32_t b; 435184610Salfred uint32_t c; 436184610Salfred uint32_t d; 437184610Salfred 438184610Salfred if ((buffer == NULL) || (config == NULL)) { 439184610Salfred return (-1); 440184610Salfred } 441184610Salfred memset(&ps, 0, sizeof(ps)); 442184610Salfred 443184610Salfred ps.a.currcfg = libusb20_parse_config_desc(buffer); 444184610Salfred ps.b.currcfg = config; 445184610Salfred if (ps.a.currcfg == NULL) { 446184610Salfred /* could not parse config or out of memory */ 447184610Salfred return (-1); 448184610Salfred } 449184610Salfred /* do the pre-parse */ 450184610Salfred ps.preparse = 1; 451184610Salfred usb_parse_config(&ps); 452184610Salfred 453184610Salfred a = ((uint8_t *)(ps.b.currifcw) - ((uint8_t *)0)); 454184610Salfred b = ((uint8_t *)(ps.b.currifc) - ((uint8_t *)0)); 455184610Salfred c = ((uint8_t *)(ps.b.currep) - ((uint8_t *)0)); 456184610Salfred d = ((uint8_t *)(ps.b.currextra) - ((uint8_t *)0)); 457184610Salfred 458184610Salfred /* allocate memory for our configuration */ 459184610Salfred ptr = malloc(a + b + c + d); 460184610Salfred 461184610Salfred /* "currifcw" must be first, hence this pointer is freed */ 462184610Salfred ps.b.currifcw = (void *)(ptr); 463184610Salfred ps.b.currifc = (void *)(ptr + a); 464184610Salfred ps.b.currep = (void *)(ptr + a + b); 465184610Salfred ps.b.currextra = (void *)(ptr + a + b + c); 466184610Salfred 467184610Salfred /* generate a libusb v0.1 compatible structure */ 468184610Salfred ps.preparse = 0; 469184610Salfred usb_parse_config(&ps); 470184610Salfred 471184610Salfred /* free config structure */ 472184610Salfred free(ps.a.currcfg); 473184610Salfred 474184610Salfred return (0); /* success */ 475184610Salfred} 476184610Salfred 477184610Salfredvoid 478184610Salfredusb_destroy_configuration(struct usb_device *dev) 479184610Salfred{ 480184610Salfred uint8_t c; 481184610Salfred 482184610Salfred if (dev->config == NULL) { 483184610Salfred return; 484184610Salfred } 485184610Salfred for (c = 0; c != dev->descriptor.bNumConfigurations; c++) { 486184610Salfred struct usb_config_descriptor *cf = &dev->config[c]; 487184610Salfred 488184610Salfred if (cf->interface != NULL) { 489184610Salfred free(cf->interface); 490184610Salfred cf->interface = NULL; 491184610Salfred } 492184610Salfred } 493184610Salfred 494184610Salfred free(dev->config); 495184610Salfred dev->config = NULL; 496184610Salfred return; 497184610Salfred} 498184610Salfred 499184610Salfredvoid 500184610Salfredusb_fetch_and_parse_descriptors(usb_dev_handle * udev) 501184610Salfred{ 502184610Salfred struct usb_device *dev; 503184610Salfred struct libusb20_device *pdev; 504184610Salfred uint8_t *ptr; 505184610Salfred int error; 506184610Salfred uint32_t size; 507184610Salfred uint16_t len; 508184610Salfred uint8_t x; 509184610Salfred 510184610Salfred if (udev == NULL) { 511184610Salfred /* be NULL safe */ 512184610Salfred return; 513184610Salfred } 514184610Salfred dev = usb_device(udev); 515184610Salfred pdev = (void *)udev; 516184610Salfred 517184610Salfred if (dev->descriptor.bNumConfigurations == 0) { 518184610Salfred /* invalid device */ 519184610Salfred return; 520184610Salfred } 521184610Salfred size = dev->descriptor.bNumConfigurations * 522184610Salfred sizeof(struct usb_config_descriptor); 523184610Salfred 524184610Salfred dev->config = malloc(size); 525184610Salfred if (dev->config == NULL) { 526184610Salfred /* out of memory */ 527184610Salfred return; 528184610Salfred } 529184610Salfred memset(dev->config, 0, size); 530184610Salfred 531184610Salfred for (x = 0; x != dev->descriptor.bNumConfigurations; x++) { 532184610Salfred 533184610Salfred error = (pdev->methods->get_config_desc_full) ( 534184610Salfred pdev, &ptr, &len, x); 535184610Salfred 536184610Salfred if (error) { 537184610Salfred usb_destroy_configuration(dev); 538184610Salfred return; 539184610Salfred } 540184610Salfred usb_parse_configuration(dev->config + x, ptr); 541184610Salfred 542184610Salfred /* free config buffer */ 543184610Salfred free(ptr); 544184610Salfred } 545184610Salfred return; 546184610Salfred} 547184610Salfred 548184610Salfredstatic int 549184610Salfredusb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size, 550184610Salfred int timeout, int is_intr) 551184610Salfred{ 552184610Salfred struct libusb20_transfer *xfer; 553184610Salfred uint32_t temp; 554184610Salfred uint32_t maxsize; 555184610Salfred uint32_t actlen; 556184610Salfred char *oldbytes; 557184610Salfred 558184610Salfred xfer = usb_get_transfer_by_ep_no(dev, ep); 559184610Salfred if (xfer == NULL) 560184610Salfred return (-1); 561184610Salfred 562184610Salfred if (libusb20_tr_pending(xfer)) { 563184610Salfred /* there is already a transfer ongoing */ 564184610Salfred return (-1); 565184610Salfred } 566184610Salfred maxsize = libusb20_tr_get_max_total_length(xfer); 567184610Salfred oldbytes = bytes; 568184610Salfred 569184610Salfred /* 570184610Salfred * We allow transferring zero bytes which is the same 571184610Salfred * equivalent to a zero length USB packet. 572184610Salfred */ 573184610Salfred do { 574184610Salfred 575184610Salfred temp = size; 576184610Salfred if (temp > maxsize) { 577184610Salfred /* find maximum possible length */ 578184610Salfred temp = maxsize; 579184610Salfred } 580184610Salfred if (is_intr) 581184610Salfred libusb20_tr_setup_intr(xfer, bytes, temp, timeout); 582184610Salfred else 583184610Salfred libusb20_tr_setup_bulk(xfer, bytes, temp, timeout); 584184610Salfred 585184610Salfred libusb20_tr_start(xfer); 586184610Salfred 587184610Salfred while (1) { 588184610Salfred 589184610Salfred if (libusb20_dev_process((void *)dev) != 0) { 590184610Salfred /* device detached */ 591184610Salfred return (-1); 592184610Salfred } 593184610Salfred if (libusb20_tr_pending(xfer) == 0) { 594184610Salfred /* transfer complete */ 595184610Salfred break; 596184610Salfred } 597184610Salfred /* wait for USB event from kernel */ 598184610Salfred libusb20_dev_wait_process((void *)dev, -1); 599184610Salfred } 600184610Salfred 601188678Sthompsa switch (libusb20_tr_get_status(xfer)) { 602188678Sthompsa case 0: 603188678Sthompsa /* success */ 604188678Sthompsa break; 605188678Sthompsa case LIBUSB20_TRANSFER_TIMED_OUT: 606188678Sthompsa /* transfer timeout */ 607188678Sthompsa return (-ETIMEDOUT); 608188678Sthompsa default: 609188678Sthompsa /* other transfer error */ 610188678Sthompsa return (-ENXIO); 611184610Salfred } 612184610Salfred actlen = libusb20_tr_get_actual_length(xfer); 613184610Salfred 614184610Salfred bytes += actlen; 615184610Salfred size -= actlen; 616184610Salfred 617184610Salfred if (actlen != temp) { 618184610Salfred /* short transfer */ 619184610Salfred break; 620184610Salfred } 621184610Salfred } while (size > 0); 622184610Salfred 623184610Salfred return (bytes - oldbytes); 624184610Salfred} 625184610Salfred 626184610Salfredint 627184610Salfredusb_bulk_write(usb_dev_handle * dev, int ep, char *bytes, 628184610Salfred int size, int timeout) 629184610Salfred{ 630185087Salfred return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, 631185087Salfred bytes, size, timeout, 0)); 632184610Salfred} 633184610Salfred 634184610Salfredint 635184610Salfredusb_bulk_read(usb_dev_handle * dev, int ep, char *bytes, 636184610Salfred int size, int timeout) 637184610Salfred{ 638185087Salfred return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, 639185087Salfred bytes, size, timeout, 0)); 640184610Salfred} 641184610Salfred 642184610Salfredint 643184610Salfredusb_interrupt_write(usb_dev_handle * dev, int ep, char *bytes, 644184610Salfred int size, int timeout) 645184610Salfred{ 646185087Salfred return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, 647185087Salfred bytes, size, timeout, 1)); 648184610Salfred} 649184610Salfred 650184610Salfredint 651184610Salfredusb_interrupt_read(usb_dev_handle * dev, int ep, char *bytes, 652184610Salfred int size, int timeout) 653184610Salfred{ 654185087Salfred return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, 655185087Salfred bytes, size, timeout, 1)); 656184610Salfred} 657184610Salfred 658184610Salfredint 659184610Salfredusb_control_msg(usb_dev_handle * dev, int requesttype, int request, 660185087Salfred int value, int wIndex, char *bytes, int size, int timeout) 661184610Salfred{ 662184610Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 663184610Salfred int err; 664184610Salfred uint16_t actlen; 665184610Salfred 666184610Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 667184610Salfred 668184610Salfred req.bmRequestType = requesttype; 669184610Salfred req.bRequest = request; 670184610Salfred req.wValue = value; 671185087Salfred req.wIndex = wIndex; 672184610Salfred req.wLength = size; 673184610Salfred 674184610Salfred err = libusb20_dev_request_sync((void *)dev, &req, bytes, 675184610Salfred &actlen, timeout, 0); 676184610Salfred 677184610Salfred if (err) 678184610Salfred return (-1); 679184610Salfred 680184610Salfred return (actlen); 681184610Salfred} 682184610Salfred 683184610Salfredint 684185087Salfredusb_set_configuration(usb_dev_handle * udev, int bConfigurationValue) 685184610Salfred{ 686185087Salfred struct usb_device *dev; 687184610Salfred int err; 688185087Salfred uint8_t i; 689184610Salfred 690185087Salfred /* 691185087Salfred * Need to translate from "bConfigurationValue" to 692185087Salfred * configuration index: 693185087Salfred */ 694184610Salfred 695185087Salfred if (bConfigurationValue == 0) { 696185087Salfred /* unconfigure */ 697185087Salfred i = 255; 698185087Salfred } else { 699185087Salfred /* lookup configuration index */ 700185087Salfred dev = usb_device(udev); 701185087Salfred 702185087Salfred /* check if the configuration array is not there */ 703185087Salfred if (dev->config == NULL) { 704185087Salfred return (-1); 705185087Salfred } 706185087Salfred for (i = 0;; i++) { 707185087Salfred if (i == dev->descriptor.bNumConfigurations) { 708185087Salfred /* "bConfigurationValue" not found */ 709185087Salfred return (-1); 710185087Salfred } 711185290Salfred if ((dev->config + i)->bConfigurationValue == 712185290Salfred bConfigurationValue) { 713185087Salfred break; 714185087Salfred } 715185087Salfred } 716185087Salfred } 717185087Salfred 718185087Salfred err = libusb20_dev_set_config_index((void *)udev, i); 719185087Salfred 720184610Salfred if (err) 721184610Salfred return (-1); 722184610Salfred 723184610Salfred return (0); 724184610Salfred} 725184610Salfred 726184610Salfredint 727184610Salfredusb_claim_interface(usb_dev_handle * dev, int interface) 728184610Salfred{ 729194069Sthompsa struct libusb20_device *pdev = (void *)dev; 730184610Salfred 731194069Sthompsa pdev->claimed_interface = interface; 732184610Salfred 733184610Salfred return (0); 734184610Salfred} 735184610Salfred 736184610Salfredint 737184610Salfredusb_release_interface(usb_dev_handle * dev, int interface) 738184610Salfred{ 739194069Sthompsa /* do nothing */ 740184610Salfred return (0); 741184610Salfred} 742184610Salfred 743184610Salfredint 744184610Salfredusb_set_altinterface(usb_dev_handle * dev, int alternate) 745184610Salfred{ 746194069Sthompsa struct libusb20_device *pdev = (void *)dev; 747184610Salfred int err; 748184610Salfred uint8_t iface; 749184610Salfred 750194069Sthompsa iface = pdev->claimed_interface; 751184610Salfred 752184610Salfred err = libusb20_dev_set_alt_index((void *)dev, iface, alternate); 753184610Salfred 754184610Salfred if (err) 755184610Salfred return (-1); 756184610Salfred 757184610Salfred return (0); 758184610Salfred} 759184610Salfred 760184610Salfredint 761184610Salfredusb_resetep(usb_dev_handle * dev, unsigned int ep) 762184610Salfred{ 763184610Salfred /* emulate an endpoint reset through clear-STALL */ 764184610Salfred return (usb_clear_halt(dev, ep)); 765184610Salfred} 766184610Salfred 767184610Salfredint 768184610Salfredusb_clear_halt(usb_dev_handle * dev, unsigned int ep) 769184610Salfred{ 770184610Salfred struct libusb20_transfer *xfer; 771184610Salfred 772184610Salfred xfer = usb_get_transfer_by_ep_no(dev, ep); 773184610Salfred if (xfer == NULL) 774184610Salfred return (-1); 775184610Salfred 776184610Salfred libusb20_tr_clear_stall_sync(xfer); 777184610Salfred 778184610Salfred return (0); 779184610Salfred} 780184610Salfred 781184610Salfredint 782184610Salfredusb_reset(usb_dev_handle * dev) 783184610Salfred{ 784184610Salfred int err; 785184610Salfred 786184610Salfred err = libusb20_dev_reset((void *)dev); 787184610Salfred 788184610Salfred if (err) 789184610Salfred return (-1); 790184610Salfred 791189621Sthompsa /* 792189621Sthompsa * Be compatible with LibUSB from sourceforge and close the 793189621Sthompsa * handle after reset! 794189621Sthompsa */ 795189621Sthompsa return (usb_close(dev)); 796184610Salfred} 797184610Salfred 798185087Salfredconst char * 799184610Salfredusb_strerror(void) 800184610Salfred{ 801184610Salfred /* TODO */ 802184610Salfred return ("Unknown error"); 803184610Salfred} 804184610Salfred 805184610Salfredvoid 806184610Salfredusb_init(void) 807184610Salfred{ 808184610Salfred /* nothing to do */ 809184610Salfred return; 810184610Salfred} 811184610Salfred 812184610Salfredvoid 813184610Salfredusb_set_debug(int level) 814184610Salfred{ 815184610Salfred /* use kernel UGEN debugging if you need to see what is going on */ 816184610Salfred return; 817184610Salfred} 818184610Salfred 819184610Salfredint 820184610Salfredusb_find_busses(void) 821184610Salfred{ 822184610Salfred usb_busses = &usb_global_bus; 823184610Salfred return (0); 824184610Salfred} 825184610Salfred 826184610Salfredint 827184610Salfredusb_find_devices(void) 828184610Salfred{ 829184610Salfred struct libusb20_device *pdev; 830184610Salfred struct usb_device *udev; 831184610Salfred struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; 832203773Swkoszek int devnum; 833184610Salfred int err; 834184610Salfred 835184610Salfred /* cleanup after last device search */ 836185290Salfred /* close all opened devices, if any */ 837184610Salfred 838185290Salfred while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { 839195957Salfred udev = pdev->privLuData; 840185290Salfred libusb20_be_dequeue_device(usb_backend, pdev); 841185290Salfred libusb20_dev_free(pdev); 842185290Salfred if (udev != NULL) { 843185290Salfred LIST_DEL(usb_global_bus.devices, udev); 844185290Salfred free(udev); 845184610Salfred } 846184610Salfred } 847184610Salfred 848185290Salfred /* free old USB backend, if any */ 849185290Salfred 850185290Salfred libusb20_be_free(usb_backend); 851185290Salfred 852184610Salfred /* do a new backend device search */ 853184610Salfred usb_backend = libusb20_be_alloc_default(); 854184610Salfred if (usb_backend == NULL) { 855184610Salfred return (-1); 856184610Salfred } 857184610Salfred /* iterate all devices */ 858184610Salfred 859203773Swkoszek devnum = 1; 860184610Salfred pdev = NULL; 861184610Salfred while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) { 862184610Salfred udev = malloc(sizeof(*udev)); 863184610Salfred if (udev == NULL) 864184610Salfred break; 865184610Salfred 866184610Salfred memset(udev, 0, sizeof(*udev)); 867184610Salfred 868184610Salfred udev->bus = &usb_global_bus; 869184610Salfred 870184610Salfred snprintf(udev->filename, sizeof(udev->filename), 871184610Salfred "/dev/ugen%u.%u", 872184610Salfred libusb20_dev_get_bus_number(pdev), 873184610Salfred libusb20_dev_get_address(pdev)); 874184610Salfred 875184610Salfred ddesc = libusb20_dev_get_device_desc(pdev); 876184610Salfred 877184610Salfred udev->descriptor.bLength = sizeof(udev->descriptor); 878184610Salfred udev->descriptor.bDescriptorType = ddesc->bDescriptorType; 879184610Salfred udev->descriptor.bcdUSB = ddesc->bcdUSB; 880184610Salfred udev->descriptor.bDeviceClass = ddesc->bDeviceClass; 881184610Salfred udev->descriptor.bDeviceSubClass = ddesc->bDeviceSubClass; 882184610Salfred udev->descriptor.bDeviceProtocol = ddesc->bDeviceProtocol; 883184610Salfred udev->descriptor.bMaxPacketSize0 = ddesc->bMaxPacketSize0; 884184610Salfred udev->descriptor.idVendor = ddesc->idVendor; 885184610Salfred udev->descriptor.idProduct = ddesc->idProduct; 886184610Salfred udev->descriptor.bcdDevice = ddesc->bcdDevice; 887184610Salfred udev->descriptor.iManufacturer = ddesc->iManufacturer; 888184610Salfred udev->descriptor.iProduct = ddesc->iProduct; 889184610Salfred udev->descriptor.iSerialNumber = ddesc->iSerialNumber; 890184610Salfred udev->descriptor.bNumConfigurations = 891184610Salfred ddesc->bNumConfigurations; 892184610Salfred if (udev->descriptor.bNumConfigurations > USB_MAXCONFIG) { 893184610Salfred /* truncate number of configurations */ 894184610Salfred udev->descriptor.bNumConfigurations = USB_MAXCONFIG; 895184610Salfred } 896203773Swkoszek udev->devnum = devnum++; 897184610Salfred /* link together the two structures */ 898184610Salfred udev->dev = pdev; 899195957Salfred pdev->privLuData = udev; 900184610Salfred 901184610Salfred err = libusb20_dev_open(pdev, 0); 902184610Salfred if (err == 0) { 903184610Salfred /* XXX get all config descriptors by default */ 904184610Salfred usb_fetch_and_parse_descriptors((void *)pdev); 905184610Salfred libusb20_dev_close(pdev); 906184610Salfred } 907184610Salfred LIST_ADD(usb_global_bus.devices, udev); 908184610Salfred } 909184610Salfred 910184610Salfred return (0); /* success */ 911184610Salfred} 912184610Salfred 913184610Salfredstruct usb_device * 914184610Salfredusb_device(usb_dev_handle * dev) 915184610Salfred{ 916184610Salfred struct libusb20_device *pdev; 917184610Salfred 918184610Salfred pdev = (void *)dev; 919184610Salfred 920195957Salfred return (pdev->privLuData); 921184610Salfred} 922184610Salfred 923184610Salfredstruct usb_bus * 924184610Salfredusb_get_busses(void) 925184610Salfred{ 926184610Salfred return (usb_busses); 927184610Salfred} 928