pl2303.c revision cdc97792289179974af6dda781c855696358d307
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 * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See Documentation/usb/usb-serial.txt for more information on using this driver 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/usb.h> 30a969888ce91673c7f4b86520d851a6f0d5a5fa7dGreg Kroah-Hartman#include <linux/usb/serial.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pl2303.h" 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version Information 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PL2303_CLOSING_WAIT (30*HZ) 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PL2303_BUF_SIZE 1024 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PL2303_TMP_BUF_SIZE 1024 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pl2303_buf { 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int buf_size; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf_buf; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf_get; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf_put; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_device_id id_table [] = { 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, 553d861494729c70d9ebeb7d93caa107897925c355Peter Moulder { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, 58b483b6aaa56f0db72fa50e85b6499a32d82009bfMax Arnold { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, 608a28dea3accda319d51a1bf4d3e280771d946f78Masakazu Mokuno { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, 6658381719845d9ee19a321c2eb69cfa9b7886be9aWang Jun { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, 6957833ea6b95a3995149f1f6d1a8d8862ab7a0ba2Akira Tsukamoto { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 76a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 78a8310f3b8b713e52d77c56d4b8865685ee40d02aLuiz Fernando Capitulino { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, 79e7beb667842ad0f6ec95a22e7c88e71dfbd60649Andreas Loibl { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, 80acbb36f116243bed515357264ecbb6ff9c6d2a5bPeter Favrholdt { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, 81c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, 82c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, 836cceb05f8df6e28ab90f44bdeba50d33928cdee5Denis MONTERRAT { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, 84c6c27721a42b991965bb792d5c196b8331d008d5Christian Lindner { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, 85491b04ce1c9adfa0cd73f095086f3c37da81b667Dick Streefland { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, 863b92847425a98d26ad9d2b8682d3ce6020c90752Matthew Meno { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, 87b7aa94b682dc6b6dcdc01d36f8e65cef5aae81e2Kim Oldfield { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, 888fd801339350b63cbb90730ff8b2be349fb3dc67Johannes Steingraeber { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, 892d94b981c7fcb0fba4aa3442cd180066dbedbbc8YOSHIFUJI Hideaki { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, 909e3285dba5cac12d656da66fd7d420ff1bc0ecc0Magnus Damm { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, 91002e8f2c80c6be76bb312940bc278fc10b2b2487Piotr Roszatycki { USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) }, 92cc311ee7d29d96f0bf15599f4456012d6f5ea23cDamien Stuart { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 96372db8a780f63368c6960a167b7a19aad776d704Thiago GalesiMODULE_DEVICE_TABLE(usb, id_table); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_driver pl2303_driver = { 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "pl2303", 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = usb_serial_probe, 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .disconnect = usb_serial_disconnect, 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = id_table, 103fcf9e55e066d12c18add7c8a292bf879b45b1d55Sarah Sharp .suspend = usb_serial_suspend, 104fcf9e55e066d12c18add7c8a292bf879b45b1d55Sarah Sharp .resume = usb_serial_resume, 105ba9dc657af86d05d2971633e57d1f6f94ed60472Greg Kroah-Hartman .no_dynamic_id = 1, 106fcf9e55e066d12c18add7c8a292bf879b45b1d55Sarah Sharp .supports_autosuspend = 1, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST_TYPE 0x21 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_LINE_REQUEST 0x20 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST_TYPE 0x21 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_CONTROL_REQUEST 0x22 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_DTR 0x01 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONTROL_RTS 0x02 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_REQUEST_TYPE 0x21 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_REQUEST 0x23 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_ON 0xffff 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAK_OFF 0x0000 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST_TYPE 0xa1 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GET_LINE_REQUEST 0x21 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST_TYPE 0x40 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_WRITE_REQUEST 0x01 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST_TYPE 0xc0 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VENDOR_READ_REQUEST 0x01 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE 0x08 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_STATE_TRANSIENT_MASK 0x74 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DCD 0x01 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_DSR 0x02 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_BREAK_ERROR 0x04 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_RING 0x08 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_FRAME_ERROR 0x10 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_PARITY_ERROR 0x20 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_OVERRUN_ERROR 0x40 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UART_CTS 0x80 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum pl2303_type { 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_0, /* don't know the difference between type 0 and */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_1, /* type 1, until someone from prolific tells us... */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HX, /* HX version of the pl2303 chip */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pl2303_private { 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_buf *buf; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int write_urb_in_use; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_queue_head_t delta_msr_wait; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_control; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 line_status; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 termios_initialized; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 160572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* 161572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * pl2303_buf_alloc 162572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 163572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Allocate a circular buffer and all associated memory. 164572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi */ 165572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic struct pl2303_buf *pl2303_buf_alloc(unsigned int size) 166572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 167572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi struct pl2303_buf *pb; 168572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 169572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (size == 0) 170572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return NULL; 171572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 1725cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); 173572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb == NULL) 174572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return NULL; 175572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 176572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_buf = kmalloc(size, GFP_KERNEL); 177572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb->buf_buf == NULL) { 178572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi kfree(pb); 179572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return NULL; 180572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } 181572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 182572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_size = size; 183572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_get = pb->buf_put = pb->buf_buf; 184572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 185572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return pb; 186572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 187572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 188572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* 189572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * pl2303_buf_free 190572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 191572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Free the buffer and all associated memory. 192572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi */ 193572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic void pl2303_buf_free(struct pl2303_buf *pb) 194572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 195572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb) { 196572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi kfree(pb->buf_buf); 197572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi kfree(pb); 198572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } 199572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 200572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 201572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* 202572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * pl2303_buf_clear 203572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 204572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Clear out all data in the circular buffer. 205572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi */ 206572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic void pl2303_buf_clear(struct pl2303_buf *pb) 207572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 208572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb != NULL) 209572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_get = pb->buf_put; 210572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* equivalent to a get of all data available */ 211572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 212572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 213572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* 214572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * pl2303_buf_data_avail 215572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 216572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Return the number of bytes of data available in the circular 217572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * buffer. 218572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi */ 219572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) 220572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 221572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb == NULL) 222572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return 0; 223572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 224572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); 225572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 226572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 227572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* 228572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * pl2303_buf_space_avail 229572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 230572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Return the number of bytes of space available in the circular 231572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * buffer. 232572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi */ 233572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) 234572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 235572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb == NULL) 236572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return 0; 237572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 238572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); 239572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 240572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 241572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* 242572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * pl2303_buf_put 243572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 244572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Copy data data from a user buffer and put it into the circular buffer. 245572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Restrict to the amount of space available. 246572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 247572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Return the number of bytes copied. 248572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi */ 249572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, 250572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi unsigned int count) 251572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 252572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi unsigned int len; 253572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 254572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb == NULL) 255572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return 0; 256572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 257572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi len = pl2303_buf_space_avail(pb); 258572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count > len) 259572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi count = len; 260572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 261572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count == 0) 262572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return 0; 263572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 264572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi len = pb->buf_buf + pb->buf_size - pb->buf_put; 265572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count > len) { 266572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi memcpy(pb->buf_put, buf, len); 267572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi memcpy(pb->buf_buf, buf+len, count - len); 268572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_put = pb->buf_buf + count - len; 269572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } else { 270572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi memcpy(pb->buf_put, buf, count); 271572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count < len) 272572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_put += count; 273572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi else /* count == len */ 274572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_put = pb->buf_buf; 275572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } 276572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 277572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return count; 278572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 279572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 280572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* 281572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * pl2303_buf_get 282572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 283572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Get data from the circular buffer and copy to the given buffer. 284572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Restrict to the amount of data available. 285572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * 286572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi * Return the number of bytes copied. 287572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi */ 288572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, 289572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi unsigned int count) 290572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 291572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi unsigned int len; 292572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 293572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pb == NULL) 294572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return 0; 295572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 296572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi len = pl2303_buf_data_avail(pb); 297572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count > len) 298572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi count = len; 299572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 300572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count == 0) 301572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return 0; 302572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 303572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi len = pb->buf_buf + pb->buf_size - pb->buf_get; 304572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count > len) { 305572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi memcpy(buf, pb->buf_get, len); 306572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi memcpy(buf+len, pb->buf_buf, count - len); 307572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_get = pb->buf_buf + count - len; 308572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } else { 309572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi memcpy(buf, pb->buf_get, count); 310572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (count < len) 311572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_get += count; 312572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi else /* count == len */ 313572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pb->buf_get = pb->buf_buf; 314572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } 315572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 316572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return count; 317572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 319eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_read(__u16 value, __u16 index, 320eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial, unsigned char *buf) 321eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 322eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 323eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, 324eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, buf, 1, 100); 325eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE, 326eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_READ_REQUEST, value, index, res, buf[0]); 327eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 328eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 329eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 330eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharpstatic int pl2303_vendor_write(__u16 value, __u16 index, 331eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp struct usb_serial *serial) 332eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp{ 333eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 334eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, 335eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp value, index, NULL, 0, 100); 336eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE, 337eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp VENDOR_WRITE_REQUEST, value, index, res); 338eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp return res; 339eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp} 340eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp 341372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_startup(struct usb_serial *serial) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pl2303_type type = type_0; 3453e152505a57db6622deb1322c22551c046e33d16Sarah Sharp unsigned char *buf; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3483e152505a57db6622deb1322c22551c046e33d16Sarah Sharp buf = kmalloc(10, GFP_KERNEL); 3493e152505a57db6622deb1322c22551c046e33d16Sarah Sharp if (buf == NULL) 3503e152505a57db6622deb1322c22551c046e33d16Sarah Sharp return -ENOMEM; 3513e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serial->dev->descriptor.bDeviceClass == 0x02) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_0; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = HX; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0x00) 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (serial->dev->descriptor.bDeviceClass == 0xFF) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = type_1; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("device type: %d", type); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < serial->num_ports; ++i) { 36380b6ca48321974a6566a1c9048ba34f60420bca6Eric Sesterhenn priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!priv) 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto cleanup; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&priv->lock); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->buf == NULL) { 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto cleanup; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&priv->delta_msr_wait); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->type = type; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], priv); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3763e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 3773e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 3783e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 0, serial); 3793e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 3803e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 3813e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 3823e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0x0404, 1, serial); 3833e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8484, 0, serial, buf); 3843e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_read(0x8383, 0, serial, buf); 3853e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(0, 1, serial); 3863e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(1, 0, serial); 3873e152505a57db6622deb1322c22551c046e33d16Sarah Sharp if (type == HX) 3883e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(2, 0x44, serial); 3893e152505a57db6622deb1322c22551c046e33d16Sarah Sharp else 3903e152505a57db6622deb1322c22551c046e33d16Sarah Sharp pl2303_vendor_write(2, 0x24, serial); 3913e152505a57db6622deb1322c22551c046e33d16Sarah Sharp 3923e152505a57db6622deb1322c22551c046e33d16Sarah Sharp kfree(buf); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscleanup: 3963e152505a57db6622deb1322c22551c046e33d16Sarah Sharp kfree(buf); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (--i; i>=0; --i) { 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = usb_get_serial_port_data(serial->port[i]); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_buf_free(priv->buf); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], NULL); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 406372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int set_control_lines(struct usb_device *dev, u8 value) 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 410372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 411372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, 412372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi value, 0, NULL, 0, 100); 413441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - value = %d, retval = %d", __func__, value, retval); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pl2303_send(struct usb_serial_port *port) 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count, result; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 423441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->write_urb_in_use) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, 433372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi port->bulk_out_size); 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) { 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 1; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 444441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &port->dev, __func__, count, 445372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi port->write_urb->transfer_buffer); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->transfer_buffer_length = count; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->dev = port->serial->dev; 449372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_submit_urb(port->write_urb, GFP_ATOMIC); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 451372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&port->dev, "%s - failed submitting write urb," 452441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " error %d\n", __func__, result); 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 0; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // TODO: reschedule pl2303_send 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 457cf2c7481d2ff7f0c266de873b2fe93883e9782f9Pete Zaitcev usb_serial_port_softint(port); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 460572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic int pl2303_write(struct usb_serial_port *port, const unsigned char *buf, 461572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi int count) 462572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 463572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi struct pl2303_private *priv = usb_get_serial_port_data(port); 464572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi unsigned long flags; 465572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 466441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d, %d bytes", __func__, port->number, count); 467572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 468572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (!count) 469572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return count; 470572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 471572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_lock_irqsave(&priv->lock, flags); 472572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi count = pl2303_buf_put(priv->buf, buf, count); 473572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 474572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 475572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pl2303_send(port); 476572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 477572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi return count; 478572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 479572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_write_room(struct usb_serial_port *port) 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int room = 0; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 486441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds room = pl2303_buf_space_avail(priv->buf); 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 492441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - returns %d", __func__, room); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return room; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pl2303_chars_in_buffer(struct usb_serial_port *port) 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chars = 0; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 502441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chars = pl2303_buf_data_avail(priv->buf); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 508441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - returns %d", __func__, chars); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return chars; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 512372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic void pl2303_set_termios(struct usb_serial_port *port, 513606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old_termios) 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cflag; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *buf; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int baud; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 524441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!priv->termios_initialized) { 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(port->tty->termios) = tty_std_termios; 529372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi port->tty->termios->c_cflag = B9600 | CS8 | CREAD | 530372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi HUPCL | CLOCAL; 531df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox port->tty->termios->c_ispeed = 9600; 532df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox port->tty->termios->c_ospeed = 9600; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->termios_initialized = 1; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 537bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox /* The PL2303 is reported to lose bytes if you change 538bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox serial settings even to the same values as before. Thus 539bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox we actually need to filter in this specific case */ 540bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox 541bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox if (!tty_termios_hw_change(port->tty->termios, old_termios)) 542bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox return; 543bf5e5834bffc62b50cd4a201804506eb11ef1af8Alan Cox 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cflag = port->tty->termios->c_cflag; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 546372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi buf = kzalloc(7, GFP_KERNEL); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!buf) { 548441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dev_err(&port->dev, "%s - out of memory.\n", __func__); 549a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox /* Report back no change occurred */ 550a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox *port->tty->termios = *old_termios; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 554372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 555372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 556372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 557372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, 558372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CSIZE) { 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cflag & CSIZE) { 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS5: buf[6] = 5; break; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS6: buf[6] = 6; break; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS7: buf[6] = 7; break; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CS8: buf[6] = 8; break; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 568441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - data bits = %d", __func__, buf[6]); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571e0c79f512cf469bc11fe9d53a4dcc5d0c39a3b79Alan Cox baud = tty_get_baud_rate(port->tty);; 572441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - baud = %d", __func__, baud); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (baud) { 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = baud & 0xff; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[1] = (baud >> 8) & 0xff; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[2] = (baud >> 16) & 0xff; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[3] = (baud >> 24) & 0xff; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=0 is 1 stop bits */ 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=1 is 1.5 stop bits */ 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[4]=2 is 2 stop bits */ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CSTOPB) { 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = 2; 585441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - stop bits = 2", __func__); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[4] = 0; 588441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - stop bits = 1", __func__); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARENB) { 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=0 is none parity */ 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=1 is odd parity */ 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=2 is even parity */ 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=3 is mark parity */ 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For reference buf[5]=4 is space parity */ 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & PARODD) { 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 1; 599441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = odd", __func__); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 2; 602441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = even", __func__); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[5] = 0; 606441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = none", __func__); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 609372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 610372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 611372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 612372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dbg("0x21:0x20:0:0 %d", i); 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* change control lines if we are switching to or from B0 */ 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cflag & CBAUD) == B0) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (control != priv->line_control) { 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_control_lines(serial->dev, control); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 628372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 632372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 633372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, 0, buf, 7, 100); 634372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cflag & CRTSCTS) { 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->type == HX) 639eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x61, serial); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 641eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x41, serial); 642715f9527c1c1edd1a9c7a55ab4535211279c9374t.sefzick } else { 643eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(0x0, 0x0, serial); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 645572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 646df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox /* FIXME: Need to read back resulting baud rate */ 647df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox if (baud) 648df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox tty_encode_baud_rate(port->tty, baud, baud); 649df64c47184aedf34fd2a69a4b7f68584fe982fdfAlan Cox 650572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi kfree(buf); 651572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi} 652572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 653572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic void pl2303_close(struct usb_serial_port *port, struct file *filp) 654572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi{ 655572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi struct pl2303_private *priv = usb_get_serial_port_data(port); 656572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi unsigned long flags; 657572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi unsigned int c_cflag; 658572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi int bps; 659572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi long timeout; 660572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi wait_queue_t wait; 661572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 662441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 663572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 664572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* wait for data to drain from the buffer */ 665572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_lock_irqsave(&priv->lock, flags); 666572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi timeout = PL2303_CLOSING_WAIT; 667572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi init_waitqueue_entry(&wait, current); 668572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi add_wait_queue(&port->tty->write_wait, &wait); 669572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi for (;;) { 670572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi set_current_state(TASK_INTERRUPTIBLE); 671572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (pl2303_buf_data_avail(priv->buf) == 0 || 672572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi timeout == 0 || signal_pending(current) || 6730915f490d81c1a5098b399ec6c0be45bd421ee1dOliver Neukum port->serial->disconnected) 674572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi break; 675572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 676572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi timeout = schedule_timeout(timeout); 677572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_lock_irqsave(&priv->lock, flags); 678572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } 679572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi set_current_state(TASK_RUNNING); 680572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi remove_wait_queue(&port->tty->write_wait, &wait); 681572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* clear out any remaining data in the buffer */ 682572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi pl2303_buf_clear(priv->buf); 683572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 684572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 685572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* wait for characters to drain from the device */ 686572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* (this is long enough for the entire 256 byte */ 687572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* pl2303 hardware buffer to drain with no flow */ 688572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* control for data rates of 1200 bps or more, */ 689572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* for lower rates we should really know how much */ 690572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* data is in the buffer to compute a delay */ 691572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* that is not unnecessarily long) */ 692572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi bps = tty_get_baud_rate(port->tty); 693572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (bps > 1200) 694572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi timeout = max((HZ*2560)/bps,HZ/10); 695572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi else 696572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi timeout = 2*HZ; 697572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi schedule_timeout_interruptible(timeout); 698572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 699572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* shutdown our urbs */ 700441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - shutting down urbs", __func__); 701572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi usb_kill_urb(port->write_urb); 702572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi usb_kill_urb(port->read_urb); 703572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi usb_kill_urb(port->interrupt_in_urb); 704572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi 705572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (port->tty) { 706572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi c_cflag = port->tty->termios->c_cflag; 707572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi if (c_cflag & HUPCL) { 708572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi /* drop DTR and RTS */ 709572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_lock_irqsave(&priv->lock, flags); 710572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi priv->line_control = 0; 711572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 712572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi set_control_lines(port->serial->dev, 0); 713572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } 714572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi } 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 717372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_open(struct usb_serial_port *port, struct file *filp) 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 719606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios tmp_termios; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 724441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261694899fd1af43636351aac97f415fd3c9cefb1dDariusz M if (priv->type != HX) { 7271694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->write_urb->pipe); 7281694899fd1af43636351aac97f415fd3c9cefb1dDariusz M usb_clear_halt(serial->dev, port->read_urb->pipe); 7293e152505a57db6622deb1322c22551c046e33d16Sarah Sharp } else { 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset upstream data pipes */ 731eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(8, 0, serial); 732eb44da0b3aa0105cb38d81c5747a8feae64834beSarah Sharp pl2303_vendor_write(9, 0, serial); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup termios */ 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->tty) { 737372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi pl2303_set_termios(port, &tmp_termios); 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds //FIXME: need to assert RTS and DTR if CRTSCTS off 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 742441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - submitting read urb", __func__); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->read_urb->dev = serial->dev; 744372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_submit_urb(port->read_urb, GFP_KERNEL); 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 746372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&port->dev, "%s - failed submitting read urb," 747441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " error %d\n", __func__, result); 748372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi pl2303_close(port, NULL); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPROTO; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 752441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - submitting interrupt urb", __func__); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->interrupt_in_urb->dev = serial->dev; 754372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 756372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&port->dev, "%s - failed submitting interrupt urb," 757441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " error %d\n", __func__, result); 758372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi pl2303_close(port, NULL); 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPROTO; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 764372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_tiocmset(struct usb_serial_port *port, struct file *file, 765372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int set, unsigned int clear) 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 control; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7716fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner if (!usb_get_intfdata(port->serial->interface)) 7726fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner return -ENODEV; 7736fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 774372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_RTS; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control |= CONTROL_DTR; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_RTS; 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_control &= ~CONTROL_DTR; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control = priv->line_control; 784372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 786372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi return set_control_lines(port->serial->dev, control); 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 789372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_tiocmget(struct usb_serial_port *port, struct file *file) 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mcr; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int result; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 797441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d)", __func__, port->number); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7996fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner if (!usb_get_intfdata(port->serial->interface)) 8006fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner return -ENODEV; 8016fdd8e8e33730a2abc886113bd0b6c4343f63cc9Flavio Leitner 802372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mcr = priv->line_control; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 805372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_CTS) ? TIOCM_CTS : 0) 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DSR) ? TIOCM_DSR : 0) 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_RING) ? TIOCM_RI : 0) 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((status & UART_DCD) ? TIOCM_CD : 0); 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 814441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - result = %x", __func__, result); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_modem_info(struct usb_serial_port *port, unsigned int arg) 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int prevstatus; 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status; 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int changed; 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 827372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = priv->line_status; 829372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds interruptible_sleep_on(&priv->delta_msr_wait); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* see if a signal did it */ 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ERESTARTSYS; 836372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 837372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_lock_irqsave(&priv->lock, flags); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = priv->line_status; 839372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi spin_unlock_irqrestore(&priv->lock, flags); 840372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds changed=prevstatus^status; 842372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((arg & TIOCM_RNG) && (changed & UART_RING)) || 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_DSR) && (changed & UART_DSR)) || 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_CD) && (changed & UART_DCD)) || 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) { 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prevstatus = status; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 855372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int pl2303_ioctl(struct usb_serial_port *port, struct file *file, 856372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi unsigned int cmd, unsigned long arg) 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 858441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCMIWAIT: 862441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCMIWAIT", __func__, port->number); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return wait_modem_info(port, arg); 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 866441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s not supported = 0x%04x", __func__, cmd); 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 873372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic void pl2303_break_ctl(struct usb_serial_port *port, int break_state) 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial *serial = port->serial; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 state; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 879441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (break_state == 0) 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_OFF; 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = BREAK_ON; 885441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on"); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 887372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 888372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 889372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 0, NULL, 0, 100); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 891441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - error sending break = %d", __func__, result); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 894372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic void pl2303_shutdown(struct usb_serial *serial) 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv; 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 899441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < serial->num_ports; ++i) { 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = usb_get_serial_port_data(serial->port[i]); 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv) { 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_buf_free(priv->buf); 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_port_data(serial->port[i], NULL); 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 908372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi } 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitnerstatic void pl2303_update_line_status(struct usb_serial_port *port, 91297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned char *data, 91397bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length) 91497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner{ 91597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 91697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner struct pl2303_private *priv = usb_get_serial_port_data(port); 91797bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned long flags; 91897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner u8 status_idx = UART_STATE; 91995f209f93663103db2a8fb989e226ac68a98b036Horst Schirmeier u8 length = UART_STATE + 1; 9209c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi u16 idv, idp; 92197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 9229c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); 9239c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp = le16_to_cpu(port->serial->dev->descriptor.idProduct); 9249c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 9259c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 9269c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idv == SIEMENS_VENDOR_ID) { 9279c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi if (idp == SIEMENS_PRODUCT_ID_X65 || 9289c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_SX1 || 9299c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi idp == SIEMENS_PRODUCT_ID_X75) { 9309c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi 9319c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi length = 1; 9329c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi status_idx = 0; 9339c53761681497d598a31ed2f6b29b5b3480c49dbThiago Galesi } 93497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner } 93597bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 93697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner if (actual_length < length) 937a009b75aa0ed55f0bc473c8a3b3e872cbca807ecLuiz Fernando N. Capitulino return; 93897bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner 93997bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner /* Save off the uart status for others to look at */ 94097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_lock_irqsave(&priv->lock, flags); 94197bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner priv->line_status = data[status_idx]; 94297bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner spin_unlock_irqrestore(&priv->lock, flags); 943372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi wake_up_interruptible(&priv->delta_msr_wait); 94497bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner} 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9467d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void pl2303_read_int_callback(struct urb *urb) 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 948cdc97792289179974af6dda781c855696358d307Ming Lei struct usb_serial_port *port = urb->context; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *data = urb->transfer_buffer; 95097bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner unsigned int actual_length = urb->actual_length; 951461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int status = urb->status; 952461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int retval; 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 954441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d)", __func__, port->number); 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 956461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman switch (status) { 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 964441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - urb shutting down with status: %d", __func__, 965461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman status); 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 968441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - nonzero urb status received: %d", __func__, 969461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman status); 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 973441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &port->dev, __func__, 974372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi urb->actual_length, urb->transfer_buffer); 975372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 97697bb13ec5bc156352cca8af90080597e04299a73Flavio Leitner pl2303_update_line_status(port, data, actual_length); 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 979461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman retval = usb_submit_urb(urb, GFP_ATOMIC); 980461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (retval) 981372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&urb->dev->dev, 982372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi "%s - usb_submit_urb failed with result %d\n", 983441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, retval); 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9867d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void pl2303_read_bulk_callback(struct urb *urb) 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 988cdc97792289179974af6dda781c855696358d307Ming Lei struct usb_serial_port *port = urb->context; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tty_struct *tty; 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *data = urb->transfer_buffer; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 995461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int status = urb->status; 996461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman u8 line_status; 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char tty_flag; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 999441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (status) { 1002441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - urb status = %d", __func__, status); 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!port->open_count) { 1004441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port is closed, exiting.", __func__); 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1007461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (status == -EPROTO) { 1008372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi /* PL2303 mysteriously fails with -EPROTO reschedule 1009372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi * the read */ 1010372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dbg("%s - caught -EPROTO, resubmitting the urb", 1011441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__); 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->dev = port->serial->dev; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb(urb, GFP_ATOMIC); 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 1015372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&urb->dev->dev, "%s - failed" 1016372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi " resubmitting read urb, error %d\n", 1017441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, result); 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1020441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - unable to handle the error, exiting.", __func__); 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1024441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &port->dev, __func__, 1025372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi urb->actual_length, data); 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get tty_flag from status */ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_NORMAL; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 1031461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman line_status = priv->line_status; 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->line_status &= ~UART_STATE_TRANSIENT_MASK; 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 1034372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi wake_up_interruptible(&priv->delta_msr_wait); 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* break takes precedence over parity, */ 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* which takes precedence over framing errors */ 1038461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (line_status & UART_BREAK_ERROR ) 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_BREAK; 1040461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman else if (line_status & UART_PARITY_ERROR) 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_PARITY; 1042461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman else if (line_status & UART_FRAME_ERROR) 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_flag = TTY_FRAME; 1044441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - tty_flag = %d", __func__, tty_flag); 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty = port->tty; 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty && urb->actual_length) { 104833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox tty_buffer_request_room(tty, urb->actual_length + 1); 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* overrun is special, not associated with a char */ 1050461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman if (line_status & UART_OVERRUN_ERROR) 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_insert_flip_char(tty, 0, TTY_OVERRUN); 105233f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox for (i = 0; i < urb->actual_length; ++i) 1053372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi tty_insert_flip_char(tty, data[i], tty_flag); 1054372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi tty_flip_buffer_push(tty); 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Schedule the next read _if_ we are still open */ 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->open_count) { 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->dev = port->serial->dev; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb(urb, GFP_ATOMIC); 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 1062372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&urb->dev->dev, "%s - failed resubmitting" 1063441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " read urb, error %d\n", __func__, result); 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10697d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void pl2303_write_bulk_callback(struct urb *urb) 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1071cdc97792289179974af6dda781c855696358d307Ming Lei struct usb_serial_port *port = urb->context; 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pl2303_private *priv = usb_get_serial_port_data(port); 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 1074461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman int status = urb->status; 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1076441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1078461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman switch (status) { 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 1086441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - urb shutting down with status: %d", __func__, 1087461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman status); 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 0; 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* error in the urb, so we have to resubmit it */ 1092441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - Overflow in write", __func__); 1093441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - nonzero write bulk status received: %d", __func__, 1094461d696aeeae294ad22dfcaae462d1757f955778Greg Kroah-Hartman status); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->transfer_buffer_length = 1; 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->write_urb->dev = port->serial->dev; 1097372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi result = usb_submit_urb(port->write_urb, GFP_ATOMIC); 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 1099372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi dev_err(&urb->dev->dev, "%s - failed resubmitting write" 1100441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison " urb, error %d\n", __func__, result); 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->write_urb_in_use = 0; 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* send any buffered data */ 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pl2303_send(port); 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi/* All of the device info needed for the PL2303 SIO serial converter */ 1112572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesistatic struct usb_serial_driver pl2303_device = { 1113572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .driver = { 1114572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .owner = THIS_MODULE, 1115572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .name = "pl2303", 1116572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi }, 1117572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .id_table = id_table, 1118d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .usb_driver = &pl2303_driver, 1119572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .num_ports = 1, 1120572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .open = pl2303_open, 1121572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .close = pl2303_close, 1122572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .write = pl2303_write, 1123572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .ioctl = pl2303_ioctl, 1124572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .break_ctl = pl2303_break_ctl, 1125572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .set_termios = pl2303_set_termios, 1126572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmget = pl2303_tiocmget, 1127572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .tiocmset = pl2303_tiocmset, 1128572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .read_bulk_callback = pl2303_read_bulk_callback, 1129572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .read_int_callback = pl2303_read_int_callback, 1130572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .write_bulk_callback = pl2303_write_bulk_callback, 1131572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .write_room = pl2303_write_room, 1132572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .chars_in_buffer = pl2303_chars_in_buffer, 1133572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .attach = pl2303_startup, 1134572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi .shutdown = pl2303_shutdown, 1135572d3138eb0cf17a2bf36944cc1d2c753578862eThiago Galesi}; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1137372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic int __init pl2303_init(void) 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 1140372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_serial_register(&pl2303_device); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_usb_serial_register; 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_register(&pl2303_driver); 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed_usb_register; 114717a882fc0c91477b2582a6dfd4ca93ae7eb58cd3Greg Kroah-Hartman info(DRIVER_DESC); 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed_usb_register: 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_serial_deregister(&pl2303_device); 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed_usb_serial_register: 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1155372db8a780f63368c6960a167b7a19aad776d704Thiago Galesistatic void __exit pl2303_exit(void) 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1157372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi usb_deregister(&pl2303_driver); 1158372db8a780f63368c6960a167b7a19aad776d704Thiago Galesi usb_serial_deregister(&pl2303_device); 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(pl2303_init); 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(pl2303_exit); 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRIVER_DESC); 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, bool, S_IRUGO | S_IWUSR); 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug enabled or not"); 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1170