xref: /aosp_15_r20/external/libese/libese-hw/ese_hw_echo.c (revision 5c4dab75aa57366379dce576b1a9e082a44e2b3a)
1*5c4dab75SAndroid Build Coastguard Worker /*
2*5c4dab75SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*5c4dab75SAndroid Build Coastguard Worker  *
4*5c4dab75SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*5c4dab75SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*5c4dab75SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*5c4dab75SAndroid Build Coastguard Worker  *
8*5c4dab75SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*5c4dab75SAndroid Build Coastguard Worker  *
10*5c4dab75SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*5c4dab75SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*5c4dab75SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5c4dab75SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*5c4dab75SAndroid Build Coastguard Worker  * limitations under the License.
15*5c4dab75SAndroid Build Coastguard Worker  *
16*5c4dab75SAndroid Build Coastguard Worker  * Implement a simple T=1 echo endpoint.
17*5c4dab75SAndroid Build Coastguard Worker  */
18*5c4dab75SAndroid Build Coastguard Worker 
19*5c4dab75SAndroid Build Coastguard Worker #include <stdlib.h>
20*5c4dab75SAndroid Build Coastguard Worker #include <string.h>
21*5c4dab75SAndroid Build Coastguard Worker #include <unistd.h>
22*5c4dab75SAndroid Build Coastguard Worker 
23*5c4dab75SAndroid Build Coastguard Worker #include "../libese-teq1/include/ese/teq1.h"
24*5c4dab75SAndroid Build Coastguard Worker #include "../libese/include/ese/ese.h"
25*5c4dab75SAndroid Build Coastguard Worker #include "../libese/include/ese/log.h"
26*5c4dab75SAndroid Build Coastguard Worker 
27*5c4dab75SAndroid Build Coastguard Worker struct EchoState {
28*5c4dab75SAndroid Build Coastguard Worker   struct Teq1Frame frame;
29*5c4dab75SAndroid Build Coastguard Worker   uint8_t *rx_fill;
30*5c4dab75SAndroid Build Coastguard Worker   uint8_t *tx_sent;
31*5c4dab75SAndroid Build Coastguard Worker   int recvd;
32*5c4dab75SAndroid Build Coastguard Worker };
33*5c4dab75SAndroid Build Coastguard Worker 
34*5c4dab75SAndroid Build Coastguard Worker #define ECHO_STATE(ese) (*(struct EchoState **)(&ese->pad[1]))
35*5c4dab75SAndroid Build Coastguard Worker 
echo_open(struct EseInterface * ese,void * hw_opts)36*5c4dab75SAndroid Build Coastguard Worker static int echo_open(struct EseInterface *ese, void *hw_opts) {
37*5c4dab75SAndroid Build Coastguard Worker   struct EchoState *es = hw_opts; /* shorter than __attribute */
38*5c4dab75SAndroid Build Coastguard Worker   struct EchoState **es_ptr;
39*5c4dab75SAndroid Build Coastguard Worker   if (sizeof(ese->pad) < sizeof(struct EchoState *)) {
40*5c4dab75SAndroid Build Coastguard Worker     /* This is a compile-time correctable error only. */
41*5c4dab75SAndroid Build Coastguard Worker     ALOGE("Pad size too small to use Echo HW (%zu < %zu)", sizeof(ese->pad),
42*5c4dab75SAndroid Build Coastguard Worker           sizeof(struct EchoState *));
43*5c4dab75SAndroid Build Coastguard Worker     return -1;
44*5c4dab75SAndroid Build Coastguard Worker   }
45*5c4dab75SAndroid Build Coastguard Worker   es_ptr = &ECHO_STATE(ese);
46*5c4dab75SAndroid Build Coastguard Worker   *es_ptr = malloc(sizeof(struct EchoState));
47*5c4dab75SAndroid Build Coastguard Worker   if (!*es_ptr) {
48*5c4dab75SAndroid Build Coastguard Worker     return -1;
49*5c4dab75SAndroid Build Coastguard Worker   }
50*5c4dab75SAndroid Build Coastguard Worker   es = ECHO_STATE(ese);
51*5c4dab75SAndroid Build Coastguard Worker   es->rx_fill = &es->frame.header.NAD;
52*5c4dab75SAndroid Build Coastguard Worker   es->tx_sent = es->rx_fill;
53*5c4dab75SAndroid Build Coastguard Worker   es->recvd = 0;
54*5c4dab75SAndroid Build Coastguard Worker   return 0;
55*5c4dab75SAndroid Build Coastguard Worker }
56*5c4dab75SAndroid Build Coastguard Worker 
echo_close(struct EseInterface * ese)57*5c4dab75SAndroid Build Coastguard Worker static void echo_close(struct EseInterface *ese) {
58*5c4dab75SAndroid Build Coastguard Worker   struct EchoState *es;
59*5c4dab75SAndroid Build Coastguard Worker   es = ECHO_STATE(ese);
60*5c4dab75SAndroid Build Coastguard Worker   if (!es) {
61*5c4dab75SAndroid Build Coastguard Worker     return;
62*5c4dab75SAndroid Build Coastguard Worker   }
63*5c4dab75SAndroid Build Coastguard Worker   free(es);
64*5c4dab75SAndroid Build Coastguard Worker   es = NULL;
65*5c4dab75SAndroid Build Coastguard Worker }
66*5c4dab75SAndroid Build Coastguard Worker 
echo_receive(struct EseInterface * ese,uint8_t * buf,uint32_t len,int complete)67*5c4dab75SAndroid Build Coastguard Worker static uint32_t echo_receive(struct EseInterface *ese, uint8_t *buf,
68*5c4dab75SAndroid Build Coastguard Worker                              uint32_t len, int complete) {
69*5c4dab75SAndroid Build Coastguard Worker   struct EchoState *es = ECHO_STATE(ese);
70*5c4dab75SAndroid Build Coastguard Worker   ALOGV("interface attempting to read data");
71*5c4dab75SAndroid Build Coastguard Worker   if (!es->recvd) {
72*5c4dab75SAndroid Build Coastguard Worker     return 0;
73*5c4dab75SAndroid Build Coastguard Worker   }
74*5c4dab75SAndroid Build Coastguard Worker 
75*5c4dab75SAndroid Build Coastguard Worker   if (len > sizeof(es->frame) - (es->tx_sent - &es->frame.header.NAD)) {
76*5c4dab75SAndroid Build Coastguard Worker     return 0;
77*5c4dab75SAndroid Build Coastguard Worker   }
78*5c4dab75SAndroid Build Coastguard Worker 
79*5c4dab75SAndroid Build Coastguard Worker   /* NAD was polled for so skip it. */
80*5c4dab75SAndroid Build Coastguard Worker   memcpy(buf, es->tx_sent, len);
81*5c4dab75SAndroid Build Coastguard Worker   es->tx_sent += len;
82*5c4dab75SAndroid Build Coastguard Worker   if (complete) {
83*5c4dab75SAndroid Build Coastguard Worker     es->tx_sent = &es->frame.header.NAD;
84*5c4dab75SAndroid Build Coastguard Worker     es->recvd = 0;
85*5c4dab75SAndroid Build Coastguard Worker     ALOGV("card sent a frame");
86*5c4dab75SAndroid Build Coastguard Worker   }
87*5c4dab75SAndroid Build Coastguard Worker   return sizeof(es->frame.header) + es->frame.header.LEN;
88*5c4dab75SAndroid Build Coastguard Worker }
89*5c4dab75SAndroid Build Coastguard Worker 
echo_transmit(struct EseInterface * ese,const uint8_t * buf,uint32_t len,int complete)90*5c4dab75SAndroid Build Coastguard Worker static uint32_t echo_transmit(struct EseInterface *ese, const uint8_t *buf,
91*5c4dab75SAndroid Build Coastguard Worker                               uint32_t len, int complete) {
92*5c4dab75SAndroid Build Coastguard Worker   struct EchoState *es = ECHO_STATE(ese);
93*5c4dab75SAndroid Build Coastguard Worker   ALOGV("interface transmitting data");
94*5c4dab75SAndroid Build Coastguard Worker   if (len > sizeof(es->frame) - (es->rx_fill - &es->frame.header.NAD)) {
95*5c4dab75SAndroid Build Coastguard Worker     return 0;
96*5c4dab75SAndroid Build Coastguard Worker   }
97*5c4dab75SAndroid Build Coastguard Worker   memcpy(es->rx_fill, buf, len);
98*5c4dab75SAndroid Build Coastguard Worker   es->rx_fill += len;
99*5c4dab75SAndroid Build Coastguard Worker   es->recvd = complete;
100*5c4dab75SAndroid Build Coastguard Worker   if (complete) {
101*5c4dab75SAndroid Build Coastguard Worker     es->frame.header.NAD = 0x00;
102*5c4dab75SAndroid Build Coastguard Worker     if (teq1_compute_LRC(&es->frame) != es->frame.INF[es->frame.header.LEN]) {
103*5c4dab75SAndroid Build Coastguard Worker       ALOGV("card received frame with bad LRC");
104*5c4dab75SAndroid Build Coastguard Worker       return 0;
105*5c4dab75SAndroid Build Coastguard Worker     }
106*5c4dab75SAndroid Build Coastguard Worker     ALOGV("card received valid frame");
107*5c4dab75SAndroid Build Coastguard Worker     es->rx_fill = &es->frame.header.NAD;
108*5c4dab75SAndroid Build Coastguard Worker   }
109*5c4dab75SAndroid Build Coastguard Worker   return len;
110*5c4dab75SAndroid Build Coastguard Worker }
111*5c4dab75SAndroid Build Coastguard Worker 
echo_poll(struct EseInterface * ese,uint8_t poll_for,float timeout,int complete)112*5c4dab75SAndroid Build Coastguard Worker static int echo_poll(struct EseInterface *ese, uint8_t poll_for, float timeout,
113*5c4dab75SAndroid Build Coastguard Worker                      int complete) {
114*5c4dab75SAndroid Build Coastguard Worker   struct EchoState *es = ECHO_STATE(ese);
115*5c4dab75SAndroid Build Coastguard Worker   const struct Teq1ProtocolOptions *opts = ese->ops->opts;
116*5c4dab75SAndroid Build Coastguard Worker   ALOGV("interface polling for start of frame/host node address: %x", poll_for);
117*5c4dab75SAndroid Build Coastguard Worker   /* In reality, we should be polling at intervals up to the timeout. */
118*5c4dab75SAndroid Build Coastguard Worker   if (timeout > 0.0) {
119*5c4dab75SAndroid Build Coastguard Worker     usleep(timeout * 1000);
120*5c4dab75SAndroid Build Coastguard Worker   }
121*5c4dab75SAndroid Build Coastguard Worker   if (poll_for == opts->host_address) {
122*5c4dab75SAndroid Build Coastguard Worker     ALOGV("interface received NAD");
123*5c4dab75SAndroid Build Coastguard Worker     if (!complete) {
124*5c4dab75SAndroid Build Coastguard Worker       es->tx_sent++; /* Consume the polled byte: NAD */
125*5c4dab75SAndroid Build Coastguard Worker     }
126*5c4dab75SAndroid Build Coastguard Worker     return 1;
127*5c4dab75SAndroid Build Coastguard Worker   }
128*5c4dab75SAndroid Build Coastguard Worker   return -1;
129*5c4dab75SAndroid Build Coastguard Worker }
130*5c4dab75SAndroid Build Coastguard Worker 
echo_preprocess(const struct Teq1ProtocolOptions * const opts,struct Teq1Frame * frame,int tx)131*5c4dab75SAndroid Build Coastguard Worker int echo_preprocess(const struct Teq1ProtocolOptions *const opts,
132*5c4dab75SAndroid Build Coastguard Worker                     struct Teq1Frame *frame, int tx) {
133*5c4dab75SAndroid Build Coastguard Worker   if (tx) {
134*5c4dab75SAndroid Build Coastguard Worker     /* Recompute the LRC with the NAD of 0x00 */
135*5c4dab75SAndroid Build Coastguard Worker     frame->header.NAD = 0x00;
136*5c4dab75SAndroid Build Coastguard Worker     frame->INF[frame->header.LEN] = teq1_compute_LRC(frame);
137*5c4dab75SAndroid Build Coastguard Worker     frame->header.NAD = opts->node_address;
138*5c4dab75SAndroid Build Coastguard Worker     ALOGV("interface is preprocessing outbound frame");
139*5c4dab75SAndroid Build Coastguard Worker   } else {
140*5c4dab75SAndroid Build Coastguard Worker     /* Replace the NAD with 0x00 so the LRC check passes. */
141*5c4dab75SAndroid Build Coastguard Worker     frame->header.NAD = 0x00;
142*5c4dab75SAndroid Build Coastguard Worker     ALOGV("interface is preprocessing inbound frame");
143*5c4dab75SAndroid Build Coastguard Worker   }
144*5c4dab75SAndroid Build Coastguard Worker   return 0;
145*5c4dab75SAndroid Build Coastguard Worker }
146*5c4dab75SAndroid Build Coastguard Worker 
147*5c4dab75SAndroid Build Coastguard Worker static const struct Teq1ProtocolOptions kTeq1Options = {
148*5c4dab75SAndroid Build Coastguard Worker     .host_address = 0xAA,
149*5c4dab75SAndroid Build Coastguard Worker     .node_address = 0xBB,
150*5c4dab75SAndroid Build Coastguard Worker     .bwt = 3.14152f,
151*5c4dab75SAndroid Build Coastguard Worker     .etu = 1.0f,
152*5c4dab75SAndroid Build Coastguard Worker     .preprocess = &echo_preprocess,
153*5c4dab75SAndroid Build Coastguard Worker };
154*5c4dab75SAndroid Build Coastguard Worker 
echo_transceive(struct EseInterface * ese,const struct EseSgBuffer * tx_buf,uint32_t tx_len,struct EseSgBuffer * rx_buf,uint32_t rx_len)155*5c4dab75SAndroid Build Coastguard Worker uint32_t echo_transceive(struct EseInterface *ese,
156*5c4dab75SAndroid Build Coastguard Worker                          const struct EseSgBuffer *tx_buf, uint32_t tx_len,
157*5c4dab75SAndroid Build Coastguard Worker                          struct EseSgBuffer *rx_buf, uint32_t rx_len) {
158*5c4dab75SAndroid Build Coastguard Worker   return teq1_transceive(ese, &kTeq1Options, tx_buf, tx_len, rx_buf, rx_len);
159*5c4dab75SAndroid Build Coastguard Worker }
160*5c4dab75SAndroid Build Coastguard Worker 
161*5c4dab75SAndroid Build Coastguard Worker static const char *kErrorMessages[] = {
162*5c4dab75SAndroid Build Coastguard Worker     "T=1 hard failure.",        /* TEQ1_ERROR_HARD_FAIL */
163*5c4dab75SAndroid Build Coastguard Worker     "T=1 abort.",               /* TEQ1_ERROR_ABORT */
164*5c4dab75SAndroid Build Coastguard Worker     "T=1 device reset failed.", /* TEQ1_ERROR_DEVICE_ABORT */
165*5c4dab75SAndroid Build Coastguard Worker };
166*5c4dab75SAndroid Build Coastguard Worker 
167*5c4dab75SAndroid Build Coastguard Worker static const struct EseOperations ops = {
168*5c4dab75SAndroid Build Coastguard Worker     .name = "eSE Echo Hardware (fake)",
169*5c4dab75SAndroid Build Coastguard Worker     .open = &echo_open,
170*5c4dab75SAndroid Build Coastguard Worker     .hw_receive = &echo_receive,
171*5c4dab75SAndroid Build Coastguard Worker     .hw_transmit = &echo_transmit,
172*5c4dab75SAndroid Build Coastguard Worker     .transceive = &echo_transceive,
173*5c4dab75SAndroid Build Coastguard Worker     .poll = &echo_poll,
174*5c4dab75SAndroid Build Coastguard Worker     .close = &echo_close,
175*5c4dab75SAndroid Build Coastguard Worker     .opts = &kTeq1Options,
176*5c4dab75SAndroid Build Coastguard Worker     .errors = kErrorMessages,
177*5c4dab75SAndroid Build Coastguard Worker     .errors_count = sizeof(kErrorMessages),
178*5c4dab75SAndroid Build Coastguard Worker };
179*5c4dab75SAndroid Build Coastguard Worker ESE_DEFINE_HW_OPS(ESE_HW_ECHO, ops);
180