pl2303.c revision 97bb13ec5bc156352cca8af90080597e04299a73
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Prolific PL2303 USB to serial adaptor driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 IBM Corp. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Original driver for 2.2.x by anonymous 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See Documentation/usb/usb-serial.txt for more information on using this driver 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2002_Mar_26 gkh 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allowed driver to work properly if there is no tty assigned to a port 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (this happens for serial console devices.) 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001_Oct_06 gkh 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001_Sep_19 gkh 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Added break support. 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001_Aug_30 gkh 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fixed oops in write_bulk_callback. 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001_Aug_28 gkh 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reworked buffer logic to be like other usb-serial drivers. Hopefully 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * removing some reported problems. 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001_Jun_06 gkh 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * finished porting to 2.4 format. 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/usb.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "usb-serial.h" 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pl2303.h" 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version Information 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_VERSION "v0.12" 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PL2303_CLOSING_WAIT (30*HZ) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PL2303_BUF_SIZE 1024 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PL2303_TMP_BUF_SIZE 1024 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_MUTEX(pl2303_tmp_buf_sem); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pl2303_buf { 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int buf_size; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf_buf; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf_get; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf_put; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_device_id id_table [] = { 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE (usb, id_table); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_driver pl2303_driver = { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "pl2303", 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = usb_serial_probe, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .disconnect = usb_serial_disconnect, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = id_table, 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST_TYPE 0x21 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST 0x20 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST_TYPE 0x21 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST 0x22 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_DTR 0x01 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_RTS 0x02 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_REQUEST_TYPE 0x21 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_REQUEST 0x23 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_ON 0xffff 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_OFF 0x0000 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST_TYPE 0xa1 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST 0x21 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST_TYPE 0x40 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST 0x01 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST_TYPE 0xc0 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST 0x01 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE 0x08 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE_TRANSIENT_MASK 0x74 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DCD 0x01 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DSR 0x02 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_BREAK_ERROR 0x04 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_RING 0x08 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_FRAME_ERROR 0x10 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_PARITY_ERROR 0x20 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_OVERRUN_ERROR 0x40 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_CTS 0x80 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* function prototypes for a PL2303 serial converter */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_open (struct usb_serial_port *port, struct file *filp); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_close (struct usb_serial_port *port, struct file *filp); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_set_termios (struct usb_serial_port *port, 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct termios *old); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_ioctl (struct usb_serial_port *port, struct file *file, 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_write (struct usb_serial_port *port, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const unsigned char *buf, int count); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_send (struct usb_serial_port *port); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_write_room(struct usb_serial_port *port); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_chars_in_buffer(struct usb_serial_port *port); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_break_ctl(struct usb_serial_port *port,int break_state); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_tiocmget (struct usb_serial_port *port, struct file *file); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_startup (struct usb_serial *serial); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_shutdown (struct usb_serial *serial); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pl2303_buf *pl2303_buf_alloc(unsigned int size); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_buf_free(struct pl2303_buf *pb); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_buf_clear(struct pl2303_buf *pb); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int count); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int count); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All of the device info needed for the PL2303 SIO serial converter */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_serial_device_type pl2303_device = { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "PL-2303", 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = id_table, 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_interrupt_in = NUM_DONT_CARE, 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_bulk_in = 1, 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_bulk_out = 1, 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_ports = 1, 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = pl2303_open, 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = pl2303_close, 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = pl2303_write, 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = pl2303_ioctl, 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .break_ctl = pl2303_break_ctl, 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_termios = pl2303_set_termios, 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmget = pl2303_tiocmget, 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmset = pl2303_tiocmset, 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_bulk_callback = pl2303_read_bulk_callback, 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_int_callback = pl2303_read_int_callback, 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write_bulk_callback = pl2303_write_bulk_callback, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write_room = pl2303_write_room, 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chars_in_buffer = pl2303_chars_in_buffer, 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attach = pl2303_startup, 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .shutdown = pl2303_shutdown, 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum pl2303_type { 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_0, /* don't know the difference between type 0 and */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_1, /* type 1, until someone from prolific tells us... */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HX, /* HX version of the pl2303 chip */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pl2303_private { 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_buf *buf; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int write_urb_in_use; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_queue_head_t delta_msr_wait; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_control; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_status; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 termios_initialized; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_startup (struct usb_serial *serial) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type = type_0; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serial->dev->descriptor.bDeviceClass == 0x02) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_0; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = HX; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0x00) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0xFF) 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("device type: %d", type); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < serial->num_ports; ++i) { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!priv) 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto cleanup; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset (priv, 0x00, sizeof (struct pl2303_private)); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&priv->lock); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->buf == NULL) { 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto cleanup; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&priv->delta_msr_wait); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->type = type; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], priv); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscleanup: 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (--i; i>=0; --i) { 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = usb_get_serial_port_data(serial->port[i]); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_buf_free(priv->buf); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], NULL); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int set_control_lines (struct usb_device *dev, u8 value) 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_control_msg (dev, usb_sndctrlpipe (dev, 0), 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value, 0, NULL, 0, 100); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_write (struct usb_serial_port *port, const unsigned char *buf, int count) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!count) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = pl2303_buf_put(priv->buf, buf, count); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_send(port); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_send(struct usb_serial_port *port) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count, result; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->write_urb_in_use) { 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->bulk_out_size); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) { 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 1; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->transfer_buffer_length = count; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->dev = port->serial->dev; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb (port->write_urb, GFP_ATOMIC); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 0; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // TODO: reschedule pl2303_send 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_work(&port->work); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_write_room(struct usb_serial_port *port) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int room = 0; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds room = pl2303_buf_space_avail(priv->buf); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - returns %d", __FUNCTION__, room); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return room; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_chars_in_buffer(struct usb_serial_port *port) 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chars = 0; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chars = pl2303_buf_data_avail(priv->buf); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - returns %d", __FUNCTION__, chars); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return chars; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios) 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cflag; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *buf; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int baud; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((!port->tty) || (!port->tty->termios)) { 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - no tty structures", __FUNCTION__); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!priv->termios_initialized) { 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(port->tty->termios) = tty_std_termios; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->termios_initialized = 1; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cflag = port->tty->termios->c_cflag; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check that they really want us to change something */ 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_termios) { 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cflag == old_termios->c_cflag) && 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - nothing to change...", __FUNCTION__); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = kmalloc (7, GFP_KERNEL); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!buf) { 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset (buf, 0x00, 0x07); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, 0, buf, 7, 100); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg ("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CSIZE) { 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cflag & CSIZE) { 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS5: buf[6] = 5; break; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS6: buf[6] = 6; break; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS7: buf[6] = 7; break; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS8: buf[6] = 8; break; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - data bits = %d", __FUNCTION__, buf[6]); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baud = 0; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cflag & CBAUD) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B0: baud = 0; break; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B75: baud = 75; break; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B150: baud = 150; break; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B300: baud = 300; break; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B600: baud = 600; break; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B1200: baud = 1200; break; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B1800: baud = 1800; break; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B2400: baud = 2400; break; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B4800: baud = 4800; break; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B9600: baud = 9600; break; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B19200: baud = 19200; break; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B38400: baud = 38400; break; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B57600: baud = 57600; break; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B115200: baud = 115200; break; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B230400: baud = 230400; break; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case B460800: baud = 460800; break; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&port->dev, "pl2303 driver does not support the baudrate requested (fix it)\n"); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - baud = %d", __FUNCTION__, baud); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (baud) { 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = baud & 0xff; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[1] = (baud >> 8) & 0xff; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[2] = (baud >> 16) & 0xff; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[3] = (baud >> 24) & 0xff; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=0 is 1 stop bits */ 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=1 is 1.5 stop bits */ 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=2 is 2 stop bits */ 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CSTOPB) { 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = 2; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - stop bits = 2", __FUNCTION__); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = 0; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - stop bits = 1", __FUNCTION__); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARENB) { 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=0 is none parity */ 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=1 is odd parity */ 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=2 is even parity */ 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=3 is mark parity */ 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=4 is space parity */ 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARODD) { 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 1; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - parity = odd", __FUNCTION__); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 2; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - parity = even", __FUNCTION__); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 0; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - parity = none", __FUNCTION__); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, 0, buf, 7, 100); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg ("0x21:0x20:0:0 %d", i); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* change control lines if we are switching to or from B0 */ 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cflag & CBAUD) == B0) 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (control != priv->line_control) { 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_control_lines(serial->dev, control); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, 0, buf, 7, 100); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg ("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CRTSCTS) { 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u16 index; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->type == HX) 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds index = 0x61; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds index = 0x41; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = usb_control_msg(serial->dev, 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_sndctrlpipe(serial->dev, 0), 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VENDOR_WRITE_REQUEST, 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VENDOR_WRITE_REQUEST_TYPE, 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x0, index, NULL, 0, 100); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg ("0x40:0x1:0x0:0x%x %d", index, i); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree (buf); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_open (struct usb_serial_port *port, struct file *filp) 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct termios tmp_termios; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *buf; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_clear_halt(serial->dev, port->write_urb->pipe); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_clear_halt(serial->dev, port->read_urb->pipe); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = kmalloc(10, GFP_KERNEL); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buf==NULL) 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FISH(a,b,c,d) \ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds b, a, c, d, buf, 1, 100); \ 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SOUP(a,b,c,d) \ 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \ 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds b, a, c, d, NULL, 0, 100); \ 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1); 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->type == HX) { 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* HX chip */ 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset upstream data pipes */ 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(buf); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup termios */ 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->tty) { 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_set_termios (port, &tmp_termios); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds //FIXME: need to assert RTS and DTR if CRTSCTS off 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - submitting read urb", __FUNCTION__); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->read_urb->dev = serial->dev; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb (port->read_urb, GFP_KERNEL); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_close (port, NULL); 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPROTO; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - submitting interrupt urb", __FUNCTION__); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->interrupt_in_urb->dev = serial->dev; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n", __FUNCTION__, result); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_close (port, NULL); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPROTO; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_close (struct usb_serial_port *port, struct file *filp) 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int c_cflag; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bps; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long timeout; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_queue_t wait; \ 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* wait for data to drain from the buffer */ 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timeout = PL2303_CLOSING_WAIT; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_entry(&wait, current); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_wait_queue(&port->tty->write_wait, &wait); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_INTERRUPTIBLE); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pl2303_buf_data_avail(priv->buf) == 0 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || timeout == 0 || signal_pending(current) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || !usb_get_intfdata(port->serial->interface)) /* disconnect */ 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timeout = schedule_timeout(timeout); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_RUNNING); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_wait_queue(&port->tty->write_wait, &wait); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* clear out any remaining data in the buffer */ 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_buf_clear(priv->buf); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* wait for characters to drain from the device */ 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* (this is long enough for the entire 256 byte */ 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pl2303 hardware buffer to drain with no flow */ 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* control for data rates of 1200 bps or more, */ 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for lower rates we should really know how much */ 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* data is in the buffer to compute a delay */ 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* that is not unnecessarily long) */ 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bps = tty_get_baud_rate(port->tty); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bps > 1200) 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timeout = max((HZ*2560)/bps,HZ/10); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timeout = 2*HZ; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_INTERRUPTIBLE); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_timeout(timeout); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* shutdown our urbs */ 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - shutting down urbs", __FUNCTION__); 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_kill_urb(port->write_urb); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_kill_urb(port->read_urb); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_kill_urb(port->interrupt_in_urb); 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->tty) { 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c_cflag = port->tty->termios->c_cflag; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (c_cflag & HUPCL) { 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* drop DTR and RTS */ 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control = 0; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&priv->lock, flags); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_control_lines (port->serial->dev, 0); 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear) 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6806fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner if (!usb_get_intfdata(port->serial->interface)) 6816fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner return -ENODEV; 6826fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&priv->lock, flags); 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_RTS; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_DTR; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_RTS; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_DTR; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&priv->lock, flags); 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return set_control_lines (port->serial->dev, control); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_tiocmget (struct usb_serial_port *port, struct file *file) 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mcr; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int result; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s (%d)", __FUNCTION__, port->number); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7086fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner if (!usb_get_intfdata(port->serial->interface)) 7096fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner return -ENODEV; 7106fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&priv->lock, flags); 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mcr = priv->line_control; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&priv->lock, flags); 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_CTS) ? TIOCM_CTS : 0) 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DSR) ? TIOCM_DSR : 0) 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_RING) ? TIOCM_RI : 0) 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DCD) ? TIOCM_CD : 0); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - result = %x", __FUNCTION__, result); 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_modem_info(struct usb_serial_port *port, unsigned int arg) 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int prevstatus; 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int changed; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&priv->lock, flags); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = priv->line_status; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&priv->lock, flags); 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds interruptible_sleep_on(&priv->delta_msr_wait); 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* see if a signal did it */ 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ERESTARTSYS; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&priv->lock, flags); 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&priv->lock, flags); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds changed=prevstatus^status; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((arg & TIOCM_RNG) && (changed & UART_RING)) || 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_DSR) && (changed & UART_DSR)) || 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_CD) && (changed & UART_DCD)) || 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) { 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = status; 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCMIWAIT: 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return wait_modem_info(port, arg); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s not supported = 0x%04x", __FUNCTION__, cmd); 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_break_ctl (struct usb_serial_port *port, int break_state) 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 state; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (break_state == 0) 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_OFF; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_ON; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on"); 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, NULL, 0, 100); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - error sending break = %d", __FUNCTION__, result); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_shutdown (struct usb_serial *serial) 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s", __FUNCTION__); 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < serial->num_ports; ++i) { 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = usb_get_serial_port_data(serial->port[i]); 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv) { 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_buf_free(priv->buf); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], NULL); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 82097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitnerstatic void pl2303_update_line_status(struct usb_serial_port *port, 82197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned char *data, 82297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length) 82397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner{ 82497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 82597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner struct pl2303_private *priv = usb_get_serial_port_data(port); 82697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned long flags; 82797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner u8 status_idx = UART_STATE; 82897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner u8 length = UART_STATE; 82997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 83097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && 83197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65)) { 83297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner length = 1; 83397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner status_idx = 0; 83497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner } 83597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 83697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner if (actual_length < length) 83797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner goto exit; 83897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 83997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner /* Save off the uart status for others to look at */ 84097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_lock_irqsave(&priv->lock, flags); 84197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner priv->line_status = data[status_idx]; 84297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_unlock_irqrestore(&priv->lock, flags); 84397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 84497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitnerexit: 84597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner return; 84697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner} 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs) 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial_port *port = (struct usb_serial_port *) urb->context; 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *data = urb->transfer_buffer; 85297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length = urb->actual_length; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s (%d)", __FUNCTION__, port->number); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (urb->status) { 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer); 87397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner pl2303_update_line_status(port, data, actual_length); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = usb_submit_urb (urb, GFP_ATOMIC); 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status) 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __FUNCTION__, status); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial_port *port = (struct usb_serial_port *) urb->context; 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tty_struct *tty; 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *data = urb->transfer_buffer; 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 status; 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char tty_flag; 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (urb->status) { 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - urb->status = %d", __FUNCTION__, urb->status); 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!port->open_count) { 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port is closed, exiting.", __FUNCTION__); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (urb->status == -EPROTO) { 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PL2303 mysteriously fails with -EPROTO reschedule the read */ 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__); 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->status = 0; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->dev = port->serial->dev; 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb(urb, GFP_ATOMIC); 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - unable to handle the error, exiting.", __FUNCTION__); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get tty_flag from status */ 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_NORMAL; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_status &= ~UART_STATE_TRANSIENT_MASK; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible (&priv->delta_msr_wait); 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* break takes precedence over parity, */ 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* which takes precedence over framing errors */ 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & UART_BREAK_ERROR ) 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_BREAK; 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (status & UART_PARITY_ERROR) 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_PARITY; 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (status & UART_FRAME_ERROR) 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_FRAME; 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag); 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty = port->tty; 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty && urb->actual_length) { 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* overrun is special, not associated with a char */ 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & UART_OVERRUN_ERROR) 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_insert_flip_char(tty, 0, TTY_OVERRUN); 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < urb->actual_length; ++i) { 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flip_buffer_push(tty); 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_insert_flip_char (tty, data[i], tty_flag); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flip_buffer_push (tty); 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Schedule the next read _if_ we are still open */ 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->open_count) { 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->dev = port->serial->dev; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb(urb, GFP_ATOMIC); 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial_port *port = (struct usb_serial_port *) urb->context; 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (urb->status) { 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 0; 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* error in the urb, so we have to resubmit it */ 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - Overflow in write", __FUNCTION__); 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->transfer_buffer_length = 1; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->dev = port->serial->dev; 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb (port->write_urb, GFP_ATOMIC); 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result); 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 0; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* send any buffered data */ 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_send(port); 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pl2303_buf_alloc 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate a circular buffer and all associated memory. 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pl2303_buf *pl2303_buf_alloc(unsigned int size) 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_buf *pb; 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (size == 0) 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb == NULL) 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_buf = kmalloc(size, GFP_KERNEL); 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb->buf_buf == NULL) { 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(pb); 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_size = size; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_get = pb->buf_put = pb->buf_buf; 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pb; 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pl2303_buf_free 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free the buffer and all associated memory. 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_buf_free(struct pl2303_buf *pb) 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb != NULL) { 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb->buf_buf != NULL) 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(pb->buf_buf); 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(pb); 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pl2303_buf_clear 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear out all data in the circular buffer. 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_buf_clear(struct pl2303_buf *pb) 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb != NULL) 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_get = pb->buf_put; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* equivalent to a get of all data available */ 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pl2303_buf_data_avail 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return the number of bytes of data available in the circular 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * buffer. 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb != NULL) 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pl2303_buf_space_avail 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return the number of bytes of space available in the circular 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * buffer. 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb != NULL) 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pl2303_buf_put 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copy data data from a user buffer and put it into the circular buffer. 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Restrict to the amount of space available. 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return the number of bytes copied. 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int count) 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int len; 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb == NULL) 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = pl2303_buf_space_avail(pb); 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > len) 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = len; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = pb->buf_buf + pb->buf_size - pb->buf_put; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > len) { 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(pb->buf_put, buf, len); 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(pb->buf_buf, buf+len, count - len); 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_put = pb->buf_buf + count - len; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(pb->buf_put, buf, count); 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count < len) 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_put += count; 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else /* count == len */ 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_put = pb->buf_buf; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pl2303_buf_get 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get data from the circular buffer and copy to the given buffer. 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Restrict to the amount of data available. 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return the number of bytes copied. 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int count) 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int len; 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pb == NULL) 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = pl2303_buf_data_avail(pb); 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > len) 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = len; 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = pb->buf_buf + pb->buf_size - pb->buf_get; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > len) { 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(buf, pb->buf_get, len); 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(buf+len, pb->buf_buf, count - len); 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_get = pb->buf_buf + count - len; 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(buf, pb->buf_get, count); 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count < len) 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_get += count; 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else /* count == len */ 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pb->buf_get = pb->buf_buf; 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pl2303_init (void) 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_serial_register(&pl2303_device); 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_usb_serial_register; 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_register(&pl2303_driver); 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_usb_register; 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info(DRIVER_DESC " " DRIVER_VERSION); 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed_usb_register: 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_serial_deregister(&pl2303_device); 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed_usb_serial_register: 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit pl2303_exit (void) 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_deregister (&pl2303_driver); 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_serial_deregister (&pl2303_device); 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(pl2303_init); 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(pl2303_exit); 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRIVER_DESC); 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(DRIVER_VERSION); 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, bool, S_IRUGO | S_IWUSR); 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug enabled or not"); 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1222