예제 #1
0
// Allocates one new ecu response and fills it with given data.
// (not used yet, here for "just in case")
struct sim_ecu_response*
sim_new_ecu_response_bin(const uint8_t* data, const uint8_t len)
{
	struct sim_ecu_response *resp;

	if (diag_calloc(&resp, 1))
		return diag_pseterr(DIAG_ERR_NOMEM);
	//resp = calloc(1, sizeof(struct sim_ecu_response));
	resp->data = NULL;
	resp->len = 0;
	resp->text = NULL;
	resp->next = NULL;

	if ((len > 0) && (data != NULL)) {
		if (diag_calloc(&resp->data, len)) {
			free(resp);
			return diag_pseterr(DIAG_ERR_NOMEM);
		}
		//resp->data = calloc(len, sizeof(uint8_t));
		memcpy(resp->data, data, len);
		resp->len = len;
	}

	return resp;
}
예제 #2
0
struct diag_msg *
dl2p_raw_request(struct diag_l2_conn *d_l2_conn, struct diag_msg *msg,
		int *errval) {
	int rv;
	struct diag_msg *rmsg = NULL;
	uint8_t rxbuf[MAXRBUF];

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

	/* And wait for response */
	rv = diag_l1_recv (d_l2_conn->diag_link->l2_dl0d,
		0, rxbuf, sizeof(rxbuf), 1000);

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

	/*
	 * Ok, alloc a message
	 */
	rmsg = diag_allocmsg((size_t)rv);
	if (rmsg == NULL) {
		return diag_pseterr(DIAG_ERR_NOMEM);
	}
	memcpy(&rmsg->data, rxbuf, (size_t)rv);	/* Data */
	rmsg->fmt = 0;
	rmsg->rxtime = diag_os_getms();

	return rmsg;
}
예제 #3
0
// Allocates one new ecu response and fills it with given text.
struct sim_ecu_response*
sim_new_ecu_response_txt(const char* text)
{
	struct sim_ecu_response *resp;
	int rv;

	if ((rv=diag_calloc(&resp, 1)))
		return diag_pseterr(rv);

	resp->data = NULL;
	resp->len = 0;
	resp->text = NULL;
	resp->next = NULL;

	if ((text != NULL) && strlen(text)) {
		if ((rv=diag_calloc(&(resp->text), strlen(text)+1))) {
			free(resp);
			return diag_pseterr(rv);
		}

		strncpy(resp->text, text, strlen(text));
	}

	return resp;
}
예제 #4
0
/*
 * Open the diagnostic device, returns a file descriptor
 * records original state of term interface so we can restore later
 */
static struct diag_l0_device *
diag_l0_muleng_open(const char *subinterface, int iProtocol)
{
	int rv;
	struct diag_l0_device *dl0d;
	struct diag_l0_muleng_device *dev;
	struct diag_serial_settings set;

	if (diag_l0_debug & DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "open subinterface %s protocol %d\n",
			FL, subinterface, iProtocol);
	}

	diag_l0_muleng_init();

	if ((rv=diag_calloc(&dev, 1)))
		return diag_pseterr(rv);

	dev->protocol = iProtocol;

	dl0d = diag_l0_new(&diag_l0_me, (void *)dev);
	if (!dl0d) {
		free(dev);
		return diag_pseterr(rv);
	}
	/* try to open TTY */
	if ((rv=diag_tty_open(dl0d, subinterface))) {
		diag_l0_del(dl0d);
		free(dev);
		return diag_pseterr(rv);
	}

	/* And set to 19200 baud , 8N1 */

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

	if ((rv=diag_tty_setup(dl0d, &set))) {
		diag_l0_muleng_close(dl0d);
		return diag_pseterr(rv);
	}

	/* And set DTR high and RTS low to power the device */
	if ((rv=diag_tty_control(dl0d, 1, 0))) {
		diag_l0_muleng_close(dl0d);
		return diag_pseterr(rv);
	}

	diag_tty_iflush(dl0d);	/* Flush unread input */

	return dl0d ;
}
예제 #5
0
// Opens the simulator DB file.
static struct diag_l0_device *
diag_l0_sim_open(UNUSED(const char *subinterface), int iProtocol)
{
	int rv;
	struct diag_l0_device *dl0d;
	struct diag_l0_sim_device *dev;

	// If we're doing debugging, print to stderr
	if (diag_l0_debug & DIAG_DEBUG_OPEN)
		fprintf(stderr, FLFMT "open simfile %s proto=%d\n", FL, simfile, iProtocol);

	diag_l0_sim_init();

	// Create diag_l0_sim_device:
	if ((rv=diag_calloc(&dev, 1)))
		return diag_pseterr(rv);

	dev->protocol = iProtocol;

	// Create diag_l0_device:
	if ((rv=diag_calloc(&dl0d, 1))) {
		free(dev);
		return diag_pseterr(rv);
	}

	dl0d->dl0_handle = dev;
	dl0d->dl0 = &diag_l0_sim;

	if ((rv=diag_calloc(&dl0d->name, strlen(simfile)+1))) {
		free(dev);
		free(dl0d);
		return diag_pseterr(rv);
	}
	strcpy(dl0d->name, simfile);

	// Open the DB file:
	if ((dev->fp = fopen(dl0d->name, "r")) == NULL) {
		fprintf(stderr, FLFMT "Unable to open file \"%s\": ", FL, dl0d->name);
		perror(NULL);
		free(dl0d->name);
		free(dev);
		free(dl0d);
		return diag_pseterr(DIAG_ERR_GENERAL);
	}

	rewind(dev->fp);

	// Read the configuration flags from the db file:
	sim_read_cfg(dev->fp);

	return dl0d;
}
예제 #6
0
/*
 * Open the diagnostic device, returns a file descriptor
 * records original state of term interface so we can restore later
 */
