New driver proposal: iuu_phoenix
"Alain Degreffe" <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Message-ID | <005201c7c379$59d4dcd0$0d7e9670$@com> |
Hi, I try to make a new driver for infinity unlimited usb. I use the usbserial layer to manage the lowlevel functions like probing or ttyUSBx creation/selection. The driver works but only after a first sequence "open and close" of the device by a program in the user space. After this first "open/close" sequence, all is running well. I join the (hugly ?) code for a review. I'm a newbie in driver coding, so there is a lot of bad things in the code probably and with your help, I hope to have soon a clean and working code. For exemple, I'm not very sure if I need to use the lock mechanism (spin_lock_irq) . This code is for kernel 2.6.21 with GCC 4.1. Thanks, 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, 29.3 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. * * An 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 #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> #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, int count); static int iuu_uart_flush (struct usb_serial_port *port); static int iuu_uart_read (struct usb_serial_port *port, u_int8_t * data, u_int8_t * 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, int count); //static int iuu_write_room (struct usb_serial_port *port); 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 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 im_read_busy; int im_write_busy; int TIOSTATUS; struct serial_struct status; int loop; }; 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; } 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); } } 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; iuu_reset (port, 0x0C); current->state = TASK_INTERRUPTIBLE; schedule_timeout (1 + 500 * HZ / 1000); iuu_uart_read_and_store (port); } return 0; } static int iuu_tiocmget (struct usb_serial_port *port, struct file *file) { struct iuu_private *priv = usb_get_serial_port_data (port); dbg ("%s (%d) msg ", __FUNCTION__, port->number); return priv->TIOSTATUS | CS8 | B9600 | TIOCM_CTS | CSTOPB | PARENB; } 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; u_int8_t buf[4]; status = iuu_uart_flush (port); if (status != IUU_OPERATION_OK) { dbg ("%s - reset (flush) error ", __FUNCTION__); return status; } 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__); return status; } /* static void iuu_set_termios * Function not really needed because all settings are done directly in startup * Perhaps we can add later a way to choose between 3.457 and 6 Mhz with this call */ //static void iuu_set_termios (struct usb_serial_port *port, struct termios *old_termios){ //} /* * static void iuu_open * Here we open the usb device and perform the initilization * send special wakeup seq * make default 16457,8,E,1 and 6Mhz clock */ static int bulk_immediate (struct usb_serial_port *port, unsigned char *buf, int count) { int status; struct usb_serial *serial = port->serial; struct iuu_private *priv = usb_get_serial_port_data (port); int actual = 0; /* send the data out the bulk port */ priv->im_write_busy = 1; 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, int 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, u_int16_t R, u_int16_t G, u_int16_t B, u_int8_t f) { int status; u_int8_t buf[8]; 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); 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; unsigned char buf2[256]; unsigned char buf3[256]; unsigned char finalbuf[256]; char blen[1]; char debugbuf[512]; //port->tty->termios->c_lflag = 0; //~( ICANON | ISIG | ECHONL | IEXTEN | ECHOCTL | ECHO | NOFLSH ) ;//~ (ECHO | ECHOCTL) ; // disable echo //port->tty->termios->c_oflag = 0; //port->tty->termios->c_iflag = 0; if (count == 0) return (0); if (priv->write_busy) return -1; /* if ( priv->loop > 2000) { dbg("%s - loop detected ", __FUNCTION__); return 0; } */ priv->write_busy = 1; priv->loop++; dbg ("%s - try to write %i chars : %02X ", __FUNCTION__, count, buf[0]); buf2[0] = IUU_UART_ESC; buf2[1] = IUU_UART_TX; buf2[2] = count; memcpy (&buf2[3], buf, count); dbg ("%s - try to write %i chars ", __FUNCTION__, buf2[2]); status = bulk_immediate (port, buf2, count + 3); if (status != IUU_OPERATION_OK) { dbg ("%s - uart_write error", __FUNCTION__); priv->write_busy = 0; return status; } tty = port->tty; tty->low_latency = 1; finalbuf[5] = '\0'; while (security < 100) { if (turbo == 0) { current->state = TASK_INTERRUPTIBLE; schedule_timeout (1 + 1 * HZ / 1000); } iuu_uart_read (port, buf3, blen); if (blen[0] > 0) { memcpy (&finalbuf[curpos], buf3, blen[0]); dbg ("%s - finalbuf[5] = %02X , %02X", __FUNCTION__, finalbuf[5], finalbuf[5] >> 4); curpos += blen[0]; for (i = 0; i < blen[0]; ++i) { if (tty_buffer_request_room (tty, 1) == 0) break; tty_insert_flip_char (tty, buf3[i], TTY_NORMAL); sprintf (debugbuf + ((curpos - blen[0] + i) * 2), "%02X", buf3[i]); } debugbuf[curpos * 2] = '\0'; dbg ("%s - read = %s", __FUNCTION__, debugbuf); tty_schedule_flip (tty); } if ((finalbuf[curpos - 2] == 0x90) && (finalbuf[curpos - 1] == 0x00)) security = 99; if (count == 5 && curpos == count + 1 && buf[2] != 0 && buf[3] != 0) security = 99; security++; } priv->write_busy = 0; return count; } static int iuu_uart_read_and_store (struct usb_serial_port *port) { unsigned char buf[256]; char len[1]; struct tty_struct *tty; int i; iuu_uart_read (port, buf, len); tty = port->tty; tty->low_latency = 1; for (i = 0; i < len[0]; ++i) { if (tty_buffer_request_room (tty, 1) == 0) break; tty_insert_flip_char (tty, buf[i], TTY_NORMAL); } tty_flip_buffer_push (tty); tty_flip_buffer_push (tty); return len[0]; } static int iuu_clk (struct usb_serial_port *port, int dwFrq) { int status; 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; if (frq == 0) { WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* //0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x09; WriteBuffer[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 *) WriteBuffer, Count); if (status != 0) { dbg ("%s - write error ", __FUNCTION__); 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; WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x09; WriteBuffer[Count++] = 0x20; /* Adr = 0x09 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x0C; WriteBuffer[Count++] = DIV; /* Adr = 0x0C */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x12; WriteBuffer[Count++] = XDRV; /* Adr = 0x12 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x13; WriteBuffer[Count++] = 0x6B; /* Adr = 0x13 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x40; WriteBuffer[Count++] = (0xC0 | ((PUMP & 0x07) << 2)) | (PBmsb & 0x03); /* Adr = 0x40 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x41; WriteBuffer[Count++] = PBlsb; /* Adr = 0x41 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x42; WriteBuffer[Count++] = Q | (((PO & 0x01) << 7)); /* Adr = 0x42 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x44; WriteBuffer[Count++] = (char) 0xFF; /* Adr = 0x44 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x45; WriteBuffer[Count++] = (char) 0xFE; /* Adr = 0x45 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x46; WriteBuffer[Count++] = 0x7F; /* Adr = 0x46 */ WriteBuffer[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */ WriteBuffer[Count++] = FrqGenAdr << 1; WriteBuffer[Count++] = 0x47; WriteBuffer[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, (u_int8_t *) WriteBuffer, Count); if (status != IUU_OPERATION_OK) dbg ("%s - write error ", __FUNCTION__); return status; } static int iuu_uart_flush (struct usb_serial_port *port) { int i; u_int8_t datalen = 0; int status; u_int8_t rxcmd = IUU_UART_RX; u_int8_t datain[256]; iuu_led (port, 0xF000, 0, 0, 0xFF); 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, &datalen, 1); if (status != IUU_OPERATION_OK) { dbg ("%s - uart_flush_read error", __FUNCTION__); return status; } if (datalen > 0) { dbg ("%s - uart_flush datalen is : %i ", __FUNCTION__, datalen); status = read_immediate (port, datain, datalen); if (status != IUU_OPERATION_OK) { dbg ("%s - uart_flush_read error", __FUNCTION__); return status; } } } dbg ("%s - uart_flush_read OK!", __FUNCTION__); iuu_led (port, 0, 0xF000, 0, 0xFF); return status; } static int iuu_uart_read (struct usb_serial_port *port, u_int8_t * data, u_int8_t * len) { int status; u_int8_t rxcmd = IUU_UART_RX; status = bulk_immediate (port, &rxcmd, 1); if (status != IUU_OPERATION_OK) { dbg ("%s - uart_flush_write error", __FUNCTION__); return status; } status = read_immediate (port, len, 1); if (status != IUU_OPERATION_OK) { dbg ("%s - uart_flush_read error", __FUNCTION__); len = 0; return status; } if (*len > 0) { dbg ("%s - uart_read datalen is : %i ", __FUNCTION__, len[0]); status = read_immediate (port, data, *len); if (status != IUU_OPERATION_OK) { dbg ("%s - uart_flush_read error", __FUNCTION__); len = 0; return status; } } dbg ("%s - uart_read OK!", __FUNCTION__); return *len; } static int iuu_uart_on (struct usb_serial_port *port) { int status; u_int8_t buf[4]; buf[0] = IUU_UART_ENABLE; buf[1] = (u_int8_t) ((IUU_BAUD_9600 >> 8) & 0x00FF); /* high byte */ buf[2] = (u_int8_t) (0x00FF & IUU_BAUD_9600); /* low byte */ buf[3] = (u_int8_t) (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__); 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__); return status; } // Diables the IUU UART (a.k.a. the Phoenix voiderface) static int iuu_uart_off (struct usb_serial_port *port) { int status; u_int8_t 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, u_int8_t br, u_int8_t parity, u_int8_t sbits) { int status; u_int8_t buf[5]; 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__); 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; u_int8_t dataout[5]; u_int8_t DataCount = 0; unsigned char T1Frekvens = 0; unsigned char T1reload = 0; unsigned int T1FrekvensHZ = 0; 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_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; // if (port_paranoia_check(port, __FUNCTION__)) // return; 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 !");
Makefile
(application/octet-stream, 259 B) - not displayed