Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0d795e4 authored by Felipe Balbi's avatar Felipe Balbi Committed by Greg Kroah-Hartman
Browse files

usb: irda: cleanup on ir-usb module



General cleanup on ir-usb module. Introduced
a common header that could be used also on
usb gadget framework.

Lot's of cleanups and now using macros from the header
file.

Signed-off-by: default avatarFelipe Balbi <me@felipebalbi.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b9638011
Loading
Loading
Loading
Loading
+270 −220
Original line number Original line Diff line number Diff line
@@ -19,7 +19,12 @@
 * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli
 * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli
 * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com>
 * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com>
 *
 *
 * See Documentation/usb/usb-serial.txt for more information on using this driver
 * 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.
 *
 *
 * 2007_Jun_21  Alan Cox <alan@redhat.com>
 * 2007_Jun_21  Alan Cox <alan@redhat.com>
 *	Minimal cleanups for some of the driver problens and tty layer abuse.
 *	Minimal cleanups for some of the driver problens and tty layer abuse.
@@ -59,9 +64,10 @@
#include <linux/tty_flip.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/usb/serial.h>
#include <linux/usb/irda.h>


/*
/*
 * Version Information
 * Version Information
@@ -70,73 +76,48 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB IR Dongle driver"
#define DRIVER_DESC "USB IR Dongle driver"


/* USB IrDA class spec information */
#define USB_CLASS_IRDA		0x02
#define USB_DT_IRDA		0x21
#define IU_REQ_GET_CLASS_DESC	0x06
#define SPEED_2400		0x01
#define SPEED_9600		0x02
#define SPEED_19200		0x03
#define SPEED_38400		0x04
#define SPEED_57600		0x05
#define SPEED_115200		0x06
#define SPEED_576000		0x07
#define SPEED_1152000		0x08
#define SPEED_4000000		0x09

struct irda_class_desc {
	u8	bLength;
	u8	bDescriptorType;
	u16	bcdSpecRevision;
	u8	bmDataSize;
	u8	bmWindowSize;
	u8	bmMinTurnaroundTime;
	u16	wBaudRate;
	u8	bmAdditionalBOFs;
	u8	bIrdaRateSniff;
	u8	bMaxUnicastList;
} __attribute__ ((packed));

static int debug;
static int debug;


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

/* if overridden by the user, then use the specified number of XBOFs */
/* if overridden by the user, then use the specified number of XBOFs */
static int xbof = -1;
static int xbof = -1;


static int ir_startup(struct usb_serial *serial);
static int ir_startup(struct usb_serial *serial);
static int ir_open(struct usb_serial_port *port, struct file *filep);
static int ir_open(struct usb_serial_port *port, struct file *filep);
static void ir_close(struct usb_serial_port *port, struct file *filep);
static void ir_close(struct usb_serial_port *port, struct file *filep);
static int  ir_write (struct usb_serial_port *port, const unsigned char *buf, int count);
static int ir_write(struct usb_serial_port *port,
		const unsigned char *buf, int count);
static void ir_write_bulk_callback(struct urb *urb);
static void ir_write_bulk_callback(struct urb *urb);
static void ir_read_bulk_callback(struct urb *urb);
static void ir_read_bulk_callback(struct urb *urb);
static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void ir_set_termios(struct usb_serial_port *port,
		struct ktermios *old_termios);


/* Not that this lot means you can only have one per system */
/* Not that this lot means you can only have one per system */
static u8 ir_baud = 0;
static u8 ir_baud;
static u8 ir_xbof = 0;
static u8 ir_xbof;
static u8 ir_add_bof = 0;
static u8 ir_add_bof;


