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