Module Name:    src
Committed By:   maxv
Date:           Tue Mar 31 16:17:32 UTC 2020

Modified Files:
        src/sys/dev/usb: vhci.c

Log Message:
Allow short transfers. We introduce a third packet, in the U->H list, that
contains a vhci_response_t, which indicates the size.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/usb/vhci.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/vhci.c
diff -u src/sys/dev/usb/vhci.c:1.13 src/sys/dev/usb/vhci.c:1.14
--- src/sys/dev/usb/vhci.c:1.13	Sun Mar 29 09:46:14 2020
+++ src/sys/dev/usb/vhci.c	Tue Mar 31 16:17:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: vhci.c,v 1.13 2020/03/29 09:46:14 maxv Exp $ */
+/*	$NetBSD: vhci.c,v 1.14 2020/03/31 16:17:32 maxv Exp $ */
 
 /*
  * Copyright (c) 2019-2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.13 2020/03/29 09:46:14 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.14 2020/03/31 16:17:32 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -182,6 +182,10 @@ typedef struct {
 	} u;
 } vhci_request_t;
 
+typedef struct {
+	size_t size;
+} vhci_response_t;
+
 struct vhci_xfer;
 
 typedef struct vhci_packet {
@@ -192,6 +196,13 @@ typedef struct vhci_packet {
 	bool utoh;
 	uint8_t addr;
 
+	/* Type. */
+	struct {
+		bool req:1;
+		bool res:1;
+		bool dat:1;
+	} type;
+
 	/* Exposed for FD operations. */
 	uint8_t *buf;
 	size_t size;
@@ -229,6 +240,7 @@ typedef struct vhci_xfer {
 
 	/* Header storage. */
 	vhci_request_t reqbuf;
+	vhci_response_t resbuf;
 
 	/* Used for G/C. */
 	TAILQ_ENTRY(vhci_xfer) freelist;
@@ -276,8 +288,8 @@ vhci_pkt_ctrl_create(vhci_port_t *port, 
     uint8_t addr)
 {
 	vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
-	vhci_packet_list_t *reqlist, *datlist;
-	vhci_packet_t *req, *dat = NULL;
+	vhci_packet_list_t *reqlist, *reslist, *datlist = NULL;
+	vhci_packet_t *req, *res = NULL, *dat = NULL;
 	size_t npkts = 0;
 
 	/* Request packet. */
@@ -286,6 +298,7 @@ vhci_pkt_ctrl_create(vhci_port_t *port, 
 	req->vxfer = vxfer;
 	req->utoh = false;
 	req->addr = addr;
+	req->type.req = true;
 	req->buf = (uint8_t *)&vxfer->reqbuf;
 	req->size = sizeof(vxfer->reqbuf);
 	req->cursor = 0;
@@ -297,6 +310,20 @@ vhci_pkt_ctrl_create(vhci_port_t *port, 
 	memcpy(&vxfer->reqbuf.u.ctrl, &xfer->ux_request,
 	    sizeof(xfer->ux_request));
 
+	/* Response packet. */
+	if (utoh && (xfer->ux_length > 0)) {
+		reslist = &port->endpoints[addr].usb_to_host;
+		res = kmem_zalloc(sizeof(*res), KM_SLEEP);
+		res->vxfer = vxfer;
+		res->utoh = true;
+		res->addr = addr;
+		res->type.res = true;
+		res->buf = (uint8_t *)&vxfer->resbuf;
+		res->size = sizeof(vxfer->resbuf);
+		res->cursor = 0;
+		npkts++;
+	}
+
 	/* Data packet. */
 	if (xfer->ux_length > 0) {
 		if (utoh) {
@@ -308,6 +335,7 @@ vhci_pkt_ctrl_create(vhci_port_t *port, 
 		dat->vxfer = vxfer;
 		dat->utoh = utoh;
 		dat->addr = addr;
+		dat->type.dat = true;
 		dat->buf = xfer->ux_buf;
 		dat->size = xfer->ux_length;
 		dat->cursor = 0;
@@ -319,12 +347,16 @@ vhci_pkt_ctrl_create(vhci_port_t *port, 
 	vxfer->npkts = npkts;
 	TAILQ_INIT(&vxfer->pkts);
 	TAILQ_INSERT_TAIL(&vxfer->pkts, req, xferlist);
+	if (res != NULL)
+		TAILQ_INSERT_TAIL(&vxfer->pkts, res, xferlist);
 	if (dat != NULL)
 		TAILQ_INSERT_TAIL(&vxfer->pkts, dat, xferlist);
 
 	/* Insert in the port. */
 	KASSERT(mutex_owned(&port->lock));
 	TAILQ_INSERT_TAIL(reqlist, req, portlist);
+	if (res != NULL)
+		TAILQ_INSERT_TAIL(reslist, res, portlist);
 	if (dat != NULL)
 		TAILQ_INSERT_TAIL(datlist, dat, portlist);
 }
@@ -1084,6 +1116,7 @@ vhci_fd_read(struct file *fp, off_t *off
 	TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
 		vxfer = pkt->vxfer;
 		buf = pkt->buf + pkt->cursor;
+
 		KASSERT(pkt->size >= pkt->cursor);
 		size = uimin(uio->uio_resid, pkt->size - pkt->cursor);
 
@@ -1138,7 +1171,7 @@ vhci_fd_write(struct file *fp, off_t *of
 	vhci_port_t *port;
 	int error = 0;
 	uint8_t *buf;
-	size_t size;
+	size_t pktsize, size;
 
 	if (uio->uio_resid == 0)
 		return 0;
@@ -1157,8 +1190,13 @@ vhci_fd_write(struct file *fp, off_t *of
 	TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
 		vxfer = pkt->vxfer;
 		buf = pkt->buf + pkt->cursor;
-		KASSERT(pkt->size >= pkt->cursor);
-		size = uimin(uio->uio_resid, pkt->size - pkt->cursor);
+
+		pktsize = pkt->size;
+		if (pkt->type.dat)
+			pktsize = ulmin(vxfer->resbuf.size, pktsize);
+
+		KASSERT(pktsize >= pkt->cursor);
+		size = uimin(uio->uio_resid, pktsize - pkt->cursor);
 
 		KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
 
@@ -1170,7 +1208,7 @@ vhci_fd_write(struct file *fp, off_t *of
 
 		pkt->cursor += size;
 
-		if (pkt->cursor == pkt->size) {
+		if (pkt->cursor == pktsize) {
 			vhci_pkt_destroy(sc, pkt);
 			if (vxfer->npkts == 0) {
 				TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
@@ -1189,7 +1227,7 @@ out:
 		TAILQ_REMOVE(&vxferlist, vxfer, freelist);
 
 		mutex_enter(&sc->sc_lock);
-		xfer->ux_actlen = xfer->ux_length;
+		xfer->ux_actlen = ulmin(vxfer->resbuf.size, xfer->ux_length);
 		xfer->ux_status = USBD_NORMAL_COMPLETION;
 		usb_transfer_complete(xfer);
 		mutex_exit(&sc->sc_lock);

Reply via email to