summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-06-15 00:05:22 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-06-15 00:05:22 -0700
commit39412effc99bdfd977fcd7c98b451b0e129d73b2 (patch)
treedb524e6436701d74aad3a755130028ce5a9cd15d
parent079f066ac1f3173136fc9d9e84624fb6e90723e8 (diff)
parent260f84a6ecb8b2a4b5ebf7cb3c5264bddfb30706 (diff)
Merge http://gkernel.bkbits.net/irda-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--drivers/net/irda/Config.help8
-rw-r--r--drivers/net/irda/Config.in4
-rw-r--r--drivers/net/irda/Makefile2
-rw-r--r--drivers/net/irda/act200l.c299
-rw-r--r--drivers/net/irda/irda-usb.c120
-rw-r--r--drivers/net/irda/ma600.c356
-rw-r--r--include/linux/irda.h2
-rw-r--r--include/net/irda/discovery.h2
-rw-r--r--net/irda/ircomm/ircomm_core.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c6
10 files changed, 732 insertions, 69 deletions
diff --git a/drivers/net/irda/Config.help b/drivers/net/irda/Config.help
index 3cd3fe9cc883..295357525c8c 100644
--- a/drivers/net/irda/Config.help
+++ b/drivers/net/irda/Config.help
@@ -157,3 +157,11 @@ CONFIG_OLD_BELKIN_DONGLE
called old_belkin.o. Some information is contained in the comments
at the top of <file:drivers/net/irda/old_belkin.c>.
+ACTiSYS IR-200L dongle (Experimental)
+CONFIG_ACT200L_DONGLE
+ 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
+ Documentation/modules.txt. The ACTiSYS IR-200L dongle attaches to
+ the normal 9-pin serial port connector, and can currently only be
+ used by IrTTY. To activate support for ACTiSYS IR-200L dongles
+ you will have to start irattach like this: "irattach -d act200l".
diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in
index 4b9add183508..36d973f32956 100644
--- a/drivers/net/irda/Config.in
+++ b/drivers/net/irda/Config.in
@@ -18,6 +18,10 @@ if [ "$CONFIG_DONGLE" != "n" ]; then
if [ "$CONFIG_ARCH_EP7211" = "y" ]; then
dep_tristate ' EP7211 I/R support' CONFIG_EP7211_IR $CONFIG_IRDA
fi
+ if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+ dep_tristate ' ACTiSYS IR-200L dongle (Experimental)' CONFIG_ACT200L_DONGLE $CONFIG_IRDA
+ dep_tristate ' Mobile Action MA600 dongle (Experimental)' CONFIG_MA600_DONGLE $CONFIG_IRDA
+ fi
fi
comment 'FIR device drivers'
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index efc5a48272e9..7f005a2fe9a3 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -25,5 +25,7 @@ obj-$(CONFIG_LITELINK_DONGLE) += litelink.o
obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin.o
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
include $(TOPDIR)/Rules.make
diff --git a/drivers/net/irda/act200l.c b/drivers/net/irda/act200l.c
new file mode 100644
index 000000000000..0a6282912197
--- /dev/null
+++ b/drivers/net/irda/act200l.c
@@ -0,0 +1,299 @@
+/*********************************************************************
+ *
+ * Filename: act200l.c
+ * Version: 0.8
+ * Description: Implementation for the ACTiSYS ACT-IR200L dongle
+ * Status: Experimental.
+ * Author: SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>
+ * Created at: Fri Aug 3 17:35:42 2001
+ * Modified at: Fri Aug 17 10:22:40 2001
+ * Modified by: SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>
+ *
+ * Copyright (c) 2001 SHIMIZU Takuya, 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.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irtty.h>
+
+static int act200l_reset(struct irda_task *task);
+static void act200l_open(dongle_t *self, struct qos_info *qos);
+static void act200l_close(dongle_t *self);
+static int act200l_change_speed(struct irda_task *task);
+
+/* Regsiter 0: Control register #1 */
+#define ACT200L_REG0 0x00
+#define ACT200L_TXEN 0x01 /* Enable transmitter */
+#define ACT200L_RXEN 0x02 /* Enable receiver */
+
+/* Register 1: Control register #2 */
+#define ACT200L_REG1 0x10
+#define ACT200L_LODB 0x01 /* Load new baud rate count value */
+#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */
+
+/* Register 4: Output Power register */
+#define ACT200L_REG4 0x40
+#define ACT200L_OP0 0x01 /* Enable LED1C output */
+#define ACT200L_OP1 0x02 /* Enable LED2C output */
+#define ACT200L_BLKR 0x04
+
+/* Register 5: Receive Mode register */
+#define ACT200L_REG5 0x50
+#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */
+
+/* Register 6: Receive Sensitivity register #1 */
+#define ACT200L_REG6 0x60
+#define ACT200L_RS0 0x01 /* receive threshold bit 0 */
+#define ACT200L_RS1 0x02 /* receive threshold bit 1 */
+
+/* Register 7: Receive Sensitivity register #2 */
+#define ACT200L_REG7 0x70
+#define ACT200L_ENPOS 0x04 /* Ignore the falling edge */
+
+/* Register 8,9: Baud Rate Dvider register #1,#2 */
+#define ACT200L_REG8 0x80
+#define ACT200L_REG9 0x90
+
+#define ACT200L_2400 0x5f
+#define ACT200L_9600 0x17
+#define ACT200L_19200 0x0b
+#define ACT200L_38400 0x05
+#define ACT200L_57600 0x03
+#define ACT200L_115200 0x01
+
+/* Register 13: Control register #3 */
+#define ACT200L_REG13 0xd0
+#define ACT200L_SHDW 0x01 /* Enable access to shadow registers */
+
+/* Register 15: Status register */
+#define ACT200L_REG15 0xf0
+
+/* Register 21: Control register #4 */
+#define ACT200L_REG21 0x50
+#define ACT200L_EXCK 0x02 /* Disable clock output driver */
+#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */
+
+static struct dongle_reg dongle = {
+ Q_NULL,
+ IRDA_ACT200L_DONGLE,
+ act200l_open,
+ act200l_close,
+ act200l_reset,
+ act200l_change_speed,
+};
+
+int __init act200l_init(void)
+{
+ return irda_device_register_dongle(&dongle);
+}
+
+void __exit act200l_cleanup(void)
+{
+ irda_device_unregister_dongle(&dongle);
+}
+
+static void act200l_open(dongle_t *self, struct qos_info *qos)
+{
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ /* Power on the dongle */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+ /* Set the speeds we can accept */
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits = 0x03;
+
+ MOD_INC_USE_COUNT;
+}
+
+static void act200l_close(dongle_t *self)
+{
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ /* Power off the dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function act200l_change_speed (dev, speed)
+ *
+ * Set the speed for the ACTiSYS ACT-IR200L type dongle.
+ *
+ */
+static int act200l_change_speed(struct irda_task *task)
+{
+ dongle_t *self = (dongle_t *) task->instance;
+ __u32 speed = (__u32) task->param;
+ __u8 control[3];
+ int ret = 0;
+
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ self->speed_task = task;
+
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ if (irda_task_execute(self, act200l_reset, NULL, task,
+ (void *) speed))
+ {
+ /* Dongle need more time to reset */
+ irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+ /* Give reset 1 sec to finish */
+ ret = MSECS_TO_JIFFIES(1000);
+ }
+ break;
+ case IRDA_TASK_CHILD_WAIT:
+ WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+ ret = -1;
+ break;
+ case IRDA_TASK_CHILD_DONE:
+ /* Clear DTR and set RTS to enter command mode */
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
+
+ switch (speed) {
+ case 9600:
+ default:
+ control[0] = ACT200L_REG8 | (ACT200L_9600 & 0x0f);
+ control[1] = ACT200L_REG9 | ((ACT200L_9600 >> 4) & 0x0f);
+ break;
+ case 19200:
+ control[0] = ACT200L_REG8 | (ACT200L_19200 & 0x0f);
+ control[1] = ACT200L_REG9 | ((ACT200L_19200 >> 4) & 0x0f);
+ break;
+ case 38400:
+ control[0] = ACT200L_REG8 | (ACT200L_38400 & 0x0f);
+ control[1] = ACT200L_REG9 | ((ACT200L_38400 >> 4) & 0x0f);
+ break;
+ case 57600:
+ control[0] = ACT200L_REG8 | (ACT200L_57600 & 0x0f);
+ control[1] = ACT200L_REG9 | ((ACT200L_57600 >> 4) & 0x0f);
+ break;
+ case 115200:
+ control[0] = ACT200L_REG8 | (ACT200L_115200 & 0x0f);
+ control[1] = ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f);
+ break;
+ }
+ control[2] = ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE;
+
+ /* Write control bytes */
+ self->write(self->dev, control, 3);
+ irda_task_next_state(task, IRDA_TASK_WAIT);
+ ret = MSECS_TO_JIFFIES(5);
+ break;
+ case IRDA_TASK_WAIT:
+ /* Go back to normal mode */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->speed_task = NULL;
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->speed_task = NULL;
+ ret = -1;
+ break;
+ }
+ return ret;
+}
+
+/*
+ * Function act200l_reset (driver)
+ *
+ * Reset the ACTiSYS ACT-IR200L type dongle.
+ */
+static int act200l_reset(struct irda_task *task)
+{
+ dongle_t *self = (dongle_t *) task->instance;
+ __u8 control[9] = {
+ ACT200L_REG15,
+ ACT200L_REG13 | ACT200L_SHDW,
+ ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL,
+ ACT200L_REG13,
+ ACT200L_REG7 | ACT200L_ENPOS,
+ ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1,
+ ACT200L_REG5 | ACT200L_RWIDL,
+ ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR,
+ ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN
+ };
+ int ret = 0;
+
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ self->reset_task = task;
+
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ /* Power on the dongle */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+ irda_task_next_state(task, IRDA_TASK_WAIT1);
+ ret = MSECS_TO_JIFFIES(50);
+ break;
+ case IRDA_TASK_WAIT1:
+ /* Reset the dongle : set RTS low for 25 ms */
+ self->set_dtr_rts(self->dev, TRUE, FALSE);
+
+ irda_task_next_state(task, IRDA_TASK_WAIT2);
+ ret = MSECS_TO_JIFFIES(50);
+ break;
+ case IRDA_TASK_WAIT2:
+ /* Clear DTR and set RTS to enter command mode */
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
+
+ /* Write control bytes */
+ self->write(self->dev, control, 9);
+ irda_task_next_state(task, IRDA_TASK_WAIT3);
+ ret = MSECS_TO_JIFFIES(15);
+ break;
+ case IRDA_TASK_WAIT3:
+ /* Go back to normal mode */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->reset_task = NULL;
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->reset_task = NULL;
+ ret = -1;
+ break;
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>");
+MODULE_DESCRIPTION("ACTiSYS ACT-IR200L dongle driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize ACTiSYS ACT-IR200L module
+ *
+ */
+module_init(act200l_init);
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Cleanup ACTiSYS ACT-IR200L module
+ *
+ */
+module_exit(act200l_cleanup);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index b3a91975bdb4..019fb6f816fb 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -30,23 +30,24 @@
* IMPORTANT NOTE
* --------------
*
- * As of kernel 2.4.10, this is the state of compliance and testing of
+ * As of kernel 2.5.20, this is the state of compliance and testing of
* this driver (irda-usb) with regards to the USB low level drivers...
*
* This driver has been tested SUCCESSFULLY with the following drivers :
- * o usb-uhci (For Intel/Via USB controllers)
- * o usb-ohci (For other USB controllers)
+ * o usb-uhci-hcd (For Intel/Via USB controllers)
+ * o uhci-hcd (Alternate/JE driver for Intel/Via USB controllers)
*
* This driver has NOT been tested with the following drivers :
- * o usb-ehci (USB 2.0 controllers)
+ * o ehci-hcd (USB 2.0 controllers)
*
- * This driver WON'T WORK with the following drivers :
- * o uhci (Alternate/JE driver for Intel/Via USB controllers)
- * Amongst the reasons :
- * o uhci doesn't implement USB_ZERO_PACKET
- * o uhci non-compliant use of urb->timeout
- * The final fix for USB_ZERO_PACKET in uhci is likely to be in 2.4.19 and
- * 2.5.8. With this fix, the driver will work properly. More on that later.
+ * This driver DOESN'T SEEM TO WORK with the following drivers :
+ * o ohci-hcd (For other USB controllers)
+ * The first outgoing URB never calls its completion/failure callback.
+ *
+ * Note that all HCD drivers do USB_ZERO_PACKET and timeout properly,
+ * so we don't have to worry about that anymore.
+ * One common problem is the failure to set the address on the dongle,
+ * but this happens before the driver gets loaded...
*
* Jean II
*/
@@ -167,7 +168,8 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed);
self->speed = self->new_speed;
- self->new_speed = -1;
+ /* We will do ` self->new_speed = -1; ' in the completion
+ * handler just in case the current URB fail - Jean II */
switch (self->speed) {
case 2400:
@@ -208,7 +210,8 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
if (self->new_xbofs != -1) {
IRDA_DEBUG(2, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs);
self->xbofs = self->new_xbofs;
- self->new_xbofs = -1;
+ /* We will do ` self->new_xbofs = -1; ' in the completion
+ * handler just in case the current URB fail - Jean II */
switch (self->xbofs) {
case 48:
@@ -286,7 +289,8 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
/*------------------------------------------------------------------*/
/*
- * Note : this function will be called with both speed_urb and empty_urb...
+ * Speed URB callback
+ * Now, we can only get called for the speed URB.
*/
static void speed_bulk_callback(struct urb *urb)
{
@@ -295,10 +299,9 @@ static void speed_bulk_callback(struct urb *urb)
IRDA_DEBUG(2, __FUNCTION__ "()\n");
/* We should always have a context */
- if (self == NULL) {
- WARNING(__FUNCTION__ "(), Bug : self == NULL\n");
- return;
- }
+ ASSERT(self != NULL, return;);
+ /* We should always be called for the speed URB */
+ ASSERT(urb == self->speed_urb, return;);
/* Check for timeout and other USB nasties */
if (urb->status != 0) {
@@ -314,12 +317,14 @@ static void speed_bulk_callback(struct urb *urb)
}
/* urb is now available */
- urb->status = 0;
+ //urb->status = 0; -> tested above
- /* If it was the speed URB, allow the stack to send more packets */
- if(urb == self->speed_urb) {
- netif_wake_queue(self->netdev);
- }
+ /* New speed and xbof is now commited in hardware */
+ self->new_speed = -1;
+ self->new_xbofs = -1;
+
+ /* Allow the stack to send more packets */
+ netif_wake_queue(self->netdev);
}
/*------------------------------------------------------------------*/
@@ -334,6 +339,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
s32 speed;
s16 xbofs;
int res, mtt;
+ int err = 1; /* Failed */
+
+ IRDA_DEBUG(4, __FUNCTION__ "() on %s\n", netdev->name);
netif_stop_queue(netdev);
@@ -343,10 +351,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Check if the device is still there.
* We need to check self->present under the spinlock because
* of irda_usb_disconnect() is synchronous - Jean II */
- if ((!self) || (!self->present)) {
+ if (!self->present) {
IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n");
- spin_unlock_irqrestore(&self->lock, flags);
- return 1; /* Failed */
+ goto drop;
}
/* Check if we need to change the number of xbofs */
@@ -373,6 +380,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
irda_usb_change_speed_xbofs(self);
netdev->trans_start = jiffies;
/* Will netif_wake_queue() in callback */
+ err = 0; /* No error */
goto drop;
}
}
@@ -479,7 +487,7 @@ drop:
/* Drop silently the skb and exit */
dev_kfree_skb(skb);
spin_unlock_irqrestore(&self->lock, flags);
- return 0;
+ return err; /* Usually 1 */
}
/*------------------------------------------------------------------*/
@@ -495,10 +503,9 @@ static void write_bulk_callback(struct urb *urb)
IRDA_DEBUG(2, __FUNCTION__ "()\n");
/* We should always have a context */
- if (self == NULL) {
- WARNING(__FUNCTION__ "(), Bug : self == NULL\n");
- return;
- }
+ ASSERT(self != NULL, return;);
+ /* We should always be called for the speed URB */
+ ASSERT(urb == self->tx_urb, return;);
/* Free up the skb */
dev_kfree_skb_any(skb);
@@ -531,10 +538,21 @@ static void write_bulk_callback(struct urb *urb)
return;
}
- /* If we need to change the speed or xbofs, do it now */
+ /* If changes to speed or xbofs is pending... */
if ((self->new_speed != -1) || (self->new_xbofs != -1)) {
- IRDA_DEBUG(1, __FUNCTION__ "(), Changing speed now...\n");
- irda_usb_change_speed_xbofs(self);
+ if ((self->new_speed != self->speed) ||
+ (self->new_xbofs != self->xbofs)) {
+ /* We haven't changed speed yet (because of
+ * IUC_SPEED_BUG), so do it now - Jean II */
+ IRDA_DEBUG(1, __FUNCTION__ "(), Changing speed now...\n");
+ irda_usb_change_speed_xbofs(self);
+ } else {
+ /* New speed and xbof is now commited in hardware */
+ self->new_speed = -1;
+ self->new_xbofs = -1;
+ /* Done, waiting for next packet */
+ netif_wake_queue(self->netdev);
+ }
} else {
/* Otherwise, allow the stack to send more packets */
netif_wake_queue(self->netdev);
@@ -559,11 +577,13 @@ static void irda_usb_net_timeout(struct net_device *netdev)
int done = 0; /* If we have made any progress */
IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n");
+ ASSERT(self != NULL, return;);
/* Protect us from USB callbacks, net Tx and else. */
spin_lock_irqsave(&self->lock, flags);
- if ((!self) || (!self->present)) {
+ /* self->present *MUST* be read under spinlock */
+ if (!self->present) {
WARNING(__FUNCTION__ "(), device not present!\n");
netif_stop_queue(netdev);
spin_unlock_irqrestore(&self->lock, flags);
@@ -678,35 +698,7 @@ static void irda_usb_net_timeout(struct net_device *netdev)
/*------------------------------------------------------------------*/
/*
* Submit a Rx URB to the USB layer to handle reception of a frame
- *
- * Important note :
- * The function process_urb() in usb-uhci.c contains the following code :
- * > urb->complete ((struct urb *) urb);
- * > // Re-submit the URB if ring-linked
- * > if (is_ring && (urb->status != -ENOENT) && !contains_killed) {
- * > urb->dev=usb_dev;
- * > uhci_submit_urb (urb);
- * > }
- * The way I see it is that if we submit more than one Rx URB at a
- * time, the Rx URB can be automatically re-submitted after the
- * completion handler is called.
- *
- * My take is that it's a questionable feature, and quite difficult
- * to control and to make work effectively.
- * The outcome (re-submited or not) depend on various complex
- * test ('is_ring' and 'contains_killed'), and the completion handler
- * don't have this information, so basically the driver has no way
- * to know if URB are resubmitted or not. Yuck !
- * If everything is perfect, it's cool, but the problem is when
- * an URB is killed (timeout, call to unlink_urb(), ...), things get
- * messy...
- * The other problem is that this scheme deal only with the URB
- * and ignore everything about the associated buffer. So, it would
- * resubmit URB even if the buffer is still in use or non-existent.
- * On the other hand, submitting ourself in the completion callback
- * is quite trivial and work well (this function).
- * Moreover, this scheme doesn't allow to have an idle URB, which is
- * necessary to overcome some URB failures.
+ * Mostly called by the completion callback of the previous URB.
*
* Jean II
*/
diff --git a/drivers/net/irda/ma600.c b/drivers/net/irda/ma600.c
new file mode 100644
index 000000000000..a2e1e8eb8fd4
--- /dev/null
+++ b/drivers/net/irda/ma600.c
@@ -0,0 +1,356 @@
+/*********************************************************************
+ *
+ * Filename: ma600.c
+ * Version: 0.1
+ * Description: Implementation of the MA600 dongle
+ * Status: Experimental.
+ * Author: Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95
+ * Created at: Sat Jun 10 20:02:35 2000
+ * Modified at:
+ * Modified by:
+ *
+ * Note: very thanks to Mr. Maru Wang <maru@mobileaction.com.tw> for providing
+ * information on the MA600 dongle
+ *
+ * Copyright (c) 2000 Leung, 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
+ *
+ ********************************************************************/
+
+/* define this macro for release version */
+//#define NDEBUG
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irtty.h>
+
+#ifndef NDEBUG
+ #undef IRDA_DEBUG
+ #define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args))
+
+ #undef ASSERT(expr, func)
+ #define ASSERT(expr, func) \
+ if(!(expr)) { \
+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+ #expr,__FILE__,__FUNCTION__,__LINE__); \
+ ##func}
+#endif
+
+/* convert hex value to ascii hex */
+static const char hexTbl[] = "0123456789ABCDEF";
+
+
+static void ma600_open(dongle_t *self, struct qos_info *qos);
+static void ma600_close(dongle_t *self);
+static int ma600_change_speed(struct irda_task *task);
+static int ma600_reset(struct irda_task *task);
+
+/* control byte for MA600 */
+#define MA600_9600 0x00
+#define MA600_19200 0x01
+#define MA600_38400 0x02
+#define MA600_57600 0x03
+#define MA600_115200 0x04
+#define MA600_DEV_ID1 0x05
+#define MA600_DEV_ID2 0x06
+#define MA600_2400 0x08
+
+static struct dongle_reg dongle = {
+ Q_NULL,
+ IRDA_MA600_DONGLE,
+ ma600_open,
+ ma600_close,
+ ma600_reset,
+ ma600_change_speed,
+};
+
+int __init ma600_init(void)
+{
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+ return irda_device_register_dongle(&dongle);
+}
+
+void __exit ma600_cleanup(void)
+{
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+ irda_device_unregister_dongle(&dongle);
+}
+
+/*
+ Power on:
+ (0) Clear RTS and DTR for 1 second
+ (1) Set RTS and DTR for 1 second
+ (2) 9600 bps now
+ Note: assume RTS, DTR are clear before
+*/
+static void ma600_open(dongle_t *self, struct qos_info *qos)
+{
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
+ |IR_57600|IR_115200;
+ qos->min_turn_time.bits = 0x01; /* Needs at least 1 ms */
+ irda_qos_bits_to_value(qos);
+
+ //self->set_dtr_rts(self->dev, FALSE, FALSE);
+ // should wait 1 second
+
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+ // should wait 1 second
+
+ MOD_INC_USE_COUNT;
+}
+
+static void ma600_close(dongle_t *self)
+{
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ /* Power off dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+
+ MOD_DEC_USE_COUNT;
+}
+
+static __u8 get_control_byte(__u32 speed)
+{
+ __u8 byte;
+
+ switch (speed) {
+ default:
+ case 115200:
+ byte = MA600_115200;
+ break;
+ case 57600:
+ byte = MA600_57600;
+ break;
+ case 38400:
+ byte = MA600_38400;
+ break;
+ case 19200:
+ byte = MA600_19200;
+ break;
+ case 9600:
+ byte = MA600_9600;
+ break;
+ case 2400:
+ byte = MA600_2400;
+ break;
+ }
+
+ return byte;
+}
+
+/*
+ * Function ma600_change_speed (dev, state, speed)
+ *
+ * Set the speed for the MA600 type dongle. Warning, this
+ * function must be called with a process context!
+ *
+ * Algorithm
+ * 1. Reset
+ * 2. clear RTS, set DTR and wait for 1ms
+ * 3. send Control Byte to the MA600 through TXD to set new baud rate
+ * wait until the stop bit of Control Byte is sent (for 9600 baud rate,
+ * it takes about 10 msec)
+ * 4. set RTS, set DTR (return to NORMAL Operation)
+ * 5. wait at least 10 ms, new setting (baud rate, etc) takes effect here
+ * after
+ */
+static int ma600_change_speed(struct irda_task *task)
+{
+ dongle_t *self = (dongle_t *) task->instance;
+ __u32 speed = (__u32) task->param;
+ static __u8 byte;
+ __u8 byte_echo;
+ int ret = 0;
+
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ ASSERT(task != NULL, return -1;);
+
+ if (self->speed_task && self->speed_task != task) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+ return MSECS_TO_JIFFIES(10);
+ } else {
+ self->speed_task = task;
+ }
+
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ case IRDA_TASK_CHILD_INIT:
+ /*
+ * Need to reset the dongle and go to 9600 bps before
+ * programming
+ */
+ if (irda_task_execute(self, ma600_reset, NULL, task,
+ (void *) speed)) {
+ /* Dongle need more time to reset */
+ irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+ /* give 1 second to finish */
+ ret = MSECS_TO_JIFFIES(1000);
+ } else {
+ irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+ }
+ break;
+
+ case IRDA_TASK_CHILD_WAIT:
+ WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+ ret = -1;
+ break;
+
+ case IRDA_TASK_CHILD_DONE:
+ /* Set DTR, Clear RTS */
+ self->set_dtr_rts(self->dev, TRUE, FALSE);
+
+ ret = MSECS_TO_JIFFIES(1); /* Sleep 1 ms */
+ irda_task_next_state(task, IRDA_TASK_WAIT);
+ break;
+
+ case IRDA_TASK_WAIT:
+ speed = (__u32) task->param;
+ byte = get_control_byte(speed);
+
+ /* Write control byte */
+ self->write(self->dev, &byte, sizeof(byte));
+
+ irda_task_next_state(task, IRDA_TASK_WAIT1);
+
+ /* Wait at least 10 ms */
+ ret = MSECS_TO_JIFFIES(15);
+ break;
+
+ case IRDA_TASK_WAIT1:
+ /* Read control byte echo */
+ self->read(self->dev, &byte_echo, sizeof(byte_echo));
+
+ if(byte != byte_echo) {
+ /* if control byte != echo, I don't know what to do */
+ printk(KERN_WARNING __FUNCTION__ "() control byte written != read!\n");
+ printk(KERN_WARNING "control byte = 0x%c%c\n",
+ hexTbl[(byte>>4)&0x0f], hexTbl[byte&0x0f]);
+ printk(KERN_WARNING "byte echo = 0x%c%c\n",
+ hexTbl[(byte_echo>>4) & 0x0f],
+ hexTbl[byte_echo & 0x0f]);
+ #ifndef NDEBUG
+ } else {
+ IRDA_DEBUG(2, __FUNCTION__ "() control byte write read OK\n");
+ #endif
+ }
+
+ /* Set DTR, Set RTS */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+ irda_task_next_state(task, IRDA_TASK_WAIT2);
+
+ /* Wait at least 10 ms */
+ ret = MSECS_TO_JIFFIES(10);
+ break;
+
+ case IRDA_TASK_WAIT2:
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->speed_task = NULL;
+ break;
+
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->speed_task = NULL;
+ ret = -1;
+ break;
+ }
+ return ret;
+}
+
+/*
+ * Function ma600_reset (driver)
+ *
+ * This function resets the ma600 dongle. Warning, this function
+ * must be called with a process context!!
+ *
+ * Algorithm:
+ * 0. DTR=0, RTS=1 and wait 10 ms
+ * 1. DTR=1, RTS=1 and wait 10 ms
+ * 2. 9600 bps now
+ */
+int ma600_reset(struct irda_task *task)
+{
+ dongle_t *self = (dongle_t *) task->instance;
+ int ret = 0;
+
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ ASSERT(task != NULL, return -1;);
+
+ if (self->reset_task && self->reset_task != task) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+ return MSECS_TO_JIFFIES(10);
+ } else
+ self->reset_task = task;
+
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ /* Clear DTR and Set RTS */
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
+ irda_task_next_state(task, IRDA_TASK_WAIT1);
+ ret = MSECS_TO_JIFFIES(10); /* Sleep 10 ms */
+ break;
+ case IRDA_TASK_WAIT1:
+ /* Set DTR and RTS */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+ irda_task_next_state(task, IRDA_TASK_WAIT2);
+ ret = MSECS_TO_JIFFIES(10); /* Sleep 10 ms */
+ break;
+ case IRDA_TASK_WAIT2:
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->reset_task = NULL;
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->reset_task = NULL;
+ ret = -1;
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95");
+MODULE_DESCRIPTION("MA600 dongle driver version 0.1");
+MODULE_LICENSE("GPL");
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize MA600 module
+ *
+ */
+module_init(ma600_init);
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Cleanup MA600 module
+ *
+ */
+module_exit(ma600_cleanup);
+
diff --git a/include/linux/irda.h b/include/linux/irda.h
index 65fa89989607..bdf23baa5483 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -68,6 +68,8 @@ typedef enum {
IRDA_OLD_BELKIN_DONGLE = 7,
IRDA_EP7211_IR = 8,
IRDA_MCP2120_DONGLE = 9,
+ IRDA_ACT200L_DONGLE = 10,
+ IRDA_MA600_DONGLE = 11,
} IRDA_DONGLE;
/* Protocol types to be used for SOCK_DGRAM */
diff --git a/include/net/irda/discovery.h b/include/net/irda/discovery.h
index 8e22eeab5332..b69dd381ae1e 100644
--- a/include/net/irda/discovery.h
+++ b/include/net/irda/discovery.h
@@ -36,7 +36,7 @@
#include <net/irda/irda.h>
#include <net/irda/irqueue.h>
-#define DISCOVERY_EXPIRE_TIMEOUT 6*HZ
+#define DISCOVERY_EXPIRE_TIMEOUT (2*sysctl_discovery_timeout*HZ)
#define DISCOVERY_DEFAULT_SLOTS 0
/* Types of discovery */
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 4bdbe90fb944..b82142848f1c 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -514,7 +514,7 @@ int ircomm_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct ircomm_cb *) hashbin_get_first(ircomm);
while (self != NULL) {
- ASSERT(self->magic == IRCOMM_MAGIC, return len;);
+ ASSERT(self->magic == IRCOMM_MAGIC, break;);
if(self->line < 0x10)
len += sprintf(buf+len, "ircomm%d", self->line);
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index bbe977d619bd..5e1e75f0262a 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -525,6 +525,9 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
if (!tty)
return;
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
save_flags(flags);
cli();
@@ -536,9 +539,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
return;
}
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
-
if ((tty->count == 1) && (self->open_count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty