libusb20.c revision 188622
1184610Salfred/* $FreeBSD: head/lib/libusb20/libusb20.c 188622 2009-02-14 23:20:00Z 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#include <stdio.h> 28184610Salfred#include <stdlib.h> 29184610Salfred#include <string.h> 30184610Salfred#include <poll.h> 31184610Salfred#include <ctype.h> 32184610Salfred#include <sys/queue.h> 33184610Salfred 34184610Salfred#include "libusb20.h" 35184610Salfred#include "libusb20_desc.h" 36184610Salfred#include "libusb20_int.h" 37184610Salfred 38184610Salfredstatic int 39184610Salfreddummy_int(void) 40184610Salfred{ 41184610Salfred return (LIBUSB20_ERROR_NOT_SUPPORTED); 42184610Salfred} 43184610Salfred 44184610Salfredstatic void 45184610Salfreddummy_void(void) 46184610Salfred{ 47184610Salfred return; 48184610Salfred} 49184610Salfred 50184610Salfredstatic void 51184610Salfreddummy_callback(struct libusb20_transfer *xfer) 52184610Salfred{ 53184610Salfred ; /* style fix */ 54184610Salfred switch (libusb20_tr_get_status(xfer)) { 55184610Salfred case LIBUSB20_TRANSFER_START: 56184610Salfred libusb20_tr_submit(xfer); 57184610Salfred break; 58184610Salfred default: 59184610Salfred /* complete or error */ 60184610Salfred break; 61184610Salfred } 62184610Salfred return; 63184610Salfred} 64184610Salfred 65184610Salfred#define dummy_get_config_desc_full (void *)dummy_int 66184610Salfred#define dummy_get_config_index (void *)dummy_int 67184610Salfred#define dummy_set_config_index (void *)dummy_int 68184610Salfred#define dummy_claim_interface (void *)dummy_int 69184610Salfred#define dummy_release_interface (void *)dummy_int 70184610Salfred#define dummy_set_alt_index (void *)dummy_int 71184610Salfred#define dummy_reset_device (void *)dummy_int 72184610Salfred#define dummy_set_power_mode (void *)dummy_int 73184610Salfred#define dummy_get_power_mode (void *)dummy_int 74184610Salfred#define dummy_kernel_driver_active (void *)dummy_int 75184610Salfred#define dummy_detach_kernel_driver (void *)dummy_int 76184610Salfred#define dummy_do_request_sync (void *)dummy_int 77184610Salfred#define dummy_tr_open (void *)dummy_int 78184610Salfred#define dummy_tr_close (void *)dummy_int 79184610Salfred#define dummy_tr_clear_stall_sync (void *)dummy_int 80184610Salfred#define dummy_process (void *)dummy_int 81188622Sthompsa#define dummy_dev_info (void *)dummy_int 82188622Sthompsa#define dummy_dev_get_iface_driver (void *)dummy_int 83184610Salfred 84184610Salfred#define dummy_tr_submit (void *)dummy_void 85184610Salfred#define dummy_tr_cancel_async (void *)dummy_void 86184610Salfred 87184610Salfredstatic const struct libusb20_device_methods libusb20_dummy_methods = { 88184610Salfred LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy) 89184610Salfred}; 90184610Salfred 91184610Salfredvoid 92184610Salfredlibusb20_tr_callback_wrapper(struct libusb20_transfer *xfer) 93184610Salfred{ 94184610Salfred ; /* style fix */ 95184610Salfred 96184610Salfredrepeat: 97184610Salfred 98184610Salfred if (!xfer->is_pending) { 99184610Salfred xfer->status = LIBUSB20_TRANSFER_START; 100184610Salfred } else { 101184610Salfred xfer->is_pending = 0; 102184610Salfred } 103184610Salfred 104188622Sthompsa xfer->callback(xfer); 105184610Salfred 106184610Salfred if (xfer->is_restart) { 107184610Salfred xfer->is_restart = 0; 108184610Salfred goto repeat; 109184610Salfred } 110184610Salfred if (xfer->is_draining && 111184610Salfred (!xfer->is_pending)) { 112184610Salfred xfer->is_draining = 0; 113184610Salfred xfer->status = LIBUSB20_TRANSFER_DRAINED; 114188622Sthompsa xfer->callback(xfer); 115184610Salfred } 116184610Salfred return; 117184610Salfred} 118184610Salfred 119184610Salfredint 120184610Salfredlibusb20_tr_close(struct libusb20_transfer *xfer) 121184610Salfred{ 122184610Salfred int error; 123184610Salfred 124184610Salfred if (!xfer->is_opened) { 125184610Salfred return (LIBUSB20_ERROR_OTHER); 126184610Salfred } 127188622Sthompsa error = xfer->pdev->methods->tr_close(xfer); 128184610Salfred 129184610Salfred if (xfer->pLength) { 130184610Salfred free(xfer->pLength); 131184610Salfred } 132184610Salfred if (xfer->ppBuffer) { 133184610Salfred free(xfer->ppBuffer); 134184610Salfred } 135184610Salfred /* clear some fields */ 136184610Salfred xfer->is_opened = 0; 137184610Salfred xfer->maxFrames = 0; 138184610Salfred xfer->maxTotalLength = 0; 139184610Salfred xfer->maxPacketLen = 0; 140184610Salfred return (error); 141184610Salfred} 142184610Salfred 143184610Salfredint 144184610Salfredlibusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize, 145184610Salfred uint32_t MaxFrameCount, uint8_t ep_no) 146184610Salfred{ 147184610Salfred uint32_t size; 148184610Salfred int error; 149184610Salfred 150184610Salfred if (xfer->is_opened) { 151184610Salfred return (LIBUSB20_ERROR_BUSY); 152184610Salfred } 153184610Salfred if (MaxFrameCount == 0) { 154184610Salfred return (LIBUSB20_ERROR_INVALID_PARAM); 155184610Salfred } 156184610Salfred xfer->maxFrames = MaxFrameCount; 157184610Salfred 158184610Salfred size = MaxFrameCount * sizeof(xfer->pLength[0]); 159184610Salfred xfer->pLength = malloc(size); 160184610Salfred if (xfer->pLength == NULL) { 161184610Salfred return (LIBUSB20_ERROR_NO_MEM); 162184610Salfred } 163184610Salfred memset(xfer->pLength, 0, size); 164184610Salfred 165184610Salfred size = MaxFrameCount * sizeof(xfer->ppBuffer[0]); 166184610Salfred xfer->ppBuffer = malloc(size); 167184610Salfred if (xfer->ppBuffer == NULL) { 168184610Salfred free(xfer->pLength); 169184610Salfred return (LIBUSB20_ERROR_NO_MEM); 170184610Salfred } 171184610Salfred memset(xfer->ppBuffer, 0, size); 172184610Salfred 173188622Sthompsa error = xfer->pdev->methods->tr_open(xfer, MaxBufSize, 174184610Salfred MaxFrameCount, ep_no); 175184610Salfred 176184610Salfred if (error) { 177184610Salfred free(xfer->ppBuffer); 178184610Salfred free(xfer->pLength); 179184610Salfred } else { 180184610Salfred xfer->is_opened = 1; 181184610Salfred } 182184610Salfred return (error); 183184610Salfred} 184184610Salfred 185184610Salfredstruct libusb20_transfer * 186184610Salfredlibusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t trIndex) 187184610Salfred{ 188184610Salfred if (trIndex >= pdev->nTransfer) { 189184610Salfred return (NULL); 190184610Salfred } 191184610Salfred return (pdev->pTransfer + trIndex); 192184610Salfred} 193184610Salfred 194184610Salfreduint32_t 195184610Salfredlibusb20_tr_get_actual_frames(struct libusb20_transfer *xfer) 196184610Salfred{ 197184610Salfred return (xfer->aFrames); 198184610Salfred} 199184610Salfred 200184610Salfreduint16_t 201184610Salfredlibusb20_tr_get_time_complete(struct libusb20_transfer *xfer) 202184610Salfred{ 203184610Salfred return (xfer->timeComplete); 204184610Salfred} 205184610Salfred 206184610Salfreduint32_t 207184610Salfredlibusb20_tr_get_actual_length(struct libusb20_transfer *xfer) 208184610Salfred{ 209184610Salfred uint32_t x; 210184610Salfred uint32_t actlen = 0; 211184610Salfred 212184610Salfred for (x = 0; x != xfer->aFrames; x++) { 213184610Salfred actlen += xfer->pLength[x]; 214184610Salfred } 215184610Salfred return (actlen); 216184610Salfred} 217184610Salfred 218184610Salfreduint32_t 219184610Salfredlibusb20_tr_get_max_frames(struct libusb20_transfer *xfer) 220184610Salfred{ 221184610Salfred return (xfer->maxFrames); 222184610Salfred} 223184610Salfred 224184610Salfreduint32_t 225184610Salfredlibusb20_tr_get_max_packet_length(struct libusb20_transfer *xfer) 226184610Salfred{ 227184610Salfred /* 228184610Salfred * Special Case NOTE: If the packet multiplier is non-zero for 229184610Salfred * High Speed USB, the value returned is equal to 230184610Salfred * "wMaxPacketSize * multiplier" ! 231184610Salfred */ 232184610Salfred return (xfer->maxPacketLen); 233184610Salfred} 234184610Salfred 235184610Salfreduint32_t 236184610Salfredlibusb20_tr_get_max_total_length(struct libusb20_transfer *xfer) 237184610Salfred{ 238184610Salfred return (xfer->maxTotalLength); 239184610Salfred} 240184610Salfred 241184610Salfreduint8_t 242184610Salfredlibusb20_tr_get_status(struct libusb20_transfer *xfer) 243184610Salfred{ 244184610Salfred return (xfer->status); 245184610Salfred} 246184610Salfred 247184610Salfreduint8_t 248184610Salfredlibusb20_tr_pending(struct libusb20_transfer *xfer) 249184610Salfred{ 250184610Salfred return (xfer->is_pending); 251184610Salfred} 252184610Salfred 253184610Salfredvoid * 254184610Salfredlibusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer) 255184610Salfred{ 256184610Salfred return (xfer->priv_sc0); 257184610Salfred} 258184610Salfred 259184610Salfredvoid * 260184610Salfredlibusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer) 261184610Salfred{ 262184610Salfred return (xfer->priv_sc1); 263184610Salfred} 264184610Salfred 265184610Salfredvoid 266184610Salfredlibusb20_tr_stop(struct libusb20_transfer *xfer) 267184610Salfred{ 268184610Salfred if (!xfer->is_pending) { 269184610Salfred /* transfer not pending */ 270184610Salfred return; 271184610Salfred } 272184610Salfred if (xfer->is_cancel) { 273184610Salfred /* already cancelling */ 274184610Salfred return; 275184610Salfred } 276184610Salfred xfer->is_cancel = 1; /* we are cancelling */ 277184610Salfred 278188622Sthompsa xfer->pdev->methods->tr_cancel_async(xfer); 279184610Salfred return; 280184610Salfred} 281184610Salfred 282184610Salfredvoid 283184610Salfredlibusb20_tr_drain(struct libusb20_transfer *xfer) 284184610Salfred{ 285184610Salfred /* make sure that we are cancelling */ 286184610Salfred libusb20_tr_stop(xfer); 287184610Salfred 288184610Salfred if (xfer->is_pending) { 289184610Salfred xfer->is_draining = 1; 290184610Salfred } 291184610Salfred return; 292184610Salfred} 293184610Salfred 294184610Salfredvoid 295184610Salfredlibusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer) 296184610Salfred{ 297188622Sthompsa xfer->pdev->methods->tr_clear_stall_sync(xfer); 298184610Salfred return; 299184610Salfred} 300184610Salfred 301184610Salfredvoid 302184610Salfredlibusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex) 303184610Salfred{ 304184610Salfred xfer->ppBuffer[frIndex] = buffer; 305184610Salfred return; 306184610Salfred} 307184610Salfred 308184610Salfredvoid 309184610Salfredlibusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb) 310184610Salfred{ 311184610Salfred xfer->callback = cb; 312184610Salfred return; 313184610Salfred} 314184610Salfred 315184610Salfredvoid 316184610Salfredlibusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags) 317184610Salfred{ 318184610Salfred xfer->flags = flags; 319184610Salfred return; 320184610Salfred} 321184610Salfred 322184610Salfredvoid 323184610Salfredlibusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex) 324184610Salfred{ 325184610Salfred xfer->pLength[frIndex] = length; 326184610Salfred return; 327184610Salfred} 328184610Salfred 329184610Salfredvoid 330184610Salfredlibusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0) 331184610Salfred{ 332184610Salfred xfer->priv_sc0 = sc0; 333184610Salfred return; 334184610Salfred} 335184610Salfred 336184610Salfredvoid 337184610Salfredlibusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1) 338184610Salfred{ 339184610Salfred xfer->priv_sc1 = sc1; 340184610Salfred return; 341184610Salfred} 342184610Salfred 343184610Salfredvoid 344184610Salfredlibusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout) 345184610Salfred{ 346184610Salfred xfer->timeout = timeout; 347184610Salfred return; 348184610Salfred} 349184610Salfred 350184610Salfredvoid 351184610Salfredlibusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames) 352184610Salfred{ 353184610Salfred if (nFrames > xfer->maxFrames) { 354184610Salfred /* should not happen */ 355184610Salfred nFrames = xfer->maxFrames; 356184610Salfred } 357184610Salfred xfer->nFrames = nFrames; 358184610Salfred return; 359184610Salfred} 360184610Salfred 361184610Salfredvoid 362184610Salfredlibusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 363184610Salfred{ 364184610Salfred xfer->ppBuffer[0] = pBuf; 365184610Salfred xfer->pLength[0] = length; 366184610Salfred xfer->timeout = timeout; 367184610Salfred xfer->nFrames = 1; 368184610Salfred return; 369184610Salfred} 370184610Salfred 371184610Salfredvoid 372184610Salfredlibusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout) 373184610Salfred{ 374184610Salfred uint16_t len; 375184610Salfred 376184610Salfred xfer->ppBuffer[0] = psetup; 377184610Salfred xfer->pLength[0] = 8; /* fixed */ 378184610Salfred xfer->timeout = timeout; 379184610Salfred 380184610Salfred len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8); 381184610Salfred 382184610Salfred if (len != 0) { 383184610Salfred xfer->nFrames = 2; 384184610Salfred xfer->ppBuffer[1] = pBuf; 385184610Salfred xfer->pLength[1] = len; 386184610Salfred } else { 387184610Salfred xfer->nFrames = 1; 388184610Salfred } 389184610Salfred return; 390184610Salfred} 391184610Salfred 392184610Salfredvoid 393184610Salfredlibusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout) 394184610Salfred{ 395184610Salfred xfer->ppBuffer[0] = pBuf; 396184610Salfred xfer->pLength[0] = length; 397184610Salfred xfer->timeout = timeout; 398184610Salfred xfer->nFrames = 1; 399184610Salfred return; 400184610Salfred} 401184610Salfred 402184610Salfredvoid 403184610Salfredlibusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex) 404184610Salfred{ 405184610Salfred if (frIndex >= xfer->maxFrames) { 406184610Salfred /* should not happen */ 407184610Salfred return; 408184610Salfred } 409184610Salfred xfer->ppBuffer[frIndex] = pBuf; 410184610Salfred xfer->pLength[frIndex] = length; 411184610Salfred return; 412184610Salfred} 413184610Salfred 414184610Salfredvoid 415184610Salfredlibusb20_tr_submit(struct libusb20_transfer *xfer) 416184610Salfred{ 417184610Salfred if (xfer->is_pending) { 418184610Salfred /* should not happen */ 419184610Salfred return; 420184610Salfred } 421184610Salfred xfer->is_pending = 1; /* we are pending */ 422184610Salfred xfer->is_cancel = 0; /* not cancelling */ 423184610Salfred xfer->is_restart = 0; /* not restarting */ 424184610Salfred 425188622Sthompsa xfer->pdev->methods->tr_submit(xfer); 426184610Salfred return; 427184610Salfred} 428184610Salfred 429184610Salfredvoid 430184610Salfredlibusb20_tr_start(struct libusb20_transfer *xfer) 431184610Salfred{ 432184610Salfred if (xfer->is_pending) { 433184610Salfred if (xfer->is_cancel) { 434184610Salfred /* cancelling - restart */ 435184610Salfred xfer->is_restart = 1; 436184610Salfred } 437184610Salfred /* transfer not pending */ 438184610Salfred return; 439184610Salfred } 440184610Salfred /* get into the callback */ 441184610Salfred libusb20_tr_callback_wrapper(xfer); 442184610Salfred return; 443184610Salfred} 444184610Salfred 445184610Salfred/* USB device operations */ 446184610Salfred 447184610Salfredint 448184610Salfredlibusb20_dev_claim_interface(struct libusb20_device *pdev, uint8_t ifaceIndex) 449184610Salfred{ 450184610Salfred int error; 451184610Salfred 452184610Salfred if (ifaceIndex >= 32) { 453184610Salfred error = LIBUSB20_ERROR_INVALID_PARAM; 454184610Salfred } else if (pdev->claimed_interfaces & (1 << ifaceIndex)) { 455184610Salfred error = LIBUSB20_ERROR_NOT_FOUND; 456184610Salfred } else { 457188622Sthompsa error = pdev->methods->claim_interface(pdev, ifaceIndex); 458184610Salfred } 459184610Salfred if (!error) { 460184610Salfred pdev->claimed_interfaces |= (1 << ifaceIndex); 461184610Salfred } 462184610Salfred return (error); 463184610Salfred} 464184610Salfred 465184610Salfredint 466184610Salfredlibusb20_dev_close(struct libusb20_device *pdev) 467184610Salfred{ 468184610Salfred struct libusb20_transfer *xfer; 469184610Salfred uint16_t x; 470184610Salfred int error = 0; 471184610Salfred 472184610Salfred if (!pdev->is_opened) { 473184610Salfred return (LIBUSB20_ERROR_OTHER); 474184610Salfred } 475184610Salfred for (x = 0; x != pdev->nTransfer; x++) { 476184610Salfred xfer = pdev->pTransfer + x; 477184610Salfred 478184610Salfred libusb20_tr_drain(xfer); 479184610Salfred } 480184610Salfred 481184610Salfred if (pdev->pTransfer != NULL) { 482184610Salfred free(pdev->pTransfer); 483184610Salfred pdev->pTransfer = NULL; 484184610Salfred } 485188622Sthompsa error = pdev->beMethods->close_device(pdev); 486184610Salfred 487184610Salfred pdev->methods = &libusb20_dummy_methods; 488184610Salfred 489184610Salfred pdev->is_opened = 0; 490184610Salfred 491187184Sthompsa pdev->claimed_interfaces = 0; 492187184Sthompsa 493184610Salfred return (error); 494184610Salfred} 495184610Salfred 496184610Salfredint 497184610Salfredlibusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex) 498184610Salfred{ 499184610Salfred int error; 500184610Salfred 501188622Sthompsa error = pdev->methods->detach_kernel_driver(pdev, ifaceIndex); 502184610Salfred return (error); 503184610Salfred} 504184610Salfred 505184610Salfredstruct LIBUSB20_DEVICE_DESC_DECODED * 506184610Salfredlibusb20_dev_get_device_desc(struct libusb20_device *pdev) 507184610Salfred{ 508184610Salfred return (&(pdev->ddesc)); 509184610Salfred} 510184610Salfred 511184610Salfredint 512184610Salfredlibusb20_dev_get_fd(struct libusb20_device *pdev) 513184610Salfred{ 514184610Salfred return (pdev->file); 515184610Salfred} 516184610Salfred 517184610Salfredint 518184610Salfredlibusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex) 519184610Salfred{ 520184610Salfred int error; 521184610Salfred 522188622Sthompsa error = pdev->methods->kernel_driver_active(pdev, ifaceIndex); 523184610Salfred return (error); 524184610Salfred} 525184610Salfred 526184610Salfredint 527184610Salfredlibusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax) 528184610Salfred{ 529184610Salfred struct libusb20_transfer *xfer; 530184610Salfred uint32_t size; 531184610Salfred uint16_t x; 532184610Salfred int error; 533184610Salfred 534184610Salfred if (pdev->is_opened) { 535184610Salfred return (LIBUSB20_ERROR_BUSY); 536184610Salfred } 537184610Salfred if (nTransferMax >= 256) { 538184610Salfred return (LIBUSB20_ERROR_INVALID_PARAM); 539184610Salfred } else if (nTransferMax != 0) { 540184610Salfred size = sizeof(pdev->pTransfer[0]) * nTransferMax; 541184610Salfred pdev->pTransfer = malloc(size); 542184610Salfred if (pdev->pTransfer == NULL) { 543184610Salfred return (LIBUSB20_ERROR_NO_MEM); 544184610Salfred } 545184610Salfred memset(pdev->pTransfer, 0, size); 546184610Salfred } 547184610Salfred /* initialise all transfers */ 548184610Salfred for (x = 0; x != nTransferMax; x++) { 549184610Salfred 550184610Salfred xfer = pdev->pTransfer + x; 551184610Salfred 552184610Salfred xfer->pdev = pdev; 553184610Salfred xfer->trIndex = x; 554184610Salfred xfer->callback = &dummy_callback; 555184610Salfred } 556184610Salfred 557185087Salfred /* set "nTransfer" early */ 558185087Salfred pdev->nTransfer = nTransferMax; 559185087Salfred 560188622Sthompsa error = pdev->beMethods->open_device(pdev, nTransferMax); 561184610Salfred 562184610Salfred if (error) { 563184610Salfred if (pdev->pTransfer != NULL) { 564184610Salfred free(pdev->pTransfer); 565184610Salfred pdev->pTransfer = NULL; 566184610Salfred } 567184610Salfred pdev->file = -1; 568184610Salfred pdev->file_ctrl = -1; 569184610Salfred pdev->nTransfer = 0; 570184610Salfred } else { 571184610Salfred pdev->is_opened = 1; 572184610Salfred } 573184610Salfred return (error); 574184610Salfred} 575184610Salfred 576184610Salfredint 577184610Salfredlibusb20_dev_release_interface(struct libusb20_device *pdev, uint8_t ifaceIndex) 578184610Salfred{ 579184610Salfred int error; 580184610Salfred 581184610Salfred if (ifaceIndex >= 32) { 582184610Salfred error = LIBUSB20_ERROR_INVALID_PARAM; 583184610Salfred } else if (!(pdev->claimed_interfaces & (1 << ifaceIndex))) { 584184610Salfred error = LIBUSB20_ERROR_NOT_FOUND; 585184610Salfred } else { 586188622Sthompsa error = pdev->methods->release_interface(pdev, ifaceIndex); 587184610Salfred } 588184610Salfred if (!error) { 589184610Salfred pdev->claimed_interfaces &= ~(1 << ifaceIndex); 590184610Salfred } 591184610Salfred return (error); 592184610Salfred} 593184610Salfred 594184610Salfredint 595184610Salfredlibusb20_dev_reset(struct libusb20_device *pdev) 596184610Salfred{ 597184610Salfred int error; 598184610Salfred 599188622Sthompsa error = pdev->methods->reset_device(pdev); 600184610Salfred return (error); 601184610Salfred} 602184610Salfred 603184610Salfredint 604184610Salfredlibusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode) 605184610Salfred{ 606184610Salfred int error; 607184610Salfred 608188622Sthompsa error = pdev->methods->set_power_mode(pdev, power_mode); 609184610Salfred return (error); 610184610Salfred} 611184610Salfred 612184610Salfreduint8_t 613184610Salfredlibusb20_dev_get_power_mode(struct libusb20_device *pdev) 614184610Salfred{ 615184610Salfred int error; 616184610Salfred uint8_t power_mode; 617184610Salfred 618188622Sthompsa error = pdev->methods->get_power_mode(pdev, &power_mode); 619184610Salfred if (error) 620184610Salfred power_mode = LIBUSB20_POWER_ON; /* fake power mode */ 621184610Salfred return (power_mode); 622184610Salfred} 623184610Salfred 624184610Salfredint 625184610Salfredlibusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex) 626184610Salfred{ 627184610Salfred int error; 628184610Salfred 629188622Sthompsa error = pdev->methods->set_alt_index(pdev, ifaceIndex, altIndex); 630184610Salfred return (error); 631184610Salfred} 632184610Salfred 633184610Salfredint 634184610Salfredlibusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex) 635184610Salfred{ 636184610Salfred int error; 637184610Salfred 638188622Sthompsa error = pdev->methods->set_config_index(pdev, configIndex); 639184610Salfred return (error); 640184610Salfred} 641184610Salfred 642184610Salfredint 643184610Salfredlibusb20_dev_request_sync(struct libusb20_device *pdev, 644184610Salfred struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data, 645184610Salfred uint16_t *pactlen, uint32_t timeout, uint8_t flags) 646184610Salfred{ 647184610Salfred int error; 648184610Salfred 649188622Sthompsa error = pdev->methods->do_request_sync(pdev, 650184610Salfred setup, data, pactlen, timeout, flags); 651184610Salfred return (error); 652184610Salfred} 653184610Salfred 654184610Salfredint 655184610Salfredlibusb20_dev_req_string_sync(struct libusb20_device *pdev, 656185087Salfred uint8_t str_index, uint16_t langid, void *ptr, uint16_t len) 657184610Salfred{ 658184610Salfred struct LIBUSB20_CONTROL_SETUP_DECODED req; 659184610Salfred int error; 660184610Salfred 661184610Salfred if (len < 4) { 662184610Salfred /* invalid length */ 663184610Salfred return (LIBUSB20_ERROR_INVALID_PARAM); 664184610Salfred } 665184610Salfred LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); 666184610Salfred 667184610Salfred /* 668184610Salfred * We need to read the USB string in two steps else some USB 669184610Salfred * devices will complain. 670184610Salfred */ 671184610Salfred req.bmRequestType = 672184610Salfred LIBUSB20_REQUEST_TYPE_STANDARD | 673184610Salfred LIBUSB20_RECIPIENT_DEVICE | 674184610Salfred LIBUSB20_ENDPOINT_IN; 675184610Salfred req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR; 676185087Salfred req.wValue = (LIBUSB20_DT_STRING << 8) | str_index; 677184610Salfred req.wIndex = langid; 678184610Salfred req.wLength = 4; /* bytes */ 679184610Salfred 680184610Salfred error = libusb20_dev_request_sync(pdev, &req, 681184610Salfred ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 682184610Salfred if (error) { 683184610Salfred return (error); 684184610Salfred } 685184610Salfred req.wLength = *(uint8_t *)ptr; /* bytes */ 686184610Salfred if (req.wLength > len) { 687184610Salfred /* partial string read */ 688184610Salfred req.wLength = len; 689184610Salfred } 690184610Salfred error = libusb20_dev_request_sync(pdev, &req, 691184610Salfred ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); 692184610Salfred 693184610Salfred if (error) { 694184610Salfred return (error); 695184610Salfred } 696184610Salfred if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING) { 697184610Salfred return (LIBUSB20_ERROR_OTHER); 698184610Salfred } 699184610Salfred return (0); /* success */ 700184610Salfred} 701184610Salfred 702184610Salfredint 703184610Salfredlibusb20_dev_req_string_simple_sync(struct libusb20_device *pdev, 704185087Salfred uint8_t str_index, void *ptr, uint16_t len) 705184610Salfred{ 706184610Salfred char *buf; 707184610Salfred int error; 708184610Salfred uint16_t langid; 709184610Salfred uint16_t n; 710184610Salfred uint16_t i; 711184610Salfred uint16_t c; 712184610Salfred uint8_t temp[255]; 713184610Salfred uint8_t swap; 714184610Salfred 715184610Salfred /* the following code derives from the FreeBSD USB kernel */ 716184610Salfred 717184610Salfred if ((len < 1) || (ptr == NULL)) { 718184610Salfred /* too short buffer */ 719184610Salfred return (LIBUSB20_ERROR_INVALID_PARAM); 720184610Salfred } 721184610Salfred error = libusb20_dev_req_string_sync(pdev, 722184610Salfred 0, 0, temp, sizeof(temp)); 723185087Salfred if (error < 0) { 724185087Salfred *(uint8_t *)ptr = 0; /* zero terminate */ 725184610Salfred return (error); 726185087Salfred } 727184610Salfred langid = temp[2] | (temp[3] << 8); 728184610Salfred 729185087Salfred error = libusb20_dev_req_string_sync(pdev, str_index, 730184610Salfred langid, temp, sizeof(temp)); 731185087Salfred if (error < 0) { 732185087Salfred *(uint8_t *)ptr = 0; /* zero terminate */ 733184610Salfred return (error); 734185087Salfred } 735184610Salfred if (temp[0] < 2) { 736184610Salfred /* string length is too short */ 737185087Salfred *(uint8_t *)ptr = 0; /* zero terminate */ 738184610Salfred return (LIBUSB20_ERROR_OTHER); 739184610Salfred } 740184610Salfred /* reserve one byte for terminating zero */ 741184610Salfred len--; 742184610Salfred 743184610Salfred /* find maximum length */ 744184610Salfred n = (temp[0] / 2) - 1; 745184610Salfred if (n > len) { 746184610Salfred n = len; 747184610Salfred } 748184610Salfred /* reset swap state */ 749184610Salfred swap = 3; 750184610Salfred 751184610Salfred /* setup output buffer pointer */ 752184610Salfred buf = ptr; 753184610Salfred 754184610Salfred /* convert and filter */ 755184610Salfred for (i = 0; (i != n); i++) { 756184610Salfred c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8); 757184610Salfred 758184610Salfred /* convert from Unicode, handle buggy strings */ 759184610Salfred if (((c & 0xff00) == 0) && (swap & 1)) { 760184610Salfred /* Little Endian, default */ 761184610Salfred *buf = c; 762184610Salfred swap = 1; 763184610Salfred } else if (((c & 0x00ff) == 0) && (swap & 2)) { 764184610Salfred /* Big Endian */ 765184610Salfred *buf = c >> 8; 766184610Salfred swap = 2; 767184610Salfred } else { 768185087Salfred /* skip invalid character */ 769185087Salfred continue; 770184610Salfred } 771184610Salfred /* 772184610Salfred * Filter by default - we don't allow greater and less than 773184610Salfred * signs because they might confuse the dmesg printouts! 774184610Salfred */ 775184610Salfred if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) { 776185087Salfred /* skip invalid character */ 777185087Salfred continue; 778184610Salfred } 779184610Salfred buf++; 780184610Salfred } 781184610Salfred *buf = 0; /* zero terminate string */ 782184610Salfred 783184610Salfred return (0); 784184610Salfred} 785184610Salfred 786184610Salfredstruct libusb20_config * 787184610Salfredlibusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex) 788184610Salfred{ 789184610Salfred struct libusb20_config *retval = NULL; 790184610Salfred uint8_t *ptr; 791184610Salfred uint16_t len; 792184610Salfred uint8_t do_close; 793184610Salfred int error; 794184610Salfred 795184610Salfred if (!pdev->is_opened) { 796184610Salfred error = libusb20_dev_open(pdev, 0); 797184610Salfred if (error) { 798184610Salfred return (NULL); 799184610Salfred } 800184610Salfred do_close = 1; 801184610Salfred } else { 802184610Salfred do_close = 0; 803184610Salfred } 804188622Sthompsa error = pdev->methods->get_config_desc_full(pdev, 805184610Salfred &ptr, &len, configIndex); 806184610Salfred 807184610Salfred if (error) { 808184610Salfred goto done; 809184610Salfred } 810184610Salfred /* parse new config descriptor */ 811184610Salfred retval = libusb20_parse_config_desc(ptr); 812184610Salfred 813184610Salfred /* free config descriptor */ 814184610Salfred free(ptr); 815184610Salfred 816184610Salfreddone: 817184610Salfred if (do_close) { 818184610Salfred error = libusb20_dev_close(pdev); 819184610Salfred } 820184610Salfred return (retval); 821184610Salfred} 822184610Salfred 823184610Salfredstruct libusb20_device * 824184610Salfredlibusb20_dev_alloc(void) 825184610Salfred{ 826184610Salfred struct libusb20_device *pdev; 827184610Salfred 828184610Salfred pdev = malloc(sizeof(*pdev)); 829184610Salfred if (pdev == NULL) { 830184610Salfred return (NULL); 831184610Salfred } 832184610Salfred memset(pdev, 0, sizeof(*pdev)); 833184610Salfred 834184610Salfred pdev->file = -1; 835184610Salfred pdev->file_ctrl = -1; 836184610Salfred pdev->methods = &libusb20_dummy_methods; 837184610Salfred return (pdev); 838184610Salfred} 839184610Salfred 840184610Salfreduint8_t 841184610Salfredlibusb20_dev_get_config_index(struct libusb20_device *pdev) 842184610Salfred{ 843184610Salfred int error; 844185087Salfred uint8_t cfg_index; 845184610Salfred uint8_t do_close; 846184610Salfred 847184610Salfred if (!pdev->is_opened) { 848184610Salfred error = libusb20_dev_open(pdev, 0); 849184610Salfred if (error == 0) { 850184610Salfred do_close = 1; 851184610Salfred } else { 852184610Salfred do_close = 0; 853184610Salfred } 854184610Salfred } else { 855184610Salfred do_close = 0; 856184610Salfred } 857184610Salfred 858188622Sthompsa error = pdev->methods->get_config_index(pdev, &cfg_index); 859184610Salfred if (error) { 860185087Salfred cfg_index = 0 - 1; /* current config index */ 861184610Salfred } 862184610Salfred if (do_close) { 863184610Salfred if (libusb20_dev_close(pdev)) { 864184610Salfred /* ignore */ 865184610Salfred } 866184610Salfred } 867185087Salfred return (cfg_index); 868184610Salfred} 869184610Salfred 870184610Salfreduint8_t 871184610Salfredlibusb20_dev_get_mode(struct libusb20_device *pdev) 872184610Salfred{ 873184610Salfred return (pdev->usb_mode); 874184610Salfred} 875184610Salfred 876184610Salfreduint8_t 877184610Salfredlibusb20_dev_get_speed(struct libusb20_device *pdev) 878184610Salfred{ 879184610Salfred return (pdev->usb_speed); 880184610Salfred} 881184610Salfred 882184610Salfred/* if this function returns an error, the device is gone */ 883184610Salfredint 884184610Salfredlibusb20_dev_process(struct libusb20_device *pdev) 885184610Salfred{ 886184610Salfred int error; 887184610Salfred 888188622Sthompsa error = pdev->methods->process(pdev); 889184610Salfred return (error); 890184610Salfred} 891184610Salfred 892184610Salfredvoid 893184610Salfredlibusb20_dev_wait_process(struct libusb20_device *pdev, int timeout) 894184610Salfred{ 895185087Salfred struct pollfd pfd[1]; 896184610Salfred 897184610Salfred if (!pdev->is_opened) { 898184610Salfred return; 899184610Salfred } 900184610Salfred pfd[0].fd = pdev->file; 901184610Salfred pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 902184610Salfred pfd[0].revents = 0; 903184610Salfred 904185087Salfred if (poll(pfd, 1, timeout)) { 905184610Salfred /* ignore any error */ 906184610Salfred } 907184610Salfred return; 908184610Salfred} 909184610Salfred 910184610Salfredvoid 911184610Salfredlibusb20_dev_free(struct libusb20_device *pdev) 912184610Salfred{ 913184610Salfred if (pdev == NULL) { 914184610Salfred /* be NULL safe */ 915184610Salfred return; 916184610Salfred } 917184610Salfred if (pdev->is_opened) { 918184610Salfred if (libusb20_dev_close(pdev)) { 919184610Salfred /* ignore any errors */ 920184610Salfred } 921184610Salfred } 922184610Salfred free(pdev); 923184610Salfred return; 924184610Salfred} 925184610Salfred 926188622Sthompsaint 927188622Sthompsalibusb20_dev_get_info(struct libusb20_device *pdev, 928188622Sthompsa struct usb2_device_info *pinfo) 929188622Sthompsa{ 930188622Sthompsa if (pinfo == NULL) 931188622Sthompsa return (LIBUSB20_ERROR_INVALID_PARAM); 932188622Sthompsa 933188622Sthompsa return (pdev->beMethods->dev_get_info(pdev, pinfo)); 934188622Sthompsa} 935188622Sthompsa 936184610Salfredconst char * 937184610Salfredlibusb20_dev_get_backend_name(struct libusb20_device *pdev) 938184610Salfred{ 939188622Sthompsa return (pdev->beMethods->get_backend_name()); 940184610Salfred} 941184610Salfred 942184610Salfredconst char * 943184610Salfredlibusb20_dev_get_desc(struct libusb20_device *pdev) 944184610Salfred{ 945184610Salfred return (pdev->usb_desc); 946184610Salfred} 947184610Salfred 948184610Salfredvoid 949184610Salfredlibusb20_dev_set_debug(struct libusb20_device *pdev, int debug) 950184610Salfred{ 951184610Salfred pdev->debug = debug; 952184610Salfred return; 953184610Salfred} 954184610Salfred 955184610Salfredint 956184610Salfredlibusb20_dev_get_debug(struct libusb20_device *pdev) 957184610Salfred{ 958184610Salfred return (pdev->debug); 959184610Salfred} 960184610Salfred 961184610Salfreduint8_t 962184610Salfredlibusb20_dev_get_address(struct libusb20_device *pdev) 963184610Salfred{ 964184610Salfred return (pdev->device_address); 965184610Salfred} 966184610Salfred 967184610Salfreduint8_t 968184610Salfredlibusb20_dev_get_bus_number(struct libusb20_device *pdev) 969184610Salfred{ 970184610Salfred return (pdev->bus_number); 971184610Salfred} 972184610Salfred 973184610Salfredint 974184610Salfredlibusb20_dev_set_owner(struct libusb20_device *pdev, uid_t user, gid_t group) 975184610Salfred{ 976188622Sthompsa return (pdev->beMethods->dev_set_owner(pdev, user, group)); 977184610Salfred} 978184610Salfred 979184610Salfredint 980184610Salfredlibusb20_dev_set_perm(struct libusb20_device *pdev, mode_t mode) 981184610Salfred{ 982188622Sthompsa return (pdev->beMethods->dev_set_perm(pdev, mode)); 983184610Salfred} 984184610Salfred 985184610Salfredint 986188622Sthompsalibusb20_dev_set_iface_owner(struct libusb20_device *pdev, 987188622Sthompsa uint8_t iface_index, uid_t user, gid_t group) 988184610Salfred{ 989188622Sthompsa return (pdev->beMethods->dev_set_iface_owner( 990188622Sthompsa pdev, iface_index, user, group)); 991184610Salfred} 992184610Salfred 993184610Salfredint 994188622Sthompsalibusb20_dev_set_iface_perm(struct libusb20_device *pdev, 995188622Sthompsa uint8_t iface_index, mode_t mode) 996184610Salfred{ 997188622Sthompsa return (pdev->beMethods->dev_set_iface_perm( 998188622Sthompsa pdev, iface_index, mode)); 999184610Salfred} 1000184610Salfred 1001184610Salfredint 1002184610Salfredlibusb20_dev_get_owner(struct libusb20_device *pdev, uid_t *user, gid_t *group) 1003184610Salfred{ 1004184610Salfred uid_t a; 1005184610Salfred gid_t b; 1006184610Salfred 1007184610Salfred if (user == NULL) 1008184610Salfred user = &a; 1009184610Salfred if (group == NULL) 1010184610Salfred group = &b; 1011184610Salfred 1012188622Sthompsa return (pdev->beMethods->dev_get_owner(pdev, user, group)); 1013184610Salfred} 1014184610Salfred 1015184610Salfredint 1016184610Salfredlibusb20_dev_get_perm(struct libusb20_device *pdev, mode_t *mode) 1017184610Salfred{ 1018184610Salfred mode_t a; 1019184610Salfred 1020184610Salfred if (mode == NULL) 1021184610Salfred mode = &a; 1022188622Sthompsa return (pdev->beMethods->dev_get_perm(pdev, mode)); 1023184610Salfred} 1024184610Salfred 1025184610Salfredint 1026188622Sthompsalibusb20_dev_get_iface_owner(struct libusb20_device *pdev, 1027188622Sthompsa uint8_t iface_index, uid_t *user, gid_t *group) 1028184610Salfred{ 1029184610Salfred uid_t a; 1030184610Salfred gid_t b; 1031184610Salfred 1032184610Salfred if (user == NULL) 1033184610Salfred user = &a; 1034184610Salfred if (group == NULL) 1035184610Salfred group = &b; 1036184610Salfred 1037188622Sthompsa return (pdev->beMethods->dev_get_iface_owner( 1038188622Sthompsa pdev, iface_index, user, group)); 1039184610Salfred} 1040184610Salfred 1041184610Salfredint 1042188622Sthompsalibusb20_dev_get_iface_perm(struct libusb20_device *pdev, 1043188622Sthompsa uint8_t iface_index, mode_t *mode) 1044184610Salfred{ 1045184610Salfred mode_t a; 1046184610Salfred 1047184610Salfred if (mode == NULL) 1048184610Salfred mode = &a; 1049188622Sthompsa return (pdev->beMethods->dev_get_iface_perm( 1050188622Sthompsa pdev, iface_index, mode)); 1051184610Salfred} 1052184610Salfred 1053188622Sthompsaint 1054188622Sthompsalibusb20_dev_get_iface_desc(struct libusb20_device *pdev, 1055188622Sthompsa uint8_t iface_index, char *buf, uint8_t len) 1056188622Sthompsa{ 1057188622Sthompsa if ((buf == NULL) || (len == 0)) 1058188622Sthompsa return (LIBUSB20_ERROR_INVALID_PARAM); 1059188622Sthompsa 1060188622Sthompsa return (pdev->beMethods->dev_get_iface_desc( 1061188622Sthompsa pdev, iface_index, buf, len)); 1062188622Sthompsa} 1063188622Sthompsa 1064184610Salfred/* USB bus operations */ 1065184610Salfred 1066184610Salfredint 1067188622Sthompsalibusb20_bus_set_owner(struct libusb20_backend *pbe, 1068188622Sthompsa uint8_t bus, uid_t user, gid_t group) 1069184610Salfred{ 1070188622Sthompsa return (pbe->methods->bus_set_owner(pbe, bus, user, group)); 1071184610Salfred} 1072184610Salfred 1073184610Salfredint 1074184610Salfredlibusb20_bus_set_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t mode) 1075184610Salfred{ 1076188622Sthompsa return (pbe->methods->bus_set_perm(pbe, bus, mode)); 1077184610Salfred} 1078184610Salfred 1079184610Salfredint 1080188622Sthompsalibusb20_bus_get_owner(struct libusb20_backend *pbe, 1081188622Sthompsa uint8_t bus, uid_t *user, gid_t *group) 1082184610Salfred{ 1083184610Salfred uid_t a; 1084184610Salfred gid_t b; 1085184610Salfred 1086184610Salfred if (user == NULL) 1087184610Salfred user = &a; 1088184610Salfred if (group == NULL) 1089184610Salfred group = &b; 1090188622Sthompsa return (pbe->methods->bus_get_owner(pbe, bus, user, group)); 1091184610Salfred} 1092184610Salfred 1093184610Salfredint 1094184610Salfredlibusb20_bus_get_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t *mode) 1095184610Salfred{ 1096184610Salfred mode_t a; 1097184610Salfred 1098184610Salfred if (mode == NULL) 1099184610Salfred mode = &a; 1100188622Sthompsa return (pbe->methods->bus_get_perm(pbe, bus, mode)); 1101184610Salfred} 1102184610Salfred 1103184610Salfred/* USB backend operations */ 1104184610Salfred 1105184610Salfredint 1106184610Salfredlibusb20_be_get_dev_quirk(struct libusb20_backend *pbe, 1107185087Salfred uint16_t quirk_index, struct libusb20_quirk *pq) 1108184610Salfred{ 1109188622Sthompsa return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq)); 1110184610Salfred} 1111184610Salfred 1112184610Salfredint 1113184610Salfredlibusb20_be_get_quirk_name(struct libusb20_backend *pbe, 1114185087Salfred uint16_t quirk_index, struct libusb20_quirk *pq) 1115184610Salfred{ 1116188622Sthompsa return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq)); 1117184610Salfred} 1118184610Salfred 1119184610Salfredint 1120184610Salfredlibusb20_be_add_dev_quirk(struct libusb20_backend *pbe, 1121184610Salfred struct libusb20_quirk *pq) 1122184610Salfred{ 1123188622Sthompsa return (pbe->methods->root_add_dev_quirk(pbe, pq)); 1124184610Salfred} 1125184610Salfred 1126184610Salfredint 1127184610Salfredlibusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, 1128184610Salfred struct libusb20_quirk *pq) 1129184610Salfred{ 1130188622Sthompsa return (pbe->methods->root_remove_dev_quirk(pbe, pq)); 1131184610Salfred} 1132184610Salfred 1133184610Salfredint 1134184610Salfredlibusb20_be_set_owner(struct libusb20_backend *pbe, uid_t user, gid_t group) 1135184610Salfred{ 1136188622Sthompsa return (pbe->methods->root_set_owner(pbe, user, group)); 1137184610Salfred} 1138184610Salfred 1139184610Salfredint 1140184610Salfredlibusb20_be_set_perm(struct libusb20_backend *pbe, mode_t mode) 1141184610Salfred{ 1142188622Sthompsa return (pbe->methods->root_set_perm(pbe, mode)); 1143184610Salfred} 1144184610Salfred 1145184610Salfredint 1146184610Salfredlibusb20_be_get_owner(struct libusb20_backend *pbe, uid_t *user, gid_t *group) 1147184610Salfred{ 1148184610Salfred uid_t a; 1149184610Salfred gid_t b; 1150184610Salfred 1151184610Salfred if (user == NULL) 1152184610Salfred user = &a; 1153184610Salfred if (group == NULL) 1154184610Salfred group = &b; 1155188622Sthompsa return (pbe->methods->root_get_owner(pbe, user, group)); 1156184610Salfred} 1157184610Salfred 1158184610Salfredint 1159184610Salfredlibusb20_be_get_perm(struct libusb20_backend *pbe, mode_t *mode) 1160184610Salfred{ 1161184610Salfred mode_t a; 1162184610Salfred 1163184610Salfred if (mode == NULL) 1164184610Salfred mode = &a; 1165188622Sthompsa return (pbe->methods->root_get_perm(pbe, mode)); 1166184610Salfred} 1167184610Salfred 1168184610Salfredstruct libusb20_device * 1169184610Salfredlibusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1170184610Salfred{ 1171184610Salfred if (pbe == NULL) { 1172184610Salfred pdev = NULL; 1173184610Salfred } else if (pdev == NULL) { 1174184610Salfred pdev = TAILQ_FIRST(&(pbe->usb_devs)); 1175184610Salfred } else { 1176184610Salfred pdev = TAILQ_NEXT(pdev, dev_entry); 1177184610Salfred } 1178184610Salfred return (pdev); 1179184610Salfred} 1180184610Salfred 1181184610Salfredstruct libusb20_backend * 1182184610Salfredlibusb20_be_alloc(const struct libusb20_backend_methods *methods) 1183184610Salfred{ 1184184610Salfred struct libusb20_backend *pbe; 1185184610Salfred 1186184610Salfred pbe = malloc(sizeof(*pbe)); 1187184610Salfred if (pbe == NULL) { 1188184610Salfred return (NULL); 1189184610Salfred } 1190184610Salfred memset(pbe, 0, sizeof(*pbe)); 1191184610Salfred 1192184610Salfred TAILQ_INIT(&(pbe->usb_devs)); 1193184610Salfred 1194184610Salfred pbe->methods = methods; /* set backend methods */ 1195184610Salfred 1196184610Salfred /* do the initial device scan */ 1197184610Salfred if (pbe->methods->init_backend) { 1198188622Sthompsa pbe->methods->init_backend(pbe); 1199184610Salfred } 1200184610Salfred return (pbe); 1201184610Salfred} 1202184610Salfred 1203184610Salfredstruct libusb20_backend * 1204184610Salfredlibusb20_be_alloc_linux(void) 1205184610Salfred{ 1206184610Salfred struct libusb20_backend *pbe; 1207184610Salfred 1208184610Salfred#ifdef __linux__ 1209184610Salfred pbe = libusb20_be_alloc(&libusb20_linux_backend); 1210184610Salfred#else 1211184610Salfred pbe = NULL; 1212184610Salfred#endif 1213184610Salfred return (pbe); 1214184610Salfred} 1215184610Salfred 1216184610Salfredstruct libusb20_backend * 1217184610Salfredlibusb20_be_alloc_ugen20(void) 1218184610Salfred{ 1219184610Salfred struct libusb20_backend *pbe; 1220184610Salfred 1221184610Salfred#ifdef __FreeBSD__ 1222184610Salfred pbe = libusb20_be_alloc(&libusb20_ugen20_backend); 1223184610Salfred#else 1224184610Salfred pbe = NULL; 1225184610Salfred#endif 1226184610Salfred return (pbe); 1227184610Salfred} 1228184610Salfred 1229184610Salfredstruct libusb20_backend * 1230184610Salfredlibusb20_be_alloc_default(void) 1231184610Salfred{ 1232184610Salfred struct libusb20_backend *pbe; 1233184610Salfred 1234184610Salfred pbe = libusb20_be_alloc_linux(); 1235184610Salfred if (pbe) { 1236184610Salfred return (pbe); 1237184610Salfred } 1238184610Salfred pbe = libusb20_be_alloc_ugen20(); 1239184610Salfred if (pbe) { 1240184610Salfred return (pbe); 1241184610Salfred } 1242184610Salfred return (NULL); /* no backend found */ 1243184610Salfred} 1244184610Salfred 1245184610Salfredvoid 1246184610Salfredlibusb20_be_free(struct libusb20_backend *pbe) 1247184610Salfred{ 1248184610Salfred struct libusb20_device *pdev; 1249184610Salfred 1250184610Salfred if (pbe == NULL) { 1251184610Salfred /* be NULL safe */ 1252184610Salfred return; 1253184610Salfred } 1254184610Salfred while ((pdev = libusb20_be_device_foreach(pbe, NULL))) { 1255184610Salfred libusb20_be_dequeue_device(pbe, pdev); 1256184610Salfred libusb20_dev_free(pdev); 1257184610Salfred } 1258184610Salfred if (pbe->methods->exit_backend) { 1259188622Sthompsa pbe->methods->exit_backend(pbe); 1260184610Salfred } 1261184610Salfred return; 1262184610Salfred} 1263184610Salfred 1264184610Salfredvoid 1265184610Salfredlibusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev) 1266184610Salfred{ 1267184610Salfred pdev->beMethods = pbe->methods; /* copy backend methods */ 1268184610Salfred TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry); 1269184610Salfred return; 1270184610Salfred} 1271184610Salfred 1272184610Salfredvoid 1273184610Salfredlibusb20_be_dequeue_device(struct libusb20_backend *pbe, 1274184610Salfred struct libusb20_device *pdev) 1275184610Salfred{ 1276184610Salfred TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry); 1277184610Salfred return; 1278184610Salfred} 1279