static struct diag_l0_device *
diag_l0_dumb_open(const char *subinterface, int iProtocol)
{
	int rv;
	struct diag_l0_device *dl0d;
	struct diag_l0_dumb_device *dev;

	if (diag_l0_debug & DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "open subinterface %s protocol %d\n",
			FL, subinterface, iProtocol);
	}

	diag_l0_dumb_init();	 //make sure it is initted

	if ((rv=diag_calloc(&dev, 1)))
		return diag_pseterr(DIAG_ERR_NOMEM);

	dev->protocol = iProtocol;

	dl0d = diag_l0_new(&diag_l0_dumb, (void *)dev);
	if (!dl0d) {
		free(dev);
		return diag_pseterr(rv);
	}
	/* try to open TTY */
	if ((rv=diag_tty_open(dl0d, subinterface))) {
		diag_l0_del(dl0d);
		free(dev);
		return diag_pseterr(rv);
	}

	/*
	 * We set RTS to low, and DTR high, because this allows some
	 * interfaces to work than need power from the DTR/RTS lines;
	 * this is altered according to dumb_flags.
	 */
	if (diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), (dumb_flags & SET_RTS)) < 0) {
		diag_l0_dumb_close(&dl0d);
		return diag_pseterr(DIAG_ERR_GENERAL);
	}

	if (dumb_flags & DUMBDEFAULTS)
		dumb_flags = DUMBDEFAULTS & MAN_BREAK;

	(void)diag_tty_iflush(dl0d);	/* Flush unread input */

	return dl0d;
}
예제 #7
0
파일: diag_l3.c 프로젝트: remspoor/freediag
/*
 * Send a message and return a new message with the reply.
 */
struct diag_msg *
diag_l3_request(struct diag_l3_conn *dl3c, struct diag_msg *txmsg, int *errval)
{
	struct diag_msg *rxmsg;
	const struct diag_l3_proto * dl3p = dl3c->d_l3_proto;

	if (diag_l3_debug & DIAG_DEBUG_WRITE)
		fprintf(stderr,
			FLFMT "_request dl3c=%p msg=%p called\n",
				FL, (void *)dl3c, (void *)txmsg);

	/* Call protocol specific send routine */
	if (dl3p->diag_l3_proto_request)
		rxmsg = dl3p->diag_l3_proto_request(dl3c, txmsg, errval);
	else
		rxmsg = NULL;

	if (diag_l2_debug & DIAG_DEBUG_WRITE) {
		fprintf(stderr, FLFMT "_request returns %p, err %d\n",
				FL, (void *)rxmsg, *errval);
	}

	if (rxmsg==NULL) {
		return diag_pseterr(*errval);
	}
		//update timers
	dl3c->timer = diag_os_getms();

	return rxmsg;
}
예제 #8
0
static struct diag_msg *
diag_l2_proto_vag_request(struct diag_l2_conn *d_l2_conn, struct diag_msg *msg,
                          int *errval)
{
    int rv;
    struct diag_msg *rmsg = NULL;

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

    /* And wait for response */
    //XXX this l2_iso9141 function should be re-written for l2_vag; they may be incompatible...
    rv = diag_l2_proto_iso9141_int_recv(d_l2_conn, 1000);
    if ((rv >= 0) && d_l2_conn->diag_msg)
    {
        /* OK */
        rmsg = d_l2_conn->diag_msg;
        d_l2_conn->diag_msg = NULL;
    }
    else
    {
        /* Error */
        *errval = DIAG_ERR_TIMEOUT;
        rmsg = NULL;
    }
    return rmsg;
}
예제 #9
0
static struct cfgi *br_getcfg(struct diag_l0_device *dl0d) {
	struct br_device *dev;
	if (dl0d == NULL) {
		return diag_pseterr(DIAG_ERR_BADCFG);
	}

