Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 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 | |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 19 | #include "../libese/include/ese/ese.h" |
| 20 | |
| 21 | enum EseFakeHwError { |
| 22 | kEseFakeHwErrorEarlyClose, |
| 23 | kEseFakeHwErrorReceiveDuringTransmit, |
| 24 | kEseFakeHwErrorInvalidReceiveSize, |
| 25 | kEseFakeHwErrorTransmitDuringReceive, |
| 26 | kEseFakeHwErrorInvalidTransmitSize, |
| 27 | kEseFakeHwErrorTranscieveWhileBusy, |
| 28 | kEseFakeHwErrorEmptyTransmit, |
| 29 | kEseFakeHwErrorMax, |
| 30 | }; |
| 31 | |
| 32 | static 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 | }; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 41 | |
| 42 | static 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 | |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 49 | static void fake_close(struct EseInterface *ese) { |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 50 | if (!ese->pad[0] || !ese->pad[1]) { |
| 51 | /* Set by caller. ese->error.is_error = 1; */ |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 52 | ese_set_error(ese, kEseFakeHwErrorEarlyClose); |
| 53 | return; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 54 | } |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 55 | } |
| 56 | |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 57 | static uint32_t fake_receive(struct EseInterface *ese, uint8_t *buf, |
| 58 | uint32_t len, int complete) { |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 59 | if (!ese->pad[1]) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 60 | ese_set_error(ese, kEseFakeHwErrorReceiveDuringTransmit); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 61 | return -1; |
| 62 | } |
| 63 | ese->pad[0] = complete; |
| 64 | if (!buf && len) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 65 | ese_set_error(ese, kEseFakeHwErrorInvalidReceiveSize); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 66 | return -1; |
| 67 | } |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 68 | if (!len) { |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 69 | return 0; |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 70 | } |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 71 | return len; |
| 72 | } |
| 73 | |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 74 | static uint32_t fake_transmit(struct EseInterface *ese, const uint8_t *buf, |
| 75 | uint32_t len, int complete) { |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 76 | if (!ese->pad[0]) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 77 | ese_set_error(ese, kEseFakeHwErrorTransmitDuringReceive); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 78 | return -1; |
| 79 | } |
| 80 | ese->pad[1] = complete; |
| 81 | if (!buf && len) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 82 | ese_set_error(ese, kEseFakeHwErrorInvalidTransmitSize); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 83 | return -1; |
| 84 | } |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 85 | if (!len) { |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 86 | return 0; |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 87 | } |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 88 | return len; |
| 89 | } |
| 90 | |
| 91 | static 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]) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 95 | ese_set_error(ese, kEseFakeHwErrorReceiveDuringTransmit); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 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 | |
Will Drewry | 8f367fc | 2017-03-30 22:07:48 -0500 | [diff] [blame] | 110 | uint32_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) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 113 | uint32_t processed = 0; |
Will Drewry | 8f367fc | 2017-03-30 22:07:48 -0500 | [diff] [blame] | 114 | uint32_t offset = 0; |
| 115 | struct EseSgBuffer *rx_buf = rx_bufs; |
| 116 | const struct EseSgBuffer *tx_buf = tx_bufs; |
| 117 | |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 118 | if (!ese->pad[0] || !ese->pad[1]) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 119 | ese_set_error(ese, kEseFakeHwErrorTranscieveWhileBusy); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 120 | return 0; |
| 121 | } |
Will Drewry | 8f367fc | 2017-03-30 22:07:48 -0500 | [diff] [blame] | 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 | } |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 130 | if (sent == 0) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 131 | if (ese_error(ese)) { |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 132 | return 0; |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 133 | } |
| 134 | ese_set_error(ese, kEseFakeHwErrorEmptyTransmit); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 135 | return 0; |
| 136 | } |
Will Drewry | 8f367fc | 2017-03-30 22:07:48 -0500 | [diff] [blame] | 137 | tx_buf++; |
| 138 | offset = 0; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 139 | processed += sent; |
| 140 | } |
| 141 | fake_transmit(ese, NULL, 0, 1); /* Complete. */ |
| 142 | if (fake_poll(ese, 0xad, 10, 0) != 1) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 143 | ese_set_error(ese, kEseGlobalErrorPollTimedOut); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 144 | return 0; |
| 145 | } |
Will Drewry | 8f367fc | 2017-03-30 22:07:48 -0500 | [diff] [blame] | 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 | } |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 151 | return processed; |
| 152 | } |
| 153 | |
| 154 | static 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, |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 163 | .errors = kErrorMessages, |
| 164 | .errors_count = sizeof(kErrorMessages), |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 165 | }; |
| 166 | ESE_DEFINE_HW_OPS(ESE_HW_FAKE, ops); |
| 167 | |