Skip to content

Commit b104f09

Browse files
committedNov 29, 2015
Merge branch 'ab0tj-txinh' into dev
2 parents 178375f + b68039d commit b104f09

File tree

6 files changed

+268
-105
lines changed

6 files changed

+268
-105
lines changed
 

‎atest.c

+4
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,10 @@ void ptt_set (int ot, int chan, int ptt_signal)
705705
return;
706706
}
707707

708+
int get_input (int it, int chan)
709+
{
710+
return -1;
711+
}
708712

709713
static void usage (void) {
710714

‎audio.h

+10
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,16 @@ struct audio_s {
191191

192192
} octrl[NUM_OCTYPES];
193193

194+
#define ICTYPE_TXINH 0
195+
196+
#define NUM_ICTYPES 1
197+
198+
struct {
199+
ptt_method_t method; /* none, serial port, GPIO, LPT. */
200+
int gpio; /* GPIO number */
201+
int invert; /* 1 = active low */
202+
} ictrl[NUM_ICTYPES];
203+
194204
/* Transmit timing. */
195205

196206
int dwait; /* First wait extra time for receiver squelch. */

‎config.c

+47
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,53 @@ void config_init (char *fname, struct audio_s *p_audio_config,
16101610

16111611
} /* end of PTT */
16121612

1613+
/*
1614+
* INPUTS
1615+
*
1616+
* TXINH - TX holdoff input
1617+
*
1618+
* xxx GPIO [-]gpio-num (only type supported yet)
1619+
*/
1620+
1621+
else if (strcasecmp(t, "TXINH") == 0) {
1622+
int it;
1623+
char itname[8];
1624+
1625+
it = ICTYPE_TXINH;
1626+
strlcpy (itname, "TXINH", sizeof(itname));
1627+
1628+
t = split(NULL,0);
1629+
if (t == NULL) {
1630+
text_color_set(DW_COLOR_ERROR);
1631+
dw_printf ("Config file line %d: Missing input type name for %s command.\n", line, itname);
1632+
continue;
1633+
}
1634+
1635+
if (strcasecmp(t, "GPIO") == 0) {
1636+
1637+
#if __WIN32__
1638+
text_color_set(DW_COLOR_ERROR);
1639+
dw_printf ("Config file line %d: %s with GPIO is only available on Linux.\n", line, itname);
1640+
#else
1641+
t = split(NULL,0);
1642+
if (t == NULL) {
1643+
text_color_set(DW_COLOR_ERROR);
1644+
dw_printf ("Config file line %d: Missing GPIO number for %s.\n", line, itname);
1645+
continue;
1646+
}
1647+
1648+
if (*t == '-') {
1649+
p_audio_config->achan[channel].ictrl[it].gpio = atoi(t+1);
1650+
p_audio_config->achan[channel].ictrl[it].invert = 1;
1651+
}
1652+
else {
1653+
p_audio_config->achan[channel].ictrl[it].gpio = atoi(t);
1654+
p_audio_config->achan[channel].ictrl[it].invert = 0;
1655+
}
1656+
p_audio_config->achan[channel].ictrl[it].method = PTT_METHOD_GPIO;
1657+
#endif
1658+
}
1659+
}
16131660

16141661
/*
16151662
* DWAIT - Extra delay for receiver squelch.

‎hdlc_rec.c

+6
Original file line numberDiff line numberDiff line change
@@ -626,17 +626,23 @@ void dcd_change (int chan, int subchan, int slice, int state)
626626
* at the same time. The channel is busy if ANY of them
627627
* thinks the channel is busy.
628628
*
629+
* Version 1.3: New option for input signal to inhibit transmit.
630+
*
629631
*--------------------------------------------------------------------*/
630632

631633
int hdlc_rec_data_detect_any (int chan)
632634
{
635+
633636
int sc;
634637
assert (chan >= 0 && chan < MAX_CHANS);
635638

636639
for (sc = 0; sc < num_subchan[chan]; sc++) {
637640
if (composite_dcd[chan][sc] != 0)
638641
return (1);
639642
}
643+
644+
if (get_input(ICTYPE_TXINH, chan) == 1) return (1);
645+
640646
return (0);
641647

642648
} /* end hdlc_rec_data_detect_any */

‎ptt.c

+200-105
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,135 @@ void ptt_set_debug(int debug)
147147
ptt_debug_level = debug;
148148
}
149149

