pl2303.c revision 15e7cead1ed89d445cf86c75a72368e98a7a9039
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Prolific PL2303 USB to serial adaptor driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 44d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * Copyright (C) 2001-2007 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 * 94d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * This program is free software; you can redistribute it and/or 104d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * modify it under the terms of the GNU General Public License version 114d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * 2 as published by the Free Software Foundation. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 133a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox * See Documentation/usb/usb-serial.txt for more information on using this 143a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox * driver 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 293a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox#include <linux/uaccess.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/usb.h> 31a969888ce91673c7f4b86520d851a6f0d5a5fa7dGreg Kroah-Hartman#include <linux/usb/serial.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pl2303.h" 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version Information 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 397d40d7e85a25e01948bcb4dc3eda1355af318337Németh Mártonstatic const struct usb_device_id id_table[] = { 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, 423d861494729c70d9ebeb7d93caa107897925c355Peter Moulder { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, 45b483b6aaa56f0db72fa50e85b6499a32d82009bfMax Arnold { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, 464be2fa186d54758296d30c565d7b5111dd45b000Steve Murphy { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, 47727df3569b358ef440683787c2b9fe8cc55a0954Greg Kroah-Hartman { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, 4818344a1cd5889d48dac67229fcf024ed300030d5Simone Contini { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, 4996a3e79edff6f41b0f115a82f1a39d66218077a7Dario Lombardo { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, 518a28dea3accda319d51a1bf4d3e280771d946f78Masakazu Mokuno { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, 5758381719845d9ee19a321c2eb69cfa9b7886be9aWang Jun { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 66a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 68a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, 69e7beb667842ad0f6ec95a22e7c88e71dfbd60649Andreas Loibl { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, 70912299f6f0587bb6c221705ed9949709b36b3c56Alan Cox { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ 71acbb36f116243bed515357264ecbb6ff9c6d2a5bPeter Favrholdt { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, 72c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, 73c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, 746cceb05f8df6e28ab90f44bdeba50d33928cdee5Denis MONTERRAT { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, 75c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, 76491b04ce1c9adfa0cd73f095086f3c37da81b667Dick Streefland { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, 773b92847425a98d26ad9d2b8682d3ce6020c90752Matthew Meno { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, 78b7aa94b682dc6b6dcdc01d36f8e65cef5aae81e2Kim Oldfield { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, 798fd801339350b63cbb90730ff8b2be349fb3dc67Johannes Steingraeber { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, 802d94b981c7fcb0fba4aa3442cd180066dbedbbc8YOSHIFUJI Hideaki { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, 819e3285dba5cac12d656da66fd7d420ff1bc0ecc0Magnus Damm { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, 82cc311ee7d29d96f0bf15599f4456012d6f5ea23cDamien Stuart { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, 837c99200142c04d0f1ed3f048014591f841efdaedMatthew Arnold { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, 84af4b8514aafd53d97b05a0a30b7d4cfd2cbb7b81Mike Provencher { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, 858540d66615c39010168ab97eaafb476ec2851298Gianpaolo Cugola { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, 86f36ecd5de93e4c85a9e3d25100c6e233155b12e5Jef Driesen { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, 8749276560c9004fce24c42e3c0ad75f34d956fc63Khanh-Dang Nguyen Thu Lam { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, 8835904e6b5106fda51b04c8b8080c04466865415fPawel Ludwikow { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, 899a61d72602771906e11a5944e8571f8006387b39Manuel Jander { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, 90598f0b703506da841d3459dc0c48506be14d1778Eric Benoit { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 94372db8a780f63368c6960a167b7a19aad776d704Thiago GalesiMODULE_DEVICE_TABLE(usb, id_table); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST_TYPE 0x21 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST 0x20 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST_TYPE 0x21 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST 0x22 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_DTR 0x01 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_RTS 0x02 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_REQUEST_TYPE 0x21 1053a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox#define BREAK_REQUEST 0x23 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_ON 0xffff 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_OFF 0x0000 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST_TYPE 0xa1 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST 0x21 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST_TYPE 0x40 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST 0x01 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST_TYPE 0xc0 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST 0x01 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE 0x08 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE_TRANSIENT_MASK 0x74 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DCD 0x01 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DSR 0x02 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_BREAK_ERROR 0x04 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_RING 0x08 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_FRAME_ERROR 0x10 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_PARITY_ERROR 0x20 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_OVERRUN_ERROR 0x40 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_CTS 0x80 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum pl2303_type { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_0, /* don't know the difference between type 0 and */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_1, /* type 1, until someone from prolific tells us... */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HX, /* HX version of the pl2303 chip */ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1368bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstruct pl2303_serial_private { 1378bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold enum pl2303_type type; 1388bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold}; 1398bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pl2303_private { 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_control; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_status; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 146eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_read(__u16 value, __u16 index, 147eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial, unsigned char *buf) 148eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 149eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 150eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, 151eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, buf, 1, 100); 1527b5789a86890423e1460362798140c26822798b1Johan Hovold dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", 153d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index, 154d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman res, buf[0]); 155eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 156eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 157eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 158eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_write(__u16 value, __u16 index, 159eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial) 160eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 161eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 162eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, 163eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, NULL, 0, 100); 1647b5789a86890423e1460362798140c26822798b1Johan Hovold dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d\n", 165d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index, 166d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman res); 167eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 168eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 169eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 170372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_startup(struct usb_serial *serial) 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1728bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_serial_private *spriv; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type = type_0; 1743e152505a57db6622deb1322c22551c046e33d16Sarah Sharp unsigned char *buf; 1758bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 1768bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); 1778bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (!spriv) 1788bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return -ENOMEM; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1803e152505a57db6622deb1322c22551c046e33d16Sarah Sharp buf = kmalloc(10, GFP_KERNEL); 1818bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (!buf) { 1828bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold kfree(spriv); 1833e152505a57db6622deb1322c22551c046e33d16Sarah Sharp return -ENOMEM; 1848bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold } 1853e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serial->dev->descriptor.bDeviceClass == 0x02) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_0; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = HX; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0x00) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0xFF) 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 194d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&serial->interface->dev, "device type: %d\n", type); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1968bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spriv->type = type; 1978bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold usb_set_serial_data(serial, spriv); 1983e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 1993e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2003e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 0, serial); 2013e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2023e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 2033e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2043e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 1, serial); 2053e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2063e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 2073e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0, 1, serial); 2083e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(1, 0, serial); 2093e152505a57db6622deb1322c22551c046e33d16Sarah Sharp if (type == HX) 2103e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(2, 0x44, serial); 2113e152505a57db6622deb1322c22551c046e33d16Sarah Sharp else 2123e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(2, 0x24, serial); 2133e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 2143e152505a57db6622deb1322c22551c046e33d16Sarah Sharp kfree(buf); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2168bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold} 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2188bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstatic void pl2303_release(struct usb_serial *serial) 2198bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold{ 2208bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_serial_private *spriv; 2218bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2228bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spriv = usb_get_serial_data(serial); 2238bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold kfree(spriv); 2248bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold} 2258bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2268bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstatic int pl2303_port_probe(struct usb_serial_port *port) 2278bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold{ 2288bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_private *priv; 2298bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2308bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold priv = kzalloc(sizeof(*priv), GFP_KERNEL); 2318bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (!priv) 2328bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return -ENOMEM; 2338bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2348bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spin_lock_init(&priv->lock); 2358bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2368bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold usb_set_serial_port_data(port, priv); 2378bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 238d7be62211125c85fa1dd796e92aadce84961a502Johan Hovold port->port.drain_delay = 256; 239d7be62211125c85fa1dd796e92aadce84961a502Johan Hovold 2408bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return 0; 2418bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold} 2428bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2438bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstatic int pl2303_port_remove(struct usb_serial_port *port) 2448bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold{ 2458bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_private *priv; 2468bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2478bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold priv = usb_get_serial_port_data(port); 2488bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold kfree(priv); 2498bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2508bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return 0; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovoldstatic int pl2303_set_control_lines(struct usb_serial_port *port, u8 value) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 255f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold struct usb_device *dev = port->serial->dev; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 2573a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox 258372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 259372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, 260372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi value, 0, NULL, 0, 100); 261f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__, 262d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman value, retval); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovoldstatic void pl2303_encode_baudrate(struct tty_struct *tty, 26715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct usb_serial_port *port, 26815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold u8 buf[4]) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27025b8286805e856c8c7fda127018e31032c918015Frank Schaefer const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, 27125b8286805e856c8c7fda127018e31032c918015Frank Schaefer 4800, 7200, 9600, 14400, 19200, 28800, 38400, 2720c967e7ecdc2cf42853b4c76f0b2e94ba53c5b92Luca Olivetti 57600, 115200, 230400, 460800, 500000, 614400, 27325b8286805e856c8c7fda127018e31032c918015Frank Schaefer 921600, 1228800, 2457600, 3000000, 6000000 }; 27415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 27515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct usb_serial *serial = port->serial; 27615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct pl2303_serial_private *spriv = usb_get_serial_data(serial); 27715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold int baud; 27825b8286805e856c8c7fda127018e31032c918015Frank Schaefer int baud_floor, baud_ceil; 27925b8286805e856c8c7fda127018e31032c918015Frank Schaefer int k; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28125b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* NOTE: Only the values defined in baud_sup are supported ! 28225b8286805e856c8c7fda127018e31032c918015Frank Schaefer * => if unsupported values are set, the PL2303 seems to use 28325b8286805e856c8c7fda127018e31032c918015Frank Schaefer * 9600 baud (at least my PL2303X always does) 28425b8286805e856c8c7fda127018e31032c918015Frank Schaefer */ 28595da310e66ee8090119596c70ca8432e57f9a97fAlan Cox baud = tty_get_baud_rate(tty); 286d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "baud requested = %d\n", baud); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (baud) { 28825b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* Set baudrate to nearest supported value */ 28925b8286805e856c8c7fda127018e31032c918015Frank Schaefer for (k=0; k<ARRAY_SIZE(baud_sup); k++) { 29025b8286805e856c8c7fda127018e31032c918015Frank Schaefer if (baud_sup[k] / baud) { 29125b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud_ceil = baud_sup[k]; 29225b8286805e856c8c7fda127018e31032c918015Frank Schaefer if (k==0) { 29325b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = baud_ceil; 29425b8286805e856c8c7fda127018e31032c918015Frank Schaefer } else { 29525b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud_floor = baud_sup[k-1]; 29625b8286805e856c8c7fda127018e31032c918015Frank Schaefer if ((baud_ceil % baud) 29725b8286805e856c8c7fda127018e31032c918015Frank Schaefer > (baud % baud_floor)) 29825b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = baud_floor; 29925b8286805e856c8c7fda127018e31032c918015Frank Schaefer else 30025b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = baud_ceil; 30125b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 30225b8286805e856c8c7fda127018e31032c918015Frank Schaefer break; 30325b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 30425b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 30525b8286805e856c8c7fda127018e31032c918015Frank Schaefer if (baud > 1228800) { 30625b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* type_0, type_1 only support up to 1228800 baud */ 3078bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (spriv->type != HX) 30825b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = 1228800; 30925b8286805e856c8c7fda127018e31032c918015Frank Schaefer else if (baud > 6000000) 31025b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = 6000000; 31125b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 312d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "baud set = %d\n", baud); 3138d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński if (baud <= 115200) { 3148d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[0] = baud & 0xff; 3158d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[1] = (baud >> 8) & 0xff; 3168d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[2] = (baud >> 16) & 0xff; 3178d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[3] = (baud >> 24) & 0xff; 3188d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński } else { 3198d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński /* apparently the formula for higher speeds is: 3208d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński * baudrate = 12M * 32 / (2^buf[1]) / buf[0] 3218d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński */ 3228d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński unsigned tmp = 12*1000*1000*32 / baud; 3238d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[3] = 0x80; 3248d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[2] = 0; 3258d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[1] = (tmp >= 256); 3268d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński while (tmp >= 256) { 3278d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński tmp >>= 2; 3288d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[1] <<= 1; 3298d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński } 3308d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[0] = tmp; 3318d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński } 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold /* Save resulting baud rate */ 33515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (baud) 33615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold tty_encode_baud_rate(tty, baud, baud); 33715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold} 33815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 33915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovoldstatic void pl2303_set_termios(struct tty_struct *tty, 34015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct usb_serial_port *port, struct ktermios *old_termios) 34115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold{ 34215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct usb_serial *serial = port->serial; 34315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct pl2303_serial_private *spriv = usb_get_serial_data(serial); 34415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct pl2303_private *priv = usb_get_serial_port_data(port); 34515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold unsigned long flags; 34615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold unsigned int cflag; 34715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold unsigned char *buf; 34815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold int i; 34915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold u8 control; 35015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 35115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold /* The PL2303 is reported to lose bytes if you change 35215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold serial settings even to the same values as before. Thus 35315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold we actually need to filter in this specific case */ 35415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 35515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) 35615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold return; 35715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 35815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold cflag = tty->termios.c_cflag; 35915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 36015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf = kzalloc(7, GFP_KERNEL); 36115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (!buf) { 36215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold dev_err(&port->dev, "%s - out of memory.\n", __func__); 36315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold /* Report back no change occurred */ 36415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (old_termios) 36515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold tty->termios = *old_termios; 36615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold return; 36715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold } 36815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 36915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 37015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 37115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 0, 0, buf, 7, 100); 37215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); 37315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 37415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (cflag & CSIZE) { 37515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold switch (cflag & CSIZE) { 37615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS5: 37715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 5; 37815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold break; 37915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS6: 38015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 6; 38115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold break; 38215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS7: 38315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 7; 38415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold break; 38515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold default: 38615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS8: 38715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 8; 38815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold break; 38915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold } 39015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold dev_dbg(&port->dev, "data bits = %d\n", buf[6]); 39115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold } 39215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 39315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold /* For reference buf[0]:buf[3] baud rate value */ 39415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold pl2303_encode_baudrate(tty, port, &buf[0]); 39515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=0 is 1 stop bits */ 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=1 is 1.5 stop bits */ 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=2 is 2 stop bits */ 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CSTOPB) { 40029cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer /* NOTE: Comply with "real" UARTs / RS232: 40129cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer * use 1.5 instead of 2 stop bits with 5 data bits 40229cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer */ 40329cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer if ((cflag & CSIZE) == CS5) { 40429cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer buf[4] = 1; 405d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "stop bits = 1.5\n"); 40629cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer } else { 40729cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer buf[4] = 2; 408d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "stop bits = 2\n"); 40929cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer } 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = 0; 412d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "stop bits = 1\n"); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARENB) { 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=0 is none parity */ 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=1 is odd parity */ 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=2 is even parity */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=3 is mark parity */ 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=4 is space parity */ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARODD) { 4226dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer if (cflag & CMSPAR) { 4236dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 3; 424d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = mark\n"); 4256dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } else { 4266dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 1; 427d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = odd\n"); 4286dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4306dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer if (cflag & CMSPAR) { 4316dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 4; 432d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = space\n"); 4336dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } else { 4346dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 2; 435d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = even\n"); 4366dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 0; 440d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = none\n"); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 443372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 444372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 445372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 446d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "0x21:0x20:0:0 %d\n", i); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* change control lines if we are switching to or from B0 */ 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cflag & CBAUD) == B0) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 4532d8f4447b58bba5f8cb895c07690434c02307eafJohan Hovold else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (control != priv->line_control) { 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 458f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold pl2303_set_control_lines(port, control); 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 462372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 465372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 466372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 467372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 468715cf92aeb061c47f7170d0d7899311b7597bc66Andy Shevchenko dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CRTSCTS) { 4718bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (spriv->type == HX) 472eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x61, serial); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 474eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x41, serial); 475715f9527c1c1edd1a9c7a55ab4535211279c9374t.sefzick } else { 476eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x0, serial); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 478572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 479572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi kfree(buf); 480572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 481572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 482335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void pl2303_dtr_rts(struct usb_serial_port *port, int on) 483335f8514f200e63d689113d29cb7253a5c282967Alan Cox{ 484335f8514f200e63d689113d29cb7253a5c282967Alan Cox struct pl2303_private *priv = usb_get_serial_port_data(port); 485335f8514f200e63d689113d29cb7253a5c282967Alan Cox unsigned long flags; 486335f8514f200e63d689113d29cb7253a5c282967Alan Cox u8 control; 487335f8514f200e63d689113d29cb7253a5c282967Alan Cox 488335f8514f200e63d689113d29cb7253a5c282967Alan Cox spin_lock_irqsave(&priv->lock, flags); 489335f8514f200e63d689113d29cb7253a5c282967Alan Cox /* Change DTR and RTS */ 490335f8514f200e63d689113d29cb7253a5c282967Alan Cox if (on) 491335f8514f200e63d689113d29cb7253a5c282967Alan Cox priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 492335f8514f200e63d689113d29cb7253a5c282967Alan Cox else 493335f8514f200e63d689113d29cb7253a5c282967Alan Cox priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 494335f8514f200e63d689113d29cb7253a5c282967Alan Cox control = priv->line_control; 495335f8514f200e63d689113d29cb7253a5c282967Alan Cox spin_unlock_irqrestore(&priv->lock, flags); 496f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold pl2303_set_control_lines(port, control); 497335f8514f200e63d689113d29cb7253a5c282967Alan Cox} 498335f8514f200e63d689113d29cb7253a5c282967Alan Cox 499335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void pl2303_close(struct usb_serial_port *port) 500572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 5018b0127b2082601e40295045414a8318f2c8ee5a0Johan Hovold usb_serial_generic_close(port); 502572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi usb_kill_urb(port->interrupt_in_urb); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 505a509a7e478e4766114d69f12d19d644ac63e9765Alan Coxstatic int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 5088bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_serial_private *spriv = usb_get_serial_data(serial); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5118bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (spriv->type != HX) { 5121694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->write_urb->pipe); 5131694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->read_urb->pipe); 5143e152505a57db6622deb1322c22551c046e33d16Sarah Sharp } else { 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset upstream data pipes */ 516eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(8, 0, serial); 517eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(9, 0, serial); 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup termios */ 52195da310e66ee8090119596c70ca8432e57f9a97fAlan Cox if (tty) 5222d8f4447b58bba5f8cb895c07690434c02307eafJohan Hovold pl2303_set_termios(tty, port, NULL); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 524372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 526372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&port->dev, "%s - failed submitting interrupt urb," 527441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " error %d\n", __func__, result); 528db6e9186c90188edea20aaa5161ea073440cc2a1Johan Hovold return result; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 530d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold 531f5230a53c1d551811b077ccad219105786da1becJohan Hovold result = usb_serial_generic_open(tty, port); 532d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold if (result) { 533d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold usb_kill_urb(port->interrupt_in_urb); 534d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold return result; 535d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold } 536d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 54020b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int pl2303_tiocmset(struct tty_struct *tty, 541372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int set, unsigned int clear) 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 54395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 5476f1efd6c5aa63ddcfe1ffc60ade716f5421766f4Johan Hovold int ret; 5486fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 549372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_RTS; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_DTR; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_RTS; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_DTR; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 559372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5615ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold ret = pl2303_set_control_lines(port, control); 5625ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold if (ret) 5635ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold return usb_translate_errors(ret); 5646f1efd6c5aa63ddcfe1ffc60ade716f5421766f4Johan Hovold 5655ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold return 0; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56860b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int pl2303_tiocmget(struct tty_struct *tty) 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 57095da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mcr; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int result; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 577372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mcr = priv->line_control; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 580372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_CTS) ? TIOCM_CTS : 0) 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DSR) ? TIOCM_DSR : 0) 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_RING) ? TIOCM_RI : 0) 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DCD) ? TIOCM_CD : 0); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 589d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - result = %x\n", __func__, result); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 594335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic int pl2303_carrier_raised(struct usb_serial_port *port) 595335f8514f200e63d689113d29cb7253a5c282967Alan Cox{ 596335f8514f200e63d689113d29cb7253a5c282967Alan Cox struct pl2303_private *priv = usb_get_serial_port_data(port); 597335f8514f200e63d689113d29cb7253a5c282967Alan Cox if (priv->line_status & UART_DCD) 598335f8514f200e63d689113d29cb7253a5c282967Alan Cox return 1; 599335f8514f200e63d689113d29cb7253a5c282967Alan Cox return 0; 600335f8514f200e63d689113d29cb7253a5c282967Alan Cox} 601335f8514f200e63d689113d29cb7253a5c282967Alan Cox 602824d11bef5540062d17380c65ee52d4b2948ca84Johan Hovoldstatic int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg) 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 604824d11bef5540062d17380c65ee52d4b2948ca84Johan Hovold struct usb_serial_port *port = tty->driver_data; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int prevstatus; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int changed; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = priv->line_status; 613372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 6166d0cad657a133818038683120fff9c5c5f8dc751Johan Hovold interruptible_sleep_on(&port->port.delta_msr_wait); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* see if a signal did it */ 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ERESTARTSYS; 620372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 62140509ca982c00c4b70fc00be887509feca0bff15Johan Hovold if (port->serial->disconnected) 62240509ca982c00c4b70fc00be887509feca0bff15Johan Hovold return -EIO; 62340509ca982c00c4b70fc00be887509feca0bff15Johan Hovold 624372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 626372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 627372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 6283a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox changed = prevstatus ^ status; 629372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((arg & TIOCM_RNG) && (changed & UART_RING)) || 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_DSR) && (changed & UART_DSR)) || 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_CD) && (changed & UART_DCD)) || 6333a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox ((arg & TIOCM_CTS) && (changed & UART_CTS))) { 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = status; 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64200a0d0d65b61241a718d0aee96f46b9a2d93bf26Alan Coxstatic int pl2303_ioctl(struct tty_struct *tty, 643372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int cmd, unsigned long arg) 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 64567b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas struct serial_struct ser; 64695da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 647d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman 648d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s cmd = 0x%04x\n", __func__, cmd); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 65167b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas case TIOCGSERIAL: 65267b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas memset(&ser, 0, sizeof ser); 65367b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.type = PORT_16654; 654e5b1e2062e0535e8ffef79bb34d857e21380d101Greg Kroah-Hartman ser.line = port->minor; 6551143832eca8f1d64da7d85642c956ae9d25c69e1Greg Kroah-Hartman ser.port = port->port_number; 65667b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.baud_base = 460800; 65767b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas 65867b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas if (copy_to_user((void __user *)arg, &ser, sizeof ser)) 65967b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas return -EFAULT; 66067b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas 66167b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas return 0; 6623a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox default: 663d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); 6643a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox break; 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 66995da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void pl2303_break_ctl(struct tty_struct *tty, int break_state) 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 67195da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 state; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (break_state == 0) 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_OFF; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_ON; 680d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - turning break %s\n", __func__, 6813a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox state == BREAK_OFF ? "off" : "on"); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 683372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 684372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 685372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, NULL, 0, 100); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 687d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_err(&port->dev, "error sending break = %d\n", result); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitnerstatic void pl2303_update_line_status(struct usb_serial_port *port, 69197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned char *data, 69297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length) 69397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner{ 69497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 69597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner struct pl2303_private *priv = usb_get_serial_port_data(port); 696d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek struct tty_struct *tty; 69797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned long flags; 69897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner u8 status_idx = UART_STATE; 69995f209f93663103db2a8fb989e226ac68a98b036Horst Schirmeier u8 length = UART_STATE + 1; 700d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek u8 prev_line_status; 7019c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi u16 idv, idp; 70297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 7039c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); 7049c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp = le16_to_cpu(port->serial->dev->descriptor.idProduct); 7059c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7069c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7079c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idv == SIEMENS_VENDOR_ID) { 7089c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idp == SIEMENS_PRODUCT_ID_X65 || 7099c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_SX1 || 7109c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_X75) { 7119c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7129c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi length = 1; 7139c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi status_idx = 0; 7149c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi } 71597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner } 71697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 71797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner if (actual_length < length) 718a009b75aa0ed55f0bc473c8a3b3e872cbca807ecLuiz Fernando N. Capitulino return; 71997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 7203a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox /* Save off the uart status for others to look at */ 72197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_lock_irqsave(&priv->lock, flags); 722d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek prev_line_status = priv->line_status; 72397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner priv->line_status = data[status_idx]; 72497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_unlock_irqrestore(&priv->lock, flags); 725430eb0d27c1b36c5191c16b2472b26137673a8d4Jason Wessel if (priv->line_status & UART_BREAK_ERROR) 726430eb0d27c1b36c5191c16b2472b26137673a8d4Jason Wessel usb_serial_handle_break(port); 7276d0cad657a133818038683120fff9c5c5f8dc751Johan Hovold wake_up_interruptible(&port->port.delta_msr_wait); 728d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek 729d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek tty = tty_port_tty_get(&port->port); 730d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek if (!tty) 731d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek return; 732d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek if ((priv->line_status ^ prev_line_status) & UART_DCD) 733d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek usb_serial_handle_dcd_change(port, tty, 734d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek priv->line_status & UART_DCD); 735d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek tty_kref_put(tty); 73697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner} 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7387d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void pl2303_read_int_callback(struct urb *urb) 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 740cdc97792289179974af6dda781c855696358d307Ming Lei struct usb_serial_port *port = urb->context; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *data = urb->transfer_buffer; 74297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length = urb->actual_length; 743461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int status = urb->status; 744461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int retval; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 746461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman switch (status) { 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 754d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n", 755d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman __func__, status); 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 758d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n", 759d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman __func__, status); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 76359d33f2fc2d63796296b1b76143e039d6e7cf532Greg Kroah-Hartman usb_serial_debug_data(&port->dev, __func__, 764372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi urb->actual_length, urb->transfer_buffer); 765372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 76697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner pl2303_update_line_status(port, data, actual_length); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 769461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman retval = usb_submit_urb(urb, GFP_ATOMIC); 770461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (retval) 771d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_err(&port->dev, 772372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi "%s - usb_submit_urb failed with result %d\n", 773441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, retval); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 776f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovoldstatic void pl2303_process_read_urb(struct urb *urb) 777d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox{ 778f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold struct usb_serial_port *port = urb->context; 779f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold struct pl2303_private *priv = usb_get_serial_port_data(port); 780d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox unsigned char *data = urb->transfer_buffer; 781d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox char tty_flag = TTY_NORMAL; 782f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold unsigned long flags; 783f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold u8 line_status; 784f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold int i; 785f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 786f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold /* update line status */ 787f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold spin_lock_irqsave(&priv->lock, flags); 788f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold line_status = priv->line_status; 789f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold priv->line_status &= ~UART_STATE_TRANSIENT_MASK; 790f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold spin_unlock_irqrestore(&priv->lock, flags); 7916d0cad657a133818038683120fff9c5c5f8dc751Johan Hovold wake_up_interruptible(&port->port.delta_msr_wait); 792f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 793f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold if (!urb->actual_length) 794f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold return; 795f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 796d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* break takes precedence over parity, */ 797d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* which takes precedence over framing errors */ 798d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox if (line_status & UART_BREAK_ERROR) 799d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_BREAK; 800d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox else if (line_status & UART_PARITY_ERROR) 801d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_PARITY; 802d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox else if (line_status & UART_FRAME_ERROR) 803d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_FRAME; 804d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag); 805d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox 806d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* overrun is special, not associated with a char */ 807d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox if (line_status & UART_OVERRUN_ERROR) 80892a19f9cec9a80ad93c06e115822deb729e2c6adJiri Slaby tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); 8099388e2e71a51fab0aa2309bbb45e8a23d89a95a9Johan Hovold 810d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold if (port->port.console && port->sysrq) { 811d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox for (i = 0; i < urb->actual_length; ++i) 8126ee9f4b4affe751d313d2538999aeec134d413a6Dmitry Torokhov if (!usb_serial_handle_sysrq_char(port, data[i])) 81392a19f9cec9a80ad93c06e115822deb729e2c6adJiri Slaby tty_insert_flip_char(&port->port, data[i], 81492a19f9cec9a80ad93c06e115822deb729e2c6adJiri Slaby tty_flag); 815d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold } else { 8162f69335710884ae6112fc8196ebe29b5cda7b79bJiri Slaby tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, 817d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold urb->actual_length); 8189388e2e71a51fab0aa2309bbb45e8a23d89a95a9Johan Hovold } 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8202e124b4a390ca85325fae75764bef92f0547fa25Jiri Slaby tty_flip_buffer_push(&port->port); 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 823572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* All of the device info needed for the PL2303 SIO serial converter */ 824572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic struct usb_serial_driver pl2303_device = { 825572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .driver = { 826572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .owner = THIS_MODULE, 827572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .name = "pl2303", 828572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi }, 829572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .id_table = id_table, 830572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .num_ports = 1, 8317919c2fd9e07276403b9a4d9ae52305e0d70f923Johan Hovold .bulk_in_size = 256, 8323efeaff6298290b36499532f0b4c87aa4bae8aefJohan Hovold .bulk_out_size = 256, 833572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .open = pl2303_open, 834572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .close = pl2303_close, 835335f8514f200e63d689113d29cb7253a5c282967Alan Cox .dtr_rts = pl2303_dtr_rts, 836335f8514f200e63d689113d29cb7253a5c282967Alan Cox .carrier_raised = pl2303_carrier_raised, 837572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .ioctl = pl2303_ioctl, 838572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .break_ctl = pl2303_break_ctl, 839572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .set_termios = pl2303_set_termios, 840572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmget = pl2303_tiocmget, 841572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmset = pl2303_tiocmset, 842824d11bef5540062d17380c65ee52d4b2948ca84Johan Hovold .tiocmiwait = pl2303_tiocmiwait, 843f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold .process_read_urb = pl2303_process_read_urb, 844572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .read_int_callback = pl2303_read_int_callback, 845572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .attach = pl2303_startup, 846f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern .release = pl2303_release, 8478bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold .port_probe = pl2303_port_probe, 8488bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold .port_remove = pl2303_port_remove, 849572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi}; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Sternstatic struct usb_serial_driver * const serial_drivers[] = { 852f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Stern &pl2303_device, NULL 853f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Stern}; 854f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Stern 85568e24113457e437b1576670f2419b77ed0531e9eGreg Kroah-Hartmanmodule_usb_serial_driver(serial_drivers, id_table); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRIVER_DESC); 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 859