^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Infinity Unlimited USB Phoenix driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * And tested with help of WB Electronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/tty_driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/usb/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "iuu_phoenix.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/random.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static const struct usb_device_id id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {} /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_DEVICE_TABLE(usb, id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* turbo parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static int boost = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int clockmode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int cdmode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int iuu_cardin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int iuu_cardout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static bool xmas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int vcc_default = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static int iuu_create_sysfs_attrs(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int iuu_remove_sysfs_attrs(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static void read_rxcmd_callback(struct urb *urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct iuu_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) spinlock_t lock; /* store irq state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 line_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int tiostatus; /* store IUART SIGNAL for tiocmget call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u8 reset; /* if 1 reset is needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int poll; /* number of poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u8 *writebuf; /* buffer for writing to device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int writelen; /* num of byte to write to device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 *buf; /* used for initialize speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int vcc; /* vcc (either 3 or 5 V) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 boost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u32 clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int iuu_port_probe(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct iuu_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) priv->buf = kzalloc(256, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!priv->buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) priv->writebuf = kzalloc(256, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!priv->writebuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) kfree(priv->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) priv->vcc = vcc_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) spin_lock_init(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) usb_set_serial_port_data(port, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ret = iuu_create_sysfs_attrs(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) kfree(priv->writebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) kfree(priv->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int iuu_port_remove(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) iuu_remove_sysfs_attrs(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kfree(priv->writebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) kfree(priv->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int iuu_tiocmset(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int set, unsigned int clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* FIXME: locking on tiomstatus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dev_dbg(&port->dev, "%s msg : SET = 0x%04x, CLEAR = 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) __func__, set, clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dev_dbg(&port->dev, "%s TIOCMSET RESET called !!!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) priv->reset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (set & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) priv->tiostatus = TIOCM_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* This is used to provide a carrier detect mechanism
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * When a card is present, the response is 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * When no card , the reader respond with TIOCM_CD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * This is known as CD autodetect mechanism
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int iuu_tiocmget(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) rc = priv->tiostatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void iuu_rxcmd(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* error stop all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) usb_fill_bulk_urb(port->write_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) usb_sndbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) port->write_urb->transfer_buffer, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) read_rxcmd_callback, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) usb_submit_urb(port->write_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int iuu_reset(struct usb_serial_port *port, u8 wt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) char *buf_ptr = port->write_urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* Prepare the reset sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *buf_ptr++ = IUU_RST_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *buf_ptr++ = IUU_DELAY_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *buf_ptr++ = wt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) *buf_ptr = IUU_RST_CLEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* send the sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) usb_fill_bulk_urb(port->write_urb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) usb_sndbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) port->write_urb->transfer_buffer, 4, iuu_rxcmd, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) priv->reset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* Status Function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * Return value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * 0x00 = no card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * 0x01 = smartcard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * 0x02 = sim card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void iuu_update_status_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) u8 *st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* error stop all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) st = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) dev_dbg(&port->dev, "%s - enter\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (urb->actual_length == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) switch (st[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case 0x1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) priv->tiostatus = iuu_cardout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case 0x0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) priv->tiostatus = iuu_cardin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) priv->tiostatus = iuu_cardin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) iuu_rxcmd(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void iuu_status_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) usb_fill_bulk_urb(port->read_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) usb_rcvbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) port->bulk_in_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) port->read_urb->transfer_buffer, 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) iuu_update_status_callback, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) usb_submit_urb(port->read_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int iuu_status(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) usb_fill_bulk_urb(port->write_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) usb_sndbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) port->write_urb->transfer_buffer, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) iuu_status_callback, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct usb_serial *serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) int actual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* send the data out the bulk port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) usb_bulk_msg(serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) usb_sndbulkpipe(serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) port->bulk_out_endpointAddress), buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) count, &actual, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) dev_dbg(&port->dev, "%s - write OK !\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct usb_serial *serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int actual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* send the data out the bulk port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) usb_bulk_msg(serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) usb_rcvbulkpipe(serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) port->bulk_in_endpointAddress), buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) count, &actual, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) dev_dbg(&port->dev, "%s - read OK !\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int iuu_led(struct usb_serial_port *port, unsigned int R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) unsigned int G, unsigned int B, u8 f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) buf = kmalloc(8, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) buf[0] = IUU_SET_LED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) buf[1] = R & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) buf[2] = (R >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) buf[3] = G & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) buf[4] = (G >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) buf[5] = B & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) buf[6] = (B >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) buf[7] = f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) status = bulk_immediate(port, buf, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) dev_dbg(&port->dev, "%s - led error status = %2x\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dev_dbg(&port->dev, "%s - led OK !\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return IUU_OPERATION_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u8 b2, u8 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) *buf++ = IUU_SET_LED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) *buf++ = r1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) *buf++ = r2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *buf++ = g1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) *buf++ = g2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) *buf++ = b1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) *buf++ = b2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) *buf = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static void iuu_led_activity_on(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) char *buf_ptr = port->write_urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (xmas) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) buf_ptr[0] = IUU_SET_LED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) get_random_bytes(buf_ptr + 1, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) buf_ptr[7] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) iuu_rgbf_fill_buffer(buf_ptr, 255, 255, 0, 0, 0, 0, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) usb_fill_bulk_urb(port->write_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) usb_sndbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) port->write_urb->transfer_buffer, 8 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) iuu_rxcmd, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) usb_submit_urb(port->write_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void iuu_led_activity_off(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) char *buf_ptr = port->write_urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (xmas) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) iuu_rxcmd(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) usb_fill_bulk_urb(port->write_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) usb_sndbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) port->write_urb->transfer_buffer, 8 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) iuu_rxcmd, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) usb_submit_urb(port->write_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int iuu_clk(struct usb_serial_port *port, int dwFrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int Count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) u8 FrqGenAdr = 0x69;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) u8 DIV = 0; /* 8bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) u8 XDRV = 0; /* 8bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) u8 PUMP = 0; /* 3bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) u8 PBmsb = 0; /* 2bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u8 PBlsb = 0; /* 8bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u8 PO = 0; /* 1bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) u8 Q = 0; /* 7bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* 24bit = 3bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) unsigned int P = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) unsigned int P2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int frq = (int)dwFrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (frq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) priv->buf[Count++] = IUU_UART_WRITE_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) priv->buf[Count++] = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) priv->buf[Count++] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) status = bulk_immediate(port, (u8 *) priv->buf, Count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (status != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dev_dbg(&port->dev, "%s - write error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) } else if (frq == 3579000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) DIV = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) P = 1193;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) Q = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) XDRV = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) } else if (frq == 3680000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) DIV = 105;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) P = 161;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) Q = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) XDRV = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) } else if (frq == 6000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) DIV = 66;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) P = 66;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) Q = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) XDRV = 0x28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) unsigned int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) unsigned int tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) unsigned int check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) unsigned int check2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) char found = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) unsigned int lQ = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) unsigned int lP = 2055;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) unsigned int lDiv = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) for (lQ = 2; lQ <= 47 && !found; lQ++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) for (lP = 2055; lP >= 8 && !found; lP--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) for (lDiv = 4; lDiv <= 127 && !found; lDiv++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) tmp = (12000000 / lDiv) * (lP / lQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (abs((int)(tmp - frq)) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) abs((int)(frq - result))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) check2 = (12000000 / lQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (check2 < 250000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) check = (12000000 / lQ) * lP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (check > 400000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (check < 100000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (lDiv < 4 || lDiv > 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) result = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) P = lP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) DIV = lDiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) Q = lQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (result == frq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) found = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) P2 = ((P - PO) / 2) - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) PUMP = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) PBmsb = (P2 >> 8 & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) PBlsb = P2 & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) PO = (P >> 10) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) Q = Q - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) priv->buf[Count++] = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) priv->buf[Count++] = 0x20; /* Adr = 0x09 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) priv->buf[Count++] = 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) priv->buf[Count++] = DIV; /* Adr = 0x0C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) priv->buf[Count++] = 0x12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) priv->buf[Count++] = XDRV; /* Adr = 0x12 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) priv->buf[Count++] = 0x13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) priv->buf[Count++] = 0x6B; /* Adr = 0x13 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) priv->buf[Count++] = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) priv->buf[Count++] = (0xC0 | ((PUMP & 0x07) << 2)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) (PBmsb & 0x03); /* Adr = 0x40 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) priv->buf[Count++] = 0x41;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) priv->buf[Count++] = PBlsb; /* Adr = 0x41 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) priv->buf[Count++] = 0x42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) priv->buf[Count++] = Q | (((PO & 0x01) << 7)); /* Adr = 0x42 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) priv->buf[Count++] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) priv->buf[Count++] = (char)0xFF; /* Adr = 0x44 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) priv->buf[Count++] = 0x45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) priv->buf[Count++] = (char)0xFE; /* Adr = 0x45 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) priv->buf[Count++] = 0x46;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) priv->buf[Count++] = 0x7F; /* Adr = 0x46 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) priv->buf[Count++] = FrqGenAdr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) priv->buf[Count++] = 0x47;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) priv->buf[Count++] = (char)0x84; /* Adr = 0x47 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) status = bulk_immediate(port, (u8 *) priv->buf, Count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) dev_dbg(&port->dev, "%s - write error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int iuu_uart_flush(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct device *dev = &port->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u8 *rxcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) rxcmd = kmalloc(1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!rxcmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) rxcmd[0] = IUU_UART_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) status = bulk_immediate(port, rxcmd, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (status != IUU_OPERATION_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) dev_dbg(dev, "%s - uart_flush_write error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) status = read_immediate(port, &priv->len, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (status != IUU_OPERATION_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) dev_dbg(dev, "%s - uart_flush_read error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (priv->len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) dev_dbg(dev, "%s - uart_flush datalen is : %i\n", __func__, priv->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) status = read_immediate(port, priv->buf, priv->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (status != IUU_OPERATION_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dev_dbg(dev, "%s - uart_flush_read error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) dev_dbg(dev, "%s - uart_flush_read OK!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) iuu_led(port, 0, 0xF000, 0, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) kfree(rxcmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static void read_buf_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) unsigned char *data = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (status == -EPROTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* reschedule needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (urb->actual_length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) tty_insert_flip_string(&port->port, data, urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) tty_flip_buffer_push(&port->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) iuu_led_activity_on(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static int iuu_bulk_write(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) char *buf_ptr = port->write_urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) *buf_ptr++ = IUU_UART_ESC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) *buf_ptr++ = IUU_UART_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) *buf_ptr++ = priv->writelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) memcpy(buf_ptr, priv->writebuf, priv->writelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) buf_len = priv->writelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) priv->writelen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) dev_dbg(&port->dev, "%s - writing %i chars : %*ph\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) buf_len, buf_len, buf_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) usb_fill_bulk_urb(port->write_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) usb_sndbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) port->write_urb->transfer_buffer, buf_len + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) iuu_rxcmd, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) usb_serial_port_softint(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static int iuu_read_buf(struct usb_serial_port *port, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) usb_fill_bulk_urb(port->read_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) usb_rcvbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) port->bulk_in_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) port->read_urb->transfer_buffer, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) read_buf_callback, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static void iuu_uart_read_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) unsigned char *data = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) priv->poll++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* error stop all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (urb->actual_length == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) len = (int) data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (urb->actual_length > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) dev_dbg(&port->dev, "%s - urb->actual_length = %i\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) error = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* if len > 0 call readbuf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (len > 0 && error == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dev_dbg(&port->dev, "%s - call read buf - len to read is %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) __func__, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) status = iuu_read_buf(port, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /* need to update status ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (priv->poll > 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) status = iuu_status(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) priv->poll = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /* reset waiting ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (priv->reset == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) status = iuu_reset(port, 0xC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* Writebuf is waiting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (priv->writelen > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) status = iuu_bulk_write(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* if nothing to write call again rxcmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) dev_dbg(&port->dev, "%s - rxcmd recall\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) iuu_led_activity_off(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) const u8 *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) count = min(count, 256 - priv->writelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* fill the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) memcpy(priv->writebuf + priv->writelen, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) priv->writelen += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static void read_rxcmd_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /* error stop all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) usb_fill_bulk_urb(port->read_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) usb_rcvbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) port->bulk_in_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) port->read_urb->transfer_buffer, 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) iuu_uart_read_callback, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) dev_dbg(&port->dev, "%s - submit result = %d\n", __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) static int iuu_uart_on(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) buf = kmalloc(4, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) buf[0] = IUU_UART_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) buf[2] = (u8) (0x00FF & IUU_BAUD_9600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) buf[3] = (u8) (0x0F0 & IUU_ONE_STOP_BIT) | (0x07 & IUU_PARITY_EVEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) status = bulk_immediate(port, buf, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (status != IUU_OPERATION_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) dev_dbg(&port->dev, "%s - uart_on error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) goto uart_enable_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* iuu_reset() the card after iuu_uart_on() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) status = iuu_uart_flush(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) dev_dbg(&port->dev, "%s - uart_flush error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) uart_enable_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* Disables the IUU UART (a.k.a. the Phoenix voiderface) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static int iuu_uart_off(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) buf = kmalloc(1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) buf[0] = IUU_UART_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) status = bulk_immediate(port, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) dev_dbg(&port->dev, "%s - uart_off error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) u32 *actual, u8 parity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) u32 baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) u8 *dataout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) u8 DataCount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) u8 T1Frekvens = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) u8 T1reload = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) unsigned int T1FrekvensHZ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) dev_dbg(&port->dev, "%s - enter baud_base=%d\n", __func__, baud_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) dataout = kmalloc(5, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (!dataout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /*baud = (((priv->clk / 35) * baud_base) / 100000); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) baud = baud_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (baud < 1200 || baud > 230400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) kfree(dataout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return IUU_INVALID_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (baud > 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) T1Frekvens = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) T1FrekvensHZ = 500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (baud > 3906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) T1Frekvens = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) T1FrekvensHZ = 2000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (baud > 11718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) T1Frekvens = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) T1FrekvensHZ = 6000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (baud > 46875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) T1Frekvens = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) T1FrekvensHZ = 24000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) T1reload = 256 - (u8) (T1FrekvensHZ / (baud * 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* magic number here: ENTER_FIRMWARE_UPDATE; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) dataout[DataCount++] = IUU_UART_ESC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) /* magic number here: CHANGE_BAUD; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) dataout[DataCount++] = IUU_UART_CHANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) dataout[DataCount++] = T1Frekvens;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) dataout[DataCount++] = T1reload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) *actual = (T1FrekvensHZ / (256 - T1reload)) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) switch (parity & 0x0F) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) case IUU_PARITY_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) dataout[DataCount++] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) case IUU_PARITY_EVEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) dataout[DataCount++] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) case IUU_PARITY_ODD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) dataout[DataCount++] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) case IUU_PARITY_MARK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) dataout[DataCount++] = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) case IUU_PARITY_SPACE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) dataout[DataCount++] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) kfree(dataout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return IUU_INVALID_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) switch (parity & 0xF0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) case IUU_ONE_STOP_BIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) dataout[DataCount - 1] |= IUU_ONE_STOP_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) case IUU_TWO_STOP_BITS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) dataout[DataCount - 1] |= IUU_TWO_STOP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) kfree(dataout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return IUU_INVALID_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) status = bulk_immediate(port, dataout, DataCount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) dev_dbg(&port->dev, "%s - uart_off error\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) kfree(dataout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) static void iuu_set_termios(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct usb_serial_port *port, struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) const u32 supported_mask = CMSPAR|PARENB|PARODD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) unsigned int cflag = tty->termios.c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) u32 actual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) u32 parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int csize = CS7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) int baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) u32 newval = cflag & supported_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /* Just use the ospeed. ispeed should be the same. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) baud = tty->termios.c_ospeed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) dev_dbg(&port->dev, "%s - enter c_ospeed or baud=%d\n", __func__, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /* compute the parity parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) parity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (cflag & CMSPAR) { /* Using mark space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (cflag & PARODD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) parity |= IUU_PARITY_SPACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) parity |= IUU_PARITY_MARK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) } else if (!(cflag & PARENB)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) parity |= IUU_PARITY_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) csize = CS8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) } else if (cflag & PARODD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) parity |= IUU_PARITY_ODD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) parity |= IUU_PARITY_EVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) parity |= (cflag & CSTOPB ? IUU_TWO_STOP_BITS : IUU_ONE_STOP_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* set it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) status = iuu_uart_baud(port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) baud * priv->boost / 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) &actual, parity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* set the termios value to the real one, so the user now what has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * changed. We support few fields so its easies to copy the old hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * settings back over and then adjust them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) tty_termios_copy_hw(&tty->termios, old_termios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (status != 0) /* Set failed - return old bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* Re-encode speed, parity and csize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) tty_encode_baud_rate(tty, baud, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) tty->termios.c_cflag &= ~(supported_mask|CSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) tty->termios.c_cflag |= newval | csize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static void iuu_close(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* iuu_led (port,255,0,0,0); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) iuu_uart_off(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) usb_kill_urb(port->write_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) usb_kill_urb(port->read_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) iuu_led(port, 0, 0, 0xF000, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static void iuu_init_termios(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) tty->termios.c_cflag = B9600 | CS8 | CSTOPB | CREAD | PARENB | CLOCAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) tty->termios.c_ispeed = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) tty->termios.c_ospeed = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) tty->termios.c_lflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) tty->termios.c_oflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) tty->termios.c_iflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct usb_serial *serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct device *dev = &port->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) int baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) u32 actual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) baud = tty->termios.c_ospeed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) dev_dbg(dev, "%s - baud %d\n", __func__, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) usb_clear_halt(serial->dev, port->write_urb->pipe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) usb_clear_halt(serial->dev, port->read_urb->pipe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) priv->poll = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) #define SOUP(a, b, c, d) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) result = usb_control_msg(port->serial->dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) usb_sndctrlpipe(port->serial->dev, 0), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) b, a, c, d, NULL, 0, 1000); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d\n", a, b, c, d, result); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* This is not UART related but IUU USB driver related or something */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /* like that. Basically no IUU will accept any commands from the USB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* host unless it has received the following message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* sprintf(buf ,"%c%c%c%c",0x03,0x02,0x02,0x0); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) SOUP(0x03, 0x02, 0x02, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) iuu_led(port, 0xF000, 0xF000, 0, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) iuu_uart_on(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (boost < 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) boost = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) priv->boost = boost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) switch (clockmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) case 2: /* 3.680 Mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) priv->clk = IUU_CLK_3680000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) iuu_clk(port, IUU_CLK_3680000 * boost / 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) iuu_uart_baud(port, baud * boost / 100, &actual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) IUU_PARITY_EVEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) case 3: /* 6.00 Mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) iuu_clk(port, IUU_CLK_6000000 * boost / 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) priv->clk = IUU_CLK_6000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) /* Ratio of 6000000 to 3500000 for baud 9600 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) iuu_uart_baud(port, 16457 * boost / 100, &actual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) IUU_PARITY_EVEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) default: /* 3.579 Mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) iuu_clk(port, IUU_CLK_3579000 * boost / 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) priv->clk = IUU_CLK_3579000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) iuu_uart_baud(port, baud * boost / 100, &actual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) IUU_PARITY_EVEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* set the cardin cardout signals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) switch (cdmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) iuu_cardin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) iuu_cardout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) iuu_cardin = TIOCM_CD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) iuu_cardout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) iuu_cardin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) iuu_cardout = TIOCM_CD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) iuu_cardin = TIOCM_DSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) iuu_cardout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) iuu_cardin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) iuu_cardout = TIOCM_DSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) iuu_cardin = TIOCM_CTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) iuu_cardout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) iuu_cardin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) iuu_cardout = TIOCM_CTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) iuu_cardin = TIOCM_RNG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) iuu_cardout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) iuu_cardin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) iuu_cardout = TIOCM_RNG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) iuu_uart_flush(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) dev_dbg(dev, "%s - initialization done\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) usb_fill_bulk_urb(port->write_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) usb_sndbulkpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) port->bulk_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) port->write_urb->transfer_buffer, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) read_rxcmd_callback, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) result = usb_submit_urb(port->write_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) dev_err(dev, "%s - failed submitting read urb, error %d\n", __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) iuu_close(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) dev_dbg(dev, "%s - rxcmd OK\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* how to change VCC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) buf = kmalloc(5, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) buf[0] = IUU_SET_VCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) buf[1] = vcc & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) buf[2] = (vcc >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) buf[3] = (vcc >> 16) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) buf[4] = (vcc >> 24) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) status = bulk_immediate(port, buf, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (status != IUU_OPERATION_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) dev_dbg(&port->dev, "%s - vcc error status = %2x\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) dev_dbg(&port->dev, "%s - vcc OK !\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * Sysfs Attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) static ssize_t vcc_mode_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) struct usb_serial_port *port = to_usb_serial_port(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return sprintf(buf, "%d\n", priv->vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) static ssize_t vcc_mode_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) struct device_attribute *attr, const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) struct usb_serial_port *port = to_usb_serial_port(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) struct iuu_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (kstrtoul(buf, 10, &v)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) __func__, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) goto fail_store_vcc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) dev_dbg(dev, "%s: setting vcc_mode = %ld\n", __func__, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if ((v != 3) && (v != 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) iuu_vcc_set(port, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) priv->vcc = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) fail_store_vcc_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) static DEVICE_ATTR_RW(vcc_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) static int iuu_create_sysfs_attrs(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return device_create_file(&port->dev, &dev_attr_vcc_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) static int iuu_remove_sysfs_attrs(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) device_remove_file(&port->dev, &dev_attr_vcc_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * End Sysfs Attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static struct usb_serial_driver iuu_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) .name = "iuu_phoenix",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) .id_table = id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) .num_ports = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) .num_bulk_in = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) .num_bulk_out = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .bulk_in_size = 512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) .bulk_out_size = 512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) .open = iuu_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) .close = iuu_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) .write = iuu_uart_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) .read_bulk_callback = iuu_uart_read_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) .tiocmget = iuu_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) .tiocmset = iuu_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .set_termios = iuu_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) .init_termios = iuu_init_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) .port_probe = iuu_port_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) .port_remove = iuu_port_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static struct usb_serial_driver * const serial_drivers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) &iuu_device, NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) module_usb_serial_driver(serial_drivers, id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) module_param(xmas, bool, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) MODULE_PARM_DESC(xmas, "Xmas colors enabled or not");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) module_param(boost, int, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) MODULE_PARM_DESC(boost, "Card overclock boost (in percent 100-500)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) module_param(clockmode, int, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) MODULE_PARM_DESC(clockmode, "Card clock mode (1=3.579 MHz, 2=3.680 MHz, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) "3=6 Mhz)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) module_param(cdmode, int, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) MODULE_PARM_DESC(cdmode, "Card detect mode (0=none, 1=CD, 2=!CD, 3=DSR, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) module_param(vcc_default, int, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) MODULE_PARM_DESC(vcc_default, "Set default VCC (either 3 for 3.3V or 5 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) "for 5V). Default to 5.");