--- a/src/fdmdv2_main.h
+++ b/src/fdmdv2_main.h
@@ -48,6 +48,14 @@
 #include <wx/regex.h>
 #include <wx/socket.h>
 
+#ifdef HAVE_LINUX_HIDRAW_H
+#include <linux/hidraw.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#endif
+
 #include <samplerate.h>
 
 #include <stdint.h>
@@ -193,6 +201,9 @@
 
         bool                m_boolUseSerialPTT;
         wxString            m_strRigCtrlPort;
+        wxString            m_strRigHidPort;
+        wxString            m_strRigHidBit;
+	bool                m_boolUseHIDPTT;
         bool                m_boolUseRTS;
         bool                m_boolRTSPos;
         bool                m_boolUseDTR;
@@ -468,7 +479,12 @@
         txRxThread*             m_txRxThread;
 
         bool                    OpenHamlibRig();
-        void                    OpenSerialPort(void);
+	void                    HIDPTT(int pushed);
+        void                    OpenHIDPort(void);
+	void                    CloseHIDPort(void);
+	int                     m_hidPort;
+	char                    m_hidGPIO;
+	void                    OpenSerialPort(void);
         void                    CloseSerialPort(void);
         void                    SerialPTTRx(void);
 
--- a/src/dlg_ptt.h
+++ b/src/dlg_ptt.h
@@ -49,6 +49,13 @@
     protected:
         wxCheckBox* m_ckLeftChannelVoxTone;
 
+        /* HID PTT settings.*/
+
+	wxCheckBox* m_ckUseHIDPTT;
+	wxListBox* m_listHidPorts;
+	wxTextCtrl *m_txtHidDevicePath;
+	wxTextCtrl *m_txtHidDeviceBit;
+
         /* Hamlib settings.*/
 
         wxCheckBox *m_ckUseHamlibPTT;
@@ -81,6 +88,7 @@
         void populatePortList();
 
         void PTTUseHamLibClicked(wxCommandEvent& event);
+        void PTTUseHIDClicked(wxCommandEvent& event);
         void PTTUseSerialClicked(wxCommandEvent& event);
 
         void OnTest(wxCommandEvent& event);
--- a/src/dlg_ptt.cpp
+++ b/src/dlg_ptt.cpp
@@ -51,6 +51,42 @@
     mainSizer->Add(staticBoxSizer28, 0, wxEXPAND, 5);
 
     //----------------------------------------------------------------------
+    // HID PTT
+    //----------------------------------------------------------------------
+
+    wxStaticBoxSizer* staticBoxSizerHID = new wxStaticBoxSizer( new wxStaticBox(this, wxID_ANY, _("HID PTT Settings")), wxVERTICAL);
+
+    wxBoxSizer* gridSizerHID = new wxBoxSizer(wxHORIZONTAL);
+
+    /* Use HID PTT checkbox. */
+    m_ckUseHIDPTT = new wxCheckBox(this, wxID_ANY, _("Use HID PTT"), wxDefaultPosition, wxDefaultSize, 0);
+    m_ckUseHIDPTT->SetValue(false);
+    gridSizerHID->Add(m_ckUseHIDPTT, 0, wxALIGN_CENTER_VERTICAL, 2);
+
+    /* HID device path listbox. */
+    //wxArrayString m_listHidPortsArr;
+    gridSizerHID->Add(new wxStaticText(this, wxID_ANY, _("Device (/dev/hidraw? :"), wxDefaultPosition, wxDefaultSize, 0),
+                      0, wxALIGN_CENTER_VERTICAL | wxLEFT, 2);
+    //m_listHidPorts = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(250, -1), m_listHidPortsArr, wxLB_SINGLE | wxLB_SORT);
+    //gridSizerHID->Add(m_listHidPorts, 1, wxALIGN_CENTER_VERTICAL, 0);
+
+    m_txtHidDevicePath = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(140,-1), 0);
+    gridSizerHID->Add(m_txtHidDevicePath, 1, wxEXPAND|wxALIGN_CENTER|wxALIGN_RIGHT, 2);
+
+    /* HID GPIO selector. */
+    wxArrayString m_listHidGPIOArr;
+
+    gridSizerHID->Add(new wxStaticText(this, wxID_ANY, _("GPIO PIN # :"), wxDefaultPosition, wxDefaultSize, 0),
+                      0, wxALIGN_CENTER_VERTICAL | wxLEFT, 0);
+    // listHIDGPIO = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), m_listHidGPIOArr, wxLB_SINGLE | wxLB_SORT);
+    // gridSizerHID->Add(listHIDGPIO, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 0);
+    m_txtHidDeviceBit = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(20,-1), 0);
+    gridSizerHID->Add(m_txtHidDeviceBit, 1, wxEXPAND|wxALIGN_CENTER|wxALIGN_RIGHT, 2);
+
+    staticBoxSizerHID->Add(gridSizerHID, 0);
+    mainSizer->Add(staticBoxSizerHID, 1);
+
+    //----------------------------------------------------------------------
     // Hamlib for CAT PTT
     //----------------------------------------------------------------------
 
