mirror of
https://github.com/CovidBraceletPrj/CovidBracelet.git
synced 2024-12-04 16:45:43 +01:00
Refactor and Clean Project for essential functionality
This commit is contained in:
parent
ac320271a0
commit
ee4612104d
3
.gitignore
vendored
3
.gitignore
vendored
@ -46,4 +46,5 @@ massif-*
|
|||||||
.pio
|
.pio
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
/.idea
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef BLOOM_H
|
|
||||||
#define BLOOM_H
|
|
||||||
|
|
||||||
#include "ens/storage.h"
|
|
||||||
#include "exposure-notification.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t* data;
|
|
||||||
size_t size;
|
|
||||||
} bloom_filter_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the bloom filter on basis of the already registerred records.
|
|
||||||
*/
|
|
||||||
bloom_filter_t* bloom_init(size_t size);
|
|
||||||
|
|
||||||
void bloom_destroy(bloom_filter_t* bloom);
|
|
||||||
|
|
||||||
// TODO lome: maybe only use RPI (should be sufficient)
|
|
||||||
void bloom_add_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi);
|
|
||||||
|
|
||||||
// TODO lome: maybe only use RPI (should be sufficient)
|
|
||||||
bool bloom_probably_has_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CONTACTS_H
|
|
||||||
#define CONTACTS_H
|
|
||||||
|
|
||||||
#include <zephyr.h>
|
|
||||||
#include <zephyr/types.h>
|
|
||||||
|
|
||||||
#include "covid.h"
|
|
||||||
#include "covid_types.h"
|
|
||||||
#include "ens/storage.h"
|
|
||||||
#include "exposure-notification.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ENIntervalIdentifier interval_identifier;
|
|
||||||
int met;
|
|
||||||
time_t search_start;
|
|
||||||
time_t search_end;
|
|
||||||
} __packed infected_for_interval_ident_ctx_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ENPeriodKey periodKey;
|
|
||||||
time_t start;
|
|
||||||
int met;
|
|
||||||
} __packed period_key_information_t;
|
|
||||||
|
|
||||||
typedef int (*test_func_t)(infected_for_interval_ident_ctx_t* infectedIntervals, int count);
|
|
||||||
|
|
||||||
void print_key(_ENBaseKey* key);
|
|
||||||
void print_rpi(rolling_proximity_identifier_t* rpi);
|
|
||||||
void print_aem(associated_encrypted_metadata_t* aem);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a new record in the system. This includes adding it to the storage and adding it to the bloom filter.
|
|
||||||
*
|
|
||||||
* @param record record to add
|
|
||||||
* @returns 0 in case of success, -ERRNO in case of an error
|
|
||||||
*/
|
|
||||||
int register_record(record_t* record);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the contacts module.
|
|
||||||
*/
|
|
||||||
int init_contacts();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for a list of specified interval identifiers, whether they were probably met or not.
|
|
||||||
* @param ctx list of interval identifiers to check
|
|
||||||
* @param count amount of identifiers to check
|
|
||||||
* @return the amount of met intervals, -ERRNO on error
|
|
||||||
*/
|
|
||||||
int check_possible_contacts_for_intervals(infected_for_interval_ident_ctx_t* ctx, int count);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for a list of specified period keys, whether they were probably met or not.
|
|
||||||
* @param ctx list of period keys and their meta information to check
|
|
||||||
* @param count amount of period keys to check
|
|
||||||
* @return -ERRNO on error, 0 otherwise
|
|
||||||
*/
|
|
||||||
int check_possible_contacts_for_periods(period_key_information_t periodKeyInformation[], int count);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COVID_H
|
|
||||||
#define COVID_H
|
|
||||||
|
|
||||||
#include <zephyr.h>
|
|
||||||
|
|
||||||
#include "exposure-notification.h"
|
|
||||||
|
|
||||||
typedef struct period{
|
|
||||||
ENPeriodKey periodKey;
|
|
||||||
ENIntervalNumber periodInterval;
|
|
||||||
} __packed period_t;
|
|
||||||
|
|
||||||
int init_covid();
|
|
||||||
int do_covid();
|
|
||||||
|
|
||||||
bool get_infection();
|
|
||||||
void set_infection(bool _infected);
|
|
||||||
unsigned int get_period_cnt_if_infected();
|
|
||||||
period_t* get_period_if_infected(unsigned int id, size_t* size);
|
|
||||||
|
|
||||||
int get_index_by_interval(ENIntervalNumber periodInterval);
|
|
||||||
|
|
||||||
|
|
||||||
void print_periods();
|
|
||||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COVID_TYPES_H
|
|
||||||
#define COVID_TYPES_H
|
|
||||||
|
|
||||||
#include <exposure-notification.h>
|
|
||||||
#include <zephyr.h>
|
|
||||||
#include <zephyr/types.h>
|
|
||||||
|
|
||||||
#define COVID_ROLLING_PROXIMITY_IDENTIFIER_LEN 16
|
|
||||||
|
|
||||||
typedef ENIntervalIdentifier rolling_proximity_identifier_t;
|
|
||||||
|
|
||||||
typedef struct bt_metadata {
|
|
||||||
uint8_t version;
|
|
||||||
uint8_t tx_power;
|
|
||||||
uint8_t rsv1;
|
|
||||||
uint8_t rsv2;
|
|
||||||
} __packed bt_metadata_t;
|
|
||||||
|
|
||||||
// typedef struct bt_metadata bt_metadata_t;
|
|
||||||
|
|
||||||
typedef struct associated_encrypted_metadata {
|
|
||||||
uint8_t data[sizeof(bt_metadata_t)];
|
|
||||||
} __packed associated_encrypted_metadata_t;
|
|
||||||
|
|
||||||
typedef uint8_t rssi_t;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,73 +0,0 @@
|
|||||||
#ifndef DISPLAY_H
|
|
||||||
#define DISPLAY_H
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initializes all display elements and adds them to the canvas.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int init_display();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Updates all information on the display using the get functions, defined by `display.c`. Alternatively the
|
|
||||||
* values of the displayed elements can be set explicitly via set `display_set_<property>`-functions.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int update_display();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is the entry point for the display thread. It peridocially updates the display and handles input events.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void display_thread(void*, void*, void*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Displays a message at the bottom of the display. The message will persist until it is removed expicitly, by calling `display_set_message("")`.
|
|
||||||
*
|
|
||||||
* @param msg A pointer to the string that should be displayed
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int display_set_message(char* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets the on display clock. The time should have the format `h * 100 + m`. So `display_set_time(1145)` sets the clock to 11:45.
|
|
||||||
*
|
|
||||||
* @param time A number representation of the time
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int display_set_time(int time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the battery level percentage.
|
|
||||||
*
|
|
||||||
* @param bat The battery level in percent
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int display_set_bat(int bat);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the non-volatile memory state.
|
|
||||||
*
|
|
||||||
* @param mem The occupied memory in percent
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int display_set_mem(int mem);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the number of total registered contacts in the last 14 days.
|
|
||||||
*
|
|
||||||
* @param contacts The number of contacts
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int display_set_contacts(int contacts);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the number of contacts that were tested positively on Covid and registered in the last 14 days.
|
|
||||||
*
|
|
||||||
* @param risk_contacts The number of risk contacts
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int display_set_risk_contacts(int risk_contacts);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,10 +0,0 @@
|
|||||||
#ifndef ENS_ERROR_H
|
|
||||||
#define ENS_ERROR_H
|
|
||||||
|
|
||||||
#define ENS_INTERR 1 // internal error
|
|
||||||
#define ENS_NOENT 2 // entry not found or invalid
|
|
||||||
#define ENS_DELENT 3 // entry got deleted
|
|
||||||
#define ENS_ADDRINU 4 // address alread in use or corrupt
|
|
||||||
#define ENS_INVARG 5 // invalid argument
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2021 Louis Meyer and Patrick Rathje
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ENS_RECORDS_H
|
|
||||||
#define ENS_RECORDS_H
|
|
||||||
|
|
||||||
#include "sequencenumber.h"
|
|
||||||
#include "storage.h"
|
|
||||||
|
|
||||||
typedef struct record_iterator {
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
record_t current;
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
record_sequence_number_t sn_next;
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
record_sequence_number_t sn_end; // the last sn to include
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
uint8_t finished;
|
|
||||||
} record_iterator_t;
|
|
||||||
|
|
||||||
// Also uses start and end from storage if NULL pointers given
|
|
||||||
// iterate over a sequence number range of records (Null will select the latest and newest for start / end)
|
|
||||||
// automatically
|
|
||||||
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
|
||||||
record_sequence_number_t* opt_start,
|
|
||||||
record_sequence_number_t* opt_end);
|
|
||||||
|
|
||||||
// TODO: Do we guarantee that higher sequence numbers have at least our timestamp and lower sequence numbers up to our
|
|
||||||
// timestamp?
|
|
||||||
int ens_records_iterator_init_timerange(record_iterator_t* iterator, time_t* ts_start, time_t* ts_end);
|
|
||||||
|
|
||||||
record_t* ens_records_iterator_next(record_iterator_t* iter);
|
|
||||||
|
|
||||||
int ens_record_iterator_clear(record_iterator_t* iter);
|
|
||||||
|
|
||||||
// TODO: Is a callback the easiest thing to do? -> now it is the iterator :)
|
|
||||||
// TODO: should we really indicated the last record by sending a NULL pointer?
|
|
||||||
typedef uint8_t (*ens_record_iterator_cb_t)(const record_t* record, void* userdata);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ENS_RECORD_ITER_STOP, // STOP the iteration, this would not result in a NULL callback after the end is reached
|
|
||||||
ENS_RECORD_ITER_CONTINUE, // CONTINUE the iteration, this results in a NULL callback after the end is reached
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: this function could be made asynchronous to handle delays in contact_storage reads?!
|
|
||||||
// TODO: How can we handle iteration while records are being added or deleted? (should be safe as long as the
|
|
||||||
// load_record function is thread safe?!)
|
|
||||||
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,80 +0,0 @@
|
|||||||
#ifndef CONTACT_STORAGE_H
|
|
||||||
#define CONTACT_STORAGE_H
|
|
||||||
|
|
||||||
#include <zephyr/types.h>
|
|
||||||
|
|
||||||
#include "covid_types.h"
|
|
||||||
#include "sequencenumber.h"
|
|
||||||
|
|
||||||
typedef uint64_t storage_id_t;
|
|
||||||
|
|
||||||
typedef struct record {
|
|
||||||
record_sequence_number_t sn; // TODO: Convert Sequence Number
|
|
||||||
uint32_t timestamp; // TODO: Seconds from january first 2000 (UTC+0)
|
|
||||||
rssi_t rssi; // TODO: Check correct
|
|
||||||
rolling_proximity_identifier_t rolling_proximity_identifier;
|
|
||||||
associated_encrypted_metadata_t associated_encrypted_metadata;
|
|
||||||
} __packed record_t;
|
|
||||||
|
|
||||||
typedef struct stored_records_information {
|
|
||||||
record_sequence_number_t oldest_contact;
|
|
||||||
uint32_t count;
|
|
||||||
} stored_records_information_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the contact storage component
|
|
||||||
* @param clean flag for indicating, if storage shall be init with clean state
|
|
||||||
*
|
|
||||||
* @return 0 for success
|
|
||||||
*/
|
|
||||||
int init_record_storage(bool clean);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset state of record storage.
|
|
||||||
*/
|
|
||||||
void reset_record_storage();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the record with number sn into the destination struct
|
|
||||||
* @param dest
|
|
||||||
* @param sn
|
|
||||||
* @return 0 in case of success
|
|
||||||
*/
|
|
||||||
int load_record(record_t* dest, record_sequence_number_t sn);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the record from src with number sn, increases latest sequence number
|
|
||||||
* @param sn
|
|
||||||
* @param src
|
|
||||||
* @return 0 in case of success
|
|
||||||
*/
|
|
||||||
int add_record(record_t* src);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the record from storage with number sn
|
|
||||||
* @param sn the sequence number to delete
|
|
||||||
* @return 0 in case of success
|
|
||||||
*/
|
|
||||||
int delete_record(record_sequence_number_t sn);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: How to handle if none is available?
|
|
||||||
* @return The latest available sequence number (Caution: can actually be lower than the oldes in case of a
|
|
||||||
* wrap-around!)
|
|
||||||
*/
|
|
||||||
record_sequence_number_t get_latest_sequence_number();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: How to handle if none is available?
|
|
||||||
* @return The oldest available sequence number
|
|
||||||
*/
|
|
||||||
record_sequence_number_t get_oldest_sequence_number();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The amount of contacts, usually get_latest_sequence_number() - get_oldest_sequence_number()
|
|
||||||
*/
|
|
||||||
uint32_t get_num_records();
|
|
||||||
|
|
||||||
int get_sequence_number_interval(record_sequence_number_t* oldest, record_sequence_number_t* latest);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,355 +0,0 @@
|
|||||||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
|
||||||
/* Generated from: export.proto */
|
|
||||||
|
|
||||||
#ifndef PROTOBUF_C_export_2eproto__INCLUDED
|
|
||||||
#define PROTOBUF_C_export_2eproto__INCLUDED
|
|
||||||
|
|
||||||
#include <protobuf-c.h>
|
|
||||||
|
|
||||||
PROTOBUF_C__BEGIN_DECLS
|
|
||||||
|
|
||||||
#if PROTOBUF_C_VERSION_NUMBER < 1000000
|
|
||||||
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
|
|
||||||
#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION
|
|
||||||
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct TemporaryExposureKeyExport TemporaryExposureKeyExport;
|
|
||||||
typedef struct SignatureInfo SignatureInfo;
|
|
||||||
typedef struct TemporaryExposureKey TemporaryExposureKey;
|
|
||||||
typedef struct TEKSignatureList TEKSignatureList;
|
|
||||||
typedef struct TEKSignature TEKSignature;
|
|
||||||
|
|
||||||
|
|
||||||
/* --- enums --- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Data type representing why this key was published.
|
|
||||||
*/
|
|
||||||
typedef enum _TemporaryExposureKey__ReportType {
|
|
||||||
/*
|
|
||||||
* Never returned by the client API.
|
|
||||||
*/
|
|
||||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__UNKNOWN = 0,
|
|
||||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_TEST = 1,
|
|
||||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_CLINICAL_DIAGNOSIS = 2,
|
|
||||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__SELF_REPORT = 3,
|
|
||||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__RECURSIVE = 4,
|
|
||||||
/*
|
|
||||||
* Used to revoke a key, never returned by client API.
|
|
||||||
*/
|
|
||||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__REVOKED = 5
|
|
||||||
PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(TEMPORARY_EXPOSURE_KEY__REPORT_TYPE)
|
|
||||||
} TemporaryExposureKey__ReportType;
|
|
||||||
|
|
||||||
/* --- messages --- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Protobuf definition for exports of confirmed temporary exposure keys.
|
|
||||||
* The full file format is documented under "Exposure Key Export File Format
|
|
||||||
* and Verification" at https://www.google.com/covid19/exposurenotifications/
|
|
||||||
* These files have a 16-byte, space-padded header before the protobuf data
|
|
||||||
* starts. They will be contained in a zip archive, alongside a signature
|
|
||||||
* file verifying the contents.
|
|
||||||
*/
|
|
||||||
struct TemporaryExposureKeyExport
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
/*
|
|
||||||
* Time window of keys in this file based on arrival to server, in UTC
|
|
||||||
* seconds. start_timestamp, end_timestamp, and batch_num must be unique
|
|
||||||
* at any given snapshot of the index for a server. If multiple
|
|
||||||
* files are used for a specific time period, and batch_num/batch_size
|
|
||||||
* are both 1 (See below), then offsetting the end_timestamp is the
|
|
||||||
* suggested method for forcing uniqueness.
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_start_timestamp;
|
|
||||||
uint64_t start_timestamp;
|
|
||||||
protobuf_c_boolean has_end_timestamp;
|
|
||||||
uint64_t end_timestamp;
|
|
||||||
/*
|
|
||||||
* Region for which these keys came from (e.g., country)
|
|
||||||
*/
|
|
||||||
char *region;
|
|
||||||
/*
|
|
||||||
* E.g., Batch 2 of 10. Ordinal, 1-based numbering.
|
|
||||||
* Note: Not yet supported on iOS. Use values of 1 for both.
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_batch_num;
|
|
||||||
int32_t batch_num;
|
|
||||||
protobuf_c_boolean has_batch_size;
|
|
||||||
int32_t batch_size;
|
|
||||||
/*
|
|
||||||
* Information about signatures
|
|
||||||
* If there are multiple entries, they must be ordered in descending
|
|
||||||
* time order by signing key effective time (most recent one first).
|
|
||||||
* There is a limit of 10 signature infos per export file (mobile OS may
|
|
||||||
* not check anything after that).
|
|
||||||
*/
|
|
||||||
size_t n_signature_infos;
|
|
||||||
SignatureInfo **signature_infos;
|
|
||||||
/*
|
|
||||||
* The TemporaryExposureKeys for initial release of keys.
|
|
||||||
* Keys should be included in this list for initial release,
|
|
||||||
* whereas revised or revoked keys should go in revised_keys.
|
|
||||||
*/
|
|
||||||
size_t n_keys;
|
|
||||||
TemporaryExposureKey **keys;
|
|
||||||
/*
|
|
||||||
* TemporaryExposureKeys that have changed status.
|
|
||||||
* Keys should be included in this list if they have changed status
|
|
||||||
* or have been revoked.
|
|
||||||
*/
|
|
||||||
size_t n_revised_keys;
|
|
||||||
TemporaryExposureKey **revised_keys;
|
|
||||||
};
|
|
||||||
#define TEMPORARY_EXPOSURE_KEY_EXPORT__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&temporary_exposure_key_export__descriptor) \
|
|
||||||
, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0,NULL, 0,NULL, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct SignatureInfo
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
/*
|
|
||||||
* Key version for rollovers
|
|
||||||
* Must be in character class [a-zA-Z0-9_]. E.g., 'v1'
|
|
||||||
*/
|
|
||||||
char *verification_key_version;
|
|
||||||
/*
|
|
||||||
* Alias with which to identify public key to be used for verification
|
|
||||||
* Must be in character class [a-zA-Z0-9_]
|
|
||||||
* For cross-compatibility with Apple, use MCC
|
|
||||||
* (https://en.wikipedia.org/wiki/Mobile_country_code).
|
|
||||||
*/
|
|
||||||
char *verification_key_id;
|
|
||||||
/*
|
|
||||||
* ASN.1 OID for Algorithm Identifier. Supported algorithms are
|
|
||||||
* either 1.2.840.10045.4.3.2 or 1.2.840.10045.4.3.4
|
|
||||||
*/
|
|
||||||
char *signature_algorithm;
|
|
||||||
};
|
|
||||||
#define SIGNATURE_INFO__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&signature_info__descriptor) \
|
|
||||||
, NULL, NULL, NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct TemporaryExposureKey
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
/*
|
|
||||||
* Key of infected user
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_key_data;
|
|
||||||
ProtobufCBinaryData key_data;
|
|
||||||
/*
|
|
||||||
* Varying risks associated with exposure depending on type of verification
|
|
||||||
* Ignored by the v1.5 client API when report_type is set.
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_transmission_risk_level PROTOBUF_C__DEPRECATED;
|
|
||||||
int32_t transmission_risk_level PROTOBUF_C__DEPRECATED;
|
|
||||||
/*
|
|
||||||
* The interval number since epoch for which a key starts
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_rolling_start_interval_number;
|
|
||||||
int32_t rolling_start_interval_number;
|
|
||||||
/*
|
|
||||||
* Increments of 10 minutes describing how long a key is valid
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* defaults to 24 hours
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_rolling_period;
|
|
||||||
int32_t rolling_period;
|
|
||||||
/*
|
|
||||||
* Type of diagnosis associated with a key.
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_report_type;
|
|
||||||
TemporaryExposureKey__ReportType report_type;
|
|
||||||
/*
|
|
||||||
* Number of days elapsed between symptom onset and the TEK being used.
|
|
||||||
* E.g. 2 means TEK is 2 days after onset of symptoms.
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_days_since_onset_of_symptoms;
|
|
||||||
int32_t days_since_onset_of_symptoms;
|
|
||||||
};
|
|
||||||
#define TEMPORARY_EXPOSURE_KEY__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&temporary_exposure_key__descriptor) \
|
|
||||||
, 0, {0,NULL}, 0, 0, 0, 0, 0, 144, 0, TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__UNKNOWN, 0, 0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct TEKSignatureList
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
/*
|
|
||||||
* When there are multiple signatures, they must be sorted in time order
|
|
||||||
* by first effective date for the signing key in descending order.
|
|
||||||
* The most recent effective signing key must appear first.
|
|
||||||
* There is a limit of 10 signature infos per export file (mobile OS may
|
|
||||||
* not check anything after that).
|
|
||||||
*/
|
|
||||||
size_t n_signatures;
|
|
||||||
TEKSignature **signatures;
|
|
||||||
};
|
|
||||||
#define TEKSIGNATURE_LIST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&teksignature_list__descriptor) \
|
|
||||||
, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct TEKSignature
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
/*
|
|
||||||
* Info about the signing key, version, algorithm, etc.
|
|
||||||
*/
|
|
||||||
SignatureInfo *signature_info;
|
|
||||||
/*
|
|
||||||
* E.g., Batch 2 of 10
|
|
||||||
* Must match fields from TemporaryExposureKeyExport, see
|
|
||||||
* documentation on that message.
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_batch_num;
|
|
||||||
int32_t batch_num;
|
|
||||||
protobuf_c_boolean has_batch_size;
|
|
||||||
int32_t batch_size;
|
|
||||||
/*
|
|
||||||
* Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
|
|
||||||
*/
|
|
||||||
protobuf_c_boolean has_signature;
|
|
||||||
ProtobufCBinaryData signature;
|
|
||||||
};
|
|
||||||
#define TEKSIGNATURE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&teksignature__descriptor) \
|
|
||||||
, NULL, 0, 0, 0, 0, 0, {0,NULL} }
|
|
||||||
|
|
||||||
|
|
||||||
/* TemporaryExposureKeyExport methods */
|
|
||||||
void temporary_exposure_key_export__init
|
|
||||||
(TemporaryExposureKeyExport *message);
|
|
||||||
size_t temporary_exposure_key_export__get_packed_size
|
|
||||||
(const TemporaryExposureKeyExport *message);
|
|
||||||
size_t temporary_exposure_key_export__pack
|
|
||||||
(const TemporaryExposureKeyExport *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t temporary_exposure_key_export__pack_to_buffer
|
|
||||||
(const TemporaryExposureKeyExport *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
TemporaryExposureKeyExport *
|
|
||||||
temporary_exposure_key_export__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void temporary_exposure_key_export__free_unpacked
|
|
||||||
(TemporaryExposureKeyExport *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* SignatureInfo methods */
|
|
||||||
void signature_info__init
|
|
||||||
(SignatureInfo *message);
|
|
||||||
size_t signature_info__get_packed_size
|
|
||||||
(const SignatureInfo *message);
|
|
||||||
size_t signature_info__pack
|
|
||||||
(const SignatureInfo *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t signature_info__pack_to_buffer
|
|
||||||
(const SignatureInfo *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
SignatureInfo *
|
|
||||||
signature_info__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void signature_info__free_unpacked
|
|
||||||
(SignatureInfo *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* TemporaryExposureKey methods */
|
|
||||||
void temporary_exposure_key__init
|
|
||||||
(TemporaryExposureKey *message);
|
|
||||||
size_t temporary_exposure_key__get_packed_size
|
|
||||||
(const TemporaryExposureKey *message);
|
|
||||||
size_t temporary_exposure_key__pack
|
|
||||||
(const TemporaryExposureKey *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t temporary_exposure_key__pack_to_buffer
|
|
||||||
(const TemporaryExposureKey *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
TemporaryExposureKey *
|
|
||||||
temporary_exposure_key__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void temporary_exposure_key__free_unpacked
|
|
||||||
(TemporaryExposureKey *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* TEKSignatureList methods */
|
|
||||||
void teksignature_list__init
|
|
||||||
(TEKSignatureList *message);
|
|
||||||
size_t teksignature_list__get_packed_size
|
|
||||||
(const TEKSignatureList *message);
|
|
||||||
size_t teksignature_list__pack
|
|
||||||
(const TEKSignatureList *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t teksignature_list__pack_to_buffer
|
|
||||||
(const TEKSignatureList *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
TEKSignatureList *
|
|
||||||
teksignature_list__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void teksignature_list__free_unpacked
|
|
||||||
(TEKSignatureList *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* TEKSignature methods */
|
|
||||||
void teksignature__init
|
|
||||||
(TEKSignature *message);
|
|
||||||
size_t teksignature__get_packed_size
|
|
||||||
(const TEKSignature *message);
|
|
||||||
size_t teksignature__pack
|
|
||||||
(const TEKSignature *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t teksignature__pack_to_buffer
|
|
||||||
(const TEKSignature *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
TEKSignature *
|
|
||||||
teksignature__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void teksignature__free_unpacked
|
|
||||||
(TEKSignature *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* --- per-message closures --- */
|
|
||||||
|
|
||||||
typedef void (*TemporaryExposureKeyExport_Closure)
|
|
||||||
(const TemporaryExposureKeyExport *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*SignatureInfo_Closure)
|
|
||||||
(const SignatureInfo *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*TemporaryExposureKey_Closure)
|
|
||||||
(const TemporaryExposureKey *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*TEKSignatureList_Closure)
|
|
||||||
(const TEKSignatureList *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*TEKSignature_Closure)
|
|
||||||
(const TEKSignature *message,
|
|
||||||
void *closure_data);
|
|
||||||
|
|
||||||
/* --- services --- */
|
|
||||||
|
|
||||||
|
|
||||||
/* --- descriptors --- */
|
|
||||||
|
|
||||||
extern const ProtobufCMessageDescriptor temporary_exposure_key_export__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor signature_info__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor temporary_exposure_key__descriptor;
|
|
||||||
extern const ProtobufCEnumDescriptor temporary_exposure_key__report_type__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor teksignature_list__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor teksignature__descriptor;
|
|
||||||
|
|
||||||
PROTOBUF_C__END_DECLS
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* PROTOBUF_C_export_2eproto__INCLUDED */
|
|
@ -1,41 +0,0 @@
|
|||||||
#ifndef EXTRACT_KEYS_H
|
|
||||||
#define EXTRACT_KEYS_H
|
|
||||||
|
|
||||||
#include "export.pb-c.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Process a key. This function could trigger the comparision between the key and those registered by the ENS.
|
|
||||||
*
|
|
||||||
* @param key A pointer to the Exposure key data structure
|
|
||||||
*/
|
|
||||||
void process_key(TemporaryExposureKey* key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generates a protocol buffer containing dummy keys.
|
|
||||||
*
|
|
||||||
* @param buffer_pointer A pointer to the pointer which will be used to reference the buffer externally. This will be
|
|
||||||
* set to the memory area allocated to store the protocol buffer.
|
|
||||||
* @param num_keys The number of keys that will be generated
|
|
||||||
* @return size_t The size of the protocol buffer
|
|
||||||
*/
|
|
||||||
size_t generate_keys(uint8_t** buffer_pointer, int num_keys);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unpacks the protocol buffer and iterates the `process_key` function over all keys.
|
|
||||||
*
|
|
||||||
* @param buf a pointer to the buffer
|
|
||||||
* @param buf_size the size of the buffer in bytes
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int unpack_keys(uint8_t* buf, size_t buf_size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generates an protocol buffer with a specified number of keys and measures the time to execute `unpack_keys`,
|
|
||||||
* which unpacks the protocol buffer and iterates `process_key` over the keys.
|
|
||||||
*
|
|
||||||
* @param num_keys the number of keys that will be created
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int test_unpacking(int num_keys);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GATT_SERVICE_H
|
|
||||||
#define GATT_SERVICE_H
|
|
||||||
|
|
||||||
int init_gatt(void);
|
|
||||||
int do_gatt(void);
|
|
||||||
|
|
||||||
#endif
|
|
151
include/record_storage.h
Normal file
151
include/record_storage.h
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Olaf Landsiedel
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef RECORD_STORAGE_H
|
||||||
|
#define RECORD_STORAGE_H
|
||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include "utility/sequencenumber.h"
|
||||||
|
#include <exposure-notification.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RECORD STORAGE
|
||||||
|
*/
|
||||||
|
typedef uint64_t storage_id_t;
|
||||||
|
|
||||||
|
typedef struct bt_metadata {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t tx_power;
|
||||||
|
uint8_t rsv1;
|
||||||
|
uint8_t rsv2;
|
||||||
|
} __packed bt_metadata_t;
|
||||||
|
|
||||||
|
typedef struct associated_encrypted_metadata {
|
||||||
|
uint8_t data[sizeof(bt_metadata_t)];
|
||||||
|
} __packed associated_encrypted_metadata_t;
|
||||||
|
|
||||||
|
typedef struct record {
|
||||||
|
record_sequence_number_t sn; // TODO: Convert Sequence Number
|
||||||
|
uint32_t timestamp; // TODO: Seconds from january first 2000 (UTC+0)
|
||||||
|
uint8_t rssi; // TODO: Check correct
|
||||||
|
ENIntervalIdentifier rolling_proximity_identifier;
|
||||||
|
associated_encrypted_metadata_t associated_encrypted_metadata;
|
||||||
|
} __packed record_t;
|
||||||
|
|
||||||
|
typedef struct stored_records_information {
|
||||||
|
record_sequence_number_t oldest_contact;
|
||||||
|
uint32_t count;
|
||||||
|
} stored_records_information_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the contact storage component
|
||||||
|
* @param clean flag for indicating, if storage shall be init with clean state
|
||||||
|
*
|
||||||
|
* @return 0 for success
|
||||||
|
*/
|
||||||
|
int record_storage_init(bool clean);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset state of record storage.
|
||||||
|
*/
|
||||||
|
void reset_record_storage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the record with number sn into the destination struct
|
||||||
|
* @param dest
|
||||||
|
* @param sn
|
||||||
|
* @return 0 in case of success
|
||||||
|
*/
|
||||||
|
int load_record(record_t* dest, record_sequence_number_t sn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the record from src with number sn, increases latest sequence number
|
||||||
|
* @param sn
|
||||||
|
* @param src
|
||||||
|
* @return 0 in case of success
|
||||||
|
*/
|
||||||
|
int add_record(record_t* src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the record from storage with number sn
|
||||||
|
* @param sn the sequence number to delete
|
||||||
|
* @return 0 in case of success
|
||||||
|
*/
|
||||||
|
int delete_record(record_sequence_number_t sn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: How to handle if none is available?
|
||||||
|
* @return The latest available sequence number (Caution: can actually be lower than the oldes in case of a
|
||||||
|
* wrap-around!)
|
||||||
|
*/
|
||||||
|
record_sequence_number_t get_latest_sequence_number();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: How to handle if none is available?
|
||||||
|
* @return The oldest available sequence number
|
||||||
|
*/
|
||||||
|
record_sequence_number_t get_oldest_sequence_number();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The amount of contacts, usually get_latest_sequence_number() - get_oldest_sequence_number()
|
||||||
|
*/
|
||||||
|
uint32_t get_num_records();
|
||||||
|
|
||||||
|
int get_sequence_number_interval(record_sequence_number_t* oldest, record_sequence_number_t* latest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RECORD ITERATOR
|
||||||
|
*/
|
||||||
|
typedef struct record_iterator {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
record_t current;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
record_sequence_number_t sn_next;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
record_sequence_number_t sn_end; // the last sn to include
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
uint8_t finished;
|
||||||
|
} record_iterator_t;
|
||||||
|
|
||||||
|
// Also uses start and end from storage if NULL pointers given
|
||||||
|
// iterate over a sequence number range of records (Null will select the latest and newest for start / end)
|
||||||
|
// automatically
|
||||||
|
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
||||||
|
record_sequence_number_t* opt_start,
|
||||||
|
record_sequence_number_t* opt_end);
|
||||||
|
|
||||||
|
// TODO: Do we guarantee that higher sequence numbers have at least our timestamp and lower sequence numbers up to our
|
||||||
|
// timestamp?
|
||||||
|
int ens_records_iterator_init_timerange(record_iterator_t* iterator, time_t* ts_start, time_t* ts_end);
|
||||||
|
|
||||||
|
record_t* ens_records_iterator_next(record_iterator_t* iter);
|
||||||
|
|
||||||
|
int ens_record_iterator_clear(record_iterator_t* iter);
|
||||||
|
|
||||||
|
// TODO: Is a callback the easiest thing to do? -> now it is the iterator :)
|
||||||
|
// TODO: should we really indicated the last record by sending a NULL pointer?
|
||||||
|
typedef uint8_t (*ens_record_iterator_cb_t)(const record_t* record, void* userdata);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ENS_RECORD_ITER_STOP, // STOP the iteration, this would not result in a NULL callback after the end is reached
|
||||||
|
ENS_RECORD_ITER_CONTINUE, // CONTINUE the iteration, this results in a NULL callback after the end is reached
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: this function could be made asynchronous to handle delays in contact_storage reads?!
|
||||||
|
// TODO: How can we handle iteration while records are being added or deleted? (should be safe as long as the
|
||||||
|
// load_record function is thread safe?!)
|
||||||
|
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata);
|
||||||
|
|
||||||
|
#endif
|
13
include/sync_service.h
Normal file
13
include/sync_service.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Olaf Landsiedel
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SYNC_SERVICE_H
|
||||||
|
#define SYNC_SERVICE_H
|
||||||
|
|
||||||
|
int sync_service_init(void);
|
||||||
|
int sync_service_run(void);
|
||||||
|
|
||||||
|
#endif
|
35
include/tek_storage.h
Normal file
35
include/tek_storage.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Olaf Landsiedel
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef tek_storage_H
|
||||||
|
#define tek_storage_H
|
||||||
|
|
||||||
|
#include <exposure-notification.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include "utility/sequencenumber.h"
|
||||||
|
#include "record_storage.h"
|
||||||
|
|
||||||
|
typedef struct tek {
|
||||||
|
uint32_t timestamp; // Seconds from january first 2000 (UTC+0)
|
||||||
|
ENPeriodKey tek; // the temporary exposure key
|
||||||
|
} __packed tek_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the contact storage component
|
||||||
|
* @param clean flag for indicating, if storage shall be init with clean state
|
||||||
|
*
|
||||||
|
* @return 0 for success
|
||||||
|
*/
|
||||||
|
int tek_storage_init(bool clean);
|
||||||
|
|
||||||
|
int tek_storage_add(tek_t* src);
|
||||||
|
int tek_storage_delete(tek_t* src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 0 on success, else non zero (if none available)
|
||||||
|
*/
|
||||||
|
int tek_storage_get_latest_at_ts(tek_t* dest, uint32_t timestamp);
|
||||||
|
|
||||||
|
#endif
|
@ -1,14 +1,13 @@
|
|||||||
/* io.h - Application main entry point */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
* Copyright (c) 2020 Olaf Landsiedel
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef IO_H
|
#ifndef TRACING_H
|
||||||
#define IO_H
|
#define TRACING_H
|
||||||
|
|
||||||
int init_io();
|
int tracing_init(void);
|
||||||
|
int tracing_run(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef UTIL_H
|
|
||||||
#define UTIL_H
|
|
||||||
|
|
||||||
// TODO: We should use timeutil_sync
|
|
||||||
|
|
||||||
// return the current unix timestamp in seconds
|
|
||||||
uint32_t time_get_unix_seconds();
|
|
||||||
|
|
||||||
#endif // UTIL_H
|
|
@ -7,6 +7,12 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <storage/flash_map.h>
|
#include <storage/flash_map.h>
|
||||||
|
|
||||||
|
#define ENS_INTERR 1 // internal error
|
||||||
|
#define ENS_NOENT 2 // entry not found or invalid
|
||||||
|
#define ENS_DELENT 3 // entry got deleted
|
||||||
|
#define ENS_ADDRINU 4 // address alread in use or corrupt
|
||||||
|
#define ENS_INVARG 5 // invalid argument
|
||||||
|
|
||||||
typedef struct ens_fs {
|
typedef struct ens_fs {
|
||||||
/**
|
/**
|
||||||
* Flash area for this file system.
|
* Flash area for this file system.
|
16
include/utility/util.h
Normal file
16
include/utility/util.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef UTIL_H
|
||||||
|
#define UTIL_H
|
||||||
|
|
||||||
|
#include <exposure-notification.h>
|
||||||
|
#include "../record_storage.h" // TODO: this dependency is not great...
|
||||||
|
|
||||||
|
// TODO: We should use timeutil_sync
|
||||||
|
|
||||||
|
// return the current unix timestamp in seconds
|
||||||
|
uint32_t time_get_unix_seconds();
|
||||||
|
|
||||||
|
void print_key(_ENBaseKey* key);
|
||||||
|
void print_rpi(ENIntervalIdentifier* rpi);
|
||||||
|
void print_aem(associated_encrypted_metadata_t* aem);
|
||||||
|
|
||||||
|
#endif // UTIL_H
|
@ -16,7 +16,7 @@ platform = nordicnrf52@7.0.0
|
|||||||
board = nrf52840_dk
|
board = nrf52840_dk
|
||||||
framework = zephyr
|
framework = zephyr
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_protocol = jlink
|
;upload_protocol = jlink
|
||||||
test_ignore = test_desktop
|
test_ignore = test_desktop
|
||||||
build_flags =
|
build_flags =
|
||||||
-Iinclude/tls_config
|
-Iinclude/tls_config
|
||||||
@ -28,12 +28,12 @@ lib_deps =
|
|||||||
prathje/exposure-notification @ ^0.1
|
prathje/exposure-notification @ ^0.1
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
mbedtls
|
mbedtls
|
||||||
src_filter = -<../src/main_test.c>
|
;src_filter = -<../src/main_test.c>
|
||||||
|
|
||||||
[env:nrf52840_dk_test]
|
;[env:nrf52840_dk_test]
|
||||||
src_filter = -<../src/main.c>
|
;src_filter = -<../src/main.c>
|
||||||
extends = env:nrf52840_dk
|
;extends = env:nrf52840_dk
|
||||||
board = nrf52840_mdk
|
;board = nrf52840_mdk
|
||||||
|
|
||||||
|
|
||||||
[env:nrf52840_mdk]
|
[env:nrf52840_mdk]
|
||||||
|
46
src/bloom.c
46
src/bloom.c
@ -1,46 +0,0 @@
|
|||||||
#include "bloom.h"
|
|
||||||
#include "ens/storage.h"
|
|
||||||
#include "exposure-notification.h"
|
|
||||||
|
|
||||||
bloom_filter_t* bloom_init(size_t size) {
|
|
||||||
bloom_filter_t* bloom = k_calloc(1, sizeof(bloom_filter_t));
|
|
||||||
if (!bloom) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
bloom->size = size;
|
|
||||||
bloom->data = k_calloc(size, sizeof(uint8_t));
|
|
||||||
if (!bloom->data) {
|
|
||||||
bloom->size = 0;
|
|
||||||
k_free(bloom);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return bloom;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bloom_destroy(bloom_filter_t* bloom) {
|
|
||||||
if (bloom) {
|
|
||||||
k_free(bloom->data);
|
|
||||||
k_free(bloom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bloom_add_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi) {
|
|
||||||
uint8_t* data = bloom->data;
|
|
||||||
for (int i = 0; i < sizeof(*rpi); i += 2) {
|
|
||||||
uint32_t hash = (rpi->b[i] << 8) | rpi->b[i + 1];
|
|
||||||
hash %= bloom->size * 8;
|
|
||||||
data[hash / 8] |= 1 << (hash % 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bloom_probably_has_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi) {
|
|
||||||
uint8_t* data = bloom->data;
|
|
||||||
for (int i = 0; i < sizeof(*rpi); i += 2) {
|
|
||||||
uint32_t hash = (rpi->b[i] << 8) | rpi->b[i + 1];
|
|
||||||
hash %= bloom->size * 8;
|
|
||||||
if (!(data[hash / 8] & (1 << (hash % 8)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
328
src/contacts.c
328
src/contacts.c
@ -1,328 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <sys/util.h>
|
|
||||||
#include <timing/timing.h>
|
|
||||||
#include <zephyr.h>
|
|
||||||
#include <zephyr/types.h>
|
|
||||||
|
|
||||||
#include <bluetooth/bluetooth.h>
|
|
||||||
#include <bluetooth/hci.h>
|
|
||||||
|
|
||||||
#include <device.h>
|
|
||||||
#include <devicetree.h>
|
|
||||||
#include <drivers/gpio.h>
|
|
||||||
|
|
||||||
#include "bloom.h"
|
|
||||||
#include "contacts.h"
|
|
||||||
#include "covid.h"
|
|
||||||
#include "covid_types.h"
|
|
||||||
#include "ens/records.h"
|
|
||||||
#include "ens/storage.h"
|
|
||||||
#include "exposure-notification.h"
|
|
||||||
|
|
||||||
// #define CONFIG_INTERVAL_SPREAD 100
|
|
||||||
|
|
||||||
void print_key(_ENBaseKey* key) {
|
|
||||||
for (int i = 0; i < sizeof(key->b); i++) {
|
|
||||||
printk("%02x", key->b[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_rpi(rolling_proximity_identifier_t* rpi) {
|
|
||||||
for (int i = 0; i < sizeof(rolling_proximity_identifier_t); i++) {
|
|
||||||
printk("%02x", rpi->b[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_aem(associated_encrypted_metadata_t* aem) {
|
|
||||||
for (int i = 0; i < sizeof(associated_encrypted_metadata_t); i++) {
|
|
||||||
printk("%02x", aem->data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int register_record(record_t* record) {
|
|
||||||
return add_record(record);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple implementation, where an iterator is created for every element in the passed arrray.
|
|
||||||
*/
|
|
||||||
int get_number_of_infected_for_multiple_intervals_simple(infected_for_interval_ident_ctx_t* ctx, int count) {
|
|
||||||
record_iterator_t iterator;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (!ctx[i].met) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ctx[i].met = 0;
|
|
||||||
int rc = ens_records_iterator_init_timerange(&iterator, &ctx[i].search_start, &ctx[i].search_end);
|
|
||||||
if (rc) {
|
|
||||||
// on error, skip this rpi
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
record_t* current;
|
|
||||||
while ((current = ens_records_iterator_next(&iterator))) {
|
|
||||||
if (memcmp(&(current->rolling_proximity_identifier), &ctx[i].interval_identifier,
|
|
||||||
sizeof(rolling_proximity_identifier_t)) == 0) {
|
|
||||||
ctx[i].met++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill the bloom filter with all stored records.
|
|
||||||
*/
|
|
||||||
void fill_bloom_with_stored_records(bloom_filter_t* bloom) {
|
|
||||||
// init iterator for filling bloom filter
|
|
||||||
record_iterator_t iterator;
|
|
||||||
int rc = ens_records_iterator_init_timerange(&iterator, NULL, NULL);
|
|
||||||
if (rc) {
|
|
||||||
printk("init iterator failed0 (err %d)\n", rc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill bloom filter with records
|
|
||||||
record_t* current;
|
|
||||||
while ((current = ens_records_iterator_next(&iterator))) {
|
|
||||||
bloom_add_record(bloom, &(current->rolling_proximity_identifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill the bloom filter with flash records and test passed RPIs against it.
|
|
||||||
*/
|
|
||||||
int64_t bloom_filter(infected_for_interval_ident_ctx_t* ctx, int count) {
|
|
||||||
bloom_filter_t* bloom = bloom_init(get_num_records() * 2);
|
|
||||||
if (!bloom) {
|
|
||||||
printk("bloom init failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fill_bloom_with_stored_records(bloom);
|
|
||||||
|
|
||||||
// test bloom performance
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (bloom_probably_has_record(bloom, &ctx[i].interval_identifier)) {
|
|
||||||
ctx[i].met++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bloom_destroy(bloom);
|
|
||||||
|
|
||||||
return get_number_of_infected_for_multiple_intervals_simple(ctx, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
// FILL TEST DATA //
|
|
||||||
////////////////////
|
|
||||||
|
|
||||||
static ENPeriodKey infectedPeriodKey = {
|
|
||||||
.b = {0x75, 0xc7, 0x34, 0xc6, 0xdd, 0x1a, 0x78, 0x2d, 0xe7, 0xa9, 0x65, 0xda, 0x5e, 0xb9, 0x31, 0x25}};
|
|
||||||
static ENPeriodKey dummyPeriodKey = {
|
|
||||||
.b = {0x89, 0xa7, 0x34, 0xc6, 0xdd, 0x1a, 0x14, 0xda, 0xe7, 0x00, 0x65, 0xda, 0x6a, 0x9b, 0x13, 0x52}};
|
|
||||||
static ENPeriodKey testKey = {
|
|
||||||
.b = {0x89, 0xa7, 0x72, 0xc6, 0xdd, 0x10, 0x14, 0xda, 0xe7, 0x00, 0x65, 0xda, 0x8a, 0x9b, 0x13, 0x52}};
|
|
||||||
|
|
||||||
static ENPeriodIdentifierKey infectedPik;
|
|
||||||
static ENPeriodIdentifierKey dummyPik;
|
|
||||||
static ENPeriodIdentifierKey testPik;
|
|
||||||
|
|
||||||
void fill_test_rki_data(infected_for_interval_ident_ctx_t* infectedIntervals, int count) {
|
|
||||||
int totalTime = EN_TEK_ROLLING_PERIOD * EN_INTERVAL_LENGTH;
|
|
||||||
int stepSize = totalTime / count;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
int intervalNumber = (i * stepSize) / EN_INTERVAL_LENGTH;
|
|
||||||
en_derive_interval_identifier(&infectedIntervals[i].interval_identifier, &infectedPik, intervalNumber);
|
|
||||||
infectedIntervals[i].met = 0;
|
|
||||||
infectedIntervals[i].search_start = i < 3 ? 0 : (i - 2) * stepSize;
|
|
||||||
infectedIntervals[i].search_end = (i + 2) * stepSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
// MEASURING FUNC //
|
|
||||||
////////////////////
|
|
||||||
|
|
||||||
void measure_perf(infected_for_interval_ident_ctx_t testIntervals[], int count) {
|
|
||||||
const char* label = "bloom filter";
|
|
||||||
printk("---------------------------\n'%s': starting measurement\n", label);
|
|
||||||
|
|
||||||
// fill_test_rki_data(infectedIntervals, count);
|
|
||||||
|
|
||||||
// setup our ordered array with met RPIs
|
|
||||||
printk("Starting measurements with %d RPIs to seach and an infection rate of %d\n", count,
|
|
||||||
CONFIG_TEST_INFECTED_RATE);
|
|
||||||
|
|
||||||
timing_t start_time, end_time;
|
|
||||||
uint64_t total_cycles;
|
|
||||||
uint64_t total_ns;
|
|
||||||
|
|
||||||
timing_init();
|
|
||||||
timing_start();
|
|
||||||
start_time = timing_counter_get();
|
|
||||||
|
|
||||||
check_possible_contacts_for_intervals(testIntervals, count);
|
|
||||||
|
|
||||||
end_time = timing_counter_get();
|
|
||||||
|
|
||||||
total_cycles = timing_cycles_get(&start_time, &end_time);
|
|
||||||
total_ns = timing_cycles_to_ns(total_cycles);
|
|
||||||
|
|
||||||
timing_stop();
|
|
||||||
|
|
||||||
printk("\n'%s' took %lld ms\n---------------------------\n", label, total_ns / 1000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_results(infected_for_interval_ident_ctx_t testIntervals[], int count) {
|
|
||||||
int counter = 0;
|
|
||||||
for (int i = 0; i < count / 2; i++) {
|
|
||||||
counter += CONFIG_TEST_RECORDS_PER_INTERVAL * CONFIG_TEST_INFECTED_RATE;
|
|
||||||
int met = counter / 100;
|
|
||||||
counter %= 100;
|
|
||||||
if (testIntervals[i].met != met) {
|
|
||||||
printk("interval %d should have been met %d times (met %d)\n", i, met, testIntervals[i].met);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = count / 2; j < count; j++) {
|
|
||||||
if (testIntervals[j].met) {
|
|
||||||
printk("infected interval should not have been met (interval %d)\n", j);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printk("all results are as expected!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int reverse_bloom_filter(infected_for_interval_ident_ctx_t* ctx, int count) {
|
|
||||||
bloom_filter_t* bloom = bloom_init(count * 2);
|
|
||||||
if (!bloom) {
|
|
||||||
printk("bloom init failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init bloom filter with passed records
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
bloom_add_record(bloom, &ctx[i].interval_identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
// init iterator over the entire storage
|
|
||||||
record_iterator_t iterator;
|
|
||||||
rc = ens_records_iterator_init_timerange(&iterator, NULL, NULL);
|
|
||||||
if (rc) {
|
|
||||||
printk("init iterator failed (err %d)\n", rc);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
record_t* current;
|
|
||||||
while ((current = ens_records_iterator_next(&iterator))) {
|
|
||||||
if (bloom_probably_has_record(bloom, &(current->rolling_proximity_identifier))) {
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (memcmp(&(current->rolling_proximity_identifier), &ctx[i].interval_identifier,
|
|
||||||
sizeof(current->rolling_proximity_identifier)) == 0) {
|
|
||||||
ctx[i].met++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
// destroy bloom filter after things are finished
|
|
||||||
bloom_destroy(bloom);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
// SETUP DATA //
|
|
||||||
////////////////////
|
|
||||||
|
|
||||||
void setup_test_data(infected_for_interval_ident_ctx_t testIntervals[], int count) {
|
|
||||||
en_derive_period_identifier_key(&infectedPik, &infectedPeriodKey);
|
|
||||||
en_derive_period_identifier_key(&dummyPik, &dummyPeriodKey);
|
|
||||||
en_derive_period_identifier_key(&testPik, &testKey);
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
for (int i = 0; i < EN_TEK_ROLLING_PERIOD; i++) {
|
|
||||||
record_t infectedRecord;
|
|
||||||
record_t dummyRecord;
|
|
||||||
en_derive_interval_identifier((ENIntervalIdentifier*)&infectedRecord.rolling_proximity_identifier, &infectedPik,
|
|
||||||
i);
|
|
||||||
en_derive_interval_identifier((ENIntervalIdentifier*)&dummyRecord.rolling_proximity_identifier, &dummyPik, i);
|
|
||||||
|
|
||||||
for (int j = 0; j < CONFIG_TEST_RECORDS_PER_INTERVAL; j++) {
|
|
||||||
counter += CONFIG_TEST_INFECTED_RATE;
|
|
||||||
record_t* curRecord;
|
|
||||||
if (counter >= 100) {
|
|
||||||
counter -= 100;
|
|
||||||
curRecord = &infectedRecord;
|
|
||||||
} else {
|
|
||||||
curRecord = &dummyRecord;
|
|
||||||
}
|
|
||||||
curRecord->timestamp = i * EN_INTERVAL_LENGTH + j * (EN_INTERVAL_LENGTH / CONFIG_TEST_RECORDS_PER_INTERVAL);
|
|
||||||
int rc = add_record(curRecord);
|
|
||||||
if (rc) {
|
|
||||||
printk("err %d\n", rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < count / 2; i++) {
|
|
||||||
en_derive_interval_identifier(&testIntervals[i].interval_identifier, &infectedPik, i);
|
|
||||||
testIntervals[i].met = 0;
|
|
||||||
testIntervals[i].search_start = MAX(0, (i * EN_INTERVAL_LENGTH - 2 * 60 * 60));
|
|
||||||
testIntervals[i].search_end = i * EN_INTERVAL_LENGTH + 2 * 60 * 60;
|
|
||||||
|
|
||||||
int j = i + count / 2;
|
|
||||||
en_derive_interval_identifier(&testIntervals[j].interval_identifier, &testPik, i);
|
|
||||||
testIntervals[j].met = 0;
|
|
||||||
testIntervals[j].search_start = MAX(0, (i * EN_INTERVAL_LENGTH - 2 * 60 * 60));
|
|
||||||
testIntervals[j].search_end = i * EN_INTERVAL_LENGTH + 2 * 60 * 60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_contacts() {
|
|
||||||
#if CONFIG_CONTACTS_PERFORM_RISC_CHECK_TEST
|
|
||||||
static infected_for_interval_ident_ctx_t testIntervals[EN_TEK_ROLLING_PERIOD * 2];
|
|
||||||
|
|
||||||
reset_record_storage();
|
|
||||||
setup_test_data(testIntervals, EN_TEK_ROLLING_PERIOD * 2);
|
|
||||||
|
|
||||||
measure_perf(testIntervals, EN_TEK_ROLLING_PERIOD * 2);
|
|
||||||
check_results(testIntervals, EN_TEK_ROLLING_PERIOD * 2);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int check_possible_contacts_for_intervals(infected_for_interval_ident_ctx_t* ctx, int count) {
|
|
||||||
#if CONFIG_CONTACTS_BLOOM_REVERSE
|
|
||||||
return reverse_bloom_filter(ctx, count);
|
|
||||||
#else
|
|
||||||
return bloom_filter(ctx, count);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int check_possible_contacts_for_periods(period_key_information_t periodKeyInformation[], int count) {
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
static infected_for_interval_ident_ctx_t intervalIdents[EN_TEK_ROLLING_PERIOD];
|
|
||||||
int periodStart = en_get_interval_number(periodKeyInformation[i].start);
|
|
||||||
for (int interval = 0; interval < EN_TEK_ROLLING_PERIOD; interval++) {
|
|
||||||
en_derive_interval_identifier(&intervalIdents[interval].interval_identifier,
|
|
||||||
&periodKeyInformation[i].periodKey, periodStart + interval);
|
|
||||||
}
|
|
||||||
int rc = check_possible_contacts_for_intervals(intervalIdents, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
periodKeyInformation[i].met = rc;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
258
src/display.c
258
src/display.c
@ -1,258 +0,0 @@
|
|||||||
#if CONFIG_DISPLAY
|
|
||||||
#include <device.h>
|
|
||||||
#include <drivers/display.h>
|
|
||||||
#include <lvgl.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <zephyr.h>
|
|
||||||
|
|
||||||
#include "display.h"
|
|
||||||
|
|
||||||
K_THREAD_STACK_DEFINE(display_stack_area, 5000);
|
|
||||||
|
|
||||||
#if CONFIG_DISPLAY
|
|
||||||
const struct device* display_dev;
|
|
||||||
lv_obj_t* display_center_pane;
|
|
||||||
lv_obj_t* display_top_bar;
|
|
||||||
lv_obj_t* display_bot_bar;
|
|
||||||
lv_obj_t* display_contacts_label;
|
|
||||||
lv_obj_t* display_risk_contacts_label;
|
|
||||||
lv_obj_t* risk_contacts_button;
|
|
||||||
lv_obj_t* display_clock_label;
|
|
||||||
lv_obj_t* display_battery_label;
|
|
||||||
lv_obj_t* display_memory_label;
|
|
||||||
lv_obj_t* display_msg_label;
|
|
||||||
lv_style_t green_button_style;
|
|
||||||
lv_style_t yellow_button_style;
|
|
||||||
lv_style_t red_button_style;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int get_battery_percentage() {
|
|
||||||
// TODO: Implement
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_memory_percentage() {
|
|
||||||
// TODO: Implement
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_time() {
|
|
||||||
// TODO: Implement
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_contacts() {
|
|
||||||
// TODO: Implement
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_risk_contacts() {
|
|
||||||
// TODO: Implement
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_DISPLAY
|
|
||||||
|
|
||||||
void display_thread(void* arg1, void* arg2, void* arg3) {
|
|
||||||
static uint32_t sleep_time;
|
|
||||||
while (1) {
|
|
||||||
sleep_time = lv_task_handler();
|
|
||||||
update_display();
|
|
||||||
k_msleep(sleep_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_styles() {
|
|
||||||
lv_style_init(&green_button_style);
|
|
||||||
lv_style_init(&yellow_button_style);
|
|
||||||
lv_style_init(&red_button_style);
|
|
||||||
|
|
||||||
// Properties for all styles
|
|
||||||
lv_style_set_bg_opa(&green_button_style, LV_STATE_DEFAULT, LV_OPA_COVER);
|
|
||||||
lv_style_set_pad_top(&green_button_style, LV_STATE_DEFAULT, 10);
|
|
||||||
lv_style_set_pad_bottom(&green_button_style, LV_STATE_DEFAULT, 10);
|
|
||||||
lv_style_set_pad_left(&green_button_style, LV_STATE_DEFAULT, 10);
|
|
||||||
lv_style_set_pad_right(&green_button_style, LV_STATE_DEFAULT, 10);
|
|
||||||
lv_style_set_border_width(&green_button_style, LV_STATE_DEFAULT, 1);
|
|
||||||
lv_style_set_radius(&green_button_style, LV_STATE_DEFAULT, 10);
|
|
||||||
|
|
||||||
lv_style_copy(&yellow_button_style, &green_button_style);
|
|
||||||
lv_style_copy(&red_button_style, &green_button_style);
|
|
||||||
|
|
||||||
// Set different colors
|
|
||||||
lv_style_set_bg_color(&green_button_style, LV_STATE_DEFAULT, LV_COLOR_GREEN);
|
|
||||||
lv_style_set_text_color(&green_button_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
|
||||||
lv_style_set_bg_color(&yellow_button_style, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
|
|
||||||
lv_style_set_text_color(&yellow_button_style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
|
|
||||||
lv_style_set_bg_color(&red_button_style, LV_STATE_DEFAULT, LV_COLOR_RED);
|
|
||||||
lv_style_set_text_color(&red_button_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int update_display() {
|
|
||||||
display_set_contacts(get_contacts());
|
|
||||||
display_set_risk_contacts(get_risk_contacts());
|
|
||||||
display_set_time(get_time());
|
|
||||||
display_set_bat(get_battery_percentage());
|
|
||||||
display_set_mem(get_memory_percentage());
|
|
||||||
|
|
||||||
lv_task_handler();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_display() {
|
|
||||||
init_styles();
|
|
||||||
|
|
||||||
display_dev = device_get_binding(CONFIG_LVGL_DISPLAY_DEV_NAME);
|
|
||||||
|
|
||||||
if (display_dev == NULL) {
|
|
||||||
printk("device not found. Aborting test.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
display_top_bar = lv_cont_create(lv_scr_act(), NULL);
|
|
||||||
lv_obj_set_width(display_top_bar, lv_obj_get_width(lv_scr_act()));
|
|
||||||
lv_cont_set_layout(display_top_bar, LV_LAYOUT_PRETTY_TOP);
|
|
||||||
|
|
||||||
display_bot_bar = lv_cont_create(lv_scr_act(), NULL);
|
|
||||||
lv_obj_set_width(display_bot_bar, lv_obj_get_width(lv_scr_act()));
|
|
||||||
lv_cont_set_layout(display_bot_bar, LV_LAYOUT_PRETTY_BOTTOM);
|
|
||||||
|
|
||||||
display_center_pane = lv_cont_create(lv_scr_act(), NULL);
|
|
||||||
lv_obj_align(display_center_pane, display_top_bar, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
|
||||||
lv_obj_set_width(display_center_pane, lv_obj_get_width(lv_scr_act()));
|
|
||||||
lv_obj_set_height(display_center_pane, lv_obj_get_height(lv_scr_act()) - lv_obj_get_height(display_top_bar) - lv_obj_get_height(display_bot_bar));
|
|
||||||
lv_cont_set_layout(display_center_pane, LV_LAYOUT_COLUMN_MID);
|
|
||||||
|
|
||||||
lv_obj_align(display_bot_bar, display_center_pane, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
|
||||||
|
|
||||||
display_contacts_label = lv_label_create(display_center_pane, NULL);
|
|
||||||
lv_obj_set_height_margin(display_contacts_label, 20);
|
|
||||||
lv_label_set_text(display_contacts_label, "");
|
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_LVGL_POINTER_KSCAN)) {
|
|
||||||
risk_contacts_button = lv_btn_create(display_center_pane, NULL);
|
|
||||||
lv_btn_set_fit(risk_contacts_button, LV_FIT_TIGHT);
|
|
||||||
display_risk_contacts_label = lv_label_create(risk_contacts_button, NULL);
|
|
||||||
} else {
|
|
||||||
display_risk_contacts_label = lv_label_create(display_center_pane, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_obj_set_height_margin(display_risk_contacts_label, 20);
|
|
||||||
lv_label_set_text(display_risk_contacts_label, "");
|
|
||||||
|
|
||||||
display_memory_label = lv_label_create(display_top_bar, NULL);
|
|
||||||
lv_obj_set_width_margin(display_memory_label, 10);
|
|
||||||
lv_label_set_text(display_memory_label, "");
|
|
||||||
|
|
||||||
display_clock_label = lv_label_create(display_top_bar, NULL);
|
|
||||||
lv_obj_set_width_margin(display_clock_label, 10);
|
|
||||||
lv_label_set_text(display_clock_label, "");
|
|
||||||
|
|
||||||
display_battery_label = lv_label_create(display_top_bar, NULL);
|
|
||||||
lv_obj_set_width_margin(display_battery_label, 10);
|
|
||||||
lv_label_set_text(display_battery_label, "");
|
|
||||||
|
|
||||||
display_msg_label = lv_label_create(display_bot_bar, NULL);
|
|
||||||
lv_label_set_text(display_msg_label, "");
|
|
||||||
|
|
||||||
static struct k_thread display_thread_data;
|
|
||||||
k_thread_create(&display_thread_data, display_stack_area, K_THREAD_STACK_SIZEOF(display_stack_area), display_thread, NULL, NULL, NULL, 0, 0, K_NO_WAIT);
|
|
||||||
|
|
||||||
display_blanking_off(display_dev);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_message(char* msg) {
|
|
||||||
lv_label_set_text(display_msg_label, msg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_time(int time) {
|
|
||||||
lv_label_set_text_fmt(display_clock_label, "%d:%d", time / 100, time % 100)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_bat(int bat) {
|
|
||||||
lv_label_set_text_fmt(display_battery_label, "Bat: %d%%", bat);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_mem(int mem) {
|
|
||||||
lv_label_set_text_fmt(display_memory_label, "Mem: %d%%", mem);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_contacts(int contacts) {
|
|
||||||
lv_label_set_text_fmt(display_contacts_label, "Number of contacts: %d,\nfrom which", contacts);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_risk_contacts(int risk_contacts) {
|
|
||||||
lv_label_set_text_fmt(display_risk_contacts_label, "%d are risk contacts.", risk_contacts);
|
|
||||||
|
|
||||||
if (risk_contacts == 0) {
|
|
||||||
// Set Button green
|
|
||||||
lv_obj_reset_style_list(risk_contacts_button, LV_OBJ_PART_MAIN);
|
|
||||||
lv_obj_add_style(risk_contacts_button, LV_BTN_PART_MAIN, &green_button_style);
|
|
||||||
} else if (risk_contacts < 5) {
|
|
||||||
// Set Button yellow
|
|
||||||
lv_obj_reset_style_list(risk_contacts_button, LV_OBJ_PART_MAIN);
|
|
||||||
lv_obj_add_style(risk_contacts_button, LV_BTN_PART_MAIN, &yellow_button_style);
|
|
||||||
} else {
|
|
||||||
// Set Button red
|
|
||||||
lv_obj_reset_style_list(risk_contacts_button, LV_OBJ_PART_MAIN);
|
|
||||||
lv_obj_add_style(risk_contacts_button, LV_BTN_PART_MAIN, &red_button_style);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void display_thread(void* arg1, void* arg2, void* arg3) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_styles() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int update_display() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_display() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_message(char* msg) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_time(int time) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_bat(int bat) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_mem(int mem) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_contacts(int contacts) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int display_set_risk_contacts(int risk_contacts) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,208 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "covid_types.h"
|
|
||||||
#include "ens/ens_error.h"
|
|
||||||
#include "ens/records.h"
|
|
||||||
#include "ens/sequencenumber.h"
|
|
||||||
#include "ens/storage.h"
|
|
||||||
|
|
||||||
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
|
||||||
record_sequence_number_t* opt_start,
|
|
||||||
record_sequence_number_t* opt_end) {
|
|
||||||
// prevent any changes during initialization
|
|
||||||
int rc = get_sequence_number_interval(&iterator->sn_next, &iterator->sn_end);
|
|
||||||
if (rc == 0) {
|
|
||||||
iterator->finished = false;
|
|
||||||
|
|
||||||
// we override start and end with the optional values
|
|
||||||
if (opt_start) {
|
|
||||||
iterator->sn_next = *opt_start;
|
|
||||||
}
|
|
||||||
if (opt_end) {
|
|
||||||
iterator->sn_end = *opt_end;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iterator->finished = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t get_timestamp_for_sn(record_sequence_number_t sn) {
|
|
||||||
record_t rec;
|
|
||||||
if (load_record(&rec, sn) == 0) {
|
|
||||||
return rec.timestamp;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum record_timestamp_search_mode {
|
|
||||||
RECORD_TIMESTAMP_SEARCH_MODE_MIN,
|
|
||||||
RECORD_TIMESTAMP_SEARCH_MODE_MAX,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find an entry via binary search for the timestamp.
|
|
||||||
*
|
|
||||||
* @param record pointer to the location, where the found sn shall be stored
|
|
||||||
* @param target timestamp for which to find the nearest entry for
|
|
||||||
* @param greater flag for indicating, if the loaded sn shall correspond to a greater (1) or smaller (0) timestamp
|
|
||||||
*/
|
|
||||||
int find_sn_via_binary_search(record_sequence_number_t* sn_dest,
|
|
||||||
uint32_t target,
|
|
||||||
enum record_timestamp_search_mode search_mode) {
|
|
||||||
record_sequence_number_t start_sn;
|
|
||||||
record_sequence_number_t end_sn;
|
|
||||||
|
|
||||||
// prevent any changes during binary search initialization
|
|
||||||
|
|
||||||
int rc = get_sequence_number_interval(&start_sn, &end_sn);
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
record_sequence_number_t last_sn =
|
|
||||||
start_sn; // used to check if ran into issues, e.g. could not load the entry or rounding errors
|
|
||||||
|
|
||||||
while (!sn_equal(start_sn, end_sn)) {
|
|
||||||
// calculate the sn in the middle between start and end
|
|
||||||
record_sequence_number_t cur_sn = sn_get_middle_sn(start_sn, end_sn);
|
|
||||||
|
|
||||||
if (sn_equal(cur_sn, last_sn)) {
|
|
||||||
// if we already checked this entry -> we reduce our boundaries and try again
|
|
||||||
// this also solves issues with rounding
|
|
||||||
// TODO: This is not the best way...
|
|
||||||
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
|
||||||
int64_t start_ts = get_timestamp_for_sn(start_sn);
|
|
||||||
if (start_ts == -1 || start_ts < target) {
|
|
||||||
// we could not load this entry or this entry is strictly smaller than our target
|
|
||||||
start_sn = sn_increment(start_sn); // we can safely increment as start_sn < end_sn
|
|
||||||
} else {
|
|
||||||
// we actually found the wanted entry!
|
|
||||||
end_sn = start_sn; // this will break our loop
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we search for the biggest value among them
|
|
||||||
int64_t end_ts = get_timestamp_for_sn(end_sn);
|
|
||||||
if (end_ts == -1 || end_ts > target) {
|
|
||||||
// we could not load this entry or this entry is strictly bigger than our target
|
|
||||||
end_sn = sn_decrement(end_sn); // we can safely decrement as start_sn < end_sn
|
|
||||||
} else {
|
|
||||||
// we actually found the wanted entry!
|
|
||||||
start_sn = end_sn; // this will break our loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int64_t mid_ts = get_timestamp_for_sn(cur_sn);
|
|
||||||
|
|
||||||
if (mid_ts >= 0) {
|
|
||||||
if (target < mid_ts) {
|
|
||||||
end_sn = cur_sn;
|
|
||||||
} else if (target > mid_ts) {
|
|
||||||
start_sn = cur_sn;
|
|
||||||
} else {
|
|
||||||
// target == mid_ts
|
|
||||||
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
|
||||||
// we search for the smallest value among them -> look before this item
|
|
||||||
end_sn = cur_sn;
|
|
||||||
} else {
|
|
||||||
// we search for the biggest value among them -> look after this item
|
|
||||||
start_sn = cur_sn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// some errors -> we keep the current sn and try to narrow our boundaries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_sn = cur_sn;
|
|
||||||
}
|
|
||||||
|
|
||||||
*sn_dest = start_sn; // == end_sn
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This iterator does neither check if the sequence numbers wrapped around while iteration. As a result, first
|
|
||||||
// results could have later timestamps than following entries
|
|
||||||
int ens_records_iterator_init_timerange(record_iterator_t* iterator, time_t* ts_start, time_t* ts_end) {
|
|
||||||
record_sequence_number_t oldest_sn = 0;
|
|
||||||
record_sequence_number_t newest_sn = 0;
|
|
||||||
|
|
||||||
// assure that *ts_end > *ts_start
|
|
||||||
if (ts_start && ts_end && *ts_end < *ts_start) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts_start) {
|
|
||||||
int rc = find_sn_via_binary_search(&oldest_sn, *ts_start, RECORD_TIMESTAMP_SEARCH_MODE_MIN);
|
|
||||||
if (rc) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oldest_sn = get_oldest_sequence_number();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts_end) {
|
|
||||||
int rc = find_sn_via_binary_search(&newest_sn, *ts_end, RECORD_TIMESTAMP_SEARCH_MODE_MAX);
|
|
||||||
if (rc) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newest_sn = get_latest_sequence_number();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ens_records_iterator_init_range(iterator, &oldest_sn, &newest_sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
record_t* ens_records_iterator_next(record_iterator_t* iter) {
|
|
||||||
record_t* next = NULL;
|
|
||||||
|
|
||||||
while (next == NULL && !iter->finished) {
|
|
||||||
record_t contact;
|
|
||||||
// try to load the next contact
|
|
||||||
int res = load_record(&contact, iter->sn_next);
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
next = &iter->current;
|
|
||||||
memcpy(next, &contact, sizeof(record_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sn_equal(iter->sn_next, iter->sn_end)) {
|
|
||||||
iter->finished = true; // this iterator will finish after this execution
|
|
||||||
} else {
|
|
||||||
// increase the current sn
|
|
||||||
iter->sn_next = sn_increment(iter->sn_next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ens_record_iterator_clear(record_iterator_t* iter) {
|
|
||||||
// clear all relevant fields in the iterator
|
|
||||||
iter->finished = true;
|
|
||||||
iter->sn_next = 0;
|
|
||||||
iter->sn_end = 0;
|
|
||||||
memset(&iter->current, 0, sizeof(iter->current));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata) {
|
|
||||||
record_t* cur = ens_records_iterator_next(iter);
|
|
||||||
bool cont = true;
|
|
||||||
|
|
||||||
while (cur != NULL && cont) {
|
|
||||||
int cb_res = cb(cur, userdata);
|
|
||||||
if (cb_res == ENS_RECORD_ITER_STOP) {
|
|
||||||
cont = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cont) {
|
|
||||||
cb(NULL, userdata); // we call the callback one last time but with null data
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,682 +0,0 @@
|
|||||||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
|
||||||
/* Generated from: export.proto */
|
|
||||||
|
|
||||||
/* Do not generate deprecated warnings for self */
|
|
||||||
#ifndef PROTOBUF_C__NO_DEPRECATED
|
|
||||||
#define PROTOBUF_C__NO_DEPRECATED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "export.pb-c.h"
|
|
||||||
void temporary_exposure_key_export__init
|
|
||||||
(TemporaryExposureKeyExport *message)
|
|
||||||
{
|
|
||||||
static const TemporaryExposureKeyExport init_value = TEMPORARY_EXPOSURE_KEY_EXPORT__INIT;
|
|
||||||
*message = init_value;
|
|
||||||
}
|
|
||||||
size_t temporary_exposure_key_export__get_packed_size
|
|
||||||
(const TemporaryExposureKeyExport *message)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
|
||||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
|
||||||
}
|
|
||||||
size_t temporary_exposure_key_export__pack
|
|
||||||
(const TemporaryExposureKeyExport *message,
|
|
||||||
uint8_t *out)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
|
||||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
|
||||||
}
|
|
||||||
size_t temporary_exposure_key_export__pack_to_buffer
|
|
||||||
(const TemporaryExposureKeyExport *message,
|
|
||||||
ProtobufCBuffer *buffer)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
|
||||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
|
||||||
}
|
|
||||||
TemporaryExposureKeyExport *
|
|
||||||
temporary_exposure_key_export__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data)
|
|
||||||
{
|
|
||||||
return (TemporaryExposureKeyExport *)
|
|
||||||
protobuf_c_message_unpack (&temporary_exposure_key_export__descriptor,
|
|
||||||
allocator, len, data);
|
|
||||||
}
|
|
||||||
void temporary_exposure_key_export__free_unpacked
|
|
||||||
(TemporaryExposureKeyExport *message,
|
|
||||||
ProtobufCAllocator *allocator)
|
|
||||||
{
|
|
||||||
if(!message)
|
|
||||||
return;
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
|
||||||
}
|
|
||||||
void signature_info__init
|
|
||||||
(SignatureInfo *message)
|
|
||||||
{
|
|
||||||
static const SignatureInfo init_value = SIGNATURE_INFO__INIT;
|
|
||||||
*message = init_value;
|
|
||||||
}
|
|
||||||
size_t signature_info__get_packed_size
|
|
||||||
(const SignatureInfo *message)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &signature_info__descriptor);
|
|
||||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
|
||||||
}
|
|
||||||
size_t signature_info__pack
|
|
||||||
(const SignatureInfo *message,
|
|
||||||
uint8_t *out)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &signature_info__descriptor);
|
|
||||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
|
||||||
}
|
|
||||||
size_t signature_info__pack_to_buffer
|
|
||||||
(const SignatureInfo *message,
|
|
||||||
ProtobufCBuffer *buffer)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &signature_info__descriptor);
|
|
||||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
|
||||||
}
|
|
||||||
SignatureInfo *
|
|
||||||
signature_info__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data)
|
|
||||||
{
|
|
||||||
return (SignatureInfo *)
|
|
||||||
protobuf_c_message_unpack (&signature_info__descriptor,
|
|
||||||
allocator, len, data);
|
|
||||||
}
|
|
||||||
void signature_info__free_unpacked
|
|
||||||
(SignatureInfo *message,
|
|
||||||
ProtobufCAllocator *allocator)
|
|
||||||
{
|
|
||||||
if(!message)
|
|
||||||
return;
|
|
||||||
assert(message->base.descriptor == &signature_info__descriptor);
|
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
|
||||||
}
|
|
||||||
void temporary_exposure_key__init
|
|
||||||
(TemporaryExposureKey *message)
|
|
||||||
{
|
|
||||||
static const TemporaryExposureKey init_value = TEMPORARY_EXPOSURE_KEY__INIT;
|
|
||||||
*message = init_value;
|
|
||||||
}
|
|
||||||
size_t temporary_exposure_key__get_packed_size
|
|
||||||
(const TemporaryExposureKey *message)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
|
||||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
|
||||||
}
|
|
||||||
size_t temporary_exposure_key__pack
|
|
||||||
(const TemporaryExposureKey *message,
|
|
||||||
uint8_t *out)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
|
||||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
|
||||||
}
|
|
||||||
size_t temporary_exposure_key__pack_to_buffer
|
|
||||||
(const TemporaryExposureKey *message,
|
|
||||||
ProtobufCBuffer *buffer)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
|
||||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
|
||||||
}
|
|
||||||
TemporaryExposureKey *
|
|
||||||
temporary_exposure_key__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data)
|
|
||||||
{
|
|
||||||
return (TemporaryExposureKey *)
|
|
||||||
protobuf_c_message_unpack (&temporary_exposure_key__descriptor,
|
|
||||||
allocator, len, data);
|
|
||||||
}
|
|
||||||
void temporary_exposure_key__free_unpacked
|
|
||||||
(TemporaryExposureKey *message,
|
|
||||||
ProtobufCAllocator *allocator)
|
|
||||||
{
|
|
||||||
if(!message)
|
|
||||||
return;
|
|
||||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
|
||||||
}
|
|
||||||
void teksignature_list__init
|
|
||||||
(TEKSignatureList *message)
|
|
||||||
{
|
|
||||||
static const TEKSignatureList init_value = TEKSIGNATURE_LIST__INIT;
|
|
||||||
*message = init_value;
|
|
||||||
}
|
|
||||||
size_t teksignature_list__get_packed_size
|
|
||||||
(const TEKSignatureList *message)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
|
||||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
|
||||||
}
|
|
||||||
size_t teksignature_list__pack
|
|
||||||
(const TEKSignatureList *message,
|
|
||||||
uint8_t *out)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
|
||||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
|
||||||
}
|
|
||||||
size_t teksignature_list__pack_to_buffer
|
|
||||||
(const TEKSignatureList *message,
|
|
||||||
ProtobufCBuffer *buffer)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
|
||||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
|
||||||
}
|
|
||||||
TEKSignatureList *
|
|
||||||
teksignature_list__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data)
|
|
||||||
{
|
|
||||||
return (TEKSignatureList *)
|
|
||||||
protobuf_c_message_unpack (&teksignature_list__descriptor,
|
|
||||||
allocator, len, data);
|
|
||||||
}
|
|
||||||
void teksignature_list__free_unpacked
|
|
||||||
(TEKSignatureList *message,
|
|
||||||
ProtobufCAllocator *allocator)
|
|
||||||
{
|
|
||||||
if(!message)
|
|
||||||
return;
|
|
||||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
|
||||||
}
|
|
||||||
void teksignature__init
|
|
||||||
(TEKSignature *message)
|
|
||||||
{
|
|
||||||
static const TEKSignature init_value = TEKSIGNATURE__INIT;
|
|
||||||
*message = init_value;
|
|
||||||
}
|
|
||||||
size_t teksignature__get_packed_size
|
|
||||||
(const TEKSignature *message)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &teksignature__descriptor);
|
|
||||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
|
||||||
}
|
|
||||||
size_t teksignature__pack
|
|
||||||
(const TEKSignature *message,
|
|
||||||
uint8_t *out)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &teksignature__descriptor);
|
|
||||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
|
||||||
}
|
|
||||||
size_t teksignature__pack_to_buffer
|
|
||||||
(const TEKSignature *message,
|
|
||||||
ProtobufCBuffer *buffer)
|
|
||||||
{
|
|
||||||
assert(message->base.descriptor == &teksignature__descriptor);
|
|
||||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
|
||||||
}
|
|
||||||
TEKSignature *
|
|
||||||
teksignature__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data)
|
|
||||||
{
|
|
||||||
return (TEKSignature *)
|
|
||||||
protobuf_c_message_unpack (&teksignature__descriptor,
|
|
||||||
allocator, len, data);
|
|
||||||
}
|
|
||||||
void teksignature__free_unpacked
|
|
||||||
(TEKSignature *message,
|
|
||||||
ProtobufCAllocator *allocator)
|
|
||||||
{
|
|
||||||
if(!message)
|
|
||||||
return;
|
|
||||||
assert(message->base.descriptor == &teksignature__descriptor);
|
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
|
||||||
}
|
|
||||||
static const ProtobufCFieldDescriptor temporary_exposure_key_export__field_descriptors[8] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"start_timestamp",
|
|
||||||
1,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_FIXED64,
|
|
||||||
offsetof(TemporaryExposureKeyExport, has_start_timestamp),
|
|
||||||
offsetof(TemporaryExposureKeyExport, start_timestamp),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"end_timestamp",
|
|
||||||
2,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_FIXED64,
|
|
||||||
offsetof(TemporaryExposureKeyExport, has_end_timestamp),
|
|
||||||
offsetof(TemporaryExposureKeyExport, end_timestamp),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"region",
|
|
||||||
3,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_STRING,
|
|
||||||
0, /* quantifier_offset */
|
|
||||||
offsetof(TemporaryExposureKeyExport, region),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"batch_num",
|
|
||||||
4,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT32,
|
|
||||||
offsetof(TemporaryExposureKeyExport, has_batch_num),
|
|
||||||
offsetof(TemporaryExposureKeyExport, batch_num),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"batch_size",
|
|
||||||
5,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT32,
|
|
||||||
offsetof(TemporaryExposureKeyExport, has_batch_size),
|
|
||||||
offsetof(TemporaryExposureKeyExport, batch_size),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"signature_infos",
|
|
||||||
6,
|
|
||||||
PROTOBUF_C_LABEL_REPEATED,
|
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
|
||||||
offsetof(TemporaryExposureKeyExport, n_signature_infos),
|
|
||||||
offsetof(TemporaryExposureKeyExport, signature_infos),
|
|
||||||
&signature_info__descriptor,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"keys",
|
|
||||||
7,
|
|
||||||
PROTOBUF_C_LABEL_REPEATED,
|
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
|
||||||
offsetof(TemporaryExposureKeyExport, n_keys),
|
|
||||||
offsetof(TemporaryExposureKeyExport, keys),
|
|
||||||
&temporary_exposure_key__descriptor,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"revised_keys",
|
|
||||||
8,
|
|
||||||
PROTOBUF_C_LABEL_REPEATED,
|
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
|
||||||
offsetof(TemporaryExposureKeyExport, n_revised_keys),
|
|
||||||
offsetof(TemporaryExposureKeyExport, revised_keys),
|
|
||||||
&temporary_exposure_key__descriptor,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
static const unsigned temporary_exposure_key_export__field_indices_by_name[] = {
|
|
||||||
3, /* field[3] = batch_num */
|
|
||||||
4, /* field[4] = batch_size */
|
|
||||||
1, /* field[1] = end_timestamp */
|
|
||||||
6, /* field[6] = keys */
|
|
||||||
2, /* field[2] = region */
|
|
||||||
7, /* field[7] = revised_keys */
|
|
||||||
5, /* field[5] = signature_infos */
|
|
||||||
0, /* field[0] = start_timestamp */
|
|
||||||
};
|
|
||||||
static const ProtobufCIntRange temporary_exposure_key_export__number_ranges[1 + 1] =
|
|
||||||
{
|
|
||||||
{ 1, 0 },
|
|
||||||
{ 0, 8 }
|
|
||||||
};
|
|
||||||
const ProtobufCMessageDescriptor temporary_exposure_key_export__descriptor =
|
|
||||||
{
|
|
||||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
|
||||||
"TemporaryExposureKeyExport",
|
|
||||||
"TemporaryExposureKeyExport",
|
|
||||||
"TemporaryExposureKeyExport",
|
|
||||||
"",
|
|
||||||
sizeof(TemporaryExposureKeyExport),
|
|
||||||
8,
|
|
||||||
temporary_exposure_key_export__field_descriptors,
|
|
||||||
temporary_exposure_key_export__field_indices_by_name,
|
|
||||||
1, temporary_exposure_key_export__number_ranges,
|
|
||||||
(ProtobufCMessageInit) temporary_exposure_key_export__init,
|
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
|
||||||
};
|
|
||||||
static const ProtobufCFieldDescriptor signature_info__field_descriptors[3] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"verification_key_version",
|
|
||||||
3,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_STRING,
|
|
||||||
0, /* quantifier_offset */
|
|
||||||
offsetof(SignatureInfo, verification_key_version),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"verification_key_id",
|
|
||||||
4,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_STRING,
|
|
||||||
0, /* quantifier_offset */
|
|
||||||
offsetof(SignatureInfo, verification_key_id),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"signature_algorithm",
|
|
||||||
5,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_STRING,
|
|
||||||
0, /* quantifier_offset */
|
|
||||||
offsetof(SignatureInfo, signature_algorithm),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
static const unsigned signature_info__field_indices_by_name[] = {
|
|
||||||
2, /* field[2] = signature_algorithm */
|
|
||||||
1, /* field[1] = verification_key_id */
|
|
||||||
0, /* field[0] = verification_key_version */
|
|
||||||
};
|
|
||||||
static const ProtobufCIntRange signature_info__number_ranges[1 + 1] =
|
|
||||||
{
|
|
||||||
{ 3, 0 },
|
|
||||||
{ 0, 3 }
|
|
||||||
};
|
|
||||||
const ProtobufCMessageDescriptor signature_info__descriptor =
|
|
||||||
{
|
|
||||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
|
||||||
"SignatureInfo",
|
|
||||||
"SignatureInfo",
|
|
||||||
"SignatureInfo",
|
|
||||||
"",
|
|
||||||
sizeof(SignatureInfo),
|
|
||||||
3,
|
|
||||||
signature_info__field_descriptors,
|
|
||||||
signature_info__field_indices_by_name,
|
|
||||||
1, signature_info__number_ranges,
|
|
||||||
(ProtobufCMessageInit) signature_info__init,
|
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
|
||||||
};
|
|
||||||
static const ProtobufCEnumValue temporary_exposure_key__report_type__enum_values_by_number[6] =
|
|
||||||
{
|
|
||||||
{ "UNKNOWN", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__UNKNOWN", 0 },
|
|
||||||
{ "CONFIRMED_TEST", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_TEST", 1 },
|
|
||||||
{ "CONFIRMED_CLINICAL_DIAGNOSIS", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_CLINICAL_DIAGNOSIS", 2 },
|
|
||||||
{ "SELF_REPORT", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__SELF_REPORT", 3 },
|
|
||||||
{ "RECURSIVE", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__RECURSIVE", 4 },
|
|
||||||
{ "REVOKED", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__REVOKED", 5 },
|
|
||||||
};
|
|
||||||
static const ProtobufCIntRange temporary_exposure_key__report_type__value_ranges[] = {
|
|
||||||
{0, 0},{0, 6}
|
|
||||||
};
|
|
||||||
static const ProtobufCEnumValueIndex temporary_exposure_key__report_type__enum_values_by_name[6] =
|
|
||||||
{
|
|
||||||
{ "CONFIRMED_CLINICAL_DIAGNOSIS", 2 },
|
|
||||||
{ "CONFIRMED_TEST", 1 },
|
|
||||||
{ "RECURSIVE", 4 },
|
|
||||||
{ "REVOKED", 5 },
|
|
||||||
{ "SELF_REPORT", 3 },
|
|
||||||
{ "UNKNOWN", 0 },
|
|
||||||
};
|
|
||||||
const ProtobufCEnumDescriptor temporary_exposure_key__report_type__descriptor =
|
|
||||||
{
|
|
||||||
PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
|
|
||||||
"TemporaryExposureKey.ReportType",
|
|
||||||
"ReportType",
|
|
||||||
"TemporaryExposureKey__ReportType",
|
|
||||||
"",
|
|
||||||
6,
|
|
||||||
temporary_exposure_key__report_type__enum_values_by_number,
|
|
||||||
6,
|
|
||||||
temporary_exposure_key__report_type__enum_values_by_name,
|
|
||||||
1,
|
|
||||||
temporary_exposure_key__report_type__value_ranges,
|
|
||||||
NULL,NULL,NULL,NULL /* reserved[1234] */
|
|
||||||
};
|
|
||||||
static const int32_t temporary_exposure_key__rolling_period__default_value = 144;
|
|
||||||
static const ProtobufCFieldDescriptor temporary_exposure_key__field_descriptors[6] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"key_data",
|
|
||||||
1,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_BYTES,
|
|
||||||
offsetof(TemporaryExposureKey, has_key_data),
|
|
||||||
offsetof(TemporaryExposureKey, key_data),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"transmission_risk_level",
|
|
||||||
2,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT32,
|
|
||||||
offsetof(TemporaryExposureKey, has_transmission_risk_level),
|
|
||||||
offsetof(TemporaryExposureKey, transmission_risk_level),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0 | PROTOBUF_C_FIELD_FLAG_DEPRECATED, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"rolling_start_interval_number",
|
|
||||||
3,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT32,
|
|
||||||
offsetof(TemporaryExposureKey, has_rolling_start_interval_number),
|
|
||||||
offsetof(TemporaryExposureKey, rolling_start_interval_number),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"rolling_period",
|
|
||||||
4,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT32,
|
|
||||||
offsetof(TemporaryExposureKey, has_rolling_period),
|
|
||||||
offsetof(TemporaryExposureKey, rolling_period),
|
|
||||||
NULL,
|
|
||||||
&temporary_exposure_key__rolling_period__default_value,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"report_type",
|
|
||||||
5,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_ENUM,
|
|
||||||
offsetof(TemporaryExposureKey, has_report_type),
|
|
||||||
offsetof(TemporaryExposureKey, report_type),
|
|
||||||
&temporary_exposure_key__report_type__descriptor,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"days_since_onset_of_symptoms",
|
|
||||||
6,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_SINT32,
|
|
||||||
offsetof(TemporaryExposureKey, has_days_since_onset_of_symptoms),
|
|
||||||
offsetof(TemporaryExposureKey, days_since_onset_of_symptoms),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
static const unsigned temporary_exposure_key__field_indices_by_name[] = {
|
|
||||||
5, /* field[5] = days_since_onset_of_symptoms */
|
|
||||||
0, /* field[0] = key_data */
|
|
||||||
4, /* field[4] = report_type */
|
|
||||||
3, /* field[3] = rolling_period */
|
|
||||||
2, /* field[2] = rolling_start_interval_number */
|
|
||||||
1, /* field[1] = transmission_risk_level */
|
|
||||||
};
|
|
||||||
static const ProtobufCIntRange temporary_exposure_key__number_ranges[1 + 1] =
|
|
||||||
{
|
|
||||||
{ 1, 0 },
|
|
||||||
{ 0, 6 }
|
|
||||||
};
|
|
||||||
const ProtobufCMessageDescriptor temporary_exposure_key__descriptor =
|
|
||||||
{
|
|
||||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
|
||||||
"TemporaryExposureKey",
|
|
||||||
"TemporaryExposureKey",
|
|
||||||
"TemporaryExposureKey",
|
|
||||||
"",
|
|
||||||
sizeof(TemporaryExposureKey),
|
|
||||||
6,
|
|
||||||
temporary_exposure_key__field_descriptors,
|
|
||||||
temporary_exposure_key__field_indices_by_name,
|
|
||||||
1, temporary_exposure_key__number_ranges,
|
|
||||||
(ProtobufCMessageInit) temporary_exposure_key__init,
|
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
|
||||||
};
|
|
||||||
static const ProtobufCFieldDescriptor teksignature_list__field_descriptors[1] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"signatures",
|
|
||||||
1,
|
|
||||||
PROTOBUF_C_LABEL_REPEATED,
|
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
|
||||||
offsetof(TEKSignatureList, n_signatures),
|
|
||||||
offsetof(TEKSignatureList, signatures),
|
|
||||||
&teksignature__descriptor,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
static const unsigned teksignature_list__field_indices_by_name[] = {
|
|
||||||
0, /* field[0] = signatures */
|
|
||||||
};
|
|
||||||
static const ProtobufCIntRange teksignature_list__number_ranges[1 + 1] =
|
|
||||||
{
|
|
||||||
{ 1, 0 },
|
|
||||||
{ 0, 1 }
|
|
||||||
};
|
|
||||||
const ProtobufCMessageDescriptor teksignature_list__descriptor =
|
|
||||||
{
|
|
||||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
|
||||||
"TEKSignatureList",
|
|
||||||
"TEKSignatureList",
|
|
||||||
"TEKSignatureList",
|
|
||||||
"",
|
|
||||||
sizeof(TEKSignatureList),
|
|
||||||
1,
|
|
||||||
teksignature_list__field_descriptors,
|
|
||||||
teksignature_list__field_indices_by_name,
|
|
||||||
1, teksignature_list__number_ranges,
|
|
||||||
(ProtobufCMessageInit) teksignature_list__init,
|
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
|
||||||
};
|
|
||||||
static const ProtobufCFieldDescriptor teksignature__field_descriptors[4] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"signature_info",
|
|
||||||
1,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
|
||||||
0, /* quantifier_offset */
|
|
||||||
offsetof(TEKSignature, signature_info),
|
|
||||||
&signature_info__descriptor,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"batch_num",
|
|
||||||
2,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT32,
|
|
||||||
offsetof(TEKSignature, has_batch_num),
|
|
||||||
offsetof(TEKSignature, batch_num),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"batch_size",
|
|
||||||
3,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT32,
|
|
||||||
offsetof(TEKSignature, has_batch_size),
|
|
||||||
offsetof(TEKSignature, batch_size),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"signature",
|
|
||||||
4,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_BYTES,
|
|
||||||
offsetof(TEKSignature, has_signature),
|
|
||||||
offsetof(TEKSignature, signature),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
static const unsigned teksignature__field_indices_by_name[] = {
|
|
||||||
1, /* field[1] = batch_num */
|
|
||||||
2, /* field[2] = batch_size */
|
|
||||||
3, /* field[3] = signature */
|
|
||||||
0, /* field[0] = signature_info */
|
|
||||||
};
|
|
||||||
static const ProtobufCIntRange teksignature__number_ranges[1 + 1] =
|
|
||||||
{
|
|
||||||
{ 1, 0 },
|
|
||||||
{ 0, 4 }
|
|
||||||
};
|
|
||||||
const ProtobufCMessageDescriptor teksignature__descriptor =
|
|
||||||
{
|
|
||||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
|
||||||
"TEKSignature",
|
|
||||||
"TEKSignature",
|
|
||||||
"TEKSignature",
|
|
||||||
"",
|
|
||||||
sizeof(TEKSignature),
|
|
||||||
4,
|
|
||||||
teksignature__field_descriptors,
|
|
||||||
teksignature__field_indices_by_name,
|
|
||||||
1, teksignature__number_ranges,
|
|
||||||
(ProtobufCMessageInit) teksignature__init,
|
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
|
||||||
};
|
|
@ -1,115 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <timing/timing.h>
|
|
||||||
#include <zephyr.h>
|
|
||||||
|
|
||||||
#include <protobuf-c.h>
|
|
||||||
|
|
||||||
#include "export.pb-c.h"
|
|
||||||
#include "extract_keys.h"
|
|
||||||
|
|
||||||
#define KEY_SIZE 16
|
|
||||||
|
|
||||||
void process_key(TemporaryExposureKey* key) {
|
|
||||||
// TODO: Implement
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t generate_keys(uint8_t** buffer_pointer, int num_keys) {
|
|
||||||
// Initialize the key export data structure
|
|
||||||
TemporaryExposureKeyExport export = TEMPORARY_EXPOSURE_KEY_EXPORT__INIT;
|
|
||||||
|
|
||||||
TemporaryExposureKey** key_ptrs = (TemporaryExposureKey**)k_malloc(sizeof(TemporaryExposureKey*) * num_keys);
|
|
||||||
if (key_ptrs == NULL) {
|
|
||||||
printk("Could not allocate memory for pointers\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
export.batch_num = 1;
|
|
||||||
export.batch_size = 1;
|
|
||||||
|
|
||||||
// Initialize the keys and their data
|
|
||||||
uint8_t key_data[KEY_SIZE];
|
|
||||||
for (int i = 0; i < KEY_SIZE; i++) {
|
|
||||||
key_data[i] = 0xFF;
|
|
||||||
}
|
|
||||||
TemporaryExposureKey key = TEMPORARY_EXPOSURE_KEY__INIT;
|
|
||||||
key.key_data.data = key_data;
|
|
||||||
key.key_data.len = KEY_SIZE;
|
|
||||||
key.has_key_data = true;
|
|
||||||
|
|
||||||
// All pointers will point to the same key. The protocol buffer will still have n keys encoded
|
|
||||||
for (int i = 0; i < num_keys; i++) {
|
|
||||||
key_ptrs[i] = &key;
|
|
||||||
}
|
|
||||||
export.n_keys = num_keys;
|
|
||||||
export.keys = key_ptrs;
|
|
||||||
|
|
||||||
// Check size allocate memory and pack the buffer
|
|
||||||
size_t required_buffer = temporary_exposure_key_export__get_packed_size(&export);
|
|
||||||
uint8_t* buffer = (uint8_t*) k_malloc(required_buffer);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
printk("Could not allocate memory for buffer\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*buffer_pointer = buffer;
|
|
||||||
if (buffer != NULL) {
|
|
||||||
size_t buf_size = temporary_exposure_key_export__pack(&export, buffer);
|
|
||||||
k_free(key_ptrs);
|
|
||||||
return buf_size;
|
|
||||||
} else {
|
|
||||||
printk("Buffer too small to serialize %d keys. %d bytes necessary\n", num_keys, required_buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int unpack_keys(uint8_t* buf, size_t buf_size) {
|
|
||||||
// Unpack protocol buffer
|
|
||||||
printk("Buf size: %d\n", buf_size);
|
|
||||||
TemporaryExposureKeyExport* export = temporary_exposure_key_export__unpack(NULL, buf_size, buf);
|
|
||||||
if (export == NULL) {
|
|
||||||
printk("error unpacking incoming message\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over new keys
|
|
||||||
for (int i = 0; i < export->n_keys; i++) {
|
|
||||||
TemporaryExposureKey* key = export->keys[i];
|
|
||||||
process_key(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over revised keys
|
|
||||||
for (int i = 0; i < export->n_revised_keys; i++) {
|
|
||||||
TemporaryExposureKey* key = export->revised_keys[i];
|
|
||||||
process_key(key);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test_unpacking(int num_keys) {
|
|
||||||
// Prepare time measurement
|
|
||||||
timing_t start_time, end_time;
|
|
||||||
uint64_t total_cycles;
|
|
||||||
uint64_t total_ns;
|
|
||||||
|
|
||||||
// Generate Buffer
|
|
||||||
uint8_t* buffer;
|
|
||||||
size_t buffer_size = generate_keys(&buffer, num_keys);
|
|
||||||
|
|
||||||
// Test unpacking
|
|
||||||
timing_init();
|
|
||||||
timing_start();
|
|
||||||
if (buffer_size) {
|
|
||||||
start_time = timing_counter_get();
|
|
||||||
unpack_keys(buffer, buffer_size);
|
|
||||||
end_time = timing_counter_get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate measurements
|
|
||||||
total_cycles = timing_cycles_get(&start_time, &end_time);
|
|
||||||
total_ns = timing_cycles_to_ns(total_cycles);
|
|
||||||
printk("\nUnpacking %d keys took %lld us\n\n", num_keys, total_ns / 1000);
|
|
||||||
timing_stop();
|
|
||||||
|
|
||||||
k_free(buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <zephyr/types.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <sys/byteorder.h>
|
|
||||||
#include <zephyr.h>
|
|
||||||
|
|
||||||
#include <bluetooth/bluetooth.h>
|
|
||||||
#include <bluetooth/conn.h>
|
|
||||||
#include <bluetooth/uuid.h>
|
|
||||||
#include <bluetooth/gatt.h>
|
|
||||||
|
|
||||||
#include "covid.h"
|
|
||||||
#include "contacts.h"
|
|
||||||
|
|
||||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
|
||||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
|
||||||
|
|
||||||
static const struct bt_data ad[] = {
|
|
||||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
|
||||||
/* My Service UUID (same as above) */
|
|
||||||
BT_DATA_BYTES(BT_DATA_UUID128_ALL,
|
|
||||||
0x06, 0x51, 0xC7, 0x9E, 0xAD, 0xA7, 0x42, 0xEA,
|
|
||||||
0x98, 0x6A, 0x9F, 0x69, 0x79, 0x0D, 0x11, 0xF2),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void connected(struct bt_conn *conn, uint8_t err)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
printk("Connection failed (err 0x%02x)\n", err);
|
|
||||||
} else {
|
|
||||||
printk("Connected\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disconnected(struct bt_conn *conn, uint8_t reason)
|
|
||||||
{
|
|
||||||
printk("Disconnected (reason 0x%02x)\n", reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct bt_conn_cb conn_callbacks = {
|
|
||||||
.connected = connected,
|
|
||||||
.disconnected = disconnected,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void auth_cancel(struct bt_conn *conn)
|
|
||||||
{
|
|
||||||
char addr[BT_ADDR_LE_STR_LEN];
|
|
||||||
|
|
||||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
||||||
|
|
||||||
printk("Pairing cancelled: %s\n", addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct bt_conn_auth_cb auth_cb_display = {
|
|
||||||
.cancel = auth_cancel,
|
|
||||||
};
|
|
||||||
|
|
||||||
int init_gatt(void)
|
|
||||||
{
|
|
||||||
bt_conn_cb_register(&conn_callbacks);
|
|
||||||
bt_conn_auth_cb_register(&auth_cb_display);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_BT
|
|
||||||
|
|
||||||
int do_gatt(void){
|
|
||||||
//printk("gatt start\n");
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
|
|
||||||
if (err) {
|
|
||||||
printk("Advertising failed to start (err %d)\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
k_sleep(K_SECONDS(1));
|
|
||||||
|
|
||||||
err = bt_le_adv_stop();
|
|
||||||
if (err) {
|
|
||||||
printk("Advertising failed to stop (err %d)\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printk("gatt end\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
int do_gatt(void) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
189
src/io.c
189
src/io.c
@ -1,189 +0,0 @@
|
|||||||
/* io.c - Application main entry point */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2020 Olaf Landsiedel
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <zephyr.h>
|
|
||||||
#include <device.h>
|
|
||||||
#include <drivers/gpio.h>
|
|
||||||
|
|
||||||
#include "covid.h"
|
|
||||||
#include "io.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Devicetree helper macro which gets the 'flags' cell from a 'gpios'
|
|
||||||
* property, or returns 0 if the property has no 'flags' cell.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FLAGS_OR_ZERO(node) \
|
|
||||||
COND_CODE_1(DT_PHA_HAS_CELL(node, gpios, flags), \
|
|
||||||
(DT_GPIO_FLAGS(node, gpios)), \
|
|
||||||
(0))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get button configuration from the devicetree sw0 alias.
|
|
||||||
*
|
|
||||||
* At least a GPIO device and pin number must be provided. The 'flags'
|
|
||||||
* cell is optional.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NATIVE_POSIX
|
|
||||||
//on my NRF board this is button 1
|
|
||||||
#define SW0_NODE DT_ALIAS(sw0)
|
|
||||||
|
|
||||||
#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
|
|
||||||
#define SW0_GPIO_LABEL DT_GPIO_LABEL(SW0_NODE, gpios)
|
|
||||||
#define SW0_GPIO_PIN DT_GPIO_PIN(SW0_NODE, gpios)
|
|
||||||
#define SW0_GPIO_FLAGS (GPIO_INPUT | FLAGS_OR_ZERO(SW0_NODE))
|
|
||||||
#else
|
|
||||||
#error "Unsupported board: sw0 devicetree alias is not defined"
|
|
||||||
#define SW0_GPIO_LABEL ""
|
|
||||||
#define SW0_GPIO_PIN 0
|
|
||||||
#define SW0_GPIO_FLAGS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//on my NRF board this is button 2
|
|
||||||
#define SW1_NODE DT_ALIAS(sw1)
|
|
||||||
|
|
||||||
#if DT_NODE_HAS_STATUS(SW1_NODE, okay)
|
|
||||||
#define SW1_GPIO_LABEL DT_GPIO_LABEL(SW1_NODE, gpios)
|
|
||||||
#define SW1_GPIO_PIN DT_GPIO_PIN(SW1_NODE, gpios)
|
|
||||||
#define SW1_GPIO_FLAGS (GPIO_INPUT | FLAGS_OR_ZERO(SW1_NODE))
|
|
||||||
#else
|
|
||||||
#error "Unsupported board: sw1 devicetree alias is not defined"
|
|
||||||
#define SW1_GPIO_LABEL ""
|
|
||||||
#define SW1_GPIO_PIN 0
|
|
||||||
#define SW1_GPIO_FLAGS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The devicetree node identifier for the "led0" alias. */
|
|
||||||
#define LED0_NODE DT_ALIAS(led0)
|
|
||||||
|
|
||||||
#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
|
|
||||||
#define LED0 DT_GPIO_LABEL(LED0_NODE, gpios)
|
|
||||||
#define PIN DT_GPIO_PIN(LED0_NODE, gpios)
|
|
||||||
#if DT_PHA_HAS_CELL(LED0_NODE, gpios, flags)
|
|
||||||
#define FLAGS DT_GPIO_FLAGS(LED0_NODE, gpios)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
/* A build error here means your board isn't set up to blink an LED. */
|
|
||||||
#error "Unsupported board: led0 devicetree alias is not defined"
|
|
||||||
#define LED0 ""
|
|
||||||
#define PIN 0
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FLAGS
|
|
||||||
#define FLAGS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static struct gpio_callback button_0_cb_data;
|
|
||||||
static struct gpio_callback button_1_cb_data;
|
|
||||||
|
|
||||||
#ifndef NATIVE_POSIX
|
|
||||||
|
|
||||||
void button_0_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins){
|
|
||||||
set_infection(true);
|
|
||||||
gpio_pin_set(dev, PIN, (int)1);
|
|
||||||
printk("Button 0 (=infected) pressed at %" PRIu32 "\n", k_cycle_get_32());
|
|
||||||
}
|
|
||||||
|
|
||||||
void button_1_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins){
|
|
||||||
set_infection(false);
|
|
||||||
gpio_pin_set(dev, PIN, (int)0);
|
|
||||||
printk("Button 1 (=healthy) pressed at %" PRIu32 "\n", k_cycle_get_32());
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_io(){
|
|
||||||
struct device *button0, *button1;
|
|
||||||
int err = 0;
|
|
||||||
//struct device *led;
|
|
||||||
|
|
||||||
button0 = device_get_binding(SW0_GPIO_LABEL);
|
|
||||||
if (button0 == NULL) {
|
|
||||||
printk("Error: didn't find %s device\n", SW0_GPIO_LABEL);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
button1 = device_get_binding(SW1_GPIO_LABEL);
|
|
||||||
if (button1 == NULL) {
|
|
||||||
printk("Error: didn't find %s device\n", SW1_GPIO_LABEL);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gpio_pin_configure(button0, SW0_GPIO_PIN, SW0_GPIO_FLAGS);
|
|
||||||
if (err != 0) {
|
|
||||||
printk("Error %d: failed to configure %s pin %d\n",
|
|
||||||
err, SW0_GPIO_LABEL, SW0_GPIO_PIN);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gpio_pin_configure(button1, SW1_GPIO_PIN, SW1_GPIO_FLAGS);
|
|
||||||
if (err != 0) {
|
|
||||||
printk("Error %d: failed to configure %s pin %d\n",
|
|
||||||
err, SW1_GPIO_LABEL, SW1_GPIO_PIN);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
err = gpio_pin_interrupt_configure(button0,
|
|
||||||
SW0_GPIO_PIN,
|
|
||||||
GPIO_INT_EDGE_TO_ACTIVE);
|
|
||||||
if (err != 0) {
|
|
||||||
printk("Error %d: failed to configure interrupt on %s pin %d\n",
|
|
||||||
err, SW0_GPIO_LABEL, SW0_GPIO_PIN);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gpio_pin_interrupt_configure(button1,
|
|
||||||
SW1_GPIO_PIN,
|
|
||||||
GPIO_INT_EDGE_TO_ACTIVE);
|
|
||||||
if (err != 0) {
|
|
||||||
printk("Error %d: failed to configure interrupt on %s pin %d\n",
|
|
||||||
err, SW1_GPIO_LABEL, SW1_GPIO_PIN);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_init_callback(&button_0_cb_data, button_0_pressed, BIT(SW0_GPIO_PIN));
|
|
||||||
gpio_add_callback(button0, &button_0_cb_data);
|
|
||||||
printk("Set up button at %s pin %d\n", SW0_GPIO_LABEL, SW0_GPIO_PIN);
|
|
||||||
|
|
||||||
gpio_init_callback(&button_1_cb_data, button_1_pressed, BIT(SW1_GPIO_PIN));
|
|
||||||
gpio_add_callback(button1, &button_1_cb_data);
|
|
||||||
printk("Set up button at %s pin %d\n", SW1_GPIO_LABEL, SW1_GPIO_PIN);
|
|
||||||
|
|
||||||
struct device *dev;
|
|
||||||
dev = device_get_binding(LED0);
|
|
||||||
if (dev == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
|
|
||||||
if (err < 0) {
|
|
||||||
printk("Error %d: failed to configure leds\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
//Turn LED 0 off
|
|
||||||
gpio_pin_set(dev, PIN, (int)0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void button_0_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void button_1_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_io(){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
74
src/main.c
74
src/main.c
@ -6,62 +6,41 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
|
||||||
#include <bluetooth/hci.h>
|
#include <bluetooth/hci.h>
|
||||||
#include <random/rand32.h>
|
#include <random/rand32.h>
|
||||||
#include <sys/printk.h>
|
#include <sys/printk.h>
|
||||||
|
|
||||||
#include "bloom.h"
|
#include "record_storage.h"
|
||||||
#include "contacts.h"
|
#include "tek_storage.h"
|
||||||
#include "covid.h"
|
#include "sync_service.h"
|
||||||
#include "covid_types.h"
|
#include "tracing.h"
|
||||||
#include "display.h"
|
|
||||||
#include "ens/storage.h"
|
|
||||||
#include "exposure-notification.h"
|
|
||||||
#include "extract_keys.h"
|
|
||||||
#include "gatt_service.h"
|
|
||||||
#include "io.h"
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
#if CONFIG_TEST_UNPACK_KEYS
|
|
||||||
for (int i = 0; i < CONFIG_TEST_UNPACK_KEYS_N; i++) {
|
|
||||||
test_unpacking(1 << i);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
printk("Starting Covid Contact Tracer\n");
|
printk("Starting Contact-Tracing Wristband...\n");
|
||||||
|
|
||||||
// first init everything
|
|
||||||
#ifndef NATIVE_POSIX
|
|
||||||
// Use custom randomization as the mbdet_tls context initialization messes with the Zeyhr BLE stack.
|
// Use custom randomization as the mbdet_tls context initialization messes with the Zeyhr BLE stack.
|
||||||
err = en_init(sys_csrand_get);
|
err = en_init(sys_csrand_get);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk("Cyrpto init failed (err %d)\n", err);
|
printk("Crypto init failed (err %d)\n", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_FLASH
|
err = record_storage_init(false);
|
||||||
err = init_record_storage(false);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
printk("init storage failed (err %d)\n", err);
|
printk("init record storage failed (err %d)\n", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = init_contacts();
|
err = tek_storage_init(false);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk("init contacts failed (err %d)\n", err);
|
printk("init key storage failed (err %d)\n", err);
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = init_io();
|
|
||||||
if (err) {
|
|
||||||
printk("Button init failed (err %d)\n", err);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_BT
|
|
||||||
/* Initialize the Bluetooth Subsystem */
|
/* Initialize the Bluetooth Subsystem */
|
||||||
err = bt_enable(NULL);
|
err = bt_enable(NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -69,29 +48,24 @@ void main(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("Bluetooth initialized\n");
|
/* Initialize the Tracing Subsystem */
|
||||||
|
err = tracing_init();
|
||||||
err = init_gatt();
|
|
||||||
if (err) {
|
if (err) {
|
||||||
printk("init gatt failed(err %d)\n", err);
|
printk("Tracing init failed (err %d)\n", err);
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = init_covid();
|
|
||||||
if (err) {
|
|
||||||
printk("init covid failed (err %d)\n", err);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("init display\n");
|
/* Initialize the Gatt Subsystem */
|
||||||
err = init_display();
|
err = sync_service_init();
|
||||||
if (err) {
|
if (err) {
|
||||||
printk("init display failed (err %d)\n", err);
|
printk("Sync Service init failed (err %d)\n", err);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("Components initialized! Starting Tracing and Gatt...\n");
|
||||||
|
|
||||||
do {
|
do {
|
||||||
do_covid();
|
tracing_run();
|
||||||
do_gatt();
|
sync_service_run();
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
@ -9,10 +9,10 @@
|
|||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <sys/printk.h>
|
#include <sys/printk.h>
|
||||||
|
|
||||||
|
void main_test(void) {
|
||||||
void main(void) {
|
|
||||||
while(1) {
|
while(1) {
|
||||||
|
|
||||||
printk("Hello World!\n");
|
printk("Hello World!\n");
|
||||||
|
k_msleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,10 @@
|
|||||||
#include <storage/flash_map.h>
|
#include <storage/flash_map.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "ens/ens_error.h"
|
#include "utility/ens_fs.h"
|
||||||
#include "ens/ens_fs.h"
|
#include "record_storage.h"
|
||||||
#include "ens/sequencenumber.h"
|
|
||||||
#include "ens/storage.h"
|
|
||||||
|
|
||||||
#define STORED_CONTACTS_INFO_ID 0
|
#define STORED_CONTACTS_INFO_ID 0
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ int save_storage_information() {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init_record_storage(bool clean) {
|
int record_storage_init(bool clean) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct flash_pages_info info;
|
struct flash_pages_info info;
|
||||||
// define the nvs file system
|
// define the nvs file system
|
||||||
@ -231,3 +230,207 @@ int get_sequence_number_interval(record_sequence_number_t* oldest, record_sequen
|
|||||||
uint32_t get_num_records() {
|
uint32_t get_num_records() {
|
||||||
return record_information.count;
|
return record_information.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
||||||
|
record_sequence_number_t* opt_start,
|
||||||
|
record_sequence_number_t* opt_end) {
|
||||||
|
// prevent any changes during initialization
|
||||||
|
int rc = get_sequence_number_interval(&iterator->sn_next, &iterator->sn_end);
|
||||||
|
if (rc == 0) {
|
||||||
|
iterator->finished = false;
|
||||||
|
|
||||||
|
// we override start and end with the optional values
|
||||||
|
if (opt_start) {
|
||||||
|
iterator->sn_next = *opt_start;
|
||||||
|
}
|
||||||
|
if (opt_end) {
|
||||||
|
iterator->sn_end = *opt_end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iterator->finished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t get_timestamp_for_sn(record_sequence_number_t sn) {
|
||||||
|
record_t rec;
|
||||||
|
if (load_record(&rec, sn) == 0) {
|
||||||
|
return rec.timestamp;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum record_timestamp_search_mode {
|
||||||
|
RECORD_TIMESTAMP_SEARCH_MODE_MIN,
|
||||||
|
RECORD_TIMESTAMP_SEARCH_MODE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an entry via binary search for the timestamp.
|
||||||
|
*
|
||||||
|
* @param record pointer to the location, where the found sn shall be stored
|
||||||
|
* @param target timestamp for which to find the nearest entry for
|
||||||
|
* @param greater flag for indicating, if the loaded sn shall correspond to a greater (1) or smaller (0) timestamp
|
||||||
|
*/
|
||||||
|
int find_sn_via_binary_search(record_sequence_number_t* sn_dest,
|
||||||
|
uint32_t target,
|
||||||
|
enum record_timestamp_search_mode search_mode) {
|
||||||
|
record_sequence_number_t start_sn;
|
||||||
|
record_sequence_number_t end_sn;
|
||||||
|
|
||||||
|
// prevent any changes during binary search initialization
|
||||||
|
|
||||||
|
int rc = get_sequence_number_interval(&start_sn, &end_sn);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
record_sequence_number_t last_sn =
|
||||||
|
start_sn; // used to check if ran into issues, e.g. could not load the entry or rounding errors
|
||||||
|
|
||||||
|
while (!sn_equal(start_sn, end_sn)) {
|
||||||
|
// calculate the sn in the middle between start and end
|
||||||
|
record_sequence_number_t cur_sn = sn_get_middle_sn(start_sn, end_sn);
|
||||||
|
|
||||||
|
if (sn_equal(cur_sn, last_sn)) {
|
||||||
|
// if we already checked this entry -> we reduce our boundaries and try again
|
||||||
|
// this also solves issues with rounding
|
||||||
|
// TODO: This is not the best way...
|
||||||
|
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
||||||
|
int64_t start_ts = get_timestamp_for_sn(start_sn);
|
||||||
|
if (start_ts == -1 || start_ts < target) {
|
||||||
|
// we could not load this entry or this entry is strictly smaller than our target
|
||||||
|
start_sn = sn_increment(start_sn); // we can safely increment as start_sn < end_sn
|
||||||
|
} else {
|
||||||
|
// we actually found the wanted entry!
|
||||||
|
end_sn = start_sn; // this will break our loop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we search for the biggest value among them
|
||||||
|
int64_t end_ts = get_timestamp_for_sn(end_sn);
|
||||||
|
if (end_ts == -1 || end_ts > target) {
|
||||||
|
// we could not load this entry or this entry is strictly bigger than our target
|
||||||
|
end_sn = sn_decrement(end_sn); // we can safely decrement as start_sn < end_sn
|
||||||
|
} else {
|
||||||
|
// we actually found the wanted entry!
|
||||||
|
start_sn = end_sn; // this will break our loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int64_t mid_ts = get_timestamp_for_sn(cur_sn);
|
||||||
|
|
||||||
|
if (mid_ts >= 0) {
|
||||||
|
if (target < mid_ts) {
|
||||||
|
end_sn = cur_sn;
|
||||||
|
} else if (target > mid_ts) {
|
||||||
|
start_sn = cur_sn;
|
||||||
|
} else {
|
||||||
|
// target == mid_ts
|
||||||
|
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
||||||
|
// we search for the smallest value among them -> look before this item
|
||||||
|
end_sn = cur_sn;
|
||||||
|
} else {
|
||||||
|
// we search for the biggest value among them -> look after this item
|
||||||
|
start_sn = cur_sn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// some errors -> we keep the current sn and try to narrow our boundaries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_sn = cur_sn;
|
||||||
|
}
|
||||||
|
|
||||||
|
*sn_dest = start_sn; // == end_sn
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This iterator does neither check if the sequence numbers wrapped around while iteration. As a result, first
|
||||||
|
// results could have later timestamps than following entries
|
||||||
|
int ens_records_iterator_init_timerange(record_iterator_t* iterator, time_t* ts_start, time_t* ts_end) {
|
||||||
|
record_sequence_number_t oldest_sn = 0;
|
||||||
|
record_sequence_number_t newest_sn = 0;
|
||||||
|
|
||||||
|
// assure that *ts_end > *ts_start
|
||||||
|
if (ts_start && ts_end && *ts_end < *ts_start) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts_start) {
|
||||||
|
int rc = find_sn_via_binary_search(&oldest_sn, *ts_start, RECORD_TIMESTAMP_SEARCH_MODE_MIN);
|
||||||
|
if (rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oldest_sn = get_oldest_sequence_number();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts_end) {
|
||||||
|
int rc = find_sn_via_binary_search(&newest_sn, *ts_end, RECORD_TIMESTAMP_SEARCH_MODE_MAX);
|
||||||
|
if (rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newest_sn = get_latest_sequence_number();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ens_records_iterator_init_range(iterator, &oldest_sn, &newest_sn);
|
||||||
|
}
|
||||||
|
|
||||||
|
record_t* ens_records_iterator_next(record_iterator_t* iter) {
|
||||||
|
record_t* next = NULL;
|
||||||
|
|
||||||
|
while (next == NULL && !iter->finished) {
|
||||||
|
record_t contact;
|
||||||
|
// try to load the next contact
|
||||||
|
int res = load_record(&contact, iter->sn_next);
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
next = &iter->current;
|
||||||
|
memcpy(next, &contact, sizeof(record_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sn_equal(iter->sn_next, iter->sn_end)) {
|
||||||
|
iter->finished = true; // this iterator will finish after this execution
|
||||||
|
} else {
|
||||||
|
// increase the current sn
|
||||||
|
iter->sn_next = sn_increment(iter->sn_next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ens_record_iterator_clear(record_iterator_t* iter) {
|
||||||
|
// clear all relevant fields in the iterator
|
||||||
|
iter->finished = true;
|
||||||
|
iter->sn_next = 0;
|
||||||
|
iter->sn_end = 0;
|
||||||
|
memset(&iter->current, 0, sizeof(iter->current));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata) {
|
||||||
|
record_t* cur = ens_records_iterator_next(iter);
|
||||||
|
bool cont = true;
|
||||||
|
|
||||||
|
while (cur != NULL && cont) {
|
||||||
|
int cb_res = cb(cur, userdata);
|
||||||
|
if (cb_res == ENS_RECORD_ITER_STOP) {
|
||||||
|
cont = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cont) {
|
||||||
|
cb(NULL, userdata); // we call the callback one last time but with null data
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
27
src/sync_service.c
Normal file
27
src/sync_service.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Olaf Landsiedel
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/printk.h>
|
||||||
|
#include <sys/byteorder.h>
|
||||||
|
#include <zephyr.h>
|
||||||
|
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#include <bluetooth/conn.h>
|
||||||
|
#include <bluetooth/uuid.h>
|
||||||
|
#include <bluetooth/gatt.h>
|
||||||
|
|
||||||
|
|
||||||
|
int sync_service_init(void) {
|
||||||
|
return 0; // TODO!
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync_service_run(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
26
src/tek_storage.c
Normal file
26
src/tek_storage.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "tek_storage.h"
|
||||||
|
|
||||||
|
int tek_storage_init(bool clean) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tek_storage_add(tek_t* src) {
|
||||||
|
// TODO
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tek_storage_delete(tek_t* src) {
|
||||||
|
// TODO
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 0 on success, else non zero (if none available)
|
||||||
|
* TODO: This is not really implemented...
|
||||||
|
*/
|
||||||
|
int tek_storage_get_latest_at_ts(tek_t* dest, uint32_t timestamp) {
|
||||||
|
dest->timestamp = timestamp;
|
||||||
|
memset(&dest->tek, 0, sizeof(dest->tek));
|
||||||
|
return 0;
|
||||||
|
}
|
@ -15,21 +15,29 @@
|
|||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
|
||||||
#include "exposure-notification.h"
|
#include "exposure-notification.h"
|
||||||
#include "covid_types.h"
|
#include "tracing.h"
|
||||||
#include "contacts.h"
|
#include "record_storage.h"
|
||||||
#include "covid.h"
|
|
||||||
#include "ens/storage.h"
|
|
||||||
|
|
||||||
#include "util.h"
|
#include "utility/util.h"
|
||||||
|
|
||||||
|
#define COVID_ENS (0xFD6F)
|
||||||
|
|
||||||
|
typedef ENIntervalIdentifier ENIntervalIdentifier;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct period{
|
||||||
|
ENPeriodKey periodKey;
|
||||||
|
ENIntervalNumber periodInterval;
|
||||||
|
} __packed period_t;
|
||||||
|
|
||||||
#ifndef COVID_MEASURE_PERFORMANCE
|
|
||||||
#define COVID_MEASURE_PERFORMANCE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct covid_adv_svd
|
typedef struct covid_adv_svd
|
||||||
{
|
{
|
||||||
uint16_t ens;
|
uint16_t ens;
|
||||||
rolling_proximity_identifier_t rolling_proximity_identifier;
|
ENIntervalIdentifier rolling_proximity_identifier;
|
||||||
associated_encrypted_metadata_t associated_encrypted_metadata;
|
associated_encrypted_metadata_t associated_encrypted_metadata;
|
||||||
} __packed covid_adv_svd_t;
|
} __packed covid_adv_svd_t;
|
||||||
|
|
||||||
@ -40,8 +48,6 @@ const static bt_metadata_t bt_metadata = {
|
|||||||
.rsv2 = 0,
|
.rsv2 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define COVID_ENS (0xFD6F)
|
|
||||||
|
|
||||||
static covid_adv_svd_t covid_adv_svd = {
|
static covid_adv_svd_t covid_adv_svd = {
|
||||||
.ens = COVID_ENS,
|
.ens = COVID_ENS,
|
||||||
//do not initialiuze the rest of the packet, will write this later
|
//do not initialiuze the rest of the packet, will write this later
|
||||||
@ -80,15 +86,15 @@ static void scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, str
|
|||||||
covid_adv_svd_t *rx_adv = (covid_adv_svd_t *)buf->data;
|
covid_adv_svd_t *rx_adv = (covid_adv_svd_t *)buf->data;
|
||||||
if (rx_adv->ens == COVID_ENS)
|
if (rx_adv->ens == COVID_ENS)
|
||||||
{
|
{
|
||||||
printk("Attempting to store contact...\n");
|
printk("Attempting to store record...\n");
|
||||||
record_t contact;
|
record_t record;
|
||||||
uint32_t timestamp = time_get_unix_seconds();
|
uint32_t timestamp = time_get_unix_seconds();
|
||||||
memcpy(&contact.rssi, &rssi, sizeof(contact.rssi));
|
memcpy(&record.rssi, &rssi, sizeof(record.rssi));
|
||||||
memcpy(&contact.associated_encrypted_metadata, &rx_adv->associated_encrypted_metadata, sizeof(contact.associated_encrypted_metadata));
|
memcpy(&record.associated_encrypted_metadata, &rx_adv->associated_encrypted_metadata, sizeof(record.associated_encrypted_metadata));
|
||||||
memcpy(&contact.rolling_proximity_identifier, &rx_adv->rolling_proximity_identifier, sizeof(contact.rolling_proximity_identifier));
|
memcpy(&record.rolling_proximity_identifier, &rx_adv->rolling_proximity_identifier, sizeof(record.rolling_proximity_identifier));
|
||||||
memcpy(&contact.timestamp, ×tamp, sizeof(contact.timestamp));
|
memcpy(&record.timestamp, ×tamp, sizeof(record.timestamp));
|
||||||
int rc = register_record(&contact);
|
int rc = add_record(&record);
|
||||||
printk("Contact stored (err %d)\n", rc);
|
printk("Record stored (err %d)\n", rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
net_buf_simple_pull(buf, len - 1); //consume the rest, note we already consumed one byte via net_buf_simple_pull_u8(buf)
|
net_buf_simple_pull(buf, len - 1); //consume the rest, note we already consumed one byte via net_buf_simple_pull_u8(buf)
|
||||||
@ -167,120 +173,6 @@ static void new_period_key(time_t currentTime)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COVID_MEASURE_PERFORMANCE
|
|
||||||
static void measure_performance()
|
|
||||||
{
|
|
||||||
|
|
||||||
u32_t runs = 100;
|
|
||||||
u32_t start_time;
|
|
||||||
u32_t cycles_spent;
|
|
||||||
u32_t nanoseconds_spent;
|
|
||||||
|
|
||||||
ENPeriodKey pk;
|
|
||||||
|
|
||||||
ENPeriodIdentifierKey pik;
|
|
||||||
ENIntervalIdentifier intervalIdentifier;
|
|
||||||
ENIntervalNumber intervalNumber = 2642976;
|
|
||||||
ENIntervalIdentifier id;
|
|
||||||
ENPeriodMetadataEncryptionKey pmek;
|
|
||||||
unsigned char metadata[4] = {0x40, 0x08, 0x00, 0x00};
|
|
||||||
unsigned char encryptedMetadata[sizeof(metadata)] = {0};
|
|
||||||
|
|
||||||
printk("\n----------------------------------------\n");
|
|
||||||
printk("MEASURING PERFORMANCE\n");
|
|
||||||
|
|
||||||
// Measure en_generate_period_key
|
|
||||||
{
|
|
||||||
start_time = k_cycle_get_32();
|
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++)
|
|
||||||
{
|
|
||||||
en_generate_period_key(&pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
|
||||||
printk("en_generate_period_key %d ns\n", nanoseconds_spent/runs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measure en_derive_period_identifier_key
|
|
||||||
{
|
|
||||||
start_time = k_cycle_get_32();
|
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++)
|
|
||||||
{
|
|
||||||
en_derive_period_identifier_key(&pik, &pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
|
||||||
printk("en_derive_period_identifier_key %d ns\n", nanoseconds_spent/runs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measure en_derive_interval_identifier
|
|
||||||
{
|
|
||||||
start_time = k_cycle_get_32();
|
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++)
|
|
||||||
{
|
|
||||||
en_derive_interval_identifier(&intervalIdentifier, &pik, intervalNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
|
||||||
printk("en_derive_interval_identifier %d ns\n", nanoseconds_spent/runs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measure en_derive_period_metadata_encryption_key
|
|
||||||
{
|
|
||||||
start_time = k_cycle_get_32();
|
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++)
|
|
||||||
{
|
|
||||||
en_derive_period_metadata_encryption_key(&pmek, &pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
|
||||||
printk("en_derive_period_metadata_encryption_key %d ns\n", nanoseconds_spent/runs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measure en_encrypt_interval_metadata
|
|
||||||
{
|
|
||||||
start_time = k_cycle_get_32();
|
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++)
|
|
||||||
{
|
|
||||||
en_encrypt_interval_metadata(&pmek, &intervalIdentifier, metadata, encryptedMetadata, sizeof(metadata));
|
|
||||||
}
|
|
||||||
|
|
||||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
|
||||||
printk("en_encrypt_interval_metadata %d ns\n", nanoseconds_spent/runs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measure Full key generation
|
|
||||||
{
|
|
||||||
start_time = k_cycle_get_32();
|
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++)
|
|
||||||
{
|
|
||||||
ENPeriodKey pk;
|
|
||||||
en_generate_period_key(&pk);
|
|
||||||
ENPeriodIdentifierKey ik;
|
|
||||||
en_derive_period_identifier_key(&ik, &pk);
|
|
||||||
|
|
||||||
for(int iv = 0; iv < EN_TEK_ROLLING_PERIOD; iv++) {
|
|
||||||
ENIntervalNumber intervalNumber = en_get_interval_number(iv);
|
|
||||||
ENIntervalIdentifier id;
|
|
||||||
en_derive_interval_identifier(&id, &ik, intervalNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
|
||||||
printk("Full key generation %d ns\n", nanoseconds_spent/runs);
|
|
||||||
}
|
|
||||||
|
|
||||||
printk("\FINISHED\n");
|
|
||||||
printk("----------------------------------------\n\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//To be called when new keys are needed
|
//To be called when new keys are needed
|
||||||
static void check_keys(struct k_work *work)
|
static void check_keys(struct k_work *work)
|
||||||
{
|
{
|
||||||
@ -314,10 +206,10 @@ static void check_keys(struct k_work *work)
|
|||||||
printk("Time: %u, ", currentTime);
|
printk("Time: %u, ", currentTime);
|
||||||
printk("Interval: %u, ", currentInterval);
|
printk("Interval: %u, ", currentInterval);
|
||||||
printk("TEK: ");
|
printk("TEK: ");
|
||||||
print_rpi((rolling_proximity_identifier_t *)&periods[current_period_index].periodKey);
|
print_rpi((ENIntervalIdentifier *)&periods[current_period_index].periodKey);
|
||||||
printk(", ");
|
printk(", ");
|
||||||
printk("RPI: ");
|
printk("RPI: ");
|
||||||
print_rpi((rolling_proximity_identifier_t *)&intervalIdentifier);
|
print_rpi((ENIntervalIdentifier *)&intervalIdentifier);
|
||||||
printk(", ");
|
printk(", ");
|
||||||
printk("AEM: ");
|
printk("AEM: ");
|
||||||
print_aem(&encryptedMetadata);
|
print_aem(&encryptedMetadata);
|
||||||
@ -325,7 +217,7 @@ static void check_keys(struct k_work *work)
|
|||||||
|
|
||||||
// lock, so we can be sure to only advertise correct packages
|
// lock, so we can be sure to only advertise correct packages
|
||||||
k_mutex_lock(&key_change_lock, K_FOREVER);
|
k_mutex_lock(&key_change_lock, K_FOREVER);
|
||||||
memcpy(&covid_adv_svd.rolling_proximity_identifier, &intervalIdentifier, sizeof(rolling_proximity_identifier_t));
|
memcpy(&covid_adv_svd.rolling_proximity_identifier, &intervalIdentifier, sizeof(ENIntervalIdentifier));
|
||||||
memcpy(&covid_adv_svd.associated_encrypted_metadata, &encryptedMetadata, sizeof(associated_encrypted_metadata_t));
|
memcpy(&covid_adv_svd.associated_encrypted_metadata, &encryptedMetadata, sizeof(associated_encrypted_metadata_t));
|
||||||
k_mutex_unlock(&key_change_lock);
|
k_mutex_unlock(&key_change_lock);
|
||||||
|
|
||||||
@ -351,7 +243,7 @@ static const struct bt_le_scan_param scan_param = {
|
|||||||
|
|
||||||
#define KEY_CHECK_INTERVAL (K_MSEC(EN_INTERVAL_LENGTH * 1000 / 10))
|
#define KEY_CHECK_INTERVAL (K_MSEC(EN_INTERVAL_LENGTH * 1000 / 10))
|
||||||
|
|
||||||
int init_covid()
|
int tracing_init()
|
||||||
{
|
{
|
||||||
|
|
||||||
#if COVID_MEASURE_PERFORMANCE
|
#if COVID_MEASURE_PERFORMANCE
|
||||||
@ -383,7 +275,7 @@ int init_covid()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_covid()
|
int tracing_run()
|
||||||
{
|
{
|
||||||
//printk("covid start\n");
|
//printk("covid start\n");
|
||||||
|
|
||||||
@ -445,17 +337,3 @@ period_t *get_period_if_infected(unsigned int id, size_t *size)
|
|||||||
*size = sizeof(period_t);
|
*size = sizeof(period_t);
|
||||||
return &periods[id];
|
return &periods[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_index_by_interval(ENIntervalNumber periodInterval)
|
|
||||||
{
|
|
||||||
int index = 0;
|
|
||||||
while (index < NUM_PERIOD_KEYS || index < period_cnt)
|
|
||||||
{
|
|
||||||
if (periods[index].periodInterval == periodInterval)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
#include "time.h"
|
|
||||||
#include <zephyr.h>
|
|
||||||
// TODO: this is very basic atm
|
|
||||||
uint32_t time_get_unix_seconds() {
|
|
||||||
return k_uptime_get() / 1000;
|
|
||||||
}
|
|
@ -6,8 +6,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/crc.h>
|
#include <sys/crc.h>
|
||||||
|
|
||||||
#include "ens/ens_error.h"
|
#include "utility/ens_fs.h"
|
||||||
#include "ens/ens_fs.h"
|
|
||||||
|
|
||||||
#define SEED 42
|
#define SEED 42
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
#include "ens/sequencenumber.h"
|
#include "utility/sequencenumber.h"
|
||||||
|
|
||||||
#define SN_MASK 0xffffff
|
#define SN_MASK 0xffffff
|
||||||
|
|
27
src/utility/util.c
Normal file
27
src/utility/util.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "time.h"
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include "utility/util.h"
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: this is very basic atm
|
||||||
|
uint32_t time_get_unix_seconds() {
|
||||||
|
return k_uptime_get() / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_key(_ENBaseKey* key) {
|
||||||
|
for (int i = 0; i < sizeof(key->b); i++) {
|
||||||
|
printk("%02x", key->b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_rpi(ENIntervalIdentifier* rpi) {
|
||||||
|
for (int i = 0; i < sizeof(ENIntervalIdentifier); i++) {
|
||||||
|
printk("%02x", rpi->b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_aem(associated_encrypted_metadata_t* aem) {
|
||||||
|
for (int i = 0; i < sizeof(associated_encrypted_metadata_t); i++) {
|
||||||
|
printk("%02x", aem->data[i]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user