← KD100

Handle incomplete sets gracefully in set-based mode

44a8f632244792c84e853f6af9739a517093e76a · Claude · Jan 22, 2026 20:17

When users have odd numbers of wheel functions (e.g., 3 or 5), the
previous code would wrap around unexpectedly when toggling to a
non-existent function, causing confusing jumps between sets.

Example problem:
- 3 functions (Set 1: 0-1, Set 2: 2 only)
- At Set 2, function 2, single-click tried to go to function 3
- Function 3 doesn't exist → wrapped to function 0 (jumped to Set 1!)

Solution:
- Check if target function exists before toggling
- If target doesn't exist, stay at current function (no action)
- Show debug message explaining why action was ignored

Checks added:
1. Single-click: Verify target function exists before toggling within set
2. Double-click: Verify target set's first function exists before switching
3. Triple-click: Double-check target set exists (in addition to >= 5 check)

Now works correctly with any number of functions:
- 2 functions: Set 1 complete
- 3 functions: Set 1 complete, Set 2 has only function 2 (toggle ignored)
- 4 functions: Sets 1-2 complete
- 5 functions: Sets 1-2 complete, Set 3 has only function 4 (toggle ignored)
- 6 functions: All sets complete

Files modified:
- src/device.c: Add existence checks for all set operations

+40 −13 · 1 file changed

  • src/device.c +40 −13
diff --git a/src/device.c b/src/device.c
index d024760..833a5e9 100644
--- a/src/device.c
+++ b/src/device.c
@@ -324,29 +324,56 @@ void device_run(libusb_context* ctx, config_t* config, int debug, int accept, in
                             // Process based on click count
                             if (final_click_count == 1) {
                                 // Single-click: toggle within current set
-                                wheel_position_in_set = 1 - wheel_position_in_set;
+                                int new_position = 1 - wheel_position_in_set;
+                                int target_function = (wheel_current_set * 2) + new_position;
+
+                                // Only toggle if the target function exists
+                                if (target_function < config->totalWheels) {
+                                    wheel_position_in_set = new_position;
+                                } else {
+                                    if (debug == 1) {
+                                        printf("Toggle ignored: function %d doesn't exist (have %d functions)\n",
+                                               target_function, config->totalWheels);
+                                    }
+                                }
                             } else if (final_click_count == 2) {
-                                // Double-click: toggle between Set 0 and Set 1
+                                // Double-click: toggle between Set 0 and Set 1 (only if target set exists)
+                                int target_set = -1;
                                 if (wheel_current_set == 0) {
-                                    wheel_current_set = 1;
+                                    target_set = 1;
                                 } else if (wheel_current_set == 1) {
-                                    wheel_current_set = 0;
+                                    target_set = 0;
                                 } else {
                                     // From Set 2, go to Set 0
-                                    wheel_current_set = 0;
+                                    target_set = 0;
+                                }
+
+                                // Check if target set has at least the first function
+                                int target_function = target_set * 2;
+                                if (target_function < config->totalWheels) {
+                                    wheel_current_set = target_set;
+                                    wheel_position_in_set = 0;  // Start at first function in new set
+                                } else {
+                                    if (debug == 1) {
+                                        printf("Double-click ignored: Set %d doesn't exist (have %d functions)\n",
+                                               target_set + 1, config->totalWheels);
+                                    }
                                 }
-                                wheel_position_in_set = 0;  // Start at first function in new set
                             } else if (final_click_count >= 3) {
-                                // Triple-click: toggle to/from Set 2 (only if Set 2 exists - need at least 5 functions)
+                                // Triple-click: toggle to/from Set 3 (only if Set 3 exists - need at least 5 functions)
                                 if (config->totalWheels >= 5) {
-                                    if (wheel_current_set == 2) {
-                                        // From Set 2, go back to Set 0
-                                        wheel_current_set = 0;
+                                    int target_set = (wheel_current_set == 2) ? 0 : 2;
+                                    int target_function = target_set * 2;
+
+                                    // Double-check that target function exists
+                                    if (target_function < config->totalWheels) {
+                                        wheel_current_set = target_set;
+                                        wheel_position_in_set = 0;  // Start at first function in new set
                                     } else {
-                                        // From Set 0 or 1, go to Set 2
-                                        wheel_current_set = 2;
+                                        if (debug == 1) {
+                                            printf("Triple-click ignored: Set %d doesn't exist\n", target_set + 1);
+                                        }
                                     }
-                                    wheel_position_in_set = 0;  // Start at first function in new set
                                 } else {
                                     if (debug == 1) {
                                         printf("Triple-click ignored: Set 3 requires at least 5 wheel functions (have %d)\n",