150+
/*-------------------------------------------------------------------
151+
*
152+
* Name: export_gpio
153+
*
154+
* Purpose: Tell the GPIO subsystem to export a GPIO line for
155+
* us to use, and set the initial state of the GPIO.
156+
*
157+
* Inputs: gpio - GPIO line to export
158+
* invert: - Is the GPIO active low?
159+
* direction: - 0 for input, 1 for output
160+
*
161+
* Outputs: None.
162+
*
163+
*------------------------------------------------------------------*/
164+
165+
void export_gpio(int gpio, int invert, int direction)
166+
{
167+
HANDLE fd;
168+
char stemp[80];
169+
struct stat finfo;
170+
int err;
171+
172+
fd = open("/sys/class/gpio/export", O_WRONLY);
173+
if (fd < 0) {
174+
text_color_set(DW_COLOR_ERROR);
175+
dw_printf ("Permissions do not allow ordinary users to access GPIO.\n");
176+
dw_printf ("Log in as root and type this command:\n");
177+
dw_printf (" chmod go+w /sys/class/gpio/export /sys/class/gpio/unexport\n");
178+
exit (1);
179+
}
180+
snprintf (stemp, sizeof(stemp), "%d", gpio);
181+
if (write (fd, stemp, strlen(stemp)) != strlen(stemp)) {
182+
int e = errno;
183+
/* Ignore EBUSY error which seems to mean */
184+
/* the device node already exists. */
185+
if (e != EBUSY) {
186+
text_color_set(DW_COLOR_ERROR);
187+
dw_printf ("Error writing \"%s\" to /sys/class/gpio/export, errno=%d\n", stemp, e);
188+
dw_printf ("%s\n", strerror(e));
189+
exit (1);
190+
}
191+
}
192+
close (fd);
193+
194+
/*
195+
Idea for future:
196+
197+
On the RPi, the device path for GPIO number XX is /sys/class/gpio/gpioXX.
198+
There was a report that it is different for the Cubieboard. For instance
199+
GPIO 61 has gpio61_pi13 in the path. This indicates connector "i" pin 13.
200+
201+
For another similar single board computer, we find the same thing:
202+
https://www.olimex.com/wiki/A20-OLinuXino-LIME#GPIO_under_Linux
203+
204+
How should we deal with this? Some possibilities:
205+
206+
(1) The user might explicitly mention the name in direwolf.conf.
207+
(2) We might be able to find the names in some system device config file.
208+
(3) Get a directory listing of /sys/class/gpio then search for a
209+
matching name. Suppose we wanted GPIO 61. First look for an exact
210+
match to "gpio61". If that is not found, look for something
211+
matching the pattern "gpio61_*".
212+
*/
213+
214+
/*
215+
* We will have the same permission problem if not root.
216+
* We only care about "direction" and "value".
217+
*/
218+
snprintf (stemp, sizeof(stemp), "sudo chmod go+rw /sys/class/gpio/gpio%d/direction", gpio);
219+
err = system (stemp);
220+
snprintf (stemp, sizeof(stemp), "sudo chmod go+rw /sys/class/gpio/gpio%d/value", gpio);
221+
err = system (stemp);
222+
223+
snprintf (stemp, sizeof(stemp), "/sys/class/gpio/gpio%d/value", gpio);
224+
225+
if (stat(stemp, &finfo) < 0) {
226+
int e = errno;
227+
text_color_set(DW_COLOR_ERROR);
228+
dw_printf ("Failed to get status for %s \n", stemp);
229+
dw_printf ("%s\n", strerror(e));
230+
exit (1);
231+
}
232+
233+
if (geteuid() != 0) {
234+
if ( ! (finfo.st_mode & S_IWOTH)) {
235+
text_color_set(DW_COLOR_ERROR);
236+
dw_printf ("Permissions do not allow ordinary users to access GPIO.\n");
237+
dw_printf ("Log in as root and type these commands:\n");
238+
dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/direction", gpio);
239+
dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/value", gpio);
240+
exit (1);
241+
}
242+
}
243+
244+
/*
245+
* Set output direction and initial state
246+
*/
247+
248+
snprintf (stemp, sizeof(stemp), "/sys/class/gpio/gpio%d/direction", gpio);
249+
fd = open(stemp, O_WRONLY);
250+
if (fd < 0) {
251+
int e = errno;
252+
text_color_set(DW_COLOR_ERROR);
253+
dw_printf ("Error opening %s\n", stemp);
254+
dw_printf ("%s\n", strerror(e));
255+
exit (1);
256+
}
257+
258+
char gpio_val[8];
259+
if (direction) {
260+
if (invert) {
261+
strlcpy (gpio_val, "high", sizeof(gpio_val));
262+
}
263+
else {
264+
strlcpy (gpio_val, "low", sizeof(gpio_val));
265+
}
266+
}
267+
else {
268+
strlcpy (gpio_val, "in", sizeof(gpio_val));
269+
}
270+
if (write (fd, gpio_val, strlen(gpio_val)) != strlen(gpio_val)) {
271+
int e = errno;
272+
text_color_set(DW_COLOR_ERROR);
273+
dw_printf ("Error writing initial state to %s\n", stemp);
274+
dw_printf ("%s\n", strerror(e));
275+
exit (1);
276+
}
277+
close (fd);
278+
}
150279

