[PATCH] usb: cdc_acm: Add quirk for Elatec TWN3

2017-10-11 Thread Maksim Salau
Elatec TWN3 has the union descriptor on data interface. This results in
failure to bind the device to the driver with the following log:
  usb 1-1.2: new full speed USB device using streamplug-ehci and address 4
  usb 1-1.2: New USB device found, idVendor=09d8, idProduct=0320
  usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
  usb 1-1.2: Product: RFID Device (COM)
  usb 1-1.2: Manufacturer: OEM
  cdc_acm 1-1.2:1.0: Zero length descriptor references
  cdc_acm: probe of 1-1.2:1.0 failed with error -22

Adding the NO_UNION_NORMAL quirk for the device fixes the issue.

Signed-off-by: Maksim Salau 
---

`lsusb -v` of the device:

Bus 001 Device 003: ID 09d8:0320
Device Descriptor:
  bLength18
  bDescriptorType 1
  bcdUSB   2.00
  bDeviceClass2 Communications
  bDeviceSubClass 0
  bDeviceProtocol 0
  bMaxPacketSize032
  idVendor   0x09d8
  idProduct  0x0320
  bcdDevice3.00
  iManufacturer   1 OEM
  iProduct2 RFID Device (COM)
  iSerial 0
  bNumConfigurations  1
  Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength   67
bNumInterfaces  2
bConfigurationValue 1
iConfiguration  0
bmAttributes 0x80
  (Bus Powered)
MaxPower  250mA
Interface Descriptor:
  bLength 9
  bDescriptorType 4
  bInterfaceNumber0
  bAlternateSetting   0
  bNumEndpoints   1
  bInterfaceClass 2 Communications
  bInterfaceSubClass  2 Abstract (modem)
  bInterfaceProtocol  1 AT-commands (v.25ter)
  iInterface  0
  Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83  EP 3 IN
bmAttributes3
  Transfer TypeInterrupt
  Synch Type   None
  Usage Type   Data
wMaxPacketSize 0x0020  1x 32 bytes
bInterval   2
Interface Descriptor:
  bLength 9
  bDescriptorType 4
  bInterfaceNumber1
  bAlternateSetting   0
  bNumEndpoints   2
  bInterfaceClass10 CDC Data
  bInterfaceSubClass  0 Unused
  bInterfaceProtocol  0
  iInterface  0
  Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02  EP 2 OUT
bmAttributes2
  Transfer TypeBulk
  Synch Type   None
  Usage Type   Data
wMaxPacketSize 0x0020  1x 32 bytes
bInterval   0
  Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81  EP 1 IN
bmAttributes2
  Transfer TypeBulk
  Synch Type   None
  Usage Type   Data
wMaxPacketSize 0x0020  1x 32 bytes
bInterval   0
  CDC Header:
bcdCDC   1.10
  CDC Call Management:
bmCapabilities   0x03
  call management
  use DataInterface
bDataInterface  1
  CDC ACM:
bmCapabilities   0x06
  sends break
  line coding and serial state
  CDC Union:
bMasterInterface0
bSlaveInterface 1 
Device Status: 0x
  (Bus Powered)


 drivers/usb/class/cdc-acm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 5e056064..18c923a 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1832,6 +1832,9 @@ static const struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */
.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
},
+   { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */
+   .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */
+   },
 
{ USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
.driver_info = CLEAR_HALT_CONDITIONS,
-- 
2.7.4



Re: [PATCH 3.16 084/134] usb: misc: legousbtower: Fix buffers on stack

2017-08-18 Thread Maksim Salau
On Fri, 18 Aug 2017 14:13:20 +0100
Ben Hutchings  wrote:

> 3.16.47-rc1 review patch.  If anyone has any objections, please let me know.
> 
> --
> 
> From: Maksim Salau 
> 
> commit 942a48730faf149ccbf3e12ac718aee120bb3529 upstream.
> 
> Allocate buffers on HEAP instead of STACK for local structures
> that are to be received using usb_control_msg().

Hi Ben,

The change has a memory leak, which is fixed by the commit
0bd193d62b4270a2a7a09da43ad1034c7ca5b3d3
If the commit is not in your queue, please add it.

Thanks,
Maksim.




[PATCH v2] usb: misc: legousbtower: Fix memory leak

2017-05-13 Thread Maksim Salau
get_version_reply is not freed if function returns with success.

Fixes: 942a48730faf ("usb: misc: legousbtower: Fix buffers on stack")
Reported-by: Heikki Krogerus 
Signed-off-by: Maksim Salau 
---

 v2:
 Changed tags to match guidelines.

 drivers/usb/misc/legousbtower.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index aa3c280fdf8d..0782ac6f5edf 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -926,6 +926,7 @@ static int tower_probe (struct usb_interface *interface, 
const struct usb_device
 USB_MAJOR, dev->minor);
 
 exit:
+   kfree(get_version_reply);
return retval;
 
 error:
-- 
2.9.3



[PATCH] usb: misc: legousbtower: Fix memory leak

2017-05-04 Thread Maksim Salau
get_version_reply is not freed if function returns with success.
Memory leak was introduced by commit 942a48730faf149ccbf3e12ac718aee120bb3529

Signed-off-by: Heikki Krogerus 
Signed-off-by: Maksim Salau 
---
 drivers/usb/misc/legousbtower.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index aa3c280..0782ac6 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -926,6 +926,7 @@ static int tower_probe (struct usb_interface *interface, 
const struct usb_device
 USB_MAJOR, dev->minor);
 
 exit:
+   kfree(get_version_reply);
return retval;
 
 error:
-- 
2.9.3



Re: [PATCH v3] usb: misc: legousbtower: Fix buffers on stack

2017-05-04 Thread Maksim Salau
> > @@ -913,6 +929,7 @@ static int tower_probe (struct usb_interface 
> > *interface, const struct usb_device  
> 
> Don't you need to free get_version_reply here?
> 
> > return retval;
> >  
> >  error:
> > +   kfree(get_version_reply);
> > tower_delete(dev);
> > return retval;
> >  }  

Thank you very much, Heikki!

I was so focused on failure cases, that missed memory leak in the case
 when all calls succeeded.

I'll prepare a patch shortly to fix this.

Regards,
Maksim.


Re: [PATCH v3] usb: misc: legousbtower: Fix buffers on stack

2017-04-26 Thread Maksim Salau
> >* removed Tested-by: Alfredo Rafael Vicente Boix ;
> 
> I added this back, as it matters, and your change from the previous
> version was trivial.
>   
> >* removed Cc: sta...@vger.kernel.org
> >  since this patch doesn't apply against v4.10.12
> 
> I added this back as well :)  

Thanks, Greg!

I was not sure about how strict are the rules about these tags.

Maksim.


[PATCH v3] usb: misc: legousbtower: Fix buffers on stack

2017-04-25 Thread Maksim Salau
Allocate buffers on HEAP instead of STACK for local structures
that are to be received using usb_control_msg().

Signed-off-by: Maksim Salau 

---
  Changes in v3:
   * rebased against usb-next;
   * removed Tested-by: Alfredo Rafael Vicente Boix ;
   * removed Cc: sta...@vger.kernel.org
 since this patch doesn't apply against v4.10.12
  Changes in v2:
   * made checkpatch happy with the format string passed to dev_info
 in tower_probe() (merged two parts into a single string literal);
   * changed commit message to better reflect location of the module;
 was: USB: legousbtower: Fix buffers on stack;
   * added Tested-by: Alfredo Rafael Vicente Boix 
 and Cc: sta...@vger.kernel.org

 drivers/usb/misc/legousbtower.c | 37 +++--
 1 file changed, 27 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 201c9c3..aa3c280 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -317,9 +317,16 @@ static int tower_open (struct inode *inode, struct file 
*file)
int subminor;
int retval = 0;
struct usb_interface *interface;
-   struct tower_reset_reply reset_reply;
+   struct tower_reset_reply *reset_reply;
int result;
 
+   reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL);
+
+   if (!reset_reply) {
+   retval = -ENOMEM;
+   goto exit;
+   }
+
nonseekable_open(inode, file);
subminor = iminor(inode);
 
@@ -364,8 +371,8 @@ static int tower_open (struct inode *inode, struct file 
*file)
  USB_TYPE_VENDOR | USB_DIR_IN | 
USB_RECIP_DEVICE,
  0,
  0,
- &reset_reply,
- sizeof(reset_reply),
+ reset_reply,
+ sizeof(*reset_reply),
  1000);
