Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89b54397 authored by James Courtier-Dutton's avatar James Courtier-Dutton Committed by Greg Kroah-Hartman
Browse files

USB: iuu_phoenix: Add support for different baud rates.

parent 202380d9
Loading
Loading
Loading
Loading
+41 −13
Original line number Original line Diff line number Diff line
/*
/*
 * Infinity Unlimited USB Phoenix driver
 * Infinity Unlimited USB Phoenix driver
 *
 *
 * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk)

 * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
 * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
 *
 *
 * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás)
 * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás)
@@ -40,7 +42,7 @@ static int debug;
/*
/*
 * Version Information
 * Version Information
 */
 */
#define DRIVER_VERSION "v0.11"
#define DRIVER_VERSION "v0.12"
#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"


static const struct usb_device_id id_table[] = {
static const struct usb_device_id id_table[] = {
@@ -81,6 +83,9 @@ struct iuu_private {
	u8 *dbgbuf;		/* debug buffer */
	u8 *dbgbuf;		/* debug buffer */
	u8 len;
	u8 len;
	int vcc;		/* vcc (either 3 or 5 V) */
	int vcc;		/* vcc (either 3 or 5 V) */
	u32 baud;
	u32 boost;
	u32 clk;
};
};




@@ -157,13 +162,14 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
	    port->number, set, clear);
	    port->number, set, clear);


	spin_lock_irqsave(&priv->lock, flags);
	spin_lock_irqsave(&priv->lock, flags);
	if (set & TIOCM_RTS)
		priv->tiostatus = TIOCM_RTS;


	if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
	if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) {
		dbg("%s TIOCMSET RESET called !!!", __func__);
		dbg("%s TIOCMSET RESET called !!!", __func__);
		priv->reset = 1;
		priv->reset = 1;
	}
	}
	if (set & TIOCM_RTS)
		priv->tiostatus = TIOCM_RTS;

	spin_unlock_irqrestore(&priv->lock, flags);
	spin_unlock_irqrestore(&priv->lock, flags);
	return 0;
	return 0;
}
}
@@ -851,20 +857,24 @@ static int iuu_uart_off(struct usb_serial_port *port)
	return status;
	return status;
}
}


