コード例 #1
0
ファイル: diag_l2_iso14230.c プロジェクト: shirou/freediag
/*
 * Protocol receive routine
 *
 * Will sleep until a complete set of responses has been received, or fail
 * with a timeout error
 *
 * The interbyte type in data from an ECU is between P1Min and P1Max
 * The intermessage time for part of one response is P2Min and P2Max
 *
 * If we are running with an intelligent L1 interface, then we will be
 * getting one message per frame, and we will wait a bit longer
 * for extra messages
 */
static int
diag_l2_proto_14230_recv(struct diag_l2_conn *d_l2_conn, unsigned int timeout,
	void (*callback)(void *handle, struct diag_msg *msg),
	void *handle)
{
	int rv;

	/* Call internal routine */
	rv = diag_l2_proto_14230_int_recv(d_l2_conn, timeout);

	if (rv < 0)	/* Failure */
		return rv;

	if (diag_l2_debug & DIAG_DEBUG_READ)
		fprintf(stderr, FLFMT "_int_recv : handle=%p timeout=%u\n", FL,
			(void *)handle, timeout);	//%pcallback! we won't try to printf the callback pointer.

	/*
	 * Call user callback routine
	 */
	if (callback)
		callback(handle, d_l2_conn->diag_msg);

	/* No longer needed */
	diag_freemsg(d_l2_conn->diag_msg);
	d_l2_conn->diag_msg = NULL;

	if (diag_l2_debug & DIAG_DEBUG_READ)
		fprintf(stderr, FLFMT "_recv callback completed\n", FL);

	return 0;
}
コード例 #2
0
ファイル: diag_l2_iso14230.c プロジェクト: shirou/freediag
static int
diag_l2_proto_14230_stopcomms(struct diag_l2_conn* pX)
{
	struct diag_msg stopmsg={0};
	struct diag_msg *rxmsg;
	uint8_t stopreq=DIAG_KW2K_SI_SPR;
	int errval=0;
	char * debugstr;

	stopmsg.len=1;
	stopmsg.data=&stopreq;
	stopmsg.dest=0;
	stopmsg.src=0;

	rxmsg=diag_l2_proto_14230_request(pX, &stopmsg, &errval);

	if (rxmsg != NULL) {
		//we got a message;
		if (!errval) {
			//no error : positive response from ECU.
			debugstr="ECU acknowledged request (RC=";
		} else {
			debugstr="ECU refused request; connection will time-out in 5s.(RC=";
		}
		errval=rxmsg->data[0];
		diag_freemsg(rxmsg);
	} else {
		//no message received...
		debugstr="ECU did not respond to request, connection will timeout in 5s. (err=";
	}

	if (diag_l2_debug & DIAG_DEBUG_CLOSE) {
		fprintf(stderr, FLFMT "_stopcomms: %s0x%02X).\n", FL, debugstr, errval);
	}

	//and free() what startcomms alloc'ed.
	if (pX->diag_l2_proto_data) {
		free(pX->diag_l2_proto_data);
		pX->diag_l2_proto_data=NULL;
	}

	return 0;
}
コード例 #3
0
ファイル: diag_l2_vag.c プロジェクト: shirou/freediag
/*
 * Protocol receive routine
 *
 * Will sleep until a complete set of responses has been received, or fail
 * with a timeout error
 *
 * The interbyte type in data from an ecu is between P1Min and P1Max
 * The intermessage time for part of one response is P2Min and P2Max
 *
 * If we are running with an intelligent L1 interface, then we will be
 * getting one message per frame, and we will wait a bit longer
 * for extra messages
 */