	dev = dl0d->l0_int;
	return &dev->port;
}
예제 #10
0
파일: diag_l1.c 프로젝트: butljon/freediag
/*
 * Open the diagnostic device, return a dl0 device.
 *
 * Finds the unique name in the l0 device table,
 * calls the init routine, with the device parameter from the table
 *
 * This is passed a L1 subinterface (ie, what type of physical interface
 * to run on)
 */
struct diag_l0_device *
diag_l1_open(const char *name, const char *subinterface, int l1protocol)
{
	struct diag_l0_node *node;
	const struct diag_l0 *l0dev;

	for (node = l0dev_list; node; node = node->next) {
		l0dev = node->l0dev;
		if (strcmp(name, l0dev->diag_l0_name) == 0)
		{
			/* Found it */

			/* Check h/w supports this l1 protocol */
			if ((l0dev->diag_l0_type & l1protocol) == 0)
				return (struct diag_l0_device *)diag_pseterr(DIAG_ERR_PROTO_NOTSUPP);

			/* Call the open routine */
			return (l0dev->diag_l0_open)(subinterface, l1protocol);
		}
	}

	/* Not found */
	return (struct diag_l0_device *)diag_pseterr(DIAG_ERR_GENERAL);
}
예제 #11
0
파일: diag_l3.c 프로젝트: remspoor/freediag
//this implementation is rather naive and untested. It simply forwards the
//txmsg straight to the L2 request function and returns the response msg
//as-is.
struct diag_msg * diag_l3_base_request(struct diag_l3_conn *dl3c,
	struct diag_msg* txmsg, int* errval) {

	struct diag_msg *rxmsg = NULL;

	*errval=0;

	rxmsg = diag_l2_request(dl3c->d_l3l2_conn, txmsg, errval);

	if (rxmsg == NULL) {
		return diag_pseterr(*errval);
	}
	dl3c->timer=diag_os_getms();

	return rxmsg;
}
예제 #12
0
파일: diag_l3.c 프로젝트: remspoor/freediag
/*
 * Protocol start (connect a protocol on top of a L2 connection)
 * make sure to diag_l3_stop afterwards to free() the diag_l3_conn !
 * This adds the new l3 connection to the diag_l3_list linked-list
 */
