Example #1
0
//diag_l0_elm_close : free pdl0d->dl0 (dev), call diag_tty_close.
static int
diag_l0_elm_close(struct diag_l0_device **pdl0d)
{
	assert(pdl0d != NULL);
	assert(*pdl0d != NULL);
	uint8_t buf[]="ATPC\x0D";
	elm_sendcmd(*pdl0d, buf, 5, 500, NULL);	//close protocol. So clean !
	if (pdl0d && *pdl0d) {
		struct diag_l0_device *dl0d = *pdl0d;
		struct diag_l0_elm_device *dev =
			(struct diag_l0_elm_device *)dl0d->l0_int;

		/* If debugging, print to stderr */
		if (diag_l0_debug & DIAG_DEBUG_CLOSE)
			fprintf(stderr, FLFMT "link %p closing\n",
				FL, (void *) dl0d);

		if (dev)
			free(dev);

		(void) diag_tty_close(dl0d);
		diag_l0_del(*pdl0d);
	}

	return 0;
}
Example #2
0
static void
br_close(struct diag_l0_device *dl0d) {
	if (!dl0d) {
		return;
	}

	struct br_device *dev = dl0d->l0_int;

	DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_CLOSE, DIAG_DBGLEVEL_V,
		FLFMT "link %p closing\n", FL, (void *)dl0d);

	diag_tty_close(dev->tty_int);
	dev->tty_int = NULL;
	dl0d->opened = 0;

	return;
}
Example #3
0
static int
diag_l0_br_close(struct diag_l0_device **pdl0d)
{
	if (pdl0d && *pdl0d) {
		struct diag_l0_device *dl0d = *pdl0d;
		struct diag_l0_br_device *dev =
			(struct diag_l0_br_device *)dl0d->l0_int;

		if (diag_l0_debug & DIAG_DEBUG_CLOSE)
			fprintf(stderr, FLFMT "link %p closing\n", FL, (void *)dl0d);

		if (dev)
			free(dev);
		(void) diag_tty_close(dl0d);
		diag_l0_del(dl0d);
	}

	return 0;
}
Example #4
0
static void
diag_l0_muleng_close(struct diag_l0_device *dl0d)
{
	if (!dl0d) return;
	struct diag_l0_muleng_device *dev =
		(struct diag_l0_muleng_device *)dl0d->l0_int;

	if (diag_l0_debug & DIAG_DEBUG_CLOSE)
		fprintf(stderr, FLFMT "link %p closing\n",
			FL, (void *)dl0d);

	if (dev)
		free(dev);

	diag_tty_close(dl0d);
	diag_l0_del(dl0d);

	return;
}
Example #5
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
Example #6
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;
}
Example #7
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;
}