Re: [PATCH] iuu_phoenix new driver proposal 2 fixed

<[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <000c01c7c9d4$04a35050$0de9f0f0$@com>
OOps ;-)

2 missing characters...

Now it compile without warning or error



-----Message d'origine-----
De : [email protected]
[mailto:[email protected]] De la part de Oliver
Neukum
Envoyé : jeudi 19 juillet 2007 8:22
À : [email protected]
Cc : Alain Degreffe
Objet : Re: [linux-usb-devel] [PATCH] iuu_phoenix new driver proposal 2

Am Mittwoch 18 Juli 2007 schrieb Alain Degreffe:


+static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+	u8 *st;
+	int status ;
+	st = kmalloc(sizeof(u8), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM ;
+	iuu_status(port, st);
+
+	dbg("%s (%d) msg ", __FUNCTION__, port->number);
+	if (st[0] & IUU_FULLCARD_IN) {
+		dbg("%s  card present ! value returned %i ", __FUNCTION__,
+		    TIOCM_CD);
+		status = 0 ;
+	} else {
+		status TIOCM_CD;

Could you make the code compileable and resubmit it?

	Regards
		Oliver


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
iuu_phoenix.patch (application/octet-stream, 32.6 KB)
code modified ( I have applied all of your comments...)

Signed-off-by: Alain Degreffe <[email protected]>


diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 3efe670..1afcd0d 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -554,6 +554,15 @@ config USB_SERIAL_OMNINET
 	  To compile this driver as a module, choose M here: the
 	  module will be called omninet.
 
+config USB_SERIAL_IUU
+	tristate "Infinity Usb  Unlimited SM Reader (EXPERIMENTAL)"
+	depends on USB_SERIAL && EXPERIMENTAL
+	help
+	  Say Y here if you want to use a IUU in phoenix mode.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iuu_phoenix.
+
 config USB_SERIAL_DEBUG
 	tristate "USB Debugging Device"
 	depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 61166ad..96b8ddc 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -47,4 +47,5 @@ obj-$(CONFIG_USB_SERIAL_TI)			+= ti_usb_3410_5052.o
 obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o
 obj-$(CONFIG_USB_SERIAL_XIRCOM)			+= keyspan_pda.o
+obj-$(CONFIG USB_SERIAL_IUU)			+= iuu_phoenix.o
 
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
new file mode 100644
index 0000000..52972ca
--- /dev/null
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -0,0 +1,1111 @@
+/*
+ * Infinity Unlimited USB Phoenix driver
+ *
+ * Copyright (C) 2007 Alain Degreffe ([email protected])
+ *
+ *
+ * Original code taken from iuutool ( Copyright (C) 2006 Juan Carlos Borrás )
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *  And tested with help of WB Electronics
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include "iuu_phoenix.h"
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+int debug = 1;
+#else
+int debug = 0;
+#endif
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.2"
+#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
+
+static struct usb_device_id id_table[] = {
+	{USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)},
+	{}			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver iuu_driver = {
+	.name = "iuu_phoenix",
+	.probe = usb_serial_probe,
+	.disconnect = usb_serial_disconnect,
+	.id_table = id_table,
+	.no_dynamic_id = 1,
+};
+
+static int iuu_startup(struct usb_serial *serial);
+
+static void iuu_shutdown(struct usb_serial *serial);
+
+static int iuu_open(struct usb_serial_port *port, struct file *filp);
+static void iuu_close(struct usb_serial_port *port, struct file *filp);
+
+static int iuu_uart_write(struct usb_serial_port *port,
+			  const u8 *buf, int count);
+
+static int read_immediate(struct usb_serial_port *port, u8 *buf,
+			  u8 count);
+static int iuu_uart_flush(struct usb_serial_port *port);
+static int iuu_uart_read(struct usb_serial_port *port, u8 *data,
+			 u8 *len);
+static int iuu_uart_baud(struct usb_serial_port *port, u_int32_t baud,
+			 u_int32_t *actual, u_int8_t parity);
+static int iuu_reset(struct usb_serial_port *port, u_int8_t wt);
+static int bulk_immediate(struct usb_serial_port *port, u8 *buf,
+			  u8 count);
+
+static int iuu_ioctl(struct usb_serial_port *port, struct file *file,
+		     unsigned int cmd, unsigned long arg);
+static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+			unsigned int set, unsigned int clear);
+static int iuu_tiocmget(struct usb_serial_port *port, struct file *file);
+
+static int iuu_uart_read_and_store(struct usb_serial_port *port);
+static int iuu_uart_on(struct usb_serial_port *port);
+static int iuu_uart_off(struct usb_serial_port *port);
+
+static struct usb_serial_driver iuu_device = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = "IUU Phoenix",
+		   },
+	.id_table = id_table,
+	.num_interrupt_in = NUM_DONT_CARE,
+	.num_bulk_in = 1,
+	.num_bulk_out = 1,
+	.num_ports = 1,
+	.open = iuu_open,
+	.close = iuu_close,
+	.write = iuu_uart_write,
+	.ioctl = iuu_ioctl,
+	.tiocmget = iuu_tiocmget,
+	.tiocmset = iuu_tiocmset,
+	.attach = iuu_startup,
+	.shutdown = iuu_shutdown,
+};
+
+struct iuu_private {
+	spinlock_t lock; /* store irq state */
+	wait_queue_head_t delta_msr_wait;
+	u8 line_control;
+	u8 line_status;
+	u8 termios_initialized;
+	int write_busy;
+	int TIOSTATUS;
+};
+
+/* Structure used for write/read operation */
+
+struct iuu_buffers {
+	u8 buf[256];
+	u8 finalbuf[256];
+	u8 dbgbuf[512];
+	u8 len;
+};
+
+/* turbo parameter */
+
+int multiplicator = 100;
+int clockmode = 1;
+int smart = 1;
+
+static int iuu_startup(struct usb_serial *serial)
+{
+	struct iuu_private *priv;
+	priv = kmalloc(sizeof(struct iuu_private), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	memset(priv, 0x00, sizeof(struct iuu_private));
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->delta_msr_wait);
+	usb_set_serial_port_data(serial->port[0], priv);
+	return 0;
+}
+
+/* Shutdown function */
+
+static void iuu_shutdown(struct usb_serial *serial)
+{
+
+	dbg("%s", __FUNCTION__);
+	kfree(usb_get_serial_port_data(serial->port[0]));
+	usb_set_serial_port_data(serial->port[0], NULL);
+}
+
+/* Status Function
+ * Return value is
+ * 0x00 = no card
+ * 0x01 = smartcard
+ * 0x02 = sim card
+ */
+
+int iuu_status(struct usb_serial_port *port, char *st)
+{
+	int status;
+	st[0] = IUU_GET_STATE_REGISTER;
+
+	status = bulk_immediate(port, st, 1);
+	if (status != IUU_OPERATION_OK) {
+		return status;
+	}
+
+	status = read_immediate(port, st, 1);
+	return status;
+}
+
+/* Fake settings
+ * The IUU need to be reset to deliver the ATR value
+ * ioctl is used ( tiocmget/set in new kernels) to pass the RST order
+ * In real life, a period of 500 ms is required to reset a card
+ * Here we just care that RST followed by a NONE is received to call iuu_reset
+ */
+
+static int
+iuu_tiocmset(struct usb_serial_port *port, struct file *file, unsigned int set,
+	     unsigned int clear)
+{
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	tty = port->tty;
+
+	dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __FUNCTION__,
+	    port->number, set, clear);
+	if (set == TIOCM_RTS)
+		priv->TIOSTATUS = TIOCM_RTS;
+
+	if ((set == 0) && priv->TIOSTATUS == TIOCM_RTS) {
+		dbg("%s TIOCMSET RESET called !!!", __FUNCTION__);
+		priv->TIOSTATUS = 0;
+		if (iuu_reset(port, 0x0C))
+			return -EIO;
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(1 + 500 * HZ / 1000);
+		iuu_uart_read_and_store(port);
+	}
+
+	return 0;
+}
+
+/* This is used to provide a carrier detect mechanism
+ * When a card is present, the response is 0x00
+ * When no card , the reader respond with TIOCM_CD
+ * This is known as CD autodetect mechanism
+ */
+
+static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+	u8 *st;
+	int status ;
+	st = kmalloc(sizeof(u8), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM ;
+
+	iuu_status(port, st);
+
+	dbg("%s (%d) msg ", __FUNCTION__, port->number);
+	if (st[0] & IUU_FULLCARD_IN) {
+		dbg("%s  card present ! value returned %i ", __FUNCTION__,
+		    TIOCM_CD);
+		status = 0 ;
+	} else {
+		status = TIOCM_CD;
+	}
+	kfree(st);
+	return status ;
+}
+
+
+/*
+ *
+ * I don't know if I will use this function
+ * but it could be usefull to support non classical
+ * ioctl command for special tuning with program
+ * in userland like iptable for netfilter....
+ *
+ *
+ */
+
+static int
+iuu_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd,
+	  unsigned long arg)
+{
+
+	int mask;
+
+	dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
+
+	if ( get_user(mask, (unsigned long *)arg) )
+		return -EFAULT ;
+
+	dbg("%s (%d) msg = %04x", __FUNCTION__, port->number, mask);
+	switch (cmd) {
+	case TCGETS:
+		return (0);
+
+	/* could be usefull later... */
+	case TCFLSH:
+		return -ENOIOCTLCMD;
+
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TCSETS:
+	case TIOCSSERIAL:
+		if (mask & CS8)
+			dbg("%s  TIOCMSET CS8", __FUNCTION__);
+		if (mask & CS7)
+			dbg("%s  TIOCMSET CS7", __FUNCTION__);
+		if (mask & CSTOPB)
+			dbg("%s  TIOCMSET CSTOPB", __FUNCTION__);
+		if (mask & PARENB)
+			dbg("%s  TIOCMSET PARENB", __FUNCTION__);
+		if (mask & PARODD)
+			dbg("%s  TIOCMSET PARODD", __FUNCTION__);
+
+		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
+		    port->number);
+		return (0);
+
+	case TIOCMIWAIT:
+		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+		return 0;
+
+	default:
+		dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
+
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int iuu_reset(struct usb_serial_port *port, u_int8_t wt)
+{
+	int status;
+	u8 *buf;
+
+	status = iuu_uart_flush(port);
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - reset (flush) error ", __FUNCTION__);
+		return status;
+	}
+
+	buf = kmalloc(sizeof(u8) * 4, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = IUU_RST_SET;
+	buf[1] = IUU_DELAY_MS;
+	buf[2] = wt;		/* miliseconds */
+	buf[3] = IUU_RST_CLEAR;
+
+	status = bulk_immediate(port, buf, 4);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - reset error ", __FUNCTION__);
+	else
+		dbg("%s - reset OK ", __FUNCTION__);
+	kfree(buf);
+	return status;
+}
+
+static int
+bulk_immediate(struct usb_serial_port *port, u8 *buf,
+	       u8 count)
+{
+	int status;
+	struct usb_serial *serial = port->serial;
+	int actual = 0;
+
+	/* send the data out the bulk port */
+
+	status =
+	    usb_bulk_msg(serial->dev,
+			 usb_sndbulkpipe(serial->dev,
+					 port->bulk_out_endpointAddress), buf,
+			 count, &actual, HZ * 1);
+
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - error = %2x", __FUNCTION__, status);
+	} else {
+		dbg("%s - write OK !", __FUNCTION__);
+	}
+	return status;
+}
+
+static int
+read_immediate(struct usb_serial_port *port, u8 *buf,
+	       u8 count)
+{
+	int status;
+	struct usb_serial *serial = port->serial;
+	int actual = 0;
+
+	/* send the data out the bulk port */
+
+	status =
+	    usb_bulk_msg(serial->dev,
+			 usb_rcvbulkpipe(serial->dev,
+					 port->bulk_in_endpointAddress), buf,
+			 count, &actual, HZ * 1);
+
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - error = %2x", __FUNCTION__, status);
+	} else {
+		dbg("%s - read OK !", __FUNCTION__);
+	}
+
+	return status;
+}
+
+int
+iuu_led(struct usb_serial_port *port, unsigned int R, unsigned int G,
+	unsigned int B, u8 f)
+{
+	int status;
+	u8 *buf;
+	buf = kmalloc(sizeof(u_int8_t) * 8, GFP_KERNEL);
+
+	buf[0] = IUU_SET_LED;
+	buf[1] = R & 0xFF;
+	buf[2] = (R >> 8) & 0xFF;
+	buf[3] = G & 0xFF;
+	buf[4] = (G >> 8) & 0xFF;
+	buf[5] = B & 0xFF;
+	buf[6] = (B >> 8) & 0xFF;
+	buf[7] = f;
+	status = bulk_immediate(port, buf, 8);
+	kfree(buf);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - led error status = %2x", __FUNCTION__, status);
+	else
+		dbg("%s - led OK !", __FUNCTION__);
+	return IUU_OPERATION_OK;
+}
+
+static int
+iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+	       int count)
+{
+	int status;
+	int curpos = 0;
+	int i;
+	int security = 0;
+
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	struct iuu_buffers *tmp;
+
+	if (count == 0)
+		return (0);
+
+	/* prevent buffer overflow */
+	if (count > 256)
+		return -ENOMEM;
+
+	if (priv->write_busy)
+		return -1;
+
+	tmp = kmalloc(sizeof(struct iuu_buffers), GFP_KERNEL);
+	if (!tmp)
+		return -EIO;
+
+	priv->write_busy = 1;
+	dbg("%s - try to write %i chars : %02X ", __FUNCTION__, count, buf[0]);
+	tmp->buf[0] = IUU_UART_ESC;
+	tmp->buf[1] = IUU_UART_TX;
+	tmp->buf[2] = count;
+	memcpy(&tmp->buf[3], buf, count);
+	dbg("%s - try to write %i chars ", __FUNCTION__, tmp->buf[2]);
+	status = bulk_immediate(port, tmp->buf, count + 3);
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - uart_write error", __FUNCTION__);
+		kfree(tmp);
+		priv->write_busy = 0;
+		return status;
+	}
+
+	tty = port->tty;
+
+	while (security < 200) {
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(1 + 1 * HZ / 1000);
+		if (iuu_uart_read(port, tmp->buf, &tmp->len) < 0) {
+			kfree(tmp);
+			dbg("%s - read error", __FUNCTION__);
+			return -EIO;
+		}
+		dbg("%s - port = %i , round = %i" , __FUNCTION__,
+			port->number, security );
+		if (tmp->len > 0) {
+			/* test buffer overflow */
+			if (curpos + tmp->len > 256) {
+				kfree(tmp);
+				return -1;
+			}
+			memcpy(&tmp->finalbuf[curpos], tmp->buf, tmp->len);
+			curpos += tmp->len;
+			for (i = 0; i < tmp->len; ++i) {
+				if (tty_buffer_request_room(tty, 1) == 0)
+					break;
+				tty_insert_flip_char(tty, tmp->buf[i],
+						     TTY_NORMAL);
+				sprintf(tmp->dbgbuf +
+					((curpos - tmp->len + i) * 2), "%02X",
+					tmp->buf[i]);
+			}
+			tmp->dbgbuf[curpos * 2] = '\0';
+			dbg("%s - read reader %i round %i = %s", __FUNCTION__,
+				port->number, security, tmp->dbgbuf);
+			tty_schedule_flip(tty);
+		}
+		if ( smart == 1 ) {
+
+			if ( (tmp->finalbuf[curpos - 2] == 0x90)
+				&& (curpos > count+1 )
+				&& (tmp->finalbuf[curpos - 1] == 0x00))
+					security = 200;
+			if (count == 5
+				&& curpos == count + 1
+				&& buf[2] != 0
+				&& buf[3] != 0 )
+					security = 200;
+			if ((tmp->finalbuf[curpos - 2] == 0x90)
+				&& (curpos == count + 2 )
+				&& (count > 5 ))
+					security = 200;
+		}
+		security++;
+	}
+	if ( security == 200 )
+		iuu_uart_flush(port);
+	kfree(tmp);
+	priv->write_busy = 0;
+	return count;
+
+}
+
+static int iuu_uart_read_and_store(struct usb_serial_port *port)
+{
+	struct iuu_buffers *tmp;
+	struct tty_struct *tty;
+	int i;
+
+	tmp = kmalloc(sizeof(struct iuu_buffers), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	if (iuu_uart_read(port, tmp->buf, &tmp->len) < 0) {
+		kfree(tmp);
+		return -EIO;
+	}
+
+	tty = port->tty;
+	for (i = 0; i < tmp->len; ++i) {
+		if (tty_buffer_request_room(tty, 1) == 0)
+			break;
+		tty_insert_flip_char(tty, tmp->buf[i], TTY_NORMAL);
+		sprintf(&tmp->dbgbuf[i * 2], "%02X", tmp->buf[i]);
+	}
+	tmp->dbgbuf[i * 2] = '\0';
+	dbg("%s - read = %s", __FUNCTION__, tmp->dbgbuf);
+	tty_flip_buffer_push(tty);
+	kfree(tmp);
+	return i;
+}
+
+static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+{
+	int status;
+	struct iuu_buffers *tmp;
+	int Count = 0;
+	u8 FrqGenAdr = 0x69;
+	u8 DIV = 0;	/* 8bit */
+	u8 XDRV = 0;	/* 8bit */
+	u8 PUMP = 0;	/* 3bit */
+	u8 PBmsb = 0;	/* 2bit */
+	u8 PBlsb = 0;	/* 8bit */
+	u8 PO = 0;	/* 1bit */
+	u8 Q = 0;	/* 7bit */
+	/* 24bit = 3bytes */
+	unsigned int P = 0;
+	unsigned int P2 = 0;
+	int frq = (int)dwFrq;
+
+	tmp = kmalloc(sizeof(struct iuu_buffers), GFP_KERNEL);
+
+	if (!tmp)
+		return -ENOMEM;
+
+	if (frq == 0) {
+		tmp->buf[Count++] = IUU_UART_WRITE_I2C;
+		tmp->buf[Count++] = FrqGenAdr << 1;
+		tmp->buf[Count++] = 0x09;
+		tmp->buf[Count++] = 0x00;
+
+		status = bulk_immediate(port, (u_int8_t *) tmp->buf, Count);
+		if (status != 0) {
+			dbg("%s - write error ", __FUNCTION__);
+			kfree(tmp);
+			return status;
+		}
+	} else if (frq == 3579000) {
+		DIV = 100;
+		P = 1193;
+		Q = 40;
+		XDRV = 0;
+	} else if (frq == 3680000) {
+		DIV = 105;
+		P = 161;
+		Q = 5;
+		XDRV = 0;
+	} else if (frq == 6000000) {
+		DIV = 66;
+		P = 66;
+		Q = 2;
+		XDRV = 0x28;
+	} else {
+		unsigned int result = 0;
+		unsigned int tmp = 0;
+		unsigned int check;
+		unsigned int check2;
+		char found = 0x00;
+
+		unsigned int lQ = 2;
+		unsigned int lP = 2055;
+		unsigned int lDiv = 4;
+		for (lQ = 2; lQ <= 47 && !found; lQ++)
+			for (lP = 2055; lP >= 8 && !found; lP--)
+				for (lDiv = 4; lDiv <= 127 && !found; lDiv++) {
+					tmp = (12000000 / lDiv) * (lP / lQ);
+					if (abs((int)(tmp - frq)) <
+					    abs((int)(frq - result))) {
+						check2 = (12000000 / lQ);
+						if (check2 < 250000)
+							continue;
+						check = (12000000 / lQ) * lP;
+						if (check > 400000000)
+							continue;
+						if (check < 100000000)
+							continue;
+						if (lDiv < 4 || lDiv > 127)
+							continue;
+						result = tmp;
+						P = lP;
+						DIV = lDiv;
+						Q = lQ;
+						if (result == frq)
+							found = 0x01;
+					}
+				}
+	}
+	P2 = ((P - PO) / 2) - 4;
+	DIV = DIV;
+	PUMP = 0x04;
+	PBmsb = (P2 >> 8 & 0x03);
+	PBlsb = P2 & 0xFF;
+	PO = (P >> 10) & 0x01;
+	Q = Q - 2;
+
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/* 0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x09;
+	tmp->buf[Count++] = 0x20;	/* Adr = 0x09 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/* 0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x0C;
+	tmp->buf[Count++] = DIV;	/* Adr = 0x0C */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/* 0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x12;
+	tmp->buf[Count++] = XDRV;	/* Adr = 0x12 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x13;
+	tmp->buf[Count++] = 0x6B;	/* Adr = 0x13 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x40;
+	tmp->buf[Count++] = (0xC0 | ((PUMP & 0x07) << 2))
+				| (PBmsb & 0x03); /* Adr = 0x40 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x41;
+	tmp->buf[Count++] = PBlsb;	/* Adr = 0x41 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x42;
+	tmp->buf[Count++] = Q | (((PO & 0x01) << 7));	/* Adr = 0x42 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x44;
+	tmp->buf[Count++] = (char)0xFF;	/* Adr = 0x44 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x45;
+	tmp->buf[Count++] = (char)0xFE;	/* Adr = 0x45 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x46;
+	tmp->buf[Count++] = 0x7F;	/* Adr = 0x46 */
+	tmp->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	tmp->buf[Count++] = FrqGenAdr << 1;
+	tmp->buf[Count++] = 0x47;
+	tmp->buf[Count++] = (char)0x84;	/* Adr = 0x47 */
+
+	status = bulk_immediate(port, (u8 *)tmp->buf,
+							Count);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - write error ", __FUNCTION__);
+
+	kfree(tmp);
+	return status;
+}
+
+static int iuu_uart_flush(struct usb_serial_port *port)
+{
+	int i;
+	int status;
+	u8 rxcmd = IUU_UART_RX;
+	struct iuu_buffers *tmp;
+
+	tmp = kmalloc(sizeof(struct iuu_buffers), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	/* u_int8_t datain[256]; */
+
+	if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0) {
+		kfree(tmp);
+		return -EIO;
+	}
+
+	for (i = 0; i < 2; i++) {
+		status = bulk_immediate(port, &rxcmd, 1);
+		if (status != IUU_OPERATION_OK) {
+			dbg("%s - uart_flush_write error", __FUNCTION__);
+			return status;
+		}
+
+		status = read_immediate(port, &tmp->len, 1);
+		if (status != IUU_OPERATION_OK) {
+			dbg("%s - uart_flush_read error", __FUNCTION__);
+			kfree(tmp);
+			return status;
+		}
+
+		if (tmp->len > 0) {
+			dbg("%s - uart_flush datalen is : %i ", __FUNCTION__,
+			    tmp->len);
+			status = read_immediate(port, tmp->buf, tmp->len);
+			if (status != IUU_OPERATION_OK) {
+				dbg("%s - uart_flush_read error", __FUNCTION__);
+				kfree(tmp);
+				return status;
+			}
+		}
+	}
+	dbg("%s - uart_flush_read OK!", __FUNCTION__);
+	iuu_led(port, 0, 0xF000, 0, 0xFF);
+	kfree(tmp);
+	return status;
+}
+
+static int
+iuu_uart_read(struct usb_serial_port *port, u8 *data,
+	      u8 *len)
+{
+	int status;
+	u8 rxcmd = IUU_UART_RX;
+	status = bulk_immediate(port, &rxcmd, 1);
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - uart_flush_write error", __FUNCTION__);
+		len = 0;
+		return status;
+	}
+
+	status = read_immediate(port, len, 1);
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - uart_flush_read error", __FUNCTION__);
+		len[0] = 0;
+		return status;
+	}
+
+	if (len[0] > 0) {
+		dbg("%s - uart_read datalen is : %i ", __FUNCTION__, len[0]);
+		status = read_immediate(port, data, len[0]);
+		if (status != IUU_OPERATION_OK) {
+			dbg("%s - uart_flush_read error", __FUNCTION__);
+			len[0] = 0;
+			return status;
+		}
+	}
+	dbg("%s - uart_read OK!", __FUNCTION__);
+	return len[0];
+}
+
+static int iuu_uart_on(struct usb_serial_port *port)
+{
+	int status;
+	u8 *buf;
+
+	buf = kmalloc(sizeof(u8) * 4, GFP_KERNEL);
+
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = IUU_UART_ENABLE;
+	buf[1] = (u8)((IUU_BAUD_9600 >> 8) & 0x00FF);
+	buf[2] = (u8)(0x00FF & IUU_BAUD_9600);
+	buf[3] =
+	    (u8)(0x0F0 & IUU_TWO_STOP_BITS) | (0x07 &
+						 IUU_PARITY_EVEN);
+
+	status = bulk_immediate(port, buf, 4);
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - uart_on error", __FUNCTION__);
+		kfree(buf);
+		return status;
+	}
+	/*  iuu_reset() the card after iuu_uart_on() */
+	status = iuu_uart_flush(port);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - uart_flush error", __FUNCTION__);
+
+	kfree(buf);
+	return status;
+}
+
+/*  Diables the IUU UART (a.k.a. the Phoenix voiderface) */
+static int iuu_uart_off(struct usb_serial_port *port)
+{
+	int status;
+	u8 buf = IUU_UART_DISABLE;
+
+	status = bulk_immediate(port, &buf, 1);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - uart_off error", __FUNCTION__);
+
+	return status;
+}
+
+/*
+static int
+iuu_uart_set(struct usb_serial_port *port, u8 br,
+	     u8 parity, u8 sbits)
+{
+	int status;
+	u8 *buf;
+
+	buf = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
+
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = IUU_UART_ESC;
+	buf[1] = IUU_UART_CHANGE;
+	buf[2] = (u_int8_t) ((br >> 8) & 0x00FF);
+	buf[3] = (u_int8_t) (0x00FF & br);
+	buf[4] = (u_int8_t) (parity | sbits);
+
+	status = bulk_immediate(port, buf, 5);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - uart_off error", __FUNCTION__);
+
+	kfree(buf);
+	return status;
+}
+*/
+
+static int
+iuu_uart_baud(struct usb_serial_port *port, u_int32_t baud, u_int32_t *actual,
+	      u_int8_t parity)
+{
+
+	/* SDK_STATUS sdk_status = SDK_SUCCESS; */
+	/* u8 dataout[10]; */
+	/* DWORD dwWritten = 0; */
+	/* unsigned void DataCount = 0; */
+
+	int status;
+	u8 *dataout;
+	u_int8_t DataCount = 0;
+	u8 T1Frekvens = 0;
+	u8 T1reload = 0;
+	unsigned int T1FrekvensHZ = 0;
+
+	dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
+
+	if (!dataout)
+		return -ENOMEM;
+
+	if (baud < 1200 || baud > 230400)
+		return IUU_INVALID_PARAMETER;
+
+	if (baud > 977) {
+		T1Frekvens = 3;
+		T1FrekvensHZ = 500000;
+	}
+
+	if (baud > 3906) {
+		T1Frekvens = 2;
+		T1FrekvensHZ = 2000000;
+	}
+
+	if (baud > 11718) {
+		T1Frekvens = 1;
+		T1FrekvensHZ = 6000000;
+	}
+
+	if (baud > 46875) {
+		T1Frekvens = 0;
+		T1FrekvensHZ = 24000000;
+	}
+
+	T1reload = 256 - (u8)(T1FrekvensHZ / (baud * 2));
+
+	/*  magic number here:  ENTER_FIRMWARE_UPDATE; */
+	dataout[DataCount++] = IUU_UART_ESC;
+	/*  magic number here:  CHANGE_BAUD; */
+	dataout[DataCount++] = IUU_UART_CHANGE;
+	dataout[DataCount++] = T1Frekvens;
+	dataout[DataCount++] = T1reload;
+
+	*actual = (T1FrekvensHZ / (256 - T1reload)) / 2;
+
+	switch (parity & 0x0F) {
+	case IUU_PARITY_NONE:
+		dataout[DataCount++] = 0x00;
+		break;
+	case IUU_PARITY_EVEN:
+		dataout[DataCount++] = 0x01;
+		break;
+	case IUU_PARITY_ODD:
+		dataout[DataCount++] = 0x02;
+		break;
+	case IUU_PARITY_MARK:
+		dataout[DataCount++] = 0x03;
+		break;
+	case IUU_PARITY_SPACE:
+		dataout[DataCount++] = 0x04;
+		break;
+	default:
+		return IUU_INVALID_PARAMETER;
+		break;
+	}
+
+	switch (parity & 0xF0) {
+	case IUU_ONE_STOP_BIT:
+		dataout[DataCount - 1] |= IUU_ONE_STOP_BIT;
+		break;
+
+	case IUU_TWO_STOP_BITS:
+		dataout[DataCount - 1] |= IUU_TWO_STOP_BITS;
+		break;
+	default:
+		return IUU_INVALID_PARAMETER;
+		break;
+	}
+
+	status = bulk_immediate(port, dataout, DataCount);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - uart_off error", __FUNCTION__);
+
+	return status;
+}
+
+static int iuu_open(struct usb_serial_port *port, struct file *filp)
+{
+	struct usb_serial *serial = port->serial;
+	u8 *buf;
+	int result;
+	u_int32_t actual;
+	unsigned long flags;
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+
+	dbg("%s -  port %d", __FUNCTION__, port->number);
+	usb_clear_halt(serial->dev, port->write_urb->pipe);
+	usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+	buf = kmalloc(10, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+/* set the termios structure */
+
+	spin_lock_irqsave(&priv->lock, flags);
+	/* if (!priv->termios_initialized) { */
+	*(port->tty->termios) = tty_std_termios;
+	port->tty->termios->c_cflag =
+	    CLOCAL | CREAD | CS8 | B9600 | TIOCM_CTS | CSTOPB | PARENB;
+	port->tty->termios->c_lflag = 0;
+	port->tty->termios->c_oflag = ONLCR;
+	port->tty->termios->c_iflag = 0;
+	priv->termios_initialized = 1;
+	port->tty->low_latency = 1;
+	/* } */
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+#define FISH(a, b, c, d) do { \
+	result = usb_control_msg(port->serial->dev,	\
+				usb_rcvctrlpipe(port->serial->dev, 0),	\
+				b, a, c, d, buf, 1, 1000); \
+	dbg("0x%x:0x%x:0x%x:0x%x  %d - %x", a, b, c, d, result, \
+				buf[0]); } while (0);
+
+#define SOUP(a, b, c, d)  do { \
+	result = usb_control_msg(port->serial->dev,	\
+				usb_sndctrlpipe(port->serial->dev, 0),	\
+				b, a, c, d, NULL, 0, 1000); \
+	dbg("0x%x:0x%x:0x%x:0x%x  %d", a, b, c, d, result); } while (0)
+
+	/*  This is not UART related but IUU USB driver related or something */
+	/*  like that. Basically no IUU will accept any commands from the USB */
+	/*  host unless it has received the following message */
+	/* sprintf(buf ,"%c%c%c%c",0x03,0x02,0x02,0x0); */
+
+	SOUP(0x03, 0x02, 0x02, 0x0);
+	iuu_led(port, 0xF000, 0xF000, 0, 0xFF);
+	iuu_clk(port, IUU_CLK_6000000);
+	/* iuu_clk(serial->port, IUU_CLK_3579000); */
+	iuu_uart_on(port);
+	switch (clockmode) {
+	case 2:		/*  3.680 Mhz */
+		iuu_clk(port, IUU_CLK_3680000 * multiplicator / 100);
+		result =
+		    iuu_uart_baud(port, 9600 * multiplicator / 100, &actual,
+				  IUU_PARITY_EVEN);
+		break;
+	case 3:		/*  6.00 Mhz */
+		iuu_clk(port, IUU_CLK_6000000 * multiplicator / 100);
+		result =
+		    iuu_uart_baud(port, 16457 * multiplicator / 100, &actual,
+				  IUU_PARITY_EVEN);
+		break;
+	default:		/*  3.579 Mhz */
+		iuu_clk(port, IUU_CLK_3579000 * multiplicator / 100);
+		result =
+		    iuu_uart_baud(port, 9600 * multiplicator / 100, &actual,
+				  IUU_PARITY_EVEN);
+	}
+
+	iuu_uart_flush(port);
+
+	return 0;
+}
+
+static int set_control_lines(struct usb_device *dev, u8 value)
+{
+	return 0;
+}
+
+static void iuu_close(struct usb_serial_port *port, struct file *filp)
+{
+	/* iuu_led (port,255,0,0,0); */
+	struct usb_serial *serial;
+	struct iuu_private *priv;
+	unsigned long flags;
+	unsigned int c_cflag;
+	int result;
+
+	serial = port->serial;
+	if (!serial)
+		return;
+	iuu_led(port, 0, 0, 0xF000, 0xFF);
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	iuu_uart_off(port);
+	if (serial->dev) {
+		if (port->tty) {
+			c_cflag = port->tty->termios->c_cflag;
+			if (c_cflag & HUPCL) {
+				/* drop DTR and RTS */
+				priv = usb_get_serial_port_data(port);
+				spin_lock_irqsave(&priv->lock, flags);
+				priv->line_control = 0;
+				spin_unlock_irqrestore(&priv->lock, flags);
+				set_control_lines(port->serial->dev, 0);
+			}
+		}
+
+		/* shutdown our urbs */
+		dbg("%s - shutting down urbs", __FUNCTION__);
+		result = usb_unlink_urb(port->write_urb);
+		if (result)
+			dbg("%s - usb_unlink_urb (write_urb)"
+			    " failed with reason: %d", __FUNCTION__, result);
+
+		result = usb_unlink_urb(port->read_urb);
+		if (result)
+			dbg("%s - usb_unlink_urb (read_urb) "
+			    "failed with reason: %d", __FUNCTION__, result);
+
+		result = usb_unlink_urb(port->interrupt_in_urb);
+		if (result)
+			dbg("%s - usb_unlink_urb (voiderrupt_in_urb)"
+			    " failed with reason: %d", __FUNCTION__, result);
+	}
+}
+
+static int __init iuu_init(void)
+{
+	int retval;
+	retval = usb_serial_register(&iuu_device);
+	if (retval)
+		goto failed_usb_serial_register;
+	retval = usb_register(&iuu_driver);
+	if (retval)
+		goto failed_usb_register;
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	return 0;
+failed_usb_register:
+	usb_serial_deregister(&iuu_device);
+failed_usb_serial_register:
+	return retval;
+}
+
+static void __exit iuu_exit(void)
+{
+	usb_deregister(&iuu_driver);
+	usb_serial_deregister(&iuu_device);
+}
+
+module_init(iuu_init);
+module_exit(iuu_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(DRIVER_VERSION);
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+module_param(smart, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(smart, "stop processing if card answer is 90 00  !");
+
+module_param(multiplicator, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(multiplicator, "overclock multiplicator percent 100 to 500");
+
+module_param(clockmode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(clockmode, "1=3Mhz579,2=3Mhz680,3=6Mhz");
diff --git a/drivers/usb/serial/iuu_phoenix.h b/drivers/usb/serial/iuu_phoenix.h
new file mode 100644
index 0000000..3c9a766
--- /dev/null
+++ b/drivers/usb/serial/iuu_phoenix.h
@@ -0,0 +1,122 @@
+/*
+ * Infinity Unlimited USB Phoenix driver
+ *
+ * Copyright (C) 2007 Alain Degreffe ([email protected])
+ *
+ *
+ * Original code taken from iuutool ( Copyright (C) 2006 Juan Carlos Borrás )
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *  And tested with help of WB Electronics
+ *
+ */
+
+#define   IUU_USB_VENDOR_ID  0x104f
+#define   IUU_USB_PRODUCT_ID  0x0004
+#define   IUU_USB_OP_TIMEOUT  0x0200
+
+/* Programmer commands */
+
+#define IUU_NO_OPERATION   0x00
+#define IUU_GET_FIRMWARE_VERSION   0x01
+#define IUU_GET_PRODUCT_NAME   0x02
+#define IUU_GET_STATE_REGISTER   0x03
+#define IUU_SET_LED   0x04
+#define IUU_WAIT_MUS   0x05
+#define IUU_WAIT_MS   0x06
+#define IUU_GET_LOADER_VERSION   0x50
+#define IUU_RST_SET   0x52
+#define IUU_RST_CLEAR   0x53
+#define IUU_SET_VCC   0x59
+#define IUU_UART_ENABLE   0x49
+#define IUU_UART_DISABLE   0x4A
+#define IUU_UART_WRITE_I2C   0x4C
+#define IUU_UART_ESC   0x5E
+#define IUU_UART_TRAP   0x54
+#define IUU_UART_TRAP_BREAK   0x5B
+#define IUU_UART_RX   0x56
+#define IUU_AVR_ON   0x21
+#define IUU_AVR_OFF   0x22
+#define IUU_AVR_1CLK   0x23
+#define IUU_AVR_RESET   0x24
+#define IUU_AVR_RESET_PC   0x25
+#define IUU_AVR_INC_PC   0x26
+#define IUU_AVR_INCN_PC   0x27
+#define IUU_AVR_PREAD   0x29
+#define IUU_AVR_PREADN   0x2A
+#define IUU_AVR_PWRITE   0x28
+#define IUU_AVR_DREAD   0x2C
+#define IUU_AVR_DREADN   0x2D
+#define IUU_AVR_DWRITE   0x2B
+#define IUU_AVR_PWRITEN   0x2E
+#define IUU_EEPROM_ON   0x37
+#define IUU_EEPROM_OFF   0x38
+#define IUU_EEPROM_WRITE   0x39
+#define IUU_EEPROM_WRITEX   0x3A
+#define IUU_EEPROM_WRITE8   0x3B
+#define IUU_EEPROM_WRITE16   0x3C
+#define IUU_EEPROM_WRITEX32   0x3D
+#define IUU_EEPROM_WRITEX64   0x3E
+#define IUU_EEPROM_READ   0x3F
+#define IUU_EEPROM_READX   0x40
+#define IUU_EEPROM_BREAD   0x41
+#define IUU_EEPROM_BREADX   0x42
+#define IUU_PIC_CMD   0x0A
+#define IUU_PIC_CMD_LOAD   0x0B
+#define IUU_PIC_CMD_READ   0x0C
+#define IUU_PIC_ON   0x0D
+#define IUU_PIC_OFF   0x0E
+#define IUU_PIC_RESET   0x16
+#define IUU_PIC_INC_PC   0x0F
+#define IUU_PIC_INCN_PC   0x10
+#define IUU_PIC_PWRITE   0x11
+#define IUU_PIC_PREAD   0x12
+#define IUU_PIC_PREADN   0x13
+#define IUU_PIC_DWRITE   0x14
+#define IUU_PIC_DREAD   0x15
+#define IUU_UART_NOP   0x00
+#define IUU_UART_CHANGE   0x02
+#define IUU_UART_TX   0x04
+#define IUU_DELAY_MS   0x06
+
+#define IUU_OPERATION_OK   0x00
+#define IUU_DEVICE_NOT_FOUND   0x01
+#define IUU_INVALID_HANDLE   0x02
+#define IUU_INVALID_PARAMETER   0x03
+#define IUU_INVALID_voidERFACE   0x04
+#define IUU_INVALID_REQUEST_LENGTH   0x05
+#define IUU_UART_NOT_ENABLED   0x06
+#define IUU_WRITE_ERROR   0x07
+#define IUU_READ_ERROR   0x08
+#define IUU_TX_ERROR   0x09
+#define IUU_RX_ERROR   0x0A
+
+#define IUU_PARITY_NONE   0x00
+#define IUU_PARITY_EVEN   0x01
+#define IUU_PARITY_ODD   0x02
+#define IUU_PARITY_MARK   0x03
+#define IUU_PARITY_SPACE   0x04
+#define IUU_SC_INSERTED   0x01
+#define IUU_VERIFY_ERROR   0x02
+#define IUU_SIM_INSERTED   0x04
+#define IUU_TWO_STOP_BITS   0x00
+#define IUU_ONE_STOP_BIT   0x20
+#define IUU_BAUD_2400   0x0398
+#define IUU_BAUD_9600   0x0298
+#define IUU_BAUD_19200   0x0164
+#define IUU_BAUD_28800   0x0198
+#define IUU_BAUD_38400   0x01B2
+#define IUU_BAUD_57600   0x0030
+#define IUU_BAUD_115200   0x0098
+#define IUU_CLK_3579000   3579000
+#define IUU_CLK_3680000   3680000
+#define IUU_CLK_6000000   6000000
+#define IUU_FULLCARD_IN   0x01
+#define IUU_DEV_ERROR   0x02
+#define IUU_MINICARD_IN   0x04
+#define IUU_VCC_5V   0x00
+#define IUU_VCC_3V   0x01
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.