visor.c 29.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/*
 * USB HandSpring Visor, Palm m50x, and Sony Clie driver
 * (supports all of the Palm OS USB devices)
 *
 *	Copyright (C) 1999 - 2004
 *	    Greg Kroah-Hartman (greg@kroah.com)
 *
8 9 10
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License version
 *	2 as published by the Free Software Foundation.
L
Linus Torvalds 已提交
11
 *
A
Alan Cox 已提交
12 13
 * See Documentation/usb/usb-serial.txt for more information on using this
 * driver
L
Linus Torvalds 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
A
Alan Cox 已提交
27
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
28
#include <linux/usb.h>
29
#include <linux/usb/serial.h>
L
Linus Torvalds 已提交
30 31 32 33 34 35 36 37 38
#include "visor.h"

/*
 * Version Information
 */
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"

/* function prototypes for a handspring visor */
39
static int  visor_open(struct tty_struct *tty, struct usb_serial_port *port);
40
static void visor_close(struct usb_serial_port *port);
A
Alan Cox 已提交
41 42 43 44 45 46 47
static int  visor_write(struct tty_struct *tty, struct usb_serial_port *port,
					const unsigned char *buf, int count);
static int  visor_write_room(struct tty_struct *tty);
static void visor_throttle(struct tty_struct *tty);
static void visor_unthrottle(struct tty_struct *tty);
static int  visor_probe(struct usb_serial *serial,
					const struct usb_device_id *id);
L
Linus Torvalds 已提交
48
static int  visor_calc_num_ports(struct usb_serial *serial);
49
static void visor_release(struct usb_serial *serial);
A
Alan Cox 已提交
50 51 52 53 54 55 56 57 58 59
static void visor_write_bulk_callback(struct urb *urb);
static void visor_read_bulk_callback(struct urb *urb);
static void visor_read_int_callback(struct urb *urb);
static int  clie_3_5_startup(struct usb_serial *serial);
static int  treo_attach(struct usb_serial *serial);
static int clie_5_attach(struct usb_serial *serial);
static int palm_os_3_probe(struct usb_serial *serial,
					const struct usb_device_id *id);
static int palm_os_4_probe(struct usb_serial *serial,
					const struct usb_device_id *id);
L
Linus Torvalds 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72

/* Parameters that may be passed into the module. */
static int debug;
static __u16 vendor;
static __u16 product;

static struct usb_device_id id_table [] = {
	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID),
		.driver_info = (kernel_ulong_t)&palm_os_3_probe },
	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
73 74
	{ USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
L
Linus Torvalds 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
91 92
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
L
Linus Torvalds 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
109 110
	{ USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
A
Alan Cox 已提交
111
	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
L
Linus Torvalds 已提交
112
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
A
Alan Cox 已提交
113
	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
L
Linus Torvalds 已提交
114
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
115 116
	{ USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
A
Alan Cox 已提交
117
	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
L
Linus Torvalds 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ },					/* optional parameter entry */
	{ }					/* Terminating entry */
};

static struct usb_device_id clie_id_5_table [] = {
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID),
		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
	{ },					/* optional parameter entry */
	{ }					/* Terminating entry */
};

static struct usb_device_id clie_id_3_5_table [] = {
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
	{ }					/* Terminating entry */
};

static struct usb_device_id id_table_combined [] = {
	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) },
	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) },
145
	{ USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID) },
L
Linus Torvalds 已提交
146 147 148 149 150 151 152 153
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M100_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
154
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650) },
L
Linus Torvalds 已提交
155 156 157 158 159 160 161 162 163 164 165 166
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) },
167
	{ USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID) },
L
Linus Torvalds 已提交
168 169 170 171 172 173 174 175
	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
	{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) },
	{ },					/* optional parameter entry */
	{ }					/* Terminating entry */
};

A
Alan Cox 已提交
176
MODULE_DEVICE_TABLE(usb, id_table_combined);
L
Linus Torvalds 已提交
177 178 179 180 181 182

static struct usb_driver visor_driver = {
	.name =		"visor",
	.probe =	usb_serial_probe,
	.disconnect =	usb_serial_disconnect,
	.id_table =	id_table_combined,
183
	.no_dynamic_id = 	1,
L
Linus Torvalds 已提交
184 185
};

A
Alan Cox 已提交
186 187
/* All of the device info needed for the Handspring Visor,
   and Palm 4.0 devices */
188
static struct usb_serial_driver handspring_device = {
189 190
	.driver = {
		.owner =	THIS_MODULE,
191
		.name =		"visor",
192
	},
193
	.description =		"Handspring Visor / Palm OS",
194
	.usb_driver =		&visor_driver,
L
Linus Torvalds 已提交
195 196 197 198 199 200 201 202 203
	.id_table =		id_table,
	.num_ports =		2,
	.open =			visor_open,
	.close =		visor_close,
	.throttle =		visor_throttle,
	.unthrottle =		visor_unthrottle,
	.attach =		treo_attach,
	.probe =		visor_probe,
	.calc_num_ports =	visor_calc_num_ports,
204
	.release =		visor_release,
L
Linus Torvalds 已提交
205 206 207 208 209 210 211 212
	.write =		visor_write,
	.write_room =		visor_write_room,
	.write_bulk_callback =	visor_write_bulk_callback,
	.read_bulk_callback =	visor_read_bulk_callback,
	.read_int_callback =	visor_read_int_callback,
};

/* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */
213
static struct usb_serial_driver clie_5_device = {
214 215
	.driver = {
		.owner =	THIS_MODULE,
216
		.name =		"clie_5",
217
	},
218
	.description =		"Sony Clie 5.0",
219
	.usb_driver =		&visor_driver,
L
Linus Torvalds 已提交
220 221 222 223 224 225 226 227 228
	.id_table =		clie_id_5_table,
	.num_ports =		2,
	.open =			visor_open,
	.close =		visor_close,
	.throttle =		visor_throttle,
	.unthrottle =		visor_unthrottle,
	.attach =		clie_5_attach,
	.probe =		visor_probe,
	.calc_num_ports =	visor_calc_num_ports,
229
	.release =		visor_release,
L
Linus Torvalds 已提交
230 231 232 233 234 235 236 237
	.write =		visor_write,
	.write_room =		visor_write_room,
	.write_bulk_callback =	visor_write_bulk_callback,
	.read_bulk_callback =	visor_read_bulk_callback,
	.read_int_callback =	visor_read_int_callback,
};

/* device info for the Sony Clie OS version 3.5 */
238
static struct usb_serial_driver clie_3_5_device = {
239 240
	.driver = {
		.owner =	THIS_MODULE,
241
		.name =		"clie_3.5",
242
	},
243
	.description =		"Sony Clie 3.5",
244
	.usb_driver =		&visor_driver,
L
Linus Torvalds 已提交
245 246 247 248 249 250 251
	.id_table =		clie_id_3_5_table,
	.num_ports =		1,
	.open =			visor_open,
	.close =		visor_close,
	.throttle =		visor_throttle,
	.unthrottle =		visor_unthrottle,
	.attach =		clie_3_5_startup,
J
Johan Hovold 已提交
252
	.release =		visor_release,
L
Linus Torvalds 已提交
253 254 255 256 257 258 259 260 261 262 263
	.write =		visor_write,
	.write_room =		visor_write_room,
	.write_bulk_callback =	visor_write_bulk_callback,
	.read_bulk_callback =	visor_read_bulk_callback,
};

struct visor_private {
	spinlock_t lock;
	int bytes_in;
	int bytes_out;
	int outstanding_urbs;
264 265
	unsigned char throttled;
	unsigned char actually_throttled;
L
Linus Torvalds 已提交
266 267 268 269 270 271 272 273 274 275
};

/* number of outstanding urbs to prevent userspace DoS from happening */
#define URB_UPPER_LIMIT	42

static int stats;

/******************************************************************************
 * Handspring Visor specific driver functions
 ******************************************************************************/
276
static int visor_open(struct tty_struct *tty, struct usb_serial_port *port)
L
Linus Torvalds 已提交
277 278 279 280 281 282
{
	struct usb_serial *serial = port->serial;
	struct visor_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	int result = 0;

283
	dbg("%s - port %d", __func__, port->number);
L
Linus Torvalds 已提交
284 285 286 287 288 289 290 291 292 293 294 295 296 297

	if (!port->read_urb) {
		/* this is needed for some brain dead Sony devices */
		dev_err(&port->dev, "Device lied about number of ports, please use a lower one.\n");
		return -ENODEV;
	}

	spin_lock_irqsave(&priv->lock, flags);
	priv->bytes_in = 0;
	priv->bytes_out = 0;
	priv->throttled = 0;
	spin_unlock_irqrestore(&priv->lock, flags);

	/* Start reading from the device */
A
Alan Cox 已提交
298 299
	usb_fill_bulk_urb(port->read_urb, serial->dev,
			   usb_rcvbulkpipe(serial->dev,
L
Linus Torvalds 已提交
300 301 302 303 304 305
					    port->bulk_in_endpointAddress),
			   port->read_urb->transfer_buffer,
			   port->read_urb->transfer_buffer_length,
			   visor_read_bulk_callback, port);
	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
	if (result) {
A
Alan Cox 已提交
306 307 308
		dev_err(&port->dev,
			"%s - failed submitting read urb, error %d\n",
							__func__, result);
L
Linus Torvalds 已提交
309 310
		goto exit;
	}
A
Alan Cox 已提交
311

L
Linus Torvalds 已提交
312
	if (port->interrupt_in_urb) {
313
		dbg("%s - adding interrupt input for treo", __func__);
L
Linus Torvalds 已提交
314 315
		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
		if (result)
A
Alan Cox 已提交
316 317 318
			dev_err(&port->dev,
			    "%s - failed submitting interrupt urb, error %d\n",
							__func__, result);
L
Linus Torvalds 已提交
319
	}
A
Alan Cox 已提交
320
exit:
L
Linus Torvalds 已提交
321 322 323 324
	return result;
}


325
static void visor_close(struct usb_serial_port *port)
L
Linus Torvalds 已提交
326 327 328 329
{
	struct visor_private *priv = usb_get_serial_port_data(port);
	unsigned char *transfer_buffer;

330
	dbg("%s - port %d", __func__, port->number);
A
Alan Cox 已提交
331

L
Linus Torvalds 已提交
332 333
	/* shutdown our urbs */
	usb_kill_urb(port->read_urb);
M
Mariusz Kozlowski 已提交
334
	usb_kill_urb(port->interrupt_in_urb);
L
Linus Torvalds 已提交
335

336 337 338
	mutex_lock(&port->serial->disc_mutex);
	if (!port->serial->disconnected) {
		/* Try to send shutdown message, unless the device is gone */
A
Alan Cox 已提交
339
		transfer_buffer =  kmalloc(0x12, GFP_KERNEL);
340
		if (transfer_buffer) {
A
Alan Cox 已提交
341
			usb_control_msg(port->serial->dev,
342 343 344 345
					 usb_rcvctrlpipe(port->serial->dev, 0),
					 VISOR_CLOSE_NOTIFICATION, 0xc2,
					 0x0000, 0x0000,
					 transfer_buffer, 0x12, 300);
A
Alan Cox 已提交
346
			kfree(transfer_buffer);
347
		}
L
Linus Torvalds 已提交
348
	}
349
	mutex_unlock(&port->serial->disc_mutex);
L
Linus Torvalds 已提交
350 351 352 353 354 355 356

	if (stats)
		dev_info(&port->dev, "Bytes In = %d  Bytes Out = %d\n",
			 priv->bytes_in, priv->bytes_out);
}


A
Alan Cox 已提交
357 358
static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
					const unsigned char *buf, int count)
L
Linus Torvalds 已提交
359 360 361 362 363 364 365 366
{
	struct visor_private *priv = usb_get_serial_port_data(port);
	struct usb_serial *serial = port->serial;
	struct urb *urb;
	unsigned char *buffer;
	unsigned long flags;
	int status;

367
	dbg("%s - port %d", __func__, port->number);
L
Linus Torvalds 已提交
368 369 370 371

	spin_lock_irqsave(&priv->lock, flags);
	if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
		spin_unlock_irqrestore(&priv->lock, flags);
372
		dbg("%s - write limit hit", __func__);
L
Linus Torvalds 已提交
373 374
		return 0;
	}
O
Oliver Neukum 已提交
375
	priv->outstanding_urbs++;
L
Linus Torvalds 已提交
376 377
	spin_unlock_irqrestore(&priv->lock, flags);

A
Alan Cox 已提交
378
	buffer = kmalloc(count, GFP_ATOMIC);
L
Linus Torvalds 已提交
379 380
	if (!buffer) {
		dev_err(&port->dev, "out of memory\n");
O
Oliver Neukum 已提交
381 382
		count = -ENOMEM;
		goto error_no_buffer;
L
Linus Torvalds 已提交
383 384 385 386 387
	}

	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb) {
		dev_err(&port->dev, "no more free urbs\n");
O
Oliver Neukum 已提交
388 389
		count = -ENOMEM;
		goto error_no_urb;
L
Linus Torvalds 已提交
390 391
	}

A
Alan Cox 已提交
392
	memcpy(buffer, buf, count);
L
Linus Torvalds 已提交
393

394
	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
L
Linus Torvalds 已提交
395

A
Alan Cox 已提交
396 397
	usb_fill_bulk_urb(urb, serial->dev,
			   usb_sndbulkpipe(serial->dev,
L
Linus Torvalds 已提交
398
					    port->bulk_out_endpointAddress),
A
Alan Cox 已提交
399
			   buffer, count,
L
Linus Torvalds 已提交
400 401 402 403 404
			   visor_write_bulk_callback, port);

	/* send it down the pipe */
	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status) {
A
Alan Cox 已提交
405 406 407
		dev_err(&port->dev,
		   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
							__func__, status);
L
Linus Torvalds 已提交
408
		count = status;
O
Oliver Neukum 已提交
409
		goto error;
L
Linus Torvalds 已提交
410 411 412 413 414 415 416 417
	} else {
		spin_lock_irqsave(&priv->lock, flags);
		priv->bytes_out += count;
		spin_unlock_irqrestore(&priv->lock, flags);
	}

	/* we are done with this urb, so let the host driver
	 * really free it when it is finished with it */
O
Oliver Neukum 已提交
418
	usb_free_urb(urb);
L
Linus Torvalds 已提交
419

O
Oliver Neukum 已提交
420 421 422 423 424 425 426 427 428
	return count;
error:
	usb_free_urb(urb);
error_no_urb:
	kfree(buffer);
error_no_buffer:
	spin_lock_irqsave(&priv->lock, flags);
	--priv->outstanding_urbs;
	spin_unlock_irqrestore(&priv->lock, flags);
L
Linus Torvalds 已提交
429 430 431 432
	return count;
}