static int
diag_l2_proto_vag_recv(struct diag_l2_conn *d_l2_conn, unsigned int timeout,
                       void (*callback)(void *handle, struct diag_msg *msg),
                       void *handle)
{
    uint8_t data[256];
    int rv;
    int datalen;

    /* Call internal routine */
    rv = diag_l2_proto_vag_int_recv(d_l2_conn, timeout, data, &datalen);

    if (rv <= 0)	/* Failure */
        return rv;

    if (diag_l2_debug & DIAG_DEBUG_READ)
    {
        fprintf(stderr, FLFMT "calling rcv callback, handle=%p\n", FL,
                (void *)handle);	//%pcallback! we won't try to printf the callback pointer.
    }

    /*
     * Call user callback routine
     */
    if (callback)
        callback(handle, d_l2_conn->diag_msg);

    /* No longer needed */
    diag_freemsg(d_l2_conn->diag_msg);
    d_l2_conn->diag_msg = NULL;

    if (diag_l2_debug & DIAG_DEBUG_READ)
    {
        fprintf(stderr, FLFMT "rcv callback completed\n", FL);
    }

    return 0;
}
コード例 #4
0
ファイル: diag_l2_iso14230.c プロジェクト: shirou/freediag
//iso14230 diag_l2_proto_request. See diag_l2.h
//This handles busyRepeatRequest and RspPending negative responses.
//return NULL if failed, or a newly alloced diag_msg if succesful.
//Caller must free that diag_msg.
//Sends using diag_l2_send() in order to have the timestamps updated
static struct diag_msg *
diag_l2_proto_14230_request(struct diag_l2_conn *d_l2_conn, struct diag_msg *msg,
		int *errval)
{
	int rv;
	struct diag_msg *rmsg = NULL;
	int retries=3;	//if we get a BusyRepeatRequest response.

	*errval=0;

	rv = diag_l2_send(d_l2_conn, msg);
	if (rv < 0) {
		*errval = rv;
		return diag_pseterr(rv);
	}

	while (1) {
		rv = diag_l2_proto_14230_int_recv(d_l2_conn,
			d_l2_conn->diag_l2_p2max + 10);

		if (rv < 0) {
			*errval = DIAG_ERR_TIMEOUT;
			return diag_pseterr(rv);
		}

		/*
		 * The connection now has the received message data
		 * stored, remove it and deal with it
		 */
		rmsg = d_l2_conn->diag_msg;
		d_l2_conn->diag_msg = NULL;

		/* Got a Error message */
		if (rmsg->data[0] == DIAG_KW2K_RC_NR) {
			if (rmsg->data[2] == DIAG_KW2K_RC_B_RR) {
				/*
				 * Msg is busyRepeatRequest
				 * So do a send again (if retries>0)
				 */

				if (retries > 0) {
					rv = diag_l2_send(d_l2_conn, msg);
				} else {
					rv=DIAG_ERR_GENERAL;
					fprintf(stderr, FLFMT "got too many BusyRepeatRequest responses!\n", FL);
				}

				retries--;

				if (rv < 0) {
					*errval = rv;
					return diag_pseterr(rv);
				}
				if (diag_l2_debug & DIAG_DEBUG_PROTO)
					fprintf(stderr, FLFMT "got BusyRepeatRequest: retrying...\n", FL);

				diag_freemsg(rmsg);
				continue;
			}

			if (rmsg->data[2] == DIAG_KW2K_RC_RCR_RP) {
				/*
				 * Msg is a requestCorrectlyRcvd-RspPending
				 * so do read again
				 */
				if (diag_l2_debug & DIAG_DEBUG_PROTO)
					fprintf(stderr, FLFMT "got RspPending: retrying...\n", FL);

				diag_freemsg(rmsg);
				continue;
			}
			/* Some other type of error */
			*errval= DIAG_ERR_ECUSAIDNO;
			break;
		} else {
			/* Success */
			break;
		}
	}
	/* Return the message to user, who is responsible for freeing it */
	return rmsg;
}
コード例 #5
0
ファイル: diag_l2_iso14230.c プロジェクト: shirou/freediag
/*
 * Internal receive function: does all the message building, but doesn't
 * do call back. Strips header and checksum; if address info was present
 * then msg->dest and msg->src are !=0.
 *
 * Data from the first message is put into *data, and len into *datalen if
 * those pointers are non-null.
 *
 * If the L1 interface is clever (DOESL2FRAME), then each read will give
 * us a complete message, and we will wait a little bit longer than the normal
 * timeout to detect "end of all responses"
 *
 *Similar to 9141_int_recv; timeout has to be long enough to catch at least
 *1 byte.
 * XXX this implementation doesn't accurately detect end-of-responses, because
 * it's trying to read MAXRBUF (a large number) of bytes, for every state.
 *if there is a short (say 3 byte) response from the ECU while in state 1,
 *the timer will expire because it's waiting for MAXBUF
 *bytes (MAXRBUF is much larger than any message, by design). Then, even
 *though there are no more responses, we still do another MAXRBUF read
 *in state 2 for P2min, and a last P2max read in state 3 !
 * TODO: change state1 to read 1 byte maybe ?
 * I think a more rigorous way to do this (if L1 doesn't do L2 framing), would
 * be to loop, reading 1 byte at a time, with timeout=P1max or p2min to split
 * messages, and timeout=P2max to detect the last byte of a response... this
 * means calling diag_l1_recv a whole lot more often however.

 */
