コード例 #1
0
ファイル: diag_l0_dumb.c プロジェクト: shirou/freediag
/*
 * Fastinit: ISO14230-2 sec 5.2.4.2.3
 * Caller should have waited W5 (>300ms) before calling this (from _initbus only!)
 * we assume the L line was at the correct state (1) during that time.
 * returns 0 (success), 50ms after starting the wake-up pattern.
 * Exceptionally we dont diag_iseterr on return since _initbus() takes care of that.
 */
static int
diag_l0_dumb_fastinit(struct diag_l0_device *dl0d)
{
	int rv=0;
	uint8_t cbuf[MAXRBUF];

	if (diag_l0_debug & DIAG_DEBUG_INIT)
		fprintf(stderr, FLFMT "dl0d=%p fastinit\n",
			FL, (void *)dl0d);
	//Tidle before break : W5 (>300ms) on poweron; P3 (>55ms) after a StopCommunication; or 0ms after a P3 timeout.
	// We assume the caller took care of this.
	/* Send 25/25 ms break as initialisation pattern (TiniL) */
	//ISO14230-2 says we should send the same sync pattern on both L and K together.
	// we do it almost perfectly; the L \_/ pulse starts before and ends after the K \_/ pulse.

	if (dumb_flags & USE_LLINE) {
		// do K+L only if the user wants to do both
		if (dumb_flags & FAST_BREAK) {
			//but we can't use diag_tty_fastbreak while doing the L-line.
			fprintf(stderr, FLFMT "Warning : not using L line for FAST_BREAK.\n", FL);
			rv=diag_tty_fastbreak(dl0d, 50-WUPFLUSH);
		} else {
			//normal fast break on K and L.
			//note : if LLINE_INV is 1, then we need to clear RTS to pull L down !
			if (diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), !(dumb_flags & LLINE_INV)) < 0) {
				fprintf(stderr, FLFMT "fastinit: Failed to set L\\_\n", FL);
				return DIAG_ERR_GENERAL;
				}
			rv=diag_tty_break(dl0d, 25);	//K line low for 25ms
				/* Now restore DTR/RTS */
			if (diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), (dumb_flags & SET_RTS)) < 0) {
				fprintf(stderr, FLFMT "fastinit: Failed to restore DTR & RTS!\n",
					FL);
			}
			diag_os_millisleep(25-WUPFLUSH);
		}	//if FAST_BREAK
	} else {
		// do K line only
		if (dumb_flags & FAST_BREAK) {
			rv=diag_tty_fastbreak(dl0d, 50-WUPFLUSH);
		} else {
			//normal break
			rv=diag_tty_break(dl0d, 25);	//K line low for 25ms
			diag_os_millisleep(25-WUPFLUSH);
		}
	}	//if USE_LLINE
	// here we have WUPFLUSH ms before tWUP is done; we use this
	// short time to flush RX buffers. (L2 needs to send a StartComm
	// request very soon.)

	diag_tty_read(dl0d, cbuf, sizeof(cbuf), WUPFLUSH);


	//there may have been a problem in diag_tty_break, if so :
	if (rv) {
		fprintf(stderr, FLFMT " L0 fastinit : problem !\n", FL);
		return DIAG_ERR_GENERAL;
	}
	return 0;
}
コード例 #2
0
ファイル: diag_l0_dumb.c プロジェクト: shirou/freediag
static void
diag_l0_dumb_Lline(struct diag_l0_device *dl0d, uint8_t ecuaddr)
{
	/*
	 * The bus has been high for w0 ms already, now send the
	 * 8 bit ecuaddr at 5 baud LSB first
	 *
	 */
	int i, rv=0;
//	uint8_t cbuf[10];

	// We also toggle DTR to disable RXD (blocking it at logical 1).
	// However, at least one system I tested doesn't react well to
	// DTR-toggling.
	/* Set RTS low, for 200ms (Start bit) */
	if (diag_tty_control(dl0d, (dumb_flags & CLEAR_DTR), !(dumb_flags & LLINE_INV)) < 0) {
		fprintf(stderr, FLFMT "_LLine: Failed to set DTR & RTS\n", FL);
		return;
	}
	diag_os_millisleep(BPS_PERIOD);		/* 200ms -5% */

	for (i=0; i<8; i++) {
		if (ecuaddr & (1<<i)) {
			/* High */
			rv |= diag_tty_control(dl0d, (dumb_flags & CLEAR_DTR), (dumb_flags & LLINE_INV));
		} else {
			/* Low */
			rv |= diag_tty_control(dl0d, (dumb_flags & CLEAR_DTR), !(dumb_flags & LLINE_INV));
		}

		if (rv < 0) {
			fprintf(stderr, FLFMT "_LLine: Failed to set DTR & RTS\n",
				FL);
			return;
		}
		diag_os_millisleep(BPS_PERIOD);		/* 200ms -5% */
	}
	/* And set high for the stop bit */
	if (diag_tty_control(dl0d, (dumb_flags & CLEAR_DTR), !(dumb_flags & LLINE_INV)) < 0) {
		fprintf(stderr, FLFMT "_LLine: Failed to set DTR & RTS\n",
			FL);
		return;
	}
	diag_os_millisleep(BPS_PERIOD);		/* 200ms -5% */

	/* Now put DTR/RTS back correctly so RX side is enabled */
	if (diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), (dumb_flags & SET_RTS)) < 0) {
		fprintf(stderr, FLFMT "_LLine: Failed to restore DTR & RTS\n",
			FL);
	}

	/* And clear out the break XXX no, _slowinit will do this for us after calling dumb_Lline*/
//	diag_tty_read(dl0d, cbuf, sizeof(cbuf), 20);

	return;
}
コード例 #3
0
ファイル: diag_l0_dumb.c プロジェクト: shirou/freediag
/*
 * Slowinit:
 *	We need to send a byte (the address) at 5 baud, then
 *	switch back to 10400 baud
 *	and then wait W1 (60-300ms) until we get Sync byte 0x55.
 * Caller (in L2 typically) must have waited with bus=idle beforehand.
 * This optionally does the L_line stuff according to the flags in dumb_flags.
 * Ideally returns 0 (success) immediately after receiving Sync byte.
 * This one, like fastinit, doesnt diag_iseterr when returning errors
 * since _initbus() takes care of that.
 *
 */
static int
diag_l0_dumb_slowinit(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in,
	struct diag_l0_dumb_device *dev)
{
	uint8_t cbuf[10];
	int rv;
	unsigned int tout;
	struct diag_serial_settings set;

	if (diag_l0_debug & DIAG_DEBUG_PROTO) {
		fprintf(stderr, FLFMT "slowinit dl0d=%p address 0x%X\n",
			FL, (void *)dl0d, in->addr);
	}


