📄 diag_l2.c
字号:
* We need to tell L1 what protocol we are going to use, because some L1
* interfaces are smart and can support multiple protocols, also L2 needs
* to know later (and asks L1)
*/
int
diag_l2_open(char *dev_name, int id, int L1protocol)
{
int rv;
diag_l2_link_t *d_l2_link;
if (diag_l2_debug & DIAG_DEBUG_OPEN)
fprintf(stderr,"%s: diag_l2_open %s subid %d L1proto %d called\n",
DIAG_MODULE, dev_name, id, L1protocol);
d_l2_link = diag_l2_findlink(dev_name);
if (d_l2_link)
{
/* device open */
if (d_l2_link->diag_l2_l1protocol != L1protocol)
{
/* Wrong L1 protocol, close link */
diag_l2_closelink(d_l2_link->diag_l2_fd);
d_l2_link = NULL;
}
}
if (d_l2_link)
{
/* Device was already open, with correct protocol */
return(d_l2_link->diag_l2_fd);
}
/* Else, create the link */
d_l2_link = calloc(1, sizeof(diag_l2_link_t));
if (d_l2_link == NULL)
{
/* Calloc failed */
return(DIAG_ERR_NOMEM);
}
rv = diag_l1_open(dev_name, id, L1protocol);
if (rv < 0)
{
free(d_l2_link);
return(rv);
}
d_l2_link->diag_l2_fd = rv;
d_l2_link->diag_l2_l1flags = diag_l1_getflags(rv);
d_l2_link->diag_l2_l1type = diag_l1_gettype(rv);
d_l2_link->diag_l2_l1protocol = L1protocol;
strcpy(d_l2_link->diag_l2_name, dev_name);
d_l2_link->diag_l2_id = id;
d_l2_link->next = diag_l2_links;
diag_l2_links = d_l2_link;
return(d_l2_link->diag_l2_fd);
}
/*
* Close a L2 interface, the caller
* must have closed all the connections relating to this or they will
* just get left hanging using resources. We dont kill the L1, it may
* be useful later
*
* XXX, this needs some consideration, one fd can be used for more than
* one L2, so closing by fd isnt appropriate, and so this routine does
* nothing. However, all we have is the FD unless a StartCommunications()
* has been done
*/
diag_l2_close(int fd)
{
diag_l2_link_t *d_l2_link;
if (diag_l2_debug & DIAG_DEBUG_CLOSE)
fprintf(stderr,"%s: diag_l2_close %d called\n",
DIAG_MODULE, fd);
/* XXX */
return(0);
}
/*
* Close/kill a L1link
*/
diag_l2_closelink(int fd)
{
diag_l2_link_t *d_l2_link;
if (diag_l2_debug & DIAG_DEBUG_CLOSE)
fprintf(stderr,"%s: diag_l2_closelink %d called\n",
DIAG_MODULE, fd);
d_l2_link = diag_l2_findlink_byfd(fd);
if (d_l2_link)
{
/* Clear out this link */
diag_l2_rmlink(d_l2_link);
diag_l1_close(fd);
free(d_l2_link);
}
return(0);
}
/*
* startCommunication routine, establishes a connection to
* an ECU by sending fast/slow start (or whatever the protocol is),
* and sets all the timer parameters etc etc
*/
diag_l2_conn_t *
diag_l2_StartCommunications(int fd, int L2protocol, u_int32_t type,
int bitrate, u_int8_t target, u_int8_t source)
{
diag_l2_conn_t *d_l2_conn;
diag_l2_link_t *d_l2_link;
int rv;
int reusing = 0;
u_int16_t flags;
if (diag_l2_debug & DIAG_DEBUG_OPEN)
fprintf(stderr,
"%s: diag_l2_startCommunications fd %d L2proto %d type %x baud %d target 0x%x src 0x%x called\n",
DIAG_MODULE, fd, L2protocol, type ,
bitrate, target&0xff, source&0xff);
/*
* Check connection doesn't exist already, if it does, then use it
* but reinitialise ECU - when checking connection, we look at the
* target and the fd
*/
d_l2_conn = diag_l2_conbyid[target];
while (d_l2_conn)
{
/*
* Find if there's an entry for this FD (or may be talking
* to ECU with this ID on another channel !!
*/
if (d_l2_conn->diag_link->diag_l2_fd == fd)
{
reusing = 1;
break;
}
d_l2_conn = d_l2_conn -> diag_l2_next ;
}
if (d_l2_conn == NULL)
{
/* New connection */
d_l2_conn = calloc(1, sizeof(diag_l2_conn_t));
if (d_l2_conn == NULL)
{
/* Calloc failed */
return(NULL);
}
reusing = 0;
}
d_l2_link = diag_l2_findlink_byfd(fd);
if (d_l2_link == NULL)
return(NULL);
d_l2_conn = calloc(1, sizeof(diag_l2_conn_t));
if (d_l2_conn == NULL)
{
/* Calloc failed */
return(NULL);
}
/* Link to the L1 device info that we keep (name, type, flags, fd) */
d_l2_conn->diag_link = d_l2_link;
/* Note the protocol we want to use */
d_l2_conn->diag_l2_protocol = L2protocol ;
d_l2_conn->diag_l2_type = type ;
d_l2_conn->diag_l2_srcaddr = source ;
d_l2_conn->diag_l2_destaddr = target ;
/*
* We are going to assume that the ISO default timing values
* are general suitable defaults
*/
d_l2_conn->diag_l2_p1min = ISO_14230_TIM_MIN_P1;
d_l2_conn->diag_l2_p1max = ISO_14230_TIM_MAX_P1;
d_l2_conn->diag_l2_p2min = ISO_14230_TIM_MIN_P2;
d_l2_conn->diag_l2_p2max = ISO_14230_TIM_MAX_P2;
d_l2_conn->diag_l2_p2emin = ISO_14230_TIM_MIN_P2E;
d_l2_conn->diag_l2_p2emax = ISO_14230_TIM_MAX_P2E;
d_l2_conn->diag_l2_p3min = ISO_14230_TIM_MIN_P3;
d_l2_conn->diag_l2_p3max = ISO_14230_TIM_MAX_P3;
d_l2_conn->diag_l2_p4min = ISO_14230_TIM_MIN_P4;
d_l2_conn->diag_l2_p4max = ISO_14230_TIM_MAX_P4;
d_l2_conn -> diag_l2_state = DIAG_L2_STATE_CLOSED;
/* Now do protocol version of StartCommunications */
flags = type&0xffff;
rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_startcomms(d_l2_conn, flags, bitrate, target, source);
if (rv < 0)
{
/* Something went wrong */
if (diag_l2_debug & DIAG_DEBUG_OPEN)
fprintf(stderr,"%s: protocol startcomms returned %d\n", DIAG_MODULE, rv);
if (reusing == 0)
free(d_l2_conn);
/* XXX tidy structures */
d_l2_conn = NULL;
}
/*
* note target for quick lookup of connection for received messages
* - unless were re-using a established connection, then no need
* to re-note.
*/
if ( (reusing == 0) && d_l2_conn )
{
/* And attach connection info to our main list */
d_l2_conn->next = diag_l2_connections ;
diag_l2_connections = d_l2_conn ;
/* XXX insert in second linked list */
diag_l2_conbyid[target] = d_l2_conn;
}
if (d_l2_conn)
d_l2_conn -> diag_l2_state = DIAG_L2_STATE_OPEN;
if (diag_l2_debug & DIAG_DEBUG_OPEN)
fprintf(stderr,
"%s: diag_l2_StartComms returns 0x%x\n",
DIAG_MODULE, d_l2_conn);
return (d_l2_conn);
}
/*
* Stop communications - stop talking to an ECU
* - some L2 protocols have an ordered mechanism to do this, others are
* just timeout based (i.e don't send anything for 5 seconds)
*/
int
diag_l2_StopCommunications(diag_l2_conn_t *d_l2_conn)
{
d_l2_conn->diag_l2_state = DIAG_L2_STATE_CLOSING;
/*
* Call protocol close routine, if it exists
*/
if (diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_stopcomms)
(void)diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_stopcomms(d_l2_conn);
d_l2_conn->diag_l2_state = DIAG_L2_STATE_CLOSED;
return(0);
}
/*
* This is really only an ISO14230 protocol function, but the same function
* is used to purely set the timer values on older protocols that don't
* negotiate timer parameters with the ECU thus allowing L3 protocols to
* control inter-byte delays, idle timeouts etc
*/
int
diag_l2_AccessTimingParameters(diag_l2_conn_t *d_l2_conn,
int p2min, int p2max, int p3min, int p3max, int p4min)
{
int rv = 0;
if (diag_l2_debug & DIAG_DEBUG_PROTO)
fprintf(stderr,
"%s: diag_l2_AccessTimingParameters 0x%x called\n",
DIAG_MODULE,d_l2_conn);
if ( diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_atp)
{
rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_atp(
d_l2_conn, p2min, p2max, p3min, p3max, p4min);
}
else
{
/* No protocol specific routine, just set the parameters */
d_l2_conn->diag_l2_p2min = p2min;
d_l2_conn->diag_l2_p2max = p2max;
d_l2_conn->diag_l2_p3min = p3min;
d_l2_conn->diag_l2_p3max = p3max;
d_l2_conn->diag_l2_p4min = p4min;
}
return (rv);
}
/*
* Send a message. This is synchronous.
*/
int
diag_l2_send(diag_l2_conn_t *d_l2_conn, diag_msg_t *msg)
{
int rv;
if (diag_l2_debug & DIAG_DEBUG_WRITE)
fprintf(stderr,
"%s: diag_l2_send 0x%x msg 0x%x msglen %d called\n",
DIAG_MODULE, d_l2_conn, msg, msg->len);
/* Note the time, for calculation of "wakeup" message timeouts */
(void) gettimeofday(&d_l2_conn->diag_l2_lastsend, NULL);
/* Call protocol specific send routine */
rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_send(d_l2_conn, msg);
if (diag_l2_debug & DIAG_DEBUG_WRITE)
fprintf(stderr, "%s: diag_l2_send returns %d\n",
DIAG_MODULE, rv);
return(rv);
}
/*
* Send a message, and wait the appropriate time for a response and return
* that message or an error indicator
* This is synchronous and sleeps and is meant too.
*/
diag_msg_t *
diag_l2_request(diag_l2_conn_t *d_l2_conn, diag_msg_t *msg, int *errval)
{
diag_msg_t *rv;
if (diag_l2_debug & DIAG_DEBUG_WRITE)
fprintf(stderr,
"%s: diag_l2_msg 0x%x 0x%x called\n",
DIAG_MODULE, d_l2_conn, msg);
/* Call protocol specific send routine */
rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_request(d_l2_conn, msg, errval);
if (diag_l2_debug & DIAG_DEBUG_WRITE)
fprintf(stderr, "%s: diag_l2_request returns 0x%x, err %d\n",
DIAG_MODULE, rv, *errval);
return(rv);
}
/*
* Recv a message - will end up calling the callback routine with a message
* or an error if an error has occurred
*
* At the moment this sleeps and the callback will happen before the recv()
* returns - this is not the intention
*
* Timeout is in ms
*/
int
diag_l2_recv(diag_l2_conn_t *d_l2_conn, int timeout,
void (*callback)(void *handle, diag_msg_t *msg), void *handle)
{
int rv;
if (diag_l2_debug & DIAG_DEBUG_READ)
fprintf(stderr,
"%s: diag_l2_recv 0x%x timeout %d called\n",
DIAG_MODULE, d_l2_conn, timeout);
/* Call protocol specific recv routine */
rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_recv(d_l2_conn, timeout, callback, handle);
if (diag_l2_debug & DIAG_DEBUG_READ)
fprintf(stderr, "%s: diag_l2_recv returns %d\n",
DIAG_MODULE, rv);
return(rv);
}
/*
* IOCTL, for setting/asking how various layers are working - similar to
* Unix ioctl()
*/
int diag_l2_ioctl(diag_l2_conn_t *d_l2_conn, int cmd, void *data)
{
struct diag_l2_ic *ic;
int rv = 0;
int fd;
struct diag_l2_data *d;
if (diag_l2_debug & DIAG_DEBUG_IOCTL)
fprintf(stderr,
"%s: diag_l2_ioctl 0x%x cmd %d\n",
DIAG_MODULE, d_l2_conn, cmd);
fd = d_l2_conn->diag_link->diag_l2_fd ;
switch (cmd)
{
case DIAG_IOCTL_GET_L1_TYPE:
*(int *)data = diag_l1_gettype(fd);
break;
case DIAG_IOCTL_GET_L1_FLAGS:
*(int *)data = diag_l1_getflags(fd);
break;
case DIAG_IOCTL_GET_L2_FLAGS:
*(int *)data =
diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_flags;
break;
case DIAG_IOCTL_GET_L2_DATA:
d = (struct diag_l2_data *)data;
d->physaddr = d_l2_conn->diag_l2_physaddr;
d->kb1 = d_l2_conn->diag_l2_kb1;
d->kb2 = d_l2_conn->diag_l2_kb2;
break;
case DIAG_IOCTL_SETSPEED:
ic = (struct diag_l2_ic *)data;
rv = diag_l1_setspeed(fd,
ic->speed, ic->databits, ic->stopbits, ic->parityflag);
break;
case DIAG_IOCTL_INITBUS:
rv = diag_l1_initbus(fd, data);
break;
default:
rv = 0; /* Do nothing, quietly */
break;
}
return(rv);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -