generic.c 12.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 * USB Serial Converter Generic functions
 *
4
 * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com)
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15
 * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
 *
 *	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.
 *
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
16
#include <linux/sysrq.h>
L
Linus Torvalds 已提交
17 18 19 20 21
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/usb.h>
22
#include <linux/usb/serial.h>
A
Alan Cox 已提交
23
#include <linux/uaccess.h>
24
#include <linux/kfifo.h>
25
#include <linux/serial.h>
26

L
Linus Torvalds 已提交
27
#ifdef CONFIG_USB_SERIAL_GENERIC
28

L
Linus Torvalds 已提交
29 30 31 32 33 34 35 36 37 38 39 40
static __u16 vendor  = 0x05f9;
static __u16 product = 0xffff;

module_param(vendor, ushort, 0);
MODULE_PARM_DESC(vendor, "User specified USB idVendor");

module_param(product, ushort, 0);
MODULE_PARM_DESC(product, "User specified USB idProduct");

static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */

/* All of the device info needed for the Generic Serial Converter */
41
struct usb_serial_driver usb_serial_generic_device = {
42 43
	.driver = {
		.owner =	THIS_MODULE,
44
		.name =		"generic",
45
	},
L
Linus Torvalds 已提交
46 47
	.id_table =		generic_device_ids,
	.num_ports =		1,
48
	.release =		usb_serial_generic_release,
49 50
	.throttle =		usb_serial_generic_throttle,
	.unthrottle =		usb_serial_generic_unthrottle,
51
	.resume =		usb_serial_generic_resume,
L
Linus Torvalds 已提交
52 53
};

54 55 56 57
static struct usb_serial_driver * const serial_drivers[] = {
	&usb_serial_generic_device, NULL
};

L
Linus Torvalds 已提交
58 59
#endif

60
int usb_serial_generic_register(void)
L
Linus Torvalds 已提交
61 62 63 64 65 66
{
	int retval = 0;

#ifdef CONFIG_USB_SERIAL_GENERIC
	generic_device_ids[0].idVendor = vendor;
	generic_device_ids[0].idProduct = product;
A
Alan Cox 已提交
67 68
	generic_device_ids[0].match_flags =
		USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
L
Linus Torvalds 已提交
69 70

	/* register our generic driver with ourselves */
71 72
	retval = usb_serial_register_drivers(serial_drivers,
			"usbserial_generic", generic_device_ids);
L
Linus Torvalds 已提交
73 74 75 76
#endif
	return retval;
}

A
Alan Cox 已提交
77
void usb_serial_generic_deregister(void)
L
Linus Torvalds 已提交
78 79 80
{
#ifdef CONFIG_USB_SERIAL_GENERIC
	/* remove our generic driver */
81
	usb_serial_deregister_drivers(serial_drivers);
L
Linus Torvalds 已提交
82 83 84
#endif
}

85
int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port)
L
Linus Torvalds 已提交
86 87
{
	int result = 0;
88
	unsigned long flags;
L
Linus Torvalds 已提交
89

90 91 92 93 94 95 96
	/* clear the throttle flags */
	spin_lock_irqsave(&port->lock, flags);
	port->throttled = 0;
	port->throttle_req = 0;
	spin_unlock_irqrestore(&port->lock, flags);

	/* if we have a bulk endpoint, start reading from it */
97
	if (port->bulk_in_size)
98
		result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
L
Linus Torvalds 已提交
99 100 101

	return result;
}
102
EXPORT_SYMBOL_GPL(usb_serial_generic_open);
L
Linus Torvalds 已提交
103

104
void usb_serial_generic_close(struct usb_serial_port *port)
L
Linus Torvalds 已提交
105
{
J
Johan Hovold 已提交
106
	unsigned long flags;
107
	int i;
L
Linus Torvalds 已提交
108

109 110 111 112 113 114 115 116 117 118 119
	if (port->bulk_out_size) {
		for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
			usb_kill_urb(port->write_urbs[i]);

		spin_lock_irqsave(&port->lock, flags);
		kfifo_reset_out(&port->write_fifo);
		spin_unlock_irqrestore(&port->lock, flags);
	}
	if (port->bulk_in_size) {
		for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
			usb_kill_urb(port->read_urbs[i]);
L
Linus Torvalds 已提交
120 121
	}
}
122
EXPORT_SYMBOL_GPL(usb_serial_generic_close);
L
Linus Torvalds 已提交
123