@@ -68,7 +104,7 @@
     /* Hamlib Rig Type combobox. */
 
     gridSizerhl->Add(new wxStaticText(this, wxID_ANY, _("Rig Model:"), wxDefaultPosition, wxDefaultSize, 0), 
-                      0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT, 20);
+                      0, wxALIGN_CENTER_VERTICAL | wxLEFT, 20);
     m_cbRigName = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(250, -1), 0, NULL, wxCB_DROPDOWN | wxCB_READONLY);
     wxGetApp().m_hamlib->populateComboBox(m_cbRigName);
     m_cbRigName->SetSelection(wxGetApp().m_intHamlibRig);
@@ -193,6 +229,7 @@
     // Connect events
     this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(ComPortsDlg::OnInitDialog), NULL, this);
     m_ckUseHamlibPTT->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseHamLibClicked), NULL, this);
+    m_ckUseHIDPTT->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseHIDClicked), NULL, this);
     m_ckUseSerialPTT->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseSerialClicked), NULL, this);
     m_buttonOK->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnOK), NULL, this);
     m_buttonCancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnCancel), NULL, this);
@@ -208,6 +245,7 @@
     // Disconnect Events
     this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(ComPortsDlg::OnInitDialog), NULL, this);
     m_ckUseHamlibPTT->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseHamLibClicked), NULL, this);
+    m_ckUseHIDPTT->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseHIDClicked), NULL, this);
     m_ckUseSerialPTT->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ComPortsDlg::PTTUseSerialClicked), NULL, this);
     m_buttonOK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnOK), NULL, this);
     m_buttonCancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ComPortsDlg::OnCancel), NULL, this);
