1/*
2 * Copyright (C) 2016 The Android Open Source Project
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 *      http://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 * Minimal functions that only validate arguments.
17 */
18
19#include "../libese/include/ese/ese.h"
20
21enum EseFakeHwError {
22  kEseFakeHwErrorEarlyClose,
23  kEseFakeHwErrorReceiveDuringTransmit,
24  kEseFakeHwErrorInvalidReceiveSize,
25  kEseFakeHwErrorTransmitDuringReceive,
26  kEseFakeHwErrorInvalidTransmitSize,
27  kEseFakeHwErrorTranscieveWhileBusy,
28  kEseFakeHwErrorEmptyTransmit,
29  kEseFakeHwErrorMax,
30};
31
32static const char *kErrorMessages[] = {
33    "Interface closed without finishing transmission.",
34    "Receive called without completing transmission.",
35    "Invalid receive buffer supplied with non-zero length.",
36    "Transmit called without completing reception.",
37    "Invalid transmit buffer supplied with non-zero length.",
38    "Transceive called while other I/O in process.",
39    "Transmitted no data.", /* Can reach this by setting tx_len = 0. */
40};
41
42static int fake_open(struct EseInterface *ese,
43                     void *hw_opts __attribute__((unused))) {
44  ese->pad[0] = 1; /* rx complete */
45  ese->pad[1] = 1; /* tx complete */
46  return 0;
47}
48
49static void fake_close(struct EseInterface *ese) {
50  if (!ese->pad[0] || !ese->pad[1]) {
51    /* Set by caller. ese->error.is_error = 1; */
52    ese_set_error(ese, kEseFakeHwErrorEarlyClose);
53    return;
54  }
55}
56
57static uint32_t fake_receive(struct EseInterface *ese, uint8_t *buf,
58                             uint32_t len, int complete) {
59  if (!ese->pad[1]) {
60    ese_set_error(ese, kEseFakeHwErrorReceiveDuringTransmit);
61    return -1;
62  }
63  ese->pad[0] = complete;
64  if (!buf && len) {
65    ese_set_error(ese, kEseFakeHwErrorInvalidReceiveSize);
66    return -1;
67  }
68  if (!len) {
69    return 0;
70  }
71  return len;
72}
73
74static uint32_t fake_transmit(struct EseInterface *ese, const uint8_t *buf,
75                              uint32_t len, int complete) {
76  if (!ese->pad[0]) {
77    ese_set_error(ese, kEseFakeHwErrorTransmitDuringReceive);
78    return -1;
79  }
80  ese->pad[1] = complete;
81  if (!buf && len) {
82    ese_set_error(ese, kEseFakeHwErrorInvalidTransmitSize);
83    return -1;
84  }
85  if (!len) {
86    return 0;
87  }
88  return len;
89}
90
91static int fake_poll(struct EseInterface *ese, uint8_t poll_for, float timeout,
92                     int complete) {
93  /* Poll begins a receive-train so transmit needs to be completed. */
94  if (!ese->pad[1]) {
95    ese_set_error(ese, kEseFakeHwErrorReceiveDuringTransmit);
96    return -1;
97  }
98  if (timeout == 0.0f) {
99    /* Instant timeout. */
100    return 0;
101  }
102  /* Only expect one value to work. */
103  if (poll_for == 0xad) {
104    return 1;
105  }
106  ese->pad[0] = complete;
107  return 0;
108}
109
110uint32_t fake_transceive(struct EseInterface *ese,
111                         const struct EseSgBuffer *tx_bufs, uint32_t tx_seg,
112                         struct EseSgBuffer *rx_bufs, uint32_t rx_seg) {
113  uint32_t processed = 0;
114  uint32_t offset = 0;
115  struct EseSgBuffer *rx_buf = rx_bufs;
116  const struct EseSgBuffer *tx_buf = tx_bufs;
117
118  if (!ese->pad[0] || !ese->pad[1]) {
119    ese_set_error(ese, kEseFakeHwErrorTranscieveWhileBusy);
120    return 0;
121  }
122  while (tx_buf < tx_bufs + tx_seg) {
123    uint32_t sent =
124        fake_transmit(ese, tx_buf->base + offset, tx_buf->len - offset, 0);
125    if (sent != tx_buf->len - offset) {
126      offset = tx_buf->len - sent;
127      processed += sent;
128      continue;
129    }
130    if (sent == 0) {
131      if (ese_error(ese)) {
132        return 0;
133      }
134      ese_set_error(ese, kEseFakeHwErrorEmptyTransmit);
135      return 0;
136    }
137    tx_buf++;
138    offset = 0;
139    processed += sent;
140  }
141  fake_transmit(ese, NULL, 0, 1); /* Complete. */
142  if (fake_poll(ese, 0xad, 10, 0) != 1) {
143    ese_set_error(ese, kEseGlobalErrorPollTimedOut);
144    return 0;
145  }
146  /* This reads the full RX buffer rather than a protocol specified amount. */
147  processed = 0;
148  while (rx_buf < rx_bufs + rx_seg) {
149    processed += fake_receive(ese, rx_buf->base, rx_buf->len, 1);
150  }
151  return processed;
152}
153
154static const struct EseOperations ops = {
155    .name = "eSE Fake Hardware",
156    .open = &fake_open,
157    .hw_receive = &fake_receive,
158    .hw_transmit = &fake_transmit,
159    .transceive = &fake_transceive,
160    .poll = &fake_poll,
161    .close = &fake_close,
162    .opts = NULL,
163    .errors = kErrorMessages,
164    .errors_count = sizeof(kErrorMessages),
165};
166ESE_DEFINE_HW_OPS(ESE_HW_FAKE, ops);
167
168