Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Add internal support for multiple endpoints.
details: https://anonhg.NetBSD.org/src/rev/dd0a1eb141bd
branches: trunk
changeset: 746126:dd0a1eb141bd
user: maxv <maxv%NetBSD.org@localhost>
date: Sun Mar 22 17:15:15 2020 +0000
description:
Add internal support for multiple endpoints.
diffstat:
sys/dev/usb/vhci.c | 127 ++++++++++++++++++++++++++++++++++------------------
1 files changed, 83 insertions(+), 44 deletions(-)
diffs (truncated from 329 to 300 lines):
diff -r 5380bd17b6b6 -r dd0a1eb141bd sys/dev/usb/vhci.c
--- a/sys/dev/usb/vhci.c Sun Mar 22 16:46:30 2020 +0000
+++ b/sys/dev/usb/vhci.c Sun Mar 22 17:15:15 2020 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: vhci.c,v 1.9 2020/03/22 15:14:03 maxv Exp $ */
+/* $NetBSD: vhci.c,v 1.10 2020/03/22 17:15:15 maxv Exp $ */
/*
- * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * Copyright (c) 2019-2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.9 2020/03/22 15:14:03 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.10 2020/03/22 17:15:15 maxv Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -180,6 +180,7 @@
TAILQ_ENTRY(vhci_packet) xferlist;
struct vhci_xfer *vxfer;
bool utoh;
+ uint8_t addr;
uint8_t *buf;
size_t size;
size_t cursor;
@@ -187,6 +188,8 @@
typedef TAILQ_HEAD(, vhci_packet) vhci_packet_list_t;
+#define VHCI_NADDRS 16 /* maximum supported by USB */
+
typedef struct {
kmutex_t lock;
int status;
@@ -194,7 +197,7 @@
struct {
vhci_packet_list_t usb_to_host;
vhci_packet_list_t host_to_usb;
- } pkts_device_ctrl;
+ } endpoints[VHCI_NADDRS];
} vhci_port_t;
typedef struct {
@@ -245,6 +248,7 @@
typedef struct {
u_int port;
+ uint8_t addr;
vhci_softc_t *softc;
} vhci_fd_t;
@@ -253,7 +257,8 @@
/* -------------------------------------------------------------------------- */
static void
-vhci_pkt_create(vhci_port_t *port, struct usbd_xfer *xfer, bool usb_to_host)
+vhci_pkt_create(vhci_port_t *port, struct usbd_xfer *xfer, bool utoh,
+ uint8_t addr)
{
vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
vhci_packet_list_t *reqlist, *datlist;
@@ -261,10 +266,11 @@
size_t npkts = 0;
/* Request packet. */
- reqlist = &port->pkts_device_ctrl.host_to_usb;
+ reqlist = &port->endpoints[addr].host_to_usb;
req = kmem_zalloc(sizeof(*req), KM_SLEEP);
req->vxfer = vxfer;
req->utoh = false;
+ req->addr = addr;
req->buf = (uint8_t *)&xfer->ux_request;
req->size = sizeof(xfer->ux_request);
req->cursor = 0;
@@ -272,14 +278,15 @@
/* Data packet. */
if (xfer->ux_length > 0) {
- if (usb_to_host) {
- datlist = &port->pkts_device_ctrl.usb_to_host;
+ if (utoh) {
+ datlist = &port->endpoints[addr].usb_to_host;
} else {
- datlist = &port->pkts_device_ctrl.host_to_usb;
+ datlist = &port->endpoints[addr].host_to_usb;
}
dat = kmem_zalloc(sizeof(*dat), KM_SLEEP);
dat->vxfer = vxfer;
- dat->utoh = usb_to_host;
+ dat->utoh = utoh;
+ dat->addr = addr;
dat->buf = xfer->ux_buf;
dat->size = xfer->ux_length;
dat->cursor = 0;
@@ -312,9 +319,9 @@
/* Remove from the port. */
if (pkt->utoh) {
- pktlist = &port->pkts_device_ctrl.usb_to_host;
+ pktlist = &port->endpoints[pkt->addr].usb_to_host;
} else {
- pktlist = &port->pkts_device_ctrl.host_to_usb;
+ pktlist = &port->endpoints[pkt->addr].host_to_usb;
}
TAILQ_REMOVE(pktlist, pkt, portlist);
@@ -366,8 +373,8 @@
case UE_CONTROL:
pipe->up_methods = &vhci_device_ctrl_methods;
break;
+ case UE_INTERRUPT:
case UE_BULK:
- case UE_INTERRUPT:
default:
goto bad;
}
@@ -559,14 +566,17 @@
static usbd_status
vhci_device_ctrl_start(struct usbd_xfer *xfer)
{
+ usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc;
usb_device_request_t *req = &xfer->ux_request;
struct usbd_device *dev = xfer->ux_pipe->up_dev;
vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
vhci_port_t *port;
bool polling = sc->sc_bus.ub_usepolling;
bool isread = (req->bmRequestType & UT_READ) != 0;
+ uint8_t addr = UE_GET_ADDR(ed->bEndpointAddress);
int portno, ret;
+ KASSERT(addr == 0);
KASSERT(xfer->ux_rqflags & URQ_REQUEST);
KASSERT(dev->ud_myhsport != NULL);
portno = dev->ud_myhsport->up_portno;
@@ -585,7 +595,7 @@
mutex_enter(&port->lock);
if (port->status & UPS_PORT_ENABLED) {
xfer->ux_status = USBD_IN_PROGRESS;
- vhci_pkt_create(port, xfer, isread);
+ vhci_pkt_create(port, xfer, isread, addr);
ret = USBD_IN_PROGRESS;
} else {
ret = USBD_IOERROR;
@@ -761,12 +771,19 @@
/* Current port. */
u_int port;
int status;
+
+ /* Current addr. */
+ uint8_t addr;
};
struct vhci_ioc_set_port {
u_int port;
};
+struct vhci_ioc_set_addr {
+ uint8_t addr;
+};
+
struct vhci_ioc_usb_attach {
u_int port;
};
@@ -777,6 +794,7 @@
#define VHCI_IOC_GET_INFO _IOR('V', 0, struct vhci_ioc_get_info)
#define VHCI_IOC_SET_PORT _IOW('V', 1, struct vhci_ioc_set_port)
+#define VHCI_IOC_SET_ADDR _IOW('V', 2, struct vhci_ioc_set_addr)
#define VHCI_IOC_USB_ATTACH _IOW('V', 10, struct vhci_ioc_usb_attach)
#define VHCI_IOC_USB_DETACH _IOW('V', 11, struct vhci_ioc_usb_detach)
@@ -829,41 +847,44 @@
vhci_packet_t *pkt, *nxt;
vhci_xfer_list_t vxferlist;
vhci_xfer_t *vxfer;
+ uint8_t addr;
KASSERT(mutex_owned(&sc->sc_lock));
KASSERT(mutex_owned(&port->lock));
TAILQ_INIT(&vxferlist);
- /* Drop all the packets in the H->U direction. */
- pktlist = &port->pkts_device_ctrl.host_to_usb;
- TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
- vxfer = pkt->vxfer;
- KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
- vhci_pkt_destroy(sc, pkt);
- if (vxfer->npkts == 0)
- TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
- }
- KASSERT(TAILQ_FIRST(pktlist) == NULL);
+ for (addr = 0; addr < VHCI_NADDRS; addr++) {
+ /* Drop all the packets in the H->U direction. */
+ pktlist = &port->endpoints[addr].host_to_usb;
+ TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
+ vxfer = pkt->vxfer;
+ KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
+ vhci_pkt_destroy(sc, pkt);
+ if (vxfer->npkts == 0)
+ TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
+ }
+ KASSERT(TAILQ_FIRST(pktlist) == NULL);
- /* Drop all the packets in the U->H direction. */
- pktlist = &port->pkts_device_ctrl.usb_to_host;
- TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
- vxfer = pkt->vxfer;
- KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
- vhci_pkt_destroy(sc, pkt);
- if (vxfer->npkts == 0)
- TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
- }
- KASSERT(TAILQ_FIRST(pktlist) == NULL);
+ /* Drop all the packets in the U->H direction. */
+ pktlist = &port->endpoints[addr].usb_to_host;
+ TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
+ vxfer = pkt->vxfer;
+ KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
+ vhci_pkt_destroy(sc, pkt);
+ if (vxfer->npkts == 0)
+ TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
+ }
+ KASSERT(TAILQ_FIRST(pktlist) == NULL);
- /* Terminate all the xfers collected. */
- while ((vxfer = TAILQ_FIRST(&vxferlist)) != NULL) {
- struct usbd_xfer *xfer = &vxfer->xfer;
- TAILQ_REMOVE(&vxferlist, vxfer, freelist);
+ /* Terminate all the xfers collected. */
+ while ((vxfer = TAILQ_FIRST(&vxferlist)) != NULL) {
+ struct usbd_xfer *xfer = &vxfer->xfer;
+ TAILQ_REMOVE(&vxferlist, vxfer, freelist);
- xfer->ux_status = USBD_TIMEOUT;
- usb_transfer_complete(xfer);
+ xfer->ux_status = USBD_TIMEOUT;
+ usb_transfer_complete(xfer);
+ }
}
}
@@ -920,6 +941,7 @@
mutex_enter(&port->lock);
args->status = port->status;
mutex_exit(&port->lock);
+ args->addr = vfd->addr;
return 0;
}
@@ -937,6 +959,17 @@
return 0;
}
+static int
+vhci_set_addr(vhci_fd_t *vfd, struct vhci_ioc_set_addr *args)
+{
+ if (args->addr >= VHCI_NADDRS)
+ return EINVAL;
+
+ vfd->addr = args->addr;
+
+ return 0;
+}
+
/* -------------------------------------------------------------------------- */
static dev_type_open(vhci_fd_open);
@@ -989,6 +1022,7 @@
vfd = kmem_alloc(sizeof(*vfd), KM_SLEEP);
vfd->port = 1;
+ vfd->addr = 0;
vfd->softc = device_lookup_private(&vhci_cd, minor(dev));
return fd_clone(fp, fd, flags, &vhci_fileops, vfd);
@@ -1031,7 +1065,7 @@
if (uio->uio_resid == 0)
return 0;
port = &sc->sc_port[vfd->port];
- pktlist = &port->pkts_device_ctrl.host_to_usb;
+ pktlist = &port->endpoints[vfd->addr].host_to_usb;
TAILQ_INIT(&vxferlist);
@@ -1104,7 +1138,7 @@
if (uio->uio_resid == 0)
return 0;
port = &sc->sc_port[vfd->port];
- pktlist = &port->pkts_device_ctrl.usb_to_host;
+ pktlist = &port->endpoints[vfd->addr].usb_to_host;
TAILQ_INIT(&vxferlist);
@@ -1171,6 +1205,8 @@
Home |
Main Index |
Thread Index |
Old Index