124
int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port,
125
						void *dest, size_t size)
126
{
127
	return kfifo_out_locked(&port->write_fifo, dest, size, &port->lock);
128 129
}

130 131 132 133
/**
 * usb_serial_generic_write_start - kick off an URB write
 * @port:	Pointer to the &struct usb_serial_port data
 *
134
 * Returns zero on success, or a negative errno value
135 136 137
 */
static int usb_serial_generic_write_start(struct usb_serial_port *port)
{
138 139
	struct urb *urb;
	int count, result;
140
	unsigned long flags;
141
	int i;
142

143 144 145
	if (test_and_set_bit_lock(USB_SERIAL_WRITE_BUSY, &port->flags))
		return 0;
retry:
146
	spin_lock_irqsave(&port->lock, flags);
147 148
	if (!port->write_urbs_free || !kfifo_len(&port->write_fifo)) {
		clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
149 150
		spin_unlock_irqrestore(&port->lock, flags);
		return 0;
151
	}
152 153
	i = (int)find_first_bit(&port->write_urbs_free,
						ARRAY_SIZE(port->write_urbs));
154 155
	spin_unlock_irqrestore(&port->lock, flags);

156
	urb = port->write_urbs[i];
157
	count = port->serial->type->prepare_write_buffer(port,
158 159
						urb->transfer_buffer,
						port->bulk_out_size);
160
	urb->transfer_buffer_length = count;
161
	usb_serial_debug_data(&port->dev, __func__, count, urb->transfer_buffer);
J
Johan Hovold 已提交
162 163 164 165 166
	spin_lock_irqsave(&port->lock, flags);
	port->tx_bytes += count;
	spin_unlock_irqrestore(&port->lock, flags);

	clear_bit(i, &port->write_urbs_free);
167
	result = usb_submit_urb(urb, GFP_ATOMIC);
168
	if (result) {
169
		dev_err_console(port, "%s - error submitting urb: %d\n",
170
						__func__, result);
J
Johan Hovold 已提交
171 172 173 174 175
		set_bit(i, &port->write_urbs_free);
		spin_lock_irqsave(&port->lock, flags);
		port->tx_bytes -= count;
		spin_unlock_irqrestore(&port->lock, flags);

176
		clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
177 178 179
		return result;
	}

180 181 182 183 184 185 186 187
	/* Try sending off another urb, unless in irq context (in which case
	 * there will be no free urb). */
	if (!in_irq())
		goto retry;

	clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);

	return 0;
188 189 190 191 192 193 194 195 196 197 198 199 200
}

/**
 * usb_serial_generic_write - generic write function for serial USB devices
 * @tty:	Pointer to &struct tty_struct for the device
 * @port:	Pointer to the &usb_serial_port structure for the device
 * @buf:	Pointer to the data to write
 * @count:	Number of bytes to write
 *
 * Returns the number of characters actually written, which may be anything
 * from zero to @count. If an error occurs, it returns the negative errno
 * value.
 */
A
Alan Cox 已提交
201 202
int usb_serial_generic_write(struct tty_struct *tty,
	struct usb_serial_port *port, const unsigned char *buf, int count)
L
Linus Torvalds 已提交
203 204 205
{
	int result;

206 207 208 209
	/* only do something if we have a bulk out endpoint */
	if (!port->bulk_out_size)
		return -ENODEV;

210
	if (!count)
A
Alan Cox 已提交
211
		return 0;
L
Linus Torvalds 已提交
212

213
	count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
214
	result = usb_serial_generic_write_start(port);
215 216
	if (result)
		return result;
L
Linus Torvalds 已提交
217

218
	return count;
L
Linus Torvalds 已提交
219
}
220
EXPORT_SYMBOL_GPL(usb_serial_generic_write);
L
Linus Torvalds 已提交
221

A
Alan Cox 已提交
222
int usb_serial_generic_write_room(struct tty_struct *tty)
L
Linus Torvalds 已提交
223
{
A
Alan Cox 已提交
224
	struct usb_serial_port *port = tty->driver_data;
225
	unsigned long flags;
226
	int room;
L
Linus Torvalds 已提交
227

228 229 230
	if (!port->bulk_out_size)
		return 0;

231
	spin_lock_irqsave(&port->lock, flags);
232
	room = kfifo_avail(&port->write_fifo);
233
	spin_unlock_irqrestore(&port->lock, flags);
L
Linus Torvalds 已提交
234

235
	dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
236
	return room;
L
Linus Torvalds 已提交
237 238
}

