// SPDX-License-Identifier: LGPL-2.0-only // SPDX-FileCopyrightText: 2023 Oleksij Rempel #ifndef ISOBUSFS_CLI_H #define ISOBUSFS_CLI_H #include #include #include "isobusfs_cmn.h" #include "isobusfs_cmn_cm.h" #define ISOBUSFS_CLI_MAX_EPOLL_EVENTS 10 #define ISOBUSFS_CLI_DEFAULT_WAIT_TIMEOUT_MS 1000 /* ms */ enum isobusfs_cli_state { ISOBUSFS_CLI_STATE_CONNECTING, ISOBUSFS_CLI_STATE_IDLE, ISOBUSFS_CLI_STATE_NACKED, /* here is NACKed and not what you think */ ISOBUSFS_CLI_STATE_SELFTEST, ISOBUSFS_CLI_STATE_WAIT_FS_PROPERTIES, ISOBUSFS_CLI_STATE_WAIT_CURRENT_DIR, ISOBUSFS_CLI_STATE_WAIT_CCD_RESP, ISOBUSFS_CLI_STATE_WAIT_OF_RESP, ISOBUSFS_CLI_STATE_WAIT_FILE_SIZE, ISOBUSFS_CLI_STATE_WAIT_FILE, ISOBUSFS_CLI_STATE_WAIT_VOLUME_STATUS, ISOBUSFS_CLI_STATE_WAIT_CF_RESP, ISOBUSFS_CLI_STATE_WAIT_SF_RESP, /* wait for seek file response */ ISOBUSFS_CLI_STATE_WAIT_RF_RESP, /* wait for read file response */ ISOBUSFS_CLI_STATE_MAX_WAITING, ISOBUSFS_CLI_STATE_CONNECTING_DONE, ISOBUSFS_CLI_STATE_GET_FS_PROPERTIES_DONE, ISOBUSFS_CLI_STATE_GET_CURRENT_DIR_DONE, ISOBUSFS_CLI_STATE_GET_CURRENT_DIR_FAIL, ISOBUSFS_CLI_STATE_GET_FILE_SIZE_DONE, ISOBUSFS_CLI_STATE_GET_FILE_DONE, ISOBUSFS_CLI_STATE_VOLUME_STATUS_DONE, ISOBUSFS_CLI_STATE_CCD_DONE, ISOBUSFS_CLI_STATE_CCD_FAIL, ISOBUSFS_CLI_STATE_OF_DONE, ISOBUSFS_CLI_STATE_OF_FAIL, ISOBUSFS_CLI_STATE_CF_DONE, ISOBUSFS_CLI_STATE_CF_FAIL, ISOBUSFS_CLI_STATE_SF_DONE, ISOBUSFS_CLI_STATE_SF_FAIL, ISOBUSFS_CLI_STATE_RF_CONT, ISOBUSFS_CLI_STATE_RF_DONE, ISOBUSFS_CLI_STATE_RF_FAIL, ISOBUSFS_CLI_STATE_MAX_DONE, ISOBUSFS_CLI_STATE_GET_FS_PROPERTIES, ISOBUSFS_CLI_STATE_GET_CURRENT_DIR, ISOBUSFS_CLI_STATE_GET_FILE_SIZE, ISOBUSFS_CLI_STATE_GET_FILE, ISOBUSFS_CLI_STATE_VOLUME_STATUS, ISOBUSFS_CLI_STATE_TEST_CLEANUP, ISOBUSFS_CLI_STATE_TEST_DONE, ISOBUSFS_CLI_STATE_MAX_ACTIVE, }; struct isobusfs_priv; typedef int (*isobusfs_event_callback)(struct isobusfs_priv *priv, struct isobusfs_msg *msg, void *ctx, int error); struct isobusfs_event { isobusfs_event_callback cb; struct timespec timeout; /* fs_function is needed to identify package type for event * subscription */ uint8_t fs_function; int fd; bool one_shot; void *ctx; }; struct isobusfs_priv { int sock_ccm; int sock_nack; int sock_main; int sock_bcast_rx; struct isobusfs_cm_ccm ccm; /* file server status message */ bool run_selftest; struct sockaddr_can sockname; struct sockaddr_can peername; struct isobusfs_stats stats; uint8_t next_tan; uint8_t cl_buf[1]; bool fs_is_active; struct timespec fs_last_seen; uint8_t fs_version; uint8_t fs_max_open_files; uint8_t fs_caps; struct isobusfs_buf_log tx_buf_log; enum isobusfs_cli_state state; struct libj1939_cmn cmn; uint8_t handle; uint32_t read_offset; uint8_t *read_data; size_t read_data_len; bool interactive; bool int_busy; struct isobusfs_event *events; uint num_events; uint max_events; enum isobusfs_error error_code; }; /* isobusfs_cli_cm.c */ void isobusfs_cli_ccm_init(struct isobusfs_priv *priv); int isobusfs_cli_ccm_send(struct isobusfs_priv *priv); void isobusfs_cli_fs_detect_timeout(struct isobusfs_priv *priv); int isobusfs_cli_rx_cg_cm(struct isobusfs_priv *priv, struct isobusfs_msg *msg); int isobusfs_cli_property_req(struct isobusfs_priv *priv); int isobusfs_cli_volume_status_req(struct isobusfs_priv *priv, uint8_t volume_mode, uint16_t path_name_length, const char *volume_name); /* isobusfs_cli_dh.c */ int isobusfs_cli_ccd_req(struct isobusfs_priv *priv, const char *name, size_t name_len); int isobusfs_cli_get_current_dir_req(struct isobusfs_priv *priv); int isobusfs_cli_rx_cg_dh(struct isobusfs_priv *priv, struct isobusfs_msg *msg); int isobusfs_cli_send_and_register_ccd_event(struct isobusfs_priv *priv, const char *name, size_t name_len, isobusfs_event_callback cb, void *ctx); int isobusfs_cli_send_and_register_gcd_event(struct isobusfs_priv *priv, isobusfs_event_callback cb, void *ctx); /* isobusfs_cli_fa.c */ int isobusfs_cli_rx_cg_fa(struct isobusfs_priv *priv, struct isobusfs_msg *msg); int isobusfs_cli_fa_of_req(struct isobusfs_priv *priv, const char *name, size_t name_len, uint8_t flags); int isobusfs_cli_fa_cf_req(struct isobusfs_priv *priv, uint8_t handle); int isobusfs_cli_fa_rf_req(struct isobusfs_priv *priv, uint8_t handle, uint16_t count); int isobusfs_cli_fa_sf_req(struct isobusfs_priv *priv, uint8_t handle, uint8_t position_mode, int32_t offset); int isobusfs_cli_send_and_register_fa_of_event(struct isobusfs_priv *priv, const char *name, size_t name_len, uint8_t flags, isobusfs_event_callback cb, void *ctx); int isobusfs_cli_send_and_register_fa_sf_event(struct isobusfs_priv *priv, uint8_t handle, uint8_t position_mode, int32_t offset, isobusfs_event_callback cb, void *ctx); int isobusfs_cli_send_and_register_fa_rf_event(struct isobusfs_priv *priv, uint8_t handle, uint16_t count, isobusfs_event_callback cb, void *ctx); int isobusfs_cli_send_and_register_fa_cf_event(struct isobusfs_priv *priv, uint8_t handle, isobusfs_event_callback cb, void *ctx); /* isobusfs_cli_selftests.c */ void isobusfs_cli_run_self_tests(struct isobusfs_priv *priv); /* isobusfs_cli_int.c */ void isobusfs_cli_int_start(struct isobusfs_priv *priv); int isobusfs_cli_interactive(struct isobusfs_priv *priv); /* isobusfs_cli.c */ int isobusfs_cli_process_events_and_tasks(struct isobusfs_priv *priv); void isobusfs_cli_prepare_response_event(struct isobusfs_event *event, int sock, uint8_t fs_function); int isobusfs_cli_register_event(struct isobusfs_priv *priv, const struct isobusfs_event *new_event); static inline uint8_t isobusfs_cli_get_next_tan(struct isobusfs_priv *priv) { return priv->next_tan++; } static inline bool isobusfs_cli_tan_is_valid(uint8_t tan, struct isobusfs_priv *priv) { uint8_t expected_tan = priv->next_tan == 0 ? 255 : priv->next_tan - 1; if (tan != expected_tan) { pr_err("%s: tan %d is not valid, expected tan %d\n", __func__, tan, expected_tan); return false; } return true; } #endif /* ISOBUSFS_CLI_H */