struct diag_l3_conn *
diag_l3_start(const char *protocol, struct diag_l2_conn *d_l2_conn)
{
	struct diag_l3_conn *d_l3_conn = NULL;
	unsigned int i;
	int rv;
	const struct diag_l3_proto *dp;

	assert(d_l2_conn != NULL);

	if (diag_l3_debug & DIAG_DEBUG_OPEN)
		fprintf(stderr,FLFMT "start protocol %s l2 %p\n",
			FL, protocol, (void *)d_l2_conn);


	/* Find the protocol */
	dp = NULL;
	for (i=0; diag_l3_protocols[i]; i++) {
		if (strcasecmp(protocol, diag_l3_protocols[i]->proto_name) == 0)
		{
			dp = diag_l3_protocols[i];	/* Found. */
			break;
		}
	}

	if (dp)
	{
		if (diag_l3_debug & DIAG_DEBUG_OPEN)
			fprintf(stderr,FLFMT "start protocol %s found\n",
				FL, dp->proto_name);
		/*
		 * Malloc us a L3
		 */
		if (diag_calloc(&d_l3_conn, 1))
			return diag_pseterr(DIAG_ERR_NOMEM);

		d_l3_conn->d_l3l2_conn = d_l2_conn;
		d_l3_conn->d_l3_proto = dp;

		/* Get L2 flags */
		(void)diag_l2_ioctl(d_l2_conn,
			DIAG_IOCTL_GET_L2_FLAGS,
			&d_l3_conn->d_l3l2_flags);

		/* Get L1 flags */
		(void)diag_l2_ioctl(d_l2_conn,
			DIAG_IOCTL_GET_L1_FLAGS,
			&d_l3_conn->d_l3l1_flags);

		/* Call the proto routine */
		rv = dp->diag_l3_proto_start(d_l3_conn);
		if (rv < 0) {
			free(d_l3_conn);
			return diag_pseterr(rv);
		} else {
			/*
			 * Set time to now
			 */
			d_l3_conn->timer=diag_os_getms();

			/*
			 * And add to list
			 */
			LL_PREPEND(diag_l3_list, d_l3_conn);
		}
	}

	if (diag_l3_debug & DIAG_DEBUG_OPEN)
		fprintf(stderr,FLFMT "start returns %p\n",
			FL, (void *)d_l3_conn);

	return d_l3_conn;
}
예제 #13
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;
}
예제 #14
0
/*
 * Open the diagnostic device, return a file descriptor,
 * record the original state of term interface so we can restore later
 */
static struct diag_l0_device *
diag_l0_br_open(const char *subinterface, int iProtocol)
{
	struct diag_l0_device *dl0d;
	struct diag_l0_br_device *dev;
	int rv;
	uint8_t buf[4];	/* Was MAXRBUF. We only use 1! */
	struct diag_serial_settings set;

	diag_l0_br_init();

	if ((rv=diag_calloc(&dev, 1)))
		return diag_pseterr(rv);

	dev->protocol = iProtocol;
	dev->dev_rdoffset = 0;
	dev->dev_txlen = 0;
	dev->dev_framenr = 0;
	dev->dev_state = BR_STATE_CLOSED;
	dev->dev_features = BR_FEATURE_SETADDR;

	/* Get an L0 link */
	dl0d = diag_l0_new(&diag_l0_br, (void *)dev);
	if (!dl0d) {
		free(dev);
		return diag_pseterr(rv);
	}
	/* try to open TTY */
	if ((rv=diag_tty_open(dl0d, subinterface))) {
		diag_l0_del(dl0d);
		free(dev);
		return diag_pseterr(rv);
	}

	if (diag_l0_debug & DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "features 0x%X\n", FL, dev->dev_features);
	}

	/* Set serial line to 19200 baud , 8N1 */
	set.speed = 19200;
	set.databits = diag_databits_8;
	set.stopbits = diag_stopbits_1;
	set.parflag = diag_par_n;

	if (diag_tty_setup(dl0d, &set)) {
		fprintf(stderr, FLFMT "open: TTY setup failed\n", FL);
		diag_l0_br_close(&dl0d);
		return diag_pseterr(rv);
	}

	diag_tty_iflush(dl0d);	/* Flush unread input data */

	/*
	 * Initialise the BR1 interface by sending the CHIP CONNECT
	 * (0x20h) command, we should get a 0xFF back
	 */
	buf[0] = 0x20;
	if (diag_l0_br_write(dl0d, buf, 1)) {
		if ((diag_l0_debug&DIAG_DEBUG_OPEN)) {
			fprintf(stderr, FLFMT "CHIP CONNECT write failed link %p\n",
				FL, (void *)dl0d);
		}
		diag_l0_br_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}
	/* And expect 0xff as a response */
	if (diag_tty_read(dl0d, buf, 1, 100) != 1) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN) {
			fprintf(stderr, FLFMT "CHIP CONNECT read failed link %p\n",
				FL, (void *)dl0d);
		}

		diag_l0_br_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}
	if (buf[0] != 0xff) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN) {
			fprintf(stderr, FLFMT "CHIP CONNECT rcvd 0x%X != 0xff, link %p\n",
				FL, buf[0], (void *)dl0d);
		}

		diag_l0_br_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}

	/* If it's J1850, send initialisation string now */
	rv = 0;
	switch (iProtocol)
	{
	case DIAG_L1_J1850_VPW:
		rv = diag_l0_br_initialise(dl0d, 0, 0);
		break;
	case DIAG_L1_J1850_PWM:
		rv = diag_l0_br_initialise(dl0d, 1, 0);
		break;
	case DIAG_L1_ISO9141:
	case DIAG_L1_ISO14230:
		/* This initialisation is done in the SLOWINIT code */
		break;
	}
	if (rv) {
		diag_l0_br_close(&dl0d);
		return diag_pseterr(rv);
	}

	if (diag_l0_debug & DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "open succeeded link %p features 0x%X\n",
			FL, (void *)dl0d, dev->dev_features);
	}
	return dl0d;
}
예제 #15
0
/*
 * Open the diagnostic device
 * ELM settings used : no echo (E0), headers on (H1), linefeeds off (L0), mem off (M0)
 */
