/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ESE_TEQ1_H_ #define ESE_TEQ1_H_ 1 #ifdef __cplusplus extern "C" { #endif #include "../../../libese/include/ese/ese.h" #include "../../../libese/include/ese/bit_spec.h" /* Reserved codes for T=1 devices in EseOperation­>errors. */ enum Teq1Error { kTeq1ErrorHardFail = 0, kTeq1ErrorAbort, kTeq1ErrorDeviceReset, kTeq1ErrorMax, }; /* For use in constant initializers libese-hw errors. */ #define TEQ1_ERROR_MESSAGES \ [kTeq1ErrorHardFail] = "T=1 suffered hard failure", \ [kTeq1ErrorAbort] = "T=1 aborting due to errors", \ [kTeq1ErrorDeviceReset] = "T=1 unable to recover even after device reset" enum pcb_type { kPcbTypeInfo0 = 0x0, kPcbTypeInfo1 = 0x1, kPcbTypeReceiveReady = 0x2, kPcbTypeSupervisory = 0x3, }; enum super_type { kSuperTypeResync = 0x0, kSuperTypeIFS = 0x1, kSuperTypeAbort = 0x2, kSuperTypeWTX = 0x3, }; struct PcbSpec { struct bit_spec type; struct bit_spec data; struct { struct bit_spec more_data; struct bit_spec send_seq; } I; struct { struct bit_spec parity_err; struct bit_spec other_err; struct bit_spec next_seq; } R; struct { struct bit_spec type; struct bit_spec response; } S; }; const static struct PcbSpec PCB = { .type = { .value = 3, .shift = 6, }, .data = { .value = 63, .shift = 0, }, .I = { .more_data = { .value = 1, .shift = 5, }, .send_seq = { .value = 1, .shift = 6, }, }, .R = { /* char parity or redundancy code err */ .parity_err = { .value = 1, .shift = 0, }, /* any other errors */ .other_err = { .value = 1, .shift = 1, }, /* If the same seq as last frame, then err even if other bits are 0. */ .next_seq = { .value = 1, .shift = 4, }, }, .S = { .type = { .value = 3, .shift = 0, }, .response = { .value = 1, .shift = 5, }, }, }; struct Teq1Header { uint8_t NAD; uint8_t PCB; uint8_t LEN; }; #define TEQ1HEADER_SIZE 3 #define TEQ1FRAME_SIZE INF_LEN + 1 + TEQ1HEADER_SIZE #define INF_LEN 254 #define IFSC 254 struct Teq1Frame { union { uint8_t val[sizeof(struct Teq1Header) + INF_LEN + 1]; struct { struct Teq1Header header; union { uint8_t INF[INF_LEN + 1]; /* Up to 254 with trailing LRC byte. */ }; /* If CRC was supported, it would be uint16_t. */ }; }; }; /* * Required to be the header for all EseInterface pad[]s for * cards implementing T=1. */ struct Teq1CardState { union { struct { int card:1; int interface:1; }; uint8_t seq_bits; } seq; }; /* Set "last sent" to 1 so we start at 0. */ #define TEQ1_INIT_CARD_STATE(CARD) \ (CARD)->seq.card = 1; \ (CARD)->seq.interface = 1; /* * Used by devices implementing T=1 to set specific options * or callback behavior. */ struct Teq1ProtocolOptions; typedef int (teq1_protocol_preprocess_op_t)(const struct Teq1ProtocolOptions *const, struct Teq1Frame *, int); struct Teq1ProtocolOptions { uint8_t host_address; /* NAD to listen for */ uint8_t node_address; /* NAD to send to */ float bwt; float etu; /* * If not NULL, is called immediately before transmit (1) * and immediately after receive. */ teq1_protocol_preprocess_op_t *preprocess; }; /* PCB bits */ #define kTeq1PcbType (3 << 6) /* I-block bits */ #define kTeq1InfoType (0 << 6) #define kTeq1InfoMoreBit (1 << 5) #define kTeq1InfoSeqBit (1 << 6) /* R-block bits */ #define kTeq1RrType (1 << 7) #define kTeq1RrSeqBit (1 << 4) #define kTeq1RrParityError (1) #define kTeq1RrOtherError (1 << 1) /* S-block bits */ #define kTeq1SuperType (3 << 6) #define kTeq1SuperRequestBit (0) #define kTeq1SuperResponseBit (1 << 5) #define kTeq1SuperResyncBit (0) #define kTeq1SuperIfsBit (1) #define kTeq1SuperAbortBit (1 << 1) #define kTeq1SuperWtxBit (3) /* I(Seq, More-bit) */ #define TEQ1_I(S, M) ((S) << 6) | ((M) << 5) /* R(Seq, Other Error, Parity Error) */ #define TEQ1_R(S, O, P) (kTeq1RrType | ((S) << 4) | (P) | ((O) << 1)) /* S_(response) */ #define TEQ1_S_RESYNC(R) (kTeq1SuperType | ((R) << 5) | kTeq1SuperResyncBit) #define TEQ1_S_WTX(R) (kTeq1SuperType | ((R) << 5) | kTeq1SuperWtxBit) #define TEQ1_S_ABORT(R) (kTeq1SuperType | ((R) << 5) | kTeq1SuperAbortBit) #define TEQ1_S_IFS(R) (kTeq1SuperType | ((R) << 5) | kTeq1SuperIfsBit) uint32_t teq1_transceive(struct EseInterface *ese, const struct Teq1ProtocolOptions *opts, const struct EseSgBuffer *tx_bufs, uint8_t tx_segs, struct EseSgBuffer *rx_bufs, uint8_t rx_segs); uint8_t teq1_compute_LRC(const struct Teq1Frame *frame); #define teq1_trace_header() ALOGI("%-20s --- %20s", "Interface", "Card") #define teq1_trace_transmit(PCB, LEN) ALOGI("%-20s --> %20s [%3hhu]", teq1_pcb_to_name(PCB), "", LEN) #define teq1_trace_receive(PCB, LEN) ALOGI("%-20s <-- %20s [%3hhu]", "", teq1_pcb_to_name(PCB), LEN) #ifdef __cplusplus } /* extern "C" */ #endif #endif /* ESE_TEQ1_H_ */