ir-usb.c 15.7 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * USB IR Dongle driver
 *
 *	Copyright (C) 2001-2002	Greg Kroah-Hartman (greg@kroah.com)
 *	Copyright (C) 2002	Gary Brubaker (xavyer@ix.netcom.com)
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 * This driver allows a USB IrDA device to be used as a "dumb" serial device.
 * This can be useful if you do not have access to a full IrDA stack on the
 * other side of the connection.  If you do have an IrDA stack on both devices,
 * please use the usb-irda driver, as it contains the proper error checking and
 * other goodness of a full IrDA stack.
 *
 * Portions of this driver were taken from drivers/net/irda/irda-usb.c, which
 * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli
 * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com>
 *
22 23 24 25 26 27
 * See Documentation/usb/usb-serial.txt for more information on using this
 * driver
 *
 * 2008_Jun_02  Felipe Balbi <me@felipebalbi.com>
 *	Introduced common header to be used also in USB Gadget Framework.
 *	Still needs some other style fixes.
Linus Torvalds's avatar
Linus Torvalds committed
28
 *
29
 * 2007_Jun_21  Alan Cox <alan@lxorguk.ukuu.org.uk>
30 31 32
 *	Minimal cleanups for some of the driver problens and tty layer abuse.
 *	Still needs fixing to allow multiple dongles.
 *
Linus Torvalds's avatar
Linus Torvalds committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
 * 2002_Mar_07	greg kh
 *	moved some needed structures and #define values from the
 *	net/irda/irda-usb.h file into our file, as we don't want to depend on
 *	that codebase compiling correctly :)
 *
 * 2002_Jan_14  gb
 *	Added module parameter to force specific number of XBOFs.
 *	Added ir_xbof_change().
 *	Reorganized read_bulk_callback error handling.
 *	Switched from FILL_BULK_URB() to usb_fill_bulk_urb().
 *
 * 2001_Nov_08  greg kh
 *	Changed the irda_usb_find_class_desc() function based on comments and
 *	code from Martin Diehl.
 *
 * 2001_Nov_01	greg kh
 *	Added support for more IrDA USB devices.
 *	Added support for zero packet.  Added buffer override paramater, so
 *	users can transfer larger packets at once if they wish.  Both patches
 *	came from Dag Brattli <dag@obexcode.com>.
 *
 * 2001_Oct_07	greg kh
 *	initial version released.
 */

#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/spinlock.h>
67
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
68
#include <linux/usb.h>
69
#include <linux/usb/serial.h>
70
#include <linux/usb/irda.h>
Linus Torvalds's avatar
Linus Torvalds committed
71 72 73 74 75 76 77 78 79 80 81 82 83

/*
 * Version Information
 */
#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB IR Dongle driver"

static int debug;

/* if overridden by the user, then use their value for the size of the read and
 * write urbs */
static int buffer_size;
84

Linus Torvalds's avatar
Linus Torvalds committed
85 86 87
/* if overridden by the user, then use the specified number of XBOFs */
static int xbof = -1;

Alan Cox's avatar
Alan Cox committed
88
static int  ir_startup (struct usb_serial *serial);
89
static int  ir_open(struct tty_struct *tty, struct usb_serial_port *port);
90
static void ir_close(struct usb_serial_port *port);
Alan Cox's avatar
Alan Cox committed
91 92 93 94 95 96
static int  ir_write(struct tty_struct *tty, struct usb_serial_port *port,
					const unsigned char *buf, int count);
static void ir_write_bulk_callback (struct urb *urb);
static void ir_read_bulk_callback (struct urb *urb);
static void ir_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios);
Linus Torvalds's avatar
Linus Torvalds committed
97

98
/* Not that this lot means you can only have one per system */
99 100 101
static u8 ir_baud;
static u8 ir_xbof;
static u8 ir_add_bof;
Linus Torvalds's avatar
Linus Torvalds committed
102

