/*
* Prolific PL2303 USB to serial adaptor driver
*
- * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2003 IBM Corp.
*
* Original driver for 2.2.x by anonymous
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-
-#ifdef CONFIG_USB_SERIAL_DEBUG
- static int debug = 1;
-#else
- static int debug;
-#endif
-
#include "usb-serial.h"
#include "pl2303.h"
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.10"
+#define DRIVER_VERSION "v0.11"
#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
-
+static int debug;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
{ USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
{ USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
{ USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
+ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
{ } /* Terminating entry */
};
.shutdown = pl2303_shutdown,
};
+enum pl2303_type {
+ type_0, /* don't know the difference between type 0 and */
+ type_1, /* type 1, until someone from prolific tells us... */
+ HX, /* HX version of the pl2303 chip */
+};
+
struct pl2303_private {
spinlock_t lock;
wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
u8 termios_initialized;
+ enum pl2303_type type;
};
static int pl2303_startup (struct usb_serial *serial)
{
struct pl2303_private *priv;
+ enum pl2303_type type = type_0;
int i;
+ if (serial->dev->descriptor.bDeviceClass == 0x02)
+ type = type_0;
+ else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
+ type = HX;
+ else if (serial->dev->descriptor.bDeviceClass == 0x00)
+ type = type_1;
+ else if (serial->dev->descriptor.bDeviceClass == 0xFF)
+ type = type_1;
+ dbg("device type: %d", type);
+
for (i = 0; i < serial->num_ports; ++i) {
priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL);
if (!priv)
memset (priv, 0x00, sizeof (struct pl2303_private));
spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->delta_msr_wait);
+ priv->type = type;
usb_set_serial_port_data(serial->port[i], priv);
}
return 0;
memcpy (port->write_urb->transfer_buffer, buf, count);
}
- usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
port->write_urb->transfer_buffer_length = count;
port->write_urb->dev = port->serial->dev;
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
if (cflag & CRTSCTS) {
- i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
- VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
- 0x0, 0x41, NULL, 0, 100);
- dbg ("0x40:0x1:0x0:0x41 %d", i);
+ __u16 index;
+ if (priv->type == HX)
+ index = 0x61;
+ else
+ index = 0x41;
+ i = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ VENDOR_WRITE_REQUEST,
+ VENDOR_WRITE_REQUEST_TYPE,
+ 0x0, index, NULL, 0, 100);
+ dbg ("0x40:0x1:0x0:0x%x %d", index, i);
}
kfree (buf);
-}
-
+}
static int pl2303_open (struct usb_serial_port *port, struct file *filp)
{
struct termios tmp_termios;
struct usb_serial *serial = port->serial;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned char *buf;
int result;
- if (port_paranoia_check (port, __FUNCTION__))
- return -ENODEV;
-
dbg("%s - port %d", __FUNCTION__, port->number);
usb_clear_halt(serial->dev, port->write_urb->pipe);
SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
+ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
+ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
+
+ if (priv->type == HX) {
+ /* HX chip */
+ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
+ /* reset upstream data pipes */
+ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0);
+ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0);
+ } else {
+ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24);
+ }
kfree(buf);
static void pl2303_close (struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial;
struct pl2303_private *priv;
unsigned long flags;
unsigned int c_cflag;
int result;
- if (port_paranoia_check (port, __FUNCTION__))
- return;
- serial = get_usb_serial (port, __FUNCTION__);
- if (!serial)
- return;
-
dbg("%s - port %d", __FUNCTION__, port->number);
/* shutdown our urbs */
state = BREAK_OFF;
else
state = BREAK_ON;
- dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__);
+ dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
- struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
goto exit;
}
- if (!serial) {
- return;
- }
- usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
if (urb->actual_length < UART_STATE)
goto exit;
static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
- struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct pl2303_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
u8 status;
char tty_flag;
- if (port_paranoia_check (port, __FUNCTION__))
- return;
-
dbg("%s - port %d", __FUNCTION__, port->number);
- if (!serial) {
- dbg("%s - bad serial pointer, exiting", __FUNCTION__);
- return;
- }
-
if (urb->status) {
dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
if (!port->open_count) {
/* PL2303 mysteriously fails with -EPROTO reschedule the read */
dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
urb->status = 0;
- urb->dev = serial->dev;
+ urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
return;
}
- usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
/* get tty_flag from status */
tty_flag = TTY_NORMAL;
/* Schedule the next read _if_ we are still open */
if (port->open_count) {
- urb->dev = serial->dev;
+ urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
int result;
- if (port_paranoia_check (port, __FUNCTION__))
- return;
-
dbg("%s - port %d", __FUNCTION__, port->number);
if (urb->status) {
/* error in the urb, so we have to resubmit it */
- if (serial_paranoia_check (port->serial, __FUNCTION__)) {
- return;
- }
dbg("%s - Overflow in write", __FUNCTION__);
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
port->write_urb->transfer_buffer_length = 1;
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-MODULE_PARM(debug, "i");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");