A
Alan Cox 已提交
433
static int visor_write_room(struct tty_struct *tty)
L
Linus Torvalds 已提交
434
{
A
Alan Cox 已提交
435
	struct usb_serial_port *port = tty->driver_data;
P
Pete Zaitcev 已提交
436 437 438
	struct visor_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;

439
	dbg("%s - port %d", __func__, port->number);
L
Linus Torvalds 已提交
440 441 442 443

	/*
	 * We really can take anything the user throws at us
	 * but let's pick a nice big number to tell the tty
P
Pete Zaitcev 已提交
444
	 * layer that we have lots of free space, unless we don't.
L
Linus Torvalds 已提交
445
	 */
P
Pete Zaitcev 已提交
446 447 448 449

	spin_lock_irqsave(&priv->lock, flags);
	if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
		spin_unlock_irqrestore(&priv->lock, flags);
450
		dbg("%s - write limit hit", __func__);
P
Pete Zaitcev 已提交
451 452 453 454
		return 0;
	}
	spin_unlock_irqrestore(&priv->lock, flags);

L
Linus Torvalds 已提交
455 456 457 458
	return 2048;
}


A
Alan Cox 已提交
459
static void visor_write_bulk_callback(struct urb *urb)
L
Linus Torvalds 已提交
460
{
461
	struct usb_serial_port *port = urb->context;
L
Linus Torvalds 已提交
462
	struct visor_private *priv = usb_get_serial_port_data(port);
463
	int status = urb->status;
L
Linus Torvalds 已提交
464 465 466
	unsigned long flags;

	/* free up the transfer buffer, as usb_free_urb() does not do this */
A
Alan Cox 已提交
467
	kfree(urb->transfer_buffer);
L
Linus Torvalds 已提交
468

469
	dbg("%s - port %d", __func__, port->number);
470 471

	if (status)
L
Linus Torvalds 已提交
472
		dbg("%s - nonzero write bulk status received: %d",
473
		    __func__, status);
L
Linus Torvalds 已提交
474 475 476 477 478

	spin_lock_irqsave(&priv->lock, flags);
	--priv->outstanding_urbs;
	spin_unlock_irqrestore(&priv->lock, flags);

479
	usb_serial_port_softint(port);
L
Linus Torvalds 已提交
480 481 482
}


A
Alan Cox 已提交
483
static void visor_read_bulk_callback(struct urb *urb)
L
Linus Torvalds 已提交
484
{
485
	struct usb_serial_port *port = urb->context;
L
Linus Torvalds 已提交
486 487
	struct visor_private *priv = usb_get_serial_port_data(port);
	unsigned char *data = urb->transfer_buffer;
488
	int status = urb->status;
L
Linus Torvalds 已提交
489 490
	struct tty_struct *tty;
	int result;
A
Alan Cox 已提交
491
	int available_room = 0;
L
Linus Torvalds 已提交
492

493
	dbg("%s - port %d", __func__, port->number);
L
Linus Torvalds 已提交
494

495 496
	if (status) {
		dbg("%s - nonzero read bulk status received: %d",
497
		    __func__, status);
L
Linus Torvalds 已提交
498 499 500
		return;
	}

A
Alan Cox 已提交
501 502
	usb_serial_debug_data(debug, &port->dev, __func__,
						urb->actual_length, data);
L
Linus Torvalds 已提交
503

A
Alan Cox 已提交
504 505 506
	if (urb->actual_length) {
		tty = tty_port_tty_get(&port->port);
		if (tty) {
507 508 509
			tty_insert_flip_string(tty, data,
						urb->actual_length);
			tty_flip_buffer_push(tty);
A
Alan Cox 已提交
510
			tty_kref_put(tty);
511 512
		}
		spin_lock(&priv->lock);
513 514
		if (tty)
			priv->bytes_in += available_room;
515 516 517

	} else {
		spin_lock(&priv->lock);
L
Linus Torvalds 已提交
518 519 520
	}

	/* Continue trying to always read if we should */
521
	if (!priv->throttled) {
A
Alan Cox 已提交
522
		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
L
Linus Torvalds 已提交
523
				   usb_rcvbulkpipe(port->serial->dev,
A
Alan Cox 已提交
524
					   port->bulk_in_endpointAddress),
L
Linus Torvalds 已提交
525 526 527 528 529
				   port->read_urb->transfer_buffer,
				   port->read_urb->transfer_buffer_length,
				   visor_read_bulk_callback, port);
		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
		if (result)
A
Alan Cox 已提交
530 531 532 533
			dev_err(&port->dev,
			    "%s - failed resubmitting read urb, error %d\n",
							__func__, result);
	} else
534 535
		priv->actually_throttled = 1;
	spin_unlock(&priv->lock);
L
Linus Torvalds 已提交
536 537
}

