kernel version: 4.14.141
The Serial Gadget talks to the Linux-USB generic serial driver.
This driver supports a CDC-ACM module option, which can be used
to interoperate with MS-Windows hosts or with the Linux-USB
"cdc-acm" driver.
This driver also supports a CDC-OBEX option. You will need a
user space OBEX server talking to /dev/ttyGS*, since the kernel
itself doesn't implement the OBEX protocol.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_serial".
For more information, see Documentation/usb/gadget_serial.txt
which includes instructions and a "driver info file" needed to
make MS-Windows work with CDC ACM.
1. kernel config
USB Gadget Support
build modules
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules -j8
LD [M] drivers/usb/gadget/function/u_serial.ko
LD [M] drivers/usb/gadget/function/usb_f_acm.ko
LD [M] drivers/usb/gadget/function/usb_f_obex.ko
LD [M] drivers/usb/gadget/function/usb_f_serial.ko
LD [M] drivers/usb/gadget/legacy/g_serial.ko
LD [M] drivers/usb/gadget/libcomposite.ko
2. enable
2.1 enable it in device
1) To load it as an ACM device (recommended for interoperability), do this:
modprobe g_serial
OR
insmod ./function/u_serial.ko
insmod libcomposite.ko
insmod ./function/usb_f_serial.ko
insmod ./function/usb_f_acm.ko
insmod ./legacy/g_serial.ko
2) To load it as a vendor specific bulk in/out device, do this:
modprobe g_serial use_acm=0
3) after insmod
/dev/ttyGS0
or
/dev/ttygserial
2.2 enable it in host
1) On a Linux host running the ACM driver
/dev/ttyACM0
2) On a Linux host running the USB generic serial driver
/dev/ttyUSB0
3) On win10 host
ACM driver will be installed automaticlly.
3. test ACM on win10
test mc40 usb2.0 device in haps
3.1 config & build module, then copy these KO to ~/repo-usb/rootfs/rootfs-m/opt/ko/usb
~/repo-usb/rootfs/rootfs-m/opt/ko/usb$ tree
.
└── gadget
├── function
│ ├── usb_f_acm.ko
│ ├── usb_f_obex.ko
│ ├── usb_f_serial.ko
│ └── u_serial.ko
├── legacy
│ └── g_serial.ko
└── libcomposite.ko
3.2 boot kernel and insmod ko(enable ACM gadget)
cd /opt/ko/usb/gadget/
insmod ./function/u_serial.ko
insmod libcomposite.ko
insmod ./function/usb_f_acm.ko
insmod ./legacy/g_serial.ko
Note: usb_f_obex.ko and usb_f_serial.ko is not necessary.
3.3 check if usb gadget is ok or not
1) on device
# cd /opt/ko/usb/gadget/
#
# insmod ./function/u_serial.ko
# insmod libcomposite.ko
# insmod ./function/usb_f_acm.ko
# insmod ./legacy/g_serial.ko
[ 1932.988112] g_serial gadget: high-speed config #2: CDC ACM config
#
# ls /dev/ttyGS0
/dev/ttyGS0
2) on win10 host
3.4 device send data to host
1) device
echo "hello usb2.0 gadget" > /dev/ttyGS0
2) win10 host
3.5 host send data to device
1) device
cat /dev/ttyGS0
2) win10 host
Note: xcom received a copy. it's ok when we use microcom to open /dev/ttyGS0
device:
4. test ACM on ubuntu16
ubuntu ver: ubuntu16.04 gnome(kernel 4.14)
test mc40 usb2.0 device in haps
4.1 config & build module, then copy these KO to ~/repo-usb/rootfs/rootfs-m/opt/ko/usb
~/repo-usb/rootfs/rootfs-m/opt/ko/usb$ tree
.
└── gadget
├── function
│ ├── usb_f_acm.ko
│ ├── usb_f_obex.ko
│ ├── usb_f_serial.ko
│ └── u_serial.ko
├── legacy
│ └── g_serial.ko
└── libcomposite.ko
4.2 boot kernel and insmod ko(enable ACM gadget)
cd /opt/ko/usb/gadget/
insmod ./function/u_serial.ko
insmod libcomposite.ko
insmod ./function/usb_f_acm.ko
insmod ./legacy/g_serial.ko
Note: usb_f_obex.ko and usb_f_serial.ko is not necessary.
4.3 check if usb gadget is ok or not
1) on device
# ls /dev/ttyGS0
/dev/ttyGS0
2) on ubuntu host
4.4 device send data to host
1) device
echo "hello usb2.0 gadget" > /dev/ttyGS0
2) ubuntu host
cat /dev/ttyACM0
4.5 host send data to device
1) device
cat /dev/ttyGS0
2) ubuntu host
echo "hello usb2.0 gadget" > /dev/ttyACM0
5. test g_serial on ubuntu16
ubuntu ver: ubuntu16.04 gnome(kernel 4.14)
test mc40 usb2.0 device in haps
5.1 config & build module, then copy these KO to ~/repo-usb/rootfs/rootfs-m/opt/ko/usb
~/repo-usb/rootfs/rootfs-m/opt/ko/usb$ tree
.
└── gadget
├── function
│ ├── usb_f_acm.ko
│ ├── usb_f_obex.ko
│ ├── usb_f_serial.ko
│ └── u_serial.ko
├── legacy
│ └── g_serial.ko
└── libcomposite.ko
5.2 boot kernel and insmod ko(enable ACM gadget)
cd /opt/ko/usb/gadget/
insmod ./function/u_serial.ko
insmod libcomposite.ko
insmod ./function/usb_f_serial.ko
insmod ./legacy/g_serial.ko use_acm=0
Note: usb_f_obex.ko and usb_f_acm.ko is not necessary.
after insmod ./legacy/g_serial.ko use_acm=0
[14517.574335] g_serial gadget: Gadget Serial v2.4
[14517.621586] g_serial gadget: g_serial ready
[14529.599420] g_serial gadget: high-speed config #1: Generic Serial config
5.3 check if usb gadget is ok or not
1) on device
# ls /dev/ttyGS0
/dev/ttyGS0
2) on ubuntu host
we need to install Linux USB generic serial driver, i have no time to study it now!
6. test g_serial on win10
test mc40 usb2.0 device in haps
6.1 config & build module, then copy these KO to ~/repo-usb/rootfs/rootfs-m/opt/ko/usb
~/repo-usb/rootfs/rootfs-m/opt/ko/usb$ tree
.
└── gadget
├── function
│ ├── usb_f_acm.ko
│ ├── usb_f_obex.ko
│ ├── usb_f_serial.ko
│ └── u_serial.ko
├── legacy
│ └── g_serial.ko
└── libcomposite.ko
6.2 boot kernel and insmod ko(enable ACM gadget)
cd /opt/ko/usb/gadget/
insmod ./function/u_serial.ko
insmod libcomposite.ko
insmod ./function/usb_f_serial.ko
insmod ./legacy/g_serial.ko
Note: usb_f_obex.ko and usb_f_acm.ko is not necessary.
after insmod ./legacy/g_serial.ko use_acm=0
[14517.574335] g_serial gadget: Gadget Serial v2.4
[14517.621586] g_serial gadget: g_serial ready
[14529.599420] g_serial gadget: high-speed config #1: Generic Serial config
6.3 check if usb gadget is ok or not
1) on device
# ls /dev/ttyGS0
/dev/ttyGS0
2) on win10 host
driver fail to install, win10 need digital signature. win7 maybe is ok.
7. other
serial.c:
#define GS_VENDOR_ID 0x0525 /* NetChip */
#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */
#define GS_CDC_PRODUCT_ID 0xa4a7 /* ... as CDC-ACM */
#define GS_CDC_OBEX_PRODUCT_ID 0xa4a9 /* ... as CDC-OBEX */
static int __init init(void)
{
/* We *could* export two configs; that'd be much cleaner...
* but neither of these product IDs was defined that way.
*/
if (use_acm) {
serial_config_driver.label = "CDC ACM config";
serial_config_driver.bConfigurationValue = 2;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_PRODUCT_ID);
} else if (use_obex) {
serial_config_driver.label = "CDC OBEX config";
serial_config_driver.bConfigurationValue = 3;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
} else {
serial_config_driver.label = "Generic Serial config";
serial_config_driver.bConfigurationValue = 1;
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
device_desc.idProduct =
cpu_to_le16(GS_PRODUCT_ID);
}
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
return usb_composite_probe(&gserial_driver);
}
the device has three config(function)
CDC ACM
CDC OBEX
Generic Serial