From 75602288c0566ad697b6ca4414b8bf846b7c854c Mon Sep 17 00:00:00 2001
From: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
Date: Fri, 24 Feb 2023 12:08:07 +0100
Subject: [PATCH] default: gadget: Use CDC-NCM instead of CDC-ECM

Citing Wikipedia [0]:

    Of these protocols [RNDIS, ECM, EEM and NCM] ECM could be classified
    the simplest - frames are simply sent and received without modification
    one at a time. This was a satisfactory strategy for USB 1.1 systems
    (current when the protocol was issued) with 64 byte packets but not for
    USB 2.0 systems which use 512 byte packets.

We're already using USB 3.0, so we should switch away from ECM.
Reasonable alternatives include EEM and NCM (RNDIS is a proprietary
Windows protocol, which - although supported by Linux - is considered
unsafe and may get removed [1]).

Bandwidth tests with iperf3 gave me these results:
 - ECM: 526 Mbits/sec
 - EEM: 761 Mbits/sec
 - NCM: 1.67 Gbits/sec

While NCM is newer, it's been supported in Linux since 2.6.37 already,
which is quite ancient by today's standards, so switching to it
should be safe for any kind of reasonably modern Linux host (plus we still
expose ACM serial that will be available even if NCM is not supported,
so basic communication with the device will still be possible).

It also has an added bonus of being supported in Windows 10 and
later, while ECM and EEM aren't supported there at all.

Therefore, switch the Ethernet gadget to use NCM.

[0] https://en.wikipedia.org/wiki/Ethernet_over_USB
[1] https://lore.kernel.org/lkml/20221123124620.1387499-1-gregkh@linuxfoundation.org/
---
 default/gadget/usb_gadget_start | 10 +++++-----
 default/gadget/usb_gadget_stop  |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/default/gadget/usb_gadget_start b/default/gadget/usb_gadget_start
index 4751ef4..f7f971b 100755
--- a/default/gadget/usb_gadget_start
+++ b/default/gadget/usb_gadget_start
@@ -20,16 +20,16 @@ mkdir -p strings/${ENGLISH}
 echo "0123456789" > strings/${ENGLISH}/serialnumber
 echo "Purism, SPC" > strings/${ENGLISH}/manufacturer
 echo "Librem 5" > strings/${ENGLISH}/product
-mkdir -p functions/ecm.usb0 #ethernet
+mkdir -p functions/ncm.usb0 #ethernet
 mkdir -p functions/acm.GS0 # serial
 mkdir -p configs/c.1/strings/${ENGLISH}
-echo "CDC ACM+ECM" > configs/c.1/strings/${ENGLISH}/configuration
+echo "CDC ACM+NCM" > configs/c.1/strings/${ENGLISH}/configuration
 if [ -n "${HOST_ADDR}" ]; then
-    echo "${HOST_ADDR}" > functions/ecm.usb0/host_addr
+    echo "${HOST_ADDR}" > functions/ncm.usb0/host_addr
 fi
 if [ -n "${DEV_ADDR}" ]; then
-    echo "${DEV_ADDR}" > functions/ecm.usb0/dev_addr
+    echo "${DEV_ADDR}" > functions/ncm.usb0/dev_addr
 fi
 ln -sf functions/acm.GS0 configs/c.1
-ln -sf functions/ecm.usb0 configs/c.1
+ln -sf functions/ncm.usb0 configs/c.1
 echo "38100000.usb" > UDC # Bind to the L5 USB controller
diff --git a/default/gadget/usb_gadget_stop b/default/gadget/usb_gadget_stop
index 5e6ef4e..1030b71 100755
--- a/default/gadget/usb_gadget_stop
+++ b/default/gadget/usb_gadget_stop
@@ -2,4 +2,4 @@
 set -e
 cd /sys/kernel/config/usb_gadget/g1
 echo "" > UDC
-rm configs/c.1/acm.GS0 configs/c.1/ecm.usb0
+rm configs/c.1/acm.GS0 configs/c.1/ncm.usb0
-- 
GitLab