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