@@ -339,7 +377,7 @@
 void ComPortsDlg::ExchangeData(int inout)
 {
     wxConfigBase *pConfig = wxConfigBase::Get();
-    wxString str;
+    wxString str,hidstr,hidbit;
     
     if(inout == EXCHANGE_DATA_IN) {
         m_ckLeftChannelVoxTone->SetValue(wxGetApp().m_leftChannelVoxTone);
@@ -358,13 +396,21 @@
 
         /* Serial PTT */
 
+	m_ckUseHIDPTT->SetValue(wxGetApp().m_boolUseHIDPTT);
+	hidstr = wxGetApp().m_strRigHidPort;
+	hidbit = wxGetApp().m_strRigHidBit;
+
         m_ckUseSerialPTT->SetValue(wxGetApp().m_boolUseSerialPTT);
         str = wxGetApp().m_strRigCtrlPort;
 #ifdef __WXMSW__
         m_listCtrlPorts->SetStringSelection(str);
+	m_listHidPorts->SetStringSelection(hidstr);
+	m_listHidBit->SetStringSelection(hidbit);
 #endif
 #if defined(__WXOSX__) || defined(__WXGTK__)
         m_cbCtlDevicePath->SetValue(str);
+	m_txtHidDevicePath->SetValue(hidstr);
+	m_txtHidDeviceBit->SetValue(hidbit);
 #endif
         m_rbUseRTS->SetValue(wxGetApp().m_boolUseRTS);
         m_ckRTSPos->SetValue(wxGetApp().m_boolRTSPos);
@@ -397,6 +443,21 @@
         pConfig->Write(wxT("/Hamlib/SerialPort"), wxGetApp().m_strHamlibSerialPort);
         pConfig->Write(wxT("/Hamlib/SerialRate"), wxGetApp().m_intHamlibSerialRate);
 
+        /* HID PTT settings. */
+
+        wxGetApp().m_boolUseHIDPTT = m_ckUseHIDPTT->IsChecked();
+#ifdef __WXMSW__
+        wxGetApp().m_strRigHidPort = m_listHidPorts->GetStringSelection();
+        wxGetApp().m_strRigHidBit  = m_listHidPorts->GetStringSelection();
+#endif
+#ifdef __WXGTK__
+        wxGetApp().m_strRigHidPort             = m_txtHidDevicePath->GetValue();
+        wxGetApp().m_strRigHidBit             = m_txtHidDeviceBit->GetValue();
+#endif
+        pConfig->Write(wxT("/Rig/UseHIDPTT"),    wxGetApp().m_boolUseHIDPTT);
+        pConfig->Write(wxT("/Rig/HIDPort"),    wxGetApp().m_strRigHidPort);
+        pConfig->Write(wxT("/Rig/HIDBit"),    wxGetApp().m_strRigHidBit);
+
         /* Serial settings */
 
         wxGetApp().m_boolUseSerialPTT           = m_ckUseSerialPTT->IsChecked();
@@ -545,6 +606,13 @@
 
 
 //-------------------------------------------------------------------------
+// PTTUseHIDClicked()
+//-------------------------------------------------------------------------
+void ComPortsDlg::PTTUseHIDClicked(wxCommandEvent& event)
+{
+}
+
+//-------------------------------------------------------------------------
 // PTTUseSerialClicked()
 //-------------------------------------------------------------------------
 void ComPortsDlg::PTTUseSerialClicked(wxCommandEvent& event)
--- a/src/fdmdv2_main.cpp
+++ b/src/fdmdv2_main.cpp
@@ -479,6 +479,10 @@
     wxGetApp().m_strHamlibSerialPort = pConfig->Read("/Hamlib/SerialPort", "");
     wxGetApp().m_intHamlibSerialRate = pConfig->ReadLong("/Hamlib/SerialRate", 0);
     
+    wxGetApp().m_boolUseHIDPTT      = pConfig->ReadBool(wxT("/Rig/UseHIDPTT"), false);
+    wxGetApp().m_strRigHidPort      = pConfig->Read(wxT("/Rig/HIDPort"), wxT(""));
+    wxGetApp().m_strRigHidBit      = pConfig->Read(wxT("/Rig/HIDBit"), wxT(""));
+
     wxGetApp().m_boolUseSerialPTT   = pConfig->ReadBool(wxT("/Rig/UseSerialPTT"),   false);
     wxGetApp().m_strRigCtrlPort     = pConfig->Read(wxT("/Rig/Port"),               wxT(""));
     wxGetApp().m_boolUseRTS         = pConfig->ReadBool(wxT("/Rig/UseRTS"),         true);
@@ -1639,6 +1643,14 @@
         wxGetApp().m_serialport->ptt(g_tx);
     }
 
+    if(wxGetApp().m_boolUseHIDPTT && m_hidPort >= 0)
+    {
+        if(g_tx)
+	  HIDPTT(1);
+        else
+	  HIDPTT(0);
+    }
+
     // reset level gauge
 
     m_maxLevel = 0;
@@ -2823,6 +2835,8 @@
         
         if (wxGetApp().m_boolHamlibUseForPTT)
             OpenHamlibRig();
+        if (wxGetApp().m_boolUseHIDPTT)
+            OpenHIDPort();
         if (wxGetApp().m_boolUseSerialPTT) {
             OpenSerialPort();
         }
@@ -2871,6 +2885,9 @@
             }
         }
 
+        if (wxGetApp().m_boolUseHIDPTT)
+            CloseHIDPort();
+
         if (wxGetApp().m_boolUseSerialPTT) {
             CloseSerialPort();
         }
@@ -4742,3 +4759,84 @@
         return;
     }
 }
