int32 GPS_Command_Get_Waypoint(const char *port, GPS_PWay **way, pcb_fn cb) { int32 ret=0; /* * It's a bit tacky to do this up front without ticking the * progress meter, but this come in pretty quickly... */ if (gps_category_transfer) { ret = GPS_A101_Get(port); if (!ret) { fatal("blah"); return PROTOCOL_ERROR; } } switch(gps_waypt_transfer) { case pA100: ret = GPS_A100_Get(port,way, cb); break; default: GPS_Error("Get_Waypoint: Unknown waypoint protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Send_Track(const char *port, GPS_PTrack *trk, int32 n, int eraset) { int32 ret=0; if(gps_trk_transfer == -1) return GPS_UNSUPPORTED; switch(gps_trk_transfer) { case pA300: ret = GPS_A300_Send(port, trk, n); break; case pA301: ret = GPS_A301_Send(port, trk, n, 301, NULL); break; case pA302: /* Units with A302 don't support track upload, so we convert the * track to a course on the fly and send that instead */ ret = GPS_Command_Send_Track_As_Course(port, trk, n, NULL, 0, eraset); break; default: GPS_Error("Send_Track: Unknown track protocol %d.", gps_trk_transfer); break; } return ret; }
int32 GPS_Protocol_Table_Set(US id) { int32 i; US v; char s[GPS_ARB_LEN]; i=0; while((v=GPS_MP[i].id)) { if(v==id) { gps_link_type = GPS_MP[i].link; gps_device_command = GPS_MP[i].command-10; gps_waypt_transfer = GPS_MP[i].wayptt; gps_waypt_type = GPS_MP[i].wayptd; gps_route_transfer = GPS_MP[i].rtea; gps_rte_hdr_type = GPS_MP[i].rted0; gps_rte_type = GPS_MP[i].rted1; gps_trk_transfer = GPS_MP[i].trka; gps_trk_type = GPS_MP[i].trkd; gps_prx_waypt_transfer = GPS_MP[i].prxa; gps_prx_waypt_type = GPS_MP[i].prxd; gps_almanac_transfer = GPS_MP[i].alma; gps_almanac_type = GPS_MP[i].almd; return 1; } ++i; } (void)sprintf(s,"INIT: No table entry for ID %d\n",id); GPS_Error(s); return GPS_UNSUPPORTED; }
/* * Return values are: * Negative on error. * 1 if read success - even if empty packet. */ int32 GPS_Packet_Read_usb(gpsdevh *dh, GPS_PPacket *packet, int eat_bulk) { int32 n; int32 payload_size; garmin_usb_packet pkt; memset(&pkt, 0, sizeof(pkt)); do_over: n = gusb_cmd_get(&pkt, sizeof(pkt)); if ( n < 0 ) { /* * We (probably) used to have a GPS and it went away * while we were speaking with it. Perhaps batteries * died or it was unplugged or something. */ gps_errno = PROTOCOL_ERROR; return n; } /* * This is a horrible hack for 276/296. This family sometimes * switches between bulk and interrupt on EVERY packet. Rather * than bother all the callers with that bit of unpleasantness, * silently consume zero byte "switch back to intr" packets here. * * The one caller that doesn't want this hidden is device discovery * in the A000 handler. */ if ((n == 0) && eat_bulk) { goto do_over; } /* * Populate members of serial packet from USB packet. The * copy here seems wasteful, but teaching all the callers about * a structure with the "data" member being in a different place * (Since the protocol packets was badly exposed in the core * design of jeeps) is even more painful. */ (*packet)->type = le_read16(&pkt.gusb_pkt.pkt_id); payload_size = le_read32(&pkt.gusb_pkt.datasz); if (payload_size<0 || payload_size>MAX_GPS_PACKET_SIZE) { GPS_Error("GPS_Packet_Read_usb: Bad payload size %d", payload_size); gps_errno = FRAMING_ERROR; return 0; } (*packet)->n = payload_size; memcpy((*packet)->data, &pkt.gusb_pkt.databuf, payload_size); return 1; }
int32 GPS_Serial_Off(gpsdevh *dh) { if(!GPS_Serial_Close(dh)) { GPS_Error("Error Closing port"); gps_errno = HARDWARE_ERROR; return 0; } dh = NULL; return 1; }
time_t GPS_Time_Now(void) { time_t secs; if(time(&secs)==-1) { perror("time"); GPS_Error("GPS_Time_Now: Error reading time"); gps_errno = HARDWARE_ERROR; return 0; } return secs; }
int32 GPS_Serial_On(const char *port, gpsdevh **dh) { posix_serial_data *psd = xcalloc(sizeof (posix_serial_data), 1); *dh = (gpsdevh*) psd; if(!GPS_Serial_Open((gpsdevh *) psd,port)) { GPS_Error("Cannot open serial port '%s'", port); gps_errno = SERIAL_ERROR; return 0; } return 1; }
int32 GPS_Serial_Send_Ack(gpsdevh *fd, GPS_PPacket *tra, GPS_PPacket *rec) { UC data[2]; GPS_Util_Put_Short(data,(US)(*rec)->type); GPS_Make_Packet(tra,LINK_ID[0].Pid_Ack_Byte,data,2); if(!GPS_Write_Packet(fd,*tra)) { GPS_Error("Error acknowledging packet"); gps_errno = SERIAL_ERROR; return 0; } return 1; }
void GPS_Protocol_Error(US tag, US data) { char s[GPS_ARB_LEN]; (void) sprintf(s,"PROTOCOL ERROR: Unknown tag/data [%c/%d]\n",tag,data); GPS_Error(s); if(gps_n_tag_unknown < GPS_TAGUNK) { gps_tag_unknown[gps_n_tag_unknown] = tag; gps_tag_data_unknown[gps_n_tag_unknown++] = data; } return; }
int32 GPS_Command_Send_Time(const char *port, time_t Time) { time_t ret=0; switch(gps_date_time_transfer) { case pA600: ret = GPS_A600_Send(port, Time); break; default: GPS_Error("Send_Time: Unknown date/time protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Send_Position(const char *port, double lat, double lon) { int32 ret=0; switch(gps_position_transfer) { case pA700: ret = GPS_A700_Send(port, lat, lon); break; default: GPS_Error("Send_Position: Unknown position protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Send_Waypoint(const char *port, GPS_PWay *way, int32 n, int (*cb)(struct GPS_SWay **)) { int32 ret=0; switch(gps_waypt_transfer) { case pA100: ret = GPS_A100_Send(port, way, n, cb); break; default: GPS_Error("Send_Waypoint: Unknown waypoint protocol"); return PROTOCOL_ERROR; } return ret; }
/* * Display an error from the serial subsystem. */ void GPS_Serial_Error(const char *mb, ...) { va_list ap; char msg[200]; char *s; int b; va_start(ap, mb); b = vsnprintf(msg, sizeof(msg), mb, ap); s = msg + b; *s++ = ':'; *s++ = ' '; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, s, sizeof(msg) - b - 2, 0 ); GPS_Error(msg); }
int32 GPS_Command_Send_Almanac(const char *port, GPS_PAlmanac *alm, int32 n) { int32 ret=0; if(gps_almanac_transfer == -1) return GPS_UNSUPPORTED; switch(gps_almanac_transfer) { case pA500: ret = GPS_A500_Send(port, alm, n); break; default: GPS_Error("Send_Almanac: Unknown almanac protocol"); break; } return ret; }
int32 GPS_Command_Get_Proximity(const char *port, GPS_PWay **way) { int32 ret=0; if(gps_prx_waypt_transfer == -1) return GPS_UNSUPPORTED; switch(gps_prx_waypt_transfer) { case pA400: ret = GPS_A400_Get(port,way); break; default: GPS_Error("Get_Proximity: Unknown proximity protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Get_Almanac(const char *port, GPS_PAlmanac **alm) { int32 ret=0; if(gps_almanac_transfer == -1) return GPS_UNSUPPORTED; switch(gps_almanac_transfer) { case pA500: ret = GPS_A500_Get(port,alm); break; default: GPS_Error("Get_Almanac: Unknown almanac protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Get_Route(const char *port, GPS_PWay **way) { int32 ret=0; switch(gps_route_transfer) { case pA200: ret = GPS_A200_Get(port,way); break; case pA201: ret = GPS_A201_Get(port,way); break; default: GPS_Error("Get_Route: Unknown route protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Get_Lap(const char *port, GPS_PLap **lap, pcb_fn cb) { int32 ret=0; if(gps_lap_transfer == -1) return GPS_UNSUPPORTED; switch(gps_lap_transfer) { case pA906: ret = GPS_A906_Get(port,lap, cb); break; default: GPS_Error("Get_Lap: Unknown lap protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Pvt_Off(const char *port, gpsdevh **fd) { int32 ret=0; if(gps_pvt_transfer == -1) return GPS_UNSUPPORTED; switch(gps_pvt_transfer) { case pA800: ret = GPS_A800_Off(port,fd); break; default: GPS_Error("Pvt_Off: Unknown position protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Send_Proximity(const char *port, GPS_PWay *way, int32 n) { int32 ret=0; if(gps_prx_waypt_transfer == -1) return GPS_UNSUPPORTED; switch(gps_prx_waypt_transfer) { case pA400: ret = GPS_A400_Send(port, way, n); break; default: GPS_Error("Send_Proximity: Unknown proximity protocol"); break; } return ret; }
int32 GPS_Command_Pvt_Get(gpsdevh **fd, GPS_PPvt_Data *pvt) { int32 ret=0; if(gps_pvt_transfer == -1) return GPS_UNSUPPORTED; (*pvt)->fix = 0; switch(gps_pvt_transfer) { case pA800: ret = GPS_A800_Get(fd,pvt); break; default: GPS_Error("Pvt_Get: Unknown position protocol"); return PROTOCOL_ERROR; } return ret; }
time_t GPS_Command_Get_Time(const char *port) { time_t ret=0; switch(gps_date_time_transfer) { case pA600: ret = GPS_A600_Get(port); break; /* * If the unit doesn't support it (i.e. a C320 in charging mode), * but don't treat as error; return as zero. */ case -1: return 0; default: GPS_Error("Get_Time: Unknown date/time protocol"); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Get_Track(const char *port, GPS_PTrack **trk, pcb_fn cb) { int32 ret=0; if(gps_trk_transfer == -1) return GPS_UNSUPPORTED; switch(gps_trk_transfer) { case pA300: ret = GPS_A300_Get(port,trk,cb); break; case pA301: case pA302: ret = GPS_A301_Get(port,trk,cb,301); break; default: GPS_Error("Get_Track: Unknown track protocol %d\n", gps_trk_transfer); return PROTOCOL_ERROR; } return ret; }
int32 GPS_Command_Get_Position(const char *port, double *lat, double *lon) { int32 ret=0; switch(gps_position_transfer) { case pA700: ret = GPS_A700_Get(port,lat,lon); break; /* * If the unit doesn't support it (i.e. a C320 in charging mode), * zero lat/lon, but don't treat as error. */ case -1: *lat = *lon = 0.0; break; default: GPS_Error("Get_Position: Unknown position protocol"); return PROTOCOL_ERROR; } return ret; }
/* Wrapped interface from higher level objects */ int Garmin_GPS_Init( wxString &port_name) { int ret; #ifdef GPS_DEBUG0 // if (getenv("OPENCPN_GPS_ERROR") != NULL) GPS_Enable_Error(); // if (getenv("OPENCPN_GPS_WARNING") != NULL) GPS_Enable_Warning(); // if (getenv("OPENCPN_GPS_USER") != NULL) GPS_Enable_User(); // if (getenv("OPENCPN_GPS_DIAGNOSE") != NULL) GPS_Enable_Diagnose(); #endif char m[1]; m[0] = '\0'; GPS_Error(m); ret = GPS_Init(port_name.mb_str()); VerifyPortClosed(); return ret; }
/* @func GPS_Command_Get_Course *************************************** ** ** Get Courses from GPS. According to Garmin protocol specification, this ** includes getting all course laps, course tracks and course points ** from the device. ** ** @param [r] port [const char *] serial port ** @param [w] crs [GPS_PCourse **] pointer to course array ** @param [w] clp [GPS_PCourse_Lap **] pointer to course lap array ** @param [w] trk [GPS_PTrack **] pointer to track array ** @param [w] cpt [GPS_PCourse_Point **] pointer to course point array ** @param [w] n_clp [int32 **] pointer to number of lap entries ** @param [w] n_trk [int32 **] pointer to number of track entries ** @param [w] n_cpt [int32 **] pointer to number of course point entries ** ** @return [int32] number of course entries ************************************************************************/ int32 GPS_Command_Get_Course (const char *port, GPS_PCourse **crs, GPS_PCourse_Lap **clp, GPS_PTrack **trk, GPS_PCourse_Point **cpt, int32 *n_clp, int32 *n_trk, int32 *n_cpt, pcb_fn cb) { int32 ret=0; if(gps_course_transfer == -1) return GPS_UNSUPPORTED; switch(gps_course_transfer) { case pA1006: ret = GPS_A1006_Get(port,crs,cb); break; default: GPS_Error("Get_Course: Unknown course protocol"); return PROTOCOL_ERROR; } switch(gps_course_lap_transfer) { case pA1007: *n_clp = GPS_A1007_Get(port,clp, 0); break; default: GPS_Error("Get_Course: Unknown course lap protocol"); return PROTOCOL_ERROR; } switch(gps_course_trk_transfer) { case pA1012: GPS_Error("Get_Course: Not implemented track protocol %d\n", gps_trk_transfer); break; case pA302: *n_trk = GPS_A301_Get(port,trk,cb,302); break; default: GPS_Error("Get_Course: Unknown course track protocol %d\n", gps_trk_transfer); return PROTOCOL_ERROR; } switch(gps_course_point_transfer) { case pA1008: *n_cpt = GPS_A1008_Get(port,cpt, 0); break; default: GPS_Error("Get_Course: Unknown course point protocol"); return PROTOCOL_ERROR; } return ret; }
/* @func GPS_Command_Send_Course *************************************** ** ** Send Courses to GPS. According to Garmin protocol specification, this ** includes sending all course laps, course tracks and course points ** to the device. ** ** @param [r] port [const char *] serial port ** @param [w] crs [GPS_PCourse **] course array ** @param [w] clp [GPS_PCourse_Lap *] course lap array ** @param [w] trk [GPS_PTrack *] track array ** @param [w] cpt [GPS_PCourse_Point *] course point array ** @param [w] n_crs [int32] number of course entries ** @param [w] n_clp [int32] number of lap entries ** @param [w] n_trk [int32] number of track entries ** @param [w] n_cpt [int32] number of course point entries ** ** @return [int32] Success ************************************************************************/ int32 GPS_Command_Send_Course (const char *port, GPS_PCourse *crs, GPS_PCourse_Lap *clp, GPS_PTrack *trk, GPS_PCourse_Point *cpt, int32 n_crs, int32 n_clp, int32 n_trk, int32 n_cpt) { gpsdevh *fd; GPS_OCourse_Limits limits; int32 ret; int32 ret_crs=0; int32 ret_clp=0; int32 ret_trk=0; int32 ret_cpt=0; if(gps_course_transfer == -1 || gps_course_limits_transfer == -1) return GPS_UNSUPPORTED; /* Check course limits to make sure we're not exceeding the device's * capacity. */ switch(gps_course_limits_transfer) { case pA1009: ret = GPS_A1009_Get(port,&limits); break; default: GPS_Error("Send_Course: Unknown course limitsprotocol"); return PROTOCOL_ERROR; } if (n_crs > limits.max_courses || n_clp > limits.max_course_laps || n_trk > limits.max_course_trk_pnt || n_cpt > limits.max_course_pnt) { GPS_Error("Course upload would exceed device capacity:"); GPS_Error("# of courses: %d, max: %d", n_crs, limits.max_courses); GPS_Error("# of laps: %d, max: %d", n_clp, limits.max_course_laps); GPS_Error("# of track points: %d, max: %d", n_trk, limits.max_course_trk_pnt); GPS_Error("# of course points: %d, max: %d", n_cpt, limits.max_course_pnt); return GPS_UNSUPPORTED; } /* Initialize device communication: * In contrast to other transfer protocols, this has to be handled here; * shutting off communication in between the different parts * could lead to data corruption on the device because all the courses * and their associated lap and track data have to be sent in one * transaction. */ if(!GPS_Device_On(port,&fd)) return gps_errno; switch(gps_course_transfer) { case pA1006: ret_crs = GPS_A1006_Send(port,crs,n_crs,fd); break; default: GPS_Error("Send_Course: Unknown course protocol"); return PROTOCOL_ERROR; } switch(gps_course_lap_transfer) { case pA1007: ret_clp = GPS_A1007_Send(port,clp,n_clp,fd); break; default: GPS_Error("Send_Course: Unknown course lap protocol"); return PROTOCOL_ERROR; } switch(gps_course_trk_transfer) { case pA1012: GPS_Error("Send_Course: Not implemented track protocol %d\n", gps_trk_transfer); break; case pA302: ret_trk = GPS_A301_Send(port,trk,n_trk,302,fd); break; default: GPS_Error("Send_Course: Unknown course track protocol %d\n", gps_trk_transfer); return PROTOCOL_ERROR; } switch(gps_course_point_transfer) { case pA1008: ret_cpt = GPS_A1008_Send(port,cpt,n_cpt,fd); break; default: GPS_Error("Send_Course: Unknown course point protocol"); return PROTOCOL_ERROR; } if(!GPS_Device_Off(fd)) return gps_errno; return ret_crs * ret_clp * ret_trk * ret_cpt; }
int32 GPS_Serial_Packet_Read(gpsdevh *fd, GPS_PPacket *packet) { time_t start; int32 n; int32 len; UC u; int32 isDLE; UC *p; uint32 i; UC chk=0, chk_read; const char *m1; const char *m2; len = 0; isDLE = gpsFalse; p = (*packet)->data; start = GPS_Time_Now(); GPS_Diag("Rx Data:"); while(GPS_Time_Now() < start+GPS_TIME_OUT) { if((n=GPS_Serial_Chars_Ready(fd))) { if(GPS_Serial_Read(fd,&u,1)==-1) { perror("read"); GPS_Error("GPS_Packet_Read: Read error"); gps_errno = FRAMING_ERROR; return 0; } GPS_Diag("%02x ", u); if(!len) { if(u != DLE) { (void) fprintf(stderr,"GPS_Packet_Read: No DLE. Data received, but probably not a garmin packet.\n"); (void) fflush(stderr); return 0; } ++len; continue; } if(len==1) { (*packet)->type = u; ++len; continue; } if(u == DLE) { if(isDLE) { isDLE = gpsFalse; continue; } isDLE = gpsTrue; } if(len == 2) { (*packet)->n = u; len = -1; continue; } if(u == ETX) if(isDLE) { if(p-(*packet)->data-2 != (*packet)->n) { GPS_Error("GPS_Packet_Read: Bad count"); gps_errno = FRAMING_ERROR; return 0; } chk_read = *(p-2); for(i=0,p=(*packet)->data;i<(*packet)->n;++i) chk -= *p++; chk -= (*packet)->type; chk -= (UC)((*packet)->n); if(chk != chk_read) { GPS_Error("CHECKSUM: Read error\n"); gps_errno = FRAMING_ERROR; return 0; } m1 = Get_Pkt_Type((*packet)->type, (*packet)->data[0], &m2); if (gps_show_bytes) { GPS_Diag(" "); for (i = 0; i < (*packet)->n; i++) { char c = (*packet)->data[i]; GPS_Diag("%c", c); //isalnum(c) ? c : '.'); } GPS_Diag(" "); } GPS_Diag("(%-8s%s)\n", m1, m2 ? m2 : ""); return (*packet)->n; } if (p - (*packet)->data >= MAX_GPS_PACKET_SIZE) { GPS_Error("GPS_Serial_Packet_Read: Bad payload size/no ETX found"); gps_errno = FRAMING_ERROR; return 0; } *p++ = u; } } GPS_Error("GPS_Packet_Read: Timeout. No data received."); gps_errno = SERIAL_ERROR; return 0; }
int32 GPS_Serial_Write_Packet(gpsdevh *fd, GPS_PPacket packet) { size_t ret; const char *m1, *m2; GPS_Serial_OPacket ser_pkt; UC ser_pkt_data[MAX_GPS_PACKET_SIZE * sizeof(UC)]; US bytes; if(!fd) return 0; if (packet->type >= 0xff || packet->n >= 0xff) { GPS_Error("SEND: Unsupported packet type/size for serial protocol"); return 0; } ser_pkt.data = ser_pkt_data; bytes = Build_Serial_Packet(packet, &ser_pkt); GPS_Diag("Tx Data:"); Diag(&ser_pkt.dle, 3); if((ret=GPS_Serial_Write(fd,(const void *) &ser_pkt.dle,(size_t)3)) == -1) { perror("write"); GPS_Error("SEND: Write to GPS failed"); return 0; } if(ret!=3) { GPS_Error("SEND: Incomplete write to GPS"); return 0; } Diag(ser_pkt.data, bytes); if((ret=GPS_Serial_Write(fd,(const void *)ser_pkt.data,(size_t)bytes)) == -1) { perror("write"); GPS_Error("SEND: Write to GPS failed"); return 0; } if(ret!=bytes) { GPS_Error("SEND: Incomplete write to GPS"); return 0; } Diag(&ser_pkt.chk, 3); GPS_Diag(": "); DiagS(ser_pkt.data, bytes); DiagS(&ser_pkt.chk, 3); m1 = Get_Pkt_Type(ser_pkt.type, ser_pkt.data[0], &m2); GPS_Diag("(%-8s%s)\n", m1, m2 ? m2 : ""); if((ret=GPS_Serial_Write(fd,(const void *)&ser_pkt.chk,(size_t)3)) == -1) { perror("write"); GPS_Error("SEND: Write to GPS failed"); return 0; } if(ret!=3) { GPS_Error("SEND: Incomplete write to GPS"); return 0; } return 1; }
/* * Return values are: * Negative on error. * 1 if read success - even if empty packet. */ int32 GPS_Packet_Read_usb(gpsdevh *dh, GPS_PPacket *packet, int eat_bulk) { int32 n; int32 payload_size; garmin_usb_packet pkt; memset(&pkt, 0, sizeof(pkt)); do_over: n = gusb_cmd_get(&pkt, sizeof(pkt)); if ( n < 0 ) { /* * We (probably) used to have a GPS and it went away * while we were speaking with it. Perhaps batteries * died or it was unplugged or something. */ gps_errno = PROTOCOL_ERROR; return n; } /* * This is a horrible hack for 276/296. This family sometimes * switches between bulk and interrupt on EVERY packet. Rather * than bother all the callers with that bit of unpleasantness, * silently consume zero byte "switch back to intr" packets here. * * The one caller that doesn't want this hidden is device discovery * in the A000 handler. */ if ((n == 0) && eat_bulk) { goto do_over; } /* We sometimes get corrupted packets during a track log transfer * where the first byte in a packet is lost, causing all remaining * bytes in this packet to be shifted. So far, this has only been * observed on a Forerunner 305 (both on Linux and Windows). The * cause is unknown, but it seems to be timing dependent. * We try to detect the corruption mainly by checking reserved bytes * 3 and 7 which normally should be 0, the remaining comparisons are * only sanity checks and they alone could also trigger in case of * valid packets. Note: We can't detect corrupted packets with an ID * or length that's a multiple of 256, but such corrupted packets * haven't been observed so far. */ if (gps_save_id == 484 && pkt.gusb_pkt.type == 0 && pkt.gusb_pkt.reserved1 == 0 && pkt.gusb_pkt.reserved2 == 0 && pkt.gusb_pkt.reserved3 != 0 && pkt.gusb_pkt.pkt_id[0] <= 4 && pkt.gusb_pkt.pkt_id[1] == 0 && pkt.gusb_pkt.reserved6 == 0 && pkt.gusb_pkt.reserved7 != 0) { memmove(&pkt.dbuf[1], &pkt.dbuf[0], sizeof(pkt) - 1); pkt.gusb_pkt.type = 20; } /* * Populate members of serial packet from USB packet. The * copy here seems wasteful, but teaching all the callers about * a structure with the "data" member being in a different place * (Since the protocol packets was badly exposed in the core * design of jeeps) is even more painful. */ (*packet)->type = le_read16(&pkt.gusb_pkt.pkt_id); payload_size = le_read32(&pkt.gusb_pkt.datasz); if (payload_size<0 || payload_size>MAX_GPS_PACKET_SIZE) { /* If you get this, the packet might have been corrupted * by the unit. Have a look at the corruption detection * code above. */ GPS_Error("GPS_Packet_Read_usb: Bad payload size %d", payload_size); gps_errno = FRAMING_ERROR; return 0; } (*packet)->n = payload_size; memcpy((*packet)->data, &pkt.gusb_pkt.databuf, payload_size); return 1; }