ChangeSet 1.889.26.4, 2003/01/10 11:28:45-08:00, greg@kroah.com [PATCH] USB visor: Split up the initialization command logic to handle different device types better. diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c Mon Jan 13 14:28:01 2003 +++ b/drivers/usb/serial/visor.c Mon Jan 13 14:28:01 2003 @@ -177,24 +177,40 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs); static int clie_3_5_startup (struct usb_serial *serial); +static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id); +static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id); static struct usb_device_id id_table [] = { - { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, - { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, - { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, - { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, - { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, - { 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_ZIRE_ID) }, - { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, - { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) }, - { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, - { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) }, + { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID), + .driver_info = (unsigned int)&palm_os_3_probe }, + { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) }, - { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID), + .driver_info = (unsigned int)&palm_os_4_probe }, { } /* Terminating entry */ }; @@ -600,99 +616,143 @@ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); } -static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id) +static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id) { struct device *dev = &serial->dev->dev; - int response; + struct visor_connection_info *connection_info; + unsigned char *transfer_buffer; + char *string; + int retval = 0; int i; int num_ports; - unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL); + dbg("%s", __FUNCTION__); + + transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL); if (!transfer_buffer) { - dev_err(dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 256); + dev_err(dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, + sizeof(*connection_info)); return -ENOMEM; } - dbg("%s", __FUNCTION__); - - dbg("%s - Set config to 1", __FUNCTION__); - usb_set_configuration (serial->dev, 1); - /* send a get connection info request */ - response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION, - 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); - if (response < 0) { - dev_err(dev, "%s - error getting connection information\n", __FUNCTION__); - } else { - struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer; - char *string; - - le16_to_cpus(&connection_info->num_ports); - num_ports = connection_info->num_ports; - 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; - } - dev_info(dev, "%s: port %d, is for %s use\n", serial->type->name, - connection_info->connections[i].port, string); - /* save off our num_ports info so that we can use it in the calc_num_ports call */ - usb_set_serial_data(serial, (void *)(long)num_ports); - } + retval = usb_control_msg (serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + VISOR_GET_CONNECTION_INFORMATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, + sizeof(*connection_info), 300); + if (retval < 0) { + dev_err(dev, "%s - error %d getting connection information\n", + __FUNCTION__, retval); + goto exit; } + + connection_info = (struct visor_connection_info *)transfer_buffer; - if ((serial->dev->descriptor.idVendor == PALM_VENDOR_ID) || - ((serial->dev->descriptor.idVendor == SONY_VENDOR_ID) && - (serial->dev->descriptor.idProduct != SONY_CLIE_4_1_ID))) { - /* Palm OS 4.0 Hack */ - response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), - PALM_GET_SOME_UNKNOWN_INFORMATION, - 0xc2, 0x0000, 0x0000, transfer_buffer, - 0x14, 300); - if (response < 0) { - dev_err(dev, "%s - error getting first unknown palm command\n", __FUNCTION__); - } else { - usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer); - } - response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), - PALM_GET_SOME_UNKNOWN_INFORMATION, - 0xc2, 0x0000, 0x0000, transfer_buffer, - 0x14, 300); - if (response < 0) { - dev_err(dev, "%s - error getting second unknown palm command\n", __FUNCTION__); - } else { - usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, 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; } + dev_info(dev, "%s: port %d, is for %s use\n", serial->type->name, + connection_info->connections[i].port, string); } + /* + * save off our num_ports info so that we can use it in the + * calc_num_ports callback + */ + usb_set_serial_data(serial, (void *)(long)num_ports); + /* ask for the number of bytes available, but ignore the response as it is broken */ - response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, - 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300); - if (response < 0) { - dev_err(dev, "%s - error getting bytes available request\n", __FUNCTION__); - } + retval = usb_control_msg (serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + VISOR_REQUEST_BYTES_AVAILABLE, + 0xc2, 0x0000, 0x0005, transfer_buffer, + 0x02, 300); + if (retval < 0) + dev_err(dev, "%s - error %d getting bytes available request\n", + __FUNCTION__, retval); + retval = 0; +exit: kfree (transfer_buffer); - /* continue on with initialization */ + return retval; +} + +static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id) +{ + struct device *dev = &serial->dev->dev; + struct palm_ext_connection_info *connection_info; + unsigned char *transfer_buffer; + int retval; + + dbg("%s", __FUNCTION__); + + transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL); + if (!transfer_buffer) { + dev_err(dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, + sizeof(*connection_info)); + return -ENOMEM; + } + + retval = usb_control_msg (serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + PALM_GET_EXT_CONNECTION_INFORMATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, + sizeof (*connection_info), 300); + if (retval < 0) + dev_err(dev, "%s - error %d getting connection info\n", + __FUNCTION__, retval); + else + usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer); + + kfree (transfer_buffer); return 0; +} + + +static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id) +{ + int retval = 0; + int (*startup) (struct usb_serial *serial, const struct usb_device_id *id); + + dbg("%s", __FUNCTION__); + + dbg("%s - Set config to 1", __FUNCTION__); + usb_set_configuration (serial->dev, 1); + + if (id->driver_info) { + startup = (void *)id->driver_info; + retval = startup(serial, id); + } + + return retval; } static int visor_calc_num_ports (struct usb_serial *serial)