103
static struct usb_device_id ir_id_table[] = {
Linus Torvalds's avatar
Linus Torvalds committed
104 105 106
	{ USB_DEVICE(0x050f, 0x0180) },		/* KC Technology, KC-180 */
	{ USB_DEVICE(0x08e9, 0x0100) },		/* XTNDAccess */
	{ USB_DEVICE(0x09c4, 0x0011) },		/* ACTiSys ACT-IR2000U */
107
	{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, USB_SUBCLASS_IRDA, 0) },
Linus Torvalds's avatar
Linus Torvalds committed
108 109 110
	{ }					/* Terminating entry */
};

111
MODULE_DEVICE_TABLE(usb, ir_id_table);
Linus Torvalds's avatar
Linus Torvalds committed
112 113

static struct usb_driver ir_driver = {
114 115 116 117 118
	.name		= "ir-usb",
	.probe		= usb_serial_probe,
	.disconnect	= usb_serial_disconnect,
	.id_table	= ir_id_table,
	.no_dynamic_id	= 1,
Linus Torvalds's avatar
Linus Torvalds committed
119 120
};

121
static struct usb_serial_driver ir_device = {
122 123 124
	.driver	= {
		.owner	= THIS_MODULE,
		.name	= "ir-usb",
125
	},
126 127 128 129 130 131 132 133 134 135 136
	.description		= "IR Dongle",
	.usb_driver		= &ir_driver,
	.id_table		= ir_id_table,
	.num_ports		= 1,
	.set_termios		= ir_set_termios,
	.attach			= ir_startup,
	.open			= ir_open,
	.close			= ir_close,
	.write			= ir_write,
	.write_bulk_callback	= ir_write_bulk_callback,
	.read_bulk_callback	= ir_read_bulk_callback,
Linus Torvalds's avatar
Linus Torvalds committed
137 138
};

139
static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
Linus Torvalds's avatar
Linus Torvalds committed
140 141 142
{
	dbg("bLength=%x", desc->bLength);
	dbg("bDescriptorType=%x", desc->bDescriptorType);
143
	dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision));
Linus Torvalds's avatar
Linus Torvalds committed
144 145 146
	dbg("bmDataSize=%x", desc->bmDataSize);
	dbg("bmWindowSize=%x", desc->bmWindowSize);
	dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime);
147
	dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate));
Linus Torvalds's avatar
Linus Torvalds committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
	dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs);
	dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff);
	dbg("bMaxUnicastList=%x", desc->bMaxUnicastList);
}

/*------------------------------------------------------------------*/
/*
 * Function irda_usb_find_class_desc(dev, ifnum)
 *
 *    Returns instance of IrDA class descriptor, or NULL if not found
 *
 * The class descriptor is some extra info that IrDA USB devices will
 * offer to us, describing their IrDA characteristics. We will use that in
 * irda_usb_init_qos()
 *
 * Based on the same function in drivers/net/irda/irda-usb.c
 */
165 166
static struct usb_irda_cs_descriptor *
irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
Linus Torvalds's avatar
Linus Torvalds committed
167
{
168
	struct usb_irda_cs_descriptor *desc;
Linus Torvalds's avatar
Linus Torvalds committed
169
	int ret;
170 171 172

	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
	if (!desc)
Linus Torvalds's avatar
Linus Torvalds committed
173
		return NULL;
174 175 176

	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
			USB_REQ_CS_IRDA_GET_CLASS_DESC,
Linus Torvalds's avatar
Linus Torvalds committed
177 178
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
			0, ifnum, desc, sizeof(*desc), 1000);
179

180
	dbg("%s -  ret=%d", __func__, ret);
Linus Torvalds's avatar
Linus Torvalds committed
181 182
	if (ret < sizeof(*desc)) {
		dbg("%s - class descriptor read %s (%d)",
183
				__func__,
184
				(ret < 0) ? "failed" : "too short",
Linus Torvalds's avatar
Linus Torvalds committed
185 186 187
				ret);
		goto error;
	}
