Example #1
0
/*
 * 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;
}
Example #2
0
//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;
}
Example #3
0
/*
 * 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;
}
Example #4
0
//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;
}