• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 
17 #include "include/ese/teq1.h"
18 #include "../libese/include/ese/ese.h"
19 #include "../libese/include/ese/log.h"
20 
21 #include "teq1_private.h"
22 
teq1_rule_result_to_name(enum RuleResult result)23 const char *teq1_rule_result_to_name(enum RuleResult result) {
24   switch (result) {
25   case kRuleResultComplete:
26     return "Complete";
27   case kRuleResultAbort:
28     return "Abort";
29   case kRuleResultContinue:
30     return "Continue";
31   case kRuleResultHardFail:
32     return "Hard failure";
33   case kRuleResultResetDevice:
34     return "Reset device";
35   case kRuleResultResetSession:
36     return "Reset session";
37   case kRuleResultRetransmit:
38     return "Retransmit";
39   case kRuleResultSingleShot:
40     return "Single shot";
41   };
42 }
43 
teq1_pcb_to_name(uint8_t pcb)44 const char *teq1_pcb_to_name(uint8_t pcb) {
45   switch (pcb) {
46   case I(0, 0):
47     return "I(0, 0)";
48   case I(0, 1):
49     return "I(0, 1)";
50   case I(1, 0):
51     return "I(1, 0)";
52   case I(1, 1):
53     return "I(1, 1)";
54   case R(0, 0, 0):
55     return "R(0, 0, 0)";
56   case R(0, 0, 1):
57     return "R(0, 0, 1)";
58   case R(0, 1, 0):
59     return "R(0, 1, 0)";
60   case R(0, 1, 1):
61     return "R(0, 1, 1)";
62   case R(1, 0, 0):
63     return "R(1, 0, 0)";
64   case R(1, 0, 1):
65     return "R(1, 0, 1)";
66   case R(1, 1, 0):
67     return "R(1, 1, 0)";
68   case R(1, 1, 1):
69     return "R(1, 1, 1)";
70   case S(RESYNC, REQUEST):
71     return "S(RESYNC, REQUEST)";
72   case S(RESYNC, RESPONSE):
73     return "S(RESYNC, RESPONSE)";
74   case S(IFS, REQUEST):
75     return "S(IFS, REQUEST)";
76   case S(IFS, RESPONSE):
77     return "S(IFS, RESPONSE)";
78   case S(ABORT, REQUEST):
79     return "S(ABORT, REQUEST)";
80   case S(ABORT, RESPONSE):
81     return "S(ABORT, RESPONSE)";
82   case S(WTX, REQUEST):
83     return "S(WTX, REQUEST)";
84   case S(WTX, RESPONSE):
85     return "S(WTX, RESPONSE)";
86   case 255:
87     return "INTERNAL-ERROR";
88   default:
89     return "???";
90   }
91 }
92 
teq1_dump_buf(const char * prefix,const uint8_t * buf,uint32_t len)93 void teq1_dump_buf(const char *prefix, const uint8_t *buf, uint32_t len) {
94   uint32_t recvd = 0;
95   for (recvd = 0; recvd < len; ++recvd)
96     ALOGV("%s[%u]: %.2X", prefix, recvd, buf[recvd]);
97 }
98 
teq1_transmit(struct EseInterface * ese,const struct Teq1ProtocolOptions * opts,struct Teq1Frame * frame)99 int teq1_transmit(struct EseInterface *ese,
100                   const struct Teq1ProtocolOptions *opts,
101                   struct Teq1Frame *frame) {
102   /* Set correct node address. */
103   frame->header.NAD = opts->node_address;
104 
105   /* Compute the LRC */
106   frame->INF[frame->header.LEN] = teq1_compute_LRC(frame);
107 
108   /*
109    * If the card does something weird, like expect an CRC/LRC based on a
110    * different header value, the preprocessing can handle it.
111    */
112   if (opts->preprocess) {
113     opts->preprocess(opts, frame, 1);
114   }
115 
116   /*
117    * Begins transmission and ignore errors.
118    * Failed transmissions will result eventually in a resync then reset.
119    */
120   teq1_trace_transmit(frame->header.PCB, frame->header.LEN);
121   teq1_dump_transmit(frame->val, sizeof(frame->header) + frame->header.LEN + 1);
122   ese->ops->hw_transmit(ese, frame->val,
123                         sizeof(frame->header) + frame->header.LEN + 1, 1);
124   /*
125    * Even though in practice any WTX BWT extension starts when the above
126    * transmit ends, it is easier to implement it in the polling timeout of
127    * receive.
128    */
129   return 0;
130 }
131 
teq1_receive(struct EseInterface * ese,const struct Teq1ProtocolOptions * opts,float timeout,struct Teq1Frame * frame)132 int teq1_receive(struct EseInterface *ese,
133                  const struct Teq1ProtocolOptions *opts, float timeout,
134                  struct Teq1Frame *frame) {
135   /* Poll the bus until we see the start of frame indicator, the interface NAD.
136    */
137   int bytes_consumed = ese->ops->poll(ese, opts->host_address, timeout, 0);
138   if (bytes_consumed < 0 || bytes_consumed > 1) {
139     /* Timed out or comm error. */
140     ALOGV("%s: comm error: %d", __func__, bytes_consumed);
141     return -1;
142   }
143   /* We polled for the NAD above -- if it was consumed, set it here. */
144   if (bytes_consumed) {
145     frame->header.NAD = opts->host_address;
146   }
147   /* Get the remainder of the header, but keep the line &open. */
148   ese->ops->hw_receive(ese, (uint8_t *)(&frame->header.NAD + bytes_consumed),
149                        sizeof(frame->header) - bytes_consumed, 0);
150   teq1_dump_receive((uint8_t *)(&frame->header.NAD + bytes_consumed),
151                     sizeof(frame->header) - bytes_consumed);
152   if (frame->header.LEN == 255) {
153     ALOGV("received invalid LEN of 255");
154     /* Close the receive window and return failure. */
155     ese->ops->hw_receive(ese, NULL, 0, 1);
156     return -1;
157   }
158   /*
159    * Get the data and the first byte of CRC data.
160    * Note, CRC support is not implemented. Only a single LRC byte is expected.
161    */
162   ese->ops->hw_receive(ese, (uint8_t *)(&(frame->INF[0])),
163                        frame->header.LEN + 1, 1);
164   teq1_dump_receive((uint8_t *)(&(frame->INF[0])), frame->header.LEN + 1);
165   teq1_trace_receive(frame->header.PCB, frame->header.LEN);
166 
167   /*
168    * If the card does something weird, like expect an CRC/LRC based on a
169    * different
170    * header value, the preprocessing should fix up here prior to the LRC check.
171    */
172   if (opts->preprocess) {
173     opts->preprocess(opts, frame, 0);
174   }
175 
176   /* LRC and other protocol goodness checks are not done here. */
177   return frame->header.LEN; /* Return data bytes read. */
178 }
179 
teq1_fill_info_block(struct Teq1State * state,struct Teq1Frame * frame)180 uint8_t teq1_fill_info_block(struct Teq1State *state, struct Teq1Frame *frame) {
181   uint32_t inf_len = INF_LEN;
182   if (state->ifs < inf_len) {
183     inf_len = state->ifs;
184   }
185   switch (bs_get(PCB.type, frame->header.PCB)) {
186   case kPcbTypeInfo0:
187   case kPcbTypeInfo1: {
188     uint32_t len = state->app_data.tx_total;
189     uint32_t copied = 0;
190     if (len > inf_len) {
191       len = inf_len;
192     }
193     copied = ese_sg_to_buf(state->app_data.tx, state->app_data.tx_count,
194                            state->app_data.tx_offset, len, frame->INF);
195     if (copied != len) {
196       ALOGE("Failed to copy %x bytes of app data for transmission",
197             frame->header.LEN);
198       /* TODO(wad): This return code is largely ignored. Is the precondition
199        * checking elsewhere enough? */
200       return 255;
201     }
202     frame->header.LEN = (len & 0xff);
203     ALOGV("Copying %x bytes of app data for transmission", frame->header.LEN);
204     /* Incrementing here means the caller MUST handle retransmit with prepared
205      * data. */
206     state->app_data.tx_offset += copied;
207     state->app_data.tx_total -= copied;
208     /* Perform chained transmission if needed. */
209     bs_assign(&frame->header.PCB, PCB.I.more_data, 0);
210     if (state->app_data.tx_total > 0) {
211       frame->header.PCB |= bs_mask(PCB.I.more_data, 1);
212     }
213     return len;
214   }
215   case kPcbTypeSupervisory:
216   case kPcbTypeReceiveReady:
217   default:
218     break;
219   }
220   return 255; /* Invalid block type. */
221 }
222 
teq1_get_app_data(struct Teq1State * state,const struct Teq1Frame * frame)223 void teq1_get_app_data(struct Teq1State *state, const struct Teq1Frame *frame) {
224   switch (bs_get(PCB.type, frame->header.PCB)) {
225   case kPcbTypeInfo0:
226   case kPcbTypeInfo1: {
227     uint32_t len = frame->header.LEN;
228     /* TODO(wad): Some data will be left on the table. Should this error out? */
229     if (len > state->app_data.rx_total) {
230       len = state->app_data.rx_total;
231     }
232     ese_sg_from_buf(state->app_data.rx, state->app_data.rx_count,
233                     state->app_data.rx_offset, len, frame->INF);
234     /* The original caller must retain the starting pointer to determine
235      * actual available data.
236      */
237     state->app_data.rx_total -= len;
238     state->app_data.rx_offset += len;
239     return;
240   }
241   case kPcbTypeReceiveReady:
242   case kPcbTypeSupervisory:
243   default:
244     break;
245   }
246   return;
247 }
248 
249 /* Returns an R(0) frame with error bits set. */
teq1_frame_error_check(struct Teq1State * state,struct Teq1Frame * tx_frame,struct Teq1Frame * rx_frame)250 uint8_t teq1_frame_error_check(struct Teq1State *state,
251                                struct Teq1Frame *tx_frame,
252                                struct Teq1Frame *rx_frame) {
253   uint8_t lrc = 0;
254   int chained = 0;
255   if (rx_frame->header.PCB == 255) {
256     return R(0, 1, 0); /* Other error */
257   }
258 
259   lrc = teq1_compute_LRC(rx_frame);
260   if (rx_frame->INF[rx_frame->header.LEN] != lrc) {
261     ALOGE("Invalid LRC %x instead of %x", rx_frame->INF[rx_frame->header.LEN],
262           lrc);
263     return R(0, 0, 1); /* Parity error */
264   }
265 
266   /* Check if we were chained and increment the last sent sequence. */
267   switch (bs_get(PCB.type, tx_frame->header.PCB)) {
268   case kPcbTypeInfo0:
269   case kPcbTypeInfo1:
270     chained = bs_get(PCB.I.more_data, tx_frame->header.PCB);
271     state->card_state->seq.interface =
272         bs_get(PCB.I.send_seq, tx_frame->header.PCB);
273   }
274 
275   /* Check if we've gone down an easy to catch error hole. The rest will turn up
276    * on the
277    * txrx switch.
278    */
279   switch (bs_get(PCB.type, rx_frame->header.PCB)) {
280   case kPcbTypeSupervisory:
281     if (rx_frame->header.PCB != S(RESYNC, RESPONSE) &&
282         rx_frame->header.LEN != 1) {
283       ALOGE("Invalid supervisory RX frame.");
284       return R(0, 1, 0);
285     }
286     break;
287   case kPcbTypeReceiveReady:
288     if (rx_frame->header.LEN != 0) {
289       ALOGE("Invalid ReceiveReady RX frame.");
290       return R(0, 1, 0);
291     }
292     break;
293   case kPcbTypeInfo0:
294   case kPcbTypeInfo1:
295     /* I-blocks must always alternate for each endpoint. */
296     if ((bs_get(PCB.I.send_seq, rx_frame->header.PCB)) ==
297         state->card_state->seq.card) {
298       ALOGW("Got seq %d expected %d",
299             bs_get(PCB.I.send_seq, rx_frame->header.PCB),
300             state->card_state->seq.card);
301       ALOGE("Invalid Info RX frame.");
302       return R(0, 1, 0);
303     }
304     /* Update the card's last I-block seq. */
305     state->card_state->seq.card = bs_get(PCB.I.send_seq, rx_frame->header.PCB);
306   default:
307     break;
308   };
309   return 0;
310 }
311 
teq1_rules(struct Teq1State * state,struct Teq1Frame * tx_frame,struct Teq1Frame * rx_frame,struct Teq1Frame * next_tx)312 enum RuleResult teq1_rules(struct Teq1State *state, struct Teq1Frame *tx_frame,
313                            struct Teq1Frame *rx_frame,
314                            struct Teq1Frame *next_tx) {
315   /* Rule 1 is enforced by first call∴ Start with I(0,M). */
316   /* 0 = TX, 1 = RX */
317   /* msb = tx pcb, lsb = rx pcb */
318   /* BUG_ON(!rx_frame && !tx_frame && !next_tx); */
319   uint16_t txrx = TEQ1_RULE(tx_frame->header.PCB, rx_frame->header.PCB);
320   uint8_t R_err;
321 
322   while (1) {
323     /* Timeout errors come like invalid frames: 255. */
324     if ((R_err = teq1_frame_error_check(state, tx_frame, rx_frame)) != 0) {
325       ALOGW("incoming frame failed the error check");
326       state->last_error_message = "Invalid frame received";
327       /* Mark the frame as bad for our rule evaluation. */
328       txrx = TEQ1_RULE(tx_frame->header.PCB, 255);
329       state->errors++;
330       /* Rule 6.4 */
331       if (state->errors >= 6) {
332         return kRuleResultResetDevice;
333       }
334       /* Rule 7.4.2 */
335       if (state->errors >= 3) {
336         /* Rule 7.4.1: state should start with error count = 2 */
337         if (tx_frame->header.PCB != S(RESYNC, REQUEST)) {
338           next_tx->header.PCB = S(RESYNC, REQUEST);
339           return kRuleResultContinue;
340         }
341         return kRuleResultRetransmit;
342       }
343     }
344 
345     /* Specific matches */
346     switch (txrx) {
347     /*** Rule 2.1: I() -> I() ***/
348     /* Error check will determine if the card seq is right. */
349     case TEQ1_RULE(I(0, 0), I(0, 0)):
350     case TEQ1_RULE(I(0, 0), I(1, 0)):
351     case TEQ1_RULE(I(1, 0), I(1, 0)):
352     case TEQ1_RULE(I(1, 0), I(0, 0)):
353       /* Read app data & return. */
354       teq1_get_app_data(state, rx_frame);
355       return kRuleResultComplete;
356 
357     /* Card begins chained response. */
358     case TEQ1_RULE(I(0, 0), I(0, 1)):
359     case TEQ1_RULE(I(1, 0), I(1, 1)):
360       /* Prep R(N(S)) */
361       teq1_get_app_data(state, rx_frame);
362       next_tx->header.PCB =
363           TEQ1_R(!bs_get(PCB.I.send_seq, rx_frame->header.PCB), 0, 0);
364       next_tx->header.LEN = 0;
365       return kRuleResultContinue;
366 
367     /*** Rule 2.2, Rule 5: Chained transmission ***/
368     case TEQ1_RULE(I(0, 1), R(1, 0, 0)):
369     case TEQ1_RULE(I(1, 1), R(0, 0, 0)):
370       /* Send next block -- error-checking assures the R seq is our next seq. */
371       next_tx->header.PCB =
372           TEQ1_I(bs_get(PCB.R.next_seq, rx_frame->header.PCB), 0);
373       teq1_fill_info_block(state, next_tx); /* Sets M-bit and LEN. */
374       return kRuleResultContinue;
375 
376     /*** Rule 3 ***/
377     case TEQ1_RULE(I(0, 0), S(WTX, REQUEST)):
378     case TEQ1_RULE(I(1, 0), S(WTX, REQUEST)):
379       /* Note: Spec is unclear on if WTX can occur during chaining so we make it
380       an error for now.
381       case TEQ1_RULE(I(0, 1), S(WTX, REQUEST)):
382       case TEQ1_RULE(I(1, 1), S(WTX, REQUEST)):
383       */
384       /* Send S(WTX, RESPONSE) with same INF */
385       next_tx->header.PCB = S(WTX, RESPONSE);
386       next_tx->header.LEN = 1;
387       next_tx->INF[0] = rx_frame->INF[0];
388       state->wait_mult = rx_frame->INF[0];
389       /* Then wait BWT*INF[0] after transmission. */
390       return kRuleResultSingleShot; /* Send then call back in with same tx_frame
391                                        and new rx_frame. */
392 
393     /*** Rule 4 ***/
394     case TEQ1_RULE(S(IFS, REQUEST), S(IFS, RESPONSE)):
395       /* XXX: Check INFs match. */
396       return kRuleResultComplete; /* This is treated as an unique operation. */
397     case TEQ1_RULE(I(0, 0), S(IFS, REQUEST)):
398     case TEQ1_RULE(I(0, 1), S(IFS, REQUEST)):
399     case TEQ1_RULE(I(1, 0), S(IFS, REQUEST)):
400     case TEQ1_RULE(I(1, 1), S(IFS, REQUEST)):
401     /* Don't support a IFS_REQUEST if we sent an error R-block. */
402     case TEQ1_RULE(R(0, 0, 0), S(IFS, REQUEST)):
403     case TEQ1_RULE(R(1, 0, 0), S(IFS, REQUEST)):
404       next_tx->header.PCB = S(IFS, RESPONSE);
405       next_tx->header.LEN = 1;
406       next_tx->INF[0] = rx_frame->INF[0];
407       state->ifs = rx_frame->INF[0];
408       return kRuleResultSingleShot;
409 
410     /*** Rule 5  (see Rule 2.2 for the chained-tx side. ) ***/
411     case TEQ1_RULE(R(0, 0, 0), I(0, 0)):
412     case TEQ1_RULE(R(1, 0, 0), I(1, 0)):
413       /* Chaining ended with terminal I-block. */
414       teq1_get_app_data(state, rx_frame);
415       return kRuleResultComplete;
416     case TEQ1_RULE(R(0, 0, 0), I(0, 1)):
417     case TEQ1_RULE(R(1, 0, 0), I(1, 1)):
418       /* Chaining continued; consume partial data and send R(N(S)) */
419       teq1_get_app_data(state, rx_frame);
420       /* The card seq bit will be tracked/validated earlier. */
421       next_tx->header.PCB =
422           TEQ1_R(!bs_get(PCB.I.send_seq, rx_frame->header.PCB), 0, 0);
423       return kRuleResultContinue;
424 
425     /* Rule 6: Interface can send a RESYNC */
426     /* Rule 6.1: timeout BWT right. No case here. */
427     /* Rule 6.2, 6.3 */
428     case TEQ1_RULE(S(RESYNC, REQUEST), S(RESYNC, RESPONSE)):
429       /* Rule 6.5: indicates that the card should assume its prior
430        * block was lost _and_ the interface gets transmit privilege,
431        * so we just start fresh.
432        */
433       return kRuleResultResetSession; /* Start a new exchange (rule 6.3) */
434     case TEQ1_RULE(S(RESYNC, REQUEST), 255):
435       /* Retransmit the same frame up to 3 times. */
436       return kRuleResultRetransmit;
437 
438     /* Rule 7.1, 7.5, 7.6 */
439     case TEQ1_RULE(I(0, 0), 255):
440     case TEQ1_RULE(I(1, 0), 255):
441     case TEQ1_RULE(I(0, 1), 255):
442     case TEQ1_RULE(I(1, 1), 255):
443       next_tx->header.PCB = R_err;
444       bs_assign(&next_tx->header.PCB, PCB.R.next_seq,
445                 bs_get(PCB.I.send_seq, tx_frame->header.PCB));
446       ALOGW("Rule 7.1,7.5,7.6: bad rx - sending error R: %x = %s",
447             next_tx->header.PCB, teq1_pcb_to_name(next_tx->header.PCB));
448       return kRuleResultSingleShot; /* So we still can retransmit the original.
449                                        */
450 
451     /* Caught in the error check. */
452     case TEQ1_RULE(I(0, 0), R(1, 0, 0)):
453     case TEQ1_RULE(I(0, 0), R(1, 0, 1)):
454     case TEQ1_RULE(I(0, 0), R(1, 1, 0)):
455     case TEQ1_RULE(I(0, 0), R(1, 1, 1)):
456     case TEQ1_RULE(I(1, 0), R(0, 0, 0)):
457     case TEQ1_RULE(I(1, 0), R(0, 0, 1)):
458     case TEQ1_RULE(I(1, 0), R(0, 1, 0)):
459     case TEQ1_RULE(I(1, 0), R(0, 1, 1)):
460       next_tx->header.PCB =
461           TEQ1_R(bs_get(PCB.I.send_seq, tx_frame->header.PCB), 0, 0);
462       ALOGW("Rule 7.1,7.5,7.6: weird rx - sending error R: %x = %s",
463             next_tx->header.PCB, teq1_pcb_to_name(next_tx->header.PCB));
464       return kRuleResultSingleShot;
465 
466     /* Rule 7.2: Retransmit the _same_ R-block. */
467     /* The remainder of this rule is implemented in the next switch. */
468     case TEQ1_RULE(R(0, 0, 0), 255):
469     case TEQ1_RULE(R(0, 0, 1), 255):
470     case TEQ1_RULE(R(0, 1, 0), 255):
471     case TEQ1_RULE(R(0, 1, 1), 255):
472     case TEQ1_RULE(R(1, 0, 0), 255):
473     case TEQ1_RULE(R(1, 0, 1), 255):
474     case TEQ1_RULE(R(1, 1, 0), 255):
475     case TEQ1_RULE(R(1, 1, 1), 255):
476       return kRuleResultRetransmit;
477 
478     /* Rule 7.3 request */
479     /* Note, 7.3 for transmission of S(*, RESPONSE) won't be seen because they
480      * are
481      * single shots.
482      * Instead, the invalid block will be handled as invalid for the prior TX.
483      * This should yield the correct R-block.
484      */
485     case TEQ1_RULE(I(0, 0), R(0, 0, 0)):
486     case TEQ1_RULE(I(0, 0), R(0, 0, 1)):
487     case TEQ1_RULE(I(0, 0), R(0, 1, 0)):
488     case TEQ1_RULE(I(0, 0), R(0, 1, 1)):
489     case TEQ1_RULE(I(1, 0), R(1, 0, 0)):
490     case TEQ1_RULE(I(1, 0), R(1, 1, 0)):
491     case TEQ1_RULE(I(1, 0), R(1, 0, 1)):
492     case TEQ1_RULE(I(1, 0), R(1, 1, 1)):
493     case TEQ1_RULE(I(0, 1), R(0, 0, 0)):
494     case TEQ1_RULE(I(0, 1), R(0, 1, 0)):
495     case TEQ1_RULE(I(0, 1), R(0, 0, 1)):
496     case TEQ1_RULE(I(0, 1), R(0, 1, 1)):
497     case TEQ1_RULE(I(1, 1), R(1, 0, 0)):
498     case TEQ1_RULE(I(1, 1), R(1, 1, 0)):
499     case TEQ1_RULE(I(1, 1), R(1, 0, 1)):
500     case TEQ1_RULE(I(1, 1), R(1, 1, 1)):
501       /* Retransmit I-block */
502       return kRuleResultRetransmit;
503 
504     /* Rule 8 is card only. */
505     /* Rule 9: aborting a chain.
506      * If a S(ABORT) is injected into this engine, then we may have sent an
507      * abort.
508      */
509     case TEQ1_RULE(S(ABORT, REQUEST), S(ABORT, RESPONSE)):
510       /* No need to send back a R() because we want to keep transmit. */
511       return kRuleResultComplete; /* If we sent it, then we are complete. */
512     case TEQ1_RULE(S(ABORT, RESPONSE), R(0, 0, 0)):
513     case TEQ1_RULE(S(ABORT, RESPONSE), R(1, 0, 0)):
514       /* Card triggered abortion complete but we can resume sending. */
515       return kRuleResultAbort;
516     /* An abort request can interrupt a chain anywhere and could occur
517      * after a failure path too.
518      */
519     case TEQ1_RULE(I(0, 1), S(ABORT, REQUEST)):
520     case TEQ1_RULE(I(1, 1), S(ABORT, REQUEST)):
521     case TEQ1_RULE(R(0, 0, 0), S(ABORT, REQUEST)):
522     case TEQ1_RULE(R(0, 0, 1), S(ABORT, REQUEST)):
523     case TEQ1_RULE(R(0, 1, 0), S(ABORT, REQUEST)):
524     case TEQ1_RULE(R(0, 1, 1), S(ABORT, REQUEST)):
525     case TEQ1_RULE(R(1, 0, 0), S(ABORT, REQUEST)):
526     case TEQ1_RULE(R(1, 0, 1), S(ABORT, REQUEST)):
527     case TEQ1_RULE(R(1, 1, 0), S(ABORT, REQUEST)):
528     case TEQ1_RULE(R(1, 1, 1), S(ABORT, REQUEST)):
529       next_tx->header.PCB = S(ABORT, REQUEST);
530       return kRuleResultContinue; /* Takes over prior flow. */
531     case TEQ1_RULE(S(ABORT, RESPONSE), 255):
532       return kRuleResultRetransmit;
533     /* Note, other blocks should be caught below. */
534     default:
535       break;
536     }
537 
538     /* Note, only S(ABORT, REQUEST) and S(IFS, REQUEST) are supported
539      * for transmitting to the card. Others will result in error
540      * flows.
541      *
542      * For supported flows: If an operation was paused to
543      * send it, the caller may then switch to that state and resume.
544      */
545     if (rx_frame->header.PCB != 255) {
546       ALOGW("Unexpected frame. Marking error and re-evaluating.");
547       rx_frame->header.PCB = 255;
548       continue;
549     }
550 
551     return kRuleResultHardFail;
552   }
553 }
554 
555 /*
556  * TODO(wad): Consider splitting teq1_transcieve() into
557  *   teq1_transcieve_init() and teq1_transceive_process_one()
558  *   if testing becomes onerous given the loop below.
559  */
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)560 ESE_API uint32_t teq1_transceive(struct EseInterface *ese,
561                                  const struct Teq1ProtocolOptions *opts,
562                                  const struct EseSgBuffer *tx_bufs,
563                                  uint8_t tx_segs, struct EseSgBuffer *rx_bufs,
564                                  uint8_t rx_segs) {
565   struct Teq1Frame tx_frame[2];
566   struct Teq1Frame rx_frame;
567   struct Teq1Frame *tx = &tx_frame[0];
568   int active = 0;
569   bool was_reset = false;
570   bool needs_hw_reset = false;
571   int session_resets = 0;
572   bool done = false;
573   enum RuleResult result = kRuleResultComplete;
574   uint32_t rx_total = ese_sg_length(rx_bufs, rx_segs);
575   struct Teq1CardState *card_state = (struct Teq1CardState *)(&ese->pad[0]);
576   struct Teq1State init_state = TEQ1_INIT_STATE(
577       tx_bufs, tx_segs, ese_sg_length(tx_bufs, tx_segs), rx_bufs, rx_segs,
578       ese_sg_length(rx_bufs, rx_segs), card_state);
579   struct Teq1State state = TEQ1_INIT_STATE(
580       tx_bufs, tx_segs, ese_sg_length(tx_bufs, tx_segs), rx_bufs, rx_segs,
581       ese_sg_length(rx_bufs, rx_segs), card_state);
582 
583   _static_assert(TEQ1HEADER_SIZE == sizeof(struct Teq1Header),
584                  "Ensure compiler alignment/padding matches wire protocol.");
585   _static_assert(TEQ1FRAME_SIZE == sizeof(struct Teq1Frame),
586                  "Ensure compiler alignment/padding matches wire protocol.");
587 
588   /* First I-block is always I(0, M). After that, modulo 2. */
589   tx->header.PCB = TEQ1_I(!card_state->seq.interface, 0);
590   teq1_fill_info_block(&state, tx);
591 
592   teq1_trace_header();
593   while (!done) {
594     /* Populates the node address and LRC prior to attempting to transmit. */
595     teq1_transmit(ese, opts, tx);
596 
597     /* If tx was pointed to the inactive frame for a single shot, restore it
598      * now. */
599     tx = &tx_frame[active];
600 
601     /* Clear the RX frame. */
602     ese_memset(&rx_frame, 0xff, sizeof(rx_frame));
603 
604     /* -1 indicates a timeout or failure from hardware. */
605     if (teq1_receive(ese, opts, opts->bwt * (float)state.wait_mult, &rx_frame) <
606         0) {
607       /* TODO(wad): If the ese_error(ese) == 1, should this go ahead and fail?
608        */
609       /* Failures are considered invalid blocks in the rule engine below. */
610       rx_frame.header.PCB = 255;
611     }
612     /* Always reset |wait_mult| once we have calculated the timeout. */
613     state.wait_mult = 1;
614 
615     /* Clear the inactive frame header for use as |next_tx|. */
616     ese_memset(&tx_frame[!active].header, 0, sizeof(tx_frame[!active].header));
617 
618     result = teq1_rules(&state, tx, &rx_frame, &tx_frame[!active]);
619     ALOGV("[ %s ]", teq1_rule_result_to_name(result));
620     switch (result) {
621     case kRuleResultComplete:
622       done = true;
623       break;
624     case kRuleResultRetransmit:
625       /* TODO(wad) Find a clean way to move into teq1_rules(). */
626       if (state.retransmits++ < 3) {
627         continue;
628       }
629       ALOGE("More than three retransmits have occurred");
630       if (tx->header.PCB == S(RESYNC, REQUEST)) {
631         /* More than three RESYNC retranmits have occurred. */
632         ese_set_error(ese, kTeq1ErrorHardFail);
633         return 0;
634       }
635       /* Fall through */
636       ALOGE("Triggering resynchronization.");
637       tx_frame[!active].header.PCB = S(RESYNC, REQUEST);
638     case kRuleResultContinue:
639       active = !active;
640       tx = &tx_frame[active];
641       /* Reset this to 0 to use the counter for RESYNC transmits. */
642       state.retransmits = 0;
643       /* Errors are not reset until the session is reset. */
644       continue;
645     case kRuleResultHardFail:
646       ese_set_error(ese, kTeq1ErrorHardFail);
647       return 0;
648     case kRuleResultAbort:
649       ese_set_error(ese, kTeq1ErrorAbort);
650       return 0;
651     case kRuleResultSingleShot:
652       /*
653        * Send the next_tx on loop, but tell the rule engine that
654        * the last sent state hasn't changed. This allows for easy error
655        * and supervisory block paths without nesting state.
656        */
657       tx = &tx_frame[!active];
658       continue;
659     case kRuleResultResetDevice:
660       needs_hw_reset = true;
661     /* Fall through to session reset. */
662     case kRuleResultResetSession:
663       /* Reset to initial state and possibly do hw reset */
664       if (session_resets++ > 4) {
665         /* If there have been more than 4 resyncs without a
666          * physical reset, we should pull the plug.
667          */
668         needs_hw_reset = true;
669       }
670       if (needs_hw_reset) {
671         needs_hw_reset = false;
672         if (was_reset || !ese->ops->hw_reset || ese->ops->hw_reset(ese) == -1) {
673           ese_set_error(ese, kTeq1ErrorDeviceReset);
674           return 0; /* Don't keep resetting -- hard fail. */
675         }
676         was_reset = true;
677         session_resets = 0;
678       }
679       state = init_state;
680       TEQ1_INIT_CARD_STATE(state.card_state);
681       /* Reset the active frame. */
682       ese_memset(tx, 0, sizeof(*tx));
683       /* Load initial I-block. */
684       tx->header.PCB = I(0, 0);
685       teq1_fill_info_block(&state, tx);
686       continue;
687     }
688   }
689   /* Return the number of bytes used in the RX buffers. */
690   return rx_total - state.app_data.rx_total;
691 }
692 
teq1_compute_LRC(const struct Teq1Frame * frame)693 ESE_API uint8_t teq1_compute_LRC(const struct Teq1Frame *frame) {
694   uint8_t lrc = 0;
695   const uint8_t *buffer = frame->val;
696   const uint8_t *end = buffer + frame->header.LEN + sizeof(frame->header);
697   while (buffer < end) {
698     lrc ^= *buffer++;
699   }
700   return lrc;
701 }
702