Increase cvend reliability
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,5 +3,6 @@ obj/
|
||||
.cache
|
||||
.build
|
||||
.config.old
|
||||
.gdb_history
|
||||
build.log
|
||||
include
|
||||
|
||||
2
Makefile
2
Makefile
@@ -12,7 +12,7 @@ else
|
||||
CFLAGS := $(CFLAGS) -lX11
|
||||
endif
|
||||
|
||||
TARGETS := pm3-lvgl cvend_test audio_test
|
||||
TARGETS := pm3-lvgl cvend_test cvend_decode audio_test
|
||||
EXES := $(patsubst %,bin/%,$(TARGETS))
|
||||
SRCS := $(shell find src inc -type f -iname '*.c')
|
||||
OBJS := $(patsubst src/%.c,obj/%.o,$(patsubst inc/%.c,obj/lib/%.o,$(SRCS)))
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
extra/README.md
Normal file
3
extra/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
These are pulled from the pm3 wiki.
|
||||
|
||||
<https://wiki.pm3.dev/cvend#cvend_protocol_notes>
|
||||
BIN
extra/startup-host.bin
Normal file
BIN
extra/startup-host.bin
Normal file
Binary file not shown.
142
extra/startup-host.hex
Normal file
142
extra/startup-host.hex
Normal file
@@ -0,0 +1,142 @@
|
||||
0x00
|
||||
0x00
|
||||
0xBC
|
||||
0x01
|
||||
0x00
|
||||
0xEA
|
||||
0x00
|
||||
0x02
|
||||
0xA6
|
||||
0x01
|
||||
0x00
|
||||
0x41
|
||||
0xDC
|
||||
0x3D
|
||||
0xA7
|
||||
0xBC
|
||||
0x02
|
||||
0x00
|
||||
0x02
|
||||
0x00
|
||||
0x00
|
||||
0xB6
|
||||
0xBC
|
||||
0x03
|
||||
0x00
|
||||
0xE4
|
||||
0x00
|
||||
0x04
|
||||
0x0C
|
||||
0x00
|
||||
0x05
|
||||
0x01
|
||||
0x01
|
||||
0xDF
|
||||
0xE3
|
||||
0x6C
|
||||
0xB6
|
||||
0xBC
|
||||
0x04
|
||||
0x00
|
||||
0xE4
|
||||
0x00
|
||||
0x04
|
||||
0x5D
|
||||
0x00
|
||||
0x07
|
||||
0x01
|
||||
0x01
|
||||
0xB1
|
||||
0x37
|
||||
0xE8
|
||||
0xB5
|
||||
0xBC
|
||||
0x05
|
||||
0x00
|
||||
0xE4
|
||||
0x00
|
||||
0x04
|
||||
0x90
|
||||
0x00
|
||||
0x0A
|
||||
0x01
|
||||
0x01
|
||||
0xE2
|
||||
0xA4
|
||||
0x30
|
||||
0xBD
|
||||
0xBC
|
||||
0x06
|
||||
0x00
|
||||
0xAA
|
||||
0x00
|
||||
0x04
|
||||
0x1B
|
||||
0x69
|
||||
0xA2
|
||||
0x95
|
||||
0x6C
|
||||
0x48
|
||||
0x42
|
||||
0x5B
|
||||
0x0A
|
||||
0xBC
|
||||
0x07
|
||||
0x00
|
||||
0xE8
|
||||
0x00
|
||||
0x05
|
||||
0xF6
|
||||
0x04
|
||||
0xFE
|
||||
0x0A
|
||||
0x00
|
||||
0x00
|
||||
0x60
|
||||
0x4A
|
||||
0x73
|
||||
0xA7
|
||||
0xBC
|
||||
0x08
|
||||
0x00
|
||||
0x02
|
||||
0x00
|
||||
0x00
|
||||
0x0B
|
||||
0xBC
|
||||
0x09
|
||||
0x00
|
||||
0x98
|
||||
0x00
|
||||
0x1A
|
||||
0x67
|
||||
0x00
|
||||
0x12
|
||||
0x2F
|
||||
0x68
|
||||
0x6F
|
||||
0x6D
|
||||
0x65
|
||||
0x2F
|
||||
0x61
|
||||
0x70
|
||||
0x70
|
||||
0x30
|
||||
0x2F
|
||||
0x76
|
||||
0x65
|
||||
0x72
|
||||
0x73
|
||||
0x69
|
||||
0x6F
|
||||
0x6E
|
||||
0x00
|
||||
0x00
|
||||
0x00
|
||||
0x00
|
||||
0x00
|
||||
0x64
|
||||
0xF8
|
||||
0x78
|
||||
0x80
|
||||
0x2B
|
||||
BIN
extra/startup-reader.bin
Normal file
BIN
extra/startup-reader.bin
Normal file
Binary file not shown.
4483
extra/startup-reader.hex
Normal file
4483
extra/startup-reader.hex
Normal file
File diff suppressed because it is too large
Load Diff
11
inc/cvend.h
11
inc/cvend.h
@@ -77,11 +77,14 @@ typedef struct cvend_packet {
|
||||
|
||||
const char *stringify_msg_type(uint8_t msg_type);
|
||||
|
||||
void cvend_init(const char *path);
|
||||
cvend_packet *cvend_read();
|
||||
cvend_packet *cvend_read_type(uint8_t msg_type);
|
||||
void cvend_write(uint8_t msg_type, uint8_t *msg_data, uint16_t msg_len);
|
||||
void cvend_init();
|
||||
void cvend_lock();
|
||||
void cvend_unlock();
|
||||
cvend_packet *cvend_read(FILE *file);
|
||||
cvend_packet *cvend_read_type(FILE *file, uint8_t msg_type);
|
||||
void cvend_write(FILE *file, uint8_t msg_type, uint8_t *msg_data, uint16_t msg_len);
|
||||
void cvend_free(cvend_packet *packet);
|
||||
void print_packet(cvend_packet *packet);
|
||||
void print_packet_short(char *brief, cvend_packet *packet);
|
||||
|
||||
#endif /* end of include guard: CVEND_H_WNGPTXM7 */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
typedef void (*nfc_cb)(uint8_t status, uint8_t *version, uint16_t version_size,
|
||||
uint8_t *data, uint16_t data_size);
|
||||
|
||||
void nfc_init(const char *path);
|
||||
void nfc_reset(const char *path);
|
||||
void *nfc_handle(void *data);
|
||||
|
||||
#endif /* end of include guard: NFC_H_3196CYAP */
|
||||
|
||||
71
src/cvend.c
71
src/cvend.c
@@ -7,8 +7,6 @@
|
||||
#include "crc32.h"
|
||||
#include "cvend.h"
|
||||
|
||||
const char *cvend_path;
|
||||
FILE *file;
|
||||
pthread_mutex_t cvend_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
int last_seq = 0;
|
||||
|
||||
@@ -112,6 +110,14 @@ const char *stringify_msg_type(uint8_t msg_type)
|
||||
}
|
||||
}
|
||||
|
||||
void cvend_lock() {
|
||||
pthread_mutex_lock(&cvend_mutex);
|
||||
}
|
||||
|
||||
void cvend_unlock() {
|
||||
pthread_mutex_unlock(&cvend_mutex);
|
||||
}
|
||||
|
||||
void calc_hdr_crc(cvend_packet *packet)
|
||||
{
|
||||
packet->magic = 0xbc;
|
||||
@@ -128,25 +134,23 @@ void calc_msg_crc(cvend_packet *packet)
|
||||
packet->msg_crc = 0;
|
||||
}
|
||||
|
||||
void cvend_init(const char *path)
|
||||
void cvend_init()
|
||||
{
|
||||
cvend_path = path;
|
||||
file = fopen(path, "wb+");
|
||||
}
|
||||
|
||||
cvend_packet *cvend_read()
|
||||
cvend_packet *cvend_read(FILE *file)
|
||||
{
|
||||
pthread_mutex_lock(&cvend_mutex);
|
||||
cvend_lock();
|
||||
uint8_t buf = 0x00;
|
||||
uint8_t res = 0;
|
||||
while (buf != 0xbc) {
|
||||
res = fread(&buf, 1, 1, file);
|
||||
if (res == 0) {
|
||||
fclose(file);
|
||||
file = fopen(cvend_path, "wb+");
|
||||
cvend_unlock();
|
||||
return NULL;
|
||||
}
|
||||
if (buf != 0xbc) {
|
||||
printf("bad magic char: %x\n", buf);
|
||||
printf("[WARN] bad magic char: %x\n", buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,35 +163,41 @@ cvend_packet *cvend_read()
|
||||
fread(&packet->hdr_crc, 1, 1, file);
|
||||
|
||||
packet->msg_data = malloc(packet->msg_len);
|
||||
fread(packet->msg_data, 1, packet->msg_len, file);
|
||||
uint16_t read = fread(packet->msg_data, 1, packet->msg_len, file);
|
||||
if (read < packet->msg_len) {
|
||||
printf("[ERROR] bad packet length\n");
|
||||
cvend_free(packet);
|
||||
return NULL;
|
||||
}
|
||||
if (packet->msg_type & 0x80)
|
||||
fread(&packet->msg_crc, 1, 4, file);
|
||||
else
|
||||
packet->msg_crc = 0;
|
||||
pthread_mutex_unlock(&cvend_mutex);
|
||||
cvend_unlock();
|
||||
|
||||
if (packet->msg_type != MTYPE_HEARTBEAT) {
|
||||
printf("RECEIVED:\n");
|
||||
print_packet(packet);
|
||||
print_packet_short("received", packet);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
cvend_packet *cvend_read_type(uint8_t msg_type)
|
||||
cvend_packet *cvend_read_type(FILE *file, uint8_t msg_type)
|
||||
{
|
||||
cvend_packet *packet = NULL;
|
||||
do {
|
||||
if (packet)
|
||||
cvend_free(packet);
|
||||
packet = cvend_read();
|
||||
packet = cvend_read(file);
|
||||
if (!packet)
|
||||
return NULL;
|
||||
} while (packet->msg_type != msg_type);
|
||||
return packet;
|
||||
}
|
||||
|
||||
void cvend_write(uint8_t msg_type, uint8_t *msg_data,
|
||||
void cvend_write(FILE *file, uint8_t msg_type, uint8_t *msg_data,
|
||||
uint16_t msg_len)
|
||||
{
|
||||
pthread_mutex_lock(&cvend_mutex);
|
||||
cvend_lock();
|
||||
cvend_packet packet;
|
||||
packet.seq = ++last_seq;
|
||||
packet.flags = 0;
|
||||
@@ -197,8 +207,7 @@ void cvend_write(uint8_t msg_type, uint8_t *msg_data,
|
||||
calc_hdr_crc(&packet);
|
||||
calc_msg_crc(&packet);
|
||||
|
||||
int res = fwrite(&packet.magic, 1, 1, file);
|
||||
printf("wrote %i\n", res);
|
||||
fwrite(&packet.magic, 1, 1, file);
|
||||
fwrite(&packet.seq, 1, 1, file);
|
||||
fwrite(&packet.flags, 1, 1, file);
|
||||
fwrite(&packet.msg_type, 1, 1, file);
|
||||
@@ -209,13 +218,14 @@ void cvend_write(uint8_t msg_type, uint8_t *msg_data,
|
||||
if (packet.msg_type & 0x80)
|
||||
fwrite(&packet.msg_crc, 1, 4, file);
|
||||
|
||||
pthread_mutex_unlock(&cvend_mutex);
|
||||
printf("SENT:\n");
|
||||
print_packet(&packet);
|
||||
cvend_unlock();
|
||||
print_packet_short("sent", &packet);
|
||||
}
|
||||
|
||||
void cvend_free(cvend_packet *packet)
|
||||
{
|
||||
if (!packet)
|
||||
return;
|
||||
free(packet->msg_data);
|
||||
free(packet);
|
||||
}
|
||||
@@ -238,3 +248,18 @@ void print_packet(cvend_packet *packet)
|
||||
printf("\n");
|
||||
printf("msg_crc = %u\n\n", packet->msg_crc);
|
||||
}
|
||||
|
||||
void print_packet_short(char *brief, cvend_packet *packet)
|
||||
{
|
||||
printf("[INFO] (cvend) %s: ", brief);
|
||||
printf("%s ", stringify_msg_type(packet->msg_type));
|
||||
printf("(%02X)", packet->msg_type);
|
||||
printf(", ");
|
||||
if (packet->msg_type == MTYPE_LOG) {
|
||||
printf("%s", packet->msg_data);
|
||||
} else {
|
||||
for (uint16_t i = 0; i < packet->msg_len; i++)
|
||||
printf("%02x ", packet->msg_data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
22
src/cvend_decode.c
Normal file
22
src/cvend_decode.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "cvend.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *path = argc > 1 ? argv[1] : "extra/startup-reader.bin";
|
||||
FILE *file = fopen(path, "rb");
|
||||
|
||||
if (!file) {
|
||||
printf("Failed to open %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cvend_init();
|
||||
|
||||
cvend_packet *packet = cvend_read(file);
|
||||
while (packet) {
|
||||
// print_packet(packet);
|
||||
cvend_free(packet);
|
||||
packet = cvend_read(file);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *file = argc > 1 ? argv[1] : "/dev/ttymxc3";
|
||||
FILE *file = fopen(argc > 1 ? argv[1] : "/dev/ttymxc3", "wb+");
|
||||
uint8_t desfire_enable[] = { 0x00, CTYPE_DESFIRE, 0x01, FUNC_ENABLE };
|
||||
// uint8_t desfire_get_version[] = { 0x60 };
|
||||
uint8_t desfire_select_application[] = { 0x5a, 0xF2, 0x10, 0xE0 };
|
||||
@@ -10,28 +10,28 @@ int main(int argc, char *argv[])
|
||||
uint8_t desfire_read[] = { 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t desfire_free[] = { 0x6e };
|
||||
|
||||
cvend_init(file);
|
||||
cvend_write(MTYPE_PROX_CARD_FUNCTION, desfire_enable, 4);
|
||||
cvend_init();
|
||||
cvend_write(file, MTYPE_PROX_CARD_FUNCTION, desfire_enable, 4);
|
||||
|
||||
while (1) {
|
||||
cvend_packet *packet;
|
||||
packet = cvend_read();
|
||||
packet = cvend_read(file);
|
||||
|
||||
// if (packet->msg_type != MTYPE_HEARTBEAT)
|
||||
print_packet(packet);
|
||||
|
||||
if (packet->msg_type == MTYPE_DESFIRE_READ) {
|
||||
//cvend_write(MTYPE_DESFIRE_INTERACT, desfire_get_version, 1);
|
||||
cvend_write(MTYPE_DESFIRE_COMMAND, desfire_select_application, 4);
|
||||
cvend_write(file, MTYPE_DESFIRE_COMMAND, desfire_select_application, 4);
|
||||
cvend_packet *response;
|
||||
do {
|
||||
response = cvend_read();
|
||||
response = cvend_read(file);
|
||||
} while (!response);
|
||||
print_packet(response);
|
||||
cvend_write(MTYPE_DESFIRE_COMMAND, desfire_fid_list, 1);
|
||||
cvend_write(file, MTYPE_DESFIRE_COMMAND, desfire_fid_list, 1);
|
||||
cvend_free(response);
|
||||
cvend_write(MTYPE_DESFIRE_COMMAND, desfire_read, 8);
|
||||
cvend_write(MTYPE_DESFIRE_COMMAND, desfire_free, 1);
|
||||
cvend_write(file, MTYPE_DESFIRE_COMMAND, desfire_read, 8);
|
||||
cvend_write(file, MTYPE_DESFIRE_COMMAND, desfire_free, 1);
|
||||
}
|
||||
|
||||
cvend_free(packet);
|
||||
|
||||
105
src/nfc.c
105
src/nfc.c
@@ -1,23 +1,68 @@
|
||||
#include "cvend.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <poll.h>
|
||||
#include "nfc.h"
|
||||
|
||||
void nfc_init(const char *path)
|
||||
FILE *nfc_stream = NULL;
|
||||
const char *nfc_path = NULL;
|
||||
|
||||
void nfc_reset(const char *path)
|
||||
{
|
||||
uint8_t desfire_enable[] = { 0x00, CTYPE_DESFIRE, 0x01, FUNC_ENABLE };
|
||||
cvend_packet *packet;
|
||||
struct pollfd stream_poll;
|
||||
|
||||
cvend_init(path);
|
||||
cvend_write(MTYPE_PROX_CARD_FUNCTION, desfire_enable, 4);
|
||||
if (nfc_stream)
|
||||
fclose(nfc_stream);
|
||||
nfc_stream = fopen(path, "wb+");
|
||||
|
||||
stream_poll.fd = fileno(nfc_stream);
|
||||
stream_poll.events = POLLIN;
|
||||
|
||||
cvend_init();
|
||||
printf("[INFO] checking for signs of life\n");
|
||||
cvend_write(nfc_stream, MTYPE_STATUS, NULL, 0);
|
||||
int status = poll(&stream_poll, 1, 1);
|
||||
if (status) {
|
||||
printf("[INFO] buffer active, checking status\n");
|
||||
packet = cvend_read_type(nfc_stream, MTYPE_STATUS_REPLY);
|
||||
if (!packet) {
|
||||
printf("[ERROR] failed reading status\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("[INFO] cvend seems to be working\n");
|
||||
cvend_free(packet);
|
||||
} else {
|
||||
printf("[INFO] waiting for startup\n");
|
||||
packet = cvend_read_type(nfc_stream, MTYPE_STARTUP);
|
||||
if (!packet) {
|
||||
printf("[ERROR] stream closed before startup\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("[INFO] startup complete\n");
|
||||
cvend_free(packet);
|
||||
}
|
||||
|
||||
printf("[INFO] enabling desfire\n");
|
||||
cvend_write(nfc_stream, MTYPE_PROX_CARD_FUNCTION, desfire_enable, 4);
|
||||
packet = cvend_read_type(nfc_stream, MTYPE_PROX_CARD_FUNCTION_REPLY);
|
||||
if (!packet) {
|
||||
printf("[ERROR] failed to start desfire\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("[INFO] desfire enabled\n");
|
||||
cvend_free(packet);
|
||||
}
|
||||
|
||||
void *nfc_heartbeat(void *data)
|
||||
{
|
||||
uint8_t heartbeat[2] = { 0x00, 0x00 };
|
||||
while (1) {
|
||||
cvend_write(MTYPE_STATUS, heartbeat, 2);
|
||||
sleep(10);
|
||||
cvend_write(nfc_stream, MTYPE_STATUS, heartbeat, 2);
|
||||
sleep(1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -33,34 +78,50 @@ void *nfc_handle(void *data)
|
||||
uint8_t desfire_read[] = { 0xbd, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00 };
|
||||
while (1) {
|
||||
cvend_packet *packet = cvend_read();
|
||||
usleep(100);
|
||||
cvend_packet *packet = cvend_read(nfc_stream);
|
||||
cvend_packet *resp_version = NULL;
|
||||
cvend_packet *resp_data = NULL;
|
||||
|
||||
if (!packet)
|
||||
goto reset;
|
||||
|
||||
if (packet->msg_type != MTYPE_DESFIRE_READ) {
|
||||
cvend_free(packet);
|
||||
continue;
|
||||
goto cleanup;
|
||||
}
|
||||
cvend_free(packet);
|
||||
|
||||
cvend_write(MTYPE_DESFIRE_COMMAND,
|
||||
cvend_write(nfc_stream, MTYPE_DESFIRE_COMMAND,
|
||||
desfire_select_application, 4);
|
||||
cvend_free(cvend_read_type(MTYPE_DESFIRE_COMMAND_REPLY));
|
||||
cvend_free(cvend_read_type(nfc_stream,
|
||||
MTYPE_DESFIRE_COMMAND_REPLY));
|
||||
|
||||
cvend_write(MTYPE_DESFIRE_COMMAND, desfire_get_version,
|
||||
1);
|
||||
cvend_packet *resp_version =
|
||||
cvend_read_type(MTYPE_DESFIRE_COMMAND_REPLY);
|
||||
cvend_write(nfc_stream, MTYPE_DESFIRE_COMMAND,
|
||||
desfire_get_version, 1);
|
||||
resp_version = cvend_read_type(nfc_stream,
|
||||
MTYPE_DESFIRE_COMMAND_REPLY);
|
||||
if (!resp_version)
|
||||
goto reset;
|
||||
|
||||
if (resp_version->msg_len == 2 && resp_version->msg_data[1] == 0x6e) {
|
||||
cvend_free(resp_version);
|
||||
continue;
|
||||
}
|
||||
if (resp_version->msg_len == 2 &&
|
||||
resp_version->msg_data[1] == 0x6e)
|
||||
goto cleanup;
|
||||
|
||||
cvend_write(nfc_stream, MTYPE_DESFIRE_COMMAND, desfire_read, 8);
|
||||
resp_data = cvend_read_type(nfc_stream,
|
||||
MTYPE_DESFIRE_COMMAND_REPLY);
|
||||
if (!resp_data)
|
||||
goto reset;
|
||||
|
||||
cvend_write(MTYPE_DESFIRE_COMMAND, desfire_read, 8);
|
||||
cvend_packet *resp_data =
|
||||
cvend_read_type(MTYPE_DESFIRE_COMMAND_REPLY);
|
||||
callback(resp_data->msg_data[0], resp_version->msg_data,
|
||||
resp_version->msg_len, resp_data->msg_data,
|
||||
resp_version->msg_len);
|
||||
goto cleanup;
|
||||
|
||||
reset:
|
||||
nfc_reset("/dev/ttymxc3");
|
||||
|
||||
cleanup:
|
||||
cvend_free(packet);
|
||||
cvend_free(resp_version);
|
||||
cvend_free(resp_data);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ int main(int argc, char *argv[])
|
||||
lv_linux_fbdev_set_file(display, "/dev/fb0");
|
||||
|
||||
pthread_t nfc_thread;
|
||||
nfc_init("/dev/ttymxc3");
|
||||
nfc_reset("/dev/ttymxc3");
|
||||
pthread_create(&nfc_thread, NULL, nfc_handle, read_card);
|
||||
#else
|
||||
display = lv_x11_window_create("LVGL X11 Simulation", 800, 480);
|
||||
|
||||
Reference in New Issue
Block a user