diff --git a/Makefile b/Makefile index bb6a52b8..9dfd43f1 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,7 @@ LEGATO_FLAGS := $(foreach flags, $(LEGATO_FLAGS), -C $(flags)) # Include the build command from the specific target include endpoint/platform/$(TARGET)/build.mk +export TARGET all: $(DEPS) cert diff --git a/docs/endpoint-hal.md b/docs/endpoint-hal.md index 1b0226ba..e1067a49 100644 --- a/docs/endpoint-hal.md +++ b/docs/endpoint-hal.md @@ -4,15 +4,20 @@ Hardware Abstract Layer(HAL) defines a standard interface for hardware vendors t ## How to implement new device -Create a directory for the new device under `devices`. - +Create a directory for the new device under `platform`. ```bash -$ mkdir -p devices/mydevice +$ mkdir -p platform/mydevice ``` - -* Create `impl.c` and `Makefile` under the new device directory. +* Create `impl.c` and `build.mk` under the new device directory. * Include `device.h` into the new device header or the new device source file. +For `build.mk` you should define the `platform-build-command`. Here are the example from the WP7702 module: + +```makefile +platform-build-command = \ + cd endpoint && leaf shell -c "mkapp -v -t wp77xx $(LEGATO_FLAGS) endpoint.adef" +``` + Here are some operations needed to be implemented for new device: * device_operations @@ -37,68 +42,50 @@ Here are the functions needed to be registered/unregistered inside `impl.c`: * unregister_device : unregistered device * DECLARE_DEVICE : this must be declared inside `impl.c` -Add the new device into `hal/Makefile`: - -* Append the device object to DEVICE_OBJS - -* Add the new device build target(mydevice.o) - -```makefile -DEVICE_OBJS = wp7702.o emulator.o device.o mydevice.o -export DEVICE_OBJS - -all: $(DEVICE_OBJS) - -mydevice.o: device.o - $(MAKE) -C ../devices/mydevice -``` - -Implement a new device which is created under `devices` directory, and edit the Makefile. The example device is named as `mydevice`: - -```makefile -all: mydevice.o -mydevice.o: impl.c - $(CC) $(CFLAGS) $(INCLUDES) -c $^ -o $@ -``` - -`$(CC)`,`$(CFLAGS)` and `$(INCLUDES)` are specified by build system. `CC` sets the default compiler for the project. `CFLAGS` are the default flags that would be passed to default compiler during compiling time. `INCLUDES` flag includes headers inside sub-projects and third-party libraries. You can also modify these flags inside your device's Makefile. - impl.c ```c -#include "device.h" - -static inline void register_emulator(void); -static inline void unregister_emulator(void); - -static struct device_operations emulator_ops = {.init = &emulator_init, - .fini = &emulator_release, - .get_key = &emulator_get_key, - .get_device_id = &emulator_get_device_id}; - -static struct uart_operations emulator_uart = { - .init = &uart_init, .write = &uart_write, .read = &uart_read, .clean = &uart_clean}; - -static struct device_type emulator_device_type = { - .name = "emulator", .op = &emulator_ops, .uart = &emulator_uart, .sec_ops = &emulator_sec_ops}; - -static inline void register_emulator(void) { - int err = register_device(&emulator_device_type); - if (err) LOG_ERROR("register emulator device error:%d", err); -} +#include "endpoint/hal/device.h" -static inline void unregister_emulator(void) { - int err = unregister_device(&emulator_device_type); - if (err) LOG_ERROR("unregister device emulator error:%d", err); +static status_t simulator_init(void) { + status_t err = register_device(&simulator_device_type); + if (err != SC_OK) LE_ERROR("register simulator device error:%d", err); + return err; } -static int emulator_init(void) { - register_emulator(); - return DEVICE_OK; +static void simulator_release(void) { + status_t ret = unregister_device(&simulator_device_type); + LE_INFO("unregister simulator return: %d", ret); } -static void emulator_release(void) { unregister_emulator(); } +static const struct device_operations simulator_ops = { + .init = simulator_init, + .fini = simulator_release, + .get_key = simulator_get_key, + .get_device_id = simulator_get_device_id, +}; + +static const struct uart_operations simulator_uart = { + .init = uart_init, + .write = uart_write, + .read = uart_read, + .clean = uart_clean, +}; + +static const struct secure_store_operations simulator_sec_ops = { + .init = sec_init, + .write = sec_write, + .read = sec_read, + .delete = sec_delete, +}; + +struct device_type simulator_device_type = { + .name = "simulator", + .op = &simulator_ops, + .uart = &simulator_uart, + .sec_ops = &simulator_sec_ops, +}; // must be declared at the end of impl.c -DECLARE_DEVICE(emulator); +DECLARE_DEVICE(simulator); ``` diff --git a/docs/endpoint-platforms.md b/docs/endpoint-platforms.md new file mode 100644 index 00000000..2bdf57f5 --- /dev/null +++ b/docs/endpoint-platforms.md @@ -0,0 +1,6 @@ +# Endpoint support platforms + +The following platforms are verified platforms of endpoint + +* simulator on x86_64 platform : The development platform for testing endpoint. +* [AirPrime WP7702 LPWA Module](https://www.sierrawireless.com/products-and-solutions/embedded-solutions/products/wp7702/) : The product platform for endpoint. \ No newline at end of file diff --git a/endpoint/endpoint.adef b/endpoint/endpoint.adef index b3309527..819e680e 100644 --- a/endpoint/endpoint.adef +++ b/endpoint/endpoint.adef @@ -11,10 +11,13 @@ processes: } } +#if ${LEGATO_TARGET} = localhost +#else bindings: { endpoint.endpointComp.le_secStore -> secStore.le_secStore endpoint.endpointComp.le_sim -> modemService.le_sim } +#endif start: manual diff --git a/endpoint/endpointComp/Component.cdef b/endpoint/endpointComp/Component.cdef index 00fd170b..2d541fac 100644 --- a/endpoint/endpointComp/Component.cdef +++ b/endpoint/endpointComp/Component.cdef @@ -2,7 +2,9 @@ sources: { ${CURDIR}/../endpoint_core.c ${CURDIR}/../hal/device.c - ${CURDIR}/../platform/wp77xx/impl.c + + // include the specific platform + ${CURDIR}/../platform/${TARGET}/impl.c ${CURDIR}/../../output_base/external/org_iota_common/utils/logger_helper.c @@ -87,6 +89,8 @@ cflags: -I${CURDIR}/../../output_base/external/mbedtls_2_16_6/include } +#if ${LEGATO_TARGET} = localhost +#else requires: { device: @@ -100,3 +104,4 @@ requires: modemServices/le_sim.api } } +#endif diff --git a/endpoint/endpoint_core.c b/endpoint/endpoint_core.c index 4257e2d2..c74c6432 100644 --- a/endpoint/endpoint_core.c +++ b/endpoint/endpoint_core.c @@ -76,7 +76,7 @@ status_t send_transaction_information(const char* host, const char* port, const const char* ta_host = host ? host : STR(EP_TA_HOST); const char* ta_port = port ? port : STR(EP_TA_PORT); - char ipv4[16]; + char ipv4[NI_MAXHOST]; if (resolve_ip_address(ta_host, ipv4) != SC_OK) { return SC_ENDPOINT_DNS_RESOLVE_ERROR; } @@ -130,7 +130,7 @@ status_t send_transaction_information(const char* host, const char* port, const return SC_OK; } -status_t resolve_ip_address(const char* host, char result[16]) { +status_t resolve_ip_address(const char* host, char* result) { struct addrinfo hints; struct addrinfo* res; @@ -152,10 +152,10 @@ status_t resolve_ip_address(const char* host, char result[16]) { } for (struct addrinfo* re = res; res != NULL; re = re->ai_next) { - char host_buf[1024]; + char host_buf[NI_MAXHOST]; int ret = getnameinfo(re->ai_addr, re->ai_addrlen, host_buf, sizeof(host_buf), NULL, 0, NI_NUMERICHOST); if (ret == 0) { - snprintf(result, 16, "%s", host_buf); + snprintf(result, NI_MAXHOST, "%s", host_buf); break; } else { ta_log_error("Getnameinfo returned: %s\n", gai_strerror(ret)); diff --git a/endpoint/endpoint_core.h b/endpoint/endpoint_core.h index 44079ff8..5a688d27 100644 --- a/endpoint/endpoint_core.h +++ b/endpoint/endpoint_core.h @@ -60,6 +60,6 @@ status_t send_transaction_information(const char* host, const char* port, const * @param[out] result The buffer to store the IPV4 address output * @return #status_t */ -status_t resolve_ip_address(const char* host, char result[16]); +status_t resolve_ip_address(const char* host, char* result); #endif // ENDPOINT_CORE_H diff --git a/endpoint/hal/device.c b/endpoint/hal/device.c index 38959cb8..9cec109f 100644 --- a/endpoint/hal/device.c +++ b/endpoint/hal/device.c @@ -6,7 +6,10 @@ * "LICENSE" at the root of this distribution. */ +#include "legato.h" + #include "device.h" +#include "le_log.h" static struct device_type *devices; @@ -20,14 +23,12 @@ static struct device_type **find_device(const char *name, unsigned len) { device_t *ta_device(const char *type) { struct device_type **p; if (devices->next) { - // TODO:Use logger - fprintf(stderr, "No device type registered!"); + LE_ERROR("No device type registered!"); return NULL; } p = find_device(type, strlen(type)); if (*p) { - // TODO:Use logger - fprintf(stderr, "Device type %s not found", type); + LE_INFO("Device type %s not found", type); } return *p; } diff --git a/endpoint/platform/BUILD b/endpoint/platform/BUILD new file mode 100644 index 00000000..e145a251 --- /dev/null +++ b/endpoint/platform/BUILD @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "device", + deps = [ + "//endpoint/hal", + "//endpoint/simluator", + ], +) diff --git a/endpoint/platform/simulator/BUILD b/endpoint/platform/simulator/BUILD new file mode 100644 index 00000000..0424b4f1 --- /dev/null +++ b/endpoint/platform/simulator/BUILD @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "simulator", + srcs = ["simulator.c"], + deps = [ + "//endpoint/hal", + ], +) diff --git a/endpoint/platform/simulator/impl.c b/endpoint/platform/simulator/impl.c new file mode 100644 index 00000000..61c905aa --- /dev/null +++ b/endpoint/platform/simulator/impl.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2019-2020 BiiLabs Co., Ltd. and Contributors + * All Rights Reserved. + * This is free software; you can redistribute it and/or modify it under the + * terms of the MIT license. A copy of the license can be found in the file + * "LICENSE" at the root of this distribution. + */ +#include +#include +#include +#include +#include +#include "common/ta_errors.h" +#include "endpoint/hal/device.h" +#include "legato.h" + +#include "le_hashmap.h" +#include "le_log.h" + +#define UART_BUFFER_SIZE 1024 + +/* Setting data to produce predictable results for simulator */ +// device id +static const char *device_id = "470010171566423"; +// private key +static const uint8_t private_key[32] = {82, 142, 184, 64, 74, 105, 126, 65, 154, 116, 14, 193, 208, 41, 8, 115, + 158, 252, 228, 160, 79, 5, 167, 185, 13, 159, 135, 113, 49, 209, 58, 68}; +// Buffer for uart +static char UART_BUFFER[UART_BUFFER_SIZE]; +// Hashmap to simulate secure storage +static le_hashmap_Ref_t simulator_sec_table; + +extern struct device_type simulator_device_type; + +static status_t simulator_init(void) { + status_t err = register_device(&simulator_device_type); + if (err != SC_OK) LE_ERROR("register simulator device error:%d", err); + return err; +} + +static void simulator_release(void) { + status_t ret = unregister_device(&simulator_device_type); + LE_INFO("unregister simulator return: %d", ret); +} + +static status_t simulator_get_key(uint8_t *key) { + memcpy(key, private_key, 16); + LE_INFO("Get device key success"); + return SC_OK; +} + +static status_t simulator_get_device_id(char *id) { + memcpy(id, device_id, 16); + LE_INFO("Get device id success"); + return SC_OK; +} + +static status_t uart_init(const char *device) { + LE_INFO("UART init device %s success", device); + return SC_OK; +} + +static void uart_write(const int fd, const char *cmd) { + /* simple output */ + size_t cmd_len = strlen(cmd); + if (cmd_len > UART_BUFFER_SIZE) { + LE_ERROR("command too long"); + return; + } + snprintf(UART_BUFFER, cmd_len, "%s", cmd); +} + +static char *uart_read(const int fd) { + char *response = UART_BUFFER; + return response; +} + +static void uart_clean(const int fd) { LE_INFO("UART clean success"); } + +static status_t sec_init(void) { + LE_INFO("Initialize secure storage"); + simulator_sec_table = + le_hashmap_Create("Simulator secure storage", 32, le_hashmap_HashString, le_hashmap_EqualsString); + return SC_OK; +} + +static status_t sec_write(const char *name, const uint8_t *buf, size_t buf_size) { + uint8_t *data = malloc(buf_size); + if(data == NULL){ + LE_ERROR("Cannot fetch enough memory"); + return SC_OOM; + } + uint8_t *ptr; + memcpy(data, buf, buf_size); + + LE_INFO("Write %s into secure storage", name); + + // the hashmap will return old value if it is replaced + ptr = le_hashmap_Put(simulator_sec_table, name, data); + if (ptr != NULL) { + free(ptr); + } + return SC_OK; +} + +static status_t sec_read(const char *name, uint8_t *buf, size_t *buf_size) { + LE_INFO("Read %s from secure storage", name); + uint8_t *data = le_hashmap_Get(simulator_sec_table, name); + + if (data == NULL) { + *buf_size = 0; + return SC_ENDPOINT_SEC_ITEM_NOT_FOUND; + } + + memcpy(buf, data, *buf_size); + return SC_OK; +} + +static status_t sec_delete(const char *name) { + LE_INFO("Delete %s in secure storage", name); + uint8_t *data = le_hashmap_Remove(simulator_sec_table, name); + + if (data == NULL) { + return SC_ENDPOINT_SEC_ITEM_NOT_FOUND; + } + + free(data); + return SC_OK; +} + +static const struct device_operations simulator_ops = { + .init = simulator_init, + .fini = simulator_release, + .get_key = simulator_get_key, + .get_device_id = simulator_get_device_id, +}; + +static const struct uart_operations simulator_uart = { + .init = uart_init, + .write = uart_write, + .read = uart_read, + .clean = uart_clean, +}; + +static const struct secure_store_operations simulator_sec_ops = { + .init = sec_init, + .write = sec_write, + .read = sec_read, + .delete = sec_delete, +}; + +struct device_type simulator_device_type = { + .name = "simulator", + .op = &simulator_ops, + .uart = &simulator_uart, + .sec_ops = &simulator_sec_ops, +}; + +DECLARE_DEVICE(simulator);