Esempio n. 1
0
static void sc16is7xx_set_termios(struct uart_port *port,
				  struct ktermios *termios,
				  struct ktermios *old)
{
	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
	unsigned int lcr, flow = 0;
	int baud;

	/* Mask termios capabilities we don't support */
	termios->c_cflag &= ~CMSPAR;

	/* Word size */
	switch (termios->c_cflag & CSIZE) {
	case CS5:
		lcr = SC16IS7XX_LCR_WORD_LEN_5;
		break;
	case CS6:
		lcr = SC16IS7XX_LCR_WORD_LEN_6;
		break;
	case CS7:
		lcr = SC16IS7XX_LCR_WORD_LEN_7;
		break;
	case CS8:
		lcr = SC16IS7XX_LCR_WORD_LEN_8;
		break;
	default:
		lcr = SC16IS7XX_LCR_WORD_LEN_8;
		termios->c_cflag &= ~CSIZE;
		termios->c_cflag |= CS8;
		break;
	}

	/* Parity */
	if (termios->c_cflag & PARENB) {
		lcr |= SC16IS7XX_LCR_PARITY_BIT;
		if (!(termios->c_cflag & PARODD))
			lcr |= SC16IS7XX_LCR_EVENPARITY_BIT;
	}

	/* Stop bits */
	if (termios->c_cflag & CSTOPB)
		lcr |= SC16IS7XX_LCR_STOPLEN_BIT; /* 2 stops */

	/* Set read status mask */
	port->read_status_mask = SC16IS7XX_LSR_OE_BIT;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= SC16IS7XX_LSR_PE_BIT |
					  SC16IS7XX_LSR_FE_BIT;
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= SC16IS7XX_LSR_BI_BIT;