static struct usb_device_id id_table [] = {
static struct usb_device_id ir_id_table[] = {
	{ USB_DEVICE(0x050f, 0x0180) },		/* KC Technology, KC-180 */
	{ USB_DEVICE(0x050f, 0x0180) },		/* KC Technology, KC-180 */
	{ USB_DEVICE(0x08e9, 0x0100) },		/* XTNDAccess */
	{ USB_DEVICE(0x08e9, 0x0100) },		/* XTNDAccess */
	{ USB_DEVICE(0x09c4, 0x0011) },		/* ACTiSys ACT-IR2000U */
	{ USB_DEVICE(0x09c4, 0x0011) },		/* ACTiSys ACT-IR2000U */
	{ USB_INTERFACE_INFO (USB_CLASS_APP_SPEC, USB_CLASS_IRDA, 0) },
	{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, USB_SUBCLASS_IRDA, 0) },
	{ }					/* Terminating entry */
	{ }					/* Terminating entry */
};
};


MODULE_DEVICE_TABLE (usb, id_table);
MODULE_DEVICE_TABLE(usb, ir_id_table);


static struct usb_driver ir_driver = {
static struct usb_driver ir_driver = {
	.name		= "ir-usb",
	.name		= "ir-usb",
	.probe		= usb_serial_probe,
	.probe		= usb_serial_probe,
	.disconnect	= usb_serial_disconnect,
	.disconnect	= usb_serial_disconnect,
	.id_table =	id_table,
	.id_table	= ir_id_table,
	.no_dynamic_id	= 1,
	.no_dynamic_id	= 1,
};
};



static struct usb_serial_driver ir_device = {
static struct usb_serial_driver ir_device = {
	.driver	= {
	.driver	= {
		.owner	= THIS_MODULE,
		.owner	= THIS_MODULE,
@@ -144,7 +125,7 @@ static struct usb_serial_driver ir_device = {
	},
	},
	.description		= "IR Dongle",
	.description		= "IR Dongle",
	.usb_driver		= &ir_driver,
	.usb_driver		= &ir_driver,
	.id_table =		id_table,
	.id_table		= ir_id_table,
	.num_ports		= 1,
	.num_ports		= 1,
	.set_termios		= ir_set_termios,
	.set_termios		= ir_set_termios,
	.attach			= ir_startup,
	.attach			= ir_startup,
@@ -155,15 +136,15 @@ static struct usb_serial_driver ir_device = {
	.read_bulk_callback	= ir_read_bulk_callback,
	.read_bulk_callback	= ir_read_bulk_callback,
};
};


static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc)
static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
{
{
	dbg("bLength=%x", desc->bLength);
	dbg("bLength=%x", desc->bLength);
	dbg("bDescriptorType=%x", desc->bDescriptorType);
	dbg("bDescriptorType=%x", desc->bDescriptorType);
	dbg("bcdSpecRevision=%x", desc->bcdSpecRevision); 
	dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision));
	dbg("bmDataSize=%x", desc->bmDataSize);
	dbg("bmDataSize=%x", desc->bmDataSize);
	dbg("bmWindowSize=%x", desc->bmWindowSize);
	dbg("bmWindowSize=%x", desc->bmWindowSize);
	dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime);
	dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime);
	dbg("wBaudRate=%x", desc->wBaudRate);
	dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate));
	dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs);
	dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs);
	dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff);
	dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff);
	dbg("bMaxUnicastList=%x", desc->bMaxUnicastList);
	dbg("bMaxUnicastList=%x", desc->bMaxUnicastList);
@@ -181,17 +162,18 @@ static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc)
 *
 *
 * Based on the same function in drivers/net/irda/irda-usb.c
 * Based on the same function in drivers/net/irda/irda-usb.c
 */
 */
static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
static struct usb_irda_cs_descriptor *
irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
{
{
	struct irda_class_desc *desc;
	struct usb_irda_cs_descriptor *desc;
	int ret;
	int ret;


	desc = kzalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
	if (desc == NULL) 
	if (!desc)
		return NULL;
		return NULL;


	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
			IU_REQ_GET_CLASS_DESC,
			USB_REQ_CS_IRDA_GET_CLASS_DESC,
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
			0, ifnum, desc, sizeof(*desc), 1000);
			0, ifnum, desc, sizeof(*desc), 1000);


