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