apps/garminusb2nmea-0.12a/garminusb2exif.c

Go to the documentation of this file.
00001 /*
00002  Garmin USB data source for Elphel Model 353 camera.
00003  Modified from
00004         Garmin USB NMEA converter
00005         Copyright (C) 2004 Manuel Kasper <mk@neon1.net>.
00006         All rights reserved.
00007                 
00008         Redistribution and use in source and binary forms, with or without
00009         modification, are permitted provided that the following conditions are met:
00010         
00011         1. Redistributions of source code must retain the above copyright notice,
00012            this list of conditions and the following disclaimer.
00013         
00014         2. Redistributions in binary form must reproduce the above copyright
00015            notice, this list of conditions and the following disclaimer in the
00016            documentation and/or other materials provided with the distribution.
00017         
00018         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
00019         INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00020         AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00021         AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
00022         OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023         SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024         INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025         CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026         ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027         POSSIBILITY OF SUCH DAMAGE.
00028 */
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <fcntl.h>
00032 #include <stdio.h>
00033 #include <unistd.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <termios.h>
00037 #include "garmin.h"
00038 #include "nmeagen.h"
00039 #include "exifgen.h"
00040 //#include <asm/elphel/exifa.h>
00041 
00042 #define GARMIN_HEADER_SIZE      12
00043 #define GARMIN_MAX_PKTSIZE      512
00044 #define PKTBUF_SIZE                     4097
00045 //#define D(x)
00046 #define D(x) x
00047 #pragma pack(push, 1)
00048 typedef struct {
00049         u_int8_t        mPacketType;
00050         u_int8_t        mReserved1;
00051         u_int16_t       mReserved2;
00052         u_int16_t       mPacketId;
00053         u_int16_t       mReserved3;
00054         u_int32_t       mDataSize;
00055         u_int8_t        mData[1];
00056 } Packet_t;
00057 #pragma pack(pop)
00058 
00059 int gps_fd;
00060 char pktbuf[PKTBUF_SIZE];
00061 int     pktbuf_head = 0, pktbuf_tail = 0;
00062 
00063 D800_Pvt_Data_Type      lastpvt;
00064 cpo_sat_data            lastsatdata[12];
00065 int     satdata_valid = 0;
00066 
00067 int pktbuf_size() {
00068         return (PKTBUF_SIZE - pktbuf_head + pktbuf_tail) % PKTBUF_SIZE;
00069 }
00070 
00071 int pktbuf_peek(char *buf, int n) {
00072         int i;
00073         int mypktbuf_head = pktbuf_head;
00074         for (i = 0; (i < n) && (mypktbuf_head != pktbuf_tail); i++) {
00075                 buf[i] = pktbuf[mypktbuf_head];
00076                 mypktbuf_head++;
00077                 if (mypktbuf_head == PKTBUF_SIZE)
00078                         mypktbuf_head = 0;
00079         }
00080         return i;
00081 }
00082 
00083 int pktbuf_deq(char *buf, int n) {
00084         int i;
00085 //   fprintf(stderr, "pktbuf_deq:pktbuf_size()=%d\n",pktbuf_size());
00086         for (i = 0; (i < n) && (pktbuf_head != pktbuf_tail); i++) {
00087                 buf[i] = pktbuf[pktbuf_head];
00088                 pktbuf_head++;
00089                 if (pktbuf_head == PKTBUF_SIZE)
00090                         pktbuf_head = 0;
00091         }
00092         return i;
00093 }
00094 
00095 int pktbuf_enq(char *buf, int n) {
00096         
00097         int i;
00098 //   fprintf(stderr, "pktbuf_enq:pktbuf_size()=%d\n",pktbuf_size());
00099         if (pktbuf_size() + n >= PKTBUF_SIZE)
00100                 return 0;
00101         
00102         for (i = 0; i < n; i++) {
00103                 pktbuf[pktbuf_tail] = buf[i];
00104                 pktbuf_tail++;
00105                 if (pktbuf_tail == PKTBUF_SIZE)
00106                         pktbuf_tail = 0;
00107         }
00108         
00109         return i;
00110 }
00111 
00112 int sendpacket(Packet_t *pack) {
00113         int nwr;
00114         nwr = write(gps_fd, pack, GARMIN_HEADER_SIZE + pack->mDataSize);
00115         if (nwr == -1) {
00116                 perror("GPS write error");
00117                 return 1;
00118         }
00119         return 0;
00120 }
00121 
00122 Packet_t* recvpacket(void) {
00123         Packet_t *pkt;
00124         char tmp[64];
00125         int nr;
00126         
00127         pkt = (Packet_t*)malloc(GARMIN_MAX_PKTSIZE);
00128         if (pkt == NULL) {
00129                 perror("malloc failed");
00130                 return NULL;
00131         }
00132 
00133 chkbuf: 
00134         /* complete packet in buffer? */
00135         if (pktbuf_size() >= GARMIN_HEADER_SIZE) {
00136                 Packet_t bufpkt;
00137                 pktbuf_peek((char*)&bufpkt, GARMIN_HEADER_SIZE);
00138                 int pktlen = GARMIN_HEADER_SIZE + bufpkt.mDataSize;
00139                 if (pktbuf_size() >= pktlen) {
00140                         pktbuf_deq((char*)pkt, pktlen);
00141                         return pkt;
00142                 }
00143         }
00144         
00145         /* not enough data - read some */
00146         nr = read(gps_fd, tmp, 64);
00147         if (nr == -1) {
00148                 perror("GPS read error");
00149                 free(pkt);
00150                 return NULL;
00151         }
00152         if (pktbuf_enq(tmp, nr) == 0) {
00153                 fprintf(stderr, "Input buffer full!\n");
00154 //got here during overnight run - gets stuck in the loop
00155 // probably - lost sync, need restart
00156       free(pkt);
00157       return NULL;
00158    }    
00159         goto chkbuf;
00160 }
00161 
00162 /*
00163         garmin_pvton()
00164         turn on position records
00165   
00166         receiver measurement records could also be enabled with 
00167         command 110 (instead of 49), but we don't need them at present
00168 */
00169 
00170 void garmin_pvton(void) {
00171         Packet_t *pvtpack = (Packet_t*)malloc(14);
00172 
00173         pvtpack->mPacketType = 20;
00174         pvtpack->mReserved1 = 0;
00175         pvtpack->mReserved2 = 0;
00176         pvtpack->mPacketId = 10;
00177         pvtpack->mReserved3 = 0;
00178         pvtpack->mDataSize = 2;
00179         pvtpack->mData[0] = 49;
00180         pvtpack->mData[1] = 0;
00181         
00182         sendpacket(pvtpack);
00183 }
00184 void garmin_privcmd(int fd) {
00185    u_int32_t privcmd[4];
00186    privcmd[0] = 0x01106E4B;
00187    privcmd[1] = 2;
00188    privcmd[2] = 4;
00189    privcmd[3] = 0;
00190    write(fd, privcmd, 16);
00191 }
00192 
00193 #define EXIF_DEV "/dev/exif_meta"
00194 
00195 int main(int argc, char *argv[]) {
00196 
00197    int fd_exif;
00198    struct meta_GPSInfo_t meta;  
00199 //      char nmeabuf[256];
00200 //      u_int32_t privcmd[4];
00201 //      FILE *nmeaout;
00202         struct termios termio;
00203 
00204         if (argc < 2) {
00205                 printf("Usage: %s gpsdev\n", argv[0]);
00206                 return 1;
00207         }
00208 
00209         gps_fd = open(argv[1], O_RDWR);
00210         if (gps_fd == -1) {
00211                 perror("Cannot open GPS device");
00212                 return 1;
00213         }
00214         
00215         tcgetattr(gps_fd, &termio);
00216         cfmakeraw(&termio);
00217    tcsetattr(gps_fd, TCIOFLUSH, &termio);
00218    garmin_privcmd(gps_fd);
00219    garmin_pvton();
00220    pktbuf_head = 0;
00221    pktbuf_tail = 0;
00222    fd_exif = open(EXIF_DEV, O_RDWR);
00223    if (fd_exif<=0) {
00224      fprintf(stderr,"Can not open device file "EXIF_DEV);
00225      close(gps_fd);
00226      exit (-1);
00227    }
00228    exif_init_meta(&meta);
00229    while (1) {
00230       Packet_t *pkt = recvpacket();
00231       if (pkt) {
00232         D(printf("Packet ID: %d, head=%d, tail=%d\n", pkt->mPacketId, pktbuf_head, pktbuf_tail));
00233 
00234         if (pkt->mPacketId == Pid_Pvt_Data) {
00235            memcpy(&lastpvt, pkt->mData, sizeof(lastpvt));
00236            if (exif_gen(&lastpvt, satdata_valid ? lastsatdata : NULL, &meta) >=0) {
00237              lseek (fd_exif,Exif_GPSInfo_GPSLatitudeRef,SEEK_END); // position file pointer at the beginning of the data field for GPSLatitudeRef
00238              write (fd_exif, &meta, sizeof(meta)); 
00239            }
00240         } else if (pkt->mPacketId == Pid_SatData_Record) {
00241            memcpy(lastsatdata, pkt->mData, sizeof(lastsatdata));
00242            satdata_valid = 1;
00243         }
00244         free(pkt); 
00245       } else { // lost GPS/sync, trying to restart GPS/buffer
00246         fprintf(stderr,"Lost GPS or sync, trying to restart communication and packet buffer. (pktbuf_head=%d,pktbuf_tail=%d)\n",pktbuf_head,pktbuf_tail);
00247         tcsetattr(gps_fd, TCIOFLUSH, &termio);
00248         garmin_privcmd(gps_fd);
00249         garmin_pvton();
00250         pktbuf_head = 0;
00251         pktbuf_tail = 0;
00252       }
00253    }
00254         close(gps_fd);
00255 }

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1