^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) * USB Cypress M8 driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Lonnie Mendez (dignome@gmail.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2003,2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Neil Whelchel (koyama@firstlight.net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * See Documentation/usb/usb-serial.rst for more information on using this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * See http://geocities.com/i0xox0i for information on this driver and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * earthmate usb device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Thanks to Neil Whelchel for writing the first cypress m8 implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) for linux. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* Thanks to cypress for providing references for the hid reports. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Thanks to Jiang Zhang for providing links and for general help. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/tty_driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/usb/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/kfifo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include "cypress_m8.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static bool stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static bool unstable_bauds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DRIVER_DESC "Cypress USB to Serial Driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* write buffer size defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CYPRESS_BUF_SIZE 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const struct usb_device_id id_table_earthmate[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { } /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static const struct usb_device_id id_table_cyphidcomrs232[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { USB_DEVICE(VENDOR_ID_SAI, PRODUCT_ID_CYPHIDCOM) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { } /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static const struct usb_device_id id_table_nokiaca42v2[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { } /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static const struct usb_device_id id_table_combined[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { USB_DEVICE(VENDOR_ID_SAI, PRODUCT_ID_CYPHIDCOM) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { } /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) MODULE_DEVICE_TABLE(usb, id_table_combined);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) enum packet_format {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) packet_format_1, /* b0:status, b1:payload count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) packet_format_2 /* b0[7:3]:status, b0[2:0]:payload count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct cypress_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) spinlock_t lock; /* private lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int chiptype; /* identifier of device, for quirks/etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int bytes_in; /* used for statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int bytes_out; /* used for statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int cmd_count; /* used for statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int cmd_ctrl; /* always set this to 1 before issuing a command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct kfifo write_fifo; /* write fifo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int write_urb_in_use; /* write urb in use indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int write_urb_interval; /* interval to use for write urb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int read_urb_interval; /* interval to use for read urb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int comm_is_ok; /* true if communication is (still) ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) __u8 line_control; /* holds dtr / rts value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __u8 current_config; /* stores the current configuration byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) enum packet_format pkt_fmt; /* format to use for packet send / receive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int baud_rate; /* stores current baud rate in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) integer form */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) char prev_status; /* used for TIOCMIWAIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* function prototypes for the Cypress USB to serial device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int cypress_earthmate_port_probe(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int cypress_hidcom_port_probe(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int cypress_ca42v2_port_probe(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int cypress_port_remove(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void cypress_close(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void cypress_dtr_rts(struct usb_serial_port *port, int on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) const unsigned char *buf, int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void cypress_send(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int cypress_write_room(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void cypress_earthmate_init_termios(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void cypress_set_termios(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct usb_serial_port *port, struct ktermios *old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int cypress_tiocmget(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int cypress_tiocmset(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned int set, unsigned int clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int cypress_chars_in_buffer(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void cypress_throttle(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void cypress_unthrottle(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static void cypress_set_dead(struct usb_serial_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static void cypress_read_int_callback(struct urb *urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static void cypress_write_int_callback(struct urb *urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static struct usb_serial_driver cypress_earthmate_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .name = "earthmate",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .description = "DeLorme Earthmate USB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .id_table = id_table_earthmate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .num_ports = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .port_probe = cypress_earthmate_port_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .port_remove = cypress_port_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .open = cypress_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .close = cypress_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .dtr_rts = cypress_dtr_rts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .write = cypress_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .write_room = cypress_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .init_termios = cypress_earthmate_init_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .set_termios = cypress_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .tiocmget = cypress_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .tiocmset = cypress_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .tiocmiwait = usb_serial_generic_tiocmiwait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .chars_in_buffer = cypress_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .throttle = cypress_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .unthrottle = cypress_unthrottle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .read_int_callback = cypress_read_int_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .write_int_callback = cypress_write_int_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static struct usb_serial_driver cypress_hidcom_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .name = "cyphidcom",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .description = "HID->COM RS232 Adapter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .id_table = id_table_cyphidcomrs232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .num_ports = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .port_probe = cypress_hidcom_port_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .port_remove = cypress_port_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .open = cypress_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .close = cypress_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .dtr_rts = cypress_dtr_rts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .write = cypress_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .write_room = cypress_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .set_termios = cypress_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .tiocmget = cypress_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .tiocmset = cypress_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .tiocmiwait = usb_serial_generic_tiocmiwait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .chars_in_buffer = cypress_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .throttle = cypress_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .unthrottle = cypress_unthrottle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .read_int_callback = cypress_read_int_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .write_int_callback = cypress_write_int_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static struct usb_serial_driver cypress_ca42v2_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .name = "nokiaca42v2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .description = "Nokia CA-42 V2 Adapter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .id_table = id_table_nokiaca42v2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .num_ports = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .port_probe = cypress_ca42v2_port_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .port_remove = cypress_port_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .open = cypress_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .close = cypress_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .dtr_rts = cypress_dtr_rts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .write = cypress_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .write_room = cypress_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .set_termios = cypress_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .tiocmget = cypress_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .tiocmset = cypress_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .tiocmiwait = usb_serial_generic_tiocmiwait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .chars_in_buffer = cypress_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .throttle = cypress_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .unthrottle = cypress_unthrottle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .read_int_callback = cypress_read_int_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .write_int_callback = cypress_write_int_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static struct usb_serial_driver * const serial_drivers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) &cypress_earthmate_device, &cypress_hidcom_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) &cypress_ca42v2_device, NULL
^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) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Cypress serial helper functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* FRWD Dongle hidcom needs to skip reset and speed checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static inline bool is_frwd(struct usb_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return ((le16_to_cpu(dev->descriptor.idVendor) == VENDOR_ID_FRWD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) (le16_to_cpu(dev->descriptor.idProduct) == PRODUCT_ID_CYPHIDCOM_FRWD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct cypress_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (unstable_bauds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return new_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* FRWD Dongle uses 115200 bps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (is_frwd(port->serial->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return new_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * The general purpose firmware for the Cypress M8 allows for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * a maximum speed of 57600bps (I have no idea whether DeLorme
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * chose to use the general purpose firmware or not), if you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * need to modify this speed setting for your own project
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * please add your own chiptype and modify the code likewise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * The Cypress HID->COM device will work successfully up to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * 115200bps (but the actual throughput is around 3kBps).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (port->serial->dev->speed == USB_SPEED_LOW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Mike Isely <isely@pobox.com> 2-Feb-2008: The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * Cypress app note that describes this mechanism
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * states the the low-speed part can't handle more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * than 800 bytes/sec, in which case 4800 baud is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * safest speed for a part like that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (new_rate > 4800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dev_dbg(&port->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) "%s - failed setting baud rate, device incapable speed %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) __func__, new_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) switch (priv->chiptype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case CT_EARTHMATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (new_rate <= 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* 300 and 600 baud rates are supported under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * the generic firmware, but are not used with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * NMEA and SiRF protocols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_dbg(&port->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) "%s - failed setting baud rate, unsupported speed of %d on Earthmate GPS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) __func__, new_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return new_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* This function can either set or retrieve the current serial line settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static int cypress_serial_control(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct usb_serial_port *port, speed_t baud_rate, int data_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int stop_bits, int parity_enable, int parity_type, int reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int cypress_request_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int new_baudrate = 0, retval = 0, tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct cypress_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct device *dev = &port->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u8 *feature_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) const unsigned int feature_len = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (!priv->comm_is_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) feature_buffer = kcalloc(feature_len, sizeof(u8), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!feature_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) switch (cypress_request_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case CYPRESS_SET_CONFIG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* 0 means 'Hang up' so doesn't change the true bit rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) new_baudrate = priv->baud_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (baud_rate && baud_rate != priv->baud_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) dev_dbg(dev, "%s - baud rate is changing\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) retval = analyze_baud_rate(port, baud_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (retval >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) new_baudrate = retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) dev_dbg(dev, "%s - New baud rate set to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) __func__, new_baudrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev_dbg(dev, "%s - baud rate is being sent as %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) new_baudrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* fill the feature_buffer with new configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) put_unaligned_le32(new_baudrate, feature_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* 1 bit gap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* 1 bit gap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) dev_dbg(dev, "%s - device is being sent this feature report:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dev_dbg(dev, "%s - %02X - %02X - %02X - %02X - %02X\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) feature_buffer[0], feature_buffer[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) feature_buffer[2], feature_buffer[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) feature_buffer[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) retval = usb_control_msg(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) usb_sndctrlpipe(port->serial->dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) HID_REQ_SET_REPORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 0x0300, 0, feature_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) feature_len, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (tries++ >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) } while (retval != feature_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) retval != -ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (retval != feature_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) dev_err(dev, "%s - failed sending serial line settings - %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) priv->baud_rate = new_baudrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) priv->current_config = feature_buffer[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* If we asked for a speed change encode it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (baud_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) tty_encode_baud_rate(tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) new_baudrate, new_baudrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case CYPRESS_GET_CONFIG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (priv->get_cfg_unsafe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* Not implemented for this device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) and if we try to do it we're likely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) to crash the hardware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) retval = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) dev_dbg(dev, "%s - retrieving serial line settings\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) retval = usb_control_msg(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) usb_rcvctrlpipe(port->serial->dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) HID_REQ_GET_REPORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 0x0300, 0, feature_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) feature_len, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (tries++ >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) } while (retval != feature_len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) && retval != -ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (retval != feature_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) dev_err(dev, "%s - failed to retrieve serial line settings - %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* store the config in one byte, and later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) use bit masks to check values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) priv->current_config = feature_buffer[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) priv->baud_rate = get_unaligned_le32(feature_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ++priv->cmd_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) kfree(feature_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) } /* cypress_serial_control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static void cypress_set_dead(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (!priv->comm_is_ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) priv->comm_is_ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) dev_err(&port->dev, "cypress_m8 suspending failing port %d - "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) "interval might be too short\n", port->port_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * Cypress serial driver functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static int cypress_generic_port_probe(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct usb_serial *serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct cypress_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!port->interrupt_out_urb || !port->interrupt_in_urb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) dev_err(&port->dev, "required endpoint is missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) priv->comm_is_ok = !0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) spin_lock_init(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (kfifo_alloc(&priv->write_fifo, CYPRESS_BUF_SIZE, GFP_KERNEL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* Skip reset for FRWD device. It is a workaound:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) device hangs if it receives SET_CONFIGURE in Configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (!is_frwd(serial->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) usb_reset_configuration(serial->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) priv->cmd_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) priv->line_control = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) priv->rx_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* Default packet format setting is determined by packet size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) Anything with a size larger then 9 must have a separate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) count field since the 3 bit count field is otherwise too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) small. Otherwise we can use the slightly more compact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) format. This is in accordance with the cypress_m8 serial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) converter app note. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (port->interrupt_out_size > 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) priv->pkt_fmt = packet_format_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) priv->pkt_fmt = packet_format_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (interval > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) priv->write_urb_interval = interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) priv->read_urb_interval = interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) dev_dbg(&port->dev, "%s - read & write intervals forced to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) __func__, interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) priv->write_urb_interval = port->interrupt_out_urb->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) priv->read_urb_interval = port->interrupt_in_urb->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) dev_dbg(&port->dev, "%s - intervals: read=%d write=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) __func__, priv->read_urb_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) priv->write_urb_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) usb_set_serial_port_data(port, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) port->port.drain_delay = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static int cypress_earthmate_port_probe(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct usb_serial *serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct cypress_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ret = cypress_generic_port_probe(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) priv->chiptype = CT_EARTHMATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* All Earthmate devices use the separated-count packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) format! Idiotic. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) priv->pkt_fmt = packet_format_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (serial->dev->descriptor.idProduct !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /* The old original USB Earthmate seemed able to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) handle GET_CONFIG requests; everything they've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) produced since that time crashes if this command is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) attempted :-( */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) dev_dbg(&port->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) "%s - Marking this device as unsafe for GET_CONFIG commands\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) priv->get_cfg_unsafe = !0;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int cypress_hidcom_port_probe(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct cypress_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ret = cypress_generic_port_probe(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) priv->chiptype = CT_CYPHIDCOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct cypress_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = cypress_generic_port_probe(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) priv->chiptype = CT_CA42V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static int cypress_port_remove(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct cypress_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) kfifo_free(&priv->write_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct usb_serial *serial = port->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!priv->comm_is_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* clear halts before open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) usb_clear_halt(serial->dev, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) usb_clear_halt(serial->dev, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* reset read/write statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) priv->bytes_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) priv->bytes_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) priv->cmd_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) priv->rx_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* Set termios */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) cypress_send(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) cypress_set_termios(tty, port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* setup the port and start reading from the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) port->interrupt_in_urb->transfer_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) port->interrupt_in_urb->transfer_buffer_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) cypress_read_int_callback, port, priv->read_urb_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) dev_err(&port->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) "%s - failed submitting read urb, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) } /* cypress_open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static void cypress_dtr_rts(struct usb_serial_port *port, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* drop dtr and rts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) spin_lock_irq(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (on == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) priv->line_control = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) priv->line_control = CONTROL_DTR | CONTROL_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) priv->cmd_ctrl = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) spin_unlock_irq(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) cypress_write(NULL, port, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static void cypress_close(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) kfifo_reset_out(&priv->write_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) dev_dbg(&port->dev, "%s - stopping urbs\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) usb_kill_urb(port->interrupt_in_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) usb_kill_urb(port->interrupt_out_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) priv->bytes_in, priv->bytes_out, priv->cmd_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) } /* cypress_close */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) const unsigned char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) dev_dbg(&port->dev, "%s - %d bytes\n", __func__, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* line control commands, which need to be executed immediately,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) are not put into the buffer for obvious reasons.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (priv->cmd_ctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) goto finish;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) count = kfifo_in_locked(&priv->write_fifo, buf, count, &priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) finish:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) cypress_send(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) } /* cypress_write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static void cypress_send(struct usb_serial_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) int count = 0, result, offset, actual_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct device *dev = &port->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (!priv->comm_is_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) dev_dbg(dev, "%s - interrupt out size is %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) port->interrupt_out_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (priv->write_urb_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) dev_dbg(dev, "%s - can't write, urb in use\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /* clear buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) memset(port->interrupt_out_urb->transfer_buffer, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) port->interrupt_out_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) switch (priv->pkt_fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) case packet_format_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* this is for the CY7C64013... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) offset = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) port->interrupt_out_buffer[0] = priv->line_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case packet_format_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* this is for the CY7C63743... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) offset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) port->interrupt_out_buffer[0] = priv->line_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (priv->line_control & CONTROL_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) priv->line_control &= ~CONTROL_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (priv->cmd_ctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) priv->cmd_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) dev_dbg(dev, "%s - line control command being issued\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) goto send;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) count = kfifo_out_locked(&priv->write_fifo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) &port->interrupt_out_buffer[offset],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) port->interrupt_out_size - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) &priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) switch (priv->pkt_fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) case packet_format_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) port->interrupt_out_buffer[1] = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) case packet_format_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) port->interrupt_out_buffer[0] |= count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) dev_dbg(dev, "%s - count is %d\n", __func__, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) send:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) priv->write_urb_in_use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (priv->cmd_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) actual_size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) actual_size = count +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) (priv->pkt_fmt == packet_format_1 ? 2 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) usb_serial_debug_data(dev, __func__, port->interrupt_out_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) port->interrupt_out_urb->transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) port->interrupt_out_buffer, actual_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) cypress_write_int_callback, port, priv->write_urb_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) dev_err_console(port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) "%s - failed submitting write urb, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) priv->write_urb_in_use = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (priv->cmd_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) priv->cmd_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /* do not count the line control and size bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) priv->bytes_out += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) usb_serial_port_softint(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) } /* cypress_send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* returns how much space is available in the soft buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static int cypress_write_room(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) int room = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) room = kfifo_avail(&priv->write_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return room;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static int cypress_tiocmget(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) __u8 status, control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) unsigned int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) control = priv->line_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) status = priv->current_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) | ((control & CONTROL_RTS) ? TIOCM_RTS : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) | ((status & UART_CTS) ? TIOCM_CTS : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) | ((status & UART_DSR) ? TIOCM_DSR : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) | ((status & UART_RI) ? TIOCM_RI : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) | ((status & UART_CD) ? TIOCM_CD : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) dev_dbg(&port->dev, "%s - result = %x\n", __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static int cypress_tiocmset(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) unsigned int set, unsigned int clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (set & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) priv->line_control |= CONTROL_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (set & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) priv->line_control |= CONTROL_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (clear & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) priv->line_control &= ~CONTROL_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (clear & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) priv->line_control &= ~CONTROL_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) priv->cmd_ctrl = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return cypress_write(tty, port, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) static void cypress_earthmate_init_termios(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) tty_encode_baud_rate(tty, 4800, 4800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static void cypress_set_termios(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct usb_serial_port *port, struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct device *dev = &port->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int data_bits, stop_bits, parity_type, parity_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) unsigned int cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) __u8 oldlines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) int linechange = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* Unsupported features need clearing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) tty->termios.c_cflag &= ~(CMSPAR|CRTSCTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) cflag = tty->termios.c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* set number of data bits, parity, stop bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /* when parity is disabled the parity type bit is ignored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* 1 means 2 stop bits, 0 means 1 stop bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) stop_bits = cflag & CSTOPB ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (cflag & PARENB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) parity_enable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) /* 1 means odd parity, 0 means even parity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) parity_type = cflag & PARODD ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) parity_enable = parity_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) switch (cflag & CSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) case CS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) data_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case CS6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) data_bits = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case CS7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) data_bits = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) case CS8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) data_bits = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) dev_err(dev, "%s - CSIZE was set, but not CS5-CS8\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) data_bits = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) oldlines = priv->line_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if ((cflag & CBAUD) == B0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* drop dtr and rts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) dev_dbg(dev, "%s - dropping the lines, baud rate 0bps\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) priv->line_control = (CONTROL_DTR | CONTROL_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) dev_dbg(dev, "%s - sending %d stop_bits, %d parity_enable, %d parity_type, %d data_bits (+5)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) __func__, stop_bits, parity_enable, parity_type, data_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) cypress_serial_control(tty, port, tty_get_baud_rate(tty),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) data_bits, stop_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) parity_enable, parity_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 0, CYPRESS_SET_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* we perform a CYPRESS_GET_CONFIG so that the current settings are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * filled into the private structure this should confirm that all is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * working if it returns what we just set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) cypress_serial_control(tty, port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* Here we can define custom tty settings for devices; the main tty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * termios flag base comes from empeg.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) dev_dbg(dev, "Using custom termios settings for a baud rate of 4800bps.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /* define custom termios settings for NMEA protocol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) tty->termios.c_iflag /* input modes - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) &= ~(IGNBRK /* disable ignore break */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) | BRKINT /* disable break causes interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) | PARMRK /* disable mark parity errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) | ISTRIP /* disable clear high bit of input char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) | INLCR /* disable translate NL to CR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) | IGNCR /* disable ignore CR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) | ICRNL /* disable translate CR to NL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) | IXON); /* disable enable XON/XOFF flow control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) tty->termios.c_oflag /* output modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) &= ~OPOST; /* disable postprocess output char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) tty->termios.c_lflag /* line discipline modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) &= ~(ECHO /* disable echo input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) | ECHONL /* disable echo new line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) | ICANON /* disable erase, kill, werase, and rprnt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) special characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) | ISIG /* disable interrupt, quit, and suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) special characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) | IEXTEN); /* disable non-POSIX special characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) } /* CT_CYPHIDCOM: Application should handle this for device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) linechange = (priv->line_control != oldlines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* if necessary, set lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (linechange) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) priv->cmd_ctrl = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) cypress_write(tty, port, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) } /* cypress_set_termios */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) /* returns amount of data still left in soft buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static int cypress_chars_in_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int chars = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) chars = kfifo_len(&priv->write_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return chars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static void cypress_throttle(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) spin_lock_irq(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) priv->rx_flags = THROTTLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) spin_unlock_irq(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) static void cypress_unthrottle(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct usb_serial_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) int actually_throttled, result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) spin_lock_irq(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) priv->rx_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) spin_unlock_irq(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!priv->comm_is_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (actually_throttled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) dev_err(&port->dev, "%s - failed submitting read urb, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) "error %d\n", __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static void cypress_read_int_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) struct device *dev = &urb->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) struct tty_struct *tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) unsigned char *data = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) char tty_flag = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) int bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) case 0: /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* precursor to disconnect so just go away */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) case -EPIPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /* Can't call usb_clear_halt while in_interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* something ugly is going on... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) dev_err(dev, "%s - unexpected nonzero read status received: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (priv->rx_flags & THROTTLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) dev_dbg(dev, "%s - now throttling\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) priv->rx_flags |= ACTUALLY_THROTTLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) tty = tty_port_tty_get(&port->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (!tty) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) dev_dbg(dev, "%s - bad tty pointer - exiting\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) result = urb->actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) switch (priv->pkt_fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) case packet_format_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) /* This is for the CY7C64013... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) priv->current_status = data[0] & 0xF8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) bytes = data[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) i = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) case packet_format_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /* This is for the CY7C63743... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) priv->current_status = data[0] & 0xF8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) bytes = (data[0] & 0x07) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) i = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (result < bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) dev_dbg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) "%s - wrong packet size - received %d bytes but packet said %d bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) __func__, result, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) goto continue_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) /* check to see if status has changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (priv->current_status != priv->prev_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) u8 delta = priv->current_status ^ priv->prev_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (delta & UART_MSR_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (delta & UART_CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) port->icount.cts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (delta & UART_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) port->icount.dsr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (delta & UART_RI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) port->icount.rng++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (delta & UART_CD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) port->icount.dcd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) wake_up_interruptible(&port->port.delta_msr_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) priv->prev_status = priv->current_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /* hangup, as defined in acm.c... this might be a bad place for it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * though */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (tty && !C_CLOCAL(tty) && !(priv->current_status & UART_CD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) dev_dbg(dev, "%s - calling hangup\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) tty_hangup(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) goto continue_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /* There is one error bit... I'm assuming it is a parity error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) * indicator as the generic firmware will set this bit to 1 if a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) * parity error occurs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) * I can not find reference to any other error events. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (priv->current_status & CYP_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) tty_flag = TTY_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) dev_dbg(dev, "%s - Parity Error detected\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /* process read if there is data other than line status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (bytes > i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) tty_insert_flip_string_fixed_flag(&port->port, data + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) tty_flag, bytes - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) tty_flip_buffer_push(&port->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) spin_lock_irqsave(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /* control and status byte(s) are also counted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) priv->bytes_in += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) spin_unlock_irqrestore(&priv->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) continue_read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) tty_kref_put(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /* Continue trying to always read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (priv->comm_is_ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) usb_rcvintpipe(port->serial->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) port->interrupt_in_endpointAddress),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) port->interrupt_in_urb->transfer_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) port->interrupt_in_urb->transfer_buffer_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) cypress_read_int_callback, port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) priv->read_urb_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (result && result != -EPERM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) dev_err(dev, "%s - failed resubmitting read urb, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) __func__, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) } /* cypress_read_int_callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) static void cypress_write_int_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct usb_serial_port *port = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) struct cypress_private *priv = usb_get_serial_port_data(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) struct device *dev = &urb->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) int status = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) /* this urb is terminated, clean up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) dev_dbg(dev, "%s - urb shutting down with status: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) priv->write_urb_in_use = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) case -EPIPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* Cannot call usb_clear_halt while in_interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) dev_err(dev, "%s - unexpected nonzero write status received: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) cypress_set_dead(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) priv->write_urb_in_use = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /* send any buffered data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) cypress_send(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) module_usb_serial_driver(serial_drivers, id_table_combined);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) MODULE_AUTHOR(DRIVER_AUTHOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) module_param(stats, bool, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) MODULE_PARM_DESC(stats, "Enable statistics or not");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) module_param(interval, int, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) MODULE_PARM_DESC(interval, "Overrides interrupt interval");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) module_param(unstable_bauds, bool, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) MODULE_PARM_DESC(unstable_bauds, "Allow unstable baud rates");