A
Alan Cox 已提交
538
static void visor_read_int_callback(struct urb *urb)
L
Linus Torvalds 已提交
539
{
540
	struct usb_serial_port *port = urb->context;
541
	int status = urb->status;
L
Linus Torvalds 已提交
542 543
	int result;

544
	switch (status) {
L
Linus Torvalds 已提交
545 546 547 548 549 550 551 552
	case 0:
		/* success */
		break;
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		/* this urb is terminated, clean up */
		dbg("%s - urb shutting down with status: %d",
553
		    __func__, status);
L
Linus Torvalds 已提交
554 555 556
		return;
	default:
		dbg("%s - nonzero urb status received: %d",
557
		    __func__, status);
L
Linus Torvalds 已提交
558 559 560 561 562 563 564 565 566 567
		goto exit;
	}

	/*
	 * This information is still unknown what it can be used for.
	 * If anyone has an idea, please let the author know...
	 *
	 * Rumor has it this endpoint is used to notify when data
	 * is ready to be read from the bulk ones.
	 */
568
	usb_serial_debug_data(debug, &port->dev, __func__,
L
Linus Torvalds 已提交
569 570 571
			      urb->actual_length, urb->transfer_buffer);

exit:
A
Alan Cox 已提交
572
	result = usb_submit_urb(urb, GFP_ATOMIC);
L
Linus Torvalds 已提交
573
	if (result)
A
Alan Cox 已提交
574 575 576
		dev_err(&urb->dev->dev,
				"%s - Error %d submitting interrupt urb\n",
							__func__, result);
L
Linus Torvalds 已提交
577 578
}

A
Alan Cox 已提交
579
static void visor_throttle(struct tty_struct *tty)
L
Linus Torvalds 已提交
580
{
A
Alan Cox 已提交
581
	struct usb_serial_port *port = tty->driver_data;
L
Linus Torvalds 已提交
582 583
	struct visor_private *priv = usb_get_serial_port_data(port);

584
	dbg("%s - port %d", __func__, port->number);
585
	spin_lock_irq(&priv->lock);
L
Linus Torvalds 已提交
586
	priv->throttled = 1;
587
	spin_unlock_irq(&priv->lock);
L
Linus Torvalds 已提交
588 589 590
}


A
Alan Cox 已提交
591
static void visor_unthrottle(struct tty_struct *tty)
L
Linus Torvalds 已提交
592
{
A
Alan Cox 已提交
593
	struct usb_serial_port *port = tty->driver_data;
L
Linus Torvalds 已提交
594
	struct visor_private *priv = usb_get_serial_port_data(port);
595
	int result, was_throttled;
L
Linus Torvalds 已提交
596

597
	dbg("%s - port %d", __func__, port->number);
598
	spin_lock_irq(&priv->lock);
L
Linus Torvalds 已提交
599
	priv->throttled = 0;
600
	was_throttled = priv->actually_throttled;
601
	priv->actually_throttled = 0;
602
	spin_unlock_irq(&priv->lock);
L
Linus Torvalds 已提交
603

604 605 606 607 608 609
	if (was_throttled) {
		port->read_urb->dev = port->serial->dev;
		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
		if (result)
			dev_err(&port->dev,
				"%s - failed submitting read urb, error %d\n",
A
Alan Cox 已提交
610
							__func__, result);
611
	}
L
Linus Torvalds 已提交
612 613
}

A
Alan Cox 已提交
614 615
static int palm_os_3_probe(struct usb_serial *serial,
						const struct usb_device_id *id)
L
Linus Torvalds 已提交
616 617 618 619 620 621 622 623 624
{
	struct device *dev = &serial->dev->dev;
	struct visor_connection_info *connection_info;
	unsigned char *transfer_buffer;
	char *string;
	int retval = 0;
	int i;
	int num_ports = 0;

625
	dbg("%s", __func__);
L
Linus Torvalds 已提交
626

A
Alan Cox 已提交
627
	transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
L
Linus Torvalds 已提交
628
	if (!transfer_buffer) {
629
		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
L
Linus Torvalds 已提交
630 631 632 633 634
			sizeof(*connection_info));
		return -ENOMEM;
	}

	/* send a get connection info request */
A
Alan Cox 已提交
635
	retval = usb_control_msg(serial->dev,
L
Linus Torvalds 已提交
636 637 638 639 640 641
				  usb_rcvctrlpipe(serial->dev, 0),
				  VISOR_GET_CONNECTION_INFORMATION,
				  0xc2, 0x0000, 0x0000, transfer_buffer,
				  sizeof(*connection_info), 300);
	if (retval < 0) {
		dev_err(dev, "%s - error %d getting connection information\n",
642
			__func__, retval);
L
Linus Torvalds 已提交
643 644 645 646
		goto exit;
	}

	if (retval == sizeof(*connection_info)) {
A
Alan Cox 已提交
647 648
			connection_info = (struct visor_connection_info *)
							transfer_buffer;
L
Linus Torvalds 已提交
649 650 651

		num_ports = le16_to_cpu(connection_info->num_ports);
		for (i = 0; i < num_ports; ++i) {
A
Alan Cox 已提交
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
			switch (
			   connection_info->connections[i].port_function_id) {
			case VISOR_FUNCTION_GENERIC:
				string = "Generic";
				break;
			case VISOR_FUNCTION_DEBUGGER:
				string = "Debugger";
				break;
			case VISOR_FUNCTION_HOTSYNC:
				string = "HotSync";
				break;
			case VISOR_FUNCTION_CONSOLE:
				string = "Console";
				break;
			case VISOR_FUNCTION_REMOTE_FILE_SYS:
				string = "Remote File System";
				break;
			default:
				string = "unknown";
				break;
L
Linus Torvalds 已提交
672 673
			}
			dev_info(dev, "%s: port %d, is for %s use\n",
674
				serial->type->description,
L
Linus Torvalds 已提交
675 676 677 678 679 680 681
				connection_info->connections[i].port, string);
		}
	}
	/*
	* Handle devices that report invalid stuff here.
	*/
	if (num_ports == 0 || num_ports > 2) {
A
Alan Cox 已提交
682
		dev_warn(dev, "%s: No valid connect info available\n",
683
			serial->type->description);
L
Linus Torvalds 已提交
684 685
		num_ports = 2;
	}
