diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..68bab25 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,156 @@ +name: Build & Validate Drivers + +on: + push: + branches: ['v5.4', 'v5.15', 'v6.1', 'v6.6', 'v6.12'] + workflow_dispatch: + +concurrency: + group: build-${{ github.ref_name }} + cancel-in-progress: true + +jobs: + setup: + runs-on: ubuntu-latest + outputs: + kv: ${{ steps.m.outputs.kv }} + major: ${{ steps.m.outputs.major }} + steps: + - id: m + run: | + REF="${GITHUB_REF_NAME}" + [[ "$REF" == */merge ]] && REF="${{ github.head_ref }}" + KV="${REF#v}" + echo "kv=${KV}" >> "$GITHUB_OUTPUT" + echo "major=${KV%%.*}" >> "$GITHUB_OUTPUT" + + validate-patches: + needs: setup + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Download & validate patches + shell: bash + run: | + set -euo pipefail + KV="${{ needs.setup.outputs.kv }}" + MAJ="${{ needs.setup.outputs.major }}" + curl -fSL --retry 3 -o /tmp/linux.tar.xz "https://cdn.kernel.org/pub/linux/kernel/v${MAJ}.x/linux-${KV}.tar.xz" + mkdir -p /tmp/linux-src + tar xf /tmp/linux.tar.xz -C /tmp/linux-src --strip-components=1 + cd /tmp/linux-src + ERRORS=0 + for pf in "$GITHUB_WORKSPACE/patches"/*.patch; do + [ -f "$pf" ] || continue + name=$(basename "$pf") + head -1 "$pf" | grep -q "No changes" && echo "⊘ $name: no changes needed" && continue + echo "→ $name" + patch --dry-run -p1 < "$pf" && echo "✓ $name" || { echo "✗ $name FAILED"; ERRORS=$((ERRORS+1)); } + done + exit $ERRORS + + build-out-of-tree: + needs: setup + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + - name: Install deps + run: sudo apt-get update -qq && sudo apt-get install -y -qq build-essential libelf-dev bc flex bison + + - name: Download kernel ${{ needs.setup.outputs.kv }} + shell: bash + run: | + set -euo pipefail + KV="${{ needs.setup.outputs.kv }}" + MAJ="${{ needs.setup.outputs.major }}" + curl -fSL --retry 3 -o /tmp/linux.tar.xz "https://cdn.kernel.org/pub/linux/kernel/v${MAJ}.x/linux-${KV}.tar.xz" + tar xf /tmp/linux.tar.xz -C /tmp --strip-components=1 + + - name: Configure & build kernel with USB/NET subsystems + shell: bash + run: | + set -euo pipefail + cd /tmp + make allnoconfig > /tmp/allnoconfig.log 2>&1 + scripts/config --enable CONFIG_64BIT || true + scripts/config --enable CONFIG_MODULES + scripts/config --enable CONFIG_PRINTK + scripts/config --enable CONFIG_PROC_FS + scripts/config --enable CONFIG_SYSFS + scripts/config --enable CONFIG_DEVTMPFS + scripts/config --enable CONFIG_TTY + scripts/config --enable CONFIG_BLOCK + scripts/config --enable CONFIG_GENERIC_ALLOCATOR + scripts/config --enable CONFIG_NET + scripts/config --enable CONFIG_INET + scripts/config --enable CONFIG_CRC32 + scripts/config --enable CONFIG_CRC16 + scripts/config --enable CONFIG_CRC_CCITT + scripts/config --enable CONFIG_USB + scripts/config --enable CONFIG_USB_SUPPORT || true + scripts/config --enable CONFIG_USB_COMMON || true + scripts/config --enable CONFIG_USB_ARCH_HAS_HCD || true + scripts/config --enable CONFIG_USB_ANNOUNCE_NEW_DEVICES || true + scripts/config --set-val CONFIG_USB_SERIAL y + scripts/config --enable CONFIG_USB_SERIAL_CONSOLE || true + scripts/config --enable CONFIG_USB_SERIAL_WWAN || true + scripts/config --enable CONFIG_USB_SERIAL_OPTION || true + scripts/config --enable CONFIG_USB_NET_DRIVERS || true + scripts/config --enable CONFIG_USB_ACM || true + scripts/config --enable CONFIG_WWAN || true + scripts/config --enable CONFIG_WWAN_CORE || true + scripts/config --enable CONFIG_MODULE_UNLOAD || true + scripts/config --enable CONFIG_NET_CORE || true + scripts/config --enable CONFIG_FIB_RULES || true + scripts/config --enable CONFIG_MULTIUSER || true + scripts/config --enable CONFIG_FUTEX || true + scripts/config --enable CONFIG_RATIONAL || true + scripts/config --enable CONFIG_CRC32_SLICEBY8 || true + scripts/config --disable CONFIG_STACK_VALIDATION || true + make olddefconfig > /tmp/olddefconfig.log 2>&1 || { tail -100 /tmp/olddefconfig.log; exit 1; } + grep -E 'CONFIG_(USB_SERIAL|USB_NET|WWAN|MODULES|STACK_VALIDATION)[= ]' .config | head -20 || true + make vmlinux -j$(nproc) SKIP_STACK_VALIDATION=1 HOSTCFLAGS="-Wno-error" > /tmp/vmlinux.log 2>&1 || { tail -200 /tmp/vmlinux.log; exit 1; } + make modules_prepare SKIP_STACK_VALIDATION=1 HOSTCFLAGS="-Wno-error" > /tmp/modules_prepare.log 2>&1 || { tail -200 /tmp/modules_prepare.log; exit 1; } + [ -f /tmp/vmlinux ] && echo '✓ vmlinux built' + [ -f /tmp/Module.symvers ] && echo '✓ Module.symvers present' || echo '! Module.symvers still missing; modpost warnings will be tolerated' + + - name: Build out-of-tree drivers + shell: bash + run: | + set -euo pipefail + make KDIR=/tmp KBUILD_MODPOST_WARN=1 2>&1 | tee /tmp/build.log + echo "=== Build log ===" + tail -40 /tmp/build.log + + - name: Verify modules + shell: bash + run: | + set -euo pipefail + ERRORS=0 + for mod in option.ko usb_wwan.ko qmi_wwan.ko; do + found=$(find build/ -name "$mod" -print -quit 2>/dev/null || true) + if [ -n "$found" ]; then + echo "✓ $mod" + else + echo "✗ $mod NOT found" + ERRORS=$((ERRORS + 1)) + fi + done + if grep -E 'fatal error:' /tmp/build.log; then + echo "✗ Compilation errors!" + ERRORS=$((ERRORS + 1)) + fi + exit $ERRORS + + summary: + needs: [setup, validate-patches, build-out-of-tree] + if: always() + runs-on: ubuntu-latest + steps: + - run: | + echo "## kernel ${{ needs.setup.outputs.kv }}" + echo "patches: ${{ needs.validate-patches.result }}" + echo "build: ${{ needs.build-out-of-tree.result }}" + [ "${{ needs.validate-patches.result }}" = "success" ] && [ "${{ needs.build-out-of-tree.result }}" = "success" ] || exit 1 diff --git a/LICENSE b/LICENSE index 24b410b..4d5d22b 100644 --- a/LICENSE +++ b/LICENSE @@ -4,4 +4,4 @@ Version 2, June 1991 This driver is licensed under the GNU General Public License v2.0 only (GPL-2.0-only), consistent with the Linux kernel license under which the original source code is distributed. -See: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +See: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0c826a8 --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +# Quectel USB Driver Out-of-Tree Build +# +# Copies your kernel's own upstream driver sources, applies Quectel +# enhancement patches (additional device IDs), and builds the modules. +# +# Usage: +# make # uses running kernel headers +# make KDIR=/path/to/kernel # uses specified kernel source +# make install # install built modules + +KDIR ?= /lib/modules/$(shell uname -r)/build +BUILD_DIR := build +KBUILD_MODPOST_WARN ?= 1 + +SERIAL_SRC := $(KDIR)/drivers/usb/serial +NET_SRC := $(KDIR)/drivers/net/usb + +.PHONY: all clean install + +all: prepare + $(MAKE) -C $(KDIR) M=$(CURDIR)/$(BUILD_DIR)/serial KBUILD_MODPOST_WARN=$(KBUILD_MODPOST_WARN) modules + $(MAKE) -C $(KDIR) M=$(CURDIR)/$(BUILD_DIR)/net KBUILD_MODPOST_WARN=$(KBUILD_MODPOST_WARN) modules + +prepare: + @echo "=== Quectel USB Driver Out-of-Tree Build ===" + @mkdir -p $(BUILD_DIR)/serial $(BUILD_DIR)/net + @# Copy upstream sources from kernel tree + @test -f "$(SERIAL_SRC)/option.c" && cp "$(SERIAL_SRC)/option.c" "$(BUILD_DIR)/serial/option.c" || echo "WARN: option.c not found" + @test -f "$(SERIAL_SRC)/usb_wwan.c" && cp "$(SERIAL_SRC)/usb_wwan.c" "$(BUILD_DIR)/serial/usb_wwan.c" || echo "WARN: usb_wwan.c not found" + @test -f "$(SERIAL_SRC)/usb-wwan.h" && cp "$(SERIAL_SRC)/usb-wwan.h" "$(BUILD_DIR)/serial/usb-wwan.h" || echo "WARN: usb-wwan.h not found" + @test -f "$(NET_SRC)/qmi_wwan.c" && cp "$(NET_SRC)/qmi_wwan.c" "$(BUILD_DIR)/net/qmi_wwan.c" || echo "WARN: qmi_wwan.c not found" + @# Apply Quectel enhancement patches for build/ layout + @if [ -f patches/option.c.patch ] && ! head -1 patches/option.c.patch | grep -q "No changes"; then patch -p4 -d $(BUILD_DIR)/serial < patches/option.c.patch || echo "NOTE: option.c patch may conflict"; fi + @if [ -f patches/qmi_wwan.c.patch ] && ! head -1 patches/qmi_wwan.c.patch | grep -q "No changes"; then patch -p4 -d $(BUILD_DIR)/net < patches/qmi_wwan.c.patch || echo "NOTE: qmi_wwan.c patch may conflict"; fi + @# Write Kbuild files + @echo 'obj-m += option.o usb_wwan.o' > $(BUILD_DIR)/serial/Kbuild + @echo 'obj-m += qmi_wwan.o' > $(BUILD_DIR)/net/Kbuild + @echo "Sources prepared. Building..." + +install: + $(MAKE) -C $(KDIR) M=$(CURDIR)/$(BUILD_DIR)/serial KBUILD_MODPOST_WARN=$(KBUILD_MODPOST_WARN) modules_install + $(MAKE) -C $(KDIR) M=$(CURDIR)/$(BUILD_DIR)/net KBUILD_MODPOST_WARN=$(KBUILD_MODPOST_WARN) modules_install + @echo "Done. Run: depmod -a && modprobe -r option qmi_wwan && modprobe option && modprobe qmi_wwan" + +clean: + rm -rf $(BUILD_DIR) diff --git a/README.md b/README.md index c68687a..a0a0e46 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,45 @@ -# Quectel Linux USB Driver +# Quectel USB Driver Enhancements — Linux 6.12 -Out-of-tree and in-kernel-patch drivers for Quectel cellular modems, organized by Linux kernel LTS version. +Out-of-tree build support and in-kernel patches for comprehensive Quectel +modem support on Linux kernel **6.12**. -## Quick Start - -```bash -# 1. Find your kernel version -uname -r # e.g. 5.15.0-100-generic - -# 2. Checkout the matching branch -git clone https://github.com/bacnh85/Quectel_Linux_USB_Driver.git -cd Quectel_Linux_USB_Driver -git checkout v5.15 # use your major.minor version - -# 3. Follow the README.md on that branch -``` - -## Branches +## Supported Devices -| Branch | Kernel | Quectel Devices | Patch Size | -|--------|--------|----------------|------------| -| `v5.4` | 5.4.x LTS | +30 products | 59 lines | -| `v5.15` | 5.15.x LTS | +25 products | 54 lines | -| `v6.1` | 6.1.x LTS | +21 products | 44 lines | -| `v6.6` | 6.6.x LTS | +7 products | 16 lines | -| `v6.12` | 6.12.x | Full mainline | No patch needed | +EC200(A/S/T/U), EC25, EC21, EG91, EG95, EG912Y, EG916Q, EM05 (all variants), +EM06, EM12, EM060K, EM061K, RM500Q, RM500K, RM520N, RM500U, RG650V, BG95, BG96 -## What's in Each Branch - -All driver sources are **upstream Linux kernel code** enhanced with Quectel device IDs backported from kernel 6.12. - -``` -drivers/usb/serial/option.c ← enhanced with all Quectel USB serial IDs -drivers/usb/serial/usb_wwan.c ← upstream (no Quectel-specific changes) -drivers/usb/serial/usb-wwan.h ← upstream header -drivers/net/usb/qmi_wwan.c ← enhanced with all Quectel QMI IDs -patches/option.c.patch ← diff: vanilla → enhanced (for in-kernel) -patches/qmi_wwan.c.patch ← diff: vanilla → enhanced (for in-kernel) -Makefile ← out-of-tree module build -``` +## Quick Start -## Two Build Methods +### Out-of-Tree Build (Recommended) -### Method 1: Out-of-Tree (Recommended) ```bash -make && sudo make install -sudo modprobe option qmi_wwan +make KDIR=/lib/modules/$(uname -r)/build +sudo make install +sudo depmod -a ``` -### Method 2: In-Kernel Patch +### In-Kernel Patch + ```bash -cd /path/to/kernel-source -patch -p1 < /path/to/Quectel_Linux_USB_Driver/patches/option.c.patch +cd /path/to/linux-6.12 +patch -p1 < patches/option.c.patch +patch -p1 < patches/qmi_wwan.c.patch ``` -## Supported Quectel Modules +## Files -**2G/3G:** UC15, UC20 -**4G LTE:** EC20, EC21, EC25, EG91, EG95, BG96, BG95, AG35, EP06, EM12, EC200S, EC200T, EC200A, EC200U, EG912Y, EG916Q -**5G NR:** RM500Q, RM520N, RM500K, RM500U, RG650V, EM05G series, EM060K/EM061K series, EM160R-GL +| File | Description | +|------|-------------| +| `Makefile` | Out-of-tree build: copies from kernel, patches, builds | +| `patches/option.c.patch` | USB serial device IDs for Quectel modems | +| `patches/qmi_wwan.c.patch` | QMI network device IDs for Quectel modems | -## License +## Branches -GPL-2.0-only — same as the Linux kernel +| Branch | Kernel | +|--------|--------| +| `v5.4` | 5.4 LTS | +| `v5.15` | 5.15 LTS | +| `v6.1` | 6.1 LTS | +| `v6.6` | 6.6 LTS | +| `v6.12` | 6.12 | diff --git a/patches/option.c.patch b/patches/option.c.patch new file mode 100644 index 0000000..c7d6ae0 --- /dev/null +++ b/patches/option.c.patch @@ -0,0 +1 @@ +# No changes needed diff --git a/patches/qmi_wwan.c.patch b/patches/qmi_wwan.c.patch new file mode 100644 index 0000000..c7d6ae0 --- /dev/null +++ b/patches/qmi_wwan.c.patch @@ -0,0 +1 @@ +# No changes needed