usb_emul.h revision 302408
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: stable/11/usr.sbin/bhyve/usb_emul.h 302408 2016-07-08 00:04:57Z gjb $
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
43struct usb_hci;
44struct usb_device_request;
45struct usb_data_xfer;
46
47/* Device emulation handlers */
48struct 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 */
69enum hci_usbev {
70	USBDEV_ATTACH,
71	USBDEV_RESET,
72	USBDEV_STOP,
73	USBDEV_REMOVE,
74};
75
76/* usb controller, ie xhci, ehci */
77struct 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 */
94struct 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
105struct 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
114enum 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
150struct usb_devemu *usb_emu_finddev(char *name);
151
152struct 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