A
Alan Cox 已提交
686

687
	dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
L
Linus Torvalds 已提交
688 689 690 691 692 693 694 695
		num_ports);

	/*
	 * save off our num_ports info so that we can use it in the
	 * calc_num_ports callback
	 */
	usb_set_serial_data(serial, (void *)(long)num_ports);

A
Alan Cox 已提交
696 697 698
	/* ask for the number of bytes available, but ignore the
	   response as it is broken */
	retval = usb_control_msg(serial->dev,
L
Linus Torvalds 已提交
699 700 701 702 703 704
				  usb_rcvctrlpipe(serial->dev, 0),
				  VISOR_REQUEST_BYTES_AVAILABLE,
				  0xc2, 0x0000, 0x0005, transfer_buffer,
				  0x02, 300);
	if (retval < 0)
		dev_err(dev, "%s - error %d getting bytes available request\n",
705
			__func__, retval);
L
Linus Torvalds 已提交
706 707 708
	retval = 0;

exit:
A
Alan Cox 已提交
709
	kfree(transfer_buffer);
L
Linus Torvalds 已提交
710 711 712 713

	return retval;
}

A
Alan Cox 已提交
714 715
static int palm_os_4_probe(struct usb_serial *serial,
						const struct usb_device_id *id)
L
Linus Torvalds 已提交
716 717 718 719 720 721
{
	struct device *dev = &serial->dev->dev;
	struct palm_ext_connection_info *connection_info;
	unsigned char *transfer_buffer;
	int retval;

722
	dbg("%s", __func__);
L
Linus Torvalds 已提交
723

A
Alan Cox 已提交
724
	transfer_buffer =  kmalloc(sizeof(*connection_info), GFP_KERNEL);
L
Linus Torvalds 已提交
725
	if (!transfer_buffer) {
726
		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
L
Linus Torvalds 已提交
727 728 729 730
			sizeof(*connection_info));
		return -ENOMEM;
	}

A
Alan Cox 已提交
731 732
	retval = usb_control_msg(serial->dev,
				  usb_rcvctrlpipe(serial->dev, 0),
L
Linus Torvalds 已提交
733 734
				  PALM_GET_EXT_CONNECTION_INFORMATION,
				  0xc2, 0x0000, 0x0000, transfer_buffer,
A
Alan Cox 已提交
735
				  sizeof(*connection_info), 300);
L
Linus Torvalds 已提交
736 737
	if (retval < 0)
		dev_err(dev, "%s - error %d getting connection info\n",
738
			__func__, retval);
L
Linus Torvalds 已提交
739
	else
740
		usb_serial_debug_data(debug, &serial->dev->dev, __func__,
L
Linus Torvalds 已提交
741 742
				      retval, transfer_buffer);

A
Alan Cox 已提交
743
	kfree(transfer_buffer);
L
Linus Torvalds 已提交
744 745 746 747
	return 0;
}


A
Alan Cox 已提交
748 749
static int visor_probe(struct usb_serial *serial,
					const struct usb_device_id *id)
L
Linus Torvalds 已提交
750 751
{
	int retval = 0;
A
Alan Cox 已提交
752 753
	int (*startup)(struct usb_serial *serial,
					const struct usb_device_id *id);
L
Linus Torvalds 已提交
754

755
	dbg("%s", __func__);
L
Linus Torvalds 已提交
756 757

	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
758
		dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
L
Linus Torvalds 已提交
759 760 761 762 763 764 765 766 767 768 769 770
			serial->dev->actconfig->desc.bConfigurationValue);
		return -ENODEV;
	}

	if (id->driver_info) {
		startup = (void *)id->driver_info;
		retval = startup(serial, id);
	}

	return retval;
}

A
Alan Cox 已提交
771
static int visor_calc_num_ports(struct usb_serial *serial)
L
Linus Torvalds 已提交
772 773 774 775 776 777 778 779 780 781 782
{
	int num_ports = (int)(long)(usb_get_serial_data(serial));

	if (num_ports)
		usb_set_serial_data(serial, NULL);

	return num_ports;
}