	/* Set status ignore mask */
	port->ignore_status_mask = 0;
	if (termios->c_iflag & IGNBRK)
		port->ignore_status_mask |= SC16IS7XX_LSR_BI_BIT;
	if (!(termios->c_cflag & CREAD))
		port->ignore_status_mask |= SC16IS7XX_LSR_BRK_ERROR_MASK;

	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
			     SC16IS7XX_LCR_CONF_MODE_B);

	/* Configure flow control */
	regcache_cache_bypass(s->regmap, true);
	sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]);
	sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]);
	if (termios->c_cflag & CRTSCTS)
		flow |= SC16IS7XX_EFR_AUTOCTS_BIT |
			SC16IS7XX_EFR_AUTORTS_BIT;
	if (termios->c_iflag & IXON)
		flow |= SC16IS7XX_EFR_SWFLOW3_BIT;
	if (termios->c_iflag & IXOFF)
		flow |= SC16IS7XX_EFR_SWFLOW1_BIT;

	sc16is7xx_port_write(port, SC16IS7XX_EFR_REG, flow);
	regcache_cache_bypass(s->regmap, false);

	/* Update LCR register */
	sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);

	/* Get baud rate generator configuration */
	baud = uart_get_baud_rate(port, termios, old,
				  port->uartclk / 16 / 4 / 0xffff,
				  port->uartclk / 16);

	/* Setup baudrate generator */
	baud = sc16is7xx_set_baud(port, baud);

	/* Update timeout according to new baud rate */
	uart_update_timeout(port, termios->c_cflag, baud);
}
int
main(int argc, char **argv)
{
	int spi_i2c_fd;
	char *spi_i2c_devname = DEFAULT_DEVICE;
	struct sc16is7xx *sc16is7xx;
	ssize_t txlvl, rxlvl;
	unsigned char buf[128];
	int i2c_addr = DEFAULT_I2C_ADDR;
	int ptyfd, nfds, i, j;
	fd_set readfds, writefds;
	struct timeval to;
	int baudrate = DEFAULT_BAUDRATE;
	unsigned int xfers, txcounter, rxcounter;
	int gpio_out = -1;

	while ((i=getopt(argc, argv, "d:a:b:g:h")) != -1) {
		switch (i) {
		case 'd':
			spi_i2c_devname = optarg;
			break;
		case 'a':
			i2c_addr = atoi(optarg);
			break;
		case 'b':
			baudrate = atoi(optarg);
			break;
		case 'g':
			gpio_out = strtoul(optarg, NULL, 0);
			break;
		case 'h':
			usage(argv[0]);
			exit(1);
			break;
		}
	}

	ptyfd = open("/dev/ptmx", O_RDWR|O_NOCTTY|O_NONBLOCK);
	if (ptyfd == -1) {
		perror("/dev/ptmx");
		exit(1);
	}

	if (ptsname_r(ptyfd, (char*)buf, sizeof(buf))) {
		perror("ptsname_r()");
		exit(1);
	}

	fprintf(stderr,"Virtual terminal is %s.\n", buf);;

	if (grantpt(ptyfd) == -1) {
		perror("grantpt()");
		exit(1);
	}

	if (unlockpt(ptyfd) == -1) {
		perror("unlockpt()");
		exit(1);
	}

	if ((spi_i2c_fd = open(spi_i2c_devname, O_RDWR|O_NOCTTY)) == -1) {
		perror(spi_i2c_devname);
		exit(1);
	}

	sc16is7xx = sc16is7xx_new(spi_i2c_fd, i2c_addr, 0/*flags*/);
	if (!sc16is7xx) {
		fprintf(stderr, "Could not create sc16is7xx instance.\n");
		exit(1);
	}

	if (sc16is7xx_set_baud(sc16is7xx, baudrate) == -1) {
		perror("sc16is7xx_set_baud()");
		exit(1);
	}

	if (gpio_out != -1) {
		fprintf(stderr, "setting GPIO to 0x%04x\n", gpio_out & 0xff);
		for (i=7; i>=0; i--)
			fprintf(stderr," D%d=%d", i, !!(gpio_out & (1<<i)));
		fprintf(stderr,"\n");
		if (sc16is7xx_gpio_out(sc16is7xx, 0xff, gpio_out & 0xff) == -1) {
			perror("sc16is7xx_gpio_out");
			exit(1);
		}
	}

	fprintf(stderr,"Baudrate is %d.\n\n", baudrate);

	/* main loop */
	while (1) {
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
		nfds=0;

		/* are we able to write? */
		txlvl = sc16is7xx_get_txlvl(sc16is7xx);
		if (txlvl == -1) {
			perror("sc16is7xx_get_txlvl()");
			exit(1);
		}

		if (txlvl > 0) {
			if (txlvl > (signed int)sizeof(buf))
				txlvl = (signed int)sizeof(buf);
			/* so register for reading on pty*/
			FD_SET(ptyfd, &readfds);
			if (nfds < ptyfd + 1)
				nfds = ptyfd + 1;
		}

		/* is there something in the receive buffer? */
		rxlvl = sc16is7xx_get_rxlvl(sc16is7xx);
		if (rxlvl == -1) {
			perror("sc16is7xx_get_rxlvl()");
			exit(1);
		}

		if (rxlvl > 0) {
			if (rxlvl > (signed int)sizeof(buf))
				rxlvl = (signed int)sizeof(buf);
			/* so register for writing to the pty */
			FD_SET(ptyfd, &writefds);
			if (nfds < ptyfd + 1)
				nfds = ptyfd + 1;
		}

		to.tv_sec = 0;
		to.tv_usec = (rxlvl > 0) ? 0 : 1000; /* 1ms */

		i = select(nfds, &readfds, &writefds, NULL, &to);
		if (i == -1) {
			perror("select()");
			exit(1);
		}

		sc16is7xx_stats(sc16is7xx, &xfers, &txcounter, &rxcounter);
		fprintf(stderr,"\r%u %u %u %4d %4d\r",
			xfers, txcounter, rxcounter, txlvl, rxlvl);
		fflush(stderr);

		/* amuse Marco */
		if ((txlvl==64) && (rxlvl==0) && (gpio_out != -1)) {
			gpio_out = gpio_out ^ 0xff;
			if (sc16is7xx_gpio_out(sc16is7xx, 0xff, gpio_out & 0xff) == -1) {
				perror("sc16is7xx_gpio_out");
				exit(1);
			}
		}

		if (i == 0)
			continue;

		/* check if we can read from pty -> write to uart */
		if (FD_ISSET(ptyfd, &readfds)) {
			i = read(ptyfd, buf, txlvl);
			if (i < 0) {
				perror("read(pty)");
				exit(1);
			}

			j = sc16is7xx_write(sc16is7xx, buf, i);
			if (j < 0) {
				perror("sc16is7xx_write()");
				exit(1);
			}

			if (i != j) {
				fprintf(stderr,
					"Wrote only %d of %d bytes to UART!\n",
					j, i);
			}
		}

		if (FD_ISSET(ptyfd, &writefds)) {
			i = sc16is7xx_read(sc16is7xx, buf, sizeof(buf));
			if (i < 0) {
				perror("sc16is7xx_read()");
				exit(1);
			}

			j = write(ptyfd, buf, i);
			if (j < 0) {
				perror("write(pty)");
				exit(1);
			}

			if (i != j) {
				fprintf(stderr,
					"Wrote only %d of %d bytes to pty.",
					j, i);
			}
		}

	} /* while(1) */

	return 0;
}