static int
diag_l2_proto_14230_int_recv(struct diag_l2_conn *d_l2_conn, unsigned int timeout)
{
	struct diag_l2_14230 *dp;
	int rv, l1_doesl2frame, l1flags;
	unsigned int tout;
	int state;
	struct diag_msg	*tmsg, *lastmsg;

#define ST_STATE1	1	/* Start */
#define ST_STATE2	2	/* Interbyte */
#define ST_STATE3	3	/* Inter message */

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

	if (diag_l2_debug & DIAG_DEBUG_READ)
		fprintf(stderr,
			FLFMT "_int_recv dl2conn=%p offset=0x%X, tout=%u\n",
				FL, (void *) d_l2_conn, dp->rxoffset, timeout);

	state = ST_STATE1;
	tout = timeout;

	/* Clear out last received messages if not done already */
	if (d_l2_conn->diag_msg) {
		diag_freemsg(d_l2_conn->diag_msg);
		d_l2_conn->diag_msg = NULL;
	}

	l1flags = d_l2_conn->diag_link->l1flags;

	if (l1flags & DIAG_L1_DOESL2FRAME)
		l1_doesl2frame = 1;
	else
		l1_doesl2frame = 0;

	if (l1_doesl2frame) {
		if (timeout < SMART_TIMEOUT)	/* Extend timeouts */
			timeout += 100;
	}


	while (1) {
		switch (state) {
		case ST_STATE1:
			tout = timeout;
			break;
		case ST_STATE2:
			//State 2 : if we're between bytes of the same message; if we timeout with P2min it's
			//probably because the message is ended.
			tout = d_l2_conn->diag_l2_p2min - 2;
			if (tout < d_l2_conn->diag_l2_p1max)
				tout = d_l2_conn->diag_l2_p1max;
			break;
		case ST_STATE3:
			//State 3: we timed out during state 2
			if (l1_doesl2frame)
				tout = 150;	/* Arbitrary, short, value ... */
			else
				tout = d_l2_conn->diag_l2_p2max;
		}

		/* Receive data into the buffer */

		if (diag_l2_debug & DIAG_DEBUG_PROTO)
			fprintf(stderr, FLFMT "before recv, state=%d timeout=%u, rxoffset %d\n",
				FL, state, tout, dp->rxoffset);


		/*
		 * In l1_doesl2frame mode, we get full frames, so we don't
		 * do the read in state2
		 */
		if ( (state == ST_STATE2) && l1_doesl2frame )
			rv = DIAG_ERR_TIMEOUT;
		else
			rv = diag_l1_recv(d_l2_conn->diag_link->diag_l2_dl0d, 0,
				&dp->rxbuf[dp->rxoffset],
				sizeof(dp->rxbuf) - dp->rxoffset,
				tout);

		if (diag_l2_debug & DIAG_DEBUG_PROTO)
			fprintf(stderr,
				FLFMT "after recv, rv=%d rxoffset=%d\n", FL, rv, dp->rxoffset);


		if (rv == DIAG_ERR_TIMEOUT) {
			/* Timeout, end of message, or end of responses */
			switch (state) {
			case ST_STATE1:
				/*
				 * 1st read, if we got 0 bytes, just return
				 * the timeout error
				 */
				if (dp->rxoffset == 0)
					break;
				/*
				 * Otherwise see if there are more bytes in
				 * this message,
				 */
				state = ST_STATE2;
				continue;
			case ST_STATE2:
				/*
				 * End of that message, maybe more to come
				 * Copy data into a message
				 */
				tmsg = diag_allocmsg((size_t)dp->rxoffset);
				if (tmsg == NULL)
					return diag_iseterr(DIAG_ERR_NOMEM);
				memcpy(tmsg->data, dp->rxbuf, (size_t)dp->rxoffset);
				tmsg->rxtime = diag_os_chronoms(0);
				dp->rxoffset = 0;
				/*
				 * ADD message to list
				 */
				diag_l2_addmsg(d_l2_conn, tmsg);
				if (d_l2_conn->diag_msg == tmsg) {

					if ((diag_l2_debug & DIAG_DEBUG_DATA) && (diag_l2_debug & DIAG_DEBUG_PROTO)) {
						fprintf(stderr, FLFMT "Copying %u bytes to data: ",
							FL, tmsg->len);
						diag_data_dump(stderr, tmsg->data, tmsg->len);
						fprintf(stderr, "\n");
					}

				}
				state = ST_STATE3;
				continue;
			case ST_STATE3:
				/*
				 * No more messages, but we did get one
				 */
				rv = d_l2_conn->diag_msg->len;
				break;
			}
			if (state == ST_STATE3)
				break;
		}	//if diag_err_timeout

		if (rv<=0)
			break;

		/* Data received OK */
		dp->rxoffset += rv;

		if (dp->rxoffset && (dp->rxbuf[0] == '\0')) {
			/*
			 * We get this when in
			 * monitor mode and there is
			 * a fastinit, pretend it didn't exist
			 */
			dp->rxoffset--;
			if (dp->rxoffset)
				memcpy(&dp->rxbuf[0], &dp->rxbuf[1],
					(size_t)dp->rxoffset);
			continue;
		}
		if ( (state == ST_STATE1) || (state == ST_STATE3) ) {
			/*
			 * Got some data in state1/3, now we're in a message
			 */
			state = ST_STATE2;
		}
	}

	/*
	 * Now check the messages that we have checksum etc, stripping
	 * off headers etc
	 */
	if (rv < 0)
		return rv;

	tmsg = d_l2_conn->diag_msg;
	lastmsg = NULL;

	while (tmsg != NULL) {
		int datalen=0;
		uint8_t hdrlen=0, source=0, dest=0;


		if ((l1flags & DIAG_L1_NOHDRS)==0) {

			dp = (struct diag_l2_14230 *)d_l2_conn->diag_l2_proto_data;
			rv = diag_l2_proto_14230_decode( tmsg->data,
				tmsg->len,
				&hdrlen, &datalen, &source, &dest,
				dp->first_frame);

			if (rv <= 0 || rv>255)		/* decode failure */
				return diag_iseterr(rv);

			// check for sufficient data: (rv = expected len = hdrlen + datalen + ckslen)
			if (l1_doesl2frame == 0) {
				if ((!(l1flags & DIAG_L1_STRIPSL2CKSUM) && (tmsg->len < rv)) ||
						((l1flags & DIAG_L1_STRIPSL2CKSUM) && (tmsg->len < (rv-1))))
					return diag_iseterr(DIAG_ERR_INCDATA);
			}
		}



		/*
		 * If L1 isnt doing L2 framing then it is possible
		 * we have misframed this message and it is infact
		 * more than one message, so see if we can decode it
		 */
		if ((l1_doesl2frame == 0) && (rv < tmsg->len)) {
			/*
			 * This message contains more than one
			 * data frame (because it arrived with
			 * odd timing), this means we have to
			 * do horrible copy about the data
			 * things ....
			 */
			struct diag_msg	*amsg;
			amsg = diag_dupsinglemsg(tmsg);
			if (amsg == NULL) {
				return diag_iseterr(DIAG_ERR_NOMEM);
			}
			amsg->len = (uint8_t) rv;
			tmsg->len -= (uint8_t) rv;
			tmsg->data += rv;

			/*  Insert new amsg before old msg */
			amsg->next = tmsg;
			if (lastmsg == NULL)
				d_l2_conn->diag_msg = amsg;
			else
				lastmsg->next = amsg;

			tmsg = amsg; /* Finish processing this one */
		}

		if (diag_l2_debug & DIAG_DEBUG_PROTO)
			fprintf(stderr,
			FLFMT "msg %p decode/rejig done rv=%d hdrlen=%u datalen=%d src=%02X dst=%02X\n",
				FL, (void *)tmsg, rv, hdrlen, datalen, source, dest);


		tmsg->fmt = DIAG_FMT_FRAMED;

		if ((l1flags & DIAG_L1_NOHDRS)==0) {
			if ((tmsg->data[0] & 0xC0) == 0xC0) {
				tmsg->fmt |= DIAG_FMT_ISO_FUNCADDR;
			}
		}


		//if cs wasn't stripped, we check it:
		if ((l1flags & DIAG_L1_STRIPSL2CKSUM) == 0) {
			uint8_t calc_sum=diag_cks1(tmsg->data, (tmsg->len)-1);
			if (calc_sum != tmsg->data[tmsg->len -1]) {
				fprintf(stderr, FLFMT "Bad checksum: needed %02X,got%02X. Data:",
					FL, calc_sum, tmsg->data[tmsg->len -1]);
				tmsg->fmt |= DIAG_FMT_BADCS;
				diag_data_dump(stderr, tmsg->data, tmsg->len -1);
				fprintf(stderr, "\n");
			}
			/* and remove checksum byte */
			tmsg->len--;

		}
		tmsg->fmt |= DIAG_FMT_CKSUMMED;	//checksum was verified

		tmsg->src = source;
		tmsg->dest = dest;
		tmsg->data += hdrlen;	/* Skip past header */
		tmsg->len -= hdrlen; /* remove header */



		dp->first_frame = 0;

		lastmsg = tmsg;
		tmsg = tmsg->next;
	}
	return rv;
}
コード例 #6
0
ファイル: diag_l2_vag.c プロジェクト: shirou/freediag
static int
diag_l2_proto_vag_int_recv(struct diag_l2_conn *d_l2_conn,
                           UNUSED(unsigned int timeout),
                           UNUSED(uint8_t *data),
                           UNUSED(int *datalen))
{
    struct diag_l2_vag *dp;
    int rv = 0;
    /*	struct diag_msg	*tmsg;*/

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

    if (diag_l2_debug & DIAG_DEBUG_READ)
        fprintf(stderr,
                FLFMT "diag_l2_vag_intrecv offset %X\n",
                FL, dp->rxoffset);

    /* Clear out last received message if not done already */
    if (d_l2_conn->diag_msg)
    {
        diag_freemsg(d_l2_conn->diag_msg);
        d_l2_conn->diag_msg = NULL;
    }

    /*
     * And receive the new message
     */

#if notdef

    /*
     * Now check the messages that we have checksum etc, stripping
     * off headers etc
     */
    if (rv >= 0)
    {
        tmsg = d_l2_conn->diag_msg;

        while (tmsg)
        {
            struct diag_l2_vag *dp;
            int datalen;
            uint8_t hdrlen, source, dest;

            /*
             * We have the message with the header etc, we
             * need to strip the header and checksum
             */
            dp = (struct diag_l2_vag *)d_l2_conn->diag_l2_proto_data;
            rv = diag_l2_proto_vag_decode( tmsg->data,
                                           tmsg->len,
                                           &hdrlen, &datalen, &source, &dest,
                                           dp->first_frame);

            if (rv < 0)		/* decode failure */
            {
                return rv;
            }

            if (diag_l2_debug & DIAG_DEBUG_PROTO)
                fprintf(stderr, "msg %X decode done rv %d hdrlen %d datalen %d source %02X dest %02X\n",
                        tmsg, rv, hdrlen, datalen, source, dest);

            if (tmsg->data[0] & 0xC0 == 0xC0)
            {
                tmsg->fmt = DIAG_FMT_ISO_FUNCADDR;
            } else {
                tmsg->fmt = 0;
            }

            tmsg->fmt |= DIAG_FMT_FRAMED;
            tmsg->fmt |= DIAG_FMT_CKSUMMED;

            tmsg->src = source;
            tmsg->dest = dest;
            tmsg->data += hdrlen;	/* Skip past header */
            tmsg->len -= (hdrlen + 1); /* And remove hdr/cksum */

            dp->first_frame = 0;

            tmsg = tmsg->next;
        }
    }
#endif
    return rv;
}
コード例 #7
0
ファイル: diag_l2_iso14230.c プロジェクト: remspoor/freediag
//iso14230 diag_l2_proto_request. See diag_l2.h
//This handles busyRepeatRequest and RspPending negative responses.
//return NULL if failed, or a newly alloced diag_msg if succesful.
//Caller must free that diag_msg.
//Sends using diag_l2_send() in order to have the timestamps updated
static struct diag_msg *
diag_l2_proto_14230_request(struct diag_l2_conn *d_l2_conn, struct diag_msg *msg,
		int *errval)
{
	int rv;
	struct diag_msg *rmsg = NULL;
	int retries=3;	//if we get a BusyRepeatRequest response.

	*errval=0;

	rv = diag_l2_send(d_l2_conn, msg);
	if (rv < 0) {
		*errval = rv;
		return diag_pseterr(rv);
	}

	while (1) {
		/* do read only if no messages pending */
		if (!d_l2_conn->diag_msg) {
			rv = diag_l2_proto_14230_int_recv(d_l2_conn,
				d_l2_conn->diag_l2_p2max + 10);

			if (rv < 0) {
				*errval = DIAG_ERR_TIMEOUT;
				if (rv == DIAG_ERR_TIMEOUT) {
					return NULL;
				} else {
					return diag_pseterr(rv);
				}
			}
		}

		/*
		 * The connection now has the received message(s)
		 * stored. Temporarily remove from dl2c
		 */
		rmsg = d_l2_conn->diag_msg;
		d_l2_conn->diag_msg = NULL;

		/* Check for negative response */
		if (rmsg->data[0] != DIAG_KW2K_RC_NR) {
			/* Success */
			break;
		}

		if (rmsg->data[2] == DIAG_KW2K_RC_B_RR) {
			/*
			 * Msg is busyRepeatRequest
			 * So send again (if retries>0).
			 *
			 * Is there any possibility that we would have received 2 messages,
			 * {busyrepeatrequest + a valid (unrelated) response} ?
			 * Not sure, let's simply discard everything.
			 */
			diag_freemsg(rmsg);

			if (retries > 0) {
				rv = diag_l2_send(d_l2_conn, msg);
			} else {
				rv=DIAG_ERR_GENERAL;
				fprintf(stderr, FLFMT "got too many BusyRepeatRequest responses!\n", FL);
			}

			retries--;

			if (rv < 0) {
				*errval = rv;
				return diag_pseterr(rv);
			}
			if (diag_l2_debug & DIAG_DEBUG_PROTO)
				fprintf(stderr, FLFMT "got BusyRepeatRequest: retrying...\n", FL);

			continue;
		}

		if (rmsg->data[2] == DIAG_KW2K_RC_RCR_RP) {
			/*
			 * Msg is a requestCorrectlyRcvd-RspPending
			 * so do read again
			 */
			if (diag_l2_debug & DIAG_DEBUG_PROTO)
				fprintf(stderr, FLFMT "got RspPending: retrying...\n", FL);

			/* reattach the rest of the chain, in case the good response
			 * was already received
			 */
			d_l2_conn->diag_msg = rmsg->next;
			rmsg->next = NULL;
			diag_freemsg(rmsg);
			continue;
		}
		/* Some other type of error */
		*errval= DIAG_ERR_ECUSAIDNO;
		break;
	}	//while 1
	/* Return the message to user, who is responsible for freeing it */
	return rmsg;
}
コード例 #8
0
ファイル: diag_l2_iso14230.c プロジェクト: remspoor/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;

	if (d_l2_conn->diag_link->l1flags & DIAG_L1_DOESL2FRAME) {
		dp->first_frame = 0;
	} else {
		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]
		// finished with the response message:
		diag_freemsg(d_l2_conn->diag_msg);
		d_l2_conn->diag_msg = NULL;
		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->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->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->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->l2_dl0d, 0,
		  data, sizeof(data), wait_time) != DIAG_ERR_TIMEOUT) ;

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

	return 0;
}