static int generic_startup(struct usb_serial *serial)
{
P
Pete Zaitcev 已提交
783
	struct usb_serial_port **ports = serial->port;
L
Linus Torvalds 已提交
784 785 786 787
	struct visor_private *priv;
	int i;

	for (i = 0; i < serial->num_ports; ++i) {
A
Alan Cox 已提交
788
		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
P
Pete Zaitcev 已提交
789 790 791 792 793 794
		if (!priv) {
			while (i-- != 0) {
				priv = usb_get_serial_port_data(ports[i]);
				usb_set_serial_port_data(ports[i], NULL);
				kfree(priv);
			}
L
Linus Torvalds 已提交
795
			return -ENOMEM;
P
Pete Zaitcev 已提交
796
		}
L
Linus Torvalds 已提交
797
		spin_lock_init(&priv->lock);
P
Pete Zaitcev 已提交
798
		usb_set_serial_port_data(ports[i], priv);
L
Linus Torvalds 已提交
799 800 801 802
	}
	return 0;
}

A
Alan Cox 已提交
803
static int clie_3_5_startup(struct usb_serial *serial)
L
Linus Torvalds 已提交
804 805 806
{
	struct device *dev = &serial->dev->dev;
	int result;
807
	u8 *data;
L
Linus Torvalds 已提交
808

809
	dbg("%s", __func__);
L
Linus Torvalds 已提交
810

811 812 813 814
	data = kmalloc(1, GFP_KERNEL);
	if (!data)
		return -ENOMEM;

L
Linus Torvalds 已提交
815 816 817 818 819
	/*
	 * Note that PEG-300 series devices expect the following two calls.
	 */

	/* get the config number */
A
Alan Cox 已提交
820
	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
L
Linus Torvalds 已提交
821
				  USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
822
				  0, 0, data, 1, 3000);
L
Linus Torvalds 已提交
823
	if (result < 0) {
A
Alan Cox 已提交
824 825
		dev_err(dev, "%s: get config number failed: %d\n",
							__func__, result);
826
		goto out;
L
Linus Torvalds 已提交
827 828
	}
	if (result != 1) {
A
Alan Cox 已提交
829 830
		dev_err(dev, "%s: get config number bad return length: %d\n",
							__func__, result);
831 832
		result = -EIO;
		goto out;
L
Linus Torvalds 已提交
833 834 835
	}

	/* get the interface number */
A
Alan Cox 已提交
836 837
	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
				  USB_REQ_GET_INTERFACE,
L
Linus Torvalds 已提交
838
				  USB_DIR_IN | USB_RECIP_INTERFACE,
839
				  0, 0, data, 1, 3000);
L
Linus Torvalds 已提交
840
	if (result < 0) {
A
Alan Cox 已提交
841 842
		dev_err(dev, "%s: get interface number failed: %d\n",
							__func__, result);
843
		goto out;
L
Linus Torvalds 已提交
844 845
	}
	if (result != 1) {
A
Alan Cox 已提交
846 847 848
		dev_err(dev,
			"%s: get interface number bad return length: %d\n",
							__func__, result);
849 850
		result = -EIO;
		goto out;
L
Linus Torvalds 已提交
851 852
	}

853 854 855 856 857
	result = generic_startup(serial);
out:
	kfree(data);

	return result;
L
Linus Torvalds 已提交
858
}
A
Alan Cox 已提交
859 860

static int treo_attach(struct usb_serial *serial)
L
Linus Torvalds 已提交
861 862 863 864 865
{
	struct usb_serial_port *swap_port;

	/* Only do this endpoint hack for the Handspring devices with
	 * interrupt in endpoints, which for now are the Treo devices. */
A
Alan Cox 已提交
866 867 868 869 870
	if (!((le16_to_cpu(serial->dev->descriptor.idVendor)
						== HANDSPRING_VENDOR_ID) ||
		(le16_to_cpu(serial->dev->descriptor.idVendor)
						== KYOCERA_VENDOR_ID)) ||
		(serial->num_interrupt_in == 0))
L
Linus Torvalds 已提交
871 872
		goto generic_startup;

873
	dbg("%s", __func__);
L
Linus Torvalds 已提交
874 875

	/*
A
Alan Cox 已提交
876 877 878 879
	* It appears that Treos and Kyoceras want to use the
	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
	* so let's swap the 1st and 2nd bulk in and interrupt endpoints.
	* Note that swapping the bulk out endpoints would break lots of
L
Linus Torvalds 已提交
880 881 882
	* apps that want to communicate on the second port.
	*/
#define COPY_PORT(dest, src)						\
A
Alan Cox 已提交
883 884 885 886 887 888 889 890 891
	do { \
		dest->read_urb = src->read_urb;				\
		dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
		dest->bulk_in_buffer = src->bulk_in_buffer;		\
		dest->interrupt_in_urb = src->interrupt_in_urb;		\
		dest->interrupt_in_endpointAddress = \
					src->interrupt_in_endpointAddress;\
		dest->interrupt_in_buffer = src->interrupt_in_buffer;	\
	} while (0);
L
Linus Torvalds 已提交
892 893 894 895 896 897 898 899 900 901 902 903 904

	swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
	if (!swap_port)
		return -ENOMEM;
	COPY_PORT(swap_port, serial->port[0]);
	COPY_PORT(serial->port[0], serial->port[1]);
	COPY_PORT(serial->port[1], swap_port);
	kfree(swap_port);

generic_startup:
	return generic_startup(serial);
}

A
Alan Cox 已提交
905
static int clie_5_attach(struct usb_serial *serial)
L
Linus Torvalds 已提交
906
{
907
	dbg("%s", __func__);
L
Linus Torvalds 已提交
908

A
Alan Cox 已提交
909 910 911 912 913
	/* TH55 registers 2 ports.
	   Communication in from the UX50/TH55 uses bulk_in_endpointAddress
	   from port 0. Communication out to the UX50/TH55 uses
	   bulk_out_endpointAddress from port 1

L
Linus Torvalds 已提交
914 915
	   Lets do a quick and dirty mapping
	 */
A
Alan Cox 已提交
916

L
Linus Torvalds 已提交
917 918 919
	/* some sanity check */
	if (serial->num_ports < 2)
		return -1;
A
Alan Cox 已提交
920

L
Linus Torvalds 已提交
921
	/* port 0 now uses the modified endpoint Address */
A
Alan Cox 已提交
922 923
	serial->port[0]->bulk_out_endpointAddress =
				serial->port[1]->bulk_out_endpointAddress;
L
Linus Torvalds 已提交
924 925 926 927

	return generic_startup(serial);
}

928
static void visor_release(struct usb_serial *serial)
L
Linus Torvalds 已提交
929
{
P
Pete Zaitcev 已提交
930 931 932
	struct visor_private *priv;
	int i;

933
	dbg("%s", __func__);
P
Pete Zaitcev 已提交
934 935 936

	for (i = 0; i < serial->num_ports; i++) {
		priv = usb_get_serial_port_data(serial->port[i]);
937
		kfree(priv);
P
Pete Zaitcev 已提交
938
	}
L
Linus Torvalds 已提交
939 940
}

A
Alan Cox 已提交
941
static int __init visor_init(void)
L
Linus Torvalds 已提交
942 943 944
{
	int i, retval;
	/* Only if parameters were passed to us */
A
Alan Cox 已提交
945 946 947 948 949 950 951 952
	if (vendor > 0 && product > 0) {
		struct usb_device_id usb_dev_temp[] = {
			{
				USB_DEVICE(vendor, product),
				.driver_info =
					(kernel_ulong_t) &palm_os_4_probe
			}
		};
L
Linus Torvalds 已提交
953 954

		/* Find the last entry in id_table */
A
Alan Cox 已提交
955 956
		for (i = 0;; i++) {
			if (id_table[i].idVendor == 0) {
L
Linus Torvalds 已提交
957 958 959 960 961
				id_table[i] = usb_dev_temp[0];
				break;
			}
		}
		/* Find the last entry in id_table_combined */
A
Alan Cox 已提交
962 963
		for (i = 0;; i++) {
			if (id_table_combined[i].idVendor == 0) {
L
Linus Torvalds 已提交
964 965 966 967
				id_table_combined[i] = usb_dev_temp[0];
				break;
			}
		}
968 969 970 971 972 973 974 975
		printk(KERN_INFO KBUILD_MODNAME
		       ": Untested USB device specified at time of module insertion\n");
		printk(KERN_INFO KBUILD_MODNAME
		       ": Warning: This is not guaranteed to work\n");
		printk(KERN_INFO KBUILD_MODNAME
		       ": Using a newer kernel is preferred to this method\n");
		printk(KERN_INFO KBUILD_MODNAME
		       ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
L
Linus Torvalds 已提交
976 977 978 979 980 981 982 983 984 985 986 987
			vendor, product);
	}
	retval = usb_serial_register(&handspring_device);
	if (retval)
		goto failed_handspring_register;
	retval = usb_serial_register(&clie_3_5_device);
	if (retval)
		goto failed_clie_3_5_register;
	retval = usb_serial_register(&clie_5_device);
	if (retval)
		goto failed_clie_5_register;
	retval = usb_register(&visor_driver);
A
Alan Cox 已提交
988
	if (retval)
L
Linus Torvalds 已提交
989
		goto failed_usb_register;
990
	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
L
Linus Torvalds 已提交
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005

	return 0;
failed_usb_register:
	usb_serial_deregister(&clie_5_device);
failed_clie_5_register:
	usb_serial_deregister(&clie_3_5_device);
failed_clie_3_5_register:
	usb_serial_deregister(&handspring_device);
failed_handspring_register:
	return retval;
}


static void __exit visor_exit (void)
{
A
Alan Cox 已提交
1006 1007 1008 1009
	usb_deregister(&visor_driver);
	usb_serial_deregister(&handspring_device);
	usb_serial_deregister(&clie_3_5_device);
	usb_serial_deregister(&clie_5_device);
L
Linus Torvalds 已提交
1010 1011 1012 1013 1014 1015
}


module_init(visor_init);
module_exit(visor_exit);

A
Alan Cox 已提交
1016 1017
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
L
Linus Torvalds 已提交
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
MODULE_LICENSE("GPL");

module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(stats, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(stats, "Enables statistics or not");

module_param(vendor, ushort, 0);
MODULE_PARM_DESC(vendor, "User specified vendor ID");
module_param(product, ushort, 0);
MODULE_PARM_DESC(product, "User specified product ID");