A
Alan Cox 已提交
239
int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
L
Linus Torvalds 已提交
240
{
A
Alan Cox 已提交
241
	struct usb_serial_port *port = tty->driver_data;
242
	unsigned long flags;
243
	int chars;
L
Linus Torvalds 已提交
244

245 246 247
	if (!port->bulk_out_size)
		return 0;

248
	spin_lock_irqsave(&port->lock, flags);
249
	chars = kfifo_len(&port->write_fifo) + port->tx_bytes;
250
	spin_unlock_irqrestore(&port->lock, flags);
L
Linus Torvalds 已提交
251

252
	dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
A
Alan Cox 已提交
253
	return chars;
L
Linus Torvalds 已提交
254
}
255
EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);
L
Linus Torvalds 已提交
256

257 258 259 260 261 262 263 264
static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
						int index, gfp_t mem_flags)
{
	int res;

	if (!test_and_clear_bit(index, &port->read_urbs_free))
		return 0;

265
	dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

	res = usb_submit_urb(port->read_urbs[index], mem_flags);
	if (res) {
		if (res != -EPERM) {
			dev_err(&port->dev,
					"%s - usb_submit_urb failed: %d\n",
					__func__, res);
		}
		set_bit(index, &port->read_urbs_free);
		return res;
	}

	return 0;
}

int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,
282
					gfp_t mem_flags)
L
Linus Torvalds 已提交
283
{
284 285
	int res;
	int i;
L
Linus Torvalds 已提交
286

287 288 289 290
	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
		res = usb_serial_generic_submit_read_urb(port, i, mem_flags);
		if (res)
			goto err;
291
	}
292 293 294 295 296 297 298

	return 0;
err:
	for (; i >= 0; --i)
		usb_kill_urb(port->read_urbs[i]);

	return res;
L
Linus Torvalds 已提交
299
}
300
EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urbs);
301

302
void usb_serial_generic_process_read_urb(struct urb *urb)
303
{
304
	struct usb_serial_port *port = urb->context;
305 306 307
	char *ch = (char *)urb->transfer_buffer;
	int i;

308 309 310
	if (!urb->actual_length)
		return;

311 312 313
	/* The per character mucking around with sysrq path it too slow for
	   stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases
	   where the USB serial is not a console anyway */
314
	if (!port->port.console || !port->sysrq)
J
Jiri Slaby 已提交
315
		tty_insert_flip_string(&port->port, ch, urb->actual_length);
316 317
	else {
		for (i = 0; i < urb->actual_length; i++, ch++) {
318
			if (!usb_serial_handle_sysrq_char(port, *ch))
J
Jiri Slaby 已提交
319
				tty_insert_flip_char(&port->port, *ch, TTY_NORMAL);
320
		}
321
	}
J
Jiri Slaby 已提交
322
	tty_flip_buffer_push(&port->port);
323
}
324
EXPORT_SYMBOL_GPL(usb_serial_generic_process_read_urb);
325

A
Alan Cox 已提交
326
void usb_serial_generic_read_bulk_callback(struct urb *urb)
327
{
328
	struct usb_serial_port *port = urb->context;
329
	unsigned char *data = urb->transfer_buffer;
330
	unsigned long flags;
331
	int i;
332

333 334 335 336 337
	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
		if (urb == port->read_urbs[i])
			break;
	}
	set_bit(i, &port->read_urbs_free);
338

339 340
	dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
							urb->actual_length);
341

342
	if (urb->status) {
343 344
		dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
			__func__, urb->status);
345 346 347
		return;
	}

348
	usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
349
	port->serial->type->process_read_urb(urb);
350 351

	/* Throttle the device if requested by tty */
352
	spin_lock_irqsave(&port->lock, flags);
A
Alan Cox 已提交
353 354
	port->throttled = port->throttle_req;
	if (!port->throttled) {
355
		spin_unlock_irqrestore(&port->lock, flags);
356
		usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);
A
Alan Cox 已提交
357
	} else
358
		spin_unlock_irqrestore(&port->lock, flags);
359
}
360
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
L
Linus Torvalds 已提交
361

