aboutsummaryrefslogtreecommitdiff
path: root/libese-teq1/include/ese/teq1.h
blob: 0c4a6fab8e868891035560cf8c57e2fa6aca838d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * 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 <ese/ese.h>
#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_<TYPE>(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_ */