static struct diag_l0_device *
diag_l0_elm_open(const char *subinterface, int iProtocol)
{
	int i,rv;
	struct diag_l0_device *dl0d;
	struct diag_l0_elm_device *dev;
	struct diag_serial_settings sset;
	const uint8_t *buf;
	uint8_t rxbuf[ELM_BUFSIZE];

	const char ** elm_official;
	const char ** elm_clones;	//point to elm323_ or elm327_ clone and official version string lists

	if (diag_l0_debug & DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "open subinterface %s protocol %d\n",
			FL, subinterface, iProtocol);
	}

	diag_l0_elm_init();

	if ((rv=diag_calloc(&dev, 1)))
		return diag_pseterr(rv);

	dev->protocol = iProtocol;

	dl0d = diag_l0_new(&diag_l0_elm, (void *)dev);
	if (!dl0d) {
		free(dev);
		return diag_pseterr(rv);
	}
	/* try to open TTY */
	if ((rv=diag_tty_open(dl0d, subinterface))) {
		diag_l0_del(dl0d);
		free(dev);
		return diag_pseterr(rv);
	}

	//set speed to 38400;8n1.
	sset.speed=38400;
	sset.databits = diag_databits_8;
	sset.stopbits = diag_stopbits_1;
	sset.parflag = diag_par_n;

	dev->serial = sset;

	if ((rv=diag_tty_setup(dl0d, &sset))) {
		fprintf(stderr, FLFMT "Error setting 38400;8N1 on %s\n",
			FL, subinterface);
		diag_l0_elm_close(&dl0d);
		return diag_pseterr(rv);
	}

	diag_tty_iflush(dl0d);	/* Flush unread input */

	//At this stage, the ELM has possibly been powered up for a while;
	//it may have an unfinished command / garbage in its input buffer. We
	//need to clear that before sending the real ATZ ==> ATI is quick and safe; elm_purge does this.

	dev->elmflags=0;	//we know nothing yet

	rv=elm_purge(dl0d);
	//if rv=0, we got a prompt so we know speed is set properly.
	if (rv==0) {
		dev->elmflags |= ELM_38400;
	} else {
		fprintf(stderr, FLFMT "sending ATI @ 38400 failed; trying @ 9600...\n", FL);

		sset.speed=9600;
		dev->serial = sset;

		if ((rv=diag_tty_setup(dl0d, &sset))) {
			fprintf(stderr, FLFMT "Error setting 9600;8N1 on %s\n",
				FL, subinterface);
			diag_l0_elm_close(&dl0d);
			return diag_pseterr(rv);
		}

		diag_tty_iflush(dl0d);	/* Flush unread input */
		rv = elm_purge(dl0d);	//try ATI\r again
		if (rv !=0) {
			fprintf(stderr, FLFMT "sending ATI @ 9600 failed. Verify connection to ELM\n", FL);
			diag_l0_elm_close(&dl0d);
			return diag_pseterr(DIAG_ERR_BADIFADAPTER);
		}
	}

	if (diag_l0_debug&DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "elm_open : sending ATZ...\n", FL);
	}

	//the command "ATZ" causes a full reset and the ELM replies with
	//a string like "ELM32x vX.Xx\n>"

	buf=(uint8_t *)"ATZ\x0D";
	rv=elm_sendcmd(dl0d, buf, 4, 2000, rxbuf);
	if (rv) {
		fprintf(stderr, FLFMT "elm_open : ATZ failed !\n", FL);
		diag_l0_elm_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}

	//Correct prompt received; try to identify device.
	// 1) guess 323 vs 327
	if (strstr((char *)rxbuf, "ELM323")!=NULL) {
		dev->elmflags |= ELM_323_BASIC;
		elm_official=elm323_official;
		elm_clones=elm323_clones;
	} else if (strstr((char *)rxbuf, "ELM327")!=NULL) {
		dev->elmflags |= ELM_327_BASIC;
		elm_official=elm327_official;
		elm_clones=elm327_clones;
	} else {
		fprintf(stderr, FLFMT "no valid version string !! Report this !. Got:\n%s\n", FL, rxbuf);
		//no point in continuing...
		diag_l0_elm_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}
	// 2) identify valid VS clone devices.
	rv=0;	// temp "device identified" flag
	for (i=0; elm_clones[i]; i++) {
		if (strstr((char *)rxbuf, elm_clones[i])) {
			printf("Clone ELM found, v%s\n", elm_clones[i]);
			dev->elmflags |= ELM_32x_CLONE;
			rv=1;
			break;
		}
	}

	if (rv==0) {
		for (i=0; elm_official[i]; i++) {
				if (strstr((char *)rxbuf, elm_official[i])) {
				printf("Official ELM found, v%s\n", elm_official[i]);
				rv=1;
				break;
			}
		}
	}

	if (rv==0) {
		//still not identified : assume clone.
		dev->elmflags |= ELM_32x_CLONE;
		printf("ELM version not recognized! Please report this ! Resp=%s\n", rxbuf);
	}

	if ((dev->elmflags & ELM_323_BASIC) && (dev->elmflags & ELM_32x_CLONE)) {
		printf("A 323 clone ? Report this !\n");
	}


	if (diag_l0_debug & DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "ELM reset success, elmflags=%#x\n", FL, dev->elmflags);
	}

	//now send "ATE0\n" command to disable echo.
	buf=(uint8_t *)"ATE0\x0D";
	if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN) {
			fprintf(stderr, FLFMT "sending \"ATE0\" failed\n", FL);
		}
		diag_l0_elm_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}

	//ATL0 : disable linefeeds
	buf=(uint8_t *)"ATL0\x0D";
	if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN) {
			fprintf(stderr, FLFMT "sending \"ATL0\" failed\n", FL);
		}
		diag_l0_elm_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}

	//ATH1 : always show header bytes
	buf=(uint8_t *)"ATH1\x0D";
	if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN) {
			fprintf(stderr, FLFMT "sending \"ATH1\" failed\n", FL);
		}
		diag_l0_elm_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
	}

	//for elm327 only: disable memory
	if (dev->elmflags & ELM_327_BASIC) {
		buf=(uint8_t *)"ATM0\x0D";
		if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
			if (diag_l0_debug & DIAG_DEBUG_OPEN) {
				fprintf(stderr, FLFMT "sending \"ATM0\" failed\n", FL);
			}
			diag_l0_elm_close(&dl0d);
			return diag_pseterr(DIAG_ERR_BADIFADAPTER);
		}
	}

	//check if proto is really supported (323 supports only 9141 and 14230)
	if ((dev->elmflags & ELM_323_BASIC) &&
		((iProtocol != DIAG_L1_ISO9141) && (iProtocol != DIAG_L1_ISO14230)))
			return diag_pseterr(DIAG_ERR_PROTO_NOTSUPP);

	//if 327, set proto when possible; we won't if 14230, because init type (fast vs slow) isn't decided yet
	// CAN is also not implemented here
	buf=NULL;
	if (dev->elmflags & ELM_327_BASIC) {
		switch (iProtocol) {
		case DIAG_L1_J1850_PWM:
			buf=(uint8_t *)"ATTP1\x0D";
			break;
		case DIAG_L1_J1850_VPW:
			buf=(uint8_t *)"ATTP2\x0D";
			break;
		case DIAG_L1_ISO9141:
			buf=(uint8_t *)"ATTP3\x0D";
			break;
		default:
			buf=NULL;
		}
	}

	if (buf != NULL) {
		if (elm_sendcmd(dl0d, buf, 6, 500, NULL)) {
			if (diag_l0_debug & DIAG_DEBUG_OPEN) {
				fprintf(stderr, FLFMT "sending \"ATTPx\" failed\n", FL);
			}
		diag_l0_elm_close(&dl0d);
		return diag_pseterr(DIAG_ERR_BADIFADAPTER);
		}
	}


	//at this point : ELM is ready for further ops
	if (diag_l0_debug & DIAG_DEBUG_OPEN) {
		fprintf(stderr, FLFMT "ELM ready.\n", FL);
	}
	return dl0d;
}
예제 #16
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;
}