11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * USB HandSpring Visor, Palm m50x, and Sony Clie driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (supports all of the Palm OS USB devices) 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 - 2004 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Greg Kroah-Hartman (greg@kroah.com) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 84d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * This program is free software; you can redistribute it and/or 94d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * modify it under the terms of the GNU General Public License version 104d0dce3e0b794942407391c52f8dd2760802f391Greg Kroah-Hartman * 2 as published by the Free Software Foundation. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12d60d43965e46674b9097b422336a55c6ca08559aAlan Cox * See Documentation/usb/usb-serial.txt for more information on using this 13d60d43965e46674b9097b422336a55c6ca08559aAlan Cox * driver 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 27d60d43965e46674b9097b422336a55c6ca08559aAlan Cox#include <linux/uaccess.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/usb.h> 29a969888ce91673c7f4b86520d851a6f0d5a5fa7dGreg Kroah-Hartman#include <linux/usb/serial.h> 30acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero#include <linux/usb/cdc.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "visor.h" 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version Information 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_DESC "USB HandSpring Visor / Palm OS driver" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* function prototypes for a handspring visor */ 40a509a7e478e4766114d69f12d19d644ac63e9765Alan Coxstatic int visor_open(struct tty_struct *tty, struct usb_serial_port *port); 41335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void visor_close(struct usb_serial_port *port); 42d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int visor_probe(struct usb_serial *serial, 43d60d43965e46674b9097b422336a55c6ca08559aAlan Cox const struct usb_device_id *id); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int visor_calc_num_ports(struct usb_serial *serial); 45d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic void visor_read_int_callback(struct urb *urb); 46d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int clie_3_5_startup(struct usb_serial *serial); 47d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int treo_attach(struct usb_serial *serial); 48d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int clie_5_attach(struct usb_serial *serial); 49d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int palm_os_3_probe(struct usb_serial *serial, 50d60d43965e46674b9097b422336a55c6ca08559aAlan Cox const struct usb_device_id *id); 51d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int palm_os_4_probe(struct usb_serial *serial, 52d60d43965e46674b9097b422336a55c6ca08559aAlan Cox const struct usb_device_id *id); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Parameters that may be passed into the module. */ 5590ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool debug; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __u16 vendor; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __u16 product; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_device_id id_table [] = { 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID), 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_3_probe }, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID), 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID), 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 6604d52461c6ecfc5b72e688b0eb2ead7b555eca25Hendrik Schweppe { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID), 6704d52461c6ecfc5b72e688b0eb2ead7b555eca25Hendrik Schweppe .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID), 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID), 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID), 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID), 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID), 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID), 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID), 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID), 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 84ac21e9ff08db3d6fac41d356c77fcb531c2e03e1Greg Kroah-Hartman { USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650), 85ac21e9ff08db3d6fac41d356c77fcb531c2e03e1Greg Kroah-Hartman .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID), 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID), 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID), 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID), 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID), 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID), 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID), 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID), 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 102c8ba84a0c682068a55a5892d6e12e3f196fd792cMaximilian Attems { USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID), 103c8ba84a0c682068a55a5892d6e12e3f196fd792cMaximilian Attems .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 104d60d43965e46674b9097b422336a55c6ca08559aAlan Cox { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 106d60d43965e46674b9097b422336a55c6ca08559aAlan Cox { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 108115c1ce524869309e4bddcfc3dd112ac76b92defLarry Battraw { USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID), 109115c1ce524869309e4bddcfc3dd112ac76b92defLarry Battraw .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 110d60d43965e46674b9097b422336a55c6ca08559aAlan Cox { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID), 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID), 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID), 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { }, /* optional parameter entry */ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_device_id clie_id_5_table [] = { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID), 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_info = (kernel_ulong_t)&palm_os_4_probe }, 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { }, /* optional parameter entry */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_device_id clie_id_3_5_table [] = { 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_device_id id_table_combined [] = { 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) }, 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) }, 13804d52461c6ecfc5b72e688b0eb2ead7b555eca25Hendrik Schweppe { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID) }, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID) }, 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, 147ac21e9ff08db3d6fac41d356c77fcb531c2e03e1Greg Kroah-Hartman { USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650) }, 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) }, 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) }, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) }, 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) }, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) }, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) }, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) }, 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) }, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) }, 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) }, 160115c1ce524869309e4bddcfc3dd112ac76b92defLarry Battraw { USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID) }, 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) }, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) }, 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) }, 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) }, 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { }, /* optional parameter entry */ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 169d60d43965e46674b9097b422336a55c6ca08559aAlan CoxMODULE_DEVICE_TABLE(usb, id_table_combined); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_driver visor_driver = { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "visor", 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = usb_serial_probe, 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .disconnect = usb_serial_disconnect, 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = id_table_combined, 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 178d60d43965e46674b9097b422336a55c6ca08559aAlan Cox/* All of the device info needed for the Handspring Visor, 179d60d43965e46674b9097b422336a55c6ca08559aAlan Cox and Palm 4.0 devices */ 180ea65370d025f5005649e5cb37c4d025e92c6fc38Greg Kroah-Hartmanstatic struct usb_serial_driver handspring_device = { 18118fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman .driver = { 18218fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman .owner = THIS_MODULE, 183269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman .name = "visor", 18418fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman }, 185269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman .description = "Handspring Visor / Palm OS", 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = id_table, 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_ports = 2, 1889a1f298f8bc92f21b09bd7ef396c2fc6544ce9aaJohan Hovold .bulk_out_size = 256, 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = visor_open, 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = visor_close, 191214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold .throttle = usb_serial_generic_throttle, 192214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold .unthrottle = usb_serial_generic_unthrottle, 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attach = treo_attach, 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = visor_probe, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .calc_num_ports = visor_calc_num_ports, 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_int_callback = visor_read_int_callback, 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */ 200ea65370d025f5005649e5cb37c4d025e92c6fc38Greg Kroah-Hartmanstatic struct usb_serial_driver clie_5_device = { 20118fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman .driver = { 20218fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman .owner = THIS_MODULE, 203269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman .name = "clie_5", 20418fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman }, 205269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman .description = "Sony Clie 5.0", 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = clie_id_5_table, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_ports = 2, 2089a1f298f8bc92f21b09bd7ef396c2fc6544ce9aaJohan Hovold .bulk_out_size = 256, 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = visor_open, 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = visor_close, 211214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold .throttle = usb_serial_generic_throttle, 212214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold .unthrottle = usb_serial_generic_unthrottle, 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attach = clie_5_attach, 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = visor_probe, 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .calc_num_ports = visor_calc_num_ports, 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_int_callback = visor_read_int_callback, 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* device info for the Sony Clie OS version 3.5 */ 220ea65370d025f5005649e5cb37c4d025e92c6fc38Greg Kroah-Hartmanstatic struct usb_serial_driver clie_3_5_device = { 22118fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman .driver = { 22218fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman .owner = THIS_MODULE, 223269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman .name = "clie_3.5", 22418fcac353fdc7cd072b0d24c8667042e675a4c11Greg Kroah-Hartman }, 225269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman .description = "Sony Clie 3.5", 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = clie_id_3_5_table, 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_ports = 1, 2289a1f298f8bc92f21b09bd7ef396c2fc6544ce9aaJohan Hovold .bulk_out_size = 256, 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = visor_open, 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = visor_close, 231214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold .throttle = usb_serial_generic_throttle, 232214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold .unthrottle = usb_serial_generic_unthrottle, 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attach = clie_3_5_startup, 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23629618e9fb5507b9fcf07f739a8506a3640495945Alan Sternstatic struct usb_serial_driver * const serial_drivers[] = { 23729618e9fb5507b9fcf07f739a8506a3640495945Alan Stern &handspring_device, &clie_5_device, &clie_3_5_device, NULL 23829618e9fb5507b9fcf07f739a8506a3640495945Alan Stern}; 23929618e9fb5507b9fcf07f739a8506a3640495945Alan Stern 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************** 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handspring Visor specific driver functions 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/ 243a509a7e478e4766114d69f12d19d644ac63e9765Alan Coxstatic int visor_open(struct tty_struct *tty, struct usb_serial_port *port) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result = 0; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 247441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!port->read_urb) { 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this is needed for some brain dead Sony devices */ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&port->dev, "Device lied about number of ports, please use a lower one.\n"); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start reading from the device */ 256214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold result = usb_serial_generic_open(tty, port); 257214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold if (result) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 259d60d43965e46674b9097b422336a55c6ca08559aAlan Cox 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port->interrupt_in_urb) { 261441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - adding interrupt input for treo", __func__); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 264d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dev_err(&port->dev, 265d60d43965e46674b9097b422336a55c6ca08559aAlan Cox "%s - failed submitting interrupt urb, error %d\n", 266d60d43965e46674b9097b422336a55c6ca08559aAlan Cox __func__, result); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 268d60d43965e46674b9097b422336a55c6ca08559aAlan Coxexit: 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 273335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void visor_close(struct usb_serial_port *port) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *transfer_buffer; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 277441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 278d60d43965e46674b9097b422336a55c6ca08559aAlan Cox 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* shutdown our urbs */ 280214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold usb_serial_generic_close(port); 281bcb54a54033ff9359cf64e4283e4f4b92bf9132fMariusz Kozlowski usb_kill_urb(port->interrupt_in_urb); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 283e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum mutex_lock(&port->serial->disc_mutex); 284e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum if (!port->serial->disconnected) { 285e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum /* Try to send shutdown message, unless the device is gone */ 286d60d43965e46674b9097b422336a55c6ca08559aAlan Cox transfer_buffer = kmalloc(0x12, GFP_KERNEL); 287e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum if (transfer_buffer) { 288d60d43965e46674b9097b422336a55c6ca08559aAlan Cox usb_control_msg(port->serial->dev, 289e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum usb_rcvctrlpipe(port->serial->dev, 0), 290e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum VISOR_CLOSE_NOTIFICATION, 0xc2, 291e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum 0x0000, 0x0000, 292e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum transfer_buffer, 0x12, 300); 293d60d43965e46674b9097b422336a55c6ca08559aAlan Cox kfree(transfer_buffer); 294e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum } 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29695bef012ea4a3cce437a4fcf59bb097d14944b0dOliver Neukum mutex_unlock(&port->serial->disc_mutex); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 299d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic void visor_read_int_callback(struct urb *urb) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 301cdc97792289179974af6dda781c855696358d307Ming Lei struct usb_serial_port *port = urb->context; 30238e8c910ff7a1aafe2923f085df0f74a60f9de3cGreg Kroah-Hartman int status = urb->status; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30538e8c910ff7a1aafe2923f085df0f74a60f9de3cGreg Kroah-Hartman switch (status) { 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* success */ 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ECONNRESET: 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOENT: 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ESHUTDOWN: 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this urb is terminated, clean up */ 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - urb shutting down with status: %d", 314441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, status); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s - nonzero urb status received: %d", 318441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, status); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This information is still unknown what it can be used for. 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If anyone has an idea, please let the author know... 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Rumor has it this endpoint is used to notify when data 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is ready to be read from the bulk ones. 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 329441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &port->dev, __func__, 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->actual_length, urb->transfer_buffer); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 333d60d43965e46674b9097b422336a55c6ca08559aAlan Cox result = usb_submit_urb(urb, GFP_ATOMIC); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 335d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dev_err(&urb->dev->dev, 336d60d43965e46674b9097b422336a55c6ca08559aAlan Cox "%s - Error %d submitting interrupt urb\n", 337d60d43965e46674b9097b422336a55c6ca08559aAlan Cox __func__, result); 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 340d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int palm_os_3_probe(struct usb_serial *serial, 341d60d43965e46674b9097b422336a55c6ca08559aAlan Cox const struct usb_device_id *id) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev = &serial->dev->dev; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct visor_connection_info *connection_info; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *transfer_buffer; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *string; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int num_ports = 0; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 353d60d43965e46674b9097b422336a55c6ca08559aAlan Cox transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!transfer_buffer) { 355441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__, 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(*connection_info)); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* send a get connection info request */ 361d60d43965e46674b9097b422336a55c6ca08559aAlan Cox retval = usb_control_msg(serial->dev, 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_rcvctrlpipe(serial->dev, 0), 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VISOR_GET_CONNECTION_INFORMATION, 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xc2, 0x0000, 0x0000, transfer_buffer, 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(*connection_info), 300); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(dev, "%s - error %d getting connection information\n", 368441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, retval); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval == sizeof(*connection_info)) { 373d60d43965e46674b9097b422336a55c6ca08559aAlan Cox connection_info = (struct visor_connection_info *) 374d60d43965e46674b9097b422336a55c6ca08559aAlan Cox transfer_buffer; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_ports = le16_to_cpu(connection_info->num_ports); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < num_ports; ++i) { 378d60d43965e46674b9097b422336a55c6ca08559aAlan Cox switch ( 379d60d43965e46674b9097b422336a55c6ca08559aAlan Cox connection_info->connections[i].port_function_id) { 380d60d43965e46674b9097b422336a55c6ca08559aAlan Cox case VISOR_FUNCTION_GENERIC: 381d60d43965e46674b9097b422336a55c6ca08559aAlan Cox string = "Generic"; 382d60d43965e46674b9097b422336a55c6ca08559aAlan Cox break; 383d60d43965e46674b9097b422336a55c6ca08559aAlan Cox case VISOR_FUNCTION_DEBUGGER: 384d60d43965e46674b9097b422336a55c6ca08559aAlan Cox string = "Debugger"; 385d60d43965e46674b9097b422336a55c6ca08559aAlan Cox break; 386d60d43965e46674b9097b422336a55c6ca08559aAlan Cox case VISOR_FUNCTION_HOTSYNC: 387d60d43965e46674b9097b422336a55c6ca08559aAlan Cox string = "HotSync"; 388d60d43965e46674b9097b422336a55c6ca08559aAlan Cox break; 389d60d43965e46674b9097b422336a55c6ca08559aAlan Cox case VISOR_FUNCTION_CONSOLE: 390d60d43965e46674b9097b422336a55c6ca08559aAlan Cox string = "Console"; 391d60d43965e46674b9097b422336a55c6ca08559aAlan Cox break; 392d60d43965e46674b9097b422336a55c6ca08559aAlan Cox case VISOR_FUNCTION_REMOTE_FILE_SYS: 393d60d43965e46674b9097b422336a55c6ca08559aAlan Cox string = "Remote File System"; 394d60d43965e46674b9097b422336a55c6ca08559aAlan Cox break; 395d60d43965e46674b9097b422336a55c6ca08559aAlan Cox default: 396d60d43965e46674b9097b422336a55c6ca08559aAlan Cox string = "unknown"; 397d60d43965e46674b9097b422336a55c6ca08559aAlan Cox break; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_info(dev, "%s: port %d, is for %s use\n", 400269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman serial->type->description, 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds connection_info->connections[i].port, string); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle devices that report invalid stuff here. 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (num_ports == 0 || num_ports > 2) { 408d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dev_warn(dev, "%s: No valid connect info available\n", 409269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman serial->type->description); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_ports = 2; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 412d60d43965e46674b9097b422336a55c6ca08559aAlan Cox 413269bda1c123c7caf88e1deb2264f9086f0344192Greg Kroah-Hartman dev_info(dev, "%s: Number of ports: %d\n", serial->type->description, 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_ports); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * save off our num_ports info so that we can use it in the 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * calc_num_ports callback 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_data(serial, (void *)(long)num_ports); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 422d60d43965e46674b9097b422336a55c6ca08559aAlan Cox /* ask for the number of bytes available, but ignore the 423d60d43965e46674b9097b422336a55c6ca08559aAlan Cox response as it is broken */ 424d60d43965e46674b9097b422336a55c6ca08559aAlan Cox retval = usb_control_msg(serial->dev, 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_rcvctrlpipe(serial->dev, 0), 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VISOR_REQUEST_BYTES_AVAILABLE, 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xc2, 0x0000, 0x0005, transfer_buffer, 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x02, 300); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(dev, "%s - error %d getting bytes available request\n", 431441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, retval); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 435d60d43965e46674b9097b422336a55c6ca08559aAlan Cox kfree(transfer_buffer); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 440d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int palm_os_4_probe(struct usb_serial *serial, 441d60d43965e46674b9097b422336a55c6ca08559aAlan Cox const struct usb_device_id *id) 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev = &serial->dev->dev; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct palm_ext_connection_info *connection_info; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *transfer_buffer; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 448441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 450d60d43965e46674b9097b422336a55c6ca08559aAlan Cox transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!transfer_buffer) { 452441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__, 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(*connection_info)); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 457d60d43965e46674b9097b422336a55c6ca08559aAlan Cox retval = usb_control_msg(serial->dev, 458d60d43965e46674b9097b422336a55c6ca08559aAlan Cox usb_rcvctrlpipe(serial->dev, 0), 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PALM_GET_EXT_CONNECTION_INFORMATION, 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xc2, 0x0000, 0x0000, transfer_buffer, 461d60d43965e46674b9097b422336a55c6ca08559aAlan Cox sizeof(*connection_info), 300); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(dev, "%s - error %d getting connection info\n", 464441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, retval); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 466441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &serial->dev->dev, __func__, 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval, transfer_buffer); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 469d60d43965e46674b9097b422336a55c6ca08559aAlan Cox kfree(transfer_buffer); 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 474d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int visor_probe(struct usb_serial *serial, 475d60d43965e46674b9097b422336a55c6ca08559aAlan Cox const struct usb_device_id *id) 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 478d60d43965e46674b9097b422336a55c6ca08559aAlan Cox int (*startup)(struct usb_serial *serial, 479d60d43965e46674b9097b422336a55c6ca08559aAlan Cox const struct usb_device_id *id); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 483acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero /* 484acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero * some Samsung Android phones in modem mode have the same ID 485acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero * as SPH-I500, but they are ACM devices, so dont bind to them 486acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero */ 487acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero if (id->idVendor == SAMSUNG_VENDOR_ID && 488acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero id->idProduct == SAMSUNG_SPH_I500_ID && 489acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero serial->dev->descriptor.bDeviceClass == USB_CLASS_COMM && 490acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero serial->dev->descriptor.bDeviceSubClass == 491acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero USB_CDC_SUBCLASS_ACM) 492acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero return -ENODEV; 493acb52cb1613e1d3c8a8c650717cc51965c60d7d4Maciej Szmigiero 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serial->dev->actconfig->desc.bConfigurationValue != 1) { 495194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds serial->dev->actconfig->desc.bConfigurationValue); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id->driver_info) { 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds startup = (void *)id->driver_info; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = startup(serial, id); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 508d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int visor_calc_num_ports(struct usb_serial *serial) 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int num_ports = (int)(long)(usb_get_serial_data(serial)); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (num_ports) 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_serial_data(serial, NULL); 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return num_ports; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 518d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int clie_3_5_startup(struct usb_serial *serial) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev = &serial->dev->dev; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 522401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold u8 *data; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 524441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 526401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold data = kmalloc(1, GFP_KERNEL); 527401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold if (!data) 528401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold return -ENOMEM; 529401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that PEG-300 series devices expect the following two calls. 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get the config number */ 535d60d43965e46674b9097b422336a55c6ca08559aAlan Cox result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds USB_REQ_GET_CONFIGURATION, USB_DIR_IN, 537401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold 0, 0, data, 1, 3000); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result < 0) { 539d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dev_err(dev, "%s: get config number failed: %d\n", 540d60d43965e46674b9097b422336a55c6ca08559aAlan Cox __func__, result); 541401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold goto out; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result != 1) { 544d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dev_err(dev, "%s: get config number bad return length: %d\n", 545d60d43965e46674b9097b422336a55c6ca08559aAlan Cox __func__, result); 546401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold result = -EIO; 547401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold goto out; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get the interface number */ 551d60d43965e46674b9097b422336a55c6ca08559aAlan Cox result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 552d60d43965e46674b9097b422336a55c6ca08559aAlan Cox USB_REQ_GET_INTERFACE, 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds USB_DIR_IN | USB_RECIP_INTERFACE, 554401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold 0, 0, data, 1, 3000); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result < 0) { 556d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dev_err(dev, "%s: get interface number failed: %d\n", 557d60d43965e46674b9097b422336a55c6ca08559aAlan Cox __func__, result); 558401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold goto out; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result != 1) { 561d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dev_err(dev, 562d60d43965e46674b9097b422336a55c6ca08559aAlan Cox "%s: get interface number bad return length: %d\n", 563d60d43965e46674b9097b422336a55c6ca08559aAlan Cox __func__, result); 564401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold result = -EIO; 565401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold goto out; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 568214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold result = 0; 569401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovoldout: 570401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold kfree(data); 571401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold 572401711cb575bbbdb100bc1a14cb2024dfc9b4869Johan Hovold return result; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 574d60d43965e46674b9097b422336a55c6ca08559aAlan Cox 575d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int treo_attach(struct usb_serial *serial) 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_serial_port *swap_port; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only do this endpoint hack for the Handspring devices with 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interrupt in endpoints, which for now are the Treo devices. */ 581d60d43965e46674b9097b422336a55c6ca08559aAlan Cox if (!((le16_to_cpu(serial->dev->descriptor.idVendor) 582d60d43965e46674b9097b422336a55c6ca08559aAlan Cox == HANDSPRING_VENDOR_ID) || 583d60d43965e46674b9097b422336a55c6ca08559aAlan Cox (le16_to_cpu(serial->dev->descriptor.idVendor) 584d60d43965e46674b9097b422336a55c6ca08559aAlan Cox == KYOCERA_VENDOR_ID)) || 585d60d43965e46674b9097b422336a55c6ca08559aAlan Cox (serial->num_interrupt_in == 0)) 586214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold return 0; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 588441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 591d60d43965e46674b9097b422336a55c6ca08559aAlan Cox * It appears that Treos and Kyoceras want to use the 592d60d43965e46674b9097b422336a55c6ca08559aAlan Cox * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, 593d60d43965e46674b9097b422336a55c6ca08559aAlan Cox * so let's swap the 1st and 2nd bulk in and interrupt endpoints. 594d60d43965e46674b9097b422336a55c6ca08559aAlan Cox * Note that swapping the bulk out endpoints would break lots of 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * apps that want to communicate on the second port. 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define COPY_PORT(dest, src) \ 598d60d43965e46674b9097b422336a55c6ca08559aAlan Cox do { \ 599d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dest->read_urb = src->read_urb; \ 600d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\ 601d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dest->bulk_in_buffer = src->bulk_in_buffer; \ 602d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dest->interrupt_in_urb = src->interrupt_in_urb; \ 603d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dest->interrupt_in_endpointAddress = \ 604d60d43965e46674b9097b422336a55c6ca08559aAlan Cox src->interrupt_in_endpointAddress;\ 605d60d43965e46674b9097b422336a55c6ca08559aAlan Cox dest->interrupt_in_buffer = src->interrupt_in_buffer; \ 606d60d43965e46674b9097b422336a55c6ca08559aAlan Cox } while (0); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!swap_port) 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COPY_PORT(swap_port, serial->port[0]); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COPY_PORT(serial->port[0], serial->port[1]); 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COPY_PORT(serial->port[1], swap_port); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(swap_port); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 616214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold return 0; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 619d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int clie_5_attach(struct usb_serial *serial) 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 621cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold struct usb_serial_port *port; 622cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold unsigned int pipe; 623cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold int j; 624cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold 625441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s", __func__); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 627d60d43965e46674b9097b422336a55c6ca08559aAlan Cox /* TH55 registers 2 ports. 628d60d43965e46674b9097b422336a55c6ca08559aAlan Cox Communication in from the UX50/TH55 uses bulk_in_endpointAddress 629d60d43965e46674b9097b422336a55c6ca08559aAlan Cox from port 0. Communication out to the UX50/TH55 uses 630d60d43965e46674b9097b422336a55c6ca08559aAlan Cox bulk_out_endpointAddress from port 1 631d60d43965e46674b9097b422336a55c6ca08559aAlan Cox 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Lets do a quick and dirty mapping 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 634d60d43965e46674b9097b422336a55c6ca08559aAlan Cox 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* some sanity check */ 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (serial->num_ports < 2) 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 638d60d43965e46674b9097b422336a55c6ca08559aAlan Cox 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* port 0 now uses the modified endpoint Address */ 640cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold port = serial->port[0]; 641cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold port->bulk_out_endpointAddress = 642d60d43965e46674b9097b422336a55c6ca08559aAlan Cox serial->port[1]->bulk_out_endpointAddress; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 644cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold pipe = usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress); 645cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) 646cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold port->write_urbs[j]->pipe = pipe; 647cfb8da8f69b81d367b766888e83ec0483a31bf01Johan Hovold 648214916f2ec6701e1c9972f26c60b3dc37d3153c6Johan Hovold return 0; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651d60d43965e46674b9097b422336a55c6ca08559aAlan Coxstatic int __init visor_init(void) 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, retval; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only if parameters were passed to us */ 655d60d43965e46674b9097b422336a55c6ca08559aAlan Cox if (vendor > 0 && product > 0) { 656d60d43965e46674b9097b422336a55c6ca08559aAlan Cox struct usb_device_id usb_dev_temp[] = { 657d60d43965e46674b9097b422336a55c6ca08559aAlan Cox { 658d60d43965e46674b9097b422336a55c6ca08559aAlan Cox USB_DEVICE(vendor, product), 659d60d43965e46674b9097b422336a55c6ca08559aAlan Cox .driver_info = 660d60d43965e46674b9097b422336a55c6ca08559aAlan Cox (kernel_ulong_t) &palm_os_4_probe 661d60d43965e46674b9097b422336a55c6ca08559aAlan Cox } 662d60d43965e46674b9097b422336a55c6ca08559aAlan Cox }; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Find the last entry in id_table */ 665d60d43965e46674b9097b422336a55c6ca08559aAlan Cox for (i = 0;; i++) { 666d60d43965e46674b9097b422336a55c6ca08559aAlan Cox if (id_table[i].idVendor == 0) { 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_table[i] = usb_dev_temp[0]; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Find the last entry in id_table_combined */ 672d60d43965e46674b9097b422336a55c6ca08559aAlan Cox for (i = 0;; i++) { 673d60d43965e46674b9097b422336a55c6ca08559aAlan Cox if (id_table_combined[i].idVendor == 0) { 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_table_combined[i] = usb_dev_temp[0]; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 678c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman printk(KERN_INFO KBUILD_MODNAME 679c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman ": Untested USB device specified at time of module insertion\n"); 680c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman printk(KERN_INFO KBUILD_MODNAME 681c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman ": Warning: This is not guaranteed to work\n"); 682c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman printk(KERN_INFO KBUILD_MODNAME 683c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman ": Using a newer kernel is preferred to this method\n"); 684c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman printk(KERN_INFO KBUILD_MODNAME 685c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n", 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vendor, product); 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 68929618e9fb5507b9fcf07f739a8506a3640495945Alan Stern retval = usb_serial_register_drivers(&visor_driver, serial_drivers); 69029618e9fb5507b9fcf07f739a8506a3640495945Alan Stern if (retval == 0) 69129618e9fb5507b9fcf07f739a8506a3640495945Alan Stern printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit visor_exit (void) 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 69829618e9fb5507b9fcf07f739a8506a3640495945Alan Stern usb_serial_deregister_drivers(&visor_driver, serial_drivers); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(visor_init); 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(visor_exit); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 705d60d43965e46674b9097b422336a55c6ca08559aAlan CoxMODULE_AUTHOR(DRIVER_AUTHOR); 706d60d43965e46674b9097b422336a55c6ca08559aAlan CoxMODULE_DESCRIPTION(DRIVER_DESC); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, bool, S_IRUGO | S_IWUSR); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug enabled or not"); 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(vendor, ushort, 0); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(vendor, "User specified vendor ID"); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(product, ushort, 0); 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(product, "User specified product ID"); 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 717