예제 #1
0
// diag_tty_break #1 : use Set / ClearCommBreak
// and return as soon as break is cleared.
// ret 0 if ok
int diag_tty_break(struct diag_l0_device *dl0d, const unsigned int ms) {
	LARGE_INTEGER qpc1, qpc2;	//for timing verification
	long real_t;	//"real" duration
	struct tty_int *wti = (struct tty_int *)dl0d->tty_int;
	int errval=0;

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

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

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

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

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

	return 0;
}
예제 #2
0
/*
 * Routine to read a whole BR1 message
 * length of which depends on the first value received.
 * This also handles "error" messages (top bit of first value set)
 *
 * Returns length of received message, or TIMEOUT error, or BUSERROR
 * if the BR interface tells us theres a congested bus
 */
static int
br_getmsg(struct diag_l0_device *dl0d, uint8_t *dp, unsigned int timeout) {
	uint8_t firstbyte;
	size_t readlen;
	int rv;
	struct br_device *dev = dl0d->l0_int;

	DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
			FLFMT "link %p getmsg timeout %u\n", FL, (void *)dl0d, timeout);

	/*
	 * First read the 1st byte, using the supplied timeout
	 */
	rv = diag_tty_read(dev->tty_int, &firstbyte, 1, timeout);
	if (rv != 1) {
		DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
			FLFMT "link %p getmsg 1st byte timed out\n", FL, (void *)dl0d);

		return diag_ifwderr(rv);
	}

	/*
	 * Now read data. Maximum is 15 bytes.
	 */

	readlen = firstbyte & 0x0f;

	/*
	 * Reasonable timeout here as the interface told us how
	 * much data to expect, so it should arrive
	 */
	rv = diag_tty_read(dev->tty_int, dp, readlen, 100);
	if (rv != (int)readlen) {
		fprintf(stderr, FLFMT "br_getmsg error\n", FL);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	DIAG_DBGMDATA(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V, dp, readlen,
			FLFMT "link %p getmsg read ctl 0x%X data:",
			FL, (void *)dl0d, firstbyte & 0xff);

	/*
	 * Message read complete, check error flag
	 * Top bit set means error, Bit 6 = VPW/PWM bus
	 * congestion (i.e retry).
	 */
	if (firstbyte & 0x80) { /* Error indicator */
		return diag_iseterr(DIAG_ERR_TIMEOUT);
	}

	if (firstbyte & 0x40) { /* VPW/PWM bus conflict, need to retry */
		return diag_iseterr(DIAG_ERR_BUSERROR);
	}

	if (readlen == 0) { /* Should never happen */
		return diag_iseterr(DIAG_ERR_TIMEOUT);
	}

	return (int) readlen;
}
예제 #3
0
/*
 * Safe write routine; return 0 on success
 */
static int
diag_l0_muleng_write(struct diag_l0_device *dl0d, const void *dp, size_t txlen)
{
	if (txlen <=0)
		return diag_iseterr(DIAG_ERR_BADLEN);

	if ( (diag_l0_debug & (DIAG_DEBUG_WRITE|DIAG_DEBUG_DATA)) ==
			(DIAG_DEBUG_WRITE|DIAG_DEBUG_DATA) )
	{
		fprintf(stderr, FLFMT "device link %p sending to ME device: ",
			FL, (void *)dl0d);
		diag_data_dump(stderr, dp, txlen);
		fprintf(stderr, "\n");
	}

	/*
	 * And send it to the interface
	 */
	if (diag_tty_write(dl0d, dp, txlen) != (int) txlen) {
		fprintf(stderr, FLFMT "muleng_write error!!\n", FL);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	return 0;
}
예제 #4
0
/*
 * Set/Clear DTR and RTS lines, as specified
 * on Win32 this can easily be done by calling EscapeCommFunction twice.
 * This takes around ~15-20us to do; probably with ~10 us skew between setting RTS and DTR.
 * If it proves to be a problem, it's possible to change both RTS and DTR at once by updating
 * the DCB and calling SetCommState. That call would take around 30-40us.
 * Note : passing 1 in dtr or rts means "set DTR/RTS", i.e. positive voltage.
 * ret 0 if ok
 */
int
diag_tty_control(struct diag_l0_device *dl0d,  unsigned int dtr, unsigned int rts)
{
    unsigned int escapefunc;
    struct tty_int *wti = (struct tty_int *)dl0d->tty_int;


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

    if (dtr)
        escapefunc=SETDTR;
    else
        escapefunc=CLRDTR;

    if (! EscapeCommFunction(wti->fd,escapefunc)) {
        fprintf(stderr, FLFMT "Could not change DTR: %s\n", FL, diag_os_geterr(0));
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    if (rts)
        escapefunc=SETRTS;
    else
        escapefunc=CLRRTS;

    if (! EscapeCommFunction(wti->fd,escapefunc)) {
        fprintf(stderr, FLFMT "Could not change RTS: %s\n", FL, diag_os_geterr(0));
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    return 0;
} //diag_tty_control
예제 #5
0
/*
 * Insert the L3 layer on top of the layer 2 connection
 *
 */
static int
diag_l3_vag_start(struct diag_l3_conn *d_l3_conn) {
	struct diag_l2_data l2data;
	struct diag_l2_conn *d_l2_conn;

	/* 5 baud init has been done, make sure we got the correct keybytes */
	d_l2_conn = d_l3_conn->d_l3l2_conn;

	(void)diag_l2_ioctl(d_l2_conn, DIAG_IOCTL_GET_L2_DATA, (void *)&l2data);

	DIAG_DBGM(diag_l3_debug, DIAG_DEBUG_INIT, DIAG_DBGLEVEL_V,
		FLFMT "start L3 KB 0x%X 0x%X need 0x01 0x8A\n",
		FL, l2data.kb1, l2data.kb2);

	if (l2data.kb1 != 0x01) {
		return diag_iseterr(DIAG_ERR_WRONGKB);
	}
	if (l2data.kb2 != 0x8A) {
		return diag_iseterr(DIAG_ERR_WRONGKB);
	}

	/* OK, ISO 9141 keybytes are correct ! */

	/* Get the initial stuff the ECU tells us */

	return 0;
}
예제 #6
0
static int
diag_l0_br_write(struct diag_l0_device *dl0d, const void *dp, size_t txlen)
{
	if (txlen <=0)
		return diag_iseterr(DIAG_ERR_BADLEN);

	if (diag_tty_write(dl0d, dp, txlen) != (int) txlen) {
		fprintf(stderr, FLFMT "br_write error\n", FL);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	return 0;
}
예제 #7
0
int
diag_l2_proto_raw_startcomms( struct diag_l2_conn *d_l2_conn,
UNUSED(flag_type flags),
unsigned int bitrate,
target_type target,
source_type source)
{
	int rv;
	struct diag_serial_settings set;

	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)
		return diag_iseterr(DIAG_ERR_GENERAL);

	//set tgt and src address in d_l2_conn
	d_l2_conn->diag_l2_destaddr=target;
	d_l2_conn->diag_l2_srcaddr=source;

	return 0;
}
예제 #8
0
static int
diag_l0_br_write(struct diag_l0_device *dl0d, const void *dp, size_t txlen)
{
	ssize_t xferd;

	while ((size_t)(xferd = diag_tty_write(dl0d, dp, txlen)) != txlen) {
		if (xferd < 0) {
			/* error */
			if (errno != EINTR) {
				fprintf(stderr, FLFMT "write returned error %s.\n",
					FL, strerror(errno));
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
			xferd = 0; /* Interrupted read, nothing transferred. */
			errno = 0;
		}
		/*
		 * Successfully wrote xferd bytes (or 0 bytes if EINTR),
		 * so increment the pointers and continue
		 */
		txlen -= (size_t) xferd;
		dp = (const void *)((const char *)dp + xferd);
	}
	return 0;
}
예제 #9
0
/*
 * Send the data
 *
 * - with VAG protocol this will sleep as the message is sent as each byte
 * is ack'ed by the far end
 *
 * - after each byte reset the send timer or the timeout routine may try
 * and send something
 *
 * 1st byte of message is command, followed by data
 */
static int
diag_l2_proto_vag_send(struct diag_l2_conn *d_l2_conn, struct diag_msg *msg)
{
    int rv = 0;
    /*	int i;*/
    /*	int csum;*/
    /*	int len;*/
    /*	uint8_t buf[MAXRBUF];*/
    /*	int offset;*/
    //struct diag_l2_vag *dp;

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

    //dp = (struct diag_l2_vag *)d_l2_conn->diag_l2_proto_data;	//not used ?

#if xx
    rv = diag_l1_send (d_l2_conn->diag_link->diag_l2_dl0d, 0,
                       buf, len, d_l2_conn->diag_l2_p4min);
#endif

    return rv? diag_iseterr(rv):0 ;
}
예제 #10
0
/*
 * Do wakeup on the bus
 *
 * We do this by noting a wakeup needs to be done for the next packet for
 * fastinit, and doing slowinit now
 */
static int
diag_l0_muleng_initbus(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in)
{
	int rv = 0;
	struct diag_l0_muleng_device *dev;

	dev = (struct diag_l0_muleng_device *)dl0d->l0_int;

	if (!dev)
		return diag_iseterr(DIAG_ERR_GENERAL);

	if (diag_l0_debug & DIAG_DEBUG_IOCTL)
		fprintf(stderr, FLFMT "device link %p info %p initbus type %d proto %d\n",
			FL, (void *)dl0d, (void *)dev, in->type, dev->protocol);

	diag_tty_iflush(dl0d); /* Empty the receive buffer, wait for idle bus */

	if (in->type == DIAG_L1_INITBUS_5BAUD)
		rv = diag_l0_muleng_slowinit(dl0d, in, dev);
	else
	{
		/* Do wakeup on first TX */
		dev->dev_wakeup = in->type;
		dev->dev_state = MULENG_STATE_FASTSTART;
	}

	return rv;
}
예제 #11
0
파일: diag_l1.c 프로젝트: fenugrec/freediag
/*
 * Get data (blocking, unless timeout is 0)
 * returns # of bytes read, or <0 if error.
 * XXX currently nothing handles the case of L0 returning 0 bytes read. Logically that could
 * only happen when requesting n bytes with a timeout of 0; otherwise DIAG_ERR_TIMEOUT will
 * generated.
 */
int
diag_l1_recv(struct diag_l0_device *dl0d,
	const char *subinterface, void *data, size_t len, unsigned int timeout) {
	int rv;
	if (!len) {
		return diag_iseterr(DIAG_ERR_BADLEN);
	}

	DIAG_DBGM(diag_l1_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
		FLFMT "_recv request len=%d, timeout=%u;",
		FL, (int)len, timeout);

	if (timeout == 0) {
		fprintf(stderr,
			FLFMT
			"Interesting : L1 read with timeout=0. Report this !\n",
			FL);
	}

	rv=diag_l0_recv(dl0d, subinterface, data, len, timeout);
	if (!rv) {
		fprintf(stderr, FLFMT "L0 returns with 0 bytes; returning TIMEOUT instead. Report this !\n", FL);
		return DIAG_ERR_TIMEOUT;
	}

	if (rv>0) {
		DIAG_DBGMDATA(diag_l1_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
			data, (size_t) rv, "got %d bytes; ",rv);
	}

	return rv;
}
예제 #12
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;
}
예제 #13
0
파일: diag_l1.c 프로젝트: butljon/freediag
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;
}
예제 #14
0
파일: diag_tty.c 프로젝트: butljon/freediag
int diag_tty_break(struct diag_l0_device *dl0d, const int ms)
{
	HANDLE hd;
	long h;

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

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

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

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

	return 0;
}
예제 #15
0
/*
 * Send a load of data
 *
 * Returns 0 on success, -1 on failure
 *
 * This routine will do a fastinit if needed, but all 5 baud inits
 * will have been done by the slowinit() code
 */
static int
br_send(struct diag_l0_device *dl0d,
UNUSED(const char *subinterface),
const void *data, size_t len) {
	int rv = 0;

	struct br_device *dev;

	dev = (struct br_device *)dl0d->l0_int;

	if (len <= 0) {
		return diag_iseterr(DIAG_ERR_BADLEN);
	}

	DIAG_DBGMDATA(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V, data, len,
			FLFMT "device link %p send %ld bytes protocol %d state %d: ",
			FL, (void *)dl0d, (long)len, dev->protocol, dev->dev_state);

	/*
	 * Special handling for fastinit, we need to collect up the
	 * bytes of the StartComms message sent by the upper layer
	 * when we have a whole message we can then send the request
	 * as part of a special initialisation type
	 */
	if (dev->dev_state == BR_STATE_KWP_FASTINIT) {
		uint8_t outbuf[6];
		if (dev->dev_txlen < 5) {
			memcpy(&dev->dev_txbuf[dev->dev_txlen], data, len);
			dev->dev_txlen += len;
			rv = 0;
		}

		if (dev->dev_txlen >= 5) {
			/*
			 * Startcomms request is 5 bytes long - we have
			 * 5 bytes, so now we should send the initialisation
			 */
			outbuf[0] = 0x03;
			memcpy(&outbuf[1], dev->dev_txbuf, 5);
			rv = br_writemsg(dl0d, BR_WRTYPE_INIT,
				outbuf, 6);
			/* Stays in FASTINIT state until first read */
		}
	} else {
		/*
		 * Now, keep a copy of the data, and set the framenr to 1
		 * This means the receive code will resend the request if it
		 * wants to get a frame number 2 or 3 or whatever
		 */
		memcpy(dev->dev_rxbuf, data, len);
		dev->dev_txlen = len;
		dev->dev_framenr = 1;

		/* And now encapsulate and send the data */
		rv = br_writemsg(dl0d, BR_WRTYPE_DATA, data, len);
	}

	return rv;
}
예제 #16
0
//elm_bogusinit : send a 01 00 request to force ELM to init bus.
//Only used to force clones to establish a connection... hack-grade because it assumes all ECUs support this.
// non-OBD ECUs may not work with this. ELM clones suck...
// TODO : add argument to allow either a 01 00 request (SID1 PID0, J1979) or 3E (iso14230 TesterPresent) request to force init.
static int
elm_bogusinit(struct diag_l0_device *dl0d, unsigned int timeout)
{
	int rv;
	uint8_t buf[MAXRBUF];
	uint8_t data[]={0x01,0x00};
	const char *err_str;

	rv = diag_l0_elm_send(dl0d, NULL, data, 2);
	if (rv)
		return diag_iseterr(rv);

	// receive everything; we're hoping for a prompt at the end and no error message.
	rv=diag_tty_read(dl0d, buf, MAXRBUF-5, timeout);	//rv=# bytes read
	if (diag_l0_debug & (DIAG_DEBUG_WRITE | DIAG_DEBUG_READ)) {
		fprintf(stderr, FLFMT "received %d bytes\n", FL, rv);
		if (diag_l0_debug & DIAG_DEBUG_DATA) {
			elm_parse_cr(buf, rv);
			fprintf(stderr, FLFMT "(got %.*s)\n", FL, rv, buf);
		}
	}

	if (rv<1) {
		//no data or error
		if (diag_l0_debug & DIAG_DEBUG_WRITE) {
			fprintf(stderr, FLFMT "ELM did not respond\n", FL);
		}
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	buf[rv]=0;	//terminate string
	if (buf[rv-1] != '>') {
		//if last character isn't the input prompt, there is a problem
		fprintf(stderr, FLFMT "ELM not ready (no prompt received): %s\n", FL, buf);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	err_str = elm_parse_errors(dl0d, buf);

	if (err_str != NULL) {
		fprintf(stderr, FLFMT "got error while forcing init: %s\n", FL, err_str);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	return 0;

}
예제 #17
0
// diag_tty_break #1 : use Set / ClearCommBreak
// and return as soon as break is cleared.
// ret 0 if ok
int diag_tty_break(struct diag_l0_device *dl0d, const unsigned int ms) {
    LARGE_INTEGER qpc1, qpc2;	//for timing verification
    static long correction=0;	//running average offset (us) to add to the timeout
    long real_t;	//"real" duration measured in us
    struct tty_int *wti = (struct tty_int *)dl0d->tty_int;
    int errval=0;

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

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

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

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

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

    return 0;
}
예제 #18
0
/*
 * Do wakeup on the bus
 *
 * We do this by noting a wakeup needs to be done for the next packet for
 * fastinit, and doing slowinit now
 */
static int
diag_l0_br_initbus(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in)
{
	int rv = 0;
	struct diag_l0_br_device *dev;

	dev = (struct diag_l0_br_device *)dl0d->l0_int;

	if (diag_l0_debug & DIAG_DEBUG_IOCTL)
		fprintf(stderr,
			FLFMT "device link %p info %p initbus type %d proto %d\n",
			FL, (void *)dl0d, (void *)dev, in->type,
			dev ? dev->protocol : -1);

	if (!dev)
		return diag_iseterr(DIAG_ERR_GENERAL);

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

	switch (in->type)
	{
	case DIAG_L1_INITBUS_5BAUD:
		rv = diag_l0_br_slowinit(dl0d, in);
		break;
	case DIAG_L1_INITBUS_FAST:
		if ((dev->dev_features & BR_FEATURE_FASTINIT) == 0)
		{
			/* Fast init Not supported */
			rv = DIAG_ERR_INIT_NOTSUPP;
		}
		else
		{
			/* Fastinit done on 1st TX */
			dev->dev_state = BR_STATE_KWP_FASTINIT;
			rv = 0;
		}
		break;
	default:
		rv = DIAG_ERR_INIT_NOTSUPP;
		break;
	}
	return rv? diag_iseterr(rv):0 ;
}
예제 #19
0
파일: diag_tty.c 프로젝트: butljon/freediag
/*
 * POSIX serial I/O input flush:
 */
int diag_tty_iflush(struct diag_l0_device *dl0d) {
	errno = 0;
	if (tcflush(dl0d->fd, TCIFLUSH) < 0) {
		fprintf(stderr, FLFMT "TCIFLUSH on fd %d returned %s.\n",
			FL, dl0d->fd, strerror(errno));

		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	return 0;
}
예제 #20
0
ssize_t
diag_tty_read(struct diag_l0_device *dl0d, void *buf, size_t count, unsigned int timeout) {
	DWORD bytesread;
	ssize_t rv=DIAG_ERR_TIMEOUT;
	OVERLAPPED *pOverlap;
	struct tty_int *wti = (struct tty_int *)dl0d->tty_int;
	pOverlap=NULL;
	COMMTIMEOUTS devtimeouts;

	if ((count <= 0) || (timeout <= 0)) return DIAG_ERR_BADLEN;

	if (diag_l0_debug & DIAG_DEBUG_READ) {
		fprintf(stderr, FLFMT "tty_read: ttyh=%p, fd=%p, len=%u, t=%u\n", FL,
					(void *)wti, (void *)wti->fd, count, timeout);
	}

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

//	GetCommTimeouts(dl0d->fd, &devtimeouts);	//get current timeouts
	//and modify them
	devtimeouts.ReadIntervalTimeout= timeout ? 0:MAXDWORD;	//disabled unless timeout was 0.
	devtimeouts.ReadTotalTimeoutMultiplier=0;	//timeout per requested byte
	devtimeouts.ReadTotalTimeoutConstant=timeout;	// (tconst + mult*numbytes) = total timeout on read
	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));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	if (! ReadFile(wti->fd, buf, count, &bytesread, pOverlap)) {
		fprintf(stderr, FLFMT "ReadFile error: %s\n",FL, diag_os_geterr(0));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	if (bytesread > 0)
		rv=bytesread;
	return rv;

}
예제 #21
0
static int
diag_l0_elm_send(struct diag_l0_device *dl0d,
	UNUSED(const char *subinterface), const void *data, size_t len)
{
	uint8_t buf[ELM_BUFSIZE];
	//ssize_t xferd;
	int rv;
	unsigned int i;

	if (len <= 0)
		return diag_iseterr(DIAG_ERR_BADLEN);

	if ((2*len)>(ELM_BUFSIZE-1)) {
		//too much data for buffer size
		fprintf(stderr, FLFMT "ELM: too much data for buffer (report this bug please!)\n", FL);
		return diag_iseterr(DIAG_ERR_BADLEN);
	}

	if (diag_l0_debug & DIAG_DEBUG_WRITE) {
		fprintf(stderr, FLFMT "ELM: sending %d bytes\n", FL, (int) len);
	}

	for (i=0; i<len; i++) {
		//fill buffer with ascii-fied hex data
		snprintf((char *) &buf[2*i], 3, "%02X", (unsigned int)((uint8_t *)data)[i] );
	}
	i=2*len;
	buf[i]=0x0D;
	buf[i+1]=0x00;	//terminate string

	if ((diag_l0_debug & DIAG_DEBUG_WRITE) && (diag_l0_debug & DIAG_DEBUG_DATA)) {
		fprintf(stderr, FLFMT "ELM: (sending string %s)\n", FL, (char *) buf);
	}

	rv=diag_tty_write(dl0d, buf, i+1);
	if (rv != (int) (i+1)) {	//XXX danger ! evil cast !
		fprintf(stderr, FLFMT "elm_send:write error\n",FL);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	return 0;
}
예제 #22
0
파일: diag_l3.c 프로젝트: remspoor/freediag
int diag_l3_send(struct diag_l3_conn *d_l3_conn, struct diag_msg *msg)
{
	int rv;
	const struct diag_l3_proto *dp = d_l3_conn->d_l3_proto;

	rv = dp->diag_l3_proto_send(d_l3_conn, msg);

	if (!rv)
		d_l3_conn->timer=diag_os_getms();

	return rv? diag_iseterr(rv):0;
}
예제 #23
0
/*
 * Set/Clear DTR and RTS lines, as specified
 */
int
diag_tty_control(struct diag_l0_device *dl0d,  unsigned int dtr, unsigned int rts)
{
	int flags;	/* Current flag values. */
	struct unix_tty_int *uti = (struct unix_tty_int *)dl0d->tty_int;
	int setflags = 0, clearflags = 0;

	if (dtr)
		setflags = TIOCM_DTR;
	else
		clearflags = TIOCM_DTR;

	if (rts)
		setflags = TIOCM_RTS;
	else
		clearflags = TIOCM_RTS;

	errno = 0;
	if (ioctl(uti->fd, TIOCMGET, &flags) < 0) {
		fprintf(stderr,
			FLFMT "open: Ioctl TIOCMGET failed %s\n", FL, strerror(errno));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	flags |= setflags;
	flags &= ~clearflags;

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

	if (diag_l0_debug & DIAG_DEBUG_TIMER) {
		unsigned long tc=diag_os_chronoms(0);
		fprintf(stderr, FLFMT "%lu : DTR/RTS changed\n", FL, tc);
	}

	return 0;
}
예제 #24
0
파일: diag_tty.c 프로젝트: butljon/freediag
/*
 * Set/Clear DTR and RTS lines, as specified
 */
int
diag_tty_control(struct diag_l0_device *dl0d,  int dtr, int rts)
{
	int flags;	/* Current flag values. */
	struct timeval tv;	//for getting timestamps
	int setflags = 0, clearflags = 0;

	if (dtr)
		setflags = TIOCM_DTR;
	else
		clearflags = TIOCM_DTR;
	
	if (rts)
		setflags = TIOCM_RTS;
	else
		clearflags = TIOCM_RTS;

	errno = 0;
	if (ioctl(dl0d->fd, TIOCMGET, &flags) < 0) {
		fprintf(stderr, 
			FLFMT "open: Ioctl TIOCMGET failed %s\n", FL, strerror(errno));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	flags |= setflags;
	flags &= ~clearflags;

	if (ioctl(dl0d->fd, TIOCMSET, &flags) < 0) {
		fprintf(stderr, 
			FLFMT "open: Ioctl TIOCMSET failed %s\n", FL, strerror(errno));
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	gettimeofday(&tv, NULL);
	if (diag_l0_debug & DIAG_DEBUG_TIMER) {
		fprintf(stderr, FLFMT "%04ld.%03ld : DTR/RTS changed\n", FL, tv.tv_sec, tv.tv_usec);
	}

	return 0;
}
예제 #25
0
// Simulates the send of a request.
// Returns 0 on success, -1 on failure.
// Should be called with the full message to send, because
// CARSIM behaves like a smart interface (does P4).
// Gets the list of responses from the DB file for the given request.
static int
diag_l0_sim_send(struct diag_l0_device *dl0d,
		UNUSED(const char *subinterface),
		 const void *data, const size_t len)
{
	struct diag_l0_sim_device * dev = dl0d->dl0_handle;

	if (len <= 0)
		return diag_iseterr(DIAG_ERR_BADLEN);

	if (len > 255) {
		fprintf(stderr, FLFMT "Error : calling diag_l0_sim_send with len >255 bytes! (%u)\n", FL, (unsigned int) len);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	if (sim_last_ecu_responses != NULL) {
		fprintf(stderr, FLFMT "AAAHHH!!! You're sending a new request before reading all previous responses!!! \n", FL);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	if (diag_l0_debug & DIAG_DEBUG_WRITE) {
		fprintf(stderr, FLFMT "dl0d=%p sending %u bytes\n", FL, (void *)dl0d, (unsigned int)len);
		if (diag_l0_debug & DIAG_DEBUG_DATA) {
			fprintf(stderr, FLFMT "L0 sim sending: ", FL);
			diag_data_dump(stderr, data, len);
			fprintf(stderr, "\n");
		}
	}


	// Build the list of responses for this request.
	sim_find_responses(&sim_last_ecu_responses, dev->fp, data, (uint8_t) len);

	if (diag_l0_debug & DIAG_DEBUG_DATA)
		sim_dump_ecu_responses(sim_last_ecu_responses);

	return 0;
}
예제 #26
0
// Simulates the bus initialization.
static int
diag_l0_sim_initbus(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in)
{
	struct diag_l0_sim_device *dev;
	uint8_t synch_patt[1];
	const uint8_t sim_break = 0x00;

	sim_free_ecu_responses(&sim_last_ecu_responses);

	dev = (struct diag_l0_sim_device *)dl0d->dl0_handle;

	if (diag_l0_debug & DIAG_DEBUG_IOCTL)
		fprintf(stderr, FLFMT "device link %p info %p initbus type %d\n", FL, (void *)dl0d, (void *)dev, in->type);

	if (!dev)
		return diag_iseterr(DIAG_ERR_INIT_NOTSUPP);

	switch (in->type) {
	case DIAG_L1_INITBUS_FAST:
		// Send break.
		// We simulate a break with a single "0x00" char.
		if (diag_l0_debug & DIAG_DEBUG_DATA)
			fprintf(stderr, FLFMT "Sending: BREAK!\n", FL);
		diag_l0_sim_send(dl0d, 0, &sim_break, 1);
		break;
	case DIAG_L1_INITBUS_5BAUD:
		// Send Service Address (as if it was at 5baud).
		diag_l0_sim_send(dl0d, 0, &in->addr, 1);
		// Receive Synch Pattern (as if it was at 10.4kbaud).
		diag_l0_sim_recv(dl0d, 0 , synch_patt, 1, 0);
		break;
	default:
		return diag_iseterr(DIAG_ERR_INIT_NOTSUPP);
		break;
	}

	return 0;
}
예제 #27
0
파일: diag_l1.c 프로젝트: butljon/freediag
//return <0 on error, number of bytes on success
static int
diag_l1_saferead(struct diag_l0_device *dl0d, char *buf, size_t bufsiz, int timeout)
{
	int xferd;

	/* And read back the single byte echo, which shows TX completes */
	while ( (xferd = diag_tty_read(dl0d, buf, bufsiz, timeout)) < 0) {
		if (errno != EINTR)
			return diag_iseterr(DIAG_ERR_BUSERROR);
		xferd = 0; /* Interrupted read, nothing transferred. */
	}

	return xferd;
}
예제 #28
0
int diag_l3_recv(struct diag_l3_conn *d_l3_conn, unsigned int timeout,
	void (* rcv_call_back)(void *handle ,struct diag_msg *) , void *handle)
{
	const struct diag_l3_proto *dp = d_l3_conn->d_l3_proto;
	int rv;

	rv=dp->diag_l3_proto_recv(d_l3_conn, timeout,
		rcv_call_back, handle);

	if (rv==0)
		d_l3_conn->timer=diag_os_getms();

	return rv? diag_iseterr(rv):0;
}
예제 #29
0
파일: diag_l1.c 프로젝트: fenugrec/freediag
/*
 * Open the L0 device with L1 proto.
 *
 */
int
diag_l1_open(struct diag_l0_device *dl0d, int l1protocol) {
	DIAG_DBGM(diag_l1_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
		FLFMT "diag_l1_open(0x%p, l1 proto=%d\n",
		FL, (void *)dl0d, l1protocol);

	/* Check h/w supports this l1 protocol */
	if ((dl0d->dl0->l1proto_mask & l1protocol) == 0) {
		return diag_iseterr(DIAG_ERR_PROTO_NOTSUPP);
	}

	/* Call the open routine with the requested L1 protocol */
	return diag_l0_open(dl0d, l1protocol);
}
예제 #30
0
ssize_t diag_tty_write(struct diag_l0_device *dl0d, const void *buf, const size_t count) {
    DWORD byteswritten;
    OVERLAPPED *pOverlap;
    struct tty_int *wti = (struct tty_int *)dl0d->tty_int;
    pOverlap=NULL;		//note : if overlap is eventually enabled, the CreateFile flags should be adjusted

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

    if (count <= 0)
        return diag_iseterr(DIAG_ERR_BADLEN);

    if (! WriteFile(wti->fd, buf, count, &byteswritten, pOverlap)) {
        fprintf(stderr, FLFMT "WriteFile error:%s. %u bytes written, %u requested\n", FL, diag_os_geterr(0), (unsigned int) byteswritten, count);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }
    if (!FlushFileBuffers(wti->fd)) {
        fprintf(stderr, FLFMT "tty_write : could not flush buffers, %s\n", FL, diag_os_geterr(0));
        return diag_iseterr(DIAG_ERR_GENERAL);
    }
    return byteswritten;
} //diag_tty_write