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