C++程序  |  127行  |  3.47 KB

/*
 * Copyright (C) 2017 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.
 */

#include "include/ese/ese.h"
#include "include/ese/log.h"

static const char kUnknownHw[] = "unknown hw";
static const char kNullEse[] = "NULL EseInterface";
static const char *kEseErrorMessages[] = {
    "Hardware supplied no transceive implementation.",
    "Timed out polling for value.",
};
#define ESE_MESSAGES(x) (sizeof(x) / sizeof((x)[0]))

ESE_API const char *ese_name(const struct EseInterface *ese) {
  if (!ese) {
    return kNullEse;
  }
  if (ese->ops->name) {
    return ese->ops->name;
  }
  return kUnknownHw;
}

ESE_API int ese_open(struct EseInterface *ese, void *hw_opts) {
  if (!ese) {
    return -1;
  }
  ALOGV("opening interface '%s'", ese_name(ese));
  ese->error.is_err = false;
  ese->error.code = 0;
  if (ese->ops->open) {
    return ese->ops->open(ese, hw_opts);
  }
  return 0;
}

ESE_API const char *ese_error_message(const struct EseInterface *ese) {
  return ese->error.message;
}

ESE_API int ese_error_code(const struct EseInterface *ese) {
  return ese->error.code;
}

ESE_API bool ese_error(const struct EseInterface *ese) {
  return ese->error.is_err;
}

ESE_API void ese_set_error(struct EseInterface *ese, int code) {
  if (!ese) {
    return;
  }
  /* Negative values are reserved for ESE_API wide messages. */
  ese->error.code = code;
  ese->error.is_err = true;
  if (code < 0) {
    code = -(code + 1); /* Start at 0. */
    if ((uint32_t)(code) >= ESE_MESSAGES(kEseErrorMessages)) {
      LOG_ALWAYS_FATAL("Unknown global error code passed to ese_set_error(%d)",
                       code);
    }
    ese->error.message = kEseErrorMessages[code];
    return;
  }
  if ((uint32_t)(code) >= ese->ops->errors_count) {
    LOG_ALWAYS_FATAL("Unknown hw error code passed to ese_set_error(%d)", code);
  }
  ese->error.message = ese->ops->errors[code];
}

/* Blocking. */
ESE_API int ese_transceive(struct EseInterface *ese, const uint8_t *tx_buf,
                           uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_max) {
  const struct EseSgBuffer tx = {
      .c_base = tx_buf, .len = tx_len,
  };
  struct EseSgBuffer rx = {
      .base = rx_buf, .len = rx_max,
  };
  return ese_transceive_sg(ese, &tx, 1, &rx, 1);
}

ESE_API int ese_transceive_sg(struct EseInterface *ese,
                              const struct EseSgBuffer *tx_bufs,
                              uint32_t tx_segs, struct EseSgBuffer *rx_bufs,
                              uint32_t rx_segs) {
  uint32_t recvd = 0;
  if (!ese) {
    return -1;
  }
  if (ese->error.is_err) {
    return -1;
  }
  if (ese->ops->transceive) {
    recvd = ese->ops->transceive(ese, tx_bufs, tx_segs, rx_bufs, rx_segs);
    return ese_error(ese) ? -1 : recvd;
  }

  ese_set_error(ese, kEseGlobalErrorNoTransceive);
  return -1;
}

ESE_API void ese_close(struct EseInterface *ese) {
  if (!ese) {
    return;
  }
  ALOGV("closing interface '%s'", ese_name(ese));
  if (!ese->ops->close) {
    return;
  }
  ese->ops->close(ese);
}