+
+//----------------------------------------------------------------
+// HIDPTT(int pushed)
+//----------------------------------------------------------------
+void MainFrame::HIDPTT(int pushed)
+{
+#ifdef HAVE_LINUX_HIDRAW_H
+  if (m_hidPort>0) {
+    // Build two packets for CM108 HID.  One turns a GPIO bit on.  The other turns it off.
+    // Packet is 4 bytes, preceded by a 'report number' byte
+    // 0x00 report number
+    // Write data packet (from CM108 documentation)
+    // byte 0: 00xx xxxx     Write GPIO
+    // byte 1: xxxx dcba     GPIO3-0 output values (1=high)
+    // byte 2: xxxx dcba     GPIO3-0 data-direction register (1=output)
+    // byte 3: xxxx xxxx     SPDIF
+
+    char out_rep[] = {
+      0x00, // report number
+      // HID output report
+      0x00,
+      (char)(pushed ? (1 << m_hidGPIO) : 0), // set GPIO
+      (char)(1 << m_hidGPIO), // Data direction register (1=output)
+      0x00
+    };
+
+    // printf("HIDPTT: using gpio=%d\n", m_hidGPIO);
+    // printf("HIDPTT: ptt state=%d\n", pushed ? (1 << m_hidGPIO) : 0);
+    if (write(m_hidPort, out_rep, sizeof(out_rep)) < 0) {
+      printf("HIDPTT: CM108 write error\n");
+    }
+  }
+#endif
+}
+
+//----------------------------------------------------------------
+// OpenHIDPort()
+//----------------------------------------------------------------
+void MainFrame::OpenHIDPort(void)
+{
+#ifdef HAVE_LINUX_HIDRAW_H
+  struct hidraw_devinfo hiddevinfo;
+
+    if(!wxGetApp().m_strRigHidPort.IsEmpty())
+    {
+      m_hidGPIO = 0x0f & wxAtoi(wxGetApp().m_strRigHidBit);
+      m_hidPort = open(wxGetApp().m_strRigHidPort.c_str(),O_RDWR,0);
+      // 0x0d8c is the vendor id of CMedia USB sound devices that may have HID GPIO features
+      if ((m_hidPort >=0)&&(!ioctl(m_hidPort, HIDIOCGRAWINFO, &hiddevinfo) && hiddevinfo.vendor == 0x0d8c))
+        {
+            //  always start with PTT cleared
+	    HIDPTT(0);
+            //m_btnTogPTT->Enable(true);
+            m_btnTogPTT->SetValue(false);
+        }
+        else
+        {
+#endif
+            m_hidPort = -1;
+            m_hidGPIO = -1;
+            //m_btnTogPTT->Disable();
+#ifdef HAVE_LINUX_HIDRAW_H
+        }
+    }
+#endif
+}
+
+//----------------------------------------------------------------
+// CloseHIDPort()
+//----------------------------------------------------------------
+void MainFrame::CloseHIDPort(void)
+{
+    if(m_hidPort != 0)
+    {
+      close(m_hidPort);
+      m_hidPort = 0;
+      m_hidGPIO = -1;
+      //m_btnTogPTT->SetLabel(wxT("PTT"));
+      //m_btnTogPTT->Enable(false);
+    }
+}
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -184,6 +184,7 @@
 check_include_files("inttypes.h"   HAVE_INTTYPES_H)
 check_include_files("sys/stat.h"   HAVE_SYS_STAT_H)
 check_include_files("sys/types.h"  HAVE_SYS_TYPES_H)
+check_include_files("linux/hidraw.h"  HAVE_LINUX_HIDRAW_H)
 
 include(CheckTypeSize)
 check_type_size("int" SIZEOF_INT)
@@ -201,6 +202,10 @@
 include(CheckSymbolExists)
 check_symbol_exists("_fseeki64" "stdio.h" HAVE__FSEEKI64)
 
+if(${HAVE_LINUX_HIDRAW_H})
+ add_definitions(-DHAVE_LINUX_HIDRAW_H)
+endif(${HAVE_LINUX_HIDRAW_H})
+
 # fdmdv2_main.h requires patching to find config.h as it current looks in the
 # source directory and the generated file goes in the binary directory.
 configure_file ("${PROJECT_SOURCE_DIR}/cmake/config.h.in"