@@ -203,13 +185,14 @@ static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev,
				ret);
				ret);
		goto error;
		goto error;
	}
	}
	if (desc->bDescriptorType != USB_DT_IRDA) {
	if (desc->bDescriptorType != USB_DT_CS_IRDA) {
		dbg("%s - bad class descriptor type", __func__);
		dbg("%s - bad class descriptor type", __func__);
		goto error;
		goto error;
	}
	}


	irda_usb_dump_class_desc(desc);
	irda_usb_dump_class_desc(desc);
	return desc;
	return desc;

error:
error:
	kfree(desc);
	kfree(desc);
	return NULL;
	return NULL;
@@ -219,56 +202,92 @@ error:
static u8 ir_xbof_change(u8 xbof)
static u8 ir_xbof_change(u8 xbof)
{
{
	u8 result;
	u8 result;

	/* reference irda-usb.c */
	/* reference irda-usb.c */
	switch (xbof) {
	switch (xbof) {
		case 48: result = 0x10; break;
	case 48:
		result = 0x10;
		break;
	case 28:
	case 28:
		case 24: result = 0x20; break;
	case 24:
		result = 0x20;
		break;
	default:
	default:
		case 12: result = 0x30; break;
	case 12:
		result = 0x30;
		break;
	case  5:
	case  5:
		case  6: result = 0x40; break;
	case  6:
		case  3: result = 0x50; break;
		result = 0x40;
		case  2: result = 0x60; break;
		break;
		case  1: result = 0x70; break;
	case  3:
		case  0: result = 0x80; break;
		result = 0x50;
		break;
	case  2:
		result = 0x60;
		break;
	case  1:
		result = 0x70;
		break;
	case  0:
		result = 0x80;
		break;
	}
	}

	return(result);
	return(result);
}
}




static int ir_startup(struct usb_serial *serial)
static int ir_startup(struct usb_serial *serial)
{
{
	struct irda_class_desc *irda_desc;
	struct usb_irda_cs_descriptor *irda_desc;


	irda_desc = irda_usb_find_class_desc(serial->dev, 0);
	irda_desc = irda_usb_find_class_desc(serial->dev, 0);
	if (irda_desc == NULL) {
	if (!irda_desc) {
		dev_err (&serial->dev->dev, "IRDA class descriptor not found, device not bound\n");
		dev_err(&serial->dev->dev,
			"IRDA class descriptor not found, device not bound\n");
		return -ENODEV;
		return -ENODEV;
	}
	}


	dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
	dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
		__func__,
		__func__,
		(irda_desc->wBaudRate & 0x0001) ? " 2400"    : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "",
		(irda_desc->wBaudRate & 0x0002) ? " 9600"    : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "",
		(irda_desc->wBaudRate & 0x0004) ? " 19200"   : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "",
		(irda_desc->wBaudRate & 0x0008) ? " 38400"   : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "",
		(irda_desc->wBaudRate & 0x0010) ? " 57600"   : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "",
		(irda_desc->wBaudRate & 0x0020) ? " 115200"  : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "",
		(irda_desc->wBaudRate & 0x0040) ? " 576000"  : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "",
		(irda_desc->wBaudRate & 0x0080) ? " 1152000" : "",
		(irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "",
		(irda_desc->wBaudRate & 0x0100) ? " 4000000" : "");
		(irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : "");


	switch (irda_desc->bmAdditionalBOFs) {
	switch (irda_desc->bmAdditionalBOFs) {
		case 0x01: ir_add_bof = 48; break;
	case USB_IRDA_AB_48:
		case 0x02: ir_add_bof = 24; break;
		ir_add_bof = 48;
		case 0x04: ir_add_bof = 12; break;
		break;
		case 0x08: ir_add_bof =  6; break;
	case USB_IRDA_AB_24:
		case 0x10: ir_add_bof =  3; break;
		ir_add_bof = 24;
		case 0x20: ir_add_bof =  2; break;
		break;
		case 0x40: ir_add_bof =  1; break;
	case USB_IRDA_AB_12:
		case 0x80: ir_add_bof =  0; break;
		ir_add_bof = 12;
		default:;
		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;
	}
	}


	kfree(irda_desc);
	kfree(irda_desc);
@@ -309,14 +328,17 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
	usb_fill_bulk_urb(
	usb_fill_bulk_urb(
		port->read_urb,
		port->read_urb,
		port->serial->dev,
		port->serial->dev,
		usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
		usb_rcvbulkpipe(port->serial->dev,
			port->bulk_in_endpointAddress),
		port->read_urb->transfer_buffer,
		port->read_urb->transfer_buffer,
		port->read_urb->transfer_buffer_length,
		port->read_urb->transfer_buffer_length,
		ir_read_bulk_callback,
		ir_read_bulk_callback,
		port);
		port);
	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
	if (result)
	if (result)
		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
		dev_err(&port->dev,
			"%s - failed submitting read urb, error %d\n",
			__func__, result);


	return result;
	return result;
}
}
@@ -329,7 +351,8 @@ static void ir_close (struct usb_serial_port *port, struct file * filp)
	usb_kill_urb(port->read_urb);
	usb_kill_urb(port->read_urb);
}
}


