pl2303.c revision 598f0b703506da841d3459dc0c48506be14d1778
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 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PL2303_CLOSING_WAIT (30*HZ) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 437d40d7e85a25e01948bcb4dc3eda1355af318337Németh Mártonstatic const struct usb_device_id id_table[] = { 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, 463d861494729c70d9ebeb7d93caa107897925c355Peter Moulder { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, 49b483b6aaa56f0db72fa50e85b6499a32d82009bfMax Arnold { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, 504be2fa186d54758296d30c565d7b5111dd45b000Steve Murphy { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, 51727df3569b358ef440683787c2b9fe8cc55a0954Greg Kroah-Hartman { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, 5218344a1cd5889d48dac67229fcf024ed300030d5Simone Contini { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, 5396a3e79edff6f41b0f115a82f1a39d66218077a7Dario Lombardo { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, 558a28dea3accda319d51a1bf4d3e280771d946f78Masakazu Mokuno { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, 6158381719845d9ee19a321c2eb69cfa9b7886be9aWang Jun { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 70a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 72a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, 73e7beb667842ad0f6ec95a22e7c88e71dfbd60649Andreas Loibl { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, 74912299f6f0587bb6c221705ed9949709b36b3c56Alan Cox { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ 75acbb36f116243bed515357264ecbb6ff9c6d2a5bPeter Favrholdt { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, 76c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, 77c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, 786cceb05f8df6e28ab90f44bdeba50d33928cdee5Denis MONTERRAT { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, 79c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, 80491b04ce1c9adfa0cd73f095086f3c37da81b667Dick Streefland { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, 813b92847425a98d26ad9d2b8682d3ce6020c90752Matthew Meno { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, 82b7aa94b682dc6b6dcdc01d36f8e65cef5aae81e2Kim Oldfield { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, 838fd801339350b63cbb90730ff8b2be349fb3dc67Johannes Steingraeber { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, 842d94b981c7fcb0fba4aa3442cd180066dbedbbc8YOSHIFUJI Hideaki { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, 859e3285dba5cac12d656da66fd7d420ff1bc0ecc0Magnus Damm { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, 86cc311ee7d29d96f0bf15599f4456012d6f5ea23cDamien Stuart { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, 877c99200142c04d0f1ed3f048014591f841efdaedMatthew Arnold { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, 88af4b8514aafd53d97b05a0a30b7d4cfd2cbb7b81Mike Provencher { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, 898540d66615c39010168ab97eaafb476ec2851298Gianpaolo Cugola { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, 90f36ecd5de93e4c85a9e3d25100c6e233155b12e5Jef Driesen { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, 9149276560c9004fce24c42e3c0ad75f34d956fc63Khanh-Dang Nguyen Thu Lam { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, 9235904e6b5106fda51b04c8b8080c04466865415fPawel Ludwikow { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, 939a61d72602771906e11a5944e8571f8006387b39Manuel Jander { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, 94026dfaf18973404a01f488d6aa556a8c466e06a4Wolfgang Denk { USB_DEVICE(WINCHIPHEAD_VENDOR_ID, WINCHIPHEAD_USBSER_PRODUCT_ID) }, 95598f0b703506da841d3459dc0c48506be14d1778Eric Benoit { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 99372db8a780f63368c6960a167b7a19aad776d704Thiago GalesiMODULE_DEVICE_TABLE(usb, id_table); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_driver pl2303_driver = { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "pl2303", 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = usb_serial_probe, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .disconnect = usb_serial_disconnect, 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = id_table, 106fcf9e55e066d12c18add7c8a292bf879b45b1d55Sarah Sharp .suspend = usb_serial_suspend, 107fcf9e55e066d12c18add7c8a292bf879b45b1d55Sarah Sharp .resume = usb_serial_resume, 108ba9dc657af86d05d2971633e57d1f6f94ed60472Greg Kroah-Hartman .no_dynamic_id = 1, 109fcf9e55e066d12c18add7c8a292bf879b45b1d55Sarah Sharp .supports_autosuspend = 1, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST_TYPE 0x21 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST 0x20 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST_TYPE 0x21 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST 0x22 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_DTR 0x01 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_RTS 0x02 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_REQUEST_TYPE 0x21 1213a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox#define BREAK_REQUEST 0x23 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_ON 0xffff 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_OFF 0x0000 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST_TYPE 0xa1 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST 0x21 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST_TYPE 0x40 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST 0x01 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST_TYPE 0xc0 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST 0x01 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE 0x08 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE_TRANSIENT_MASK 0x74 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DCD 0x01 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DSR 0x02 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_BREAK_ERROR 0x04 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_RING 0x08 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_FRAME_ERROR 0x10 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_PARITY_ERROR 0x20 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_OVERRUN_ERROR 0x40 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_CTS 0x80 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum pl2303_type { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_0, /* don't know the difference between type 0 and */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_1, /* type 1, until someone from prolific tells us... */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HX, /* HX version of the pl2303 chip */ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pl2303_private { 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_queue_head_t delta_msr_wait; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_control; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_status; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 160eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_read(__u16 value, __u16 index, 161eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial, unsigned char *buf) 162eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 163eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 164eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, 165eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, buf, 1, 100); 166eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE, 167eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_READ_REQUEST, value, index, res, buf[0]); 168eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 169eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 170eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 171eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_write(__u16 value, __u16 index, 172eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial) 173eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 174eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 175eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, 176eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, NULL, 0, 100); 177eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE, 178eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_WRITE_REQUEST, value, index, res); 179eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 180eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 181eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 182372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_startup(struct usb_serial *serial) 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type = type_0; 1863e152505a57db6622deb1322c22551c046e33d16Sarah Sharp unsigned char *buf; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1893e152505a57db6622deb1322c22551c046e33d16Sarah Sharp buf = kmalloc(10, GFP_KERNEL); 1903e152505a57db6622deb1322c22551c046e33d16Sarah Sharp if (buf == NULL) 1913e152505a57db6622deb1322c22551c046e33d16Sarah Sharp return -ENOMEM; 1923e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serial->dev->descriptor.bDeviceClass == 0x02) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_0; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = HX; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0x00) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0xFF) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("device type: %d", type); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < serial->num_ports; ++i) { 20480b6ca48321974a6566a1c9048ba34f60420bca6Eric Sesterhenn priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!priv) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto cleanup; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&priv->lock); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&priv->delta_msr_wait); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->type = type; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], priv); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2123e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 2133e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2143e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 0, serial); 2153e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2163e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 2173e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2183e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 1, serial); 2193e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2203e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 2213e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0, 1, serial); 2223e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(1, 0, serial); 2233e152505a57db6622deb1322c22551c046e33d16Sarah Sharp if (type == HX) 2243e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(2, 0x44, serial); 2253e152505a57db6622deb1322c22551c046e33d16Sarah Sharp else 2263e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(2, 0x24, serial); 2273e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 2283e152505a57db6622deb1322c22551c046e33d16Sarah Sharp kfree(buf); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscleanup: 2323e152505a57db6622deb1322c22551c046e33d16Sarah Sharp kfree(buf); 2333a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox for (--i; i >= 0; --i) { 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = usb_get_serial_port_data(serial->port[i]); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], NULL); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int set_control_lines(struct usb_device *dev, u8 value) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 2443a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox 245372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 246372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, 247372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi value, 0, NULL, 0, 100); 248441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - value = %d, retval = %d", __func__, value, retval); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void pl2303_set_termios(struct tty_struct *tty, 25395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port, struct ktermios *old_termios) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cflag; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *buf; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int baud; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 26325b8286805e856c8c7fda127018e31032c918015Frank Schaefer const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, 26425b8286805e856c8c7fda127018e31032c918015Frank Schaefer 4800, 7200, 9600, 14400, 19200, 28800, 38400, 26525b8286805e856c8c7fda127018e31032c918015Frank Schaefer 57600, 115200, 230400, 460800, 614400, 26625b8286805e856c8c7fda127018e31032c918015Frank Schaefer 921600, 1228800, 2457600, 3000000, 6000000 }; 26725b8286805e856c8c7fda127018e31032c918015Frank Schaefer int baud_floor, baud_ceil; 26825b8286805e856c8c7fda127018e31032c918015Frank Schaefer int k; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 270441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 272bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox /* The PL2303 is reported to lose bytes if you change 273bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox serial settings even to the same values as before. Thus 274bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox we actually need to filter in this specific case */ 275bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox 27695da310e66ee8090119596c70ca8432e57f9a97fAlan Cox if (!tty_termios_hw_change(tty->termios, old_termios)) 277bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox return; 278bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox 27995da310e66ee8090119596c70ca8432e57f9a97fAlan Cox cflag = tty->termios->c_cflag; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi buf = kzalloc(7, GFP_KERNEL); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!buf) { 283441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dev_err(&port->dev, "%s - out of memory.\n", __func__); 284a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox /* Report back no change occurred */ 28595da310e66ee8090119596c70ca8432e57f9a97fAlan Cox *tty->termios = *old_termios; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 290372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 291372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 292372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, 293372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CSIZE) { 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cflag & CSIZE) { 2973a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox case CS5: 2983a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox buf[6] = 5; 2993a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox break; 3003a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox case CS6: 3013a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox buf[6] = 6; 3023a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox break; 3033a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox case CS7: 3043a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox buf[6] = 7; 3053a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox break; 3063a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox default: 3073a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox case CS8: 3083a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox buf[6] = 8; 3093a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox break; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 311441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - data bits = %d", __func__, buf[6]); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31425b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* For reference buf[0]:buf[3] baud rate value */ 31525b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* NOTE: Only the values defined in baud_sup are supported ! 31625b8286805e856c8c7fda127018e31032c918015Frank Schaefer * => if unsupported values are set, the PL2303 seems to use 31725b8286805e856c8c7fda127018e31032c918015Frank Schaefer * 9600 baud (at least my PL2303X always does) 31825b8286805e856c8c7fda127018e31032c918015Frank Schaefer */ 31995da310e66ee8090119596c70ca8432e57f9a97fAlan Cox baud = tty_get_baud_rate(tty); 32025b8286805e856c8c7fda127018e31032c918015Frank Schaefer dbg("%s - baud requested = %d", __func__, baud); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (baud) { 32225b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* Set baudrate to nearest supported value */ 32325b8286805e856c8c7fda127018e31032c918015Frank Schaefer for (k=0; k<ARRAY_SIZE(baud_sup); k++) { 32425b8286805e856c8c7fda127018e31032c918015Frank Schaefer if (baud_sup[k] / baud) { 32525b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud_ceil = baud_sup[k]; 32625b8286805e856c8c7fda127018e31032c918015Frank Schaefer if (k==0) { 32725b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = baud_ceil; 32825b8286805e856c8c7fda127018e31032c918015Frank Schaefer } else { 32925b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud_floor = baud_sup[k-1]; 33025b8286805e856c8c7fda127018e31032c918015Frank Schaefer if ((baud_ceil % baud) 33125b8286805e856c8c7fda127018e31032c918015Frank Schaefer > (baud % baud_floor)) 33225b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = baud_floor; 33325b8286805e856c8c7fda127018e31032c918015Frank Schaefer else 33425b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = baud_ceil; 33525b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 33625b8286805e856c8c7fda127018e31032c918015Frank Schaefer break; 33725b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 33825b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 33925b8286805e856c8c7fda127018e31032c918015Frank Schaefer if (baud > 1228800) { 34025b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* type_0, type_1 only support up to 1228800 baud */ 34125b8286805e856c8c7fda127018e31032c918015Frank Schaefer if (priv->type != HX) 34225b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = 1228800; 34325b8286805e856c8c7fda127018e31032c918015Frank Schaefer else if (baud > 6000000) 34425b8286805e856c8c7fda127018e31032c918015Frank Schaefer baud = 6000000; 34525b8286805e856c8c7fda127018e31032c918015Frank Schaefer } 34625b8286805e856c8c7fda127018e31032c918015Frank Schaefer dbg("%s - baud set = %d", __func__, baud); 3478d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński if (baud <= 115200) { 3488d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[0] = baud & 0xff; 3498d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[1] = (baud >> 8) & 0xff; 3508d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[2] = (baud >> 16) & 0xff; 3518d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[3] = (baud >> 24) & 0xff; 3528d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński } else { 3538d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński /* apparently the formula for higher speeds is: 3548d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński * baudrate = 12M * 32 / (2^buf[1]) / buf[0] 3558d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński */ 3568d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński unsigned tmp = 12*1000*1000*32 / baud; 3578d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[3] = 0x80; 3588d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[2] = 0; 3598d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[1] = (tmp >= 256); 3608d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński while (tmp >= 256) { 3618d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński tmp >>= 2; 3628d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[1] <<= 1; 3638d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński } 3648d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński buf[0] = tmp; 3658d48fdf689fed2c73c493e5146d1463689246442Michał Sroczyński } 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=0 is 1 stop bits */ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=1 is 1.5 stop bits */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=2 is 2 stop bits */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CSTOPB) { 37229cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer /* NOTE: Comply with "real" UARTs / RS232: 37329cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer * use 1.5 instead of 2 stop bits with 5 data bits 37429cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer */ 37529cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer if ((cflag & CSIZE) == CS5) { 37629cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer buf[4] = 1; 37729cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer dbg("%s - stop bits = 1.5", __func__); 37829cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer } else { 37929cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer buf[4] = 2; 38029cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer dbg("%s - stop bits = 2", __func__); 38129cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = 0; 384441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - stop bits = 1", __func__); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARENB) { 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=0 is none parity */ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=1 is odd parity */ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=2 is even parity */ 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=3 is mark parity */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=4 is space parity */ 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARODD) { 3946dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer if (cflag & CMSPAR) { 3956dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 3; 3966dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer dbg("%s - parity = mark", __func__); 3976dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } else { 3986dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 1; 3996dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer dbg("%s - parity = odd", __func__); 4006dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4026dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer if (cflag & CMSPAR) { 4036dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 4; 4046dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer dbg("%s - parity = space", __func__); 4056dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } else { 4066dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 2; 4076dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer dbg("%s - parity = even", __func__); 4086dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 0; 412441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = none", __func__); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 415372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 416372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 417372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 418372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dbg("0x21:0x20:0:0 %d", i); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* change control lines if we are switching to or from B0 */ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cflag & CBAUD) == B0) 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (control != priv->line_control) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_control_lines(serial->dev, control); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 434372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 437372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 438372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 439372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 440372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CRTSCTS) { 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->type == HX) 445eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x61, serial); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 447eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x41, serial); 448715f9527c1c1edd1a9c7a55ab4535211279c9374t.sefzick } else { 449eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x0, serial); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 451572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 45225b8286805e856c8c7fda127018e31032c918015Frank Schaefer /* Save resulting baud rate */ 453df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox if (baud) 45495da310e66ee8090119596c70ca8432e57f9a97fAlan Cox tty_encode_baud_rate(tty, baud, baud); 455df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox 456572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi kfree(buf); 457572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 458572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 459335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void pl2303_dtr_rts(struct usb_serial_port *port, int on) 460335f8514f200e63d689113d29cb7253a5c282967Alan Cox{ 461335f8514f200e63d689113d29cb7253a5c282967Alan Cox struct pl2303_private *priv = usb_get_serial_port_data(port); 462335f8514f200e63d689113d29cb7253a5c282967Alan Cox unsigned long flags; 463335f8514f200e63d689113d29cb7253a5c282967Alan Cox u8 control; 464335f8514f200e63d689113d29cb7253a5c282967Alan Cox 465335f8514f200e63d689113d29cb7253a5c282967Alan Cox spin_lock_irqsave(&priv->lock, flags); 466335f8514f200e63d689113d29cb7253a5c282967Alan Cox /* Change DTR and RTS */ 467335f8514f200e63d689113d29cb7253a5c282967Alan Cox if (on) 468335f8514f200e63d689113d29cb7253a5c282967Alan Cox priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 469335f8514f200e63d689113d29cb7253a5c282967Alan Cox else 470335f8514f200e63d689113d29cb7253a5c282967Alan Cox priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 471335f8514f200e63d689113d29cb7253a5c282967Alan Cox control = priv->line_control; 472335f8514f200e63d689113d29cb7253a5c282967Alan Cox spin_unlock_irqrestore(&priv->lock, flags); 473335f8514f200e63d689113d29cb7253a5c282967Alan Cox set_control_lines(port->serial->dev, control); 474335f8514f200e63d689113d29cb7253a5c282967Alan Cox} 475335f8514f200e63d689113d29cb7253a5c282967Alan Cox 476335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void pl2303_close(struct usb_serial_port *port) 477572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 478441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 479572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 4808b0127b2082601e40295045414a8318f2c8ee5a0Johan Hovold usb_serial_generic_close(port); 481572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi usb_kill_urb(port->interrupt_in_urb); 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 484a509a7e478e4766114d69f12d19d644ac63e9765Alan Coxstatic int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 486606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios tmp_termios; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4931694899fd1af43636351aac97f415fd3c9cefb1dDariusz M if (priv->type != HX) { 4941694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->write_urb->pipe); 4951694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->read_urb->pipe); 4963e152505a57db6622deb1322c22551c046e33d16Sarah Sharp } else { 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset upstream data pipes */ 498eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(8, 0, serial); 499eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(9, 0, serial); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup termios */ 50395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox if (tty) 50495da310e66ee8090119596c70ca8432e57f9a97fAlan Cox pl2303_set_termios(tty, port, &tmp_termios); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 506441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - submitting read urb", __func__); 507f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold result = usb_serial_generic_submit_read_urb(port, GFP_KERNEL); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 509335f8514f200e63d689113d29cb7253a5c282967Alan Cox pl2303_close(port); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPROTO; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 513441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - submitting interrupt urb", __func__); 514372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 516372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&port->dev, "%s - failed submitting interrupt urb," 517441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " error %d\n", __func__, result); 518335f8514f200e63d689113d29cb7253a5c282967Alan Cox pl2303_close(port); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPROTO; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 521335f8514f200e63d689113d29cb7253a5c282967Alan Cox port->port.drain_delay = 256; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52520b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int pl2303_tiocmset(struct tty_struct *tty, 526372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int set, unsigned int clear) 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 52895da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5336fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner if (!usb_get_intfdata(port->serial->interface)) 5346fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner return -ENODEV; 5356fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 536372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_RTS; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_DTR; 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_RTS; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_DTR; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 546372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 548372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi return set_control_lines(port->serial->dev, control); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 55160b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int pl2303_tiocmget(struct tty_struct *tty) 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 55395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mcr; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int result; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 560441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d)", __func__, port->number); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5626fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner if (!usb_get_intfdata(port->serial->interface)) 5636fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner return -ENODEV; 5646fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 565372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mcr = priv->line_control; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 568372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_CTS) ? TIOCM_CTS : 0) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DSR) ? TIOCM_DSR : 0) 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_RING) ? TIOCM_RI : 0) 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DCD) ? TIOCM_CD : 0); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 577441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - result = %x", __func__, result); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 582335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic int pl2303_carrier_raised(struct usb_serial_port *port) 583335f8514f200e63d689113d29cb7253a5c282967Alan Cox{ 584335f8514f200e63d689113d29cb7253a5c282967Alan Cox struct pl2303_private *priv = usb_get_serial_port_data(port); 585335f8514f200e63d689113d29cb7253a5c282967Alan Cox if (priv->line_status & UART_DCD) 586335f8514f200e63d689113d29cb7253a5c282967Alan Cox return 1; 587335f8514f200e63d689113d29cb7253a5c282967Alan Cox return 0; 588335f8514f200e63d689113d29cb7253a5c282967Alan Cox} 589335f8514f200e63d689113d29cb7253a5c282967Alan Cox 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_modem_info(struct usb_serial_port *port, unsigned int arg) 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int prevstatus; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int changed; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 598372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = priv->line_status; 600372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds interruptible_sleep_on(&priv->delta_msr_wait); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* see if a signal did it */ 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ERESTARTSYS; 607372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 608372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 610372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 611372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 6123a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox changed = prevstatus ^ status; 613372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((arg & TIOCM_RNG) && (changed & UART_RING)) || 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_DSR) && (changed & UART_DSR)) || 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_CD) && (changed & UART_DCD)) || 6173a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox ((arg & TIOCM_CTS) && (changed & UART_CTS))) { 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = status; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 62600a0d0d65b61241a718d0aee96f46b9a2d93bf26Alan Coxstatic int pl2303_ioctl(struct tty_struct *tty, 627372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int cmd, unsigned long arg) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 62967b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas struct serial_struct ser; 63095da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 631441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 63467b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas case TIOCGSERIAL: 63567b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas memset(&ser, 0, sizeof ser); 63667b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.type = PORT_16654; 63767b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.line = port->serial->minor; 63867b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.port = port->number; 63967b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.baud_base = 460800; 64067b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas 64167b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas if (copy_to_user((void __user *)arg, &ser, sizeof ser)) 64267b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas return -EFAULT; 64367b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas 64467b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas return 0; 64567b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas 6463a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox case TIOCMIWAIT: 6473a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox dbg("%s (%d) TIOCMIWAIT", __func__, port->number); 6483a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox return wait_modem_info(port, arg); 6493a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox default: 6503a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox dbg("%s not supported = 0x%04x", __func__, cmd); 6513a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox break; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 65695da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void pl2303_break_ctl(struct tty_struct *tty, int break_state) 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 65895da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 state; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 663441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (break_state == 0) 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_OFF; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_ON; 6693a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox dbg("%s - turning break %s", __func__, 6703a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox state == BREAK_OFF ? "off" : "on"); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 672372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 673372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 674372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, NULL, 0, 100); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 676441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - error sending break = %d", __func__, result); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 679f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Sternstatic void pl2303_release(struct usb_serial *serial) 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 684441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < serial->num_ports; ++i) { 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = usb_get_serial_port_data(serial->port[i]); 688684c6e30d389f67ef727c8f5a7b23a09b4cb02e4Johan Hovold kfree(priv); 689372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi } 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitnerstatic void pl2303_update_line_status(struct usb_serial_port *port, 69397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned char *data, 69497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length) 69597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner{ 69697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 69797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner struct pl2303_private *priv = usb_get_serial_port_data(port); 698d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek struct tty_struct *tty; 69997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned long flags; 70097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner u8 status_idx = UART_STATE; 70195f209f93663103db2a8fb989e226ac68a98b036Horst Schirmeier u8 length = UART_STATE + 1; 702d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek u8 prev_line_status; 7039c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi u16 idv, idp; 70497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 7059c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); 7069c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp = le16_to_cpu(port->serial->dev->descriptor.idProduct); 7079c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7089c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7099c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idv == SIEMENS_VENDOR_ID) { 7109c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idp == SIEMENS_PRODUCT_ID_X65 || 7119c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_SX1 || 7129c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_X75) { 7139c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7149c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi length = 1; 7159c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi status_idx = 0; 7169c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi } 71797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner } 71897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 71997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner if (actual_length < length) 720a009b75aa0ed55f0bc473c8a3b3e872cbca807ecLuiz Fernando N. Capitulino return; 72197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 7223a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox /* Save off the uart status for others to look at */ 72397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_lock_irqsave(&priv->lock, flags); 724d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek prev_line_status = priv->line_status; 72597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner priv->line_status = data[status_idx]; 72697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_unlock_irqrestore(&priv->lock, flags); 727430eb0d27c1b36c5191c16b2472b26137673a8d4Jason Wessel if (priv->line_status & UART_BREAK_ERROR) 728430eb0d27c1b36c5191c16b2472b26137673a8d4Jason Wessel usb_serial_handle_break(port); 729372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi wake_up_interruptible(&priv->delta_msr_wait); 730d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek 731d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek tty = tty_port_tty_get(&port->port); 732d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek if (!tty) 733d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek return; 734d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek if ((priv->line_status ^ prev_line_status) & UART_DCD) 735d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek usb_serial_handle_dcd_change(port, tty, 736d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek priv->line_status & UART_DCD); 737d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek tty_kref_put(tty); 73897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner} 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7407d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void pl2303_read_int_callback(struct urb *urb) 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 742cdc97792289179974af6dda781c855696358d307Ming Lei struct usb_serial_port *port = urb->context; 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *data = urb->transfer_buffer; 74497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length = urb->actual_length; 745461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int status = urb->status; 746461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int retval; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 748441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d)", __func__, port->number); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 750461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman switch (status) { 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 758441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - urb shutting down with status: %d", __func__, 759461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman status); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 762441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - nonzero urb status received: %d", __func__, 763461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman status); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 767441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &port->dev, __func__, 768372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi urb->actual_length, urb->transfer_buffer); 769372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 77097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner pl2303_update_line_status(port, data, actual_length); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 773461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman retval = usb_submit_urb(urb, GFP_ATOMIC); 774461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (retval) 775372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&urb->dev->dev, 776372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi "%s - usb_submit_urb failed with result %d\n", 777441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, retval); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 780f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovoldstatic void pl2303_process_read_urb(struct urb *urb) 781d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox{ 782f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold struct usb_serial_port *port = urb->context; 783f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold struct pl2303_private *priv = usb_get_serial_port_data(port); 784f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold struct tty_struct *tty; 785d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox unsigned char *data = urb->transfer_buffer; 786d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox char tty_flag = TTY_NORMAL; 787f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold unsigned long flags; 788f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold u8 line_status; 789f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold int i; 790f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 791f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold /* update line status */ 792f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold spin_lock_irqsave(&priv->lock, flags); 793f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold line_status = priv->line_status; 794f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold priv->line_status &= ~UART_STATE_TRANSIENT_MASK; 795f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold spin_unlock_irqrestore(&priv->lock, flags); 796f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold wake_up_interruptible(&priv->delta_msr_wait); 797f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 798f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold if (!urb->actual_length) 799f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold return; 800f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 801f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold tty = tty_port_tty_get(&port->port); 802f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold if (!tty) 803f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold return; 804f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 805d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* break takes precedence over parity, */ 806d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* which takes precedence over framing errors */ 807d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox if (line_status & UART_BREAK_ERROR) 808d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_BREAK; 809d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox else if (line_status & UART_PARITY_ERROR) 810d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_PARITY; 811d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox else if (line_status & UART_FRAME_ERROR) 812d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_FRAME; 813d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox dbg("%s - tty_flag = %d", __func__, tty_flag); 814d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox 815d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* overrun is special, not associated with a char */ 816d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox if (line_status & UART_OVERRUN_ERROR) 817d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_insert_flip_char(tty, 0, TTY_OVERRUN); 8189388e2e71a51fab0aa2309bbb45e8a23d89a95a9Johan Hovold 819d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold if (port->port.console && port->sysrq) { 820d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox for (i = 0; i < urb->actual_length; ++i) 8216ee9f4b4affe751d313d2538999aeec134d413a6Dmitry Torokhov if (!usb_serial_handle_sysrq_char(port, data[i])) 822d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_insert_flip_char(tty, data[i], tty_flag); 823d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold } else { 824d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold tty_insert_flip_string_fixed_flag(tty, data, tty_flag, 825d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold urb->actual_length); 8269388e2e71a51fab0aa2309bbb45e8a23d89a95a9Johan Hovold } 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 828f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold tty_flip_buffer_push(tty); 8294a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox tty_kref_put(tty); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 832572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* All of the device info needed for the PL2303 SIO serial converter */ 833572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic struct usb_serial_driver pl2303_device = { 834572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .driver = { 835572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .owner = THIS_MODULE, 836572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .name = "pl2303", 837572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi }, 838572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .id_table = id_table, 839d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .usb_driver = &pl2303_driver, 840572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .num_ports = 1, 8417919c2fd9e07276403b9a4d9ae52305e0d70f923Johan Hovold .bulk_in_size = 256, 8423efeaff6298290b36499532f0b4c87aa4bae8aefJohan Hovold .bulk_out_size = 256, 843572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .open = pl2303_open, 844572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .close = pl2303_close, 845335f8514f200e63d689113d29cb7253a5c282967Alan Cox .dtr_rts = pl2303_dtr_rts, 846335f8514f200e63d689113d29cb7253a5c282967Alan Cox .carrier_raised = pl2303_carrier_raised, 847572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .ioctl = pl2303_ioctl, 848572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .break_ctl = pl2303_break_ctl, 849572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .set_termios = pl2303_set_termios, 850572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmget = pl2303_tiocmget, 851572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmset = pl2303_tiocmset, 852f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold .process_read_urb = pl2303_process_read_urb, 853572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .read_int_callback = pl2303_read_int_callback, 854572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .attach = pl2303_startup, 855f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern .release = pl2303_release, 856572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi}; 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 858372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int __init pl2303_init(void) 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 861372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_serial_register(&pl2303_device); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_usb_serial_register; 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_register(&pl2303_driver); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_usb_register; 868c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed_usb_register: 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_serial_deregister(&pl2303_device); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed_usb_serial_register: 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 876372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic void __exit pl2303_exit(void) 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 878372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi usb_deregister(&pl2303_driver); 879372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi usb_serial_deregister(&pl2303_device); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(pl2303_init); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(pl2303_exit); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRIVER_DESC); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, bool, S_IRUGO | S_IWUSR); 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug enabled or not"); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891