A
Alan Cox 已提交
362
void usb_serial_generic_write_bulk_callback(struct urb *urb)
L
Linus Torvalds 已提交
363
{
364
	unsigned long flags;
365
	struct usb_serial_port *port = urb->context;
366
	int status = urb->status;
367
	int i;
L
Linus Torvalds 已提交
368

369 370 371
	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
		if (port->write_urbs[i] == urb)
			break;
372

373 374 375 376 377 378
	spin_lock_irqsave(&port->lock, flags);
	port->tx_bytes -= urb->transfer_buffer_length;
	set_bit(i, &port->write_urbs_free);
	spin_unlock_irqrestore(&port->lock, flags);

	if (status) {
379 380
		dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
			__func__, status);
381

382
		spin_lock_irqsave(&port->lock, flags);
383
		kfifo_reset_out(&port->write_fifo);
384
		spin_unlock_irqrestore(&port->lock, flags);
385 386
	} else {
		usb_serial_generic_write_start(port);
L
Linus Torvalds 已提交
387
	}
388

389
	usb_serial_port_softint(port);
L
Linus Torvalds 已提交
390
}
391
EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
L
Linus Torvalds 已提交
392

A
Alan Cox 已提交
393
void usb_serial_generic_throttle(struct tty_struct *tty)
394
{
A
Alan Cox 已提交
395
	struct usb_serial_port *port = tty->driver_data;
396 397 398 399 400 401 402 403
	unsigned long flags;

	/* Set the throttle request flag. It will be picked up
	 * by usb_serial_generic_read_bulk_callback(). */
	spin_lock_irqsave(&port->lock, flags);
	port->throttle_req = 1;
	spin_unlock_irqrestore(&port->lock, flags);
}
404
EXPORT_SYMBOL_GPL(usb_serial_generic_throttle);
405

A
Alan Cox 已提交
406
void usb_serial_generic_unthrottle(struct tty_struct *tty)
407
{
A
Alan Cox 已提交
408
	struct usb_serial_port *port = tty->driver_data;
409 410 411
	int was_throttled;

	/* Clear the throttle flags */
412
	spin_lock_irq(&port->lock);
413 414
	was_throttled = port->throttled;
	port->throttled = port->throttle_req = 0;
415
	spin_unlock_irq(&port->lock);
416

417
	if (was_throttled)
418
		usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
419
}
420
EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
421

422
#ifdef CONFIG_MAGIC_SYSRQ
423
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
424
{
425
	if (port->sysrq && port->port.console) {
426
		if (ch && time_before(jiffies, port->sysrq)) {
427
			handle_sysrq(ch);
428 429 430 431 432 433 434
			port->sysrq = 0;
			return 1;
		}
		port->sysrq = 0;
	}
	return 0;
}
435
#else
436
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
437 438 439 440
{
	return 0;
}
#endif
441 442 443 444 445 446 447 448 449 450 451 452 453
EXPORT_SYMBOL_GPL(usb_serial_handle_sysrq_char);

int usb_serial_handle_break(struct usb_serial_port *port)
{
	if (!port->sysrq) {
		port->sysrq = jiffies + HZ*5;
		return 1;
	}
	port->sysrq = 0;
	return 0;
}
EXPORT_SYMBOL_GPL(usb_serial_handle_break);

454 455 456 457 458 459 460 461 462 463 464
/**
 *	usb_serial_handle_dcd_change - handle a change of carrier detect state
 *	@port: usb_serial_port structure for the open port
 *	@tty: tty_struct structure for the port
 *	@status: new carrier detect status, nonzero if active
 */
void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
				struct tty_struct *tty, unsigned int status)
{
	struct tty_port *port = &usb_port->port;

465
	dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
466 467 468 469 470 471 472 473

	if (status)
		wake_up_interruptible(&port->open_wait);
	else if (tty && !C_CLOCAL(tty))
		tty_hangup(tty);
}
EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change);

474 475 476 477 478 479 480
int usb_serial_generic_resume(struct usb_serial *serial)
{
	struct usb_serial_port *port;
	int i, c = 0, r;

	for (i = 0; i < serial->num_ports; i++) {
		port = serial->port[i];
481
		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
482 483
			continue;

484 485 486
		if (port->bulk_in_size) {
			r = usb_serial_generic_submit_read_urbs(port,
								GFP_NOIO);
487 488 489 490
			if (r < 0)
				c++;
		}

491
		if (port->bulk_out_size) {
492 493 494 495 496 497 498 499 500 501
			r = usb_serial_generic_write_start(port);
			if (r < 0)
				c++;
		}
	}

	return c ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(usb_serial_generic_resume);

502 503 504
void usb_serial_generic_release(struct usb_serial *serial)
{
}