/*****************************************************************************
*
* Filename: stir4200.c
* Version: 0.4
* Description: Irda SigmaTel USB Dongle
* Status: Experimental
* Author: Stephen Hemminger <shemminger@osdl.org>
*
* Based on earlier driver by Paul Stewart <stewart@parc.com>
*
* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2001, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
/*
* This dongle does no framing, and requires polling to receive the
* data. The STIr4200 has bulk in and out endpoints just like
* usr-irda devices, but the data it sends and receives is raw; like
* irtty, it needs to call the wrap and unwrap functions to add and
* remove SOF/BOF and escape characters to/from the frame.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/usb.h>
#include <linux/crc32.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
#include <net/irda/wrapper.h>
#include <net/irda/crc.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_DESCRIPTION("IrDA-USB Dongle Driver for SigmaTel STIr4200");
MODULE_LICENSE("GPL");
static int qos_mtt_bits = 0x07; /* 1 ms or more */
module_param(qos_mtt_bits, int, 0);
MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
static int rx_sensitivity = 1; /* FIR 0..4, SIR 0..6 */
module_param(rx_sensitivity, int, 0);
MODULE_PARM_DESC(rx_sensitivity, "Set Receiver sensitivity (0-6, 0 is most sensitive)");
static int tx_power = 0; /* 0 = highest ... 3 = lowest */
module_param(tx_power, int, 0);
MODULE_PARM_DESC(tx_power, "Set Transmitter power (0-3, 0 is highest power)");
#define STIR_IRDA_HEADER 4
#define CTRL_TIMEOUT 100 /* milliseconds */
#define TRANSMIT_TIMEOUT 200 /* milliseconds */
#define STIR_FIFO_SIZE 4096
#define FIFO_REGS_SIZE 3
enum FirChars {
FIR_CE = 0x7d,
FIR_XBOF = 0x7f,
FIR_EOF = 0x7e,
};
enum StirRequests {
REQ_WRITE_REG = 0x00,
REQ_READ_REG = 0x01,
REQ_READ_ROM = 0x02,
REQ_WRITE_SINGLE = 0x03,
};
/* Register offsets */
enum StirRegs {
REG_RSVD=0,
REG_MODE,
REG_PDCLK,
REG_CTRL1,
REG_CTRL2,
REG_FIFOCTL,
REG_FIFOLSB,
REG_FIFOMSB,
REG_DPLL,
REG_IRDIG,
REG_TEST=15,
};
enum StirModeMask {
MODE_FIR = 0x80,
MODE_SIR = 0x20,
MODE_ASK = 0x10,
MODE_FASTRX = 0x08,
MODE_FFRSTEN = 0x04,
MODE_NRESET = 0x02,
MODE_2400 = 0x01,
};
enum StirPdclkMask {
PDCLK_4000000 = 0x02,
PDCLK_115200 = 0x09,
PDCLK_57600 = 0x13,
PDCLK_38400 = 0x1D,
PDCLK_19200 = 0x3B,
PDCLK_9600 = 0x77,
PDCLK_2400 = 0xDF,
};
enum StirCtrl1Mask {
CTRL1_SDMODE = 0x80,
CTRL1_RXSLOW = 0x40,
CTRL1_TXPWD = 0x10,
CTRL1_RXPWD = 0x08,
CTRL1_SRESET = 0x01,
};
enum StirCtrl2Mask {
CTRL2_SPWIDTH = 0x08,
CTRL2_REVID = 0x03,
};
enum StirFifoCtlMask {
FIFOCTL_EOF = 0x80,
FIFOCTL_UNDER = 0x40,
FIFOCTL_OVER = 0x20,
FIFOCTL_DIR = 0x10,
FIFOCTL_CLR = 0x08,
FIFOCTL_EMPTY = 0x04,
};
enum StirDiagMask {
IRDIG_RXHIGH = 0x80,
IRDIG_RXLOW = 0x40,
};
enum StirTestMask