1 /*
2 * example.c - example program for cwdaemon
3 * Copyright (C) 2003, 2006 Joop Stakenborg <pg4i@amsat.org>
4 * Copyright (C) 2012 - 2015 Kamil Ignacak <acerion@wp.pl>
5 *
6 * Some of this code is taken from netkeyer.c, which is part of the tlf source,
7 * here is the copyright:
8 * Tlf - contest logging program for amateur radio operators
9 * Copyright (C) 2001-2002-2003 Rein Couperus <pa0rct@amsat.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * 02110-1301, USA.
25 */
26
27 /*
28 * Compile this program with "gcc -o example example.c"
29 * Usage: 'example' or 'example <portname>'
30 */
31
32 #define _POSIX_SOURCE /* getaddrinfo() and friends. */
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
42 #include <netdb.h>
43 #include <errno.h>
44 #include <signal.h>
45
46 #define K_MESSAGE 1
47
48 #define K_RESET 0
49 #define K_SPEED 2
50 #define K_TONE 3
51 #define K_ABORT 4
52 #define K_STOP 5
53 #define K_WORDMODE 6
54 #define K_WEIGHT 7
55 #define K_DEVICE 8
56 #define K_TOD 9 // set txdelay (turn on delay)
57 #define K_ADDRESS 10 // set port address of device (obsolete)
58 #define K_SET14 11 // set pin 14 on lpt
59 #define K_TUNE 12 // tune
60 #define K_PTT 13 // PTT on/off
61 #define K_SWITCH 14 // set band switch output pins 2,7,8,9 on lpt
62 #define K_SDEVICE 15 // set sound device
63 #define K_VOLUME 16 // volume for soundcard
64
65 static char netkeyer_port[] = "6789";
66 static char netkeyer_hostaddress[16] = "127.0.0.1";
67 static int socket_descriptor;
68 static struct addrinfo *addrinfo_list;
69 static struct addrinfo *selected_addrinfo;
70
71 int netkeyer_init(void);
72 int netkeyer_close(void);
73 int netkeyer(int cw_op, const char *cwmessage);
74 void catchint(int signal);
75
76
77
78
79
netkeyer_init(void)80 int netkeyer_init(void)
81 {
82 /* Code in this function has been copied from
83 getaddrinfo() man page. */
84
85 struct addrinfo hints;
86
87 memset(&hints, 0, sizeof(struct addrinfo));
88 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
89 hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
90 hints.ai_flags = 0;
91 hints.ai_protocol = IPPROTO_UDP;
92
93 int rv = getaddrinfo(netkeyer_hostaddress,
94 netkeyer_port,
95 &hints, &addrinfo_list);
96 if (rv) {
97 fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(rv));
98 return -1;
99 }
100
101 /* getaddrinfo() returns a list of address structures.
102 Try each address until we successfully connect(2).
103 If socket(2) (or connect(2)) fails, we (close the socket
104 and) try the next address. */
105
106 for (selected_addrinfo = addrinfo_list;
107 selected_addrinfo;
108 selected_addrinfo = selected_addrinfo->ai_next) {
109
110 socket_descriptor = socket(selected_addrinfo->ai_family,
111 selected_addrinfo->ai_socktype,
112 selected_addrinfo->ai_protocol);
113 if (socket_descriptor == -1) {
114 continue;
115 }
116
117 if (connect(socket_descriptor,
118 selected_addrinfo->ai_addr,
119 selected_addrinfo->ai_addrlen) != -1) {
120 break;
121 }
122
123 close(socket_descriptor);
124 }
125
126 if (!selected_addrinfo) {
127 fprintf(stderr, "Could not connect\n");
128 return -1;
129 } else {
130 return 0;
131 }
132 }
133
134
135
136
137
netkeyer_close(void)138 int netkeyer_close(void)
139 {
140 if (close(socket_descriptor) == -1) {
141 perror("close call failed");
142 return -1;
143 }
144
145 freeaddrinfo(addrinfo_list); /* No longer needed */
146
147 return 0;
148 }
149
150
151
152
153
netkeyer(int cw_op,const char * cwmessage)154 int netkeyer(int cw_op, const char *cwmessage)
155 {
156 char buf[80];
157
158 switch (cw_op) {
159 case K_RESET :
160 buf[0] = 27;
161 sprintf(buf + 1, "0");
162 break;
163 case K_MESSAGE :
164 sprintf(buf, "%s", cwmessage);
165 break;
166 case K_SPEED :
167 buf[0] = 27;
168 sprintf(buf + 1, "2");
169 sprintf(buf + 2, "%s", cwmessage);
170 break;
171 case K_TONE :
172 buf[0] = 27;
173 sprintf(buf + 1, "3");
174 sprintf(buf + 2, "%s", cwmessage);
175 break;
176 case K_ABORT :
177 buf[0] = 27;
178 sprintf(buf + 1, "4");
179 break;
180 case K_STOP :
181 buf[0] = 27;
182 sprintf(buf + 1, "5");
183 break;
184 case K_WORDMODE :
185 buf[0] = 27;
186 sprintf(buf + 1, "6");
187 break;
188 case K_WEIGHT :
189 buf[0] = 27;
190 sprintf(buf + 1, "7");
191 sprintf(buf + 2, "%s", cwmessage);
192 break;
193 case K_DEVICE :
194 buf[0] = 27;
195 sprintf(buf + 1, "8");
196 sprintf(buf + 2, "%s", cwmessage);
197 break;
198 case K_PTT :
199 buf[0] = 27;
200 sprintf(buf + 1, "a");
201 sprintf(buf + 2, "%s", cwmessage);
202 break;
203 case K_TUNE :
204 buf[0] = 27;
205 sprintf(buf + 1, "c");
206 sprintf(buf + 2, "%s", cwmessage);
207 break;
208 case K_TOD :
209 buf[0] = 27;
210 sprintf(buf + 1, "d");
211 sprintf(buf + 2, "%s", cwmessage);
212 break;
213 case K_SDEVICE :
214 buf[0] = 27;
215 sprintf(buf + 1, "f");
216 sprintf(buf + 2, "%s", cwmessage);
217 break;
218 case K_VOLUME :
219 buf[0] = 27;
220 sprintf(buf + 1, "g");
221 sprintf(buf + 2, "%s", cwmessage);
222 break;
223 default :
224 buf[0] = '\0';
225 }
226
227 ssize_t sendto_rc = 0;
228 if (buf[0] != '\0') {
229 sendto_rc = sendto(socket_descriptor,
230 buf, sizeof (buf),
231 0,
232 selected_addrinfo->ai_addr,
233 sizeof (struct addrinfo));
234 }
235
236 buf[0] = '\0';
237 cw_op = K_RESET;
238
239 if (sendto_rc == -1) {
240 printf("Keyer send failed (%s)!\n", strerror(errno));
241 return -1;
242 } else {
243 return 0;
244 }
245 }
246
247
248
249
250
catchint(int signal)251 void catchint(__attribute__((unused)) int signal)
252 {
253 __attribute__((unused)) int result = netkeyer(K_ABORT, "");
254 exit(EXIT_SUCCESS);
255 }
256
257
258
259
260
main(int argc,char ** argv)261 int main(int argc, char **argv)
262 {
263 if (netkeyer_init() == -1) {
264 exit(EXIT_FAILURE);
265 }
266
267 /* tests start here, no error handling */
268 int result;
269 if (argc > 1) {
270 result = netkeyer(K_DEVICE, argv[1]);
271 printf("opening port %s\n", argv[1]);
272 }
273
274 printf("first message at initial speed\n");
275 result = netkeyer(K_MESSAGE, "paris");
276 sleep(3);
277
278 printf("speed 40\n");
279 result = netkeyer(K_SPEED, "40");
280 result = netkeyer(K_MESSAGE, "paris");
281 sleep(2);
282
283 printf("tone 1000, speed 40\n");
284 result = netkeyer(K_TONE, "1000");
285 result = netkeyer(K_SPEED, "40");
286 result = netkeyer(K_MESSAGE, "paris");
287 sleep(2);
288
289 printf("tone 800, weight +20\n");
290 result = netkeyer(K_TONE, "800");
291 result = netkeyer(K_WEIGHT, "20");
292 result = netkeyer(K_MESSAGE, "paris");
293 sleep(2);
294
295 printf("weight -20\n");
296 result = netkeyer(K_WEIGHT, "-20");
297 result = netkeyer(K_MESSAGE, "paris");
298 sleep(2);
299
300 printf("weight 0\n");
301 result = netkeyer(K_WEIGHT, "0");
302 printf("speed increase / decrease\n");
303 result = netkeyer(K_MESSAGE, "p++++++++++aris----------");
304 sleep(2);
305
306 printf("half gap\n");
307 result = netkeyer(K_MESSAGE, "p~ari~s");
308 sleep(2);
309
310 printf("tune 3 seconds\n");
311 result = netkeyer(K_TUNE, "3");
312 sleep(4);
313
314 printf("test message abort\n");
315 result = netkeyer(K_MESSAGE, "paris paris");
316 sleep(1);
317 result = netkeyer(K_ABORT, "");
318 sleep(1);
319
320 printf("switch to soundcard\n");
321 result = netkeyer(K_SDEVICE, "s");
322 result = netkeyer(K_MESSAGE, "paris");
323 sleep(2);
324
325 printf("volume 30\n");
326 result = netkeyer(K_VOLUME, "30");
327 result = netkeyer(K_MESSAGE, "paris");
328 sleep(2);
329
330 printf("prosigns: SK BK SN AS AR\n");
331 result = netkeyer(K_MESSAGE, "< > ! & *");
332 sleep(4);
333
334 printf("set volume back to 70\n");
335 result = netkeyer(K_VOLUME, "70");
336 result = netkeyer(K_MESSAGE, "paris");
337 sleep(2);
338
339 printf("back to console\n");
340 result = netkeyer(K_SDEVICE, "c");
341 result = netkeyer(K_MESSAGE, "paris");
342 sleep(2);
343
344 printf("message with PTT on\n");
345 result = netkeyer(K_PTT, "1");
346 result = netkeyer(K_MESSAGE, "paris");
347 sleep(2);
348 result = netkeyer(K_PTT, "0");
349
350 printf("same with different TOD\n");
351 result = netkeyer(K_TOD, "20");
352 result = netkeyer(K_PTT, "1");
353 result = netkeyer(K_MESSAGE, "paris");
354 sleep(2);
355 result = netkeyer(K_PTT, "0");
356 result = netkeyer(K_TOD, "0");
357
358 /* almost done, reset keyer */
359 printf("almost done, reset\n");
360 result = netkeyer(K_RESET, "");
361
362
363 printf("test message abort with SIGALRM\n");
364 signal(SIGALRM, catchint);
365 result = netkeyer(K_MESSAGE, "paris paris");
366 alarm(2);
367 while (1) {}
368
369 printf("done");
370
371 /* end tests */
372 if (netkeyer_close() == -1) {
373 exit(EXIT_FAILURE);
374 } else {
375 exit(EXIT_SUCCESS);
376 }
377 }
378