Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Nov 2009 18:34:54 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 170781 for review
Message-ID:  <200911181834.nAIIYscs046091@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=170781

Change 170781 by hselasky@hselasky_laptop001 on 2009/11/18 18:34:28

	
	LibUSB v1.0 - fix compliancy issue. If a transfer is cancelled
	when not actually running, the library will segfault. Also
	fix the return value from libusb_cancel_transfer() to be more according
	to the LibUSB v1.0.4 specification.
	
	 - report by: Robert Jenssen
	 - fix by: HPS

Affected files ...

.. //depot/projects/usb/src/lib/libusb/libusb10.c#16 edit
.. //depot/projects/usb/src/lib/libusb/libusb10.h#10 edit

Differences ...

==== //depot/projects/usb/src/lib/libusb/libusb10.c#16 (text+ko) ====

@@ -833,8 +833,12 @@
 	if (pxfer != NULL)
 		libusb20_tr_set_priv_sc1(pxfer, NULL);
 
+	/* set transfer status */
 	uxfer->status = status;
 
+	/* update super transfer state */
+	sxfer->state = LIBUSB_SUPER_XFER_ST_NONE;
+
 	dev = libusb_get_device(uxfer->dev_handle);
 
 	TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry);
@@ -1229,12 +1233,18 @@
 	if (pxfer0 == NULL || pxfer1 == NULL) {
 		err = LIBUSB_ERROR_OTHER;
 	} else if ((sxfer->entry.tqe_prev != NULL) ||
-		    (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) ||
+	    (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) ||
 	    (libusb20_tr_get_priv_sc1(pxfer1) == sxfer)) {
 		err = LIBUSB_ERROR_BUSY;
 	} else {
+
+		/* set pending state */
+		sxfer->state = LIBUSB_SUPER_XFER_ST_PEND;
+
+		/* insert transfer into transfer head list */
 		TAILQ_INSERT_TAIL(&dev->tr_head, sxfer, entry);
 
+		/* start work transfers */
 		libusb10_submit_transfer_sub(
 		    uxfer->dev_handle, endpoint);
 
@@ -1258,6 +1268,7 @@
 	struct libusb_super_transfer *sxfer;
 	struct libusb_device *dev;
 	uint32_t endpoint;
+	int retval;
 
 	if (uxfer == NULL)
 		return (LIBUSB_ERROR_INVALID_PARAM);
@@ -1277,39 +1288,50 @@
 	sxfer = (struct libusb_super_transfer *)(
 	    (uint8_t *)uxfer - sizeof(*sxfer));
 
+	retval = 0;
+
 	CTX_LOCK(dev->ctx);
 
 	pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0);
 	pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1);
 
-	if (sxfer->entry.tqe_prev != NULL) {
+	if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) {
+		/* only update the transfer status */
+		uxfer->status = LIBUSB_TRANSFER_CANCELLED;
+		retval = LIBUSB_ERROR_NOT_FOUND;
+	} else if (sxfer->entry.tqe_prev != NULL) {
 		/* we are lucky - transfer is on a queue */
 		TAILQ_REMOVE(&dev->tr_head, sxfer, entry);
 		sxfer->entry.tqe_prev = NULL;
-		libusb10_complete_transfer(NULL, sxfer, LIBUSB_TRANSFER_CANCELLED);
+		libusb10_complete_transfer(NULL,
+		    sxfer, LIBUSB_TRANSFER_CANCELLED);
 	} else if (pxfer0 == NULL || pxfer1 == NULL) {
 		/* not started */
+		retval = LIBUSB_ERROR_NOT_FOUND;
 	} else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) {
-		libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_CANCELLED);
+		libusb10_complete_transfer(pxfer0,
+		    sxfer, LIBUSB_TRANSFER_CANCELLED);
 		libusb20_tr_stop(pxfer0);
 		/* make sure the queue doesn't stall */
 		libusb10_submit_transfer_sub(
 		    uxfer->dev_handle, endpoint);
 	} else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) {
-		libusb10_complete_transfer(pxfer1, sxfer, LIBUSB_TRANSFER_CANCELLED);
+		libusb10_complete_transfer(pxfer1,
+		    sxfer, LIBUSB_TRANSFER_CANCELLED);
 		libusb20_tr_stop(pxfer1);
 		/* make sure the queue doesn't stall */
 		libusb10_submit_transfer_sub(
 		    uxfer->dev_handle, endpoint);
 	} else {
 		/* not started */
+		retval = LIBUSB_ERROR_NOT_FOUND;
 	}
 
 	CTX_UNLOCK(dev->ctx);
 
 	DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave");
 
-	return (0);
+	return (retval);
 }
 
 UNEXPORTED void

==== //depot/projects/usb/src/lib/libusb/libusb10.h#10 (text+ko) ====

@@ -65,7 +65,9 @@
 	uint8_t *curr_data;
 	uint32_t rem_len;
 	uint32_t last_len;
-	uint8_t	flags;
+	uint8_t	state;
+#define	LIBUSB_SUPER_XFER_ST_NONE 0
+#define	LIBUSB_SUPER_XFER_ST_PEND 1
 };
 
 struct libusb_context {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911181834.nAIIYscs046091>