static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count)
static int ir_write(struct usb_serial_port *port,
		const unsigned char *buf, int count)
{
{
	unsigned char *transfer_buffer;
	unsigned char *transfer_buffer;
	int result;
	int result;
@@ -359,7 +382,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int


	/*
	/*
	 * The first byte of the packet we send to the device contains an
	 * The first byte of the packet we send to the device contains an
	 * inband header which indicates an additional number of BOFs and
	 * inbound header which indicates an additional number of BOFs and
	 * a baud rate change.
	 * a baud rate change.
	 *
	 *
	 * See section 5.4.2.2 of the USB IrDA spec.
	 * See section 5.4.2.2 of the USB IrDA spec.
@@ -384,7 +407,9 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
	if (result) {
	if (result) {
		port->write_urb_busy = 0;
		port->write_urb_busy = 0;
		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
		dev_err(&port->dev,
			"%s - failed submitting write urb, error %d\n",
			__func__, result);
	} else
	} else
		result = transfer_size;
		result = transfer_size;


@@ -451,7 +476,8 @@ static void ir_read_bulk_callback (struct urb *urb)
		tty = port->tty;
		tty = port->tty;


		if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
		if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
				tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
			tty_insert_flip_string(tty, data + 1,
					urb->actual_length - 1);
			tty_flip_buffer_push(tty);
			tty_flip_buffer_push(tty);
		}
		}


@@ -476,9 +502,9 @@ static void ir_read_bulk_callback (struct urb *urb)


		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
		if (result)
		if (result)
				dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
			dev_err(&port->dev,
				"%s - failed resubmitting read urb, error %d\n",
				__func__, result);
				__func__, result);

		break;
		break;


	default:
	default:
@@ -486,13 +512,13 @@ static void ir_read_bulk_callback (struct urb *urb)
			__func__,
			__func__,
			status);
			status);
		break;
		break;

	}
	}


	return;
	return;
}
}


static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
static void ir_set_termios(struct usb_serial_port *port,
		struct ktermios *old_termios)
{
{
	unsigned char *transfer_buffer;
	unsigned char *transfer_buffer;
	int result;
	int result;
@@ -510,18 +536,35 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
	 */
	 */


	switch (baud) {
	switch (baud) {
		case 2400:	ir_baud = SPEED_2400; break;
	case 2400:
		case 9600:	ir_baud = SPEED_9600; break;
		ir_baud = USB_IRDA_BR_2400;
		case 19200:	ir_baud = SPEED_19200; break;
		break;
		case 38400:	ir_baud = SPEED_38400; break;
	case 9600:
		case 57600:	ir_baud = SPEED_57600; break;
		ir_baud = USB_IRDA_BR_9600;
		case 115200:	ir_baud = SPEED_115200; break;
		break;
		case 576000:	ir_baud = SPEED_576000; break;
	case 19200:
		case 1152000:	ir_baud = SPEED_1152000; break;
		ir_baud = USB_IRDA_BR_19200;
		case 4000000:	ir_baud = SPEED_4000000; break;
		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;
		break;
	default:
	default:
			ir_baud = SPEED_9600;
		ir_baud = USB_IRDA_BR_9600;
		baud = 9600;
		baud = 9600;
	}
	}


@@ -541,7 +584,8 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
	usb_fill_bulk_urb(
	usb_fill_bulk_urb(
		port->write_urb,
		port->write_urb,
		port->serial->dev,
		port->serial->dev,
		usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
		usb_sndbulkpipe(port->serial->dev,
			port->bulk_out_endpointAddress),
		port->write_urb->transfer_buffer,
		port->write_urb->transfer_buffer,
		1,
		1,
		ir_write_bulk_callback,
		ir_write_bulk_callback,
@@ -551,32 +595,38 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t


	result = usb_submit_urb(port->write_urb, GFP_KERNEL);
	result = usb_submit_urb(port->write_urb, GFP_KERNEL);
	if (result)
	if (result)
		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
		dev_err(&port->dev,
				"%s - failed submitting write urb, error %d\n",
				__func__, result);


	/* Only speed changes are supported */
	/* Only speed changes are supported */
	tty_termios_copy_hw(port->tty->termios, old_termios);
	tty_termios_copy_hw(port->tty->termios, old_termios);
	tty_encode_baud_rate(port->tty, baud, baud);
	tty_encode_baud_rate(port->tty, baud, baud);
}
}



static int __init ir_init(void)
static int __init ir_init(void)
{
{
	int retval;
	int retval;

	retval = usb_serial_register(&ir_device);
	retval = usb_serial_register(&ir_device);
	if (retval)
	if (retval)
		goto failed_usb_serial_register;
		goto failed_usb_serial_register;

	retval = usb_register(&ir_driver);
	retval = usb_register(&ir_driver);
	if (retval)
	if (retval)
		goto failed_usb_register;
		goto failed_usb_register;

	info(DRIVER_DESC " " DRIVER_VERSION);
	info(DRIVER_DESC " " DRIVER_VERSION);

	return 0;
	return 0;

failed_usb_register:
failed_usb_register:
	usb_serial_deregister(&ir_device);
	usb_serial_deregister(&ir_device);

failed_usb_serial_register:
failed_usb_serial_register:
	return retval;
	return retval;
}
}



static void __exit ir_exit(void)
static void __exit ir_exit(void)
{
{
	usb_deregister(&ir_driver);
	usb_deregister(&ir_driver);
+151 −0
Original line number Original line Diff line number Diff line
/*
 * USB IrDA Bridge Device Definition
 */

#ifndef __LINUX_USB_IRDA_H
#define __LINUX_USB_IRDA_H

/* This device should use Application-specific class */

#define USB_SUBCLASS_IRDA			0x02

/*-------------------------------------------------------------------------*/

/* Class-Specific requests (bRequest field) */

#define USB_REQ_CS_IRDA_RECEIVING		1
#define USB_REQ_CS_IRDA_CHECK_MEDIA_BUSY	3
#define USB_REQ_CS_IRDA_RATE_SNIFF		4
#define USB_REQ_CS_IRDA_UNICAST_LIST		5
#define USB_REQ_CS_IRDA_GET_CLASS_DESC		6

/*-------------------------------------------------------------------------*/

/* Class-Specific descriptor */

#define USB_DT_CS_IRDA				0x21

/*-------------------------------------------------------------------------*/

/* Data sizes */

#define USB_IRDA_DS_2048			(1 << 5)
#define USB_IRDA_DS_1024			(1 << 4)
#define USB_IRDA_DS_512				(1 << 3)
#define USB_IRDA_DS_256				(1 << 2)
#define USB_IRDA_DS_128				(1 << 1)
#define USB_IRDA_DS_64				(1 << 0)

/* Window sizes */

#define USB_IRDA_WS_7				(1 << 6)
#define USB_IRDA_WS_6				(1 << 5)
#define USB_IRDA_WS_5				(1 << 4)
#define USB_IRDA_WS_4				(1 << 3)
#define USB_IRDA_WS_3				(1 << 2)
#define USB_IRDA_WS_2				(1 << 1)
#define USB_IRDA_WS_1				(1 << 0)

/* Min turnaround times in usecs */

#define USB_IRDA_MTT_0				(1 << 7)
#define USB_IRDA_MTT_10				(1 << 6)
#define USB_IRDA_MTT_50				(1 << 5)
#define USB_IRDA_MTT_100			(1 << 4)
#define USB_IRDA_MTT_500			(1 << 3)
#define USB_IRDA_MTT_1000			(1 << 2)
#define USB_IRDA_MTT_5000			(1 << 1)
#define USB_IRDA_MTT_10000			(1 << 0)

/* Baud rates */

#define USB_IRDA_BR_4000000			(1 << 8)
#define USB_IRDA_BR_1152000			(1 << 7)
#define USB_IRDA_BR_576000			(1 << 6)
#define USB_IRDA_BR_115200			(1 << 5)
#define USB_IRDA_BR_57600			(1 << 4)
#define USB_IRDA_BR_38400			(1 << 3)
#define USB_IRDA_BR_19200			(1 << 2)
#define USB_IRDA_BR_9600			(1 << 1)
#define USB_IRDA_BR_2400			(1 << 0)

/* Additional BOFs */

#define USB_IRDA_AB_0				(1 << 7)
#define USB_IRDA_AB_1				(1 << 6)
#define USB_IRDA_AB_2				(1 << 5)
#define USB_IRDA_AB_3				(1 << 4)
#define USB_IRDA_AB_6				(1 << 3)
#define USB_IRDA_AB_12				(1 << 2)
#define USB_IRDA_AB_24				(1 << 1)
#define USB_IRDA_AB_48				(1 << 0)

/* IRDA Rate Sniff */

#define USB_IRDA_RATE_SNIFF			1

/*-------------------------------------------------------------------------*/

struct usb_irda_cs_descriptor {
	__u8	bLength;
	__u8	bDescriptorType;

	__le16	bcdSpecRevision;
	__u8	bmDataSize;
	__u8	bmWindowSize;
	__u8	bmMinTurnaroundTime;
	__le16	wBaudRate;
	__u8	bmAdditionalBOFs;
	__u8	bIrdaRateSniff;
	__u8	bMaxUnicastList;
} __attribute__ ((packed));

/*-------------------------------------------------------------------------*/

/* Data Format */

#define USB_IRDA_STATUS_MEDIA_BUSY	(1 << 7)

/* The following is a 4-bit value used for both
 * inbound and outbound headers:
 *
 * 0 - speed ignored
 * 1 - 2400 bps
 * 2 - 9600 bps
 * 3 - 19200 bps
 * 4 - 38400 bps
 * 5 - 57600 bps
 * 6 - 115200 bps
 * 7 - 576000 bps
 * 8 - 1.152 Mbps
 * 9 - 5 mbps
 * 10..15 - Reserved
 */
#define USB_IRDA_STATUS_LINK_SPEED	0x0f

/* The following is a 4-bit value used only for
 * outbound header:
 *
 * 0 - No change (BOF ignored)
 * 1 - 48 BOFs
 * 2 - 24 BOFs
 * 3 - 12 BOFs
 * 4 - 6 BOFs
 * 5 - 3 BOFs
 * 6 - 2 BOFs
 * 7 - 1 BOFs
 * 8 - 0 BOFs
 * 9..15 - Reserved
 */
#define USB_IRDA_EXTRA_BOFS		0xf0

struct usb_irda_inbound_header {
	__u8		bmStatus;
};

struct usb_irda_outbound_header {
	__u8		bmChange;
};

#endif /* __LINUX_USB_IRDA_H */