aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorspv <spv@spv.sh>2025-12-03 15:10:12 -0500
committerspv <spv@spv.sh>2025-12-03 15:10:12 -0500
commitb0fbe74d91a53a7453c9dced6f75fa4cb78a6688 (patch)
tree67969c938065621ac9a89555ebab25b5e1318315
parent54b82dcc5990225575fd822cced0ab4bff0bed46 (diff)
now with c!
-rw-r--r--.gitignore2
-rw-r--r--Makefile30
-rw-r--r--README2
-rw-r--r--res/dockd.service7
-rwxr-xr-xsrc/check_docked.sh3
-rw-r--r--src/config.h13
-rwxr-xr-xsrc/dock_checker.sh34
-rw-r--r--src/logger.h19
-rw-r--r--src/main.c71
9 files changed, 143 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1005f6f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+bin
+*.swp
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2763637
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+CC=gcc
+CFLAGS=`pkg-config --cflags --libs libusb-1.0`
+
+all: bin bin/dockd
+
+bin:
+ mkdir bin
+
+bin/dockd: src/main.c
+ gcc -o $@ $< ${CFLAGS}
+
+clean:
+ rm -rf bin
+
+run: all
+ bin/dockd
+
+install: all
+ mkdir ~/.local/dockd
+ cp -pf bin/dockd ~/.local/bin
+ ln -s ${PWD}/src/sh/docked.sh ~/.local/dockd/on_docked
+ ln -s ${PWD}/src/sh/undocked.sh ~/.local/dockd/on_undocked
+# cp -pf res/dockd.service ~/.config/systemd/user/
+# ln -fs ~/.config/systemd/user/dockd.service ~/.config/systemd/user/default.target.wants/dockd.service
+
+uninstall:
+ rm -rf ~/.local/dockd
+ rm ~/.local/bin/dockd
+# rm ~/.config/systemd/user/dockd.service
+# rm ~/.config/systemd/user/default.target.wants/dockd.service
diff --git a/README b/README
index fe6e40e..146dfe0 100644
--- a/README
+++ b/README
@@ -5,4 +5,4 @@ poll usb for thinkpad ultra dock, run scripts in folder when status changes.
roadmap
-------
- [ ] c rewrite, fuck your 6-digit PIDs
+ [x] c rewrite, fuck your 6-digit PIDs
diff --git a/res/dockd.service b/res/dockd.service
new file mode 100644
index 0000000..0e09403
--- /dev/null
+++ b/res/dockd.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=mein klein dockd
+
+[Service]
+Type=exec
+ExecStart=/usr/bin/bash -c '$HOME/.local/bin/dockd 2>&1 > /tmp/dockdlog'
+Restart=always
diff --git a/src/check_docked.sh b/src/check_docked.sh
deleted file mode 100755
index 81019dc..0000000
--- a/src/check_docked.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env zsh
-
-lsusb | grep -q "ThinkPad Ultra Dock" && echo docked || echo undocked
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..2ec1d3d
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,13 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define DOCK_VENDOR 0x17ef
+#define DOCK_PRODUCT 0x100f
+
+#define ON_DOCKED "/home/spv/.local/dockd/on_docked"
+#define ON_UNDOCKED "/home/spv/.local/dockd/on_undocked"
+
+#define LOG_FP stderr
+#define LOG_LEVEL LOG_INFO
+
+#endif
diff --git a/src/dock_checker.sh b/src/dock_checker.sh
deleted file mode 100755
index 5b4f1f8..0000000
--- a/src/dock_checker.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env zsh
-
-SCRIPT_DIR=$(dirname $(realpath $0))
-cd $SCRIPT_DIR
-
-rm .{un,}docked
-
-while true; do
- if [ "$(./check_docked.sh)" = "docked" ]; then
- if [ -e .docked ]; then
- continue
- fi
-
- echo docking...
-
- rm -f .undocked
- sh/docked.sh
-
- touch .docked
- else
- if [ -e .undocked ]; then
- continue
- fi
-
- echo undocking...
-
- rm -f .docked
- sh/undocked.sh
-
- touch .undocked
- fi
-
- sleep 5
-done
diff --git a/src/logger.h b/src/logger.h
new file mode 100644
index 0000000..99b7b04
--- /dev/null
+++ b/src/logger.h
@@ -0,0 +1,19 @@
+#ifndef LOGGER_H
+#define LOGGER_H
+
+#include <stdio.h>
+
+enum log_levels {
+ LOG_ERROR,
+ LOG_INFO,
+ LOG_DEBUG,
+ LOG_INSANEDEBUG,
+};
+
+#define LOG(LEVEL, args...) do { \
+ if (LEVEL <= LOG_LEVEL) { \
+ fprintf(LOG_FP, args); \
+ } \
+} while (0)
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..80598e1
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libusb.h>
+#include "config.h"
+#include "logger.h"
+
+static char* on_docked;
+static char* on_undocked;
+
+int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
+ libusb_hotplug_event event, void *user_data) {
+ static libusb_device_handle *dev_handle = NULL;
+ struct libusb_device_descriptor desc;
+
+ (void)libusb_get_device_descriptor(dev, &desc);
+
+ LOG(LOG_DEBUG, "device: 0x%04x 0x%04x\n", desc.idVendor, desc.idProduct);
+
+ if (desc.idVendor == DOCK_VENDOR && desc.idProduct == DOCK_PRODUCT) {
+ if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
+ if (fork() == 0) {
+ execl(ON_DOCKED, ON_DOCKED, NULL);
+ }
+ LOG(LOG_DEBUG, "docked\n");
+ } else {
+ if (fork() == 0) {
+ execl(ON_UNDOCKED, ON_UNDOCKED, NULL);
+ }
+ LOG(LOG_DEBUG, "undocked\n");
+ }
+ } else {
+ LOG(LOG_DEBUG, "not dock\n");
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[]) {
+ libusb_hotplug_callback_handle callback_handle;
+ int rc;
+
+ LOG(LOG_INFO, "starting dockd...\n");
+
+ libusb_init_context(NULL, NULL, 0);
+
+ LOG(LOG_DEBUG, "init'd libusb context.\n");
+
+ rc = libusb_hotplug_register_callback(NULL,
+ LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
+ LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0,
+ LIBUSB_HOTPLUG_MATCH_ANY,
+ LIBUSB_HOTPLUG_MATCH_ANY,
+ LIBUSB_HOTPLUG_MATCH_ANY,
+ hotplug_callback, NULL,
+ &callback_handle);
+
+ if (rc != LIBUSB_SUCCESS) {
+ LOG(LOG_ERROR, "failed to register libusb callback.\n");
+ exit(rc);
+ } else {
+ LOG(LOG_DEBUG, "registered libusb hotplub callback.\n");
+ }
+
+ LOG(LOG_DEBUG, "beginning event loop...\n");
+
+ while (1) {
+ libusb_handle_events_completed(NULL, NULL);
+ nanosleep(&(struct timespec){0, 10000000UL}, NULL);
+ }
+}