1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * USB IR Dongle driver 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) 5*1da177e4SLinus Torvalds * Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com) 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 8*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 9*1da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 10*1da177e4SLinus Torvalds * (at your option) any later version. 11*1da177e4SLinus Torvalds * 12*1da177e4SLinus Torvalds * This driver allows a USB IrDA device to be used as a "dumb" serial device. 13*1da177e4SLinus Torvalds * This can be useful if you do not have access to a full IrDA stack on the 14*1da177e4SLinus Torvalds * other side of the connection. If you do have an IrDA stack on both devices, 15*1da177e4SLinus Torvalds * please use the usb-irda driver, as it contains the proper error checking and 16*1da177e4SLinus Torvalds * other goodness of a full IrDA stack. 17*1da177e4SLinus Torvalds * 18*1da177e4SLinus Torvalds * Portions of this driver were taken from drivers/net/irda/irda-usb.c, which 19*1da177e4SLinus Torvalds * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli 20*1da177e4SLinus Torvalds * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com> 21*1da177e4SLinus Torvalds * 22*1da177e4SLinus Torvalds * See Documentation/usb/usb-serial.txt for more information on using this driver 23*1da177e4SLinus Torvalds * 24*1da177e4SLinus Torvalds * 2002_Mar_07 greg kh 25*1da177e4SLinus Torvalds * moved some needed structures and #define values from the 26*1da177e4SLinus Torvalds * net/irda/irda-usb.h file into our file, as we don't want to depend on 27*1da177e4SLinus Torvalds * that codebase compiling correctly :) 28*1da177e4SLinus Torvalds * 29*1da177e4SLinus Torvalds * 2002_Jan_14 gb 30*1da177e4SLinus Torvalds * Added module parameter to force specific number of XBOFs. 31*1da177e4SLinus Torvalds * Added ir_xbof_change(). 32*1da177e4SLinus Torvalds * Reorganized read_bulk_callback error handling. 33*1da177e4SLinus Torvalds * Switched from FILL_BULK_URB() to usb_fill_bulk_urb(). 34*1da177e4SLinus Torvalds * 35*1da177e4SLinus Torvalds * 2001_Nov_08 greg kh 36*1da177e4SLinus Torvalds * Changed the irda_usb_find_class_desc() function based on comments and 37*1da177e4SLinus Torvalds * code from Martin Diehl. 38*1da177e4SLinus Torvalds * 39*1da177e4SLinus Torvalds * 2001_Nov_01 greg kh 40*1da177e4SLinus Torvalds * Added support for more IrDA USB devices. 41*1da177e4SLinus Torvalds * Added support for zero packet. Added buffer override paramater, so 42*1da177e4SLinus Torvalds * users can transfer larger packets at once if they wish. Both patches 43*1da177e4SLinus Torvalds * came from Dag Brattli <dag@obexcode.com>. 44*1da177e4SLinus Torvalds * 45*1da177e4SLinus Torvalds * 2001_Oct_07 greg kh 46*1da177e4SLinus Torvalds * initial version released. 47*1da177e4SLinus Torvalds */ 48*1da177e4SLinus Torvalds 49*1da177e4SLinus Torvalds #include <linux/config.h> 50*1da177e4SLinus Torvalds #include <linux/kernel.h> 51*1da177e4SLinus Torvalds #include <linux/errno.h> 52*1da177e4SLinus Torvalds #include <linux/init.h> 53*1da177e4SLinus Torvalds #include <linux/slab.h> 54*1da177e4SLinus Torvalds #include <linux/tty.h> 55*1da177e4SLinus Torvalds #include <linux/tty_driver.h> 56*1da177e4SLinus Torvalds #include <linux/tty_flip.h> 57*1da177e4SLinus Torvalds #include <linux/module.h> 58*1da177e4SLinus Torvalds #include <linux/spinlock.h> 59*1da177e4SLinus Torvalds #include <asm/uaccess.h> 60*1da177e4SLinus Torvalds #include <linux/usb.h> 61*1da177e4SLinus Torvalds #include "usb-serial.h" 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds /* 64*1da177e4SLinus Torvalds * Version Information 65*1da177e4SLinus Torvalds */ 66*1da177e4SLinus Torvalds #define DRIVER_VERSION "v0.4" 67*1da177e4SLinus Torvalds #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" 68*1da177e4SLinus Torvalds #define DRIVER_DESC "USB IR Dongle driver" 69*1da177e4SLinus Torvalds 70*1da177e4SLinus Torvalds /* USB IrDA class spec information */ 71*1da177e4SLinus Torvalds #define USB_CLASS_IRDA 0x02 72*1da177e4SLinus Torvalds #define USB_DT_IRDA 0x21 73*1da177e4SLinus Torvalds #define IU_REQ_GET_CLASS_DESC 0x06 74*1da177e4SLinus Torvalds #define SPEED_2400 0x01 75*1da177e4SLinus Torvalds #define SPEED_9600 0x02 76*1da177e4SLinus Torvalds #define SPEED_19200 0x03 77*1da177e4SLinus Torvalds #define SPEED_38400 0x04 78*1da177e4SLinus Torvalds #define SPEED_57600 0x05 79*1da177e4SLinus Torvalds #define SPEED_115200 0x06 80*1da177e4SLinus Torvalds #define SPEED_576000 0x07 81*1da177e4SLinus Torvalds #define SPEED_1152000 0x08 82*1da177e4SLinus Torvalds #define SPEED_4000000 0x09 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds struct irda_class_desc { 85*1da177e4SLinus Torvalds u8 bLength; 86*1da177e4SLinus Torvalds u8 bDescriptorType; 87*1da177e4SLinus Torvalds u16 bcdSpecRevision; 88*1da177e4SLinus Torvalds u8 bmDataSize; 89*1da177e4SLinus Torvalds u8 bmWindowSize; 90*1da177e4SLinus Torvalds u8 bmMinTurnaroundTime; 91*1da177e4SLinus Torvalds u16 wBaudRate; 92*1da177e4SLinus Torvalds u8 bmAdditionalBOFs; 93*1da177e4SLinus Torvalds u8 bIrdaRateSniff; 94*1da177e4SLinus Torvalds u8 bMaxUnicastList; 95*1da177e4SLinus Torvalds } __attribute__ ((packed)); 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds static int debug; 98*1da177e4SLinus Torvalds 99*1da177e4SLinus Torvalds /* if overridden by the user, then use their value for the size of the read and 100*1da177e4SLinus Torvalds * write urbs */ 101*1da177e4SLinus Torvalds static int buffer_size; 102*1da177e4SLinus Torvalds /* if overridden by the user, then use the specified number of XBOFs */ 103*1da177e4SLinus Torvalds static int xbof = -1; 104*1da177e4SLinus Torvalds 105*1da177e4SLinus Torvalds static int ir_startup (struct usb_serial *serial); 106*1da177e4SLinus Torvalds static int ir_open (struct usb_serial_port *port, struct file *filep); 107*1da177e4SLinus Torvalds static void ir_close (struct usb_serial_port *port, struct file *filep); 108*1da177e4SLinus Torvalds static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count); 109*1da177e4SLinus Torvalds static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs); 110*1da177e4SLinus Torvalds static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs); 111*1da177e4SLinus Torvalds static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios); 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds static u8 ir_baud = 0; 114*1da177e4SLinus Torvalds static u8 ir_xbof = 0; 115*1da177e4SLinus Torvalds static u8 ir_add_bof = 0; 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds static struct usb_device_id id_table [] = { 118*1da177e4SLinus Torvalds { USB_DEVICE(0x050f, 0x0180) }, /* KC Technology, KC-180 */ 119*1da177e4SLinus Torvalds { USB_DEVICE(0x08e9, 0x0100) }, /* XTNDAccess */ 120*1da177e4SLinus Torvalds { USB_DEVICE(0x09c4, 0x0011) }, /* ACTiSys ACT-IR2000U */ 121*1da177e4SLinus Torvalds { USB_INTERFACE_INFO (USB_CLASS_APP_SPEC, USB_CLASS_IRDA, 0) }, 122*1da177e4SLinus Torvalds { } /* Terminating entry */ 123*1da177e4SLinus Torvalds }; 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds MODULE_DEVICE_TABLE (usb, id_table); 126*1da177e4SLinus Torvalds 127*1da177e4SLinus Torvalds static struct usb_driver ir_driver = { 128*1da177e4SLinus Torvalds .owner = THIS_MODULE, 129*1da177e4SLinus Torvalds .name = "ir-usb", 130*1da177e4SLinus Torvalds .probe = usb_serial_probe, 131*1da177e4SLinus Torvalds .disconnect = usb_serial_disconnect, 132*1da177e4SLinus Torvalds .id_table = id_table, 133*1da177e4SLinus Torvalds }; 134*1da177e4SLinus Torvalds 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds static struct usb_serial_device_type ir_device = { 137*1da177e4SLinus Torvalds .owner = THIS_MODULE, 138*1da177e4SLinus Torvalds .name = "IR Dongle", 139*1da177e4SLinus Torvalds .id_table = id_table, 140*1da177e4SLinus Torvalds .num_interrupt_in = 1, 141*1da177e4SLinus Torvalds .num_bulk_in = 1, 142*1da177e4SLinus Torvalds .num_bulk_out = 1, 143*1da177e4SLinus Torvalds .num_ports = 1, 144*1da177e4SLinus Torvalds .set_termios = ir_set_termios, 145*1da177e4SLinus Torvalds .attach = ir_startup, 146*1da177e4SLinus Torvalds .open = ir_open, 147*1da177e4SLinus Torvalds .close = ir_close, 148*1da177e4SLinus Torvalds .write = ir_write, 149*1da177e4SLinus Torvalds .write_bulk_callback = ir_write_bulk_callback, 150*1da177e4SLinus Torvalds .read_bulk_callback = ir_read_bulk_callback, 151*1da177e4SLinus Torvalds }; 152*1da177e4SLinus Torvalds 153*1da177e4SLinus Torvalds static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc) 154*1da177e4SLinus Torvalds { 155*1da177e4SLinus Torvalds dbg("bLength=%x", desc->bLength); 156*1da177e4SLinus Torvalds dbg("bDescriptorType=%x", desc->bDescriptorType); 157*1da177e4SLinus Torvalds dbg("bcdSpecRevision=%x", desc->bcdSpecRevision); 158*1da177e4SLinus Torvalds dbg("bmDataSize=%x", desc->bmDataSize); 159*1da177e4SLinus Torvalds dbg("bmWindowSize=%x", desc->bmWindowSize); 160*1da177e4SLinus Torvalds dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime); 161*1da177e4SLinus Torvalds dbg("wBaudRate=%x", desc->wBaudRate); 162*1da177e4SLinus Torvalds dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs); 163*1da177e4SLinus Torvalds dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff); 164*1da177e4SLinus Torvalds dbg("bMaxUnicastList=%x", desc->bMaxUnicastList); 165*1da177e4SLinus Torvalds } 166*1da177e4SLinus Torvalds 167*1da177e4SLinus Torvalds /*------------------------------------------------------------------*/ 168*1da177e4SLinus Torvalds /* 169*1da177e4SLinus Torvalds * Function irda_usb_find_class_desc(dev, ifnum) 170*1da177e4SLinus Torvalds * 171*1da177e4SLinus Torvalds * Returns instance of IrDA class descriptor, or NULL if not found 172*1da177e4SLinus Torvalds * 173*1da177e4SLinus Torvalds * The class descriptor is some extra info that IrDA USB devices will 174*1da177e4SLinus Torvalds * offer to us, describing their IrDA characteristics. We will use that in 175*1da177e4SLinus Torvalds * irda_usb_init_qos() 176*1da177e4SLinus Torvalds * 177*1da177e4SLinus Torvalds * Based on the same function in drivers/net/irda/irda-usb.c 178*1da177e4SLinus Torvalds */ 179*1da177e4SLinus Torvalds static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum) 180*1da177e4SLinus Torvalds { 181*1da177e4SLinus Torvalds struct irda_class_desc *desc; 182*1da177e4SLinus Torvalds int ret; 183*1da177e4SLinus Torvalds 184*1da177e4SLinus Torvalds desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL); 185*1da177e4SLinus Torvalds if (desc == NULL) 186*1da177e4SLinus Torvalds return NULL; 187*1da177e4SLinus Torvalds memset(desc, 0, sizeof(struct irda_class_desc)); 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), 190*1da177e4SLinus Torvalds IU_REQ_GET_CLASS_DESC, 191*1da177e4SLinus Torvalds USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 192*1da177e4SLinus Torvalds 0, ifnum, desc, sizeof(*desc), 1000); 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds dbg("%s - ret=%d", __FUNCTION__, ret); 195*1da177e4SLinus Torvalds if (ret < sizeof(*desc)) { 196*1da177e4SLinus Torvalds dbg("%s - class descriptor read %s (%d)", 197*1da177e4SLinus Torvalds __FUNCTION__, 198*1da177e4SLinus Torvalds (ret<0) ? "failed" : "too short", 199*1da177e4SLinus Torvalds ret); 200*1da177e4SLinus Torvalds goto error; 201*1da177e4SLinus Torvalds } 202*1da177e4SLinus Torvalds if (desc->bDescriptorType != USB_DT_IRDA) { 203*1da177e4SLinus Torvalds dbg("%s - bad class descriptor type", __FUNCTION__); 204*1da177e4SLinus Torvalds goto error; 205*1da177e4SLinus Torvalds } 206*1da177e4SLinus Torvalds 207*1da177e4SLinus Torvalds irda_usb_dump_class_desc(desc); 208*1da177e4SLinus Torvalds return desc; 209*1da177e4SLinus Torvalds error: 210*1da177e4SLinus Torvalds kfree(desc); 211*1da177e4SLinus Torvalds return NULL; 212*1da177e4SLinus Torvalds } 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds 215*1da177e4SLinus Torvalds static u8 ir_xbof_change(u8 xbof) 216*1da177e4SLinus Torvalds { 217*1da177e4SLinus Torvalds u8 result; 218*1da177e4SLinus Torvalds /* reference irda-usb.c */ 219*1da177e4SLinus Torvalds switch(xbof) { 220*1da177e4SLinus Torvalds case 48: result = 0x10; break; 221*1da177e4SLinus Torvalds case 28: 222*1da177e4SLinus Torvalds case 24: result = 0x20; break; 223*1da177e4SLinus Torvalds default: 224*1da177e4SLinus Torvalds case 12: result = 0x30; break; 225*1da177e4SLinus Torvalds case 5: 226*1da177e4SLinus Torvalds case 6: result = 0x40; break; 227*1da177e4SLinus Torvalds case 3: result = 0x50; break; 228*1da177e4SLinus Torvalds case 2: result = 0x60; break; 229*1da177e4SLinus Torvalds case 1: result = 0x70; break; 230*1da177e4SLinus Torvalds case 0: result = 0x80; break; 231*1da177e4SLinus Torvalds } 232*1da177e4SLinus Torvalds return(result); 233*1da177e4SLinus Torvalds } 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds 236*1da177e4SLinus Torvalds static int ir_startup (struct usb_serial *serial) 237*1da177e4SLinus Torvalds { 238*1da177e4SLinus Torvalds struct irda_class_desc *irda_desc; 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds irda_desc = irda_usb_find_class_desc (serial->dev, 0); 241*1da177e4SLinus Torvalds if (irda_desc == NULL) { 242*1da177e4SLinus Torvalds dev_err (&serial->dev->dev, "IRDA class descriptor not found, device not bound\n"); 243*1da177e4SLinus Torvalds return -ENODEV; 244*1da177e4SLinus Torvalds } 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s", 247*1da177e4SLinus Torvalds __FUNCTION__, 248*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0001) ? " 2400" : "", 249*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0002) ? " 9600" : "", 250*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0004) ? " 19200" : "", 251*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0008) ? " 38400" : "", 252*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0010) ? " 57600" : "", 253*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0020) ? " 115200" : "", 254*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0040) ? " 576000" : "", 255*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0080) ? " 1152000" : "", 256*1da177e4SLinus Torvalds (irda_desc->wBaudRate & 0x0100) ? " 4000000" : ""); 257*1da177e4SLinus Torvalds 258*1da177e4SLinus Torvalds switch( irda_desc->bmAdditionalBOFs ) { 259*1da177e4SLinus Torvalds case 0x01: ir_add_bof = 48; break; 260*1da177e4SLinus Torvalds case 0x02: ir_add_bof = 24; break; 261*1da177e4SLinus Torvalds case 0x04: ir_add_bof = 12; break; 262*1da177e4SLinus Torvalds case 0x08: ir_add_bof = 6; break; 263*1da177e4SLinus Torvalds case 0x10: ir_add_bof = 3; break; 264*1da177e4SLinus Torvalds case 0x20: ir_add_bof = 2; break; 265*1da177e4SLinus Torvalds case 0x40: ir_add_bof = 1; break; 266*1da177e4SLinus Torvalds case 0x80: ir_add_bof = 0; break; 267*1da177e4SLinus Torvalds default:; 268*1da177e4SLinus Torvalds } 269*1da177e4SLinus Torvalds 270*1da177e4SLinus Torvalds kfree (irda_desc); 271*1da177e4SLinus Torvalds 272*1da177e4SLinus Torvalds return 0; 273*1da177e4SLinus Torvalds } 274*1da177e4SLinus Torvalds 275*1da177e4SLinus Torvalds static int ir_open (struct usb_serial_port *port, struct file *filp) 276*1da177e4SLinus Torvalds { 277*1da177e4SLinus Torvalds char *buffer; 278*1da177e4SLinus Torvalds int result = 0; 279*1da177e4SLinus Torvalds 280*1da177e4SLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 281*1da177e4SLinus Torvalds 282*1da177e4SLinus Torvalds if (buffer_size) { 283*1da177e4SLinus Torvalds /* override the default buffer sizes */ 284*1da177e4SLinus Torvalds buffer = kmalloc (buffer_size, GFP_KERNEL); 285*1da177e4SLinus Torvalds if (!buffer) { 286*1da177e4SLinus Torvalds dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__); 287*1da177e4SLinus Torvalds return -ENOMEM; 288*1da177e4SLinus Torvalds } 289*1da177e4SLinus Torvalds kfree (port->read_urb->transfer_buffer); 290*1da177e4SLinus Torvalds port->read_urb->transfer_buffer = buffer; 291*1da177e4SLinus Torvalds port->read_urb->transfer_buffer_length = buffer_size; 292*1da177e4SLinus Torvalds 293*1da177e4SLinus Torvalds buffer = kmalloc (buffer_size, GFP_KERNEL); 294*1da177e4SLinus Torvalds if (!buffer) { 295*1da177e4SLinus Torvalds dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__); 296*1da177e4SLinus Torvalds return -ENOMEM; 297*1da177e4SLinus Torvalds } 298*1da177e4SLinus Torvalds kfree (port->write_urb->transfer_buffer); 299*1da177e4SLinus Torvalds port->write_urb->transfer_buffer = buffer; 300*1da177e4SLinus Torvalds port->write_urb->transfer_buffer_length = buffer_size; 301*1da177e4SLinus Torvalds port->bulk_out_size = buffer_size; 302*1da177e4SLinus Torvalds } 303*1da177e4SLinus Torvalds 304*1da177e4SLinus Torvalds /* Start reading from the device */ 305*1da177e4SLinus Torvalds usb_fill_bulk_urb ( 306*1da177e4SLinus Torvalds port->read_urb, 307*1da177e4SLinus Torvalds port->serial->dev, 308*1da177e4SLinus Torvalds usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), 309*1da177e4SLinus Torvalds port->read_urb->transfer_buffer, 310*1da177e4SLinus Torvalds port->read_urb->transfer_buffer_length, 311*1da177e4SLinus Torvalds ir_read_bulk_callback, 312*1da177e4SLinus Torvalds port); 313*1da177e4SLinus Torvalds result = usb_submit_urb(port->read_urb, GFP_KERNEL); 314*1da177e4SLinus Torvalds if (result) 315*1da177e4SLinus Torvalds dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); 316*1da177e4SLinus Torvalds 317*1da177e4SLinus Torvalds return result; 318*1da177e4SLinus Torvalds } 319*1da177e4SLinus Torvalds 320*1da177e4SLinus Torvalds static void ir_close (struct usb_serial_port *port, struct file * filp) 321*1da177e4SLinus Torvalds { 322*1da177e4SLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 323*1da177e4SLinus Torvalds 324*1da177e4SLinus Torvalds /* shutdown our bulk read */ 325*1da177e4SLinus Torvalds usb_kill_urb(port->read_urb); 326*1da177e4SLinus Torvalds } 327*1da177e4SLinus Torvalds 328*1da177e4SLinus Torvalds static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count) 329*1da177e4SLinus Torvalds { 330*1da177e4SLinus Torvalds unsigned char *transfer_buffer; 331*1da177e4SLinus Torvalds int result; 332*1da177e4SLinus Torvalds int transfer_size; 333*1da177e4SLinus Torvalds 334*1da177e4SLinus Torvalds dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count); 335*1da177e4SLinus Torvalds 336*1da177e4SLinus Torvalds if (!port->tty) { 337*1da177e4SLinus Torvalds dev_err (&port->dev, "%s - no tty???\n", __FUNCTION__); 338*1da177e4SLinus Torvalds return 0; 339*1da177e4SLinus Torvalds } 340*1da177e4SLinus Torvalds 341*1da177e4SLinus Torvalds if (count == 0) 342*1da177e4SLinus Torvalds return 0; 343*1da177e4SLinus Torvalds 344*1da177e4SLinus Torvalds if (port->write_urb->status == -EINPROGRESS) { 345*1da177e4SLinus Torvalds dbg ("%s - already writing", __FUNCTION__); 346*1da177e4SLinus Torvalds return 0; 347*1da177e4SLinus Torvalds } 348*1da177e4SLinus Torvalds 349*1da177e4SLinus Torvalds transfer_buffer = port->write_urb->transfer_buffer; 350*1da177e4SLinus Torvalds transfer_size = min(count, port->bulk_out_size - 1); 351*1da177e4SLinus Torvalds 352*1da177e4SLinus Torvalds /* 353*1da177e4SLinus Torvalds * The first byte of the packet we send to the device contains an 354*1da177e4SLinus Torvalds * inband header which indicates an additional number of BOFs and 355*1da177e4SLinus Torvalds * a baud rate change. 356*1da177e4SLinus Torvalds * 357*1da177e4SLinus Torvalds * See section 5.4.2.2 of the USB IrDA spec. 358*1da177e4SLinus Torvalds */ 359*1da177e4SLinus Torvalds *transfer_buffer = ir_xbof | ir_baud; 360*1da177e4SLinus Torvalds ++transfer_buffer; 361*1da177e4SLinus Torvalds 362*1da177e4SLinus Torvalds memcpy (transfer_buffer, buf, transfer_size); 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds usb_fill_bulk_urb ( 365*1da177e4SLinus Torvalds port->write_urb, 366*1da177e4SLinus Torvalds port->serial->dev, 367*1da177e4SLinus Torvalds usb_sndbulkpipe(port->serial->dev, 368*1da177e4SLinus Torvalds port->bulk_out_endpointAddress), 369*1da177e4SLinus Torvalds port->write_urb->transfer_buffer, 370*1da177e4SLinus Torvalds transfer_size + 1, 371*1da177e4SLinus Torvalds ir_write_bulk_callback, 372*1da177e4SLinus Torvalds port); 373*1da177e4SLinus Torvalds 374*1da177e4SLinus Torvalds port->write_urb->transfer_flags = URB_ZERO_PACKET; 375*1da177e4SLinus Torvalds 376*1da177e4SLinus Torvalds result = usb_submit_urb (port->write_urb, GFP_ATOMIC); 377*1da177e4SLinus Torvalds if (result) 378*1da177e4SLinus Torvalds dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); 379*1da177e4SLinus Torvalds else 380*1da177e4SLinus Torvalds result = transfer_size; 381*1da177e4SLinus Torvalds 382*1da177e4SLinus Torvalds return result; 383*1da177e4SLinus Torvalds } 384*1da177e4SLinus Torvalds 385*1da177e4SLinus Torvalds static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs) 386*1da177e4SLinus Torvalds { 387*1da177e4SLinus Torvalds struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 388*1da177e4SLinus Torvalds 389*1da177e4SLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 390*1da177e4SLinus Torvalds 391*1da177e4SLinus Torvalds if (urb->status) { 392*1da177e4SLinus Torvalds dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); 393*1da177e4SLinus Torvalds return; 394*1da177e4SLinus Torvalds } 395*1da177e4SLinus Torvalds 396*1da177e4SLinus Torvalds usb_serial_debug_data ( 397*1da177e4SLinus Torvalds debug, 398*1da177e4SLinus Torvalds &port->dev, 399*1da177e4SLinus Torvalds __FUNCTION__, 400*1da177e4SLinus Torvalds urb->actual_length, 401*1da177e4SLinus Torvalds urb->transfer_buffer); 402*1da177e4SLinus Torvalds 403*1da177e4SLinus Torvalds schedule_work(&port->work); 404*1da177e4SLinus Torvalds } 405*1da177e4SLinus Torvalds 406*1da177e4SLinus Torvalds static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) 407*1da177e4SLinus Torvalds { 408*1da177e4SLinus Torvalds struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 409*1da177e4SLinus Torvalds struct tty_struct *tty; 410*1da177e4SLinus Torvalds unsigned char *data = urb->transfer_buffer; 411*1da177e4SLinus Torvalds int result; 412*1da177e4SLinus Torvalds 413*1da177e4SLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 414*1da177e4SLinus Torvalds 415*1da177e4SLinus Torvalds if (!port->open_count) { 416*1da177e4SLinus Torvalds dbg("%s - port closed.", __FUNCTION__); 417*1da177e4SLinus Torvalds return; 418*1da177e4SLinus Torvalds } 419*1da177e4SLinus Torvalds 420*1da177e4SLinus Torvalds switch (urb->status) { 421*1da177e4SLinus Torvalds 422*1da177e4SLinus Torvalds case 0: /* Successful */ 423*1da177e4SLinus Torvalds 424*1da177e4SLinus Torvalds /* 425*1da177e4SLinus Torvalds * The first byte of the packet we get from the device 426*1da177e4SLinus Torvalds * contains a busy indicator and baud rate change. 427*1da177e4SLinus Torvalds * See section 5.4.1.2 of the USB IrDA spec. 428*1da177e4SLinus Torvalds */ 429*1da177e4SLinus Torvalds if ((*data & 0x0f) > 0) 430*1da177e4SLinus Torvalds ir_baud = *data & 0x0f; 431*1da177e4SLinus Torvalds 432*1da177e4SLinus Torvalds usb_serial_debug_data ( 433*1da177e4SLinus Torvalds debug, 434*1da177e4SLinus Torvalds &port->dev, 435*1da177e4SLinus Torvalds __FUNCTION__, 436*1da177e4SLinus Torvalds urb->actual_length, 437*1da177e4SLinus Torvalds data); 438*1da177e4SLinus Torvalds 439*1da177e4SLinus Torvalds /* 440*1da177e4SLinus Torvalds * Bypass flip-buffers, and feed the ldisc directly 441*1da177e4SLinus Torvalds * due to our potentially large buffer size. Since we 442*1da177e4SLinus Torvalds * used to set low_latency, this is exactly what the 443*1da177e4SLinus Torvalds * tty layer did anyway :) 444*1da177e4SLinus Torvalds */ 445*1da177e4SLinus Torvalds tty = port->tty; 446*1da177e4SLinus Torvalds 447*1da177e4SLinus Torvalds /* 448*1da177e4SLinus Torvalds * FIXME: must not do this in IRQ context, 449*1da177e4SLinus Torvalds * must honour TTY_DONT_FLIP 450*1da177e4SLinus Torvalds */ 451*1da177e4SLinus Torvalds tty->ldisc.receive_buf( 452*1da177e4SLinus Torvalds tty, 453*1da177e4SLinus Torvalds data+1, 454*1da177e4SLinus Torvalds NULL, 455*1da177e4SLinus Torvalds urb->actual_length-1); 456*1da177e4SLinus Torvalds 457*1da177e4SLinus Torvalds /* 458*1da177e4SLinus Torvalds * No break here. 459*1da177e4SLinus Torvalds * We want to resubmit the urb so we can read 460*1da177e4SLinus Torvalds * again. 461*1da177e4SLinus Torvalds */ 462*1da177e4SLinus Torvalds 463*1da177e4SLinus Torvalds case -EPROTO: /* taking inspiration from pl2303.c */ 464*1da177e4SLinus Torvalds 465*1da177e4SLinus Torvalds /* Continue trying to always read */ 466*1da177e4SLinus Torvalds usb_fill_bulk_urb ( 467*1da177e4SLinus Torvalds port->read_urb, 468*1da177e4SLinus Torvalds port->serial->dev, 469*1da177e4SLinus Torvalds usb_rcvbulkpipe(port->serial->dev, 470*1da177e4SLinus Torvalds port->bulk_in_endpointAddress), 471*1da177e4SLinus Torvalds port->read_urb->transfer_buffer, 472*1da177e4SLinus Torvalds port->read_urb->transfer_buffer_length, 473*1da177e4SLinus Torvalds ir_read_bulk_callback, 474*1da177e4SLinus Torvalds port); 475*1da177e4SLinus Torvalds 476*1da177e4SLinus Torvalds result = usb_submit_urb(port->read_urb, GFP_ATOMIC); 477*1da177e4SLinus Torvalds if (result) 478*1da177e4SLinus Torvalds dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", 479*1da177e4SLinus Torvalds __FUNCTION__, result); 480*1da177e4SLinus Torvalds 481*1da177e4SLinus Torvalds break ; 482*1da177e4SLinus Torvalds 483*1da177e4SLinus Torvalds default: 484*1da177e4SLinus Torvalds dbg("%s - nonzero read bulk status received: %d", 485*1da177e4SLinus Torvalds __FUNCTION__, 486*1da177e4SLinus Torvalds urb->status); 487*1da177e4SLinus Torvalds break ; 488*1da177e4SLinus Torvalds 489*1da177e4SLinus Torvalds } 490*1da177e4SLinus Torvalds 491*1da177e4SLinus Torvalds return; 492*1da177e4SLinus Torvalds } 493*1da177e4SLinus Torvalds 494*1da177e4SLinus Torvalds static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios) 495*1da177e4SLinus Torvalds { 496*1da177e4SLinus Torvalds unsigned char *transfer_buffer; 497*1da177e4SLinus Torvalds unsigned int cflag; 498*1da177e4SLinus Torvalds int result; 499*1da177e4SLinus Torvalds 500*1da177e4SLinus Torvalds dbg("%s - port %d", __FUNCTION__, port->number); 501*1da177e4SLinus Torvalds 502*1da177e4SLinus Torvalds if ((!port->tty) || (!port->tty->termios)) { 503*1da177e4SLinus Torvalds dbg("%s - no tty structures", __FUNCTION__); 504*1da177e4SLinus Torvalds return; 505*1da177e4SLinus Torvalds } 506*1da177e4SLinus Torvalds 507*1da177e4SLinus Torvalds cflag = port->tty->termios->c_cflag; 508*1da177e4SLinus Torvalds /* check that they really want us to change something */ 509*1da177e4SLinus Torvalds if (old_termios) { 510*1da177e4SLinus Torvalds if ((cflag == old_termios->c_cflag) && 511*1da177e4SLinus Torvalds (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { 512*1da177e4SLinus Torvalds dbg("%s - nothing to change...", __FUNCTION__); 513*1da177e4SLinus Torvalds return; 514*1da177e4SLinus Torvalds } 515*1da177e4SLinus Torvalds } 516*1da177e4SLinus Torvalds 517*1da177e4SLinus Torvalds /* All we can change is the baud rate */ 518*1da177e4SLinus Torvalds if (cflag & CBAUD) { 519*1da177e4SLinus Torvalds 520*1da177e4SLinus Torvalds dbg ("%s - asking for baud %d", 521*1da177e4SLinus Torvalds __FUNCTION__, 522*1da177e4SLinus Torvalds tty_get_baud_rate(port->tty)); 523*1da177e4SLinus Torvalds 524*1da177e4SLinus Torvalds /* 525*1da177e4SLinus Torvalds * FIXME, we should compare the baud request against the 526*1da177e4SLinus Torvalds * capability stated in the IR header that we got in the 527*1da177e4SLinus Torvalds * startup function. 528*1da177e4SLinus Torvalds */ 529*1da177e4SLinus Torvalds switch (cflag & CBAUD) { 530*1da177e4SLinus Torvalds case B2400: ir_baud = SPEED_2400; break; 531*1da177e4SLinus Torvalds default: 532*1da177e4SLinus Torvalds case B9600: ir_baud = SPEED_9600; break; 533*1da177e4SLinus Torvalds case B19200: ir_baud = SPEED_19200; break; 534*1da177e4SLinus Torvalds case B38400: ir_baud = SPEED_38400; break; 535*1da177e4SLinus Torvalds case B57600: ir_baud = SPEED_57600; break; 536*1da177e4SLinus Torvalds case B115200: ir_baud = SPEED_115200; break; 537*1da177e4SLinus Torvalds case B576000: ir_baud = SPEED_576000; break; 538*1da177e4SLinus Torvalds case B1152000: ir_baud = SPEED_1152000; break; 539*1da177e4SLinus Torvalds #ifdef B4000000 540*1da177e4SLinus Torvalds case B4000000: ir_baud = SPEED_4000000; break; 541*1da177e4SLinus Torvalds #endif 542*1da177e4SLinus Torvalds } 543*1da177e4SLinus Torvalds 544*1da177e4SLinus Torvalds if (xbof == -1) { 545*1da177e4SLinus Torvalds ir_xbof = ir_xbof_change(ir_add_bof); 546*1da177e4SLinus Torvalds } else { 547*1da177e4SLinus Torvalds ir_xbof = ir_xbof_change(xbof) ; 548*1da177e4SLinus Torvalds } 549*1da177e4SLinus Torvalds 550*1da177e4SLinus Torvalds /* Notify the tty driver that the termios have changed. */ 551*1da177e4SLinus Torvalds port->tty->ldisc.set_termios(port->tty, NULL); 552*1da177e4SLinus Torvalds 553*1da177e4SLinus Torvalds /* FIXME need to check to see if our write urb is busy right 554*1da177e4SLinus Torvalds * now, or use a urb pool. 555*1da177e4SLinus Torvalds * 556*1da177e4SLinus Torvalds * send the baud change out on an "empty" data packet 557*1da177e4SLinus Torvalds */ 558*1da177e4SLinus Torvalds transfer_buffer = port->write_urb->transfer_buffer; 559*1da177e4SLinus Torvalds *transfer_buffer = ir_xbof | ir_baud; 560*1da177e4SLinus Torvalds 561*1da177e4SLinus Torvalds usb_fill_bulk_urb ( 562*1da177e4SLinus Torvalds port->write_urb, 563*1da177e4SLinus Torvalds port->serial->dev, 564*1da177e4SLinus Torvalds usb_sndbulkpipe(port->serial->dev, 565*1da177e4SLinus Torvalds port->bulk_out_endpointAddress), 566*1da177e4SLinus Torvalds port->write_urb->transfer_buffer, 567*1da177e4SLinus Torvalds 1, 568*1da177e4SLinus Torvalds ir_write_bulk_callback, 569*1da177e4SLinus Torvalds port); 570*1da177e4SLinus Torvalds 571*1da177e4SLinus Torvalds port->write_urb->transfer_flags = URB_ZERO_PACKET; 572*1da177e4SLinus Torvalds 573*1da177e4SLinus Torvalds result = usb_submit_urb (port->write_urb, GFP_KERNEL); 574*1da177e4SLinus Torvalds if (result) 575*1da177e4SLinus Torvalds dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); 576*1da177e4SLinus Torvalds } 577*1da177e4SLinus Torvalds return; 578*1da177e4SLinus Torvalds } 579*1da177e4SLinus Torvalds 580*1da177e4SLinus Torvalds 581*1da177e4SLinus Torvalds static int __init ir_init (void) 582*1da177e4SLinus Torvalds { 583*1da177e4SLinus Torvalds int retval; 584*1da177e4SLinus Torvalds retval = usb_serial_register(&ir_device); 585*1da177e4SLinus Torvalds if (retval) 586*1da177e4SLinus Torvalds goto failed_usb_serial_register; 587*1da177e4SLinus Torvalds retval = usb_register(&ir_driver); 588*1da177e4SLinus Torvalds if (retval) 589*1da177e4SLinus Torvalds goto failed_usb_register; 590*1da177e4SLinus Torvalds info(DRIVER_DESC " " DRIVER_VERSION); 591*1da177e4SLinus Torvalds return 0; 592*1da177e4SLinus Torvalds failed_usb_register: 593*1da177e4SLinus Torvalds usb_serial_deregister(&ir_device); 594*1da177e4SLinus Torvalds failed_usb_serial_register: 595*1da177e4SLinus Torvalds return retval; 596*1da177e4SLinus Torvalds } 597*1da177e4SLinus Torvalds 598*1da177e4SLinus Torvalds 599*1da177e4SLinus Torvalds static void __exit ir_exit (void) 600*1da177e4SLinus Torvalds { 601*1da177e4SLinus Torvalds usb_deregister (&ir_driver); 602*1da177e4SLinus Torvalds usb_serial_deregister (&ir_device); 603*1da177e4SLinus Torvalds } 604*1da177e4SLinus Torvalds 605*1da177e4SLinus Torvalds 606*1da177e4SLinus Torvalds module_init(ir_init); 607*1da177e4SLinus Torvalds module_exit(ir_exit); 608*1da177e4SLinus Torvalds 609*1da177e4SLinus Torvalds MODULE_AUTHOR(DRIVER_AUTHOR); 610*1da177e4SLinus Torvalds MODULE_DESCRIPTION(DRIVER_DESC); 611*1da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 612*1da177e4SLinus Torvalds 613*1da177e4SLinus Torvalds module_param(debug, bool, S_IRUGO | S_IWUSR); 614*1da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "Debug enabled or not"); 615*1da177e4SLinus Torvalds module_param(xbof, int, 0); 616*1da177e4SLinus Torvalds MODULE_PARM_DESC(xbof, "Force specific number of XBOFs"); 617*1da177e4SLinus Torvalds module_param(buffer_size, int, 0); 618*1da177e4SLinus Torvalds MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers"); 619*1da177e4SLinus Torvalds 620