pl2303.c revision 281393ad0bcfc309434d2bff38abc15805c2cbc4
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 * 757ce61aad748ceaa08c859da04043ad7dae7c15eFrank Schäfer * Copyright (C) 2009, 2013 Frank Schäfer <fschaefer.oss@googlemail.com> 857ce61aad748ceaa08c859da04043ad7dae7c15eFrank Schäfer * - fixes, improvements and documentation for the baud rate encoding methods 957ce61aad748ceaa08c859da04043ad7dae7c15eFrank Schäfer * Copyright (C) 2013 Reinhard Max <max@suse.de> 1057ce61aad748ceaa08c859da04043ad7dae7c15eFrank Schäfer * - fixes and improvements for the divisor based baud rate encoding method 1157ce61aad748ceaa08c859da04043ad7dae7c15eFrank Schäfer * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Original driver for 2.2.x by anonymous 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 144d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * This program is free software; you can redistribute it and/or 154d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * modify it under the terms of the GNU General Public License version 164d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * 2 as published by the Free Software Foundation. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 183a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox * See Documentation/usb/usb-serial.txt for more information on using this 193a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox * driver 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 343a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox#include <linux/uaccess.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/usb.h> 36a969888ce91673c7f4b86520d851a6f0d5a5fa7dGreg Kroah-Hartman#include <linux/usb/serial.h> 37b2d6d98fc71bb94ada78d433f26a93498802d3f8Johan Hovold#include <asm/unaligned.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pl2303.h" 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version Information 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 457d40d7e85a25e01948bcb4dc3eda1355af318337Németh Mártonstatic const struct usb_device_id id_table[] = { 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, 483d861494729c70d9ebeb7d93caa107897925c355Peter Moulder { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, 51b483b6aaa56f0db72fa50e85b6499a32d82009bfMax Arnold { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, 524be2fa186d54758296d30c565d7b5111dd45b000Steve Murphy { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, 53727df3569b358ef440683787c2b9fe8cc55a0954Greg Kroah-Hartman { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, 5418344a1cd5889d48dac67229fcf024ed300030d5Simone Contini { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, 5596a3e79edff6f41b0f115a82f1a39d66218077a7Dario Lombardo { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, 578a28dea3accda319d51a1bf4d3e280771d946f78Masakazu Mokuno { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, 6358381719845d9ee19a321c2eb69cfa9b7886be9aWang Jun { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 72a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 74a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, 75e7beb667842ad0f6ec95a22e7c88e71dfbd60649Andreas Loibl { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, 76912299f6f0587bb6c221705ed9949709b36b3c56Alan Cox { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ 77acbb36f116243bed515357264ecbb6ff9c6d2a5bPeter Favrholdt { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, 78c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, 79c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, 806cceb05f8df6e28ab90f44bdeba50d33928cdee5Denis MONTERRAT { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, 81c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, 82491b04ce1c9adfa0cd73f095086f3c37da81b667Dick Streefland { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, 833b92847425a98d26ad9d2b8682d3ce6020c90752Matthew Meno { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, 84b7aa94b682dc6b6dcdc01d36f8e65cef5aae81e2Kim Oldfield { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, 858fd801339350b63cbb90730ff8b2be349fb3dc67Johannes Steingraeber { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, 862d94b981c7fcb0fba4aa3442cd180066dbedbbc8YOSHIFUJI Hideaki { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, 879e3285dba5cac12d656da66fd7d420ff1bc0ecc0Magnus Damm { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, 88cc311ee7d29d96f0bf15599f4456012d6f5ea23cDamien Stuart { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, 897c99200142c04d0f1ed3f048014591f841efdaedMatthew Arnold { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, 90af4b8514aafd53d97b05a0a30b7d4cfd2cbb7b81Mike Provencher { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, 918540d66615c39010168ab97eaafb476ec2851298Gianpaolo Cugola { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, 92f36ecd5de93e4c85a9e3d25100c6e233155b12e5Jef Driesen { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, 9349276560c9004fce24c42e3c0ad75f34d956fc63Khanh-Dang Nguyen Thu Lam { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, 9435904e6b5106fda51b04c8b8080c04466865415fPawel Ludwikow { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, 959a61d72602771906e11a5944e8571f8006387b39Manuel Jander { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, 96598f0b703506da841d3459dc0c48506be14d1778Eric Benoit { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 100372db8a780f63368c6960a167b7a19aad776d704Thiago GalesiMODULE_DEVICE_TABLE(usb, id_table); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST_TYPE 0x21 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST 0x20 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST_TYPE 0x21 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST 0x22 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_DTR 0x01 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_RTS 0x02 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_REQUEST_TYPE 0x21 1113a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox#define BREAK_REQUEST 0x23 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_ON 0xffff 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_OFF 0x0000 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST_TYPE 0xa1 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST 0x21 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST_TYPE 0x40 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST 0x01 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST_TYPE 0xc0 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST 0x01 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE 0x08 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE_TRANSIENT_MASK 0x74 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DCD 0x01 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DSR 0x02 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_BREAK_ERROR 0x04 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_RING 0x08 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_FRAME_ERROR 0x10 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_PARITY_ERROR 0x20 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_OVERRUN_ERROR 0x40 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_CTS 0x80 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum pl2303_type { 137e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman type_0, /* don't know the difference between type 0 and */ 138e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman type_1, /* type 1, until someone from prolific tells us... */ 139e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman HX, /* HX version of the pl2303 chip */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1428bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstruct pl2303_serial_private { 1438bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold enum pl2303_type type; 1448bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold}; 1458bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pl2303_private { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_control; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_status; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 152eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_read(__u16 value, __u16 index, 153eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial, unsigned char *buf) 154eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 155eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 156eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, 157eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, buf, 1, 100); 1587b5789a86890423e1460362798140c26822798b1Johan Hovold dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", 159d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index, 160d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman res, buf[0]); 161eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 162eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 163eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 164eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_write(__u16 value, __u16 index, 165eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial) 166eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 167eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 168eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, 169eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, NULL, 0, 100); 1707b5789a86890423e1460362798140c26822798b1Johan Hovold dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d\n", 171d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index, 172d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman res); 173eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 174eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 175eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 176372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_startup(struct usb_serial *serial) 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1788bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_serial_private *spriv; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type = type_0; 1803e152505a57db6622deb1322c22551c046e33d16Sarah Sharp unsigned char *buf; 1818bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 1828bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); 1838bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (!spriv) 1848bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return -ENOMEM; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1863e152505a57db6622deb1322c22551c046e33d16Sarah Sharp buf = kmalloc(10, GFP_KERNEL); 1878bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (!buf) { 1888bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold kfree(spriv); 1893e152505a57db6622deb1322c22551c046e33d16Sarah Sharp return -ENOMEM; 1908bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold } 1913e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 192b52e111363e366202386f3e67f71681dbbb8e5d9Greg Kroah-Hartman if (serial->dev->descriptor.bDeviceClass == 0x02) 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_0; 194b52e111363e366202386f3e67f71681dbbb8e5d9Greg Kroah-Hartman else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) 195e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman type = HX; 196281393ad0bcfc309434d2bff38abc15805c2cbc4Greg Kroah-Hartman else if (serial->dev->descriptor.bDeviceClass == 0x00) 197281393ad0bcfc309434d2bff38abc15805c2cbc4Greg Kroah-Hartman type = type_1; 198281393ad0bcfc309434d2bff38abc15805c2cbc4Greg Kroah-Hartman else if (serial->dev->descriptor.bDeviceClass == 0xFF) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 200b52e111363e366202386f3e67f71681dbbb8e5d9Greg Kroah-Hartman dev_dbg(&serial->interface->dev, "device type: %d\n", type); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2028bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spriv->type = type; 2038bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold usb_set_serial_data(serial, spriv); 2043e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 2053e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2063e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 0, serial); 2073e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2083e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 2093e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2103e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 1, serial); 2113e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 2123e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 2133e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0, 1, serial); 2143e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(1, 0, serial); 215e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman if (type == HX) 216034d1527adebd302115c87ef343497a889638275Frank Schäfer pl2303_vendor_write(2, 0x44, serial); 217e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman else 218e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman pl2303_vendor_write(2, 0x24, serial); 2193e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 2203e152505a57db6622deb1322c22551c046e33d16Sarah Sharp kfree(buf); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2228bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold} 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2248bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstatic void pl2303_release(struct usb_serial *serial) 2258bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold{ 2268bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_serial_private *spriv; 2278bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2288bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spriv = usb_get_serial_data(serial); 2298bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold kfree(spriv); 2308bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold} 2318bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2328bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstatic int pl2303_port_probe(struct usb_serial_port *port) 2338bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold{ 2348bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_private *priv; 2358bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2368bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold priv = kzalloc(sizeof(*priv), GFP_KERNEL); 2378bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold if (!priv) 2388bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return -ENOMEM; 2398bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2408bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold spin_lock_init(&priv->lock); 2418bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2428bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold usb_set_serial_port_data(port, priv); 2438bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 244d7be62211125c85fa1dd796e92aadce84961a502Johan Hovold port->port.drain_delay = 256; 245d7be62211125c85fa1dd796e92aadce84961a502Johan Hovold 2468bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return 0; 2478bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold} 2488bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2498bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovoldstatic int pl2303_port_remove(struct usb_serial_port *port) 2508bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold{ 2518bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_private *priv; 2528bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2538bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold priv = usb_get_serial_port_data(port); 2548bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold kfree(priv); 2558bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold 2568bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold return 0; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 259f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovoldstatic int pl2303_set_control_lines(struct usb_serial_port *port, u8 value) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 261f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold struct usb_device *dev = port->serial->dev; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 2633a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox 264372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 265372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, 266372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi value, 0, NULL, 0, 100); 267f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__, 268d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman value, retval); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 272e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäferstatic int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type, 273e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer u8 buf[4]) 274e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer{ 275e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* 276e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * NOTE: Only the values defined in baud_sup are supported ! 27709169197c9f5e3b42f0c83c6d7071b3e9c94153eGreg Kroah-Hartman * => if unsupported values are set, the PL2303 seems to 27809169197c9f5e3b42f0c83c6d7071b3e9c94153eGreg Kroah-Hartman * use 9600 baud (at least my PL2303X always does) 279e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer */ 280e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, 281e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 4800, 7200, 9600, 14400, 19200, 28800, 38400, 282e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 57600, 115200, 230400, 460800, 614400, 921600, 283e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman 1228800, 2457600, 3000000, 6000000 }; 284c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer /* 285e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman * NOTE: The PL2303HX (tested with rev. 3A) also supports the following 286e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman * baud rates: 128000, 134400, 161280, 201600, 268800, 403200, 806400. 287e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman * As long as we are not using this encoding method for them, there is 288e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman * no point in complicating the code to support them. 289c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer */ 290e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer int i; 291e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 292e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* Set baudrate to nearest supported value */ 293e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) { 294e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer if (baud_sup[i] > baud) 295e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer break; 296e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer } 297e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer if (i == ARRAY_SIZE(baud_sup)) 298e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer baud = baud_sup[i - 1]; 299e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1])) 300e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer baud = baud_sup[i - 1]; 301e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer else 302e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer baud = baud_sup[i]; 303e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman /* type_0, type_1 only support up to 1228800 baud */ 304e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman if (type != HX) 305e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer baud = min_t(int, baud, 1228800); 306e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* Direct (standard) baud rate encoding method */ 307e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer put_unaligned_le32(baud, buf); 308e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 309e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer return baud; 310e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer} 311e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 312e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäferstatic int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type, 313e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer u8 buf[4]) 314e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer{ 315e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* 316e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * Divisor based baud rate encoding method 317e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * 31809169197c9f5e3b42f0c83c6d7071b3e9c94153eGreg Kroah-Hartman * NOTE: it's not clear if the type_0/1 chips support this method 319e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * 320e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * divisor = 12MHz * 32 / baudrate = 2^A * B 321e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * 322e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * with 323e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * 324e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * A = buf[1] & 0x0e 325e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * B = buf[0] + (buf[1] & 0x01) << 8 326e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * 327e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * Special cases: 328e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * => 8 < B < 16: device seems to work not properly 329e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * => B <= 8: device uses the max. value B = 512 instead 330e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer */ 331e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer unsigned int A, B; 332e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 333b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer /* 334b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * NOTE: The Windows driver allows maximum baud rates of 110% of the 335b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * specified maximium value. 336b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * Quick tests with early (2004) HX (rev. A) chips suggest, that even 337b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * higher baud rates (up to the maximum of 24M baud !) are working fine, 338b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * but that should really be tested carefully in "real life" scenarios 339b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * before removing the upper limit completely. 340b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * Baud rates smaller than the specified 75 baud are definitely working 341b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer * fine. 342b5c16c6a031c52cc4b7dda6c3de46462fbc92eabFrank Schäfer */ 343e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman if (type == HX) 344034d1527adebd302115c87ef343497a889638275Frank Schäfer baud = min_t(int, baud, 6000000 * 1.1); 345e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman else 346e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman baud = min_t(int, baud, 1228800 * 1.1); 347e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* Determine factors A and B */ 348e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer A = 0; 349e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B = 12000000 * 32 / baud; /* 12MHz */ 350e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B <<= 1; /* Add one bit for rounding */ 351e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer while (B > (512 << 1) && A <= 14) { 352e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer A += 2; 353e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B >>= 2; 354e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer } 355e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer if (A > 14) { /* max. divisor = min. baudrate reached */ 356e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer A = 14; 357e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B = 512; 358e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* => ~45.78 baud */ 359e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer } else { 360e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B = (B + 1) >> 1; /* Round the last bit */ 361e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer } 362e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* Handle special cases */ 363e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer if (B == 512) 364e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B = 0; /* also: 1 to 8 */ 365e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer else if (B < 16) 366e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* 367e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * NOTE: With the current algorithm this happens 368e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * only for A=0 and means that the min. divisor 369e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * (respectively: the max. baudrate) is reached. 370e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer */ 371e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B = 16; /* => 24 MBaud */ 372e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* Encode the baud rate */ 373e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer buf[3] = 0x80; /* Select divisor encoding method */ 374e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer buf[2] = 0; 375e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer buf[1] = (A & 0x0e); /* A */ 376e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer buf[1] |= ((B & 0x100) >> 8); /* MSB of B */ 377e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer buf[0] = B & 0xff; /* 8 LSBs of B */ 378e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* Calculate the actual/resulting baud rate */ 379e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer if (B <= 8) 380e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer B = 512; 381e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer baud = 12000000 * 32 / ((1 << A) * B); 382e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 383e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer return baud; 384e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer} 385e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer 38615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovoldstatic void pl2303_encode_baudrate(struct tty_struct *tty, 38715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct usb_serial_port *port, 388e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer enum pl2303_type type, 38915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold u8 buf[4]) 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 39115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold int baud; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox baud = tty_get_baud_rate(tty); 394d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "baud requested = %d\n", baud); 395b2d6d98fc71bb94ada78d433f26a93498802d3f8Johan Hovold if (!baud) 396b2d6d98fc71bb94ada78d433f26a93498802d3f8Johan Hovold return; 397e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* 398e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * There are two methods for setting/encoding the baud rate 399e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * 1) Direct method: encodes the baud rate value directly 400e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * => supported by all chip types 401e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer * 2) Divisor based method: encodes a divisor to a base value (12MHz*32) 40209169197c9f5e3b42f0c83c6d7071b3e9c94153eGreg Kroah-Hartman * => supported by HX chips (and likely not by type_0/1 chips) 403c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer * 404c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer * NOTE: Although the divisor based baud rate encoding method is much 405c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer * more flexible, some of the standard baud rate values can not be 406c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer * realized exactly. But the difference is very small (max. 0.2%) and 407c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer * the device likely uses the same baud rate generator for both methods 408c23bda365dfbf56aa4d6d4a97f83136c36050e01Frank Schäfer * so that there is likley no difference. 409e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer */ 410e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman if (type != HX) 411e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer baud = pl2303_baudrate_encode_direct(baud, type, buf); 412e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer else 413e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer baud = pl2303_baudrate_encode_divisor(baud, type, buf); 41415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold /* Save resulting baud rate */ 415b2d6d98fc71bb94ada78d433f26a93498802d3f8Johan Hovold tty_encode_baud_rate(tty, baud, baud); 416b2d6d98fc71bb94ada78d433f26a93498802d3f8Johan Hovold dev_dbg(&port->dev, "baud set = %d\n", baud); 41715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold} 41815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 41915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovoldstatic void pl2303_set_termios(struct tty_struct *tty, 42015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct usb_serial_port *port, struct ktermios *old_termios) 42115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold{ 42215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct usb_serial *serial = port->serial; 42315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct pl2303_serial_private *spriv = usb_get_serial_data(serial); 42415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold struct pl2303_private *priv = usb_get_serial_port_data(port); 42515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold unsigned long flags; 42615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold unsigned char *buf; 42715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold int i; 42815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold u8 control; 42915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 43087265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold /* 43187265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold * The PL2303 is reported to lose bytes if you change serial settings 43287265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold * even to the same values as before. Thus we actually need to filter 43387265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold * in this specific case. 43487265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold */ 43515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) 43615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold return; 43715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 43815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf = kzalloc(7, GFP_KERNEL); 43915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (!buf) { 44015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold dev_err(&port->dev, "%s - out of memory.\n", __func__); 44115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold /* Report back no change occurred */ 44215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold if (old_termios) 44315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold tty->termios = *old_termios; 44415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold return; 44515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold } 44615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 44715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 44815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 44915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 0, 0, buf, 7, 100); 45015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); 45115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 45287265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (C_CSIZE(tty)) { 45387265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold switch (C_CSIZE(tty)) { 45415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS5: 45515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 5; 45615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold break; 45715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS6: 45815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 6; 45915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold break; 46015e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS7: 46115e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 7; 46215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold break; 46315e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold default: 46415e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold case CS8: 46515e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold buf[6] = 8; 46615e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold } 46715e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold dev_dbg(&port->dev, "data bits = %d\n", buf[6]); 46815e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold } 46915e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 470e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer /* For reference: buf[0]:buf[3] baud rate value */ 471e917ba01d69ad705a4cd6a6c77538f55d84f5907Frank Schäfer pl2303_encode_baudrate(tty, port, spriv->type, buf); 47215e7cead1ed89d445cf86c75a72368e98a7a9039Johan Hovold 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=0 is 1 stop bits */ 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=1 is 1.5 stop bits */ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=2 is 2 stop bits */ 47687265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (C_CSTOPB(tty)) { 47787265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold /* 47887265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold * NOTE: Comply with "real" UARTs / RS232: 47929cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer * use 1.5 instead of 2 stop bits with 5 data bits 48029cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer */ 48187265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (C_CSIZE(tty) == CS5) { 48229cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer buf[4] = 1; 483d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "stop bits = 1.5\n"); 48429cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer } else { 48529cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer buf[4] = 2; 486d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "stop bits = 2\n"); 48729cf1b72f34519413b3fafbccc9ac776eb948edeFrank Schaefer } 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = 0; 490d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "stop bits = 1\n"); 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49387265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (C_PARENB(tty)) { 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=0 is none parity */ 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=1 is odd parity */ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=2 is even parity */ 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=3 is mark parity */ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=4 is space parity */ 49987265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (C_PARODD(tty)) { 50087265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (tty->termios.c_cflag & CMSPAR) { 5016dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 3; 502d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = mark\n"); 5036dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } else { 5046dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 1; 505d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = odd\n"); 5066dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 50887265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (tty->termios.c_cflag & CMSPAR) { 5096dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 4; 510d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = space\n"); 5116dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } else { 5126dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer buf[5] = 2; 513d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = even\n"); 5146dd81b45fd7628f3eb308f387aee696366718f25Frank Schaefer } 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 0; 518d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "parity = none\n"); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 522372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 523372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 524d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "0x21:0x20:0:0 %d\n", i); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* change control lines if we are switching to or from B0 */ 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 52987265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (C_BAUD(tty) == B0) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 5312d8f4447b58bba5f8cb895c07690434c02307eafJohan Hovold else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (control != priv->line_control) { 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 536f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold pl2303_set_control_lines(port, control); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 540372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 54187265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold memset(buf, 0, 7); 542372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 543372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 544372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 545715cf92aeb061c47f7170d0d7899311b7597bc66Andy Shevchenko dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 54787265b4514f5a0b79efdccdcb1c6331285652640Johan Hovold if (C_CRTSCTS(tty)) { 548e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman if (spriv->type == HX) 549034d1527adebd302115c87ef343497a889638275Frank Schäfer pl2303_vendor_write(0x0, 0x61, serial); 550e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman else 551e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman pl2303_vendor_write(0x0, 0x41, serial); 552715f9527c1c1edd1a9c7a55ab4535211279c9374t.sefzick } else { 553eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x0, serial); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 555572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 556572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi kfree(buf); 557572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 558572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 559335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void pl2303_dtr_rts(struct usb_serial_port *port, int on) 560335f8514f200e63d689113d29cb7253a5c282967Alan Cox{ 561335f8514f200e63d689113d29cb7253a5c282967Alan Cox struct pl2303_private *priv = usb_get_serial_port_data(port); 562335f8514f200e63d689113d29cb7253a5c282967Alan Cox unsigned long flags; 563335f8514f200e63d689113d29cb7253a5c282967Alan Cox u8 control; 564335f8514f200e63d689113d29cb7253a5c282967Alan Cox 565335f8514f200e63d689113d29cb7253a5c282967Alan Cox spin_lock_irqsave(&priv->lock, flags); 566335f8514f200e63d689113d29cb7253a5c282967Alan Cox /* Change DTR and RTS */ 567335f8514f200e63d689113d29cb7253a5c282967Alan Cox if (on) 568335f8514f200e63d689113d29cb7253a5c282967Alan Cox priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 569335f8514f200e63d689113d29cb7253a5c282967Alan Cox else 570335f8514f200e63d689113d29cb7253a5c282967Alan Cox priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 571335f8514f200e63d689113d29cb7253a5c282967Alan Cox control = priv->line_control; 572335f8514f200e63d689113d29cb7253a5c282967Alan Cox spin_unlock_irqrestore(&priv->lock, flags); 573f45d0a5aa593cdf48a37489fc61c145e16964288Johan Hovold pl2303_set_control_lines(port, control); 574335f8514f200e63d689113d29cb7253a5c282967Alan Cox} 575335f8514f200e63d689113d29cb7253a5c282967Alan Cox 576335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void pl2303_close(struct usb_serial_port *port) 577572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 5788b0127b2082601e40295045414a8318f2c8ee5a0Johan Hovold usb_serial_generic_close(port); 579572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi usb_kill_urb(port->interrupt_in_urb); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 582a509a7e478e4766114d69f12d19d644ac63e9765Alan Coxstatic int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 5858bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold struct pl2303_serial_private *spriv = usb_get_serial_data(serial); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 588e8bbd5c42b65b662756d67290a5c4dcda1abc596Greg Kroah-Hartman if (spriv->type != HX) { 5891694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->write_urb->pipe); 5901694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->read_urb->pipe); 5913e152505a57db6622deb1322c22551c046e33d16Sarah Sharp } else { 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset upstream data pipes */ 593eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(8, 0, serial); 594eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(9, 0, serial); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup termios */ 59895da310e66ee8090119596c70ca8432e57f9a97fAlan Cox if (tty) 5992d8f4447b58bba5f8cb895c07690434c02307eafJohan Hovold pl2303_set_termios(tty, port, NULL); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 603372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&port->dev, "%s - failed submitting interrupt urb," 604441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " error %d\n", __func__, result); 605db6e9186c90188edea20aaa5161ea073440cc2a1Johan Hovold return result; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 607d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold 608f5230a53c1d551811b077ccad219105786da1becJohan Hovold result = usb_serial_generic_open(tty, port); 609d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold if (result) { 610d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold usb_kill_urb(port->interrupt_in_urb); 611d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold return result; 612d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold } 613d4691c3fa3d371835b1eacb39066ab113c4b9d8cJohan Hovold 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61720b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int pl2303_tiocmset(struct tty_struct *tty, 618372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int set, unsigned int clear) 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 62095da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 6246f1efd6c5aa63ddcfe1ffc60ade716f5421766f4Johan Hovold int ret; 6256fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 626372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_RTS; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_DTR; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_RTS; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_DTR; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 636372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6385ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold ret = pl2303_set_control_lines(port, control); 6395ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold if (ret) 6405ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold return usb_translate_errors(ret); 6416f1efd6c5aa63ddcfe1ffc60ade716f5421766f4Johan Hovold 6425ddbb26b8b571231cace9f013b2d0ae66229b316Johan Hovold return 0; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64560b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int pl2303_tiocmget(struct tty_struct *tty) 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 64795da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mcr; 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int result; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 654372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mcr = priv->line_control; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 657372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_CTS) ? TIOCM_CTS : 0) 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DSR) ? TIOCM_DSR : 0) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_RING) ? TIOCM_RI : 0) 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DCD) ? TIOCM_CD : 0); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 666d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - result = %x\n", __func__, result); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic int pl2303_carrier_raised(struct usb_serial_port *port) 672335f8514f200e63d689113d29cb7253a5c282967Alan Cox{ 673335f8514f200e63d689113d29cb7253a5c282967Alan Cox struct pl2303_private *priv = usb_get_serial_port_data(port); 674335f8514f200e63d689113d29cb7253a5c282967Alan Cox if (priv->line_status & UART_DCD) 675335f8514f200e63d689113d29cb7253a5c282967Alan Cox return 1; 676335f8514f200e63d689113d29cb7253a5c282967Alan Cox return 0; 677335f8514f200e63d689113d29cb7253a5c282967Alan Cox} 678335f8514f200e63d689113d29cb7253a5c282967Alan Cox 679824d11bef5540062d17380c65ee52d4b2948ca84Johan Hovoldstatic int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg) 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 681824d11bef5540062d17380c65ee52d4b2948ca84Johan Hovold struct usb_serial_port *port = tty->driver_data; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int prevstatus; 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int changed; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 688372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = priv->line_status; 690372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 6936d0cad657a133818038683120fff9c5c5f8dc751Johan Hovold interruptible_sleep_on(&port->port.delta_msr_wait); 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* see if a signal did it */ 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ERESTARTSYS; 697372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 69840509ca982c00c4b70fc00be887509feca0bff15Johan Hovold if (port->serial->disconnected) 69940509ca982c00c4b70fc00be887509feca0bff15Johan Hovold return -EIO; 70040509ca982c00c4b70fc00be887509feca0bff15Johan Hovold 701372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 703372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 704372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 7053a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox changed = prevstatus ^ status; 706372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((arg & TIOCM_RNG) && (changed & UART_RING)) || 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_DSR) && (changed & UART_DSR)) || 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_CD) && (changed & UART_DCD)) || 7103a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox ((arg & TIOCM_CTS) && (changed & UART_CTS))) { 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = status; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71900a0d0d65b61241a718d0aee96f46b9a2d93bf26Alan Coxstatic int pl2303_ioctl(struct tty_struct *tty, 720372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int cmd, unsigned long arg) 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 72267b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas struct serial_struct ser; 72395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 724d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman 725d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s cmd = 0x%04x\n", __func__, cmd); 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 72867b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas case TIOCGSERIAL: 72967b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas memset(&ser, 0, sizeof ser); 73067b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.type = PORT_16654; 731e5b1e2062e0535e8ffef79bb34d857e21380d101Greg Kroah-Hartman ser.line = port->minor; 7321143832eca8f1d64da7d85642c956ae9d25c69e1Greg Kroah-Hartman ser.port = port->port_number; 73367b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas ser.baud_base = 460800; 73467b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas 73567b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas if (copy_to_user((void __user *)arg, &ser, sizeof ser)) 73667b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas return -EFAULT; 73767b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas 73867b9946dd07eeef8188e4cab816d2c370bcaa7b2John Tsiombikas return 0; 7393a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox default: 740d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); 7413a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox break; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74695da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void pl2303_break_ctl(struct tty_struct *tty, int break_state) 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 74895da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 state; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (break_state == 0) 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_OFF; 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_ON; 757d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - turning break %s\n", __func__, 7583a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox state == BREAK_OFF ? "off" : "on"); 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 760372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 761372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 762372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, NULL, 0, 100); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 764d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_err(&port->dev, "error sending break = %d\n", result); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 76797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitnerstatic void pl2303_update_line_status(struct usb_serial_port *port, 76897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned char *data, 76997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length) 77097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner{ 77197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 77297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner struct pl2303_private *priv = usb_get_serial_port_data(port); 773d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek struct tty_struct *tty; 77497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned long flags; 77597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner u8 status_idx = UART_STATE; 77695f209f93663103db2a8fb989e226ac68a98b036Horst Schirmeier u8 length = UART_STATE + 1; 777d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek u8 prev_line_status; 7789c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi u16 idv, idp; 77997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 7809c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); 7819c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp = le16_to_cpu(port->serial->dev->descriptor.idProduct); 7829c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7839c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7849c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idv == SIEMENS_VENDOR_ID) { 7859c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idp == SIEMENS_PRODUCT_ID_X65 || 7869c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_SX1 || 7879c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_X75) { 7889c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 7899c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi length = 1; 7909c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi status_idx = 0; 7919c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi } 79297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner } 79397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 79497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner if (actual_length < length) 795a009b75aa0ed55f0bc473c8a3b3e872cbca807ecLuiz Fernando N. Capitulino return; 79697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 7973a0f43e9deffd9619ac34e3b6b9ba7089aa1e511Alan Cox /* Save off the uart status for others to look at */ 79897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_lock_irqsave(&priv->lock, flags); 799d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek prev_line_status = priv->line_status; 80097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner priv->line_status = data[status_idx]; 80197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_unlock_irqrestore(&priv->lock, flags); 802430eb0d27c1b36c5191c16b2472b26137673a8d4Jason Wessel if (priv->line_status & UART_BREAK_ERROR) 803430eb0d27c1b36c5191c16b2472b26137673a8d4Jason Wessel usb_serial_handle_break(port); 8046d0cad657a133818038683120fff9c5c5f8dc751Johan Hovold wake_up_interruptible(&port->port.delta_msr_wait); 805d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek 806d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek tty = tty_port_tty_get(&port->port); 807d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek if (!tty) 808d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek return; 809d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek if ((priv->line_status ^ prev_line_status) & UART_DCD) 810d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek usb_serial_handle_dcd_change(port, tty, 811d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek priv->line_status & UART_DCD); 812d14fc1a74e846d7851f24fc9519fe87dc12a1231Libor Pechacek tty_kref_put(tty); 81397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner} 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8157d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void pl2303_read_int_callback(struct urb *urb) 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 817cdc97792289179974af6dda781c855696358d307Ming Lei struct usb_serial_port *port = urb->context; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *data = urb->transfer_buffer; 81997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length = urb->actual_length; 820461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int status = urb->status; 821461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int retval; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 823461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman switch (status) { 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 831d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n", 832d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman __func__, status); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 835d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n", 836d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman __func__, status); 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 84059d33f2fc2d63796296b1b76143e039d6e7cf532Greg Kroah-Hartman usb_serial_debug_data(&port->dev, __func__, 841372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi urb->actual_length, urb->transfer_buffer); 842372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 84397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner pl2303_update_line_status(port, data, actual_length); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 846461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman retval = usb_submit_urb(urb, GFP_ATOMIC); 847461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (retval) 848d8789b2b90aeb53ce59ac232d2ff0d8357d53893Greg Kroah-Hartman dev_err(&port->dev, 849372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi "%s - usb_submit_urb failed with result %d\n", 850441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, retval); 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 853f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovoldstatic void pl2303_process_read_urb(struct urb *urb) 854d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox{ 855f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold struct usb_serial_port *port = urb->context; 856f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold struct pl2303_private *priv = usb_get_serial_port_data(port); 857d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox unsigned char *data = urb->transfer_buffer; 858d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox char tty_flag = TTY_NORMAL; 859f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold unsigned long flags; 860f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold u8 line_status; 861f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold int i; 862f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 863f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold /* update line status */ 864f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold spin_lock_irqsave(&priv->lock, flags); 865f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold line_status = priv->line_status; 866f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold priv->line_status &= ~UART_STATE_TRANSIENT_MASK; 867f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold spin_unlock_irqrestore(&priv->lock, flags); 8686d0cad657a133818038683120fff9c5c5f8dc751Johan Hovold wake_up_interruptible(&port->port.delta_msr_wait); 869f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 870f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold if (!urb->actual_length) 871f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold return; 872f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold 873d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* break takes precedence over parity, */ 874d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* which takes precedence over framing errors */ 875d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox if (line_status & UART_BREAK_ERROR) 876d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_BREAK; 877d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox else if (line_status & UART_PARITY_ERROR) 878d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_PARITY; 879d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox else if (line_status & UART_FRAME_ERROR) 880d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox tty_flag = TTY_FRAME; 881d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox 8823ba19fe31b726371b45f91a8de9341f5625e75e4Johan Hovold if (tty_flag != TTY_NORMAL) 8833ba19fe31b726371b45f91a8de9341f5625e75e4Johan Hovold dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, 8843ba19fe31b726371b45f91a8de9341f5625e75e4Johan Hovold tty_flag); 885d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox /* overrun is special, not associated with a char */ 886d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox if (line_status & UART_OVERRUN_ERROR) 88792a19f9cec9a80ad93c06e115822deb729e2c6adJiri Slaby tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); 8889388e2e71a51fab0aa2309bbb45e8a23d89a95a9Johan Hovold 889d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold if (port->port.console && port->sysrq) { 890d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6Alan Cox for (i = 0; i < urb->actual_length; ++i) 8916ee9f4b4affe751d313d2538999aeec134d413a6Dmitry Torokhov if (!usb_serial_handle_sysrq_char(port, data[i])) 89292a19f9cec9a80ad93c06e115822deb729e2c6adJiri Slaby tty_insert_flip_char(&port->port, data[i], 89392a19f9cec9a80ad93c06e115822deb729e2c6adJiri Slaby tty_flag); 894d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold } else { 8952f69335710884ae6112fc8196ebe29b5cda7b79bJiri Slaby tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, 896d45cc8df7f59eb4db28408076ce979cd5e18f2b7Johan Hovold urb->actual_length); 8979388e2e71a51fab0aa2309bbb45e8a23d89a95a9Johan Hovold } 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8992e124b4a390ca85325fae75764bef92f0547fa25Jiri Slaby tty_flip_buffer_push(&port->port); 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 902572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* All of the device info needed for the PL2303 SIO serial converter */ 903572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic struct usb_serial_driver pl2303_device = { 904572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .driver = { 905572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .owner = THIS_MODULE, 906572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .name = "pl2303", 907572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi }, 908572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .id_table = id_table, 909572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .num_ports = 1, 9107919c2fd9e07276403b9a4d9ae52305e0d70f923Johan Hovold .bulk_in_size = 256, 9113efeaff6298290b36499532f0b4c87aa4bae8aefJohan Hovold .bulk_out_size = 256, 912572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .open = pl2303_open, 913572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .close = pl2303_close, 914335f8514f200e63d689113d29cb7253a5c282967Alan Cox .dtr_rts = pl2303_dtr_rts, 915335f8514f200e63d689113d29cb7253a5c282967Alan Cox .carrier_raised = pl2303_carrier_raised, 916572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .ioctl = pl2303_ioctl, 917572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .break_ctl = pl2303_break_ctl, 918572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .set_termios = pl2303_set_termios, 919572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmget = pl2303_tiocmget, 920572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmset = pl2303_tiocmset, 921824d11bef5540062d17380c65ee52d4b2948ca84Johan Hovold .tiocmiwait = pl2303_tiocmiwait, 922f08e07ac8b87b1a4b8ff88a061195e99282dfbbdJohan Hovold .process_read_urb = pl2303_process_read_urb, 923572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .read_int_callback = pl2303_read_int_callback, 924572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .attach = pl2303_startup, 925f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern .release = pl2303_release, 9268bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold .port_probe = pl2303_port_probe, 9278bf769eb5f6efc33f95088850f33fcc05d28b508Johan Hovold .port_remove = pl2303_port_remove, 928572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi}; 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 930f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Sternstatic struct usb_serial_driver * const serial_drivers[] = { 931f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Stern &pl2303_device, NULL 932f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Stern}; 933f667ddad41e303ebc2c6d5bf3105dffe2fbdd717Alan Stern 93468e24113457e437b1576670f2419b77ed0531e9eGreg Kroah-Hartmanmodule_usb_serial_driver(serial_drivers, id_table); 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRIVER_DESC); 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 938