BOROSOFTWAREAll work →
scantool/diag_l0_me.c 961 lines
1/*
2 * freediag - Vehicle Diagnostic Utility
3 *
4 *
5 * Copyright (C) 2001 Richard Almeida & Ibex Ltd ([email protected])
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 *************************************************************************
22 *
23 * Diag, Layer 0, Interface for Multiplex Engineering interface
24 * Supports #T16 interface only. Other interfaces need special
25 * code to read multi-frame messages with > 3 frames (and don't
26 * support all interface types)
27 *
28 * http://www.multiplex-engineering.com
29 *
30 */
31
32#include <assert.h>
33#include <stdlib.h>
34#include <stdint.h>
35#include <stdio.h>
36#include <string.h>
37
38#include "diag.h"
39#include "diag_cfg.h"
40#include "diag_err.h"
41#include "diag_iso14230.h" //for TesterPresent SID
42#include "diag_tty.h"
43#include "diag_l0.h"
44#include "diag_l1.h"
45
46
47#define ME_DEFAULT_ADDRESS 0x38
48#define ME_ADDR_SN "meaddr"
49#define ME_ADDR_DESCR "ME device address"
50
51extern const struct diag_l0 diag_l0_me;
52
53/*
54 * Baud rate table for converting single byte value from interface to
55 * baud rate. Note the single byte value is count in 2.5microseconds for
56 * receiving a bit of the 0x55
57 */
58static const unsigned int me_baud_table[] = { 0, 400000, 200000, 133333, 100000, 80000,
59 66666, 57142, 50000, 44444,
60 /* 10 */ 40000, 36363, 33333, 30769, 28571, 26666,
61 25000, 23529, 22222, 21052,
62 /* 20 */ 19200, 19200, 18181, 17391, 16666, 16000,
63 15384, 14814, 14285, 13793,
64 /* 30 */ 13333, 12903, 12500, 12121, 11764, 11428,
65 11111, 10400, 10400, 10400,
66 /* 40 */ 10400, 9600, 9600, 9600, 9600, 8888, 8695, 8510, 8333, 8163,
67 /* 50 */ 8000, 7843, 7692, 7547, 7407, 7272, 7142, 7017, 6896, 6779,
68 /* 60 */ 6666, 6557, 6451, 6349, 0, 6153, 6060, 5970, 5882, 5797,
69 /* 70 */ 5714, 5633, 5555, 5479, 5405, 5333, 5263, 5194, 5128, 5063,
70 /* 80 */ 5000, 4800, 4800, 4800, 4800, 4800, 4800, 4597, 4545, 4494,
71 /* 90 */ 4444, 4395, 4347, 4301, 4255, 4210, 4166, 4123, 4081, 4040,
72 /* 100 */ 4000, 3960, 3921, 3883, 3846, 3809, 3600, 3600, 3600, 3600,
73 /* 110 */ 3600, 3600, 3600, 3600, 3600, 3478, 3448, 3418, 3389, 3361,
74 /* 120 */ 3333, 3305, 3278, 3252, 3225, 3200, 3174, 3149, 3125, 3100,
75 /* 130 */ 3076, 3053, 3030, 3007, 2985, 2962, 2941, 2919, 2898, 2877,
76 /* 140 */ 2857, 2836, 2816, 2797, 2777, 2758, 2739, 2721, 2702, 2684,
77 /* 150 */ 2666, 2649, 2631, 2614, 2597, 2580, 2564, 2547, 2531, 2515,
78 /* 160 */ 2500, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400,
79 /* 170 */ 2400, 2400, 2400, 2400, 2298, 2285, 2272, 2259, 2247, 2234,
80 /* 180 */ 2222, 2209, 2197, 2185, 2173, 2162, 2150, 2139, 2127, 2116,
81 /* 190 */ 2105, 2094, 2083, 2072, 2061, 2051, 2040, 2030, 2020, 2010,
82 /* 200 */ 2000, 1990, 1980, 1970, 1960, 1951, 1941, 1932, 1923, 1913,
83 /* 210 */ 1904, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800,
84 /* 220 */ 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800,
85 /* 230 */ 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800,
86 /* 240 */ 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800, 1800,
87 /* 250 */ 1600, 1593, 1587, 1581, 1574, 1568, };
88
89/* Response message types */
90#define ME_RESP_14230 0x01 // Message from ISO14230 (KWP)
91#define ME_RESP_ERROR 0x80 // Error occurred (See Error Response Message Below)
92#define ME_RESP_ISO 0x81 // Message from ISO-9141-2 or ISO-14230 (KWP)
93#define ME_RESP_VPW 0x82 // Message from J1850 VPW
94#define ME_RESP_PWM 0x84 // Message from J1850 PWM
95#define ME_RESP_CAN 0x88 // Message from CAN
96
97/* interface error codes */
98static const struct {
99 int code;
100 const char *str;
101} me_errs[] = {
102 {0x00, "Request Message command not implemented in this interface."},
103 {0x01, "Request Message command is not used."},
104 {0x02, "Request Message sum check error."},
105 {0x03, "ISO or KWP - No sync or incorrect sync."},
106 {0x04, "Incorrect ISO inverted address received."},
107 {0x05, "No ISO response to the request message."},
108 {0x06, "J1850 message received was not a diagnostic message."},
109 {0x07, "No J1850 response to the request message."},
110 {0x08, "ISO checksum error detected in response message."},
111 {0x09, "J1850 CRC error detected in response message."},
112 {0x0A, "Unused"},
113 {0x0B, "KWP baud rate too slow"},
114 {0x0C, "No KWP response to the request message."},
115 {0x0D, "KWP incorrect inverted address returned by car"},
116 {0x0E, "PWM pulse width is too long"},
117 {0x0F, "Incorrect variable response counter"},
118 {0x10, "ISO not enabled"},
119 {0x11, "J1850 VPW not enabled"},
120 {0x12, "J1850 PWM not enabled"},
121 {0x13, "KWP not enabled"},
122 {0x14, "VW Pass-through mode not enabled"},
123 {0x15, "Repeated arbitration errors"},
124 {0x16, "CAN did not respond to request"},
125 {0x17, "CAN core command had a bad command count"},
126 {0x20, "CAN destination address byte error"},
127 {0x21, "CAN command byte error"},
128 {0x22, "CAN byte count byte error"},
129 {0x23, "CAN sum check byte error"},
130 {0x24, "CAN RS232 receive message - 100ms timeout error"},
131 {0x25, "CAN Configuration command address error"},
132 {0x26, "CAN stop bit error"},
133 {0x27, "CAN transmit message - 100ms timeout error"},
134 {0x28, "CAN transmit error"},
135 {0x29, "CAN transmit lost arbitration"},
136 {0x2A, "CAN receive message - 100ms timeout error"},
137 {0x2B, "CAN Mode Request - 100ms timeout error"},
138 {0x2C, "CAN invalid CAN byte count error"},
139 {0xF1, "Unimplemented USB command attempted"},
140 {0xF2, "Legacy (Non CAN) bus hardware did not respond to USB request"},
141 {0xF3, "CAN hardware did not respond to USB request"}
142};
143
144static const char *me_geterr(const int err) {
145 unsigned i;
146 for (i = 0; i < ARRAY_SIZE(me_errs); i++) {
147 if (me_errs[i].code == err) {
148 return me_errs[i].str;
149 }
150 }
151
152 return "[undefined]";
153}
154
155struct muleng_device {
156 int protocol;
157 int dev_wakeup; /* Contains wakeup type for next packet */
158 int dev_state; /* State for 5 baud startup stuff */
159 uint8_t dev_kb1; /* KB1/KB2 for 5 baud startup stuff */
160 uint8_t dev_kb2;
161
162 uint8_t dev_rxbuf[14]; /* Receive buffer */
163 unsigned dev_rxlen; /* Length of data in buffer (complete response from ME) */
164 unsigned resp_len; /* length of actual bus message, including its checksum (but not the ME response checksum) */
165 unsigned dev_rdoffset; /* Offset to read from to */
166
167 struct cfgi port; /** serial port */
168 struct cfgi dev_addr; /** ME device address; default is 0x38. */
169 ttyp *tty_int; /** handle for tty stuff */
170};
171
172#define MULENG_STATE_CLOSED 0x00
173
174/* 5 baud init was successful, need to report keybytes on first recv() */
175#define MULENG_STATE_KWP_SENDKB1 0x01
176#define MULENG_STATE_KWP_SENDKB2 0x02
177
178#define MULENG_STATE_RAW 0x10 /* Open and working in Passthru mode */
179
180#define MULENG_STATE_FASTSTART 0x18 /* 1st recv() after fast init */
181#define MULENG_STATE_OPEN 0x20 /* Open and working */
182
183
184static void muleng_close(struct diag_l0_device *dl0d);
185
186/*
187 * Init must be callable even if no physical interface is
188 * present, it's just here for the code here to initialise its
189 * variables etc
190 */
191static int muleng_init(void) {
192/* Global init flag */
193 static int muleng_initdone=0;
194
195 if (muleng_initdone) {
196 return 0;
197 }
198
199 muleng_initdone = 1;
200
201 return 0;
202}
203
204/* Put in the ME checksum at the correct place */
205static int muleng_txcksum(uint8_t *data) {
206 uint8_t cksum;
207
208 cksum = diag_cks1(&data[1], 12);
209 data[14] = cksum;
210 return cksum;
211}
212
213/* Copied from diag_l2_proto_j1850_crc() in diag_l2_saej1850.c; I don't want L0 code to
214 * rely on L2 functions so there is some amount of code duplication. According to comments
215 * this algo is from B. Roadman's website.
216 */
217static uint8_t j1850_crc(uint8_t *msg_buf, int nbytes) {
218 uint8_t crc_reg=0xff,poly,i,j;
219 uint8_t *byte_point;
220 uint8_t bit_point;
221
222 for (i=0, byte_point=msg_buf; i<nbytes; ++i, ++byte_point) {
223 for (j=0, bit_point=0x80 ; j<8; ++j, bit_point>>=1) {
224 if (bit_point & *byte_point) { // case for new bit = 1
225 if (crc_reg & 0x80) {
226 poly=1; // define the polynomial
227 } else {
228 poly = 0x1c;
229 }
230 crc_reg= ( (crc_reg << 1) | 1) ^ poly;
231 } else { // case for new bit = 0
232 poly=0;
233 if (crc_reg & 0x80) {
234 poly = 0x1d;
235 }
236 crc_reg= (crc_reg << 1) ^ poly;
237 }
238 }
239 }
240 return ~crc_reg; // Return CRC
241}
242
243/* parse an ME response buffer, and return the actual payload length (including checksum / CRC byte) by
244 * trying to find the longest message with a valid checksum or CRC.
245 * Limitations :
246 * 1- ISO payloads that really have 0 as their checksum will be reported as maximum-length, i.e.
247 * the checksum for [0xFF 0x01] is 0; but the function will report the actual message is
248 * [FF 01 00 .... 00] which also has a valid checksum.
249 *
250 * 2- J1850 CRC is less problematic; not sure if there can be collisions such as
251 * [X1 ... Xn] where Xn is the valid CRC when calculated on X1..X(n-1) , while at the same time respecting
252 * [X1 ... Xn Z1 Z2 .. Zn] where Z1..Zn are 0, and that the CRC of X1...Z(n-1) is 0x00 !?
253 */
254static unsigned me_guess_rxlen(uint8_t *buf) {
255 /* Response format :
256 * buf[1]=type; buf[2]: payload, padded with 0 bytes at the end; buf[13] : ME checksum (ignored here)
257 */
258 unsigned len;
259
260 for (len=10; len > 0; len--) {
261 uint8_t msg_type = buf[1];
262 // verify if checksum/CRC works with this length:
263
264 switch (msg_type) {
265 case ME_RESP_PWM:
266 case ME_RESP_VPW:
267 if (j1850_crc(&buf[2], len) == buf[2 + len]) {
268 return len + 1;
269 }
270 break;
271 case ME_RESP_14230:
272 case ME_RESP_ISO:
273 if (diag_cks1(&buf[2], len) == buf[2 + len]) {
274 return len + 1;
275 }
276 break;
277 default:
278 break;
279 }
280
281 // was the last byte 0, therefore possibly just padding ?
282 if (buf[2+len] != 0) {
283 //not padding : can't continue.
284 break;
285 }
286 }
287 // no properly framed message found... let L2/L3 pick up the pieces
288 return 11;
289}
290
291/*
292 * Open the diagnostic device, returns a file descriptor
293 * records original state of term interface so we can restore later
294 */
295static int muleng_open(struct diag_l0_device *dl0d, int iProtocol) {
296 int rv;
297 struct muleng_device *dev;
298 struct diag_serial_settings set;
299
300 muleng_init();
301
302 assert(dl0d);
303 dev = dl0d->l0_int;
304
305 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
306 FLFMT "open port %s L1proto %d\n",
307 FL, dev->port.val.str, iProtocol);
308
309 dev->protocol = iProtocol;
310
311 /* try to open TTY */
312 dev->tty_int = diag_tty_open(dev->port.val.str);
313 if (dev->tty_int == NULL) {
314 return diag_iseterr(DIAG_ERR_GENERAL);
315 }
316
317 /* And set to 19200 baud , 8N1 */
318
319 set.speed = 19200;
320 set.databits = diag_databits_8;
321 set.stopbits = diag_stopbits_1;
322 set.parflag = diag_par_n;
323
324 if ((rv=diag_tty_setup(dev->tty_int, &set))) {
325 muleng_close(dl0d);
326 return diag_ifwderr(rv);
327 }
328
329 /* And set DTR high and RTS low to power the device */
330 if ((rv=diag_tty_control(dev->tty_int, 1, 0))) {
331 muleng_close(dl0d);
332 return diag_ifwderr(rv);
333 }
334
335 diag_tty_iflush(dev->tty_int); /* Flush unread input */
336 dl0d->opened = 1;
337
338 return 0;
339}
340
341
342static int muleng_new(struct diag_l0_device *dl0d) {
343 struct muleng_device *dev;
344 int rv;
345
346 assert(dl0d);
347
348 rv = diag_calloc(&dev, 1);
349 if (rv != 0) {
350 return diag_ifwderr(rv);
351 }
352
353 dl0d->l0_int = dev;
354
355 rv = diag_cfgn_tty(&dev->port);
356 if (rv != 0) {
357 free(dev);
358 return diag_ifwderr(rv);
359 }
360 dev->port.next = &dev->dev_addr;
361
362 if (diag_cfgn_u8(&dev->dev_addr, ME_DEFAULT_ADDRESS, ME_DEFAULT_ADDRESS)) {
363 free(dev);
364 return diag_iseterr(DIAG_ERR_GENERAL);
365 }
366 dev->dev_addr.shortname = ME_ADDR_SN;
367 dev->dev_addr.descr = ME_ADDR_DESCR;
368
369 dev->dev_addr.next = NULL;
370
371 return 0;
372}
373
374static void muleng_del(struct diag_l0_device *dl0d) {
375 struct muleng_device *dev;
376
377 assert(dl0d);
378
379 dev = dl0d->l0_int;
380 if (!dev) {
381 return;
382 }
383
384 diag_cfg_clear(&dev->port);
385 diag_cfg_clear(&dev->dev_addr);
386 free(dev);
387 return;
388}
389
390static struct cfgi *muleng_getcfg(struct diag_l0_device *dl0d) {
391 struct muleng_device *dev;
392 if (dl0d == NULL) {
393 return diag_pseterr(DIAG_ERR_BADCFG);
394 }
395
396 dev = dl0d->l0_int;
397 return &dev->port;
398}
399
400
401static void muleng_close(struct diag_l0_device *dl0d) {
402 if (!dl0d) {
403 return;
404 }
405 struct muleng_device *dev = dl0d->l0_int;
406
407 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_CLOSE, DIAG_DBGLEVEL_V,
408 FLFMT "link %p closing\n", FL, (void *)dl0d);
409
410 diag_tty_close(dev->tty_int);
411 dev->tty_int = NULL;
412
413 dl0d->opened = 0;
414
415 return;
416}
417
418/*
419 * Safe write routine; return 0 on success
420 */
421static int muleng_write(struct diag_l0_device *dl0d, const void *dp, size_t txlen) {
422 struct muleng_device *dev = dl0d->l0_int;
423
424 if (txlen == 0) {
425 return diag_iseterr(DIAG_ERR_BADLEN);
426 }
427
428 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V, dp, txlen,
429 FLFMT "device link %p sending to ME device: ",
430 FL, (void *)dl0d);
431
432 /*
433 * And send it to the interface
434 */
435 if (diag_tty_write(dev->tty_int, dp, txlen) != (int) txlen) {
436 fprintf(stderr, FLFMT "muleng_write error!!\n", FL);
437 return diag_iseterr(DIAG_ERR_GENERAL);
438 }
439
440 return 0;
441}
442
443
444/*
445 * Do 5 Baud initialisation
446 *
447 * In the case of ISO9141 we operate in the interface's "raw" mode
448 * (VAG compatibility mode), in 14230 we do a slow init and send
449 * a tester present message
450 */
451static int muleng_slowinit( struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in,
452 struct muleng_device *dev) {
453 /*
454 * Slow init
455 * Build message into send buffer, and calculate checksum
456 */
457 uint8_t txbuf[15];
458 uint8_t rxbuf[15];
459 int rv;
460 unsigned int baud;
461
462 memset(txbuf, 0, sizeof(txbuf));
463 txbuf[0] = dev->dev_addr.val.u8;
464
465 switch (dev->protocol) {
466 case DIAG_L1_ISO9141:
467 txbuf[1] = 0x20; /* Raw mode 5 baud init */
468 txbuf[2] = in->addr;
469 break;
470 case DIAG_L1_ISO14230:
471 txbuf[1] = 0x85;
472 txbuf[2] = 0x01; /* One byte message */
473 txbuf[3] = DIAG_KW2K_SI_TP; /* tester present */
474 break;
475 }
476
477 /*
478 * Calculate the checksum, and send the request
479 */
480 (void)muleng_txcksum(txbuf);
481 if ((rv = muleng_write(dl0d, txbuf, 15))) {
482 return diag_ifwderr(rv);
483 }
484
485 /*
486 * Get answer
487 */
488 switch (dev->protocol) {
489 case DIAG_L1_ISO9141:
490 /*
491 * This is raw mode, we should get a single byte back
492 * with the timing interval, then we need to change speed
493 * to match that speed. Remember it takes 2 seconds to send
494 * the 10 bit (1+8+1) address at 5 baud
495 */
496 rv = diag_tty_read(dev->tty_int, rxbuf, 1, 2350);
497 if (rv != 1) {
498 return diag_iseterr(DIAG_ERR_GENERAL);
499 }
500
501 if (rxbuf[0] == 0x40) {
502 /* Problem ..., got an error message */
503
504 diag_tty_iflush(dev->tty_int); /* Empty the receive buffer */
505
506 return diag_iseterr(DIAG_ERR_GENERAL);
507 }
508 baud = me_baud_table[rxbuf[0]];
509
510 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_PROTO, DIAG_DBGLEVEL_V,
511 FLFMT "device link %p setting baud to %u\n",
512 FL, (void *)dl0d, baud);
513
514 if (baud) {
515 struct diag_serial_settings set;
516 set.speed = baud;
517 set.databits = diag_databits_8;
518 set.stopbits = diag_stopbits_1;
519 set.parflag = diag_par_n;
520
521 /* And set the baud rate */
522 diag_tty_setup(dev->tty_int, &set);
523 }
524
525 dev->dev_state = MULENG_STATE_RAW;
526
527 break;
528 case DIAG_L1_ISO14230:
529 /* XXX
530 * Should get an ack back, rather than an error response
531 */
532 if ((rv = diag_tty_read(dev->tty_int, rxbuf, 14, 200)) < 0) {
533 return diag_ifwderr(rv);
534 }
535
536 if (rxbuf[1] == ME_RESP_ERROR) {
537 return diag_iseterr(DIAG_ERR_GENERAL);
538 }
539
540 /*
541 * Now send the "get keybyte" request, and wait for
542 * response
543 */
544 memset(txbuf, 0, sizeof(txbuf));
545 txbuf[0] = dev->dev_addr.val.u8;
546 txbuf[1] = 0x86;
547 (void)muleng_txcksum(txbuf);
548 rv = muleng_write(dl0d, txbuf, 15);
549 if (rv < 0) {
550 return diag_ifwderr(rv);
551 }
552
553 if ((rv = diag_tty_read(dev->tty_int, rxbuf, 14, 200)) < 0) {
554 return diag_ifwderr(rv);
555 }
556
557 if (rxbuf[1] == ME_RESP_ERROR) { /* Error */
558 return diag_iseterr(DIAG_ERR_ECUSAIDNO);
559 }
560 /*
561 * Store the keybytes
562 */
563 dev->dev_kb1 = rxbuf[2];
564 dev->dev_kb2 = rxbuf[3];
565 /*
566 * And tell read code to report the keybytes on first read
567 */
568 dev->dev_state = MULENG_STATE_KWP_SENDKB1;
569 break;
570 }
571
572
573 return rv;
574}
575
576/*
577 * Do wakeup on the bus
578 *
579 * We do this by noting a wakeup needs to be done for the next packet for
580 * fastinit, and doing slowinit now
581 */
582static int muleng_initbus(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in) {
583 int rv = 0;
584 struct muleng_device *dev;
585
586 dev = (struct muleng_device *)dl0d->l0_int;
587
588 if (!dev) {
589 return diag_iseterr(DIAG_ERR_GENERAL);
590 }
591
592 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_IOCTL, DIAG_DBGLEVEL_V,
593 FLFMT "device link %p info %p initbus type %d proto %d\n",
594 FL, (void *)dl0d, (void *)dev, in->type, dev->protocol);
595
596 diag_tty_iflush(dev->tty_int); /* Empty the receive buffer, wait for idle bus */
597
598 if (in->type == DIAG_L1_INITBUS_5BAUD) {
599 rv = muleng_slowinit(dl0d, in, dev);
600 } else {
601 /* Do wakeup on first TX */
602 dev->dev_wakeup = in->type;
603 dev->dev_state = MULENG_STATE_FASTSTART;
604 }
605
606 return rv;
607}
608
609/*
610 * Send a load of data
611 *
612 * Returns 0 on success, -1 on failure
613 *
614 * This routine will do a fastinit if needed, but all 5 baud inits
615 * will have been done by the slowinit() code
616 */
617static int muleng_send(struct diag_l0_device *dl0d,
618 const void *data, size_t len) {
619 int rv;
620 uint8_t cmd;
621
622 uint8_t txbuf[MAXRBUF];
623 struct muleng_device *dev;
624
625 dev = (struct muleng_device *)dl0d->l0_int;
626
627 if (len == 0) {
628 return diag_iseterr(DIAG_ERR_BADLEN);
629 }
630
631 if (len > 255) {
632 fprintf(stderr, FLFMT "_send : requesting too many bytes !\n", FL);
633 return diag_iseterr(DIAG_ERR_BADLEN);
634 }
635
636 DIAG_DBGMDATA(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V, data, len,
637 FLFMT "device link %p send %ld bytes protocol %d ",
638 FL, (void *)dl0d, (long)len, dev->protocol);
639
640 if (dev->dev_state == MULENG_STATE_RAW) {
641 /* Raw mode, no pretty processing */
642 rv = muleng_write(dl0d, data, len);
643 return rv;
644 }
645
646 /*
647 * Figure out cmd to send depending on the hardware we have been
648 * told to use and whether we need to do fastinit or not
649 */
650 switch (dev->protocol) {
651 case DIAG_L1_ISO9141:
652 cmd = 0x10;
653 break;
654
655 case DIAG_L1_ISO14230:
656 if (dev->dev_wakeup == DIAG_L1_INITBUS_FAST) {
657 cmd = 0x87;
658 } else {
659 cmd = 0x88;
660 }
661 dev->dev_wakeup = 0; /* We've done the wakeup now */
662 break;
663
664 case DIAG_L1_J1850_VPW:
665 cmd = 0x02;
666 break;
667
668 case DIAG_L1_J1850_PWM:
669 cmd = 0x80;
670 break;
671
672 case DIAG_L1_CAN:
673 cmd = 0x08;
674 break;
675 default:
676 fprintf(stderr, FLFMT "Command never initialised.\n", FL);
677 return diag_iseterr(DIAG_ERR_PROTO_NOTSUPP);
678 }
679
680 /*
681 * Build message into send buffer, and calculate checksum and
682 * send it
683 */
684 memset(txbuf, 0, sizeof(txbuf));
685
686 txbuf[0] = dev->dev_addr.val.u8;
687 txbuf[1] = cmd;
688 txbuf[2] = (uint8_t) len;
689 memcpy(&txbuf[3], data, len);
690
691 (void)muleng_txcksum(txbuf);
692 rv = muleng_write(dl0d, txbuf, 15);
693
694 return rv;
695}
696
697/*
698 * Get data (blocking), returns number of bytes read, between 1 and len
699 * If timeout is set to 0, this becomes non-blocking
700 *
701 * This attempts to read whole message, so if we receive any data, timeout
702 * is restarted
703 *
704 * Messages received from the ME device are 14 bytes long, this will
705 * always be called with enough "len" to receive the max 11 byte message
706 * (there are 2 header and 1 checksum byte)
707
708 * Since messages are padded up to 11 bytes, this also attempts to guess
709 * the response length by
710 * finding the last non-padding byte that computes as a valid CRC / checksum.
711 */
712
713static int muleng_recv(struct diag_l0_device *dl0d,
714 void *data, size_t len, unsigned int timeout) {
715 ssize_t xferd;
716 int rv;
717 uint8_t *pdata = (uint8_t *)data;
718
719 struct muleng_device *dev;
720 dev = (struct muleng_device *)dl0d->l0_int;
721
722 if (!len) {
723 return diag_iseterr(DIAG_ERR_BADLEN);
724 }
725
726 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
727 FLFMT
728 "link %p recv upto %ld bytes timeout %u, rxlen %u offset %u\n",
729 FL, (void *)dl0d, (long)len, timeout, dev->dev_rxlen,
730 dev->dev_rdoffset);
731
732 /*
733 * Deal with 5 Baud init states where first two bytes read by
734 * user are the keybytes received from the interface, and where
735 * we are using the interface in pass thru mode on ISO-9141 protocols
736 */
737 switch (dev->dev_state) {
738 case MULENG_STATE_KWP_SENDKB1:
739 if (len >= 2) {
740 pdata[0] = dev->dev_kb1;
741 pdata[1] = dev->dev_kb2;
742 dev->dev_state = MULENG_STATE_OPEN;
743 return 2;
744 } else if (len == 1) {
745 *pdata = dev->dev_kb1;
746 dev->dev_state = MULENG_STATE_KWP_SENDKB2;
747 return 1;
748 }
749 return 0; /* Strange, user asked for 0 bytes */
750
751
752 case MULENG_STATE_KWP_SENDKB2:
753 if (len >= 1) {
754 *pdata = dev->dev_kb2;
755 dev->dev_state = MULENG_STATE_OPEN;
756 return 1;
757 }
758 return 0; /* Strange, user asked for 0 bytes */
759
760
761 case MULENG_STATE_RAW:
762 xferd = diag_tty_read(dev->tty_int, data, len, timeout);
763 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
764 FLFMT "link %p read %ld bytes\n", FL, (void *)dl0d, (long)xferd);
765
766 return xferd;
767
768 case MULENG_STATE_FASTSTART:
769 /* Extend timeout for 1st recv */
770 timeout = 200;
771 dev->dev_state = MULENG_STATE_OPEN;
772 /* Drop thru */
773 default: /* Some other mode */
774 break;
775 }
776
777 if (dev->dev_rxlen >= 14) {
778 /*
779 * There's a full packet been received, but the user
780 * has only asked for a few bytes from it previously
781 * Of the packet, bytes x[2]->x[11] are the network data
782 * others are header from the ME device
783 *
784 * The amount of data remaining to be sent to user is
785 * as below:
786 */
787 size_t bufbytes = dev->resp_len - (dev->dev_rdoffset - 2);
788
789 if (bufbytes <= len) {
790 memcpy(data, &dev->dev_rxbuf[dev->dev_rdoffset], bufbytes);
791 dev->dev_rxlen = dev->dev_rdoffset = dev->resp_len = 0;
792 return (int) bufbytes;
793 }
794 memcpy(data, &dev->dev_rxbuf[dev->dev_rdoffset], len);
795 dev->dev_rdoffset += len;
796 return (int) len;
797 }
798
799 /*
800 * There's either no data waiting, or only a partial read in the
801 * buffer (incomplete ME frame), read some more.
802 */
803
804 rv = diag_tty_read(dev->tty_int, &dev->dev_rxbuf[dev->dev_rxlen],
805 (size_t)(14 - dev->dev_rxlen), timeout);
806 if (rv == DIAG_ERR_TIMEOUT) {
807 return DIAG_ERR_TIMEOUT;
808 }
809
810 if (rv <= 0) {
811 fprintf(stderr, FLFMT "read returned EOF !!\n", FL);
812 return diag_iseterr(DIAG_ERR_GENERAL);
813 }
814
815 dev->dev_rxlen += rv;
816 if (dev->dev_rxlen != 14) {
817 return DIAG_ERR_TIMEOUT;
818 }
819
820 /* OK, got whole message */
821 DIAG_DBGMDATA(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
822 dev->dev_rxbuf, dev->dev_rxlen,
823 FLFMT "link %p received from ME: ", FL, (void *)dl0d);
824
825 /* Verify ME response checksum, 2nd byte onward */
826
827 xferd = diag_cks1(&dev->dev_rxbuf[1], 12);
828 if ((xferd & 0xff) != dev->dev_rxbuf[13]) {
829
830/* XXX, we should deal with this properly rather than just printing a message */
831 fprintf(stderr,"Got bad checksum from ME device 0x%X != 0x%X\n",
832 (int) xferd & 0xff, dev->dev_rxbuf[13]);
833 fprintf(stderr,"PC Serial port probably out of spec.\nRX Data: ");
834 diag_data_dump(stderr, dev->dev_rxbuf, dev->dev_rxlen);
835 fprintf(stderr, "\n");
836 }
837
838
839 /*
840 * Check the type
841 */
842 if (dev->dev_rxbuf[1] == ME_RESP_ERROR) {
843 /* It's an error message not a data frame */
844 dev->dev_rxlen = 0;
845 dev->resp_len = 0;
846
847 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
848 FLFMT
849 "link %p ME returns err 0x%X : %s; s/w v 0x%X i/f cap. 0x%X\n",
850 FL, (void *)dl0d, dev->dev_rxbuf[3],
851 me_geterr(dev->dev_rxbuf[3]), dev->dev_rxbuf[2],
852 dev->dev_rxbuf[4]);
853
854 switch (dev->dev_rxbuf[3]) {
855 case 0x05: /* No ISO response to request */
856 case 0x07: /* No J1850 response to request */
857 case 0x0c: /* No KWP response to request */
858 return DIAG_ERR_TIMEOUT;
859 break;
860
861 default:
862 fprintf(stderr, FLFMT "ME error 0x%0X: %s\n.", FL,
863 dev->dev_rxbuf[3], me_geterr(dev->dev_rxbuf[3]) );
864 return diag_iseterr(DIAG_ERR_GENERAL);
865 }
866 /* NOTREACHED */
867 }
868
869 /* get actual bus message length without padding 0x00 bytes */
870 dev->resp_len = me_guess_rxlen(dev->dev_rxbuf);
871
872 dev->dev_rdoffset = 2; /* Skip the ME header */
873
874 /* Copy data to user */
875 xferd = MIN(len, dev->resp_len);
876
877 memcpy(data, &dev->dev_rxbuf[dev->dev_rdoffset], (size_t)xferd);
878 dev->dev_rdoffset += xferd;
879 if (dev->dev_rdoffset == dev->resp_len +2) {
880 /* End of message, reset pointers */
881 dev->dev_rxlen = 0;
882 dev->dev_rdoffset = 0;
883 dev->resp_len = 0;
884 }
885 return xferd;
886}
887
888static uint32_t muleng_getflags(struct diag_l0_device *dl0d) {
889 /*
890 * ISO14230/J1850 protocol does L2 framing, ISO9141 doesn't
891 */
892 struct muleng_device *dev;
893 int flags;
894
895 dev = (struct muleng_device *)dl0d->l0_int;
896
897 flags = DIAG_L1_AUTOSPEED;
898 switch (dev->protocol) {
899 case DIAG_L1_J1850_VPW:
900 case DIAG_L1_J1850_PWM:
901 flags |= DIAG_L1_DOESL2CKSUM;
902 flags |= DIAG_L1_DOESL2FRAME;
903 break;
904 case DIAG_L1_ISO9141:
905 flags |= DIAG_L1_SLOW;
906/* XX does it ? flags |= DIAG_L1_DOESL2CKSUM; */
907 break;
908
909 case DIAG_L1_ISO14230:
910 flags |= DIAG_L1_SLOW | DIAG_L1_FAST | DIAG_L1_PREFFAST;
911 flags |= DIAG_L1_DOESL2FRAME;
912 flags |= DIAG_L1_DOESSLOWINIT;
913 flags |= DIAG_L1_DOESL2CKSUM;
914 break;
915
916 }
917
918 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_PROTO, DIAG_DBGLEVEL_V,
919 FLFMT "getflags link %p proto %d flags 0x%X\n",
920 FL, (void *)dl0d, dev->protocol, flags);
921
922 return flags;
923}
924
925
926static int muleng_ioctl(struct diag_l0_device *dl0d, unsigned cmd, void *data) {
927 int rv = 0;
928
929 switch (cmd) {
930 case DIAG_IOCTL_INITBUS:
931 rv = muleng_initbus(dl0d, (struct diag_l1_initbus_args *)data);
932 break;
933 case DIAG_IOCTL_IFLUSH:
934 //do nothing
935 rv = 0;
936 break;
937 default:
938 rv = DIAG_ERR_IOCTL_NOTSUPP;
939 break;
940 }
941
942 return rv;
943}
944
945const struct diag_l0 diag_l0_me = {
946 "Multiplex Engineering T16 interface",
947 "MET16",
948 DIAG_L1_J1850_VPW | DIAG_L1_J1850_PWM |
949 DIAG_L1_ISO9141 | DIAG_L1_ISO14230,
950 muleng_init,
951 muleng_new,
952 muleng_getcfg,
953 muleng_del,
954 muleng_open,
955 muleng_close,
956 muleng_getflags,
957 muleng_recv,
958 muleng_send,
959 muleng_ioctl
960};
961