Преглед на файлове

Add GPIO control through RPC (#1282)

* Add GPIO control through RPC
* Assets: sync protobuf to 0.10
* Assets: update protobuf to fixed v10

Co-authored-by: あく <alleteam@gmail.com>
Samuel Yvon преди 3 години
родител
ревизия
793501d62d
променени са 6 файла, в които са добавени 444 реда и са изтрити 2 реда
  1. 4 1
      applications/rpc/rpc.c
  2. 221 0
      applications/rpc/rpc_gpio.c
  3. 2 0
      applications/rpc/rpc_i.h
  4. 33 0
      assets/compiled/gpio.pb.c
  5. 183 0
      assets/compiled/gpio.pb.h
  6. 1 1
      assets/protobuf

+ 4 - 1
applications/rpc/rpc.c

@@ -51,7 +51,10 @@ static RpcSystemCallbacks rpc_systems[] = {
         .alloc = rpc_system_gui_alloc,
         .free = rpc_system_gui_free,
     },
-};
+    {
+        .alloc = rpc_system_gpio_alloc,
+        .free = NULL,
+    }};
 
 struct RpcSession {
     Rpc* rpc;

+ 221 - 0
applications/rpc/rpc_gpio.c

@@ -0,0 +1,221 @@
+#include "flipper.pb.h"
+#include "rpc_i.h"
+#include "gpio.pb.h"
+#include <furi_hal_gpio.h>
+#include <furi_hal_resources.h>
+
+static const GpioPin* rpc_pin_to_hal_pin(PB_Gpio_GpioPin rpc_pin) {
+    switch(rpc_pin) {
+    case PB_Gpio_GpioPin_PC0:
+        return &gpio_ext_pc0;
+    case PB_Gpio_GpioPin_PC1:
+        return &gpio_ext_pc1;
+    case PB_Gpio_GpioPin_PC3:
+        return &gpio_ext_pc3;
+    case PB_Gpio_GpioPin_PB2:
+        return &gpio_ext_pb2;
+    case PB_Gpio_GpioPin_PB3:
+        return &gpio_ext_pb3;
+    case PB_Gpio_GpioPin_PA4:
+        return &gpio_ext_pa4;
+    case PB_Gpio_GpioPin_PA6:
+        return &gpio_ext_pa6;
+    case PB_Gpio_GpioPin_PA7:
+        return &gpio_ext_pa7;
+    }
+
+    __builtin_unreachable();
+}
+
+static GpioMode rpc_mode_to_hal_mode(PB_Gpio_GpioPinMode rpc_mode) {
+    switch(rpc_mode) {
+    case PB_Gpio_GpioPinMode_OUTPUT:
+        return GpioModeOutputPushPull;
+    case PB_Gpio_GpioPinMode_INPUT:
+        return GpioModeInput;
+    }
+
+    __builtin_unreachable();
+}
+
+static GpioPull rpc_pull_mode_to_hall_pull_mode(PB_Gpio_GpioInputPull pull_mode) {
+    switch(pull_mode) {
+    case PB_Gpio_GpioInputPull_UP:
+        return GpioPullUp;
+    case PB_Gpio_GpioInputPull_DOWN:
+        return GpioPullDown;
+    case PB_Gpio_GpioInputPull_NO:
+        return GpioPullNo;
+    }
+
+    __builtin_unreachable();
+}
+
+static void rpc_system_gpio_set_pin_mode(const PB_Main* request, void* context) {
+    furi_assert(request);
+    furi_assert(context);
+    furi_assert(request->which_content == PB_Main_gpio_set_pin_mode_tag);
+
+    RpcSession* session = context;
+    furi_assert(session);
+
+    PB_Gpio_SetPinMode cmd = request->content.gpio_set_pin_mode;
+    const GpioPin* pin = rpc_pin_to_hal_pin(cmd.pin);
+    GpioMode mode = rpc_mode_to_hal_mode(cmd.mode);
+
+    furi_hal_gpio_init_simple(pin, mode);
+    if(mode == GpioModeOutputPushPull) {
+        furi_hal_gpio_write(pin, false);
+    }
+
+    rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
+}
+
+static void rpc_system_gpio_write_pin(const PB_Main* request, void* context) {
+    furi_assert(request);
+    furi_assert(context);
+    furi_assert(request->which_content == PB_Main_gpio_write_pin_tag);
+
+    RpcSession* session = context;
+    furi_assert(session);
+
+    PB_Gpio_WritePin cmd = request->content.gpio_write_pin;
+    const GpioPin* pin = rpc_pin_to_hal_pin(cmd.pin);
+    uint8_t value = !!(cmd.value);
+
+    PB_Main* response = malloc(sizeof(PB_Main));
+    response->command_id = request->command_id;
+    response->has_next = false;
+
+    if(LL_GPIO_MODE_OUTPUT != LL_GPIO_GetPinMode(pin->port, pin->pin)) {
+        response->command_status = PB_CommandStatus_ERROR_GPIO_MODE_INCORRECT;
+    } else {
+        response->command_status = PB_CommandStatus_OK;
+        furi_hal_gpio_write(pin, value);
+    }
+
+    rpc_send_and_release(session, response);
+
+    free(response);
+}
+
+static void rpc_system_gpio_read_pin(const PB_Main* request, void* context) {
+    furi_assert(request);
+    furi_assert(context);
+    furi_assert(request->which_content == PB_Main_gpio_read_pin_tag);
+
+    RpcSession* session = context;
+    furi_assert(session);
+
+    PB_Gpio_ReadPin cmd = request->content.gpio_read_pin;
+    const GpioPin* pin = rpc_pin_to_hal_pin(cmd.pin);
+
+    PB_Main* response = malloc(sizeof(PB_Main));
+    response->command_id = request->command_id;
+    response->has_next = false;
+
+    if(LL_GPIO_MODE_INPUT != LL_GPIO_GetPinMode(pin->port, pin->pin)) {
+        response->command_status = PB_CommandStatus_ERROR_GPIO_MODE_INCORRECT;
+    } else {
+        response->command_status = PB_CommandStatus_OK;
+        response->which_content = PB_Main_gpio_read_pin_response_tag;
+        response->content.gpio_read_pin_response.value = !!furi_hal_gpio_read(pin);
+    }
+
+    rpc_send_and_release(session, response);
+
+    free(response);
+}
+
+void rpc_system_gpio_get_pin_mode(const PB_Main* request, void* context) {
+    furi_assert(request);
+    furi_assert(context);
+    furi_assert(request->which_content == PB_Main_gpio_get_pin_mode_tag);
+
+    RpcSession* session = context;
+    furi_assert(session);
+
+    PB_Gpio_GetPinMode cmd = request->content.gpio_get_pin_mode;
+    const GpioPin* pin = rpc_pin_to_hal_pin(cmd.pin);
+
+    PB_Main* response = malloc(sizeof(PB_Main));
+    response->command_id = request->command_id;
+    response->has_next = false;
+
+    uint32_t raw_pin_mode = LL_GPIO_GetPinMode(pin->port, pin->pin);
+
+    PB_Gpio_GpioPinMode pin_mode;
+    if(LL_GPIO_MODE_INPUT == raw_pin_mode) {
+        pin_mode = PB_Gpio_GpioPinMode_INPUT;
+        response->command_status = PB_CommandStatus_OK;
+    } else if(LL_GPIO_MODE_OUTPUT == raw_pin_mode) {
+        pin_mode = PB_Gpio_GpioPinMode_OUTPUT;
+        response->command_status = PB_CommandStatus_OK;
+    } else {
+        pin_mode = PB_Gpio_GpioPinMode_INPUT;
+        response->command_status = PB_CommandStatus_ERROR_GPIO_UNKNOWN_PIN_MODE;
+    }
+
+    response->which_content = PB_Main_gpio_get_pin_mode_response_tag;
+    response->content.gpio_get_pin_mode_response.mode = pin_mode;
+
+    rpc_send_and_release(session, response);
+
+    free(response);
+}
+
+void rpc_system_gpio_set_input_pull(const PB_Main* request, void* context) {
+    furi_assert(request);
+    furi_assert(context);
+    furi_assert(request->which_content == PB_Main_gpio_set_input_pull_tag);
+
+    RpcSession* session = context;
+    furi_assert(session);
+
+    PB_Gpio_SetInputPull cmd = request->content.gpio_set_input_pull;
+    const GpioPin* pin = rpc_pin_to_hal_pin(cmd.pin);
+    const GpioPull pull_mode = rpc_pull_mode_to_hall_pull_mode(cmd.pull_mode);
+
+    PB_Main* response = malloc(sizeof(PB_Main));
+    response->command_id = request->command_id;
+    response->has_next = false;
+
+    PB_CommandStatus status;
+    if(LL_GPIO_MODE_INPUT != LL_GPIO_GetPinMode(pin->port, pin->pin)) {
+        status = PB_CommandStatus_ERROR_GPIO_MODE_INCORRECT;
+    } else {
+        status = PB_CommandStatus_OK;
+        furi_hal_gpio_init(pin, GpioModeInput, pull_mode, GpioSpeedLow);
+    }
+
+    rpc_send_and_release_empty(session, request->command_id, status);
+
+    free(response);
+}
+
+void* rpc_system_gpio_alloc(RpcSession* session) {
+    furi_assert(session);
+
+    RpcHandler rpc_handler = {
+        .message_handler = NULL,
+        .decode_submessage = NULL,
+        .context = session,
+    };
+
+    rpc_handler.message_handler = rpc_system_gpio_set_pin_mode;
+    rpc_add_handler(session, PB_Main_gpio_set_pin_mode_tag, &rpc_handler);
+
+    rpc_handler.message_handler = rpc_system_gpio_write_pin;
+    rpc_add_handler(session, PB_Main_gpio_write_pin_tag, &rpc_handler);
+
+    rpc_handler.message_handler = rpc_system_gpio_read_pin;
+    rpc_add_handler(session, PB_Main_gpio_read_pin_tag, &rpc_handler);
+
+    rpc_handler.message_handler = rpc_system_gpio_get_pin_mode;
+    rpc_add_handler(session, PB_Main_gpio_get_pin_mode_tag, &rpc_handler);
+
+    rpc_handler.message_handler = rpc_system_gpio_set_input_pull;
+    rpc_add_handler(session, PB_Main_gpio_set_input_pull_tag, &rpc_handler);
+
+    return NULL;
+}

+ 2 - 0
applications/rpc/rpc_i.h

@@ -32,6 +32,8 @@ void* rpc_system_app_alloc(RpcSession* session);
 void rpc_system_app_free(void* ctx);
 void* rpc_system_gui_alloc(RpcSession* session);
 void rpc_system_gui_free(void* ctx);
+void* rpc_system_gpio_alloc(RpcSession* session);
+void rpc_system_gpio_free(void* ctx);
 
 void rpc_print_message(const PB_Main* message);
 void rpc_cli_command_start_session(Cli* cli, string_t args, void* context);

+ 33 - 0
assets/compiled/gpio.pb.c

@@ -0,0 +1,33 @@
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.4.5 */
+
+#include "gpio.pb.h"
+#if PB_PROTO_HEADER_VERSION != 40
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+PB_BIND(PB_Gpio_SetPinMode, PB_Gpio_SetPinMode, AUTO)
+
+
+PB_BIND(PB_Gpio_SetInputPull, PB_Gpio_SetInputPull, AUTO)
+
+
+PB_BIND(PB_Gpio_GetPinMode, PB_Gpio_GetPinMode, AUTO)
+
+
+PB_BIND(PB_Gpio_GetPinModeResponse, PB_Gpio_GetPinModeResponse, AUTO)
+
+
+PB_BIND(PB_Gpio_ReadPin, PB_Gpio_ReadPin, AUTO)
+
+
+PB_BIND(PB_Gpio_ReadPinResponse, PB_Gpio_ReadPinResponse, AUTO)
+
+
+PB_BIND(PB_Gpio_WritePin, PB_Gpio_WritePin, AUTO)
+
+
+
+
+
+

+ 183 - 0
assets/compiled/gpio.pb.h

@@ -0,0 +1,183 @@
+/* Automatically generated nanopb header */
+/* Generated by nanopb-0.4.5 */
+
+#ifndef PB_PB_GPIO_GPIO_PB_H_INCLUDED
+#define PB_PB_GPIO_GPIO_PB_H_INCLUDED
+#include <pb.h>
+
+#if PB_PROTO_HEADER_VERSION != 40
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+/* Enum definitions */
+typedef enum _PB_Gpio_GpioPin { 
+    PB_Gpio_GpioPin_PC0 = 0, 
+    PB_Gpio_GpioPin_PC1 = 1, 
+    PB_Gpio_GpioPin_PC3 = 2, 
+    PB_Gpio_GpioPin_PB2 = 3, 
+    PB_Gpio_GpioPin_PB3 = 4, 
+    PB_Gpio_GpioPin_PA4 = 5, 
+    PB_Gpio_GpioPin_PA6 = 6, 
+    PB_Gpio_GpioPin_PA7 = 7 
+} PB_Gpio_GpioPin;
+
+typedef enum _PB_Gpio_GpioPinMode { 
+    PB_Gpio_GpioPinMode_OUTPUT = 0, 
+    PB_Gpio_GpioPinMode_INPUT = 1 
+} PB_Gpio_GpioPinMode;
+
+typedef enum _PB_Gpio_GpioInputPull { 
+    PB_Gpio_GpioInputPull_NO = 0, 
+    PB_Gpio_GpioInputPull_UP = 1, 
+    PB_Gpio_GpioInputPull_DOWN = 2
+} PB_Gpio_GpioInputPull;
+
+/* Struct definitions */
+typedef struct _PB_Gpio_GetPinMode { 
+    PB_Gpio_GpioPin pin; 
+} PB_Gpio_GetPinMode;
+
+typedef struct _PB_Gpio_GetPinModeResponse { 
+    PB_Gpio_GpioPinMode mode; 
+} PB_Gpio_GetPinModeResponse;
+
+typedef struct _PB_Gpio_ReadPin { 
+    PB_Gpio_GpioPin pin; 
+} PB_Gpio_ReadPin;
+
+typedef struct _PB_Gpio_ReadPinResponse { 
+    uint32_t value; 
+} PB_Gpio_ReadPinResponse;
+
+typedef struct _PB_Gpio_SetInputPull { 
+    PB_Gpio_GpioPin pin; 
+    PB_Gpio_GpioInputPull pull_mode; 
+} PB_Gpio_SetInputPull;
+
+typedef struct _PB_Gpio_SetPinMode { 
+    PB_Gpio_GpioPin pin; 
+    PB_Gpio_GpioPinMode mode; 
+} PB_Gpio_SetPinMode;
+
+typedef struct _PB_Gpio_WritePin { 
+    PB_Gpio_GpioPin pin; 
+    uint32_t value; 
+} PB_Gpio_WritePin;
+
+
+/* Helper constants for enums */
+#define _PB_Gpio_GpioPin_MIN PB_Gpio_GpioPin_PC0
+#define _PB_Gpio_GpioPin_MAX PB_Gpio_GpioPin_PA7
+#define _PB_Gpio_GpioPin_ARRAYSIZE ((PB_Gpio_GpioPin)(PB_Gpio_GpioPin_PA7+1))
+
+#define _PB_Gpio_GpioPinMode_MIN PB_Gpio_GpioPinMode_OUTPUT
+#define _PB_Gpio_GpioPinMode_MAX PB_Gpio_GpioPinMode_INPUT
+#define _PB_Gpio_GpioPinMode_ARRAYSIZE ((PB_Gpio_GpioPinMode)(PB_Gpio_GpioPinMode_INPUT+1))
+
+#define _PB_Gpio_GpioInputPull_MIN PB_Gpio_GpioInputPull_NO
+#define _PB_Gpio_GpioInputPull_MAX PB_Gpio_GpioInputPull_DOWN
+#define _PB_Gpio_GpioInputPull_ARRAYSIZE ((PB_Gpio_GpioInputPull)(PB_Gpio_GpioInputPull_DOWN+1))
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initializer values for message structs */
+#define PB_Gpio_SetPinMode_init_default          {_PB_Gpio_GpioPin_MIN, _PB_Gpio_GpioPinMode_MIN}
+#define PB_Gpio_SetInputPull_init_default        {_PB_Gpio_GpioPin_MIN, _PB_Gpio_GpioInputPull_MIN}
+#define PB_Gpio_GetPinMode_init_default          {_PB_Gpio_GpioPin_MIN}
+#define PB_Gpio_GetPinModeResponse_init_default  {_PB_Gpio_GpioPinMode_MIN}
+#define PB_Gpio_ReadPin_init_default             {_PB_Gpio_GpioPin_MIN}
+#define PB_Gpio_ReadPinResponse_init_default     {0}
+#define PB_Gpio_WritePin_init_default            {_PB_Gpio_GpioPin_MIN, 0}
+#define PB_Gpio_SetPinMode_init_zero             {_PB_Gpio_GpioPin_MIN, _PB_Gpio_GpioPinMode_MIN}
+#define PB_Gpio_SetInputPull_init_zero           {_PB_Gpio_GpioPin_MIN, _PB_Gpio_GpioInputPull_MIN}
+#define PB_Gpio_GetPinMode_init_zero             {_PB_Gpio_GpioPin_MIN}
+#define PB_Gpio_GetPinModeResponse_init_zero     {_PB_Gpio_GpioPinMode_MIN}
+#define PB_Gpio_ReadPin_init_zero                {_PB_Gpio_GpioPin_MIN}
+#define PB_Gpio_ReadPinResponse_init_zero        {0}
+#define PB_Gpio_WritePin_init_zero               {_PB_Gpio_GpioPin_MIN, 0}
+
+/* Field tags (for use in manual encoding/decoding) */
+#define PB_Gpio_GetPinMode_pin_tag               1
+#define PB_Gpio_GetPinModeResponse_mode_tag      1
+#define PB_Gpio_ReadPin_pin_tag                  1
+#define PB_Gpio_ReadPinResponse_value_tag        2
+#define PB_Gpio_SetInputPull_pin_tag             1
+#define PB_Gpio_SetInputPull_pull_mode_tag       2
+#define PB_Gpio_SetPinMode_pin_tag               1
+#define PB_Gpio_SetPinMode_mode_tag              2
+#define PB_Gpio_WritePin_pin_tag                 1
+#define PB_Gpio_WritePin_value_tag               2
+
+/* Struct field encoding specification for nanopb */
+#define PB_Gpio_SetPinMode_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UENUM,    pin,               1) \
+X(a, STATIC,   SINGULAR, UENUM,    mode,              2)
+#define PB_Gpio_SetPinMode_CALLBACK NULL
+#define PB_Gpio_SetPinMode_DEFAULT NULL
+
+#define PB_Gpio_SetInputPull_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UENUM,    pin,               1) \
+X(a, STATIC,   SINGULAR, UENUM,    pull_mode,         2)
+#define PB_Gpio_SetInputPull_CALLBACK NULL
+#define PB_Gpio_SetInputPull_DEFAULT NULL
+
+#define PB_Gpio_GetPinMode_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UENUM,    pin,               1)
+#define PB_Gpio_GetPinMode_CALLBACK NULL
+#define PB_Gpio_GetPinMode_DEFAULT NULL
+
+#define PB_Gpio_GetPinModeResponse_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UENUM,    mode,              1)
+#define PB_Gpio_GetPinModeResponse_CALLBACK NULL
+#define PB_Gpio_GetPinModeResponse_DEFAULT NULL
+
+#define PB_Gpio_ReadPin_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UENUM,    pin,               1)
+#define PB_Gpio_ReadPin_CALLBACK NULL
+#define PB_Gpio_ReadPin_DEFAULT NULL
+
+#define PB_Gpio_ReadPinResponse_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UINT32,   value,             2)
+#define PB_Gpio_ReadPinResponse_CALLBACK NULL
+#define PB_Gpio_ReadPinResponse_DEFAULT NULL
+
+#define PB_Gpio_WritePin_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UENUM,    pin,               1) \
+X(a, STATIC,   SINGULAR, UINT32,   value,             2)
+#define PB_Gpio_WritePin_CALLBACK NULL
+#define PB_Gpio_WritePin_DEFAULT NULL
+
+extern const pb_msgdesc_t PB_Gpio_SetPinMode_msg;
+extern const pb_msgdesc_t PB_Gpio_SetInputPull_msg;
+extern const pb_msgdesc_t PB_Gpio_GetPinMode_msg;
+extern const pb_msgdesc_t PB_Gpio_GetPinModeResponse_msg;
+extern const pb_msgdesc_t PB_Gpio_ReadPin_msg;
+extern const pb_msgdesc_t PB_Gpio_ReadPinResponse_msg;
+extern const pb_msgdesc_t PB_Gpio_WritePin_msg;
+
+/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
+#define PB_Gpio_SetPinMode_fields &PB_Gpio_SetPinMode_msg
+#define PB_Gpio_SetInputPull_fields &PB_Gpio_SetInputPull_msg
+#define PB_Gpio_GetPinMode_fields &PB_Gpio_GetPinMode_msg
+#define PB_Gpio_GetPinModeResponse_fields &PB_Gpio_GetPinModeResponse_msg
+#define PB_Gpio_ReadPin_fields &PB_Gpio_ReadPin_msg
+#define PB_Gpio_ReadPinResponse_fields &PB_Gpio_ReadPinResponse_msg
+#define PB_Gpio_WritePin_fields &PB_Gpio_WritePin_msg
+
+/* Maximum encoded size of messages (where known) */
+#define PB_Gpio_GetPinModeResponse_size          2
+#define PB_Gpio_GetPinMode_size                  2
+#define PB_Gpio_ReadPinResponse_size             6
+#define PB_Gpio_ReadPin_size                     2
+#define PB_Gpio_SetInputPull_size                4
+#define PB_Gpio_SetPinMode_size                  4
+#define PB_Gpio_WritePin_size                    8
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif

+ 1 - 1
assets/protobuf

@@ -1 +1 @@
-Subproject commit 6c1b8ae66a85bcd7e79e993a0b5573c38c302db5
+Subproject commit d9e343661dd36cfab792b78be1dea4e5950cb4dd