Host Communication Protocol  2.0
fpc_com_link.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Fingerprint Cards AB
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
22 #include <string.h>
23 #include <stdlib.h>
24 
25 #include "fpc_com_link.h"
26 
28 {
29  uint32_t ack;
30  uint16_t size;
31  fpc_com_result_t result;
32 
33  if (packet == NULL) {
35  goto exit;
36  }
37 
38  /* Calculate CRC for payload */
39  packet->crc = chain->crc_calc(0, packet->data, packet->size);
40 
41  /* Get total size to be transfered over PHY layer */
42  size = packet->size + fpc_com_link_get_overhead(NULL);
43 
45  *((uint16_t *)(chain->phy_mtu_buffer[FPC_COM_CHAIN_TX] + sizeof(packet->channel)))
46  = packet->size;
47  /* Copy CRC to PHY mtu buffer */
48  memcpy(packet->data + packet->size, &packet->crc, sizeof(packet->crc));
49 
50  /* Send Packet */
51  result = chain->phy_tx(size, chain->phy_mtu_buffer[FPC_COM_CHAIN_TX], chain->phy_timeout_tx,
52  chain->session);
53  if (result != FPC_COM_RESULT_OK) {
54  goto exit;
55  }
56 
57  /* Receive ACK */
58  result = chain->phy_rx(sizeof(ack), (uint8_t *)&ack, chain->phy_timeout_rx, chain->session);
59  /* Handle no ack and timeout as IO error */
60  if (ack != FPC_COM_ACK || result == FPC_COM_RESULT_TIMEOUT) {
61  result = FPC_COM_RESULT_IO_ERROR;
62  goto exit;
63  }
64  /* Handle rest as normal error */
65  if (result != FPC_COM_RESULT_OK) {
66  goto exit;
67  }
68 
69 exit:
70  return result;
71 }
72 
74 {
75  bool status;
76  uint32_t ack = FPC_COM_ACK;
77  const uint8_t header_size = sizeof(packet->channel) + sizeof(packet->size);
78  fpc_com_result_t result;
79 
80  if (packet == NULL) {
82  goto exit;
83  }
84 
85  /* Receive Header */
86  result = chain->phy_rx(header_size, chain->phy_mtu_buffer[FPC_COM_CHAIN_RX],
87  chain->phy_timeout_rx, chain->session);
88  if (result != FPC_COM_RESULT_OK) {
89  goto exit;
90  }
91 
93  packet->size = *((uint16_t *) (chain->phy_mtu_buffer[FPC_COM_CHAIN_RX]
94  + sizeof(fpc_com_channel_t)));
95  packet->data = chain->phy_mtu_buffer[FPC_COM_CHAIN_RX] + header_size;
96 
97  /* Check if packet size is valid */
98  if (chain->phy_mtu_size[FPC_COM_CHAIN_RX]
99  < (header_size + packet->size + sizeof(packet->crc))) {
100  result = FPC_COM_RESULT_IO_ERROR;
101  goto exit;
102  }
103 
104  /* Receive Payload */
105  result = chain->phy_rx(packet->size + sizeof(packet->crc), packet->data,
106  chain->phy_timeout_rx, chain->session);
107  if (result != FPC_COM_RESULT_OK) {
108  goto exit;
109  }
110 
111  /* Check incoming packet CRC */
112  memcpy(&packet->crc, packet->data + packet->size, sizeof(packet->crc));
113  status = (packet->crc == chain->crc_calc(0, packet->data, packet->size));
114  if (!status) {
115  result = FPC_COM_RESULT_IO_ERROR;
116  goto exit;
117  }
118 
119  /* Send ACK */
120  result = chain->phy_tx(sizeof(ack), (uint8_t *)&ack, chain->phy_timeout_tx, chain->session);
121 
122 exit:
123  return result;
124 }
125 
126 uint16_t fpc_com_link_get_overhead(uint16_t *offset)
127 {
128  fpc_com_packet_link_t *packet;
129  static const uint16_t internal_offset = sizeof(packet->channel) + sizeof(packet->size);
130 
131  if (offset) {
132  *offset = internal_offset;
133  }
134  return internal_offset + sizeof(packet->crc);
135 }
uint8_t * phy_mtu_buffer[2]
uint16_t phy_mtu_size[2]
fpc_com_result_t(* phy_rx)(uint16_t size, uint8_t *buffer, uint32_t timeout, void *session)
uint32_t phy_timeout_tx
void * session
User session pointer. User private stuff, to be able to pass necessary info from the layer that calls...
uint32_t(* crc_calc)(uint32_t start, const void *data, uint32_t size)
Definition: fpc_com_chain.h:66
#define FPC_COM_ACK
fpc_com_result_t(* phy_tx)(uint16_t size, const uint8_t *buffer, uint32_t timeout, void *session)
uint32_t phy_timeout_rx
uint8_t fpc_com_result_t
uint16_t fpc_com_channel_t