/* * Send a load of data * * P4 is the inter byte gap * * This does very un-clever half duplex removal, there better not be * any outstanding data on the bus (or in the l0 buffers) or this * will think it has a half-duplex failure, i.e a bus error * * Returns 0 on success -1 on failure */ int diag_l1_send(struct diag_l0_device *dl0d, const char *subinterface, const void *data, size_t len, int p4) { int rv = -1; int l0flags; const struct diag_l0 *dl0 = diag_l0_device_dl0(dl0d); /* * If p4 is zero and not in half duplex mode, or if * L1 is a "DOESL2" interface send the whole message to L0 * as one write */ l0flags = diag_l1_getflags(dl0d); if ( ((p4 == 0) && ((l0flags & DIAG_L1_HALFDUPLEX) == 0)) || (l0flags & DIAG_L1_DOESL2FRAME) || (l0flags & DIAG_L1_DOESP4WAIT) ) { /* * Send the lot if we don't need to delay, or collect * the echos */ rv = (dl0->diag_l0_send)(dl0d, subinterface, data, len); } else { const uint8_t *dp = (const uint8_t *)data; /* Send each byte */ while (len--) { rv = (dl0->diag_l0_send)(dl0d, subinterface, dp, 1); if (rv != 0) break; /* * If half duplex, read back the echo, if * the echo is wrong then this is an error * i.e something wrote on the diag bus whilst * we were writing */ if (l0flags & DIAG_L1_HALFDUPLEX) { uint8_t c; c = *dp - 1; /* set it with wrong val */ if (diag_l1_saferead(dl0d, &c, 1, 1000) < 0) { rv=DIAG_ERR_GENERAL; break; } if (c != *dp) { if (c == *dp - 1) fprintf(stderr,"Half duplex interface not echoing!\n"); else fprintf(stderr,"Bus Error: got 0x%x expected 0x%x\n", c&0xff, *dp & 0xff); rv = DIAG_ERR_BUSERROR; break; } } dp++; if (p4) /* Inter byte gap */ diag_os_millisleep(p4); } } return rv; }
/* * Send a load of data * * P4 is the inter byte gap * * This does very un-clever half duplex removal, there better not be * any outstanding data on the bus (or in the l0 buffers) or this * will think it has a half-duplex failure, i.e a bus error * * Returns 0 on success */ int diag_l1_send(struct diag_l0_device *dl0d, const char *subinterface, const void *data, size_t len, unsigned int p4) { int rv = DIAG_ERR_GENERAL; uint32_t l0flags; uint8_t duplexbuf[MAXRBUF]; if (len > MAXRBUF) { return diag_iseterr(DIAG_ERR_BADLEN); } l0flags = diag_l1_getflags(dl0d); DIAG_DBGMDATA(diag_l1_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V, data, len, FLFMT "_send: len=%d P4=%u l0flags=0x%X; ", FL, (int) len, p4, l0flags); /* * If p4 is zero and not in half duplex mode, or if * L1 is a "DOESL2" interface, or if L0 takes care of P4 waits, * or if P4==0 and we do per-message duplex removal: * send the whole message to L0 as one write */ if ( ((p4 == 0) && ((l0flags & DIAG_L1_HALFDUPLEX) == 0)) || (l0flags & DIAG_L1_DOESL2FRAME) || (l0flags & DIAG_L1_DOESP4WAIT) || ((p4==0) && (l0flags & DIAG_L1_BLOCKDUPLEX)) ) { /* * Send the lot */ rv = diag_l0_send(dl0d, subinterface, data, len); //optionally remove echos if ((l0flags & DIAG_L1_BLOCKDUPLEX) && (rv==0)) { //try to read the same number of sent bytes; timeout=300ms + 1ms/byte //This is plenty OK for typical 10.4kbps but should be changed //if ever slow speeds are used. if (diag_l0_recv(dl0d, NULL, duplexbuf, len, 300+len) != (int) len) { rv=DIAG_ERR_GENERAL; } //compare to sent bytes if ( memcmp(duplexbuf, data, len) !=0) { fprintf(stderr,FLFMT "Bus Error: bad half duplex echo!\n", FL); rv=DIAG_ERR_BUSERROR; } } } else { /* else: send each byte */ const uint8_t *dp = (const uint8_t *)data; while (len--) { rv = diag_l0_send(dl0d, subinterface, dp, 1); if (rv != 0) { break; } /* * If half duplex, read back the echo, if * the echo is wrong then this is an error * i.e something wrote on the diag bus whilst * we were writing */ if (l0flags & DIAG_L1_HALFDUPLEX) { uint8_t c; c = *dp - 1; /* set it with wrong val. */ if (diag_l0_recv(dl0d, NULL, &c, 1, 200) != 1) { rv=DIAG_ERR_GENERAL; break; } if (c != *dp) { if (c == *dp - 1) { fprintf(stderr,"Half duplex interface not echoing!\n"); } else { fprintf(stderr, "Bus Error: got 0x%X " "expected 0x%X\n", c, *dp); } rv = DIAG_ERR_BUSERROR; break; } } dp++; if (p4) { /* Inter byte gap */ diag_os_millisleep(p4); } } } return rv? diag_iseterr(rv):0; }