C++程序  |  205行  |  5.45 KB

/*
 * 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_<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 uint8_t *const tx_buf, uint32_t tx_len,
                         uint8_t *rx_buf, uint32_t rx_max);

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_ */