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/ese.h"
18 #include "include/ese/log.h"
19 
20 #include "ese_private.h"
21 
22 static const char kUnknownHw[] = "unknown hw";
23 static const char kNullEse[] = "NULL EseInterface";
24 static const char *kEseErrorMessages[] = {
25     "Hardware supplied no transceive implementation.",
26     "Timed out polling for value.",
27 };
28 #define ESE_MESSAGES(x) (sizeof(x) / sizeof((x)[0]))
29 
ese_name(const struct EseInterface * ese)30 API const char *ese_name(const struct EseInterface *ese) {
31   if (!ese) {
32     return kNullEse;
33   }
34   if (ese->ops->name) {
35     return ese->ops->name;
36   }
37   return kUnknownHw;
38 }
39 
ese_open(struct EseInterface * ese,void * hw_opts)40 API int ese_open(struct EseInterface *ese, void *hw_opts) {
41   if (!ese) {
42     return -1;
43   }
44   ALOGV("opening interface '%s'", ese_name(ese));
45   if (ese->ops->open) {
46     return ese->ops->open(ese, hw_opts);
47   }
48   return 0;
49 }
50 
ese_error_message(const struct EseInterface * ese)51 API const char *ese_error_message(const struct EseInterface *ese) {
52   return ese->error.message;
53 }
54 
ese_error_code(const struct EseInterface * ese)55 API int ese_error_code(const struct EseInterface *ese) {
56   return ese->error.code;
57 }
58 
ese_error(const struct EseInterface * ese)59 API bool ese_error(const struct EseInterface *ese) { return ese->error.is_err; }
60 
ese_set_error(struct EseInterface * ese,int code)61 API void ese_set_error(struct EseInterface *ese, int code) {
62   if (!ese) {
63     return;
64   }
65   /* Negative values are reserved for API wide messages. */
66   ese->error.code = code;
67   ese->error.is_err = true;
68   if (code < 0) {
69     code = -(code + 1); /* Start at 0. */
70     if ((uint32_t)(code) >= ESE_MESSAGES(kEseErrorMessages)) {
71       LOG_ALWAYS_FATAL("Unknown global error code passed to ese_set_error(%d)",
72                        code);
73     }
74     ese->error.message = kEseErrorMessages[code];
75     return;
76   }
77   if ((uint32_t)(code) >= ese->ops->errors_count) {
78     LOG_ALWAYS_FATAL("Unknown hw error code passed to ese_set_error(%d)", code);
79   }
80   ese->error.message = ese->ops->errors[code];
81 }
82 
83 /* Blocking. */
ese_transceive(struct EseInterface * ese,const uint8_t * tx_buf,uint32_t tx_len,uint8_t * rx_buf,uint32_t rx_max)84 API int ese_transceive(struct EseInterface *ese, const uint8_t *tx_buf,
85                        uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_max) {
86   uint32_t recvd = 0;
87   if (!ese) {
88     return -1;
89   }
90 
91   if (ese->ops->transceive) {
92     recvd = ese->ops->transceive(ese, tx_buf, tx_len, rx_buf, rx_max);
93     return ese_error(ese) ? -1 : recvd;
94   }
95 
96   if (ese->ops->hw_transmit && ese->ops->hw_receive) {
97     ese->ops->hw_transmit(ese, tx_buf, tx_len, 1);
98     if (!ese_error(ese)) {
99       recvd = ese->ops->hw_receive(ese, rx_buf, rx_max, 1);
100     }
101     return ese_error(ese) ? -1 : recvd;
102   }
103 
104   ese_set_error(ese, kEseGlobalErrorNoTransceive);
105   return -1;
106 }
107 
ese_close(struct EseInterface * ese)108 API void ese_close(struct EseInterface *ese) {
109   if (!ese) {
110     return;
111   }
112   ALOGV("closing interface '%s'", ese_name(ese));
113   if (!ese->ops->close) {
114     return;
115   }
116   ese->ops->close(ese);
117 }
118