--- a/src/fdmdv2_main.h
+++ b/src/fdmdv2_main.h
@@ -51,6 +51,15 @@
 #include <wx/regex.h>
 #include <wx/socket.h>
 
+#define HAVE_LINUX_HIDRAW_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 <hamlib.h> 
@@ -186,6 +195,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;
@@ -406,6 +418,11 @@
         txRxThread*             m_txRxThread;
 
         bool                    OpenHamlibRig();
+	void                    HIDPTT(int pushed);
+	void                    SetupHIDPort(void);
+	void                    CloseHIDPort(void);
+	int                     m_hidPort;
+	char                    m_hidGPIO;
         void                    SetupSerialPort(void);
         void                    CloseSerialPort(void);
         void                    SerialPTTRx(void);
--- a/src/dlg_ptt.h
+++ b/src/dlg_ptt.h
@@ -57,6 +57,13 @@
         wxTextCtrl   *m_txtCtrlVoiceKeyerRxPause;
         wxTextCtrl   *m_txtCtrlVoiceKeyerRepeats;
 
+        /* HID PTT settings.*/
+
+	wxCheckBox* m_ckUseHIDPTT;
+	wxListBox* m_listHidPorts;
+	wxTextCtrl *m_txtHidDevicePath;
+	wxTextCtrl *m_txtHidDeviceBit;
+
         /* Hamlib settings.*/
 
         wxCheckBox *m_ckUseHamlibPTT;
@@ -87,6 +94,7 @@
         void populatePortList();
 
         void PTTUseHamLibClicked(wxCommandEvent& event);
+        void PTTUseHIDClicked(wxCommandEvent& event);
         void PTTUseSerialClicked(wxCommandEvent& event);
 
         void OnChooseVoiceKeyerWaveFile(wxCommandEvent& event);
--- a/src/dlg_ptt.cpp
+++ b/src/dlg_ptt.cpp
@@ -84,6 +84,42 @@
     mainSizer->Add(staticBoxSizer28a, 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
     //----------------------------------------------------------------------
 
@@ -97,7 +133,7 @@
     gridSizer100->Add(m_ckUseHamlibPTT, 0, wxALIGN_CENTER_VERTICAL, 0);
 
     /* Hamlib Rig Type combobox. */
-    gridSizer100->Add(new wxStaticText(this, wxID_ANY, _("Rig Model:"), wxDefaultPosition, wxDefaultSize, 0), 
+   gridSizer100->Add(new wxStaticText(this, wxID_ANY, _("Rig Model:"), wxDefaultPosition, wxDefaultSize, 0),
                       0, wxALIGN_CENTER_VERTICAL | wxLEFT, 20);
     m_cbRigName = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(250, -1), 0, NULL, wxCB_DROPDOWN);
     /* TODO(Joel): this is a hack. At the least, need to gurantee that m_hamLib
@@ -210,6 +246,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);
@@ -225,6 +262,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);
@@ -344,7 +382,7 @@
 void ComPortsDlg::ExchangeData(int inout)
 {
     wxConfigBase *pConfig = wxConfigBase::Get();
-    wxString str;
+    wxString str,hidstr,hidbit;
     
     if(inout == EXCHANGE_DATA_IN)
     {
@@ -361,13 +399,21 @@
         m_cbRigName->SetSelection(wxGetApp().m_intHamlibRig);
         m_cbSerialPort->SetValue(wxGetApp().m_strHamlibSerialPort);
 
+	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);
@@ -403,6 +449,21 @@
         pConfig->Write(wxT("/Hamlib/RigName"), wxGetApp().m_intHamlibRig);
         pConfig->Write(wxT("/Hamlib/SerialPort"), wxGetApp().m_strHamlibSerialPort);
 
+        /* 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();
@@ -438,6 +499,13 @@
 }
 
 //-------------------------------------------------------------------------
+// PTTUseHIDClicked()
+//-------------------------------------------------------------------------
+void ComPortsDlg::PTTUseHIDClicked(wxCommandEvent& event)
+{
+}
+
+//-------------------------------------------------------------------------
 // PTTUseSerialClicked()
 //-------------------------------------------------------------------------
 void ComPortsDlg::PTTUseSerialClicked(wxCommandEvent& event)
--- a/src/fdmdv2_main.cpp
+++ b/src/fdmdv2_main.cpp
@@ -359,6 +359,10 @@
     wxGetApp().m_intHamlibRig = pConfig->ReadLong("/Hamlib/RigName", 0);
     wxGetApp().m_strHamlibSerialPort = pConfig->Read("/Hamlib/SerialPort", "");
     
+    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);
@@ -1473,6 +1477,14 @@
  
     }
 
+    if(wxGetApp().m_boolUseHIDPTT && m_hidPort >= 0)
+    {
+        if(g_tx)
+	  HIDPTT(1);
+        else
+	  HIDPTT(0);
+    }
+
     // reset level gauge
 
     m_maxLevel = 0;
@@ -2144,6 +2156,9 @@
             OpenHamlibRig();
             wxGetApp().m_hamlib->close();
         }
+        if (wxGetApp().m_boolUseHIDPTT) {
+            SetupHIDPort();
+        }
         if (wxGetApp().m_boolUseSerialPTT) {
             SetupSerialPort();
             CloseSerialPort();
@@ -2410,6 +2425,9 @@
             }
         }
 
+        if (wxGetApp().m_boolUseHIDPTT)
+            CloseHIDPort();
+
         if (wxGetApp().m_boolUseSerialPTT)
             CloseSerialPort();
 
@@ -3898,3 +3916,84 @@
     foff_phase_rect->real /= mag;	 
     foff_phase_rect->imag /= mag;	 
 }
+
+//----------------------------------------------------------------
+// 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
+}
+
+//----------------------------------------------------------------
+// SetupHIDPort()
+//----------------------------------------------------------------
+void MainFrame::SetupHIDPort(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);
+    }
+}
