Beispiel #1
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;
}
Beispiel #2
0
int
diag_l1_add_l0dev(const struct diag_l0 *l0dev) {
	int rv;

	struct diag_l0_node *last_node, *new_node;

	if (l0dev_list == NULL) {
		/*
		 * No devices yet, create the root.
		 */
		if ( (rv = diag_calloc(&l0dev_list, 1)) ) 
			return rv;

		l0dev_list->l0dev = l0dev;
		return 0;
	}

	for (last_node = l0dev_list; last_node != NULL; last_node = last_node->next)
		if (last_node->l0dev == l0dev)
			return diag_iseterr(DIAG_ERR_GENERAL);	/* Already there. */

	if ( (rv = diag_calloc(&new_node, 1)) ) 
		return rv;

	for (last_node = l0dev_list; last_node->next != NULL; last_node = last_node->next)
		/* Search for the next-to-last node */;

	new_node->l0dev = l0dev;
	last_node->next = new_node;

	return 0;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
0
int main(void)
{
	struct diag_vcdiff_pcode *pcodes;
	struct diag_vcdiff_script *script;
	uint8_t *result;
	size_t size, i;

	pcodes = diag_calloc(2, sizeof(struct diag_vcdiff_pcode));
	pcodes[0].inst = DIAG_VCD_RUN;
	pcodes[0].size = 1;
	pcodes[0].attr.byte = 'a';
	pcodes[1].inst = DIAG_VCD_COPY;
	pcodes[1].size = 20;
	pcodes[1].attr.addr = 0;
	script = diag_malloc(sizeof(struct diag_vcdiff_script));
	script->source = NULL;
	script->s_pcodes = 2;
	script->pcodes = pcodes;
	result = diag_vcdiff_expand(script, &size);
	ASSERT_NOT_NULL(result);
	ASSERT_EQ_UINT32(21, size);
	for (i = 0; i < size; i++) {
		ASSERT_EQ_UINT8('a', result[i]);
	}
	diag_free(result);
	diag_free(script);
	diag_free(pcodes);

	return EXIT_SUCCESS;
}
Beispiel #6
0
/*
 * XXX All commands should probably have optional "init" hooks.
 */
int set_init(void)
{
	/* Reset parameters to defaults. */

	set_speed = 10400;	/* Comms speed; ECUs will probably send at 10416 bps (96us per bit) */
	set_testerid = 0xf1;	/* Our tester ID */
	set_addrtype = 1;	/* Use virtual addressing */
	set_destaddr = 0x33;	/* Dest ECU address */
	store_set_destaddr = set_destaddr;
	set_L1protocol = DIAG_L1_ISO9141;	/* L1 protocol type */
	set_L2protocol = DIAG_L2_PROT_ISO9141;	/* Protocol type */
	set_initmode = DIAG_L2_TYPE_FASTINIT ;

	set_display = 0;		/* English (1), or Metric (0) */

	set_vehicle = "ODBII";	/* Vehicle */
	set_ecu = "ODBII";	/* ECU name */

	set_interface_idx= DEFAULT_INTERFACE;
	set_interface = l0_names[DEFAULT_INTERFACE].code;	/* Default H/w interface to use */

	strncpy(set_subinterface,"/dev/null",sizeof(set_subinterface));
	printf( "%s: Interface set to default: %s on %s\n", progname, l0_names[set_interface_idx].longname, set_subinterface);

	if (diag_calloc(&set_simfile, strlen(DB_FILE)+1))
		return diag_iseterr(DIAG_ERR_GENERAL);	
	strcpy(set_simfile, DB_FILE);			//default simfile for use with CARSIM
	diag_l0_sim_setfile(set_simfile);
	
	return 0;
}
Beispiel #7
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 ;
}
Beispiel #8
0
// Parses a response's text to data.
// Replaces special tokens with function results.
void sim_parse_response(struct sim_ecu_response* resp_p)
{
// the magic number here is "5": all elements in a file line
// are exactly 5 characters long ("0x00 ", "cks1 ", etc).
// don't screw this! :)
#define TOKEN_SINE1	 "sin1"
#define TOKEN_SAWTOOTH1 "swt1"
#define TOKEN_ISO9141CS "cks1"
#define SRESP_SIZE 255

	uint8_t synth_resp[SRESP_SIZE];	// 255 response bytes.
	char token[5];	// to get tokens from the text.
	char* parse_offset = NULL;
	int ret = 0;
	uint8_t pos = 0;

	// extract byte values from response line, allowing for tokens.
	memset(synth_resp, 0, SRESP_SIZE);
	do {
		if ((size_t) pos*5 >= strlen(resp_p->text))
			break;
		// scan an element.
		parse_offset = resp_p->text + pos*5;
		ret = sscanf(parse_offset, "%s", token);
		// try replacing a token with a calculated value.
		if (strcmp(token, TOKEN_SINE1) == 0)
			synth_resp[pos] = sine1(synth_resp, pos);
		else if (strcmp(token, TOKEN_SAWTOOTH1) == 0)
			synth_resp[pos] = sawtooth1(synth_resp, pos);
		else if (strcmp(token, TOKEN_ISO9141CS) == 0)
			synth_resp[pos] = diag_cks1(synth_resp, pos);
		else {
			// failed. try scanning element as an Hex byte.
			ret = sscanf(parse_offset, "%X", ((unsigned int *)(&synth_resp[pos])));
			if (ret != 1) {
				// failed. something's wrong.
				fprintf(stderr, FLFMT "Error parsing line: %s at position %d.\n", FL, resp_p->text, pos*5);
				break;
			}
		}
		// next byte.
		pos++;
	} while (ret != 0);

	// copy to user.
	//resp_p->data = calloc(pos, sizeof(uint8_t));
	if (diag_calloc(&(resp_p->data),pos)) {
		fprintf(stderr, FLFMT "Error parsing response\n", FL);
		return;
	}
	memcpy(resp_p->data, synth_resp, pos);
	resp_p->len = pos;
}
Beispiel #9
0
struct diag_command *diag_command_new(char **argv,
				      const char *dir,
				      const char *in,
				      const char *out,
				      const char *err)
{
	struct diag_command *command = diag_malloc(sizeof(*command));
	size_t argc;
	for (argc = 0; argv[argc]; argc++) ;
	command->argv = diag_calloc(argc + 1, sizeof(char *));
	size_t i;
	for (i = 0; i < argc; i++) {
		command->argv[i] = diag_strdup(argv[i]);
	}
	command->argv[argc] = NULL; /* NULL-terminated */
	command->file = argv[0];

	if (dir) {
		command->dir = diag_strdup(dir);
	} else {
		command->dir = diag_malloc(PATH_LENGTH);
		char *p;
#if defined(_WIN32) && defined(__MINGW32__)
		p = _getcwd(command->dir, PATH_LENGTH);
#elif defined(HAVE_UNISTD_H)
		p = getcwd(command->dir, PATH_LENGTH);
#endif
		if (!p) {
			perror(NULL);
			diag_fatal("failed to get current working directory");
		}
	}

	if (in) {
		command->in = diag_strdup(in);
	} else {
		command->in = NULL;
	}
	if (out) {
		command->out = diag_strdup(out);
	} else {
		command->out = NULL;
	}
	if (err) {
		command->err = diag_strdup(err);
	} else {
		command->err = NULL;
	}
	return command;
}
Beispiel #10
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;
}
Beispiel #11
0
static int
br_new(struct diag_l0_device *dl0d) {
	struct br_device *dev;
	int rv;

	assert(dl0d);

	rv = diag_calloc(&dev, 1);
	if (rv != 0) {
		return diag_ifwderr(rv);
	}

	dl0d->l0_int = dev;

	rv = diag_cfgn_tty(&dev->port);
	if (rv != 0) {
		free(dev);
		return diag_ifwderr(rv);
	}

	dev->port.next = NULL;

	return 0;
}
Beispiel #12
0
void *diag_qselect(void *base, size_t nmemb, size_t size,
		   int (*cmp)(const void *, const void *),
		   size_t k)
{
	assert(base);
	assert(nmemb > 0);
	assert(size > 0);

	if (nmemb <= k) return NULL;
	if (nmemb == 1) return base;

	int *rv = diag_calloc(nmemb, sizeof(int));
	size_t i;
	size_t n_lt;
	size_t n_gt;
	size_t n_eq;
	char *p;

 partition:
	assert(k < nmemb);
	if (nmemb == 1) goto done;

	n_lt = 0;
	n_gt = 0;
	p = (char *)base;
	for (i = 1; i < nmemb; i++) {
		int r = cmp(p, p + size * i);
		if (r < 0) n_lt++;
		if (0 < r) n_gt++;
		rv[i] = r;
	}
	n_eq = nmemb - n_lt - n_gt;
	if (k < n_lt) {
		size_t j = n_lt + 1;
		for (i = 1; i <= n_lt; i++) {
			if (rv[i] >= 0) {
				while (j < nmemb && rv[j] >= 0) {
					j++;
				}
				assert(j < nmemb);
				memcpy(p + size * i, p + size * j++, size);
			}
		}
		base = p + size;
		nmemb = n_lt;
		/* k is unchanged */
		goto partition;
	}
	if (k >= n_lt + n_eq) {
		size_t j = n_gt + 1;
		for (i = 1; i <= n_gt; i++) {
			if (rv[i] <= 0) {
				while (j < nmemb && rv[j] <= 0) {
					j++;
				}
				assert(j < nmemb);
				memcpy(p + size * i, p + size * j++, size);
			}
		}
		base = p + size;
		nmemb = n_gt;
		k -= n_lt + n_eq;
		goto partition;
	}

 done:
	diag_free(rv);
	return base;
}
Beispiel #13
0
/*
 * 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;
}
Beispiel #14
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;
}
Beispiel #15
0
int diag_tty_open(struct diag_l0_device *dl0d,
	const char *portname)
{
	int rv;
	struct unix_tty_int *uti;
#if defined(_POSIX_TIMERS) && (SEL_TIMEOUT==S_POSIX || SEL_TIMEOUT==S_AUTO)
	struct sigevent to_sigev;
	struct sigaction sa;
	clockid_t timeout_clkid;
#endif

	assert(dl0d != NULL);
	if (dl0d->tty_int) return diag_iseterr(DIAG_ERR_GENERAL);

	if ((rv=diag_calloc(&uti,1))) {
		return diag_iseterr(rv);
	}

#if defined(_POSIX_TIMERS) && (SEL_TIMEOUT==S_POSIX || SEL_TIMEOUT==S_AUTO)
	//set-up the r/w timeouts clock - here we just create it; it will be armed when needed
	#ifdef _POSIX_MONOTONIC_CLOCK
	timeout_clkid = CLOCK_MONOTONIC;
	#else
	timeout_clkid = CLOCK_REALTIME;
	#endif // _POSIX_MONOTONIC_CLOCK
	sa.sa_flags = SA_SIGINFO;
	sa.sa_sigaction = diag_tty_rw_timeout_handler;
	sigemptyset(&sa.sa_mask);
	if(sigaction(SIGUSR1, &sa, NULL) != 0) {
		fprintf(stderr, FLFMT "Could not set-up action for timeout timer... report this\n", FL);
		free(uti);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	to_sigev.sigev_notify = SIGEV_SIGNAL;
	to_sigev.sigev_signo = SIGUSR1;
	to_sigev.sigev_value.sival_ptr = uti;
	if(timer_create(timeout_clkid, &to_sigev, &uti->timerid) != 0) {
		fprintf(stderr, FLFMT "Could not create timeout timer... report this\n", FL);
		free(uti);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
#endif

	uti->fd = DL0D_INVALIDHANDLE;

	size_t n = strlen(portname) + 1;

	if ((rv=diag_malloc(&uti->name, n))) {
		free(uti);
		return diag_iseterr(rv);
	}
	strncpy(uti->name, portname, n);
	dl0d->tty_int = uti;
	//past this point, we can call diag_tty_close(dl0d) to abort in case of errors

	errno = 0;

#if defined(O_NONBLOCK) && (SEL_TTYOPEN==S_ALT1 || SEL_TTYOPEN==S_AUTO)
	/*
	 * For POSIX behavior:  Open serial device non-blocking to avoid
	 * modem control issues, then set to blocking.
	 */
	{
		int fl;
		uti->fd = open(uti->name, O_RDWR | O_NONBLOCK);

		if (uti->fd > 0) {
			errno = 0;
			if ((fl = fcntl(uti->fd, F_GETFL, 0)) < 0) {
				fprintf(stderr,
					FLFMT "Can't get flags with fcntl on fd %d: %s.\n",
					FL, uti->fd, strerror(errno));
				diag_tty_close(dl0d);
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
			fl &= ~O_NONBLOCK;
			errno = 0;
			if (fcntl(uti->fd, F_SETFL, fl) < 0) {
				fprintf(stderr,
					FLFMT "Can't set flags with fcntl on fd %d: %s.\n",
					FL, uti->fd, strerror(errno));
				diag_tty_close(dl0d);
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
		}
	}
#else
	#ifndef O_NONBLOCK
	#warning No O_NONBLOCK on your system ?! Please report this
	#endif
	uti->fd = open(uti->name, O_RDWR);

#endif // O_NONBLOCK

	if (uti->fd >= 0) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN)
			fprintf(stderr, FLFMT "Device %s opened, fd %d\n",
				FL, uti->name, uti->fd);
	} else {
		fprintf(stderr,
			FLFMT "Could not open \"%s\" : %s. "
			"Make sure the device specified corresponds to the "
			"serial device your interface is connected to.\n",
			FL, uti->name, strerror(errno));
		diag_tty_close(dl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	/*
	 * Save original settings so can reset
	 * device on close - we also set "current" settings to
	 * those we just read aswell
	 */

#if defined(__linux__)
	if (ioctl(uti->fd, TIOCGSERIAL, &uti->ss_orig) < 0) {
		fprintf(stderr,
			FLFMT "open: TIOCGSERIAL failed: %s\n", FL, strerror(errno));
		uti->tioc_works = 0;
	} else {
		uti->ss_cur = uti->ss_orig;
		uti->tioc_works = 1;
	}
#endif

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

#ifdef 	USE_TERMIOS2
	rv = ioctl(uti->fd, TCGETS, &uti->st_orig);
#else
	rv = tcgetattr(uti->fd, &uti->st_orig);
#endif
	if (rv != 0) {
		fprintf(stderr, FLFMT "open: could not get orig settings: %s\n",
			FL, strerror(errno));
		diag_tty_close(dl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	//and set common flags
	uti->st_cur = uti->st_orig;

	/* "stty raw"-like iflag settings: */
	/* Clear a bunch of un-needed flags */
	uti->st_cur.c_iflag &= ~ (IGNBRK | BRKINT | IGNPAR | PARMRK
		| INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF
		| IXANY | IMAXBEL);
#ifdef __linux__
	uti->st_cur.c_iflag  &= ~(IUCLC);   /* non-posix; disable ucase/lcase conversion */
#endif

	uti->st_cur.c_oflag &= ~(OPOST);	//disable impl-defined output processing

	/* Disable canonical input and keyboard signals.
	+* There is no need to also clear the many ECHOXX flags, both because
	+* many systems have non-POSIX flags and also because the ECHO
	+* flags don't don't matter when ICANON is clear.
	 */
	/* CJH: However, taking 'man termios' at its word, the ECHO flag is
	 *not* affected by ICANON, and it seems we do need to clear it  */
	uti->st_cur.c_lflag &= ~( ICANON | ISIG | ECHO | IEXTEN);

	uti->st_cur.c_cflag &= ~( CRTSCTS );	//non-posix; disables hardware flow ctl
	uti->st_cur.c_cflag |= (CLOCAL | CREAD);	//ignore modem control lines; enable read

	uti->st_cur.c_cc[VMIN] = 1;		//Minimum # of bytes before read() returns (default: 0!!!)

	//and update termios with new flags.
#ifdef USE_TERMIOS2
	rv = ioctl(uti->fd, TCSETS, &uti->st_cur);
	rv |= ioctl(uti->fd, TCGETS2, &uti->st2_cur);
#else
	rv=tcsetattr(uti->fd, TCSAFLUSH, &uti->st_cur);
#endif
	if (rv != 0) {
		fprintf(stderr, FLFMT "open: can't set input flags: %s.\n",
				FL, strerror(errno));
		diag_tty_close(dl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	//arbitrarily set the single byte write timeout to 1ms
	uti->byte_write_timeout_us = 1000ul;

	return 0;
}
Beispiel #16
0
//diag_tty_open : open specified port for L0
int diag_tty_open(struct diag_l0_device *dl0d,
                  const char *portname)
{
    int rv;
    struct tty_int *wti;
    size_t n = strlen(portname) + 1;
    COMMTIMEOUTS devtimeouts;

    if (!dl0d) return diag_iseterr(DIAG_ERR_GENERAL);

    if ((rv=diag_calloc(&wti,1))) {
        return diag_iseterr(rv);
    }

    dl0d->tty_int = wti;
    wti->fd = INVALID_HANDLE_VALUE;

    //allocate space for portname name
    if ((rv=diag_malloc(&wti->name, n))) {
        free(dl0d->tty_int);
        return diag_iseterr(rv);
    }
    //Now, in case of errors we can call diag_tty_close() on the dl0d since its members are alloc'ed
    strncpy(wti->name, portname, n);

    wti->fd=CreateFile(portname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
                       NULL);
    //File hande is created as non-overlapped. This may change eventually.

    if (wti->fd != INVALID_HANDLE_VALUE) {
        if (diag_l0_debug & DIAG_DEBUG_OPEN)
            fprintf(stderr, FLFMT "Device %s opened, fd %p\n",
                    FL, wti->name, wti->fd);
    } else {
        fprintf(stderr,
                FLFMT "Open of device interface \"%s\" failed: %s\n",
                FL, wti->name, diag_os_geterr(0));
        fprintf(stderr, FLFMT
                "(Make sure the device specified corresponds to the\n", FL );
        fprintf(stderr,
                FLFMT "serial device your interface is connected to.\n", FL);

        diag_tty_close(dl0d);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    //purge & abort everything.
    PurgeComm(wti->fd,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    //as opposed to the unix diag_tty.c ; this one doesn't save previous commstate. The next program to use the COM port
    //will need to deal with it...

    //We will load the DCB with the current comm state. This way we only need to call GetCommState once during a session
    //and the DCB should contain coherent initial values
    if (! GetCommState(wti->fd, &wti->dcb)) {
        fprintf(stderr, FLFMT "Could not get comm state: %s\n",FL, diag_os_geterr(0));
        diag_tty_close(dl0d);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    //Finally set COMMTIMEOUTS to reasonable values (all in ms) ?
    devtimeouts.ReadIntervalTimeout=30;	//i.e. more than 30ms between received bytes
    devtimeouts.ReadTotalTimeoutMultiplier=5;	//timeout per requested byte
    devtimeouts.ReadTotalTimeoutConstant=20;	// (constant + multiplier*numbytes) = total timeout on read(buf, numbytes)
    devtimeouts.WriteTotalTimeoutMultiplier=0;	//probably useless as all flow control will be disabled ??
    devtimeouts.WriteTotalTimeoutConstant=0;
    if (! SetCommTimeouts(wti->fd,&devtimeouts)) {
        fprintf(stderr, FLFMT "Could not set comm timeouts: %s\n",FL, diag_os_geterr(0));
        diag_tty_close(dl0d);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    return 0;
} //diag_tty_open
Beispiel #17
0
int diag_tty_open(struct diag_l0_device **ppdl0d, 
const char *subinterface,
const struct diag_l0 *dl0,
void *dl0_handle)
{
	int rv;
	struct diag_ttystate	*dt;
	struct diag_l0_device *dl0d;

	char *endptr;
	int iInterface;

	const char *tty_template ="/dev/obdII%d";

	if (rv=diag_calloc(&dl0d, 1))		//free'd in diag_tty_close
		return diag_iseterr(rv);

	dl0d->fd = -1;
	dl0d->dl0_handle = dl0_handle;
	dl0d->dl0 = dl0;

	if ((rv=diag_calloc(&dl0d->ttystate, 1))) {
		free(dl0d);
		return diag_iseterr(rv);
	}

	*ppdl0d = dl0d;

	/*
	 * XXX this should probably be removed... "historical compatibility" with what ?? Who ?
	
	 * For historical compatibility, if the subinterface decodes cleanly
	 * as an integer we will write it into a string to get the name.
	 * You can create a symlink to "/dev/obdII<NUMBER>" if you want to,
	 * or just set the subinterface to a valid device name.
	 */

	iInterface = strtol(subinterface, &endptr, 10);
	if (*endptr == 0) {
		/* Entire string is a valid number: Provide compatibility.  */
		size_t n = strlen(tty_template) + 32;
		printf("Warning : using deprecated /dev/obdII<x> subinterface definition.\n");
		printf("Support for this will be discontinued shortly...\n");

		if ((rv=diag_malloc(&dl0d->name, n))) {
			(void)diag_tty_close(ppdl0d);;
			return diag_iseterr(rv);
		}
		(void)snprintf(dl0d->name, n, tty_template, iInterface);
	} else {
		size_t n = strlen(subinterface) + 1;

		if ((rv=diag_malloc(&dl0d->name, n))) {
			(void)diag_tty_close(ppdl0d);;
			return diag_iseterr(rv);
		}
		strncpy(dl0d->name, subinterface, n);
	}

	errno = 0;
#if defined(__linux__) && (TRY_POSIX == 0)
	dl0d->fd = open(dl0d->name, O_RDWR);
#else
	/*
	+* For POSIX behavior:  Open serial device non-blocking to avoid
	+* modem control issues, then set to blocking.
	 */
	/* CODE BLOCK */
	{
		int fl;
		dl0d->fd = open(dl0d->name, O_RDWR | O_NONBLOCK);

		if (dl0d->fd > 0) {
			errno = 0;
			if ((fl = fcntl(dl0d->fd, F_GETFL, 0)) < 0) {
				fprintf(stderr,
					FLFMT "Can't get flags with fcntl on fd %d: %s.\n",
					FL, dl0d->fd, strerror(errno));
				(void)diag_tty_close(ppdl0d);;
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
			fl &= ~O_NONBLOCK;
			errno = 0;
			if (fcntl(dl0d->fd, F_SETFL, fl) < 0) {
				fprintf(stderr,
					FLFMT "Can't set flags with fcntl on fd %d: %s.\n",
					FL, dl0d->fd, strerror(errno));
				(void)diag_tty_close(ppdl0d);
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
		}
	}
#endif

	if (dl0d->fd >= 0) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN)
			fprintf(stderr, FLFMT "Device %s opened, fd %d\n", 
				FL, dl0d->name, dl0d->fd);
	} else {
		fprintf(stderr,
			FLFMT "Open of device interface \"%s\" failed: %s\n", 
			FL, dl0d->name, strerror(errno));
		fprintf(stderr, FLFMT
			"(Make sure the device specified corresponds to the\n", FL );
		fprintf(stderr,
			FLFMT "serial device your interface is connected to.\n", FL);

		(void)diag_tty_close(ppdl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	dt = dl0d->ttystate;

	/*
	 * Save original settings so can reset
	 * device on close - we also set "current" settings to
	 * those we just read aswell
	 */

#if defined(__linux__) && (TRY_POSIX == 0)
	if (ioctl(dl0d->fd, TIOCGSERIAL, &dt->dt_osinfo) < 0)
	{
		fprintf(stderr,
			FLFMT "open: Ioctl TIOCGSERIAL failed %d\n", FL, errno);
		(void)diag_tty_close(ppdl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	dt->dt_sinfo = dt->dt_osinfo;
#endif

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

	if (tcgetattr(dl0d->fd, &dt->dt_otinfo) < 0)
	{
		fprintf(stderr, FLFMT "open: tcgetattr failed %s\n",
			FL, strerror(errno));
		(void)diag_tty_close(ppdl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	dt->dt_tinfo = dt->dt_otinfo;

	return 0;
}
Beispiel #18
0
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;
}
Beispiel #19
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;
}
Beispiel #20
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;
}