if (result < 0) {
dev_err(&dev->udev->dev,
@@ -406,6 +413,7 @@ static int tower_open (struct inode *inode, struct file 
*file)
mutex_unlock(&dev->lock);
 
 exit:
+   kfree(reset_reply);
return retval;
 }
 
@@ -806,7 +814,7 @@ static int tower_probe (struct usb_interface *interface, 
const struct usb_device
struct device *idev = &interface->dev;
struct usb_device *udev = interface_to_usbdev(interface);
struct lego_usb_tower *dev = NULL;
-   struct tower_get_version_reply get_version_reply;
+   struct tower_get_version_reply *get_version_reply = NULL;
int retval = -ENOMEM;
int result;
 
@@ -871,6 +879,13 @@ static int tower_probe (struct usb_interface *interface, 
const struct usb_device
dev->interrupt_in_interval = interrupt_in_interval ? 
interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
dev->interrupt_out_interval = interrupt_out_interval ? 
interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
 
+   get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL);
+
+   if (!get_version_reply) {
+   retval = -ENOMEM;
+   goto error;
+   }
+
/* get the firmware version and log it */
result = usb_control_msg (udev,
  usb_rcvctrlpipe(udev, 0),
@@ -878,18 +893,19 @@ static int tower_probe (struct usb_interface *interface, 
const struct usb_device
  USB_TYPE_VENDOR | USB_DIR_IN | 
USB_RECIP_DEVICE,
  0,
  0,
- &get_version_reply,
- sizeof(get_version_reply),
+ get_version_reply,
+ sizeof(*get_version_reply),
  1000);
if (result < 0) {
dev_err(idev, "LEGO USB Tower get version control request 
failed\n");
retval = result;
goto error;
}
-   dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d "
-"build %d\n", get_version_reply.major,
-get_version_reply.minor,
-le16_to_cpu(get_version_reply.build_no));
+   dev_info(&interface->dev,
+"LEGO USB Tower firmware version is %d.%d build %d\n",
+get_version_reply->major,
+get_version_reply->minor,
+le16_to_cpu(get_version_reply->build_no));
 
/* we can register the device now, as it is ready */
usb_set_intfdata (interface, dev);
@@ -913,6 +929,7 @@ static int tower_probe (struct usb_interface *interface, 
const struct usb_device
return retval;
 
 error:
+   kfree(get_version_reply);
tower_delete(dev);
return retval;
 }
-- 
2.9.3



Re: [PATCH v2] usb: core: Warn if an URB's transfer_buffer is on stack

2017-04-25 Thread Maksim Salau
> + } else if (object_is_on_stack(urb->transfer_buffer)) {
> + WARN_ONCE(1, "transfer buffer is on stack\n");
> + ret = -EAGAIN;
>   } else {

Hi,

Has anyone considered a fail-safe mode? I.e.: if a buffer is on stack,
kmemdup it and continue with a warning. This will give us both: functional
drivers (with possibly decreased efficiency in speed and memory footprint)
and warnings for developers that a particular driver requires attention.

This mode will not affect drivers which obey the rules, but will make
offenders at least functional. My main concern is that not every user is able
to detect and report a problem, which prevents drivers from functioning.
Especially this is a problem for not wide spread devices.
Due to this users a seeing unusable equipment, but developers are not
aware of those, even if fixes are trivial.

Such mode has a also a negative effect: if a developer has a device
with an offending driver, he can miss the warning message, since the driver
just works.

Regards,
Maksim.


[PATCH] usb: serial: upd78f0730: Make constants static

2017-04-24 Thread Maksim Salau
Some local constants don't change from call to call and are good
candidates to become static. This will prevent copying of these
constants to stack during runtime.

Signed-off-by: Maksim Salau 
---
 drivers/usb/serial/upd78f0730.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/serial/upd78f0730.c b/drivers/usb/serial/upd78f0730.c
index a028dd2..6819a34 100644
--- a/drivers/usb/serial/upd78f0730.c
+++ b/drivers/usb/serial/upd78f0730.c
@@ -288,7 +288,7 @@ static void upd78f0730_dtr_rts(struct usb_serial_port 
*port, int on)
 static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty)
 {
const speed_t baud_rate = tty_get_baud_rate(tty);
-   const speed_t supported[] = {
+   static const speed_t supported[] = {
0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600
};
int i;
@@ -384,7 +384,7 @@ static void upd78f0730_set_termios(struct tty_struct *tty,
 
 static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port 
*port)
 {
-   struct upd78f0730_open_close request = {
+   static const struct upd78f0730_open_close request = {
.opcode = UPD78F0730_CMD_OPEN_CLOSE,
.state = UPD78F0730_PORT_OPEN
};
@@ -402,7 +402,7 @@ static int upd78f0730_open(struct tty_struct *tty, struct 
usb_serial_port *port)
 
 static void upd78f0730_close(struct usb_serial_port *port)
 {
-   struct upd78f0730_open_close request = {
+   static const struct upd78f0730_open_close request = {
.opcode = UPD78F0730_CMD_OPEN_CLOSE,
.state = UPD78F0730_PORT_CLOSE
};
-- 
2.9.3