packet.c
来自「gpsd, a popular GPS daemon.」· C语言 代码 · 共 1,271 行 · 第 1/3 页
C
1,271 行
break; case SIRF_TRAILER_1: if (c == 0xb3) lexer->state = SIRF_RECOGNIZED; else lexer->state = GROUND_STATE; break; case SIRF_RECOGNIZED: if (c == 0xa0) lexer->state = SIRF_LEADER_1; else lexer->state = GROUND_STATE; break;#endif /* SIRF_ENABLE */#if defined(TSIP_ENABLE) || defined(EVERMORE_ENABLE) || defined(GARMIN_ENABLE) case DLE_LEADER:#ifdef EVERMORE_ENABLE if (c == STX) { lexer->state = EVERMORE_LEADER_2; break; }#endif /* EVERMORE_ENABLE */#if defined(TSIP_ENABLE) || defined(GARMIN_ENABLE) || defined(NAVCOM_ENABLE) /* garmin is special case of TSIP */ /* check last because there's no checksum */ if (c >= 0x13) { lexer->state = TSIP_PAYLOAD; break; } if (c == DLE) { lexer->state = GROUND_STATE; break; } // FALL-THRU!!!!! no break here#endif /* TSIP_ENABLE */#ifdef NAVCOM_ENABLE case NAVCOM_LEADER_1: if (c == 0x99) lexer->state = NAVCOM_LEADER_2; else lexer->state = GROUND_STATE; break; case NAVCOM_LEADER_2: if (c == 0x66) lexer->state = NAVCOM_LEADER_3; else lexer->state = GROUND_STATE; break; case NAVCOM_LEADER_3: lexer->state = NAVCOM_ID; break; case NAVCOM_ID: lexer->length = (size_t)c - 4; lexer->state = NAVCOM_LENGTH_1; break; case NAVCOM_LENGTH_1: lexer->length += (c << 8); lexer->state = NAVCOM_LENGTH_2; break; case NAVCOM_LENGTH_2: if (--lexer->length == 0) lexer->state = NAVCOM_PAYLOAD; break; case NAVCOM_PAYLOAD: { unsigned int n; unsigned char csum = lexer->inbuffer[3]; for(n=4; (unsigned char *)(lexer->inbuffer + n) < lexer->inbufptr - 1; n++) csum ^= lexer->inbuffer[n]; if(csum != c) { gpsd_report(LOG_INF, "Navcom packet type 0x%hx bad checksum 0x%hx, expecting 0x%hx\n", lexer->inbuffer[3], csum, c); gpsd_report(LOG_RAW, "Navcom packet dump: %s\n", gpsd_hexdump(lexer->inbuffer, lexer->inbuflen)); lexer->state = GROUND_STATE; break; } } lexer->state = NAVCOM_CSUM; break; case NAVCOM_CSUM: if (c == 0x03) lexer->state = NAVCOM_RECOGNIZED; else lexer->state = GROUND_STATE; break; case NAVCOM_RECOGNIZED: if (c == 0x02) lexer->state = NAVCOM_LEADER_1; else lexer->state = GROUND_STATE; break;#endif /* NAVCOM_ENABLE */#endif /* TSIP_ENABLE || EVERMORE_ENABLE || GARMIN_ENABLE */#ifdef ZODIAC_ENABLE case ZODIAC_EXPECTED: case ZODIAC_RECOGNIZED: if (c == 0xff) lexer->state = ZODIAC_LEADER_1; else lexer->state = GROUND_STATE; break; case ZODIAC_LEADER_1: if (c == 0x81) lexer->state = ZODIAC_LEADER_2; else lexer->state = GROUND_STATE; break; case ZODIAC_LEADER_2: lexer->state = ZODIAC_ID_1; break; case ZODIAC_ID_1: lexer->state = ZODIAC_ID_2; break; case ZODIAC_ID_2: lexer->length = (size_t)c; lexer->state = ZODIAC_LENGTH_1; break; case ZODIAC_LENGTH_1: lexer->length += (c << 8); lexer->state = ZODIAC_LENGTH_2; break; case ZODIAC_LENGTH_2: lexer->state = ZODIAC_FLAGS_1; break; case ZODIAC_FLAGS_1: lexer->state = ZODIAC_FLAGS_2; break; case ZODIAC_FLAGS_2: lexer->state = ZODIAC_HSUM_1; break; case ZODIAC_HSUM_1: { #define getword(i) (short)(lexer->inbuffer[2*(i)] | (lexer->inbuffer[2*(i)+1] << 8)) short sum = getword(0) + getword(1) + getword(2) + getword(3); sum *= -1; if (sum != getword(4)) { gpsd_report(LOG_IO, "Zodiac Header checksum 0x%hx expecting 0x%hx\n", sum, getword(4)); lexer->state = GROUND_STATE; break; } } gpsd_report(LOG_RAW+1,"Zodiac header id=%hd len=%hd flags=%hx\n", getword(1), getword(2), getword(3)); #undef getword if (lexer->length == 0) { lexer->state = ZODIAC_RECOGNIZED; break; } lexer->length *= 2; /* word count to byte count */ lexer->length += 2; /* checksum */ /* 10 bytes is the length of the Zodiac header */ if (lexer->length <= MAX_PACKET_LENGTH - 10) lexer->state = ZODIAC_PAYLOAD; else lexer->state = GROUND_STATE; break; case ZODIAC_PAYLOAD: if (--lexer->length == 0) lexer->state = ZODIAC_RECOGNIZED; break;#endif /* ZODIAC_ENABLE */#ifdef UBX_ENABLE case UBX_LEADER_1: if (c == 0x62) lexer->state = UBX_LEADER_2; else lexer->state = GROUND_STATE; break; case UBX_LEADER_2: lexer->state = UBX_CLASS_ID; break; case UBX_CLASS_ID: lexer->state = UBX_MESSAGE_ID; break; case UBX_MESSAGE_ID: lexer->length = (size_t)c; lexer->state = UBX_LENGTH_1; break; case UBX_LENGTH_1: lexer->length += (c << 8); if (lexer->length <= MAX_PACKET_LENGTH) lexer->state = UBX_LENGTH_2; else lexer->state = GROUND_STATE; break; case UBX_LENGTH_2: lexer->state = UBX_PAYLOAD; break; case UBX_PAYLOAD: if (--lexer->length == 0) lexer->state = UBX_CHECKSUM_A; /* else stay in payload state */ break; case UBX_CHECKSUM_A: lexer->state = UBX_RECOGNIZED; break; case UBX_RECOGNIZED: if (c == 0xb5) lexer->state = UBX_LEADER_1; else lexer->state = GROUND_STATE; break;#endif /* UBX_ENABLE */#ifdef EVERMORE_ENABLE case EVERMORE_LEADER_1: if (c == STX) lexer->state = EVERMORE_LEADER_2; else lexer->state = GROUND_STATE; break; case EVERMORE_LEADER_2: lexer->length = (size_t)c; if (c == DLE) lexer->state = EVERMORE_PAYLOAD_DLE; else lexer->state = EVERMORE_PAYLOAD; break; case EVERMORE_PAYLOAD: if (c == DLE) lexer->state = EVERMORE_PAYLOAD_DLE; else if (--lexer->length == 0) lexer->state = GROUND_STATE; break; case EVERMORE_PAYLOAD_DLE: switch (c) { case DLE: lexer->state = EVERMORE_PAYLOAD; break; case ETX: lexer->state = EVERMORE_RECOGNIZED; break; default: lexer->state = GROUND_STATE; } break; case EVERMORE_RECOGNIZED: if (c == DLE) lexer->state = EVERMORE_LEADER_1; else lexer->state = GROUND_STATE; break;#endif /* EVERMORE_ENABLE */#ifdef ITRAX_ENABLE case ITALK_LEADER_1: if (c == '!') lexer->state = ITALK_LEADER_2; else lexer->state = GROUND_STATE; break; case ITALK_LEADER_2: lexer->length = (size_t)(lexer->inbuffer[6] & 0xff); lexer->state = ITALK_LENGTH; break; case ITALK_LENGTH: lexer->length += 1; /* fix number of words in payload */ lexer->length *= 2; /* convert to number of bytes */ lexer->length += 3; /* add trailer length */ lexer->state = ITALK_PAYLOAD; break; case ITALK_PAYLOAD: /* lookahead for "<!" because sometimes packets are short but valid */ if ((c == '>') && (lexer->inbufptr[0] == '<') && (lexer->inbufptr[1] == '!')){ lexer->state = ITALK_RECOGNIZED; gpsd_report(LOG_PROG, "ITALK: trying to process runt packet\n"); break; } else if (--lexer->length == 0) lexer->state = ITALK_DELIVERED; break; case ITALK_DELIVERED: if (c == '>') lexer->state = ITALK_RECOGNIZED; else lexer->state = GROUND_STATE; break; case ITALK_RECOGNIZED: if (c == '<') lexer->state = ITALK_LEADER_1; else lexer->state = GROUND_STATE; break;#endif /* ITRAX_ENABLE */#ifdef TSIP_ENABLE case TSIP_LEADER: /* unused case */ if (c >= 0x13) lexer->state = TSIP_PAYLOAD; else lexer->state = GROUND_STATE; break; case TSIP_PAYLOAD: if (c == DLE) lexer->state = TSIP_DLE; break; case TSIP_DLE: switch (c) { case ETX: lexer->state = TSIP_RECOGNIZED; break; case DLE: lexer->state = TSIP_PAYLOAD; break; default: lexer->state = GROUND_STATE; break; } break; case TSIP_RECOGNIZED: if (c == DLE) /* * Don't go to TSIP_LEADER state -- TSIP packets aren't * checksummed, so false positives are easy. We might be * looking at another DLE-stuffed protocol like EverMore * or Garmin streaming binary. */ lexer->state = DLE_LEADER; else lexer->state = GROUND_STATE; break;#endif /* TSIP_ENABLE */#ifdef RTCM104_ENABLE case RTCM_SYNC_STATE: case RTCM_SKIP_STATE: if ((isgpsstat = rtcm_decode(lexer, c)) == ISGPS_MESSAGE) { lexer->state = RTCM_RECOGNIZED; break; } else if (isgpsstat == ISGPS_NO_SYNC) lexer->state = GROUND_STATE; break; case RTCM_RECOGNIZED: if (rtcm_decode(lexer, c) == ISGPS_SYNC) { lexer->state = RTCM_SYNC_STATE; break; } else lexer->state = GROUND_STATE; break;#endif /* RTCM104_ENABLE */ }/*@ -charint +casebreak @*/}#define STATE_DEBUGstatic void packet_accept(struct gps_packet_t *lexer, int packet_type)/* packet grab succeeded, move to output buffer */{ size_t packetlen = lexer->inbufptr-lexer->inbuffer; if (packetlen < sizeof(lexer->outbuffer)) { memcpy(lexer->outbuffer, lexer->inbuffer, packetlen); lexer->outbuflen = packetlen; lexer->outbuffer[packetlen] = '\0'; lexer->type = packet_type;#ifdef STATE_DEBUG gpsd_report(LOG_RAW+1, "Packet type %d accepted %d = %s\n", packet_type, packetlen, gpsd_hexdump(lexer->outbuffer, lexer->outbuflen));#endif /* STATE_DEBUG */ } else { gpsd_report(LOG_ERROR, "Rejected too long packet type %d len %d\n", packet_type,packetlen); }}static void packet_discard(struct gps_packet_t *lexer)/* shift the input buffer to discard all data up to current input pointer */{ size_t discard = lexer->inbufptr - lexer->inbuffer; size_t remaining = lexer->inbuflen - discard; lexer->inbufptr = memmove(lexer->inbuffer, lexer->inbufptr, remaining); lexer->inbuflen = remaining;#ifdef STATE_DEBUG gpsd_report(LOG_RAW+1, "Packet discard of %d, chars remaining is %d = %s\n", discard, remaining, gpsd_hexdump(lexer->inbuffer, lexer->inbuflen));#endif /* STATE_DEBUG */}static void character_discard(struct gps_packet_t *lexer)/* shift the input buffer to discard one character and reread data */{ memmove(lexer->inbuffer, lexer->inbuffer+1, (size_t)--lexer->inbuflen); lexer->inbufptr = lexer->inbuffer;#ifdef STATE_DEBUG gpsd_report(LOG_RAW+1, "Character discarded, buffer %d chars = %s\n", lexer->inbuflen, gpsd_hexdump(lexer->inbuffer, lexer->inbuflen));#endif /* STATE_DEBUG */}/* get 0-origin big-endian words relative to start of packet buffer */#define getword(i) (short)(lexer->inbuffer[2*(i)] | (lexer->inbuffer[2*(i)+1] << 8))/* entry points begin here */ssize_t packet_parse(struct gps_packet_t *lexer, size_t fix)/* grab a packet; returns either BAD_PACKET or the length */{#ifdef STATE_DEBUG gpsd_report(LOG_RAW+1, "Read %d chars to buffer offset %d (total %d): %s\n", fix, lexer->inbuflen, lexer->inbuflen+fix, gpsd_hexdump(lexer->inbufptr, fix));#endif /* STATE_DEBUG */ lexer->outbuflen = 0; lexer->inbuflen += fix; while (lexer->inbufptr < lexer->inbuffer + lexer->inbuflen) { /*@ -modobserver @*/ unsigned char c = *lexer->inbufptr++; /*@ +modobserver @*/ char *state_table[] = {#include "packet_names.h" }; nextstate(lexer, c); gpsd_report(LOG_RAW+2, "%08ld: character '%c' [%02x], new state: %s\n", lexer->char_counter, (isprint(c)?c:'.'), c, state_table[lexer->state]); lexer->char_counter++;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?