1 /*
2  * Copyright (c) 2001 Tommy Bohlin <tommy@gatespace.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 /* litelink.c
27  */
28 
29 #include <irda.h>
30 
31 /**********************************************************************
32  * Constants
33  **********************************************************************/
34 
35 static const char id_litelink[]="litelink";
36 
37 /**********************************************************************
38  * Data structures
39  **********************************************************************/
40 
41 typedef struct LiteLink {
42   SerialDevice sd;
43   SerialPort* sp;
44   bool initial;
45   int pulses;
46   int state;
47 } LiteLink;
48 
49 /**********************************************************************
50  * LiteLink control
51  **********************************************************************/
52 
speedTimer(void * sd)53 static void speedTimer(void* sd)
54 {
55   LiteLink* ll=(LiteLink*)sd;
56   SerialPort* sp=ll->sp;
57 
58   switch(ll->state) {
59   case 1:
60     sp->setLine(sp,LINE_RTS);
61     ll->initial=FALSE;
62     ll->state=2;
63     evtSetTimer(1,speedTimer,ll); /* At least 15us */
64     break;
65   case 2:
66     sp->setLine(sp,LINE_DTR|LINE_RTS);
67     if(ll->pulses-->0) {
68       ll->state=3;
69       evtSetTimer(1,speedTimer,ll);  /* At least 15us */
70     } else {
71       ll->state=0;
72     }
73     break;
74   case 3:
75     sp->setLine(sp,LINE_DTR);
76     ll->state=2;
77     evtSetTimer(1,speedTimer,ll);  /* At least 15us */
78     break;
79   }
80 }
81 
82 /**********************************************************************
83  * Methods
84  **********************************************************************/
85 
llSetSpeed(SerialDevice * sd,int speed)86 static int llSetSpeed(SerialDevice* sd, int speed)
87 {
88   LiteLink* ll=(LiteLink*)sd;
89   SerialPort* sp=ll->sp;
90 
91   sp->setSpeed(sp,speed);
92 
93   switch(speed) {
94   case 57600: ll->pulses=1; break;
95   case 38400: ll->pulses=2; break;
96   case 19200: ll->pulses=3; break;
97   case 9600:  ll->pulses=4; break;
98   default: /* 115200 */ ll->pulses=0; break;
99   }
100 
101   if(ll->initial) {
102     ll->state=1;
103     sp->setLine(sp,LINE_DTR|LINE_RTS);
104   } else {
105     ll->state=2;
106     sp->setLine(sp,LINE_RTS);
107   }
108   evtSetTimer(1,speedTimer,ll); /* At least 15us */
109 
110   /* Reasonable estimate */
111   return 40+20*ll->pulses;
112 }
113 
llGetSpeedMask(SerialDevice * sd)114 static int llGetSpeedMask(SerialDevice* sd)
115 {
116   LiteLink* ll=(LiteLink*)sd;
117 
118   return ll->sp->getSpeedMask(ll->sp)&
119     (SPEED_9600|SPEED_19200|SPEED_38400|SPEED_57600|SPEED_115200);
120 }
121 
llGetMinTurnaroundMask(SerialDevice * sd)122 static int llGetMinTurnaroundMask(SerialDevice* sd)
123 {
124   return MIN_TA_10ms|MIN_TA_5ms|MIN_TA_1ms|MIN_TA_500us|
125     MIN_TA_100us|MIN_TA_50us|MIN_TA_10us;
126 }
127 
llGetChar(SerialDevice * sd)128 static int llGetChar(SerialDevice* sd)
129 {
130   LiteLink* ll=(LiteLink*)sd;
131 
132   return ll->sp->getChar(ll->sp);
133 }
134 
llPutChar(SerialDevice * sd,int c)135 static void llPutChar(SerialDevice* sd, int c)
136 {
137   LiteLink* ll=(LiteLink*)sd;
138 
139   if(ll->state==0) ll->sp->putChar(ll->sp,c);
140 }
141 
llClose(SerialDevice * sd)142 static void llClose(SerialDevice* sd)
143 {
144   LiteLink* ll=(LiteLink*)sd;
145   SerialPort* sp=ll->sp;
146 
147   evtCancelTimer(speedTimer,ll);
148   sp->setLine(sp,0);
149   sp->handle=0;
150   sp->status=0;
151   freeMem(ll);
152 }
153 
llStatus(SerialPort * sp,int event)154 static void llStatus(SerialPort* sp, int event)
155 {
156   LiteLink* ll=(LiteLink*)sp->handle;
157 
158   if(ll->sd.status) ll->sd.status(&ll->sd,event);
159 }
160 
161 /**********************************************************************
162  * External interface
163  **********************************************************************/
164 
createLiteLinkDevice(SerialPort * sp)165 SerialDevice* createLiteLinkDevice(SerialPort* sp)
166 {
167   LiteLink* ll=allocMem(id_litelink,sizeof(LiteLink));
168 
169   ll->sd.close=llClose;
170   ll->sd.setSpeed=llSetSpeed;
171   ll->sd.getSpeedMask=llGetSpeedMask;
172   ll->sd.getMinTurnaroundMask=llGetMinTurnaroundMask;
173   ll->sd.getChar=llGetChar;
174   ll->sd.putChar=llPutChar;
175   ll->sd.handle=0;
176   ll->sd.status=0;
177   ll->sp=sp;
178   ll->initial=TRUE;
179   ll->state=0;
180 
181   sp->handle=ll;
182   sp->status=llStatus;
183 
184   return &ll->sd;
185 }
186