X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fvisor.c;h=377a18479dead7a27d4a200362d8e91005862f0f;hb=d939d46ba7caa14e960be18e18f5c07be8806d7a;hp=37e0dae944e9f3fbcd6c4d3a01d8c0a98df283f9;hpb=86090fcac5e27b630656fe3d963a6b80e26dac44;p=linux-2.6.git diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 37e0dae94..377a18479 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -2,7 +2,7 @@ * USB HandSpring Visor, Palm m50x, and Sony Clie driver * (supports all of the Palm OS USB devices) * - * Copyright (C) 1999 - 2003 + * Copyright (C) 1999 - 2004 * Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify @@ -151,6 +151,7 @@ #include #include #include +#include #include #include #include @@ -194,8 +195,8 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id); /* Parameters that may be passed into the module. */ -static int vendor = -1; -static int product = -1; +static __u16 vendor; +static __u16 product; static struct usb_device_id id_table [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID), @@ -222,6 +223,8 @@ static struct usb_device_id id_table [] = { .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID), @@ -273,6 +276,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, @@ -393,9 +397,6 @@ static int visor_open (struct usb_serial_port *port, struct file *filp) struct usb_serial *serial = port->serial; int result = 0; - if (port_paranoia_check (port, __FUNCTION__)) - return -ENODEV; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->read_urb) { @@ -443,18 +444,10 @@ exit: static void visor_close (struct usb_serial_port *port, struct file * filp) { - struct usb_serial *serial; unsigned char *transfer_buffer; - if (port_paranoia_check (port, __FUNCTION__)) - return; - dbg("%s - port %d", __FUNCTION__, port->number); - serial = get_usb_serial (port, __FUNCTION__); - if (!serial) - return; - /* shutdown our urbs */ usb_unlink_urb (port->read_urb); if (port->interrupt_in_urb) @@ -463,8 +456,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) /* Try to send shutdown message, if the device is gone, this will just fail. */ transfer_buffer = kmalloc (0x12, GFP_KERNEL); if (transfer_buffer) { - usb_control_msg (serial->dev, - usb_rcvctrlpipe(serial->dev, 0), + usb_control_msg (port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), VISOR_CLOSE_NOTIFICATION, 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); @@ -568,9 +561,6 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree (urb->transfer_buffer); - if (port_paranoia_check (port, __FUNCTION__)) - return; - dbg("%s - port %d", __FUNCTION__, port->number); if (urb->status) @@ -584,22 +574,13 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) static void visor_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 tty_struct *tty; unsigned char *data = urb->transfer_buffer; int i; int result; - 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 - nonzero read bulk status received: %d", __FUNCTION__, urb->status); return; @@ -622,9 +603,9 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs) bytes_in += urb->actual_length; /* Continue trying to always read */ - usb_fill_bulk_urb (port->read_urb, serial->dev, - usb_rcvbulkpipe (serial->dev, - port->bulk_in_endpointAddress), + usb_fill_bulk_urb (port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, visor_read_bulk_callback, port); @@ -699,7 +680,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i char *string; int retval = 0; int i; - int num_ports; + int num_ports = 0; dbg("%s", __FUNCTION__); @@ -721,41 +702,50 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i __FUNCTION__, retval); goto exit; } - - connection_info = (struct visor_connection_info *)transfer_buffer; - - le16_to_cpus(&connection_info->num_ports); - num_ports = connection_info->num_ports; - /* handle devices that report invalid stuff here */ - if (num_ports > 2) - num_ports = 2; - dev_info(dev, "%s: Number of ports: %d\n", serial->type->name, - connection_info->num_ports); - for (i = 0; i < num_ports; ++i) { - switch (connection_info->connections[i].port_function_id) { - case VISOR_FUNCTION_GENERIC: - string = "Generic"; - break; - case VISOR_FUNCTION_DEBUGGER: - string = "Debugger"; - break; - case VISOR_FUNCTION_HOTSYNC: - string = "HotSync"; - break; - case VISOR_FUNCTION_CONSOLE: - string = "Console"; - break; - case VISOR_FUNCTION_REMOTE_FILE_SYS: - string = "Remote File System"; - break; - default: - string = "unknown"; - break; + if (retval == sizeof(*connection_info)) { + connection_info = (struct visor_connection_info *)transfer_buffer; + + le16_to_cpus(&connection_info->num_ports); + num_ports = connection_info->num_ports; + + for (i = 0; i < num_ports; ++i) { + switch (connection_info->connections[i].port_function_id) { + case VISOR_FUNCTION_GENERIC: + string = "Generic"; + break; + case VISOR_FUNCTION_DEBUGGER: + string = "Debugger"; + break; + case VISOR_FUNCTION_HOTSYNC: + string = "HotSync"; + break; + case VISOR_FUNCTION_CONSOLE: + string = "Console"; + break; + case VISOR_FUNCTION_REMOTE_FILE_SYS: + string = "Remote File System"; + break; + default: + string = "unknown"; + break; + } + dev_info(dev, "%s: port %d, is for %s use\n", + serial->type->name, + connection_info->connections[i].port, string); } - dev_info(dev, "%s: port %d, is for %s use\n", serial->type->name, - connection_info->connections[i].port, string); } + /* + * Handle devices that report invalid stuff here. + */ + if (num_ports == 0 || num_ports > 2) { + dev_warn (dev, "%s: No valid connect info available\n", + serial->type->name); + num_ports = 2; + } + + dev_info(dev, "%s: Number of ports: %d\n", serial->type->name, + num_ports); /* * save off our num_ports info so that we can use it in the @@ -887,8 +877,7 @@ static int clie_3_5_startup (struct usb_serial *serial) static int treo_attach (struct usb_serial *serial) { - struct usb_serial_port *port; - int i; + struct usb_serial_port *swap_port; /* Only do this endpoint hack for the Handspring devices with * interrupt in endpoints, which for now are the Treo devices. */ @@ -898,31 +887,28 @@ static int treo_attach (struct usb_serial *serial) dbg("%s", __FUNCTION__); - /* Ok, this is pretty ugly, but these devices want to use the - * interrupt endpoint as paired up with a bulk endpoint for a - * "virtual serial port". So let's force the endpoints to be - * where we want them to be. */ - for (i = serial->num_bulk_in; i < serial->num_ports; ++i) { - port = serial->port[i]; - port->read_urb = serial->port[0]->read_urb; - port->bulk_in_endpointAddress = serial->port[0]->bulk_in_endpointAddress; - port->bulk_in_buffer = serial->port[0]->bulk_in_buffer; - } - - for (i = serial->num_bulk_out; i < serial->num_ports; ++i) { - port = serial->port[i]; - port->write_urb = serial->port[0]->write_urb; - port->bulk_out_size = serial->port[0]->bulk_out_size; - port->bulk_out_endpointAddress = serial->port[0]->bulk_out_endpointAddress; - port->bulk_out_buffer = serial->port[0]->bulk_out_buffer; - } - - for (i = serial->num_interrupt_in; i < serial->num_ports; ++i) { - port = serial->port[i]; - port->interrupt_in_urb = serial->port[0]->interrupt_in_urb; - port->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; - port->interrupt_in_buffer = serial->port[0]->interrupt_in_buffer; - } + /* + * It appears that Treos want to use the 1st interrupt endpoint to + * communicate with the 2nd bulk out endpoint, so let's swap the 1st + * and 2nd bulk in and interrupt endpoints. Note that swapping the + * bulk out endpoints would break lots of apps that want to communicate + * on the second port. + */ +#define COPY_PORT(dest, src) \ + dest->read_urb = src->read_urb; \ + dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress; \ + dest->bulk_in_buffer = src->bulk_in_buffer; \ + dest->interrupt_in_urb = src->interrupt_in_urb; \ + dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress; \ + dest->interrupt_in_buffer = src->interrupt_in_buffer; + + swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL); + if (!swap_port) + return -ENOMEM; + COPY_PORT(swap_port, serial->port[0]); + COPY_PORT(serial->port[0], serial->port[1]); + COPY_PORT(serial->port[1], swap_port); + kfree(swap_port); return 0; } @@ -1099,10 +1085,10 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); 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"); -MODULE_PARM(vendor, "i"); +module_param(vendor, ushort, 0); MODULE_PARM_DESC(vendor, "User specified vendor ID"); -MODULE_PARM(product, "i"); +module_param(product, ushort, 0); MODULE_PARM_DESC(product, "User specified product ID");