188
	if (desc->bDescriptorType != USB_DT_CS_IRDA) {
189
		dbg("%s - bad class descriptor type", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
190 191
		goto error;
	}
192

Linus Torvalds's avatar
Linus Torvalds committed
193 194
	irda_usb_dump_class_desc(desc);
	return desc;
195

Linus Torvalds's avatar
Linus Torvalds committed
196 197 198 199 200 201 202 203 204
error:
	kfree(desc);
	return NULL;
}


static u8 ir_xbof_change(u8 xbof)
{
	u8 result;
205

Linus Torvalds's avatar
Linus Torvalds committed
206
	/* reference irda-usb.c */
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
	switch (xbof) {
	case 48:
		result = 0x10;
		break;
	case 28:
	case 24:
		result = 0x20;
		break;
	default:
	case 12:
		result = 0x30;
		break;
	case  5:
	case  6:
		result = 0x40;
		break;
	case  3:
		result = 0x50;
		break;
	case  2:
		result = 0x60;
		break;
	case  1:
		result = 0x70;
		break;
	case  0:
		result = 0x80;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
235
	}
236

Linus Torvalds's avatar
Linus Torvalds committed
237 238 239 240
	return(result);
}


241
static int ir_startup(struct usb_serial *serial)
Linus Torvalds's avatar
Linus Torvalds committed
242
{
243
	struct usb_irda_cs_descriptor *irda_desc;
Linus Torvalds's avatar
Linus Torvalds committed
244

245 246 247 248
	irda_desc = irda_usb_find_class_desc(serial->dev, 0);
	if (!irda_desc) {
		dev_err(&serial->dev->dev,
			"IRDA class descriptor not found, device not bound\n");
Linus Torvalds's avatar
Linus Torvalds committed
249 250 251
		return -ENODEV;
	}

252
	dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
253
		__func__,
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
		(irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : "");

	switch (irda_desc->bmAdditionalBOFs) {
	case USB_IRDA_AB_48:
		ir_add_bof = 48;
		break;
	case USB_IRDA_AB_24:
		ir_add_bof = 24;
		break;
	case USB_IRDA_AB_12:
		ir_add_bof = 12;
		break;
	case USB_IRDA_AB_6:
		ir_add_bof = 6;
		break;
	case USB_IRDA_AB_3:
		ir_add_bof = 3;
		break;
	case USB_IRDA_AB_2:
		ir_add_bof = 2;
		break;
	case USB_IRDA_AB_1:
		ir_add_bof = 1;
		break;
	case USB_IRDA_AB_0:
		ir_add_bof = 0;
		break;
	default:
		break;
Linus Torvalds's avatar
Linus Torvalds committed
291 292
	}

293
	kfree(irda_desc);
Linus Torvalds's avatar
Linus Torvalds committed
294

295
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
296 297
}