151280
/*-------------------------------------------------------------------
152281
*
@@ -368,6 +497,11 @@ void ptt_init (struct audio_s *audio_config_p)
368497
using_gpio = 1;
369498
}
370499
}
500+
for (ot = 0; ot < NUM_ICTYPES; ot++) {
501+
if (audio_config_p->achan[ch].ictrl[ot].method == PTT_METHOD_GPIO) {
502+
using_gpio = 1;
503+
}
504+
}
371505
}
372506
}
373507

@@ -434,111 +568,12 @@ void ptt_init (struct audio_s *audio_config_p)
434568
int ot;
435569
for (ot = 0; ot < NUM_OCTYPES; ot++) {
436570
if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIO) {
437-
char stemp[80];
438-
struct stat finfo;
439-
int err;
440-
441-
fd = open("/sys/class/gpio/export", O_WRONLY);
442-
if (fd < 0) {
443-
text_color_set(DW_COLOR_ERROR);
444-
dw_printf ("Permissions do not allow ordinary users to access GPIO.\n");
445-
dw_printf ("Log in as root and type this command:\n");
446-
dw_printf (" chmod go+w /sys/class/gpio/export /sys/class/gpio/unexport\n");
447-
exit (1);
448-
}
449-
snprintf (stemp, sizeof(stemp), "%d", audio_config_p->achan[ch].octrl[ot].ptt_gpio);
450-
if (write (fd, stemp, strlen(stemp)) != strlen(stemp)) {
451-
int e = errno;
452-
/* Ignore EBUSY error which seems to mean */
453-
/* the device node already exists. */
454-
if (e != EBUSY) {
455-
text_color_set(DW_COLOR_ERROR);
456-
dw_printf ("Error writing \"%s\" to /sys/class/gpio/export, errno=%d\n", stemp, e);
457-
dw_printf ("%s\n", strerror(e));
458-
exit (1);
459-
}
460-
}
461-
close (fd);
462-
463-
/*
464-
Idea for future:
465-
466-
On the RPi, the device path for GPIO number XX is /sys/class/gpio/gpioXX.
467-
There was a report that it is different for the Cubieboard. For instance
468-
GPIO 61 has gpio61_pi13 in the path. This indicates connector "i" pin 13.
469-
470-
For another similar single board computer, we find the same thing:
471-
https://www.olimex.com/wiki/A20-OLinuXino-LIME#GPIO_under_Linux
472-
473-
How should we deal with this? Some possibilities:
474-
475-
(1) The user might explicitly mention the name in direwolf.conf.
476-
(2) We might be able to find the names in some system device config file.
477-
(3) Get a directory listing of /sys/class/gpio then search for a
478-
matching name. Suppose we wanted GPIO 61. First look for an exact
479-
match to "gpio61". If that is not found, look for something
480-
matching the pattern "gpio61_*".
481-
*/
482-
483-
/*
484-
* We will have the same permission problem if not root.
485-
* We only care about "direction" and "value".
486-
*/
487-
snprintf (stemp, sizeof(stemp), "sudo chmod go+rw /sys/class/gpio/gpio%d/direction", audio_config_p->achan[ch].octrl[ot].ptt_gpio);
488-
err = system (stemp);
489-
snprintf (stemp, sizeof(stemp), "sudo chmod go+rw /sys/class/gpio/gpio%d/value", audio_config_p->achan[ch].octrl[ot].ptt_gpio);
490-
err = system (stemp);
491-
492-
snprintf (stemp, sizeof(stemp), "/sys/class/gpio/gpio%d/value", audio_config_p->achan[ch].octrl[ot].ptt_gpio);
493-
494-
if (stat(stemp, &finfo) < 0) {
495-
int e = errno;
496-
text_color_set(DW_COLOR_ERROR);
497-
dw_printf ("Failed to get status for %s \n", stemp);
498-
dw_printf ("%s\n", strerror(e));
499-
exit (1);
500-
}
501-
502-
if (geteuid() != 0) {
503-
if ( ! (finfo.st_mode & S_IWOTH)) {
504-
text_color_set(DW_COLOR_ERROR);
505-
dw_printf ("Permissions do not allow ordinary users to access GPIO.\n");
506-
dw_printf ("Log in as root and type these commands:\n");
507-
dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/direction", audio_config_p->achan[ch].octrl[ot].ptt_gpio);
508-
dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/value", audio_config_p->achan[ch].octrl[ot].ptt_gpio);
509-
exit (1);
510-
}
511-
}
512-
513-
/*
514-
* Set output direction with initial state off.
515-
*/
516-
517-
snprintf (stemp, sizeof(stemp), "/sys/class/gpio/gpio%d/direction", audio_config_p->achan[ch].octrl[ot].ptt_gpio);
518-
fd = open(stemp, O_WRONLY);
519-
if (fd < 0) {
520-
int e = errno;
521-
text_color_set(DW_COLOR_ERROR);
522-
dw_printf ("Error opening %s\n", stemp);
523-
dw_printf ("%s\n", strerror(e));
524-
exit (1);
525-
}
526-
527-
char hilo[8];
528-
if (audio_config_p->achan[ch].octrl[ot].ptt_invert) {
529-
strlcpy (hilo, "high", sizeof(hilo));
530-
}
531-
else {
532-
strlcpy (hilo, "low", sizeof(hilo));
533-
}
534-
if (write (fd, hilo, strlen(hilo)) != strlen(hilo)) {
535-
int e = errno;
536-
text_color_set(DW_COLOR_ERROR);
537-
dw_printf ("Error writing initial state to %s\n", stemp);
538-
dw_printf ("%s\n", strerror(e));
539-
exit (1);
540-
}
541-
close (fd);
571+
export_gpio(audio_config_p->achan[ch].octrl[ot].ptt_gpio, audio_config_p->achan[ch].octrl[ot].ptt_invert, 1);
572+
}
573+
}
574+
for (ot = 0; ot < NUM_ICTYPES; ot++) {
575+
if (audio_config_p->achan[ch].ictrl[ot].method == PTT_METHOD_GPIO) {
576+
export_gpio(audio_config_p->achan[ch].ictrl[ot].gpio, audio_config_p->achan[ch].ictrl[ot].invert, 0);
542577
}
543578
}
544579
}
@@ -823,7 +858,67 @@ void ptt_set (int ot, int chan, int ptt_signal)
823858

