31 #define RECORD_TYPE_OSD 0x01 32 #define RECORD_TYPE_HOME 0x02 33 #define RECORD_TYPE_GIMBAL 0x03 34 #define RECORD_TYPE_RC 0x04 35 #define RECORD_TYPE_CUSTOM 0x05 36 #define RECORD_TYPE_DEFORM 0x06 37 #define RECORD_TYPE_CENTER_BATTERY 0x07 38 #define RECORD_TYPE_SMART_BATTERY 0x08 39 #define RECORD_TYPE_APP_TIP 0x09 40 #define RECORD_TYPE_APP_WARN 0x0A 41 #define RECORD_TYPE_RC_GPS 0x0B 42 #define RECORD_TYPE_RC_DEBUG 0x0C 43 #define RECORD_TYPE_RECOVER 0x0D 44 #define RECORD_TYPE_APP_GPS 0x0E 45 #define RECORD_TYPE_FIRMWARE 0x0F 46 #define RECORD_TYPE_OFDM_DEBUG 0x10 47 #define RECORD_TYPE_VISION_GROUP 0x11 48 #define RECORD_TYPE_VISION_WARN 0x12 49 #define RECORD_TYPE_MC_PARAM 0x13 50 #define RECORD_TYPE_APP_OPERATION 0x14 52 #define RECORD_TYPE_APP_SER_WARN 0x18 56 #define RECORD_TYPE_COMPONENT 0x28 57 #define RECORD_TYPE_JPEG 0x39 58 #define RECORD_TYPE_OTHER 0xFE 60 #define JPEG_SOI_BYTE 0xD8 66 u_int8_t recordType =
getByte(ptr, limit);
67 unsigned recordLength =
getByte(ptr, limit);
76 #ifdef DEBUG_RECORD_PARSING 78 if (recordTypeName == NULL) recordTypeName =
"???";
83 u_int16_t next2Bytes =
get2BytesBE(ptr, limit); ptr -= 2;
84 if (next2Bytes == 0x0000) {
89 }
else if (recordType == 0xFF && recordLength ==
JPEG_SOI_BYTE) {
96 if (ptr + recordLength + 1 >= limit)
throw END_OF_DATA;
97 if (ptr[recordLength] != 0xFF) {
99 if (ptr + recordLength + 2 < limit && ptr[recordLength+1] == 0xFF) {
100 fprintf(stderr,
"Extra byte 0x%02x seen in record (type 0x%x)\n", ptr[recordLength], recordType);
103 fprintf(stderr,
"'End of record' byte (0xFF) not seen; advancing to the next 0xFF\n");
106 }
while (ptr + recordLength + 1 < limit && ptr[recordLength+1] != 0xFF);
107 if (ptr + recordLength + 1 >= limit)
throw END_OF_DATA;
110 u_int8_t
const* recordStart = ptr;
111 u_int8_t
const* recordLimit = ptr + recordLength;
112 ptr += recordLength + 1;
114 u_int8_t unscrambledRecord[recordLength-1];
119 u_int8_t keyByte =
getByte(recordStart, limit);
123 u_int8_t scrambleBytes[8];
127 for (
unsigned i = 0; i < recordLength; ++i) {
128 unscrambledRecord[i] = recordStart[i] ^ scrambleBytes[i%8];
131 recordStart = unscrambledRecord;
132 recordLimit = unscrambledRecord + recordLength;
135 switch (recordType) {
229 #ifdef DEBUG_RECORD_PARSING 231 if (recordTypeName == NULL) {
232 fprintf(stderr,
"Unknown record type 0x%02x\n", recordType);
234 fprintf(stderr,
"Unhandled record type 0x%02x [%s]\n", recordType, recordTypeName);
237 fprintf(stderr,
"Unhandled record type 0x%02x\n", recordType);
242 fprintf(stderr,
"Unexpected error in parsing\n");
250 #ifdef DEBUG_RECORD_PARSING 252 unsigned maxRecordTypeFieldLen = 0;
253 for (
unsigned i = 0; i < 256; ++i) {
255 unsigned recordTypeNameLen = recordTypeName == NULL ? 3 : strlen(recordTypeName);
256 unsigned iLog10 = i<10 ? 0 : i<100 ? 1 : 2;
257 unsigned recordTypeFieldLen = iLog10 + 2 + recordTypeNameLen + 2;
258 if (recordTypeFieldLen > maxRecordTypeFieldLen) maxRecordTypeFieldLen = recordTypeFieldLen;
260 unsigned maxNumTabs = maxRecordTypeFieldLen/8 + 1;
262 for (
unsigned i = 0; i < 255; ++i) {
265 if (recordTypeName == NULL) recordTypeName =
"???";
266 unsigned iLog10 = i<10 ? 0 : i<100 ? 1 : 2;
267 unsigned recordTypeFieldLen = iLog10 + 2 + strlen(recordTypeName) + 2;
268 unsigned numTabs = maxNumTabs - recordTypeFieldLen/8;
270 fprintf(stderr,
"%d[%s]:", i, recordTypeName);
271 for (
unsigned j = 0; j < numTabs; ++j) fprintf(stderr,
"\t");
void parseRecord_HOME(u_int8_t const *&ptr, u_int8_t const *limit)
u_int8_t getByte(u_int8_t const *&ptr, u_int8_t const *limit)
#define RECORD_TYPE_SMART_BATTERY
#define RECORD_TYPE_VISION_WARN
RecordTypeStat fRecordTypeStats[256]
void parseRecord_RECOVER(u_int8_t const *&ptr, u_int8_t const *limit)
void parseRecord_APP_GPS(u_int8_t const *&ptr, u_int8_t const *limit)
void parseRecordUnknownFormat(char const *recordTypeName, u_int8_t const *&ptr, u_int8_t const *limit)
virtual void summarizeRecordParsing()
#define RECORD_TYPE_APP_TIP
void getScrambleBytes(u_int8_t recordType, u_int8_t keyByte, u_int8_t *resultScrambleBytes)
#define RECORD_TYPE_COMPONENT
void parseRecord_APP_WARN(u_int8_t const *&ptr, u_int8_t const *limit)
virtual int parseRecord(u_int8_t const *&ptr, u_int8_t const *limit, int isScrambled)
#define RECORD_TYPE_RC_GPS
#define RECORD_TYPE_DEFORM
#define RECORD_TYPE_GIMBAL
void parseRecord_COMPONENT(u_int8_t const *&ptr, u_int8_t const *limit)
void parseRecord_CENTER_BATTERY(u_int8_t const *&ptr, u_int8_t const *limit)
#define RECORD_TYPE_RC_DEBUG
unsigned fMaxNumRecordsForOneType
#define RECORD_TYPE_APP_OPERATION
void parseRecord_CUSTOM(u_int8_t const *&ptr, u_int8_t const *limit)
void parseRecord_DEFORM(u_int8_t const *&ptr, u_int8_t const *limit)
#define RECORD_TYPE_APP_SER_WARN
#define RECORD_TYPE_FIRMWARE
void parseRecord_APP_TIP(u_int8_t const *&ptr, u_int8_t const *limit)
#define RECORD_TYPE_OFDM_DEBUG
#define RECORD_TYPE_APP_GPS
#define RECORD_TYPE_APP_WARN
int parseRecord_JPEG(u_int8_t const *&ptr, u_int8_t const *limit)
void parseRecord_RC(u_int8_t const *&ptr, u_int8_t const *limit)
#define RECORD_TYPE_CENTER_BATTERY
void parseRecord_APP_SER_WARN(u_int8_t const *&ptr, u_int8_t const *limit)
#define RECORD_TYPE_CUSTOM
void parseRecord_SMART_BATTERY(u_int8_t const *&ptr, u_int8_t const *limit)
void parseRecord_GIMBAL(u_int8_t const *&ptr, u_int8_t const *limit)
virtual void outputOneRow(int outputColumnLabels)
#define RECORD_TYPE_VISION_GROUP
void parseRecord_FIRMWARE(u_int8_t const *&ptr, u_int8_t const *limit)
#define RECORD_TYPE_MC_PARAM
#define RECORD_TYPE_RECOVER
char const * fRecordTypeName[256]
u_int16_t get2BytesBE(u_int8_t const *&ptr, u_int8_t const *limit)
void parseRecord_OSD(u_int8_t const *&ptr, u_int8_t const *limit)