298
static int ir_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds's avatar
Linus Torvalds committed
299 300 301 302
{
	char *buffer;
	int result = 0;

303
	dbg("%s - port %d", __func__, port->number);
Linus Torvalds's avatar
Linus Torvalds committed
304 305 306

	if (buffer_size) {
		/* override the default buffer sizes */
307
		buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
308
		if (!buffer) {
309
			dev_err(&port->dev, "%s - out of memory.\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
310 311
			return -ENOMEM;
		}
312
		kfree(port->read_urb->transfer_buffer);
Linus Torvalds's avatar
Linus Torvalds committed
313 314 315
		port->read_urb->transfer_buffer = buffer;
		port->read_urb->transfer_buffer_length = buffer_size;

316
		buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
317
		if (!buffer) {
318
			dev_err(&port->dev, "%s - out of memory.\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
319 320
			return -ENOMEM;
		}
321
		kfree(port->write_urb->transfer_buffer);
Linus Torvalds's avatar
Linus Torvalds committed
322 323 324 325 326 327
		port->write_urb->transfer_buffer = buffer;
		port->write_urb->transfer_buffer_length = buffer_size;
		port->bulk_out_size = buffer_size;
	}

	/* Start reading from the device */
328
	usb_fill_bulk_urb(
Linus Torvalds's avatar
Linus Torvalds committed
329
		port->read_urb,
330 331 332
		port->serial->dev,
		usb_rcvbulkpipe(port->serial->dev,
			port->bulk_in_endpointAddress),
Linus Torvalds's avatar
Linus Torvalds committed
333 334 335 336 337 338
		port->read_urb->transfer_buffer,
		port->read_urb->transfer_buffer_length,
		ir_read_bulk_callback,
		port);
	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
	if (result)
339 340 341
		dev_err(&port->dev,
			"%s - failed submitting read urb, error %d\n",
			__func__, result);
Linus Torvalds's avatar
Linus Torvalds committed
342 343 344 345

	return result;
}

346
static void ir_close(struct usb_serial_port *port)
Linus Torvalds's avatar
Linus Torvalds committed
347
{
348
	dbg("%s - port %d", __func__, port->number);
349

Linus Torvalds's avatar
Linus Torvalds committed
350 351 352 353
	/* shutdown our bulk read */
	usb_kill_urb(port->read_urb);
}

Alan Cox's avatar
Alan Cox committed
354 355
static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
					const unsigned char *buf, int count)
Linus Torvalds's avatar
Linus Torvalds committed
356 357 358 359 360
{
	unsigned char *transfer_buffer;
	int result;
	int transfer_size;

361
	dbg("%s - port = %d, count = %d", __func__, port->number, count);
Linus Torvalds's avatar
Linus Torvalds committed
362 363 364 365

	if (count == 0)
		return 0;

366
	spin_lock_bh(&port->lock);
367
	if (port->write_urb_busy) {
368
		spin_unlock_bh(&port->lock);
369
		dbg("%s - already writing", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
370 371
		return 0;
	}
372
	port->write_urb_busy = 1;
373
	spin_unlock_bh(&port->lock);
Linus Torvalds's avatar
Linus Torvalds committed
374 375 376 377 378 379

	transfer_buffer = port->write_urb->transfer_buffer;
	transfer_size = min(count, port->bulk_out_size - 1);

	/*
	 * The first byte of the packet we send to the device contains an
380
	 * inbound header which indicates an additional number of BOFs and
Linus Torvalds's avatar
Linus Torvalds committed
381 382 383 384 385 386 387
	 * a baud rate change.
	 *
	 * See section 5.4.2.2 of the USB IrDA spec.
	 */
	*transfer_buffer = ir_xbof | ir_baud;
	++transfer_buffer;

388
	memcpy(transfer_buffer, buf, transfer_size);
Linus Torvalds's avatar
Linus Torvalds committed
389

390
	usb_fill_bulk_urb(
Linus Torvalds's avatar
Linus Torvalds committed
391 392 393 394 395 396 397 398 399 400 401
		port->write_urb,
		port->serial->dev,
		usb_sndbulkpipe(port->serial->dev,
			port->bulk_out_endpointAddress),
		port->write_urb->transfer_buffer,
		transfer_size + 1,
		ir_write_bulk_callback,
		port);

	port->write_urb->transfer_flags = URB_ZERO_PACKET;

402
	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
403 404
	if (result) {
		port->write_urb_busy = 0;
405 406 407
		dev_err(&port->dev,
			"%s - failed submitting write urb, error %d\n",
			__func__, result);
408
	} else
Linus Torvalds's avatar
Linus Torvalds committed
409 410 411 412 413
		result = transfer_size;

	return result;
}

414
static void ir_write_bulk_callback(struct urb *urb)
Linus Torvalds's avatar
Linus Torvalds committed
415
{
416
	struct usb_serial_port *port = urb->context;
417
	int status = urb->status;
Linus Torvalds's avatar
Linus Torvalds committed
418

419
	dbg("%s - port %d", __func__, port->number);
420 421

	port->write_urb_busy = 0;
422 423
	if (status) {
		dbg("%s - nonzero write bulk status received: %d",
424
		    __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
425 426 427
		return;
	}

428
	usb_serial_debug_data(
Linus Torvalds's avatar
Linus Torvalds committed
429 430
		debug,
		&port->dev,
431
		__func__,
Linus Torvalds's avatar
Linus Torvalds committed
432 433 434
		urb->actual_length,
		urb->transfer_buffer);

435
	usb_serial_port_softint(port);
Linus Torvalds's avatar
Linus Torvalds committed
436 437
}

438
static void ir_read_bulk_callback(struct urb *urb)
Linus Torvalds's avatar
Linus Torvalds committed
439
{
440
	struct usb_serial_port *port = urb->context;
Linus Torvalds's avatar
Linus Torvalds committed
441 442 443
	struct tty_struct *tty;
	unsigned char *data = urb->transfer_buffer;
	int result;
444
	int status = urb->status;
Linus Torvalds's avatar
Linus Torvalds committed
445

446
	dbg("%s - port %d", __func__, port->number);
Linus Torvalds's avatar
Linus Torvalds committed
447

Alan Cox's avatar
Alan Cox committed
448
	if (!port->port.count) {
449
		dbg("%s - port closed.", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
450 451 452
		return;
	}

453
	switch (status) {
454 455 456 457 458 459 460 461
	case 0: /* Successful */
		/*
		 * The first byte of the packet we get from the device
		 * contains a busy indicator and baud rate change.
		 * See section 5.4.1.2 of the USB IrDA spec.
		 */
		if ((*data & 0x0f) > 0)
			ir_baud = *data & 0x0f;
Alan Cox's avatar
Alan Cox committed
462 463
		usb_serial_debug_data(debug, &port->dev, __func__,
						urb->actual_length, data);
Alan Cox's avatar
Alan Cox committed
464
		tty = tty_port_tty_get(&port->port);
465
		if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
Alan Cox's avatar
Alan Cox committed
466
			tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
467 468
			tty_flip_buffer_push(tty);
		}
Alan Cox's avatar
Alan Cox committed
469
		tty_kref_put(tty);
Linus Torvalds's avatar
Linus Torvalds committed
470

471 472 473 474 475 476 477
		/*
		 * No break here.
		 * We want to resubmit the urb so we can read
		 * again.
		 */

	case -EPROTO: /* taking inspiration from pl2303.c */
Alan Cox's avatar
Alan Cox committed
478
			/* Continue trying to always read */
479 480
		usb_fill_bulk_urb(
			port->read_urb,
Alan Cox's avatar
Alan Cox committed
481
			port->serial->dev, 
482 483 484 485 486 487 488 489 490
			usb_rcvbulkpipe(port->serial->dev,
				port->bulk_in_endpointAddress),
			port->read_urb->transfer_buffer,
			port->read_urb->transfer_buffer_length,
			ir_read_bulk_callback,
			port);

		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
		if (result)
Alan Cox's avatar
Alan Cox committed
491
			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
492
				__func__, result);
Alan Cox's avatar
Alan Cox committed
493
			break ;
494 495
	default:
		dbg("%s - nonzero read bulk status received: %d",
Alan Cox's avatar
Alan Cox committed
496 497
			__func__, status);
		break ;
Linus Torvalds's avatar
Linus Torvalds committed
498 499 500 501
	}
	return;
}

Alan Cox's avatar
Alan Cox committed
502 503
static void ir_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds's avatar
Linus Torvalds committed
504 505 506
{
	unsigned char *transfer_buffer;
	int result;
507 508
	speed_t baud;
	int ir_baud;
Linus Torvalds's avatar
Linus Torvalds committed
509

510
	dbg("%s - port %d", __func__, port->number);
Linus Torvalds's avatar
Linus Torvalds committed
511

Alan Cox's avatar
Alan Cox committed
512
	baud = tty_get_baud_rate(tty);
513 514 515 516 517 518 519 520

	/*
	 * FIXME, we should compare the baud request against the
	 * capability stated in the IR header that we got in the
	 * startup function.
	 */

	switch (baud) {
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
	case 2400:
		ir_baud = USB_IRDA_BR_2400;
		break;
	case 9600:
		ir_baud = USB_IRDA_BR_9600;
		break;
	case 19200:
		ir_baud = USB_IRDA_BR_19200;
		break;
	case 38400:
		ir_baud = USB_IRDA_BR_38400;
		break;
	case 57600:
		ir_baud = USB_IRDA_BR_57600;
		break;
	case 115200:
		ir_baud = USB_IRDA_BR_115200;
		break;
	case 576000:
		ir_baud = USB_IRDA_BR_576000;
		break;
	case 1152000:
		ir_baud = USB_IRDA_BR_1152000;
		break;
	case 4000000:
		ir_baud = USB_IRDA_BR_4000000;
		break;
	default:
		ir_baud = USB_IRDA_BR_9600;
		baud = 9600;
Linus Torvalds's avatar
Linus Torvalds committed
551 552
	}

553 554 555 556
	if (xbof == -1)
		ir_xbof = ir_xbof_change(ir_add_bof);
	else
		ir_xbof = ir_xbof_change(xbof) ;
Linus Torvalds's avatar
Linus Torvalds committed
557

558 559 560 561 562 563 564
	/* FIXME need to check to see if our write urb is busy right
	 * now, or use a urb pool.
	 *
	 * send the baud change out on an "empty" data packet
	 */
	transfer_buffer = port->write_urb->transfer_buffer;
	*transfer_buffer = ir_xbof | ir_baud;
Linus Torvalds's avatar
Linus Torvalds committed
565

566
	usb_fill_bulk_urb(
567 568
		port->write_urb,
		port->serial->dev,
569 570
		usb_sndbulkpipe(port->serial->dev,
			port->bulk_out_endpointAddress),
571 572 573 574 575 576 577
		port->write_urb->transfer_buffer,
		1,
		ir_write_bulk_callback,
		port);

	port->write_urb->transfer_flags = URB_ZERO_PACKET;

578
	result = usb_submit_urb(port->write_urb, GFP_KERNEL);
579
	if (result)
580 581 582
		dev_err(&port->dev,
				"%s - failed submitting write urb, error %d\n",
				__func__, result);
Alan Cox's avatar
Alan Cox committed
583 584

	/* Only speed changes are supported */
Alan Cox's avatar
Alan Cox committed
585 586
	tty_termios_copy_hw(tty->termios, old_termios);
	tty_encode_baud_rate(tty, baud, baud);
Linus Torvalds's avatar
Linus Torvalds committed
587 588
}

589
static int __init ir_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
590 591
{
	int retval;
592

Linus Torvalds's avatar
Linus Torvalds committed
593 594 595
	retval = usb_serial_register(&ir_device);
	if (retval)
		goto failed_usb_serial_register;
596

Linus Torvalds's avatar
Linus Torvalds committed
597
	retval = usb_register(&ir_driver);
598
	if (retval)
Linus Torvalds's avatar
Linus Torvalds committed
599
		goto failed_usb_register;
600

601 602
	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
	       DRIVER_DESC "\n");
603

Linus Torvalds's avatar
Linus Torvalds committed
604
	return 0;
605

Linus Torvalds's avatar
Linus Torvalds committed
606 607
failed_usb_register:
	usb_serial_deregister(&ir_device);
608

Linus Torvalds's avatar
Linus Torvalds committed
609 610 611 612
failed_usb_serial_register:
	return retval;
}

613
static void __exit ir_exit(void)
Linus Torvalds's avatar
Linus Torvalds committed
614
{
615 616
	usb_deregister(&ir_driver);
	usb_serial_deregister(&ir_device);
Linus Torvalds's avatar
Linus Torvalds committed
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
}


module_init(ir_init);
module_exit(ir_exit);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(xbof, int, 0);
MODULE_PARM_DESC(xbof, "Force specific number of XBOFs");
module_param(buffer_size, int, 0);
MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers");