aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAndrew Thompson <thompsa@FreeBSD.org>2009-02-27 17:27:16 +0000
committerAndrew Thompson <thompsa@FreeBSD.org>2009-02-27 17:27:16 +0000
commitee3e3ff5c201f0b8942ea912ce7ebfdccb32af52 (patch)
tree799ccaf32ee5b67a3fd075acab472e59c72735d8 /sys/dev
parent2ebdf042257919c7ee6a2c7d8761a3803c0c87c0 (diff)
downloadsrc-ee3e3ff5c201f0b8942ea912ce7ebfdccb32af52.tar.gz
src-ee3e3ff5c201f0b8942ea912ce7ebfdccb32af52.zip
Change USB over to make_dev() for all device nodes, previously it hooked into
the devfs clone handler to open the (invisible) devices on the fly. The /dev entries are layed out as follows, /dev/usbctl = master device /dev/usb/0.1.0.5 = usb device, (<bus>.<dev>.<iface>.<endpoint>) /dev/ugen0.1 -> usb/0.1.0.0 = ugen link to ctrl endpoint This also removes the custom permissions model from USB. Bump __FreeBSD_version to 800066. Submitted by: rink (earlier version)
Notes
Notes: svn path=/head/; revision=189110
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/sound/usb/uaudio.c18
-rw-r--r--sys/dev/usb/bluetooth/ubtbcmfw.c13
-rw-r--r--sys/dev/usb/image/uscanner.c10
-rw-r--r--sys/dev/usb/input/uhid.c12
-rw-r--r--sys/dev/usb/input/ums.c14
-rw-r--r--sys/dev/usb/misc/ufm.c11
-rw-r--r--sys/dev/usb/serial/ulpt.c20
-rw-r--r--sys/dev/usb/storage/urio.c12
-rw-r--r--sys/dev/usb/usb_bus.h1
-rw-r--r--sys/dev/usb/usb_core.h34
-rw-r--r--sys/dev/usb/usb_dev.c1367
-rw-r--r--sys/dev/usb/usb_dev.h52
-rw-r--r--sys/dev/usb/usb_device.c182
-rw-r--r--sys/dev/usb/usb_device.h11
-rw-r--r--sys/dev/usb/usb_generic.c19
-rw-r--r--sys/dev/usb/usb_ioctl.h24
16 files changed, 630 insertions, 1170 deletions
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 7ea61f3fd66c..2c00e27625eb 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -379,9 +379,9 @@ static void umidi_start_read(struct usb2_fifo *);
static void umidi_stop_read(struct usb2_fifo *);
static void umidi_start_write(struct usb2_fifo *);
static void umidi_stop_write(struct usb2_fifo *);
-static int umidi_open(struct usb2_fifo *, int, struct thread *);
-static int umidi_ioctl(struct usb2_fifo *, u_long cmd, void *, int, struct thread *);
-static void umidi_close(struct usb2_fifo *, int, struct thread *);
+static int umidi_open(struct usb2_fifo *, int);
+static int umidi_ioctl(struct usb2_fifo *, u_long cmd, void *, int);
+static void umidi_close(struct usb2_fifo *, int);
static void umidi_init(device_t dev);
static int32_t umidi_probe(device_t dev);
static int32_t umidi_detach(device_t dev);
@@ -3585,7 +3585,7 @@ umidi_stop_write(struct usb2_fifo *fifo)
}
static int
-umidi_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+umidi_open(struct usb2_fifo *fifo, int fflags)
{
struct umidi_chan *chan = fifo->priv_sc0;
struct umidi_sub_chan *sub = umidi_sub_by_fifo(fifo);
@@ -3617,7 +3617,7 @@ umidi_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
}
static void
-umidi_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
+umidi_close(struct usb2_fifo *fifo, int fflags)
{
if (fflags & FREAD) {
usb2_fifo_free_buffer(fifo);
@@ -3630,7 +3630,7 @@ umidi_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
static int
umidi_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data,
- int fflags, struct thread *td)
+ int fflags)
{
return (ENODEV);
}
@@ -3684,9 +3684,6 @@ umidi_probe(device_t dev)
(chan->max_cable == 0)) {
chan->max_cable = UMIDI_CABLES_MAX;
}
- /* set interface permissions */
- usb2_set_iface_perm(sc->sc_udev, chan->iface_index,
- UID_ROOT, GID_OPERATOR, 0644);
for (n = 0; n < chan->max_cable; n++) {
@@ -3694,7 +3691,8 @@ umidi_probe(device_t dev)
error = usb2_fifo_attach(sc->sc_udev, chan, &chan->mtx,
&umidi_fifo_methods, &sub->fifo, unit, n,
- chan->iface_index);
+ chan->iface_index,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error) {
goto detach;
}
diff --git a/sys/dev/usb/bluetooth/ubtbcmfw.c b/sys/dev/usb/bluetooth/ubtbcmfw.c
index 3685f5671736..6929f2da0226 100644
--- a/sys/dev/usb/bluetooth/ubtbcmfw.c
+++ b/sys/dev/usb/bluetooth/ubtbcmfw.c
@@ -211,13 +211,10 @@ ubtbcmfw_attach(device_t dev)
goto detach;
}
- /* Set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
-
error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&ubtbcmfw_fifo_methods, &sc->sc_fifo,
- device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex);
+ device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error != 0) {
device_printf(dev, "could not attach fifo. %s\n",
usb2_errstr(error));
@@ -369,7 +366,7 @@ ubtbcmfw_stop_write(struct usb2_fifo *fifo)
*/
static int
-ubtbcmfw_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+ubtbcmfw_open(struct usb2_fifo *fifo, int fflags)
{
struct ubtbcmfw_softc *sc = fifo->priv_sc0;
struct usb2_xfer *xfer;
@@ -398,7 +395,7 @@ ubtbcmfw_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
*/
static void
-ubtbcmfw_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
+ubtbcmfw_close(struct usb2_fifo *fifo, int fflags)
{
if (fflags & (FREAD | FWRITE))
usb2_fifo_free_buffer(fifo);
@@ -410,7 +407,7 @@ ubtbcmfw_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
static int
ubtbcmfw_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data,
- int fflags, struct thread *td)
+ int fflags)
{
struct ubtbcmfw_softc *sc = fifo->priv_sc0;
int error = 0;
diff --git a/sys/dev/usb/image/uscanner.c b/sys/dev/usb/image/uscanner.c
index ca631b5824bb..bc4614d2d4b5 100644
--- a/sys/dev/usb/image/uscanner.c
+++ b/sys/dev/usb/image/uscanner.c
@@ -399,13 +399,11 @@ uscanner_attach(device_t dev)
"error=%s\n", usb2_errstr(error));
goto detach;
}
- /* set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&uscanner_fifo_methods, &sc->sc_fifo,
- unit, 0 - 1, uaa->info.bIfaceIndex);
+ unit, 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error) {
goto detach;
}
@@ -553,7 +551,7 @@ uscanner_write_clear_stall_callback(struct usb2_xfer *xfer)
* uscanner character device opening method.
*/
static int
-uscanner_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+uscanner_open(struct usb2_fifo *fifo, int fflags)
{
struct uscanner_softc *sc;
@@ -585,7 +583,7 @@ uscanner_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
}
static void
-uscanner_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
+uscanner_close(struct usb2_fifo *fifo, int fflags)
{
if (fflags & (FREAD | FWRITE)) {
usb2_fifo_free_buffer(fifo);
diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c
index 563bd9959eae..c2307f580cbc 100644
--- a/sys/dev/usb/input/uhid.c
+++ b/sys/dev/usb/input/uhid.c
@@ -447,7 +447,7 @@ done:
}
static int
-uhid_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+uhid_open(struct usb2_fifo *fifo, int fflags)
{
struct uhid_softc *sc = fifo->priv_sc0;
@@ -474,7 +474,7 @@ uhid_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
}
static void
-uhid_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
+uhid_close(struct usb2_fifo *fifo, int fflags)
{
if (fflags & (FREAD | FWRITE)) {
usb2_fifo_free_buffer(fifo);
@@ -483,7 +483,7 @@ uhid_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
static int
uhid_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr,
- int fflags, struct thread *td)
+ int fflags)
{
struct uhid_softc *sc = fifo->priv_sc0;
struct usb2_gen_descriptor *ugd;
@@ -734,13 +734,11 @@ uhid_attach(device_t dev)
sc->sc_fsize);
sc->sc_fsize = UHID_BSIZE;
}
- /* set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&uhid_fifo_methods, &sc->sc_fifo,
- unit, 0 - 1, uaa->info.bIfaceIndex);
+ unit, 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error) {
goto detach;
}
diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c
index 04e258057d05..36460b400a36 100644
--- a/sys/dev/usb/input/ums.c
+++ b/sys/dev/usb/input/ums.c
@@ -583,13 +583,10 @@ ums_attach(device_t dev)
sc->sc_status.dy = 0;
sc->sc_status.dz = 0;
- /* set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
-
err = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&ums_fifo_methods, &sc->sc_fifo,
- unit, 0 - 1, uaa->info.bIfaceIndex);
+ unit, 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (err) {
goto detach;
}
@@ -697,7 +694,7 @@ ums_reset_buf(struct ums_softc *sc)
}
static int
-ums_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+ums_open(struct usb2_fifo *fifo, int fflags)
{
struct ums_softc *sc = fifo->priv_sc0;
@@ -724,7 +721,7 @@ ums_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
}
static void
-ums_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
+ums_close(struct usb2_fifo *fifo, int fflags)
{
if (fflags & FREAD) {
usb2_fifo_free_buffer(fifo);
@@ -732,8 +729,7 @@ ums_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
}
static int
-ums_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr,
- int fflags, struct thread *td)
+ums_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags)
{
struct ums_softc *sc = fifo->priv_sc0;
mousemode_t mode;
diff --git a/sys/dev/usb/misc/ufm.c b/sys/dev/usb/misc/ufm.c
index 81ce1b3c0895..7f85b4fa4485 100644
--- a/sys/dev/usb/misc/ufm.c
+++ b/sys/dev/usb/misc/ufm.c
@@ -139,13 +139,10 @@ ufm_attach(device_t dev)
device_set_usb2_desc(dev);
- /* set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
-
error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&ufm_fifo_methods, &sc->sc_fifo,
- device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex);
+ device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error) {
goto detach;
}
@@ -169,7 +166,7 @@ ufm_detach(device_t dev)
}
static int
-ufm_open(struct usb2_fifo *dev, int fflags, struct thread *td)
+ufm_open(struct usb2_fifo *dev, int fflags)
{
if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) {
return (EACCES);
@@ -300,7 +297,7 @@ ufm_get_stat(struct ufm_softc *sc, void *addr)
static int
ufm_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr,
- int fflags, struct thread *td)
+ int fflags)
{
struct ufm_softc *sc = fifo->priv_sc0;
int error = 0;
diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c
index 36e082b3f3c3..b3008633b909 100644
--- a/sys/dev/usb/serial/ulpt.c
+++ b/sys/dev/usb/serial/ulpt.c
@@ -395,7 +395,7 @@ ulpt_stop_write(struct usb2_fifo *fifo)
}
static int
-ulpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+ulpt_open(struct usb2_fifo *fifo, int fflags)
{
struct ulpt_softc *sc = fifo->priv_sc0;
@@ -404,11 +404,11 @@ ulpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
if (sc->sc_fflags == 0) {
ulpt_reset(sc);
}
- return (unlpt_open(fifo, fflags, td));
+ return (unlpt_open(fifo, fflags));
}
static int
-unlpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+unlpt_open(struct usb2_fifo *fifo, int fflags)
{
struct ulpt_softc *sc = fifo->priv_sc0;
@@ -446,7 +446,7 @@ unlpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
}
static void
-ulpt_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
+ulpt_close(struct usb2_fifo *fifo, int fflags)
{
struct ulpt_softc *sc = fifo->priv_sc0;
@@ -459,7 +459,7 @@ ulpt_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
static int
ulpt_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data,
- int fflags, struct thread *td)
+ int fflags)
{
return (ENODEV);
}
@@ -595,19 +595,17 @@ found:
}
#endif
- /* set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
-
error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&ulpt_fifo_methods, &sc->sc_fifo,
- unit, 0 - 1, uaa->info.bIfaceIndex);
+ unit, 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error) {
goto detach;
}
error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&unlpt_fifo_methods, &sc->sc_fifo_noreset,
- unit, 0 - 1, uaa->info.bIfaceIndex);
+ unit, 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error) {
goto detach;
}
diff --git a/sys/dev/usb/storage/urio.c b/sys/dev/usb/storage/urio.c
index 82e16d90f881..278a952bf3e7 100644
--- a/sys/dev/usb/storage/urio.c
+++ b/sys/dev/usb/storage/urio.c
@@ -228,13 +228,11 @@ urio_attach(device_t dev)
DPRINTF("error=%s\n", usb2_errstr(error));
goto detach;
}
- /* set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&urio_fifo_methods, &sc->sc_fifo,
- device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex);
+ device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
if (error) {
goto detach;
}
@@ -370,7 +368,7 @@ urio_stop_write(struct usb2_fifo *fifo)
}
static int
-urio_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
+urio_open(struct usb2_fifo *fifo, int fflags)
{
struct urio_softc *sc = fifo->priv_sc0;
@@ -403,7 +401,7 @@ urio_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
}
static void
-urio_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
+urio_close(struct usb2_fifo *fifo, int fflags)
{
if (fflags & (FREAD | FWRITE)) {
usb2_fifo_free_buffer(fifo);
@@ -412,7 +410,7 @@ urio_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
static int
urio_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr,
- int fflags, struct thread *td)
+ int fflags)
{
struct usb2_ctl_request ur;
struct RioCommand *rio_cmd;
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index 59287c448d4b..d2fecb94621c 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -69,7 +69,6 @@ struct usb2_bus {
* This mutex protects the USB hardware:
*/
struct mtx bus_mtx;
- struct usb2_perm perm;
struct usb2_xfer_queue intr_q;
struct usb2_callout power_wdog; /* power management */
diff --git a/sys/dev/usb/usb_core.h b/sys/dev/usb/usb_core.h
index f89c22fd7a8d..62dcbd92d6ea 100644
--- a/sys/dev/usb/usb_core.h
+++ b/sys/dev/usb/usb_core.h
@@ -178,16 +178,6 @@ typedef void (usb2_callback_t)(struct usb2_xfer *);
/* structures */
/*
- * This structure contains permissions.
- */
-
-struct usb2_perm {
- uint32_t uid;
- uint32_t gid;
- uint16_t mode;
-};
-
-/*
* Common queue structure for USB transfers.
*/
struct usb2_xfer_queue {
@@ -383,25 +373,6 @@ struct usb2_attach_arg {
uint8_t use_generic; /* hint for generic drivers */
};
-/* Structure used when referring an USB device */
-
-struct usb2_location {
- struct usb2_bus *bus;
- struct usb2_device *udev;
- struct usb2_interface *iface;
- struct usb2_fifo *rxfifo;
- struct usb2_fifo *txfifo;
- uint32_t devloc; /* original devloc */
- uint16_t bus_index; /* bus index */
- uint8_t dev_index; /* device index */
- uint8_t iface_index; /* interface index */
- uint8_t fifo_index; /* FIFO index */
- uint8_t is_read; /* set if location has read access */
- uint8_t is_write; /* set if location has write access */
- uint8_t is_uref; /* set if USB refcount decr. needed */
- uint8_t is_usbfs; /* set if USB-FS is active */
-};
-
/* external variables */
MALLOC_DECLARE(M_USB);
@@ -449,13 +420,8 @@ uint8_t usb2_transfer_pending(struct usb2_xfer *xfer);
void usb2_transfer_start(struct usb2_xfer *xfer);
void usb2_transfer_stop(struct usb2_xfer *xfer);
void usb2_transfer_unsetup(struct usb2_xfer **pxfer, uint16_t n_setup);
-usb2_error_t usb2_ref_device(struct file *fp, struct usb2_location *ploc,
- uint32_t devloc);
-void usb2_unref_device(struct usb2_location *ploc);
void usb2_set_parent_iface(struct usb2_device *udev, uint8_t iface_index,
uint8_t parent_index);
-void usb2_set_iface_perm(struct usb2_device *udev, uint8_t iface_index,
- uint32_t uid, uint32_t gid, uint16_t mode);
uint8_t usb2_get_bus_index(struct usb2_device *udev);
uint8_t usb2_get_device_index(struct usb2_device *udev);
void usb2_set_power_mode(struct usb2_device *udev, uint8_t power_mode);
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index 87a656a3f561..6d385ede9801 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -72,381 +72,77 @@ SYSCTL_INT(_hw_usb2_dev, OID_AUTO, debug, CTLFLAG_RW,
/* prototypes */
-static uint32_t usb2_path_convert_one(const char **);
-static uint32_t usb2_path_convert(const char *);
-static int usb2_check_access(int, struct usb2_perm *);
-static int usb2_fifo_open(struct usb2_fifo *, struct file *,
- struct thread *, int);
-static void usb2_fifo_close(struct usb2_fifo *, struct thread *, int);
+static int usb2_fifo_open(struct usb2_fifo *, int);
+static void usb2_fifo_close(struct usb2_fifo *, int);
static void usb2_dev_init(void *);
static void usb2_dev_init_post(void *);
static void usb2_dev_uninit(void *);
static int usb2_fifo_uiomove(struct usb2_fifo *, void *, int,
struct uio *);
static void usb2_fifo_check_methods(struct usb2_fifo_methods *);
-static void usb2_clone(void *, USB_UCRED char *, int, struct cdev **);
static struct usb2_fifo *usb2_fifo_alloc(void);
static struct usb2_pipe *usb2_dev_get_pipe(struct usb2_device *, uint8_t,
uint8_t, uint8_t);
-
-static d_fdopen_t usb2_fdopen;
-static d_close_t usb2_close;
+static void usb2_loc_fill(struct usb2_fs_privdata *,
+ struct usb2_cdev_privdata *);
+static void usb2_close(void *);
+static usb2_error_t usb2_ref_device(struct usb2_cdev_privdata *, int);
+static usb2_error_t usb2_uref_location(struct usb2_cdev_privdata *);
+static void usb2_unref_device(struct usb2_cdev_privdata *);
+
+static d_open_t usb2_open;
static d_ioctl_t usb2_ioctl;
+static d_read_t usb2_read;
+static d_write_t usb2_write;
+static d_poll_t usb2_poll;
-static fo_rdwr_t usb2_read_f;
-static fo_rdwr_t usb2_write_f;
-
-#if __FreeBSD_version > 800009
-static fo_truncate_t usb2_truncate_f;
-
-#endif
-static fo_ioctl_t usb2_ioctl_f;
-static fo_poll_t usb2_poll_f;
-static fo_kqfilter_t usb2_kqfilter_f;
-static fo_stat_t usb2_stat_f;
-static fo_close_t usb2_close_f;
+static d_ioctl_t usb2_static_ioctl;
static usb2_fifo_open_t usb2_fifo_dummy_open;
static usb2_fifo_close_t usb2_fifo_dummy_close;
static usb2_fifo_ioctl_t usb2_fifo_dummy_ioctl;
static usb2_fifo_cmd_t usb2_fifo_dummy_cmd;
-static struct usb2_perm usb2_perm = {
- .uid = UID_ROOT,
- .gid = GID_OPERATOR,
- .mode = 0660,
-};
-
-static struct cdevsw usb2_devsw = {
+/* character device structure used for devices (/dev/ugenX.Y and /dev/uXXX) */
+struct cdevsw usb2_devsw = {
.d_version = D_VERSION,
- .d_fdopen = usb2_fdopen,
- .d_close = usb2_close,
+ .d_open = usb2_open,
.d_ioctl = usb2_ioctl,
- .d_name = "usb",
+ .d_name = "usbdev",
.d_flags = D_TRACKCLOSE,
+ .d_read = usb2_read,
+ .d_write = usb2_write,
+ .d_poll = usb2_poll
};
-static struct fileops usb2_ops_f = {
- .fo_read = usb2_read_f,
- .fo_write = usb2_write_f,
-#if __FreeBSD_version > 800009
- .fo_truncate = usb2_truncate_f,
-#endif
- .fo_ioctl = usb2_ioctl_f,
- .fo_poll = usb2_poll_f,
- .fo_kqfilter = usb2_kqfilter_f,
- .fo_stat = usb2_stat_f,
- .fo_close = usb2_close_f,
- .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
+static struct cdev* usb2_dev = NULL;
+
+/* character device structure used for /dev/usb */
+struct cdevsw usb2_static_devsw = {
+ .d_version = D_VERSION,
+ .d_ioctl = usb2_static_ioctl,
+ .d_name = "usb"
};
-static const dev_clone_fn usb2_clone_ptr = &usb2_clone;
-static struct cdev *usb2_dev;
-static uint32_t usb2_last_devloc = 0 - 1;
-static eventhandler_tag usb2_clone_tag;
-static void *usb2_old_f_data;
-static struct fileops *usb2_old_f_ops;
static TAILQ_HEAD(, usb2_symlink) usb2_sym_head;
static struct sx usb2_sym_lock;
struct mtx usb2_ref_lock;
-static uint32_t
-usb2_path_convert_one(const char **pp)
-{
- const char *ptr;
- uint32_t temp = 0;
-
- ptr = *pp;
-
- while ((*ptr >= '0') && (*ptr <= '9')) {
- temp *= 10;
- temp += (*ptr - '0');
- if (temp >= 1000000) {
- /* catch overflow early */
- return (0 - 1);
- }
- ptr++;
- }
-
- if (*ptr == '.') {
- /* skip dot */
- ptr++;
- }
- *pp = ptr;
-
- return (temp);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_path_convert
- *
- * Path format: "/dev/usb<bus>.<dev>.<iface>.<fifo>"
- *
- * Returns: Path converted into numerical format.
- *------------------------------------------------------------------------*/
-static uint32_t
-usb2_path_convert(const char *path)
-{
- uint32_t temp;
- uint32_t devloc;
-
- devloc = 0;
-
- temp = usb2_path_convert_one(&path);
-
- if (temp >= USB_BUS_MAX) {
- return (0 - 1);
- }
- devloc += temp;
-
- temp = usb2_path_convert_one(&path);
-
- if (temp >= USB_DEV_MAX) {
- return (0 - 1);
- }
- devloc += (temp * USB_BUS_MAX);
-
- temp = usb2_path_convert_one(&path);
-
- if (temp >= USB_IFACE_MAX) {
- return (0 - 1);
- }
- devloc += (temp * USB_DEV_MAX * USB_BUS_MAX);
-
- temp = usb2_path_convert_one(&path);
-
- if (temp >= ((USB_FIFO_MAX / 2) + (USB_EP_MAX / 2))) {
- return (0 - 1);
- }
- devloc += (temp * USB_IFACE_MAX * USB_DEV_MAX * USB_BUS_MAX);
-
- return (devloc);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_set_iface_perm
- *
- * This function will set the interface permissions.
- *------------------------------------------------------------------------*/
-void
-usb2_set_iface_perm(struct usb2_device *udev, uint8_t iface_index,
- uint32_t uid, uint32_t gid, uint16_t mode)
-{
- struct usb2_interface *iface;
-
- iface = usb2_get_iface(udev, iface_index);
- if (iface && iface->idesc) {
- mtx_lock(&usb2_ref_lock);
- iface->perm.uid = uid;
- iface->perm.gid = gid;
- iface->perm.mode = mode;
- mtx_unlock(&usb2_ref_lock);
-
- }
-}
-
-/*------------------------------------------------------------------------*
- * usb2_set_perm
- *
- * This function will set the permissions at the given level.
- *
- * Return values:
- * 0: Success.
- * Else: Failure.
- *------------------------------------------------------------------------*/
-static int
-usb2_set_perm(struct usb2_dev_perm *psrc, uint8_t level)
-{
- struct usb2_location loc;
- struct usb2_perm *pdst;
- uint32_t devloc;
- int error;
-
- /* check if the current thread can change USB permissions. */
- error = priv_check(curthread, PRIV_ROOT);
- if (error) {
- return (error);
- }
- /* range check device location */
- if ((psrc->bus_index >= USB_BUS_MAX) ||
- (psrc->dev_index >= USB_DEV_MAX) ||
- (psrc->iface_index >= USB_IFACE_MAX)) {
- return (EINVAL);
- }
- if (level == 1)
- devloc = USB_BUS_MAX; /* use root-HUB to access bus */
- else
- devloc = 0;
- switch (level) {
- case 3:
- devloc += psrc->iface_index *
- USB_DEV_MAX * USB_BUS_MAX;
- /* FALLTHROUGH */
- case 2:
- devloc += psrc->dev_index *
- USB_BUS_MAX;
- /* FALLTHROUGH */
- case 1:
- devloc += psrc->bus_index;
- break;
- default:
- break;
- }
-
- if ((level > 0) && (level < 4)) {
- error = usb2_ref_device(NULL, &loc, devloc);
- if (error) {
- return (error);
- }
- }
- switch (level) {
- case 3:
- if (loc.iface == NULL) {
- usb2_unref_device(&loc);
- return (EINVAL);
- }
- pdst = &loc.iface->perm;
- break;
- case 2:
- pdst = &loc.udev->perm;
- break;
- case 1:
- pdst = &loc.bus->perm;
- break;
- default:
- pdst = &usb2_perm;
- break;
- }
-
- /* all permissions are protected by "usb2_ref_lock" */
- mtx_lock(&usb2_ref_lock);
- pdst->uid = psrc->user_id;
- pdst->gid = psrc->group_id;
- pdst->mode = psrc->mode;
- mtx_unlock(&usb2_ref_lock);
-
- if ((level > 0) && (level < 4)) {
- usb2_unref_device(&loc);
- }
- return (0); /* success */
-}
-
-/*------------------------------------------------------------------------*
- * usb2_get_perm
- *
- * This function will get the permissions at the given level.
- *
- * Return values:
- * 0: Success.
- * Else: Failure.
- *------------------------------------------------------------------------*/
-static int
-usb2_get_perm(struct usb2_dev_perm *pdst, uint8_t level)
-{
- struct usb2_location loc;
- struct usb2_perm *psrc;
- uint32_t devloc;
- int error;
-
- if ((pdst->bus_index >= USB_BUS_MAX) ||
- (pdst->dev_index >= USB_DEV_MAX) ||
- (pdst->iface_index >= USB_IFACE_MAX)) {
- return (EINVAL);
- }
- if (level == 1)
- devloc = USB_BUS_MAX; /* use root-HUB to access bus */
- else
- devloc = 0;
- switch (level) {
- case 3:
- devloc += pdst->iface_index *
- USB_DEV_MAX * USB_BUS_MAX;
- /* FALLTHROUGH */
- case 2:
- devloc += pdst->dev_index *
- USB_BUS_MAX;
- /* FALLTHROUGH */
- case 1:
- devloc += pdst->bus_index;
- break;
- default:
- break;
- }
-
- if ((level > 0) && (level < 4)) {
- error = usb2_ref_device(NULL, &loc, devloc);
- if (error) {
- return (error);
- }
- }
- switch (level) {
- case 3:
- if (loc.iface == NULL) {
- usb2_unref_device(&loc);
- return (EINVAL);
- }
- psrc = &loc.iface->perm;
- break;
- case 2:
- psrc = &loc.udev->perm;
- break;
- case 1:
- psrc = &loc.bus->perm;
- break;
- default:
- psrc = &usb2_perm;
- break;
- }
-
- /* all permissions are protected by "usb2_ref_lock" */
- mtx_lock(&usb2_ref_lock);
- if (psrc->mode != 0) {
- pdst->user_id = psrc->uid;
- pdst->group_id = psrc->gid;
- pdst->mode = psrc->mode;
- } else {
- /* access entry at this level and location is not active */
- pdst->user_id = 0;
- pdst->group_id = 0;
- pdst->mode = 0;
- }
- mtx_unlock(&usb2_ref_lock);
-
- if ((level > 0) && (level < 4)) {
- usb2_unref_device(&loc);
- }
- return (0);
-}
-
/*------------------------------------------------------------------------*
- * usb2_check_access
- *
- * This function will verify the given access information.
+ * usb2_loc_fill
*
- * Return values:
- * 0: Access granted.
- * Else: No access granted.
+ * This is used to fill out a usb2_cdev_privdata structure based on the
+ * device's address as contained in usb2_fs_privdata.
*------------------------------------------------------------------------*/
-static int
-usb2_check_access(int fflags, struct usb2_perm *puser)
+static void
+usb2_loc_fill(struct usb2_fs_privdata* pd, struct usb2_cdev_privdata *cpd)
{
- mode_t accmode;
-
- if ((fflags & (FWRITE | FREAD)) && (puser->mode != 0)) {
- /* continue */
- } else {
- return (EPERM); /* no access */
- }
-
- accmode = 0;
- if (fflags & FWRITE)
- accmode |= VWRITE;
- if (fflags & FREAD)
- accmode |= VREAD;
-
- return (vaccess(VCHR, puser->mode, puser->uid,
- puser->gid, accmode, curthread->td_ucred, NULL));
+ cpd->bus_index = pd->bus_index;
+ cpd->dev_index = pd->dev_index;
+ cpd->iface_index = pd->iface_index;
+ cpd->ep_addr = pd->ep_addr;
+ cpd->fifo_index = pd->fifo_index;
}
/*------------------------------------------------------------------------*
@@ -461,89 +157,53 @@ usb2_check_access(int fflags, struct usb2_perm *puser)
* Else: Failure.
*------------------------------------------------------------------------*/
usb2_error_t
-usb2_ref_device(struct file *fp, struct usb2_location *ploc, uint32_t devloc)
+usb2_ref_device(struct usb2_cdev_privdata* cpd, int need_uref)
{
struct usb2_fifo **ppf;
struct usb2_fifo *f;
- int fflags;
- uint8_t dev_ep_index;
-
- if (fp) {
- /* check if we need uref */
- ploc->is_uref = devloc ? 0 : 1;
- /* get devloc - already verified */
- devloc = USB_P2U(fp->f_data);
- /* get file flags */
- fflags = fp->f_flag;
- } else {
- /* only ref device */
- fflags = 0;
- /* search for FIFO */
- ploc->is_uref = 1;
- /* check "devloc" */
- if (devloc >= (USB_BUS_MAX * USB_DEV_MAX *
- USB_IFACE_MAX * ((USB_EP_MAX / 2) + (USB_FIFO_MAX / 2)))) {
- return (USB_ERR_INVAL);
- }
- }
+ int dev_ep_index;
- /* store device location */
- ploc->devloc = devloc;
- ploc->bus_index = devloc % USB_BUS_MAX;
- ploc->dev_index = (devloc / USB_BUS_MAX) % USB_DEV_MAX;
- ploc->iface_index = (devloc / (USB_BUS_MAX *
- USB_DEV_MAX)) % USB_IFACE_MAX;
- ploc->fifo_index = (devloc / (USB_BUS_MAX * USB_DEV_MAX *
- USB_IFACE_MAX));
+ DPRINTFN(2, "usb2_ref_device, cpd=%p need uref=%d\n", cpd, need_uref);
mtx_lock(&usb2_ref_lock);
- ploc->bus = devclass_get_softc(usb2_devclass_ptr, ploc->bus_index);
- if (ploc->bus == NULL) {
- DPRINTFN(2, "no bus at %u\n", ploc->bus_index);
+ cpd->bus = devclass_get_softc(usb2_devclass_ptr, cpd->bus_index);
+ if (cpd->bus == NULL) {
+ DPRINTFN(2, "no bus at %u\n", cpd->bus_index);
goto error;
}
- if (ploc->dev_index >= ploc->bus->devices_max) {
- DPRINTFN(2, "invalid dev index, %u\n", ploc->dev_index);
+ cpd->udev = cpd->bus->devices[cpd->dev_index];
+ if (cpd->udev == NULL) {
+ DPRINTFN(2, "no device at %u\n", cpd->dev_index);
goto error;
}
- ploc->udev = ploc->bus->devices[ploc->dev_index];
- if (ploc->udev == NULL) {
- DPRINTFN(2, "no device at %u\n", ploc->dev_index);
- goto error;
- }
- if (ploc->udev->refcount == USB_DEV_REF_MAX) {
+ if (cpd->udev->refcount == USB_DEV_REF_MAX) {
DPRINTFN(2, "no dev ref\n");
goto error;
}
/* check if we are doing an open */
- if (fp == NULL) {
+ dev_ep_index = cpd->ep_addr;
+ if (cpd->fflags == 0) {
/* set defaults */
- ploc->txfifo = NULL;
- ploc->rxfifo = NULL;
- ploc->is_write = 0;
- ploc->is_read = 0;
- ploc->is_usbfs = 0;
- /* NOTE: variable overloading: */
- dev_ep_index = ploc->fifo_index;
+ cpd->txfifo = NULL;
+ cpd->rxfifo = NULL;
+ cpd->is_write = 0;
+ cpd->is_read = 0;
+ cpd->is_usbfs = 0;
} else {
/* initialise "is_usbfs" flag */
- ploc->is_usbfs = 0;
- dev_ep_index = 255; /* dummy */
+ cpd->is_usbfs = 0;
/* check for write */
- if (fflags & FWRITE) {
- ppf = ploc->udev->fifo;
- f = ppf[ploc->fifo_index + USB_FIFO_TX];
- ploc->txfifo = f;
- ploc->is_write = 1; /* ref */
- if ((f == NULL) ||
- (f->refcount == USB_FIFO_REF_MAX) ||
- (f->curr_file != fp)) {
+ if (cpd->fflags & FWRITE) {
+ ppf = cpd->udev->fifo;
+ f = ppf[cpd->fifo_index + USB_FIFO_TX];
+ cpd->txfifo = f;
+ cpd->is_write = 1; /* ref */
+ if (f == NULL || f->refcount == USB_FIFO_REF_MAX)
goto error;
- }
/* check if USB-FS is active */
if (f->fs_ep_max != 0) {
- ploc->is_usbfs = 1;
+ cpd->is_usbfs = 1;
}
/*
* Get real endpoint index associated with
@@ -551,24 +211,21 @@ usb2_ref_device(struct file *fp, struct usb2_location *ploc, uint32_t devloc)
*/
dev_ep_index = f->dev_ep_index;
} else {
- ploc->txfifo = NULL;
- ploc->is_write = 0; /* no ref */
+ cpd->txfifo = NULL;
+ cpd->is_write = 0; /* no ref */
}
/* check for read */
- if (fflags & FREAD) {
- ppf = ploc->udev->fifo;
- f = ppf[ploc->fifo_index + USB_FIFO_RX];
- ploc->rxfifo = f;
- ploc->is_read = 1; /* ref */
- if ((f == NULL) ||
- (f->refcount == USB_FIFO_REF_MAX) ||
- (f->curr_file != fp)) {
+ if (cpd->fflags & FREAD) {
+ ppf = cpd->udev->fifo;
+ f = ppf[cpd->fifo_index + USB_FIFO_RX];
+ cpd->rxfifo = f;
+ cpd->is_read = 1; /* ref */
+ if (f == NULL || f->refcount == USB_FIFO_REF_MAX)
goto error;
- }
/* check if USB-FS is active */
if (f->fs_ep_max != 0) {
- ploc->is_usbfs = 1;
+ cpd->is_usbfs = 1;
}
/*
* Get real endpoint index associated with
@@ -576,45 +233,46 @@ usb2_ref_device(struct file *fp, struct usb2_location *ploc, uint32_t devloc)
*/
dev_ep_index = f->dev_ep_index;
} else {
- ploc->rxfifo = NULL;
- ploc->is_read = 0; /* no ref */
+ cpd->rxfifo = NULL;
+ cpd->is_read = 0; /* no ref */
}
}
/* check if we require an interface */
- ploc->iface = usb2_get_iface(ploc->udev, ploc->iface_index);
+ cpd->iface = usb2_get_iface(cpd->udev, cpd->iface_index);
if (dev_ep_index != 0) {
/* non control endpoint - we need an interface */
- if (ploc->iface == NULL) {
+ if (cpd->iface == NULL) {
DPRINTFN(2, "no iface\n");
goto error;
}
- if (ploc->iface->idesc == NULL) {
+ if (cpd->iface->idesc == NULL) {
DPRINTFN(2, "no idesc\n");
goto error;
}
}
/* when everything is OK we increment the refcounts */
- if (ploc->is_write) {
+ if (cpd->is_write) {
DPRINTFN(2, "ref write\n");
- ploc->txfifo->refcount++;
+ cpd->txfifo->refcount++;
}
- if (ploc->is_read) {
+ if (cpd->is_read) {
DPRINTFN(2, "ref read\n");
- ploc->rxfifo->refcount++;
+ cpd->rxfifo->refcount++;
}
- if (ploc->is_uref) {
+ if (need_uref) {
DPRINTFN(2, "ref udev - needed\n");
- ploc->udev->refcount++;
+ cpd->udev->refcount++;
+ cpd->is_uref = 1;
}
mtx_unlock(&usb2_ref_lock);
- if (ploc->is_uref) {
+ if (cpd->is_uref) {
/*
* We are about to alter the bus-state. Apply the
* required locks.
*/
- sx_xlock(ploc->udev->default_sx + 1);
+ sx_xlock(cpd->udev->default_sx + 1);
mtx_lock(&Giant); /* XXX */
}
return (0);
@@ -636,39 +294,39 @@ error:
* Else: Failure.
*------------------------------------------------------------------------*/
static usb2_error_t
-usb2_uref_location(struct usb2_location *ploc)
+usb2_uref_location(struct usb2_cdev_privdata *cpd)
{
/*
* Check if we already got an USB reference on this location:
*/
- if (ploc->is_uref) {
+ if (cpd->is_uref) {
return (0); /* success */
}
mtx_lock(&usb2_ref_lock);
- if (ploc->bus != devclass_get_softc(usb2_devclass_ptr, ploc->bus_index)) {
- DPRINTFN(2, "bus changed at %u\n", ploc->bus_index);
+ if (cpd->bus != devclass_get_softc(usb2_devclass_ptr, cpd->bus_index)) {
+ DPRINTFN(2, "bus changed at %u\n", cpd->bus_index);
goto error;
}
- if (ploc->udev != ploc->bus->devices[ploc->dev_index]) {
- DPRINTFN(2, "device changed at %u\n", ploc->dev_index);
+ if (cpd->udev != cpd->bus->devices[cpd->dev_index]) {
+ DPRINTFN(2, "device changed at %u\n", cpd->dev_index);
goto error;
}
- if (ploc->udev->refcount == USB_DEV_REF_MAX) {
+ if (cpd->udev->refcount == USB_DEV_REF_MAX) {
DPRINTFN(2, "no dev ref\n");
goto error;
}
DPRINTFN(2, "ref udev\n");
- ploc->udev->refcount++;
+ cpd->udev->refcount++;
mtx_unlock(&usb2_ref_lock);
/* set "uref" */
- ploc->is_uref = 1;
+ cpd->is_uref = 1;
/*
* We are about to alter the bus-state. Apply the
* required locks.
*/
- sx_xlock(ploc->udev->default_sx + 1);
+ sx_xlock(cpd->udev->default_sx + 1);
mtx_lock(&Giant); /* XXX */
return (0);
@@ -685,27 +343,30 @@ error:
* given USB device.
*------------------------------------------------------------------------*/
void
-usb2_unref_device(struct usb2_location *ploc)
+usb2_unref_device(struct usb2_cdev_privdata *cpd)
{
- if (ploc->is_uref) {
+ if (cpd->is_uref) {
mtx_unlock(&Giant); /* XXX */
- sx_unlock(ploc->udev->default_sx + 1);
+ sx_unlock(cpd->udev->default_sx + 1);
}
mtx_lock(&usb2_ref_lock);
- if (ploc->is_read) {
- if (--(ploc->rxfifo->refcount) == 0) {
- usb2_cv_signal(&ploc->rxfifo->cv_drain);
+ if (cpd->is_read) {
+ if (--(cpd->rxfifo->refcount) == 0) {
+ usb2_cv_signal(&cpd->rxfifo->cv_drain);
}
+ cpd->is_read = 0;
}
- if (ploc->is_write) {
- if (--(ploc->txfifo->refcount) == 0) {
- usb2_cv_signal(&ploc->txfifo->cv_drain);
+ if (cpd->is_write) {
+ if (--(cpd->txfifo->refcount) == 0) {
+ usb2_cv_signal(&cpd->txfifo->cv_drain);
}
+ cpd->is_write = 0;
}
- if (ploc->is_uref) {
- if (--(ploc->udev->refcount) == 0) {
- usb2_cv_signal(ploc->udev->default_cv + 1);
+ if (cpd->is_uref) {
+ if (--(cpd->udev->refcount) == 0) {
+ usb2_cv_signal(cpd->udev->default_cv + 1);
}
+ cpd->is_uref = 0;
}
mtx_unlock(&usb2_ref_lock);
}
@@ -728,28 +389,46 @@ usb2_fifo_alloc(void)
* usb2_fifo_create
*------------------------------------------------------------------------*/
static int
-usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
+usb2_fifo_create(struct usb2_cdev_privdata *cpd)
{
- struct usb2_device *udev = ploc->udev;
+ struct usb2_device *udev = cpd->udev;
struct usb2_fifo *f;
struct usb2_pipe *pipe;
- uint8_t iface_index = ploc->iface_index;
-
- /* NOTE: variable overloading: */
- uint8_t dev_ep_index = ploc->fifo_index;
+ uint8_t iface_index = cpd->iface_index;
uint8_t n;
uint8_t is_tx;
uint8_t is_rx;
uint8_t no_null;
uint8_t is_busy;
+ int ep = cpd->ep_addr;
- is_tx = (fflags & FWRITE) ? 1 : 0;
- is_rx = (fflags & FREAD) ? 1 : 0;
+ is_tx = (cpd->fflags & FWRITE) ? 1 : 0;
+ is_rx = (cpd->fflags & FREAD) ? 1 : 0;
no_null = 1;
is_busy = 0;
- /* search for a free FIFO slot */
+ /* Preallocated FIFO */
+ if (ep < 0) {
+ DPRINTFN(5, "Preallocated FIFO\n");
+ if (is_tx) {
+ f = udev->fifo[cpd->fifo_index + USB_FIFO_TX];
+ if (f == NULL)
+ return (EINVAL);
+ cpd->txfifo = f;
+ }
+ if (is_rx) {
+ f = udev->fifo[cpd->fifo_index + USB_FIFO_RX];
+ if (f == NULL)
+ return (EINVAL);
+ cpd->rxfifo = f;
+ }
+ return (0);
+ }
+
+ KASSERT(ep >= 0 && ep <= 15, ("endpoint %d out of range", ep));
+ /* search for a free FIFO slot */
+ DPRINTFN(5, "Endpoint device, searching for 0x%02x\n", ep);
for (n = 0;; n += 2) {
if (n == USB_FIFO_MAX) {
@@ -758,6 +437,7 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
n = 0;
} else {
/* end of FIFOs reached */
+ DPRINTFN(5, "out of FIFOs\n");
return (ENOMEM);
}
}
@@ -765,16 +445,16 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
if (is_tx) {
f = udev->fifo[n + USB_FIFO_TX];
if (f != NULL) {
- if (f->dev_ep_index != dev_ep_index) {
+ if (f->dev_ep_index != ep) {
/* wrong endpoint index */
continue;
}
- if ((dev_ep_index != 0) &&
- (f->iface_index != iface_index)) {
+ if (ep != 0 &&
+ f->iface_index != iface_index) {
/* wrong interface index */
continue;
}
- if (f->curr_file != NULL) {
+ if (f->opened) {
/* FIFO is opened */
is_busy = 1;
continue;
@@ -787,16 +467,16 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
if (is_rx) {
f = udev->fifo[n + USB_FIFO_RX];
if (f != NULL) {
- if (f->dev_ep_index != dev_ep_index) {
+ if (f->dev_ep_index != ep) {
/* wrong endpoint index */
continue;
}
- if ((dev_ep_index != 0) &&
- (f->iface_index != iface_index)) {
+ if (ep != 0 &&
+ f->iface_index != iface_index) {
/* wrong interface index */
continue;
}
- if (f->curr_file != NULL) {
+ if (f->opened) {
/* FIFO is opened */
is_busy = 1;
continue;
@@ -809,8 +489,9 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
}
if (no_null == 0) {
- if (dev_ep_index >= (USB_EP_MAX / 2)) {
+ if (ep >= (USB_EP_MAX / 2)) {
/* we don't create any endpoints in this range */
+ DPRINTFN(5, "dev_ep_index out of range\n");
return (is_busy ? EBUSY : EINVAL);
}
}
@@ -818,17 +499,20 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
if (is_tx &&
(udev->fifo[n + USB_FIFO_TX] == NULL)) {
pipe = usb2_dev_get_pipe(udev,
- iface_index, dev_ep_index, USB_FIFO_TX);
+ iface_index, ep, USB_FIFO_TX);
+ DPRINTFN(5, "dev_get_pipe(%d, 0x%x, 0x%x)\n", iface_index, ep, USB_FIFO_TX);
if (pipe == NULL) {
+ DPRINTFN(5, "dev_get_pipe returned NULL\n");
return (EINVAL);
}
f = usb2_fifo_alloc();
if (f == NULL) {
+ DPRINTFN(5, "could not alloc tx fifo\n");
return (ENOMEM);
}
/* update some fields */
f->fifo_index = n + USB_FIFO_TX;
- f->dev_ep_index = dev_ep_index;
+ f->dev_ep_index = ep;
f->priv_mtx = udev->default_mtx;
f->priv_sc0 = pipe;
f->methods = &usb2_ugen_methods;
@@ -843,17 +527,20 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
(udev->fifo[n + USB_FIFO_RX] == NULL)) {
pipe = usb2_dev_get_pipe(udev,
- iface_index, dev_ep_index, USB_FIFO_RX);
+ iface_index, ep, USB_FIFO_RX);
+ DPRINTFN(5, "dev_get_pipe(%d, 0x%x, 0x%x)\n", iface_index, ep, USB_FIFO_RX);
if (pipe == NULL) {
+ DPRINTFN(5, "dev_get_pipe returned NULL\n");
return (EINVAL);
}
f = usb2_fifo_alloc();
if (f == NULL) {
+ DPRINTFN(5, "could not alloc rx fifo\n");
return (ENOMEM);
}
/* update some fields */
f->fifo_index = n + USB_FIFO_RX;
- f->dev_ep_index = dev_ep_index;
+ f->dev_ep_index = ep;
f->priv_mtx = udev->default_mtx;
f->priv_sc0 = pipe;
f->methods = &usb2_ugen_methods;
@@ -864,15 +551,14 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags)
mtx_unlock(&usb2_ref_lock);
}
if (is_tx) {
- ploc->txfifo = udev->fifo[n + USB_FIFO_TX];
+ cpd->txfifo = udev->fifo[n + USB_FIFO_TX];
}
if (is_rx) {
- ploc->rxfifo = udev->fifo[n + USB_FIFO_RX];
+ cpd->rxfifo = udev->fifo[n + USB_FIFO_RX];
}
- /* replace endpoint index by FIFO index */
-
- (*pdevloc) %= (USB_BUS_MAX * USB_DEV_MAX * USB_IFACE_MAX);
- (*pdevloc) += (USB_BUS_MAX * USB_DEV_MAX * USB_IFACE_MAX) * n;
+ /* fill out fifo index */
+ DPRINTFN(5, "fifo index = %d\n", n);
+ cpd->fifo_index = n;
/* complete */
@@ -928,7 +614,7 @@ usb2_fifo_free(struct usb2_fifo *f)
mtx_unlock(&usb2_ref_lock);
/* take care of closing the device here, if any */
- usb2_fifo_close(f, curthread, 0);
+ usb2_fifo_close(f, 0);
usb2_cv_destroy(&f->cv_io);
usb2_cv_destroy(&f->cv_drain);
@@ -990,8 +676,7 @@ usb2_dev_get_pipe(struct usb2_device *udev,
* Else: Failure
*------------------------------------------------------------------------*/
static int
-usb2_fifo_open(struct usb2_fifo *f, struct file *fp, struct thread *td,
- int fflags)
+usb2_fifo_open(struct usb2_fifo *f, int fflags)
{
int err;
@@ -1012,12 +697,13 @@ usb2_fifo_open(struct usb2_fifo *f, struct file *fp, struct thread *td,
/* check if we are already opened */
/* we don't need any locks when checking this variable */
- if (f->curr_file) {
+ if (f->opened) {
err = EBUSY;
goto done;
}
+
/* call open method */
- err = (f->methods->f_open) (f, fflags, td);
+ err = (f->methods->f_open) (f, fflags);
if (err) {
goto done;
}
@@ -1041,9 +727,9 @@ usb2_fifo_open(struct usb2_fifo *f, struct file *fp, struct thread *td,
/* reset ASYNC proc flag */
f->async_p = NULL;
- /* set which file we belong to */
+ /* flag the fifo as opened to prevent others */
mtx_lock(&usb2_ref_lock);
- f->curr_file = fp;
+ f->opened = 1;
mtx_unlock(&usb2_ref_lock);
/* reset queue */
@@ -1079,19 +765,19 @@ usb2_fifo_reset(struct usb2_fifo *f)
* usb2_fifo_close
*------------------------------------------------------------------------*/
static void
-usb2_fifo_close(struct usb2_fifo *f, struct thread *td, int fflags)
+usb2_fifo_close(struct usb2_fifo *f, int fflags)
{
int err;
/* check if we are not opened */
- if (!f->curr_file) {
+ if (!f->opened) {
/* nothing to do - already closed */
return;
}
mtx_lock(f->priv_mtx);
/* clear current file flag */
- f->curr_file = NULL;
+ f->opened = 0;
/* check if we are selected */
if (f->flag_isselect) {
@@ -1149,310 +835,126 @@ usb2_fifo_close(struct usb2_fifo *f, struct thread *td, int fflags)
mtx_unlock(f->priv_mtx);
/* call close method */
- (f->methods->f_close) (f, fflags, td);
+ (f->methods->f_close) (f, fflags);
DPRINTF("closed\n");
}
/*------------------------------------------------------------------------*
- * usb2_check_thread_perm
- *
- * Returns:
- * 0: Has permission.
- * Else: No permission.
- *------------------------------------------------------------------------*/
-int
-usb2_check_thread_perm(struct usb2_device *udev, struct thread *td,
- int fflags, uint8_t iface_index, uint8_t ep_index)
-{
- struct usb2_interface *iface;
- int err;
-
- if (ep_index != 0) {
- /*
- * Non-control endpoints are always
- * associated with an interface:
- */
- iface = usb2_get_iface(udev, iface_index);
- if (iface == NULL) {
- return (EINVAL);
- }
- if (iface->idesc == NULL) {
- return (EINVAL);
- }
- } else {
- iface = NULL;
- }
- /* scan down the permissions tree */
- if ((iface != NULL) &&
- (usb2_check_access(fflags, &iface->perm) == 0)) {
- /* we got access through the interface */
- err = 0;
- } else if (udev &&
- (usb2_check_access(fflags, &udev->perm) == 0)) {
- /* we got access through the device */
- err = 0;
- } else if (udev->bus &&
- (usb2_check_access(fflags, &udev->bus->perm) == 0)) {
- /* we got access through the USB bus */
- err = 0;
- } else if (usb2_check_access(fflags, &usb2_perm) == 0) {
- /* we got general access */
- err = 0;
- } else {
- /* no access */
- err = EPERM;
- }
- return (err);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_fdopen - cdev callback
+ * usb2_open - cdev callback
*------------------------------------------------------------------------*/
static int
-usb2_fdopen(struct cdev *dev, int xxx_oflags, struct thread *td,
- struct file *fp)
+usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
{
- struct usb2_location loc;
- uint32_t devloc;
- int err;
- int fflags;
-
- DPRINTFN(2, "oflags=0x%08x\n", xxx_oflags);
+ struct usb2_fs_privdata* pd = (struct usb2_fs_privdata*)dev->si_drv1;
+ struct usb2_cdev_privdata *cpd;
+ int err, ep;
- devloc = usb2_last_devloc;
- usb2_last_devloc = (0 - 1); /* reset "usb2_last_devloc" */
-
- if (fp == NULL) {
- DPRINTFN(2, "fp == NULL\n");
- return (ENXIO);
- }
- if (usb2_old_f_data != fp->f_data) {
- if (usb2_old_f_data != NULL) {
- DPRINTFN(0, "File data mismatch!\n");
- return (ENXIO);
- }
- usb2_old_f_data = fp->f_data;
- }
- if (usb2_old_f_ops != fp->f_ops) {
- if (usb2_old_f_ops != NULL) {
- DPRINTFN(0, "File ops mismatch!\n");
- return (ENXIO);
- }
- usb2_old_f_ops = fp->f_ops;
- }
- fflags = fp->f_flag;
DPRINTFN(2, "fflags=0x%08x\n", fflags);
- if (!(fflags & (FREAD | FWRITE))) {
- /* should not happen */
+ KASSERT(fflags & (FREAD|FWRITE), ("invalid open flags"));
+ if (((fflags & FREAD) && !(pd->mode & FREAD)) ||
+ ((fflags & FWRITE) && !(pd->mode & FWRITE))) {
+ DPRINTFN(2, "access mode not supported\n");
return (EPERM);
}
- if (devloc == (uint32_t)(0 - 2)) {
- /* tried to open "/dev/usb" */
- return (0);
- } else if (devloc == (uint32_t)(0 - 1)) {
- /* tried to open "/dev/usb " */
- DPRINTFN(2, "no devloc\n");
- return (ENXIO);
- }
- err = usb2_ref_device(NULL, &loc, devloc);
+
+ cpd = malloc(sizeof(*cpd), M_USBDEV, M_WAITOK | M_ZERO);
+ ep = cpd->ep_addr = pd->ep_addr;
+
+ usb2_loc_fill(pd, cpd);
+ err = usb2_ref_device(cpd, 1);
if (err) {
DPRINTFN(2, "cannot ref device\n");
+ free(cpd, M_USBDEV);
return (ENXIO);
}
- /*
- * NOTE: Variable overloading. "usb2_fifo_create" will update
- * the FIFO index. Right here we can assume that the
- * "fifo_index" is the same like the endpoint number without
- * direction mask, if the "fifo_index" is less than 16.
- */
- err = usb2_check_thread_perm(loc.udev, td, fflags,
- loc.iface_index, loc.fifo_index);
+ cpd->fflags = fflags; /* access mode for open lifetime */
- /* check for error */
- if (err) {
- usb2_unref_device(&loc);
- return (err);
+ /* Check if the endpoint is already open, we always allow EP0 */
+ if (ep > 0) {
+ if ((fflags & FREAD && cpd->udev->ep_rd_opened & (1 << ep)) ||
+ (fflags & FWRITE && cpd->udev->ep_wr_opened & (1 << ep))) {
+ DPRINTFN(2, "endpoint already open\n");
+ usb2_unref_device(cpd);
+ free(cpd, M_USBDEV);
+ return (EBUSY);
+ }
+ if (fflags & FREAD)
+ cpd->udev->ep_rd_opened |= (1 << ep);
+ if (fflags & FWRITE)
+ cpd->udev->ep_wr_opened |= (1 << ep);
}
+
/* create FIFOs, if any */
- err = usb2_fifo_create(&loc, &devloc, fflags);
+ err = usb2_fifo_create(cpd);
/* check for error */
if (err) {
- usb2_unref_device(&loc);
+ DPRINTFN(2, "cannot create fifo\n");
+ usb2_unref_device(cpd);
+ free(cpd, M_USBDEV);
return (err);
}
if (fflags & FREAD) {
- err = usb2_fifo_open(loc.rxfifo, fp, td, fflags);
+ err = usb2_fifo_open(cpd->rxfifo, fflags);
if (err) {
DPRINTFN(2, "read open failed\n");
- usb2_unref_device(&loc);
+ usb2_unref_device(cpd);
+ free(cpd, M_USBDEV);
return (err);
}
}
if (fflags & FWRITE) {
- err = usb2_fifo_open(loc.txfifo, fp, td, fflags);
+ err = usb2_fifo_open(cpd->txfifo, fflags);
if (err) {
DPRINTFN(2, "write open failed\n");
if (fflags & FREAD) {
- usb2_fifo_close(loc.rxfifo, td,
- fflags);
+ usb2_fifo_close(cpd->rxfifo, fflags);
}
- usb2_unref_device(&loc);
+ usb2_unref_device(cpd);
+ free(cpd, M_USBDEV);
return (err);
}
}
- /*
- * Take over the file so that we get all the callbacks
- * directly and don't have to create another device:
- */
- finit(fp, fp->f_flag, DTYPE_VNODE,
- ((uint8_t *)0) + devloc, &usb2_ops_f);
+ usb2_unref_device(cpd);
+ devfs_set_cdevpriv(cpd, usb2_close);
- usb2_unref_device(&loc);
-
- DPRINTFN(2, "error=%d\n", err);
-
- return (err);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_close - cdev callback
- *------------------------------------------------------------------------*/
-static int
-usb2_close(struct cdev *dev, int flag, int mode, struct thread *p)
-{
- DPRINTF("\n");
- return (0); /* nothing to do */
+ return (0);
}
/*------------------------------------------------------------------------*
* usb2_close - cdev callback
*------------------------------------------------------------------------*/
-static int
-usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
- int fflag, struct thread *td)
+static void
+usb2_close(void *arg)
{
- union {
- struct usb2_read_dir *urd;
- struct usb2_dev_perm *udp;
- void *data;
- } u;
+ struct usb2_cdev_privdata *cpd = arg;
+ struct usb2_device *udev;
int err;
- u.data = data;
-
- err = 0;
- switch (cmd) {
- case USB_READ_DIR:
- err = usb2_read_symlink(u.urd->urd_data,
- u.urd->urd_startentry, u.urd->urd_maxlen);
- break;
- case USB_SET_IFACE_PERM:
- err = usb2_set_perm(u.udp, 3);
- break;
- case USB_SET_DEVICE_PERM:
- err = usb2_set_perm(u.udp, 2);
- break;
- case USB_SET_BUS_PERM:
- err = usb2_set_perm(u.udp, 1);
- break;
- case USB_SET_ROOT_PERM:
- err = usb2_set_perm(u.udp, 0);
- break;
- case USB_GET_IFACE_PERM:
- err = usb2_get_perm(u.udp, 3);
- break;
- case USB_GET_DEVICE_PERM:
- err = usb2_get_perm(u.udp, 2);
- break;
- case USB_GET_BUS_PERM:
- err = usb2_get_perm(u.udp, 1);
- break;
- case USB_GET_ROOT_PERM:
- err = usb2_get_perm(u.udp, 0);
- break;
- case USB_DEV_QUIRK_GET:
- case USB_QUIRK_NAME_GET:
- case USB_DEV_QUIRK_ADD:
- case USB_DEV_QUIRK_REMOVE:
- err = usb2_quirk_ioctl_p(cmd, data, fflag, td);
- break;
- case USB_GET_TEMPLATE:
- *(int *)data = usb2_template;
- break;
- case USB_SET_TEMPLATE:
- err = priv_check(curthread, PRIV_ROOT);
- if (err)
- break;
- usb2_template = *(int *)data;
- break;
- default:
- err = ENOTTY;
- break;
- }
- return (err);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_clone - cdev callback
- *
- * This function is the kernel clone callback for "/dev/usbX.Y".
- *
- * NOTE: This function assumes that the clone and device open
- * operation is atomic.
- *------------------------------------------------------------------------*/
-static void
-usb2_clone(void *arg, USB_UCRED char *name, int namelen, struct cdev **dev)
-{
- enum {
- USB_DNAME_LEN = sizeof(USB_DEVICE_NAME) - 1,
- USB_GNAME_LEN = sizeof(USB_GENERIC_NAME) - 1,
- };
+ DPRINTFN(2, "usb2_close, cpd=%p\n", cpd);
- if (*dev) {
- /* someone else has created a device */
+ err = usb2_ref_device(cpd, 1);
+ if (err) {
+ free(cpd, M_USBDEV);
return;
}
- /* reset device location */
- usb2_last_devloc = (uint32_t)(0 - 1);
- /*
- * Check if we are matching "usb", "ugen" or an internal
- * symbolic link:
- */
- if ((namelen >= USB_DNAME_LEN) &&
- (bcmp(name, USB_DEVICE_NAME, USB_DNAME_LEN) == 0)) {
- if (namelen == USB_DNAME_LEN) {
- /* USB management device location */
- usb2_last_devloc = (uint32_t)(0 - 2);
- } else {
- /* USB endpoint */
- usb2_last_devloc =
- usb2_path_convert(name + USB_DNAME_LEN);
- }
- } else if ((namelen >= USB_GNAME_LEN) &&
- (bcmp(name, USB_GENERIC_NAME, USB_GNAME_LEN) == 0)) {
- if (namelen == USB_GNAME_LEN) {
- /* USB management device location */
- usb2_last_devloc = (uint32_t)(0 - 2);
- } else {
- /* USB endpoint */
- usb2_last_devloc =
- usb2_path_convert(name + USB_GNAME_LEN);
- }
- }
- if (usb2_last_devloc == (uint32_t)(0 - 1)) {
- /* Search for symbolic link */
- usb2_last_devloc =
- usb2_lookup_symlink(name, namelen);
+ udev = cpd->udev;
+ if (cpd->fflags & FREAD) {
+ usb2_fifo_close(cpd->rxfifo, cpd->fflags);
+ /* clear read bitmask */
+ udev->ep_rd_opened &= ~(1 << cpd->ep_addr);
}
- if (usb2_last_devloc == (uint32_t)(0 - 1)) {
- /* invalid location */
- return;
+ if (cpd->fflags & FWRITE) {
+ usb2_fifo_close(cpd->txfifo, cpd->fflags);
+ /* clear write bitmask */
+ udev->ep_wr_opened &= ~(1 << cpd->ep_addr);
}
- dev_ref(usb2_dev);
- *dev = usb2_dev;
+
+ usb2_unref_device(cpd);
+ free(cpd, M_USBDEV);
+ return;
}
static void
@@ -1472,24 +974,14 @@ static void
usb2_dev_init_post(void *arg)
{
/*
- * Create a dummy device so that we are visible. This device
- * should never be opened. Therefore a space character is
- * appended after the USB device name.
- *
- * NOTE: The permissions of this device is 0666, because we
- * check the permissions again in the open routine against the
- * real USB permissions which are not 0666. Else USB access
- * will be limited to one user and one group.
+ * Create /dev/usb - this is needed for usbconfig(8), which
+ * needs a well-known device name to access.
*/
- usb2_dev = make_dev(&usb2_devsw, 0, UID_ROOT, GID_OPERATOR,
- 0666, USB_DEVICE_NAME " ");
+ usb2_dev = make_dev(&usb2_static_devsw, 0, UID_ROOT, GID_OPERATOR,
+ 0644, USB_DEVICE_NAME);
if (usb2_dev == NULL) {
DPRINTFN(0, "Could not create usb bus device!\n");
}
- usb2_clone_tag = EVENTHANDLER_REGISTER(dev_clone, usb2_clone_ptr, NULL, 1000);
- if (usb2_clone_tag == NULL) {
- DPRINTFN(0, "Registering clone handler failed!\n");
- }
}
SYSINIT(usb2_dev_init_post, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, usb2_dev_init_post, NULL);
@@ -1497,13 +989,10 @@ SYSINIT(usb2_dev_init_post, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, usb2_dev_init
static void
usb2_dev_uninit(void *arg)
{
- if (usb2_clone_tag) {
- EVENTHANDLER_DEREGISTER(dev_clone, usb2_clone_tag);
- usb2_clone_tag = NULL;
- }
- if (usb2_dev) {
+ if (usb2_dev != NULL) {
destroy_dev(usb2_dev);
usb2_dev = NULL;
+
}
mtx_destroy(&usb2_ref_lock);
sx_destroy(&usb2_sym_lock);
@@ -1512,43 +1001,6 @@ usb2_dev_uninit(void *arg)
SYSUNINIT(usb2_dev_uninit, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, usb2_dev_uninit, NULL);
static int
-usb2_close_f(struct file *fp, struct thread *td)
-{
- struct usb2_location loc;
- int fflags;
- int err;
-
- fflags = fp->f_flag;
-
- DPRINTFN(2, "fflags=%u\n", fflags);
-
- err = usb2_ref_device(fp, &loc, 0 /* need uref */ );;
-
- /* restore some file variables */
- fp->f_ops = usb2_old_f_ops;
- fp->f_data = usb2_old_f_data;
-
- /* check for error */
- if (err) {
- DPRINTFN(2, "could not ref\n");
- goto done;
- }
- if (fflags & FREAD) {
- usb2_fifo_close(loc.rxfifo, td, fflags);
- }
- if (fflags & FWRITE) {
- usb2_fifo_close(loc.txfifo, td, fflags);
- }
- usb2_unref_device(&loc);
-
-done:
- /* call old close method */
- USB_VNOPS_FO_CLOSE(fp, td, &err);
-
- return (err);
-}
-
-static int
usb2_ioctl_f_sub(struct usb2_fifo *f, u_long cmd, void *addr,
struct thread *td)
{
@@ -1592,20 +1044,26 @@ usb2_ioctl_f_sub(struct usb2_fifo *f, u_long cmd, void *addr,
return (error);
}
+/*------------------------------------------------------------------------*
+ * usb2_ioctl - cdev callback
+ *------------------------------------------------------------------------*/
static int
-usb2_ioctl_f(struct file *fp, u_long cmd, void *addr,
- struct ucred *cred, struct thread *td)
+usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* td)
{
- struct usb2_location loc;
+ struct usb2_cdev_privdata* cpd;
struct usb2_fifo *f;
int fflags;
int err;
- err = usb2_ref_device(fp, &loc, 1 /* no uref */ );;
+ err = devfs_get_cdevpriv((void **)&cpd);
+ if (err != 0)
+ return (err);
+
+ err = usb2_ref_device(cpd, 1);
if (err) {
return (ENXIO);
}
- fflags = fp->f_flag;
+ fflags = cpd->fflags;
DPRINTFN(2, "fflags=%u, cmd=0x%lx\n", fflags, cmd);
@@ -1613,65 +1071,62 @@ usb2_ioctl_f(struct file *fp, u_long cmd, void *addr,
err = ENOIOCTL; /* set default value */
if (fflags & FWRITE) {
- f = loc.txfifo;
+ f = cpd->txfifo;
err = usb2_ioctl_f_sub(f, cmd, addr, td);
}
if (fflags & FREAD) {
- f = loc.rxfifo;
+ f = cpd->rxfifo;
err = usb2_ioctl_f_sub(f, cmd, addr, td);
}
+ KASSERT(f != NULL, ("fifo not found"));
if (err == ENOIOCTL) {
- err = (f->methods->f_ioctl) (f, cmd, addr, fflags, td);
+ err = (f->methods->f_ioctl) (f, cmd, addr, fflags);
if (err == ENOIOCTL) {
- if (usb2_uref_location(&loc)) {
+ if (usb2_uref_location(cpd)) {
err = ENXIO;
goto done;
}
- err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags, td);
+ err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags);
}
}
if (err == ENOIOCTL) {
err = ENOTTY;
}
done:
- usb2_unref_device(&loc);
+ usb2_unref_device(cpd);
return (err);
}
/* ARGSUSED */
static int
-usb2_kqfilter_f(struct file *fp, struct knote *kn)
-{
- return (ENXIO);
-}
-
-/* ARGSUSED */
-static int
-usb2_poll_f(struct file *fp, int events,
- struct ucred *cred, struct thread *td)
+usb2_poll(struct cdev* dev, int events, struct thread* td)
{
- struct usb2_location loc;
+ struct usb2_cdev_privdata* cpd;
struct usb2_fifo *f;
struct usb2_mbuf *m;
int fflags;
- int revents;
+ int err, revents;
+
+ err = devfs_get_cdevpriv((void **)&cpd);
+ if (err != 0)
+ return (err);
- revents = usb2_ref_device(fp, &loc, 1 /* no uref */ );;
- if (revents) {
+ err = usb2_ref_device(cpd, 0 /* no uref */ );
+ if (err)
return (POLLHUP);
- }
- fflags = fp->f_flag;
- /* Figure out who needs service */
+ fflags = cpd->fflags;
+ /* Figure out who needs service */
+ revents = 0;
if ((events & (POLLOUT | POLLWRNORM)) &&
(fflags & FWRITE)) {
- f = loc.txfifo;
+ f = cpd->txfifo;
mtx_lock(f->priv_mtx);
- if (!loc.is_usbfs) {
+ if (!cpd->is_usbfs) {
if (f->flag_iserror) {
/* we got an error */
m = (void *)1;
@@ -1706,11 +1161,11 @@ usb2_poll_f(struct file *fp, int events,
if ((events & (POLLIN | POLLRDNORM)) &&
(fflags & FREAD)) {
- f = loc.rxfifo;
+ f = cpd->rxfifo;
mtx_lock(f->priv_mtx);
- if (!loc.is_usbfs) {
+ if (!cpd->is_usbfs) {
if (f->flag_iserror) {
/* we have and error */
m = (void *)1;
@@ -1739,7 +1194,7 @@ usb2_poll_f(struct file *fp, int events,
f->flag_isselect = 1;
selrecord(td, &f->selinfo);
- if (!loc.is_usbfs) {
+ if (!cpd->is_usbfs) {
/* start reading data */
(f->methods->f_start_read) (f);
}
@@ -1747,16 +1202,14 @@ usb2_poll_f(struct file *fp, int events,
mtx_unlock(f->priv_mtx);
}
- usb2_unref_device(&loc);
+ usb2_unref_device(cpd);
return (revents);
}
-/* ARGSUSED */
static int
-usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred,
- int flags, struct thread *td)
+usb2_read(struct cdev *dev, struct uio *uio, int ioflag)
{
- struct usb2_location loc;
+ struct usb2_cdev_privdata* cpd;
struct usb2_fifo *f;
struct usb2_mbuf *m;
int fflags;
@@ -1765,25 +1218,23 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred,
int err;
uint8_t tr_data = 0;
- DPRINTFN(2, "\n");
-
- fflags = fp->f_flag & (O_NONBLOCK | O_DIRECT | FREAD | FWRITE);
- if (fflags & O_DIRECT)
- fflags |= IO_DIRECT;
+ err = devfs_get_cdevpriv((void **)&cpd);
+ if (err != 0)
+ return (err);
- err = usb2_ref_device(fp, &loc, 1 /* no uref */ );
+ err = usb2_ref_device(cpd, 0 /* no uref */ );
if (err) {
return (ENXIO);
}
- f = loc.rxfifo;
+ fflags = cpd->fflags;
+
+ f = cpd->rxfifo;
if (f == NULL) {
/* should not happen */
return (EPERM);
}
- resid = uio->uio_resid;
- if ((flags & FOF_OFFSET) == 0)
- uio->uio_offset = fp->f_offset;
+ resid = uio->uio_resid;
mtx_lock(f->priv_mtx);
@@ -1793,7 +1244,7 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred,
goto done;
}
/* check if USB-FS interface is active */
- if (loc.is_usbfs) {
+ if (cpd->is_usbfs) {
/*
* The queue is used for events that should be
* retrieved using the "USB_FS_COMPLETE" ioctl.
@@ -1811,7 +1262,7 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred,
(f->methods->f_start_read) (f);
- if (fflags & O_NONBLOCK) {
+ if (fflags & IO_NDELAY) {
if (tr_data) {
/* return length before error */
break;
@@ -1871,35 +1322,15 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred,
done:
mtx_unlock(f->priv_mtx);
- usb2_unref_device(&loc);
+ usb2_unref_device(cpd);
- if ((flags & FOF_OFFSET) == 0)
- fp->f_offset = uio->uio_offset;
- fp->f_nextoff = uio->uio_offset;
return (err);
}
static int
-usb2_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td)
+usb2_write(struct cdev *dev, struct uio *uio, int ioflag)
{
- return (USB_VNOPS_FO_STAT(fp, sb, cred, td));
-}
-
-#if __FreeBSD_version > 800009
-static int
-usb2_truncate_f(struct file *fp, off_t length, struct ucred *cred, struct thread *td)
-{
- return (USB_VNOPS_FO_TRUNCATE(fp, length, cred, td));
-}
-
-#endif
-
-/* ARGSUSED */
-static int
-usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred,
- int flags, struct thread *td)
-{
- struct usb2_location loc;
+ struct usb2_cdev_privdata* cpd;
struct usb2_fifo *f;
struct usb2_mbuf *m;
int fflags;
@@ -1910,26 +1341,24 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred,
DPRINTFN(2, "\n");
- fflags = fp->f_flag & (O_NONBLOCK | O_DIRECT |
- FREAD | FWRITE | O_FSYNC);
- if (fflags & O_DIRECT)
- fflags |= IO_DIRECT;
+ err = devfs_get_cdevpriv((void **)&cpd);
+ if (err != 0)
+ return (err);
- err = usb2_ref_device(fp, &loc, 1 /* no uref */ );
+ err = usb2_ref_device(cpd, 0 /* no uref */ );
if (err) {
return (ENXIO);
}
- f = loc.txfifo;
+ fflags = cpd->fflags;
+
+ f = cpd->txfifo;
if (f == NULL) {
/* should not happen */
- usb2_unref_device(&loc);
+ usb2_unref_device(cpd);
return (EPERM);
}
resid = uio->uio_resid;
- if ((flags & FOF_OFFSET) == 0)
- uio->uio_offset = fp->f_offset;
-
mtx_lock(f->priv_mtx);
/* check for permanent write error */
@@ -1938,7 +1367,7 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred,
goto done;
}
/* check if USB-FS interface is active */
- if (loc.is_usbfs) {
+ if (cpd->is_usbfs) {
/*
* The queue is used for events that should be
* retrieved using the "USB_FS_COMPLETE" ioctl.
@@ -1956,7 +1385,7 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred,
if (m == NULL) {
- if (fflags & O_NONBLOCK) {
+ if (fflags & IO_NDELAY) {
if (tr_data) {
/* return length before error */
break;
@@ -2006,12 +1435,43 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred,
done:
mtx_unlock(f->priv_mtx);
- usb2_unref_device(&loc);
+ usb2_unref_device(cpd);
- if ((flags & FOF_OFFSET) == 0)
- fp->f_offset = uio->uio_offset;
- fp->f_nextoff = uio->uio_offset;
+ return (err);
+}
+
+int
+usb2_static_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ union {
+ struct usb2_read_dir *urd;
+ void* data;
+ } u;
+ int err = ENOTTY;
+ u.data = data;
+ switch (cmd) {
+ case USB_READ_DIR:
+ err = usb2_read_symlink(u.urd->urd_data,
+ u.urd->urd_startentry, u.urd->urd_maxlen);
+ break;
+ case USB_DEV_QUIRK_GET:
+ case USB_QUIRK_NAME_GET:
+ case USB_DEV_QUIRK_ADD:
+ case USB_DEV_QUIRK_REMOVE:
+ err = usb2_quirk_ioctl_p(cmd, data, fflag, td);
+ break;
+ case USB_GET_TEMPLATE:
+ *(int *)data = usb2_template;
+ break;
+ case USB_SET_TEMPLATE:
+ err = priv_check(curthread, PRIV_ROOT);
+ if (err)
+ break;
+ usb2_template = *(int *)data;
+ break;
+ }
return (err);
}
@@ -2081,53 +1541,20 @@ usb2_fifo_wakeup(struct usb2_fifo *f)
}
}
-/*------------------------------------------------------------------------*
- * usb2_fifo_opened
- *
- * Returns:
- * 0: FIFO not opened.
- * Else: FIFO is opened.
- *------------------------------------------------------------------------*/
-uint8_t
-usb2_fifo_opened(struct usb2_fifo *f)
-{
- uint8_t temp;
- uint8_t do_unlock;
-
- if (f == NULL) {
- return (0); /* be NULL safe */
- }
- if (mtx_owned(f->priv_mtx)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- mtx_lock(f->priv_mtx);
- }
- temp = f->curr_file ? 1 : 0;
- if (do_unlock) {
- mtx_unlock(f->priv_mtx);
- }
- return (temp);
-}
-
-
static int
-usb2_fifo_dummy_open(struct usb2_fifo *fifo,
- int fflags, struct thread *td)
+usb2_fifo_dummy_open(struct usb2_fifo *fifo, int fflags)
{
return (0);
}
static void
-usb2_fifo_dummy_close(struct usb2_fifo *fifo,
- int fflags, struct thread *td)
+usb2_fifo_dummy_close(struct usb2_fifo *fifo, int fflags)
{
return;
}
static int
-usb2_fifo_dummy_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr,
- int fflags, struct thread *td)
+usb2_fifo_dummy_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags)
{
return (ENOIOCTL);
}
@@ -2181,13 +1608,13 @@ int
usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
struct mtx *priv_mtx, struct usb2_fifo_methods *pm,
struct usb2_fifo_sc *f_sc, uint16_t unit, uint16_t subunit,
- uint8_t iface_index)
+ uint8_t iface_index, uid_t uid, gid_t gid, int mode)
{
struct usb2_fifo *f_tx;
struct usb2_fifo *f_rx;
- char buf[32];
- char src[32];
+ char devname[32];
uint8_t n;
+ struct usb2_fs_privdata* pd;
f_sc->fp[USB_FIFO_TX] = NULL;
f_sc->fp[USB_FIFO_RX] = NULL;
@@ -2253,28 +1680,20 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
udev->fifo[f_rx->fifo_index] = f_rx;
mtx_unlock(&usb2_ref_lock);
- if (snprintf(src, sizeof(src),
- USB_DEVICE_NAME "%u.%u.%u.%u",
- device_get_unit(udev->bus->bdev),
- udev->device_index,
- iface_index,
- f_tx->dev_ep_index)) {
- /* ignore */
- }
for (n = 0; n != 4; n++) {
if (pm->basename[n] == NULL) {
continue;
}
if (subunit == 0xFFFF) {
- if (snprintf(buf, sizeof(buf),
+ if (snprintf(devname, sizeof(devname),
"%s%u%s", pm->basename[n],
unit, pm->postfix[n] ?
pm->postfix[n] : "")) {
/* ignore */
}
} else {
- if (snprintf(buf, sizeof(buf),
+ if (snprintf(devname, sizeof(devname),
"%s%u.%u%s", pm->basename[n],
unit, subunit, pm->postfix[n] ?
pm->postfix[n] : "")) {
@@ -2287,12 +1706,28 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
*/
if (n & 1) {
f_rx->symlink[n / 2] =
- usb2_alloc_symlink(src, "%s", buf);
+ usb2_alloc_symlink(devname);
} else {
f_tx->symlink[n / 2] =
- usb2_alloc_symlink(src, "%s", buf);
+ usb2_alloc_symlink(devname);
}
- printf("Symlink: %s -> %s\n", buf, src);
+
+ /*
+ * Initialize device private data - this is used to find the
+ * actual USB device itself.
+ */
+ pd = malloc(sizeof(struct usb2_fs_privdata), M_USBDEV, M_WAITOK | M_ZERO);
+ pd->bus_index = device_get_unit(udev->bus->bdev);
+ pd->dev_index = udev->device_index;
+ pd->iface_index = iface_index;
+ pd->ep_addr = -1; /* not an endpoint */
+ pd->fifo_index = f_tx->fifo_index;
+ pd->mode = FREAD|FWRITE;
+
+ /* Now, create the device itself */
+ f_sc->dev = make_dev(&usb2_devsw, 0, uid, gid, mode,
+ devname);
+ f_sc->dev->si_drv1 = pd;
}
DPRINTFN(2, "attached %p/%p\n", f_tx, f_rx);
@@ -2345,6 +1780,12 @@ usb2_fifo_free_buffer(struct usb2_fifo *f)
bzero(&f->used_q, sizeof(f->used_q));
}
+static void
+usb2_fifo_cleanup(void* ptr)
+{
+ free(ptr, M_USBDEV);
+}
+
void
usb2_fifo_detach(struct usb2_fifo_sc *f_sc)
{
@@ -2357,6 +1798,10 @@ usb2_fifo_detach(struct usb2_fifo_sc *f_sc)
f_sc->fp[USB_FIFO_TX] = NULL;
f_sc->fp[USB_FIFO_RX] = NULL;
+ if (f_sc->dev != NULL) {
+ destroy_dev_sched_cb(f_sc->dev, usb2_fifo_cleanup, f_sc->dev->si_drv1);
+ }
+
DPRINTFN(2, "detached %p\n", f_sc);
}
@@ -2642,24 +2087,20 @@ usb2_fifo_get_data_error(struct usb2_fifo *f)
* Else: Pointer to symlink entry
*------------------------------------------------------------------------*/
struct usb2_symlink *
-usb2_alloc_symlink(const char *target, const char *fmt,...)
+usb2_alloc_symlink(const char *target)
{
struct usb2_symlink *ps;
- va_list ap;
ps = malloc(sizeof(*ps), M_USBDEV, M_WAITOK);
if (ps == NULL) {
return (ps);
}
+ /* XXX no longer needed */
+ strlcpy(ps->src_path, target, sizeof(ps->src_path));
+ ps->src_len = strlen(ps->src_path);
strlcpy(ps->dst_path, target, sizeof(ps->dst_path));
ps->dst_len = strlen(ps->dst_path);
- va_start(ap, fmt);
- vsnrprintf(ps->src_path,
- sizeof(ps->src_path), 32, fmt, ap);
- va_end(ap);
- ps->src_len = strlen(ps->src_path);
-
sx_xlock(&usb2_sym_lock);
TAILQ_INSERT_TAIL(&usb2_sym_head, ps, sym_entry);
sx_unlock(&usb2_sym_lock);
@@ -2683,46 +2124,6 @@ usb2_free_symlink(struct usb2_symlink *ps)
}
/*------------------------------------------------------------------------*
- * usb2_lookup_symlink
- *
- * Return value:
- * Numerical device location
- *------------------------------------------------------------------------*/
-uint32_t
-usb2_lookup_symlink(const char *src_ptr, uint8_t src_len)
-{
- enum {
- USB_DNAME_LEN = sizeof(USB_DEVICE_NAME) - 1,
- };
- struct usb2_symlink *ps;
- uint32_t temp;
-
- sx_xlock(&usb2_sym_lock);
-
- TAILQ_FOREACH(ps, &usb2_sym_head, sym_entry) {
-
- if (src_len != ps->src_len)
- continue;
-
- if (memcmp(ps->src_path, src_ptr, src_len))
- continue;
-
- if (USB_DNAME_LEN > ps->dst_len)
- continue;
-
- if (memcmp(ps->dst_path, USB_DEVICE_NAME, USB_DNAME_LEN))
- continue;
-
- temp = usb2_path_convert(ps->dst_path + USB_DNAME_LEN);
- sx_unlock(&usb2_sym_lock);
-
- return (temp);
- }
- sx_unlock(&usb2_sym_lock);
- return (0 - 1);
-}
-
-/*------------------------------------------------------------------------*
* usb2_read_symlink
*
* Return value:
diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h
index 6203572cfb32..ee00852a03b4 100644
--- a/sys/dev/usb/usb_dev.h
+++ b/sys/dev/usb/usb_dev.h
@@ -41,9 +41,9 @@
struct usb2_fifo;
struct usb2_mbuf;
-typedef int (usb2_fifo_open_t)(struct usb2_fifo *fifo, int fflags, struct thread *td);
-typedef void (usb2_fifo_close_t)(struct usb2_fifo *fifo, int fflags, struct thread *td);
-typedef int (usb2_fifo_ioctl_t)(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags, struct thread *td);
+typedef int (usb2_fifo_open_t)(struct usb2_fifo *fifo, int fflags);
+typedef void (usb2_fifo_close_t)(struct usb2_fifo *fifo, int fflags);
+typedef int (usb2_fifo_ioctl_t)(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags);
typedef void (usb2_fifo_cmd_t)(struct usb2_fifo *fifo);
typedef void (usb2_fifo_filter_t)(struct usb2_fifo *fifo, struct usb2_mbuf *m);
@@ -82,6 +82,39 @@ struct usb2_fifo_methods {
};
/*
+ * Private per-device information.
+ */
+struct usb2_cdev_privdata {
+ struct usb2_bus *bus;
+ struct usb2_device *udev;
+ struct usb2_interface *iface;
+ struct usb2_fifo *rxfifo;
+ struct usb2_fifo *txfifo;
+ int bus_index; /* bus index */
+ int dev_index; /* device index */
+ int iface_index; /* interface index */
+ int ep_addr; /* endpoint address */
+ uint8_t fifo_index; /* FIFO index */
+ uint8_t is_read; /* location has read access */
+ uint8_t is_write; /* location has write access */
+ uint8_t is_uref; /* USB refcount decr. needed */
+ uint8_t is_usbfs; /* USB-FS is active */
+ int fflags;
+};
+
+struct usb2_fs_privdata {
+ int bus_index;
+ int dev_index;
+ int iface_index;
+ int ep_addr;
+ int mode;
+ int fifo_index;
+ struct cdev *cdev;
+
+ LIST_ENTRY(usb2_fs_privdata) pd_next;
+};
+
+/*
* Most of the fields in the "usb2_fifo" structure are used by the
* generic USB access layer.
*/
@@ -99,7 +132,7 @@ struct usb2_fifo {
struct usb2_xfer *xfer[2];
struct usb2_xfer **fs_xfer;
struct mtx *priv_mtx; /* client data */
- struct file *curr_file; /* set if FIFO is opened by a FILE */
+ int opened; /* set if FIFO is opened by a FILE */
void *priv_sc0; /* client data */
void *priv_sc1; /* client data */
void *queue_data;
@@ -126,8 +159,11 @@ struct usb2_fifo {
struct usb2_fifo_sc {
struct usb2_fifo *fp[2];
+ struct cdev* dev;
};
+extern struct cdevsw usb2_devsw;
+
int usb2_fifo_wait(struct usb2_fifo *fifo);
void usb2_fifo_signal(struct usb2_fifo *fifo);
int usb2_fifo_alloc_buffer(struct usb2_fifo *f, uint32_t bufsize,
@@ -136,7 +172,7 @@ void usb2_fifo_free_buffer(struct usb2_fifo *f);
int usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
struct mtx *priv_mtx, struct usb2_fifo_methods *pm,
struct usb2_fifo_sc *f_sc, uint16_t unit, uint16_t subunit,
- uint8_t iface_index);
+ uint8_t iface_index, uid_t uid, gid_t gid, int mode);
void usb2_fifo_detach(struct usb2_fifo_sc *f_sc);
uint32_t usb2_fifo_put_bytes_max(struct usb2_fifo *fifo);
void usb2_fifo_put_data(struct usb2_fifo *fifo, struct usb2_page_cache *pc,
@@ -155,13 +191,9 @@ void usb2_fifo_get_data_error(struct usb2_fifo *fifo);
uint8_t usb2_fifo_opened(struct usb2_fifo *fifo);
void usb2_fifo_free(struct usb2_fifo *f);
void usb2_fifo_reset(struct usb2_fifo *f);
-int usb2_check_thread_perm(struct usb2_device *udev, struct thread *td,
- int fflags, uint8_t iface_index, uint8_t ep_index);
void usb2_fifo_wakeup(struct usb2_fifo *f);
-struct usb2_symlink *usb2_alloc_symlink(const char *target,
- const char *fmt,...);
+struct usb2_symlink *usb2_alloc_symlink(const char *target);
void usb2_free_symlink(struct usb2_symlink *ps);
-uint32_t usb2_lookup_symlink(const char *src_ptr, uint8_t src_len);
int usb2_read_symlink(uint8_t *user_ptr, uint32_t startentry,
uint32_t user_len);
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 7746c010d0a8..9e11e8ea906d 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -74,6 +74,10 @@ static usb2_error_t usb2_fill_iface_data(struct usb2_device *, uint8_t,
uint8_t);
static void usb2_notify_addq(const char *type, struct usb2_device *);
static void usb2_fifo_free_wrap(struct usb2_device *, uint8_t, uint8_t);
+static struct cdev *usb2_make_dev(struct usb2_device *, int, int, int);
+static void usb2_cdev_create(struct usb2_device *);
+static void usb2_cdev_free(struct usb2_device *);
+static void usb2_cdev_cleanup(void *);
/* This variable is global to allow easy access to it: */
@@ -274,6 +278,7 @@ static void
usb2_fill_pipe_data(struct usb2_device *udev, uint8_t iface_index,
struct usb2_endpoint_descriptor *edesc, struct usb2_pipe *pipe)
{
+
bzero(pipe, sizeof(*pipe));
(udev->bus->methods->pipe_init) (udev, edesc, pipe);
@@ -416,6 +421,7 @@ usb2_fill_iface_data(struct usb2_device *udev,
iface->idesc = id;
iface->alt_index = alt_index;
iface->parent_iface_index = USB_IFACE_INDEX_ANY;
+ iface->ep_in_mask = iface->ep_out_mask = 0;
nendpt = id->bNumEndpoints;
DPRINTFN(5, "found idesc nendpt=%d\n", nendpt);
@@ -439,6 +445,14 @@ usb2_fill_iface_data(struct usb2_device *udev,
found:
ed = (void *)desc;
+ /* Fill in the endpoint bitmasks */
+ if (ed->bEndpointAddress & UE_DIR_IN)
+ iface->ep_in_mask |=
+ 1 << UE_GET_ADDR(ed->bEndpointAddress);
+ else
+ iface->ep_out_mask |=
+ 1 << UE_GET_ADDR(ed->bEndpointAddress);
+
/* find a free pipe */
while (pipe != pipe_end) {
if (pipe->edesc == NULL) {
@@ -488,7 +502,6 @@ usb2_free_iface_data(struct usb2_device *udev)
iface->idesc = NULL;
iface->alt_index = 0;
iface->parent_iface_index = USB_IFACE_INDEX_ANY;
- iface->perm.mode = 0; /* disable permissions */
iface++;
}
@@ -543,6 +556,7 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
usb2_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, 0);
/* free all configuration data structures */
+ usb2_cdev_free(udev);
usb2_free_iface_data(udev);
if (index == USB_UNCONFIG_INDEX) {
@@ -652,10 +666,13 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
goto done;
}
}
+ /* create device nodes for each endpoint */
+ usb2_cdev_create(udev);
done:
DPRINTF("error=%s\n", usb2_errstr(err));
if (err) {
+ usb2_cdev_free(udev);
usb2_free_iface_data(udev);
}
if (do_unlock) {
@@ -713,6 +730,7 @@ usb2_set_alt_interface_index(struct usb2_device *udev,
* Free all generic FIFOs for this interface, except control
* endpoint FIFOs:
*/
+ usb2_cdev_free(udev);
usb2_fifo_free_wrap(udev, iface_index, 0);
err = usb2_fill_iface_data(udev, iface_index, alt_index);
@@ -722,6 +740,9 @@ usb2_set_alt_interface_index(struct usb2_device *udev,
err = usb2_req_set_alt_interface_no(udev, NULL, iface_index,
iface->idesc->bAlternateSetting);
+ /* create device nodes for each endpoint */
+ usb2_cdev_create(udev);
+
done:
if (do_unlock) {
sx_unlock(udev->default_sx + 1);
@@ -1354,6 +1375,8 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
usb2_cv_init(udev->default_cv, "WCTRL");
usb2_cv_init(udev->default_cv + 1, "UGONE");
+ LIST_INIT(&udev->pd_list);
+
/* initialise our mutex */
mtx_init(udev->default_mtx, "USB device mutex", NULL, MTX_DEF);
@@ -1423,6 +1446,14 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
/* set device index */
udev->device_index = device_index;
+ /* Create the control endpoint device */
+ udev->default_dev = usb2_make_dev(udev, 0 , 0, FREAD|FWRITE);
+ /* Create a link from /dev/ugenX.X to the default endpoint */
+ snprintf(udev->ugen_name, sizeof(udev->ugen_name),
+ USB_GENERIC_NAME "%u.%u", device_get_unit(bus->bdev),
+ device_index);
+ make_dev_alias(udev->default_dev, udev->ugen_name);
+
if (udev->flags.usb2_mode == USB_MODE_HOST) {
err = usb2_req_set_address(udev, NULL, device_index);
@@ -1673,21 +1704,9 @@ repeat_set_config:
usb2_bus_port_set_device(bus, parent_hub ?
parent_hub->hub->ports + port_index : NULL, udev, device_index);
- /* make a symlink for UGEN */
- if (snprintf((char *)scratch_ptr, scratch_size,
- USB_DEVICE_NAME "%u.%u.0.0",
- device_get_unit(udev->bus->bdev),
- udev->device_index)) {
- /* ignore */
- }
- udev->ugen_symlink =
- usb2_alloc_symlink((char *)scratch_ptr, "ugen%u.%u",
- device_get_unit(udev->bus->bdev),
- udev->device_index);
-
- printf("ugen%u.%u: <%s> at %s\n",
- device_get_unit(udev->bus->bdev),
- udev->device_index, udev->manufacturer,
+ /* Link and announce the ugen device name */
+ udev->ugen_symlink = usb2_alloc_symlink(udev->ugen_name);
+ printf("%s: <%s> at %s\n", udev->ugen_name, udev->manufacturer,
device_get_nameunit(udev->bus->bdev));
usb2_notify_addq("+", udev);
@@ -1700,6 +1719,100 @@ done:
return (udev);
}
+static struct cdev *
+usb2_make_dev(struct usb2_device *udev, int iface_index, int ep, int mode)
+{
+ struct usb2_fs_privdata* pd;
+ char devname[20];
+
+ /* Store information to locate ourselves again later */
+ pd = malloc(sizeof(struct usb2_fs_privdata), M_USBDEV,
+ M_WAITOK | M_ZERO);
+ pd->bus_index = device_get_unit(udev->bus->bdev);
+ pd->dev_index = udev->device_index;
+ pd->iface_index = iface_index;
+ pd->ep_addr = ep;
+ pd->mode = mode;
+
+ /* Now, create the device itself */
+ snprintf(devname, sizeof(devname), "%u.%u.%u.%u",
+ pd->bus_index, pd->dev_index,
+ pd->iface_index, pd->ep_addr);
+ pd->cdev = make_dev(&usb2_devsw, 0, UID_ROOT,
+ GID_OPERATOR, 0600, USB_DEVICE_DIR "/%s", devname);
+ pd->cdev->si_drv1 = pd;
+
+ return (pd->cdev);
+}
+
+static void
+usb2_cdev_create(struct usb2_device *udev)
+{
+ struct usb2_interface *iface;
+ struct usb2_fs_privdata* pd;
+ struct cdev *dev;
+ uint8_t niface;
+ int i, ep, mode, inmode, outmode;
+
+ KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("stale cdev entries"));
+
+ DPRINTFN(2, "Creating device nodes\n");
+
+ usb2_interface_count(udev, &niface);
+ if (niface == 0)
+ return; /* nothing to do */
+
+ if (usb2_get_mode(udev) == USB_MODE_DEVICE) {
+ inmode = FWRITE;
+ outmode = FREAD;
+ } else { /* USB_MODE_HOST */
+ inmode = FREAD;
+ outmode = FWRITE;
+ }
+
+ for (i = 0; i < niface; i++) {
+ iface = usb2_get_iface(udev, i);
+ if (iface == NULL)
+ break;
+
+ /* Create all available endpoints except EP0 */
+ for (ep = 1; ep < 16; ep++) {
+ mode = 0;
+ mode |= iface->ep_in_mask & (1 << ep) ? inmode : 0;
+ mode |= iface->ep_out_mask & (1 << ep) ? outmode : 0;
+ if (mode == 0)
+ continue; /* no IN or OUT endpoint */
+
+ dev = usb2_make_dev(udev, i , ep, mode);
+ pd = dev->si_drv1;
+ LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next);
+ }
+ }
+}
+
+static void
+usb2_cdev_free(struct usb2_device *udev)
+{
+ struct usb2_fs_privdata* pd;
+
+ DPRINTFN(2, "Freeing device nodes\n");
+
+ while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) {
+ KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt"));
+ KASSERT(pd->ep_addr > 0, ("freeing EP0"));
+
+ destroy_dev_sched_cb(pd->cdev, usb2_cdev_cleanup, pd);
+ pd->cdev = NULL;
+ LIST_REMOVE(pd, pd_next);
+ }
+}
+
+static void
+usb2_cdev_cleanup(void* arg)
+{
+ free(arg, M_USBDEV);
+}
+
/*------------------------------------------------------------------------*
* usb2_free_device
*
@@ -1708,26 +1821,16 @@ done:
void
usb2_free_device(struct usb2_device *udev)
{
- struct usb2_bus *bus;
+ struct usb2_bus *bus = udev->bus;;
- if (udev == NULL) {
- /* already freed */
- return;
- }
DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no);
usb2_notify_addq("-", udev);
- bus = udev->bus;
-
- printf("ugen%u.%u: <%s> at %s (disconnected)\n",
- device_get_unit(bus->bdev),
- udev->device_index, udev->manufacturer,
- device_get_nameunit(bus->bdev));
+ printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name,
+ udev->manufacturer, device_get_nameunit(bus->bdev));
- /*
- * Destroy UGEN symlink, if any
- */
+ /* Destroy UGEN symlink, if any */
if (udev->ugen_symlink) {
usb2_free_symlink(udev->ugen_symlink);
udev->ugen_symlink = NULL;
@@ -1759,7 +1862,10 @@ usb2_free_device(struct usb2_device *udev)
/*
* Free all interface related data and FIFOs, if any.
*/
+ usb2_cdev_free(udev);
usb2_free_iface_data(udev);
+ destroy_dev_sched_cb(udev->default_dev, usb2_cdev_cleanup,
+ udev->default_dev->si_drv1);
/* unsetup any leftover default USB transfers */
usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX);
@@ -1783,6 +1889,7 @@ usb2_free_device(struct usb2_device *udev)
usb2_cv_destroy(udev->default_cv + 1);
mtx_destroy(udev->default_mtx);
+ KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("leaked cdev entries"));
/* free device */
free(udev, M_USB);
@@ -2112,7 +2219,7 @@ usb2_notify_addq(const char *type, struct usb2_device *udev)
if (udev->parent_hub) {
snprintf(data, 1024,
"%s"
- "ugen%u.%u "
+ "%s "
"vendor=0x%04x "
"product=0x%04x "
"devclass=0x%02x "
@@ -2121,22 +2228,20 @@ usb2_notify_addq(const char *type, struct usb2_device *udev)
"at "
"port=%u "
"on "
- "ugen%u.%u\n",
+ "%s\n",
type,
- device_get_unit(udev->bus->bdev),
- udev->device_index,
+ udev->ugen_name,
UGETW(udev->ddesc.idVendor),
UGETW(udev->ddesc.idProduct),
udev->ddesc.bDeviceClass,
udev->ddesc.bDeviceSubClass,
udev->serial,
udev->port_no,
- device_get_unit(udev->bus->bdev),
- udev->parent_hub->device_index);
+ udev->parent_hub->ugen_name);
} else {
snprintf(data, 1024,
"%s"
- "ugen%u.%u "
+ "%s "
"vendor=0x%04x "
"product=0x%04x "
"devclass=0x%02x "
@@ -2146,8 +2251,7 @@ usb2_notify_addq(const char *type, struct usb2_device *udev)
"on "
"%s\n",
type,
- device_get_unit(udev->bus->bdev),
- udev->device_index,
+ udev->ugen_name,
UGETW(udev->ddesc.idVendor),
UGETW(udev->ddesc.idProduct),
udev->ddesc.bDeviceClass,
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index 4c296d456725..bca3a1d32822 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -61,11 +61,12 @@ struct usb2_pipe {
* The following structure defines an USB interface.
*/
struct usb2_interface {
- struct usb2_perm perm; /* interface permissions */
struct usb2_interface_descriptor *idesc;
device_t subdev;
uint8_t alt_index;
uint8_t parent_iface_index;
+ uint16_t ep_in_mask; /* bitmask of IN endpoints */
+ uint16_t ep_out_mask; /* bitmask of OUT endpoints */
};
/*
@@ -101,12 +102,12 @@ struct usb2_power_save {
struct usb2_device {
struct usb2_clear_stall_msg cs_msg[2]; /* generic clear stall
* messages */
- struct usb2_perm perm;
struct sx default_sx[2];
struct mtx default_mtx[1];
struct cv default_cv[2];
struct usb2_interface ifaces[USB_IFACE_MAX];
struct usb2_pipe default_pipe; /* Control Endpoint 0 */
+ struct cdev *default_dev; /* Control Endpoint 0 device node */
struct usb2_pipe pipes[USB_EP_MAX];
struct usb2_power_save pwr_save;/* power save data */
@@ -120,10 +121,16 @@ struct usb2_device {
struct usb2_temp_data *usb2_template_ptr;
struct usb2_pipe *pipe_curr; /* current clear stall pipe */
struct usb2_fifo *fifo[USB_FIFO_MAX];
+
+ char ugen_name[20]; /* name of ugenX.X device */
struct usb2_symlink *ugen_symlink; /* our generic symlink */
+ LIST_HEAD(,usb2_fs_privdata) pd_list;
+
uint32_t plugtime; /* copy of "ticks" */
+ uint16_t ep_rd_opened; /* bitmask of endpoints opened */
+ uint16_t ep_wr_opened; /* from the device nodes. */
uint16_t refcount;
#define USB_DEV_REF_MAX 0xffff
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index 75b985c2c52a..49b072c342e3 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -149,7 +149,7 @@ ugen_transfer_setup(struct usb2_fifo *f,
}
static int
-ugen_open(struct usb2_fifo *f, int fflags, struct thread *td)
+ugen_open(struct usb2_fifo *f, int fflags)
{
struct usb2_pipe *pipe = f->priv_sc0;
struct usb2_endpoint_descriptor *ed = pipe->edesc;
@@ -183,7 +183,7 @@ ugen_open(struct usb2_fifo *f, int fflags, struct thread *td)
}
static void
-ugen_close(struct usb2_fifo *f, int fflags, struct thread *td)
+ugen_close(struct usb2_fifo *f, int fflags)
{
DPRINTFN(6, "flag=0x%x\n", fflags);
@@ -872,10 +872,6 @@ ugen_check_request(struct usb2_device *udev, struct usb2_device_request *req)
if (pipe == NULL) {
return (EINVAL);
}
- if (usb2_check_thread_perm(udev, curthread, FREAD | FWRITE,
- pipe->iface_index, req->wIndex[0] & UE_ADDR)) {
- return (EPERM);
- }
if ((req->bRequest == UR_CLEAR_FEATURE) &&
(UGETW(req->wValue) == UF_ENDPOINT_HALT)) {
usb2_clear_data_toggle(udev, pipe);
@@ -1367,8 +1363,7 @@ ugen_fifo_in_use(struct usb2_fifo *f, int fflags)
}
static int
-ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags,
- struct thread *td)
+ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags)
{
struct usb2_config usb2_config[1];
struct usb2_device_request req;
@@ -1458,11 +1453,6 @@ ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags,
}
iface_index = pipe->iface_index;
- error = usb2_check_thread_perm(f->udev, curthread, fflags,
- iface_index, u.popen->ep_no);
- if (error) {
- break;
- }
bzero(usb2_config, sizeof(usb2_config));
usb2_config[0].type = ed->bmAttributes & UE_XFERTYPE;
@@ -1948,8 +1938,7 @@ ugen_iface_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags)
}
static int
-ugen_ioctl_post(struct usb2_fifo *f, u_long cmd, void *addr, int fflags,
- struct thread *td)
+ugen_ioctl_post(struct usb2_fifo *f, u_long cmd, void *addr, int fflags)
{
union {
struct usb2_interface_descriptor *idesc;
diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h
index 73f77964e110..81e2c466dec7 100644
--- a/sys/dev/usb/usb_ioctl.h
+++ b/sys/dev/usb/usb_ioctl.h
@@ -36,7 +36,8 @@
#include <dev/usb/usb_endian.h>
#include <dev/usb/usb.h>
-#define USB_DEVICE_NAME "usb"
+#define USB_DEVICE_NAME "usbctl"
+#define USB_DEVICE_DIR "usb"
#define USB_GENERIC_NAME "ugen"
struct usb2_read_dir {
@@ -180,18 +181,6 @@ struct usb2_fs_clear_stall_sync {
uint8_t ep_index;
};
-struct usb2_dev_perm {
- /* Access information */
- uint32_t user_id;
- uint32_t group_id;
- uint16_t mode;
-
- /* Device location */
- uint16_t bus_index;
- uint16_t dev_index;
- uint16_t iface_index;
-};
-
struct usb2_gen_quirk {
uint16_t index; /* Quirk Index */
uint16_t vid; /* Vendor ID */
@@ -248,14 +237,7 @@ struct usb2_gen_quirk {
#define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int)
#define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t)
#define USB_READ_DIR _IOW ('U', 127, struct usb2_read_dir)
-#define USB_SET_ROOT_PERM _IOW ('U', 128, struct usb2_dev_perm)
-#define USB_SET_BUS_PERM _IOW ('U', 129, struct usb2_dev_perm)
-#define USB_SET_DEVICE_PERM _IOW ('U', 130, struct usb2_dev_perm)
-#define USB_SET_IFACE_PERM _IOW ('U', 131, struct usb2_dev_perm)
-#define USB_GET_ROOT_PERM _IOWR('U', 132, struct usb2_dev_perm)
-#define USB_GET_BUS_PERM _IOWR('U', 133, struct usb2_dev_perm)
-#define USB_GET_DEVICE_PERM _IOWR('U', 134, struct usb2_dev_perm)
-#define USB_GET_IFACE_PERM _IOWR('U', 135, struct usb2_dev_perm)
+/* 128 - 135 unused */
#define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int)
#define USB_SET_TX_TIMEOUT _IOW ('U', 137, int)
#define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int)