1*4c87aefeSPatrick Mooney /*- 2*4c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*4c87aefeSPatrick Mooney * 4*4c87aefeSPatrick Mooney * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com> 5*4c87aefeSPatrick Mooney * Copyright 2018 Joyent, Inc. 6*4c87aefeSPatrick Mooney * All rights reserved. 7*4c87aefeSPatrick Mooney * 8*4c87aefeSPatrick Mooney * Redistribution and use in source and binary forms, with or without 9*4c87aefeSPatrick Mooney * modification, are permitted provided that the following conditions 10*4c87aefeSPatrick Mooney * are met: 11*4c87aefeSPatrick Mooney * 1. Redistributions of source code must retain the above copyright 12*4c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer. 13*4c87aefeSPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright 14*4c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer in the 15*4c87aefeSPatrick Mooney * documentation and/or other materials provided with the distribution. 16*4c87aefeSPatrick Mooney * 17*4c87aefeSPatrick Mooney * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*4c87aefeSPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*4c87aefeSPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*4c87aefeSPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*4c87aefeSPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*4c87aefeSPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*4c87aefeSPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*4c87aefeSPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*4c87aefeSPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*4c87aefeSPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*4c87aefeSPatrick Mooney * SUCH DAMAGE. 28*4c87aefeSPatrick Mooney * 29*4c87aefeSPatrick Mooney * $FreeBSD$ 30*4c87aefeSPatrick Mooney */ 31*4c87aefeSPatrick Mooney 32*4c87aefeSPatrick Mooney #ifndef _USB_EMUL_H_ 33*4c87aefeSPatrick Mooney #define _USB_EMUL_H_ 34*4c87aefeSPatrick Mooney 35*4c87aefeSPatrick Mooney #include <stdlib.h> 36*4c87aefeSPatrick Mooney #include <sys/linker_set.h> 37*4c87aefeSPatrick Mooney #include <pthread.h> 38*4c87aefeSPatrick Mooney #ifndef __FreeBSD__ 39*4c87aefeSPatrick Mooney #include <synch.h> 40*4c87aefeSPatrick Mooney #endif 41*4c87aefeSPatrick Mooney 42*4c87aefeSPatrick Mooney #define USB_MAX_XFER_BLOCKS 8 43*4c87aefeSPatrick Mooney 44*4c87aefeSPatrick Mooney #define USB_XFER_OUT 0 45*4c87aefeSPatrick Mooney #define USB_XFER_IN 1 46*4c87aefeSPatrick Mooney 47*4c87aefeSPatrick Mooney 48*4c87aefeSPatrick Mooney 49*4c87aefeSPatrick Mooney struct usb_hci; 50*4c87aefeSPatrick Mooney struct usb_device_request; 51*4c87aefeSPatrick Mooney struct usb_data_xfer; 52*4c87aefeSPatrick Mooney 53*4c87aefeSPatrick Mooney /* Device emulation handlers */ 54*4c87aefeSPatrick Mooney struct usb_devemu { 55*4c87aefeSPatrick Mooney char *ue_emu; /* name of device emulation */ 56*4c87aefeSPatrick Mooney int ue_usbver; /* usb version: 2 or 3 */ 57*4c87aefeSPatrick Mooney int ue_usbspeed; /* usb device speed */ 58*4c87aefeSPatrick Mooney 59*4c87aefeSPatrick Mooney /* instance creation */ 60*4c87aefeSPatrick Mooney void *(*ue_init)(struct usb_hci *hci, char *opt); 61*4c87aefeSPatrick Mooney 62*4c87aefeSPatrick Mooney /* handlers */ 63*4c87aefeSPatrick Mooney int (*ue_request)(void *sc, struct usb_data_xfer *xfer); 64*4c87aefeSPatrick Mooney int (*ue_data)(void *sc, struct usb_data_xfer *xfer, int dir, 65*4c87aefeSPatrick Mooney int epctx); 66*4c87aefeSPatrick Mooney int (*ue_reset)(void *sc); 67*4c87aefeSPatrick Mooney int (*ue_remove)(void *sc); 68*4c87aefeSPatrick Mooney int (*ue_stop)(void *sc); 69*4c87aefeSPatrick Mooney }; 70*4c87aefeSPatrick Mooney #define USB_EMUL_SET(x) DATA_SET(usb_emu_set, x); 71*4c87aefeSPatrick Mooney 72*4c87aefeSPatrick Mooney /* 73*4c87aefeSPatrick Mooney * USB device events to notify HCI when state changes 74*4c87aefeSPatrick Mooney */ 75*4c87aefeSPatrick Mooney enum hci_usbev { 76*4c87aefeSPatrick Mooney USBDEV_ATTACH, 77*4c87aefeSPatrick Mooney USBDEV_RESET, 78*4c87aefeSPatrick Mooney USBDEV_STOP, 79*4c87aefeSPatrick Mooney USBDEV_REMOVE, 80*4c87aefeSPatrick Mooney }; 81*4c87aefeSPatrick Mooney 82*4c87aefeSPatrick Mooney /* usb controller, ie xhci, ehci */ 83*4c87aefeSPatrick Mooney struct usb_hci { 84*4c87aefeSPatrick Mooney int (*hci_intr)(struct usb_hci *hci, int epctx); 85*4c87aefeSPatrick Mooney int (*hci_event)(struct usb_hci *hci, enum hci_usbev evid, 86*4c87aefeSPatrick Mooney void *param); 87*4c87aefeSPatrick Mooney void *hci_sc; /* private softc for hci */ 88*4c87aefeSPatrick Mooney 89*4c87aefeSPatrick Mooney /* controller managed fields */ 90*4c87aefeSPatrick Mooney int hci_address; 91*4c87aefeSPatrick Mooney int hci_port; 92*4c87aefeSPatrick Mooney }; 93*4c87aefeSPatrick Mooney 94*4c87aefeSPatrick Mooney /* 95*4c87aefeSPatrick Mooney * Each xfer block is mapped to the hci transfer block. 96*4c87aefeSPatrick Mooney * On input into the device handler, blen is set to the lenght of buf. 97*4c87aefeSPatrick Mooney * The device handler is to update blen to reflect on the residual size 98*4c87aefeSPatrick Mooney * of the buffer, i.e. len(buf) - len(consumed). 99*4c87aefeSPatrick Mooney */ 100*4c87aefeSPatrick Mooney struct usb_data_xfer_block { 101*4c87aefeSPatrick Mooney void *buf; /* IN or OUT pointer */ 102*4c87aefeSPatrick Mooney int blen; /* in:len(buf), out:len(remaining) */ 103*4c87aefeSPatrick Mooney int bdone; /* bytes transferred */ 104*4c87aefeSPatrick Mooney uint32_t processed; /* device processed this + errcode */ 105*4c87aefeSPatrick Mooney void *hci_data; /* HCI private reference */ 106*4c87aefeSPatrick Mooney int ccs; 107*4c87aefeSPatrick Mooney uint32_t streamid; 108*4c87aefeSPatrick Mooney uint64_t trbnext; /* next TRB guest address */ 109*4c87aefeSPatrick Mooney }; 110*4c87aefeSPatrick Mooney 111*4c87aefeSPatrick Mooney struct usb_data_xfer { 112*4c87aefeSPatrick Mooney struct usb_data_xfer_block data[USB_MAX_XFER_BLOCKS]; 113*4c87aefeSPatrick Mooney struct usb_device_request *ureq; /* setup ctl request */ 114*4c87aefeSPatrick Mooney int ndata; /* # of data items */ 115*4c87aefeSPatrick Mooney int head; 116*4c87aefeSPatrick Mooney int tail; 117*4c87aefeSPatrick Mooney pthread_mutex_t mtx; 118*4c87aefeSPatrick Mooney }; 119*4c87aefeSPatrick Mooney 120*4c87aefeSPatrick Mooney enum USB_ERRCODE { 121*4c87aefeSPatrick Mooney USB_ACK, 122*4c87aefeSPatrick Mooney USB_NAK, 123*4c87aefeSPatrick Mooney USB_STALL, 124*4c87aefeSPatrick Mooney USB_NYET, 125*4c87aefeSPatrick Mooney USB_ERR, 126*4c87aefeSPatrick Mooney USB_SHORT 127*4c87aefeSPatrick Mooney }; 128*4c87aefeSPatrick Mooney 129*4c87aefeSPatrick Mooney #define USB_DATA_GET_ERRCODE(x) (x)->processed >> 8 130*4c87aefeSPatrick Mooney #define USB_DATA_SET_ERRCODE(x,e) do { \ 131*4c87aefeSPatrick Mooney (x)->processed = ((x)->processed & 0xFF) | (e << 8); \ 132*4c87aefeSPatrick Mooney } while (0) 133*4c87aefeSPatrick Mooney 134*4c87aefeSPatrick Mooney #define USB_DATA_OK(x,i) ((x)->data[(i)].buf != NULL) 135*4c87aefeSPatrick Mooney 136*4c87aefeSPatrick Mooney #define USB_DATA_XFER_INIT(x) do { \ 137*4c87aefeSPatrick Mooney memset((x), 0, sizeof(*(x))); \ 138*4c87aefeSPatrick Mooney pthread_mutex_init(&((x)->mtx), NULL); \ 139*4c87aefeSPatrick Mooney } while (0) 140*4c87aefeSPatrick Mooney 141*4c87aefeSPatrick Mooney #define USB_DATA_XFER_RESET(x) do { \ 142*4c87aefeSPatrick Mooney memset((x)->data, 0, sizeof((x)->data)); \ 143*4c87aefeSPatrick Mooney (x)->ndata = 0; \ 144*4c87aefeSPatrick Mooney (x)->head = (x)->tail = 0; \ 145*4c87aefeSPatrick Mooney } while (0) 146*4c87aefeSPatrick Mooney 147*4c87aefeSPatrick Mooney #define USB_DATA_XFER_LOCK(x) do { \ 148*4c87aefeSPatrick Mooney pthread_mutex_lock(&((x)->mtx)); \ 149*4c87aefeSPatrick Mooney } while (0) 150*4c87aefeSPatrick Mooney 151*4c87aefeSPatrick Mooney #define USB_DATA_XFER_UNLOCK(x) do { \ 152*4c87aefeSPatrick Mooney pthread_mutex_unlock(&((x)->mtx)); \ 153*4c87aefeSPatrick Mooney } while (0) 154*4c87aefeSPatrick Mooney #ifndef __FreeBSD__ 155*4c87aefeSPatrick Mooney #define USB_DATA_XFER_LOCK_HELD(x) MUTEX_HELD(&((x)->mtx)) 156*4c87aefeSPatrick Mooney #endif 157*4c87aefeSPatrick Mooney 158*4c87aefeSPatrick Mooney struct usb_devemu *usb_emu_finddev(char *name); 159*4c87aefeSPatrick Mooney 160*4c87aefeSPatrick Mooney struct usb_data_xfer_block *usb_data_xfer_append(struct usb_data_xfer *xfer, 161*4c87aefeSPatrick Mooney void *buf, int blen, void *hci_data, int ccs); 162*4c87aefeSPatrick Mooney 163*4c87aefeSPatrick Mooney 164*4c87aefeSPatrick Mooney #endif /* _USB_EMUL_H_ */ 165