diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4e02a13..07faa33 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -420,6 +420,24 @@ if(UDEV_FOUND)
endif()
+# Utility for setting the CM108 GPIO pins.
+if(UDEV_FOUND)
+ list(APPEND cm108_set_gpio_SOURCES
+ cm108_set_gpio.c
+ ${cm108_SOURCES}
+ )
+
+ add_executable(cm108_set_gpio
+ ${cm108_set_gpio_SOURCES}
+ )
+
+ target_link_libraries(cm108_set_gpio
+ ${MISC_LIBRARIES}
+ ${UDEV_LIBRARIES}
+ )
+endif()
+
+
# Touch Tone to Speech sample application.
# ttcalc
list(APPEND ttcalc_SOURCES
diff --git a/src/cm108.c b/src/cm108.c
index ad3b0b8..3e8cd41 100644
--- a/src/cm108.c
+++ b/src/cm108.c
@@ -836,10 +836,11 @@ static int cm108_write (char *name, int iomask, int iodata)
io[3] = iomask;
io[4] = 0;
- // Writing 4 bytes fails with errno 32, EPIPE, "broken pipe."
- // Hamlib writes 5 bytes which I don't understand.
- // Writing 5 bytes works.
- // I have no idea why. From the CMedia datasheet it looks like we need 4.
+ // Per https://www.kernel.org/doc/Documentation/hid/hidraw.txt, the
+ // first byte is the report number, which is always 0 since the device
+ // only has 1 report per the datasheet. The remaining 4 bytes follow the
+ // structure specified in the datasheet, although we only care about the
+ // GPIO bytes here.
n = write (fd, io, sizeof(io));
if (n != sizeof(io)) {
diff --git a/src/cm108_set_gpio.c b/src/cm108_set_gpio.c
new file mode 100644
index 0000000..1ce0ff9
--- /dev/null
+++ b/src/cm108_set_gpio.c
@@ -0,0 +1,54 @@
+//
+// This file is part of Dire Wolf, an amateur radio packet TNC.
+//
+// Copyright (C) 2014, 2016, 2017 John Langner, WB2OSZ
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+
+
+/*------------------------------------------------------------------
+ *
+ * Module: cm108_set_gpio.c
+ *
+ * Purpose: Utility to set GPIO pins on a CM108.
+ *
+ * Description: Test utility to set the GPIO pins on a CM108 USB sound device.
+ *
+ *---------------------------------------------------------------*/
+
+#include
+
+#include "cm108.h"
+#include "textcolor.h"
+
+void usage() {
+ text_color_set(DW_COLOR_INFO);
+ dw_printf("\n");
+ dw_printf("cm108_set_gpio - Utility to set a CM108 GPIO pin.\n");
+ dw_printf("\n");
+ dw_printf("Usage: cm108_set_gpio /dev/hidrawN PIN_NUMBER <0|1>\n");
+ dw_printf("\n");
+}
+
+int main (int argc, char **argv) {
+ if (argc != 4) {
+ usage();
+ return 1;
+ }
+ char* hidraw_filename = argv[1];
+ int pin_num = atoi(argv[2]);
+ int state = atoi(argv[3]);
+ return cm108_set_gpio_pin(hidraw_filename, pin_num, state);
+}