mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
commit
a061980804
7 changed files with 173 additions and 8 deletions
|
@ -4,7 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
- Fixed `lf hid clone --bin` - now correctly handles sentinel bits (@iceman1001)
|
- Fixed `lf hid clone --bin` - now correctly handles sentinel bits (@iceman1001)
|
||||||
- Experimental UDP support in linux (@iceman1001)
|
- Experimental UDP support in linux (@iceman1001, @wh201906)
|
||||||
- Changed CI scripts to speed up the builds (@wh201906)
|
- Changed CI scripts to speed up the builds (@wh201906)
|
||||||
- Changed the timeout of local TCP connections (@wh201906)
|
- Changed the timeout of local TCP connections (@wh201906)
|
||||||
- Finalized implementation of configcard generation for keyroll when cardhelper is not present (@Antiklesys)
|
- Finalized implementation of configcard generation for keyroll when cardhelper is not present (@Antiklesys)
|
||||||
|
|
|
@ -286,6 +286,7 @@ set (TARGET_SOURCES
|
||||||
${PM3_ROOT}/client/src/mifare/desfirecore.c
|
${PM3_ROOT}/client/src/mifare/desfirecore.c
|
||||||
${PM3_ROOT}/client/src/mifare/desfiretest.c
|
${PM3_ROOT}/client/src/mifare/desfiretest.c
|
||||||
${PM3_ROOT}/client/src/mifare/gallaghercore.c
|
${PM3_ROOT}/client/src/mifare/gallaghercore.c
|
||||||
|
${PM3_ROOT}/client/src/uart/ringbuffer.c
|
||||||
${PM3_ROOT}/client/src/uart/uart_posix.c
|
${PM3_ROOT}/client/src/uart/uart_posix.c
|
||||||
${PM3_ROOT}/client/src/uart/uart_win32.c
|
${PM3_ROOT}/client/src/uart/uart_win32.c
|
||||||
${PM3_ROOT}/client/src/ui/overlays.ui
|
${PM3_ROOT}/client/src/ui/overlays.ui
|
||||||
|
|
|
@ -707,6 +707,7 @@ SRCS = mifare/aiddesfire.c \
|
||||||
pm3line.c \
|
pm3line.c \
|
||||||
proxmark3.c \
|
proxmark3.c \
|
||||||
scandir.c \
|
scandir.c \
|
||||||
|
uart/ringbuffer.c \
|
||||||
uart/uart_posix.c \
|
uart/uart_posix.c \
|
||||||
uart/uart_win32.c \
|
uart/uart_win32.c \
|
||||||
scripting.c \
|
scripting.c \
|
||||||
|
|
|
@ -286,6 +286,7 @@ set (TARGET_SOURCES
|
||||||
${PM3_ROOT}/client/src/mifare/desfirecore.c
|
${PM3_ROOT}/client/src/mifare/desfirecore.c
|
||||||
${PM3_ROOT}/client/src/mifare/desfiretest.c
|
${PM3_ROOT}/client/src/mifare/desfiretest.c
|
||||||
${PM3_ROOT}/client/src/mifare/gallaghercore.c
|
${PM3_ROOT}/client/src/mifare/gallaghercore.c
|
||||||
|
${PM3_ROOT}/client/src/uart/ringbuffer.c
|
||||||
${PM3_ROOT}/client/src/uart/uart_posix.c
|
${PM3_ROOT}/client/src/uart/uart_posix.c
|
||||||
${PM3_ROOT}/client/src/uart/uart_win32.c
|
${PM3_ROOT}/client/src/uart/uart_win32.c
|
||||||
${PM3_ROOT}/client/src/ui/overlays.ui
|
${PM3_ROOT}/client/src/ui/overlays.ui
|
||||||
|
|
102
client/src/uart/ringbuffer.c
Normal file
102
client/src/uart/ringbuffer.c
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
#include "ringbuffer.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
RingBuffer* RingBuf_create(int capacity) {
|
||||||
|
RingBuffer* buffer = (RingBuffer*)malloc(sizeof(RingBuffer));
|
||||||
|
if (!buffer) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->data = (uint8_t*)calloc(capacity, sizeof(uint8_t));
|
||||||
|
if (!buffer->data) {
|
||||||
|
free(buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->capacity = capacity;
|
||||||
|
buffer->size = 0;
|
||||||
|
buffer->front = 0;
|
||||||
|
buffer->rear = 0;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RingBuf_isFull(RingBuffer* buffer) {
|
||||||
|
return buffer->size == buffer->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RingBuf_isEmpty(RingBuffer* buffer) {
|
||||||
|
return buffer->size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RingBuf_enqueue(RingBuffer* buffer, uint8_t value) {
|
||||||
|
if (RingBuf_isFull(buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->data[buffer->rear] = value;
|
||||||
|
buffer->rear = (buffer->rear + 1) % buffer->capacity;
|
||||||
|
buffer->size++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RingBuf_dequeue(RingBuffer* buffer, uint8_t* value) {
|
||||||
|
if (RingBuf_isEmpty(buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = buffer->data[buffer->front];
|
||||||
|
buffer->front = (buffer->front + 1) % buffer->capacity;
|
||||||
|
buffer->size--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RingBuf_enqueueBatch(RingBuffer* buffer, const uint8_t* values, int count) {
|
||||||
|
int processed = 0;
|
||||||
|
|
||||||
|
if (RingBuf_getAvailableSize(buffer) < count) {
|
||||||
|
count = RingBuf_getAvailableSize(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
buffer->data[buffer->rear] = values[i];
|
||||||
|
buffer->rear = (buffer->rear + 1) % buffer->capacity;
|
||||||
|
processed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->size += processed;
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RingBuf_dequeueBatch(RingBuffer* buffer, uint8_t* values, int count) {
|
||||||
|
int processed = 0;
|
||||||
|
|
||||||
|
if (buffer->size < count) {
|
||||||
|
count = buffer->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
values[i] = buffer->data[buffer->front];
|
||||||
|
buffer->front = (buffer->front + 1) % buffer->capacity;
|
||||||
|
processed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->size -= processed;
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int RingBuf_getUsedSize(RingBuffer* buffer) {
|
||||||
|
return buffer->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int RingBuf_getAvailableSize(RingBuffer* buffer) {
|
||||||
|
return (buffer->capacity) - (buffer->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RingBuf_destroy(RingBuffer* buffer) {
|
||||||
|
if (buffer != NULL)
|
||||||
|
free(buffer->data);
|
||||||
|
free(buffer);
|
||||||
|
}
|
26
client/src/uart/ringbuffer.h
Normal file
26
client/src/uart/ringbuffer.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef _RINGBUFFER_H_
|
||||||
|
#define _RINGBUFFER_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* data;
|
||||||
|
int capacity;
|
||||||
|
int size;
|
||||||
|
int front;
|
||||||
|
int rear;
|
||||||
|
} RingBuffer;
|
||||||
|
|
||||||
|
RingBuffer* RingBuf_create(int capacity);
|
||||||
|
bool RingBuf_isFull(RingBuffer* buffer);
|
||||||
|
bool RingBuf_isEmpty(RingBuffer* buffer);
|
||||||
|
bool RingBuf_enqueue(RingBuffer* buffer, uint8_t value);
|
||||||
|
bool RingBuf_dequeue(RingBuffer* buffer, uint8_t* value);
|
||||||
|
int RingBuf_enqueueBatch(RingBuffer* buffer, const uint8_t* values, int count);
|
||||||
|
int RingBuf_dequeueBatch(RingBuffer* buffer, uint8_t* values, int count);
|
||||||
|
int RingBuf_getUsedSize(RingBuffer* buffer);
|
||||||
|
int RingBuf_getAvailableSize(RingBuffer* buffer);
|
||||||
|
void RingBuf_destroy(RingBuffer* buffer);
|
||||||
|
|
||||||
|
#endif
|
|
@ -21,6 +21,7 @@
|
||||||
#define _DEFAULT_SOURCE
|
#define _DEFAULT_SOURCE
|
||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
#include "ringbuffer.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -55,6 +56,7 @@ typedef struct {
|
||||||
int fd; // Serial port file descriptor
|
int fd; // Serial port file descriptor
|
||||||
term_info tiOld; // Terminal info before using the port
|
term_info tiOld; // Terminal info before using the port
|
||||||
term_info tiNew; // Terminal info during the transaction
|
term_info tiNew; // Terminal info during the transaction
|
||||||
|
RingBuffer* udpBuffer;
|
||||||
} serial_port_unix_t_t;
|
} serial_port_unix_t_t;
|
||||||
|
|
||||||
// see pm3_cmd.h
|
// see pm3_cmd.h
|
||||||
|
@ -84,6 +86,7 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) {
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp->udpBuffer = NULL;
|
||||||
// init timeouts
|
// init timeouts
|
||||||
timeout.tv_usec = UART_FPC_CLIENT_RX_TIMEOUT_MS * 1000;
|
timeout.tv_usec = UART_FPC_CLIENT_RX_TIMEOUT_MS * 1000;
|
||||||
|
|
||||||
|
@ -239,6 +242,7 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sp->fd = sfd;
|
sp->fd = sfd;
|
||||||
|
sp->udpBuffer = RingBuf_create(MAX(sizeof(PacketResponseNGRaw), sizeof(PacketResponseOLD)) * 20);
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
@ -427,6 +431,7 @@ void uart_close(const serial_port sp) {
|
||||||
//silent error message as it can be called from uart_open failing modes, e.g. when waiting for port to appear
|
//silent error message as it can be called from uart_open failing modes, e.g. when waiting for port to appear
|
||||||
//PrintAndLogEx(ERR, "UART error while closing port");
|
//PrintAndLogEx(ERR, "UART error while closing port");
|
||||||
}
|
}
|
||||||
|
RingBuf_destroy(spu->udpBuffer);
|
||||||
close(spu->fd);
|
close(spu->fd);
|
||||||
free(sp);
|
free(sp);
|
||||||
}
|
}
|
||||||
|
@ -435,6 +440,7 @@ int uart_receive(const serial_port sp, uint8_t *pbtRx, uint32_t pszMaxRxLen, uin
|
||||||
uint32_t byteCount; // FIONREAD returns size on 32b
|
uint32_t byteCount; // FIONREAD returns size on 32b
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
const serial_port_unix_t_t *spu = (serial_port_unix_t_t *)sp;
|
||||||
|
|
||||||
if (newtimeout_pending) {
|
if (newtimeout_pending) {
|
||||||
timeout.tv_usec = newtimeout_value * 1000;
|
timeout.tv_usec = newtimeout_value * 1000;
|
||||||
|
@ -443,11 +449,30 @@ int uart_receive(const serial_port sp, uint8_t *pbtRx, uint32_t pszMaxRxLen, uin
|
||||||
// Reset the output count
|
// Reset the output count
|
||||||
*pszRxLen = 0;
|
*pszRxLen = 0;
|
||||||
do {
|
do {
|
||||||
|
int res;
|
||||||
|
if(spu->udpBuffer != NULL) {
|
||||||
|
// for UDP connection, try to use the data from the buffer
|
||||||
|
|
||||||
|
byteCount = RingBuf_getAvailableSize(spu->udpBuffer);
|
||||||
|
// Cap the number of bytes, so we don't overrun the buffer
|
||||||
|
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
|
||||||
|
// PrintAndLogEx(ERR, "UART:: RX prevent overrun (have %u, need %u)", pszMaxRxLen - (*pszRxLen), byteCount);
|
||||||
|
byteCount = pszMaxRxLen - (*pszRxLen);
|
||||||
|
}
|
||||||
|
res = RingBuf_dequeueBatch(spu->udpBuffer, pbtRx + (*pszRxLen), byteCount);
|
||||||
|
*pszRxLen += res;
|
||||||
|
|
||||||
|
if (*pszRxLen == pszMaxRxLen) {
|
||||||
|
// We have all the data we wanted.
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reset file descriptor
|
// Reset file descriptor
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(((serial_port_unix_t_t *)sp)->fd, &rfds);
|
FD_SET(spu->fd, &rfds);
|
||||||
tv = timeout;
|
tv = timeout;
|
||||||
int res = select(((serial_port_unix_t_t *)sp)->fd + 1, &rfds, NULL, NULL, &tv);
|
res = select(spu->fd + 1, &rfds, NULL, NULL, &tv);
|
||||||
|
|
||||||
// Read error
|
// Read error
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
@ -466,10 +491,18 @@ int uart_receive(const serial_port sp, uint8_t *pbtRx, uint32_t pszMaxRxLen, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the count of the incoming bytes
|
// Retrieve the count of the incoming bytes
|
||||||
res = ioctl(((serial_port_unix_t_t *)sp)->fd, FIONREAD, &byteCount);
|
res = ioctl(spu->fd, FIONREAD, &byteCount);
|
||||||
// PrintAndLogEx(ERR, "UART:: RX ioctl res %d byteCount %u", res, byteCount);
|
// PrintAndLogEx(ERR, "UART:: RX ioctl res %d byteCount %u", res, byteCount);
|
||||||
if (res < 0) return PM3_ENOTTY;
|
if (res < 0) return PM3_ENOTTY;
|
||||||
|
|
||||||
|
// For UDP connection, put the incoming data into the buffer and handle them in the next round
|
||||||
|
if (spu->udpBuffer != NULL) {
|
||||||
|
uint8_t recvBuf[MAX(sizeof(PacketResponseNGRaw), sizeof(PacketResponseOLD)) * 20];
|
||||||
|
res = read(spu->fd, recvBuf, RingBuf_getAvailableSize(spu->udpBuffer));
|
||||||
|
RingBuf_enqueueBatch(spu->udpBuffer, recvBuf, res);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Cap the number of bytes, so we don't overrun the buffer
|
// Cap the number of bytes, so we don't overrun the buffer
|
||||||
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
|
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
|
||||||
// PrintAndLogEx(ERR, "UART:: RX prevent overrun (have %u, need %u)", pszMaxRxLen - (*pszRxLen), byteCount);
|
// PrintAndLogEx(ERR, "UART:: RX prevent overrun (have %u, need %u)", pszMaxRxLen - (*pszRxLen), byteCount);
|
||||||
|
@ -477,7 +510,7 @@ int uart_receive(const serial_port sp, uint8_t *pbtRx, uint32_t pszMaxRxLen, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is something available, read the data
|
// There is something available, read the data
|
||||||
res = read(((serial_port_unix_t_t *)sp)->fd, pbtRx + (*pszRxLen), byteCount);
|
res = read(spu->fd, pbtRx + (*pszRxLen), byteCount);
|
||||||
|
|
||||||
// Stop if the OS has some troubles reading the data
|
// Stop if the OS has some troubles reading the data
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
|
@ -499,13 +532,14 @@ int uart_send(const serial_port sp, const uint8_t *pbtTx, const uint32_t len) {
|
||||||
uint32_t pos = 0;
|
uint32_t pos = 0;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
const serial_port_unix_t_t *spu = (serial_port_unix_t_t *)sp;
|
||||||
|
|
||||||
while (pos < len) {
|
while (pos < len) {
|
||||||
// Reset file descriptor
|
// Reset file descriptor
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(((serial_port_unix_t_t *)sp)->fd, &rfds);
|
FD_SET(spu->fd, &rfds);
|
||||||
tv = timeout;
|
tv = timeout;
|
||||||
int res = select(((serial_port_unix_t_t *)sp)->fd + 1, NULL, &rfds, NULL, &tv);
|
int res = select(spu->fd + 1, NULL, &rfds, NULL, &tv);
|
||||||
|
|
||||||
// Write error
|
// Write error
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
@ -520,7 +554,7 @@ int uart_send(const serial_port sp, const uint8_t *pbtTx, const uint32_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send away the bytes
|
// Send away the bytes
|
||||||
res = write(((serial_port_unix_t_t *)sp)->fd, pbtTx + pos, len - pos);
|
res = write(spu->fd, pbtTx + pos, len - pos);
|
||||||
|
|
||||||
// Stop if the OS has some troubles sending the data
|
// Stop if the OS has some troubles sending the data
|
||||||
if (res <= 0)
|
if (res <= 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue