root/drivers/usb/serial/visor.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. visor_open
  2. visor_close
  3. visor_read_int_callback
  4. palm_os_3_probe
  5. palm_os_4_probe
  6. visor_probe
  7. visor_calc_num_ports
  8. clie_5_calc_num_ports
  9. clie_3_5_startup

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * USB HandSpring Visor, Palm m50x, and Sony Clie driver
   4  * (supports all of the Palm OS USB devices)
   5  *
   6  *      Copyright (C) 1999 - 2004
   7  *          Greg Kroah-Hartman (greg@kroah.com)
   8  *
   9  * See Documentation/usb/usb-serial.rst for more information on using this
  10  * driver
  11  *
  12  */
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/errno.h>
  16 #include <linux/slab.h>
  17 #include <linux/tty.h>
  18 #include <linux/tty_driver.h>
  19 #include <linux/tty_flip.h>
  20 #include <linux/module.h>
  21 #include <linux/moduleparam.h>
  22 #include <linux/spinlock.h>
  23 #include <linux/uaccess.h>
  24 #include <linux/usb.h>
  25 #include <linux/usb/serial.h>
  26 #include <linux/usb/cdc.h>
  27 #include "visor.h"
  28 
  29 /*
  30  * Version Information
  31  */
  32 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
  33 #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
  34 
  35 /* function prototypes for a handspring visor */
  36 static int  visor_open(struct tty_struct *tty, struct usb_serial_port *port);
  37 static void visor_close(struct usb_serial_port *port);
  38 static int  visor_probe(struct usb_serial *serial,
  39                                         const struct usb_device_id *id);
  40 static int  visor_calc_num_ports(struct usb_serial *serial,
  41                                         struct usb_serial_endpoints *epds);
  42 static int  clie_5_calc_num_ports(struct usb_serial *serial,
  43                                         struct usb_serial_endpoints *epds);
  44 static void visor_read_int_callback(struct urb *urb);
  45 static int  clie_3_5_startup(struct usb_serial *serial);
  46 static int palm_os_3_probe(struct usb_serial *serial,
  47                                         const struct usb_device_id *id);
  48 static int palm_os_4_probe(struct usb_serial *serial,
  49                                         const struct usb_device_id *id);
  50 
  51 static const struct usb_device_id id_table[] = {
  52         { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID),
  53                 .driver_info = (kernel_ulong_t)&palm_os_3_probe },
  54         { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID),
  55                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  56         { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID),
  57                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  58         { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID),
  59                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  60         { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID),
  61                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  62         { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID),
  63                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  64         { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID),
  65                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  66         { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID),
  67                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  68         { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID),
  69                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  70         { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID),
  71                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  72         { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID),
  73                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  74         { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID),
  75                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  76         { USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650),
  77                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  78         { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID),
  79                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  80         { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID),
  81                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  82         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID),
  83                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  84         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID),
  85                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  86         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID),
  87                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  88         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID),
  89                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  90         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID),
  91                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  92         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID),
  93                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  94         { USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID),
  95                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  96         { USB_DEVICE_INTERFACE_CLASS(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID, 0xff),
  97                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
  98         { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
  99                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
 100         { USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID),
 101                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
 102         { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
 103                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
 104         { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
 105                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
 106         { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID),
 107                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
 108         { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID),
 109                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
 110         { }                                     /* Terminating entry */
 111 };
 112 
 113 static const struct usb_device_id clie_id_5_table[] = {
 114         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID),
 115                 .driver_info = (kernel_ulong_t)&palm_os_4_probe },
 116         { }                                     /* Terminating entry */
 117 };
 118 
 119 static const struct usb_device_id clie_id_3_5_table[] = {
 120         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
 121         { }                                     /* Terminating entry */
 122 };
 123 
 124 static const struct usb_device_id id_table_combined[] = {
 125         { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 126         { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) },
 127         { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) },
 128         { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID) },
 129         { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
 130         { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
 131         { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
 132         { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
 133         { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID) },
 134         { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
 135         { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
 136         { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
 137         { USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650) },
 138         { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
 139         { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
 140         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
 141         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
 142         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
 143         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
 144         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) },
 145         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) },
 146         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
 147         { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 148         { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 149         { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) },
 150         { USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID) },
 151         { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
 152         { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
 153         { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
 154         { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) },
 155         { }                                     /* Terminating entry */
 156 };
 157 
 158 MODULE_DEVICE_TABLE(usb, id_table_combined);
 159 
 160 /* All of the device info needed for the Handspring Visor,
 161    and Palm 4.0 devices */
 162 static struct usb_serial_driver handspring_device = {
 163         .driver = {
 164                 .owner =        THIS_MODULE,
 165                 .name =         "visor",
 166         },
 167         .description =          "Handspring Visor / Palm OS",
 168         .id_table =             id_table,
 169         .num_ports =            2,
 170         .bulk_out_size =        256,
 171         .open =                 visor_open,
 172         .close =                visor_close,
 173         .throttle =             usb_serial_generic_throttle,
 174         .unthrottle =           usb_serial_generic_unthrottle,
 175         .probe =                visor_probe,
 176         .calc_num_ports =       visor_calc_num_ports,
 177         .read_int_callback =    visor_read_int_callback,
 178 };
 179 
 180 /* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */
 181 static struct usb_serial_driver clie_5_device = {
 182         .driver = {
 183                 .owner =        THIS_MODULE,
 184                 .name =         "clie_5",
 185         },
 186         .description =          "Sony Clie 5.0",
 187         .id_table =             clie_id_5_table,
 188         .num_ports =            2,
 189         .num_bulk_out =         2,
 190         .bulk_out_size =        256,
 191         .open =                 visor_open,
 192         .close =                visor_close,
 193         .throttle =             usb_serial_generic_throttle,
 194         .unthrottle =           usb_serial_generic_unthrottle,
 195         .probe =                visor_probe,
 196         .calc_num_ports =       clie_5_calc_num_ports,
 197         .read_int_callback =    visor_read_int_callback,
 198 };
 199 
 200 /* device info for the Sony Clie OS version 3.5 */
 201 static struct usb_serial_driver clie_3_5_device = {
 202         .driver = {
 203                 .owner =        THIS_MODULE,
 204                 .name =         "clie_3.5",
 205         },
 206         .description =          "Sony Clie 3.5",
 207         .id_table =             clie_id_3_5_table,
 208         .num_ports =            1,
 209         .bulk_out_size =        256,
 210         .open =                 visor_open,
 211         .close =                visor_close,
 212         .throttle =             usb_serial_generic_throttle,
 213         .unthrottle =           usb_serial_generic_unthrottle,
 214         .attach =               clie_3_5_startup,
 215 };
 216 
 217 static struct usb_serial_driver * const serial_drivers[] = {
 218         &handspring_device, &clie_5_device, &clie_3_5_device, NULL
 219 };
 220 
 221 /******************************************************************************
 222  * Handspring Visor specific driver functions
 223  ******************************************************************************/
 224 static int visor_open(struct tty_struct *tty, struct usb_serial_port *port)
 225 {
 226         int result = 0;
 227 
 228         if (!port->read_urb) {
 229                 /* this is needed for some brain dead Sony devices */
 230                 dev_err(&port->dev, "Device lied about number of ports, please use a lower one.\n");
 231                 return -ENODEV;
 232         }
 233 
 234         /* Start reading from the device */
 235         result = usb_serial_generic_open(tty, port);
 236         if (result)
 237                 goto exit;
 238 
 239         if (port->interrupt_in_urb) {
 240                 dev_dbg(&port->dev, "adding interrupt input for treo\n");
 241                 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 242                 if (result)
 243                         dev_err(&port->dev,
 244                             "%s - failed submitting interrupt urb, error %d\n",
 245                                                         __func__, result);
 246         }
 247 exit:
 248         return result;
 249 }
 250 
 251 
 252 static void visor_close(struct usb_serial_port *port)
 253 {
 254         unsigned char *transfer_buffer;
 255 
 256         usb_serial_generic_close(port);
 257         usb_kill_urb(port->interrupt_in_urb);
 258 
 259         transfer_buffer = kmalloc(0x12, GFP_KERNEL);
 260         if (!transfer_buffer)
 261                 return;
 262         usb_control_msg(port->serial->dev,
 263                                          usb_rcvctrlpipe(port->serial->dev, 0),
 264                                          VISOR_CLOSE_NOTIFICATION, 0xc2,
 265                                          0x0000, 0x0000,
 266                                          transfer_buffer, 0x12, 300);
 267         kfree(transfer_buffer);
 268 }
 269 
 270 static void visor_read_int_callback(struct urb *urb)
 271 {
 272         struct usb_serial_port *port = urb->context;
 273         int status = urb->status;
 274         int result;
 275 
 276         switch (status) {
 277         case 0:
 278                 /* success */
 279                 break;
 280         case -ECONNRESET:
 281         case -ENOENT:
 282         case -ESHUTDOWN:
 283                 /* this urb is terminated, clean up */
 284                 dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
 285                         __func__, status);
 286                 return;
 287         default:
 288                 dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
 289                         __func__, status);
 290                 goto exit;
 291         }
 292 
 293         /*
 294          * This information is still unknown what it can be used for.
 295          * If anyone has an idea, please let the author know...
 296          *
 297          * Rumor has it this endpoint is used to notify when data
 298          * is ready to be read from the bulk ones.
 299          */
 300         usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
 301                               urb->transfer_buffer);
 302 
 303 exit:
 304         result = usb_submit_urb(urb, GFP_ATOMIC);
 305         if (result)
 306                 dev_err(&urb->dev->dev,
 307                                 "%s - Error %d submitting interrupt urb\n",
 308                                                         __func__, result);
 309 }
 310 
 311 static int palm_os_3_probe(struct usb_serial *serial,
 312                                                 const struct usb_device_id *id)
 313 {
 314         struct device *dev = &serial->dev->dev;
 315         struct visor_connection_info *connection_info;
 316         unsigned char *transfer_buffer;
 317         char *string;
 318         int retval = 0;
 319         int i;
 320         int num_ports = 0;
 321 
 322         transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
 323         if (!transfer_buffer)
 324                 return -ENOMEM;
 325 
 326         /* send a get connection info request */
 327         retval = usb_control_msg(serial->dev,
 328                                   usb_rcvctrlpipe(serial->dev, 0),
 329                                   VISOR_GET_CONNECTION_INFORMATION,
 330                                   0xc2, 0x0000, 0x0000, transfer_buffer,
 331                                   sizeof(*connection_info), 300);
 332         if (retval < 0) {
 333                 dev_err(dev, "%s - error %d getting connection information\n",
 334                         __func__, retval);
 335                 goto exit;
 336         }
 337 
 338         if (retval != sizeof(*connection_info)) {
 339                 dev_err(dev, "Invalid connection information received from device\n");
 340                 retval = -ENODEV;
 341                 goto exit;
 342         }
 343 
 344         connection_info = (struct visor_connection_info *)transfer_buffer;
 345 
 346         num_ports = le16_to_cpu(connection_info->num_ports);
 347 
 348         /* Handle devices that report invalid stuff here. */
 349         if (num_ports == 0 || num_ports > 2) {
 350                 dev_warn(dev, "%s: No valid connect info available\n",
 351                         serial->type->description);
 352                 num_ports = 2;
 353         }
 354 
 355         for (i = 0; i < num_ports; ++i) {
 356                 switch (connection_info->connections[i].port_function_id) {
 357                 case VISOR_FUNCTION_GENERIC:
 358                         string = "Generic";
 359                         break;
 360                 case VISOR_FUNCTION_DEBUGGER:
 361                         string = "Debugger";
 362                         break;
 363                 case VISOR_FUNCTION_HOTSYNC:
 364                         string = "HotSync";
 365                         break;
 366                 case VISOR_FUNCTION_CONSOLE:
 367                         string = "Console";
 368                         break;
 369                 case VISOR_FUNCTION_REMOTE_FILE_SYS:
 370                         string = "Remote File System";
 371                         break;
 372                 default:
 373                         string = "unknown";
 374                         break;
 375                 }
 376                 dev_info(dev, "%s: port %d, is for %s use\n",
 377                         serial->type->description,
 378                         connection_info->connections[i].port, string);
 379         }
 380         dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
 381                 num_ports);
 382 
 383         /*
 384          * save off our num_ports info so that we can use it in the
 385          * calc_num_ports callback
 386          */
 387         usb_set_serial_data(serial, (void *)(long)num_ports);
 388 
 389         /* ask for the number of bytes available, but ignore the
 390            response as it is broken */
 391         retval = usb_control_msg(serial->dev,
 392                                   usb_rcvctrlpipe(serial->dev, 0),
 393                                   VISOR_REQUEST_BYTES_AVAILABLE,
 394                                   0xc2, 0x0000, 0x0005, transfer_buffer,
 395                                   0x02, 300);
 396         if (retval < 0)
 397                 dev_err(dev, "%s - error %d getting bytes available request\n",
 398                         __func__, retval);
 399         retval = 0;
 400 
 401 exit:
 402         kfree(transfer_buffer);
 403 
 404         return retval;
 405 }
 406 
 407 static int palm_os_4_probe(struct usb_serial *serial,
 408                                                 const struct usb_device_id *id)
 409 {
 410         struct device *dev = &serial->dev->dev;
 411         struct palm_ext_connection_info *connection_info;
 412         unsigned char *transfer_buffer;
 413         int retval;
 414 
 415         transfer_buffer =  kmalloc(sizeof(*connection_info), GFP_KERNEL);
 416         if (!transfer_buffer)
 417                 return -ENOMEM;
 418 
 419         retval = usb_control_msg(serial->dev,
 420                                   usb_rcvctrlpipe(serial->dev, 0),
 421                                   PALM_GET_EXT_CONNECTION_INFORMATION,
 422                                   0xc2, 0x0000, 0x0000, transfer_buffer,
 423                                   sizeof(*connection_info), 300);
 424         if (retval < 0)
 425                 dev_err(dev, "%s - error %d getting connection info\n",
 426                         __func__, retval);
 427         else
 428                 usb_serial_debug_data(dev, __func__, retval, transfer_buffer);
 429 
 430         kfree(transfer_buffer);
 431         return 0;
 432 }
 433 
 434 
 435 static int visor_probe(struct usb_serial *serial,
 436                                         const struct usb_device_id *id)
 437 {
 438         int retval = 0;
 439         int (*startup)(struct usb_serial *serial,
 440                                         const struct usb_device_id *id);
 441 
 442         /*
 443          * some Samsung Android phones in modem mode have the same ID
 444          * as SPH-I500, but they are ACM devices, so dont bind to them
 445          */
 446         if (id->idVendor == SAMSUNG_VENDOR_ID &&
 447                 id->idProduct == SAMSUNG_SPH_I500_ID &&
 448                 serial->dev->descriptor.bDeviceClass == USB_CLASS_COMM &&
 449                 serial->dev->descriptor.bDeviceSubClass ==
 450                         USB_CDC_SUBCLASS_ACM)
 451                 return -ENODEV;
 452 
 453         if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
 454                 dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
 455                         serial->dev->actconfig->desc.bConfigurationValue);
 456                 return -ENODEV;
 457         }
 458 
 459         if (id->driver_info) {
 460                 startup = (void *)id->driver_info;
 461                 retval = startup(serial, id);
 462         }
 463 
 464         return retval;
 465 }
 466 
 467 static int visor_calc_num_ports(struct usb_serial *serial,
 468                                         struct usb_serial_endpoints *epds)
 469 {
 470         unsigned int vid = le16_to_cpu(serial->dev->descriptor.idVendor);
 471         int num_ports = (int)(long)(usb_get_serial_data(serial));
 472 
 473         if (num_ports)
 474                 usb_set_serial_data(serial, NULL);
 475 
 476         /*
 477          * Only swap the bulk endpoints for the Handspring devices with
 478          * interrupt in endpoints, which for now are the Treo devices.
 479          */
 480         if (!(vid == HANDSPRING_VENDOR_ID || vid == KYOCERA_VENDOR_ID) ||
 481                         epds->num_interrupt_in == 0)
 482                 goto out;
 483 
 484         if (epds->num_bulk_in < 2 || epds->num_interrupt_in < 2) {
 485                 dev_err(&serial->interface->dev, "missing endpoints\n");
 486                 return -ENODEV;
 487         }
 488 
 489         /*
 490          * It appears that Treos and Kyoceras want to use the
 491          * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
 492          * so let's swap the 1st and 2nd bulk in and interrupt endpoints.
 493          * Note that swapping the bulk out endpoints would break lots of
 494          * apps that want to communicate on the second port.
 495          */
 496         swap(epds->bulk_in[0], epds->bulk_in[1]);
 497         swap(epds->interrupt_in[0], epds->interrupt_in[1]);
 498 out:
 499         return num_ports;
 500 }
 501 
 502 static int clie_5_calc_num_ports(struct usb_serial *serial,
 503                                         struct usb_serial_endpoints *epds)
 504 {
 505         /*
 506          * TH55 registers 2 ports.
 507          * Communication in from the UX50/TH55 uses the first bulk-in
 508          * endpoint, while communication out to the UX50/TH55 uses the second
 509          * bulk-out endpoint.
 510          */
 511 
 512         /*
 513          * FIXME: Should we swap the descriptors instead of using the same
 514          *        bulk-out endpoint for both ports?
 515          */
 516         epds->bulk_out[0] = epds->bulk_out[1];
 517 
 518         return serial->type->num_ports;
 519 }
 520 
 521 static int clie_3_5_startup(struct usb_serial *serial)
 522 {
 523         struct device *dev = &serial->dev->dev;
 524         int result;
 525         u8 *data;
 526 
 527         data = kmalloc(1, GFP_KERNEL);
 528         if (!data)
 529                 return -ENOMEM;
 530 
 531         /*
 532          * Note that PEG-300 series devices expect the following two calls.
 533          */
 534 
 535         /* get the config number */
 536         result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 537                                   USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
 538                                   0, 0, data, 1, 3000);
 539         if (result < 0) {
 540                 dev_err(dev, "%s: get config number failed: %d\n",
 541                                                         __func__, result);
 542                 goto out;
 543         }
 544         if (result != 1) {
 545                 dev_err(dev, "%s: get config number bad return length: %d\n",
 546                                                         __func__, result);
 547                 result = -EIO;
 548                 goto out;
 549         }
 550 
 551         /* get the interface number */
 552         result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 553                                   USB_REQ_GET_INTERFACE,
 554                                   USB_DIR_IN | USB_RECIP_INTERFACE,
 555                                   0, 0, data, 1, 3000);
 556         if (result < 0) {
 557                 dev_err(dev, "%s: get interface number failed: %d\n",
 558                                                         __func__, result);
 559                 goto out;
 560         }
 561         if (result != 1) {
 562                 dev_err(dev,
 563                         "%s: get interface number bad return length: %d\n",
 564                                                         __func__, result);
 565                 result = -EIO;
 566                 goto out;
 567         }
 568 
 569         result = 0;
 570 out:
 571         kfree(data);
 572 
 573         return result;
 574 }
 575 
 576 module_usb_serial_driver(serial_drivers, id_table_combined);
 577 
 578 MODULE_AUTHOR(DRIVER_AUTHOR);
 579 MODULE_DESCRIPTION(DRIVER_DESC);
 580 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */