]> git.itanic.dy.fi Git - maemo-mapper/blob - src/aprs_kiss.c
Added basic APRS support - Can be disabled by removing definition of INCLUDE_APRS
[maemo-mapper] / src / aprs_kiss.c
1 /*
2  * 
3  * This file is part of Maemo Mapper.
4  *
5  * Maemo Mapper is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Maemo Mapper is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Maemo Mapper.  If not, see <http://www.gnu.org/licenses/>.
17  * 
18  * 
19  * Parts of this code have been ported from Xastir by Rob Williams (10 Aug 2008):
20  * 
21  *  * XASTIR, Amateur Station Tracking and Information Reporting
22  * Copyright (C) 1999,2000  Frank Giannandrea
23  * Copyright (C) 2000-2007  The Xastir Group
24  * 
25  */
26
27
28 #ifdef HAVE_CONFIG_H
29 #    include "config.h"
30 #endif
31
32 #ifdef INCLUDE_APRS
33
34 #include "aprs_kiss.h"
35 #include "aprs.h"
36 #include "defines.h"
37 #include "data.h"
38 #include <sys/types.h>
39 #include <sys/ioctl.h>
40
41 #include <pthread.h>
42
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <assert.h>
47 #include <ctype.h>
48 #include <sys/stat.h>
49 #include <sys/file.h>
50 #include <unistd.h>
51 #include <dirent.h>
52 #include <signal.h>
53 #include <termios.h>
54 #include <pwd.h>
55 #include <termios.h>
56 #include <setjmp.h>
57 #include <sys/socket.h>
58 #include <fcntl.h>
59
60 #include <netinet/in.h>     // Moved ahead of inet.h as reports of some *BSD's not
61                             // including this as they should.
62
63
64 #define _GNU_SOURCE
65
66 #include <errno.h>
67 #include <unistd.h>
68 #include <fcntl.h>
69 #include <string.h>
70 #include <signal.h>
71 #include <sys/types.h>
72 #include <sys/stat.h>
73 #include <sys/wait.h>
74 #include <sys/time.h>
75 #include <time.h>
76
77 #define DBUS_API_SUBJECT_TO_CHANGE
78 #include <dbus/dbus-glib.h>
79
80
81 #define DISABLE_SETUID_PRIVILEGE do { \
82 seteuid(getuid()); \
83 setegid(getgid()); \
84 } while(0)
85 #define ENABLE_SETUID_PRIVILEGE do { \
86 seteuid(euid); \
87 setegid(egid); \
88 } while(0)
89
90
91
92
93 #define MAX_INPUT_QUEUE 1000
94 gint decode_ax25_line(gchar *line, TAprsPort port);
95
96 typedef struct
97 {
98     pthread_mutex_t lock;
99     pthread_t threadID;
100 } xastir_mutex;
101
102 xastir_mutex connect_lock;              // Protects port_data[].thread_status and port_data[].connect_status
103
104 // Read/write pointers for the circular input queue
105 /*
106 static int incoming_read_ptr = 0;
107 static int incoming_write_ptr = 0;
108 static int queue_depth = 0;
109 static int push_count = 0;
110 static int pop_count = 0;
111 */
112 uid_t euid;
113 gid_t egid;
114
115
116
117 iface port_data;     // shared port data
118
119
120 //WE7U2
121 // We feed a raw 7-byte string into this routine.  It decodes the
122 // callsign-SSID and tells us whether there are more callsigns after
123 // this.  If the "asterisk" input parameter is nonzero it'll add an
124 // asterisk to the callsign if it has been digipeated.  This
125 // function is called by the decode_ax25_header() function.
126 //
127 // Inputs:  string          Raw input string
128 //          asterisk        1 = add "digipeated" asterisk
129 //
130 // Outputs: callsign        Processed string
131 //          returned int    1=more callsigns follow, 0=end of address field
132 //
133 gint decode_ax25_address(gchar *string, gchar *callsign, gint asterisk) {
134     gint i,j;
135     gchar ssid;
136     gchar t;
137     gint more = 0;
138     gint digipeated = 0;
139
140     // Shift each of the six callsign characters right one bit to
141     // convert to ASCII.  We also get rid of the extra spaces here.
142     j = 0;
143     for (i = 0; i < 6; i++) {
144         t = ((unsigned char)string[i] >> 1) & 0x7f;
145         if (t != ' ') {
146             callsign[j++] = t;
147         }
148     }
149
150     // Snag out the SSID byte to play with.  We need more than just
151     // the 4 SSID bits out of it.
152     ssid = (unsigned char)string[6];
153
154     // Check the digipeat bit
155     if ( (ssid & 0x80) && asterisk)
156         digipeated++;   // Has been digipeated
157
158     // Check whether it is the end of the address field
159     if ( !(ssid & 0x01) )
160         more++; // More callsigns to come after this one
161
162     // Snag the four SSID bits
163     ssid = (ssid >> 1) & 0x0f;
164
165     // Construct the SSID number and add it to the end of the
166     // callsign if non-zero.  If it's zero we don't add it.
167     if (ssid) {
168         callsign[j++] = '-';
169         if (ssid > 9) {
170             callsign[j++] = '1';
171         }
172         ssid = ssid % 10;
173         callsign[j++] = '0' + ssid;
174     }
175
176     // Add an asterisk if the packet has been digipeated through
177     // this callsign
178     if (digipeated)
179         callsign[j++] = '*';
180
181     // Terminate the string
182     callsign[j] = '\0';
183
184     return(more);
185 }
186
187
188 // Function which receives raw AX.25 packets from a KISS interface and
189 // converts them to a printable TAPR-2 (more or less) style string.
190 // We receive the packet with a KISS Frame End character at the
191 // beginning and a "\0" character at the end.  We can end up with
192 // multiple asterisks, one for each callsign that the packet was
193 // digipeated through.  A few other TNC's put out this same sort of
194 // format.
195 //
196 // Note about KISS & CRC's:  The TNC checks the CRC.  If bad, it
197 // drops the packet.  If good, it sends it to the computer WITHOUT
198 // the CRC bytes.  There's no way at the computer end to check
199 // whether the packet was corrupted over the serial channel between
200 // the TNC and the computer.  Upon sending a KISS packet to the TNC,
201 // the TNC itself adds the CRC bytes back on before sending it over
202 // the air.  In Xastir we can just assume that we're getting
203 // error-free packets from the TNC, ignoring possible corruption
204 // over the serial line.
205 //
206 // Some versions of KISS can encode the radio channel (for
207 // multi-port TNC's) in the command byte.  How do we know we're
208 // running those versions of KISS though?  Here are the KISS
209 // variants that I've been able to discover to date:
210 //
211 // KISS               No CRC, one radio port
212 //
213 // SMACK              16-bit CRC, multiport TNC's
214 //
215 // KISS-CRC
216 //
217 // 6-PACK
218 //
219 // KISS Multi-drop (Kantronics) 8-bit XOR Checksum, multiport TNC's (AGWPE compatible)
220 // BPQKISS (Multi-drop)         8-bit XOR Checksum, multiport TNC's
221 // XKISS (Kantronics)           8-bit XOR Checksum, multiport TNC's
222 //
223 // JKISS              (AGWPE and BPQ32 compatible)
224 //
225 // MKISS              Linux driver which supports KISS/BPQ and
226 //                    hardware handshaking?  Also Paccomm command to
227 //                    immediately enter KISS mode.
228 //
229 // FlexKISS           -,
230 // FlexCRC            -|-- These are all the same!
231 // RMNC-KISS          -|
232 // CRC-RMNC           -'
233 //
234 //
235 // It appears that none of the above protocols implement any form of
236 // hardware flow control.
237 // 
238 // 
239 // Compare this function with interface.c:process_ax25_packet() to
240 // see if we're missing anything important.
241 //
242 //
243 // Inputs:  data_string         Raw string (must be MAX_LINE_SIZE or bigger)
244 //          length              Length of raw string (may get changed here)
245 //
246 // Outputs: int                 0 if it is a bad packet,
247 //                              1 if it is good
248 //          data_string         Processed string
249 //
250 gint decode_ax25_header(
251                 unsigned char *data_string, 
252                 gint *length) {
253     gchar temp[20];
254     gchar result[MAX_LINE_SIZE+100];
255     gchar dest[15];
256     gint i, ptr;
257     gchar callsign[15];
258     gchar more;
259     gchar num_digis = 0;
260
261
262     // Do we have a string at all?
263     if (data_string == NULL)
264         return(0);
265
266     // Drop the packet if it is too long.  Note that for KISS packets
267     // we can't use strlen() as there can be 0x00 bytes in the
268     // data itself.
269     if (*length > 1024) {
270         data_string[0] = '\0';
271         *length = 0;
272         return(0);
273     }
274
275     // Start with an empty string for the result
276     result[0] = '\0';
277
278     ptr = 0;
279
280     // Process the destination address
281     for (i = 0; i < 7; i++)
282         temp[i] = data_string[ptr++];
283     temp[7] = '\0';
284     more = decode_ax25_address(temp, callsign, 0); // No asterisk
285     snprintf(dest,sizeof(dest),"%s",callsign);
286
287     // Process the source address
288     for (i = 0; i < 7; i++)
289         temp[i] = data_string[ptr++];
290     temp[7] = '\0';
291     more = decode_ax25_address(temp, callsign, 0); // No asterisk
292
293     // Store the two callsigns we have into "result" in the correct
294     // order
295     snprintf(result,sizeof(result),"%s>%s",callsign,dest);
296
297     // Process the digipeater addresses (if any)
298     num_digis = 0;
299     while (more && num_digis < 8) {
300         for (i = 0; i < 7; i++)
301             temp[i] = data_string[ptr++];
302         temp[7] = '\0';
303
304         more = decode_ax25_address(temp, callsign, 1); // Add asterisk
305         strncat(result,
306             ",",
307             sizeof(result) - strlen(result));
308         
309         strncat(result,
310             callsign,
311             sizeof(result) - strlen(result));
312         num_digis++;
313     }
314
315     strncat(result,
316         ":",
317         sizeof(result) - strlen(result));
318
319
320     // Check the Control and PID bytes and toss packets that are
321     // AX.25 connect/disconnect or information packets.  We only
322     // want to process UI packets in Xastir.
323
324
325     // Control byte should be 0x03 (UI Frame).  Strip the poll-bit
326     // from the PID byte before doing the comparison.
327     if ( (data_string[ptr++] & (~0x10)) != 0x03) {
328         return(0);
329     }
330
331
332     // PID byte should be 0xf0 (normal AX.25 text)
333     if (data_string[ptr++] != 0xf0)
334         return(0);
335
336
337 // WE7U:  We get multiple concatenated KISS packets sometimes.  Look
338 // for that here and flag when it happens (so we know about it and
339 // can fix it someplace earlier in the process).  Correct the
340 // current packet so we don't get the extra garbage tacked onto the
341 // end.
342     for (i = ptr; i < *length; i++) {
343         if (data_string[i] == KISS_FEND) {
344             fprintf(stderr,"***Found concatenated KISS packets:***\n");
345             data_string[i] = '\0';    // Truncate the string
346             break;
347         }
348     }
349
350     // Add the Info field to the decoded header info
351     strncat(result,
352         (char *)(&data_string[ptr]),
353         sizeof(result) - strlen(result));
354
355     // Copy the result onto the top of the input data.  Note that
356     // the length can sometimes be longer than the input string, so
357     // we can't just use the "length" variable here or we'll
358     // truncate our string.  Make sure the data_string variable is
359     // MAX_LINE_SIZE or bigger.
360     //
361     snprintf((char *)data_string,
362         MAX_LINE_SIZE,
363         "%s",
364         result);
365
366     // Write out the new length
367     *length = strlen(result); 
368
369 //fprintf(stderr,"%s\n",data_string);
370
371     return(1);
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390 // Added by KB6MER for KAM XL(SERIAL_TNC_AUX_GPS) support
391 // buf is a null terminated string
392 // returns buf as a null terminated string after cleaning.
393 // Currently:
394 //    removes leading 'cmd:' prompts from TNC if needed
395 // Can be used to add any additional data cleaning functions desired.
396 // Currently only called for SERIAL_TNC_AUX_GPS, but could be added
397 // to other device routines to improve packet decode on other devices.
398 //
399 // Note that the length of "buf" can be up to MAX_DEVICE_BUFFER,
400 // which is currently set to 4096.
401 //
402 void tnc_data_clean(gchar *buf) {
403
404     while (!strncmp(buf,"cmd:",4)) {
405         int ii;
406
407         // We're _shortening_ the string here, so we don't need to
408         // know the length of the buffer unless it has no '\0'
409         // terminator to begin with!  In that one case we could run
410         // off the end of the string and get a segfault or cause
411         // other problems.
412         for (ii = 0; ; ii++) {
413             buf[ii] = buf[ii+4];
414             if (buf[ii] == '\0')
415                 break;
416         }
417     }
418 }
419
420
421
422 static gboolean aprs_parse_tty_packet(gchar *packet)
423 {
424     decode_ax25_line(packet, APRS_PORT_TTY);
425
426     g_free(packet);
427
428     return FALSE;
429 }
430
431
432 static gboolean kiss_parse_packet(unsigned char *data_string, gint data_length)
433 {
434         
435         
436         //fprintf(stderr, "Parse: %s\n", data_string);
437         
438         gint devicetype = port_data.device_type;
439         
440         
441         switch(devicetype)
442         {
443     case DEVICE_SERIAL_KISS_TNC:
444     case DEVICE_SERIAL_MKISS_TNC:
445             if ( !decode_ax25_header( data_string,
446                     &data_length ) ) {
447                 // Had a problem decoding it.  Drop
448                 // it on the floor.
449                 break;
450             }
451             else {
452                 // Good decode.  Drop through to the
453                 // next block to log and decode the
454                 // packet.
455             }
456         
457         case DEVICE_SERIAL_TNC:
458             tnc_data_clean((char *)data_string);
459
460         case DEVICE_AX25_TNC:   
461
462
463
464                 
465 //fprintf(stderr, "Decoded kiss: %s\n", data_string);
466       g_idle_add((GSourceFunc)aprs_parse_tty_packet, data_string);
467 //              decode_ax25_line(data_string, "T", 0);
468                 break;
469                 
470         default:
471                 break;
472         }
473
474     
475     
476         return FALSE; 
477 }
478
479 // Add one record to the circular queue.  Returns 1 if queue is
480 // full, 0 if successful.
481 //
482 /*
483 int push_incoming_data(unsigned char *data_string, int length) {
484         
485     int next_write_ptr = (incoming_write_ptr + 1) % MAX_INPUT_QUEUE;
486
487     // Check whether queue is full
488     if (incoming_read_ptr == next_write_ptr) {
489         // Yep, it's full!
490         return(1);
491     }
492
493     // Advance the write pointer
494     incoming_write_ptr = next_write_ptr;
495
496     incoming_data_queue[incoming_write_ptr].length = length;
497
498 //    incoming_data_queue[incoming_write_ptr].port = port;
499
500     snprintf((char *)incoming_data_queue[incoming_write_ptr].data,
501         (length < MAX_LINE_SIZE) ? length : MAX_LINE_SIZE,
502         "%s",
503         data_string);
504
505     queue_depth++;
506     push_count++;
507
508     return(0);
509 }
510 */
511
512
513
514
515
516
517
518
519
520 //***********************************************************
521 // channel_data()
522 //
523 // Takes data read in from a port and adds it to the
524 // incoming_data_queue.  If queue is full, waits for queue to have
525 // space before continuing.
526 //
527 // port #                                                    
528 // string is the string of data
529 // length is the length of the string.  If 0 then use strlen()
530 // on the string itself to determine the length.
531 //
532 // Note that decode_ax25_header() and perhaps other routines may
533 // increase the length of the string while processing.  We need to
534 // send a COPY of our input string off to the decoding routines for
535 // this reason, and the size of the buffer must be MAX_LINE_SIZE
536 // for this reason also.
537 //***********************************************************
538 void channel_data(unsigned char *string, int length) {
539     int max;
540 //    struct timeval tmv;
541     // Some messiness necessary because we're using xastir_mutex's
542     // instead of pthread_mutex_t's.
543     int process_it = 0;
544
545
546     //fprintf(stderr,"channel_data: %x %d\n",string[0],length);
547
548     
549     max = 0;
550
551     if (string == NULL)
552     {
553         return;
554     }
555
556     if (string[0] == '\0')
557     {
558         return;
559     }
560
561     if (length == 0) {
562         // Compute length of string including terminator
563         length = strlen((const char *)string) + 1;
564     }
565
566     // Check for excessively long packets.  These might be TCP/IP
567     // packets or concatenated APRS packets.  In any case it's some
568     // kind of garbage that we don't want to try to parse.
569
570     // Note that for binary data (WX stations and KISS packets), the
571     // strlen() function may not work correctly.
572     if (length > MAX_LINE_SIZE) {   // Too long!
573 //      fprintf(stderr, "Too long");
574         string[0] = '\0';   // Truncate it to zero length
575         return;
576     }
577
578
579     // This protects channel_data from being run by more than one
580     // thread at the same time.
581
582     if (length > 0) {
583
584
585         // Install the cleanup routine for the case where this
586         // thread gets killed while the mutex is locked.  The
587         // cleanup routine initiates an unlock before the thread
588         // dies.  We must be in deferred cancellation mode for the
589         // thread to have this work properly.  We must first get the
590         // pthread_mutex_t address.
591
592
593
594         // If it's any of three types of GPS ports and is a GPRMC or
595         // GPGGA string, just stick it in one of two global
596         // variables for holding such strings.  UpdateTime() can
597         // come along and process/clear-out those strings at the
598         // gps_time interval.
599         //
600         process_it++;
601
602         // Remove the cleanup routine for the case where this thread
603         // gets killed while the mutex is locked.  The cleanup
604         // routine initiates an unlock before the thread dies.  We
605         // must be in deferred cancellation mode for the thread to
606         // have this work properly.
607   //      pthread_cleanup_pop(0);
608
609  
610 //fprintf(stderr,"Channel data on Port [%s]\n",(char *)string);
611
612         if (process_it) {
613
614             // Wait for empty space in queue
615 //fprintf(stderr,"\n== %s", string);
616                 
617                 
618 /*
619             while (push_incoming_data(string, length) && max < 5400) {
620                 sched_yield();  // Yield to other threads
621                 tmv.tv_sec = 0;
622                 tmv.tv_usec = 2;  // 2 usec
623                 (void)select(0,NULL,NULL,NULL,&tmv);
624                 max++;
625             }
626 */
627                 
628                 kiss_parse_packet(g_strdup(string), length);
629             //g_idle_add((GSourceFunc)kiss_parse_packet, g_strdup(string));
630
631             
632         }
633 //        else
634 //        {
635 //              fprintf(stderr,"Channel data on Port [%s]\n",(char *)string);
636 //        }
637     }
638
639 }
640
641
642
643
644 //****************************************************************
645 // get device name only (the portion at the end of the full path)
646 // device_name current full name of device
647 //****************************************************************
648
649 char *get_device_name_only(char *device_name) {
650     int i,len,done;
651
652     if (device_name == NULL)
653         return(NULL);
654
655     done = 0;
656     len = (int)strlen(device_name);
657     for(i = len; i > 0 && !done; i--){
658         if(device_name[i] == '/'){
659             device_name += (i+1);
660             done = 1;
661         }
662     }
663     return(device_name);
664 }
665
666
667 int filethere(char *fn) {
668     FILE *f;
669     int ret;
670
671     ret =0;
672     f=fopen(fn,"r");
673     if (f != NULL) {
674         ret=1;
675         (void)fclose(f);
676     }
677     return(ret);
678 }
679
680
681
682 /*
683  * Close the serial port
684  * */
685 gint serial_detach() {
686 //    char fn[600];
687     int ok;
688     ok = -1;
689
690     if (port_data.active == DEVICE_IN_USE && port_data.status == DEVICE_UP) 
691     {
692         // Close port first
693         (void)tcsetattr(port_data.channel, TCSANOW, &port_data.t_old);
694         if (close(port_data.channel) == 0) 
695         {
696             port_data.status = DEVICE_DOWN;
697             usleep(200);
698             port_data.active = DEVICE_NOT_IN_USE;
699             ok = 1;
700
701         }
702         else 
703         {
704             fprintf(stderr,"Could not close port %s\n",port_data.device_name);
705
706             port_data.status = DEVICE_DOWN;
707             usleep(200);
708             port_data.active = DEVICE_NOT_IN_USE;
709
710         }
711
712         //update_interface_list();
713   /*      
714         // Delete lockfile
715         snprintf(fn, sizeof(fn), "/var/lock/LCK..%s", get_device_name_only(port_data.device_name));
716
717         ENABLE_SETUID_PRIVILEGE;
718         (void)unlink(fn);
719         DISABLE_SETUID_PRIVILEGE;
720 */
721     }
722
723     return(ok);
724 }
725
726
727 typedef struct {
728   char *adapter;  /* do not free this, it is freed somewhere else */
729   char *bonding;  /* allocated from heap, you must free this */
730 } bonding_t;
731
732 gboolean open_bluetooth_tty_connection(gchar *bda, gchar **aprs_bt_port)
733 {
734         gint i, st, num_bondings = 0, num_rfcomms = 0, num_posdev = 0;
735         //gint j, k, num_classes = 0, bonding_cnt = 0,  
736         GError *error = NULL;
737         DBusGConnection *bus = NULL;
738         DBusGProxy *proxy = NULL;
739         //char **str_iter = NULL;
740         //char **tmp_bondings = 0, **tmp_classes = 0;
741         //char **adapters = 0;
742         gchar **rfcomms = 0;
743         bonding_t *bondings = 0; /* points to array of bonding_t */
744         bonding_t *posdev = 0; /* bondings with positioning bit on */
745         gchar *tmp;
746         //gchar *onoff;
747         const gchar const *spp="SPP";
748         //gint timeout;
749 //      gchar *gpsd_prog;
750 //      gchar *gpsd_ctrl_sock;
751   
752         /* Use the dbus interface to get the BT information */
753         
754
755 #if (__GNUC__ > 2) && ((__GNUC__ > 3) || (__GNUC_MINOR__ > 2))
756 #define ERRSTR(fmt, args...)                                     \
757   if (error_buf && error_buf_max_len>0) {                        \
758     set_error_msg(error_buf, error_buf_max_len, fmt, args);      \
759   } else {                                                       \
760     PDEBUG(fmt, args);                                           \
761   }
762 #else
763 #define ERRSTR(fmt, args...)                                     \
764   if (error_buf && error_buf_max_len>0) {                        \
765     set_error_msg(error_buf, error_buf_max_len, fmt, ##args);    \
766   } else {                                                       \
767     PDEBUG(fmt, ##args);                                         \
768   }
769 #endif  
770
771
772         error = NULL;
773         bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
774
775         if (error) 
776         {
777             st = -1;
778             errno = ECONNREFUSED; /* close enough :) */
779             //ERRSTR("%s", error->message);
780             //PDEBUG("Cannot get reply message [%s]\n", error->message);
781             goto OUT;
782     }
783
784         /* We need BT information only if the caller does not specify
785          * the BT address. If address is defined, it is assumed that
786          * it is already bonded and we just create RFCOMM connection
787          * to it.
788          */
789         if (!bda) 
790         {
791                 // May want to support auto detect for serial ports?
792         } else {  /* if (!bda) */
793             /* Caller supplied BT address so use it */
794             num_posdev = 1;
795             posdev = calloc(1, sizeof(bonding_t *));
796             if (!posdev) 
797             {
798               st = -1;
799               errno = ENOMEM;
800               goto OUT;
801             }
802             posdev[0].bonding = strdup(bda);
803
804             /* Adapter information is not needed */
805             posdev[0].adapter = "<not avail>";
806         }
807         
808         /* For each bondend BT GPS device, try to create rfcomm */
809         for (i=0; i<num_posdev; i++) 
810         {
811                 /* Note that bluez does not provide this interface (its defined but not
812              * yet implemented) so we use btcond for creating rfcomm device(s)
813              */
814
815             proxy = dbus_g_proxy_new_for_name(bus,
816                 BTCOND_DBUS, BTCOND_PATH, BTCOND_INTERFACE);
817
818             error = NULL;
819             tmp = NULL;
820             if(!dbus_g_proxy_call(proxy, BTCOND_CONNECT, &error,
821                   G_TYPE_STRING, posdev[i].bonding,
822                   G_TYPE_STRING, spp,
823               G_TYPE_BOOLEAN, TRUE,
824                   G_TYPE_INVALID,
825                   G_TYPE_STRING, &tmp,
826                   G_TYPE_INVALID)
827                 || error || !tmp || !*tmp) 
828             {
829                 /*PDEBUG("dbus_g_proxy_call returned an error: (error=(%d,%s), tmp=%s\n",
830                   error ? error->code : -1,
831                   error ? error->message : "<null>",
832                   tmp ? tmp : "<null>");
833 */
834                 /* No error if already connected */
835                 if (error && !strstr(error->message,
836                     "com.nokia.btcond.error.connected")) 
837                 {
838                         ERROR:
839                                 fprintf(stderr, "Cannot send msg (service=%s, object=%s, interface=%s, "
840                                                 "method=%s) [%s]\n",
841                                                 BTCOND_DBUS,
842                                                 BTCOND_PATH,
843                                                 BTCOND_INTERFACE,
844                                                 BTCOND_CONNECT,
845                                                 error->message ? error->message : "<no error msg>");
846 /*                              ERRSTR("Cannot send msg (service=%s, object=%s, interface=%s, "
847                                                 "method=%s) [%s]\n",
848                                                 BTCOND_DBUS,
849                                                 BTCOND_PATH,
850                                                 BTCOND_INTERFACE,
851                                                 BTCOND_CONNECT,
852                                                 error->message ? error->message : "<no error msg>");
853 */
854                                 continue;
855                 } 
856                 else if(!tmp || !*tmp) 
857                 {
858                         /* hack: rfcommX device name is at the end of error message */
859                         char *last_space = strstr(error->message, " rfcomm");
860                         if (!last_space) 
861                         {
862                                 goto ERROR;
863                         }
864
865                         g_free(tmp);
866                         tmp = g_strdup_printf("/dev/%s", last_space+1);
867                 }
868             }
869             g_object_unref(proxy);
870
871             if (tmp && tmp[0]) 
872             {
873                 rfcomms = (char **)realloc(rfcomms, (num_rfcomms+1)*sizeof(char *));
874                 if (!rfcomms) 
875                 {
876                         st = -1;
877                         errno = ENOMEM;
878                         goto OUT;
879                 }
880
881                 rfcomms[num_rfcomms] = tmp;
882                 num_rfcomms++;
883
884                 fprintf(stderr, "BT addr=%s, RFCOMM %s now exists (adapter=%s)\n",
885                       posdev[i].bonding, tmp, posdev[i].adapter);
886
887                 tmp = NULL;
888             }
889             else 
890             {
891                 g_free(tmp);
892             }
893         }
894
895         if (num_rfcomms==0) 
896         {
897             /* serial device creation failed */
898             fprintf(stderr, "No rfcomm created\n");
899             st = -1;
900             errno = EINVAL;
901
902         } 
903         else 
904         {
905             /* Add null at the end */
906             rfcomms = (char **)realloc(rfcomms, (num_rfcomms+1)*sizeof(char *));
907             if (!rfcomms) 
908             {
909                 st = -1;
910                 errno = ENOMEM;
911
912             } 
913             else 
914             {
915                 rfcomms[num_rfcomms] = NULL;
916
917                 /* Just start the beast (to be done if everything is ok) */
918                 st = 0;
919                                 
920                 *aprs_bt_port = g_strdup_printf("%s",rfcomms[0]);
921
922             }
923         }
924
925 OUT:
926 /*      if (adapters) 
927         {
928             g_strfreev(adapters);
929         }
930 */
931         if (posdev) 
932         {
933             for (i=0; i<num_posdev; i++) 
934             {
935                 if (posdev[i].bonding) 
936                 {
937                         free(posdev[i].bonding);
938                         memset(&posdev[i], 0, sizeof(bonding_t)); /* just in case */
939                 }
940             }
941             free(posdev);
942             posdev = 0;
943         }
944
945         if (bondings) 
946         {
947             for (i=0; i<num_bondings; i++) 
948             {
949                 if (bondings[i].bonding) 
950                 {
951                         free(bondings[i].bonding);
952                         memset(&bondings[i], 0, sizeof(bonding_t)); /* just in case */
953                 }
954             }
955             free(bondings);
956             bondings = 0;
957         }
958
959         if (rfcomms) 
960         {
961                 for (i=0; i<num_rfcomms; i++) 
962                 {
963                         if (rfcomms[i]) 
964                         {
965                                 free(rfcomms[i]);
966                                 rfcomms[i]=0;
967                         }
968            }
969            free(rfcomms);
970            rfcomms = 0;
971         }
972
973         if (bus) 
974         {
975                 dbus_g_connection_unref(bus);
976         }
977
978         return st>-1;
979 }
980
981
982
983
984
985
986
987 //***********************************************************
988 // Serial port INIT
989 //***********************************************************
990 int serial_init () {
991 //    FILE *lock;
992     int speed;
993 //    pid_t mypid = 0;
994 //    int myintpid;
995 //    char fn[600];
996 //    uid_t user_id;
997 //    struct passwd *user_info;
998 //    char temp[100];
999 //    char temp1[100];
1000 //    pid_t status;
1001
1002 //    status = -9999;
1003
1004     
1005     euid = geteuid();
1006     egid = getegid();
1007
1008
1009     // clear port_channel
1010     port_data.channel = -1;
1011
1012     // clear port active
1013     port_data.active = DEVICE_NOT_IN_USE;
1014
1015     // clear port status
1016     port_data.status = DEVICE_DOWN;
1017
1018     // Show the latest status in the interface control dialog
1019 //    update_interface_list();
1020
1021     
1022     
1023     //gw-obex.h
1024     if(_aprs_tnc_method == TNC_CONNECTION_BT)
1025     {
1026         // Bluetooth connection
1027         gchar * aprs_bt_port = NULL;
1028         
1029         if(!open_bluetooth_tty_connection(_aprs_tnc_bt_mac, &aprs_bt_port))
1030         {
1031                 fprintf(stderr, "Failed to connect to BT device\n");
1032                 // Failed to connect
1033                 return -1;
1034         }
1035         
1036         
1037         snprintf(port_data.device_name, MAX_DEVICE_NAME, aprs_bt_port);
1038         g_free(aprs_bt_port);
1039         
1040         fprintf(stderr, "BT Port: %s\n", port_data.device_name);
1041     }
1042     else
1043     {
1044         snprintf(port_data.device_name, MAX_DEVICE_NAME, _aprs_tty_port);
1045     }
1046     
1047     
1048     port_data.device_type = DEVICE_SERIAL_KISS_TNC;
1049     port_data.sp = B9600; 
1050     
1051
1052     // check for lock file
1053     
1054     // Try to open the serial port now
1055     ENABLE_SETUID_PRIVILEGE;
1056     port_data.channel = open(port_data.device_name, O_RDWR|O_NOCTTY);
1057     DISABLE_SETUID_PRIVILEGE;
1058     if (port_data.channel == -1){
1059
1060         fprintf(stderr,"Could not open channel on port!\n");
1061
1062         return (-1);
1063     }
1064
1065     // Attempt to create the lock file
1066 /*    snprintf(fn, sizeof(fn), "/var/lock/LCK..%s", get_device_name_only(port_data.device_name));
1067
1068     ENABLE_SETUID_PRIVILEGE;
1069     lock = fopen(fn,"w");
1070     DISABLE_SETUID_PRIVILEGE;
1071     if (lock != NULL) {
1072         // get my process id for lock file
1073         mypid = getpid();
1074
1075         // get user info
1076         user_id = getuid();
1077         user_info = getpwuid(user_id);
1078         snprintf(temp,
1079             sizeof(temp),
1080             "%s",
1081             user_info->pw_name);
1082
1083         fprintf(lock,"%9d %s %s",(int)mypid,"xastir",temp);
1084         (void)fclose(lock);
1085         // We've successfully created our own lock file
1086     }
1087     else {
1088         // lock failed
1089         fprintf(stderr,"Warning:  Failed opening LCK file!  Continuing on...\n");
1090
1091     }
1092 */
1093     
1094     // get port attributes for new and old
1095     if (tcgetattr(port_data.channel, &port_data.t) != 0) {
1096         fprintf(stderr,"Could not get t port attributes for port!\n");
1097
1098         // Here we should close the port and remove the lock.
1099         serial_detach();
1100
1101         return (-1);
1102     }
1103
1104     if (tcgetattr(port_data.channel, &port_data.t_old) != 0) {
1105
1106         fprintf(stderr,"Could not get t_old port attributes for port!\n");
1107
1108         // Here we should close the port and remove the lock.
1109         serial_detach();
1110
1111         return (-1);
1112     }
1113
1114     // set time outs
1115     port_data.t.c_cc[VMIN] = (cc_t)1;
1116     port_data.t.c_cc[VTIME] = (cc_t)2;
1117
1118     // set port flags
1119     port_data.t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
1120     port_data.t.c_iflag = (tcflag_t)(IGNBRK | IGNPAR);
1121
1122     port_data.t.c_oflag = (0);
1123     port_data.t.c_lflag = (0);
1124
1125 #ifdef    CBAUD
1126     speed = (int)(port_data.t.c_cflag & CBAUD);
1127 #else   // CBAUD
1128     speed = 0;
1129 #endif  // CBAUD
1130     
1131     port_data.t.c_cflag = (tcflag_t)(HUPCL|CLOCAL|CREAD);
1132     port_data.t.c_cflag &= ~PARENB;
1133     switch (port_data.style){
1134         case(0):
1135             // No parity (8N1)
1136             port_data.t.c_cflag &= ~CSTOPB;
1137             port_data.t.c_cflag &= ~CSIZE;
1138             port_data.t.c_cflag |= CS8;
1139             break;
1140
1141         case(1):
1142             // Even parity (7E1)
1143             port_data.t.c_cflag &= ~PARODD;
1144             port_data.t.c_cflag &= ~CSTOPB;
1145             port_data.t.c_cflag &= ~CSIZE;
1146             port_data.t.c_cflag |= CS7;
1147             break;
1148
1149         case(2):
1150             // Odd parity (7O1):
1151             port_data.t.c_cflag |= PARODD;
1152             port_data.t.c_cflag &= ~CSTOPB;
1153             port_data.t.c_cflag &= ~CSIZE;
1154             port_data.t.c_cflag |= CS7;
1155             break;
1156
1157         default:
1158             break;
1159     }
1160
1161     port_data.t.c_cflag |= speed;
1162     // set input and out put speed
1163     if (cfsetispeed(&port_data.t, port_data.sp) == -1) 
1164     {
1165         fprintf(stderr,"Could not set port input speed for port!\n");
1166
1167         // Here we should close the port and remove the lock.
1168         serial_detach();
1169
1170         return (-1);
1171     }
1172
1173     if (cfsetospeed(&port_data.t, port_data.sp) == -1) {
1174
1175         fprintf(stderr,"Could not set port output speed for port!\n");
1176
1177         // Here we should close the port and remove the lock.
1178         serial_detach();
1179
1180         return (-1);
1181     }
1182
1183     if (tcflush(port_data.channel, TCIFLUSH) == -1) {
1184
1185         fprintf(stderr,"Could not flush data for port!\n");
1186
1187         // Here we should close the port and remove the lock.
1188         serial_detach();
1189
1190         return (-1);
1191     }
1192
1193     if (tcsetattr(port_data.channel,TCSANOW, &port_data.t) == -1) 
1194     {
1195         fprintf(stderr,"Could not set port attributes for port!\n");
1196
1197         // Here we should close the port and remove the lock.
1198         serial_detach();
1199
1200         return (-1);
1201     }
1202
1203     // clear port active
1204     port_data.active = DEVICE_IN_USE;
1205
1206     // clear port status
1207     port_data.status = DEVICE_UP;
1208
1209     // Show the latest status in the interface control dialog
1210 //    update_interface_list();
1211
1212     // Ensure we are in KISS mode
1213     if(port_data.device_type == DEVICE_SERIAL_KISS_TNC)
1214     {
1215         // Send KISS init string
1216         gchar * cmd = g_strdup("\nINT KISS\nRESTART\n");
1217         port_write_string(cmd, strlen(cmd), APRS_PORT_TTY);
1218     }
1219     
1220     // return good condition
1221     return (1);
1222 }
1223
1224
1225 //***********************************************************
1226 // port_read()
1227 //
1228 //
1229 // This function becomes the long-running thread that snags
1230 // characters from an interface and passes them off to the
1231 // decoding routines.  One copy of this is run for each read
1232 // thread for each interface.
1233 //***********************************************************
1234
1235 void port_read() {
1236     unsigned char cin, last;
1237 //    unsigned char buffer[MAX_DEVICE_BUFFER];    // Only used for AX.25 packets
1238     gint i;
1239     struct timeval tmv;
1240     fd_set rd;
1241 //    gint group;
1242 //    gint max;
1243     /*
1244     * Some local variables used for checking AX.25 data - PE1DNN
1245     *
1246     * "from"     is used to look up where the data comes from
1247     * "from_len" is used to keep the size of sockaddr structure
1248     * "dev"      is used to keep the name of the interface that
1249     *            belongs to our port/device_name
1250     */
1251 //    struct sockaddr from;
1252 //    socklen_t from_len;
1253
1254  //   group = 0;
1255 //    max = MAX_DEVICE_BUFFER - 1;
1256     cin = (unsigned char)0;
1257     last = (unsigned char)0;
1258     
1259     
1260
1261     // We stay in this read loop until the port is shut down
1262     while(port_data.active == DEVICE_IN_USE){
1263
1264         if (port_data.status == DEVICE_UP){
1265
1266             port_data.read_in_pos = 0;
1267             port_data.scan = 1;
1268
1269             while (port_data.scan
1270                     && (port_data.read_in_pos < (MAX_DEVICE_BUFFER - 1) )
1271                     && (port_data.status == DEVICE_UP) ) {
1272
1273                 int skip = 0;
1274
1275 //                pthread_testcancel();   // Check for thread termination request
1276  
1277                 // Handle all EXCEPT AX25_TNC interfaces here
1278                 // Get one character
1279                 port_data.scan = (int)read(port_data.channel,&cin,1);
1280 //fprintf(stderr,"tty in:%02x ",cin);
1281
1282
1283                 // Below is code for ALL types of interfaces
1284                 if (port_data.scan > 0 && port_data.status == DEVICE_UP ) {
1285
1286                     if (port_data.device_type != DEVICE_AX25_TNC)
1287                         port_data.bytes_input += port_data.scan;      // Add character to read buffer
1288
1289
1290
1291                     // Handle all EXCEPT AX25_TNC interfaces here
1292                     if (port_data.device_type != DEVICE_AX25_TNC){
1293
1294
1295                         // Do special KISS packet processing here.
1296                         // We save the last character in
1297                         // port_data.channel2, as it is
1298                         // otherwise only used for AX.25 ports.
1299
1300                         if ( (port_data.device_type == DEVICE_SERIAL_KISS_TNC)
1301                                 || (port_data.device_type == DEVICE_SERIAL_MKISS_TNC) ) {
1302
1303
1304                             if (port_data.channel2 == KISS_FESC) { // Frame Escape char
1305                                 if (cin == KISS_TFEND) { // Transposed Frame End char
1306
1307                                     // Save this char for next time
1308                                     // around
1309                                         port_data.channel2 = cin;
1310
1311                                     cin = KISS_FEND;
1312                                 }
1313                                 else if (cin == KISS_TFESC) { // Transposed Frame Escape char
1314
1315                                     // Save this char for next time
1316                                     // around
1317                                         port_data.channel2 = cin;
1318
1319                                     cin = KISS_FESC;
1320                                 }
1321                                 else {
1322                                         port_data.channel2 = cin;
1323                                 }
1324                             }
1325                             else if (port_data.channel2 == KISS_FEND) { // Frame End char
1326                                 // Frame start or frame end.  Drop
1327                                 // the next character which should
1328                                 // either be another frame end or a
1329                                 // type byte.
1330
1331 // Note this "type" byte is where it specifies which KISS interface
1332 // the packet came from.  We may want to use this later for
1333 // multi-drop KISS or other types of KISS protocols.
1334
1335                                 // Save this char for next time
1336                                 // around
1337                                 port_data.channel2 = cin;
1338
1339                                 skip++;
1340                             }
1341                             else if (cin == KISS_FESC) { // Frame Escape char
1342                                 port_data.channel2 = cin;
1343                                 skip++;
1344                             }
1345                             else {
1346                                 port_data.channel2 = cin;
1347                             }
1348                         }   // End of first special KISS processing
1349
1350
1351                         // We shouldn't see any AX.25 flag
1352                         // characters on a KISS interface because
1353                         // they are stripped out by the KISS code.
1354                         // What we should see though are KISS_FEND
1355                         // characters at the beginning of each
1356                         // packet.  These characters are where we
1357                         // should break the data apart in order to
1358                         // send strings to the decode routines.  It
1359                         // may be just fine to still break it on \r
1360                         // or \n chars, as the KISS_FEND should
1361                         // appear immediately afterwards in
1362                         // properly formed packets.
1363
1364
1365                         if ( (!skip)
1366                                 && (cin == (unsigned char)'\r'
1367                                     || cin == (unsigned char)'\n'
1368                                     || port_data.read_in_pos >= (MAX_DEVICE_BUFFER - 1)
1369                                     || ( (cin == KISS_FEND) && (port_data.device_type == DEVICE_SERIAL_KISS_TNC) )
1370                                     || ( (cin == KISS_FEND) && (port_data.device_type == DEVICE_SERIAL_MKISS_TNC) ) )
1371                                && port_data.data_type == 0) {     // If end-of-line
1372
1373 // End serial/net type data send it to the decoder Put a terminating
1374 // zero at the end of the read-in data
1375
1376                                 port_data.device_read_buffer[port_data.read_in_pos] = (char)0;
1377
1378                             if (port_data.status == DEVICE_UP && port_data.read_in_pos > 0) {
1379                                 int length;
1380
1381                                 // Compute length of string in
1382                                 // circular queue
1383
1384                                 //fprintf(stderr,"%d\t%d\n",port_data.read_in_pos,port_data.read_out_pos);
1385
1386                                 // KISS TNC sends binary data
1387                                 if ( (port_data.device_type == DEVICE_SERIAL_KISS_TNC)
1388                                         || (port_data.device_type == DEVICE_SERIAL_MKISS_TNC) ) {
1389  
1390                                     length = port_data.read_in_pos - port_data.read_out_pos;
1391                                     if (length < 0)
1392                                         length = (length + MAX_DEVICE_BUFFER) % MAX_DEVICE_BUFFER;
1393
1394                                     length++;
1395                                 }
1396                                 else {  // ASCII data
1397                                     length = 0;
1398                                 }
1399
1400                                 channel_data(
1401                                     (unsigned char *)port_data.device_read_buffer,
1402                                     length);   // Length of string
1403                             }
1404
1405                             for (i = 0; i <= port_data.read_in_pos; i++)
1406                                 port_data.device_read_buffer[i] = (char)0;
1407
1408                             port_data.read_in_pos = 0;
1409                         }
1410                         else if (!skip) {
1411
1412                             // Check for binary WX station data
1413                             if (cin == '\0')    // OWW WX daemon sends 0x00's!
1414                                 cin = '\n';
1415
1416                             if (port_data.read_in_pos < (MAX_DEVICE_BUFFER - 1) ) {
1417                                 port_data.device_read_buffer[port_data.read_in_pos] = (char)cin;
1418                                 port_data.read_in_pos++;
1419                                 port_data.device_read_buffer[port_data.read_in_pos] = (char)0;
1420                             }
1421                             else {
1422                                 port_data.read_in_pos = 0;
1423                             }
1424                         }
1425
1426                     }   // End of non-AX.25 interface code block
1427
1428
1429                 }
1430                 else if (port_data.status == DEVICE_UP) {    /* error or close on read */
1431                     port_data.errors++;
1432                     if (port_data.scan == 0) {
1433                         // Should not get this unless the device is down.  NOT TRUE!
1434                         // We seem to also be able to get here if we're closing/restarting
1435                         // another interface.  For that reason I commented out the below
1436                         // statement so that this interface won't go down.  The inactivity
1437                         // timer solves that issue now anyway.  --we7u.
1438                         port_data.status = DEVICE_ERROR;
1439
1440                         // If the below statement is enabled, it causes an immediate reconnect
1441                         // after one time-period of inactivity, currently 7.5 minutes, as set in
1442                         // main.c:UpdateTime().  This means the symbol will never change from green
1443                         // to red on the status bar, so the operator might not know about a
1444                         // connection that is being constantly reconnected.  By leaving it commented
1445                         // out we get one time period of red, and then it will reconnect at the 2nd
1446                         // time period.  This means we can reconnect within 15 minutes if a line
1447                         // goes dead.
1448                         //
1449                         port_data.reconnects = -1;     // Causes an immediate reconnect
1450  
1451                         // Show the latest status in the interface control dialog
1452 //                        update_interface_list();
1453
1454                     } else {
1455                         if (port_data.scan == -1) {
1456                             /* Should only get this if an real error occurs */
1457                             port_data.status = DEVICE_ERROR;
1458
1459                             // If the below statement is enabled, it causes an immediate reconnect
1460                             // after one time-period of inactivity, currently 7.5 minutes, as set in
1461                             // main.c:UpdateTime().  This means the symbol will never change from green
1462                             // to red on the status bar, so the operator might not know about a
1463                             // connection that is being constantly reconnected.  By leaving it commented
1464                             // out we get one time period of red, and then it will reconnect at the 2nd
1465                             // time period.  This means we can reconnect within 15 minutes if a line
1466                             // goes dead.
1467                             //
1468                             port_data.reconnects = -1;     // Causes an immediate reconnect
1469  
1470                             // Show the latest status in the
1471                             // interface control dialog
1472 //                            update_interface_list();
1473
1474                         }
1475                     }
1476                 }
1477                 
1478                 
1479                 /*
1480                 
1481                 // Send any packets queued
1482                         // try to get lock, otherwise try next time
1483                         if(g_mutex_trylock (_write_buffer[APRS_PORT_TTY].write_lock))
1484                         {
1485                         // Store the current end pointer as it may change
1486                                 
1487                     while (_write_buffer[APRS_PORT_TTY].write_in_pos != _write_buffer[APRS_PORT_TTY].write_out_pos) {
1488
1489                         port_write_string(
1490                                 _write_buffer[APRS_PORT_TTY].device_write_buffer[_write_buffer[APRS_PORT_TTY].write_out_pos],
1491                                 APRS_PORT_TTY);
1492
1493                         _write_buffer[APRS_PORT_TTY].write_out_pos++;
1494                         if (_write_buffer[APRS_PORT_TTY].write_out_pos >= MAX_DEVICE_BUFFER)
1495                                 _write_buffer[APRS_PORT_TTY].write_out_pos = 0;
1496
1497                     }
1498
1499                                         
1500                     g_mutex_unlock(_write_buffer[APRS_PORT_TTY].write_lock);
1501                         }            
1502 */
1503             }
1504         }
1505         if (port_data.active == DEVICE_IN_USE)  {
1506
1507             // We need to delay here so that the thread doesn't use
1508             // high amounts of CPU doing nothing.
1509
1510 // This select that waits on data and a timeout, so that if data
1511 // doesn't come in within a certain period of time, we wake up to
1512 // check whether the socket has gone down.  Else, we go back into
1513 // the select to wait for more data or a timeout.  FreeBSD has a
1514 // problem if this is less than 1ms.  Linux works ok down to 100us.
1515 // We don't need it anywhere near that short though.  We just need
1516 // to check whether the main thread has requested the interface be
1517 // closed, and so need to have this short enough to have reasonable
1518 // response time to the user.
1519
1520 //sched_yield();  // Yield to other threads
1521
1522             // Set up the select to block until data ready or 100ms
1523             // timeout, whichever occurs first.
1524             FD_ZERO(&rd);
1525             FD_SET(port_data.channel, &rd);
1526             tmv.tv_sec = 0;
1527             tmv.tv_usec = 100000;    // 100 ms
1528             (void)select(0,&rd,NULL,NULL,&tmv);
1529         }
1530     }
1531
1532 }
1533
1534 #endif //INCLUDE_APRS