summaryrefslogtreecommitdiff
path: root/src/pmdas/roomtemp/mlan
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/roomtemp/mlan')
-rw-r--r--src/pmdas/roomtemp/mlan/GNUmakefile45
-rw-r--r--src/pmdas/roomtemp/mlan/ds2480.h183
-rw-r--r--src/pmdas/roomtemp/mlan/ds2480ut.c206
-rw-r--r--src/pmdas/roomtemp/mlan/linuxlnk.c443
-rw-r--r--src/pmdas/roomtemp/mlan/mlan.h94
-rw-r--r--src/pmdas/roomtemp/mlan/mlanllu.c499
-rw-r--r--src/pmdas/roomtemp/mlan/mlannetu.c599
-rw-r--r--src/pmdas/roomtemp/mlan/mlansesu.c102
-rw-r--r--src/pmdas/roomtemp/mlan/mlantrnu.c579
9 files changed, 2750 insertions, 0 deletions
diff --git a/src/pmdas/roomtemp/mlan/GNUmakefile b/src/pmdas/roomtemp/mlan/GNUmakefile
new file mode 100644
index 0000000..f6e33ae
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/GNUmakefile
@@ -0,0 +1,45 @@
+#!gmake
+#
+# Copyright (c) 2000,2004 Silicon Graphics, Inc. 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.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+TOPDIR = ../../../..
+include $(TOPDIR)/src/include/builddefs
+
+CFILES=mlannetu.c mlansesu.c mlanllu.c linuxlnk.c ds2480ut.c mlantrnu.c
+HFILES=mlan.h ds2480.h
+STATICLIBTARGET = libmlan.a
+LDIRT = libmlan.a
+LCFLAGS = -g
+
+default : $(STATICLIBTARGET)
+
+ifeq "$(findstring $(TARGET_OS),solaris linux)" ""
+default:
+else
+default : $(STATICLIBTARGET)
+endif
+
+.NOTPARALLEL:
+
+install :
+
+default_pcp : default
+
+install_pcp : install
+
+include $(BUILDRULES)
diff --git a/src/pmdas/roomtemp/mlan/ds2480.h b/src/pmdas/roomtemp/mlan/ds2480.h
new file mode 100644
index 0000000..139e2c4
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/ds2480.h
@@ -0,0 +1,183 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// DS2480.H - This file contains the DS2480 constants
+//
+// Version: 1.03
+// History: 1.02 -> 1.03 Make sure uchar is not defined twice.
+//
+//
+
+// typedefs
+#ifndef UCHAR
+ #define UCHAR
+ typedef unsigned char uchar;
+#endif
+
+// Mode Commands
+#define MODE_DATA 0xE1
+#define MODE_COMMAND 0xE3
+#define MODE_STOP_PULSE 0xF1
+
+// Return byte value
+#define RB_CHIPID_MASK 0x1C
+#define RB_RESET_MASK 0x03
+#define RB_1WIRESHORT 0x00
+#define RB_PRESENCE 0x01
+#define RB_ALARMPRESENCE 0x02
+#define RB_NOPRESENCE 0x03
+
+#define RB_BIT_MASK 0x03
+#define RB_BIT_ONE 0x03
+#define RB_BIT_ZERO 0x00
+
+// Masks for all bit ranges
+#define CMD_MASK 0x80
+#define FUNCTSEL_MASK 0x60
+#define BITPOL_MASK 0x10
+#define SPEEDSEL_MASK 0x0C
+#define MODSEL_MASK 0x02
+#define PARMSEL_MASK 0x70
+#define PARMSET_MASK 0x0E
+
+// Command or config bit
+#define CMD_COMM 0x81
+#define CMD_CONFIG 0x01
+
+// Function select bits
+#define FUNCTSEL_BIT 0x00
+#define FUNCTSEL_SEARCHON 0x30
+#define FUNCTSEL_SEARCHOFF 0x20
+#define FUNCTSEL_RESET 0x40
+#define FUNCTSEL_CHMOD 0x60
+
+// Bit polarity/Pulse voltage bits
+#define BITPOL_ONE 0x10
+#define BITPOL_ZERO 0x00
+#define BITPOL_5V 0x00
+#define BITPOL_12V 0x10
+
+// One Wire speed bits
+#define SPEEDSEL_STD 0x00
+#define SPEEDSEL_FLEX 0x04
+#define SPEEDSEL_OD 0x08
+#define SPEEDSEL_PULSE 0x0C
+
+// Data/Command mode select bits
+#define MODSEL_DATA 0x00
+#define MODSEL_COMMAND 0x02
+
+// 5V Follow Pulse select bits (If 5V pulse
+// will be following the next byte or bit.)
+#define PRIME5V_TRUE 0x02
+#define PRIME5V_FALSE 0x00
+
+// Parameter select bits
+#define PARMSEL_PARMREAD 0x00
+#define PARMSEL_SLEW 0x10
+#define PARMSEL_12VPULSE 0x20
+#define PARMSEL_5VPULSE 0x30
+#define PARMSEL_WRITE1LOW 0x40
+#define PARMSEL_SAMPLEOFFSET 0x50
+#define PARMSEL_ACTIVEPULLUPTIME 0x60
+#define PARMSEL_BAUDRATE 0x70
+
+// Pull down slew rate.
+#define PARMSET_Slew15Vus 0x00
+#define PARMSET_Slew2p2Vus 0x02
+#define PARMSET_Slew1p65Vus 0x04
+#define PARMSET_Slew1p37Vus 0x06
+#define PARMSET_Slew1p1Vus 0x08
+#define PARMSET_Slew0p83Vus 0x0A
+#define PARMSET_Slew0p7Vus 0x0C
+#define PARMSET_Slew0p55Vus 0x0E
+
+// 12V programming pulse time table
+#define PARMSET_32us 0x00
+#define PARMSET_64us 0x02
+#define PARMSET_128us 0x04
+#define PARMSET_256us 0x06
+#define PARMSET_512us 0x08
+#define PARMSET_1024us 0x0A
+#define PARMSET_2048us 0x0C
+#define PARMSET_infinite 0x0E
+
+// 5V strong pull up pulse time table
+#define PARMSET_16p4ms 0x00
+#define PARMSET_65p5ms 0x02
+#define PARMSET_131ms 0x04
+#define PARMSET_262ms 0x06
+#define PARMSET_524ms 0x08
+#define PARMSET_1p05s 0x0A
+#define PARMSET_2p10s 0x0C
+#define PARMSET_infinite 0x0E
+
+// Write 1 low time
+#define PARMSET_Write8us 0x00
+#define PARMSET_Write9us 0x02
+#define PARMSET_Write10us 0x04
+#define PARMSET_Write11us 0x06
+#define PARMSET_Write12us 0x08
+#define PARMSET_Write13us 0x0A
+#define PARMSET_Write14us 0x0C
+#define PARMSET_Write15us 0x0E
+
+// Data sample offset and Write 0 recovery time
+#define PARMSET_SampOff3us 0x00
+#define PARMSET_SampOff4us 0x02
+#define PARMSET_SampOff5us 0x04
+#define PARMSET_SampOff6us 0x06
+#define PARMSET_SampOff7us 0x08
+#define PARMSET_SampOff8us 0x0A
+#define PARMSET_SampOff9us 0x0C
+#define PARMSET_SampOff10us 0x0E
+
+// Active pull up on time
+#define PARMSET_PullUp0p0us 0x00
+#define PARMSET_PullUp0p5us 0x02
+#define PARMSET_PullUp1p0us 0x04
+#define PARMSET_PullUp1p5us 0x06
+#define PARMSET_PullUp2p0us 0x08
+#define PARMSET_PullUp2p5us 0x0A
+#define PARMSET_PullUp3p0us 0x0C
+#define PARMSET_PullUp3p5us 0x0E
+
+// Baud rate bits
+#define PARMSET_9600 0x00
+#define PARMSET_19200 0x02
+#define PARMSET_57600 0x04
+#define PARMSET_115200 0x06
+
+// DS2480 program voltage available
+#define DS2480PROG_MASK 0x20
+
+// mode bit flags
+#define MODE_NORMAL 0x00
+#define MODE_OVERDRIVE 0x01
+#define MODE_STRONG5 0x02
+#define MODE_PROGRAM 0x04
+#define MODE_BREAK 0x08
+
diff --git a/src/pmdas/roomtemp/mlan/ds2480ut.c b/src/pmdas/roomtemp/mlan/ds2480ut.c
new file mode 100644
index 0000000..d353743
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/ds2480ut.c
@@ -0,0 +1,206 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// ds2480ut.c - DS2480 utility functions.
+//
+// Version: 1.03
+//
+// History: 1.00 -> 1.01 Default PDSRC changed from 0.83 to 1.37V/us
+// in DS2480Detect. Changed to use msDelay instead
+// of Delay.
+//
+// 1.01 -> 1.02 Changed global declarations from 'uchar' to 'int'.
+// Changed DSO/WORT from 7 to 10us in DS2480Detect.
+//
+// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
+
+#include "ds2480.h"
+#include "mlan.h"
+
+// external COM functions required
+extern void FlushCOM(void);
+extern int WriteCOM(int, uchar *);
+extern int ReadCOM(int, uchar *);
+extern void BreakCOM(void);
+//extern void SetBaudCOM(uchar);
+extern void msDelay(int);
+
+// exportable functions
+int DS2480Detect(void);
+int DS2480ChangeBaud(uchar);
+
+// global DS2480 state
+int UMode = MODSEL_COMMAND; // current DS2480 command or data mode stateuchar
+int UBaud = PARMSET_9600; // current DS2480 baud rate
+int USpeed = SPEEDSEL_FLEX; // current DS2480 MicroLAN communication speed
+int ULevel = MODE_NORMAL; // current DS2480 MicroLAN level
+
+//---------------------------------------------------------------------------
+// Attempt to resyc and detect a DS2480
+//
+// Returns: TRUE - DS2480 detected successfully
+// FALSE - Could not detect DS2480
+//
+int DS2480Detect(void)
+{
+ uchar sendpacket[10],readbuffer[10];
+ short sendlen=0;
+
+ // reset modes
+ UMode = MODSEL_COMMAND;
+ UBaud = PARMSET_9600;
+ USpeed = SPEEDSEL_FLEX;
+
+ // set the baud rate to 9600
+ SetBaudCOM((uchar)UBaud);
+
+ // send a break to reset the DS2480
+ BreakCOM();
+
+ // delay to let line settle
+ msDelay(2);
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the timing byte
+ sendpacket[0] = 0xC1;
+ if (WriteCOM(1,sendpacket) != 1)
+ return FALSE;
+
+ // set the FLEX configuration parameters
+ // default PDSRC = 1.37Vus
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus;
+ // default W1LT = 12us
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write12us;
+ // default DSO/WORT = 10us
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff10us;
+
+ // construct the command to read the baud rate (to test command block)
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
+
+ // also do 1 bit operation (to test 1-Wire block)
+ sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_BIT | UBaud | BITPOL_ONE;
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the response
+ if (ReadCOM(5,readbuffer) == 5)
+ {
+ // look at the baud rate and bit operation
+ // to see if the response makes sense
+ if (((readbuffer[3] & 0xF1) == 0x00) &&
+ ((readbuffer[3] & 0x0E) == UBaud) &&
+ ((readbuffer[4] & 0xF0) == 0x90) &&
+ ((readbuffer[4] & 0x0C) == UBaud))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+//---------------------------------------------------------------------------
+// Change the DS2480 from the current baud rate to the new baud rate.
+//
+// 'newbaud' - the new baud rate to change to, defined as:
+// PARMSET_9600 0x00
+// PARMSET_19200 0x02
+// PARMSET_57600 0x04
+// PARMSET_115200 0x06
+//
+// Returns: current DS2480 baud rate.
+//
+int DS2480ChangeBaud(uchar newbaud)
+{
+ int rt=FALSE;
+ uchar readbuffer[5],sendpacket[5],sendpacket2[5];
+ int sendlen=0,sendlen2=0;
+
+ // see if diffenent then current baud rate
+ if (UBaud == newbaud)
+ return TRUE;
+ else
+ {
+ // build the command packet
+ // check if correct mode
+ if (UMode != MODSEL_COMMAND)
+ {
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+ }
+ // build the command
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud;
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (!WriteCOM(sendlen,sendpacket))
+ rt = FALSE;
+ else
+ {
+ // make sure buffer is flushed
+ msDelay(5);
+
+ // change our baud rate
+ SetBaudCOM(newbaud);
+ UBaud = newbaud;
+
+ // wait for things to settle
+ msDelay(5);
+
+ // build a command packet to read back baud rate
+ sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen2,sendpacket2))
+ {
+ // read back the 1 byte response
+ if (ReadCOM(1,readbuffer) == 1)
+ {
+ // verify correct baud
+ if (((readbuffer[0] & 0x0E) == (sendpacket[sendlen-1] & 0x0E)))
+ rt = TRUE;
+ }
+ }
+ }
+ }
+
+ // if lost communication with DS2480 then reset
+ if (rt != TRUE)
+ DS2480Detect();
+
+ return UBaud;
+}
diff --git a/src/pmdas/roomtemp/mlan/linuxlnk.c b/src/pmdas/roomtemp/mlan/linuxlnk.c
new file mode 100644
index 0000000..aa20695
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/linuxlnk.c
@@ -0,0 +1,443 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// TODO.C - COM functions required by MLANLL.C, MLANTRNU, MLANNETU.C and
+// MLanFile.C for MLANU to communicate with the DS2480 based
+// Universal Serial Adapter 'U'. Fill in the platform specific code.
+//
+// Version: 1.02
+//
+// History: 1.00 -> 1.01 Added function msDelay.
+//
+// 1.01 -> 1.02 Changed to generic OpenCOM/CloseCOM for easier
+// use with other platforms.
+//
+
+//--------------------------------------------------------------------------
+// Copyright (C) 1998 Andrea Chambers and University of Newcastle upon Tyne,
+// All Rights Reserved.
+//--------------------------------------------------------------------------
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE UNIVERSITY OF NEWCASTLE UPON TYNE OR ANDREA CHAMBERS
+// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//---------------------------------------------------------------------------
+//
+// LinuxLNK.C - COM functions required by MLANLLU.C, MLANTRNU.C, MLANNETU.C
+// and MLanFile.C for MLANU to communicate with the DS2480 based
+// Universal Serial Adapter 'U'. Platform specific code.
+//
+// Version: 1.03
+// History: 1.00 -> 1.03 modifications by David Smiczek
+// Changed to use generic OpenCOM/CloseCOM
+// Pass port name to OpenCOM instead of hard coded
+// Changed msDelay to handle long delays
+// Reformatted to look like 'TODO.C'
+// Added #include "ds2480.h" to use constants.
+// Added function SetBaudCOM()
+// Added function msGettick()
+// Removed delay from WriteCOM(), used tcdrain()
+// Added wait for byte available with timeout using
+// select() in ReadCOM()
+/*
+ cfmakeraw function from nut-0.45.0 package
+ common.c - common useful functions
+
+ Copyright (C) 2000 Russell Kroll <rkroll@exploits.org>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <termios.h>
+#include <sys/time.h>
+
+#include "mlan.h"
+#include "ds2480.h"
+#include "pmapi.h"
+
+// Exportable functions required for MLANLL.C, MLANTRNU.C, or MLANNETU.C
+void FlushCOM(void);
+int WriteCOM(int, unsigned char*);
+int ReadCOM(int, unsigned char*);
+void BreakCOM(void);
+void msDelay(int);
+long msGettick(void);
+
+// Exportable functions for opening/closing serial port
+int OpenCOM(char *);
+void CloseCOM(void);
+
+// LinuxLNK global
+int fd;
+
+#ifdef IS_SOLARIS
+int cfmakeraw(struct termios *termios_p)
+{
+ termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ termios_p->c_oflag &= ~OPOST;
+ termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ termios_p->c_cflag &= ~(CSIZE|PARENB);
+ termios_p->c_cflag |= CS8;
+ return 0;
+}
+#endif
+
+//--------------------------------------------------------------------------
+// Write an array of bytes to the COM port, verify that it was
+// sent out. Assume that baud rate has been set.
+//
+// Returns 1 for success and 0 for failure
+//
+int WriteCOM(int outlen, uchar *outbuf)
+{
+ long count = outlen;
+ int i;
+ int sts;
+
+ if (MLanDebug) {
+ fprintf(stderr, "WriteCOM: calling write: %d bytes:", outlen);
+ for (i = 0; i < outlen; i++) fprintf(stderr, " %02x", 0xff & outbuf[i]);
+ fputc('\n', stderr);
+ fflush(stderr);
+ }
+
+ i = write(fd, outbuf, outlen);
+
+ if (MLanDebug) {
+ fprintf(stderr, "WriteCOM: write returns %d\nWriteCOM: calling tcdrain\n", i);
+ fflush(stderr);
+ }
+
+ sts = tcdrain(fd);
+
+ if (MLanDebug) {
+ fprintf(stderr, "WriteCOM: tcdrain returns %d\n", sts);
+ fflush(stderr);
+ }
+
+ return (i == count);
+}
+
+
+//--------------------------------------------------------------------------
+// Read an array of bytes to the COM port, verify that it was
+// sent out. Assume that baud rate has been set.
+//
+// Returns number of characters read
+//
+int ReadCOM(int inlen, uchar *inbuf)
+{
+ fd_set filedescr;
+ struct timeval tval;
+ int cnt;
+ int sts;
+
+ if (MLanDebug) {
+ fprintf(stderr, "ReadCOM: calling read: want %d bytes:", inlen);
+ fflush(stderr);
+ }
+
+ // loop to wait until each byte is available and read it
+ for (cnt = 0; cnt < inlen; cnt++)
+ {
+ // set a descriptor to wait for a character available
+ FD_ZERO(&filedescr);
+ FD_SET(fd,&filedescr);
+ // set timeout to 10ms
+ tval.tv_sec = 0;
+ tval.tv_usec = 10000;
+
+ // if byte available read or return bytes read
+ if (0 != select(fd+1,&filedescr,NULL,NULL,&tval)) {
+ if ((sts = read(fd,&inbuf[cnt],1)) != 1) {
+ if (MLanDebug) {
+ fprintf(stderr, ": read returns %d, got %d bytes\n", sts, cnt);
+ fflush(stderr);
+ }
+ return cnt;
+ }
+ if (MLanDebug) {
+ fprintf(stderr, " %02x", 0xff & inbuf[cnt]);
+ fflush(stderr);
+ }
+ }
+ else {
+ if (MLanDebug) {
+ fprintf(stderr, ": select timeout, got %d bytes\n", cnt);
+ fflush(stderr);
+ }
+ return cnt;
+ }
+
+ }
+
+ // success, so return desired length
+ if (MLanDebug) {
+ fprintf(stderr, ": got 'em all\n");
+ fflush(stderr);
+ }
+ return inlen;
+}
+
+
+//---------------------------------------------------------------------------
+// Description:
+// flush the rx and tx buffers
+//
+void FlushCOM(void)
+{
+ tcflush (fd, TCIOFLUSH);
+}
+
+
+//--------------------------------------------------------------------------
+// Description:
+// Delay for at least 'len' ms
+//
+void msDelay(int len)
+{
+ struct timespec s; // Set aside memory space on the stack
+
+ s.tv_sec = len / 1000;
+ s.tv_nsec = (len - (s.tv_sec * 1000)) * 1000000;
+ nanosleep(&s, NULL);
+}
+
+
+//--------------------------------------------------------------------------
+// Description:
+// Send a break on the com port for at least 2 ms
+//
+void BreakCOM(void)
+{
+ int duration = 0; // see man termios break may be
+ tcsendbreak(fd, duration); // too long
+}
+
+
+//---------------------------------------------------------------------------
+// Attempt to open a com port.
+// Set the starting baud rate to 9600.
+//
+// 'port_zstr' - zero terminate port name. Format is platform
+// dependent.
+//
+// Returns: TRUE - success, COM port opened
+//
+int OpenCOM(char *port_zstr)
+{
+ struct termios t; // see man termios - declared as above
+ int rc;
+
+ fd = open(port_zstr, O_RDWR|O_NONBLOCK);
+ if (fd<0) return fd;
+ rc = tcgetattr (fd, &t);
+ if (rc < 0)
+ {
+ int tmp;
+ tmp = oserror();
+ close(fd);
+ setoserror(tmp);
+ return rc;
+ }
+ if (MLanDebug) {
+ fprintf(stderr, "OpenCOM: initial tty settings\niflag: %07o oflag: %07o lflag: %07o cflag: %07o\n", (unsigned int)t.c_iflag, (unsigned int)t.c_oflag, (unsigned int)t.c_lflag, (unsigned int)t.c_cflag);
+ fflush(stderr);
+ }
+
+ cfsetospeed(&t, B9600);
+ cfsetispeed (&t, B9600);
+
+#ifdef IRIX
+// IRIX tty games ...
+//
+// per the Linux man page cfmakeraw sets the terminal attributes as follows:
+//
+ t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ t.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ t.c_oflag &= ~OPOST;
+ t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ t.c_cflag &= ~(CSIZE|PARENB);
+ t.c_cflag |= CS8;
+// to this we have to clear the additional IRIX goodies like:
+//
+ t.c_iflag &= ~(IXANY|IGNPAR);
+ t.c_oflag &= ~(TAB3);
+// and finally, CLOCAL is in c_cflag, not c_lflag
+//
+ t.c_cflag |= CLOCAL; // ignore modem signals
+#else
+// assumed to be Linux
+//
+ cfmakeraw(&t); // don't generate signals, translate or echo
+ t.c_lflag |= CLOCAL; // ignore modem signals
+#endif
+
+ if (MLanDebug) {
+ fprintf(stderr, "OpenCOM: new tty settings\niflag: %07o oflag: %07o lflag: %07o cflag: %07o\n", (unsigned int)t.c_iflag, (unsigned int)t.c_oflag, (unsigned int)t.c_lflag, (unsigned int)t.c_cflag);
+ fprintf(stderr, "OpenCOM: calling tcsetattr\n");
+ fflush(stderr);
+ }
+ rc = tcsetattr (fd, TCSAFLUSH, &t);
+ if (MLanDebug) {
+ fprintf(stderr, "OpenCOM: tcsetattr returns %d\n", rc);
+ fflush(stderr);
+ }
+ if (rc < 0)
+ {
+ int tmp;
+ tmp = oserror();
+ close(fd);
+ setoserror(tmp);
+ return rc;
+ }
+
+ return fd;
+}
+
+
+//---------------------------------------------------------------------------
+// Closes the connection to the port.
+//
+void CloseCOM(void)
+{
+ FlushCOM();
+ close(fd);
+}
+
+
+//--------------------------------------------------------------------------
+// Set the baud rate on the com port. The possible baud rates for
+// 'new_baud' are:
+//
+// PARMSET_9600 0x00
+// PARMSET_19200 0x02
+// PARMSET_57600 0x04
+// PARMSET_115200 0x06
+//
+void SetBaudCOM(int new_baud)
+{
+ struct termios t;
+ int rc;
+ speed_t baud = B0;
+
+ // read the attribute structure
+ rc = tcgetattr(fd, &t);
+ if (rc < 0)
+ {
+ close(fd);
+ return;
+ }
+
+ // convert parameter to linux baud rate
+ switch(new_baud)
+ {
+ case PARMSET_9600:
+ baud = B9600;
+ break;
+ case PARMSET_19200:
+ baud = B19200;
+ break;
+ case PARMSET_57600:
+#ifdef B57600
+ baud = B57600;
+ break;
+#else
+#define ERR_MSG_57600 "SetBaudCOM: no support for 57600 baud, sorry!"
+ write(2, ERR_MSG_57600, strlen(ERR_MSG_57600));
+ exit(1);
+#endif
+ case PARMSET_115200:
+#ifdef B115200
+ baud = B115200;
+ break;
+#else
+#define ERR_MSG_115200 "SetBaudCOM: no support for 115200 baud, sorry!"
+ write(2, ERR_MSG_115200, strlen(ERR_MSG_115200));
+ exit(1);
+#endif
+ }
+
+ // set baud in structure
+ cfsetospeed(&t, baud);
+ cfsetispeed(&t, baud);
+
+ // change baud on port
+ rc = tcsetattr(fd, TCSAFLUSH, &t);
+ if (rc < 0)
+ close(fd);
+}
+
+
+//--------------------------------------------------------------------------
+// Get the current millisecond tick count. Does not have to represent
+// an actual time, it just needs to be an incrementing timer.
+//
+long msGettick(void)
+{
+ struct timezone tmzone;
+ struct timeval tmval;
+ long ms;
+
+ gettimeofday(&tmval,&tmzone);
+ ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000;
+ return ms;
+}
+
diff --git a/src/pmdas/roomtemp/mlan/mlan.h b/src/pmdas/roomtemp/mlan/mlan.h
new file mode 100644
index 0000000..4ca742b
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/mlan.h
@@ -0,0 +1,94 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// MLan.H - Include file for MicroLAN library
+//
+// Version: 1.03
+// History: 1.02 -> 1.03 Make sure uchar is not defined twice.
+//
+
+// Typedefs
+#ifndef UCHAR
+ #define UCHAR
+ typedef unsigned char uchar;
+#endif
+#if 0
+// not needed most places - kenmcd
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+#endif
+
+// general defines
+#define WRITE_FUNCTION 1
+#define READ_FUNCTION 0
+
+// error codes
+#define READ_ERROR -1
+#define INVALID_DIR -2
+#define NO_FILE -3
+#define WRITE_ERROR -4
+#define WRONG_TYPE -5
+#define FILE_TOO_BIG -6
+
+// Misc
+#define FALSE 0
+#define TRUE 1
+
+// mode bit flags
+#define MODE_NORMAL 0x00
+#define MODE_OVERDRIVE 0x01
+#define MODE_STRONG5 0x02
+#define MODE_PROGRAM 0x04
+#define MODE_BREAK 0x08
+
+// product families
+#define TEMP_FAMILY 0x10
+#define SWITCH_FAMILY 0x12
+#define COUNT_FAMILY 0x1D
+#define DIR_FAMILY 0x01
+
+// externs
+extern uchar DOWCRC;
+
+// debugging
+extern int MLanDebug;
+
+// function prototypes
+extern int Aquire1WireNet(char *, char *);
+extern void Release1WireNet(char *);
+extern int MLanAccess(void);
+extern int MLanBlock(int DoReset, uchar *TransferBuffer, int TransferLen);
+extern void MLanFamilySearchSetup(int SearchFamily);
+extern int MLanLevel(int NewLevel);
+extern int MLanNext(int DoReset, int OnlyAlarmingDevices);
+extern void MLanSerialNum(uchar *SerialNumBuf, int DoRead);
+extern int MLanTouchByte(int sendbyte);
+extern int MLanVerify(int OnlyAlarmingDevices);
+extern uchar dowcrc(uchar x);
+extern void msDelay(int len);
+extern int DS2480ChangeBaud(uchar newbaud);
+extern void SetBaudCOM(int new_baud);
+
diff --git a/src/pmdas/roomtemp/mlan/mlanllu.c b/src/pmdas/roomtemp/mlan/mlanllu.c
new file mode 100644
index 0000000..91b23f0
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/mlanllu.c
@@ -0,0 +1,499 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// MLanLLU.C - Link Layer MicroLAN functions using the DS2480 (U)
+// serial interface chip.
+//
+// Version: 1.03
+//
+// History: 1.00 -> 1.01 DS2480 version number now ignored in
+// MLanTouchReset.
+// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
+// Removed #include <windows.h>
+// Add #include "mlan.h" to define TRUE,FALSE
+
+#include "ds2480.h"
+#include "mlan.h"
+
+// external COM functions required
+extern void FlushCOM(void);
+extern int WriteCOM(int, uchar *);
+extern int ReadCOM(int, uchar *);
+//extern void SetBaudCOM(int);
+
+// external DS2480 utility function
+extern int DS2480Detect(void);
+//extern int DS2480ChangeBaud(int);
+
+// local functions
+int MLanTouchReset(void);
+int MLanTouchBit(int sendbit);
+int MLanTouchByte(int sendbyte);
+int MLanWriteByte(int sendbyte);
+int MLanReadByte(void);
+int MLanSpeed(int);
+int MLanLevel(int);
+int MLanProgramPulse(void);
+
+// external globals
+extern int UMode; // current DS2480 command or data mode state
+extern int UBaud; // current DS2480 baud rate
+extern int USpeed; // current DS2480 MicroLAN communication speed
+extern int ULevel; // current DS2480 MicroLAN level
+
+// local varable flag, true if program voltage available
+static int ProgramAvailable=FALSE;
+
+
+//--------------------------------------------------------------------------
+// Reset all of the devices on the MicroLAN and return the result.
+//
+// Returns: TRUE(1): presense pulse(s) detected, device(s) reset
+// FALSE(0): no presense pulses detected
+//
+// WARNING: This routine will not function correctly on some
+// Alarm reset types of the DS1994/DS1427/DS2404 with
+// Rev 1 and 2 of the DS2480.
+//
+int MLanTouchReset(void)
+{
+ uchar readbuffer[10],sendpacket[10];
+ int sendlen=0;
+
+ // make sure normal level
+ MLanLevel(MODE_NORMAL);
+
+ // check if correct mode
+ if (UMode != MODSEL_COMMAND)
+ {
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+ }
+
+ // construct the command
+ sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_RESET | USpeed);
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the 1 byte response
+ if (ReadCOM(1,readbuffer) == 1)
+ {
+ // make sure this byte looks like a reset byte
+ if (((readbuffer[0] & RB_RESET_MASK) == RB_PRESENCE) ||
+ ((readbuffer[0] & RB_RESET_MASK) == RB_ALARMPRESENCE))
+ {
+ // check if programming voltage available
+ ProgramAvailable = ((readbuffer[0] & 0x20) == 0x20);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Send 1 bit of communication to the MicroLAN and return the
+// result 1 bit read from the MicroLAN. The parameter 'sendbit'
+// least significant bit is used and the least significant bit
+// of the result is the return bit.
+//
+// 'sendbit' - the least significant bit is the bit to send
+//
+// Returns: 0: 0 bit read from sendbit
+// 1: 1 bit read from sendbit
+//
+int MLanTouchBit(int sendbit)
+{
+ uchar readbuffer[10],sendpacket[10];
+ int sendlen=0;
+
+ // make sure normal level
+ MLanLevel(MODE_NORMAL);
+
+ // check if correct mode
+ if (UMode != MODSEL_COMMAND)
+ {
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+ }
+
+ // construct the command
+ sendpacket[sendlen] = (sendbit != 0) ? BITPOL_ONE : BITPOL_ZERO;
+ sendpacket[sendlen++] |= CMD_COMM | FUNCTSEL_BIT | USpeed;
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the response
+ if (ReadCOM(1,readbuffer) == 1)
+ {
+ // interpret the response
+ if (((readbuffer[0] & 0xE0) == 0x80) &&
+ ((readbuffer[0] & RB_BIT_MASK) == RB_BIT_ONE))
+ return 1;
+ else
+ return 0;
+ }
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ return 0;
+}
+
+
+//--------------------------------------------------------------------------
+// Send 8 bits of communication to the MicroLAN and verify that the
+// 8 bits read from the MicroLAN is the same (write operation).
+// The parameter 'sendbyte' least significant 8 bits are used.
+//
+// 'sendbyte' - 8 bits to send (least significant byte)
+//
+// Returns: TRUE: bytes written and echo was the same
+// FALSE: echo was not the same
+//
+int MLanWriteByte(int sendbyte)
+{
+ return (MLanTouchByte(sendbyte) == sendbyte) ? TRUE : FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Send 8 bits of read communication to the MicroLAN and and return the
+// result 8 bits read from the MicroLAN.
+//
+// Returns: 8 bytes read from MicroLAN
+//
+int MLanReadByte(void)
+{
+ return MLanTouchByte(0xFF);
+}
+
+
+//--------------------------------------------------------------------------
+// Send 8 bits of communication to the MicroLAN and return the
+// result 8 bits read from the MicroLAN. The parameter 'sendbyte'
+// least significant 8 bits are used and the least significant 8 bits
+// of the result is the return byte.
+//
+// 'sendbyte' - 8 bits to send (least significant byte)
+//
+// Returns: 8 bytes read from sendbyte
+//
+int MLanTouchByte(int sendbyte)
+{
+ uchar readbuffer[10],sendpacket[10];
+ int sendlen=0;
+
+ // make sure normal level
+ MLanLevel(MODE_NORMAL);
+
+ // check if correct mode
+ if (UMode != MODSEL_DATA)
+ {
+ UMode = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+ }
+
+ // add the byte to send
+ sendpacket[sendlen++] = (uchar)sendbyte;
+
+ // check for duplication of data that looks like COMMAND mode
+ if (sendbyte == MODE_COMMAND)
+ sendpacket[sendlen++] = (uchar)sendbyte;
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the 1 byte response
+ if (ReadCOM(1,readbuffer) == 1)
+ {
+ // return the response
+ return (int)readbuffer[0];
+ }
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ return 0;
+}
+
+
+//--------------------------------------------------------------------------
+// Set the MicroLAN communucation speed.
+//
+// 'NewSpeed' - new speed defined as
+// MODE_NORMAL 0x00
+// MODE_OVERDRIVE 0x01
+//
+// Returns: current MicroLAN speed
+//
+int MLanSpeed(int NewSpeed)
+{
+ uchar sendpacket[5];
+ short sendlen=0;
+ int rt = FALSE;
+
+ // check if change from current mode
+ if (((NewSpeed == MODE_OVERDRIVE) &&
+ (USpeed != SPEEDSEL_OD)) ||
+ ((NewSpeed == MODE_NORMAL) &&
+ (USpeed != SPEEDSEL_FLEX)))
+ {
+ if (NewSpeed == MODE_OVERDRIVE)
+ {
+ // if overdrive then switch to 115200 baud
+ if (DS2480ChangeBaud(PARMSET_57600) == PARMSET_57600)
+ {
+ USpeed = SPEEDSEL_OD;
+ rt = TRUE;
+ }
+ }
+ else if (NewSpeed == MODE_NORMAL)
+ {
+ // else normal so set to 9600 baud
+ if (DS2480ChangeBaud(PARMSET_9600) == PARMSET_9600)
+ {
+ USpeed = SPEEDSEL_FLEX;
+ rt = TRUE;
+ }
+ }
+
+ // if baud rate is set correctly then change DS2480 speed
+ if (rt)
+ {
+ // check if correct mode
+ if (UMode != MODSEL_COMMAND)
+ {
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+ }
+
+ // proceed to set the DS2480 communication speed
+ sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed;
+
+ // send the packet
+ if (!WriteCOM(sendlen,sendpacket))
+ {
+ rt = FALSE;
+ // lost communication with DS2480 then reset
+ DS2480Detect();
+ }
+ }
+ }
+
+ // return the current speed
+ return (USpeed == SPEEDSEL_OD) ? MODE_OVERDRIVE : MODE_NORMAL;
+}
+
+
+//--------------------------------------------------------------------------
+// Set the MicroLAN line level. The values for NewLevel are
+// as follows:
+//
+// 'NewLevel' - new level defined as
+// MODE_NORMAL 0x00
+// MODE_STRONG5 0x02
+// MODE_PROGRAM 0x04
+// MODE_BREAK 0x08 (not supported)
+//
+// Returns: current MicroLAN level
+//
+int MLanLevel(int NewLevel)
+{
+ uchar sendpacket[10],readbuffer[10];
+ short sendlen=0;
+ short rt=FALSE;
+
+ // check if need to change level
+ if (NewLevel != ULevel)
+ {
+ // check if just putting back to normal
+ if (NewLevel == MODE_NORMAL)
+ {
+ // check if correct mode
+ if (UMode != MODSEL_COMMAND)
+ {
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+ }
+
+ // stop pulse command
+ sendpacket[sendlen++] = MODE_STOP_PULSE;
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the 1 byte response
+ if (ReadCOM(1,readbuffer) == 1)
+ {
+ // check response byte
+ if ((readbuffer[0] & 0xE0) == 0xE0)
+ {
+ rt = TRUE;
+ ULevel = MODE_NORMAL;
+ }
+ }
+ }
+ }
+ // set new level
+ else
+ {
+ // check if correct mode
+ if (UMode != MODSEL_COMMAND)
+ {
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+ }
+
+ // strong 5 volts
+ if (NewLevel == MODE_STRONG5)
+ {
+ // set the SPUD time value
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite;
+ // add the command to begin the pulse
+ sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V;
+ }
+ // 12 volts
+ else if (NewLevel == MODE_PROGRAM)
+ {
+ // check if programming voltage available
+ if (!ProgramAvailable)
+ return MODE_NORMAL;
+
+ // set the PPD time value
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_infinite;
+ // add the command to begin the pulse
+ sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_12V;
+ }
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the 1 byte response from setting time limit
+ if (ReadCOM(1,readbuffer) == 1)
+ {
+ // check response byte
+ if ((readbuffer[0] & 0x81) == 0)
+ {
+ ULevel = NewLevel;
+ rt = TRUE;
+ }
+ }
+ }
+ }
+
+ // if lost communication with DS2480 then reset
+ if (rt != TRUE)
+ DS2480Detect();
+ }
+
+ // return the current level
+ return ULevel;
+}
+
+
+//--------------------------------------------------------------------------
+// This procedure creates a fixed 480 microseconds 12 volt pulse
+// on the MicroLAN for programming EPROM iButtons.
+//
+// Returns: TRUE successful
+// FALSE program voltage not available
+//
+int MLanProgramPulse(void)
+{
+ uchar sendpacket[10],readbuffer[10];
+ short sendlen=0;
+
+ // check if programming voltage available
+ if (!ProgramAvailable)
+ return FALSE;
+
+ // make sure normal level
+ MLanLevel(MODE_NORMAL);
+
+ // check if correct mode
+ if (UMode != MODSEL_COMMAND)
+ {
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+ }
+
+ // set the SPUD time value
+ sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us;
+
+ // pulse command
+ sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE;
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the 2 byte response
+ if (ReadCOM(2,readbuffer) == 2)
+ {
+ // check response byte
+ if (((readbuffer[0] | CMD_CONFIG) ==
+ (CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us)) &&
+ ((readbuffer[1] & 0xFC) ==
+ (0xFC & (CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE))))
+ return TRUE;
+ }
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ return FALSE;
+}
+
diff --git a/src/pmdas/roomtemp/mlan/mlannetu.c b/src/pmdas/roomtemp/mlan/mlannetu.c
new file mode 100644
index 0000000..88ddbbd
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/mlannetu.c
@@ -0,0 +1,599 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// MLanNetU.C - Network functions for MicroLAN 1-Wire devices
+// using the DS2480 (U) serial interface chip.
+//
+// Version: 1.03
+//
+// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
+//
+
+#include "ds2480.h"
+#include "mlan.h"
+
+// external MicroLAN functions required
+extern int MLanTouchReset(void);
+extern int MLanTouchBit(int);
+extern int MLanWriteByte(int sendbyte);
+extern int MLanReadByte(void);
+extern int MLanSpeed(int);
+extern int MLanLevel(int);
+extern int MLanBlock(int, uchar *, int);
+
+// external COM functions required
+extern void FlushCOM(void);
+extern int WriteCOM(int, uchar *);
+extern int ReadCOM(int, uchar *);
+
+// external DS2480 utility function
+extern int DS2480Detect(void);
+
+// exportable functions
+int MLanFirst(int,int);
+int MLanNext(int,int);
+void MLanSerialNum(uchar *, int);
+void MLanFamilySearchSetup(int);
+void MLanSkipFamily(void);
+int MLanAccess(void);
+int MLanVerify(int);
+int MLanOverdriveAccess(void);
+
+// local functions
+int bitacc(int, int, int, uchar *);
+uchar dowcrc(uchar);
+
+// global variables for this module to hold search state information
+static int LastDiscrepancy;
+static int LastFamilyDiscrepancy;
+static int LastDevice;
+uchar DOWCRC;
+uchar SerialNum[8];
+
+// external globals
+extern int UMode;
+extern int UBaud;
+extern int USpeed;
+
+//--------------------------------------------------------------------------
+// The 'MLanFirst' finds the first device on the MicroLAN This function
+// contains one parameter 'OnlyAlarmingDevices'. When
+// 'OnlyAlarmingDevices' is TRUE (1) the find alarm command 0xEC is
+// sent instead of the normal search command 0xF0.
+// Using the find alarm command 0xEC will limit the search to only
+// 1-Wire devices that are in an 'alarm' state.
+//
+// 'DoReset' - TRUE (1) perform reset before search, FALSE (0) do not
+// perform reset before search.
+// 'OnlyAlarmDevices' - TRUE (1) the find alarm command 0xEC is
+// sent instead of the normal search command 0xF0
+//
+// Returns: TRUE (1) : when a 1-Wire device was found and it's
+// Serial Number placed in the global SerialNum
+// FALSE (0): There are no devices on the MicroLAN.
+//
+int MLanFirst(int DoReset, int OnlyAlarmingDevices)
+{
+ // reset the search state
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+
+ return MLanNext(DoReset, OnlyAlarmingDevices);
+}
+
+//--------------------------------------------------------------------------
+// The 'MLanNext' function does a general search. This function
+// continues from the previos search state. The search state
+// can be reset by using the 'MLanFirst' function.
+// This function contains one parameter 'OnlyAlarmingDevices'.
+// When 'OnlyAlarmingDevices' is TRUE (1) the find alarm command
+// 0xEC is sent instead of the normal search command 0xF0.
+// Using the find alarm command 0xEC will limit the search to only
+// 1-Wire devices that are in an 'alarm' state.
+//
+// 'DoReset' - TRUE (1) perform reset before search, FALSE (0) do not
+// perform reset before search.
+// 'OnlyAlarmDevices' - TRUE (1) the find alarm command 0xEC is
+// sent instead of the normal search command 0xF0
+//
+// Returns: TRUE (1) : when a 1-Wire device was found and it's
+// Serial Number placed in the global SerialNum
+// FALSE (0): when no new device was found. Either the
+// last search was the last device or there
+// are no devices on the MicroLAN.
+//
+int MLanNext(int DoReset, int OnlyAlarmingDevices)
+{
+ int i,TempLastDescrepancy,pos;
+ uchar TempSerialNum[8];
+ uchar readbuffer[20],sendpacket[40];
+ int sendlen=0;
+
+ // if the last call was the last one
+ if (LastDevice)
+ {
+ // reset the search
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+ return FALSE;
+ }
+
+ // check if reset first is requested
+ if (DoReset)
+ {
+ // reset the 1-wire
+ // if there are no parts on 1-wire, return FALSE
+ if (!MLanTouchReset())
+ {
+ // reset the search
+ LastDiscrepancy = 0;
+ LastFamilyDiscrepancy = 0;
+ return FALSE;
+ }
+ }
+
+ // build the command stream
+ // call a function that may add the change mode command to the buff
+ // check if correct mode
+ if (UMode != MODSEL_DATA)
+ {
+ UMode = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+ }
+
+ // search command
+ if (OnlyAlarmingDevices)
+ sendpacket[sendlen++] = 0xEC; // issue the alarming search command
+ else
+ sendpacket[sendlen++] = 0xF0; // issue the search command
+
+ // change back to command mode
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+
+ // search mode on
+ sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHON | USpeed);
+
+ // change back to data mode
+ UMode = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+
+ // set the temp Last Descrep to none
+ TempLastDescrepancy = 0xFF;
+
+ // add the 16 bytes of the search
+ pos = sendlen;
+ for (i = 0; i < 16; i++)
+ sendpacket[sendlen++] = 0;
+
+ // only modify bits if not the first search
+ if (LastDiscrepancy != 0xFF)
+ {
+ // set the bits in the added buffer
+ for (i = 0; i < 64; i++)
+ {
+ // before last discrepancy
+ if (i < (LastDiscrepancy - 1))
+ bitacc(WRITE_FUNCTION,
+ bitacc(READ_FUNCTION,0,i,&SerialNum[0]),
+ (short)(i * 2 + 1),
+ &sendpacket[pos]);
+ // at last discrepancy
+ else if (i == (LastDiscrepancy - 1))
+ bitacc(WRITE_FUNCTION,1,
+ (short)(i * 2 + 1),
+ &sendpacket[pos]);
+ // after last discrepancy so leave zeros
+ }
+ }
+
+ // change back to command mode
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+
+ // search OFF
+ sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed);
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the 1 byte response
+ if (ReadCOM(17,readbuffer) == 17)
+ {
+ // interpret the bit stream
+ for (i = 0; i < 64; i++)
+ {
+ // get the SerialNum bit
+ bitacc(WRITE_FUNCTION,
+ bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]),
+ i,
+ &TempSerialNum[0]);
+ // check LastDiscrepancy
+ if ((bitacc(READ_FUNCTION,0,(short)(i * 2),&readbuffer[1]) == 1) &&
+ (bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]) == 0))
+ {
+ TempLastDescrepancy = i + 1;
+ // check LastFamilyDiscrepancy
+ if (i < 8)
+ LastFamilyDiscrepancy = i + 1;
+ }
+ }
+
+ // do dowcrc
+ DOWCRC = 0;
+ for (i = 0; i < 8; i++)
+ dowcrc(TempSerialNum[i]);
+
+ // check results
+ if ((DOWCRC != 0) || (LastDiscrepancy == 63) || (TempSerialNum[0] == 0))
+ {
+ // error during search
+ // reset the search
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+ return FALSE;
+ }
+ // successful search
+ else
+ {
+ // check for lastone
+ if ((TempLastDescrepancy == LastDiscrepancy) || (TempLastDescrepancy == 0xFF))
+ LastDevice = TRUE;
+
+ // copy the SerialNum to the buffer
+ for (i = 0; i < 8; i++)
+ SerialNum[i] = TempSerialNum[i];
+
+ // set the count
+ LastDiscrepancy = TempLastDescrepancy;
+ return TRUE;
+ }
+ }
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ // reset the search
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// The 'MLanSerialNum' function either reads or sets the SerialNum buffer
+// that is used in the search functions 'MLanFirst' and 'MLanNext'.
+// This function contains two parameters, 'SerialNumBuf' is a pointer
+// to a buffer provided by the caller. 'SerialNumBuf' should point to
+// an array of 8 unsigned chars. The second parameter is a flag called
+// 'DoRead' that is TRUE (1) if the operation is to read and FALSE
+// (0) if the operation is to set the internal SerialNum buffer from
+// the data in the provided buffer.
+//
+// 'SerialNumBuf' - buffer to that contains the serial number to set
+// when DoRead = FALSE (0) and buffer to get the serial
+// number when DoRead = TRUE (1).
+// 'DoRead' - flag to indicate reading (1) or setting (0) the current
+// serial number.
+//
+void MLanSerialNum(uchar *SerialNumBuf, int DoRead)
+{
+ int i;
+
+ // read the internal buffer and place in 'SerialNumBuf'
+ if (DoRead)
+ {
+ for (i = 0; i < 8; i++)
+ SerialNumBuf[i] = SerialNum[i];
+ }
+ // set the internal buffer from the data in 'SerialNumBuf'
+ else
+ {
+ for (i = 0; i < 8; i++)
+ SerialNum[i] = SerialNumBuf[i];
+ }
+}
+
+
+//--------------------------------------------------------------------------
+// Setup the search algorithm to find a certain family of devices
+// the next time a search function is called 'MLanNext'.
+//
+// 'SearchFamily' - family code type to set the search algorithm to find
+// next.
+//
+void MLanFamilySearchSetup(int SearchFamily)
+{
+ int i;
+
+ // set the search state to find SearchFamily type devices
+ SerialNum[0] = (uchar)SearchFamily;
+ for (i = 1; i < 8; i++)
+ SerialNum[i] = 0;
+ LastDiscrepancy = 64;
+ LastDevice = FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Set the current search state to skip the current family code.
+//
+void MLanSkipFamily(void)
+{
+ // set the Last discrepancy to last family discrepancy
+ LastDiscrepancy = LastFamilyDiscrepancy;
+
+ // check for end of list
+ if (LastDiscrepancy == 0)
+ LastDevice = TRUE;
+}
+
+
+//--------------------------------------------------------------------------
+// The 'MLanAccess' function resets the 1-Wire and sends a MATCH Serial
+// Number command followed by the current SerialNum code. After this
+// function is complete the 1-Wire device is ready to accept device-specific
+// commands.
+//
+// Returns: TRUE (1) : reset indicates present and device is ready
+// for commands.
+// FALSE (0): reset does not indicate presence or echos 'writes'
+// are not correct.
+//
+int MLanAccess(void)
+{
+ uchar TranBuf[9];
+ int i;
+
+ // reset the 1-wire
+ if (MLanTouchReset())
+ {
+ // create a buffer to use with block function
+ // match Serial Number command 0x55
+ TranBuf[0] = 0x55;
+ // Serial Number
+ for (i = 1; i < 9; i++)
+ TranBuf[i] = SerialNum[i-1];
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(FALSE,TranBuf,9))
+ {
+ // verify that the echo of the writes was correct
+ for (i = 1; i < 9; i++)
+ if (TranBuf[i] != SerialNum[i-1])
+ return FALSE;
+ if (TranBuf[0] != 0x55)
+ return FALSE;
+ else
+ return TRUE;
+ }
+ }
+
+ // reset or match echo failed
+ return FALSE;
+}
+
+
+//----------------------------------------------------------------------
+// The function 'MLanVerify' verifies that the current device
+// is in contact with the MicroLAN.
+// Using the find alarm command 0xEC will verify that the device
+// is in contact with the MicroLAN and is in an 'alarm' state.
+//
+// 'OnlyAlarmingDevices' - TRUE (1) the find alarm command 0xEC
+// is sent instead of the normal search
+// command 0xF0.
+//
+// Returns: TRUE (1) : when the 1-Wire device was verified
+// to be on the MicroLAN
+// with OnlyAlarmingDevices == FALSE
+// or verified to be on the MicroLAN
+// AND in an alarm state when
+// OnlyAlarmingDevices == TRUE.
+// FALSE (0): the 1-Wire device was not on the
+// MicroLAN or if OnlyAlarmingDevices
+// == TRUE, the device may be on the
+// MicroLAN but in a non-alarm state.
+//
+int MLanVerify(int OnlyAlarmingDevices)
+{
+ int i,TranCnt=0,goodbits=0,cnt=0,s,tst;
+ uchar TranBuf[50];
+
+ // construct the search rom
+ if (OnlyAlarmingDevices)
+ TranBuf[TranCnt++] = 0xEC; // issue the alarming search command
+ else
+ TranBuf[TranCnt++] = 0xF0; // issue the search command
+ // set all bits at first
+ for (i = 1; i <= 24; i++)
+ TranBuf[TranCnt++] = 0xFF;
+ // now set or clear apropriate bits for search
+ for (i = 0; i < 64; i++)
+ bitacc(WRITE_FUNCTION,bitacc(READ_FUNCTION,0,i,&SerialNum[0]),(int)((i+1)*3-1),&TranBuf[1]);
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // check results to see if it was a success
+ for (i = 0; i < 192; i += 3)
+ {
+ tst = (bitacc(READ_FUNCTION,0,i,&TranBuf[1]) << 1) |
+ bitacc(READ_FUNCTION,0,(int)(i+1),&TranBuf[1]);
+
+ s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[0]);
+
+ if (tst == 0x03) // no device on line
+ {
+ goodbits = 0; // number of good bits set to zero
+ break; // quit
+ }
+
+ if (((s == 0x01) && (tst == 0x02)) ||
+ ((s == 0x00) && (tst == 0x01)) ) // correct bit
+ goodbits++; // count as a good bit
+ }
+
+ // check too see if there were enough good bits to be successful
+ if (goodbits >= 8)
+ return TRUE;
+ }
+
+ // block fail or device not present
+ return FALSE;
+}
+
+
+//----------------------------------------------------------------------
+// Perform a overdrive MATCH command to select the 1-Wire device with
+// the address in the ID data register.
+//
+// Returns: TRUE: If the device is present on the MicroLAN and
+// can do overdrive then the device is selected.
+// FALSE: Device is not present or not capable of overdrive.
+//
+// *Note: This function could be converted to send DS2480
+// commands in one packet.
+//
+int MLanOverdriveAccess(void)
+{
+ uchar TranBuf[8];
+ int i, EchoBad = FALSE;
+
+ // make sure normal level
+ MLanLevel(MODE_NORMAL);
+
+ // force to normal communication speed
+ MLanSpeed(MODE_NORMAL);
+
+ // call the MicroLAN reset function
+ if (MLanTouchReset())
+ {
+ // send the match command 0x69
+ if (MLanWriteByte(0x69))
+ {
+ // switch to overdrive communication speed
+ MLanSpeed(MODE_OVERDRIVE);
+
+ // create a buffer to use with block function
+ // Serial Number
+ for (i = 0; i < 8; i++)
+ TranBuf[i] = SerialNum[i];
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(FALSE,TranBuf,8))
+ {
+ // verify that the echo of the writes was correct
+ for (i = 0; i < 8; i++)
+ if (TranBuf[i] != SerialNum[i])
+ EchoBad = TRUE;
+ // if echo ok then success
+ if (!EchoBad)
+ return TRUE;
+ }
+ }
+ }
+
+ // failure, force back to normal communication speed
+ MLanSpeed(MODE_NORMAL);
+
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Update the Dallas Semiconductor One Wire CRC (DOWCRC) from the global
+// variable DOWCRC and the argument.
+//
+// 'x' - data byte to calculate the 8 bit crc from
+//
+// Returns: the updated DOWCRC.
+//
+uchar dscrc_table[] = {
+ 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
+ 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
+ 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
+ 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
+ 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
+ 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
+ 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
+ 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
+ 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
+ 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
+ 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
+ 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
+ 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
+ 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
+ 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
+ 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
+
+uchar dowcrc(uchar x)
+{
+ DOWCRC = dscrc_table[DOWCRC ^ x];
+ return DOWCRC;
+}
+
+
+//--------------------------------------------------------------------------
+// Bit utility to read and write a bit in the buffer 'buf'.
+//
+// 'op' - operation (1) to set and (0) to read
+// 'state' - set (1) or clear (0) if operation is write (1)
+// 'loc' - bit number location to read or write
+// 'buf' - pointer to array of bytes that contains the bit
+// to read or write
+//
+// Returns: 1 if operation is set (1)
+// 0/1 state of bit number 'loc' if operation is reading
+//
+int bitacc(int op, int state, int loc, uchar *buf)
+{
+ int nbyt,nbit;
+
+ nbyt = (loc / 8);
+ nbit = loc - (nbyt * 8);
+
+ if (op == WRITE_FUNCTION)
+ {
+ if (state)
+ buf[nbyt] |= (0x01 << nbit);
+ else
+ buf[nbyt] &= ~(0x01 << nbit);
+
+ return 1;
+ }
+ else
+ return ((buf[nbyt] >> nbit) & 0x01);
+}
diff --git a/src/pmdas/roomtemp/mlan/mlansesu.c b/src/pmdas/roomtemp/mlan/mlansesu.c
new file mode 100644
index 0000000..b46c349
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/mlansesu.c
@@ -0,0 +1,102 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// MLanSesU.C - Aquire and release a Session on the 1-Wire Net.
+//
+// Version: 1.03
+//
+
+#include "pmapi.h"
+#include "mlan.h"
+
+// external function prototypes
+extern int OpenCOM(char *);
+extern void CloseCOM(void);
+extern int DS2480Detect(void);
+
+// local function prototypes
+int Aquire1WireNet(char *, char *);
+void Release1WireNet(char *);
+
+// keep port name for later message when closing
+char portname[128];
+
+// debugging
+int MLanDebug = 0;
+
+//---------------------------------------------------------------------------
+// Attempt to aquire a 1-Wire net using a com port and a DS2480 based
+// adapter.
+//
+// 'port_zstr' - zero terminated port name. For this platform
+// use format COMX where X is the port number.
+// 'return_msg' - zero terminated return message.
+//
+// Returns: TRUE - success, COM port opened
+//
+int Aquire1WireNet(char *port_zstr, char *return_msg)
+{
+ int cnt=0;
+ portname[0] = 0;
+
+ // attempt to open the communications port
+ if (OpenCOM(port_zstr) >= 0)
+ cnt += sprintf(&return_msg[cnt],"%s opened\n",port_zstr);
+ else
+ {
+ cnt += sprintf(&return_msg[cnt],"Could not open port %s: %s,"
+ " aborting.\nClosing port %s.\n",port_zstr,osstrerror(),port_zstr);
+ return FALSE;
+ }
+
+ // detect DS2480
+ if (DS2480Detect())
+ cnt += sprintf(&return_msg[cnt],"DS2480-based adapter detected\n");
+ else
+ {
+ cnt += sprintf(&return_msg[cnt],"DS2480-based adapter not detected, aborting program\n");
+ cnt += sprintf(&return_msg[cnt],"Closing port %s.\n",port_zstr);
+ CloseCOM();
+ return FALSE;
+ }
+
+ // success
+ sprintf(portname,"%s",port_zstr);
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------
+// Release the previously aquired a 1-Wire net.
+//
+// 'return_msg' - zero terminated return message.
+//
+void Release1WireNet(char *return_msg)
+{
+ // close the communications port
+ sprintf(return_msg,"Closing port %s.\n",portname);
+ CloseCOM();
+}
diff --git a/src/pmdas/roomtemp/mlan/mlantrnu.c b/src/pmdas/roomtemp/mlan/mlantrnu.c
new file mode 100644
index 0000000..5a0b376
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/mlantrnu.c
@@ -0,0 +1,579 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// MLanTranU.C - Transport functions for MicroLAN 1-Wire devices
+// using the DS2480 (U) serial interface chip.
+//
+// Version: 1.03
+//
+// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
+//
+
+#include "ds2480.h"
+#include "mlan.h"
+
+// external low-level functions required
+extern int MLanTouchReset(void);
+extern int MLanWriteByte(int);
+extern int MLanReadByte(void);
+extern int MLanProgramPulse(void);
+
+// external network-level functions required
+extern int MLanAccess();
+
+// external COM functions required
+extern void FlushCOM(void);
+extern int WriteCOM(int, uchar *);
+extern int ReadCOM(int, uchar *);
+
+// other external functions
+extern int DS2480Detect(void);
+extern uchar dowcrc(uchar);
+
+// external globals
+extern int UMode;
+extern int UBaud;
+extern int USpeed;
+extern uchar SerialNum[8];
+extern uchar DOWCRC;
+
+// local exportable functions
+int MLanBlock(int, uchar *, int);
+int MLanReadPacketStd(int, int, uchar *);
+int MLanWritePacketStd(int, uchar *, int, int, int);
+int MLanProgramByte(int, int, int, int, int);
+
+// local functions
+static int Write_Scratchpad(uchar *, int, int);
+static int Copy_Scratchpad(int, int);
+unsigned short crc16(int);
+
+// global variable
+unsigned short CRC16;
+
+
+//--------------------------------------------------------------------------
+// The 'MLanBlock' transfers a block of data to and from the
+// MicroLAN with an optional reset at the begining of communication.
+// The result is returned in the same buffer.
+//
+// 'DoReset' - cause a MLanTouchReset to occure at the begining of
+// communication TRUE(1) or not FALSE(0)
+// 'TransferBuffer' - pointer to a block of unsigned
+// chars of length 'TranferLength' that will be sent
+// to the MicroLAN
+// 'TranferLength' - length in bytes to transfer
+
+// Supported devices: all
+//
+// Returns: TRUE (1) : The optional reset returned a valid
+// presence (DoReset == TRUE) or there
+// was no reset required.
+// FALSE (0): The reset did not return a valid prsence
+// (DoReset == TRUE).
+//
+// The maximum TransferLength is 64
+//
+int MLanBlock(int DoReset, uchar *TransferBuffer, int TransferLen)
+{
+ uchar sendpacket[150];
+ int sendlen=0,i;
+
+ // check for a block too big
+ if (TransferLen > 64)
+ return FALSE;
+
+ // check if need to do a MLanTouchReset first
+ if (DoReset)
+ {
+ if (!MLanTouchReset())
+ return FALSE;
+ }
+
+ // construct the packet to send to the DS2480
+ // check if correct mode
+ if (UMode != MODSEL_DATA)
+ {
+ UMode = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+ }
+
+ // add the bytes to send
+ for (i = 0; i < TransferLen; i++)
+ {
+ sendpacket[sendlen++] = TransferBuffer[i];
+
+ // check for duplication of data that looks like COMMAND mode
+ if (TransferBuffer[i] == MODE_COMMAND)
+ sendpacket[sendlen++] = TransferBuffer[i];
+ }
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the response
+ if (ReadCOM(TransferLen,TransferBuffer) == TransferLen)
+ return TRUE;
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Read a Universal Data Packet from a standard NVRAM iButton
+// and return it in the provided buffer. The page that the
+// packet resides on is 'StartPage'. Note that this function is limited
+// to single page packets. The buffer 'ReadBuffer' must be at least
+// 29 bytes long.
+//
+// The Universal Data Packet always start on page boundaries but
+// can end anywhere. The length is the number of data bytes not
+// including the length byte and the CRC16 bytes. There is one
+// length byte. The CRC16 is first initialized to the starting
+// page number. This provides a check to verify the page that
+// was intended is being read. The CRC16 is then calculated over
+// the length and data bytes. The CRC16 is then inverted and stored
+// low byte first followed by the high byte.
+//
+// Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982,
+// DS1985, DS1986, DS2407, and DS1971.
+//
+// 'DoAccess' - flag to indicate if an 'MLanAccess' should be
+// peformed at the begining of the read. This may
+// be FALSE (0) if the previous call was to read the
+// previous page (StartPage-1).
+// 'StartPage' - page number to start the read from
+// 'ReadBuffer' - pointer to a location to store the data read
+//
+// Returns: >=0 success, number of data bytes in the buffer
+// -1 failed to read a valid UDP
+//
+//
+int MLanReadPacketStd(int DoAccess, int StartPage, uchar *ReadBuffer)
+{
+ int i,length,TranCnt=0,HeadLen=0;
+ uchar TranBuf[50];
+
+ // check if access header is done
+ // (only use if in sequention read with one access at begining)
+ if (DoAccess)
+ {
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // read memory command
+ TranBuf[TranCnt++] = 0xF0;
+ // write the target address
+ TranBuf[TranCnt++] = ((StartPage << 5) & 0xFF);
+ TranBuf[TranCnt++] = (StartPage >> 3);
+ // check for DS1982 exception (redirection byte)
+ if (SerialNum[0] == 0x09)
+ TranBuf[TranCnt++] = 0xFF;
+ // record the header length
+ HeadLen = TranCnt;
+ }
+ // read the entire page length byte
+ for (i = 0; i < 32; i++)
+ TranBuf[TranCnt++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(DoAccess,TranBuf,TranCnt))
+ {
+ // seed crc with page number
+ CRC16 = StartPage;
+
+ // attempt to read UDP from TranBuf
+ length = TranBuf[HeadLen];
+ crc16(length);
+
+ // verify length is not too large
+ if (length <= 29)
+ {
+ // loop to read packet including CRC
+ for (i = 0; i < length; i++)
+ {
+ ReadBuffer[i] = TranBuf[i+1+HeadLen];
+ crc16(ReadBuffer[i]);
+ }
+
+ // read and compute the CRC16
+ crc16(TranBuf[i+1+HeadLen]);
+ crc16(TranBuf[i+2+HeadLen]);
+
+ // verify the CRC16 is correct
+ if (CRC16 == 0xB001)
+ return length; // return number of byte in record
+ }
+ }
+
+ // failed block or incorrect CRC
+ return -1;
+}
+
+
+//--------------------------------------------------------------------------
+// Write a Universal Data Packet onto a standard NVRAM 1-Wire device
+// on page 'StartPage'. This function is limited to UDPs that
+// fit on one page. The data to write is provided as a buffer
+// 'WriteBuffer' with a length 'WriteLength'.
+//
+// The Universal Data Packet always start on page boundaries but
+// can end anywhere. The length is the number of data bytes not
+// including the length byte and the CRC16 bytes. There is one
+// length byte. The CRC16 is first initialized to the starting
+// page number. This provides a check to verify the page that
+// was intended is being read. The CRC16 is then calculated over
+// the length and data bytes. The CRC16 is then inverted and stored
+// low byte first followed by the high byte.
+//
+// Supported devices: DeviceEPROM=0
+// DS1992, DS1993, DS1994, DS1995, DS1996
+// DeviceEPROM=1, EPROMCRCType=0(CRC8)
+// DS1982
+// DeviceEPROM=1, EPROMCRCType=1(CRC16)
+// DS1985, DS1986, DS2407
+//
+// 'StartPage' - page number to write packet to
+// 'WriteBuffer' - pointer to buffer containing data to write
+// 'WriteLength' - number of data byte in WriteBuffer
+// 'DeviceEPROM' - flag set if device is an EPROM (1 EPROM, 0 NVRAM)
+// 'EPROMCRCType' - if DeviceEPROM=1 then indicates CRC type
+// (0 CRC8, 1 CRC16)
+//
+// Returns: TRUE(1) success, packet written
+// FALSE(0) failure to write, contact lost or device locked
+//
+//
+int MLanWritePacketStd(int StartPage, uchar *WriteBuffer,
+ int WriteLength, int DeviceEPROM, int EPROMCRCType)
+{
+ uchar construct_buffer[32];
+ int i,buffer_cnt=0,start_address,do_access;
+
+ // check to see if data too long to fit on device
+ if (WriteLength > 29)
+ return FALSE;
+
+ // seed crc with page number
+ CRC16 = StartPage;
+
+ // set length byte
+ construct_buffer[buffer_cnt++] = (uchar)(WriteLength);
+ crc16(WriteLength);
+
+ // fill in the data to write
+ for (i = 0; i < WriteLength; i++)
+ {
+ crc16(WriteBuffer[i]);
+ construct_buffer[buffer_cnt++] = WriteBuffer[i];
+ }
+
+ // add the crc
+ construct_buffer[buffer_cnt++] = (uchar)(~(CRC16 & 0xFF));
+ construct_buffer[buffer_cnt++] = (uchar)(~((CRC16 & 0xFF00) >> 8));
+
+ // check if not EPROM
+ if (!DeviceEPROM)
+ {
+ // write the page
+ if (!Write_Scratchpad(construct_buffer,StartPage,buffer_cnt))
+ return FALSE;
+
+ // copy the scratchpad
+ if (!Copy_Scratchpad(StartPage,buffer_cnt))
+ return FALSE;
+
+ // copy scratch pad was good then success
+ return TRUE;
+ }
+ // is EPROM
+ else
+ {
+ // calculate the start address
+ start_address = ((StartPage >> 3) << 8) | ((StartPage << 5) & 0xFF);
+ do_access = TRUE;
+ // loop to program each byte
+ for (i = 0; i < buffer_cnt; i++)
+ {
+ if (MLanProgramByte(construct_buffer[i], start_address + i,
+ 0x0F, EPROMCRCType, do_access) != construct_buffer[i])
+ return FALSE;
+ do_access = FALSE;
+ }
+ return TRUE;
+ }
+}
+
+
+//--------------------------------------------------------------------------
+// Write a byte to an EPROM 1-Wire device.
+//
+// Supported devices: CRCType=0(CRC8)
+// DS1982
+// CRCType=1(CRC16)
+// DS1985, DS1986, DS2407
+//
+// 'WRByte' - byte to program
+// 'Addr' - address of byte to program
+// 'WriteCommand' - command used to write (0x0F reg mem, 0x55 status)
+// 'CRCType' - CRC used (0 CRC8, 1 CRC16)
+// 'DoAccess' - Flag to access device for each byte
+// (0 skip access, 1 do the access)
+// WARNING, only use DoAccess=0 if programing the NEXT
+// byte immediatly after the previous byte.
+//
+// Returns: >=0 success, this is the resulting byte from the program
+// effort
+// -1 error, device not connected or program pulse voltage
+// not available
+//
+int MLanProgramByte(int WRByte, int Addr, int WriteCommand,
+ int CRCType, int DoAccess)
+{
+ // optionally access the device
+ if (DoAccess)
+ {
+ if (!MLanAccess())
+ return -1;
+
+ // send the write command
+ if (!MLanWriteByte(WriteCommand))
+ return -1;
+
+ // send the address
+ if (!MLanWriteByte(Addr & 0xFF))
+ return -1;
+ if (!MLanWriteByte(Addr >> 8))
+ return -1;
+ }
+
+ // send the data to write
+ if (!MLanWriteByte(WRByte))
+ return -1;
+
+ // read the CRC
+ if (CRCType == 0)
+ {
+ // calculate CRC8
+ if (DoAccess)
+ {
+ DOWCRC = 0;
+ dowcrc((uchar)WriteCommand);
+ dowcrc((uchar)(Addr & 0xFF));
+ dowcrc((uchar)(Addr >> 8));
+ }
+ else
+ DOWCRC = (uchar)(Addr & 0xFF);
+
+ dowcrc((uchar)WRByte);
+ // read and calculate the read crc
+ dowcrc((uchar)MLanReadByte());
+ // crc should now be 0x00
+ if (DOWCRC != 0)
+ return -1;
+ }
+ else
+ {
+ // CRC16
+ if (DoAccess)
+ {
+ CRC16 = 0;
+ crc16(WriteCommand);
+ crc16(Addr & 0xFF);
+ crc16(Addr >> 8);
+ }
+ else
+ CRC16 = Addr;
+ crc16(WRByte);
+ // read and calculate the read crc
+ crc16(MLanReadByte());
+ crc16(MLanReadByte());
+ // crc should now be 0xB001
+ if (CRC16 != 0xB001)
+ return -1;
+ }
+
+ // send the program pulse
+ if (!MLanProgramPulse())
+ return -1;
+
+ // read back and return the resulting byte
+ return MLanReadByte();
+}
+
+
+//--------------------------------------------------------------------------
+// Write the scratchpad of a standard NVRam device such as the DS1992,3,4
+// and verify its contents.
+//
+// 'WriteBuffer' - pointer to buffer containing data to write
+// 'StartPage' - page number to write packet to
+// 'WriteLength' - number of data byte in WriteBuffer
+//
+// Returns: TRUE(1) success, the data was written and verified
+// FALSE(0) failure, the data could not be written
+//
+//
+int Write_Scratchpad(uchar *WriteBuffer, int StartPage, int WriteLength)
+{
+ int i,TranCnt=0;
+ uchar TranBuf[50];
+
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // write scratchpad command
+ TranBuf[TranCnt++] = 0x0F;
+ // write the target address
+ TranBuf[TranCnt++] = ((StartPage << 5) & 0xFF);
+ TranBuf[TranCnt++] = (StartPage >> 3);
+
+ // write packet bytes
+ for (i = 0; i < WriteLength; i++)
+ TranBuf[TranCnt++] = WriteBuffer[i];
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // now attempt to read back to check
+ TranCnt = 0;
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // read scratchpad command
+ TranBuf[TranCnt++] = 0xAA;
+ // read the target address, offset and data
+ for (i = 0; i < (WriteLength + 3); i++)
+ TranBuf[TranCnt++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // check address and offset of scratchpad read
+ if ((TranBuf[10] != (int)((StartPage << 5) & 0xFF)) ||
+ (TranBuf[11] != (int)(StartPage >> 3)) ||
+ (TranBuf[12] != (int)(WriteLength - 1)))
+ return FALSE;
+
+ // verify each data byte
+ for (i = 0; i < WriteLength; i++)
+ if (TranBuf[i+13] != WriteBuffer[i])
+ return FALSE;
+
+ // must have verified
+ return TRUE;
+ }
+ }
+
+ // failed a block tranfer
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Copy the contents of the scratchpad to its intended nv ram page. The
+// page and length of the data is needed to build the authorization bytes
+// to copy.
+//
+// 'StartPage' - page number to write packet to
+// 'WriteLength' - number of data bytes that are being copied
+//
+// Returns: TRUE(1) success
+// FALSE(0) failure
+//
+int Copy_Scratchpad(int StartPage, int WriteLength)
+{
+ int i,TranCnt=0;
+ uchar TranBuf[50];
+
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // copy scratchpad command
+ TranBuf[TranCnt++] = 0x55;
+ // write the target address
+ TranBuf[TranCnt++] = ((StartPage << 5) & 0xFF);
+ TranBuf[TranCnt++] = (StartPage >> 3);
+ TranBuf[TranCnt++] = WriteLength - 1;
+ // read copy result
+ TranBuf[TranCnt++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // check address and offset of scratchpad read
+ if ((TranBuf[10] != (int)((StartPage << 5) & 0xFF)) ||
+ (TranBuf[11] != (int)(StartPage >> 3)) ||
+ (TranBuf[12] != (int)(WriteLength - 1)) ||
+ (TranBuf[13] & 0xF0))
+ return FALSE;
+ else
+ return TRUE;
+ }
+
+ // failed a block tranfer
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Calculate a new CRC16 from the input data integer. Return the current
+// CRC16 and also update the global variable CRC16.
+//
+// 'data' - data to perform a CRC16 on
+//
+// Returns: the current CRC16
+//
+static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
+
+unsigned short crc16(int data)
+{
+ data = (data ^ (CRC16 & 0xff)) & 0xff;
+ CRC16 >>= 8;
+
+ if (oddparity[data & 0xf] ^ oddparity[data >> 4])
+ CRC16 ^= 0xc001;
+
+ data <<= 6;
+ CRC16 ^= data;
+ data <<= 1;
+ CRC16 ^= data;
+
+ return CRC16;
+}
+
+