int main(int argc, char **argv) { plan_tests(2); // XModem ok1(UpdateCRC16CCITT("123456789", 9, 0) == 0x31C3); // CCITT ok1(UpdateCRC16CCITT("123456789", 9, 0xFFFF) == 0x29B1); return exit_status(); }
bool Volkslogger::WriteBulk(Port &port, OperationEnvironment &env, const void *buffer, unsigned length) { const unsigned delay = 1; env.SetProgressRange(length); uint16_t crc16 = 0; const uint8_t *p = (const uint8_t *)buffer, *end = p + length; while (p < end) { unsigned n = end - p; if (n > 400) n = 400; n = port.Write(p, n); if (n == 0) return false; crc16 = UpdateCRC16CCITT(p, n, crc16); p += n; env.SetProgressPosition(p - (const uint8_t *)buffer); /* throttle sending a bit, or the Volkslogger's receive buffer will overrun */ env.Sleep(delay * 100); } return port.Write(crc16 >> 8) && port.Write(crc16 & 0xff); }
uint16_t FLARM::CalculateCRC(const FrameHeader &header, const void *data, size_t length) { assert((data != NULL && length > 0) || (data == NULL && length == 0)); uint16_t crc = 0x00; crc = UpdateCRC16CCITT((const uint8_t *)&header, 6, crc); if (length == 0 || data == NULL) return crc; crc = UpdateCRC16CCITT((const uint8_t *)data, length, crc); return crc; }
static bool SendWithCRC(Port &port, const void *data, size_t length, OperationEnvironment &env) { if (!port.FullWrite(data, length, env, 2000)) return false; uint16_t crc16 = UpdateCRC16CCITT(data, length, 0); return port.Write(crc16 >> 8) && port.Write(crc16 & 0xff); }
inline void SkyLinesTracking::Client::OnDatagramReceived(void *data, size_t length) { Header &header = *(Header *)data; if (length < sizeof(header)) return; const uint16_t received_crc = FromBE16(header.crc); header.crc = 0; const uint16_t calculated_crc = UpdateCRC16CCITT(data, length, 0); if (received_crc != calculated_crc) return; const ACKPacket &ack = *(const ACKPacket *)data; const TrafficResponsePacket &traffic = *(const TrafficResponsePacket *)data; const UserNameResponsePacket &user_name = *(const UserNameResponsePacket *)data; const auto &wave = *(const WaveResponsePacket *)data; const auto &thermal = *(const ThermalResponsePacket *)data; switch ((Type)FromBE16(header.type)) { case PING: case FIX: case TRAFFIC_REQUEST: case USER_NAME_REQUEST: case WAVE_SUBMIT: case WAVE_REQUEST: case THERMAL_SUBMIT: case THERMAL_REQUEST: break; case ACK: handler->OnAck(FromBE16(ack.id)); break; case TRAFFIC_RESPONSE: OnTrafficReceived(traffic, length); break; case USER_NAME_RESPONSE: OnUserNameReceived(user_name, length); break; case WAVE_RESPONSE: OnWaveReceived(wave, length); break; case THERMAL_RESPONSE: OnThermalReceived(thermal, length); break; } }
SkyLinesTracking::UserNameRequestPacket SkyLinesTracking::MakeUserNameRequest(uint64_t key, uint32_t user_id) { assert(key != 0); UserNameRequestPacket packet; packet.header.magic = ToBE32(MAGIC); packet.header.crc = 0; packet.header.type = ToBE16(Type::USER_NAME_REQUEST); packet.header.key = ToBE64(key); packet.user_id = ToBE32(user_id); packet.reserved = 0; packet.header.crc = ToBE16(UpdateCRC16CCITT(&packet, sizeof(packet), 0)); return packet; }
SkyLinesTracking::PingPacket SkyLinesTracking::MakePing(uint64_t key, uint16_t id) { assert(key != 0); PingPacket packet; packet.header.magic = ToBE32(MAGIC); packet.header.crc = 0; packet.header.type = ToBE16(Type::PING); packet.header.key = ToBE64(key); packet.id = ToBE16(id); packet.reserved = 0; packet.reserved2 = 0; packet.header.crc = ToBE16(UpdateCRC16CCITT(&packet, sizeof(packet), 0)); return packet; }
bool SkyLinesTracking::Client::SendUserNameRequest(uint32_t user_id) { if (key == 0 || !socket.IsDefined()) return false; UserNameRequestPacket packet; packet.header.magic = ToBE32(MAGIC); packet.header.crc = 0; packet.header.type = ToBE16(Type::USER_NAME_REQUEST); packet.header.key = ToBE64(key); packet.user_id = ToBE32(user_id); packet.reserved = 0; packet.header.crc = ToBE16(UpdateCRC16CCITT(&packet, sizeof(packet), 0)); return socket.Write(&packet, sizeof(packet), address) == sizeof(packet); }
bool SkyLinesTracking::Client::SendTrafficRequest(bool followees, bool club) { if (key == 0 || !socket.IsDefined()) return false; TrafficRequestPacket packet; packet.header.magic = ToBE32(MAGIC); packet.header.crc = 0; packet.header.type = ToBE16(Type::TRAFFIC_REQUEST); packet.header.key = ToBE64(key); packet.flags = ToBE32((followees ? packet.FLAG_FOLLOWEES : 0) | (club ? packet.FLAG_CLUB : 0)); packet.reserved = 0; packet.header.crc = ToBE16(UpdateCRC16CCITT(&packet, sizeof(packet), 0)); return socket.Write(&packet, sizeof(packet), address) == sizeof(packet); }
bool SkyLinesTracking::Client::SendPing(uint16_t id) { if (key == 0 || !socket.IsDefined()) return false; PingPacket packet; packet.header.magic = ToBE32(MAGIC); packet.header.crc = 0; packet.header.type = ToBE16(Type::PING); packet.header.key = ToBE64(key); packet.id = ToBE16(id); packet.reserved = 0; packet.reserved2 = 0; packet.header.crc = ToBE16(UpdateCRC16CCITT(&packet, sizeof(packet), 0)); return socket.Write(&packet, sizeof(packet), address) == sizeof(packet); }
SkyLinesTracking::TrafficRequestPacket SkyLinesTracking::MakeTrafficRequest(uint64_t key, bool followees, bool club, bool near) { assert(key != 0); TrafficRequestPacket packet; packet.header.magic = ToBE32(MAGIC); packet.header.crc = 0; packet.header.type = ToBE16(Type::TRAFFIC_REQUEST); packet.header.key = ToBE64(key); packet.flags = ToBE32((followees ? packet.FLAG_FOLLOWEES : 0) | (club ? packet.FLAG_CLUB : 0) | (near ? packet.FLAG_NEAR : 0)); packet.reserved = 0; packet.header.crc = ToBE16(UpdateCRC16CCITT(&packet, sizeof(packet), 0)); return packet; }
int Volkslogger::ReadBulk(Port &port, OperationEnvironment &env, void *buffer, size_t max_length, unsigned timeout_firstchar_ms) { unsigned nbytes = 0; bool dle_r = false; uint16_t crc16 = 0; bool start = false, ende = false; memset(buffer, 0xff, max_length); uint8_t *p = (uint8_t *)buffer; constexpr unsigned TIMEOUT_NORMAL_MS = 2000; /** * We need to wait longer for the first char to * give the logger time to calculate security * when downloading a log-file. * Therefore timeout_firstchar is configurable. * If the timeout parameter is not specified or 0, * set standard timeout */ if (timeout_firstchar_ms == 0) timeout_firstchar_ms = TIMEOUT_NORMAL_MS; while (!ende) { // Zeichen anfordern und darauf warten if (!port.Write(ACK)) return -1; // Set longer timeout on first char unsigned timeout = start ? TIMEOUT_NORMAL_MS : timeout_firstchar_ms; if (port.WaitRead(env, timeout) != Port::WaitResult::READY) return -1; int ch = port.GetChar(); if (ch < 0) return -1; // dabei ist Benutzerabbruch jederzeit möglich if (env.IsCancelled()) { env.Sleep(10); port.Write(CAN); port.Write(CAN); port.Write(CAN); return -1; } // oder aber das empfangene Zeichen wird ausgewertet switch (ch) { case DLE: if (!dle_r) { //!DLE, DLE -> Achtung! dle_r = true; } else { // DLE, DLE -> DLE-Zeichen dle_r = false; if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } } break; case ETX: if (!dle_r) { //!DLE, ETX -> Zeichen if (start) { if(nbytes < max_length) { *p++ = ch; } nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); }; } else { if (start) { ende = true; // DLE, ETX -> Blockende dle_r = false; } } break; case STX: if (!dle_r) { //!DLE, STX -> Zeichen if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } } else { start = true; // DLE, STX -> Blockstart dle_r = false; crc16 = 0; } break; default: if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } break; } } env.Sleep(100); if (crc16 != 0) return -1; if (nbytes < 2) return 0; // CRC am Ende abschneiden return nbytes - 2; }
bool SkyLinesTracking::Client::SendFix(const NMEAInfo &basic) { assert(basic.time_available); if (key == 0 || !socket.IsDefined()) return false; FixPacket packet; packet.header.magic = ToBE32(MAGIC); packet.header.crc = 0; packet.header.type = ToBE16(Type::FIX); packet.header.key = ToBE64(key); packet.flags = 0; packet.time = ToBE32(uint32_t(basic.time * 1000)); packet.reserved = 0; if (basic.location_available) { packet.flags |= ToBE32(FixPacket::FLAG_LOCATION); ::GeoPoint location = basic.location; location.Normalize(); packet.location.latitude = ToBE32(int(location.latitude.Degrees() * 1000000)); packet.location.longitude = ToBE32(int(location.longitude.Degrees() * 1000000)); } else packet.location.latitude = packet.location.longitude = 0; if (basic.track_available) { packet.flags |= ToBE32(FixPacket::FLAG_TRACK); packet.track = ToBE16(uint16_t(basic.track.AsBearing().Degrees())); } else packet.track = 0; if (basic.ground_speed_available) { packet.flags |= ToBE32(FixPacket::FLAG_GROUND_SPEED); packet.ground_speed = ToBE16(uint16_t(basic.ground_speed * 16)); } else packet.ground_speed = 0; if (basic.airspeed_available) { packet.flags |= ToBE32(FixPacket::FLAG_AIRSPEED); packet.airspeed = ToBE16(uint16_t(basic.indicated_airspeed * 16)); } else packet.airspeed = 0; if (basic.baro_altitude_available) { packet.flags |= ToBE32(FixPacket::FLAG_ALTITUDE); packet.altitude = ToBE16(int(basic.baro_altitude)); } else if (basic.gps_altitude_available) { packet.flags |= ToBE32(FixPacket::FLAG_ALTITUDE); packet.altitude = ToBE16(int(basic.gps_altitude)); } else packet.altitude = 0; if (basic.total_energy_vario_available) { packet.flags |= ToBE32(FixPacket::FLAG_VARIO); packet.vario = ToBE16(int(basic.total_energy_vario * 256)); } else if (basic.netto_vario_available) { packet.flags |= ToBE32(FixPacket::FLAG_VARIO); packet.vario = ToBE16(int(basic.netto_vario * 256)); } else if (basic.noncomp_vario_available) { packet.flags |= ToBE32(FixPacket::FLAG_VARIO); packet.vario = ToBE16(int(basic.noncomp_vario * 256)); } else packet.vario = 0; if (basic.engine_noise_level_available) { packet.flags |= ToBE32(FixPacket::FLAG_ENL); packet.engine_noise_level = ToBE16(basic.engine_noise_level); } else packet.engine_noise_level = 0; packet.header.crc = ToBE16(UpdateCRC16CCITT(&packet, sizeof(packet), 0)); return socket.Write(&packet, sizeof(packet), address) == sizeof(packet); }
inline void Server::OnDatagramReceived(Client &&client, void *data, size_t length) { Header &header = *(Header *)data; if (length < sizeof(header)) return; const uint16_t received_crc = FromBE16(header.crc); header.crc = 0; const uint16_t calculated_crc = UpdateCRC16CCITT(data, length, 0); if (received_crc != calculated_crc) return; client.key = FromBE64(header.key); const auto &ping = *(const PingPacket *)data; const auto &fix = *(const FixPacket *)data; const auto &traffic = *(const TrafficRequestPacket *)data; const auto &user_name = *(const UserNameRequestPacket *)data; const auto &wave = ((const WaveSubmitPacket *)data)->wave; const auto &thermal = ((const ThermalSubmitPacket *)data)->thermal; switch ((Type)FromBE16(header.type)) { case PING: if (length < sizeof(ping)) return; OnPing(client, FromBE16(ping.id)); break; case FIX: if (length < sizeof(fix)) return; OnFix(client, ImportTimeMs(fix.time), fix.flags & ToBE32(FixPacket::FLAG_LOCATION) ? ImportGeoPoint(fix.location) : ::GeoPoint::Invalid(), fix.flags & ToBE32(FixPacket::FLAG_ALTITUDE) ? FromBE16(fix.altitude) : -1); break; case TRAFFIC_REQUEST: if (length < sizeof(traffic)) return; OnTrafficRequest(client, traffic.flags & ToBE32(TrafficRequestPacket::FLAG_NEAR)); break; case USER_NAME_REQUEST: if (length < sizeof(user_name)) return; OnUserNameRequest(client, FromBE32(user_name.user_id)); break; case WAVE_SUBMIT: if (length < sizeof(wave)) return; OnWaveSubmit(client, ImportTimeMs(wave.time), ImportGeoPoint(wave.a), ImportGeoPoint(wave.b), (int16_t)FromBE16(wave.bottom_altitude), (int16_t)FromBE16(wave.top_altitude), FromBE16(wave.lift) / 256.); break; case WAVE_REQUEST: OnWaveRequest(client); break; case THERMAL_SUBMIT: if (length < sizeof(thermal)) return; OnThermalSubmit(client, ImportTimeMs(thermal.time), ImportGeoPoint(thermal.bottom_location), (int16_t)FromBE16(thermal.bottom_altitude), ImportGeoPoint(thermal.top_location), (int16_t)FromBE16(thermal.top_altitude), FromBE16(thermal.lift) / 256.); break; case THERMAL_REQUEST: OnThermalRequest(client); break; case ACK: case TRAFFIC_RESPONSE: case USER_NAME_RESPONSE: case WAVE_RESPONSE: case THERMAL_RESPONSE: /* these are server-to-client packets; ignore them */ break; } }