14 Commits
Author SHA1 Message Date
NotAlexNoyle 5bfd977df5 Generic install script 2026-06-14 23:48:00 -04:00
NotAlexNoyle e313b97dc3 Modernize, merge ARM macOS support from @incidentist 2026-06-14 09:26:48 -04:00
NotAlexNoyle 38f144d38f opendoas support 2026-06-13 14:54:31 -04:00
NotAlexNoyle 3fd1f67b3b Merge pull request #1 from jessicarod7/patch-1
Update instructions for GCC 15
2026-02-11 05:05:35 +00:00
Jessica Rodriguez 61b3452840 Update instructions for GCC 15
Add instruction to target C17 standard on GCC 15 or later
2026-02-10 10:25:29 -05:00
NotAlexNoyle 8361062427 Compatibility with libusb-compat-0.1 2025-11-20 22:49:14 -05:00
codepoet fb63e66c65 Update README.md 2022-11-09 07:51:15 -05:00
Dan Kurtz a5e6c23d53 Updated README 2020-12-04 12:02:14 -08:00
Dan Kurtz dfd12c7187 Pretend Darwin is Linux in makefile 2020-12-04 11:47:13 -08:00
Dan Kurtz 9b98aec864 Use PLATFORM_PTHREADS on host builds 2020-12-04 11:26:53 -08:00
Dan Kurtz 0f49b2447f Remove unused linux import 2020-12-04 11:24:42 -08:00
Dan Kurtz 2e69450243 Add gitignore 2020-12-04 11:24:12 -08:00
NotAlexNoyle f0343e4c41 Fix typos, clarify usage 2019-11-14 04:53:17 -05:00
NotAlexNoyle 5ed3a1def2 Add screenshot for release 2019-02-18 01:33:53 -05:00
7 changed files with 169 additions and 25 deletions

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
build-*
*.swp
*~
tags
TAGS
*.orig
cscope.*
*.dSYM
+49 -6
View File
@@ -1,17 +1,60 @@
novacomd
========
This build of novacomd is for armhf (raspberry Pi 3!)
A 2026 build of novacomd for UNIX-like hosts built on top of libusb-compat-0.1. novacomd runs as a daemon or service on the host and the device.
Requires libusb-dev
## Dependencies
To build:
Building from source needs a C compiler (GCC or Clang), **GNU make**, and **libusb-compat-0.1**.
make host && mv build-novacom-host /usr/local/webos/usr/sbin/novacomd (or whatever your preferred install location is in your $PATH)
Get a compiler:
novacomd runs as a daemon or service on the host and the device
* **macOS:** Apple's Clang and make come with the Xcode Command Line Tools (`xcode-select --install`).
* **Linux:** install your distribution's build tools (`build-essential` on Debian/Ubuntu, `base-devel` on Arch, etc.).
# Copyright and License Information
Get libusb-compat-0.1:
| Platform | Command |
| --- | --- |
| macOS (Homebrew) | `brew install libusb-compat` |
| Debian / Ubuntu | `sudo apt install libusb-dev` |
| Fedora | `sudo dnf install libusb-compat-0.1-devel` |
| Arch | `sudo pacman -S libusb-compat` |
| Void | `doas xbps-install -Su libusb-compat-devel` |
(On Debian/Ubuntu the libusb-0.1 development package is named `libusb-dev`; `libusb-1.0-0-dev` is a legacy, unused package.)
## Building
Run the build script from the source directory. It picks a compiler and adds `-std=gnu17` when supported:
> ./install-novacomd.sh
To force a specific compiler, set `CC`:
> CC="gcc -std=gnu17" ./install-novacomd.sh
The built daemon lands at `build-novacomd-host/novacomd`.
## Installing
**Linux** — re-run the script with privilege escalation. It still builds as your normal user, then installs to `/usr/local/bin` (override with `INSTALL_DIR`):
> sudo ./install-novacomd.sh
`doas ./install-novacomd.sh` works too.
**macOS** — build *without* privilege escalation (running the script as root is refused), then copy the binary into your Palm SDK `bin`, usually `/opt/nova/bin`:
> ./install-novacomd.sh
>
> sudo cp build-novacomd-host/novacomd /opt/nova/bin/novacomd
![In Action](https://i.imgur.com/GUqOYEp.png)
Thanks to [incidentist](https://github.com/incidentist/novacomd) for the macOS build support.
## Copyright
Unless otherwise specified, all content, including all source code files
and documentation files in this repository are:
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env bash
#
# Build and (optionally) install novacomd -- NotAlexNoyle's 2025 libusb-compat fork.
#
# Run from the novacomd source dir, or point at it with $NOVACOMD_SRC or the first argument.
# Unprivileged: builds only. As root (sudo/doas): builds as the invoking user, then installs.
#
# Environment overrides:
# NOVACOMD_SRC source directory (default: this script's directory)
# CC C compiler (default: gcc/cc + -std=gnu17 when supported; whitespace-split, no quoted args)
# INSTALL_DIR install location (default: /usr/local/bin)
# JOBS parallel make jobs (default: CPU count)
#
# Exit status: 0 on success, non-zero on failure. Public domain.
# Author: NotAlexNoyle (alexnoyle@icloud.com)
set -u
readonly TARGET="novacomd"
readonly BUILD_BIN="build-${TARGET}-host/${TARGET}"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
log() { printf 'novacomd-install: %s\n' "$*"; }
err() { printf 'novacomd-install: ERROR: %s\n' "$*" >&2; }
die() { err "$*"; exit 1; }
# --- locate the source tree ---
# Source precedence: argument 1, then $NOVACOMD_SRC, then this script's own directory.
self="$(readlink -f -- "${BASH_SOURCE[0]}" 2>/dev/null || printf '%s' "${BASH_SOURCE[0]}")"
script_dir="$(cd -- "$(dirname -- "$self")" >/dev/null 2>&1 && pwd -P)"
src_dir="${1:-${NOVACOMD_SRC:-$script_dir}}"
cd -- "$src_dir" >/dev/null 2>&1 || die "cannot enter novacomd source directory: $src_dir"
src_dir="$(pwd -P)"
[ -f makefile ] || [ -f Makefile ] || die "no makefile in $src_dir -- pass the source directory as the first argument."
# --- privilege model ---
# The build toolchain must never run as root; when root, drop to the invoking user for every build step.
orig_user="${SUDO_USER:-${DOAS_USER:-}}"
builder_prefix=()
if (( EUID == 0 )); then
builder_uid="$(id -u "$orig_user" 2>/dev/null || true)" # require a real, non-root account (UID > 0)
if [ -n "$orig_user" ] && [[ "$builder_uid" =~ ^[1-9][0-9]*$ ]] && command -v runuser >/dev/null 2>&1; then
builder_prefix=(runuser -u "$orig_user" --)
else
die "refusing to build as root -- run as a normal user; privilege escalation is only used to install."
fi
fi
as_builder() { "${builder_prefix[@]}" "$@"; }
# --- preflight: build tools ---
command -v make >/dev/null 2>&1 || die "'make' not found -- install your build tools (build-essential / base-devel)."
# --- compiler selection ---
# Default the compiler when CC is unset, and add -std=gnu17 only if accepted (C23-default compilers need it).
if [ -z "${CC:-}" ]; then
if command -v gcc >/dev/null 2>&1; then CC=gcc; else CC=cc; fi
if printf 'int main(void){return 0;}\n' | as_builder $CC -std=gnu17 -fsyntax-only -xc - >/dev/null 2>&1; then
CC="$CC -std=gnu17"
fi
fi
# Split CC ("gcc -std=gnu17") into an argv array, then confirm a compiler is set and exists.
read -r -a cc_argv <<<"$CC"
[ "${#cc_argv[@]}" -gt 0 ] || die "CC is empty -- set it to a C compiler, e.g. CC=gcc."
command -v "${cc_argv[0]}" >/dev/null 2>&1 || die "C compiler not found: ${cc_argv[0]}"
# --- preflight: libusb-compat header ---
# The host transport needs libusb-compat-0.1 (<usb.h>); probe for it up front for a clear message.
if ! printf '#include <usb.h>\nint main(void){return 0;}\n' | as_builder "${cc_argv[@]}" -fsyntax-only -xc - >/dev/null 2>&1; then
die "missing libusb-compat-0.1 (<usb.h>). Install it, e.g.:
Debian/Ubuntu: sudo apt install libusb-dev
Fedora: sudo dnf install libusb-compat-0.1-devel
Void: doas xbps-install -Su libusb-compat-devel
Arch: sudo pacman -S libusb-compat"
fi
# --- build ---
# Default JOBS to the CPU count, and clear inherited make flags that could turn the build into a no-op.
[ -n "${JOBS:-}" ] || JOBS="$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)"
[[ "$JOBS" =~ ^[1-9][0-9]*$ ]] || JOBS=1
unset MAKEFLAGS MFLAGS GNUMAKEFLAGS MAKEFILES
log "building $TARGET (CC=$CC, jobs=$JOBS${builder_prefix:+, as $orig_user})..."
as_builder make -j"$JOBS" CC="$CC" host || die "build failed -- see the compiler output above."
[ -f "$BUILD_BIN" ] && [ -x "$BUILD_BIN" ] || die "build reported success but $BUILD_BIN is missing."
log "build succeeded: $BUILD_BIN"
# --- install (root only) ---
if (( EUID == 0 )); then
dest="$INSTALL_DIR/$TARGET"
[ -d "$dest" ] && die "install destination is a directory: $dest"
mkdir -p -- "$INSTALL_DIR" || die "cannot create $INSTALL_DIR"
log "installing to $dest..."
install -T -m 0755 -- "$BUILD_BIN" "$dest" || die "failed to install to $dest"
[ -f "$dest" ] && [ -x "$dest" ] || die "post-install check failed: $dest"
log "installed: $dest"
else
# Not root: print the manual install command using the available privilege escalation tool.
if command -v doas >/dev/null 2>&1; then elevate="doas"; else elevate="sudo"; fi
log "not running as root -- skipping install."
log "to install: $elevate install -T -m 0755 '$src_dir/$BUILD_BIN' '$INSTALL_DIR/$TARGET'"
fi
exit 0
+2 -2
View File
@@ -39,7 +39,7 @@ CFLAGS :=
ifneq ($(MACHINE),)
MYCFLAGS += -DMACHINE=\"$(MACHINE)\"
endif
HOSTCFLAGS := $(MYCFLAGS) $(CFLAGS) -Isrc
HOSTCFLAGS := $(MYCFLAGS) $(CFLAGS) -Isrc -DPLATFORM_PTHREADS=1
DEVICECFLAGS := $(MYCFLAGS) $(OECFLAGS) $(TARGET_CC_ARCH) -DPLATFORM_PTHREADS=1
CPPFLAGS := -g
ASMFLAGS :=
@@ -62,7 +62,7 @@ DEVICELD := arm-none-linux-gnueabi-ld
endif
ifeq ($(UNAME),Linux)
ifeq ($(UNAME), $(filter $(UNAME), Linux Darwin))
LDFLAGS += -Wl,-rpath,. # add the local path to the program's search path
HOSTLDLIBS += -lpthread -lusb
HOSTPLATFORM := pthreads
+1 -1
View File
@@ -42,7 +42,7 @@ typedef struct recovery_entry_s {
} recovery_entry_t;
/* list of recovery tokens */
TAILQ_HEAD(recovery_queue_s, recovery_entry_s) t_recovery_queue;
static TAILQ_HEAD(recovery_queue_s, recovery_entry_s) t_recovery_queue;
static platform_mutex_t recovery_lock;
-16
View File
@@ -33,7 +33,6 @@
#include <log.h>
#include <sys/queue.h>
#include <linux/usbdevice_fs.h>
#include "../novacom/mux.h"
#include "device_list.h"
@@ -68,19 +67,9 @@ typedef struct {
int iface;
} novacom_usb_handle_t;
typedef struct recovery_entry_s {
transport_recovery_token_t *t_token; /* transport recovery token */
int timeout; /* timout value */
TAILQ_ENTRY(recovery_entry_s) entries; /* holds pointers to prev, next entries */
} recovery_entry_t;
/* vars */
static platform_thread_t findandattach_thread;
volatile int novacom_shutdown = 0;
/* list of recovery tokens */
TAILQ_HEAD(recovery_queue_s, recovery_entry_s) t_recovery_queue;
static platform_mutex_t recovery_lock;
/* find_endpoints */
@@ -541,9 +530,6 @@ static void *novacom_usb_findandattach_thread(void *arg)
/* init records */
usbrecords_init();
/* initialize records queue */
TAILQ_INIT(&t_recovery_queue);
/* device discovery */
while (!novacom_shutdown) {
@@ -578,7 +564,6 @@ int novacom_usb_transport_start(void)
{
novacom_shutdown = 0;
platform_create_thread(&findandattach_thread, &novacom_usb_findandattach_thread, NULL);
platform_mutex_init(&recovery_lock);
return 0;
}
@@ -587,7 +572,6 @@ int novacom_usb_transport_stop(void)
novacom_shutdown = 1;
platform_waitfor_thread(findandattach_thread);
platform_mutex_destroy(&recovery_lock);
return 0;
}
+4
View File
@@ -255,6 +255,10 @@ void *packet_thread(void *arg)
break;
case PACKET_HEADER_TYPE_ERR:
TRACEF("unexpected incoming stderr data");
rc = bufq_consume_sleep(args->in_queue, h.size);
if ((size_t)rc < h.size)
goto conn_fail;
break;
default:
rc = bufq_consume_sleep(args->in_queue, h.size);
if ((size_t)rc < h.size)