Module Name:    src
Committed By:   martin
Date:           Tue Nov 20 16:05:38 UTC 2018

Modified Files:
        src/sys/dev/usb [netbsd-8]: usb_quirks.c usb_quirks.h usbdi.c

Log Message:
Pull up following revision(s) (requested by manu in ticket #1099):

        sys/dev/usb/usb_quirks.c: revision 1.90
        sys/dev/usb/usbdi.c: revision 1.179
        sys/dev/usb/usb_quirks.h: revision 1.29
        sys/dev/usb/usbdi.c: revision 1.180

Workaround NBP PN533 USB toggle bit bugs

The PN533 is known to mishandle the USB toggle bit, causing replies to
be filtered out by the host controller. As a result, the kernel sees
a timed out operation.

Vendor errata suggests that userland applications should detect the
situation on read timeout, and write a dumy frame to resync the toggle bit.
NFC Tools's libnfc does just that, but in order to succeed, the dummy
frame write must not be reported as timed out.

We therefore introduce a new USB quirk for devices known to miss output
acks. When that occur, we pretend that the operation succeeded, leaving
userland the duty to check that everything went okay.

This workaround lets libnfc recover from interrupted communications
without the need te reboot the system.

 -

Build fix
>From David H. Gutteridge


To generate a diff of this commit:
cvs rdiff -u -r1.86.8.1 -r1.86.8.2 src/sys/dev/usb/usb_quirks.c
cvs rdiff -u -r1.27.10.1 -r1.27.10.2 src/sys/dev/usb/usb_quirks.h
cvs rdiff -u -r1.173.2.3 -r1.173.2.4 src/sys/dev/usb/usbdi.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/usb_quirks.c
diff -u src/sys/dev/usb/usb_quirks.c:1.86.8.1 src/sys/dev/usb/usb_quirks.c:1.86.8.2
--- src/sys/dev/usb/usb_quirks.c:1.86.8.1	Mon Nov 12 16:01:35 2018
+++ src/sys/dev/usb/usb_quirks.c	Tue Nov 20 16:05:38 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb_quirks.c,v 1.86.8.1 2018/11/12 16:01:35 martin Exp $	*/
+/*	$NetBSD: usb_quirks.c,v 1.86.8.2 2018/11/20 16:05:38 martin Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.30 2003/01/02 04:15:55 imp Exp $	*/
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.86.8.1 2018/11/12 16:01:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.86.8.2 2018/11/20 16:05:38 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -310,13 +310,24 @@ Static const struct usbd_quirk_entry {
  { USB_VENDOR_ZOOM,		USB_PRODUCT_ZOOM_3095,			ANY,
 	{ UQ_LOST_CS_DESC, NULL }},
 
- /* NXP PN533 corrupts its USB configuration descriptors */
+ /*
+  * NXP PN533 bugs
+  * 
+  * 1. It corrupts its USB descriptors. The quirk is to provide hardcoded
+  *    descriptors instead of getting them from the device.
+  * 2. It mishandles the USB toggle bit. This causes some replies to be
+  *    filered out by the USB host controller and be reported as timed out.
+  *    NFC tool's libnfc workaround this bug by sending a dummy frame to
+  *    resync the toggle bit, but in order to succeed, that operation must
+  *    not be reported as failed. The quirk is therefore to pretend to 
+  *    userland that output timeouts are successes.
+  */
  { USB_VENDOR_PHILIPSSEMI,	USB_PRODUCT_PHILIPSSEMI_PN533,		ANY,
-	{ UQ_DESC_CORRUPT, desc_pn533 }},
+	{ UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
  { USB_VENDOR_SHUTTLE,		USB_PRODUCT_SHUTTLE_SCL3711,		ANY,
-	{ UQ_DESC_CORRUPT, desc_pn533 }},
+	{ UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
  { USB_VENDOR_SHUTTLE,		USB_PRODUCT_SHUTTLE_SCL3712,		ANY,
-	{ UQ_DESC_CORRUPT, desc_pn533 }},
+	{ UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
  { 0, 0, 0, { 0, NULL } }
 };
 

Index: src/sys/dev/usb/usb_quirks.h
diff -u src/sys/dev/usb/usb_quirks.h:1.27.10.1 src/sys/dev/usb/usb_quirks.h:1.27.10.2
--- src/sys/dev/usb/usb_quirks.h:1.27.10.1	Mon Nov 12 16:01:35 2018
+++ src/sys/dev/usb/usb_quirks.h	Tue Nov 20 16:05:38 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb_quirks.h,v 1.27.10.1 2018/11/12 16:01:35 martin Exp $	*/
+/*	$NetBSD: usb_quirks.h,v 1.27.10.2 2018/11/20 16:05:38 martin Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.9 1999/11/12 23:31:03 n_hibma Exp $	*/
 
 /*
@@ -50,6 +50,7 @@ struct usbd_quirks {
 #define UQ_LOST_CS_DESC 0x10000 /* look everywhere for the CS descriptors */
 #define UQ_APPLE_ISO	0x20000	/* force ISO layout on Apple keyboards */
 #define UQ_DESC_CORRUPT	0x40000	/* may corrupt its config descriptors */
+#define UQ_MISS_OUT_ACK	0x80000	/* may fail to ack output */
 	const usb_descriptor_t **desc;	/* Replacement for UQ_DESC_CORRUPT */
 };
 

Index: src/sys/dev/usb/usbdi.c
diff -u src/sys/dev/usb/usbdi.c:1.173.2.3 src/sys/dev/usb/usbdi.c:1.173.2.4
--- src/sys/dev/usb/usbdi.c:1.173.2.3	Thu Sep 27 14:52:26 2018
+++ src/sys/dev/usb/usbdi.c	Tue Nov 20 16:05:38 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi.c,v 1.173.2.3 2018/09/27 14:52:26 martin Exp $	*/
+/*	$NetBSD: usbdi.c,v 1.173.2.4 2018/11/20 16:05:38 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2012, 2015 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.173.2.3 2018/09/27 14:52:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.173.2.4 2018/11/20 16:05:38 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -897,9 +897,7 @@ usb_transfer_complete(struct usbd_xfer *
 	struct usbd_pipe *pipe = xfer->ux_pipe;
 	struct usbd_bus *bus = pipe->up_dev->ud_bus;
 	int sync = xfer->ux_flags & USBD_SYNCHRONOUS;
-	int erred =
-	    xfer->ux_status == USBD_CANCELLED ||
-	    xfer->ux_status == USBD_TIMEOUT;
+	int erred;
 	int polling = bus->ub_usepolling;
 	int repeat = pipe->up_repeat;
 
@@ -914,6 +912,27 @@ usb_transfer_complete(struct usbd_xfer *
 	    xfer->ux_state);
 	KASSERT(pipe != NULL);
 
+	/*
+	 * If device is known to miss out ack, then pretend that
+	 * output timeout is a success. Userland should handle
+	 * the logic to verify that the operation succeeded.
+	 */
+	if (pipe->up_dev->ud_quirks &&
+	    pipe->up_dev->ud_quirks->uq_flags & UQ_MISS_OUT_ACK &&
+	    xfer->ux_status == USBD_TIMEOUT &&
+	    !usbd_xfer_isread(xfer)) {
+		USBHIST_LOG(usbdebug, "Possible output ack miss for xfer %#jx: "
+		    "hiding write timeout to %d.%s for %d bytes written",
+		    (uintptr_t)xfer, curlwp->l_proc->p_pid, curlwp->l_lid,
+		    xfer->ux_length);
+
+		xfer->ux_status = USBD_NORMAL_COMPLETION;
+		xfer->ux_actlen = xfer->ux_length;
+	}
+
+	erred = xfer->ux_status == USBD_CANCELLED ||
+	        xfer->ux_status == USBD_TIMEOUT;
+
 	if (!repeat) {
 		/* Remove request from queue. */
 

Reply via email to