mirror of
https://github.com/linux-can/can-utils.git
synced 2026-11-04 15:31:10 +01:00
Compare commits
21
Commits
cbbad5eede
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
834ceef1f1 | ||
|
|
f9086772a1 | ||
|
|
8355b57133 | ||
|
|
0f55228325 | ||
|
|
aa54819b65 | ||
|
|
8222f517b7 | ||
|
|
775611dba2 | ||
|
|
cd0ff30788 | ||
|
|
3a980d83e0 | ||
|
|
1a90b9a75d | ||
|
|
13dc8e9cc5 | ||
|
|
d5571a5bc3 | ||
|
|
33f7ddb5ed | ||
|
|
c7a02c0258 | ||
|
|
a63fd488b2 | ||
|
|
64280dc9c3 | ||
|
|
1663fc32b3 | ||
|
|
38cf8dd1a5 | ||
|
|
411a68675f | ||
|
|
6bdb574707 | ||
|
|
fa647cc3e2 |
@@ -42,6 +42,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -114,6 +115,42 @@ static void get_can_id(canid_t *can_id, char *idstring, int base)
|
|||||||
*can_id |= strtoul(idstring, NULL, base);
|
*can_id |= strtoul(idstring, NULL, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read 'len' ASCII hex bytes separated by single whitespace characters.
|
||||||
|
* Returns a pointer to the content behind the data or NULL on error.
|
||||||
|
*/
|
||||||
|
static char *get_hex_data(char *ptr, unsigned char *data, int len)
|
||||||
|
{
|
||||||
|
unsigned char ctmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
ctmp = asc2nibble(ptr[0]);
|
||||||
|
if (ctmp > 0x0F)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data[i] = (ctmp << 4);
|
||||||
|
|
||||||
|
ctmp = asc2nibble(ptr[1]);
|
||||||
|
if (ctmp > 0x0F)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data[i] |= ctmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The hex byte has to be followed by a separator (space/tab)
|
||||||
|
* or an EOL char ('\n', '\r'). This also ensures that we do
|
||||||
|
* not skip the string termination with ptr += 3 below.
|
||||||
|
*/
|
||||||
|
if (!isspace((unsigned char)ptr[2]))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ptr += 3; /* start of next ASCII hex byte */
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
static void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
static void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
||||||
struct timeval *date_tv, char timestamps, int dplace)
|
struct timeval *date_tv, char timestamps, int dplace)
|
||||||
{
|
{
|
||||||
@@ -155,7 +192,7 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
struct canfd_frame cf = { 0 };
|
struct canfd_frame cf = { 0 };
|
||||||
struct can_frame *ccf = (struct can_frame *)&cf; /* for len8_dlc */
|
struct can_frame *ccf = (struct can_frame *)&cf; /* for len8_dlc */
|
||||||
char rtr;
|
char rtr;
|
||||||
int dlc = 0;
|
unsigned int dlc = 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int data[8];
|
int data[8];
|
||||||
char idstr[21];
|
char idstr[21];
|
||||||
@@ -261,13 +298,12 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
static struct timeval tv; /* current frame timestamp */
|
static struct timeval tv; /* current frame timestamp */
|
||||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
struct canfd_frame cf = { 0 };
|
struct canfd_frame cf = { 0 };
|
||||||
unsigned char brs, esi, ctmp;
|
unsigned char brs, esi;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int dlc, dlen = 0;
|
unsigned int dlc, dlen = 0;
|
||||||
char idstr[21];
|
char idstr[21];
|
||||||
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int i;
|
|
||||||
int n = 0; /* sscanf consumed characters */
|
int n = 0; /* sscanf consumed characters */
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
@@ -283,12 +319,12 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* check for valid line without symbolic name */
|
/* check for valid line without symbolic name */
|
||||||
if (sscanf(buf, "%llu.%llu %*s %d %4s %20s %hhx %hhx %x %d %n",
|
if (sscanf(buf, "%llu.%llu %*s %d %4s %20s %hhx %hhx %x %u %n",
|
||||||
&sec, &usec, &interface,
|
&sec, &usec, &interface,
|
||||||
dir, idstr, &brs, &esi, &dlc, &dlen, &n) != 9) {
|
dir, idstr, &brs, &esi, &dlc, &dlen, &n) != 9) {
|
||||||
|
|
||||||
/* check for valid line with a symbolic name */
|
/* check for valid line with a symbolic name */
|
||||||
if (sscanf(buf, "%llu.%llu %*s %d %4s %20s %*s %hhx %hhx %x %d %n",
|
if (sscanf(buf, "%llu.%llu %*s %d %4s %20s %*s %hhx %hhx %x %u %n",
|
||||||
&sec, &usec, &interface,
|
&sec, &usec, &interface,
|
||||||
dir, idstr, &brs, &esi, &dlc, &dlen, &n) != 9) {
|
dir, idstr, &brs, &esi, &dlc, &dlen, &n) != 9) {
|
||||||
|
|
||||||
@@ -328,21 +364,9 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
|
|
||||||
cf.len = dlen;
|
cf.len = dlen;
|
||||||
|
|
||||||
for (i = 0; i < dlen; i++) {
|
ptr = get_hex_data(ptr, cf.data, dlen);
|
||||||
ctmp = asc2nibble(ptr[0]);
|
if (!ptr)
|
||||||
if (ctmp > 0x0F)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] = (ctmp << 4);
|
|
||||||
|
|
||||||
ctmp = asc2nibble(ptr[1]);
|
|
||||||
if (ctmp > 0x0F)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] |= ctmp;
|
|
||||||
|
|
||||||
ptr += 3; /* start of next ASCII hex byte */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip MessageDuration and MessageLength to get Flags value */
|
/* skip MessageDuration and MessageLength to get Flags value */
|
||||||
if (sscanf(ptr, " %*x %*x %x ", &flags) != 1)
|
if (sscanf(ptr, " %*x %*x %x ", &flags) != 1)
|
||||||
@@ -387,13 +411,11 @@ static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
static struct timeval tv; /* current frame timestamp */
|
static struct timeval tv; /* current frame timestamp */
|
||||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
struct can_frame cf = { 0 };
|
struct can_frame cf = { 0 };
|
||||||
unsigned char ctmp;
|
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int dlc, dlen = 0;
|
unsigned int dlc, dlen = 0;
|
||||||
char idstr[21];
|
char idstr[21];
|
||||||
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int i;
|
|
||||||
int n = 0; /* sscanf consumed characters */
|
int n = 0; /* sscanf consumed characters */
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
@@ -408,7 +430,7 @@ static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
if (sscanf(buf,
|
if (sscanf(buf,
|
||||||
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
"%x %d %n", /* DLC, Datalen */
|
"%x %u %n", /* DLC, Datalen */
|
||||||
&sec, &usec, &interface, dir,
|
&sec, &usec, &interface, dir,
|
||||||
idstr,
|
idstr,
|
||||||
&dlc, &dlen, &n) != 7) {
|
&dlc, &dlen, &n) != 7) {
|
||||||
@@ -416,7 +438,7 @@ static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
if (sscanf(buf,
|
if (sscanf(buf,
|
||||||
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
"%*s %x %d %n", /* sym name, DLC, Datalen */
|
"%*s %x %u %n", /* sym name, DLC, Datalen */
|
||||||
&sec, &usec, &interface, dir,
|
&sec, &usec, &interface, dir,
|
||||||
idstr,
|
idstr,
|
||||||
&dlc, &dlen, &n) != 7) {
|
&dlc, &dlen, &n) != 7) {
|
||||||
@@ -452,21 +474,9 @@ static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
|
|
||||||
cf.len = dlen;
|
cf.len = dlen;
|
||||||
|
|
||||||
for (i = 0; i < dlen; i++) {
|
ptr = get_hex_data(ptr, cf.data, dlen);
|
||||||
ctmp = asc2nibble(ptr[0]);
|
if (!ptr)
|
||||||
if (ctmp > 0x0F)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] = (ctmp << 4);
|
|
||||||
|
|
||||||
ctmp = asc2nibble(ptr[1]);
|
|
||||||
if (ctmp > 0x0F)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] |= ctmp;
|
|
||||||
|
|
||||||
ptr += 3; /* start of next ASCII hex byte */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip FCRC to get Flags value */
|
/* skip FCRC to get Flags value */
|
||||||
if (sscanf(ptr, "%*x %x ", &flags) != 1)
|
if (sscanf(ptr, "%*x %x ", &flags) != 1)
|
||||||
@@ -498,13 +508,11 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
static struct timeval tv; /* current frame timestamp */
|
static struct timeval tv; /* current frame timestamp */
|
||||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
struct canfd_frame cf = { 0 };
|
struct canfd_frame cf = { 0 };
|
||||||
unsigned char ctmp;
|
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int dlc, dlen = 0;
|
unsigned int dlc, dlen = 0;
|
||||||
char idstr[21];
|
char idstr[21];
|
||||||
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int i;
|
|
||||||
int n = 0; /* sscanf consumed characters */
|
int n = 0; /* sscanf consumed characters */
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
@@ -519,7 +527,7 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
if (sscanf(buf,
|
if (sscanf(buf,
|
||||||
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
"%x %d %n", /* DLC, Datalen */
|
"%x %u %n", /* DLC, Datalen */
|
||||||
&sec, &usec, &interface, dir,
|
&sec, &usec, &interface, dir,
|
||||||
idstr,
|
idstr,
|
||||||
&dlc, &dlen, &n) != 7) {
|
&dlc, &dlen, &n) != 7) {
|
||||||
@@ -527,7 +535,7 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
if (sscanf(buf,
|
if (sscanf(buf,
|
||||||
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
"%*s %x %d %n", /* sym name, DLC, Datalen */
|
"%*s %x %u %n", /* sym name, DLC, Datalen */
|
||||||
&sec, &usec, &interface, dir,
|
&sec, &usec, &interface, dir,
|
||||||
idstr,
|
idstr,
|
||||||
&dlc, &dlen, &n) != 7) {
|
&dlc, &dlen, &n) != 7) {
|
||||||
@@ -563,21 +571,9 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
|
|
||||||
cf.len = dlen;
|
cf.len = dlen;
|
||||||
|
|
||||||
for (i = 0; i < dlen; i++) {
|
ptr = get_hex_data(ptr, cf.data, dlen);
|
||||||
ctmp = asc2nibble(ptr[0]);
|
if (!ptr)
|
||||||
if (ctmp > 0x0F)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] = (ctmp << 4);
|
|
||||||
|
|
||||||
ctmp = asc2nibble(ptr[1]);
|
|
||||||
if (ctmp > 0x0F)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] |= ctmp;
|
|
||||||
|
|
||||||
ptr += 3; /* start of next ASCII hex byte */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip stuff field and FCRC to get Flags value */
|
/* skip stuff field and FCRC to get Flags value */
|
||||||
if (sscanf(ptr, "%*s %*s %x ", &flags) != 1)
|
if (sscanf(ptr, "%*s %*s %x ", &flags) != 1)
|
||||||
@@ -605,13 +601,12 @@ static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
static struct timeval tv; /* current frame timestamp */
|
static struct timeval tv; /* current frame timestamp */
|
||||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
struct canxl_frame cf = { 0 };
|
struct canxl_frame cf = { 0 };
|
||||||
unsigned char sdt, vcid, secbit, ctmp;
|
unsigned char sdt, vcid, secbit;
|
||||||
unsigned int af, flags;
|
unsigned int af, flags;
|
||||||
int dlc, dlen = 0;
|
unsigned int dlc, dlen = 0;
|
||||||
char idstr[21];
|
char idstr[21];
|
||||||
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int i;
|
|
||||||
int n = 0; /* sscanf consumed characters */
|
int n = 0; /* sscanf consumed characters */
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
@@ -627,7 +622,7 @@ static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
if (sscanf(buf,
|
if (sscanf(buf,
|
||||||
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
"%hhx %hhx %x %d " /* SDT, SEC, DLC, Datalen */
|
"%hhx %hhx %x %u " /* SDT, SEC, DLC, Datalen */
|
||||||
"%*s %*s %hhx %x %n", /* stuff bit count, crc, VCID, AF */
|
"%*s %*s %hhx %x %n", /* stuff bit count, crc, VCID, AF */
|
||||||
&sec, &usec, &interface, dir,
|
&sec, &usec, &interface, dir,
|
||||||
idstr,
|
idstr,
|
||||||
@@ -637,7 +632,7 @@ static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
if (sscanf(buf,
|
if (sscanf(buf,
|
||||||
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
"%*s %hhx %hhx %x %d " /* sym name, SDT, SEC, DLC, Datalen */
|
"%*s %hhx %hhx %x %u " /* sym name, SDT, SEC, DLC, Datalen */
|
||||||
"%*s %*s %hhx %x %n", /* stuff bit count, crc, VCID, AF */
|
"%*s %*s %hhx %x %n", /* stuff bit count, crc, VCID, AF */
|
||||||
&sec, &usec, &interface, dir,
|
&sec, &usec, &interface, dir,
|
||||||
idstr,
|
idstr,
|
||||||
@@ -689,21 +684,9 @@ static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
|
|
||||||
cf.len = dlen;
|
cf.len = dlen;
|
||||||
|
|
||||||
for (i = 0; i < dlen; i++) {
|
ptr = get_hex_data(ptr, cf.data, dlen);
|
||||||
ctmp = asc2nibble(ptr[0]);
|
if (!ptr)
|
||||||
if (ctmp > 0x0F)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] = (ctmp << 4);
|
|
||||||
|
|
||||||
ctmp = asc2nibble(ptr[1]);
|
|
||||||
if (ctmp > 0x0F)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cf.data[i] |= ctmp;
|
|
||||||
|
|
||||||
ptr += 3; /* start of next ASCII hex byte */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip FCRC to get Flags value */
|
/* skip FCRC to get Flags value */
|
||||||
if (sscanf(ptr, "%*x %x ", &flags) != 1)
|
if (sscanf(ptr, "%*x %x ", &flags) != 1)
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ static int parse_mod(char *optarg, struct modattr *modmsg)
|
|||||||
ptr = optarg;
|
ptr = optarg;
|
||||||
nptr = strchr(ptr, ':');
|
nptr = strchr(ptr, ':');
|
||||||
|
|
||||||
if ((nptr - ptr > 3) || (nptr - ptr == 0))
|
if (!nptr || (nptr - ptr > 3) || (nptr - ptr == 0))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!strncmp(ptr, "AND", 3))
|
if (!strncmp(ptr, "AND", 3))
|
||||||
@@ -355,7 +355,7 @@ static int parse_mod(char *optarg, struct modattr *modmsg)
|
|||||||
ptr = nptr+1;
|
ptr = nptr+1;
|
||||||
nptr = strchr(ptr, ':');
|
nptr = strchr(ptr, ':');
|
||||||
|
|
||||||
if ((nptr - ptr > 3) || (nptr - ptr == 0))
|
if (!nptr || (nptr - ptr > 3) || (nptr - ptr == 0))
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
modmsg->modtype = 0;
|
modmsg->modtype = 0;
|
||||||
@@ -406,7 +406,7 @@ static int parse_fdmod(char *optarg, struct fdmodattr *modmsg)
|
|||||||
ptr = optarg;
|
ptr = optarg;
|
||||||
nptr = strchr(ptr, ':');
|
nptr = strchr(ptr, ':');
|
||||||
|
|
||||||
if ((nptr - ptr > 3) || (nptr - ptr == 0))
|
if (!nptr || (nptr - ptr > 3) || (nptr - ptr == 0))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!strncmp(ptr, "AND", 3))
|
if (!strncmp(ptr, "AND", 3))
|
||||||
@@ -423,7 +423,7 @@ static int parse_fdmod(char *optarg, struct fdmodattr *modmsg)
|
|||||||
ptr = nptr+1;
|
ptr = nptr+1;
|
||||||
nptr = strchr(ptr, ':');
|
nptr = strchr(ptr, ':');
|
||||||
|
|
||||||
if ((nptr - ptr > 4) || (nptr - ptr == 0))
|
if (!nptr || (nptr - ptr > 4) || (nptr - ptr == 0))
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
modmsg->modtype = 0;
|
modmsg->modtype = 0;
|
||||||
|
|||||||
@@ -671,6 +671,10 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = isobusfs_cli_process_events_and_tasks(priv);
|
ret = isobusfs_cli_process_events_and_tasks(priv);
|
||||||
|
if (ret == ISOBUSFS_CLI_RET_EXIT) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
#define ISOBUSFS_CLI_MAX_EPOLL_EVENTS 10
|
#define ISOBUSFS_CLI_MAX_EPOLL_EVENTS 10
|
||||||
#define ISOBUSFS_CLI_DEFAULT_WAIT_TIMEOUT_MS 1000 /* ms */
|
#define ISOBUSFS_CLI_DEFAULT_WAIT_TIMEOUT_MS 1000 /* ms */
|
||||||
|
|
||||||
|
/* internal return codes, not errno values */
|
||||||
|
#define ISOBUSFS_CLI_RET_EXIT 1
|
||||||
|
|
||||||
enum isobusfs_cli_state {
|
enum isobusfs_cli_state {
|
||||||
ISOBUSFS_CLI_STATE_CONNECTING,
|
ISOBUSFS_CLI_STATE_CONNECTING,
|
||||||
ISOBUSFS_CLI_STATE_IDLE,
|
ISOBUSFS_CLI_STATE_IDLE,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 Oleksij Rempel <linux@rempel-privat.de>
|
// SPDX-FileCopyrightText: 2023 Oleksij Rempel <linux@rempel-privat.de>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ int isobusfs_cli_ccm_send(struct isobusfs_priv *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (time_diff < -ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
if (time_diff < -ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
||||||
pr_warn("too late to send next fs status message: %ld ms",
|
pr_warn("too late to send next fs status message: %" PRId64 " ms",
|
||||||
time_diff);
|
time_diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ static int isobusfs_cli_rx_fs_status(struct isobusfs_priv *priv,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (msg->len != sizeof(*fs_status)) {
|
if (msg->len != sizeof(*fs_status)) {
|
||||||
pr_warn("wrong message length: %d", msg->len);
|
pr_warn("wrong message length: %zd", msg->len);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ static int isobusfs_cli_rx_fs_property_res(struct isobusfs_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg->len != sizeof(*fs_prop)) {
|
if (msg->len != sizeof(*fs_prop)) {
|
||||||
pr_warn("wrong message length: %d", msg->len);
|
pr_warn("wrong message length: %zd", msg->len);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ int isobusfs_cli_ccd_req(struct isobusfs_priv *priv, const char *name,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (name_len > ISOBUSFS_MAX_PATH_NAME_LENGTH) {
|
if (name_len > ISOBUSFS_MAX_PATH_NAME_LENGTH) {
|
||||||
pr_warn("path name too long: %i, max is %i", name_len,
|
pr_warn("path name too long: %zu, max is %i", name_len,
|
||||||
ISOBUSFS_MAX_PATH_NAME_LENGTH);
|
ISOBUSFS_MAX_PATH_NAME_LENGTH);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ int isobusfs_cli_ccd_req(struct isobusfs_priv *priv, const char *name,
|
|||||||
req->tan = isobusfs_cli_get_next_tan(priv);
|
req->tan = isobusfs_cli_get_next_tan(priv);
|
||||||
|
|
||||||
memcpy(&req->name[0], name, name_len);
|
memcpy(&req->name[0], name, name_len);
|
||||||
req->name_len = name_len;
|
req->name_len = htole16(name_len);
|
||||||
|
|
||||||
if (padding_size) {
|
if (padding_size) {
|
||||||
/* Fill the rest of the res structure with 0xff */
|
/* Fill the rest of the res structure with 0xff */
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ int isobusfs_cli_fa_of_req(struct isobusfs_priv *priv, const char *name,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (name_len > ISOBUSFS_MAX_PATH_NAME_LENGTH) {
|
if (name_len > ISOBUSFS_MAX_PATH_NAME_LENGTH) {
|
||||||
pr_warn("path name too long: %i, max is %i", name_len,
|
pr_warn("path name too long: %zu, max is %i", name_len,
|
||||||
ISOBUSFS_MAX_PATH_NAME_LENGTH);
|
ISOBUSFS_MAX_PATH_NAME_LENGTH);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -308,7 +308,7 @@ int isobusfs_cli_fa_of_req(struct isobusfs_priv *priv, const char *name,
|
|||||||
req->tan = isobusfs_cli_get_next_tan(priv);
|
req->tan = isobusfs_cli_get_next_tan(priv);
|
||||||
req->flags = flags;
|
req->flags = flags;
|
||||||
memcpy(&req->name[0], name, name_len);
|
memcpy(&req->name[0], name, name_len);
|
||||||
req->name_len = name_len;
|
req->name_len = htole16(name_len);
|
||||||
|
|
||||||
if (padding_size) {
|
if (padding_size) {
|
||||||
/* Fill the rest of the res structure with 0xff */
|
/* Fill the rest of the res structure with 0xff */
|
||||||
|
|||||||
+81
-34
@@ -16,6 +16,12 @@
|
|||||||
#define MAX_COMMAND_LENGTH 256
|
#define MAX_COMMAND_LENGTH 256
|
||||||
|
|
||||||
#define MAX_DISPLAY_FILENAME_LENGTH 100
|
#define MAX_DISPLAY_FILENAME_LENGTH 100
|
||||||
|
/*
|
||||||
|
* ISO 11783-13:2021 B.21 minimal directory entry payload size in bytes:
|
||||||
|
* 1 (name length) + 1 (min name byte) + 1 (attributes) +
|
||||||
|
* 2 (date) + 2 (time) + 4 (size).
|
||||||
|
*/
|
||||||
|
#define ISOBUSFS_MIN_DIR_ENTRY_SIZE (1 + 1 + 1 + 2 + 2 + 4)
|
||||||
|
|
||||||
struct command_mapping {
|
struct command_mapping {
|
||||||
const char *command;
|
const char *command;
|
||||||
@@ -66,8 +72,8 @@ static int cmd_help(struct isobusfs_priv *priv, const char *options)
|
|||||||
static int cmd_exit(struct isobusfs_priv *priv, const char *options)
|
static int cmd_exit(struct isobusfs_priv *priv, const char *options)
|
||||||
{
|
{
|
||||||
pr_int("exit interactive mode\n");
|
pr_int("exit interactive mode\n");
|
||||||
/* Return -EINTR to indicate the program should exit */
|
|
||||||
return -EINTR;
|
return ISOBUSFS_CLI_RET_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_dmesg(struct isobusfs_priv *priv, const char *options)
|
static int cmd_dmesg(struct isobusfs_priv *priv, const char *options)
|
||||||
@@ -510,8 +516,12 @@ isobusfs_cli_ls_handle_open_dir_sent(struct isobusfs_priv *priv,
|
|||||||
|
|
||||||
ctx->handle = res->handle;
|
ctx->handle = res->handle;
|
||||||
|
|
||||||
|
ctx->offset = 0;
|
||||||
|
ctx->entry_count = 0;
|
||||||
|
|
||||||
ret = isobusfs_cli_send_and_register_fa_sf_event(priv, ctx->handle,
|
ret = isobusfs_cli_send_and_register_fa_sf_event(priv, ctx->handle,
|
||||||
0, ctx->entry_count,
|
ISOBUSFS_FA_SEEK_SET,
|
||||||
|
ctx->offset,
|
||||||
cb, ctx);
|
cb, ctx);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_int("Failed to send seek file request: %i\n", ret);
|
pr_int("Failed to send seek file request: %i\n", ret);
|
||||||
@@ -530,21 +540,23 @@ isobusfs_cli_ls_handle_seek_dir_sent(struct isobusfs_priv *priv,
|
|||||||
{
|
{
|
||||||
isobusfs_event_callback cb = isobusfs_cli_ls_event_callback;
|
isobusfs_event_callback cb = isobusfs_cli_ls_event_callback;
|
||||||
struct isobusfs_fa_seekf_res *res =
|
struct isobusfs_fa_seekf_res *res =
|
||||||
(struct isobusfs_fa_seekf_res *)msg;
|
(struct isobusfs_fa_seekf_res *)msg->buf;
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (isobusfs_cli_int_is_error(priv, 0, res->error_code, res->tan))
|
if (isobusfs_cli_int_is_error(priv, 0, res->error_code, res->tan))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (res->position != ctx->offset) {
|
if (le32toh(res->position) != ctx->offset) {
|
||||||
pr_int("Failed to seek to position %zu, got %zu\n",
|
pr_int("Failed to seek to position %zu, got %u\n",
|
||||||
ctx->offset, res->position);
|
ctx->offset, le32toh(res->position));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set max possible number fitting in to 16bits */
|
/* ISO 11783-13:2021 C.3.5.2: count is number of directory entries. */
|
||||||
count = UINT16_MAX;
|
count = ISOBUSFS_MAX_DATA_LENGH / ISOBUSFS_MIN_DIR_ENTRY_SIZE;
|
||||||
|
if (!count)
|
||||||
|
count = 1;
|
||||||
ctx->request_count = count;
|
ctx->request_count = count;
|
||||||
|
|
||||||
ret = isobusfs_cli_send_and_register_fa_rf_event(priv, ctx->handle,
|
ret = isobusfs_cli_send_and_register_fa_rf_event(priv, ctx->handle,
|
||||||
@@ -616,8 +628,8 @@ static bool isobusfs_cli_extract_directory_entry(const uint8_t *buffer,
|
|||||||
uint16_t *file_time,
|
uint16_t *file_time,
|
||||||
uint32_t *file_size)
|
uint32_t *file_size)
|
||||||
{
|
{
|
||||||
|
size_t entry_total_len, copy_len;
|
||||||
uint8_t filename_length;
|
uint8_t filename_length;
|
||||||
size_t entry_total_len;
|
|
||||||
|
|
||||||
if (*pos + 2 > buffer_length) {
|
if (*pos + 2 > buffer_length) {
|
||||||
pr_int("Error: Incomplete data in buffer\n");
|
pr_int("Error: Incomplete data in buffer\n");
|
||||||
@@ -633,8 +645,14 @@ static bool isobusfs_cli_extract_directory_entry(const uint8_t *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*pos)++;
|
(*pos)++;
|
||||||
strncpy(filename, (const char *)buffer + *pos, filename_length);
|
|
||||||
filename[filename_length] = '\0';
|
if (filename_length > ISOBUSFS_MAX_DIR_ENTRY_NAME_LENGTH)
|
||||||
|
copy_len = ISOBUSFS_MAX_DIR_ENTRY_NAME_LENGTH;
|
||||||
|
else
|
||||||
|
copy_len = filename_length;
|
||||||
|
|
||||||
|
strncpy(filename, (const char *)buffer + *pos, copy_len);
|
||||||
|
filename[copy_len] = '\0';
|
||||||
*pos += filename_length;
|
*pos += filename_length;
|
||||||
if (filename_length > MAX_DISPLAY_FILENAME_LENGTH) {
|
if (filename_length > MAX_DISPLAY_FILENAME_LENGTH) {
|
||||||
/* Truncate the filename and replace the last character
|
/* Truncate the filename and replace the last character
|
||||||
@@ -688,15 +706,17 @@ isobusfs_cli_print_directory_entry(struct isobusfs_cli_ls_context *ctx,
|
|||||||
static void
|
static void
|
||||||
isobusfs_cli_print_directory_entries(struct isobusfs_cli_ls_context *ctx,
|
isobusfs_cli_print_directory_entries(struct isobusfs_cli_ls_context *ctx,
|
||||||
const uint8_t *buffer,
|
const uint8_t *buffer,
|
||||||
size_t buffer_length)
|
size_t buffer_length,
|
||||||
|
uint16_t max_entries)
|
||||||
{
|
{
|
||||||
char filename[ISOBUSFS_MAX_DIR_ENTRY_NAME_LENGTH + 1];
|
char filename[ISOBUSFS_MAX_DIR_ENTRY_NAME_LENGTH + 1];
|
||||||
uint16_t file_date, file_time;
|
uint16_t file_date, file_time;
|
||||||
uint32_t file_size;
|
uint32_t file_size;
|
||||||
uint8_t attributes;
|
uint8_t attributes;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
uint16_t entries = 0;
|
||||||
|
|
||||||
while (pos < buffer_length) {
|
while (pos < buffer_length && entries < max_entries) {
|
||||||
if (!isobusfs_cli_extract_directory_entry(buffer, buffer_length,
|
if (!isobusfs_cli_extract_directory_entry(buffer, buffer_length,
|
||||||
&pos, filename,
|
&pos, filename,
|
||||||
&attributes,
|
&attributes,
|
||||||
@@ -709,6 +729,7 @@ isobusfs_cli_print_directory_entries(struct isobusfs_cli_ls_context *ctx,
|
|||||||
file_date, file_time,
|
file_date, file_time,
|
||||||
file_size);
|
file_size);
|
||||||
ctx->entry_count++;
|
ctx->entry_count++;
|
||||||
|
entries++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,26 +742,42 @@ isobusfs_cli_ls_handle_read_dir_sent(struct isobusfs_priv *priv,
|
|||||||
(struct isobusfs_read_file_response *)msg->buf;
|
(struct isobusfs_read_file_response *)msg->buf;
|
||||||
size_t buffer_length = msg->len - sizeof(*res);
|
size_t buffer_length = msg->len - sizeof(*res);
|
||||||
isobusfs_event_callback cb;
|
isobusfs_event_callback cb;
|
||||||
|
size_t entries_before;
|
||||||
|
size_t entries_in_message;
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pr_debug("< rx: Read File Response. Error code: %i", res->error_code);
|
pr_debug("< rx: Read File Response. Error code: %i", res->error_code);
|
||||||
|
|
||||||
if (isobusfs_cli_int_is_error(priv, 0, res->error_code, res->tan))
|
if (isobusfs_cli_int_is_error(priv, 0, res->error_code, res->tan))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
count = le16toh(res->count);
|
count = le16toh(res->count);
|
||||||
if (count && count != buffer_length) {
|
if (count && buffer_length) {
|
||||||
pr_int("Buffer length mismatch: %u != %zu\n", count,
|
entries_before = ctx->entry_count;
|
||||||
buffer_length);
|
isobusfs_cli_print_directory_entries(ctx, res->data,
|
||||||
goto error;
|
buffer_length, count);
|
||||||
|
entries_in_message = ctx->entry_count - entries_before;
|
||||||
|
} else {
|
||||||
|
entries_in_message = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count)
|
if (count != entries_in_message) {
|
||||||
isobusfs_cli_print_directory_entries(ctx, res->data,
|
pr_warn("Directory entry count mismatch: server sent %u, parsed %zu\n",
|
||||||
buffer_length);
|
count, entries_in_message);
|
||||||
|
/* Continue processing if we parsed at least some entries.
|
||||||
|
* Strict validation would reject valid responses if parsing
|
||||||
|
* fails partway through due to corruption.
|
||||||
|
*/
|
||||||
|
if (entries_in_message == 0 && count > 0) {
|
||||||
|
pr_int("Error: Failed to parse any directory entries\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cb = isobusfs_cli_ls_event_callback;
|
cb = isobusfs_cli_ls_event_callback;
|
||||||
if (count) {
|
|
||||||
|
if (res->error_code == ISOBUSFS_ERR_END_OF_FILE) {
|
||||||
ret = isobusfs_cli_send_and_register_fa_cf_event(priv,
|
ret = isobusfs_cli_send_and_register_fa_cf_event(priv,
|
||||||
ctx->handle,
|
ctx->handle,
|
||||||
cb, ctx);
|
cb, ctx);
|
||||||
@@ -750,21 +787,31 @@ isobusfs_cli_ls_handle_read_dir_sent(struct isobusfs_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->state = ISOBUSFS_CLI_LS_STATE_CLOSE_DIR_SENT;
|
ctx->state = ISOBUSFS_CLI_LS_STATE_CLOSE_DIR_SENT;
|
||||||
} else {
|
return;
|
||||||
ctx->offset = ctx->entry_count;
|
|
||||||
ret = isobusfs_cli_send_and_register_fa_sf_event(priv,
|
|
||||||
ctx->handle, 0,
|
|
||||||
ctx->offset,
|
|
||||||
cb, ctx);
|
|
||||||
if (ret)
|
|
||||||
pr_int("Failed to send seek file request: %i\n", ret);
|
|
||||||
|
|
||||||
ctx->state = ISOBUSFS_CLI_LS_STATE_SEEK_DIR_SENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!count) {
|
||||||
|
pr_int("Error: zero-length read without EOF\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Directory seek offset is entry index, not byte offset.
|
||||||
|
* Server side seek rewinds and skips "offset" entries.
|
||||||
|
*/
|
||||||
|
ctx->offset = ctx->entry_count;
|
||||||
|
|
||||||
|
ret = isobusfs_cli_send_and_register_fa_sf_event(priv,
|
||||||
|
ctx->handle, 0,
|
||||||
|
ctx->offset,
|
||||||
|
cb, ctx);
|
||||||
|
if (ret)
|
||||||
|
pr_int("Failed to send seek file request: %i\n", ret);
|
||||||
|
|
||||||
|
ctx->state = ISOBUSFS_CLI_LS_STATE_SEEK_DIR_SENT;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
|
|
||||||
ctx->state = ISOBUSFS_CLI_LS_STATE_ERROR;
|
ctx->state = ISOBUSFS_CLI_LS_STATE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -821,7 +868,7 @@ static void isobusfs_cli_process_ls_command(struct isobusfs_priv *priv,
|
|||||||
ctx->handle, NULL, NULL);
|
ctx->handle, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_int("Entries found: %i\n", ctx->entry_count);
|
pr_int("Entries found: %zu\n", ctx->entry_count);
|
||||||
priv->int_busy = false;
|
priv->int_busy = false;
|
||||||
isobusfs_cli_ls_free_ctx(ctx);
|
isobusfs_cli_ls_free_ctx(ctx);
|
||||||
isobusfs_cli_promt(priv);
|
isobusfs_cli_promt(priv);
|
||||||
|
|||||||
@@ -603,23 +603,24 @@ struct isobusfs_cli_test_rf_path {
|
|||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t read_size;
|
uint32_t read_size;
|
||||||
|
uint32_t expected_size;
|
||||||
bool expect_pass;
|
bool expect_pass;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct isobusfs_cli_test_rf_path test_rf_patterns[] = {
|
static struct isobusfs_cli_test_rf_path test_rf_patterns[] = {
|
||||||
/* expected result \\vol1\dir1\dir2\ */
|
/* expected result \\vol1\dir1\dir2\ */
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 0, 0, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 0, 0, 0, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 0, 1, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 0, 1, 1, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 1, 1, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 1, 1, 1, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 2, 1, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 2, 1, 1, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 3, 1, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1k", 0, 3, 1, 1, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, 8, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, 8, 8, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, 8 * 100, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, 8 * 100, 8 * 100, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 100, 8 * 100, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 100, 8 * 100, 8 * 100, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, ISOBUSFS_MAX_DATA_LENGH, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, ISOBUSFS_MAX_DATA_LENGH, ISOBUSFS_MAX_DATA_LENGH, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, (ISOBUSFS_MAX_DATA_LENGH & ~3) + 16, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, (ISOBUSFS_MAX_DATA_LENGH & ~3) + 16, (ISOBUSFS_MAX_DATA_LENGH & ~3) + 16, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, ISOBUSFS_MAX_DATA_LENGH + 1, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, ISOBUSFS_MAX_DATA_LENGH + 1, ISOBUSFS_MAX_DATA_LENGH + 1, true },
|
||||||
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, -1, true },
|
{ "\\\\vol1\\dir1\\dir2\\file1m", 0, 0, UINT32_MAX, 1024 * 1024, true },
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t current_rf_pattern_test;
|
size_t current_rf_pattern_test;
|
||||||
@@ -678,7 +679,8 @@ static int isobusfs_cli_test_rf_req(struct isobusfs_priv *priv, bool *complete)
|
|||||||
&test_rf_patterns[current_rf_pattern_test];
|
&test_rf_patterns[current_rf_pattern_test];
|
||||||
uint32_t actual_sum, expected_sum;
|
uint32_t actual_sum, expected_sum;
|
||||||
struct timespec current_time;
|
struct timespec current_time;
|
||||||
ssize_t remaining_size, read_size;
|
int64_t remaining_size;
|
||||||
|
ssize_t read_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, ¤t_time);
|
clock_gettime(CLOCK_MONOTONIC, ¤t_time);
|
||||||
@@ -801,16 +803,23 @@ static int isobusfs_cli_test_rf_req(struct isobusfs_priv *priv, bool *complete)
|
|||||||
free(priv->read_data);
|
free(priv->read_data);
|
||||||
priv->read_data = NULL;
|
priv->read_data = NULL;
|
||||||
|
|
||||||
remaining_size = (tp->offset + tp->read_size) -
|
remaining_size = ((int64_t)tp->offset + tp->read_size) -
|
||||||
(priv->read_offset + priv->read_data_len);
|
((int64_t)priv->read_offset + priv->read_data_len);
|
||||||
pr_debug("remaining_size: %zd, read_offset: %zu, read_data_len: %zu, test read size: %zu, test offset %zu",
|
pr_debug("remaining_size: %lld, read_offset: %u, read_data_len: %zu, test read size: %u, test offset %u",
|
||||||
remaining_size, priv->read_offset, priv->read_data_len,
|
(long long)remaining_size, priv->read_offset, priv->read_data_len,
|
||||||
tp->read_size, tp->offset);
|
tp->read_size, tp->offset);
|
||||||
if (remaining_size < 0) {
|
if (remaining_size < 0) {
|
||||||
pr_err("pattern test failed: %s. Read size is too big",
|
pr_err("pattern test failed: %s. Read size is too big",
|
||||||
tp->path_name);
|
tp->path_name);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto test_fail;
|
goto test_fail;
|
||||||
|
} else if (remaining_size == 0) {
|
||||||
|
if (tp->read_size > tp->expected_size) {
|
||||||
|
pr_err("read test failed: %s. Server returned more data than expected file size (%u > %u)",
|
||||||
|
tp->path_name, tp->read_size, tp->expected_size);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto test_fail;
|
||||||
|
}
|
||||||
} else if (remaining_size > 0 && priv->read_data_len != 0) {
|
} else if (remaining_size > 0 && priv->read_data_len != 0) {
|
||||||
priv->read_offset += priv->read_data_len;
|
priv->read_offset += priv->read_data_len;
|
||||||
|
|
||||||
@@ -825,11 +834,20 @@ static int isobusfs_cli_test_rf_req(struct isobusfs_priv *priv, bool *complete)
|
|||||||
goto test_fail;
|
goto test_fail;
|
||||||
test_start_time = current_time;
|
test_start_time = current_time;
|
||||||
break;
|
break;
|
||||||
} else if (remaining_size > 0 && priv->read_data_len == 0 && tp->expect_pass) {
|
} else if (remaining_size > 0 && priv->read_data_len == 0) {
|
||||||
pr_err("read test failed: %s. Read size is zero, but expected more data: %zd",
|
if (tp->read_size > tp->expected_size &&
|
||||||
tp->path_name, remaining_size);
|
tp->read_size - remaining_size == tp->expected_size) {
|
||||||
ret = -EINVAL;
|
/* this is acceptable case when read size
|
||||||
goto test_fail;
|
* is larger than actual file size
|
||||||
|
*/
|
||||||
|
pr_info("read test passed: %s. Reached end of file as expected.",
|
||||||
|
tp->path_name);
|
||||||
|
} else {
|
||||||
|
pr_err("read test failed: %s. Server returned zero bytes, but expected more data: %lld",
|
||||||
|
tp->path_name, (long long)remaining_size);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto test_fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fall troth */
|
/* fall troth */
|
||||||
|
|||||||
@@ -443,8 +443,8 @@ void isobusfs_dump_tx_data(const struct isobusfs_buf_log *buffer)
|
|||||||
for (j = 0; j < ISOBUSFS_MIN_TRANSFER_LENGH; ++j)
|
for (j = 0; j < ISOBUSFS_MIN_TRANSFER_LENGH; ++j)
|
||||||
snprintf(data_str + j * 3, 4, "%02X ", entry->data[j]);
|
snprintf(data_str + j * 3, 4, "%02X ", entry->data[j]);
|
||||||
|
|
||||||
pr_debug("Entry %u: %s Timestamp: %ld.%09ld\n", i, data_str,
|
pr_debug("Entry %u: %s Timestamp: %lld.%09ld\n", i, data_str,
|
||||||
entry->ts.tv_sec, entry->ts.tv_nsec);
|
(long long)entry->ts.tv_sec, entry->ts.tv_nsec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -322,7 +322,8 @@ typedef enum {
|
|||||||
} log_level_t;
|
} log_level_t;
|
||||||
|
|
||||||
void isobusfs_log_level_set(log_level_t level);
|
void isobusfs_log_level_set(log_level_t level);
|
||||||
void isobusfs_log(log_level_t level, const char *fmt, ...);
|
void isobusfs_log(log_level_t level, const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
void isobusfs_set_interactive(bool interactive);
|
void isobusfs_set_interactive(bool interactive);
|
||||||
void isobusfs_print_log_buffer(void);
|
void isobusfs_print_log_buffer(void);
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ struct isobusfs_cm_fss {
|
|||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint8_t num_open_files;
|
uint8_t num_open_files;
|
||||||
uint8_t reserved[5];
|
uint8_t reserved[5];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.1.3 Client Connection Maintenance
|
* C.1.3 Client Connection Maintenance
|
||||||
@@ -58,7 +58,7 @@ struct isobusfs_cm_ccm {
|
|||||||
uint8_t fs_function;
|
uint8_t fs_function;
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
uint8_t reserved[6];
|
uint8_t reserved[6];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.1.4 Get File Server Properties
|
* C.1.4 Get File Server Properties
|
||||||
@@ -75,7 +75,7 @@ struct isobusfs_cm_ccm {
|
|||||||
struct isobusfs_cm_get_fs_props_req {
|
struct isobusfs_cm_get_fs_props_req {
|
||||||
uint8_t fs_function;
|
uint8_t fs_function;
|
||||||
uint8_t reserved[7];
|
uint8_t reserved[7];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/* File Server Capabilities */
|
/* File Server Capabilities */
|
||||||
/* server support removable volumes */
|
/* server support removable volumes */
|
||||||
@@ -104,7 +104,7 @@ struct isobusfs_cm_get_fs_props_resp {
|
|||||||
uint8_t max_open_files;
|
uint8_t max_open_files;
|
||||||
uint8_t fs_capabilities;
|
uint8_t fs_capabilities;
|
||||||
uint8_t reserved[4];
|
uint8_t reserved[4];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
#define ISOBUSFS_VOL_MODE_PREP_TO_REMOVE BIT(1)
|
#define ISOBUSFS_VOL_MODE_PREP_TO_REMOVE BIT(1)
|
||||||
#define ISOBUSFS_VOL_MODE_USED_BY_CLIENT BIT(0)
|
#define ISOBUSFS_VOL_MODE_USED_BY_CLIENT BIT(0)
|
||||||
@@ -130,7 +130,7 @@ struct isobusfs_cm_vol_stat_req {
|
|||||||
uint8_t volume_mode;
|
uint8_t volume_mode;
|
||||||
__le16 name_len;
|
__le16 name_len;
|
||||||
char name[ISOBUSFS_MAX_VOLUME_NAME_LENGTH];
|
char name[ISOBUSFS_MAX_VOLUME_NAME_LENGTH];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|
||||||
enum isobusfs_vol_status {
|
enum isobusfs_vol_status {
|
||||||
@@ -169,7 +169,7 @@ struct isobusfs_cm_vol_stat_res {
|
|||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
__le16 name_len;
|
__le16 name_len;
|
||||||
char name[ISOBUSFS_MAX_VOLUME_NAME_LENGTH];
|
char name[ISOBUSFS_MAX_VOLUME_NAME_LENGTH];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|
||||||
#endif /* ISOBUSFS_CMN_CM_H */
|
#endif /* ISOBUSFS_CMN_CM_H */
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ struct isobusfs_dh_get_cd_req {
|
|||||||
uint8_t fs_function;
|
uint8_t fs_function;
|
||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t reserved[6];
|
uint8_t reserved[6];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.2.2.3 Get Current Directory Response
|
* C.2.2.3 Get Current Directory Response
|
||||||
@@ -50,7 +50,7 @@ struct isobusfs_dh_get_cd_res {
|
|||||||
__le32 free_space;
|
__le32 free_space;
|
||||||
__le16 name_len;
|
__le16 name_len;
|
||||||
uint8_t name[];
|
uint8_t name[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.2.3.2 Change Current Directory Request
|
* C.2.3.2 Change Current Directory Request
|
||||||
@@ -71,7 +71,7 @@ struct isobusfs_dh_ccd_req {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
__le16 name_len;
|
__le16 name_len;
|
||||||
uint8_t name[];
|
uint8_t name[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.2.3.3 Change Current Directory Response
|
* C.2.3.3 Change Current Directory Response
|
||||||
@@ -101,7 +101,7 @@ struct isobusfs_dh_ccd_res {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t reserved[5];
|
uint8_t reserved[5];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|
||||||
#endif /* _ISOBUSFS_CMN_DH_H */
|
#endif /* _ISOBUSFS_CMN_DH_H */
|
||||||
|
|||||||
+11
-11
@@ -105,7 +105,7 @@ struct isobusfs_fa_openf_req {
|
|||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
__le16 name_len;
|
__le16 name_len;
|
||||||
uint8_t name[];
|
uint8_t name[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.3.3 Open File Response
|
* C.3.3.3 Open File Response
|
||||||
@@ -141,7 +141,7 @@ struct isobusfs_fa_openf_res {
|
|||||||
uint8_t handle;
|
uint8_t handle;
|
||||||
uint8_t attributes;
|
uint8_t attributes;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/* B.17 Position mode */
|
/* B.17 Position mode */
|
||||||
/* From the beginning of the file */
|
/* From the beginning of the file */
|
||||||
@@ -168,7 +168,7 @@ struct isobusfs_fa_seekf_req {
|
|||||||
uint8_t handle;
|
uint8_t handle;
|
||||||
uint8_t position_mode;
|
uint8_t position_mode;
|
||||||
__le32 offset;
|
__le32 offset;
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.4.2 Seek File Response
|
* C.3.4.2 Seek File Response
|
||||||
@@ -195,7 +195,7 @@ struct isobusfs_fa_seekf_res {
|
|||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t reserved;
|
uint8_t reserved;
|
||||||
__le32 position;
|
__le32 position;
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.5.2 Read File Request
|
* C.3.5.2 Read File Request
|
||||||
@@ -220,7 +220,7 @@ struct isobusfs_fa_readf_req {
|
|||||||
uint8_t handle;
|
uint8_t handle;
|
||||||
__le16 count;
|
__le16 count;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.5.3 Read File Response (Handle-referenced file)
|
* C.3.5.3 Read File Response (Handle-referenced file)
|
||||||
@@ -250,7 +250,7 @@ struct isobusfs_read_file_response {
|
|||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
__le16 count;
|
__le16 count;
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.5.4 Read Directory Response (Handle-referenced directory)
|
* C.3.5.4 Read Directory Response (Handle-referenced directory)
|
||||||
@@ -280,7 +280,7 @@ struct isobusfs_read_dir_response {
|
|||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
__le16 count;
|
__le16 count;
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.6.2 Write File Request
|
* C.3.6.2 Write File Request
|
||||||
@@ -303,7 +303,7 @@ struct isobusfs_write_file_request {
|
|||||||
uint8_t handle;
|
uint8_t handle;
|
||||||
__le16 count;
|
__le16 count;
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.6.3 Write File Response
|
* C.3.6.3 Write File Response
|
||||||
@@ -333,7 +333,7 @@ struct isobusfs_write_file_response {
|
|||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
__le16 count;
|
__le16 count;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.7.1 Close File Request
|
* C.3.7.1 Close File Request
|
||||||
@@ -354,7 +354,7 @@ struct isobusfs_close_file_request {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t handle;
|
uint8_t handle;
|
||||||
uint8_t reserved[5];
|
uint8_t reserved[5];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.3.7.2 Close File Response
|
* C.3.7.2 Close File Response
|
||||||
@@ -378,7 +378,7 @@ struct isobusfs_close_file_res {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t reserved[6];
|
uint8_t reserved[6];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|
||||||
#endif /* _LINUX_ISOBUS_FS_H */
|
#endif /* _LINUX_ISOBUS_FS_H */
|
||||||
|
|||||||
+10
-10
@@ -32,7 +32,7 @@ struct isobusfs_move_file_request {
|
|||||||
/* Variable length data follows */
|
/* Variable length data follows */
|
||||||
/* uint8_t src_path[]; */
|
/* uint8_t src_path[]; */
|
||||||
/* uint8_t dst_path[]; */
|
/* uint8_t dst_path[]; */
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.2.3 Move File Response
|
* C.4.2.3 Move File Response
|
||||||
@@ -64,7 +64,7 @@ struct isobusfs_move_file_response {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t reserved[5];
|
uint8_t reserved[5];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.3.1 Delete File Request
|
* C.4.3.1 Delete File Request
|
||||||
@@ -87,7 +87,7 @@ struct isobusfs_delete_file_request {
|
|||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
__le16 path_len;
|
__le16 path_len;
|
||||||
uint8_t path[];
|
uint8_t path[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,7 +118,7 @@ struct isobusfs_delete_file_response {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t reserved[5];
|
uint8_t reserved[5];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.4.2 Get File Attributes Request
|
* C.4.4.2 Get File Attributes Request
|
||||||
@@ -139,7 +139,7 @@ struct isobusfs_get_file_attributes_request {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
__le16 pathname_len;
|
__le16 pathname_len;
|
||||||
uint8_t pathname[];
|
uint8_t pathname[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.4.3 Get File Attributes Response
|
* C.4.4.3 Get File Attributes Response
|
||||||
@@ -171,7 +171,7 @@ struct isobusfs_get_file_attributes_response {
|
|||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t attributes;
|
uint8_t attributes;
|
||||||
__le32 file_size;
|
__le32 file_size;
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.5.2 Set File Attributes Request
|
* C.4.5.2 Set File Attributes Request
|
||||||
@@ -194,7 +194,7 @@ struct isobusfs_set_file_attributes_request {
|
|||||||
uint8_t attributes;
|
uint8_t attributes;
|
||||||
__le16 name_length;
|
__le16 name_length;
|
||||||
uint8_t name[]; /* Variable length */
|
uint8_t name[]; /* Variable length */
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.5.3 Set File Attributes Response
|
* C.4.5.3 Set File Attributes Response
|
||||||
@@ -225,7 +225,7 @@ struct isobusfs_set_file_attributes_response {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t reserved[5];
|
uint8_t reserved[5];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.6.2 Get File Date & Time Request
|
* C.4.6.2 Get File Date & Time Request
|
||||||
@@ -246,7 +246,7 @@ struct isobusfs_get_file_date_time_request {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
__le16 name_length;
|
__le16 name_length;
|
||||||
uint8_t name[]; /* Variable length */
|
uint8_t name[]; /* Variable length */
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.4.6.2 Get File Date & Time Response
|
* C.4.6.2 Get File Date & Time Response
|
||||||
@@ -278,6 +278,6 @@ struct isobusfs_get_file_date_time_response {
|
|||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
__le16 date;
|
__le16 date;
|
||||||
__le16 time;
|
__le16 time;
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
#endif /* _LINUX_ISOBUS_FS_H */
|
#endif /* _LINUX_ISOBUS_FS_H */
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ struct isobusfs_va_init_vol_req {
|
|||||||
uint8_t volume_flags;
|
uint8_t volume_flags;
|
||||||
__le16 name_len;
|
__le16 name_len;
|
||||||
uint8_t name[];
|
uint8_t name[];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C.5.2.3 Initialize Volume Response
|
* C.5.2.3 Initialize Volume Response
|
||||||
@@ -62,6 +62,6 @@ struct isobusfs_va_init_vol_res {
|
|||||||
uint8_t tan;
|
uint8_t tan;
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t reserved[4];
|
uint8_t reserved[4];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
#endif /* _ISOBUSFS_CMN_VA_H */
|
#endif /* _ISOBUSFS_CMN_VA_H */
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -473,8 +474,14 @@ static int isobusfs_srv_process_volume_status_request(struct isobusfs_srv_priv *
|
|||||||
|
|
||||||
req_name_len = le16toh(req->name_len);
|
req_name_len = le16toh(req->name_len);
|
||||||
|
|
||||||
pr_debug("< rx volume status request. mode: %x, length: %d, name: %s",
|
/* the volume name has to fit into the received message */
|
||||||
req->volume_mode, req_name_len, req->name);
|
if (req_name_len > msg->len - offsetof(struct isobusfs_cm_vol_stat_req, name)) {
|
||||||
|
pr_warn("volume name length exceeds message length");
|
||||||
|
return ISOBUSFS_ERR_MALFORMED_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("< rx volume status request. mode: %x, length: %zu, name: %.*s",
|
||||||
|
req->volume_mode, req_name_len, (int)req_name_len, req->name);
|
||||||
|
|
||||||
client = isobusfs_srv_get_client_by_msg(priv, msg);
|
client = isobusfs_srv_get_client_by_msg(priv, msg);
|
||||||
if (!client) {
|
if (!client) {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ int isobusfs_srv_fss_send(struct isobusfs_srv_priv *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (time_diff < -ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
if (time_diff < -ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
||||||
pr_warn("too late to send next fs status message: %ld ms",
|
pr_warn("too late to send next fs status message: %" PRId64 " ms",
|
||||||
time_diff);
|
time_diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ int isobusfs_check_current_dir_access(struct isobusfs_srv_priv *priv,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
pr_debug("convert ISOBUS FS path to linux path: %.*s -> %s",
|
pr_debug("convert ISOBUS FS path to linux path: %.*s -> %s",
|
||||||
path_size, path, linux_path);
|
(int)path_size, path, linux_path);
|
||||||
|
|
||||||
ret = isobusfs_cmn_dh_validate_dir_path(linux_path, false);
|
ret = isobusfs_cmn_dh_validate_dir_path(linux_path, false);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -170,10 +170,13 @@ static int isobusfs_srv_dh_current_dir_res(struct isobusfs_srv_priv *priv,
|
|||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -ENOENT:
|
case -ENOENT:
|
||||||
error_code = ISOBUSFS_ERR_FILE_ORPATH_NOT_FOUND;
|
error_code = ISOBUSFS_ERR_FILE_ORPATH_NOT_FOUND;
|
||||||
|
break;
|
||||||
case -ENOMEDIUM:
|
case -ENOMEDIUM:
|
||||||
error_code = ISOBUSFS_ERR_VOLUME_NOT_INITIALIZED;
|
error_code = ISOBUSFS_ERR_VOLUME_NOT_INITIALIZED;
|
||||||
|
break;
|
||||||
case -ENOMEM:
|
case -ENOMEM:
|
||||||
error_code = ISOBUSFS_ERR_OUT_OF_MEM;
|
error_code = ISOBUSFS_ERR_OUT_OF_MEM;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error_code = ISOBUSFS_ERR_OTHER;
|
error_code = ISOBUSFS_ERR_OTHER;
|
||||||
}
|
}
|
||||||
@@ -657,15 +660,22 @@ static int isobusfs_srv_dh_ccd_res(struct isobusfs_srv_priv *priv,
|
|||||||
uint8_t error_code = ISOBUSFS_ERR_SUCCESS;
|
uint8_t error_code = ISOBUSFS_ERR_SUCCESS;
|
||||||
struct isobusfs_srv_client *client;
|
struct isobusfs_srv_client *client;
|
||||||
struct isobusfs_dh_ccd_res res;
|
struct isobusfs_dh_ccd_res res;
|
||||||
|
uint16_t name_len = le16toh(req->name_len);
|
||||||
size_t abs_path_len;
|
size_t abs_path_len;
|
||||||
char *abs_path;
|
char *abs_path;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* the path name has to fit into the received message */
|
||||||
|
if (name_len > msg->len - sizeof(*req)) {
|
||||||
|
pr_warn("path name length exceeds message length");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We assume, the relative path stored in res->name is not longer
|
* We assume, the relative path stored in res->name is not longer
|
||||||
* than absolute path
|
* than absolute path
|
||||||
*/
|
*/
|
||||||
if (req->name_len > ISOBUSFS_SRV_MAX_PATH_LEN) {
|
if (name_len > ISOBUSFS_SRV_MAX_PATH_LEN) {
|
||||||
pr_warn("path too long");
|
pr_warn("path too long");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -684,10 +694,10 @@ static int isobusfs_srv_dh_ccd_res(struct isobusfs_srv_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("< rx change current directory request from client 0x%2x: %.*s. Current directory: %s",
|
pr_debug("< rx change current directory request from client 0x%2x: %.*s. Current directory: %s",
|
||||||
client->addr, req->name_len, req->name, client->current_dir);
|
client->addr, name_len, req->name, client->current_dir);
|
||||||
/* Normalize provided string and convert it to absolute ISOBUS FS path */
|
/* Normalize provided string and convert it to absolute ISOBUS FS path */
|
||||||
ret = isobusfs_convert_relative_to_absolute(priv, client->current_dir,
|
ret = isobusfs_convert_relative_to_absolute(priv, client->current_dir,
|
||||||
(char *)req->name, req->name_len,
|
(char *)req->name, name_len,
|
||||||
abs_path, abs_path_len);
|
abs_path, abs_path_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto process_error;
|
goto process_error;
|
||||||
|
|||||||
+248
-49
@@ -45,6 +45,9 @@ static int isobusfs_srv_add_file(struct isobusfs_srv_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->handles[j].path = strdup(path);
|
priv->handles[j].path = strdup(path);
|
||||||
|
if (!priv->handles[j].path)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
priv->handles[j].fd = fd;
|
priv->handles[j].fd = fd;
|
||||||
priv->handles[j].dir = dir;
|
priv->handles[j].dir = dir;
|
||||||
|
|
||||||
@@ -108,6 +111,28 @@ isobusfs_srv_get_handle(struct isobusfs_srv_priv *priv, int handle)
|
|||||||
return &priv->handles[handle];
|
return &priv->handles[handle];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the handle only when it is in use and has been opened by the
|
||||||
|
* requesting client. Otherwise return NULL.
|
||||||
|
*/
|
||||||
|
static struct isobusfs_srv_handles *
|
||||||
|
isobusfs_srv_get_client_handle(struct isobusfs_srv_priv *priv,
|
||||||
|
struct isobusfs_srv_client *client, int handle)
|
||||||
|
{
|
||||||
|
struct isobusfs_srv_handles *hdl = isobusfs_srv_get_handle(priv, handle);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!hdl || !hdl->path)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(hdl->clients); i++) {
|
||||||
|
if (hdl->clients[i] == client)
|
||||||
|
return hdl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int isobusfs_srv_release_handle(struct isobusfs_srv_priv *priv,
|
static int isobusfs_srv_release_handle(struct isobusfs_srv_priv *priv,
|
||||||
struct isobusfs_srv_client *client,
|
struct isobusfs_srv_client *client,
|
||||||
int handle)
|
int handle)
|
||||||
@@ -137,6 +162,7 @@ static int isobusfs_srv_release_handle(struct isobusfs_srv_priv *priv,
|
|||||||
closedir(hdl->dir);
|
closedir(hdl->dir);
|
||||||
else
|
else
|
||||||
close(hdl->fd);
|
close(hdl->fd);
|
||||||
|
free(hdl->path);
|
||||||
memset(hdl, 0, sizeof(*hdl));
|
memset(hdl, 0, sizeof(*hdl));
|
||||||
priv->handles_count--;
|
priv->handles_count--;
|
||||||
}
|
}
|
||||||
@@ -261,7 +287,7 @@ static int isobusfs_srv_fa_open_file(struct isobusfs_srv_priv *priv,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
pr_debug("convert ISOBUS FS path to linux path: %.*s -> %s",
|
pr_debug("convert ISOBUS FS path to linux path: %.*s -> %s",
|
||||||
path_len, path, linux_path);
|
(int)path_len, path, linux_path);
|
||||||
|
|
||||||
/* Determine open flags based on the requested access type */
|
/* Determine open flags based on the requested access type */
|
||||||
switch (flags & ISOBUSFS_FA_OPEN_MASK) {
|
switch (flags & ISOBUSFS_FA_OPEN_MASK) {
|
||||||
@@ -495,15 +521,119 @@ static int check_access_with_base(const char *base_dir,
|
|||||||
return access(full_path, mode);
|
return access(full_path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISO 11783-13:2021 B.21 and B.15:
|
||||||
|
* Filters directory entries that can be returned in a Read File response
|
||||||
|
* for directory handles while collecting the attributes and name length.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* isobusfs_srv_dir_entry_visible() - Filter visible directory entries.
|
||||||
|
* @handle: Directory handle for access checks.
|
||||||
|
* @entry: Directory entry to inspect.
|
||||||
|
* @file_stat: Stat buffer to fill for the entry.
|
||||||
|
* @entry_name_len: Returns entry name length on success.
|
||||||
|
* @attributes: Returns computed attributes on success.
|
||||||
|
*
|
||||||
|
* ISO 11783-13:2021 B.21 and B.15 define the directory entry layout and
|
||||||
|
* attributes. This helper skips entries that are not readable or too long
|
||||||
|
* and returns attributes for the entry that will be serialized.
|
||||||
|
*
|
||||||
|
* Return: true when the entry should be emitted, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool isobusfs_srv_dir_entry_visible(struct isobusfs_srv_handles *handle,
|
||||||
|
const struct dirent *entry,
|
||||||
|
struct stat *file_stat,
|
||||||
|
size_t *entry_name_len,
|
||||||
|
uint8_t *attributes)
|
||||||
|
{
|
||||||
|
if (check_access_with_base(handle->path, entry->d_name, R_OK) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fstatat(handle->fd, entry->d_name, file_stat, 0) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*entry_name_len = strlen(entry->d_name);
|
||||||
|
if (*entry_name_len > ISOBUSFS_MAX_DIR_ENTRY_NAME_LENGTH)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (S_ISDIR(file_stat->st_mode))
|
||||||
|
*attributes |= ISOBUSFS_ATTR_DIRECTORY;
|
||||||
|
if (check_access_with_base(handle->path, entry->d_name, W_OK) != 0)
|
||||||
|
*attributes |= ISOBUSFS_ATTR_READ_ONLY;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISO 11783-13:2021 C.3.4.2 and C.3.5.2:
|
||||||
|
* Directory offsets/counts are in entries, so advance the directory stream
|
||||||
|
* by visible entries only and report EOF if the entry offset is past the end.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* isobusfs_srv_dir_skip_entries() - Advance directory stream by entries.
|
||||||
|
* @handle: Directory handle to reposition.
|
||||||
|
* @offset: Entry offset to seek to.
|
||||||
|
*
|
||||||
|
* ISO 11783-13:2021 C.3.4.2 and C.3.5.2 state directory offsets/counts are in
|
||||||
|
* entries. This helper advances by visible entries only.
|
||||||
|
*
|
||||||
|
* Return: ISOBUSFS_ERR_SUCCESS or a protocol error code.
|
||||||
|
*/
|
||||||
|
static int isobusfs_srv_dir_skip_entries(struct isobusfs_srv_handles *handle,
|
||||||
|
int32_t offset)
|
||||||
|
{
|
||||||
|
struct dirent *entry;
|
||||||
|
int32_t skipped = 0;
|
||||||
|
|
||||||
|
rewinddir(handle->dir);
|
||||||
|
|
||||||
|
while (skipped < offset && (entry = readdir(handle->dir)) != NULL) {
|
||||||
|
struct stat file_stat;
|
||||||
|
size_t entry_name_len = 0;
|
||||||
|
uint8_t attributes = 0;
|
||||||
|
|
||||||
|
if (!isobusfs_srv_dir_entry_visible(handle, entry, &file_stat,
|
||||||
|
&entry_name_len,
|
||||||
|
&attributes))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
skipped++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > 0 && skipped < offset)
|
||||||
|
return ISOBUSFS_ERR_END_OF_FILE;
|
||||||
|
|
||||||
|
return ISOBUSFS_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isobusfs_srv_read_directory() - Read directory entries into a response buffer.
|
||||||
|
* @handle: Directory handle to read.
|
||||||
|
* @buffer: Output buffer for directory entries.
|
||||||
|
* @max_bytes: Maximum payload bytes allowed in the response.
|
||||||
|
* @max_entries: Maximum number of entries to return.
|
||||||
|
* @readed_size: Returns payload size in bytes.
|
||||||
|
* @entries_read: Returns number of entries serialized.
|
||||||
|
*
|
||||||
|
* ISO 11783-13:2021 C.3.5.2: directory Count is entry based. This function
|
||||||
|
* encodes up to @max_entries entries while respecting @max_bytes.
|
||||||
|
*
|
||||||
|
* Return: ISOBUSFS_ERR_SUCCESS or a protocol error code.
|
||||||
|
*/
|
||||||
static int isobusfs_srv_read_directory(struct isobusfs_srv_handles *handle,
|
static int isobusfs_srv_read_directory(struct isobusfs_srv_handles *handle,
|
||||||
uint8_t *buffer, size_t count,
|
uint8_t *buffer, size_t max_bytes,
|
||||||
ssize_t *readed_size)
|
uint16_t max_entries,
|
||||||
|
ssize_t *readed_size,
|
||||||
|
uint16_t *entries_read)
|
||||||
{
|
{
|
||||||
DIR *dir = handle->dir;
|
DIR *dir = handle->dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* ISO 11783-13:2021 C.3.5.2:
|
||||||
|
* Directory offsets are entry indices, not byte positions.
|
||||||
* Position the directory stream to the previously stored offset (handle->dir_pos).
|
* Position the directory stream to the previously stored offset (handle->dir_pos).
|
||||||
*
|
*
|
||||||
* Handling Changes in Directory Contents:
|
* Handling Changes in Directory Contents:
|
||||||
@@ -519,13 +649,18 @@ static int isobusfs_srv_read_directory(struct isobusfs_srv_handles *handle,
|
|||||||
* either returning an error or restarting from the beginning of the directory, depending
|
* either returning an error or restarting from the beginning of the directory, depending
|
||||||
* on the application's requirements.
|
* on the application's requirements.
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < handle->dir_pos &&
|
if (handle->dir_pos < 0) {
|
||||||
(entry = readdir(dir)) != NULL; i++) {
|
pr_err("Directory handle in invalid state (pos=%d)\n",
|
||||||
/* Iterating to the desired position */
|
handle->dir_pos);
|
||||||
|
return ISOBUSFS_ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = isobusfs_srv_dir_skip_entries(handle, handle->dir_pos);
|
||||||
|
if (ret != ISOBUSFS_ERR_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Directory Entry Layout:
|
* Directory Entry Layout (ISO 11783-13:2021 B.21):
|
||||||
* This loop reads directory entries and encodes them into a buffer.
|
* This loop reads directory entries and encodes them into a buffer.
|
||||||
* Each entry in the buffer follows the format specified in ISO 11783-13:2021.
|
* Each entry in the buffer follows the format specified in ISO 11783-13:2021.
|
||||||
*
|
*
|
||||||
@@ -550,26 +685,23 @@ static int isobusfs_srv_read_directory(struct isobusfs_srv_handles *handle,
|
|||||||
* The handle->dir_pos is incremented after processing each entry, marking
|
* The handle->dir_pos is incremented after processing each entry, marking
|
||||||
* the current position in the directory stream for subsequent reads.
|
* the current position in the directory stream for subsequent reads.
|
||||||
*/
|
*/
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
*entries_read = 0;
|
||||||
|
while ((entry = readdir(dir)) != NULL &&
|
||||||
|
(*entries_read) < max_entries) {
|
||||||
size_t entry_name_len, entry_total_len;
|
size_t entry_name_len, entry_total_len;
|
||||||
__le16 file_date, file_time;
|
__le16 file_date, file_time;
|
||||||
uint8_t attributes = 0;
|
|
||||||
struct stat file_stat;
|
struct stat file_stat;
|
||||||
|
uint8_t attributes = 0;
|
||||||
__le32 size;
|
__le32 size;
|
||||||
|
|
||||||
if (check_access_with_base(handle->path, entry->d_name, R_OK) != 0)
|
if (!isobusfs_srv_dir_entry_visible(handle, entry, &file_stat,
|
||||||
continue; /* Skip this entry if it's not readable */
|
&entry_name_len,
|
||||||
|
&attributes))
|
||||||
if (fstatat(handle->fd, entry->d_name, &file_stat, 0) < 0)
|
|
||||||
continue; /* Skip this entry on error */
|
|
||||||
|
|
||||||
entry_name_len = strlen(entry->d_name);
|
|
||||||
if (entry_name_len > ISOBUSFS_MAX_DIR_ENTRY_NAME_LENGTH)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
entry_total_len = 1 + entry_name_len + 1 + 2 + 2 + 4;
|
entry_total_len = 1 + entry_name_len + 1 + 2 + 2 + 4;
|
||||||
|
|
||||||
if (pos + entry_total_len > count)
|
if (pos + entry_total_len > max_bytes)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
buffer[pos++] = (uint8_t)entry_name_len;
|
buffer[pos++] = (uint8_t)entry_name_len;
|
||||||
@@ -577,10 +709,6 @@ static int isobusfs_srv_read_directory(struct isobusfs_srv_handles *handle,
|
|||||||
memcpy(buffer + pos, entry->d_name, entry_name_len);
|
memcpy(buffer + pos, entry->d_name, entry_name_len);
|
||||||
pos += entry_name_len;
|
pos += entry_name_len;
|
||||||
|
|
||||||
if (S_ISDIR(file_stat.st_mode))
|
|
||||||
attributes |= ISOBUSFS_ATTR_DIRECTORY;
|
|
||||||
if (check_access_with_base(handle->path, entry->d_name, W_OK) != 0)
|
|
||||||
attributes |= ISOBUSFS_ATTR_READ_ONLY;
|
|
||||||
buffer[pos++] = attributes;
|
buffer[pos++] = attributes;
|
||||||
|
|
||||||
file_date = htole16(convert_to_file_date(file_stat.st_mtime));
|
file_date = htole16(convert_to_file_date(file_stat.st_mtime));
|
||||||
@@ -594,9 +722,11 @@ static int isobusfs_srv_read_directory(struct isobusfs_srv_handles *handle,
|
|||||||
size = htole32(file_stat.st_size);
|
size = htole32(file_stat.st_size);
|
||||||
memcpy(buffer + pos, &size, sizeof(size));
|
memcpy(buffer + pos, &size, sizeof(size));
|
||||||
pos += sizeof(size);
|
pos += sizeof(size);
|
||||||
|
(*entries_read)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*readed_size = pos;
|
*readed_size = pos;
|
||||||
|
handle->dir_pos += *entries_read;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,13 +739,19 @@ static int isobusfs_srv_fa_rf_req(struct isobusfs_srv_priv *priv,
|
|||||||
struct isobusfs_srv_client *client;
|
struct isobusfs_srv_client *client;
|
||||||
struct isobusfs_fa_readf_req *req;
|
struct isobusfs_fa_readf_req *req;
|
||||||
ssize_t readed_size = 0;
|
ssize_t readed_size = 0;
|
||||||
|
uint16_t entries_read = 0;
|
||||||
uint8_t error_code = 0;
|
uint8_t error_code = 0;
|
||||||
ssize_t send_size;
|
ssize_t send_size;
|
||||||
|
bool res_allocated = false;
|
||||||
|
size_t alloc_size;
|
||||||
|
size_t max_bytes = 0;
|
||||||
|
uint16_t count = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int count;
|
bool is_dir = false;
|
||||||
|
|
||||||
req = (struct isobusfs_fa_readf_req *)msg->buf;
|
req = (struct isobusfs_fa_readf_req *)msg->buf;
|
||||||
count = le16toh(req->count);
|
count = le16toh(req->count);
|
||||||
|
res = (struct isobusfs_read_file_response *)&res_fail[0];
|
||||||
|
|
||||||
pr_debug("< rx: Read File Request. tan: %d, handle: %d, count: %d",
|
pr_debug("< rx: Read File Request. tan: %d, handle: %d, count: %d",
|
||||||
req->tan, req->handle, count);
|
req->tan, req->handle, count);
|
||||||
@@ -627,17 +763,6 @@ static int isobusfs_srv_fa_rf_req(struct isobusfs_srv_priv *priv,
|
|||||||
* TODO: currently we are not able to detect support transport mode,
|
* TODO: currently we are not able to detect support transport mode,
|
||||||
* so ETP is assumed.
|
* so ETP is assumed.
|
||||||
*/
|
*/
|
||||||
if (count > ISOBUSFS_MAX_DATA_LENGH)
|
|
||||||
count = ISOBUSFS_MAX_DATA_LENGH;
|
|
||||||
|
|
||||||
res = malloc(sizeof(*res) + count);
|
|
||||||
if (!res) {
|
|
||||||
pr_warn("failed to allocate memory");
|
|
||||||
res = (struct isobusfs_read_file_response *)&res_fail[0];
|
|
||||||
error_code = ISOBUSFS_ERR_OUT_OF_MEM;
|
|
||||||
goto send_response;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = isobusfs_srv_get_client_by_msg(priv, msg);
|
client = isobusfs_srv_get_client_by_msg(priv, msg);
|
||||||
if (!client) {
|
if (!client) {
|
||||||
pr_warn("client not found");
|
pr_warn("client not found");
|
||||||
@@ -645,16 +770,42 @@ static int isobusfs_srv_fa_rf_req(struct isobusfs_srv_priv *priv,
|
|||||||
goto send_response;
|
goto send_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle = isobusfs_srv_get_handle(priv, req->handle);
|
handle = isobusfs_srv_get_client_handle(priv, client, req->handle);
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
pr_warn("failed to find file with handle: %x", req->handle);
|
pr_warn("failed to find file with handle: %x", req->handle);
|
||||||
error_code = ISOBUSFS_ERR_FILE_ORPATH_NOT_FOUND;
|
error_code = ISOBUSFS_ERR_FILE_ORPATH_NOT_FOUND;
|
||||||
|
goto send_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine whether to read a file or a directory */
|
/* Determine whether to read a file or a directory */
|
||||||
if (handle->dir) {
|
if (handle->dir) {
|
||||||
ret = isobusfs_srv_read_directory(handle, res->data, count,
|
/* ISO 11783-13:2021 C.3.5.2: count is entry count for directories. */
|
||||||
&readed_size);
|
is_dir = true;
|
||||||
|
max_bytes = ISOBUSFS_MAX_DATA_LENGH;
|
||||||
|
} else {
|
||||||
|
if (count > ISOBUSFS_MAX_DATA_LENGH)
|
||||||
|
count = ISOBUSFS_MAX_DATA_LENGH;
|
||||||
|
max_bytes = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the response is padded to ISOBUSFS_MIN_TRANSFER_LENGH (see below) */
|
||||||
|
alloc_size = sizeof(*res) + max_bytes;
|
||||||
|
if (alloc_size < ISOBUSFS_MIN_TRANSFER_LENGH)
|
||||||
|
alloc_size = ISOBUSFS_MIN_TRANSFER_LENGH;
|
||||||
|
|
||||||
|
res = malloc(alloc_size);
|
||||||
|
if (!res) {
|
||||||
|
pr_warn("failed to allocate memory");
|
||||||
|
res = (struct isobusfs_read_file_response *)&res_fail[0];
|
||||||
|
error_code = ISOBUSFS_ERR_OUT_OF_MEM;
|
||||||
|
goto send_response;
|
||||||
|
}
|
||||||
|
res_allocated = true;
|
||||||
|
|
||||||
|
if (is_dir) {
|
||||||
|
ret = isobusfs_srv_read_directory(handle, res->data, max_bytes,
|
||||||
|
count, &readed_size,
|
||||||
|
&entries_read);
|
||||||
} else {
|
} else {
|
||||||
ret = isobusfs_srv_read_file(handle, res->data, count,
|
ret = isobusfs_srv_read_file(handle, res->data, count,
|
||||||
&readed_size);
|
&readed_size);
|
||||||
@@ -663,7 +814,10 @@ static int isobusfs_srv_fa_rf_req(struct isobusfs_srv_priv *priv,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_code = ret;
|
error_code = ret;
|
||||||
readed_size = 0;
|
readed_size = 0;
|
||||||
} else if (count != 0 && readed_size == 0) {
|
entries_read = 0;
|
||||||
|
} else if (count != 0 &&
|
||||||
|
((is_dir && entries_read == 0) ||
|
||||||
|
(!is_dir && readed_size == 0))) {
|
||||||
error_code = ISOBUSFS_ERR_END_OF_FILE;
|
error_code = ISOBUSFS_ERR_END_OF_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,11 +827,18 @@ send_response:
|
|||||||
ISOBUSFS_FA_F_READ_FILE_RES);
|
ISOBUSFS_FA_F_READ_FILE_RES);
|
||||||
res->tan = req->tan;
|
res->tan = req->tan;
|
||||||
res->error_code = error_code;
|
res->error_code = error_code;
|
||||||
res->count = htole16(readed_size);
|
if (is_dir)
|
||||||
|
res->count = htole16(entries_read);
|
||||||
|
else
|
||||||
|
res->count = htole16(readed_size);
|
||||||
|
|
||||||
send_size = sizeof(*res) + readed_size;
|
send_size = sizeof(*res) + readed_size;
|
||||||
if (send_size < ISOBUSFS_MIN_TRANSFER_LENGH)
|
if (send_size < ISOBUSFS_MIN_TRANSFER_LENGH) {
|
||||||
|
/* fill the unused bytes with 0xff */
|
||||||
|
memset((uint8_t *)res + send_size, 0xff,
|
||||||
|
ISOBUSFS_MIN_TRANSFER_LENGH - send_size);
|
||||||
send_size = ISOBUSFS_MIN_TRANSFER_LENGH;
|
send_size = ISOBUSFS_MIN_TRANSFER_LENGH;
|
||||||
|
}
|
||||||
|
|
||||||
/* send to socket */
|
/* send to socket */
|
||||||
ret = isobusfs_srv_sendto(priv, msg, res, send_size);
|
ret = isobusfs_srv_sendto(priv, msg, res, send_size);
|
||||||
@@ -686,11 +847,12 @@ send_response:
|
|||||||
goto free_res;
|
goto free_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("> tx: Read File Response. Error code: %d (%s), read size: %d",
|
pr_debug("> tx: Read File Response. Error code: %d (%s), read size: %zd",
|
||||||
error_code, isobusfs_error_to_str(error_code), readed_size);
|
error_code, isobusfs_error_to_str(error_code), readed_size);
|
||||||
|
|
||||||
free_res:
|
free_res:
|
||||||
free(res);
|
if (res_allocated)
|
||||||
|
free(res);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,19 +916,56 @@ static int isobusfs_srv_seek(struct isobusfs_srv_priv *priv,
|
|||||||
return ISOBUSFS_ERR_SUCCESS;
|
return ISOBUSFS_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isobusfs_srv_seek_directory() - Seek a directory by entry index.
|
||||||
|
* @handle: Directory handle to seek.
|
||||||
|
* @offset: Entry index to seek to.
|
||||||
|
*
|
||||||
|
* ISO 11783-13:2021 C.3.4.2 defines directory offsets as entry indices.
|
||||||
|
*
|
||||||
|
* Return: ISOBUSFS_ERR_SUCCESS or a protocol error code.
|
||||||
|
*/
|
||||||
static int isobusfs_srv_seek_directory(struct isobusfs_srv_handles *handle,
|
static int isobusfs_srv_seek_directory(struct isobusfs_srv_handles *handle,
|
||||||
int32_t offset)
|
int32_t offset)
|
||||||
{
|
{
|
||||||
DIR *dir = fdopendir(handle->fd);
|
int32_t current_pos = handle->dir_pos;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!dir)
|
if (!handle->dir)
|
||||||
return ISOBUSFS_ERR_OTHER;
|
return ISOBUSFS_ERR_OTHER;
|
||||||
|
|
||||||
rewinddir(dir);
|
/* Check if handle is in valid state */
|
||||||
|
if (current_pos < 0) {
|
||||||
|
pr_err("Cannot seek directory in invalid state (pos=%d)\n",
|
||||||
|
current_pos);
|
||||||
|
return ISOBUSFS_ERR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; i < offset; i++) {
|
/* Validate requested offset */
|
||||||
if (readdir(dir) == NULL)
|
if (offset < 0) {
|
||||||
return ISOBUSFS_ERR_END_OF_FILE;
|
pr_err("Invalid seek offset: %d\n", offset);
|
||||||
|
return ISOBUSFS_ERR_INVALID_REQUESTED_LENGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISO 11783-13:2021 C.3.4.2:
|
||||||
|
* Directory offsets are entry indices. If we fail to seek, restore
|
||||||
|
* the previous entry position since the position shall not change on error.
|
||||||
|
*/
|
||||||
|
ret = isobusfs_srv_dir_skip_entries(handle, offset);
|
||||||
|
if (ret != ISOBUSFS_ERR_SUCCESS) {
|
||||||
|
int restore_ret;
|
||||||
|
|
||||||
|
restore_ret = isobusfs_srv_dir_skip_entries(handle, current_pos);
|
||||||
|
if (restore_ret != ISOBUSFS_ERR_SUCCESS) {
|
||||||
|
pr_warn("Failed to restore directory position after seek failure: %d -> %d",
|
||||||
|
current_pos, restore_ret);
|
||||||
|
/* Directory stream is now in undefined state.
|
||||||
|
* Mark position as invalid.
|
||||||
|
*/
|
||||||
|
handle->dir_pos = -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->dir_pos = offset;
|
handle->dir_pos = offset;
|
||||||
@@ -796,7 +995,7 @@ static int isobusfs_srv_fa_sf_req(struct isobusfs_srv_priv *priv,
|
|||||||
goto send_response;
|
goto send_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle = isobusfs_srv_get_handle(priv, req->handle);
|
handle = isobusfs_srv_get_client_handle(priv, client, req->handle);
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
pr_warn("failed to find handle: %x", req->handle);
|
pr_warn("failed to find handle: %x", req->handle);
|
||||||
error_code = ISOBUSFS_ERR_INVALID_HANDLE;
|
error_code = ISOBUSFS_ERR_INVALID_HANDLE;
|
||||||
|
|||||||
@@ -618,6 +618,12 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case J1939_PGN_ADDRESS_COMMANDED:
|
case J1939_PGN_ADDRESS_COMMANDED:
|
||||||
|
/* 8 bytes NAME + 1 byte new source address */
|
||||||
|
if (ret < 9)
|
||||||
|
break;
|
||||||
|
/* only accept valid unicast addresses */
|
||||||
|
if (dat[8] > J1939_MAX_UNICAST_ADDR)
|
||||||
|
break;
|
||||||
if (!host_is_little_endian())
|
if (!host_is_little_endian())
|
||||||
bswap(dat, 8);
|
bswap(dat, 8);
|
||||||
memcpy(&cmd_name, dat, 8);
|
memcpy(&cmd_name, dat, 8);
|
||||||
|
|||||||
@@ -664,6 +664,7 @@ int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check CANERR_BUFFSZ in lib.h when changing the error frame strings */
|
||||||
static const char *error_classes[] = {
|
static const char *error_classes[] = {
|
||||||
"tx-timeout",
|
"tx-timeout",
|
||||||
"lost-arbitration",
|
"lost-arbitration",
|
||||||
@@ -844,6 +845,13 @@ int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf
|
|||||||
if (!sep)
|
if (!sep)
|
||||||
sep = defsep;
|
sep = defsep;
|
||||||
|
|
||||||
|
/* the size of the provided buffer has to fit CANERR_BUFFSZ (see lib.h) */
|
||||||
|
if (len < CANERR_BUFFSZ) {
|
||||||
|
if (len)
|
||||||
|
buf[0] = 0; /* empty terminated string */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < (int)ARRAY_SIZE(error_classes); i++) {
|
for (i = 0; i < (int)ARRAY_SIZE(error_classes); i++) {
|
||||||
mask = 1 << i;
|
mask = 1 << i;
|
||||||
if (class & mask) {
|
if (class & mask) {
|
||||||
|
|||||||
@@ -238,11 +238,30 @@ int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view);
|
|||||||
* data bytes is limited to 64 to fit terminal output use-cases.
|
* data bytes is limited to 64 to fit terminal output use-cases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf,
|
|
||||||
const char *sep);
|
|
||||||
/*
|
/*
|
||||||
* Creates a CAN error frame output in user readable format.
|
* Creates a CAN error frame output in user readable format.
|
||||||
|
*
|
||||||
|
* buf: buffer for the output string
|
||||||
|
* len: size of the provided buffer buf in bytes (incl. string termination)
|
||||||
|
* sep: separator string between the error classes (NULL => default ",")
|
||||||
|
*
|
||||||
|
* The buffer size len needs to be at least CANERR_BUFFSZ bytes - otherwise
|
||||||
|
* an empty string is returned.
|
||||||
|
*
|
||||||
|
* Calculation of the required buffer size:
|
||||||
|
* The longest error frame content (all error classes and details set) has
|
||||||
|
* 465 characters plus the string termination = 466 bytes. Additionally up
|
||||||
|
* to 9 separators are inserted which results in 466 + 9 * strlen(sep) bytes,
|
||||||
|
* e.g. 466 + 9 * 2 = 484 bytes for "\n\t" (as used in candump).
|
||||||
|
* With CANERR_BUFFSZ = 800 the separator must not exceed 37 characters.
|
||||||
|
*
|
||||||
|
* When the error frame content (the strings in lib.c) is changed, the current
|
||||||
|
* values have to be re-calculated and CANERR_BUFFSZ has to be adapted if needed.
|
||||||
*/
|
*/
|
||||||
|
#define CANERR_BUFFSZ 800
|
||||||
|
|
||||||
|
int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf,
|
||||||
|
const char *sep);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* timespec_diff_ms - calculate timespec difference in milliseconds
|
* timespec_diff_ms - calculate timespec difference in milliseconds
|
||||||
|
|||||||
+12
-23
@@ -58,6 +58,7 @@ static int pty2can(int pty, int socket, struct can_filter *fi,
|
|||||||
static char buf[200];
|
static char buf[200];
|
||||||
char replybuf[10]; /* for answers to received commands */
|
char replybuf[10]; /* for answers to received commands */
|
||||||
unsigned int ptr;
|
unsigned int ptr;
|
||||||
|
unsigned int msglen; /* length of the current SLCAN message w/o '\r' */
|
||||||
struct can_frame frame;
|
struct can_frame frame;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
static unsigned int rxoffset = 0; /* points to the end of an received incomplete SLCAN message */
|
static unsigned int rxoffset = 0; /* points to the end of an received incomplete SLCAN message */
|
||||||
@@ -102,6 +103,7 @@ rx_restart:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msglen = tmp;
|
||||||
cmd = buf[0];
|
cmd = buf[0];
|
||||||
buf[nbytes] = 0;
|
buf[nbytes] = 0;
|
||||||
|
|
||||||
@@ -112,10 +114,11 @@ rx_restart:
|
|||||||
pr_debug("%c", buf[tmp]);
|
pr_debug("%c", buf[tmp]);
|
||||||
pr_debug("\n");
|
pr_debug("\n");
|
||||||
|
|
||||||
|
/* terminate the current SLCAN message to not read the following content */
|
||||||
|
buf[msglen] = 0;
|
||||||
|
|
||||||
/* check for filter configuration commands */
|
/* check for filter configuration commands */
|
||||||
if (cmd == 'm' || cmd == 'M') {
|
if (cmd == 'm' || cmd == 'M') {
|
||||||
buf[9] = 0; /* terminate filter string */
|
|
||||||
ptr = 9;
|
|
||||||
#if 0
|
#if 0
|
||||||
/* the filter is no SocketCAN filter :-( */
|
/* the filter is no SocketCAN filter :-( */
|
||||||
|
|
||||||
@@ -140,14 +143,12 @@ rx_restart:
|
|||||||
/* check for timestamp on/off command */
|
/* check for timestamp on/off command */
|
||||||
if (cmd == 'Z') {
|
if (cmd == 'Z') {
|
||||||
*tstamp = buf[1] & 0x01;
|
*tstamp = buf[1] & 0x01;
|
||||||
ptr = 2;
|
|
||||||
goto rx_out_ack;
|
goto rx_out_ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for 'O'pen command */
|
/* check for 'O'pen command */
|
||||||
if (cmd == 'O') {
|
if (cmd == 'O') {
|
||||||
setsockopt(socket, SOL_CAN_RAW, CAN_RAW_FILTER, fi, sizeof(struct can_filter));
|
setsockopt(socket, SOL_CAN_RAW, CAN_RAW_FILTER, fi, sizeof(struct can_filter));
|
||||||
ptr = 1;
|
|
||||||
*is_open = 1;
|
*is_open = 1;
|
||||||
goto rx_out_ack;
|
goto rx_out_ack;
|
||||||
}
|
}
|
||||||
@@ -155,7 +156,6 @@ rx_restart:
|
|||||||
/* check for 'C'lose command */
|
/* check for 'C'lose command */
|
||||||
if (cmd == 'C') {
|
if (cmd == 'C') {
|
||||||
setsockopt(socket, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
setsockopt(socket, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||||
ptr = 1;
|
|
||||||
*is_open = 0;
|
*is_open = 0;
|
||||||
goto rx_out_ack;
|
goto rx_out_ack;
|
||||||
}
|
}
|
||||||
@@ -164,14 +164,12 @@ rx_restart:
|
|||||||
if (cmd == 'V') {
|
if (cmd == 'V') {
|
||||||
sprintf(replybuf, "V1013\r");
|
sprintf(replybuf, "V1013\r");
|
||||||
tmp = strlen(replybuf);
|
tmp = strlen(replybuf);
|
||||||
ptr = 1;
|
|
||||||
goto rx_out;
|
goto rx_out;
|
||||||
}
|
}
|
||||||
/* check for 'v'ersion command */
|
/* check for 'v'ersion command */
|
||||||
if (cmd == 'v') {
|
if (cmd == 'v') {
|
||||||
sprintf(replybuf, "v1014\r");
|
sprintf(replybuf, "v1014\r");
|
||||||
tmp = strlen(replybuf);
|
tmp = strlen(replybuf);
|
||||||
ptr = 1;
|
|
||||||
goto rx_out;
|
goto rx_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +177,6 @@ rx_restart:
|
|||||||
if (cmd == 'N') {
|
if (cmd == 'N') {
|
||||||
sprintf(replybuf, "N4242\r");
|
sprintf(replybuf, "N4242\r");
|
||||||
tmp = strlen(replybuf);
|
tmp = strlen(replybuf);
|
||||||
ptr = 1;
|
|
||||||
goto rx_out;
|
goto rx_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,29 +184,23 @@ rx_restart:
|
|||||||
if (cmd == 'F') {
|
if (cmd == 'F') {
|
||||||
sprintf(replybuf, "F00\r");
|
sprintf(replybuf, "F00\r");
|
||||||
tmp = strlen(replybuf);
|
tmp = strlen(replybuf);
|
||||||
ptr = 1;
|
|
||||||
goto rx_out;
|
goto rx_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* correctly answer unsupported commands */
|
/* correctly answer unsupported commands */
|
||||||
if (cmd == 'U') {
|
if (cmd == 'U') {
|
||||||
ptr = 2;
|
|
||||||
goto rx_out_ack;
|
goto rx_out_ack;
|
||||||
}
|
}
|
||||||
if (cmd == 'S') {
|
if (cmd == 'S') {
|
||||||
ptr = 2;
|
|
||||||
goto rx_out_ack;
|
goto rx_out_ack;
|
||||||
}
|
}
|
||||||
if (cmd == 's') {
|
if (cmd == 's') {
|
||||||
ptr = 5;
|
|
||||||
goto rx_out_ack;
|
goto rx_out_ack;
|
||||||
}
|
}
|
||||||
if (cmd == 'P' || cmd == 'A') {
|
if (cmd == 'P' || cmd == 'A') {
|
||||||
ptr = 1;
|
|
||||||
goto rx_out_nack;
|
goto rx_out_nack;
|
||||||
}
|
}
|
||||||
if (cmd == 'X') {
|
if (cmd == 'X') {
|
||||||
ptr = 2;
|
|
||||||
if (buf[1] & 0x01)
|
if (buf[1] & 0x01)
|
||||||
goto rx_out_ack;
|
goto rx_out_ack;
|
||||||
else
|
else
|
||||||
@@ -217,16 +208,18 @@ rx_restart:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* catch unknown commands */
|
/* catch unknown commands */
|
||||||
if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R')) {
|
if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R'))
|
||||||
ptr = nbytes - 1;
|
|
||||||
goto rx_out_nack;
|
goto rx_out_nack;
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd & 0x20) /* tiny chars 'r' 't' => SFF */
|
if (cmd & 0x20) /* tiny chars 'r' 't' => SFF */
|
||||||
ptr = 4; /* dlc position tiiid */
|
ptr = 4; /* dlc position tiiid */
|
||||||
else
|
else
|
||||||
ptr = 9; /* dlc position Tiiiiiiiid */
|
ptr = 9; /* dlc position Tiiiiiiiid */
|
||||||
|
|
||||||
|
/* the CAN ID has to fit into the current SLCAN message */
|
||||||
|
if (ptr > msglen)
|
||||||
|
goto rx_out_nack;
|
||||||
|
|
||||||
memset(&frame.data, 0, 8); /* clear data[] */
|
memset(&frame.data, 0, 8); /* clear data[] */
|
||||||
|
|
||||||
if ((cmd | 0x20) == 'r' && buf[ptr] != '0') {
|
if ((cmd | 0x20) == 'r' && buf[ptr] != '0') {
|
||||||
@@ -249,7 +242,6 @@ rx_restart:
|
|||||||
|
|
||||||
buf[ptr] = frame.can_dlc; /* restore following byte */
|
buf[ptr] = frame.can_dlc; /* restore following byte */
|
||||||
frame.can_dlc = 0;
|
frame.can_dlc = 0;
|
||||||
ptr--; /* we have no dlc component in the violation case */
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (!(buf[ptr] >= '0' && buf[ptr] < '9'))
|
if (!(buf[ptr] >= '0' && buf[ptr] < '9'))
|
||||||
@@ -277,9 +269,6 @@ rx_restart:
|
|||||||
goto rx_out_nack;
|
goto rx_out_nack;
|
||||||
frame.data[i] |= tmp;
|
frame.data[i] |= tmp;
|
||||||
}
|
}
|
||||||
/* point to last real data */
|
|
||||||
if (frame.can_dlc)
|
|
||||||
ptr--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = write(socket, &frame, sizeof(frame));
|
ret = write(socket, &frame, sizeof(frame));
|
||||||
@@ -303,8 +292,8 @@ rx_out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if there is another command in this buffer */
|
/* check if there is another command in this buffer */
|
||||||
if (nbytes > ptr + 1) {
|
if (nbytes > msglen + 1) {
|
||||||
for (tmp = 0, ptr++; ptr + tmp < nbytes; tmp++)
|
for (tmp = 0, ptr = msglen + 1; ptr + tmp < nbytes; tmp++)
|
||||||
buf[tmp] = buf[ptr + tmp];
|
buf[tmp] = buf[ptr + tmp];
|
||||||
nbytes = tmp;
|
nbytes = tmp;
|
||||||
goto rx_restart;
|
goto rx_restart;
|
||||||
|
|||||||
Reference in New Issue
Block a user