iuu_phoenix drivers. New submit for review
"Alain Degreffe" <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Message-ID | <001101c7c591$d3e9e780$7bbdb680$@com> |
As requested, I have replaced all DMA by kmalloc. The CodingStyle came from Lindent script. The all defines are now in a .h file.... So I'm ready for your comments... Thanks for your time and your help. It's funny to observe that the driver is running faster with kmalloc than before ( with DMA ).... A lot of return value control are added... Alain ------------------------------------------------------------------------- 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.c
(application/octet-stream, 26.8 KB)
/* * 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 <asm/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "iuu_phoenix.h" #ifdef CONFIG_USB_SERIAL_DEBUG static int debug = 1; #else static int debug = 0; #endif /* * Version Information */ #define DRIVER_VERSION "v0.1" #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 unsigned char *buf, int count); static int read_immediate(struct usb_serial_port *port, unsigned char *buf, unsigned char count); static int iuu_uart_flush(struct usb_serial_port *port); static int iuu_uart_read(struct usb_serial_port *port, unsigned char *data, unsigned char *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, unsigned char *buf, unsigned char 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 void iuu_set_termios(struct usb_serial_port *port, struct ktermios *old); 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, .set_termios = iuu_set_termios, .attach = iuu_startup, .shutdown = iuu_shutdown, }; struct iuu_private { spinlock_t lock; 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 { unsigned char buf[256]; unsigned char finalbuf[256]; unsigned char dbgbuf[512]; unsigned char len; }; /* turbo parameter */ int turbo = 0; static int iuu_startup(struct usb_serial *serial) { struct iuu_private *priv; int i; for (i = 0; i < serial->num_ports; ++i) { 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[i], priv); } return 0; } /* Shutdown function */ static void iuu_shutdown(struct usb_serial *serial) { int i; dbg("%s", __FUNCTION__); for (i = 0; i < serial->num_ports; ++i) { kfree(usb_get_serial_port_data(serial->port[i])); usb_set_serial_port_data(serial->port[i], 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_INTERRUPTIBLE; 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) { unsigned char *st; st = kmalloc(sizeof(unsigned char), GFP_KERNEL); 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); kfree(st); return 0; } else { kfree(st); return TIOCM_CD; } } 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); get_user(mask, (unsigned long *)arg); dbg("%s (%d) msg = %04x", __FUNCTION__, port->number, mask); switch (cmd) { case TCGETS: return (0); case TCFLSH: return (-1); 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 void iuu_set_termios(struct usb_serial_port *port, struct ktermios *old) { dbg("%s - call ", __FUNCTION__); } static int iuu_reset(struct usb_serial_port *port, u_int8_t wt) { int status; unsigned char *buf; status = iuu_uart_flush(port); if (status != IUU_OPERATION_OK) { dbg("%s - reset (flush) error ", __FUNCTION__); return status; } buf = kmalloc(sizeof(unsigned char) * 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, unsigned char *buf, unsigned char 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, unsigned char *buf, unsigned char 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, unsigned char f) { int status; unsigned char *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 unsigned char *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; tty->low_latency = 1; while (security < 100) { if (turbo == 0) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(1 + 1 * HZ / 1000); } if (iuu_uart_read(port, tmp->buf, &tmp->len) < 0) { kfree(tmp); return -EIO; } 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 = %s", __FUNCTION__, tmp->dbgbuf); tty_schedule_flip(tty); } if ((tmp->finalbuf[curpos - 2] == 0x90) && (tmp->finalbuf[curpos - 1] == 0x00)) security = 99; if (count == 5 && curpos == count + 1 && buf[2] != 0 && buf[3] != 0) security = 99; security++; } 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; tty->low_latency = 1; 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); } 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; //char WriteBuffer[255]; int Count = 0; unsigned char FrqGenAdr = 0x69; unsigned char DIV = 0; /* 8bit */ unsigned char XDRV = 0; /* 8bit */ /* //0b'110xxxxx' = 0x0C //3 */ unsigned char PUMP = 0; /* 3bit */ unsigned char PBmsb = 0; /* 2bit */ unsigned char PBlsb = 0; /* 8bit */ unsigned char PO = 0; /* 1bit */ unsigned char 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; /* //0x4C */ tmp->buf[Count++] = FrqGenAdr << 1; tmp->buf[Count++] = 0x09; tmp->buf[Count++] = 0x00; /* //Adr = 0x09 */ /* EnterCriticalSection (&instances[dwDevice]->IOCriticalSection); sdk_status = INFUNLTD_Write (hDevice, WriteBuffer, Count, &dwWritten); LeaveCriticalSection (&instances[dwDevice]->IOCriticalSection); return sdk_status; */ 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 (unsigned void lQ = 2; lQ <= 47 && !found; lQ++) for (unsigned void lP = 2055; lP >= 8 && !found; lP--) for (unsigned void lDiv = 4; lDiv <= 127 && !found; lDiv++) */ for (lQ = 2; lQ <= 47 && !found; lQ++) for (lP = 2055; lP >= 8 && !found; lP--) for (lDiv = 4; lDiv <= 127 && !found; lDiv++) { /* tmp = ((12000000*lP)/(lQ*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; /* true */ } } } 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 */ /* EnterCriticalSection (&instances[dwDevice]->IOCriticalSection); sdk_status = INFUNLTD_Write (hDevice, WriteBuffer, Count, &dwWritten); LeaveCriticalSection (&instances[dwDevice]->IOCriticalSection); */ status = bulk_immediate(port, (unsigned char *)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; unsigned char 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, unsigned char *data, unsigned char *len) { int status; unsigned char 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; unsigned char *buf; buf = kmalloc(sizeof(unsigned char) * 4, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = IUU_UART_ENABLE; buf[1] = (unsigned char)((IUU_BAUD_9600 >> 8) & 0x00FF); /* high byte */ buf[2] = (unsigned char)(0x00FF & IUU_BAUD_9600); /* low byte */ buf[3] = (unsigned char)(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; } status = iuu_uart_flush(port); // iuu_reset() the card after iuu_uart_on() 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; unsigned char 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, unsigned char br, unsigned char parity, unsigned char sbits) { int status; unsigned char *buf; buf = kmalloc(sizeof(unsigned char) * 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); /* high byte */ buf[3] = (u_int8_t) (0x00FF & br); /* low byte */ buf[4] = (u_int8_t) (parity | sbits); /* both parity and stop now */ 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; //unsigned char dataout[10]; //DWORD dwWritten = 0; //unsigned void DataCount = 0; int status; unsigned char *dataout; u_int8_t DataCount = 0; unsigned char T1Frekvens = 0; unsigned char T1reload = 0; unsigned int T1FrekvensHZ = 0; dataout = kmalloc(sizeof(unsigned char) * 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 - (unsigned char)(((float) ((float)T1FrekvensHZ / (float)((float)2.0 * (float)baud)))); dataout[DataCount++] = IUU_UART_ESC; // magic number here: ENTER_FIRMWARE_UPDATE; dataout[DataCount++] = IUU_UART_CHANGE; // magic number here: CHANGE_BAUD; dataout[DataCount++] = T1Frekvens; dataout[DataCount++] = T1reload; /* *actual = (unsigned void)(((float)T1FrekvensHZ / (float)((float)256 - (float)T1reload)) / (float)2.0); */ *actual = (u_int32_t) (((float)T1FrekvensHZ / (float)((float)256 - (float)T1reload)) / (float)2.0); 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; } //sdk_status = INFUNLTD_Write(hDevice,dataout,DataCount,&dwWritten); status = bulk_immediate(port, dataout, DataCount); //if(dwWritten != DataCount) //return SDK_INVALID_HANDLE; 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; unsigned char *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; //~( ICANON | ISIG | ECHONL | IEXTEN | ECHOCTL | ECHO | NOFLSH ) ;//~ (ECHO | ECHOCTL) ; // disable echo port->tty->termios->c_oflag = ONLCR; port->tty->termios->c_iflag = 0; priv->termios_initialized = 1; //} spin_unlock_irqrestore(&priv->lock, flags); #define FISH(a,b,c,d) \ 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]); #define SOUP(a,b,c,d) \ 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); // 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); iuu_uart_off(port); iuu_uart_on(port); iuu_uart_baud(port, 16457, &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(turbo, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Doesn't sleep - Use with Caution !");
iuu_phoenix.h
(application/octet-stream, 3.6 KB)
/* * 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
Makefile
(application/octet-stream, 242 B) - not displayed