1 //---------------------------------------------------------------------------
2 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Except as contained in this notice, the name of Dallas Semiconductor
23 // shall not be used except as stated in the Dallas Semiconductor
24 // Branding Policy.
25 //---------------------------------------------------------------------------
26 //
27 // linuxlnk.C - COM functions required by MLANLL.C, MLANTRNU, MLANNETU.C and
28 // MLanFile.C for MLANU to communicate with the DS2480 based
29 // Universal Serial Adapter 'U'. Fill in the platform specific code.
30 //
31 // Version: 1.02
32 //
33 // History: 1.00 -> 1.01 Added function msDelay.
34 //
35 // 1.01 -> 1.02 Changed to generic OpenCOM/CloseCOM for easier
36 // use with other platforms.
37 //
38
39 //--------------------------------------------------------------------------
40 // Copyright (C) 1998 Andrea Chambers and University of Newcastle upon Tyne,
41 // All Rights Reserved.
42 //--------------------------------------------------------------------------
43 //
44 // Permission is hereby granted, free of charge, to any person obtaining a
45 // copy of this software and associated documentation files (the "Software"),
46 // to deal in the Software without restriction, including without limitation
47 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
48 // and/or sell copies of the Software, and to permit persons to whom the
49 // Software is furnished to do so, subject to the following conditions:
50 //
51 // The above copyright notice and this permission notice shall be included
52 // in all copies or substantial portions of the Software.
53 //
54 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
55 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
57 // IN NO EVENT SHALL THE UNIVERSITY OF NEWCASTLE UPON TYNE OR ANDREA CHAMBERS
58 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
59 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
60 // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
61 //---------------------------------------------------------------------------
62 //
63 // LinuxLNK.C - COM functions required by MLANLLU.C, MLANTRNU.C, MLANNETU.C
64 // and MLanFile.C for MLANU to communicate with the DS2480 based
65 // Universal Serial Adapter 'U'. Platform specific code.
66 //
67 // Version: 2.01
68 // History: 1.02 -> 1.03 modifications by David Smiczek
69 // Changed to use generic OpenCOM/CloseCOM
70 // Pass port name to OpenCOM instead of hard coded
71 // Changed msDelay to handle long delays
72 // Reformatted to look like 'TODO.C'
73 // Added #include "ds2480.h" to use constants.
74 // Added function SetBaudCOM()
75 // Added function msGettick()
76 // Removed delay from WriteCOM(), used tcdrain()
77 // Added wait for byte available with timeout using
78 // select() in ReadCOM()
79 //
80 // 1.03 -> 2.00 Support for multiple ports. Include "ownet.h". Use
81 // 'uchar'. Reorder functions. Provide correct
82 // return values to OpenCOM. Replace 'makeraw' call.
83 // Should now be POSIX.
84 // 2.00 -> 2.01 Added support for owError library.
85 //
86
87 #include <unistd.h>
88 #include <sys/types.h>
89 #include <sys/stat.h>
90 #include <fcntl.h>
91 #include <sys/ioctl.h>
92 #include <time.h>
93 #include <termios.h>
94 #include <errno.h>
95 #include <sys/time.h>
96 #include <string.h>
97
98 #include "ds2480.h"
99 #include "ownet.h"
100
101 /* exportable functions */
102 SMALLINT OpenCOM(int, char*);
103 SMALLINT WriteCOM(int, int, uchar*);
104 void CloseCOM(int);
105 void FlushCOM(int);
106 int ReadCOM(int, int, uchar*);
107 void BreakCOM(int);
108 void SetBaudCOM(int, int);
109 void msDelay(int);
110 long msGettick(void);
111
112 // LinuxLNK global
113 int fd[MAX_PORTNUM];
114 struct termios origterm;
115
116 //---------------------------------------------------------------------------
117 // Attempt to open a com port.
118 // Set the starting baud rate to 9600.
119 //
120 // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will
121 // be used to indicate the port number desired when calling
122 // all other functions in this library.
123 //
124 // 'port_zstr' - zero terminate port name. For this platform
125 // use format COMX where X is the port number.
126 //
127 //
128 // Returns: TRUE(1) - success, COM port opened
129 // FALSE(0) - failure, could not open specified port
130 //
OpenCOM(int portnum,char * port_zstr)131 SMALLINT OpenCOM(int portnum, char *port_zstr)
132 {
133 struct termios t; // see man termios - declared as above
134 int rc;
135
136 fd[portnum] = open(port_zstr, O_RDWR|O_NONBLOCK);
137 if (fd[portnum]<0)
138 {
139 OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED);
140 return FALSE; // changed (2.00), used to return fd;
141 }
142 rc = tcgetattr (fd[portnum], &t);
143 if (rc < 0)
144 {
145 int tmp;
146 tmp = errno;
147 close(fd[portnum]);
148 errno = tmp;
149 OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED);
150 return FALSE; // changed (2.00), used to return rc;
151 }
152
153 cfsetospeed(&t, B9600);
154 cfsetispeed (&t, B9600);
155
156 // Get terminal parameters. (2.00) removed raw
157 tcgetattr(fd[portnum],&t);
158 // Save original settings.
159 origterm = t;
160
161 // Set to non-canonical mode, and no RTS/CTS handshaking
162 t.c_iflag &= ~(BRKINT|ICRNL|IGNCR|INLCR|INPCK|ISTRIP|IXON|IXOFF|PARMRK);
163 t.c_iflag |= IGNBRK|IGNPAR;
164 t.c_oflag &= ~(OPOST);
165 t.c_cflag &= ~(CRTSCTS|CSIZE|HUPCL|PARENB);
166 t.c_cflag |= (CLOCAL|CS8|CREAD);
167 t.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|IEXTEN|ISIG);
168 t.c_cc[VMIN] = 0;
169 t.c_cc[VTIME] = 3;
170
171 rc = tcsetattr(fd[portnum], TCSAFLUSH, &t);
172 tcflush(fd[portnum],TCIOFLUSH);
173
174 if (rc < 0)
175 {
176 int tmp;
177 tmp = errno;
178 close(fd[portnum]);
179 errno = tmp;
180 OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED);
181 return FALSE; // changed (2.00), used to return rc;
182 }
183
184 return TRUE; // changed (2.00), used to return fd;
185 }
186
187
188 //---------------------------------------------------------------------------
189 // Closes the connection to the port.
190 //
191 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
192 // OpenCOM to indicate the port number.
193 //
CloseCOM(int portnum)194 void CloseCOM(int portnum)
195 {
196 // restore tty settings
197 tcsetattr(fd[portnum], TCSAFLUSH, &origterm);
198 FlushCOM(portnum);
199 close(fd[portnum]);
200 }
201
202
203 //--------------------------------------------------------------------------
204 // Write an array of bytes to the COM port, verify that it was
205 // sent out. Assume that baud rate has been set.
206 //
207 // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will
208 // be used to indicate the port number desired when calling
209 // all other functions in this library.
210 // Returns 1 for success and 0 for failure
211 //
WriteCOM(int portnum,int outlen,uchar * outbuf)212 SMALLINT WriteCOM(int portnum, int outlen, uchar *outbuf)
213 {
214 long count = outlen;
215 int i = write(fd[portnum], outbuf, outlen);
216
217 tcdrain(fd[portnum]);
218 return (i == count);
219 }
220
221
222 //--------------------------------------------------------------------------
223 // Read an array of bytes to the COM port, verify that it was
224 // sent out. Assume that baud rate has been set.
225 //
226 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
227 // OpenCOM to indicate the port number.
228 // 'outlen' - number of bytes to write to COM port
229 // 'outbuf' - pointer ot an array of bytes to write
230 //
231 // Returns: TRUE(1) - success
232 // FALSE(0) - failure
233 //
ReadCOM(int portnum,int inlen,uchar * inbuf)234 int ReadCOM(int portnum, int inlen, uchar *inbuf)
235 {
236 fd_set filedescr;
237 struct timeval tval;
238 int cnt;
239
240 // loop to wait until each byte is available and read it
241 for (cnt = 0; cnt < inlen; cnt++)
242 {
243 // set a descriptor to wait for a character available
244 FD_ZERO(&filedescr);
245 FD_SET(fd[portnum],&filedescr);
246 // set timeout to 10ms
247 tval.tv_sec = 0;
248 tval.tv_usec = 10000;
249
250 // if byte available read or return bytes read
251 if (select(fd[portnum]+1,&filedescr,NULL,NULL,&tval) != 0)
252 {
253 if (read(fd[portnum],&inbuf[cnt],1) != 1)
254 return cnt;
255 }
256 else
257 return cnt;
258 }
259
260 // success, so return desired length
261 return inlen;
262 }
263
264
265 //---------------------------------------------------------------------------
266 // Description:
267 // flush the rx and tx buffers
268 //
269 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
270 // OpenCOM to indicate the port number.
271 //
FlushCOM(int portnum)272 void FlushCOM(int portnum)
273 {
274 tcflush(fd[portnum], TCIOFLUSH);
275 }
276
277
278 //--------------------------------------------------------------------------
279 // Description:
280 // Send a break on the com port for at least 2 ms
281 //
282 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
283 // OpenCOM to indicate the port number.
284 //
BreakCOM(int portnum)285 void BreakCOM(int portnum)
286 {
287 int duration = 0; // see man termios break may be
288 tcsendbreak(fd[portnum], duration); // too long
289 }
290
291
292 //--------------------------------------------------------------------------
293 // Set the baud rate on the com port.
294 //
295 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
296 // OpenCOM to indicate the port number.
297 // 'new_baud' - new baud rate defined as
298 // PARMSET_9600 0x00
299 // PARMSET_19200 0x02
300 // PARMSET_57600 0x04
301 // PARMSET_115200 0x06
302 //
SetBaudCOM(int portnum,int new_baud)303 void SetBaudCOM(int portnum, int new_baud)
304 {
305 struct termios t;
306 int rc;
307 speed_t baud;
308
309 // read the attribute structure
310 rc = tcgetattr(fd[portnum], &t);
311 if (rc < 0)
312 {
313 close(fd[portnum]);
314 return;
315 }
316
317 // convert parameter to linux baud rate
318 switch(new_baud)
319 {
320 case PARMSET_9600:
321 baud = B9600;
322 break;
323 case PARMSET_19200:
324 baud = B19200;
325 break;
326 case PARMSET_57600:
327 baud = B57600;
328 break;
329 case PARMSET_115200:
330 baud = B115200;
331 break;
332 }
333
334 // set baud in structure
335 cfsetospeed(&t, baud);
336 cfsetispeed(&t, baud);
337
338 // change baud on port
339 rc = tcsetattr(fd[portnum], TCSAFLUSH, &t);
340 if (rc < 0)
341 close(fd[portnum]);
342 }
343
344
345 //--------------------------------------------------------------------------
346 // Get the current millisecond tick count. Does not have to represent
347 // an actual time, it just needs to be an incrementing timer.
348 //
msGettick(void)349 long msGettick(void)
350 {
351 struct timezone tmzone;
352 struct timeval tmval;
353 long ms;
354
355 gettimeofday(&tmval,&tmzone);
356 ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000;
357 return ms;
358 }
359
360
361 //--------------------------------------------------------------------------
362 // Description:
363 // Delay for at least 'len' ms
364 //
msDelay(int len)365 void msDelay(int len)
366 {
367 struct timespec s; // Set aside memory space on the stack
368
369 s.tv_sec = len / 1000;
370 s.tv_nsec = (len - (s.tv_sec * 1000)) * 1000000;
371 nanosleep(&s, NULL);
372 }
373
374