fpc_com_link.c
Go to the documentation of this file.
/*
* Copyright (c) 2020 Fingerprint Cards AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <stdlib.h>
#include "fpc_com_link.h"
fpc_com_result_t fpc_com_link_transmit(fpc_com_packet_link_t *packet, fpc_com_chain_t *chain)
{
uint32_t ack;
uint16_t size;
fpc_com_result_t result;
if (packet == NULL) {
result = FPC_COM_RESULT_INVALID_ARGUMENT;
goto exit;
}
/* Calculate CRC for payload */
packet->crc = chain->crc_calc(0, packet->data, packet->size);
/* Get total size to be transfered over PHY layer */
size = packet->size + fpc_com_link_get_overhead(NULL);
*((fpc_com_channel_t *)chain->phy_mtu_buffer[FPC_COM_CHAIN_TX]) = packet->channel;
*((uint16_t *)(chain->phy_mtu_buffer[FPC_COM_CHAIN_TX] + sizeof(packet->channel)))
= packet->size;
/* Copy CRC to PHY mtu buffer */
memcpy(packet->data + packet->size, &packet->crc, sizeof(packet->crc));
/* Send Packet */
result = chain->phy_tx(size, chain->phy_mtu_buffer[FPC_COM_CHAIN_TX], chain->phy_timeout_tx,
chain->session);
if (result != FPC_COM_RESULT_OK) {
goto exit;
}
/* Receive ACK */
result = chain->phy_rx(sizeof(ack), (uint8_t *)&ack, chain->phy_timeout_rx, chain->session);
/* Handle no ack and timeout as IO error */
if (ack != FPC_COM_ACK || result == FPC_COM_RESULT_TIMEOUT) {
result = FPC_COM_RESULT_IO_ERROR;
goto exit;
}
/* Handle rest as normal error */
if (result != FPC_COM_RESULT_OK) {
goto exit;
}
exit:
return result;
}
fpc_com_result_t fpc_com_link_receive(fpc_com_packet_link_t *packet, fpc_com_chain_t *chain)
{
bool status;
uint32_t ack = FPC_COM_ACK;
const uint8_t header_size = sizeof(packet->channel) + sizeof(packet->size);
fpc_com_result_t result;
if (packet == NULL) {
result = FPC_COM_RESULT_INVALID_ARGUMENT;
goto exit;
}
/* Receive Header */
result = chain->phy_rx(header_size, chain->phy_mtu_buffer[FPC_COM_CHAIN_RX],
chain->phy_timeout_rx, chain->session);
if (result != FPC_COM_RESULT_OK) {
goto exit;
}
packet->channel = *((fpc_com_channel_t *)chain->phy_mtu_buffer[FPC_COM_CHAIN_RX]);
packet->size = *((uint16_t *) (chain->phy_mtu_buffer[FPC_COM_CHAIN_RX]
+ sizeof(fpc_com_channel_t)));
packet->data = chain->phy_mtu_buffer[FPC_COM_CHAIN_RX] + header_size;
/* Check if packet size is valid */
if (chain->phy_mtu_size[FPC_COM_CHAIN_RX]
< (header_size + packet->size + sizeof(packet->crc))) {
result = FPC_COM_RESULT_IO_ERROR;
goto exit;
}
/* Receive Payload */
result = chain->phy_rx(packet->size + sizeof(packet->crc), packet->data,
chain->phy_timeout_rx, chain->session);
if (result != FPC_COM_RESULT_OK) {
goto exit;
}
/* Check incoming packet CRC */
memcpy(&packet->crc, packet->data + packet->size, sizeof(packet->crc));
status = (packet->crc == chain->crc_calc(0, packet->data, packet->size));
if (!status) {
result = FPC_COM_RESULT_IO_ERROR;
goto exit;
}
/* Send ACK */
result = chain->phy_tx(sizeof(ack), (uint8_t *)&ack, chain->phy_timeout_tx, chain->session);
exit:
return result;
}
uint16_t fpc_com_link_get_overhead(uint16_t *offset)
{
fpc_com_packet_link_t *packet;
static const uint16_t internal_offset = sizeof(packet->channel) + sizeof(packet->size);
if (offset) {
*offset = internal_offset;
}
return internal_offset + sizeof(packet->crc);
}
fpc_com_link_transmit
fpc_com_result_t fpc_com_link_transmit(fpc_com_packet_link_t *packet, fpc_com_chain_t *chain)
Sends a packet over the physical link in blocking mode.
Definition: fpc_com_link.c:27
FPC_COM_RESULT_IO_ERROR
Definition: fpc_com_result.h:37
fpc_com_chain::phy_mtu_buffer
uint8_t * phy_mtu_buffer[2]
Definition: fpc_com_chain.h:121
fpc_com_chain::phy_mtu_size
uint16_t phy_mtu_size[2]
Definition: fpc_com_chain.h:119
fpc_com_chain
Definition: fpc_com_chain.h:50
FPC_COM_CHAIN_TX
Definition: fpc_com_chain.h:150
fpc_com_chain::phy_rx
fpc_com_result_t(* phy_rx)(uint16_t size, uint8_t *buffer, uint32_t timeout, void *session)
Definition: fpc_com_chain.h:116
fpc_com_chain::phy_timeout_tx
uint32_t phy_timeout_tx
Definition: fpc_com_chain.h:123
FPC_COM_RESULT_TIMEOUT
Definition: fpc_com_result.h:38
fpc_com_chain::session
void * session
User session pointer. User private stuff, to be able to pass necessary info from the layer that calls...
Definition: fpc_com_chain.h:137
fpc_com_packet_link::size
uint16_t size
Definition: fpc_com_packets.h:65
FPC_COM_RESULT_INVALID_ARGUMENT
Definition: fpc_com_result.h:35
fpc_com_packet_link::data
uint8_t * data
Definition: fpc_com_packets.h:67
fpc_com_chain::crc_calc
uint32_t(* crc_calc)(uint32_t start, const void *data, uint32_t size)
Definition: fpc_com_chain.h:66
FPC_COM_ACK
#define FPC_COM_ACK
Definition: fpc_com_packets.h:32
fpc_com_link_get_overhead
uint16_t fpc_com_link_get_overhead(uint16_t *offset)
Returns the overhead of the layer.
Definition: fpc_com_link.c:126
fpc_com_chain::phy_tx
fpc_com_result_t(* phy_tx)(uint16_t size, const uint8_t *buffer, uint32_t timeout, void *session)
Definition: fpc_com_chain.h:113
fpc_com_chain::phy_timeout_rx
uint32_t phy_timeout_rx
Definition: fpc_com_chain.h:125
FPC_COM_CHAIN_RX
Definition: fpc_com_chain.h:151
fpc_com_packet_link::channel
fpc_com_channel_t channel
Definition: fpc_com_packets.h:63
fpc_com_result_t
uint8_t fpc_com_result_t
Definition: fpc_com_result.h:41
fpc_com_packet_link::crc
uint32_t crc
Definition: fpc_com_packets.h:69
fpc_com_channel_t
uint16_t fpc_com_channel_t
Definition: fpc_com_packets.h:58
fpc_com_link.h
Communication link interface.
fpc_com_link_receive
fpc_com_result_t fpc_com_link_receive(fpc_com_packet_link_t *packet, fpc_com_chain_t *chain)
Receives a packet from the physical link.
Definition: fpc_com_link.c:73
FPC_COM_RESULT_OK
Definition: fpc_com_result.h:33
fpc_com_packet_link
Definition: fpc_com_packets.h:61