Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Pfeiffer, Götz
MultiCAN
Commits
ce6ba54e
Commit
ce6ba54e
authored
Nov 13, 2019
by
Franksen, Benjamin
Browse files
scan: implement auto-reconnect
parent
bfd0e911
Changes
3
Hide whitespace changes
Inline
Side-by-side
MultiCAN/src/drivers/scan/ellsi.c
View file @
ce6ba54e
...
...
@@ -186,6 +186,7 @@ struct ellsi_state {
unsigned
unread
;
/* number of as yet unread telegrams in packet */
int
sock
;
/* socket to communicate over */
struct
sockaddr_in
addr
;
/* socket address info */
int
baudrate
;
};
static
ssize_t
ellsi_write
(
void
*
pvt
,
const
struct
can_frame
*
frame
)
{
...
...
@@ -297,7 +298,11 @@ static int ellsi_check(int sock) {
memset
(
&
ack
,
0
,
sizeof
(
ack
));
r
=
recv
(
sock
,
&
ack
,
sizeof
(
ack
),
MSG_WAITALL
);
if
(
r
<
0
)
{
fprintf
(
stderr
,
"ellsi_check: recv failed
\n
"
);
return
r
;
if
(
errno
!=
EAGAIN
&&
errno
!=
EWOULDBLOCK
)
{
errbuf_t
buf
;
fprintf
(
stderr
,
"ellsi_check: recv failed (%s)
\n
"
,
ERRNO_STR
(
buf
));
}
return
r
;
}
debug
(
"ellsi_check: got back magic %#x cmd %#x subcmd %#x payloadLen %d
\n
"
,
ntohl
(
ack
.
header
.
magic
),
...
...
@@ -419,10 +424,54 @@ static int ellsi_add_can_ids(ellsi_state_t *state) {
return
ellsi_check
(
state
->
sock
);
}
static
int
ellsi_connect
(
void
*
pvt
)
{
errbuf_t
buf
;
ellsi_state_t
*
state
=
(
ellsi_state_t
*
)
pvt
;
struct
timeval
tmo
=
{
5
,
0
};
/* connect socket */
if
(
connect
(
state
->
sock
,
(
struct
sockaddr
*
)
&
state
->
addr
,
sizeof
(
struct
sockaddr_in
))
<
0
)
{
fprintf
(
stderr
,
"ellsi_connect: error in socket connect (%s)
\n
"
,
ERRNO_STR
(
buf
));
return
-
1
;
}
/* set recv timout for during connect */
if
(
setsockopt
(
state
->
sock
,
SOL_SOCKET
,
SO_RCVTIMEO
,
&
tmo
,
sizeof
(
tmo
))
<
0
)
{
fprintf
(
stderr
,
"ellsi_connect: error setting socket option SO_RCVTIMEO (%s)
\n
"
,
ERRNO_STR
(
buf
));
return
-
1
;
}
/* initialize protocol */
if
(
ellsi_register
(
state
))
{
return
-
1
;
}
/* configure baudrate */
if
(
ellsi_set_baudrate
(
state
,
state
->
baudrate
))
{
return
-
1
;
}
/* enable all CAN ids */
if
(
ellsi_add_can_ids
(
state
))
{
return
-
1
;
}
/* reset timout for recv operation to zero (default, infinite) */
tmo
.
tv_sec
=
0
;
if
(
setsockopt
(
state
->
sock
,
SOL_SOCKET
,
SO_RCVTIMEO
,
&
tmo
,
sizeof
(
tmo
))
<
0
)
{
fprintf
(
stderr
,
"ellsi_connect: error resetting socket option SO_RCVTIMEO (%s)
\n
"
,
ERRNO_STR
(
buf
));
return
-
1
;
}
return
0
;
}
static
scan_methods_t
methods
=
{
ellsi_read
,
ellsi_write
,
ellsi_dump
,
ellsi_connect
};
int
ellsiConfigPort
(
int
can_port
,
const
char
*
ip_addr
,
int
ip_port
,
int
baudrate
)
{
errbuf_t
buf
;
ellsi_state_t
*
state
=
new
(
ellsi_state_t
);
scan_methods_t
*
methods
;
if
(
!
state
)
{
fprintf
(
stderr
,
"ellsiConfigPort: out of memory
\n
"
);
...
...
@@ -442,41 +491,8 @@ int ellsiConfigPort(int can_port, const char *ip_addr, int ip_port, int baudrate
free
(
state
);
return
-
1
;
}
/* success, connect socket */
if
(
connect
(
state
->
sock
,
(
struct
sockaddr
*
)
&
state
->
addr
,
sizeof
(
struct
sockaddr_in
))
<
0
)
{
fprintf
(
stderr
,
"ellsiConfigPort: error in socket connect (%s)
\n
"
,
ERRNO_STR
(
buf
));
free
(
state
);
return
-
1
;
}
/* success, allocate methods */
methods
=
new
(
scan_methods_t
);
if
(
!
methods
)
{
fprintf
(
stderr
,
"ellsiConfigPort: out of memory
\n
"
);
free
(
state
);
return
-
1
;
}
/* success, fill methods struct */
methods
->
write
=
ellsi_write
;
methods
->
read
=
ellsi_read
;
methods
->
dump
=
ellsi_dump
;
/* initialize protocol */
if
(
ellsi_register
(
state
))
{
fprintf
(
stderr
,
"ellsiConfigPort: error in ellsi_register
\n
"
);
free
(
state
);
return
-
1
;
}
/* configure baudrate */
if
(
ellsi_set_baudrate
(
state
,
baudrate
))
{
fprintf
(
stderr
,
"ellsiConfigPort: error in ellsi_set_baudrate
\n
"
);
free
(
state
);
return
-
1
;
}
/* enable all CAN ids */
if
(
ellsi_add_can_ids
(
state
))
{
fprintf
(
stderr
,
"ellsiConfigPort: error in ellsi_add_can_ids
\n
"
);
free
(
state
);
return
-
1
;
}
/* success, store driver specific configuration */
state
->
baudrate
=
baudrate
;
/* install driver and initialize sci port */
return
scan_config_port
(
can_port
,
state
,
methods
);
return
scan_config_port
(
can_port
,
state
,
&
methods
);
}
MultiCAN/src/drivers/scan/scan.c
View file @
ce6ba54e
...
...
@@ -481,7 +481,6 @@ int scan_config_port(
tid
=
epicsThreadCreate
(
name
,
epicsThreadPriorityMax
-
1
,
epicsThreadGetStackSize
(
epicsThreadStackSmall
),
sci_listen
,
sci_port
);
if
(
tid
)
{
/* done */
res
=
0
;
}
else
{
fprintf
(
stderr
,
"scan_config_port: thread create failed (%s)
\n
"
,
...
...
@@ -512,7 +511,13 @@ static void sci_listen(void *parg) {
errbuf_t
buf
;
struct
sci_port
*
port
=
(
struct
sci_port
*
)
parg
;
port
->
connected
=
1
;
/* initial connection attempt */
if
(
port
->
methods
->
connect
)
{
/* try to reconnect */
port
->
connected
=
(
port
->
methods
->
connect
(
port
->
driver_pvt
)
==
0
);
}
else
{
port
->
connected
=
1
;
}
while
(
1
)
{
if
(
port
->
connected
)
{
...
...
@@ -567,8 +572,15 @@ static void sci_listen(void *parg) {
}
}
else
{
epicsThreadSleep
(
5
.
0
);
/* TODO try to reconnect */
port
->
connected
=
1
;
if
(
port
->
methods
->
connect
)
{
/* try to reconnect */
port
->
connected
=
(
port
->
methods
->
connect
(
port
->
driver_pvt
)
==
0
);
if
(
port
->
connected
)
{
errlogSevPrintf
(
errlogInfo
,
"sci_listen: successfully re-connected port %d
\n
"
,
port
->
port_num
);
}
}
}
}
}
...
...
MultiCAN/src/drivers/scan/scan_driver.h
View file @
ce6ba54e
...
...
@@ -4,6 +4,9 @@
* The driver should implement a configuration/initialization call.
* This should create a socket, allocate struct scan_io_methods,
* fill in appropriate methods, and then call scan_config_port.
* This in turn will call connect method, when port has been set up.
* The connect method is also called when connection has been lost
* and we should re-connect.
* It can also remember private data in the driver_pvt parameter
* passed to scan_config_port.
*
...
...
@@ -21,6 +24,7 @@
typedef
ssize_t
write_t
(
void
*
pvt
,
const
struct
can_frame
*
frame
);
typedef
ssize_t
read_t
(
void
*
pvt
,
struct
can_frame
*
frame
);
typedef
void
dump_t
(
void
*
pvt
);
typedef
int
connect_t
(
void
*
pvt
);
typedef
struct
scan_methods
scan_methods_t
;
...
...
@@ -28,12 +32,13 @@ struct scan_methods {
read_t
*
read
;
/* read a can frame */
write_t
*
write
;
/* write a can frame to a socket */
dump_t
*
dump
;
/* dump private driver info to stdout */
connect_t
*
connect
;
/* driver specific connect actions for this port */
};
/*
* Parameter 'methods' must be allocated by the caller and fully
* initialized. NULL is admissible for 'driver_pvt' but not for
* the methods.
* the methods
, except 'connect', which may be NULL
.
* It is an error if the port is already configured.
*/
extern
int
scan_config_port
(
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment