git commit -m "first commit for v2"
This commit is contained in:
241
Devices/Libraries/Systems/can-utils/isobusfs/isobusfs_cli_cm.c
Executable file
241
Devices/Libraries/Systems/can-utils/isobusfs/isobusfs_cli_cm.c
Executable file
@@ -0,0 +1,241 @@
|
||||
// SPDX-License-Identifier: LGPL-2.0-only
|
||||
// SPDX-FileCopyrightText: 2023 Oleksij Rempel <linux@rempel-privat.de>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "isobusfs_cli.h"
|
||||
#include "isobusfs_cmn_cm.h"
|
||||
|
||||
|
||||
int isobusfs_cli_volume_status_req(struct isobusfs_priv *priv,
|
||||
uint8_t volume_mode,
|
||||
uint16_t path_name_length,
|
||||
const char *volume_name)
|
||||
{
|
||||
struct isobusfs_cm_vol_stat_req req;
|
||||
size_t req_size;
|
||||
int ret;
|
||||
|
||||
req.fs_function =
|
||||
isobusfs_cg_function_to_buf(ISOBUSFS_CG_CONNECTION_MANAGMENT,
|
||||
ISOBUSFS_CM_VOLUME_STATUS_REQ);
|
||||
|
||||
req.volume_mode = volume_mode;
|
||||
req.name_len = htole16(path_name_length);
|
||||
req_size = sizeof(req) - sizeof(req.name) + path_name_length;
|
||||
|
||||
memcpy(req.name, volume_name, path_name_length);
|
||||
|
||||
ret = isobusfs_send(priv->sock_main, &req, req_size, &priv->tx_buf_log);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
pr_warn("failed to send volume status request: %d (%s)", ret, strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->state = ISOBUSFS_CLI_STATE_WAIT_VOLUME_STATUS;
|
||||
|
||||
pr_debug("> tx: volume status request");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int isobusfs_cli_property_req(struct isobusfs_priv *priv)
|
||||
{
|
||||
uint8_t buf[ISOBUSFS_MIN_TRANSFER_LENGH];
|
||||
int ret;
|
||||
|
||||
/* not used space should be filled with 0xff */
|
||||
memset(buf, 0xff, ARRAY_SIZE(buf));
|
||||
buf[0] = isobusfs_cg_function_to_buf(ISOBUSFS_CG_CONNECTION_MANAGMENT,
|
||||
ISOBUSFS_CM_GET_FS_PROPERTIES);
|
||||
|
||||
/* send property request */
|
||||
ret = isobusfs_send(priv->sock_main, buf, sizeof(buf), &priv->tx_buf_log);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->state = ISOBUSFS_CLI_STATE_WAIT_FS_PROPERTIES;
|
||||
|
||||
pr_debug("> tx: FS property request");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ccm section */
|
||||
void isobusfs_cli_ccm_init(struct isobusfs_priv *priv)
|
||||
{
|
||||
struct isobusfs_cm_ccm *ccm = &priv->ccm;
|
||||
|
||||
ccm->fs_function =
|
||||
isobusfs_cg_function_to_buf(ISOBUSFS_CG_CONNECTION_MANAGMENT,
|
||||
ISOBUSFS_CM_F_FS_STATUS);
|
||||
ccm->version = 2;
|
||||
memset(ccm->reserved, 0xFF, sizeof(ccm->reserved));
|
||||
}
|
||||
|
||||
/**
|
||||
* isobusfs_cli_ccm_send - send periodic file server status messages
|
||||
* @priv: pointer to the isobusfs_priv structure
|
||||
*
|
||||
* Returns 0 on success, -1 on errors.
|
||||
*/
|
||||
int isobusfs_cli_ccm_send(struct isobusfs_priv *priv)
|
||||
{
|
||||
int64_t time_diff;
|
||||
int ret;
|
||||
|
||||
/* Test if it is proper time to send next status message. */
|
||||
time_diff = timespec_diff_ms(&priv->cmn.next_send_time,
|
||||
&priv->cmn.last_time);
|
||||
if (time_diff > ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
||||
/* too early to send next message */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (time_diff < -ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
||||
pr_warn("too late to send next fs status message: %ld ms",
|
||||
time_diff);
|
||||
}
|
||||
|
||||
/* Make sure we send the message with the latest stats */
|
||||
if (priv->stats.tskey_sch != priv->stats.tskey_ack)
|
||||
pr_warn("previous message was not acked");
|
||||
|
||||
/* send periodic file servers status messages. */
|
||||
ret = isobusfs_send(priv->sock_ccm, &priv->ccm, sizeof(priv->ccm),
|
||||
&priv->tx_buf_log);
|
||||
if (ret < 0) {
|
||||
pr_err("sendto() failed: %d (%s)", ret, strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_debug("> tx: ccm version: %d", priv->ccm.version);
|
||||
|
||||
priv->cmn.next_send_time = priv->cmn.last_time;
|
||||
timespec_add_ms(&priv->cmn.next_send_time, 2000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* detect if FS is timeout */
|
||||
void isobusfs_cli_fs_detect_timeout(struct isobusfs_priv *priv)
|
||||
{
|
||||
int64_t time_diff;
|
||||
|
||||
if (!priv->fs_is_active)
|
||||
return;
|
||||
|
||||
time_diff = timespec_diff_ms(&priv->cmn.last_time,
|
||||
&priv->fs_last_seen);
|
||||
if (time_diff > ISOBUSFS_FS_TIMEOUT) {
|
||||
pr_debug("file server timeout");
|
||||
priv->fs_is_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* activate FS status if was not active till now */
|
||||
static void isobusfs_cli_fs_activate(struct isobusfs_priv *priv)
|
||||
{
|
||||
if (priv->fs_is_active)
|
||||
return;
|
||||
|
||||
pr_debug("file server detectet");
|
||||
priv->fs_is_active = true;
|
||||
}
|
||||
|
||||
static int isobusfs_cli_rx_fs_status(struct isobusfs_priv *priv,
|
||||
struct isobusfs_msg *msg)
|
||||
{
|
||||
struct isobusfs_cm_fss *fs_status = (void *)msg->buf;
|
||||
int ret = 0;
|
||||
|
||||
if (msg->len != sizeof(*fs_status)) {
|
||||
pr_warn("wrong message length: %d", msg->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
isobusfs_cli_fs_activate(priv);
|
||||
|
||||
priv->fs_last_seen = priv->cmn.last_time;
|
||||
pr_debug("< rx: fs status: %x, opened files: %d",
|
||||
fs_status->status, fs_status->num_open_files);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* process FS properties response */
|
||||
static int isobusfs_cli_rx_fs_property_res(struct isobusfs_priv *priv,
|
||||
struct isobusfs_msg *msg)
|
||||
{
|
||||
struct isobusfs_cm_get_fs_props_resp *fs_prop = (void *)msg->buf;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->state != ISOBUSFS_CLI_STATE_WAIT_FS_PROPERTIES) {
|
||||
pr_warn("unexpected fs properties response");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msg->len != sizeof(*fs_prop)) {
|
||||
pr_warn("wrong message length: %d", msg->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->fs_version = fs_prop->version_number;
|
||||
priv->fs_max_open_files = fs_prop->max_open_files;
|
||||
priv->fs_caps = fs_prop->fs_capabilities;
|
||||
|
||||
|
||||
pr_debug("< rx: fs properties: version: %d, max open files: %d, caps: %x",
|
||||
priv->fs_version, priv->fs_max_open_files, priv->fs_caps);
|
||||
|
||||
priv->state = ISOBUSFS_CLI_STATE_GET_FS_PROPERTIES_DONE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* function to handle ISOBUSFS_CM_VOLUME_STATUS_RES */
|
||||
static int isobusfs_cli_rx_volume_status_res(struct isobusfs_priv *priv,
|
||||
struct isobusfs_msg *msg)
|
||||
{
|
||||
struct isobusfs_cm_vol_stat_res *vol_status = (void *)msg->buf;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->state != ISOBUSFS_CLI_STATE_WAIT_VOLUME_STATUS) {
|
||||
pr_warn("unexpected volume status response");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("< rx: volume status: %x, max time before remove %d, error code %d, path name length %d, name %s",
|
||||
vol_status->volume_status,
|
||||
vol_status->max_time_before_removal,
|
||||
vol_status->error_code,
|
||||
vol_status->name_len,
|
||||
vol_status->name);
|
||||
|
||||
priv->state = ISOBUSFS_CLI_STATE_VOLUME_STATUS_DONE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Command group: connection management */
|
||||
int isobusfs_cli_rx_cg_cm(struct isobusfs_priv *priv, struct isobusfs_msg *msg)
|
||||
{
|
||||
int func = isobusfs_buf_to_function(msg->buf);
|
||||
int ret = 0;
|
||||
|
||||
switch (func) {
|
||||
case ISOBUSFS_CM_F_FS_STATUS:
|
||||
return isobusfs_cli_rx_fs_status(priv, msg);
|
||||
case ISOBUSFS_CM_GET_FS_PROPERTIES_RES:
|
||||
return isobusfs_cli_rx_fs_property_res(priv, msg);
|
||||
case ISOBUSFS_CM_VOLUME_STATUS_RES:
|
||||
return isobusfs_cli_rx_volume_status_res(priv, msg);
|
||||
default:
|
||||
pr_warn("unsupported function: %i", func);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user