	//two methods of sending at 5bps. Most USB-serial converts don't support such a slow bitrate !
	if (dumb_flags & MAN_BREAK) {
		//MAN_BREAK means we bitbang K and optionally L as well.
		if (dumb_flags & USE_LLINE) {
			//do manual 5bps init on K and L.
			//we need to send the byte at in->addr, bit by bit.

			int bitcounter;
			uint8_t tempbyte=in->addr;
			diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), !(dumb_flags & LLINE_INV));	//L is the logical opposite of RTS...
			diag_tty_break(dl0d, BPS_PERIOD);	//start startbit
			for (bitcounter=0; bitcounter<=7; bitcounter++) {
				//LSB first.
				if (tempbyte & 1) {
					diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), (dumb_flags & LLINE_INV));	//release L
					diag_os_millisleep(BPS_PERIOD);
				} else {
					unsigned int lowtime=BPS_PERIOD;
					//to prevent spurious breaks if we have a sequence of 0's :
					//this is an RLE of sorts...
					for (; bitcounter <=6; bitcounter++) {
						if (tempbyte & 2) //test bit 1; we just tested bit 0 before getting here.
							break;
						lowtime += BPS_PERIOD;
						tempbyte = tempbyte >>1;
					}
					//this way, we know for sure the next bit is 1 (either bit 7==1 or stopbit==1 !)
					diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), !(dumb_flags & LLINE_INV));	//pull L down
					diag_tty_break(dl0d, lowtime);
				}
				tempbyte = tempbyte >>1;
			}
			//at this point we just finished the last bit, we'll wait the duration of the stop bit.
			diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), (dumb_flags & SET_RTS));	//release L
			diag_os_millisleep(BPS_PERIOD);	//stop bit
		} else {
コード例 #4
0
ファイル: diag_tty.c プロジェクト: butljon/freediag
int diag_tty_break(struct diag_l0_device *dl0d, const int ms)
{
	HANDLE hd;
	long h;

	/*
	 * I'm going through this convoluted two-step conversion
	 * to avoid compiler warnings:
	 */

	h = get_osfhandle(dl0d->fd);
	hd = (HANDLE)h;

	if (tcdrain(dl0d->fd)) {
			fprintf(stderr, FLFMT "tcdrain returned %s.\n",
				FL, strerror(errno));
			return diag_iseterr(DIAG_ERR_GENERAL);
		}

	SetCommBreak(hd);
	diag_os_millisleep(ms);
	ClearCommBreak(hd);

	return 0;
}
コード例 #5
0
ファイル: diag_tty_win.c プロジェクト: remspoor/freediag
// diag_tty_break #1 : use Set / ClearCommBreak
// and return as soon as break is cleared.
// ret 0 if ok
int diag_tty_break(struct diag_l0_device *dl0d, const unsigned int ms) {
	LARGE_INTEGER qpc1, qpc2;	//for timing verification
	long real_t;	//"real" duration
	struct tty_int *wti = (struct tty_int *)dl0d->tty_int;
	int errval=0;

	if (wti->fd == INVALID_HANDLE_VALUE) {
		fprintf(stderr, FLFMT "Error. Is the port open ?\n", FL);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	if (ms <= 1)
		return diag_iseterr(DIAG_ERR_GENERAL);

	QueryPerformanceCounter(&qpc1);
	errval = !SetCommBreak(wti->fd);
	QueryPerformanceCounter(&qpc2);
	//that call can take quite a while (6ms !!) on some setups (win7 + CH340 USB-Serial).
	//It's still impossible to know (from here) when exactly TXD goes low (beginning or end of the call)
	real_t=(long) (pf_conv * (qpc2.QuadPart-qpc1.QuadPart)) / 1000L;
	real_t = (long) ms - real_t;	//time remaining
	if (real_t <= 0) real_t = 0;
	diag_os_millisleep((unsigned int ) real_t);

	errval |= !ClearCommBreak(wti->fd);

	if (errval) {
		//if either of the calls failed
		fprintf(stderr, FLFMT "tty_break could not set/clear break!\n", FL);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	return 0;
}
コード例 #6
0
ファイル: diag_tty_win.c プロジェクト: shirou/freediag
// diag_tty_break #1 : use Set / ClearCommBreak
// and return as soon as break is cleared.
// ret 0 if ok
int diag_tty_break(struct diag_l0_device *dl0d, const unsigned int ms) {
    LARGE_INTEGER qpc1, qpc2;	//for timing verification
    static long correction=0;	//running average offset (us) to add to the timeout
    long real_t;	//"real" duration measured in us
    struct tty_int *wti = (struct tty_int *)dl0d->tty_int;
    int errval=0;

    if (wti->fd == INVALID_HANDLE_VALUE) {
        fprintf(stderr, FLFMT "Error. Is the port open ?\n", FL);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    if ( (ms + correction/1000)<1)
        return diag_iseterr(DIAG_ERR_GENERAL);

    QueryPerformanceCounter(&qpc1);
    errval=!SetCommBreak(wti->fd);
    diag_os_millisleep(ms + correction/1000);
    QueryPerformanceCounter(&qpc2);
    errval += !ClearCommBreak(wti->fd);

    if (errval) {
        //if either of the calls failed
        fprintf(stderr, FLFMT "tty_break could not set/clear break!\n", FL);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }
    real_t=(long) (pf_conv * (qpc2.QuadPart-qpc1.QuadPart));

    //now verify if it's within 1ms of the requested delay.
    real_t = real_t - (ms*1000);
    if (real_t < -3000) {
        diag_os_millisleep((unsigned int)(real_t / -1000));
    } else if ((real_t > -1000) && (real_t < 1000)) {
        //good enough:
        return 0;
    }
    //we're here if we were off by more than -3ms or +1ms.
    //correct by a fraction of the error.
    //diag_os_millisleep also does some self-correcting; we don't want to overdo it.
    correction = correction - (real_t / 3);
    //fprintf(stderr, FLFMT "tty_break off by %ldus, new correction=%ldus.\n",
    //	FL, real_t, correction);

    return 0;
}
/* fake run measures */
int fake_run_measure_data(int data_pid)
{
  int rpm;
  
  diag_os_millisleep(250);

  rpm = 1000 + counter2 * 200;
  if (counter2 < 5500/200)
    counter2++;
  else
    counter2--;
  
  if (data_pid == RPM_PID)
    return rpm;
  else if (data_pid == SPEED_PID)
    return rpm * (9000*100/6000) / 36;
}
コード例 #8
0
ファイル: diag_tty.c プロジェクト: butljon/freediag
int diag_tty_break(struct diag_l0_device *dl0d, const int ms)
{
	if (tcdrain(dl0d->fd)) {
			fprintf(stderr, FLFMT "tcdrain returned %s.\n",
				FL, strerror(errno));
			return diag_iseterr(DIAG_ERR_GENERAL);
		}

	if (ioctl(dl0d->fd, TIOCSBRK, 0) < 0) {
		fprintf(stderr, 
			FLFMT "open: Ioctl TIOCSBRK failed %s\n", FL, strerror(errno));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	diag_os_millisleep(ms);

	if (ioctl(dl0d->fd, TIOCCBRK, 0) < 0) {
		fprintf(stderr, 
			FLFMT "open: Ioctl TIOCCBRK failed %s\n", FL, strerror(errno));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	return 0;
}
コード例 #9
0
ファイル: diag_l1.c プロジェクト: butljon/freediag
/*
 * 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;
}
コード例 #10
0
ファイル: scantool_dyno.c プロジェクト: fenugrec/freediag
/* fake loss measures */
int fake_loss_measure_data() {
	unsigned long tv;
	unsigned long elapsed; /* elapsed time */
	int speed;

	if (counter == 0) {
		tv0d=diag_os_getms();
	}

	diag_os_millisleep(250);

	/* get elapsed time */
	tv=diag_os_getms();
	elapsed = tv - tv0d;


	//I think we're supposed to simulate an exponential decreasing
	//function ; speed = b * e^(elapsed / a).
	float a= -62810;
	float b= 25027;

	return (int) (b * exp(elapsed / a));


	elapsed += 11000;

	//XXX This was a most interesting lookup table!! Can be deleted soon.
  if      (elapsed < 11983) speed = 89*10000/36;
  else if (elapsed < 12723) speed = 88*10000/36;
  else if (elapsed < 13473) speed = 87*10000/36;
  else if (elapsed < 14713) speed = 85*10000/36;
  else if (elapsed < 15713) speed = 84*10000/36;
  else if (elapsed < 16213) speed = 83*10000/36;
  else if (elapsed < 16963) speed = 82*10000/36;
  else if (elapsed < 17463) speed = 81*10000/36;
  else if (elapsed < 18463) speed = 80*10000/36;
  else if (elapsed < 19463) speed = 79*10000/36;
  else if (elapsed < 20213) speed = 78*10000/36;
  else if (elapsed < 20963) speed = 77*10000/36;
  else if (elapsed < 22463) speed = 76*10000/36;
  else if (elapsed < 22963) speed = 75*10000/36;
  else if (elapsed < 23713) speed = 74*10000/36;
  else if (elapsed < 25213) speed = 73*10000/36;
  else if (elapsed < 26453) speed = 72*10000/36;
  else if (elapsed < 27203) speed = 71*10000/36;
  else if (elapsed < 27953) speed = 70*10000/36;
  else if (elapsed < 29193) speed = 69*10000/36;
  else if (elapsed < 29943) speed = 68*10000/36;
  else if (elapsed < 30693) speed = 67*10000/36;
  else if (elapsed < 32183) speed = 66*10000/36;
  else if (elapsed < 32933) speed = 65*10000/36;
  else if (elapsed < 33683) speed = 64*10000/36;
  else if (elapsed < 34683) speed = 63*10000/36;
  else if (elapsed < 35433) speed = 62*10000/36;
  else if (elapsed < 36433) speed = 61*10000/36;
  else if (elapsed < 37183) speed = 60*10000/36;
  else if (elapsed < 38433) speed = 59*10000/36;
  else if (elapsed < 39433) speed = 58*10000/36;
  else if (elapsed < 40183) speed = 57*10000/36;
  else if (elapsed < 40683) speed = 56*10000/36;
  else if (elapsed < 42183) speed = 55*10000/36;
  else if (elapsed < 43183) speed = 54*10000/36;
  else if (elapsed < 44683) speed = 53*10000/36;
  else if (elapsed < 45933) speed = 52*10000/36;
  else if (elapsed < 47183) speed = 51*10000/36;
  else if (elapsed < 48183) speed = 50*10000/36;
  else if (elapsed < 49433) speed = 49*10000/36;
  else                      speed = 48*10000/36;

  counter++;

  return speed;
}
コード例 #11
0
ファイル: diag_tty_win.c プロジェクト: shirou/freediag
/*
 * diag_tty_fastbreak: send 0x00 at 360bps => fixed 25ms break; return [ms] after starting break.
 * This is for ISO14230 fast init : typically diag_tty_fastbreak(dl0d, 50)
 * It assumes the interface is half-duplex.
 * Ret 0 if ok
 */
int diag_tty_fastbreak(struct diag_l0_device *dl0d, const unsigned int ms) {
    HANDLE dh;	//just to clarify code
    struct tty_int *wti = (struct tty_int *)dl0d->tty_int;
    DCB tempDCB; 	//for sabotaging the settings just to do the break
    DCB origDCB;
    LARGE_INTEGER qpc1, qpc2, qpc3;	//to time the break period
    LONGLONG timediff;		//64bit delta
    long int tremain,counts, break_error;

    uint8_t cbuf;
    int xferd;
    DWORD byteswritten;

    dh = wti->fd;
    if (ms<25)		//very funny
        return diag_iseterr(DIAG_ERR_TIMEOUT);

    if (dh == INVALID_HANDLE_VALUE) {
        fprintf(stderr, FLFMT "Error. Is the port open ?\n", FL);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    GetCommState(dh, &origDCB);
    GetCommState(dh, &tempDCB); //ugly, but a memcpy would be worse

    tempDCB.BaudRate=360;
    tempDCB.ByteSize=8;
    tempDCB.fParity=0;
    tempDCB.Parity=NOPARITY;
    tempDCB.StopBits=ONESTOPBIT;

    if (! SetCommState(dh, &tempDCB)) {
        fprintf(stderr, FLFMT "SetCommState error\n", FL);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    /* Send a 0x00 byte message */

    if (! WriteFile(dh, "\0", 1, &byteswritten, NULL)) {
        fprintf(stderr, FLFMT "WriteFile error:%s\n", FL, diag_os_geterr(0));
        return diag_iseterr(DIAG_ERR_GENERAL);
    }
    //get approx starting time. I think this is the closest we can
    //get to the actual time the byte gets sent since we call FFB
    //right after.
    QueryPerformanceCounter(&qpc1);

    if (!FlushFileBuffers(dh)) {
        fprintf(stderr, FLFMT "FFB error, %s\n", FL, diag_os_geterr(0));
        return diag_iseterr(DIAG_ERR_GENERAL);
    }


    /*
     * And read back the single byte echo, which shows TX completes
     */
    xferd = diag_tty_read(dl0d, &cbuf, 1, ms + 20);

    //we'll usually have a few ms left to wait; we'll use this
    //to restore the port settings

    if (! SetCommState(dh, &origDCB)) {
        fprintf(stderr, FLFMT "tty_fastbreak: could not restore setting: %s\n", FL, diag_os_geterr(0));
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    //Not getting the echo byte doesn't mean fastbreak has necessarily
    // failed. But we really should be getting an echo back...
    if (xferd < 0)
        return diag_iseterr(xferd);
    if ((xferd == 0) || (cbuf != 0)) {
        /* Error, EOF or bad echo */
        fprintf(stderr, FLFMT "Did not get fastbreak echo!\n", FL);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }


    QueryPerformanceCounter(&qpc2);		//get current time,
    timediff=qpc2.QuadPart-qpc1.QuadPart;	//elapsed counts since diag_tty_write
    counts=(ms*perfo_freq.QuadPart)/1000;		//total # of counts for requested tWUP
    tremain=counts-timediff;	//counts remaining
    if (tremain<=0)
        return 0;

    tremain = ((LONGLONG) tremain*1000)/perfo_freq.QuadPart;	//convert to ms; imprecise but that should be OK.
    diag_os_millisleep((unsigned int) tremain);
    QueryPerformanceCounter(&qpc3);

    timediff=qpc3.QuadPart-qpc1.QuadPart;	//total cycle time.
    break_error= (long) timediff - counts;	//real - requested
    break_error= (long) (break_error * pf_conv);	//convert to us !
    if (break_error > 1000 || break_error < -1000)
        fprintf(stderr, FLFMT "tty_fastbreak: tWUP out of spec by %ldus!\n", FL, break_error);


    return 0;
}	//diag_tty_fastbreak
コード例 #12
0
ファイル: diag_l2_vag.c プロジェクト: shirou/freediag
static int
diag_l2_proto_vag_startcomms( struct diag_l2_conn *d_l2_conn,
                              UNUSED(flag_type flags),
                              unsigned int bitrate, target_type target, UNUSED(source_type source))
{
    struct diag_serial_settings set;
    struct diag_l2_vag *dp;
    uint8_t data[MAXRBUF];
    int rv;
    /*	int wait_time;*/
    /*	int hdrlen;*/
    /*	int datalen;*/
    /*	int datasrc;*/
    uint8_t cbuf[MAXRBUF];
    /*	int len;*/

    struct diag_l1_initbus_args in;

    if (diag_calloc(&dp, 1))
        return diag_iseterr(DIAG_ERR_NOMEM);

    d_l2_conn->diag_l2_proto_data = (void *)dp;


    memset(data, 0, sizeof(data));

    /*
     * If 0 has been specified, use a useful default of 9600
     */
    if (bitrate == 0)
        bitrate = 9600;
    d_l2_conn->diag_l2_speed = bitrate;

    set.speed = bitrate;
    set.databits = diag_databits_8;
    set.stopbits = diag_stopbits_1;
    set.parflag = diag_par_n;

    /* Set the speed as shown */
    rv = diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_SETSPEED, &set);
    if (rv < 0)
    {
        free(dp);
        d_l2_conn->diag_l2_proto_data=NULL;
        return diag_iseterr(rv);
    }

    /* Flush unread input, then wait for idle bus. */
    (void)diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_IFLUSH, NULL);
    diag_os_millisleep(300);


    /* Now do 5 baud init of supplied address */
    in.type = DIAG_L1_INITBUS_5BAUD;
    in.addr = target;
    rv = diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_INITBUS, &in);
    if (rv < 0) {
        free(dp);
        d_l2_conn->diag_l2_proto_data=NULL;
        return rv;
    }


    /* Mode bytes are in 7-Odd-1, read as 8N1 and ignore parity */
    rv = diag_l1_recv (d_l2_conn->diag_link->diag_l2_dl0d, 0,
                       cbuf, 1, 100);
    if (rv < 0) {
        free(dp);
        d_l2_conn->diag_l2_proto_data=NULL;
        return diag_iseterr(rv);
    }
    rv = diag_l1_recv (d_l2_conn->diag_link->diag_l2_dl0d, 0,
                       &cbuf[1], 1, 100);
    if (rv < 0) {
        free(dp);
        d_l2_conn->diag_l2_proto_data=NULL;
        return diag_iseterr(rv);
    }

    /* Keybytes are 0x1 0x8a for VAG protocol */
    if ((cbuf[0] != 0x01) || (cbuf[1] != 0x8a)) {
        free(dp);
        d_l2_conn->diag_l2_proto_data=NULL;
        return diag_iseterr(DIAG_ERR_WRONGKB);
    }

    /* Note down the mode bytes */
    d_l2_conn->diag_l2_kb1 = cbuf[0] & 0x7f;
    d_l2_conn->diag_l2_kb2 = cbuf[1] & 0x7f;

    if ( (d_l2_conn->diag_link->l1flags
            & DIAG_L1_DOESSLOWINIT) == 0)
    {

        /*
         * Now transmit KB2 inverted
         */
        cbuf[0] = ~ d_l2_conn->diag_l2_kb2;
        rv = diag_l1_send (d_l2_conn->diag_link->diag_l2_dl0d, 0,
                           cbuf, 1, d_l2_conn->diag_l2_p4min);

    }


    /*
     * Now receive the first 3 messages
     * which show ECU versions etc
     */


    return 0;
}
コード例 #13
0
ファイル: diag_tty.c プロジェクト: butljon/freediag
ssize_t
diag_tty_slow_write(struct diag_l0_device *dl0d,
const void *buf, const size_t count)
{
//        int   ms = 950 * dl0d->ttystate->dt_sinfo.custom_divisor/24000000;
#if 1
	/* for rtc interrupt: */
  	int ms = 204;
#else
	/* for nanosleep interrupt (try up to 191 / 192): */
  	int ms = 191;
#endif
	short   bits, parBit, stpBit, i, high=1, parity;
	size_t num;
	char message_buff[3];

	if((dl0d->ttystate->dt_tinfo.c_cflag & CS8) == CS8) {
	  bits = diag_databits_8;
	  sprintf(&message_buff[0], "%c", '8');
	}
	if((dl0d->ttystate->dt_tinfo.c_cflag & CS8) == CS7) {
	  bits = diag_databits_7;
	  sprintf(&message_buff[0], "%c", '7');
	}
	if((dl0d->ttystate->dt_tinfo.c_cflag & CS8) == CS6) {
	  bits = diag_databits_6;
	  sprintf(&message_buff[0], "%c", '6');
	}
	if((dl0d->ttystate->dt_tinfo.c_cflag & CS8) == CS5) {
	  bits = diag_databits_5;
	  sprintf(&message_buff[0], "%c", '5');
	}
        if((dl0d->ttystate->dt_tinfo.c_cflag & PARENB) == PARENB) {
	  parBit = diag_par_e;
	  sprintf(&message_buff[1], "%c", 'E');
	}
        if((dl0d->ttystate->dt_tinfo.c_cflag & (PARENB | PARODD)) == (PARENB | PARODD)) {
	  parBit = diag_par_o; 
	  sprintf(&message_buff[1], "%c", 'O');
	}
        if(!(dl0d->ttystate->dt_tinfo.c_cflag & PARENB)) {
	  parBit = diag_par_n;
	  sprintf(&message_buff[1], "%c", 'N');
	}
        if((dl0d->ttystate->dt_tinfo.c_cflag & CSTOPB) == CSTOPB) {
	  stpBit = diag_stopbits_2;
	  sprintf(&message_buff[2], "%c", '2');
	}
        if((dl0d->ttystate->dt_tinfo.c_cflag & ~CSTOPB) != CSTOPB) {
	  stpBit = diag_stopbits_1;
	  sprintf(&message_buff[2], "%c", '1');
	}

// start bit
	if (ioctl(dl0d->fd, TIOCSBRK, 0) < 0) {
		fprintf(stderr, 
			FLFMT "open: Ioctl TIOCSBRK failed %s\n", FL, strerror(errno));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
        high = 0;
	printf("Init bits: 0");
	diag_os_millisleep(ms);
	
	for(num=0; num < count; num++) {
	    parity = 1;
            for(i=0; i< bits; i++) {
	        if(*((char *) (buf+num)) & (1<<i)) {
		  parity *= -1;
		  if(!high) {
	              if (ioctl(dl0d->fd, TIOCCBRK, 0) < 0) {
		          fprintf(stderr, 
			      FLFMT "open: Ioctl TIOCCBRK failed %s\n", FL, strerror(errno));
		          return diag_iseterr(DIAG_ERR_GENERAL);
		      }
		      high=1;
		  }
		} else {
		  if(high) {
	              if (ioctl(dl0d->fd, TIOCSBRK, 0) < 0) {
		          fprintf(stderr, 
			      FLFMT "open: Ioctl TIOCSBRK failed %s\n", FL, strerror(errno));
		          return diag_iseterr(DIAG_ERR_GENERAL);
		      }
		      high=0;
		  }
		}
                 if(high)
		  printf("1");
		else
 		  printf("0");
                diag_os_millisleep(ms);
	    }
// parity bit
	    if(parBit == diag_par_e) {
	      if (parity < 0) {
		if(!high) {
	              if (ioctl(dl0d->fd, TIOCCBRK, 0) < 0) {
		          fprintf(stderr, 
			      FLFMT "open: Ioctl TIOCCBRK2 failed %s\n", FL, strerror(errno));
		          return diag_iseterr(DIAG_ERR_GENERAL);
		      }
		      high=1;
		}
	      } else {
		if(high) {
	              if (ioctl(dl0d->fd, TIOCSBRK, 0) < 0) {
		          fprintf(stderr, 
			      FLFMT "open: Ioctl TIOCSBRK2 failed %s\n", FL, strerror(errno));
		          return diag_iseterr(DIAG_ERR_GENERAL);
		      }
		      high=0;
	        }
	      }
                 if(high)
		  printf("1");
		else
		  printf("0");
	      diag_os_millisleep(ms);
	    }
	    if(parBit == diag_par_o) {
	      if (parity > 0) {
		if(!high) {
	              if (ioctl(dl0d->fd, TIOCCBRK, 0) < 0) {
		          fprintf(stderr, 
			      FLFMT "open: Ioctl TIOCCBRK3 failed %s\n", FL, strerror(errno));
		          return diag_iseterr(DIAG_ERR_GENERAL);
		      }
		      high=1;
		}
	      } else {
		if(high) {
	              if (ioctl(dl0d->fd, TIOCSBRK, 0) < 0) {
		          fprintf(stderr, 
			      FLFMT "open: Ioctl TIOCSBRK3 failed %s\n", FL, strerror(errno));
		          return diag_iseterr(DIAG_ERR_GENERAL);
		      }
		      high=0;
	        }
	      }
                 if(high)
		  printf("1");
		else
 		  printf("0");
	      diag_os_millisleep(ms);
	    }
// stop bit(s)
            if(!high) {
	         if (ioctl(dl0d->fd, TIOCCBRK, 0) < 0) {
		     fprintf(stderr, 
			FLFMT "open: Ioctl TIOCCBRK2 failed %s\n", FL, strerror(errno));
		     return diag_iseterr(DIAG_ERR_GENERAL);
		 }
		 high=1;
	    }
	    if (stpBit == diag_stopbits_1) {
	      printf("1");
  	      diag_os_millisleep(ms);
	    } else {
	      diag_os_millisleep(2*ms);
	      printf("11");
	    }

	}

	printf(", which is ");
	for(num=0; num < count; num++)
	  printf("<%d>", *(char *) (buf+num));
	printf(", %.*s at 5 bps\n", 3, (char *) &message_buff);

	return count;
}
コード例 #14
0
ファイル: diag_tty.c プロジェクト: butljon/freediag
/*
 * diag_tty_break
 */
int diag_tty_break(struct diag_l0_device *dl0d, const int ms)
{
	char cbuf;
	struct timeval tv;
	int xferd;
	struct diag_serial_settings set;

	/*
	 *	We need to send an 25ms (+/- 1ms) break
	 *	and then wait 25ms. We must have waited Tidle (300ms) first
	 *
	 *	The trouble here is Linux doesn't let us be that accurate sending
	 *	a break - so we do it by sending a '0x00' at a baud rate that means
	 *	the output is low for 25ms, then we wait for 25ms, using busy
	 *	waits (which we get from being in real-time mode and doing nanosleeps
	 *	of less than 2ms each)
	 *
	 */

	/* Set baud rate etc to 360 baud, 8, N, 1 */
	set.speed = 360;
	set.databits = diag_databits_8;
	set.stopbits = diag_stopbits_1;
	set.parflag = diag_par_n;

	diag_tty_setup(dl0d, &set);

	gettimeofday(&tv,NULL);
	/* Send a 0x00 byte message */
	diag_tty_write(dl0d, "", 1);
	
	if (diag_l0_debug & DIAG_DEBUG_TIMER) {
		fprintf(stderr, FLFMT "%04ld.%03ld : break start\n", FL, tv.tv_sec, tv.tv_usec);
	}

	/*
	 * And read back the single byte echo, which shows TX completes
 	 */
	while ( (xferd = diag_tty_read(dl0d, &cbuf, 1, 1000)) <= 0)
	{
		if (xferd == DIAG_ERR_TIMEOUT)
			return diag_iseterr(DIAG_ERR_TIMEOUT);
		if (xferd == 0)
		{
			/* Error, EOF */
			fprintf(stderr, FLFMT "read returned EOF.\n", FL);
			return diag_iseterr(DIAG_ERR_GENERAL);
		}
		if (errno != EINTR)
		{
			/* Error, EOF */
			fprintf(stderr, FLFMT "read returned error %s.\n", FL,
				strerror(errno));
			return diag_iseterr(DIAG_ERR_GENERAL);
		}
	}

	/* Now wait the requested number of ms */
	gettimeofday(&tv,NULL);
	diag_os_millisleep(ms);
	if (diag_l0_debug & DIAG_DEBUG_TIMER) {
		fprintf(stderr, FLFMT "%04ld.%03ld : end of break_L\n", FL, tv.tv_sec, tv.tv_usec);
	}

	return 0;
}
コード例 #15
0
ファイル: diag_l1.c プロジェクト: fenugrec/freediag
/*
 * 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;
}
コード例 #16
0
ファイル: diag_l2_iso14230.c プロジェクト: shirou/freediag
/*
 * The complex initialisation routine for ISO14230, which supports
 * 2 types of initialisation (5-BAUD, FAST) and functional
 * and physical addressing. The ISO14230 spec describes CARB initialisation
 * which is done in the ISO9141 code
 *
 * Remember, we have to wait longer on smart L1 interfaces.
 */
static int
diag_l2_proto_14230_startcomms( struct diag_l2_conn	*d_l2_conn, flag_type flags,
	unsigned int bitrate, target_type target, source_type source)
{
	struct diag_l2_14230 *dp;
	struct diag_msg msg={0};
	uint8_t data[MAXRBUF];
	int rv;
	unsigned int wait_time;
	uint8_t cbuf[MAXRBUF];
	unsigned int timeout;
	struct diag_serial_settings set;

	struct diag_l1_initbus_args in;

	if (diag_calloc(&dp, 1))
		return diag_iseterr(DIAG_ERR_NOMEM);

	d_l2_conn->diag_l2_proto_data = (void *)dp;
	dp->initype = flags & DIAG_L2_TYPE_INITMASK;	//only keep initmode flags

	dp->srcaddr = source;
	dp->dstaddr = target;
	//set iso14230-specific flags according to what we were given
	if (flags & DIAG_L2_IDLE_J1978)
		dp->modeflags |= ISO14230_IDLE_J1978;
	if (flags & DIAG_L2_TYPE_FUNCADDR)
		dp->modeflags |= ISO14230_FUNCADDR;

	dp->first_frame = 1;
	if (diag_l2_debug & DIAG_DEBUG_PROTO)
		fprintf(stderr, FLFMT "_startcomms flags=0x%X tgt=0x%X src=0x%X\n",
			FL, flags, target, source);

	memset(data, 0, sizeof(data));

	/*
	 * If 0 has been specified, use the correct speed
	 * for ISO14230 protocol
	 */
	if (bitrate == 0)
		bitrate = 10400;
	d_l2_conn->diag_l2_speed = bitrate;

	set.speed = bitrate;
	set.databits = diag_databits_8;
	set.stopbits = diag_stopbits_1;
	set.parflag = diag_par_n;

	/* Set the speed*/
	if ((rv=diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_SETSPEED, (void *) &set))) {
			free(dp);
			d_l2_conn->diag_l2_proto_data=NULL;	//delete pointer to dp
			return diag_iseterr(rv);
	}

	dp->state = STATE_CONNECTING ;

	/* Flush unread input, then wait for idle bus. */
	(void)diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_IFLUSH, NULL);
	diag_os_millisleep(300);

	//inside this switch, we set rv=0 or rv=error before "break;"
	switch (dp->initype & DIAG_L2_TYPE_INITMASK) {
	/* Fast initialisation */
	case DIAG_L2_TYPE_FASTINIT:

		/* Build an ISO14230 StartComms message */
		if (flags & DIAG_L2_TYPE_FUNCADDR) {
			msg.fmt = DIAG_FMT_ISO_FUNCADDR;
			d_l2_conn->diag_l2_physaddr = 0; /* Don't know it yet */
			in.physaddr = 0;
		} else {
			msg.fmt = 0;
			d_l2_conn->diag_l2_physaddr = target;
			in.physaddr = 1;
		}
		msg.src = source;
		msg.dest = target;
		msg.len = 1 ;
		data[0]= DIAG_KW2K_SI_SCR ;	/* startCommunication rqst*/
		msg.data = data;

		/* Do fast init stuff */
		in.type = DIAG_L1_INITBUS_FAST;
		in.addr = target;
		in.testerid = source;
		rv = diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_INITBUS, &in);

		// some L0 devices already do the full startcomm transaction:
		if ((d_l2_conn->diag_link->l1flags & DIAG_L1_DOESFULLINIT) && (rv==0)) {
			//TODO : somehow extract keybyte data for those cases...
			//original elm327s have the "atkw" command to get the keybytes, but clones suck.
			dp->state = STATE_ESTABLISHED;
			break;
		}

		if (rv < 0)
			break;

		/* Send the prepared message */
		if (diag_l2_proto_14230_send(d_l2_conn, &msg)) {
			rv=DIAG_ERR_GENERAL;
			break;
		}

		if (d_l2_conn->diag_link->l1flags & DIAG_L1_DOESL2FRAME)
			timeout = 200;
		else
			timeout = d_l2_conn->diag_l2_p2max + RXTOFFSET;

		/* And wait for a response, ISO14230 says will arrive in P2 */
		rv = diag_l2_proto_14230_int_recv(d_l2_conn, timeout);
		if (rv < 0)
			break;

		// _int_recv() should have filled  d_l2_conn->diag_msg properly.
		// check if message is OK :
		if (d_l2_conn->diag_msg->fmt & DIAG_FMT_BADCS) {
			rv=DIAG_ERR_BADCSUM;
			break;
		}

		switch (d_l2_conn->diag_msg->data[0]) {
		case DIAG_KW2K_RC_SCRPR:	/* StartComms positive response */

			d_l2_conn->diag_l2_kb1 = d_l2_conn->diag_msg->data[1];
			d_l2_conn->diag_l2_kb2 = d_l2_conn->diag_msg->data[2];
			d_l2_conn->diag_l2_physaddr = d_l2_conn->diag_msg->src;

			if (diag_l2_debug & DIAG_DEBUG_PROTO) {
				fprintf(stderr,
					FLFMT "_StartComms Physaddr=0x%X KB1=%02X, KB2=%02X\n",
					FL, d_l2_conn->diag_l2_physaddr, d_l2_conn->diag_l2_kb1, d_l2_conn->diag_l2_kb2);
			}
			rv=0;
			dp->state = STATE_ESTABLISHED ;
			break;
		case DIAG_KW2K_RC_NR:
			if (diag_l2_debug & DIAG_DEBUG_PROTO) {
				fprintf(stderr,
					FLFMT "_StartComms got neg response\n", FL);
			}
			rv=DIAG_ERR_ECUSAIDNO;
			break;
		default:
			if (diag_l2_debug & DIAG_DEBUG_PROTO) {
				fprintf(stderr,
					FLFMT "_StartComms got unexpected response 0x%X\n",
					FL, d_l2_conn->diag_msg->data[0]);
			}
			rv=DIAG_ERR_ECUSAIDNO;
			break;
		}	//switch data[0]
		break;	//case _FASTINIT
	/* 5 Baud init */
	case DIAG_L2_TYPE_SLOWINIT:
		in.type = DIAG_L1_INITBUS_5BAUD;
		in.addr = target;
		rv = diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_INITBUS, &in);

		//some L0 devices handle the full init transaction:
		if ((d_l2_conn->diag_link->l1flags & DIAG_L1_DOESFULLINIT) && (rv==0)) {
			dp->state = STATE_ESTABLISHED ;
			break;
		}

		if (rv < 0)
			break;

		/* Mode bytes are in 7-Odd-1, read as 8N1 and ignore parity */
		rv = diag_l1_recv (d_l2_conn->diag_link->diag_l2_dl0d, 0,
			cbuf, 2, 100);
		if (rv < 0)
			break;

		/* ISO14230 uses KB2 of 0x8F */
		if (cbuf[1] != 0x8f) {
			rv=DIAG_ERR_WRONGKB;
			break;
		}

		/* Note down the mode bytes */
		// KB1 : we eliminate the Parity bit (MSB !)
		d_l2_conn->diag_l2_kb1 = cbuf[0] & 0x7f;
		d_l2_conn->diag_l2_kb2 = cbuf[1];

		if ( (d_l2_conn->diag_link->l1flags
			& DIAG_L1_DOESSLOWINIT) == 0) {

			/*
			 * Now transmit KB2 inverted
			 */
			cbuf[0] = ~ d_l2_conn->diag_l2_kb2;
			rv = diag_l1_send (d_l2_conn->diag_link->diag_l2_dl0d, 0,
				cbuf, 1, d_l2_conn->diag_l2_p4min);

			/*
			 * And wait for the address byte inverted
			 */
			//first init cbuf[0] to the wrong value in case l1_recv gets nothing
			cbuf[0]= (uint8_t) target;
			rv = diag_l1_recv (d_l2_conn->diag_link->diag_l2_dl0d, 0,
				cbuf, 1, 350);

			if (cbuf[0] != ((~target) & 0xFF) ) {
				fprintf(stderr, FLFMT "_startcomms : addr mismatch %02X!=%02X\n",
					FL, cbuf[0], (uint8_t) ~target);
				rv=DIAG_ERR_WRONGKB;
				break;
			}

			if (diag_l2_debug & DIAG_DEBUG_INIT)
					fprintf(stderr, FLFMT "ISO14230 KB1=%02X KB2=%02X\n", FL,
						d_l2_conn->diag_l2_kb1, d_l2_conn->diag_l2_kb2);
		}
		rv=0;
		dp->state = STATE_ESTABLISHED ;
		break;	//case _SLOWINIT
	case DIAG_L2_TYPE_MONINIT:
		/* Monitor mode, don't send anything */
		dp->state = STATE_ESTABLISHED ;
		rv = 0;
		break;
	default:
		rv = DIAG_ERR_INIT_NOTSUPP;
		break;
	}	//end of switch dp->initype
	//At this point we just finished the handshake and got KB1 and KB2

	if (rv < 0) {
		free(dp);
		d_l2_conn->diag_l2_proto_data=NULL;	//delete pointer to dp
		return diag_iseterr(rv);
	}
	// Analyze keybytes and set modeflags properly. See
	// iso14230 5.2.4.1 & Table 8
	dp->modeflags |= ((d_l2_conn->diag_l2_kb1 & 1)? ISO14230_FMTLEN:0) |
			((d_l2_conn->diag_l2_kb1 & 2)? ISO14230_LENBYTE:0) |
			((d_l2_conn->diag_l2_kb1 & 4)? ISO14230_SHORTHDR:0) |
			((d_l2_conn->diag_l2_kb1 & 8)? ISO14230_LONGHDR:0);
	if (diag_l2_debug & DIAG_DEBUG_PROTO)
		fprintf(stderr, FLFMT "new modeflags=0x%04X\n", FL, dp->modeflags);
	//For now, we won't bother with Normal / Extended timings. We don't
	//need to unless we use the AccessTimingParameters service (scary)

	/*
	 * Now, we want to remove any rubbish left
	 * in inbound buffers, and wait for the bus to be
	 * quiet for a while before we will communicate
	 * (so that the next byte received is the first byte
	 * of an iso14230 frame, not a middle byte)
	 * We use 1/2 of P2max (inter response gap) or
	 * 5 * p4max (inter byte delay), whichever is larger
	 * a correct value to use
	 */
	wait_time = d_l2_conn->diag_l2_p2max / 2 ;
	if ((d_l2_conn->diag_l2_p4max * 5) > wait_time)
		wait_time = d_l2_conn->diag_l2_p4max * 5;

	while ( diag_l1_recv (d_l2_conn->diag_link->diag_l2_dl0d, 0,
		  data, sizeof(data), wait_time) != DIAG_ERR_TIMEOUT) ;

	/* And we're done */
	dp->state = STATE_ESTABLISHED ;

	return 0;
}
コード例 #17
0
ファイル: diag_l2_iso14230.c プロジェクト: shirou/freediag
/*
 * Just send the data
 *
 * We add the header and checksums here as appropriate, based on the keybytes
 *
 * We take the source and dest from the internal data NOT from the msg fields
 *
 * We also wait p3 ms
 * return 0 if ok, <0 if err
 * argument msg must have .len, .data, .dest and .src assigned.
 */
static int
diag_l2_proto_14230_send(struct diag_l2_conn *d_l2_conn, struct diag_msg *msg)
{
	int rv;
	uint8_t csum;
	unsigned int i;
	size_t len;
	uint8_t buf[MAXRBUF];
	int offset=0;	//data payload starts at buf[offset}
	struct diag_l2_14230 *dp;

	if (msg->len < 1)
			return diag_iseterr(DIAG_ERR_BADLEN);

	if (diag_l2_debug & DIAG_DEBUG_WRITE)
		fprintf(stderr,
			FLFMT "_send: dl2conn=%p msg=%p len=%d\n",
				FL, (void *)d_l2_conn, (void *)msg, msg->len);

	dp = (struct diag_l2_14230 *)d_l2_conn->diag_l2_proto_data;


	//if L1 requires headerless data, send directly :
	if (d_l2_conn->diag_link->l1flags & DIAG_L1_DATAONLY) {
		rv = diag_l1_send (d_l2_conn->diag_link->diag_l2_dl0d, NULL,
				msg->data, msg->len, d_l2_conn->diag_l2_p4min);
		return rv? diag_iseterr(rv):0;
	}

	/* Build the new message */

	if ((dp->modeflags & ISO14230_LONGHDR) || !(dp->modeflags & ISO14230_SHORTHDR)) {
		//we use full headers if they're supported or if we don't have a choice.
		//set the "address present" bit
		//and functional addressing if applicable
		if (dp->modeflags & ISO14230_FUNCADDR)
			buf[0] = 0xC0;
		else
			buf[0] = 0x80;

		/* If user supplied addresses, use them, else use the originals */
		if (msg->dest)
			buf[1] = msg->dest;
		else
			buf[1] = dp->dstaddr;

		if (msg->src)
			buf[2] = msg->src;
		else
			buf[2] = dp->srcaddr;
		offset = 3;
	} else if (dp->modeflags & ISO14230_SHORTHDR) {
		//here, short addressless headers are required.
		//basic format byte : 0
		buf[0]=0;
		offset = 1 ;
	}



	if ((dp->modeflags & ISO14230_FMTLEN)|| !(dp->modeflags & ISO14230_LENBYTE))  {
		//if ECU supports length in format byte, or doesn't support extra len byte
		if (msg->len < 64) {
			buf[0] |= msg->len;
		} else {
			//len >=64, can we use a length byte ?
			if (dp->modeflags & ISO14230_LENBYTE) {
				buf[offset] = msg->len;
				offset += 1;
			} else {
				fprintf(stderr, FLFMT "can't send >64 byte msgs to this ECU !\n", FL);
				return diag_iseterr(DIAG_ERR_BADLEN);
			}
		}
	} else if (dp->modeflags & ISO14230_LENBYTE) {
		// if the ecu needs a length byte
		buf[offset] = msg->len;
		offset += 1;
	}

	memcpy(&buf[offset], msg->data, msg->len);

	len = msg->len + offset;	/* data + hdr */

	if ((d_l2_conn->diag_link->l1flags & DIAG_L1_DOESL2CKSUM) == 0) {
		/* We must add checksum, which is sum of bytes */
		for (i = 0, csum = 0; i < len; i++)
			csum += buf[i];
		buf[len] = csum;
		len++;				/* + checksum */
	}

	if ((diag_l2_debug & DIAG_DEBUG_WRITE) && (diag_l2_debug & DIAG_DEBUG_DATA)) {
		fprintf(stderr, FLFMT "_send: ", FL);
		diag_data_dump(stderr, buf, len);
		fprintf(stderr, "\n");
	}

	/* Wait p3min milliseconds, but not if doing fast/slow init */
	if (dp->state == STATE_ESTABLISHED)
		diag_os_millisleep(d_l2_conn->diag_l2_p3min);

	rv = diag_l1_send (d_l2_conn->diag_link->diag_l2_dl0d, NULL,
		buf, len, d_l2_conn->diag_l2_p4min);

	return rv? diag_iseterr(rv):0;
}
/* fake loss measures */
int fake_loss_measure_data()
{
  struct timeval tv; /* measuring time */
  int elapsed; /* elapsed time */
  int speed;
  
  if (counter == 0)
  {
    gettimeofday(&tv0, 0);
  }
  
  diag_os_millisleep(250);

  /* get elapsed time */
  gettimeofday(&tv, 0);
  elapsed = MILLIS(tv) - MILLIS(tv0);
  elapsed += 11000;
  
  if      (elapsed < 11983) speed = 89*10000/36;
  else if (elapsed < 12723) speed = 88*10000/36;
  else if (elapsed < 13473) speed = 87*10000/36;
  else if (elapsed < 14713) speed = 85*10000/36;
  else if (elapsed < 15713) speed = 84*10000/36;
  else if (elapsed < 16213) speed = 83*10000/36;
  else if (elapsed < 16963) speed = 82*10000/36;
  else if (elapsed < 17463) speed = 81*10000/36;
  else if (elapsed < 18463) speed = 80*10000/36;
  else if (elapsed < 19463) speed = 79*10000/36;
  else if (elapsed < 20213) speed = 78*10000/36;
  else if (elapsed < 20963) speed = 77*10000/36;
  else if (elapsed < 22463) speed = 76*10000/36;
  else if (elapsed < 22963) speed = 75*10000/36;
  else if (elapsed < 23713) speed = 74*10000/36;
  else if (elapsed < 25213) speed = 73*10000/36;
  else if (elapsed < 26453) speed = 72*10000/36;
  else if (elapsed < 27203) speed = 71*10000/36;
  else if (elapsed < 27953) speed = 70*10000/36;
  else if (elapsed < 29193) speed = 69*10000/36;
  else if (elapsed < 29943) speed = 68*10000/36;
  else if (elapsed < 30693) speed = 67*10000/36;
  else if (elapsed < 32183) speed = 66*10000/36;
  else if (elapsed < 32933) speed = 65*10000/36;
  else if (elapsed < 33683) speed = 64*10000/36;
  else if (elapsed < 34683) speed = 63*10000/36;
  else if (elapsed < 35433) speed = 62*10000/36;
  else if (elapsed < 36433) speed = 61*10000/36;
  else if (elapsed < 37183) speed = 60*10000/36;
  else if (elapsed < 38433) speed = 59*10000/36;
  else if (elapsed < 39433) speed = 58*10000/36;
  else if (elapsed < 40183) speed = 57*10000/36;
  else if (elapsed < 40683) speed = 56*10000/36;
  else if (elapsed < 42183) speed = 55*10000/36;
  else if (elapsed < 43183) speed = 54*10000/36;
  else if (elapsed < 44683) speed = 53*10000/36;
  else if (elapsed < 45933) speed = 52*10000/36;
  else if (elapsed < 47183) speed = 51*10000/36;
  else if (elapsed < 48183) speed = 50*10000/36;
  else if (elapsed < 49433) speed = 49*10000/36;
  else                      speed = 48*10000/36;
  
  counter++;
  
  return (speed);
}