From aa9d18bf7d9ff9e9fd8c097a63c907c768f24e64 Mon Sep 17 00:00:00 2001 From: Hang Zhao <259427778+hangzqcom@users.noreply.github.com> Date: Wed, 8 Apr 2026 23:19:03 -0700 Subject: [PATCH 1/2] Add Debian packaging (DKMS) for Linux kernel drivers Add .deb package support using DKMS to handle install, uninstall, upgrade, and version control of Qualcomm USB kernel drivers on Debian/Ubuntu systems. New files: - debian/: Full Debian packaging (control, rules, changelog, maintainer scripts) - build-deb.sh: Build script that syncs version from version.h - dkms.conf: DKMS configuration for 4 kernel modules Features: - Builds qtiDevInf, qcom_usb, qcom_usbnet, qcom-serial via DKMS - Auto-rebuilds modules on kernel updates - Blacklists conflicting in-tree modules (qcserial, qmi_wwan, etc.) - Detects and removes conflicting userspace drivers (deb package, /opt/qcom/qcom_userspace, /opt/qcom/QUD, /opt/QTI/QUD, qcom-qud.service) - Cleans up pre-existing manual installs before installation - Installs udev rules for device permissions - Loads modules immediately after installation Updated: - README.md: Added deb package as recommended Linux install method - src/linux/README.md: Added deb package documentation - src/linux/version.h: Version 1.0.6.1 Signed-off-by: Hang Zhao <259427778+hangzqcom@users.noreply.github.com> --- README.md | 59 +- build-deb.sh | 65 ++ debian/.gitignore | 7 + debian/60-qcom-usb-drivers.rules | 10 + debian/changelog | 8 + debian/control | 23 + debian/copyright | 23 + debian/qcom-usb-drivers-dkms.dkms | 1 + debian/qcom-usb-drivers-dkms.modprobe | 16 + debian/qcom-usb-drivers-dkms.postinst | 43 + debian/qcom-usb-drivers-dkms.preinst | 191 +++++ debian/qcom-usb-drivers-dkms.prerm | 30 + debian/rules | 65 ++ debian/source/format | 1 + dkms.conf | 27 + src/linux/QcDevDriver.sh | 1083 +++++++++++++++++++++++++ src/linux/README.md | 60 +- src/linux/version.h | 2 +- 18 files changed, 1705 insertions(+), 9 deletions(-) create mode 100755 build-deb.sh create mode 100644 debian/.gitignore create mode 100644 debian/60-qcom-usb-drivers.rules create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/qcom-usb-drivers-dkms.dkms create mode 100644 debian/qcom-usb-drivers-dkms.modprobe create mode 100755 debian/qcom-usb-drivers-dkms.postinst create mode 100644 debian/qcom-usb-drivers-dkms.preinst create mode 100755 debian/qcom-usb-drivers-dkms.prerm create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 dkms.conf create mode 100644 src/linux/QcDevDriver.sh diff --git a/README.md b/README.md index 411cc16..6a65312 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,12 @@ The project is organized to facilitate easy compilation, testing, and integratio ``` / +├─ debian/ # Debian packaging files for .deb package build ├─ docs/ # Architecture diagrams and design documents ├─ src/ # Qualcomm USB kernel driver for windows and linux platform -├─ examples/ # samples scripts +├─ examples/ # Sample scripts +├─ build-deb.sh # Build script for generating the .deb package +├─ dkms.conf # DKMS configuration for kernel module management ├─ README.md # This file └─ ... # Other files and directories ``` @@ -33,6 +36,7 @@ The project is organized to facilitate easy compilation, testing, and integratio - GNU Make, GCC/Clang. - Kernel headers for the target kernel version (`linux-headers-$(uname -r)`). +- For deb package build: `debhelper`, `dkms`, `dpkg-dev`, `dh-dkms`. ### Build Steps @@ -86,9 +90,51 @@ pnputil /add-driver /install ```bash pnputil /delete-driver oemxx.inf /uninstall /force ``` -#### Linux command: - Navigate to folder `src/linux` - + +#### Linux — Debian Package (Recommended) + +The recommended way to install on Debian/Ubuntu systems is via the `.deb` package, which uses DKMS to automatically build kernel modules for the running kernel and handles install, uninstall, upgrade, and version control. + +- Build the package +```bash +# Install build dependencies (one-time) +sudo apt-get install debhelper dkms dpkg-dev dh-dkms + +# Build +./build-deb.sh +``` + +- Installation +```bash +sudo dpkg -i ../qcom-usb-drivers-dkms__all.deb +``` + +- Uninstallation +```bash +sudo dpkg -r qcom-usb-drivers-dkms +``` + +- Check installed version +```bash +dpkg -s qcom-usb-drivers-dkms | grep Version +dkms status +``` + +- Upgrade + + Simply install a newer `.deb` — it automatically removes the old version and installs the new one. + +**What the deb package does:** +- Builds all 4 kernel modules (`qtiDevInf`, `qcom_usb`, `qcom_usbnet`, `qcom-serial`) via DKMS +- Automatically rebuilds modules when the kernel is updated +- Installs udev rules and blacklists conflicting in-tree modules +- Handles cleanup of pre-existing manual installs +- Loads modules immediately after installation + +#### Linux — Manual Install (Alternative) + +Navigate to folder `src/linux` + - Installation ```bash sudo ./qcom_drivers.sh install @@ -97,7 +143,8 @@ sudo ./qcom_drivers.sh install ```bash sudo ./qcom_drivers.sh uninstall ``` -For more guidance on build process, FAQ's and troubleshooting, please refer to [README](./src/linux/README.md) document. + +For more guidance on build process, FAQ's and troubleshooting, please refer to [README](./src/linux/README.md) document. ## Contributing @@ -119,4 +166,4 @@ and conditions before contributing. ## Contact -For questions, bug reports, or feature requests, please open an issue on GitHub or contact the maintainers +For questions, bug reports, or feature requests, please open an issue on GitHub or contact the maintainers \ No newline at end of file diff --git a/build-deb.sh b/build-deb.sh new file mode 100755 index 0000000..925700d --- /dev/null +++ b/build-deb.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# Build script for qcom-usb-drivers-dkms debian package +# Usage: ./build-deb.sh +# +# Prerequisites: sudo apt-get install debhelper dkms dpkg-dev dh-dkms +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +PKG_VERSION=$(grep '#define DRIVER_VERSION' src/linux/version.h | awk '{print $3}' | tr -d '"') +echo "Building qcom-usb-drivers-dkms version $PKG_VERSION" + +# Update version in dkms.conf if needed +sed -i "s/^PACKAGE_VERSION=.*/PACKAGE_VERSION=\"${PKG_VERSION}\"/" dkms.conf + +# Update version in debian/changelog if needed +CHANGELOG_VER=$(head -1 debian/changelog | grep -oP '\(\K[^)]+') +if [ "$CHANGELOG_VER" != "$PKG_VERSION" ]; then + sed -i "1s/([^)]*)/($PKG_VERSION)/" debian/changelog +fi + +# Update version in postinst and preinst if needed +sed -i "s/^PKG_VERSION=.*/PKG_VERSION=\"${PKG_VERSION}\"/" debian/qcom-usb-drivers-dkms.postinst +sed -i "s/^PKG_VERSION=.*/PKG_VERSION=\"${PKG_VERSION}\"/" debian/qcom-usb-drivers-dkms.preinst + +# Update version in debian/rules if needed +sed -i "s/^PKG_VERSION := .*/PKG_VERSION := ${PKG_VERSION}/" debian/rules + +# Check for required build tools +for tool in dpkg-buildpackage debhelper dkms; do + if [ "$tool" = "debhelper" ]; then + dpkg -l debhelper >/dev/null 2>&1 || { echo "Error: $tool not installed. Run: sudo apt-get install $tool"; exit 1; } + elif [ "$tool" = "dkms" ]; then + dpkg -l dkms >/dev/null 2>&1 || { echo "Error: $tool not installed. Run: sudo apt-get install $tool"; exit 1; } + else + command -v $tool >/dev/null 2>&1 || { echo "Error: $tool not found. Run: sudo apt-get install dpkg-dev"; exit 1; } + fi +done + +# Check for dh-dkms (provides dh_dkms helper) +dpkg -l dh-dkms >/dev/null 2>&1 || { echo "Error: dh-dkms not installed. Run: sudo apt-get install dh-dkms"; exit 1; } + +# Ensure debian/rules is executable +chmod +x debian/rules + +# Clean previous build artifacts +rm -f ../qcom-usb-drivers-dkms_*.deb +rm -f ../qcom-usb-drivers-dkms_*.buildinfo +rm -f ../qcom-usb-drivers-dkms_*.changes +rm -rf debian/qcom-usb-drivers-dkms +rm -rf debian/.debhelper + +# Build the package (unsigned) +dpkg-buildpackage -us -uc -b + +echo "" +echo "========================================" +echo "Build complete! Package files:" +ls -la ../qcom-usb-drivers-dkms_${PKG_VERSION}*.deb 2>/dev/null || echo "(deb file in parent directory)" +echo "" +echo "Install with: sudo dpkg -i ../qcom-usb-drivers-dkms_${PKG_VERSION}_all.deb" +echo "Uninstall with: sudo dpkg -r qcom-usb-drivers-dkms" +echo "Check status: dpkg -s qcom-usb-drivers-dkms" +echo "========================================" \ No newline at end of file diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 0000000..e5ce6e6 --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1,7 @@ +# Build artifacts generated by dpkg-buildpackage +.debhelper/ +debhelper-build-stamp +files +*.substvars +*.debhelper +qcom-usb-drivers-dkms/ diff --git a/debian/60-qcom-usb-drivers.rules b/debian/60-qcom-usb-drivers.rules new file mode 100644 index 0000000..a49b76d --- /dev/null +++ b/debian/60-qcom-usb-drivers.rules @@ -0,0 +1,10 @@ +# Qualcomm USB device udev rules +# GobiNet network device +SUBSYSTEM=="net", DRIVERS=="GobiNet", MODE="0660", GROUP="plugdev" + +# GobiSerial serial ports +SUBSYSTEM=="tty", DRIVERS=="GobiSerial", MODE="0660", GROUP="dialout" + +# QDSS diagnostic devices +SUBSYSTEM=="usb", DRIVERS=="QdssDiag", MODE="0660", GROUP="plugdev" +SUBSYSTEM=="usb", DRIVERS=="QdssMdm", MODE="0660", GROUP="plugdev" \ No newline at end of file diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c6b072c --- /dev/null +++ b/debian/changelog @@ -0,0 +1,8 @@ +qcom-usb-drivers-dkms (1.0.6.1) unstable; urgency=medium + + * Initial DKMS debian package for Qualcomm USB kernel drivers + * Includes qtiDevInf, qcom_usb, qcom_usbnet, qcom-serial modules + * Blacklists conflicting in-tree modules (qcserial, qmi_wwan, option, usb_wwan) + * Installs udev rules for Qualcomm USB device permissions + + -- Qualcomm Technologies, Inc. Tue, 08 Apr 2025 10:00:00 -0700 \ No newline at end of file diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..f37d627 --- /dev/null +++ b/debian/control @@ -0,0 +1,23 @@ +Source: qcom-usb-drivers-dkms +Section: kernel +Priority: optional +Maintainer: Qualcomm Technologies, Inc. +Build-Depends: debhelper-compat (= 13), dkms +Standards-Version: 4.6.0 +Rules-Requires-Root: no + +Package: qcom-usb-drivers-dkms +Architecture: all +Depends: ${misc:Depends}, dkms, linux-headers-generic | linux-headers-amd64 | linux-headers-arm64 +Conflicts: qcom-usb-userspace-drivers, qcom-usb-userspace-drivers-dkms +Replaces: qcom-usb-userspace-drivers, qcom-usb-userspace-drivers-dkms +Description: Qualcomm USB kernel drivers (DKMS) + DKMS package for Qualcomm USB kernel drivers including: + * qtiDevInf - INF file parser for device enumeration + * qcom_usb - USB diagnostic and QDSS driver + * qcom_usbnet - USB network (WWAN) adapter driver + * qcom-serial - USB serial/modem port driver + . + These drivers are automatically built for the running kernel using DKMS + and will be rebuilt when the kernel is updated. Conflicting in-tree + modules (qcserial, qmi_wwan, option, usb_wwan) are blacklisted. \ No newline at end of file diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..e86c1f5 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,23 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: qcom-usb-drivers +Upstream-Contact: Qualcomm Technologies + +Files: * +Copyright: 2025-2026 Qualcomm Technologies, Inc. and/or its subsidiaries. +License: BSD-3-Clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + . + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. \ No newline at end of file diff --git a/debian/qcom-usb-drivers-dkms.dkms b/debian/qcom-usb-drivers-dkms.dkms new file mode 100644 index 0000000..bb29b14 --- /dev/null +++ b/debian/qcom-usb-drivers-dkms.dkms @@ -0,0 +1 @@ +dkms.conf \ No newline at end of file diff --git a/debian/qcom-usb-drivers-dkms.modprobe b/debian/qcom-usb-drivers-dkms.modprobe new file mode 100644 index 0000000..16c12a6 --- /dev/null +++ b/debian/qcom-usb-drivers-dkms.modprobe @@ -0,0 +1,16 @@ +# Qualcomm USB kernel drivers - module configuration +# Installed by qcom-usb-drivers-dkms package + +# Blacklist conflicting in-tree modules so that Qualcomm drivers are used +blacklist qcserial +install qcserial /bin/false +blacklist qmi_wwan +install qmi_wwan /bin/false +blacklist option +install option /bin/false +blacklist usb_wwan +install usb_wwan /bin/false + +# Load Qualcomm USB drivers at boot (qtiDevInf must load first) +softdep qcom_usb pre: qtiDevInf +softdep qcom_usbnet pre: qtiDevInf \ No newline at end of file diff --git a/debian/qcom-usb-drivers-dkms.postinst b/debian/qcom-usb-drivers-dkms.postinst new file mode 100755 index 0000000..c8ed243 --- /dev/null +++ b/debian/qcom-usb-drivers-dkms.postinst @@ -0,0 +1,43 @@ +#!/bin/bash +# Post-installation script for qcom-usb-drivers-dkms +set -e + +PKG_NAME="qcom-usb-drivers" +PKG_VERSION="1.0.6.1" + +# DEBHELPER runs dkms add/build/install here +#DEBHELPER# + +case "$1" in + configure) + # Reload udev rules + udevadm control --reload-rules 2>/dev/null || true + udevadm trigger 2>/dev/null || true + + # Update module dependencies + depmod -a 2>/dev/null || true + + # Unload conflicting in-tree modules if loaded + for mod in qcserial qmi_wwan cdc_wdm option usb_wwan; do + if lsmod | grep -qw "$mod"; then + echo " Unloading conflicting module: $mod" + rmmod "$mod" 2>/dev/null || true + fi + done + + # Load the Qualcomm drivers (order matters: qtiDevInf first) + for mod in qtiDevInf qcom_usb qcom_usbnet qcom-serial; do + modprobe "$mod" 2>/dev/null || true + done + + echo "qcom-usb-drivers $PKG_VERSION: modules installed and loaded successfully." + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + ;; +esac + +exit 0 \ No newline at end of file diff --git a/debian/qcom-usb-drivers-dkms.preinst b/debian/qcom-usb-drivers-dkms.preinst new file mode 100644 index 0000000..000b9a2 --- /dev/null +++ b/debian/qcom-usb-drivers-dkms.preinst @@ -0,0 +1,191 @@ +#!/bin/bash +# Pre-install: detect conflicting userspace drivers, clean up pre-existing modules +set -e + +PKG_NAME="qcom-usb-drivers" +PKG_VERSION="1.0.6.1" + +# Our module names +MODULES="qtiDevInf qcom_usb qcom_usbnet qcom-serial" + +# Userspace driver detection paths +USERSPACE_DEB_PATTERN="qcom-usb-userspace" +USERSPACE_INSTALL_DIR="/opt/qcom/qcom_userspace" +OLD_QUD_DIR="/opt/qcom/QUD" +LEGACY_QUD_DIR="/opt/QTI/QUD" +USERSPACE_SERVICE="qcom-qud.service" +USERSPACE_MODULES="GobiNet QdssDiag" +USERSPACE_CONFIG="/etc/qcom_libusb.conf" + +case "$1" in + install|upgrade) + echo "qcom-usb-drivers: preparing installation (version $PKG_VERSION)..." + + # --- Step 0: Detect and remove conflicting userspace drivers --- + USERSPACE_FOUND=false + + # Check for userspace deb package + USERSPACE_PKG=$(dpkg -l 2>/dev/null | grep -i "$USERSPACE_DEB_PATTERN" | awk '{print $2}' | head -1) + if [ -n "$USERSPACE_PKG" ]; then + USERSPACE_FOUND=true + echo "" + echo " WARNING: Conflicting userspace driver package detected: $USERSPACE_PKG" + echo " The kernel-mode drivers are incompatible with the userspace drivers." + echo " Removing userspace driver package: $USERSPACE_PKG ..." + dpkg -r "$USERSPACE_PKG" 2>/dev/null || true + echo " Userspace driver package removed." + fi + + # Check for manually installed userspace drivers + if [ -d "$USERSPACE_INSTALL_DIR" ]; then + USERSPACE_FOUND=true + echo "" + echo " WARNING: Userspace driver installation detected at: $USERSPACE_INSTALL_DIR" + + # Try to use the uninstall script if available + if [ -x "$USERSPACE_INSTALL_DIR/qcom_drivers.sh" ]; then + echo " Running userspace driver uninstaller..." + "$USERSPACE_INSTALL_DIR/qcom_drivers.sh" uninstall 2>/dev/null || true + fi + + # Clean up remaining files + echo " Removing userspace driver directory: $USERSPACE_INSTALL_DIR" + rm -rf "$USERSPACE_INSTALL_DIR" + fi + + # Check for old QUD installation (/opt/qcom/QUD) + if [ -d "$OLD_QUD_DIR" ]; then + # Check if it has the userspace uninstaller (not the kernel driver one) + if [ -f "$OLD_QUD_DIR/qcom_drivers.sh" ]; then + USERSPACE_FOUND=true + echo "" + echo " WARNING: Old QUD installation detected at: $OLD_QUD_DIR" + echo " Running old QUD uninstaller..." + bash "$OLD_QUD_DIR/qcom_drivers.sh" uninstall 2>/dev/null || true + echo " Removing old QUD directory: $OLD_QUD_DIR" + rm -rf "$OLD_QUD_DIR" + fi + fi + + # Check for legacy QTI installation (/opt/QTI/QUD) + if [ -d "$LEGACY_QUD_DIR" ]; then + USERSPACE_FOUND=true + echo "" + echo " WARNING: Legacy QTI installation detected at: $LEGACY_QUD_DIR" + if [ -f "$LEGACY_QUD_DIR/QcDevDriver.sh" ]; then + echo " Running legacy uninstaller..." + bash "$LEGACY_QUD_DIR/QcDevDriver.sh" uninstall 2>/dev/null || true + fi + echo " Removing legacy directory: $LEGACY_QUD_DIR" + rm -rf "$LEGACY_QUD_DIR" + fi + + # Unload userspace-specific modules (GobiNet, QdssDiag) + for mod in $USERSPACE_MODULES; do + mod_under=$(echo "$mod" | tr '-' '_') + if lsmod | grep -qi "^${mod_under}"; then + USERSPACE_FOUND=true + echo " Unloading userspace module: $mod" + rmmod "$mod" 2>/dev/null || true + fi + done + + # Remove userspace-specific module files from kernel tree + KVER=$(uname -r) + for mod in GobiNet.ko QdssDiag.ko qdssdiag.ko; do + for dir in "/lib/modules/$KVER/kernel/drivers/net/usb" "/lib/modules/$KVER/kernel/drivers/usb/misc" "/lib/modules/$KVER/extra"; do + for ext in "" ".xz" ".zst" ".gz"; do + fpath="$dir/${mod}${ext}" + if [ -f "$fpath" ]; then + USERSPACE_FOUND=true + echo " Removing userspace module file: $fpath" + rm -f "$fpath" + fi + done + done + done + + # Stop and disable the userspace systemd service + if systemctl list-unit-files "$USERSPACE_SERVICE" >/dev/null 2>&1; then + if systemctl is-active "$USERSPACE_SERVICE" >/dev/null 2>&1; then + USERSPACE_FOUND=true + echo " Stopping userspace service: $USERSPACE_SERVICE" + systemctl stop "$USERSPACE_SERVICE" 2>/dev/null || true + fi + if systemctl is-enabled "$USERSPACE_SERVICE" >/dev/null 2>&1; then + echo " Disabling userspace service: $USERSPACE_SERVICE" + systemctl disable "$USERSPACE_SERVICE" 2>/dev/null || true + fi + # Remove the service file + rm -f "/etc/systemd/system/$USERSPACE_SERVICE" 2>/dev/null || true + systemctl daemon-reload 2>/dev/null || true + fi + + # Remove userspace config file + if [ -f "$USERSPACE_CONFIG" ]; then + echo " Removing userspace config: $USERSPACE_CONFIG" + rm -f "$USERSPACE_CONFIG" + fi + + if [ "$USERSPACE_FOUND" = true ]; then + echo " Userspace driver cleanup complete." + echo "" + fi + + # --- Step 1: Unload any currently loaded kernel-mode modules --- + for mod in qcom-serial qcom_usbnet qcom_usb qtiDevInf; do + mod_under=$(echo "$mod" | tr '-' '_') + if lsmod | grep -q "^${mod_under}"; then + echo " Unloading currently loaded module: $mod" + rmmod "$mod" 2>/dev/null || true + fi + done + + # --- Step 2: Remove any older DKMS versions of our package --- + if command -v dkms >/dev/null 2>&1; then + # Get all installed versions of our package + OLD_VERSIONS=$(dkms status "$PKG_NAME" 2>/dev/null | grep -oP "${PKG_NAME}/\K[^,]+" || true) + for old_ver in $OLD_VERSIONS; do + old_ver=$(echo "$old_ver" | tr -d '[:space:]') + if [ -n "$old_ver" ] && [ "$old_ver" != "$PKG_VERSION" ]; then + echo " Removing older DKMS version: $PKG_NAME/$old_ver" + dkms remove "$PKG_NAME/$old_ver" --all 2>/dev/null || true + fi + done + fi + + # --- Step 3: Remove manually installed modules from kernel tree --- + # These are modules installed outside of DKMS (e.g., via make install) + MANUAL_PATHS=( + "/lib/modules/$KVER/kernel/drivers/usb/misc" + "/lib/modules/$KVER/kernel/drivers/net/usb" + "/lib/modules/$KVER/kernel/drivers/usb/serial" + "/lib/modules/$KVER/extra" + ) + MODULE_FILES="qtiDevInf.ko qcom_usb.ko qcom_usbnet.ko qcom-serial.ko" + + for dir in "${MANUAL_PATHS[@]}"; do + for mf in $MODULE_FILES; do + # Check for .ko, .ko.xz, .ko.zst, .ko.gz variants + for ext in "" ".xz" ".zst" ".gz"; do + fpath="$dir/${mf}${ext}" + if [ -f "$fpath" ]; then + echo " Removing pre-existing module: $fpath" + rm -f "$fpath" + fi + done + done + done + + # Update module dependencies after removal + if [ -d "/lib/modules/$KVER" ]; then + depmod -a "$KVER" 2>/dev/null || true + fi + + echo " Pre-installation cleanup complete." + ;; +esac + +#DEBHELPER# + +exit 0 \ No newline at end of file diff --git a/debian/qcom-usb-drivers-dkms.prerm b/debian/qcom-usb-drivers-dkms.prerm new file mode 100755 index 0000000..5d00b82 --- /dev/null +++ b/debian/qcom-usb-drivers-dkms.prerm @@ -0,0 +1,30 @@ +#!/bin/bash +# Pre-removal script for qcom-usb-drivers-dkms +set -e + +case "$1" in + remove|upgrade|deconfigure) + # Unload Qualcomm modules (reverse dependency order: serial depends on qtiDevInf) + for mod in qcom-serial qcom_usbnet qcom_usb qtiDevInf; do + if lsmod | grep -qw "${mod//-/_}"; then + rmmod "$mod" 2>/dev/null || true + fi + done + + # Restore blacklisted in-tree modules + # (the blacklist config file is removed automatically with the package) + depmod -a 2>/dev/null || true + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument '$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 \ No newline at end of file diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..5c36c9c --- /dev/null +++ b/debian/rules @@ -0,0 +1,65 @@ +#!/usr/bin/make -f + +PKG_NAME := qcom-usb-drivers +PKG_VERSION := 1.0.6.1 +DKMS_SRC := debian/qcom-usb-drivers-dkms/usr/src/$(PKG_NAME)-$(PKG_VERSION) + +%: + dh $@ --with dkms + +override_dh_auto_configure: +override_dh_auto_build: +override_dh_auto_test: +override_dh_auto_install: + # Create DKMS source directory + mkdir -p $(DKMS_SRC) + + # Copy top-level Makefile (the one that builds all sub-modules) + cp src/linux/Makefile $(DKMS_SRC)/Makefile + + # Copy version header + cp src/linux/version.h $(DKMS_SRC)/version.h + + # Copy DKMS configuration + cp dkms.conf $(DKMS_SRC)/dkms.conf + + # Copy InfParser sources + mkdir -p $(DKMS_SRC)/InfParser + cp src/linux/InfParser/Makefile $(DKMS_SRC)/InfParser/ + cp src/linux/InfParser/*.c $(DKMS_SRC)/InfParser/ + cp src/linux/InfParser/*.h $(DKMS_SRC)/InfParser/ + + # Copy qcom_usb sources + mkdir -p $(DKMS_SRC)/qcom_usb + cp src/linux/qcom_usb/Makefile $(DKMS_SRC)/qcom_usb/ + cp src/linux/qcom_usb/*.c $(DKMS_SRC)/qcom_usb/ + cp src/linux/qcom_usb/*.h $(DKMS_SRC)/qcom_usb/ + + # Copy qcom_usbnet sources + mkdir -p $(DKMS_SRC)/qcom_usbnet + cp src/linux/qcom_usbnet/Makefile $(DKMS_SRC)/qcom_usbnet/ + cp src/linux/qcom_usbnet/*.c $(DKMS_SRC)/qcom_usbnet/ + cp src/linux/qcom_usbnet/*.h $(DKMS_SRC)/qcom_usbnet/ + + # Copy qcom_serial sources + mkdir -p $(DKMS_SRC)/qcom_serial + cp src/linux/qcom_serial/Makefile $(DKMS_SRC)/qcom_serial/ + cp src/linux/qcom_serial/*.c $(DKMS_SRC)/qcom_serial/ + cp src/linux/qcom_serial/*.h $(DKMS_SRC)/qcom_serial/ + + # Copy INF files needed by the drivers + cp src/linux/qcom_usb/*.inf $(DKMS_SRC)/qcom_usb/ 2>/dev/null || true + cp src/linux/qcom_usbnet/*.inf $(DKMS_SRC)/qcom_usbnet/ 2>/dev/null || true + cp src/linux/qcom_serial/*.inf $(DKMS_SRC)/qcom_serial/ 2>/dev/null || true + + # Install udev rules (modprobe config is installed automatically by dh_dkms from .modprobe file) + mkdir -p debian/qcom-usb-drivers-dkms/etc/udev/rules.d + echo 'SUBSYSTEMS=="qcom_usbnet", MODE="0666"' > debian/qcom-usb-drivers-dkms/etc/udev/rules.d/99-qcom-usb-devices.rules + echo 'SUBSYSTEMS=="qcom_usb", MODE="0666"' >> debian/qcom-usb-drivers-dkms/etc/udev/rules.d/99-qcom-usb-devices.rules + echo 'SUBSYSTEMS=="qcom_ports", MODE="0666"' >> debian/qcom-usb-drivers-dkms/etc/udev/rules.d/99-qcom-usb-devices.rules + echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="05c6", NAME="usb%n"' > debian/qcom-usb-drivers-dkms/etc/udev/rules.d/80-qcom-usbnet-devices.rules + +override_dh_dkms: + dh_dkms -V $(PKG_VERSION) + +override_dh_auto_clean: \ No newline at end of file diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..9f67427 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) \ No newline at end of file diff --git a/dkms.conf b/dkms.conf new file mode 100644 index 0000000..435c066 --- /dev/null +++ b/dkms.conf @@ -0,0 +1,27 @@ +# DKMS configuration for Qualcomm USB kernel drivers +PACKAGE_NAME="qcom-usb-drivers" +PACKAGE_VERSION="1.0.6.1" + +# Module 1: qtiDevInf (INF Parser) +BUILT_MODULE_NAME[0]="qtiDevInf" +BUILT_MODULE_LOCATION[0]="InfParser/" +DEST_MODULE_LOCATION[0]="/updates/dkms" + +# Module 2: qcom_usb (USB diagnostic/QDSS driver) +BUILT_MODULE_NAME[1]="qcom_usb" +BUILT_MODULE_LOCATION[1]="qcom_usb/" +DEST_MODULE_LOCATION[1]="/updates/dkms" + +# Module 3: qcom_usbnet (USB network driver) +BUILT_MODULE_NAME[2]="qcom_usbnet" +BUILT_MODULE_LOCATION[2]="qcom_usbnet/" +DEST_MODULE_LOCATION[2]="/updates/dkms" + +# Module 4: qcom-serial (USB serial driver) +BUILT_MODULE_NAME[3]="qcom-serial" +BUILT_MODULE_LOCATION[3]="qcom_serial/" +DEST_MODULE_LOCATION[3]="/updates/dkms" + +AUTOINSTALL="yes" +CLEAN="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build clean" +MAKE[0]="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules" \ No newline at end of file diff --git a/src/linux/QcDevDriver.sh b/src/linux/QcDevDriver.sh new file mode 100644 index 0000000..767ed21 --- /dev/null +++ b/src/linux/QcDevDriver.sh @@ -0,0 +1,1083 @@ +#!/bin/bash +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause + +DEST_QTI_PATH=/opt/QTI/ +DEST_QUD_PATH=/opt/QTI/QUD +DEST_INS_RMNET_PATH=/opt/QTI/QUD/rmnet +DEST_INS_QDSS_PATH=/opt/QTI/QUD/diag +DEST_INF_PATH=/opt/QTI/QUD/diag/InfParser +DEST_QDSS_DAIG_PATH=/opt/QTI/QUD/diag/QdssDiag +DEST_SIGN_PATH=/opt/QTI/sign +QC_MODBIN_DIR=/sbin +QC_MAKE_DIR=/usr/bin +QC_MODULE_INF_NAME=qtiDevInf.ko +QC_MODULE_QDSS_DIAG_NAME=QdssDiag.ko +QC_MODULE_RMNET_NAME=GobiNet.ko +QC_DIAG_INF_PATH=/opt/QTI/QUD/diag/qtiser.inf +QC_QDSS_INF_PATH=/opt/QTI/QUD/diag/qdbusb.inf +QC_MODEM_INF_PATH=/opt/QTI/QUD/serial/qtimdm.inf +DEST_INS_SERIAL_PATH=/opt/QTI/QUD/serial +QC_UDEV_PATH=/etc/udev/rules.d +QC_MODULE_GOBISERIAL_NAME=GobiSerial.ko +QC_SERIAL=/lib/modules/`uname -r`/kernel/drivers/usb/serial +QC_QMI_WWAN=/lib/modules/`uname -r`/kernel/drivers/net/usb +QC_NET=/lib/modules/`uname -r`/kernel/drivers/net +QC_LN_RM_MK_DIR=/bin +MODULE_BLACKLIST=/etc/modprobe.d +OS_RELEASE="`cat /etc/os-release | grep PRETTY_NAME`" +OSName=`echo $OS_RELEASE | awk -F= '{printf $2}'` +KERNEL_VERSION=`uname -r` +GREEN='\033[0;32m' +RED='\033[0;31m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +RESET='\033[0m' + +#check and install mokutil package +if [ ! -f "$QC_MAKE_DIR/mokutil" ]; then + echo -e "${RED}Error: mokutil not found, installing..\n${RESET}" +fi + +if [ ! -f "$QC_MAKE_DIR/keyctl" ]; then + echo -e ${RED}"Error: keyutils not found, installing..\n"${RESET} +fi + +if [[ ! -f "$QC_MAKE_DIR/mokutil" ]] || [[ ! -f "$QC_MAKE_DIR/keyctl" ]]; then + if [[ $OSName =~ "Red Hat Enterprise Linux" ]]; then + sudo dnf install -y mokutil + sudo dnf install -y keyutils + fi + + if [[ $OSName =~ "Ubuntu" ]]; then + sudo apt-get install -y mokutil + sudo apt-get install -y keyutils + fi +fi + +if [[ $OSName =~ "Fedora Linux" ]]; then + sudo dnf install -y make automake gcc gcc-c++ kernel-devel +fi + +QC_SECURE_BOOT_CHECK=`mokutil --sb-state` + +if [[ $QC_SECURE_BOOT_CHECK = "SecureBoot enabled" ]]; then + QC_PUBLIC_KEY_VERIFY=`mokutil --test-key $DEST_SIGN_PATH/Signkey_pub.der` +fi + +if [ ! -d $DEST_QUD_PATH ]; then + echo -e "${RED}Error: $DEST_QUD_PATH doesn't exist. Creating Now.${RESET}" + $QC_LN_RM_MK_DIR/mkdir -m 0755 -p $DEST_QUD_PATH +fi + +if [ $# == 0 ]; then + echo -e "${RED}Usage: QCDevInstaller.sh ${RESET}" + exit 1 +else + if [ $1 == "uninstall" ]; then + echo -e "Operating System: $OSName" + echo -e "Kernel Version: "\""`uname -r`"\""" + + if [ -f ./version.h ]; then + VERSION="`grep -r '#define DRIVER_VERSION' version.h`" + DRIVER_VERSION=`echo $VERSION | awk '{printf $3}'` + echo -e "Driver Version: $DRIVER_VERSION" + elif [ -f ./BuildPackage/version.h ]; then + VERSION="`grep -r '#define DRIVER_VERSION' ./BuildPackage/version.h`" + DRIVER_VERSION=`echo $VERSION | awk '{printf $3}'` + echo -e "Driver Version: $DRIVER_VERSION" + fi + + if [ -d $DEST_INS_QDSS_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + if [ ! -d $DEST_INS_QDSS_PATH ]; then + echo -e "Successfully removed $DEST_INS_QDSS_PATH" + else + echo -e "${RED}Failed to remove $DEST_INS_QDSS_PATH${RESET}" + fi + else + echo -e "$DEST_INS_QDSS_PATH does not exist, nothing to remove" + fi + if [ -d $DEST_INS_RMNET_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + if [ ! -d $DEST_INS_RMNET_PATH ]; then + echo -e "Successfully removed $DEST_INS_RMNET_PATH" + else + echo -e "${RED}Failed to remove $DEST_INS_RMNET_PATH${RESET}" + fi + else + echo -e "$DEST_INS_RMNET_PATH does not exist, nothing to remove" + fi + if [ -d $DEST_INS_SERIAL_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_SERIAL_PATH + if [ ! -d $DEST_INS_SERIAL_PATH ]; then + echo -e "Successfully removed $DEST_INS_SERIAL_PATH" + else + echo -e "${RED}Failed to remove $DEST_INS_SERIAL_PATH${RESET}" + fi + else + echo -e "$DEST_INS_SERIAL_PATH does not exist, nothing to remove" + fi + + if [ -f $QC_UDEV_PATH/qti_usb_device.rules ]; then + rm -r $QC_UDEV_PATH/qti_usb_device.rules + if [ ! -f $QC_UDEV_PATH/qti_usb_device.rules ]; then + echo -e "Successfully removed $QC_UDEV_PATH/qti_usb_device.rules" + else + echo -e "${RED}Failed to remove $QC_UDEV_PATH/qti_usb_device.rules${RESET}" + fi + else + echo -e "$QC_UDEV_PATH/qti_usb_device.rules does not exist, nothing to remove" + fi + # < "Redundant 80-net-setup-link.rules. This code will be eliminated after few releases" + if [ -f $QC_UDEV_PATH/80-net-setup-link.rules ]; then + sed -i '/GobiQMI/d' $QC_UDEV_PATH/80-net-setup-link.rules + if [ ! -s $QC_UDEV_PATH/80-net-setup-link.rules ]; then + echo -e "Removed GobiQMI rule from $QC_UDEV_PATH/80-net-setup-link.rules" + rm -rf $QC_UDEV_PATH/80-net-setup-link.rules + if [ ! -f $QC_UDEV_PATH/80-net-setup-link.rules ]; then + echo -e "File was empty. Removed $QC_UDEV_PATH/80-net-setup-link.rules successfully" + else + echo -e "File is empty but Failed to remove $QC_UDEV_PATH/80-net-setup-link.rules" + fi + else + echo -e "Pre-Existing data $QC_UDEV_PATH/80-net-setup-link.rules, so not removing it." + fi + else + echo -e "$QC_UDEV_PATH/80-net-setup-link.rules does not exist, nothing to remove" + fi + # > + if [ -f $QC_UDEV_PATH/80-gobinet-usbdevice.rules ]; then + sed -i '/usb/d' $QC_UDEV_PATH/80-gobinet-usbdevice.rules + if [ ! -s $QC_UDEV_PATH/80-gobinet-usbdevice.rules ]; then + echo -e "Removed GobiQMI rule from $QC_UDEV_PATH/80-gobinet-usbdevice.rules" + rm -rf $QC_UDEV_PATH/80-gobinet-usbdevice.rules + if [ ! -f $QC_UDEV_PATH/80-gobinet-usbdevice.rules ]; then + echo -e "File was empty. Removed $QC_UDEV_PATH/80-gobinet-usbdevice.rules successfully" + else + echo -e "File is empty but Failed to remove $QC_UDEV_PATH/80-gobinet-usbdevice.rules" + fi + else + echo -e "Pre-Existing data $QC_UDEV_PATH/80-gobinet-usbdevice.rules, so not removing it." + fi + else + echo -e "$QC_UDEV_PATH/80-gobinet-usbdevice.rules does not exist, nothing to remove" + fi + + # Informs udev deamon to reload the newly added device rule and re-trigger service + sudo udevadm control --reload-rules + sudo udevadm trigger + + if [ "`lsmod | grep GobiSerial`" ]; then + ($QC_MODBIN_DIR/rmmod $QC_MODULE_GOBISERIAL_NAME && echo -e "$QC_MODULE_GOBISERIAL_NAME removed successfully") || { echo -e "$QC_MODULE_GOBISERIAL_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } + else + echo -e "Module $QC_MODULE_GOBISERIAL_NAME is not currently loaded" + fi + if [ "`lsmod | grep GobiNet`" ]; then + ( $QC_MODBIN_DIR/rmmod $QC_MODULE_RMNET_NAME && echo -e "$QC_MODULE_RMNET_NAME removed successfully" ) || { echo -e "$QC_MODULE_RMNET_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } + else + echo -e "Module $QC_MODULE_RMNET_NAME is not currently loaded" + fi + if [ "`lsmod | grep QdssDiag`" ]; then + ($QC_MODBIN_DIR/rmmod $QC_MODULE_QDSS_DIAG_NAME && echo -e "$QC_MODULE_QDSS_DIAG_NAME removed successfully") || { echo -e "$QC_MODULE_QDSS_DIAG_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } + else + echo -e "Module $QC_MODULE_QDSS_DIAG_NAME is not currently loaded" + fi + if [ "`lsmod | grep qtiDevInf`" ]; then + ($QC_MODBIN_DIR/rmmod $QC_MODULE_INF_NAME && echo -e "$QC_MODULE_INF_NAME removed successfully") || { echo -e "$QC_MODULE_INF_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } + else + echo -e "Module $QC_MODULE_INF_NAME is not currently loaded" + fi + + MODLOADED="`/sbin/lsmod | grep usb_wwan`" + if [ "$MODLOADED" != "" ]; then + echo -e "usb_wwan module is already loaded. nothing to do" + fi + if [ -f $QC_SERIAL/usb_wwan_dup* ]; then + echo -e "usb_wwan_dup is found. restoring to usb_wwan" + mv /lib/modules/`uname -r`/kernel/drivers/usb/serial/usb_wwan_dup* /lib/modules/`uname -r`/kernel/drivers/usb/serial/usb_wwan.ko + #$QC_MODBIN_DIR/insmod /lib/modules/`uname -r`/kernel/drivers/usb/serial/usb_wwan.ko + + MODLOADED="`/sbin/lsmod | grep usb_wwan`" + if [ "$MODLOADED" != "" ]; then + echo -e "Successfully loaded usb_wwan module." + fi + fi + + MODLOADED="`/sbin/lsmod | grep qcserial`" + if [ "$MODLOADED" != "" ]; then + echo -e "qcserial module is already loaded. nothing to do" + fi + if [ -f $QC_SERIAL/qcserial_dup* ]; then + echo -e "qcserial_dup is found. restoring to qcserial" + mv /lib/modules/`uname -r`/kernel/drivers/usb/serial/qcserial_dup* /lib/modules/`uname -r`/kernel/drivers/usb/serial/qcserial.ko + #$QC_MODBIN_DIR/insmod /lib/modules/`uname -r`/kernel/drivers/usb/serial/qcserial.ko + + MODLOADED="`/sbin/lsmod | grep qcserial`" + if [ "$MODLOADED" != "" ]; then + echo -e "Successfully loaded qcserial module." + fi + fi + + MODLOADED="`/sbin/lsmod | grep option`" + if [ "$MODLOADED" != "" ]; then + echo -e "option module is already loaded. nothing to do" + fi + if [ -f $QC_SERIAL/option_dup* ]; then + echo -e "option_dup is found. restoring to option" + mv /lib/modules/`uname -r`/kernel/drivers/usb/serial/option_dup* /lib/modules/`uname -r`/kernel/drivers/usb/serial/option.ko + #$QC_MODBIN_DIR/insmod /lib/modules/`uname -r`/kernel/drivers/usb/serial/option.ko + + MODLOADED="`/sbin/lsmod | grep option`" + if [ "$MODLOADED" != "" ]; then + echo -e "Successfully loaded option module." + fi + fi + + MODLOADED="`/sbin/lsmod | grep qmi_wwan`" + if [ "$MODLOADED" != "" ]; then + echo -e "qmi_wwan module is already loaded. nothing to do" + fi + if [ -f $QC_QMI_WWAN/qmi_wwan_dup* ]; then + echo -e "qmi_wwan_dup is found. restoring to qmi_wwan" + mv /lib/modules/`uname -r`/kernel/drivers/usb/class/cdc-wdm_dup* /lib/modules/`uname -r`/kernel/drivers/usb/class/cdc-wdm.ko + mv /lib/modules/`uname -r`/kernel/drivers/net/usb/qmi_wwan_dup* /lib/modules/`uname -r`/kernel/drivers/net/usb/qmi_wwan.ko + #$QC_MODBIN_DIR/insmod /lib/modules/`uname -r`/kernel/drivers/usb/class/cdc-wdm.ko + #$QC_MODBIN_DIR/insmod /lib/modules/`uname -r`/kernel/drivers/net/usb/qmi_wwan.ko + + MODLOADED="`/sbin/lsmod | grep qmi_wwan`" + if [ "$MODLOADED" != "" ]; then + echo -e "Successfully loaded qmi_wwan module." + fi + fi + + if [[ $OSName =~ "Ubuntu 24.04" ]]; then + if [ -f $QC_NET/mii.ko ]; then + $QC_LN_RM_MK_DIR/rm -rf $QC_NET/mii.ko + fi + if [ -f $QC_QMI_WWAN/usbnet.ko ]; then + $QC_LN_RM_MK_DIR/rm -rf $QC_QMI_WWAN/usbnet.ko + fi + fi + + if [ "`grep -nr 'Qualcomm clients' /etc/modprobe.d/blacklist.conf`" != "" ]; then + sed -i '/# Blacklist these module so that Qualcomm clients use only/d' /etc/modprobe.d/blacklist.conf + sed -i '/# GobiNet, GobiSerial, QdssDiag, qtiDevInf driver/d' /etc/modprobe.d/blacklist.conf + fi + + MOD_EXIST="`grep -nr 'blacklist qcserial' /etc/modprobe.d/blacklist.conf`" + if [ "$MOD_EXIST" != "" ]; then + sed -i '/qcserial/d' $MODULE_BLACKLIST/blacklist.conf + echo -e "Successfully removed qcserial from $MODULE_BLACKLIST/blacklist.conf" + fi + + MOD_EXIST="`grep -nr 'blacklist qmi_wwan' /etc/modprobe.d/blacklist.conf`" + if [ "$MOD_EXIST" != "" ]; then + sed -i '/qmi_wwan/d' $MODULE_BLACKLIST/blacklist.conf + echo -e "Successfully removed qmi_wwan from $MODULE_BLACKLIST/blacklist.conf" + fi + + MOD_EXIST="`grep -nr 'blacklist option' /etc/modprobe.d/blacklist.conf`" + if [ "$MOD_EXIST" != "" ]; then + sed -i '/option/d' $MODULE_BLACKLIST/blacklist.conf + echo -e "Successfully removed option from $MODULE_BLACKLIST/blacklist.conf" + fi + + MOD_EXIST="`grep -nr 'blacklist usb_wwan' /etc/modprobe.d/blacklist.conf`" + if [ "$MOD_EXIST" != "" ]; then + sed -i '/usb_wwan/d' $MODULE_BLACKLIST/blacklist.conf + echo -e "Successfully removed usb_wwan from $MODULE_BLACKLIST/blacklist.conf" + fi + + #change to permission to default mode + $QC_LN_RM_MK_DIR/chmod 644 $MODULE_BLACKLIST/blacklist.conf + + echo -e "Removing modules for /etc/modules." + MODUPDATE="`grep -r qtiDevInf /etc/modules`" + if [ "$MODUPDATE" == "qtiDevInf" ]; then + sed -i '/qtiDevInf/d' /etc/modules + fi + MODUPDATE="`grep -r QdssDiag /etc/modules`" + if [ "$MODUPDATE" == "QdssDiag" ]; then + sed -i '/QdssDiag/d' /etc/modules + fi + MODUPDATE="`grep -r GobiNet /etc/modules`" + if [ "$MODUPDATE" == "GobiNet" ]; then + sed -i '/GobiNet/d' /etc/modules + fi + MODUPDATE="`grep -r GobiSerial /etc/modules`" + if [ "$MODUPDATE" == "GobiSerial" ]; then + sed -i '/GobiSerial/d' /etc/modules + fi + if [[ $OSName != *"Red Hat Enterprise Linux"* ]]; then + MODUPDATE="`grep -nr 'iface usb0 inet static' /etc/network/interfaces`" + if [ "$MODUPDATE" != "" ]; then + sed -i '/iface usb0 inet static/d' /etc/network/interfaces + fi + fi + + echo -e "Removing modules from $QC_SERIAL" + if [ -f $QC_SERIAL/$QC_MODULE_GOBISERIAL_NAME ]; then + rm -rf $QC_SERIAL/$QC_MODULE_GOBISERIAL_NAME + fi + echo -e "Removing modules from $QC_QMI_WWAN" + if [ -f $QC_QMI_WWAN/$QC_MODULE_QDSS_DIAG_NAME ]; then + rm -rf $QC_QMI_WWAN/$QC_MODULE_QDSS_DIAG_NAME + fi + if [ -f $QC_QMI_WWAN/$QC_MODULE_RMNET_NAME ]; then + rm -rf $QC_QMI_WWAN/$QC_MODULE_RMNET_NAME + fi + if [ -f $QC_QMI_WWAN/$QC_MODULE_INF_NAME ]; then + rm -rf $QC_QMI_WWAN/$QC_MODULE_INF_NAME + fi + # update modules.dep and modules.alias + depmod + + echo -e "Uninstallation completed successfully." + exit 0 + else + if [ $1 != "install" ]; then + echo -e "Usage: QCDevInstaller.sh " + exit 1 + fi + fi +fi + +######## Installation ########### + +if [[ $OSName =~ "Ubuntu" ]]; then + sudo apt-get update + sudo apt-get install -y build-essential + sudo apt-get install -y gawk + sudo apt-get install -y python3-tk +fi + +IFS=. read -r major_ver minor_ver patch_ver <<< "$KERNEL_VERSION" +if [[ $OSName =~ "Ubuntu 22." ]] && (( "$major_ver" >= 6 && "$minor_ver" >= 5 )); then + echo -e "Installing gcc 12 version ..." + sudo apt install -y gcc-12 g++-12 +fi + +echo -e "${CYAN}=======================================================================================" +echo -e "=======================================================================================${RESET}" +echo -e " " + +echo -e "Operating System:${RED} $OSName"${RESET} +echo -e "Kernel Version: ${RED}"\"$KERNEL_VERSION\"""${RESET} + +if [ -f ./version.h ]; then + VERSION="`grep -r '#define DRIVER_VERSION' version.h`" + DRIVER_VERSION=`echo $VERSION | awk '{printf $3}'` + echo -e "Driver Version: $DRIVER_VERSION" +fi + +echo -e "Installing at the following paths:" +echo $DEST_INS_SERIAL_PATH +echo $DEST_INS_QDSS_PATH +echo $DEST_INS_RMNET_PATH + +# this script will use in qik uninstallation process +if [ -f "$DEST_QUD_PATH/QcDevDriver.sh" ]; then + echo -e "Delete and copy again (QcDevDriver.sh)" + $QC_LN_RM_MK_DIR/rm -rf $DEST_QUD_PATH/QcDevDriver.sh + $QC_LN_RM_MK_DIR/cp -rf ./QcDevDriver.sh $DEST_QUD_PATH/ +else + echo -e "Does not exist and copying now.. (QcDevDriver.sh)" + $QC_LN_RM_MK_DIR/cp -rf ./QcDevDriver.sh $DEST_QUD_PATH/ +fi + +# Create directories +if [ -d $DEST_INS_SERIAL_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_SERIAL_PATH +fi + +$QC_LN_RM_MK_DIR/mkdir -m 0755 -p $DEST_INS_SERIAL_PATH +if [ ! -d $DEST_INS_SERIAL_PATH ]; then + echo -e "${RED}Error: Failed to create installation path, please run installer under root." + exit 1 +fi + +if [ -d $DEST_INS_QDSS_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH +fi + +$QC_LN_RM_MK_DIR/mkdir -m 0755 -p $DEST_INS_QDSS_PATH +if [ ! -d $DEST_INS_QDSS_PATH ]; then + echo -e "${RED}Error: Failed to create installation path, please run installer under root." + exit 1 +fi + +if [ -d $DEST_INF_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_INF_PATH +fi + +$QC_LN_RM_MK_DIR/mkdir -m 0755 -p $DEST_INF_PATH +if [ ! -d $DEST_INF_PATH ]; then + echo -e "${RED}Error: Failed to create installation path, please run installer under root." + exit 1 +fi + +if [ -d $DEST_QDSS_DAIG_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_QDSS_DAIG_PATH +fi + +$QC_LN_RM_MK_DIR/mkdir -m 0755 -p $DEST_QDSS_DAIG_PATH +if [ ! -d $DEST_QDSS_DAIG_PATH ]; then + echo -e "${RED}Error: Failed to create installation path, please run installer under root." + exit 1 +fi + +# Important: Do not delete or recreate the "sign" folder. +# The sign files will be automatically generated whenever the Signpub key is not enrolled. +$QC_LN_RM_MK_DIR/mkdir -m 0777 -p $DEST_SIGN_PATH +if [ ! -d $DEST_SIGN_PATH ]; then + echo -e "${RED}Error: Failed to create installation path, please run installer under root." + exit 1 +fi + +# $QC_LN_RM_MK_DIR/cp ./GobiSerial/GobiSerial.c $DEST_INS_SERIAL_PATH +# if [ ! -f $DEST_INS_SERIAL_PATH/GobiSerial.c ]; then +# echo -e "${RED}Error: Failed to copy GobiSerial.c to installation path, installation abort." +# rm -r $DEST_INS_SERIAL_PATH +# exit 1 +# fi + +# $QC_LN_RM_MK_DIR/cp ./GobiSerial/GobiSerial.h $DEST_INS_SERIAL_PATH +# if [ ! -f $DEST_INS_SERIAL_PATH/GobiSerial.h ]; then +# echo -e "${RED}Error: Failed to copy GobiSerial.h to installation path, installation abort." +# rm -r $DEST_INS_SERIAL_PATH +# exit 1 +# fi + +# $QC_LN_RM_MK_DIR/cp ./GobiSerial/Makefile $DEST_INS_SERIAL_PATH +# if [ ! -f $DEST_INS_SERIAL_PATH/Makefile ]; then +# echo -e "${RED}Error: Failed to copy Makefile installation path, installation abort." +# rm -r $DEST_INS_SERIAL_PATH +# exit 1 +# fi + +# $QC_LN_RM_MK_DIR/cp ./GobiSerial/qtidev.pl $DEST_INS_SERIAL_PATH +# if [ ! -f $DEST_INS_SERIAL_PATH/qtidev.pl ]; then +# echo -e "${RED}Error: Failed to copy qtidev.pl installation path, installation abort." +# rm -r $DEST_INS_SERIAL_PATH +# exit 1 +# fi +# $QC_LN_RM_MK_DIR/chmod 755 $DEST_INS_SERIAL_PATH/qtidev.pl + +$QC_LN_RM_MK_DIR/cp ./GobiSerial/qtiname.inf $DEST_INS_SERIAL_PATH +if [ ! -f $DEST_INS_SERIAL_PATH/qtiname.inf ]; then + echo -e "${RED}Error: Failed to copy qtiname.inf installation path, installation abort." + rm -r $DEST_INS_SERIAL_PATH + exit 1 +fi +$QC_LN_RM_MK_DIR/chmod 644 $DEST_INS_SERIAL_PATH/qtiname.inf + +$QC_LN_RM_MK_DIR/cp ./GobiSerial/qtimdm.inf $DEST_INS_SERIAL_PATH +if [ ! -f $DEST_INS_SERIAL_PATH/qtimdm.inf ]; then + echo -e "${RED}Error: Failed to copy qtiname.inf installation path, installation abort." + rm -r $DEST_INS_SERIAL_PATH + exit 1 +fi +$QC_LN_RM_MK_DIR/chmod 644 $DEST_INS_SERIAL_PATH/qtimdm.inf + + +$QC_LN_RM_MK_DIR/cp ./GobiSerial/qtiname.inf $DEST_INS_QDSS_PATH/ +if [ ! -f $DEST_INS_QDSS_PATH//qtiname.inf ]; then + echo -e "${RED}Error: Failed to copy qtiname.inf installation path, installation abort." + rm -r $DEST_INS_QDSS_PATH/ + exit 1 +fi +$QC_LN_RM_MK_DIR/chmod 644 $DEST_INS_SERIAL_PATH/qtiname.inf + +$QC_LN_RM_MK_DIR/cp ./GobiSerial/qtimdm.inf $DEST_INS_QDSS_PATH/ +if [ ! -f $DEST_INS_QDSS_PATH//qtimdm.inf ]; then + echo -e "${RED}Error: Failed to copy qtiname.inf installation path, installation abort." + rm -r $DEST_INS_QDSS_PATH/ + exit 1 +fi +$QC_LN_RM_MK_DIR/chmod 644 $DEST_INS_QDSS_PATH/qtimdm.inf + + +$QC_LN_RM_MK_DIR/cp ./QdssDiag/qdbusb.inf $DEST_INS_QDSS_PATH/ +if [ ! -f $DEST_INS_QDSS_PATH/qdbusb.inf ]; then + echo -e "${RED}Error: Failed to copy 'qdbusb.inf' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./QdssDiag/qtiser.inf $DEST_INS_QDSS_PATH/ +if [ ! -f $DEST_INS_QDSS_PATH/qtiser.inf ]; then + echo -e "${RED}Error: Failed to copy 'qtiser.inf' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/chmod 644 $DEST_INS_QDSS_PATH/qdbusb.inf +$QC_LN_RM_MK_DIR/chmod 644 $DEST_INS_QDSS_PATH/qtiser.inf + +$QC_LN_RM_MK_DIR/cp ./InfParser/qtiDevInf.h $DEST_INF_PATH/ +if [ ! -f $DEST_INF_PATH/qtiDevInf.h ]; then + echo -e "${RED}Error: Failed to copy 'InfParser/qtiDevInf.h' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./InfParser/qtiDevInf.c $DEST_INF_PATH/ +if [ ! -f $DEST_INF_PATH/qtiDevInf.c ]; then + echo -e "${RED}Error: Failed to copy 'InfParser/qtiDevInf.c' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./InfParser/Makefile $DEST_INF_PATH/ +if [ ! -f $DEST_INF_PATH/Makefile ]; then + echo -e "${RED}Error: Failed to copy 'InfParser/Makefile' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./QdssDiag/qtiDevInf.h $DEST_QDSS_DAIG_PATH/ +if [ ! -f $DEST_QDSS_DAIG_PATH/qtiDevInf.h ]; then + echo -e "${RED}Error: Failed to copy 'QdssDiag/qtiDevInf.h' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./QdssDiag/qtiDiag.h $DEST_QDSS_DAIG_PATH/ +if [ ! -f $DEST_QDSS_DAIG_PATH/qtiDiag.h ]; then + echo -e "${RED}Error: Failed to copy 'QdssDiag/qtiDiag.h' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./QdssDiag/qtiDiag.c $DEST_QDSS_DAIG_PATH/ +if [ ! -f $DEST_QDSS_DAIG_PATH/qtiDiag.c ]; then + echo -e "${RED}Error: Failed to copy 'QdssDiag/qtiDiag.c' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./Makefile $DEST_QDSS_DAIG_PATH/ +if [ ! -f $DEST_QDSS_DAIG_PATH/Makefile ]; then + echo -e "${RED}Error: Failed to copy 'QdssDiag/Makefile' to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + exit 1 +fi + +if [ -d $DEST_INS_RMNET_PATH ]; then + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH +fi + +$QC_LN_RM_MK_DIR/mkdir -p $DEST_INS_RMNET_PATH +if [ ! -d $DEST_INS_RMNET_PATH ]; then + echo -e "${RED}Error: Failed to create installation path, please run installer under root." + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/IPAssignmentScript.sh $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/IPAssignmentScript.sh ]; then + echo -e "${RED}Error: Failed to copy IPAssignmentScript.sh to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/chmod 755 $DEST_INS_RMNET_PATH/IPAssignmentScript.sh + +$QC_LN_RM_MK_DIR/cp ./rmnet/GobiUSBNet.c $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/GobiUSBNet.c ]; then + echo -e "${RED}Error: Failed to copy GobiUSBNet.c to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/QMIDevice.c $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/QMIDevice.c ]; then + echo -e "${RED}Error: Failed to copy QMIDevice.c to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/QMIDevice.h $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/QMIDevice.h ]; then + echo -e "${RED}Error: Failed to copy QMIDevice.h to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/QMI.c $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/QMI.c ]; then + echo -e "${RED}Error: Failed to copy QMI.c to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/QMI.h $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/QMI.h ]; then + echo -e "${RED}Error: Failed to copy QMI.h to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/qmap.c $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/qmap.c ]; then + echo -e "${RED}Error: Failed to copy qmap.c to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/qmap.h $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/qmap.h ]; then + echo -e "${RED}Error: Failed to copy qmap.h to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/Structs.h $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/Structs.h ]; then + echo -e "${RED}Error: Failed to copy Structs.h to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/Makefile $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/Makefile ]; then + echo -e "${RED}Error: Failed to copy Makefile installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/qtiwwan.inf $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/qtiwwan.inf ]; then + echo -e "${RED}Error: Failed to copy qtiwwan.inf installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi +$QC_LN_RM_MK_DIR/chmod 644 $DEST_INS_RMNET_PATH/qtiwwan.inf + +#DEST_SIGN_PATH=/opt/QTI/sign/ +$QC_LN_RM_MK_DIR/cp ./sign/SignConf.config $DEST_SIGN_PATH +$QC_LN_RM_MK_DIR/chmod 777 $DEST_SIGN_PATH/SignConf.config +awk -i inplace -v name=`hostname` '{gsub(/O = /,"O = "name)}1' $DEST_SIGN_PATH/SignConf.config +awk -i inplace -v name=`hostname` '{gsub(/CN = /,"CN = "name" Signing Key")}1' $DEST_SIGN_PATH/SignConf.config +awk -i inplace -v name=`hostname` '{gsub(/emailAddress = /,"emailAddress = "name"@no-reply.com")}1' $DEST_SIGN_PATH/SignConf.config + +if [ ! -f $DEST_SIGN_PATH/SignConf.config ]; then + echo -e "${RED}Error: Failed to copy SignConf.config installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_SIGN_PATH + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./sign/signReadme.txt $DEST_SIGN_PATH +if [ ! -f $DEST_SIGN_PATH/signReadme.txt ]; then + echo -e "${RED}Error: Failed to copy signReadme.txt installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_SIGN_PATH + exit 1 +fi +$QC_LN_RM_MK_DIR/chmod 644 $DEST_SIGN_PATH/signReadme.txt + + +if [[ $QC_SECURE_BOOT_CHECK = "SecureBoot enabled" ]]; then + echo -e "${RED}SecureBoot enabled" + if [ -f $DEST_SIGN_PATH/Signkey_pub.der ]; then + if [[ $QC_PUBLIC_KEY_VERIFY = "$DEST_SIGN_PATH/Signkey_pub.der is already enrolled" ]]; then + echo -e "${CYAN}===========================================================" + echo -e "${GREEN}$DEST_SIGN_PATH/Signkey_pub.der is enrolled" + echo -e "${CYAN}===========================================================${RESET}" + else + echo -e "${RED}===========================================================" + echo -e "${CYAN}Secure Boot is enabled. User must enroll the Public Signkey located at /opt/QTI/sign/Signkey_pub.der" + echo -e "${CYAN}Please follow the mandatory instructions in /opt/QTI/sign/signReadme.txt" + echo -e "${CYAN}The QUD driver installation Failed!!!" + echo -e "${RED}===========================================================${RESET}" + exit 1 + fi + else + echo -e "${RED}Signkey_pub.der doesn't exist. Creating public and private key${RESET}" + openssl req -x509 -new -nodes -utf8 -sha256 -days 36500 -batch -config $DEST_SIGN_PATH/SignConf.config -outform DER -out $DEST_SIGN_PATH/Signkey_pub.der -keyout $DEST_SIGN_PATH/Signkey.priv + $QC_LN_RM_MK_DIR/chmod 755 $DEST_SIGN_PATH/Signkey_pub.der + $QC_LN_RM_MK_DIR/chmod 755 $DEST_SIGN_PATH/Signkey.priv + echo -e "${RED}##############################################################" + echo -e "${CYAN}Secure Boot is enabled. User must enroll the Public Signkey located at /opt/QTI/sign/Signkey_pub.der" + echo -e "${CYAN}Please follow the mandatory instructions in /opt/QTI/sign/signReadme.txt" + echo -e "${CYAN}The QUD driver installation Failed!!!" + echo -e "${RED}##############################################################${RESET}" + exit 1 + fi +else + echo -e "${GREEN}Secure boot disabled${RESET}" +fi + +# "********************* Compilation of modules Starts ***************************" +$QC_MAKE_DIR/make install +if [ ! -f ./InfParser/$QC_MODULE_INF_NAME ]; then + echo -e "${RED}Error: Failed to generate kernel module $QC_MODULE_INF_NAME, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + $QC_MAKE_DIR/make clean + exit 1 +fi +if [ ! -f ./QdssDiag/$QC_MODULE_QDSS_DIAG_NAME ]; then + echo -e "${RED}Error: Failed to generate kernel module $QC_MODULE_QDSS_DIAG_NAME, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + $QC_MAKE_DIR/make clean + exit 1 +fi + +if [ ! -f ./rmnet/$QC_MODULE_RMNET_NAME ]; then + echo -e "${RED}Error: Failed to generate kernel module $QC_MODULE_RMNET_NAME, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + $QC_MAKE_DIR/make clean + exit 1 +fi + +# if [ ! -f ./GobiSerial/$QC_MODULE_GOBISERIAL_NAME ]; then +# echo -e "${RED}Error: Failed to generate kernel module $QC_MODULE_GOBISERIAL_NAME, installation abort." +# $QC_LN_RM_MK_DIR/rm -rf $QC_MODULE_GOBISERIAL_NAME +# $QC_MAKE_DIR/make clean +# exit 1 +# fi + +# Copy .ko object to destination folders +# $QC_LN_RM_MK_DIR/cp ./GobiSerial/$QC_MODULE_GOBISERIAL_NAME $DEST_INS_SERIAL_PATH +# if [ ! -f $DEST_INS_SERIAL_PATH/$QC_MODULE_GOBISERIAL_NAME ]; then +# echo -e "${RED}Error: Failed to copy $QC_MODULE_GOBISERIAL_NAME to installation path, installation abort." +# $QC_LN_RM_MK_DIR/rm -r $DEST_INS_SERIAL_PATH +# $QC_MAKE_DIR/make clean +# exit 1 +# fi + +$QC_LN_RM_MK_DIR/cp ./InfParser/$QC_MODULE_INF_NAME $DEST_INF_PATH +if [ ! -f $DEST_INF_PATH/$QC_MODULE_INF_NAME ]; then + echo -e "${RED}Error: Failed to copy $QC_MODULE_INF_NAME to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + $QC_MAKE_DIR/make clean + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./QdssDiag/$QC_MODULE_QDSS_DIAG_NAME $DEST_QDSS_DAIG_PATH +if [ ! -f $DEST_QDSS_DAIG_PATH/$QC_MODULE_QDSS_DIAG_NAME ]; then + echo -e "${RED}Error: Failed to copy $QC_MODULE_QDSS_DIAG_NAME to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_QDSS_PATH + $QC_MAKE_DIR/make clean + exit 1 +fi + +$QC_LN_RM_MK_DIR/cp ./rmnet/$QC_MODULE_RMNET_NAME $DEST_INS_RMNET_PATH +if [ ! -f $DEST_INS_RMNET_PATH/$QC_MODULE_RMNET_NAME ]; then + echo -e "${RED}Error: Failed to copy $QC_MODULE_RMNET_NAME to installation path, installation abort." + $QC_LN_RM_MK_DIR/rm -rf $DEST_INS_RMNET_PATH + exit 1 +fi + +$QC_MAKE_DIR/make clean + +# echo SUBSYSTEMS==\"tty\", PROGRAM=\"$DEST_INS_SERIAL_PATH/qtidev.pl $DEST_INS_SERIAL_PATH/qtiname.inf %k\", SYMLINK+=\"%c\" , MODE=\"0666\" > ./qti_usb_device.rules +echo SUBSYSTEMS==\"GobiQMI\", MODE=\"0666\" >> ./qti_usb_device.rules +echo SUBSYSTEMS==\"GobiUSB\", MODE=\"0666\" >> ./qti_usb_device.rules +echo SUBSYSTEMS==\"GobiPorts\", MODE=\"0666\" >> ./qti_usb_device.rules + +$QC_LN_RM_MK_DIR/chmod 644 ./qti_usb_device.rules +$QC_LN_RM_MK_DIR/cp ./qti_usb_device.rules $QC_UDEV_PATH +echo -e "Generated QC rules" + +# udev rules for QMI +if [ -f $QC_UDEV_PATH/80-gobinet-usbdevice.rules ]; then + RULE_EXIST="`grep -nr 'usb' $QC_UDEV_PATH/80-gobinet-usbdevice.rules`" + if [ "$RULE_EXIST" != "" ]; then + echo -e "Subsystem GobiQMI rule already exist in $QC_UDEV_PATH/80-gobinet-usbdevice.rules, nothing to add" + else + echo -e "Subsystem GobiQMI rule doesn't exist in $QC_UDEV_PATH/80-gobinet-usbdevice.rules, so adding now" + $QC_LN_RM_MK_DIR/chmod 644 $QC_UDEV_PATH/80-gobinet-usbdevice.rules + echo SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"05c6\", NAME=\"usb%n\" >> $QC_UDEV_PATH/80-gobinet-usbdevice.rules + fi +else + echo SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"05c6\", NAME=\"usb%n\" >> ./80-gobinet-usbdevice.rules + $QC_LN_RM_MK_DIR/chmod 644 ./80-gobinet-usbdevice.rules + $QC_LN_RM_MK_DIR/cp ./80-gobinet-usbdevice.rules $QC_UDEV_PATH + echo -e "Creating new udev rule for GobiQMI in $QC_UDEV_PATH/80-gobinet-usbdevice.rules" +fi + +# Informs udev deamon to reload the newly added device rule and re-trigger service +sudo udevadm control --reload-rules +sudo udevadm trigger + +if [ ! -f $QC_UDEV_PATH/qti_usb_device.rules ]; then + echo -e "${RED}Error: Failed to generate $QC_UDEV_PATH/qti_usb_device.rules" + exit 1 +fi + +if [ ! -f $QC_UDEV_PATH/80-gobinet-usbdevice.rules ]; then + echo -e "${RED}Error: Failed to generate $QC_UDEV_PATH/80-gobinet-usbdevice.rules" + exit 1 +fi + +rm -f ./qti_usb_device.rules +rm -f ./80-net-setup-link.rules +rm -f ./80-gobinet-usbdevice.rules +echo -e "Removed local rules" + +MODLOADED="`/sbin/lsmod | grep usbserial`" +if [ "$MODLOADED" == "" ]; then + echo -e "To load dependency" + echo -e "Loading module usbserial" + if [[ $OSName =~ "Red Hat Enterprise Linux" ]]; then + if [ -f $QC_SERIAL/usbserial.ko.xz ]; then + xz -d $QC_SERIAL/usbserial.ko.xz + $QC_MODBIN_DIR/insmod $QC_SERIAL/usbserial.ko + fi + MODLOADED="`/sbin/lsmod | grep usbserial`" + if [ "$MODLOADED" == "" ]; then + echo -e "$OSName: usbserial.ko module not present at $QC_SERIAL" + fi + else + $QC_MODBIN_DIR/insmod $QC_SERIAL/usbserial.ko + fi +else + echo -e "Module usbserial already in place" +fi + +#echo Changing Permission of blacklist file +$QC_LN_RM_MK_DIR/chmod 777 $MODULE_BLACKLIST/blacklist.conf +echo -e "Changed Permission of blacklist file" +if [ "`grep -nr 'Qualcomm clients' /etc/modprobe.d/blacklist.conf`" != "" ]; then + sed -i '/# Blacklist these module so that Qualcomm clients use only/d' /etc/modprobe.d/blacklist.conf + sed -i '/# GobiNet, GobiSerial, QdssDiag, qtiDevInf driver/d' /etc/modprobe.d/blacklist.conf +fi +echo -e "# Blacklist these module so that Qualcomm clients use only" >> /etc/modprobe.d/blacklist.conf +echo -e "# GobiNet, GobiSerial, QdssDiag, qtiDevInf driver" >> /etc/modprobe.d/blacklist.conf + +MOD_EXIST="`grep -nr 'blacklist qcserial' /etc/modprobe.d/blacklist.conf`" +if [ "$MOD_EXIST" != "" ]; then + sed -i '/qcserial/d' $MODULE_BLACKLIST/blacklist.conf +fi +echo -e "blacklist qcserial" >> /etc/modprobe.d/blacklist.conf +echo -e "install qcserial /bin/false" >> /etc/modprobe.d/blacklist.conf +echo -e "blacklisted qcserial module" + +MODLOADED="`/sbin/lsmod | grep qcserial`" +if [ "$MODLOADED" != "" ]; then + echo -e "qcserial is found. Unloaded qcserial module" + $QC_MODBIN_DIR/rmmod qcserial.ko + MODLOADED="`/sbin/lsmod | grep qcserial`" + if [ "$MODLOADED" != "" ]; then + echo -e "${RED}Failed to unload qcserial.ko. try manually sudo rmmod ModuleName${RESET}" + fi +fi +if [ -f $QC_SERIAL/qcserial.ko ]; then + echo -e "qcserial is found. renamed to qcserial_dup" + mv /lib/modules/`uname -r`/kernel/drivers/usb/serial/qcserial.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial/qcserial_dup +fi + +MOD_EXIST="`grep -nr 'blacklist qmi_wwan' /etc/modprobe.d/blacklist.conf`" +if [ "$MOD_EXIST" != "" ]; then + sed -i '/qmi_wwan/d' $MODULE_BLACKLIST/blacklist.conf +fi +echo -e "blacklist qmi_wwan" >> /etc/modprobe.d/blacklist.conf +echo -e "install qmi_wwan /bin/false" >> /etc/modprobe.d/blacklist.conf +echo -e "blacklisted qmi_wwan module" + +MODLOADED="`/sbin/lsmod | grep qmi_wwan`" +if [ "$MODLOADED" != "" ]; then + echo -e "qmi_wwan is found. Unloaded qmi_wwan module" + echo -e "cdc-wdm is found. Unloaded cdc-wdm module" + $QC_MODBIN_DIR/rmmod qmi_wwan.ko + $QC_MODBIN_DIR/rmmod cdc-wdm.ko + MODLOADED="`/sbin/lsmod | grep qmi_wwan`" + if [ "$MODLOADED" != "" ]; then + echo -e "${RED}Failed to unload qmi_wwan.ko. Run manually sudo rmmod ModuleName${RESET}" + fi + MODLOADED="`/sbin/lsmod | grep cdc_wdm`" + if [ "$MODLOADED" != "" ]; then + echo -e "${RED}Failed to unload cdc_wdm.ko. Run manually sudo rmmod ModuleName${RESET}" + fi +fi +if [ -f $QC_QMI_WWAN/qmi_wwan.ko ]; then + echo -e "qmi_wwan is found. renamed to qmi_wwan_dup" + echo -e "cdc-wdm is found. renamed to cdc-wdm_dup" + mv /lib/modules/`uname -r`/kernel/drivers/usb/class/cdc-wdm.ko /lib/modules/`uname -r`/kernel/drivers/usb/class/cdc-wdm_dup + mv /lib/modules/`uname -r`/kernel/drivers/net/usb/qmi_wwan.ko /lib/modules/`uname -r`/kernel/drivers/net/usb/qmi_wwan_dup +fi + +MOD_EXIST="`grep -nr 'blacklist option' /etc/modprobe.d/blacklist.conf`" +if [ "$MOD_EXIST" != "" ]; then + sed -i '/option/d' $MODULE_BLACKLIST/blacklist.conf +fi +echo -e "blacklist option" >> /etc/modprobe.d/blacklist.conf +echo -e "install option /bin/false" >> /etc/modprobe.d/blacklist.conf +echo -e "blacklisted option module" + +MODLOADED="`/sbin/lsmod | grep option`" +if [ "$MODLOADED" != "" ]; then + echo -e "option is found. Unloaded option module" + $QC_MODBIN_DIR/rmmod option.ko + MODLOADED="`/sbin/lsmod | grep option`" + if [ "$MODLOADED" != "" ]; then + echo -e "${RED}Failed to unload option.ko. Run manually sudo rmmod option${RESET}" + fi +fi +if [ -f $QC_SERIAL/option.ko ]; then + echo -e "option is found. renamed to to option_dup" + mv /lib/modules/`uname -r`/kernel/drivers/usb/serial/option.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial/option_dup +fi + +MOD_EXIST="`grep -nr 'blacklist usb_wwan' /etc/modprobe.d/blacklist.conf`" +if [ "$MOD_EXIST" != "" ]; then + sed -i '/usb_wwan/d' $MODULE_BLACKLIST/blacklist.conf +fi +echo -e "blacklist usb_wwan" >> /etc/modprobe.d/blacklist.conf +echo -e "install usb_wwan /bin/false" >> /etc/modprobe.d/blacklist.conf +echo -e "blacklisted usb_wwan module" + +MODLOADED="`/sbin/lsmod | grep usb_wwan`" +if [ "$MODLOADED" != "" ]; then + echo -e "usb_wwan is found. Unloaded usb_wwan module" + $QC_MODBIN_DIR/rmmod usb_wwan.ko + MODLOADED="`/sbin/lsmod | grep usb_wwan`" + if [ "$MODLOADED" != "" ]; then + echo -e "${RED}Failed to unload usb_wwan.ko. Run manually sudo rmmod ModuleName${RESET}" + fi +fi +if [ -f $QC_SERIAL/usb_wwan.ko ]; then + echo -e "usb_wwan is found. renamed to usb_wwan_dup" + mv /lib/modules/`uname -r`/kernel/drivers/usb/serial/usb_wwan.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial/usb_wwan_dup +fi + +MODLOADED="`/sbin/lsmod | grep GobiSerial`" +if [ "$MODLOADED" != "" ]; then + ( $QC_MODBIN_DIR/rmmod $QC_MODULE_GOBISERIAL_NAME && echo -e "$QC_MODULE_GOBISERIAL_NAME removed successfully.." ) || { echo -e "$QC_MODULE_GOBISERIAL_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } +fi + +# echo -e "Loading module $QC_MODULE_GOBISERIAL_NAME" +# $QC_MODBIN_DIR/insmod $DEST_INS_SERIAL_PATH/$QC_MODULE_GOBISERIAL_NAME gQTIModemInfFilePath=$QC_MODEM_INF_PATH debug=0 + +MODLOADED="`/sbin/lsmod | grep QdssDiag`" +if [ "$MODLOADED" != "" ]; then + ($QC_MODBIN_DIR/rmmod $QC_MODULE_QDSS_DIAG_NAME && echo -e "$QC_MODULE_QDSS_DIAG_NAME removed successfully..") || { echo -e "$QC_MODULE_QDSS_DIAG_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } +fi + +echo -e "Loading module dependency" +MODLOADED="`/sbin/lsmod | grep mii`" +if [ "$MODLOADED" == "" ]; then + echo -e "Loading module mii" + if [[ $OSName =~ "Red Hat Enterprise Linux" ]] || [[ $OSName =~ "Fedora Linux" ]] || [[ $OSName =~ "Ubuntu 24.04" ]]; then + if [ -f $QC_NET/mii.ko.xz ]; then + xz -d $QC_NET/mii.ko.xz + fi + if [ -f $QC_NET/mii.ko.zst ]; then + unzstd -d $QC_NET/mii.ko.zst + fi + if [ -f $QC_NET/mii.ko ]; then + $QC_MODBIN_DIR/insmod $QC_NET/mii.ko + fi + MODLOADED="`/sbin/lsmod | grep mii`" + if [ "$MODLOADED" == "" ]; then + echo -e "$OSName: mii.ko module not present at $QC_NET" + fi + else + $QC_MODBIN_DIR/insmod $QC_NET/mii.ko + fi +else + echo -e "Module mii already in place" +fi + +MODLOADED="`/sbin/lsmod | grep usbnet`" +if [ "$MODLOADED" == "" ]; then + echo -e "Loading module usbnet" + if [[ $OSName =~ "Red Hat Enterprise Linux" ]] || [[ $OSName =~ "Fedora Linux" ]] || [[ $OSName =~ "Ubuntu 24.04" ]]; then + if [ -f $QC_QMI_WWAN/usbnet.ko.xz ]; then + xz -d $QC_QMI_WWAN/usbnet.ko.xz + fi + if [ -f $QC_QMI_WWAN/usbnet.ko.zst ]; then + unzstd -d $QC_QMI_WWAN/usbnet.ko.zst + fi + if [ -f $QC_QMI_WWAN/usbnet.ko ]; then + $QC_MODBIN_DIR/insmod $QC_QMI_WWAN/usbnet.ko + fi + MODLOADED="`/sbin/lsmod | grep usbnet`" + if [ "$MODLOADED" == "" ]; then + echo -e "$OSName: usbnet.ko module not present at $QC_QMI_WWAN" + fi + else + $QC_MODBIN_DIR/insmod $QC_QMI_WWAN/usbnet.ko + fi +else + echo -e "Module usbnet already in place" +fi + +MODLOADED="`/sbin/lsmod | grep GobiNet`" +if [ "$MODLOADED" != "" ]; then + ($QC_MODBIN_DIR/rmmod $QC_MODULE_RMNET_NAME && echo -e "$QC_MODULE_RMNET_NAME removed successfully..") || { echo -e "$QC_MODULE_RMNET_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } +fi + +MODLOADED="`/sbin/lsmod | grep qtiDevInf`" +if [ "$MODLOADED" != "" ]; then + ($QC_MODBIN_DIR/rmmod $QC_MODULE_INF_NAME && echo -e "$QC_MODULE_INF_NAME removed successfully..") || { echo -e "$QC_MODULE_INF_NAME in use"; echo -e "${RED}Note: ${CYAN} Close all applications that make use of the driver, including QUTS clients."; echo -e "${RED}ps -aux | grep QUTS, sudo kill -9 OR sudo pkill QUTS"; echo -e "${GREEN}Try $1ation again!"; exit 1; } +fi + +echo -e "Loading new module $QC_MODULE_INF_NAME" +$QC_MODBIN_DIR/insmod $DEST_INF_PATH/$QC_MODULE_INF_NAME debug_g=0 +MODLOADED="`/sbin/lsmod | grep qtiDevInf`" +if [ "$MODLOADED" == "" ]; then + echo -e "${RED}Failed to load new $QC_MODULE_INF_NAME module" + exit 1 +fi +echo -e "Loading new module $QC_MODULE_QDSS_DIAG_NAME" +$QC_MODBIN_DIR/insmod $DEST_QDSS_DAIG_PATH/$QC_MODULE_QDSS_DIAG_NAME gQdssInfFilePath=$QC_QDSS_INF_PATH gDiagInfFilePath=$QC_DIAG_INF_PATH debug_g=0 +MODLOADED="`/sbin/lsmod | grep QdssDiag`" +if [ "$MODLOADED" == "" ]; then + echo -e "${RED}Failed to load new $QC_MODULE_INF_NAME module" + exit 1 +fi +echo -e "Loading new module $QC_MODULE_RMNET_NAME" +$QC_MODBIN_DIR/insmod $DEST_INS_RMNET_PATH/$QC_MODULE_RMNET_NAME debug_g=0 debug_aggr=0 +MODLOADED="`/sbin/lsmod | grep GobiNet`" +if [ "$MODLOADED" == "" ]; then + echo -e "${RED}Failed to load new $QC_MODULE_INF_NAME module" + exit 1 +fi +# update modules.dep and modules.alias +depmod + +$QC_MAKE_DIR/find $DEST_QTI_PATH -type d -exec chmod 0755 {} \; + +echo -e "Qualcomm GobiNet driver is installed at $DEST_INS_RMNET_PATH" +echo -e "Qualcomm INF Parser driver is installed at $DEST_INF_PATH" +echo -e "Qualcomm QDSS/Diag driver is installed at $DEST_QDSS_DAIG_PATH" +echo -e "Qualcomm Modem driver is installed at $DEST_INS_SERIAL_PATH" +echo -e "Qualcomm Gobi device naming rules are installed at $QC_UDEV_PATH" + +if [ -f "$DEST_QUD_PATH/ReleaseNotes*.txt" ]; then + echo -e "QUD Release Notes available at $DEST_QUD_PATH" +fi + +MODUPDATE="`grep -r QCDevInf /etc/modules`" +if [ "$MODUPDATE" == "QCDevInf" ]; then + sed -i '/QCDevInf/d' /etc/modules +fi +MODUPDATE="`grep -nr qtiDevInf /etc/modules`" +if [ "$MODUPDATE" == "" ]; then + echo -e "qtiDevInf" >> /etc/modules +fi + +MODUPDATE="`grep -nr QdssDiag /etc/modules`" +if [ "$MODUPDATE" == "" ]; then + echo -e "QdssDiag" >> /etc/modules +fi + +MODUPDATE="`grep -nr GobiNet /etc/modules`" +if [ "$MODUPDATE" == "" ]; then + echo -e "GobiNet" >> /etc/modules +fi + +# MODUPDATE="`grep -nr GobiSerial /etc/modules`" +# if [ "$MODUPDATE" == "" ]; then +# echo -e "GobiSerial" >> /etc/modules +# fi + +if [[ $OSName != *"Red Hat Enterprise Linux"* ]]; then + MODUPDATE="`grep -nr 'iface usb0 inet static' /etc/network/interfaces`" + if [ "$MODUPDATE" == "" ]; then + echo -e "iface usb0 inet static" >> /etc/network/interfaces + fi +fi + +exit 0 diff --git a/src/linux/README.md b/src/linux/README.md index 1ffed05..7cb0bf2 100644 --- a/src/linux/README.md +++ b/src/linux/README.md @@ -1,3 +1,59 @@ +## Installing Qualcomm USB Kernel Drivers on Linux + +### Debian Package Installation (Recommended) + +The recommended way to install on Debian/Ubuntu systems is via the `.deb` package. It uses DKMS to automatically build, install, and manage the kernel modules. + +#### Build the Package + +```bash +# Install build dependencies (one-time) +sudo apt-get install debhelper dkms dpkg-dev dh-dkms linux-headers-$(uname -r) + +# Build from the repository root +./build-deb.sh +``` + +The version is read from `src/linux/version.h` and automatically synced to all packaging files. + +#### Install + +```bash +sudo dpkg -i ../qcom-usb-drivers-dkms__all.deb +``` + +#### Uninstall + +```bash +sudo dpkg -r qcom-usb-drivers-dkms +``` + +#### Upgrade + +Install the newer `.deb` directly — it automatically removes the old version, builds, and installs the new modules: + +```bash +sudo dpkg -i ../qcom-usb-drivers-dkms__all.deb +``` + +#### Check Status + +```bash +dpkg -s qcom-usb-drivers-dkms | grep Version +dkms status +lsmod | grep qti +``` + +#### What the Package Does + +- Builds 4 kernel modules via DKMS: `qtiDevInf`, `qcom_usb`, `qcom_usbnet`, `qcom-serial` +- Automatically rebuilds modules when the kernel is updated +- Blacklists conflicting in-tree modules (`qcserial`, `qmi_wwan`, `cdc_wdm`, `option`, `usb_wwan`) +- Installs udev rules for device permissions +- Cleans up pre-existing manual installs during installation +- Loads modules immediately after installation + +--- ## Building, Installing, and Uninstalling QUD Driver Modules (Without qcom_drivers.sh) @@ -35,7 +91,7 @@ Then execute: #### Note - Modifying qcom_drivers.sh is not recommended, as it is reserved for full installation and uninstallation workflows. -- For complete installations, dependency handling, conflict resolution, and thorough cleanup, we recommend using qcom_driver.sh +- For complete installations, dependency handling, conflict resolution, and thorough cleanup, we recommend using the deb package or qcom_driver.sh @@ -97,4 +153,4 @@ Step 3: If installation is successful, verify QUD status once again! ```bash lsmod | grep qti ``` -(you will see GobiNet, qtiDevInf, qdssdiag). If drivers are not present. Verify “/lib/modules/`uname -r`/kernel/drivers/net/usb” location for GobiNet, qtiDevInf, qdssdiag driver. \ No newline at end of file +(you will see GobiNet, qtiDevInf, qdssdiag). If drivers are not present. Verify "/lib/modules/`uname -r`/kernel/drivers/net/usb" location for GobiNet, qtiDevInf, qdssdiag driver. \ No newline at end of file diff --git a/src/linux/version.h b/src/linux/version.h index 95ed94c..9cbf24f 100644 --- a/src/linux/version.h +++ b/src/linux/version.h @@ -5,5 +5,5 @@ #ifndef VERSION_H #define VERSION_H -#define DRIVER_VERSION "1.0.6.0" +#define DRIVER_VERSION "1.0.6.1" #endif From 1dfc5e33007a842609bf0c27f56f482eeff3ecb4 Mon Sep 17 00:00:00 2001 From: hangz Date: Thu, 9 Apr 2026 00:03:40 -0700 Subject: [PATCH 2/2] fix: correct Conflicts/Replaces to use actual userspace package name The Conflicts and Replaces fields referenced non-existent package names (qcom-usb-userspace-drivers, qcom-usb-userspace-drivers-dkms). Fixed to use the actual installed package name: qcom-usb-userspace-driver. This enables apt to automatically resolve the mutual exclusion between kernel-mode and userspace driver packages during cross-installation. --- debian/control | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index f37d627..9c12d7a 100644 --- a/debian/control +++ b/debian/control @@ -9,8 +9,8 @@ Rules-Requires-Root: no Package: qcom-usb-drivers-dkms Architecture: all Depends: ${misc:Depends}, dkms, linux-headers-generic | linux-headers-amd64 | linux-headers-arm64 -Conflicts: qcom-usb-userspace-drivers, qcom-usb-userspace-drivers-dkms -Replaces: qcom-usb-userspace-drivers, qcom-usb-userspace-drivers-dkms +Conflicts: qcom-usb-userspace-driver +Replaces: qcom-usb-userspace-driver Description: Qualcomm USB kernel drivers (DKMS) DKMS package for Qualcomm USB kernel drivers including: * qtiDevInf - INF file parser for device enumeration