Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
net
irda
toim3232-sir.c
Go to the documentation of this file.
1
/*********************************************************************
2
*
3
* Filename: toim3232-sir.c
4
* Version: 1.0
5
* Description: Implementation of dongles based on the Vishay/Temic
6
* TOIM3232 SIR Endec chipset. Currently only the
7
* IRWave IR320ST-2 is tested, although it should work
8
* with any TOIM3232 or TOIM4232 chipset based RS232
9
* dongle with minimal modification.
10
* Based heavily on the Tekram driver (tekram.c),
11
* with thanks to Dag Brattli and Martin Diehl.
12
* Status: Experimental.
13
* Author: David Basden <
[email protected]
>
14
* Created at: Thu Feb 09 23:47:32 2006
15
*
16
* Copyright (c) 2006 David Basden.
17
* Copyright (c) 1998-1999 Dag Brattli,
18
* Copyright (c) 2002 Martin Diehl,
19
* All Rights Reserved.
20
*
21
* This program is free software; you can redistribute it and/or
22
* modify it under the terms of the GNU General Public License as
23
* published by the Free Software Foundation; either version 2 of
24
* the License, or (at your option) any later version.
25
*
26
* Neither Dag Brattli nor University of Tromsø admit liability nor
27
* provide warranty for any of this software. This material is
28
* provided "AS-IS" and at no charge.
29
*
30
********************************************************************/
31
32
/*
33
* This driver has currently only been tested on the IRWave IR320ST-2
34
*
35
* PROTOCOL:
36
*
37
* The protocol for talking to the TOIM3232 is quite easy, and is
38
* designed to interface with RS232 with only level convertors. The
39
* BR/~D line on the chip is brought high to signal 'command mode',
40
* where a command byte is sent to select the baudrate of the RS232
41
* interface and the pulse length of the IRDA output. When BR/~D
42
* is brought low, the dongle then changes to the selected baudrate,
43
* and the RS232 interface is used for data until BR/~D is brought
44
* high again. The initial speed for the TOIMx323 after RESET is
45
* 9600 baud. The baudrate for command-mode is the last selected
46
* baud-rate, or 9600 after a RESET.
47
*
48
* The dongle I have (below) adds some extra hardware on the front end,
49
* but this is mostly directed towards pariasitic power from the RS232
50
* line rather than changing very much about how to communicate with
51
* the TOIM3232.
52
*
53
* The protocol to talk to the TOIM4232 chipset seems to be almost
54
* identical to the TOIM3232 (and the 4232 datasheet is more detailed)
55
* so this code will probably work on that as well, although I haven't
56
* tested it on that hardware.
57
*
58
* Target dongle variations that might be common:
59
*
60
* DTR and RTS function:
61
* The data sheet for the 4232 has a sample implementation that hooks the
62
* DTR and RTS lines to the RESET and BaudRate/~Data lines of the
63
* chip (through line-converters). Given both DTR and RTS would have to
64
* be held low in normal operation, and the TOIMx232 requires +5V to
65
* signal ground, most dongle designers would almost certainly choose
66
* an implementation that kept at least one of DTR or RTS high in
67
* normal operation to provide power to the dongle, but will likely
68
* vary between designs.
69
*
70
* User specified command bits:
71
* There are two user-controllable output lines from the TOIMx232 that
72
* can be set low or high by setting the appropriate bits in the
73
* high-nibble of the command byte (when setting speed and pulse length).
74
* These might be used to switch on and off added hardware or extra
75
* dongle features.
76
*
77
*
78
* Target hardware: IRWave IR320ST-2
79
*
80
* The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic
81
* TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transceiver.
82
* It uses a hex inverter and some discrete components to buffer and
83
* line convert the RS232 down to 5V.
84
*
85
* The dongle is powered through a voltage regulator, fed by a large
86
* capacitor. To switch the dongle on, DTR is brought high to charge
87
* the capacitor and drive the voltage regulator. DTR isn't associated
88
* with any control lines on the TOIM3232. Parisitic power is also taken
89
* from the RTS, TD and RD lines when brought high, but through resistors.
90
* When DTR is low, the circuit might lose power even with RTS high.
91
*
92
* RTS is inverted and attached to the BR/~D input pin. When RTS
93
* is high, BR/~D is low, and the TOIM3232 is in the normal 'data' mode.
94
* RTS is brought low, BR/~D is high, and the TOIM3232 is in 'command
95
* mode'.
96
*
97
* For some unknown reason, the RESET line isn't actually connected
98
* to anything. This means to reset the dongle to get it to a known
99
* state (9600 baud) you must drop DTR and RTS low, wait for the power
100
* capacitor to discharge, and then bring DTR (and RTS for data mode)
101
* high again, and wait for the capacitor to charge, the power supply
102
* to stabilise, and the oscillator clock to stabilise.
103
*
104
* Fortunately, if the current baudrate is known, the chipset can
105
* easily change speed by entering command mode without having to
106
* reset the dongle first.
107
*
108
* Major Components:
109
*
110
* - Vishay/Temic TOIM3232 SIR Endec to change RS232 pulse timings
111
* to IRDA pulse timings
112
* - 3.6864MHz crystal to drive TOIM3232 clock oscillator
113
* - DM74lS04M Inverting Hex line buffer for RS232 input buffering
114
* and level conversion
115
* - PJ2951AC 150mA voltage regulator
116
* - Vishay/Temic TFDS4500 SIR IRDA front-end transceiver
117
*
118
*/
119
120
#include <linux/module.h>
121
#include <
linux/delay.h
>
122
#include <
linux/init.h
>
123
#include <linux/sched.h>
124
125
#include <
net/irda/irda.h
>
126
127
#include "
sir-dev.h
"
128
129
static
int
toim3232delay = 150;
/* default is 150 ms */
130
module_param
(toim3232delay,
int
, 0);
131
MODULE_PARM_DESC
(toim3232delay,
"toim3232 dongle write complete delay"
);
132
133
#if 0
134
static
int
toim3232flipdtr = 0;
/* default is DTR high to reset */
135
module_param
(toim3232flipdtr,
int
, 0);
136
MODULE_PARM_DESC
(toim3232flipdtr,
"toim3232 dongle invert DTR (Reset)"
);
137
138
static
int
toim3232fliprts = 0;
/* default is RTS high for baud change */
139
module_param
(toim3232fliptrs,
int
, 0);
140
MODULE_PARM_DESC
(toim3232fliprts,
"toim3232 dongle invert RTS (BR/D)"
);
141
#endif
142
143
static
int
toim3232_open(
struct
sir_dev
*);
144
static
int
toim3232_close(
struct
sir_dev
*);
145
static
int
toim3232_change_speed(
struct
sir_dev
*,
unsigned
);
146
static
int
toim3232_reset(
struct
sir_dev
*);
147
148
#define TOIM3232_115200 0x00
149
#define TOIM3232_57600 0x01
150
#define TOIM3232_38400 0x02
151
#define TOIM3232_19200 0x03
152
#define TOIM3232_9600 0x06
153
#define TOIM3232_2400 0x0A
154
155
#define TOIM3232_PW 0x10
/* Pulse select bit */
156
157
static
struct
dongle_driver
toim3232 = {
158
.owner =
THIS_MODULE
,
159
.driver_name =
"Vishay TOIM3232"
,
160
.type =
IRDA_TOIM3232_DONGLE
,
161
.open = toim3232_open,
162
.close = toim3232_close,
163
.reset = toim3232_reset,
164
.set_speed = toim3232_change_speed,
165
};
166
167
static
int
__init
toim3232_sir_init(
void
)
168
{
169
if
(toim3232delay < 1 || toim3232delay > 500)
170
toim3232delay = 200;
171
IRDA_DEBUG
(1,
"%s - using %d ms delay\n"
,
172
toim3232.
driver_name
, toim3232delay);
173
return
irda_register_dongle
(&toim3232);
174
}
175
176
static
void
__exit
toim3232_sir_cleanup(
void
)
177
{
178
irda_unregister_dongle
(&toim3232);
179
}
180
181
static
int
toim3232_open(
struct
sir_dev
*
dev
)
182
{
183
struct
qos_info
*qos = &dev->
qos
;
184
185
IRDA_DEBUG
(2,
"%s()\n"
, __func__);
186
187
/* Pull the lines high to start with.
188
*
189
* For the IR320ST-2, we need to charge the main supply capacitor to
190
* switch the device on. We keep DTR high throughout to do this.
191
* When RTS, TD and RD are high, they will also trickle-charge the
192
* cap. RTS is high for data transmission, and low for baud rate select.
193
* -- DGB
194
*/
195
sirdev_set_dtr_rts
(dev,
TRUE
,
TRUE
);
196
197
/* The TOI3232 supports many speeds between 1200bps and 115000bps.
198
* We really only care about those supported by the IRDA spec, but
199
* 38400 seems to be implemented in many places */
200
qos->
baud_rate
.
bits
&=
IR_2400
|
IR_9600
|
IR_19200
|
IR_38400
|
IR_57600
|
IR_115200
;
201
202
/* From the tekram driver. Not sure what a reasonable value is -- DGB */
203
qos->
min_turn_time
.
bits
= 0x01;
/* Needs at least 10 ms */
204
irda_qos_bits_to_value
(qos);
205
206
/* irda thread waits 50 msec for power settling */
207
208
return
0;
209
}
210
211
static
int
toim3232_close(
struct
sir_dev
*
dev
)
212
{
213
IRDA_DEBUG
(2,
"%s()\n"
, __func__);
214
215
/* Power off dongle */
216
sirdev_set_dtr_rts
(dev,
FALSE
,
FALSE
);
217
218
return
0;
219
}
220
221
/*
222
* Function toim3232change_speed (dev, state, speed)
223
*
224
* Set the speed for the TOIM3232 based dongle. Warning, this
225
* function must be called with a process context!
226
*
227
* Algorithm
228
* 1. keep DTR high but clear RTS to bring into baud programming mode
229
* 2. wait at least 7us to enter programming mode
230
* 3. send control word to set baud rate and timing
231
* 4. wait at least 1us
232
* 5. bring RTS high to enter DATA mode (RS232 is passed through to transceiver)
233
* 6. should take effect immediately (although probably worth waiting)
234
*/
235
236
#define TOIM3232_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
237
238
static
int
toim3232_change_speed(
struct
sir_dev
*
dev
,
unsigned
speed)
239
{
240
unsigned
state
= dev->
fsm
.substate;
241
unsigned
delay
= 0;
242
u8
byte
;
243
static
int
ret
= 0;
244
245
IRDA_DEBUG
(2,
"%s()\n"
, __func__);
246
247
switch
(state) {
248
case
SIRDEV_STATE_DONGLE_SPEED
:
249
250
/* Figure out what we are going to send as a control byte */
251
switch
(speed) {
252
case
2400:
253
byte =
TOIM3232_PW
|
TOIM3232_2400
;
254
break
;
255
default
:
256
speed = 9600;
257
ret = -
EINVAL
;
258
/* fall thru */
259
case
9600:
260
byte =
TOIM3232_PW
|
TOIM3232_9600
;
261
break
;
262
case
19200:
263
byte =
TOIM3232_PW
|
TOIM3232_19200
;
264
break
;
265
case
38400:
266
byte =
TOIM3232_PW
|
TOIM3232_38400
;
267
break
;
268
case
57600:
269
byte =
TOIM3232_PW
|
TOIM3232_57600
;
270
break
;
271
case
115200:
272
byte =
TOIM3232_115200
;
273
break
;
274
}
275
276
/* Set DTR, Clear RTS: Go into baud programming mode */
277
sirdev_set_dtr_rts
(dev,
TRUE
,
FALSE
);
278
279
/* Wait at least 7us */
280
udelay
(14);
281
282
/* Write control byte */
283
sirdev_raw_write
(dev, &byte, 1);
284
285
dev->
speed
= speed;
286
287
state =
TOIM3232_STATE_WAIT_SPEED
;
288
delay = toim3232delay;
289
break
;
290
291
case
TOIM3232_STATE_WAIT_SPEED
:
292
/* Have transmitted control byte * Wait for 'at least 1us' */
293
udelay
(14);
294
295
/* Set DTR, Set RTS: Go into normal data mode */
296
sirdev_set_dtr_rts
(dev,
TRUE
,
TRUE
);
297
298
/* Wait (TODO: check this is needed) */
299
udelay
(50);
300
break
;
301
302
default
:
303
printk
(
KERN_ERR
"%s - undefined state %d\n"
, __func__, state);
304
ret = -
EINVAL
;
305
break
;
306
}
307
308
dev->
fsm
.substate =
state
;
309
return
(delay > 0) ? delay :
ret
;
310
}
311
312
/*
313
* Function toim3232reset (driver)
314
*
315
* This function resets the toim3232 dongle. Warning, this function
316
* must be called with a process context!!
317
*
318
* What we should do is:
319
* 0. Pull RESET high
320
* 1. Wait for at least 7us
321
* 2. Pull RESET low
322
* 3. Wait for at least 7us
323
* 4. Pull BR/~D high
324
* 5. Wait for at least 7us
325
* 6. Send control byte to set baud rate
326
* 7. Wait at least 1us after stop bit
327
* 8. Pull BR/~D low
328
* 9. Should then be in data mode
329
*
330
* Because the IR320ST-2 doesn't have the RESET line connected for some reason,
331
* we'll have to do something else.
332
*
333
* The default speed after a RESET is 9600, so lets try just bringing it up in
334
* data mode after switching it off, waiting for the supply capacitor to
335
* discharge, and then switch it back on. This isn't actually pulling RESET
336
* high, but it seems to have the same effect.
337
*
338
* This behaviour will probably work on dongles that have the RESET line connected,
339
* but if not, add a flag for the IR320ST-2, and implment the above-listed proper
340
* behaviour.
341
*
342
* RTS is inverted and then fed to BR/~D, so to put it in programming mode, we
343
* need to have pull RTS low
344
*/
345
346
static
int
toim3232_reset(
struct
sir_dev
*
dev
)
347
{
348
IRDA_DEBUG
(2,
"%s()\n"
, __func__);
349
350
/* Switch off both DTR and RTS to switch off dongle */
351
sirdev_set_dtr_rts
(dev,
FALSE
,
FALSE
);
352
353
/* Should sleep a while. This might be evil doing it this way.*/
354
set_current_state
(
TASK_UNINTERRUPTIBLE
);
355
schedule_timeout
(
msecs_to_jiffies
(50));
356
357
/* Set DTR, Set RTS (data mode) */
358
sirdev_set_dtr_rts
(dev,
TRUE
,
TRUE
);
359
360
/* Wait at least 10 ms for power to stabilize again */
361
set_current_state
(
TASK_UNINTERRUPTIBLE
);
362
schedule_timeout
(
msecs_to_jiffies
(10));
363
364
/* Speed should now be 9600 */
365
dev->
speed
= 9600;
366
367
return
0;
368
}
369
370
MODULE_AUTHOR
(
"David Basden <
[email protected]
>"
);
371
MODULE_DESCRIPTION
(
"Vishay/Temic TOIM3232 based dongle driver"
);
372
MODULE_LICENSE
(
"GPL"
);
373
MODULE_ALIAS
(
"irda-dongle-12"
);
/* IRDA_TOIM3232_DONGLE */
374
375
module_init
(toim3232_sir_init);
376
module_exit
(toim3232_sir_cleanup);
Generated on Thu Jan 10 2013 14:06:56 for Linux Kernel by
1.8.2