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