824859
} /* end ptt_set */
825860

861+
/*-------------------------------------------------------------------
862+
*
863+
* Name: get_input
864+
*
865+
* Purpose: Read the value of an input line
866+
*
867+
* Inputs: it - Input type (ICTYPE_TCINH supported so far)
868+
* chan - Audio channel number
869+
*
870+
* Outputs: 0 = inactive, 1 = active, -1 = error
871+
*
872+
* ------------------------------------------------------------------*/
873+
874+
int get_input (int it, int chan)
875+
{
876+
assert (it >= 0 && it < NUM_ICTYPES);
877+
assert (chan >= 0 && chan < MAX_CHANS);
878+
879+
if ( ! save_audio_config_p->achan[chan].valid) {
880+
text_color_set(DW_COLOR_ERROR);
881+
dw_printf ("Internal error, get_input ( %d, %d ), did not expect invalid channel.\n", it, chan);
882+
return -1;
883+
}
884+
885+
#if __WIN32__
886+
#else
887+
if (save_audio_config_p->achan[chan].ictrl[it].method == PTT_METHOD_GPIO) {
888+
int fd;
889+
char stemp[80];
890+
891+
snprintf (stemp, sizeof(stemp), "/sys/class/gpio/gpio%d/value", save_audio_config_p->achan[chan].ictrl[it].gpio);
892+
893+
fd = open(stemp, O_RDONLY);
894+
if (fd < 0) {
895+
int e = errno;
896+
text_color_set(DW_COLOR_ERROR);
897+
dw_printf ("Error opening %s to check input.\n", stemp);
898+
dw_printf ("%s\n", strerror(e));
899+
return -1;
900+
}
901+
902+
char vtemp[2];
903+
if (read (fd, vtemp, 1) != 1) {
904+
int e = errno;
905+
text_color_set(DW_COLOR_ERROR);
906+
dw_printf ("Error getting GPIO %d value\n", save_audio_config_p->achan[chan].ictrl[it].gpio);
907+
dw_printf ("%s\n", strerror(e));
908+
}
909+
close (fd);
910+
911+
if (atoi(vtemp) != save_audio_config_p->achan[chan].ictrl[it].invert) {
912+
return 1;
913+
}
914+
else {
915+
return 0;
916+
}
917+
}
918+
#endif
826919

920+
return -1; /* Method was none, or something went wrong */
921+
}
827922

828923
/*-------------------------------------------------------------------
829924
*

‎ptt.h

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ void ptt_set (int octype, int chan, int ptt);
1515

1616
void ptt_term (void);
1717

18+
int get_input (int it, int chan);
1819

1920
#endif
2021

0 commit comments

Comments
 (0)
Please sign in to comment.