📄 diag_l0_me.c
字号:
if (diag_l0_debug & DIAG_DEBUG_IOCTL)
fprintf(stderr, "%s: device fd %d info %x initbus type %d proto %d\n",
DIAG_MODULE, fd, dev, in->type,
dev ? dev->dev_protocol : -1);
if (!dev)
return(-1);
/* Empty our Receive buffer and wait for idle bus */
(void)diag_os_read( fd, cbuf, sizeof(cbuf), 200);
if (in->type == DIAG_L1_INITBUS_5BAUD)
rv = diag_l0_muleng_slowinit(fd, in, dev);
else
{
/* Do wakeup on first TX */
dev->dev_wakeup = in->type;
dev->dev_state = MULENG_STATE_FASTSTART;
}
return(rv);
}
/*
* Set speed/parity etc
*
* If called by the user then we ignore what he says and use 19200
* 8 none 1
*/
diag_l0_muleng_setspeed(int fd, int speed, int bits,
int stop_bits, int parflag )
{
struct diag_l0_muleng_device *dev;
dev = diag_l0_muleng_finddev(fd); /* Find dev for this fd */
return (diag_os_tty_setup(fd, &dev->dev_ttystate, 19200, 8, 1,
DIAG_L1_PAR_N) );
}
/*
* Routine to read a whole ME message
* which is 14 bytes
*/
diag_l0_muleng_getmsg(int fd, u_int8_t *dp)
{
int offset = 0;
int cnt;
while (offset != 14)
{
cnt = diag_os_read(fd, &dp[offset], 14 - offset, 200);
if (cnt < 0)
return(cnt);
offset += cnt;
}
return(offset);
}
/*
* Safe write routine
*/
diag_l0_muleng_write(int fd, char *dp, int txlen)
{
int cnt, i;
if ( (diag_l0_debug & (DIAG_DEBUG_WRITE|DIAG_DEBUG_DATA)) ==
(DIAG_DEBUG_WRITE|DIAG_DEBUG_DATA) )
{
fprintf(stderr, "%s: device fd %d sending to ME device: ",
DIAG_MODULE, fd);
for (i=0; i<txlen; i++)
fprintf(stderr, "0x%02x ", dp[i] & 0xff);
fprintf(stderr, "\n");
}
/*
* And send it to the interface
*/
while ((cnt = write(fd, dp, txlen)) != txlen)
{
/* Partial write */
if (cnt < 0)
{
/* error */
if (errno != EINTR)
{
perror("write");
fprintf(stderr, "%s: write returned error %d !!\n", DIAG_MODULE, errno);
return(-1);
}
/* errno - EINTR is OK */
}
/* Successfully wrote cnt bytes (or 0 && EINTR), so inc pointers and continue */
txlen -= cnt;
dp += cnt;
}
return(0);
}
/*
* Send a load of data
*
* Returns 0 on success, -1 on failure
*
* This routine will do a fastinit if needed, but all 5 baud inits
* will have been done by the slowinit() code
*/
diag_l0_muleng_send(int fd, int subinterface, char *data, int len)
{
int cnt, i, cmd, rv;
u_int8_t *dp;
u_int8_t txbuf[1024];
int txlen;
u_int8_t kwpbuf[2];
struct diag_l0_muleng_device *dev;
dev = diag_l0_muleng_finddev(fd); /* Find an unused diag block */
if (diag_l0_debug & DIAG_DEBUG_WRITE)
{
fprintf(stderr, "%s: device fd %d send %d bytes protocol %d ",
DIAG_MODULE, fd, len, dev->dev_protocol);
if (diag_l0_debug & DIAG_DEBUG_DATA)
{
int i;
for (i=0; i<len; i++)
fprintf(stderr, "0x%x ", data[i] & 0xff);
fprintf(stderr, "\n");
}
}
if (dev->dev_state == MULENG_STATE_RAW)
{
/* Raw mode, no pretty processing */
rv = diag_l0_muleng_write(fd, data, len);
return (rv);
}
/*
* Figure out cmd to send depending on the hardware we have been
* told to use and whether we need to do fastinit or not
*/
switch (dev->dev_protocol)
{
case DIAG_L1_ISO9141:
cmd = 0x10;
break;
case DIAG_L1_ISO14230:
if (dev->dev_wakeup == DIAG_L1_INITBUS_FAST)
cmd = 0x87;
else
cmd = 0x88;
dev->dev_wakeup = 0; /* We've done the wakeup now */
break;
case DIAG_L1_J1850_VPW:
cmd = 0x02;
break;
case DIAG_L1_J1850_PWM:
cmd = 0x04;
break;
case DIAG_L1_CAN:
cmd = 0x08;
break;
}
/*
* Build message into send buffer, and calculate checksum and
* send it
*/
memset(txbuf, 0, sizeof(txbuf));
txbuf[0] = INTERFACE_ADDRESS;
txbuf[1] = cmd;
txbuf[2] = len;
memcpy(&txbuf[3], data, len);
(void)diag_l0_muleng_txcksum(txbuf);
rv = diag_l0_muleng_write(fd, txbuf, 15);
return(rv);
}
/*
* Get data (blocking), returns number of chars read, between 1 and len
* If timeout is set to 0, this becomes non-blocking
*
* This attempts to read whole message, so if we receive any data, timeout
* is restarted
*
* Messages received from the ME device are 14 bytes long, this will
* always be called with enough "len" to receive the max 11 byte message
* (there are 2 header and 1 checksum byte)
*/
diag_l0_muleng_recv(int fd , int subinterface, char *data, int len, int timeout)
{
int cksum, cnt, i;
struct diag_l0_muleng_device *dev;
dev = diag_l0_muleng_finddev(fd); /* Find an unused diag block */
if (diag_l0_debug & DIAG_DEBUG_READ)
fprintf(stderr,
"%s: fd %d recv upto %d bytes timeout %d, rxlen %d offset %d\n",
DIAG_MODULE, fd, len, timeout, dev->dev_rxlen, dev->dev_rdoffset);
/*
* Deal with 5 Baud init states where first two bytes read by
* user are the keybytes received from the interface, and where
* we are using the interface in pass thru mode on ISO09141 protocols
*/
switch (dev->dev_state)
{
case MULENG_STATE_KWP_SENDKB1:
if (len >= 2)
{
data[0] = dev->dev_kb1;
data[1] = dev->dev_kb2;
dev->dev_state = MULENG_STATE_OPEN;
return (2);
}
else if (len == 1)
{
*data = dev->dev_kb1;
dev->dev_state = MULENG_STATE_KWP_SENDKB2;
return (1);
}
return(0); /* Strange, user asked for 0 bytes */
case MULENG_STATE_KWP_SENDKB2:
if (len >= 1)
{
*data = dev->dev_kb2;
dev->dev_state = MULENG_STATE_OPEN;
return (1);
}
return(0); /* Strange, user asked for 0 bytes */
case MULENG_STATE_RAW:
cnt = diag_os_read(fd, data, len, timeout);
if (diag_l0_debug & DIAG_DEBUG_READ)
fprintf(stderr, "%s: fd %d read %d bytes\n", DIAG_MODULE,
fd, cnt);
return (cnt);
case MULENG_STATE_FASTSTART:
/* Extend timeout for 1st recv */
timeout = 200;
dev->dev_state = MULENG_STATE_OPEN;
/* Drop thru */
default: /* Some other mode */
break;
}
if (dev->dev_rxlen >= 14)
{
/*
* There's a full packet been received, but the user
* has only asked for a few bytes from it previously
* Of the packet, bytes x[2]->x[11] are the network data
* others are header from the ME device
*
* The amount of data remaining to be sent to user is
* as below, -1 because the checksum is at the end
*/
int bufbytes = dev->dev_rxlen - dev->dev_rdoffset - 1;
if (bufbytes <= len)
{
memcpy(data, &dev->dev_rxbuf[dev->dev_rdoffset], bufbytes);
dev->dev_rxlen = dev->dev_rdoffset = 0;
return(bufbytes);
}
else
{
memcpy(data, &dev->dev_rxbuf[dev->dev_rdoffset], len);
dev->dev_rdoffset += len;
return(len);
}
}
/*
* There's either no data waiting, or only a partial read in the
* buffer, read some more
*/
while (dev->dev_rxlen < 14)
{
while ( (cnt = diag_os_read(fd, &dev->dev_rxbuf[dev->dev_rxlen],
14 - dev->dev_rxlen, timeout)) <= 0)
{
if (cnt == DIAG_ERR_TIMEOUT)
return (DIAG_ERR_TIMEOUT);
if (cnt == 0)
{
/* Error, EOF */
fprintf(stderr, "%s: read returned EOF !!\n", DIAG_MODULE);
return(-1);
}
if (errno != EINTR)
{
/* Error, EOF */
fprintf(stderr, "%s: read returned error %d !!\n", DIAG_MODULE, errno);
return(-1);
}
}
dev->dev_rxlen += cnt;
}
/* OK, got whole message */
if (diag_l0_debug & DIAG_DEBUG_READ)
{
int i;
fprintf(stderr,
"%s: fd %d received from ME: ", DIAG_MODULE, fd);
for (i=0; i < dev->dev_rxlen; i++)
fprintf(stderr, "0x%x ",
dev->dev_rxbuf[i] & 0xff);
fprintf(stderr, "\n");
}
/*
* Check the checksum, 2nd byte onward
*/
for (i=1, cnt = 0; i < 13; i++)
cnt += dev->dev_rxbuf[i];
if ((cnt & 0xff) != dev->dev_rxbuf[13])
{
/* XXX, we should deal with this properly rather than just printing a message */
int i;
fprintf(stderr,"Got bad checksum from ME device 0x%x != 0x%x\n",
cnt & 0xff, dev->dev_rxbuf[13]);
fprintf(stderr,"PC Serial port probably out of spec.\n");
fprintf(stderr,"RX Data: ");
for (i=0; i < dev->dev_rxlen; i++)
fprintf(stderr, "0x%x ",
dev->dev_rxbuf[i] & 0xff);
fprintf(stderr, "\n");
}
/*
* Check the type
*/
if (dev->dev_rxbuf[1] == 0x80)
{
/* It's an error message not a data frame */
dev->dev_rxlen = 0;
if (diag_l0_debug & DIAG_DEBUG_READ)
fprintf(stderr,
"%s: fd %d ME returns err 0x%x : s/w v 0x%x i/f cap. 0x%x\n",
DIAG_MODULE, fd, dev->dev_rxbuf[3],
dev->dev_rxbuf[2], dev->dev_rxbuf[4]);
switch (dev->dev_rxbuf[3])
{
case 0x05: /* No ISO response to request */
case 0x07: /* No J1850 response to request */
case 0x0c: /* No KWP response to request */
return(DIAG_ERR_TIMEOUT);
default:
return(-1);
}
/* NOTREACHED */
}
dev->dev_rdoffset = 2; /* Skip the ME header */
/* Copy data to user */
cnt = (len>11) ? 11 : cnt;
cnt = (cnt>(13-dev->dev_rdoffset)) ? 13-dev->dev_rdoffset : cnt;
memcpy(data, &dev->dev_rxbuf[dev->dev_rdoffset], cnt);
dev->dev_rdoffset += cnt;
if (dev->dev_rdoffset == 13)
{
/* End of message, reset pointers */
dev->dev_rxlen = 0;
dev->dev_rdoffset = 0;
}
return(cnt);
}
int
diag_l0_muleng_getflags(int fd)
{
/*
* ISO14230/J1850 protocol does L2 framing, ISO9141 doesn't
*/
struct diag_l0_muleng_device *dev;
int flags;
dev = diag_l0_muleng_finddev(fd); /* Find an unused diag block */
flags = 0;
switch (dev->dev_protocol)
{
case DIAG_L1_J1850_VPW:
case DIAG_L1_J1850_PWM:
flags = DIAG_L1_DOESL2CKSUM;
flags |= DIAG_L1_DOESL2FRAME;
break;
case DIAG_L1_ISO9141:
flags = DIAG_L1_SLOW ;
/* XX does it ? flags |= DIAG_L1_DOESL2CKSUM; */
break;
case DIAG_L1_ISO14230:
flags = DIAG_L1_SLOW | DIAG_L1_FAST | DIAG_L1_PREFFAST;
flags |= DIAG_L1_DOESL2FRAME;
flags |= DIAG_L1_DOESSLOWINIT;
flags |= DIAG_L1_DOESL2CKSUM;
break;
}
if (diag_l0_debug & DIAG_DEBUG_PROTO)
fprintf(stderr,
"%s: getflags fd %d proto %d flags 0x%x\n",
DIAG_MODULE, fd, dev->dev_protocol, flags);
return( flags );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -