Re: Problem of Serial_State in cdc-acm.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Freitag, den 10.03.2017, 17:20 +0800 schrieb 家瑋:
> 


Hi,

>     I have encounter a problem while sending Serial_State packet of
> CDC-ACM from Linux gadget to Linux host .
> Here is my question:
>     The environment is a USB device which runs Linux is using
> CDC-ACM(f_acm.c) to communicate with a Linux host(cdc-acm.c). When
> device tries to send Serial_State packet to host, host always can't
> get correct data. I look into the host driver(cdc-acm.c) and found
> driver calls get_unaligned_le16 on data and this function inverts
> byte
> order of data.
>     Following is the link of cdc-acm.c and f_acm.c
> ACM host:     http://lxr.free-electrons.com/source/drivers/usb/class/
> cdc-acm.c#L325
> ACM gadget:    http://lxr.free-electrons.com/source/drivers/usb/gadge
> t/function/f_acm.c#L493
>     From the current code, gadget send Serial_State in big-endian but
> host treat it as little-endian.
> Is this a problem?

Yes, it is. The gadget driver is exporting its internal endianness.

> Appreciate for your time
> 
Please test the attached patch.

	Regards
		Oliver
From cd9678d5482937907be3d238da8f4078bfdad796 Mon Sep 17 00:00:00 2001
From: Oliver Neukum <oneukum@xxxxxxxx>
Date: Fri, 10 Mar 2017 12:25:26 +0100
Subject: [PATCH] ACM gadget: fix endianness in notifications

The gadget code exports the bitfield for serial status changes
over the wire in its internal endianness. The fix is to convert
to little endian before sending it over the wire.

Signed-off-by: Oliver Neukum <oneukum@xxxxxxxx>
CC: stable@xxxxxxxxxxxxxxx
---
 drivers/usb/gadget/function/f_acm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c
index a30766c..5e3828d 100644
--- a/drivers/usb/gadget/function/f_acm.c
+++ b/drivers/usb/gadget/function/f_acm.c
@@ -535,13 +535,15 @@ static int acm_notify_serial_state(struct f_acm *acm)
 {
 	struct usb_composite_dev *cdev = acm->port.func.config->cdev;
 	int			status;
+	__le16			serial_state;
 
 	spin_lock(&acm->lock);
 	if (acm->notify_req) {
 		dev_dbg(&cdev->gadget->dev, "acm ttyGS%d serial state %04x\n",
 			acm->port_num, acm->serial_state);
+		serial_state = cpu_to_le16(acm->serial_state);
 		status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
-				0, &acm->serial_state, sizeof(acm->serial_state));
+				0, &serial_state, sizeof(acm->serial_state));
 	} else {
 		acm->pending = true;
 		status = 0;
-- 
2.10.2


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux