@@ -147,6 +147,135 @@ void ptt_set_debug(int debug)
147
147
ptt_debug_level = debug ;
148
148
}
149
149
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
+ }
150
279
151
280
/*-------------------------------------------------------------------
152
281
*
@@ -368,6 +497,11 @@ void ptt_init (struct audio_s *audio_config_p)
368
497
using_gpio = 1 ;
369
498
}
370
499
}
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
+ }
371
505
}
372
506
}
373
507
@@ -434,111 +568,12 @@ void ptt_init (struct audio_s *audio_config_p)
434
568
int ot ;
435
569
for (ot = 0 ; ot < NUM_OCTYPES ; ot ++ ) {
436
570
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 );
542
577
}
543
578
}
544
579
}
@@ -823,7 +858,67 @@ void ptt_set (int ot, int chan, int ptt_signal)
823
858
824
859
} /* end ptt_set */
825
860
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
826
919
920
+ return -1 ; /* Method was none, or something went wrong */
921
+ }
827
922
828
923
/*-------------------------------------------------------------------
829
924
*
0 commit comments