static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base,
			 u32 *actual, u8 parity)
			 u32 *actual, u8 parity)
{
{
	int status;
	int status;
	u32 baud;
	u8 *dataout;
	u8 *dataout;
	u8 DataCount = 0;
	u8 DataCount = 0;
	u8 T1Frekvens = 0;
	u8 T1Frekvens = 0;
	u8 T1reload = 0;
	u8 T1reload = 0;
	unsigned int T1FrekvensHZ = 0;
	unsigned int T1FrekvensHZ = 0;


	dbg("%s - enter baud_base=%d", __func__, baud_base);
	dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
	dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);


	if (!dataout)
	if (!dataout)
		return -ENOMEM;
		return -ENOMEM;
	/*baud = (((priv->clk / 35) * baud_base) / 100000); */
	baud = baud_base;


	if (baud < 1200 || baud > 230400) {
	if (baud < 1200 || baud > 230400) {
		kfree(dataout);
		kfree(dataout);
@@ -948,15 +958,20 @@ static void iuu_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios)
		struct usb_serial_port *port, struct ktermios *old_termios)
{
{
	const u32 supported_mask = CMSPAR|PARENB|PARODD;
	const u32 supported_mask = CMSPAR|PARENB|PARODD;

	struct iuu_private *priv = usb_get_serial_port_data(port);
	unsigned int cflag = tty->termios->c_cflag;
	unsigned int cflag = tty->termios->c_cflag;
	int status;
	int status;
	u32 actual;
	u32 actual;
	u32 parity;
	u32 parity;
	int csize = CS7;
	int csize = CS7;
	int baud = 9600;	/* Fixed for the moment */
	int baud;
	u32 newval = cflag & supported_mask;
	u32 newval = cflag & supported_mask;


	/* Just use the ospeed. ispeed should be the same. */
	baud = tty->termios->c_ospeed;

	dbg("%s - enter c_ospeed or baud=%d", __func__, baud);

	/* compute the parity parameter */
	/* compute the parity parameter */
	parity = 0;
	parity = 0;
	if (cflag & CMSPAR) {	/* Using mark space */
	if (cflag & CMSPAR) {	/* Using mark space */
@@ -976,7 +991,7 @@ static void iuu_set_termios(struct tty_struct *tty,


	/* set it */
	/* set it */
	status = iuu_uart_baud(port,
	status = iuu_uart_baud(port,
			(clockmode == 2) ? 16457 : 9600 * boost / 100,
			baud * priv->boost / 100,
			&actual, parity);
			&actual, parity);


	/* set the termios value to the real one, so the user now what has
	/* set the termios value to the real one, so the user now what has
@@ -1018,6 +1033,7 @@ static void iuu_close(struct usb_serial_port *port)


static void iuu_init_termios(struct tty_struct *tty)
static void iuu_init_termios(struct tty_struct *tty)
{
{
	dbg("%s - enter", __func__);
	*(tty->termios) = tty_std_termios;
	*(tty->termios) = tty_std_termios;
	tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
	tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
				| TIOCM_CTS | CSTOPB | PARENB;
				| TIOCM_CTS | CSTOPB | PARENB;
@@ -1033,10 +1049,16 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
	struct usb_serial *serial = port->serial;
	struct usb_serial *serial = port->serial;
	u8 *buf;
	u8 *buf;
	int result;
	int result;
	int baud;
	u32 actual;
	u32 actual;
	struct iuu_private *priv = usb_get_serial_port_data(port);
	struct iuu_private *priv = usb_get_serial_port_data(port);


	dbg("%s -  port %d", __func__, port->number);
	baud = tty->termios->c_ospeed;
	tty->termios->c_ispeed = baud;
	/* Re-encode speed */
	tty_encode_baud_rate(tty, baud, baud);

	dbg("%s -  port %d, baud %d", __func__, port->number, baud);
	usb_clear_halt(serial->dev, port->write_urb->pipe);
	usb_clear_halt(serial->dev, port->write_urb->pipe);
	usb_clear_halt(serial->dev, port->read_urb->pipe);
	usb_clear_halt(serial->dev, port->read_urb->pipe);


@@ -1071,23 +1093,29 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
	iuu_uart_on(port);
	iuu_uart_on(port);
	if (boost < 100)
	if (boost < 100)
		boost = 100;
		boost = 100;
	priv->boost = boost;
	priv->baud = baud;
	switch (clockmode) {
	switch (clockmode) {
	case 2:		/*  3.680 Mhz */
	case 2:		/*  3.680 Mhz */
		priv->clk = IUU_CLK_3680000;
		iuu_clk(port, IUU_CLK_3680000 * boost / 100);
		iuu_clk(port, IUU_CLK_3680000 * boost / 100);
		result =
		result =
		    iuu_uart_baud(port, 9600 * boost / 100, &actual,
		    iuu_uart_baud(port, baud * boost / 100, &actual,
				  IUU_PARITY_EVEN);
				  IUU_PARITY_EVEN);
		break;
		break;
	case 3:		/*  6.00 Mhz */
	case 3:		/*  6.00 Mhz */
		iuu_clk(port, IUU_CLK_6000000 * boost / 100);
		iuu_clk(port, IUU_CLK_6000000 * boost / 100);
		priv->clk = IUU_CLK_6000000;
		/* Ratio of 6000000 to 3500000 for baud 9600 */
		result =
		result =
		    iuu_uart_baud(port, 16457 * boost / 100, &actual,
		    iuu_uart_baud(port, 16457 * boost / 100, &actual,
				  IUU_PARITY_EVEN);
				  IUU_PARITY_EVEN);
		break;
		break;
	default:		/*  3.579 Mhz */
	default:		/*  3.579 Mhz */
		iuu_clk(port, IUU_CLK_3579000 * boost / 100);
		iuu_clk(port, IUU_CLK_3579000 * boost / 100);
		priv->clk = IUU_CLK_3579000;
		result =
		result =
		    iuu_uart_baud(port, 9600 * boost / 100, &actual,
		    iuu_uart_baud(port, baud * boost / 100, &actual,
				  IUU_PARITY_EVEN);
				  IUU_PARITY_EVEN);
	}
	}