PERFORCE change 170781 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Nov 18 18:34:55 UTC 2009
http://p4web.freebsd.org/chv.cgi?CH=170781
Change 170781 by hselasky at 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 {
More information about the p4-projects
mailing list