[PATCH] USB: usblp: don't call usb_set_interface if there's a single alt

2021-01-23 Thread Jeremy Figgins
Some devices, such as the Winbond Electronics Corp. Virtual Com Port
(Vendor=0416, ProdId=5011), lockup when usb_set_interface() or
usb_clear_halt() are called. This device has only a single
altsetting, so it should not be necessary to call usb_set_interface().

Signed-off-by: Jeremy Figgins 
---
An alternative fix was submitted previously as:

USB: usblp: add USBLP_QUIRK_NO_SETF_INTF flag

and this superscedes that patch. This is a different approach, so
I submitted it as a new patch, rather than adding a v2 to the first
one; I hope that was the correct thing to do in this case.

 drivers/usb/class/usblp.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 134dc2005ce9..c9f6e9758288 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -1329,14 +1329,17 @@ static int usblp_set_protocol(struct usblp *usblp, int 
protocol)
if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
return -EINVAL;
 
-   alts = usblp->protocol[protocol].alt_setting;
-   if (alts < 0)
-   return -EINVAL;
-   r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
-   if (r < 0) {
-   printk(KERN_ERR "usblp: can't set desired altsetting %d on 
interface %d\n",
-   alts, usblp->ifnum);
-   return r;
+   /* Don't unnecessarily set the interface if there's a single alt. */
+   if (usblp->intf->num_altsetting > 1) {
+   alts = usblp->protocol[protocol].alt_setting;
+   if (alts < 0)
+   return -EINVAL;
+   r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
+   if (r < 0) {
+   printk(KERN_ERR "usblp: can't set desired altsetting %d 
on interface %d\n",
+   alts, usblp->ifnum);
+   return r;
+   }
}
 
usblp->bidir = (usblp->protocol[protocol].epread != NULL);
-- 
2.29.0



[PATCH] USB: usblp: add USBLP_QUIRK_NO_SET_INTF flag

2021-01-17 Thread Jeremy Figgins
Certain devices such as Winbond Virtual Com Port,
which is used in some usb printers, will stop
responding after the usb_control_msg_send()
calls in usb_set_interface(). These devices work
fine without having usb_set_interface() called, so
this flag prevents that call.

The naming is designed to mirror the existing
USB_QUIRK_NO_SET_INTF flag, but that flag is
not sufficient to make these devices work.

Signed-off-by: Jeremy Figgins 
---
 drivers/usb/class/usblp.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 134dc2005ce9..6e2d58813d7d 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -209,6 +209,7 @@ struct quirk_printer_struct {
 #define USBLP_QUIRK_BIDIR  0x1 /* reports bidir but requires 
unidirectional mode (no INs/reads) */
 #define USBLP_QUIRK_USB_INIT   0x2 /* needs vendor USB init string */
 #define USBLP_QUIRK_BAD_CLASS  0x4 /* descriptor uses vendor-specific 
Class or SubClass */
+#define USBLP_QUIRK_NO_SET_INTF0x8 /* device can't handle 
Set-Interface requests */
 
 static const struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
@@ -227,6 +228,7 @@ static const struct quirk_printer_struct quirk_printers[] = 
{
{ 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut 
 */
{ 0x04f9, 0x000d, USBLP_QUIRK_BIDIR }, /* Brother Industries, Ltd 
HL-1440 Laser Printer */
{ 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt 
Printer M129C */
+   { 0x0416, 0x5011, USBLP_QUIRK_NO_SET_INTF }, /* Winbond Electronics 
Corp. Virtual Com Port */
{ 0, 0 }
 };
 
@@ -1332,7 +1334,11 @@ static int usblp_set_protocol(struct usblp *usblp, int 
protocol)
alts = usblp->protocol[protocol].alt_setting;
if (alts < 0)
return -EINVAL;
-   r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
+   if (usblp->quirks & USBLP_QUIRK_NO_SET_INTF) {
+   r = 0;
+   } else {
+   r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
+   }
if (r < 0) {
printk(KERN_ERR "usblp: can't set desired altsetting %d on 
interface %d\n",
alts, usblp->ifnum);
-- 
2.29.0