mirror of
https://github.com/thelsing/knx.git
synced 2025-08-17 13:47:28 +02:00
save work
This commit is contained in:
parent
f1085a39cc
commit
7c34f15e67
@ -6,9 +6,19 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MIN(a, b) ((a < b) ? (a) : (b))
|
||||
|
||||
#define MAX_EP_SIZE 64
|
||||
#define HID_HEADER_SIZE 3
|
||||
|
||||
// Maximum possible payload data bytes in a transfer protocol body
|
||||
#define MAX_DATASIZE_START_PACKET 52
|
||||
#define MAX_DATASIZE_PARTIAL_PACKET 61
|
||||
|
||||
#define PACKET_TYPE_START 1
|
||||
#define PACKET_TYPE_END 2
|
||||
#define PACKET_TYPE_PARTIAL 4
|
||||
|
||||
//#define DEBUG_TX_HID_REPORT
|
||||
//#define DEBUG_RX_HID_REPORT
|
||||
|
||||
@ -34,14 +44,8 @@ void UsbTunnelInterface::loop()
|
||||
uint8_t* buffer;
|
||||
uint16_t length;
|
||||
loadNextTxFrame(&buffer, &length);
|
||||
/*
|
||||
print("cEMI USB TX len: ");
|
||||
print(length);
|
||||
|
||||
print(" data: ");
|
||||
printHex(" data: ", buffer, length);
|
||||
*/
|
||||
sendKnxTunnelHidReport(buffer, length);
|
||||
sendKnxHidReport(buffer, length);
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
if (!isRxQueueEmpty())
|
||||
@ -56,37 +60,29 @@ void UsbTunnelInterface::loop()
|
||||
|
||||
/* USB TX */
|
||||
|
||||
bool UsbTunnelInterface::sendCemiFrame(CemiFrame& frame)
|
||||
void UsbTunnelInterface::sendCemiFrame(CemiFrame& frame)
|
||||
{
|
||||
addFrameTxQueue(frame);
|
||||
|
||||
return true;
|
||||
sendKnxTunnelHidReport(frame.data(), frame.dataLength());
|
||||
}
|
||||
|
||||
void UsbTunnelInterface::addFrameTxQueue(CemiFrame& frame)
|
||||
void UsbTunnelInterface::addBufferTxQueue(uint8_t* data, uint16_t length)
|
||||
{
|
||||
_queue_buffer_t* tx_frame = new _queue_buffer_t;
|
||||
_queue_buffer_t* tx_buffer = new _queue_buffer_t;
|
||||
|
||||
tx_frame->length = frame.dataLength();
|
||||
tx_frame->data = new uint8_t[tx_frame->length];
|
||||
tx_frame->next = nullptr;
|
||||
tx_buffer->length = length;
|
||||
tx_buffer->data = new uint8_t[tx_buffer->length];
|
||||
tx_buffer->next = nullptr;
|
||||
|
||||
memcpy(tx_frame->data, frame.data(), tx_frame->length);
|
||||
memcpy(tx_buffer->data, data, tx_buffer->length);
|
||||
|
||||
/*
|
||||
print("cEMI USB TX len: ");
|
||||
print(tx_frame->length);
|
||||
|
||||
printHex(" data:", tx_frame->data, tx_frame->length);
|
||||
*/
|
||||
if (_tx_queue.back == nullptr)
|
||||
{
|
||||
_tx_queue.front = _tx_queue.back = tx_frame;
|
||||
_tx_queue.front = _tx_queue.back = tx_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
_tx_queue.back->next = tx_frame;
|
||||
_tx_queue.back = tx_frame;
|
||||
_tx_queue.back->next = tx_buffer;
|
||||
_tx_queue.back = tx_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,30 +101,78 @@ void UsbTunnelInterface::loadNextTxFrame(uint8_t** sendBuffer, uint16_t* sendBuf
|
||||
{
|
||||
return;
|
||||
}
|
||||
_queue_buffer_t* tx_frame = _tx_queue.front;
|
||||
*sendBuffer = tx_frame->data;
|
||||
*sendBufferLength = tx_frame->length;
|
||||
_tx_queue.front = tx_frame->next;
|
||||
_queue_buffer_t* tx_buffer = _tx_queue.front;
|
||||
*sendBuffer = tx_buffer->data;
|
||||
*sendBufferLength = tx_buffer->length;
|
||||
_tx_queue.front = tx_buffer->next;
|
||||
|
||||
if (_tx_queue.front == nullptr)
|
||||
{
|
||||
_tx_queue.back = nullptr;
|
||||
}
|
||||
delete tx_frame;
|
||||
delete tx_buffer;
|
||||
}
|
||||
|
||||
void UsbTunnelInterface::sendKnxTunnelHidReport(uint8_t* data, uint16_t length)
|
||||
{
|
||||
uint8_t buffer[length + 11];
|
||||
uint16_t maxData = MAX_DATASIZE_START_PACKET;
|
||||
uint8_t packetType = PACKET_TYPE_START;
|
||||
|
||||
buffer[0] = 0x01; // ReportID (fixed 0x01)
|
||||
buffer[1] = 0x13; // PacketInfo must be 0x13 (SeqNo: 1, Type: 3)
|
||||
if (length > maxData)
|
||||
{
|
||||
packetType |= PACKET_TYPE_PARTIAL;
|
||||
}
|
||||
|
||||
uint16_t offset = 0;
|
||||
uint8_t* buffer = nullptr;
|
||||
|
||||
for(uint8_t seqNum = 1; seqNum < 6; seqNum++)
|
||||
{
|
||||
uint16_t copyLen = MIN(length, maxData);
|
||||
|
||||
// If this is the first packet we include the transport protocol header
|
||||
if (packetType & PACKET_TYPE_START)
|
||||
{
|
||||
buffer = new uint8_t[copyLen + 8 + HID_HEADER_SIZE]; // length of transport protocol header: 11 bytes
|
||||
buffer[2] = 8 + copyLen; // KNX USB Transfer Protocol Header length
|
||||
buffer[3] = 0x00; // Protocol version (fixed 0x00)
|
||||
buffer[4] = 0x08; // USB KNX Transfer Protocol Header Length (fixed 0x08)
|
||||
buffer[7] = 0x01; // KNX Tunneling (0x01)
|
||||
buffer[8] = 0x03; // EMI ID: 3 -> cEMI
|
||||
buffer[9] = 0x00; // Manufacturer
|
||||
buffer[10] = 0x00; // Manufacturer
|
||||
memcpy(&buffer[11], &data[offset], copyLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = new uint8_t[copyLen]; // length of transport protocol header: 11 bytes
|
||||
buffer[2] = copyLen; // KNX USB Transfer Protocol Header length
|
||||
memcpy(&buffer[0], &data[offset], copyLen);
|
||||
}
|
||||
|
||||
offset += copyLen;
|
||||
if (offset >= length)
|
||||
{
|
||||
packetType |= PACKET_TYPE_END;
|
||||
}
|
||||
|
||||
buffer[0] = 0x01; // ReportID (fixed 0x01)
|
||||
buffer[1] = ((seqNum << 4) & 0xF0) | (packetType & 0x07); // PacketInfo (SeqNo and Type)
|
||||
addBufferTxQueue(buffer, (buffer[2] + HID_HEADER_SIZE));
|
||||
delete[] buffer;
|
||||
|
||||
if (offset >= length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
packetType &= ~PACKET_TYPE_START;
|
||||
maxData = MAX_DATASIZE_PARTIAL_PACKET;
|
||||
}
|
||||
|
||||
|
||||
uint8_t buffer[length + 11];
|
||||
|
||||
|
||||
// Copy cEMI frame to buffer
|
||||
memcpy(&buffer[11], data, length + HID_HEADER_SIZE + 8);
|
||||
@ -150,7 +194,7 @@ void UsbTunnelInterface::sendKnxTunnelHidReport(uint8_t* data, uint16_t length)
|
||||
Serial1.println("");
|
||||
#endif
|
||||
|
||||
sendKnxHidReport(buffer, MAX_EP_SIZE);
|
||||
addBufferTxQueue(buffer, (buffer[2] + HID_HEADER_SIZE));
|
||||
}
|
||||
|
||||
/* USB RX */
|
||||
@ -180,12 +224,6 @@ void UsbTunnelInterface::addBufferRxQueue(const uint8_t* data, uint16_t length)
|
||||
|
||||
memcpy(rx_buffer->data, data, rx_buffer->length);
|
||||
|
||||
/*
|
||||
print("cEMI USB RX len: ");
|
||||
print(rx_buffer->length);
|
||||
|
||||
printHex(" data:", rx_buffer->data, rx_buffer->length);
|
||||
*/
|
||||
if (_rx_queue.back == nullptr)
|
||||
{
|
||||
_rx_queue.front =_rx_queue.back = rx_buffer;
|
||||
@ -377,7 +415,7 @@ void UsbTunnelInterface::handleBusAccessServerProtocol(const uint8_t* requestDat
|
||||
}
|
||||
Serial1.println("");
|
||||
#endif
|
||||
sendKnxHidReport(data, MAX_EP_SIZE);
|
||||
addBufferTxQueue(data, packetLength + respDataSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ class UsbTunnelInterface
|
||||
void loop();
|
||||
|
||||
// from cEMI server
|
||||
bool sendCemiFrame(CemiFrame& frame);
|
||||
void sendCemiFrame(CemiFrame& frame);
|
||||
|
||||
static const uint8_t* getKnxHidReportDescriptor();
|
||||
static uint16_t getHidReportDescriptorLength();
|
||||
@ -44,7 +44,7 @@ class UsbTunnelInterface
|
||||
|
||||
// USB TX queue
|
||||
_queue_t _tx_queue;
|
||||
void addFrameTxQueue(CemiFrame& frame);
|
||||
void addBufferTxQueue(uint8_t* data, uint16_t length);
|
||||
bool isTxQueueEmpty();
|
||||
void loadNextTxFrame(uint8_t** sendBuffer, uint16_t* sendBufferLength);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user