• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*********************************************************************
2  *
3  * Filename:      tekram.c
4  * Version:       1.3
5  * Description:   Implementation of the Tekram IrMate IR-210B dongle
6  * Status:        Experimental.
7  * Author:        Dag Brattli <dagb@cs.uit.no>
8  * Created at:    Wed Oct 21 20:02:35 1998
9  * Modified at:   Sun Oct 27 22:02:38 2002
10  * Modified by:   Martin Diehl <mad@mdiehl.de>
11  *
12  *     Copyright (c) 1998-1999 Dag Brattli,
13  *     Copyright (c) 2002 Martin Diehl,
14  *     All Rights Reserved.
15  *
16  *     This program is free software; you can redistribute it and/or
17  *     modify it under the terms of the GNU General Public License as
18  *     published by the Free Software Foundation; either version 2 of
19  *     the License, or (at your option) any later version.
20  *
21  *     Neither Dag Brattli nor University of Tromsø admit liability nor
22  *     provide warranty for any of this software. This material is
23  *     provided "AS-IS" and at no charge.
24  *
25  ********************************************************************/
26 
27 #include <linux/module.h>
28 #include <linux/delay.h>
29 #include <linux/init.h>
30 
31 #include <net/irda/irda.h>
32 
33 #include "sir-dev.h"
34 
35 static int tekram_delay = 150;		/* default is 150 ms */
36 module_param(tekram_delay, int, 0);
37 MODULE_PARM_DESC(tekram_delay, "tekram dongle write complete delay");
38 
39 static int tekram_open(struct sir_dev *);
40 static int tekram_close(struct sir_dev *);
41 static int tekram_change_speed(struct sir_dev *, unsigned);
42 static int tekram_reset(struct sir_dev *);
43 
44 #define TEKRAM_115200 0x00
45 #define TEKRAM_57600  0x01
46 #define TEKRAM_38400  0x02
47 #define TEKRAM_19200  0x03
48 #define TEKRAM_9600   0x04
49 
50 #define TEKRAM_PW     0x10 /* Pulse select bit */
51 
52 static struct dongle_driver tekram = {
53 	.owner		= THIS_MODULE,
54 	.driver_name	= "Tekram IR-210B",
55 	.type		= IRDA_TEKRAM_DONGLE,
56 	.open		= tekram_open,
57 	.close		= tekram_close,
58 	.reset		= tekram_reset,
59 	.set_speed	= tekram_change_speed,
60 };
61 
tekram_sir_init(void)62 static int __init tekram_sir_init(void)
63 {
64 	if (tekram_delay < 1  ||  tekram_delay > 500)
65 		tekram_delay = 200;
66 	pr_debug("%s - using %d ms delay\n",
67 		 tekram.driver_name, tekram_delay);
68 	return irda_register_dongle(&tekram);
69 }
70 
tekram_sir_cleanup(void)71 static void __exit tekram_sir_cleanup(void)
72 {
73 	irda_unregister_dongle(&tekram);
74 }
75 
tekram_open(struct sir_dev * dev)76 static int tekram_open(struct sir_dev *dev)
77 {
78 	struct qos_info *qos = &dev->qos;
79 
80 	sirdev_set_dtr_rts(dev, TRUE, TRUE);
81 
82 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
83 	qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
84 	irda_qos_bits_to_value(qos);
85 
86 	/* irda thread waits 50 msec for power settling */
87 
88 	return 0;
89 }
90 
tekram_close(struct sir_dev * dev)91 static int tekram_close(struct sir_dev *dev)
92 {
93 	/* Power off dongle */
94 	sirdev_set_dtr_rts(dev, FALSE, FALSE);
95 
96 	return 0;
97 }
98 
99 /*
100  * Function tekram_change_speed (dev, state, speed)
101  *
102  *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this
103  *    function must be called with a process context!
104  *
105  *    Algorithm
106  *    1. clear DTR
107  *    2. set RTS, and wait at least 7 us
108  *    3. send Control Byte to the IR-210 through TXD to set new baud rate
109  *       wait until the stop bit of Control Byte is sent (for 9600 baud rate,
110  *       it takes about 100 msec)
111  *
112  *	[oops, why 100 msec? sending 1 byte (10 bits) takes 1.05 msec
113  *	 - is this probably to compensate for delays in tty layer?]
114  *
115  *    5. clear RTS (return to NORMAL Operation)
116  *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here
117  *       after
118  */
119 
120 #define TEKRAM_STATE_WAIT_SPEED	(SIRDEV_STATE_DONGLE_SPEED + 1)
121 
tekram_change_speed(struct sir_dev * dev,unsigned speed)122 static int tekram_change_speed(struct sir_dev *dev, unsigned speed)
123 {
124 	unsigned state = dev->fsm.substate;
125 	unsigned delay = 0;
126 	u8 byte;
127 	static int ret = 0;
128 
129 	switch(state) {
130 	case SIRDEV_STATE_DONGLE_SPEED:
131 
132 		switch (speed) {
133 		default:
134 			speed = 9600;
135 			ret = -EINVAL;
136 			/* fall thru */
137 		case 9600:
138 			byte = TEKRAM_PW|TEKRAM_9600;
139 			break;
140 		case 19200:
141 			byte = TEKRAM_PW|TEKRAM_19200;
142 			break;
143 		case 38400:
144 			byte = TEKRAM_PW|TEKRAM_38400;
145 			break;
146 		case 57600:
147 			byte = TEKRAM_PW|TEKRAM_57600;
148 			break;
149 		case 115200:
150 			byte = TEKRAM_115200;
151 			break;
152 		}
153 
154 		/* Set DTR, Clear RTS */
155 		sirdev_set_dtr_rts(dev, TRUE, FALSE);
156 
157 		/* Wait at least 7us */
158 		udelay(14);
159 
160 		/* Write control byte */
161 		sirdev_raw_write(dev, &byte, 1);
162 
163 		dev->speed = speed;
164 
165 		state = TEKRAM_STATE_WAIT_SPEED;
166 		delay = tekram_delay;
167 		break;
168 
169 	case TEKRAM_STATE_WAIT_SPEED:
170 		/* Set DTR, Set RTS */
171 		sirdev_set_dtr_rts(dev, TRUE, TRUE);
172 		udelay(50);
173 		break;
174 
175 	default:
176 		net_err_ratelimited("%s - undefined state %d\n",
177 				    __func__, state);
178 		ret = -EINVAL;
179 		break;
180 	}
181 
182 	dev->fsm.substate = state;
183 	return (delay > 0) ? delay : ret;
184 }
185 
186 /*
187  * Function tekram_reset (driver)
188  *
189  *      This function resets the tekram dongle. Warning, this function
190  *      must be called with a process context!!
191  *
192  *      Algorithm:
193  *    	  0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 )
194  *        1. clear RTS
195  *        2. set DTR, and wait at least 1 ms
196  *        3. clear DTR to SPACE state, wait at least 50 us for further
197  *         operation
198  */
199 
tekram_reset(struct sir_dev * dev)200 static int tekram_reset(struct sir_dev *dev)
201 {
202 	/* Clear DTR, Set RTS */
203 	sirdev_set_dtr_rts(dev, FALSE, TRUE);
204 
205 	/* Should sleep 1 ms */
206 	msleep(1);
207 
208 	/* Set DTR, Set RTS */
209 	sirdev_set_dtr_rts(dev, TRUE, TRUE);
210 
211 	/* Wait at least 50 us */
212 	udelay(75);
213 
214 	dev->speed = 9600;
215 
216 	return 0;
217 }
218 
219 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
220 MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
221 MODULE_LICENSE("GPL");
222 MODULE_ALIAS("irda-dongle-0"); /* IRDA_TEKRAM_DONGLE */
223 
224 module_init(tekram_sir_init);
225 module_exit(tekram_sir_cleanup);
226