Commit a2252286 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://gkernel.bkbits.net/irda-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents eee79d4f b4093065
......@@ -9,7 +9,7 @@ config IRTTY_SIR
depends on IRDA
help
Say Y here if you want to build support for the IrTTY line
discipline. If you want to compile it as a module (irtty.o), say M
discipline. If you want to compile it as a module (irtty-sir.o), say M
here and read <file:Documentation/modules.txt>. IrTTY makes it
possible to use Linux's own serial driver for all IrDA ports that
are 16550 compatible. Most IrDA chips are 16550 compatible so you
......@@ -18,6 +18,69 @@ config IRTTY_SIR
If unsure, say Y.
comment "Dongle support"
config DONGLE
bool "Serial dongle support"
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
or M to the driver for your particular dongle below.
Note that the answer to this question won't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about serial dongles.
config ESI_DONGLE
tristate "ESI JetEye PC dongle"
depends on DONGLE && IRDA
help
Say Y here if you want to build support for the Extended Systems
JetEye PC dongle. If you want to compile it as a module, say M here
and read <file:Documentation/modules.txt>. The ESI dongle attaches
to the normal 9-pin serial port connector, and can currently only be
used by IrTTY. To activate support for ESI dongles you will have to
start irattach like this: "irattach -d esi".
config ACTISYS_DONGLE
tristate "ACTiSYS IR-220L and IR220L+ dongle"
depends on DONGLE && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-220L and
IR220L+ dongles. If you want to compile it as a module, say M here
and read <file:Documentation/modules.txt>. The ACTiSYS dongles
attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for ACTiSYS
dongles you will have to start irattach like this:
"irattach -d actisys" or "irattach -d actisys+".
config TEKRAM_DONGLE
tristate "Tekram IrMate 210B dongle"
depends on DONGLE && IRDA
help
Say Y here if you want to build support for the Tekram IrMate 210B
dongle. If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. The Tekram dongle attaches to the
normal 9-pin serial port connector, and can currently only be used
by IrTTY. To activate support for Tekram dongles you will have to
start irattach like this: "irattach -d tekram".
comment "Old SIR device drivers"
config IRTTY_OLD
tristate "Old IrTTY (broken)"
depends on IRDA
help
Say Y here if you want to build support for the IrTTY line
discipline. If you want to compile it as a module (irtty.o), say M
here and read <file:Documentation/modules.txt>. IrTTY makes it
possible to use Linux's own serial driver for all IrDA ports that
are 16550 compatible. Most IrDA chips are 16550 compatible so you
should probably say Y to this option. Using IrTTY will however
limit the speed of the connection to 115200 bps (IrDA SIR mode).
If unsure, say N.
config IRPORT_SIR
tristate "IrPORT (IrDA serial driver)"
depends on IRDA
......@@ -35,10 +98,10 @@ config IRPORT_SIR
If unsure, say Y.
comment "Dongle support"
comment "Old Serial dongle support"
config DONGLE
bool "Serial dongle support"
config DONGLE_OLD
bool "Old Serial dongle support"
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
......@@ -48,9 +111,9 @@ config DONGLE
kernel: saying N will just cause the configurator to skip all
the questions about serial dongles.
config ESI_DONGLE
config ESI_DONGLE_OLD
tristate "ESI JetEye PC dongle"
depends on DONGLE && IRDA
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Extended Systems
JetEye PC dongle. If you want to compile it as a module, say M here
......@@ -59,9 +122,9 @@ config ESI_DONGLE
used by IrTTY. To activate support for ESI dongles you will have to
start irattach like this: "irattach -d esi".
config ACTISYS_DONGLE
config ACTISYS_DONGLE_OLD
tristate "ACTiSYS IR-220L and IR220L+ dongle"
depends on DONGLE && IRDA
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-220L and
IR220L+ dongles. If you want to compile it as a module, say M here
......@@ -71,9 +134,9 @@ config ACTISYS_DONGLE
dongles you will have to start irattach like this:
"irattach -d actisys" or "irattach -d actisys+".
config TEKRAM_DONGLE
config TEKRAM_DONGLE_OLD
tristate "Tekram IrMate 210B dongle"
depends on DONGLE && IRDA
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Tekram IrMate 210B
dongle. If you want to compile it as a module, say M here and read
......@@ -84,7 +147,7 @@ config TEKRAM_DONGLE
config GIRBIL_DONGLE
tristate "Greenwich GIrBIL dongle"
depends on DONGLE && IRDA
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Greenwich GIrBIL
dongle. If you want to compile it as a module, say M here and read
......@@ -95,7 +158,7 @@ config GIRBIL_DONGLE
config LITELINK_DONGLE
tristate "Parallax LiteLink dongle"
depends on DONGLE && IRDA
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Parallax Litelink
dongle. If you want to compile it as a module, say M here and read
......@@ -106,7 +169,7 @@ config LITELINK_DONGLE
config MCP2120_DONGLE
tristate "Microchip MCP2120"
depends on DONGLE && IRDA
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Microchip MCP2120
dongle. If you want to compile it as a module, say M here and read
......@@ -120,7 +183,7 @@ config MCP2120_DONGLE
config OLD_BELKIN_DONGLE
tristate "Old Belkin dongle"
depends on DONGLE && IRDA
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Adaptec Airport 1000
and 2000 dongles. If you want to compile it as a module, say M here
......@@ -130,11 +193,11 @@ config OLD_BELKIN_DONGLE
config EP7211_IR
tristate "EP7211 I/R support"
depends on DONGLE && ARCH_EP7211 && IRDA
depends on DONGLE_OLD && ARCH_EP7211 && IRDA
config ACT200L_DONGLE
tristate "ACTiSYS IR-200L dongle (EXPERIMENTAL)"
depends on DONGLE && EXPERIMENTAL && IRDA
depends on DONGLE_OLD && EXPERIMENTAL && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-200L
dongle. If you want to compile it as a module, say M here and read
......@@ -145,7 +208,7 @@ config ACT200L_DONGLE
config MA600_DONGLE
tristate "Mobile Action MA600 dongle (EXPERIMENTAL)"
depends on DONGLE && EXPERIMENTAL && IRDA
depends on DONGLE_OLD && EXPERIMENTAL && IRDA
---help---
Say Y here if you want to build support for the Mobile Action MA600
dongle. If you want to compile it as a module, say M here and read
......
......@@ -5,10 +5,12 @@
# Rewritten to use lists instead of if-statements.
#
export-objs = irport.o
export-objs = irport.o sir_core.o
obj-$(CONFIG_IRTTY_SIR) += irtty.o
# Old SIR drivers (irtty is broken)
obj-$(CONFIG_IRTTY_OLD) += irtty.o
obj-$(CONFIG_IRPORT_SIR) += irport.o
# FIR drivers
obj-$(CONFIG_USB_IRDA) += irda-usb.o
obj-$(CONFIG_NSC_FIR) += nsc-ircc.o
obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o
......@@ -18,9 +20,10 @@ obj-$(CONFIG_TOSHIBA_FIR) += donauboe.o
obj-$(CONFIG_SMC_IRCC_FIR) += smc-ircc.o irport.o
obj-$(CONFIG_ALI_FIR) += ali-ircc.o
obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o
obj-$(CONFIG_ESI_DONGLE) += esi.o
obj-$(CONFIG_TEKRAM_DONGLE) += tekram.o
obj-$(CONFIG_ACTISYS_DONGLE) += actisys.o
# Old dongle drivers for old SIR drivers
obj-$(CONFIG_ESI_OLD) += esi.o
obj-$(CONFIG_TEKRAM_OLD) += tekram.o
obj-$(CONFIG_ACTISYS_OLD) += actisys.o
obj-$(CONFIG_GIRBIL_DONGLE) += girbil.o
obj-$(CONFIG_LITELINK_DONGLE) += litelink.o
obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin.o
......@@ -28,5 +31,14 @@ obj-$(CONFIG_EP7211_IR) += ep7211_ir.o
obj-$(CONFIG_MCP2120_DONGLE) += mcp2120.o
obj-$(CONFIG_ACT200L_DONGLE) += act200l.o
obj-$(CONFIG_MA600_DONGLE) += ma600.o
# New SIR drivers
obj-$(CONFIG_IRTTY_SIR) += irtty-sir.o sir-dev.o
# New dongles drivers for new SIR drivers
obj-$(CONFIG_ESI_DONGLE) += esi-sir.o
obj-$(CONFIG_TEKRAM_DONGLE) += tekram-sir.o
obj-$(CONFIG_ACTISYS_DONGLE) += actisys-sir.o
# The SIR helper module
sir-dev-objs := sir_core.o sir_dev.o sir_dongle.o sir_kthread.o
include $(TOPDIR)/Rules.make
/*********************************************************************
*
* Filename: actisys.c
* Version: 1.1
* Description: Implementation for the ACTiSYS IR-220L and IR-220L+
* dongles
* Status: Beta.
* Authors: Dag Brattli <dagb@cs.uit.no> (initially)
* Jean Tourrilhes <jt@hpl.hp.com> (new version)
* Martin Diehl <mad@mdiehl.de> (new version for sir_dev)
* Created at: Wed Oct 21 20:02:35 1998
* Modified at: Sun Oct 27 22:02:13 2002
* Modified by: Martin Diehl <mad@mdiehl.de>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Copyright (c) 1999 Jean Tourrilhes
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
* Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
/*
* Changelog
*
* 0.8 -> 0.9999 - Jean
* o New initialisation procedure : much safer and correct
* o New procedure the change speed : much faster and simpler
* o Other cleanups & comments
* Thanks to Lichen Wang @ Actisys for his excellent help...
*
* 1.0 -> 1.1 - Martin Diehl
* modified for new sir infrastructure
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
/*
* Define the timing of the pulses we send to the dongle (to reset it, and
* to toggle speeds). Basically, the limit here is the propagation speed of
* the signals through the serial port, the dongle being much faster. Any
* serial port support 115 kb/s, so we are sure that pulses 8.5 us wide can
* go through cleanly . If you are on the wild side, you can try to lower
* this value (Actisys recommended me 2 us, and 0 us work for me on a P233!)
*/
#define MIN_DELAY 10 /* 10 us to be on the conservative side */
static int actisys_open(struct sir_dev *);
static int actisys_close(struct sir_dev *);
static int actisys_change_speed(struct sir_dev *, unsigned);
static int actisys_reset(struct sir_dev *);
/* These are the baudrates supported, in the order available */
/* Note : the 220L doesn't support 38400, but we will fix that below */
static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
#define MAX_SPEEDS (sizeof(baud_rates)/sizeof(baud_rates[0]))
static struct dongle_driver act220l = {
.owner = THIS_MODULE,
.driver_name = "Actisys ACT-220L",
.type = IRDA_ACTISYS_DONGLE,
.open = actisys_open,
.close = actisys_close,
.reset = actisys_reset,
.set_speed = actisys_change_speed,
};
static struct dongle_driver act220l_plus = {
.owner = THIS_MODULE,
.driver_name = "Actisys ACT-220L+",
.type = IRDA_ACTISYS_PLUS_DONGLE,
.open = actisys_open,
.close = actisys_close,
.reset = actisys_reset,
.set_speed = actisys_change_speed,
};
int __init actisys_sir_init(void)
{
int ret;
/* First, register an Actisys 220L dongle */
ret = irda_register_dongle(&act220l);
if (ret < 0)
return ret;
/* Now, register an Actisys 220L+ dongle */
ret = irda_register_dongle(&act220l_plus);
if (ret < 0) {
irda_unregister_dongle(&act220l);
return ret;
}
return 0;
}
void __exit actisys_sir_cleanup(void)
{
/* We have to remove both dongles */
irda_unregister_dongle(&act220l_plus);
irda_unregister_dongle(&act220l);
}
static int actisys_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
dev->set_dtr_rts(dev, TRUE, TRUE);
/* Set the speeds we can accept */
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
/* Remove support for 38400 if this is not a 220L+ dongle */
if (dev->dongle_drv->type == IRDA_ACTISYS_DONGLE)
qos->baud_rate.bits &= ~IR_38400;
qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
irda_qos_bits_to_value(qos);
return 0;
}
static int actisys_close(struct sir_dev *dev)
{
/* Power off the dongle */
dev->set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function actisys_change_speed (task)
*
* Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
* To cycle through the available baud rates, pulse RTS low for a few us.
*
* First, we reset the dongle to always start from a known state.
* Then, we cycle through the speeds by pulsing RTS low and then up.
* The dongle allow us to pulse quite fast, se we can set speed in one go,
* which is must faster ( < 100 us) and less complex than what is found
* in some other dongle drivers...
* Note that even if the new speed is the same as the current speed,
* we reassert the speed. This make sure that things are all right,
* and it's fast anyway...
* By the way, this function will work for both type of dongles,
* because the additional speed is at the end of the sequence...
*/
static int actisys_change_speed(struct sir_dev *dev, unsigned speed)
{
int ret = 0;
int i = 0;
IRDA_DEBUG(4, "%s(), speed=%d (was %d)\n", __FUNCTION__,
speed, dev->speed);
/* dongle was already resetted from irda_request state machine,
* we are in known state (dongle default)
*/
/*
* Now, we can set the speed requested. Send RTS pulses until we
* reach the target speed
*/
for (i=0; i<MAX_SPEEDS; i++) {
if (speed == baud_rates[i]) {
dev->speed = baud_rates[i];
break;
}
/* Set RTS low for 10 us */
dev->set_dtr_rts(dev, TRUE, FALSE);
udelay(MIN_DELAY);
/* Set RTS high for 10 us */
dev->set_dtr_rts(dev, TRUE, TRUE);
udelay(MIN_DELAY);
}
/* Check if life is sweet... */
if (i >= MAX_SPEEDS)
ret = -1; /* This should not happen */
/* Basta lavoro, on se casse d'ici... */
return ret;
}
/*
* Function actisys_reset (task)
*
* Reset the Actisys type dongle. Warning, this function must only be
* called with a process context!
*
* We need to do two things in this function :
* o first make sure that the dongle is in a state where it can operate
* o second put the dongle in a know state
*
* The dongle is powered of the RTS and DTR lines. In the dongle, there
* is a big capacitor to accomodate the current spikes. This capacitor
* takes a least 50 ms to be charged. In theory, the Bios set those lines
* up, so by the time we arrive here we should be set. It doesn't hurt
* to be on the conservative side, so we will wait...
* <Martin : move above comment to irda_config_fsm>
* Then, we set the speed to 9600 b/s to get in a known state (see in
* change_speed for details). It is needed because the IrDA stack
* has tried to set the speed immediately after our first return,
* so before we can be sure the dongle is up and running.
*/
static int actisys_reset(struct sir_dev *dev)
{
/* Reset the dongle : set DTR low for 10 us */
dev->set_dtr_rts(dev, FALSE, TRUE);
udelay(MIN_DELAY);
/* Go back to normal mode */
dev->set_dtr_rts(dev, TRUE, TRUE);
dev->speed = 9600; /* That's the default */
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no> - Jean Tourrilhes <jt@hpl.hp.com>");
MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");
MODULE_LICENSE("GPL");
module_init(actisys_sir_init);
module_exit(actisys_sir_cleanup);
......@@ -1825,26 +1825,26 @@ toshoboe_wakeup (struct pci_dev *pci_dev)
return 0;
}
static struct pci_driver toshoboe_pci_driver = {
name : "toshoboe",
id_table : toshoboe_pci_tbl,
probe : toshoboe_open,
remove : toshoboe_close,
suspend : toshoboe_gotosleep,
resume : toshoboe_wakeup
static struct pci_driver donauboe_pci_driver = {
.name = "donauboe",
.id_table = toshoboe_pci_tbl,
.probe = toshoboe_open,
.remove = toshoboe_close,
.suspend = toshoboe_gotosleep,
.resume = toshoboe_wakeup
};
int __init
toshoboe_init (void)
static int __init
donauboe_init (void)
{
return pci_module_init(&toshoboe_pci_driver);
return pci_module_init(&donauboe_pci_driver);
}
STATIC void __exit
toshoboe_cleanup (void)
static void __exit
donauboe_cleanup (void)
{
pci_unregister_driver(&toshoboe_pci_driver);
pci_unregister_driver(&donauboe_pci_driver);
}
module_init(toshoboe_init);
module_exit(toshoboe_cleanup);
module_init(donauboe_init);
module_exit(donauboe_cleanup);
/*********************************************************************
*
* Filename: esi.c
* Version: 1.6
* Description: Driver for the Extended Systems JetEye PC dongle
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Feb 21 18:54:38 1998
* Modified at: Sun Oct 27 22:01:04 2002
* Modified by: Martin Diehl <mad@mdiehl.de>
*
* Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
* Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
* Copyright (c) 2002 Martin Diehl, <mad@mdiehl.de>,
* All Rights Reserved.
*
* 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 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
static int esi_open(struct sir_dev *);
static int esi_close(struct sir_dev *);
static int esi_change_speed(struct sir_dev *, unsigned);
static int esi_reset(struct sir_dev *);
static struct dongle_driver esi = {
.owner = THIS_MODULE,
.driver_name = "JetEye PC ESI-9680 PC",
.type = IRDA_ESI_DONGLE,
.open = esi_open,
.close = esi_close,
.reset = esi_reset,
.set_speed = esi_change_speed,
};
static int __init esi_sir_init(void)
{
return irda_register_dongle(&esi);
}
static void __exit esi_sir_cleanup(void)
{
irda_unregister_dongle(&esi);
}
static int esi_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
irda_qos_bits_to_value(qos);
/* shouldn't we do set_dtr_rts(FALSE, TRUE) here (power up at 9600)? */
return 0;
}
static int esi_close(struct sir_dev *dev)
{
/* Power off dongle */
dev->set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function esi_change_speed (task)
*
* Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
*
*/
static int esi_change_speed(struct sir_dev *dev, unsigned speed)
{
int dtr, rts;
switch (speed) {
case 19200:
dtr = TRUE;
rts = FALSE;
break;
case 115200:
dtr = rts = TRUE;
break;
default:
speed = 9600;
/* fall through */
case 9600:
dtr = FALSE;
rts = TRUE;
break;
}
/* Change speed of dongle */
dev->set_dtr_rts(dev, dtr, rts);
dev->speed = speed;
/* do we need some delay for power stabilization? */
return 0;
}
/*
* Function esi_reset (task)
*
* Reset dongle;
*
*/
static int esi_reset(struct sir_dev *dev)
{
dev->set_dtr_rts(dev, FALSE, FALSE);
/* Hm, probably repower to 9600 and some delays? */
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
MODULE_LICENSE("GPL");
module_init(esi_sir_init);
module_exit(esi_sir_cleanup);
This diff is collapsed.
/*********************************************************************
*
* sir_tty.h: definitions for the irtty_sir client driver (former irtty)
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#ifndef IRTTYSIR_H
#define IRTTYSIR_H
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> // chipio_t
#define IRTTY_IOC_MAGIC 'e'
#define IRTTY_IOCTDONGLE _IO(IRTTY_IOC_MAGIC, 1)
#define IRTTY_IOCGET _IOR(IRTTY_IOC_MAGIC, 2, struct irtty_info)
#define IRTTY_IOC_MAXNR 2
struct sirtty_cb {
magic_t magic;
struct sir_dev *dev;
struct tty_struct *tty;
chipio_t io; /* IrDA controller information */
};
#endif
/*********************************************************************
*
* sir.h: include file for irda-sir device abstraction layer
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#ifndef IRDA_SIR_H
#define IRDA_SIR_H
#include <linux/netdevice.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> // iobuff_t
/* FIXME: unify irda_request with sir_fsm! */
struct irda_request {
struct list_head lh_request;
unsigned long pending;
void (*func)(void *);
void *data;
struct timer_list timer;
};
struct sir_fsm {
struct semaphore sem;
struct irda_request rq;
unsigned state, substate;
int param;
int result;
};
#define SIRDEV_STATE_WAIT_TX_COMPLETE 0x0100
/* substates for wait_tx_complete */
#define SIRDEV_STATE_WAIT_XMIT 0x0101
#define SIRDEV_STATE_WAIT_UNTIL_SENT 0x0102
#define SIRDEV_STATE_TX_DONE 0x0103
#define SIRDEV_STATE_DONGLE_OPEN 0x0300
/* 0x0301-0x03ff reserved for individual dongle substates */
#define SIRDEV_STATE_DONGLE_CLOSE 0x0400
/* 0x0401-0x04ff reserved for individual dongle substates */
#define SIRDEV_STATE_SET_DTR_RTS 0x0500
#define SIRDEV_STATE_SET_SPEED 0x0700
#define SIRDEV_STATE_DONGLE_CHECK 0x0800
#define SIRDEV_STATE_DONGLE_RESET 0x0900
/* 0x0901-0x09ff reserved for individual dongle substates */
#define SIRDEV_STATE_DONGLE_SPEED 0x0a00
/* 0x0a01-0x0aff reserved for individual dongle substates */
#define SIRDEV_STATE_PORT_SPEED 0x0b00
#define SIRDEV_STATE_DONE 0x0c00
#define SIRDEV_STATE_ERROR 0x0d00
#define SIRDEV_STATE_COMPLETE 0x0e00
#define SIRDEV_STATE_DEAD 0xffff
struct sir_dev;
struct dongle_driver {
struct module *owner;
const char *driver_name;
IRDA_DONGLE type;
int (*open)(struct sir_dev *dev);
int (*close)(struct sir_dev *dev);
int (*reset)(struct sir_dev *dev);
int (*set_speed)(struct sir_dev *dev, unsigned speed);
struct list_head dongle_list;
};
struct sir_driver {
struct module *owner;
const char *driver_name;
int qos_mtt_bits;
int (*chars_in_buffer)(struct sir_dev *dev);
void (*wait_until_sent)(struct sir_dev *dev);
int (*set_speed)(struct sir_dev *dev, unsigned speed);
int (*set_dtr_rts)(struct sir_dev *dev, int dtr, int rts);
int (*do_write)(struct sir_dev *dev, const unsigned char *ptr, size_t len);
int (*start_dev)(struct sir_dev *dev);
int (*stop_dev)(struct sir_dev *dev);
};
/* exported */
extern int irda_register_dongle(struct dongle_driver *new);
extern int irda_unregister_dongle(struct dongle_driver *drv);
extern struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name);
extern int sirdev_put_instance(struct sir_dev *self);
extern int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type);
extern void sirdev_write_complete(struct sir_dev *dev);
extern int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count);
/* not exported */
extern int sirdev_get_dongle(struct sir_dev *self, IRDA_DONGLE type);
extern int sirdev_put_dongle(struct sir_dev *self);
extern int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len);
extern int sirdev_raw_read(struct sir_dev *dev, char *buf, int len);
extern void sirdev_enable_rx(struct sir_dev *dev);
extern int sirdev_schedule_request(struct sir_dev *dev, int state, unsigned param);
extern int __init irda_thread_create(void);
extern void __exit irda_thread_join(void);
/* inline helpers */
static inline int sirdev_schedule_speed(struct sir_dev *dev, unsigned speed)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_SET_SPEED, speed);
}
static inline int sirdev_schedule_dongle_open(struct sir_dev *dev, int dongle_id)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_DONGLE_OPEN, dongle_id);
}
static inline int sirdev_schedule_dongle_close(struct sir_dev *dev)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_DONGLE_CLOSE, 0);
}
static inline int sirdev_schedule_dtr_rts(struct sir_dev *dev, int dtr, int rts)
{
int dtrrts;
dtrrts = ((dtr) ? 0x02 : 0x00) | ((rts) ? 0x01 : 0x00);
return sirdev_schedule_request(dev, SIRDEV_STATE_SET_DTR_RTS, dtrrts);
}
#if 0
static inline int sirdev_schedule_mode(struct sir_dev *dev, int mode)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_SET_MODE, mode);
}
#endif
struct sir_dev {
struct net_device *netdev;
struct net_device_stats stats;
struct irlap_cb *irlap;
struct qos_info qos;
char hwname[32];
struct sir_fsm fsm;
atomic_t enable_rx;
spinlock_t tx_lock;
u32 new_speed;
u32 flags;
unsigned speed;
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
struct sk_buff *tx_skb;
const struct dongle_driver * dongle_drv;
const struct sir_driver * drv;
void *priv;
/* dongle callbacks to the SIR device */
int (*read)(struct sir_dev *, char *buf, int len);
int (*write)(struct sir_dev *, const char *buf, int len);
int (*set_dtr_rts)(struct sir_dev *, int dtr, int rts);
};
#endif /* IRDA_SIR_H */
/*********************************************************************
*
* sir_core.c: module core for irda-sir abstraction layer
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
/***************************************************************************/
MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
MODULE_DESCRIPTION("IrDA SIR core");
MODULE_LICENSE("GPL");
/***************************************************************************/
EXPORT_SYMBOL(irda_register_dongle);
EXPORT_SYMBOL(irda_unregister_dongle);
EXPORT_SYMBOL(sirdev_get_instance);
EXPORT_SYMBOL(sirdev_put_instance);
EXPORT_SYMBOL(sirdev_set_dongle);
EXPORT_SYMBOL(sirdev_write_complete);
EXPORT_SYMBOL(sirdev_receive);
static int __init sir_core_init(void)
{
return irda_thread_create();
}
static void __exit sir_core_exit(void)
{
irda_thread_join();
}
module_init(sir_core_init);
module_exit(sir_core_exit);
This diff is collapsed.
/*********************************************************************
*
* sir_dongle.c: manager for serial dongle protocol drivers
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/kmod.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
/**************************************************************************
*
* dongle registration and attachment
*
*/
static LIST_HEAD(dongle_list); /* list of registered dongle drivers */
static DECLARE_MUTEX(dongle_list_lock); /* protects the list */
int irda_register_dongle(struct dongle_driver *new)
{
struct list_head *entry;
struct dongle_driver *drv;
IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n",
__FUNCTION__, new->driver_name, new->type);
down(&dongle_list_lock);
list_for_each(entry, &dongle_list) {
drv = list_entry(entry, struct dongle_driver, dongle_list);
if (new->type == drv->type) {
up(&dongle_list_lock);
return -EEXIST;
}
}
list_add(&new->dongle_list, &dongle_list);
up(&dongle_list_lock);
return 0;
}
int irda_unregister_dongle(struct dongle_driver *drv)
{
down(&dongle_list_lock);
list_del(&drv->dongle_list);
up(&dongle_list_lock);
return 0;
}
int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
{
struct list_head *entry;
const struct dongle_driver *drv = NULL;
int err = -EINVAL;
#ifdef CONFIG_KMOD
char modname[30];
sprintf(modname, "irda-dongle-%d", type);
request_module(modname);
#endif
if (dev->dongle_drv != NULL)
return -EBUSY;
/* serialize access to the list of registered dongles */
down(&dongle_list_lock);
list_for_each(entry, &dongle_list) {
drv = list_entry(entry, struct dongle_driver, dongle_list);
if (drv->type == type)
break;
else
drv = NULL;
}
if (!drv) {
err = -ENODEV;
goto out_unlock; /* no such dongle */
}
/* handling of SMP races with dongle module removal - three cases:
* 1) dongle driver was already unregistered - then we haven't found the
* requested dongle above and are already out here
* 2) the module is already marked deleted but the driver is still
* registered - then the try_inc_mod_count() below will fail
* 3) the try_inc_mod_count() below succeeds before the module is marked
* deleted - then sys_delete_module() fails and prevents the removal
* because the module is in use.
*/
if (drv->owner && !try_inc_mod_count(drv->owner)) {
err = -ESTALE;
goto out_unlock; /* rmmod already pending */
}
/* Initialize dongle driver callbacks */
dev->read = sirdev_raw_read;
dev->write = sirdev_raw_write;
dev->set_dtr_rts = dev->drv->set_dtr_rts;
dev->dongle_drv = drv;
if (!drv->open || (err=drv->open(dev))!=0)
goto out_reject; /* failed to open driver */
up(&dongle_list_lock);
return 0;
out_reject:
dev->dongle_drv = NULL;
if (drv->owner)
__MOD_DEC_USE_COUNT(drv->owner);
out_unlock:
up(&dongle_list_lock);
return err;
}
int sirdev_put_dongle(struct sir_dev *dev)
{
const struct dongle_driver *drv = dev->dongle_drv;
if (drv) {
if (drv->close)
drv->close(dev); /* close this dongle instance */
dev->dongle_drv = NULL; /* unlink the dongle driver */
if (drv->owner)
__MOD_DEC_USE_COUNT(drv->owner);/* decrement driver's module refcount */
}
return 0;
}
This diff is collapsed.
/*********************************************************************
*
* Filename: tekram.c
* Version: 1.3
* Description: Implementation of the Tekram IrMate IR-210B dongle
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Wed Oct 21 20:02:35 1998
* Modified at: Sun Oct 27 22:02:38 2002
* Modified by: Martin Diehl <mad@mdiehl.de>
*
* Copyright (c) 1998-1999 Dag Brattli,
* Copyright (c) 2002 Martin Diehl,
* All Rights Reserved.
*
* 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.
*
* Neither Dag Brattli nor University of Troms admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
MODULE_PARM(tekram_delay, "i");
MODULE_PARM_DESC(tekram_delay, "tekram dongle write complete delay");
static int tekram_delay = 50; /* default is 50 ms */
static int tekram_open(struct sir_dev *);
static int tekram_close(struct sir_dev *);
static int tekram_change_speed(struct sir_dev *, unsigned);
static int tekram_reset(struct sir_dev *);
#define TEKRAM_115200 0x00
#define TEKRAM_57600 0x01
#define TEKRAM_38400 0x02
#define TEKRAM_19200 0x03
#define TEKRAM_9600 0x04
#define TEKRAM_PW 0x10 /* Pulse select bit */
static struct dongle_driver tekram = {
.owner = THIS_MODULE,
.driver_name = "Tekram IR-210B",
.type = IRDA_TEKRAM_DONGLE,
.open = tekram_open,
.close = tekram_close,
.reset = tekram_reset,
.set_speed = tekram_change_speed,
};
int __init tekram_sir_init(void)
{
if (tekram_delay < 1 || tekram_delay>500)
tekram_delay = 200;
return irda_register_dongle(&tekram);
}
void __exit tekram_sir_cleanup(void)
{
irda_unregister_dongle(&tekram);
}
#define TEKRAM_STATE_POWERED (SIRDEV_STATE_DONGLE_OPEN + 1)
static int tekram_open(struct sir_dev *dev)
{
unsigned delay = 0;
unsigned next_state = dev->fsm.substate;
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
switch(dev->fsm.substate) {
case SIRDEV_STATE_DONGLE_OPEN:
dev->set_dtr_rts(dev, TRUE, TRUE);
next_state = TEKRAM_STATE_POWERED;
delay = 50;
break;
case TEKRAM_STATE_POWERED:
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
irda_qos_bits_to_value(qos);
return 0;
default:
ERROR("%s - undefined state\n", __FUNCTION__);
return -EINVAL;
}
dev->fsm.substate = next_state;
return delay;
}
static int tekram_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
dev->set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function tekram_change_speed (dev, state, speed)
*
* Set the speed for the Tekram IRMate 210 type dongle. Warning, this
* function must be called with a process context!
*
* Algorithm
* 1. clear DTR
* 2. set RTS, and wait at least 7 us
* 3. send Control Byte to the IR-210 through TXD to set new baud rate
* wait until the stop bit of Control Byte is sent (for 9600 baud rate,
* it takes about 100 msec)
*
* [oops, why 100 msec? sending 1 byte (10 bits) takes 1.05 msec
* - is this probably to compensate for delays in tty layer?]
*
* 5. clear RTS (return to NORMAL Operation)
* 6. wait at least 50 us, new setting (baud rate, etc) takes effect here
* after
*/
#define TEKRAM_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
static int tekram_change_speed(struct sir_dev *dev, unsigned speed)
{
unsigned delay = 0;
unsigned next_state = dev->fsm.substate;
u8 byte;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
switch(dev->fsm.substate) {
case SIRDEV_STATE_DONGLE_SPEED:
switch (speed) {
default:
speed = 9600;
/* fall thru */
case 9600:
byte = TEKRAM_PW|TEKRAM_9600;
break;
case 19200:
byte = TEKRAM_PW|TEKRAM_19200;
break;
case 38400:
byte = TEKRAM_PW|TEKRAM_38400;
break;
case 57600:
byte = TEKRAM_PW|TEKRAM_57600;
break;
case 115200:
byte = TEKRAM_115200;
break;
}
/* Set DTR, Clear RTS */
dev->set_dtr_rts(dev, TRUE, FALSE);
/* Wait at least 7us */
udelay(14);
/* Write control byte */
dev->write(dev, &byte, 1);
dev->speed = speed;
next_state = TEKRAM_STATE_WAIT_SPEED;
delay = tekram_delay; /* default: 50 ms */
break;
case TEKRAM_STATE_WAIT_SPEED:
/* Set DTR, Set RTS */
dev->set_dtr_rts(dev, TRUE, TRUE);
udelay(50);
return 0;
default:
ERROR("%s - undefined state\n", __FUNCTION__);
return -EINVAL;
}
dev->fsm.substate = next_state;
return delay;
}
/*
* Function tekram_reset (driver)
*
* This function resets the tekram dongle. Warning, this function
* must be called with a process context!!
*
* Algorithm:
* 0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 )
* 1. clear RTS
* 2. set DTR, and wait at least 1 ms
* 3. clear DTR to SPACE state, wait at least 50 us for further
* operation
*/
#define TEKRAM_STATE_WAIT_RESET (SIRDEV_STATE_DONGLE_RESET + 1)
static int tekram_reset(struct sir_dev *dev)
{
unsigned delay = 0;
unsigned next_state = dev->fsm.substate;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
switch(dev->fsm.substate) {
case SIRDEV_STATE_DONGLE_RESET:
/* Clear DTR, Set RTS */
dev->set_dtr_rts(dev, FALSE, TRUE);
next_state = TEKRAM_STATE_WAIT_RESET;
delay = 1; /* Should sleep 1 ms */
break;
case TEKRAM_STATE_WAIT_RESET:
/* Set DTR, Set RTS */
dev->set_dtr_rts(dev, TRUE, TRUE);
/* Wait at least 50 us */
udelay(75);
return 0;
default:
ERROR("%s - undefined state\n", __FUNCTION__);
return -EINVAL;
}
dev->fsm.substate = next_state;
return delay;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
MODULE_LICENSE("GPL");
module_init(tekram_sir_init);
module_exit(tekram_sir_cleanup);
......@@ -1280,6 +1280,20 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
return -1;
}
/* We are no longer an "old" protocol, so we need to handle
* share and non linear skbs. This should never happen, so
* we don't need to be clever about it. Jean II */
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
ERROR("%s: can't clone shared skb!\n", __FUNCTION__);
return -1;
}
if (skb_is_nonlinear(skb))
if (skb_linearize(skb, GFP_ATOMIC) != 0) {
ERROR("%s: can't linearize skb!\n", __FUNCTION__);
dev_kfree_skb(skb);
return -1;
}
/* Check if frame is large enough for parsing */
if (skb->len < 2) {
ERROR("%s: frame to short!\n", __FUNCTION__);
......
......@@ -180,13 +180,16 @@ EXPORT_SYMBOL(irtty_set_packet_mode);
__u32 irda_debug = IRDA_DEBUG_LEVEL;
#endif
/* Packet type handler.
* Tell the kernel how IrDA packets should be handled.
*/
static struct packet_type irda_packet_type =
{
0, /* MUTTER ntohs(ETH_P_IRDA),*/
NULL,
irlap_driver_rcv,
NULL,
NULL,
.type = __constant_htons(ETH_P_IRDA),
.dev = NULL, /* Wildcard : All devices */
.func = irlap_driver_rcv, /* Packet type handler irlap_frame.c */
.data = (void*) 1, /* Understand shared skbs */
//.next = NULL,
};
/*
......@@ -267,7 +270,6 @@ int __init irda_init(void)
irsock_init();
/* Add IrDA packet type (Start receiving packets) */
irda_packet_type.type = htons(ETH_P_IRDA);
dev_add_pack(&irda_packet_type);
/* Notifier for Interface changes */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment