#include "rawmem.h"
#include "mbnv.h"
#include "mbappreg.h"
#include "mbeprom.h"
#include "mbnvcrc.h"
#include "mbshaee.h"
#include "mbscrcrc.h"
#include "mbscrex.h"
#include "mbsha.h"
#include "mbscree.h"
#include "mbscr.h"
#include "mbee77.h"
#include "mbscrx77.h"
#include "mbee.h"
#include "pw77.h"
/**
* Reads memory in this bank with no CRC checking (device or
* data). The resulting data from this API may or may not be what is on
* the 1-Wire device. It is recommended that the data contain some kind
* of checking (CRC) like in the owReadPagePacket method.
* Some 1-Wire devices provide thier own CRC as in owReadPageCRC
* The owReadPageCRC method is not supported on all memory types, see hasPageAutoCRC
* in the same interface. If neither is an option then this method could be called more
* then once to at least verify that the same data is read consistently. The
* readContinue parameter is used to eliminate the overhead in re-accessing
* a part already being read from. For example, if pages 0 - 4 are to
* be read, readContinue would be set to false for page 0 and would be set
* to true for the next four calls.
*
* Note: Using readContinue = true can only be used if the new
* read continuous where the last one led off
* and it is inside a 'beginExclusive/endExclusive'
* block.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* str_add starting address
* rd_cont true then device read is
* continued without re-selecting
* buff location for data read
* len length in bytes to read
*
* @return 'true' if the read was complete
*/
SMALLINT owRead(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) {
SMALLINT ret = 0;
uchar extra[5];
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = readEE(bank, portnum, SNum, str_add, rd_cont, buff, len);
else if (bank == 0)
ret = readAppReg(bank, portnum, SNum, str_add, rd_cont, buff, len);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = readNV(bank, portnum, SNum, str_add, rd_cont, buff, len);
else if (bank == 0)
ret = readScratch(bank, portnum, SNum, str_add, rd_cont, buff, len);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = readNV(bank, portnum, SNum, str_add, rd_cont, buff, len);
else if (bank == 0)
ret = readScratch(bank, portnum, SNum, str_add, rd_cont, buff, len);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = readNV(bank, portnum, SNum, str_add, rd_cont, buff, len);
else if (bank == 0)
ret = readScratch(bank, portnum, SNum, str_add, rd_cont, buff, len);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = readNV(bank, portnum, SNum, str_add, rd_cont, buff, len);
else if (bank == 0)
ret = readScratch(bank, portnum, SNum, str_add, rd_cont, buff, len);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = readSHAEE(bank, portnum, SNum, str_add, rd_cont, buff, len);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = readEPROM(bank, portnum, SNum, str_add, rd_cont, buff, len);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = readEEPsw77(bank, portnum, SNum, str_add, rd_cont, buff, len);
} else if (bank == 0) {
ret = readScratchPadCRC77(portnum, SNum, buff, len, &extra[0]);
}
break;
default:
break;
}
return ret;
}
/**
* Writes memory in this bank. It is recommended that a structure with some
* built in error checking is used to provide data integrity on read.
* The method owWritePagePacket, which automatically wraps the data in a length
* and CRC, could be used for this purpose.
*
* When using on Write-Once devices care must be taken to write into
* into empty space. If owWrite is used to write over an unlocked
* page on a Write-Once device it will fail.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* str_add starting address
* buff data to write
* len length in bytes to write
*
* @return 'true' if the write was complete
*/
SMALLINT owWrite(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = writeEE(bank, portnum, SNum, str_add, buff, len);
else if (bank == 0)
ret = writeAppReg(bank, portnum, SNum, str_add, buff, len);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = writeNV(bank, portnum, SNum, str_add, buff, len);
else if (bank == 0)
ret = writeScratch(bank, portnum, SNum, str_add, buff, len);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = writeNV(bank, portnum, SNum, str_add, buff, len);
else if (bank == 0)
ret = writeScratch(bank, portnum, SNum, str_add, buff, len);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = writeNV(bank, portnum, SNum, str_add, buff, len);
else if (bank == 0)
ret = writeScratch(bank, portnum, SNum, str_add, buff, len);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = writeNV(bank, portnum, SNum, str_add, buff, len);
else if (bank == 0)
ret = writeScratch(bank, portnum, SNum, str_add, buff, len);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = writeSHAEE(bank, portnum, SNum, str_add, buff, len);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = writeEPROM(bank, portnum, SNum, str_add, buff, len);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = writeEE77(bank, portnum, SNum, str_add, buff, len);
} else if (bank == 0) {
ret = writeScratchPadEx77(portnum, SNum, str_add, buff, len);
}
break;
default:
break;
}
return ret;
}
/**
* Reads a page in this memory bank with no
* CRC checking (device or data). The resulting data from this API
* may or may not be what is on the 1-Wire device. It is recommends
* that the data contain some kind of checking (CRC) like in the
* owReadPagePacket function or have the 1-Wire device provide the
* CRC as in owReadPageCRC.
* However device CRC generation is not
* supported on all memory types, see owHasPageAutoCRC}.
* If neither is an option then this method could be called more
* then once to at least verify that the same data is read consistently.
*
* The readContinue parameter is used to eliminate the overhead in re-accessing
* a part already being read from. For example, if pages 0 - 4 are to
* be read, readContinue would be set to false for page 0 and would be set
* to true for the next four calls.
* Note: Using readContinue = true can only be used if the new
* read continues where the last one left off
* and it is inside a 'beginExclusive/endExclusive'
* block.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page page number to read packet from
* rd_cont true, then device read
* is continued without re-selecting
* buff location for data read
*
* @return 'true' if the read was complete
*/
SMALLINT owReadPage(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = readPageEE(bank, portnum, SNum, page, rd_cont, buff);
else if (bank == 0)
ret = readPageAppReg(bank, portnum, SNum, page, rd_cont, buff);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = readPageNV(bank, portnum, SNum, page, rd_cont, buff);
else if (bank == 0)
ret = readPageScratch(bank, portnum, SNum, page, rd_cont, buff);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank == 3)
ret = readPageNV(bank, portnum, SNum, page, rd_cont, buff);
else if (bank > 0)
ret = readPageNVCRC(bank, portnum, SNum, page, rd_cont, buff);
else if (bank == 0)
ret = readPageScratch(bank, portnum, SNum, page, rd_cont, buff);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = readPageNVCRC(bank, portnum, SNum, page, rd_cont, buff);
else if (bank == 0)
ret = readPageScratch(bank, portnum, SNum, page, rd_cont, buff);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = readPageNVCRC(bank, portnum, SNum, page, rd_cont, buff);
else if (bank == 0)
ret = readPageScratch(bank, portnum, SNum, page, rd_cont, buff);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = readPageSHAEE(bank, portnum, SNum, page, rd_cont, buff);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = readPageEPROM(bank, portnum, SNum, page, rd_cont, buff);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = readPageEE77(bank, portnum, SNum, page, rd_cont, buff);
} else if (bank == 0) {
ret = readPageScratchEx77(bank, portnum, SNum, page, rd_cont, buff);
}
break;
default:
break;
}
return ret;
}
/**
* Reads a page in this memory bank with extra information with no
* CRC checking (device or data). The resulting data from this API
* may or may not be what is on the 1-Wire device. It is recommends
* that the data contain some kind of checking (CRC) like in the
* owReadPagePacket function or have the 1-Wire device provide the
* CRC as in owReadPageCRC}.
* However device CRC generation is not
* supported on all memory types, see owHasPageAutoCRC}.
* If neither is an option then this method could be called more
* then once to at least verify that the same data is read consistently.The
* readContinue parameter is used to eliminate the overhead in re-accessing
* a part already being read from. For example, if pages 0 - 4 are to
* be read, readContinue would be set to false for page 0 and would be set
* to true for the next four calls.
*
* Note: Using readContinue = true can only be used if the new
* read continues where the last one left off
* and it is inside a 'beginExclusive/endExclusive'
* block.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page page number to read packet from
* rd_cont true then device read
* is continued without re-selecting
* buff location for data read
* extra location for extra info read
*
* @return 'true' if the read was complete
*/
SMALLINT owReadPageExtra(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = readPageExtraEE(bank, portnum, SNum, page, rd_cont, buff, extra);
else if (bank == 0)
ret = readPageExtraAppReg(bank, portnum, SNum, page, rd_cont, buff, extra);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = readPageExtraNV(bank, portnum, SNum, page, rd_cont, buff, extra);
else if (bank == 0)
ret = readPageExtraScratch(bank, portnum, SNum, page, rd_cont, buff, extra);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank == 3)
ret = readPageExtraNV(bank, portnum, SNum, page, rd_cont, buff, extra);
else if (bank > 0)
ret = readPageExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, extra);
else if (bank == 0)
ret = readPageExtraScratch(bank, portnum, SNum, page, rd_cont, buff, extra);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = readPageExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, extra);
else if (bank == 0)
ret = readPageExtraScratch(bank, portnum, SNum, page, rd_cont, buff, extra);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = readPageExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, extra);
else if (bank == 0)
ret = readPageExtraScratch(bank, portnum, SNum, page, rd_cont, buff, extra);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = readPageExtraSHAEE(bank, portnum, SNum, page, rd_cont, buff, extra);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = readPageExtraEPROM(bank, portnum, SNum, page, rd_cont, buff, extra);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = readPageExtraEE77(bank, portnum, SNum, page, rd_cont, buff, extra);
} else if (bank == 0) {
ret = readPageExtraScratchEx77(bank, portnum, SNum, page, rd_cont, buff, extra);
}
break;
default:
break;
}
return ret;
}
/**
* Reads a complete memory page with CRC verification provided by the
* device with extra information. Not supported by all devices. The
* rd_Continue parameter is used to eliminate the overhead in re-accessing
* a part already being read from. For example, if pages 0 - 4 are to
* be read, readContinue would be set to false for page 0 and would be set
* to true for the next four calls.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page page number to read
* read_buff location for data read
* extra location for extra info read
*
* @return 'true' if the read was complete
*/
SMALLINT owReadPageExtraCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = readPageExtraCRCEE(bank, portnum, SNum, page, read_buff, extra);
else if (bank == 0)
ret = readPageExtraCRCAppReg(bank, portnum, SNum, page, read_buff, extra);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = readPageExtraCRCNV(bank, portnum, SNum, page, read_buff, extra);
else if (bank == 0)
ret = readPageExtraCRCScratch(bank, portnum, SNum, page, read_buff, extra);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank == 3)
ret = readPageExtraCRCNV(bank, portnum, SNum, page, read_buff, extra);
else if (bank > 0)
ret = readPageExtraCRCNVCRC(bank, portnum, SNum, page, read_buff, extra);
else if (bank == 0)
ret = readPageExtraCRCScratch(bank, portnum, SNum, page, read_buff, extra);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = readPageExtraCRCNVCRC(bank, portnum, SNum, page, read_buff, extra);
else if (bank == 0)
ret = readPageExtraCRCScratch(bank, portnum, SNum, page, read_buff, extra);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = readPageExtraCRCNVCRC(bank, portnum, SNum, page, read_buff, extra);
else if (bank == 0)
ret = readPageExtraCRCScratch(bank, portnum, SNum, page, read_buff, extra);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = readPageExtraCRCSHAEE(bank, portnum, SNum, page, read_buff, extra);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = readPageExtraCRCEPROM(bank, portnum, SNum, page, read_buff, extra);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = readPageExtraCRCEE77(bank, portnum, SNum, page, read_buff, extra);
} else if (bank == 0) {
ret = readPageExtraCRCScratchEx77(bank, portnum, SNum, page, read_buff, extra);
}
break;
default:
break;
}
return ret;
}
/**
* Reads a complete memory page with CRC verification provided by the
* device. Not supported by all devices. The
* readContinue parameter is used to eliminate the overhead in re-accessing
* a part already being read from. For example, if pages 0 - 4 are to
* be read, readContinue would be set to false for page 0 and would be set
* to true for the next four calls.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page page number to read
* buff location for data read
*
* @return 'true' if the read was complete
*/
SMALLINT owReadPageCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = readPageCRCEE(bank, portnum, SNum, page, buff);
else if (bank == 0)
ret = readPageCRCAppReg(bank, portnum, SNum, page, buff);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = readPageCRCNV(bank, portnum, SNum, page, buff);
else if (bank == 0)
ret = readPageCRCScratch(bank, portnum, SNum, page, buff);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank == 3)
ret = readPageCRCNV(bank, portnum, SNum, page, buff);
else if (bank > 0)
ret = readPageCRCNVCRC(bank, portnum, SNum, page, buff);
else if (bank == 0)
ret = readPageCRCScratch(bank, portnum, SNum, page, buff);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = readPageCRCNVCRC(bank, portnum, SNum, page, buff);
else if (bank == 0)
ret = readPageCRCScratch(bank, portnum, SNum, page, buff);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = readPageCRCNVCRC(bank, portnum, SNum, page, buff);
else if (bank == 0)
ret = readPageCRCScratch(bank, portnum, SNum, page, buff);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = readPageCRCSHAEE(bank, portnum, SNum, page, buff);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = readPageCRCEPROM(bank, portnum, SNum, page, buff);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = readPageCRCEE77(bank, portnum, SNum, page, buff);
} else {
ret = readPageCRCScratchEx77(bank, portnum, SNum, page, buff);
}
break;
default:
break;
}
return ret;
}
/**
* Reads a Universal Data Packet.
*
* The Universal Data Packet always starts on page boundaries but
* can end anywhere in the page. The structure specifies the length of
* data bytes not including the length byte and the CRC16 bytes.
* There is one length byte. The CRC16 is first initialized to
* the 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. The structure is
* used by this method to verify the data but only
* the data payload is returned. The
* readContinue parameter is used to eliminate the overhead in re-accessing
* a part already being read from. For example, if pages 0 - 4 are to
* be read, readContinue would be set to false for page 0 and would be set
* to true for the next four calls.
*
* See Dallas Semiconductor Application Note 114
* for details: http://www.dalsemi.com/datasheets/pdfs/app114.pdf
* http://www.dalsemi.com/datasheets/pdfs/app114.pdf
*
* Note: Using rd_cont = true can only be used if the new
* read continues where the last one left off
* and it is inside a 'beginExclusive/endExclusive'
* block.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page page number to read packet from
* rd_cont true then device read
* is continued without re-selecting
* buff location for data read
* len the length of the data
*
* @return 'true' if the read was complete
*/
SMALLINT owReadPagePacket(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = readPagePacketEE(bank, portnum, SNum, page, rd_cont, buff, len);
else if (bank == 0)
ret = readPagePacketAppReg(bank, portnum, SNum, page, rd_cont, buff, len);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = readPagePacketNV(bank, portnum, SNum, page, rd_cont, buff, len);
else if (bank == 0)
ret = readPagePacketScratch(bank, portnum, SNum, page, rd_cont, buff, len);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = readPagePacketNV(bank, portnum, SNum, page, rd_cont, buff, len);
else if (bank == 0)
ret = readPagePacketScratch(bank, portnum, SNum, page, rd_cont, buff, len);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = readPagePacketNV(bank, portnum, SNum, page, rd_cont, buff, len);
else if (bank == 0)
ret = readPagePacketScratch(bank, portnum, SNum, page, rd_cont, buff, len);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = readPagePacketNV(bank, portnum, SNum, page, rd_cont, buff, len);
else if (bank == 0)
ret = readPagePacketScratch(bank, portnum, SNum, page, rd_cont, buff, len);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = readPagePacketSHAEE(bank, portnum, SNum, page, rd_cont, buff, len);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = readPagePacketEPROM(bank, portnum, SNum, page, rd_cont, buff, len);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = readPagePacketEE77(bank, portnum, SNum, page, rd_cont, buff, len);
} else if (bank == 0) {
ret = readPagePacketScratchEx77(bank, portnum, SNum, page, rd_cont, buff, len);
}
break;
default:
break;
}
return ret;
}
/**
* Reads a Universal Data Packet and extra information. See the
* function owReadPagePacket}
* for a description of the packet structure. The
* rd_cont parameter is used to eliminate the overhead in re-accessing
* a part already being read from. For example, if pages 0 - 4 are to
* be read, readContinue would be set to false for page 0 and would be set
* to true for the next four calls.
*
* Note: Using readContinue = true can only be used if the new
* read continues where the last one left off
* and it is inside a 'beginExclusive/endExclusive'
* block.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page page number to read packet from
* rd_cont true then device read
* is continued without re-selecting
* buff location for data read
* len the length of the data
* extra location for extra info read
*
* @return 'true' if the read was complete
*/
SMALLINT owReadPagePacketExtra(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len,
uchar *extra) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = readPagePacketExtraEE(bank, portnum, SNum, page, rd_cont, buff, len, extra);
else if (bank == 0)
ret = readPagePacketExtraAppReg(bank, portnum, SNum, page, rd_cont, buff, len, extra);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = readPagePacketExtraNV(bank, portnum, SNum, page, rd_cont, buff, len, extra);
else if (bank == 0)
ret = readPagePacketExtraScratch(bank, portnum, SNum, page, rd_cont, buff, len, extra);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank == 3)
ret = readPagePacketExtraNV(bank, portnum, SNum, page, rd_cont, buff, len, extra);
else if (bank > 0)
ret = readPagePacketExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, len, extra);
else if (bank == 0)
ret = readPagePacketExtraScratch(bank, portnum, SNum, page, rd_cont, buff, len, extra);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = readPagePacketExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, len, extra);
else if (bank == 0)
ret = readPagePacketExtraScratch(bank, portnum, SNum, page, rd_cont, buff, len, extra);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = readPagePacketExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, len, extra);
else if (bank == 0)
ret = readPagePacketExtraScratch(bank, portnum, SNum, page, rd_cont, buff, len, extra);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = readPagePacketExtraSHAEE(bank, portnum, SNum, page, rd_cont, buff, len, extra);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = readPagePacketExtraEPROM(bank, portnum, SNum, page, rd_cont, buff, len, extra);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = readPagePacketExtraEE77(bank, portnum, SNum, page, rd_cont, buff, len, extra);
} else if (bank == 0) {
ret = readPagePacketExtraScratchEx77(bank, portnum, SNum, page, rd_cont, buff, len, extra);
}
break;
default:
break;
}
return ret;
}
/**
* Writes a Universal Data Packet. See the funtion owReadPagePacket
* for a description of the packet structure.
*
* bank to tell what memory bank of the ibutton to use.
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page page number to write packet to
* buff data to write
* len number of bytes to write with a max of owGetMaxPacketDataLength
* elements
*
* @return 'true' if the write was complete
*/
SMALLINT owWritePagePacket(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = writePagePacketEE(bank, portnum, SNum, page, buff, len);
else if (bank == 0)
ret = writePagePacketAppReg(bank, portnum, SNum, page, buff, len);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = writePagePacketNV(bank, portnum, SNum, page, buff, len);
else if (bank == 0)
ret = writePagePacketScratch(bank, portnum, SNum, page, buff, len);
break;
case (0x18): // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = writePagePacketNV(bank, portnum, SNum, page, buff, len);
else if (bank == 0)
ret = writePagePacketScratch(bank, portnum, SNum, page, buff, len);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = writePagePacketNV(bank, portnum, SNum, page, buff, len);
else if (bank == 0)
ret = writePagePacketScratch(bank, portnum, SNum, page, buff, len);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = writePagePacketNV(bank, portnum, SNum, page, buff, len);
else if (bank == 0)
ret = writePagePacketScratch(bank, portnum, SNum, page, buff, len);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = writePagePacketSHAEE(bank, portnum, SNum, page, buff, len);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = writePagePacketEPROM(bank, portnum, SNum, page, buff, len);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = writePagePacketEE77(bank, portnum, SNum, page, buff, len);
} else if (bank == 0) {
ret = writePagePacketScratchEx77(bank, portnum, SNum, page, buff, len);
}
break;
default:
break;
}
return ret;
}
/**
* Gets the number of banks for a certain button given it's family code.
*
* family the family code
*
* @return the number of banks
*/
SMALLINT owGetNumberBanks(uchar family) {
SMALLINT ret = 0;
switch (family & 0x7F) {
case 0x14:
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x09:
case 0x12:
case 0x23:
ret = 2;
break;
case 0x1A:
ret = 3;
break;
case 0x33:
case 0xB3:
case 0x18:
case 0x1D:
ret = 4;
break;
case 0x0B:
case 0x0F:
case 0x13:
ret = 5;
break;
case 0x21:
ret = 6;
break;
case 0x37:
case 0x77:
ret = 2;
break;
default:
break;
}
return ret;
}
/**
* Gets the number of pages in this memory bank.
* The page numbers are then always 0 to (owGetNumberPages() - 1).
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return number of pages in this memory bank
*/
SMALLINT owGetNumberPages(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = getNumberPagesEE(bank, SNum);
else if (bank == 0)
ret = getNumberPagesAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = getNumberPagesNV(bank, SNum);
else if (bank == 0)
ret = getNumberPagesScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = getNumberPagesNV(bank, SNum);
else if (bank == 0)
ret = getNumberPagesScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = getNumberPagesNV(bank, SNum);
else if (bank == 0)
ret = getNumberPagesScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = getNumberPagesNV(bank, SNum);
else if (bank == 0)
ret = getNumberPagesScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = getNumberPagesSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = getNumberPagesEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0) {
ret = getNumberPagesEE77(bank, SNum);
} else if (bank == 0) {
ret = getNumberPagesScratchEx77(bank, SNum);
}
break;
default:
break;
}
return ret;
}
/**
* Gets the size of this memory bank in bytes.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return number of bytes in current memory bank
*/
int owGetSize(SMALLINT bank, uchar *SNum) {
int ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = getSizeEE(bank, SNum);
else if (bank == 0)
ret = getSizeAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = getSizeNV(bank, SNum);
else if (bank == 0)
ret = getSizeScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = getSizeNV(bank, SNum);
else if (bank == 0)
ret = getSizeScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = getSizeNV(bank, SNum);
else if (bank == 0)
ret = getSizeScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = getSizeNV(bank, SNum);
else if (bank == 0)
ret = getSizeScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = getSizeSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = getSizeEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = getSizeEE77(bank, SNum);
else if (bank == 0)
ret = getSizeScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Gets raw page length in bytes in this memory bank.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return page length in bytes in this memory bank
*/
SMALLINT owGetPageLength(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = getPageLengthEE(bank, SNum);
else if (bank == 0)
ret = getPageLengthAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = getPageLengthNV(bank, SNum);
else if (bank == 0)
ret = getPageLengthScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = getPageLengthNV(bank, SNum);
else if (bank == 0)
ret = getPageLengthScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = getPageLengthNV(bank, SNum);
else if (bank == 0)
ret = getPageLengthScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = getPageLengthNV(bank, SNum);
else if (bank == 0)
ret = getPageLengthScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = getPageLengthSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13:
ret = getPageLengthEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = getPageLengthEE77(bank, SNum);
else if (bank == 0)
ret = getPageLengthScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Gets the starting physical address of this bank. Physical
* banks are sometimes sub-divided into logical banks due to changes
* in attributes. Note that this method is for information only. The read
* and write methods will automatically calculate the physical address
* when writing to a logical memory bank.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return physical starting address of this logical bank
*/
int owGetStartingAddress(SMALLINT bank, uchar *SNum) {
int ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = getStartingAddressEE(bank, SNum);
else if (bank == 0)
ret = getStartingAddressAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = getStartingAddressNV(bank, SNum);
else if (bank == 0)
ret = getStartingAddressScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = getStartingAddressNV(bank, SNum);
else if (bank == 0)
ret = getStartingAddressScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = getStartingAddressNV(bank, SNum);
else if (bank == 0)
ret = getStartingAddressScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = getStartingAddressNV(bank, SNum);
else if (bank == 0)
ret = getStartingAddressScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = getStartingAddressSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = getStartingAddressEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = getStartingAddressEE77(bank, SNum);
else if (bank == 0)
ret = getStartingAddressScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Gets a string description of this memory bank.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return the memory bank description
*/
char *owGetBankDescription(SMALLINT bank, uchar *SNum) {
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
return getBankDescriptionEE(bank, SNum);
else if (bank == 0)
return getBankDescriptionAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
return getBankDescriptionNV(bank, SNum);
else if (bank == 0)
return getBankDescriptionScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
return getBankDescriptionNV(bank, SNum);
else if (bank == 0)
return getBankDescriptionScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
return getBankDescriptionNV(bank, SNum);
else if (bank == 0)
return getBankDescriptionScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
return getBankDescriptionNV(bank, SNum);
else if (bank == 0)
return getBankDescriptionScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
return getBankDescriptionSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
return getBankDescriptionEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
return getBankDescriptionEE77(bank, SNum);
else if (bank == 0)
return getBankDescriptionScratchEx77(bank, SNum);
break;
default:
break;
}
return "";
}
/**
* Retrieves the Dallas Semiconductor part number of the 1-Wire device
* as a String. For example 'Crypto iButton' or 'DS1992'.
*
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return 1-Wire device name
*/
char *owGetName(uchar *SNum) {
switch (SNum[0] & 0x7F) {
case 0x14:
return "DS1971";
break;
case 0x04:
return "DS1994";
break;
case 0x06:
return "DS1993";
break;
case 0x08:
return "DS1992";
break;
case 0x09:
return "DS1982";
break;
case 0x0A:
return "DS1995";
break;
case 0x0B:
return "DS1985";
break;
case 0x0C:
return "DS1996";
break;
case 0x18:
return "DS1963S";
break;
case 0x1A:
return "DS1963L";
break;
case 0x1D:
return "DS2423";
break;
case 0x23:
return "DS1973";
break;
case 0x33:
case 0xB3:
return "DS1961S";
break;
case 0x37:
case 0x77:
return "DS1977";
break;
default:
return "No Name";
}
}
/**
* Retrieves the alternate Dallas Semiconductor part numbers or names.
* A 'family' of 1-Wire Network devices may have more than one part number
* depending on packaging. There can also be nicknames such as
* 'Crypto iButton'.
*
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return 1-Wire device alternate names
*/
char *owGetAlternateName(uchar *SNum) {
switch (SNum[0] & 0x7F) {
case 0x14:
return "DS2430A";
break;
case 0x04:
return "DS2404, Time-in-a-can, DS1427";
break;
case 0x09:
return "DS2502";
break;
case 0x0B:
return "DS2505";
break;
case 0x18:
return "SHA-1 iButton";
break;
case 0x1A:
return "Monetary iButton";
break;
case 0x23:
return "DS2433";
break;
case 0x33:
case 0xB3:
return "DS2432";
break;
default:
return "No Alternate Name";
}
}
/**
* Retrieves a short description of the function of the 1-Wire device type.
*
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return device functional description
*/
char *owGetDescription(uchar *SNum) {
switch (SNum[0] & 0x7F) {
case 0x14:
return "Electrically Erasable Programmable Read Only Memory\n"
"*\t(EEPROM) organized as one page of 256 bits and 64 bit\n"
"*\tone-time programmable application register.";
break;
case 0x04:
return "4096 bit read/write nonvolatile memory partitioned\n"
"*\tinto sixteen pages of 256 bits each and a real\n"
"*\ttime clock/calendar in binary format.";
break;
case 0x06:
return "4096 bit read/write nonvolatile memory partitioned\n"
"*\tinto sixteen pages of 256 bits each.";
break;
case 0x08:
return "1024 bit read/write nonvolatile memory partitioned\n"
"*\tinto four pages of 256 bits each.";
break;
case 0x09:
return "1024 bit Electrically Programmable Read Only Memory\n"
"*\t(EPROM) partitioned into four 256 bit pages.\n"
"*\tEach memory page can be permanently write-protected\n"
"*\tto prevent tampering. Architecture allows software\n"
"*\tto patch data by supersending a used page in favor of\n"
"*\ta newly programmed page.";
break;
case 0x0A:
return "16384 bit read/write nonvolatile memory partitioned\n"
"*\tinto sixty-four pages of 256 bits each.";
break;
case 0x0B:
return "16384 bit Electrically Programmable Read Only Memory\n"
"*\t(EPROM) partitioned into sixty-four 256 bit pages.\n"
"*\tEach memory page can be permanently write-protected\n"
"*\tto prevent tampering. Architecture allows software\n"
"*\tto patch data by supersending a used page in favor of\n"
"*\ta newly programmed page.\n";
break;
case 0x0C:
return "65536 bit read/write nonvolatile memory partitioned\n"
"*\tinto two-hundred fifty-six pages of 256 bits each.";
break;
case 0x18:
return "4096 bits of read/write nonvolatile memory. Memory\n"
"*\tis partitioned into sixteen pages of 256 bits each.\n"
"*\tHas overdrive mode. One-chip 512-bit SHA-1 engine\n"
"*\tand secret storage.\n";
break;
case 0x1A:
return "4096 bit read/write nonvolatile memory with\n"
"*\tfour 32-bit read-only non rolling-over page write\n"
"*\tcycle counters and tamper-detect bits for small\n"
"*\tmoney storage.\n";
break;
case 0x1D:
return "1-Wire counter with 4096 bits of read/write, nonvolatile\n"
"*\tmemory. Memory is partitioned into sixteen pages of 256\n"
"*\tbits each. 256 bit scratchpad ensures data transfer\n"
"*\tintegrity. Has overdrive mode. Last four pages each have\n"
"*\t32 bit read-only non rolling-over counter. The first two\n"
"*\tcounters increment on a page write cycle and the second two\n"
"*\thave active-low external triggers.\n";
break;
case 0x23:
return "4096 bit Electrically Erasable Programmable Read\n"
"*\tOnly Memory (EEPROM) organized as sixteen pages of 256 bits.";
break;
case 0x33:
case 0xB3:
return "1K-Bit protected 1-Wire EEPROM with SHA-1 Engine.";
break;
case 0x37:
case 0x77:
return "32Kbyte EEPROM with read-only password and full\n"
"*\taccess password.";
break;
default:
return "No given description";
}
}
/**
* Checks to see if this memory bank is general purpose
* user memory. If it is NOT then it may be Memory-Mapped and writing
* values to this memory may affect the behavior of the 1-Wire
* device.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if this memory bank is general purpose
*/
SMALLINT owIsGeneralPurposeMemory(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = isGeneralPurposeMemoryEE(bank, SNum);
else if (bank == 0)
ret = isGeneralPurposeMemoryAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = isGeneralPurposeMemoryNV(bank, SNum);
else if (bank == 0)
ret = isGeneralPurposeMemoryScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = isGeneralPurposeMemoryNV(bank, SNum);
else if (bank == 0)
ret = isGeneralPurposeMemoryScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = isGeneralPurposeMemoryNV(bank, SNum);
else if (bank == 0)
ret = isGeneralPurposeMemoryScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = isGeneralPurposeMemoryNV(bank, SNum);
else if (bank == 0)
ret = isGeneralPurposeMemoryScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = isGeneralPurposeMemorySHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = isGeneralPurposeMemoryEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = isGeneralPurposeMemoryEE77(bank, SNum);
else if (bank == 0)
ret = isGeneralPurposeMemoryScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank is read/write.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if this memory bank is read/write
*/
SMALLINT owIsReadWrite(SMALLINT bank, int portnum, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = isReadWriteEE(bank, portnum, SNum);
else if (bank == 0)
ret = isReadWriteAppReg(bank, portnum, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = isReadWriteNV(bank, portnum, SNum);
else if (bank == 0)
ret = isReadWriteScratch(bank, portnum, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = isReadWriteNV(bank, portnum, SNum);
else if (bank == 0)
ret = isReadWriteScratch(bank, portnum, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = isReadWriteNV(bank, portnum, SNum);
else if (bank == 0)
ret = isReadWriteScratch(bank, portnum, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = isReadWriteNV(bank, portnum, SNum);
else if (bank == 0)
ret = isReadWriteScratch(bank, portnum, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = isReadWriteSHAEE(bank, portnum, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = isReadWriteEPROM(bank, portnum, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = isReadWriteEE77(bank, portnum, SNum);
else if (bank == 0)
ret = isReadWriteScratchEx77(bank, portnum, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank is write once such
* as with EPROM technology.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if this memory bank can only be written once
*/
SMALLINT owIsWriteOnce(SMALLINT bank, int portnum, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = isWriteOnceEE(bank, portnum, SNum);
else if (bank == 0)
ret = isWriteOnceAppReg(bank, portnum, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = isWriteOnceNV(bank, portnum, SNum);
else if (bank == 0)
ret = isWriteOnceScratch(bank, portnum, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = isWriteOnceNV(bank, portnum, SNum);
else if (bank == 0)
ret = isWriteOnceScratch(bank, portnum, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = isWriteOnceNV(bank, portnum, SNum);
else if (bank == 0)
ret = isWriteOnceScratch(bank, portnum, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = isWriteOnceNV(bank, portnum, SNum);
else if (bank == 0)
ret = isWriteOnceScratch(bank, portnum, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = isWriteOnceSHAEE(bank, portnum, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = isWriteOnceEPROM(bank, portnum, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = isWriteOnceEE77(bank, portnum, SNum);
else if (bank == 0)
ret = isWriteOnceScratchEx77(bank, portnum, SNum);
break;
default:
break;
}
return ret;
}
/**
* Query to see if current memory bank is read only.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if current memory bank can only be read
*/
SMALLINT owIsReadOnly(SMALLINT bank, int portnum, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = isReadOnlyEE(bank, portnum, SNum);
else if (bank == 0)
ret = isReadOnlyAppReg(bank, portnum, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = isReadOnlyNV(bank, portnum, SNum);
else if (bank == 0)
ret = isReadOnlyScratch(bank, portnum, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = isReadOnlyNV(bank, portnum, SNum);
else if (bank == 0)
ret = isReadOnlyScratch(bank, portnum, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = isReadOnlyNV(bank, portnum, SNum);
else if (bank == 0)
ret = isReadOnlyScratch(bank, portnum, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = isReadOnlySHAEE(bank, portnum, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = isReadOnlyEPROM(bank, portnum, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = isReadOnlyEE77(bank, portnum, SNum);
else if (bank == 0)
ret = isReadOnlyScratchEx77(bank, portnum, SNum);
break;
default:
break;
}
return ret;
}
/**
* Query to see if current memory bank non-volatile. Memory is
* non-volatile if it retains its contents even when removed from
* the 1-Wire network.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if current memory bank non volatile.
*/
SMALLINT owIsNonVolatile(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = isNonVolatileEE(bank, SNum);
else if (bank == 0)
ret = isNonVolatileAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = isNonVolatileNV(bank, SNum);
else if (bank == 0)
ret = isNonVolatileScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = isNonVolatileNV(bank, SNum);
else if (bank == 0)
ret = isNonVolatileScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = isNonVolatileNV(bank, SNum);
else if (bank == 0)
ret = isNonVolatileScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = isNonVolatileNV(bank, SNum);
else if (bank == 0)
ret = isNonVolatileScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank //SHAEE Memory Bank
ret = isNonVolatileSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = isNonVolatileEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = isNonVolatileEE77(bank, SNum);
else if (bank == 0)
ret = isNonVolatileScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank requires a
* 'ProgramPulse' in order to write.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if writing to this memory bank
* requires a 'ProgramPulse' from the 1-Wire Adapter.
*/
SMALLINT owNeedsProgramPulse(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = needsProgramPulseEE(bank, SNum);
else if (bank == 0)
ret = needsProgramPulseAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = needsProgramPulseNV(bank, SNum);
else if (bank == 0)
ret = needsProgramPulseScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = needsProgramPulseNV(bank, SNum);
else if (bank == 0)
ret = needsProgramPulseScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = needsProgramPulseNV(bank, SNum);
else if (bank == 0)
ret = needsProgramPulseScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = needsProgramPulseNV(bank, SNum);
else if (bank == 0)
ret = needsProgramPulseScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = needsProgramPulseSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = needsProgramPulseEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = needsProgramPulseEE77(bank, SNum);
else if (bank == 0)
ret = needsProgramPulseScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank requires 'PowerDelivery'
* in order to write.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if writing to this memory bank
* requires 'PowerDelivery' from the 1-Wire Adapter
*/
SMALLINT owNeedsPowerDelivery(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = needsPowerDeliveryEE(bank, SNum);
else if (bank == 0)
ret = needsPowerDeliveryAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = needsPowerDeliveryNV(bank, SNum);
else if (bank == 0)
ret = needsPowerDeliveryScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = needsPowerDeliveryNV(bank, SNum);
else if (bank == 0)
ret = needsPowerDeliveryScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = needsPowerDeliveryNV(bank, SNum);
else if (bank == 0)
ret = needsPowerDeliveryScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = needsPowerDeliveryNV(bank, SNum);
else if (bank == 0)
ret = needsPowerDeliveryScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = needsPowerDeliverySHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = needsPowerDeliveryEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = needsPowerDeliveryEE77(bank, SNum);
else if (bank == 0)
ret = needsPowerDeliveryScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank's pages deliver extra
* information outside of the normal data space, when read. Examples
* of this may be a redirection byte, counter, tamper protection
* bytes, or SHA-1 result. If this method returns true then the
* methods with an 'extraInfo' parameter can be used:
* owReadPageExtra,
* owReadPageExtraCRC, and
* owReadPagePacketExtra.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if reading the this memory bank's
* pages provides extra information
*/
SMALLINT owHasExtraInfo(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = hasExtraInfoEE(bank, SNum);
else if (bank == 0)
ret = hasExtraInfoAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = hasExtraInfoNV(bank, SNum);
else if (bank == 0)
ret = hasExtraInfoScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = hasExtraInfoNV(bank, SNum);
else if (bank == 0)
ret = hasExtraInfoScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = hasExtraInfoNV(bank, SNum);
else if (bank == 0)
ret = hasExtraInfoScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = hasExtraInfoNV(bank, SNum);
else if (bank == 0)
ret = hasExtraInfoScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = hasExtraInfoSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = hasExtraInfoEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = hasExtraInfoEE77(bank, SNum);
else if (bank == 0)
ret = hasExtraInfoScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Gets the length in bytes of extra information that
* is read when reading a page in this memory bank.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return number of bytes in Extra Information read when reading
* pages from this memory bank
*/
SMALLINT owGetExtraInfoLength(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = getExtraInfoLengthEE(bank, SNum);
else if (bank == 0)
ret = getExtraInfoLengthAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = getExtraInfoLengthNV(bank, SNum);
else if (bank == 0)
ret = getExtraInfoLengthScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = getExtraInfoLengthNV(bank, SNum);
else if (bank == 0)
ret = getExtraInfoLengthScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = getExtraInfoLengthNV(bank, SNum);
else if (bank == 0)
ret = getExtraInfoLengthScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = getExtraInfoLengthNV(bank, SNum);
else if (bank == 0)
ret = getExtraInfoLengthScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = getExtraInfoLengthSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = getExtraInfoLengthEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = getExtraInfoLengthEE77(bank, SNum);
else if (bank == 0)
ret = getExtraInfoLengthScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Gets a string description of what is contained in
* the Extra Information returned when reading pages in this
* memory bank.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return extra information description.
*/
char *owGetExtraInfoDesc(SMALLINT bank, uchar *SNum) {
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
return getExtraInfoDescEE(bank, SNum);
else if (bank == 0)
return getExtraInfoDescAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
return getExtraInfoDescNV(bank, SNum);
else if (bank == 0)
return getExtraInfoDescScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
return getExtraInfoDescNV(bank, SNum);
else if (bank == 0)
return getExtraInfoDescScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
return getExtraInfoDescNV(bank, SNum);
else if (bank == 0)
return getExtraInfoDescScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
return getExtraInfoDescNV(bank, SNum);
else if (bank == 0)
return getExtraInfoDescScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
return getExtraInfoDescSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
return getExtraInfoDescEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
return getExtraInfoDescEE77(bank, SNum);
else if (bank == 0)
return getExtraInfoDescScratchEx77(bank, SNum);
break;
default:
break;
}
return "";
}
/**
* Gets Maximum data page length in bytes for a packet
* read or written in this memory bank. See the
* owReadPagePacket and owWritePagePacket
* function. This function is only usefull
* if this memory bank is general purpose memory.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return max packet page length in bytes in this memory bank
*/
SMALLINT owGetMaxPacketDataLength(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = getMaxPacketDataLengthEE(bank, SNum);
else if (bank == 0)
ret = getMaxPacketDataLengthAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = getMaxPacketDataLengthNV(bank, SNum);
else if (bank == 0)
ret = getMaxPacketDataLengthScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = getMaxPacketDataLengthNV(bank, SNum);
else if (bank == 0)
ret = getMaxPacketDataLengthScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = getMaxPacketDataLengthNV(bank, SNum);
else if (bank == 0)
ret = getMaxPacketDataLengthScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = getMaxPacketDataLengthSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = getMaxPacketDataLengthEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = getMaxPacketDataLengthEE77(bank, SNum);
else if (bank == 0)
ret = getMaxPacketDataLengthScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank's pages can be read with
* the contents being verified by a device generated CRC.
* This is used to see if the owReadPageCRC function can be used.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if this memory bank can be
* read with self generated CRC
*/
SMALLINT owHasPageAutoCRC(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = hasPageAutoCRCEE(bank, SNum);
else if (bank == 0)
ret = hasPageAutoCRCAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = hasPageAutoCRCNV(bank, SNum);
else if (bank == 0)
ret = hasPageAutoCRCScratch(bank, SNum);
break;
case 0x18: // NV Memory Bank and Scratch SHA Memory Bank
if (bank > 0)
ret = hasPageAutoCRCNV(bank, SNum);
else if (bank == 0)
ret = hasPageAutoCRCScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = hasPageAutoCRCNV(bank, SNum);
else if (bank == 0)
ret = hasPageAutoCRCScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = hasPageAutoCRCNV(bank, SNum);
else if (bank == 0)
ret = hasPageAutoCRCScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = hasPageAutoCRCSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13: // EPROM Memory Bank
ret = hasPageAutoCRCEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = hasPageAutoCRCEE77(bank, SNum);
else if (bank == 0)
ret = hasPageAutoCRCScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank has pages that can be redirected
* to a new page. This is used in Write-Once memory
* to provide a means to update.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if this memory bank pages can be redirected
* to a new page
*/
SMALLINT owCanRedirectPage(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = canRedirectPageEE(bank, SNum);
else if (bank == 0)
ret = canRedirectPageAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = canRedirectPageNV(bank, SNum);
else if (bank == 0)
ret = canRedirectPageScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = canRedirectPageNV(bank, SNum);
else if (bank == 0)
ret = canRedirectPageScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = canRedirectPageNV(bank, SNum);
else if (bank == 0)
ret = canRedirectPageScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = canRedirectPageSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13:
ret = canRedirectPageEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = canRedirectPageEE77(bank, SNum);
else if (bank == 0)
ret = canRedirectPageScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank has pages that can be locked. A
* locked page would prevent any changes to it's contents.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if this memory bank has pages that can be
* locked
*/
SMALLINT owCanLockPage(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = canLockPageEE(bank, SNum);
else if (bank == 0)
ret = canLockPageAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = canLockPageNV(bank, SNum);
else if (bank == 0)
ret = canLockPageScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = canLockPageNV(bank, SNum);
else if (bank == 0)
ret = canLockPageScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = canLockPageNV(bank, SNum);
else if (bank == 0)
ret = canLockPageScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = canLockPageSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13:
ret = canLockPageEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = canLockPageEE77(bank, SNum);
else if (bank == 0)
ret = canLockPageScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Checks to see if this memory bank has pages that can be locked from
* being redirected. This would prevent a Write-Once memory from
* being updated.
*
* bank to tell what memory bank of the ibutton to use.
* SNum the serial number for the part that the operation is
* to be done on.
*
* @return true if this memory bank has pages that can
* be locked from being redirected to a new page
*/
SMALLINT owCanLockRedirectPage(SMALLINT bank, uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x14: // EE Memory Bank and AppReg Memory Bank
if (bank > 0)
ret = canLockRedirectPageEE(bank, SNum);
else if (bank == 0)
ret = canLockRedirectPageAppReg(bank, SNum);
break;
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x23: // NV Memory Bank and Scratch Memory Bank
if (bank > 0)
ret = canLockRedirectPageNV(bank, SNum);
else if (bank == 0)
ret = canLockRedirectPageScratch(bank, SNum);
break;
case 0x1A:
case 0x1D: // NVCRC Memory Bank and Scratch Ex Memory Bank
if (bank > 0)
ret = canLockRedirectPageNV(bank, SNum);
else if (bank == 0)
ret = canLockRedirectPageScratch(bank, SNum);
break;
case 0x21: // NVCRC Memory Bank and Scratch CRC Memory Bank
if (bank > 0)
ret = canLockRedirectPageNV(bank, SNum);
else if (bank == 0)
ret = canLockRedirectPageScratch(bank, SNum);
break;
case 0x33:
case 0xB3: // SHAEE Memory Bank
ret = canLockRedirectPageSHAEE(bank, SNum);
break;
case 0x09:
case 0x0B:
case 0x0F:
case 0x12:
case 0x13:
ret = canLockRedirectPageEPROM(bank, SNum);
break;
case 0x37:
case 0x77:
if (bank > 0)
ret = canLockRedirectPageEE77(bank, SNum);
else if (bank == 0)
ret = canLockRedirectPageScratchEx77(bank, SNum);
break;
default:
break;
}
return ret;
}
/**
* Tells whether a password is possibly needed.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* pass the password to set for read/write operations.
*
* @return 'true' if the password was set..
*/
SMALLINT owNeedPassword(uchar *SNum) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x37:
case 0x77:
ret = TRUE;
break;
default:
ret = FALSE;
break;
}
return ret;
}
/**
* Sets the password on the part for read-only operations.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* pass the password to set for read-only operations.
*
* @return 'true' if the password was set..
*/
SMALLINT owSetReadOnlyPassword(int portnum, uchar *SNum, uchar *pass) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x37:
case 0x77:
if (setPassword(portnum, SNum, pass, READ_PSW)) {
ret = verifyPassword(portnum, SNum, pass, READ_PSW);
if (ret)
setBMPassword(pass);
} else {
ret = FALSE;
}
break;
default:
OWERROR(OWERROR_NO_READ_ONLY_PASSWORD);
ret = FALSE;
break;
}
return ret;
}
/**
* Sets the password on the part for read/write operations.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* pass the password to set for read/write operations.
*
* @return 'true' if the password was set..
*/
SMALLINT owSetReadWritePassword(int portnum, uchar *SNum, uchar *pass) {
SMALLINT ret = FALSE;
switch (SNum[0] & 0x7F) {
case 0x37:
case 0x77:
if (setPassword(portnum, SNum, pass, READ_WRITE_PSW)) {
ret = verifyPassword(portnum, SNum, pass, READ_WRITE_PSW);
if (ret)
setBMPassword(pass);
} else {
ret = FALSE;
}
break;
default:
OWERROR(OWERROR_NO_READ_WRITE_PASSWORD);
ret = FALSE;
break;
}
return ret;
}
/**
* Sets the password for read-only operations.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* pass the password for read-only operations.
*
* @return 'true' if the password was set..
*/
SMALLINT owSetBMReadOnlyPassword(int portnum, uchar *SNum, uchar *pass) {
SMALLINT ret = 0;
switch (SNum[0] & 0x7F) {
case 0x37:
case 0x77:
setBMPassword(pass);
ret = TRUE;
break;
default:
OWERROR(OWERROR_NO_READ_ONLY_PASSWORD);
ret = FALSE;
break;
}
return ret;
}
/**
* Sets the password for read/write operations.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* pass the password for read/write operations.
*
* @return 'true' if the password was set..
*/
SMALLINT owSetBMReadWritePassword(int portnum, uchar *SNum, uchar *pass) {
SMALLINT ret = FALSE;
switch (SNum[0] & 0x7F) {
case 0x37:
case 0x77:
setBMPassword(pass);
ret = TRUE;
break;
default:
OWERROR(OWERROR_NO_READ_WRITE_PASSWORD);
ret = FALSE;
break;
}
return ret;
}
/**
* Sets the password for read/write operations.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* pass the password for read/write operations.
*
* @return 'true' if the password was set..
*/
SMALLINT owSetPasswordMode(int portnum, uchar *SNum, int mode) {
SMALLINT ret = FALSE;
switch (SNum[0] & 0x7F) {
case 0x37:
case 0x77:
ret = setPasswordMode(portnum, SNum, mode);
break;
default:
OWERROR(OWERROR_NO_READ_WRITE_PASSWORD);
ret = FALSE;
break;
}
return ret;
}
/**
* Gets the memory bank given the page for the part.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page the page number for the part not memory bank
* flag the flag to indicate status memory or regular memory
*
* @return the bank number that the page is in.
*/
SMALLINT getBank(int portnum, uchar *SNum, PAGE_TYPE page, uchar flag) {
SMALLINT bank = 1;
SMALLINT i, starting_bank = 1;
int tmp_pg;
int num_pg;
if (flag == STATUSMEM) {
tmp_pg = page;
for (i = starting_bank; i < owGetNumberBanks(SNum[0]); i++) {
if ((i + 1) == owGetNumberBanks(SNum[0]))
return i;
else {
if (owGetPageLength(bank, SNum) != 0)
num_pg = owGetStartingAddress(i + 1, SNum) / owGetPageLength(bank, SNum);
else
return FALSE;
}
if (num_pg >= tmp_pg) {
if (num_pg == tmp_pg)
return i + 1;
else
return i;
}
}
} else {
if (owIsWriteOnce(bank, portnum, SNum)) {
tmp_pg = page;
for (i = 0; i < owGetNumberBanks(SNum[0]); i++) {
if (owIsNonVolatile(i, SNum) && owIsGeneralPurposeMemory(i, SNum)) {
num_pg = owGetNumberPages(i, SNum);
if (num_pg >= tmp_pg)
return i;
else
tmp_pg = tmp_pg - num_pg;
}
}
} else {
tmp_pg = page;
for (i = 0; i < owGetNumberBanks(SNum[0]); i++) {
if (owIsNonVolatile(i, SNum) && owIsGeneralPurposeMemory(i, SNum) && owIsReadWrite(i, portnum, SNum)) {
num_pg = owGetNumberPages(i, SNum);
if (num_pg > tmp_pg)
return i;
else
tmp_pg = tmp_pg - num_pg;
}
}
}
}
return FALSE;
}
/**
* Gets the memory bank given the page for the part.
*
* portnum the port number of the port being used for the
* 1-Wire Network.
* SNum the serial number for the part that the operation is
* to be done on.
* page the page number for the part not memory bank
* flag the flag to indicate status memory or regular memory
*
* @return the bank number that the page is in.
*/
SMALLINT getPage(int portnum, uchar *SNum, PAGE_TYPE page, uchar flag) {
SMALLINT bank = 1;
SMALLINT i, starting_bank = 1;
int tmp_pg;
int num_pg;
if (flag == STATUSMEM) {
tmp_pg = page;
for (i = starting_bank; i < owGetNumberBanks(SNum[0]); i++) {
if ((i + 1) == owGetNumberBanks(SNum[0])) {
if (owGetPageLength(bank, SNum) != 0)
return (tmp_pg - (owGetStartingAddress(i, SNum) / owGetPageLength(bank, SNum)));
else
return FALSE;
} else {
if (owGetPageLength(bank, SNum) != 0)
num_pg = owGetStartingAddress(i + 1, SNum) / owGetPageLength(bank, SNum);
else
return FALSE;
}
if (num_pg >= tmp_pg) {
if (num_pg == tmp_pg)
return 0;
else if (owGetStartingAddress(i, SNum) == 0x00)
return tmp_pg;
else {
if (owGetPageLength(bank, SNum) != 0)
return (tmp_pg - (owGetStartingAddress(i, SNum) / owGetPageLength(bank, SNum)));
else
return FALSE;
}
}
}
} else {
if (owIsWriteOnce(bank, portnum, SNum)) {
tmp_pg = page;
for (i = 0; i < owGetNumberBanks(SNum[0]); i++) {
if (owIsNonVolatile(i, SNum) && owIsGeneralPurposeMemory(i, SNum)) {
num_pg = owGetNumberPages(i, SNum);
if (num_pg >= tmp_pg)
return tmp_pg;
else
tmp_pg = tmp_pg - num_pg;
}
}
} else {
tmp_pg = page;
for (i = 0; i < owGetNumberBanks(SNum[0]); i++) {
if (owIsNonVolatile(i, SNum) && owIsGeneralPurposeMemory(i, SNum) && owIsReadWrite(i, portnum, SNum)) {
num_pg = owGetNumberPages(i, SNum);
if (num_pg > tmp_pg)
return tmp_pg;
else
tmp_pg = tmp_pg - num_pg;
}
}
}
}
return FALSE;
}
w1retap/src/libusblinux300/rawmem.h 0000664 0000000 0000000 00000010455 14464462352 0017473 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// mbEE.h - Include memory bank EE functions.
//
// Version: 2.10
//
#include "owfile.h"
SMALLINT owRead(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len);
SMALLINT owWrite(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len);
SMALLINT owReadPage(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff);
SMALLINT owReadPageExtra(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra);
SMALLINT owReadPageExtraCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra);
SMALLINT owReadPageCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff);
SMALLINT owReadPagePacket(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len);
SMALLINT owReadPagePacketExtra(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len,
uchar *extra);
SMALLINT owWritePagePacket(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len);
SMALLINT owGetNumberBanks(uchar family);
SMALLINT owGetNumberPages(SMALLINT bank, uchar *SNum);
int owGetSize(SMALLINT bank, uchar *SNum);
SMALLINT owGetPageLength(SMALLINT bank, uchar *SNum);
int owGetStartingAddress(SMALLINT bank, uchar *SNum);
char *owGetBankDescription(SMALLINT bank, uchar *SNum);
char *owGetDescription(uchar *SNum);
SMALLINT owIsGeneralPurposeMemory(SMALLINT bank, uchar *SNum);
SMALLINT owIsReadWrite(SMALLINT bank, int portnum, uchar *SNum);
SMALLINT owIsWriteOnce(SMALLINT bank, int portnum, uchar *SNum);
SMALLINT owIsReadOnly(SMALLINT bank, int portnum, uchar *SNum);
SMALLINT owIsNonVolatile(SMALLINT bank, uchar *SNum);
SMALLINT owNeedsProgramPulse(SMALLINT bank, uchar *SNum);
SMALLINT owNeedsPowerDelivery(SMALLINT bank, uchar *SNum);
SMALLINT owHasExtraInfo(SMALLINT bank, uchar *SNum);
SMALLINT owGetExtraInfoLength(SMALLINT bank, uchar *SNum);
char *owGetExtraInfoDesc(SMALLINT bank, uchar *SNum);
SMALLINT owGetMaxPacketDataLength(SMALLINT bank, uchar *SNum);
SMALLINT owHasPageAutoCRC(SMALLINT bank, uchar *SNum);
SMALLINT owCanRedirectPage(SMALLINT bank, uchar *SNum);
SMALLINT owCanLockPage(SMALLINT bank, uchar *SNum);
SMALLINT owCanLockRedirectPage(SMALLINT bank, uchar *SNum);
char *owGetName(uchar *SNum);
char *owGetAlternateName(uchar *SNum);
SMALLINT owSetReadOnlyPassword(int portnum, uchar *SNum, uchar *pass);
SMALLINT owSetReadWritePassword(int portnum, uchar *SNum, uchar *pass);
SMALLINT owSetBMReadOnlyPassword(int portnum, uchar *SNum, uchar *pass);
SMALLINT owSetBMReadWritePassword(int portnum, uchar *SNum, uchar *pass);
SMALLINT owSetPasswordMode(int portnum, uchar *SNum, int mode);
SMALLINT owNeedPassword(uchar *SNum);
SMALLINT getBank(int portnum, uchar *SNum, PAGE_TYPE page, uchar flag);
SMALLINT getPage(int portnum, uchar *SNum, PAGE_TYPE page, uchar flag);
w1retap/src/libusblinux300/screenio.c 0000664 0000000 0000000 00000007034 14464462352 0020004 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// screenio.c - Utility functions for SHA iButton applications
//
// Version: 2.00
// History:
//
#include "ownet.h"
// Include files for the Palm and Visor
#ifdef __MC68K__
#include
#include
#endif
// defines
#define MAXLINE 16
// local function prototypes
void output_status(int, char *);
void reset_screen(void);
int available_screen(int);
void ClearScreen(int);
// globals
int VERBOSE = 0;
// keep track of line number on screen
int current_line = 0;
//--------------------------------------------------------------------------
// output status message
//
void output_status(int level, char *st) {
char *p;
static char linebuf[256];
static int cnt = 0;
// skip null strings
if (st[0] == 0)
return;
// check if in verbose mode
if ((level >= LV_ALWAYS) || VERBOSE) {
// look for embedded \n
for (p = st; *p; p++) {
if (*p == 0x0A || ((cnt > 33) && (*p == ' ')) || (*(p + 1) == 0)) {
// zero terminate the line
linebuf[cnt] = 0;
// print it out ???????? replace
#ifndef __MC68K__
printf("%s", linebuf);
#else
WinDrawChars(linebuf, StrLen(linebuf), 5, 10 * current_line++);
#endif
// check if too many lines
if (current_line == MAXLINE)
reset_screen();
cnt = 0;
} else
linebuf[cnt++] = *p;
}
}
}
//--------------------------------------------------------------------------
// check for available space on screen. Return 1 if available 0 otherwise
//
int available_screen(int lines) { return !((current_line + lines) > MAXLINE); }
//--------------------------------------------------------------------------
// reset the screen
//
void reset_screen(void) {
// set lines back to zero
current_line = 0;
// reset screen
ClearScreen(0);
}
//------------------------------------------------------------------------
// Clears the screen on the palm device
//
void ClearScreen(int row) {
#ifdef __MC68K__
int i;
for (i = row; i < 16; i++)
WinDrawChars((char *)" ", 80, 5, i * 10);
#endif
}
w1retap/src/libusblinux300/setds2409.c 0000664 0000000 0000000 00000002550 14464462352 0017634 0 ustar 00root root 0000000 0000000
// Include files
#include
#include
#include "ownet.h"
#include "swt1f.h"
#include
#include
static void w1_make_serial(char *asc, unsigned char *bin) {
int i, j;
for (i = j = 0; i < 8; i++) {
bin[i] = ToHex(asc[j]) << 4;
j++;
bin[i] += ToHex(asc[j]);
j++;
}
}
int main(int argc, char **argv) {
uchar a[3];
int portnum = 0;
char *serial = NULL;
char *dev = NULL;
int c, line = 0;
u_char ident[8];
while ((c = getopt(argc, argv, "ams:")) != EOF) {
switch (c) {
case 's':
serial = strdup(optarg);
break;
case 'm':
line = 1;
break;
case 'a':
line = 2;
break;
default:
break;
}
}
dev = argv[optind];
if (dev == NULL || serial == NULL) {
fputs("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n",
stderr);
return 0;
}
if ((portnum = owAcquireEx(dev)) < 0) {
fputs("Failed to acquire port.\n", stderr);
return 0;
} else {
w1_make_serial(serial, ident);
switch (line) {
case 1:
SetSwitch1F(portnum, ident, DIRECT_MAIN_ON, 0, a, TRUE);
break;
case 2:
SetSwitch1F(portnum, ident, AUXILARY_ON, 2, a, TRUE);
break;
}
owRelease(portnum);
}
return 0;
}
w1retap/src/libusblinux300/sha18.c 0000664 0000000 0000000 00000070512 14464462352 0017122 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// sha18.c - Low-level memory and SHA functions for the DS1963S.
//
// Version: 2.10
//
#include "ownet.h"
#include "shaib.h"
//--------------------------------------------------------------------------
// Attempt to erase the scratchpad of the specified SHA iButton for DS1963S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - value for TA2/TA1 (Note: TA2/TA1 aren't always set by
// Erase Scratchpad command.)
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Returns: TRUE, success, scratchpad erased
// FALSE, failure to erase scratchpad
//
SMALLINT EraseScratchpadSHA18(int portnum, int address, SMALLINT resume) {
uchar send_block[50];
int num_verf;
short send_cnt = 0;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// change number of verification bytes if in overdrive
num_verf = (in_overdrive[portnum & 0x0FF]) ? 6 : 2;
// erase scratchpad command
send_block[send_cnt++] = CMD_ERASE_SCRATCHPAD;
// TA1
send_block[send_cnt++] = (uchar)(address & 0xFF);
// TA2
send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF);
// now add the verification bytes
// for (i = 0; i < num_verf; i++)
// send_block[send_cnt++] = 0xFF;
memset(&send_block[send_cnt], 0x0FF, num_verf);
send_cnt += num_verf;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// check verification
OWASSERT(((send_block[send_cnt - 1] & 0xF0) == 0x50) || ((send_block[send_cnt - 1] & 0xF0) == 0xA0),
OWERROR_NO_COMPLETION_BYTE, FALSE);
return TRUE;
}
//----------------------------------------------------------------------
// Read the scratchpad with CRC16 verification for DS1963S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - pointer to address that is read from scratchpad
// 'es' - pointer to offset byte read from scratchpad
// 'data' - pointer data buffer read from scratchpad
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - scratch read, address, es, and data returned
// FALSE - error reading scratch, device not present
//
//
SMALLINT ReadScratchpadSHA18(int portnum, int *address, uchar *es, uchar *data, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[40];
SMALLINT i;
ushort lastcrc16 = 0;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
resume = 1; // for addition later
}
// read scratchpad command
send_block[send_cnt++] = CMD_READ_SCRATCHPAD;
// now add the read bytes for data bytes and crc16
// for (i = 0; i < 37; i++)
// send_block[send_cnt++] = 0xFF;
memset(&send_block[send_cnt], 0x0FF, 37);
send_cnt += 37;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// calculate CRC16 of result
setcrc16(portnum, 0);
for (i = resume; i < send_cnt; i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
// copy data to return buffers
if (address)
*address = (send_block[2 + resume] << 8) | send_block[1 + resume];
if (es)
*es = send_block[3 + resume];
memcpy(data, &send_block[4 + resume], 32);
// success
return TRUE;
}
//----------------------------------------------------------------------
// Write the scratchpad with CRC16 verification for DS1963S. The data
// is padded until the offset is 0x1F so that the CRC16 is retrieved.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - address to write data to
// 'data' - data to write
// 'data_len' - number of bytes of data to write
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - write to scratch verified
// FALSE - error writing scratch, device not present, or HIDE
// flag is in incorrect state for address being written.
//
SMALLINT WriteScratchpadSHA18(int portnum, int address, uchar *data, SMALLINT data_len, SMALLINT resume) {
uchar send_block[50];
short send_cnt = 0, i;
ushort lastcrc16;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
setcrc16(portnum, 0);
// write scratchpad command
send_block[send_cnt] = CMD_WRITE_SCRATCHPAD;
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// address 1
send_block[send_cnt] = (uchar)(address & 0xFF);
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// address 2
send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// data
for (i = 0; i < data_len; i++) {
send_block[send_cnt] = data[i];
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
}
// pad if needed
for (i = 0; i < (0x1F - ((address + data_len - 1) & 0x1F)); i++) {
send_block[send_cnt] = 0xFF;
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
}
// CRC16
send_block[send_cnt++] = 0xFF;
send_block[send_cnt++] = 0xFF;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// perform CRC16 of last 2 byte in packet
for (i = send_cnt - 2; i < send_cnt; i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
// success
return TRUE;
}
//----------------------------------------------------------------------
// Copy the scratchpad with verification for DS1963S. Assume that the
// data was padded to get the CRC16 verification on write scratchpad.
// This will result in the 'es' byte to be 0x1F.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - address of destination
// 'len' - length of data
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - copy scratch verified
// FALSE - error during copy scratch, device not present, or HIDE
// flag is in incorrect state for address being written.
//
SMALLINT CopyScratchpadSHA18(int portnum, int address, SMALLINT len, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[10];
int num_verf;
uchar es = (address + len - 1) & 0x1F;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// change number of verification bytes if in overdrive
num_verf = (in_overdrive[portnum & 0x0FF]) ? 4 : 2;
// copy scratchpad command
send_block[send_cnt++] = CMD_COPY_SCRATCHPAD;
// address 1
send_block[send_cnt++] = (uchar)(address & 0xFF);
// address 2
send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF);
// es
send_block[send_cnt++] = es;
// verification bytes
// for (i = 0; i < num_verf; i++)
// send_block[send_cnt++] = 0xFF;
memset(&send_block[send_cnt], 0x0FF, num_verf);
send_cnt += num_verf;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// check verification
OWASSERT(((send_block[send_cnt - 1] & 0xF0) == 0x50) || ((send_block[send_cnt - 1] & 0xF0) == 0xA0),
OWERROR_NO_COMPLETION_BYTE, FALSE);
return TRUE;
}
//----------------------------------------------------------------------
// Perform a scratchpad match using provided data. Fixed data length
// of 20 bytes.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'data' - data to use in match scratch operation
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - valid match
// FALSE - no match or device not present
//
SMALLINT MatchScratchpadSHA18(int portnum, uchar *data, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[50];
int i;
ushort lastcrc16;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
setcrc16(portnum, 0);
// match scratchpad command
send_block[send_cnt] = CMD_MATCH_SCRATCHPAD;
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// send 20 data bytes
for (i = 0; i < 20; i++) {
send_block[send_cnt] = data[i];
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
}
// send two crc bytes and verification byte
// for (i = 0; i < 3; i++)
// send_block[send_cnt++] = 0xFF;
memset(&send_block[send_cnt], 0x0FF, 3);
send_cnt += 3;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// check the CRC
for (i = (send_cnt - 3); i < (send_cnt - 1); i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
// check verification
if (send_block[send_cnt - 1] != (uchar)0xFF)
return TRUE;
else
return FALSE;
}
//----------------------------------------------------------------------
// Read Memory Page for DS1963S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - page number to do a read authenticate
// 'data' - buffer to read into from page
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Read successfull
// FALSE - error occurred during read.
//
SMALLINT ReadMemoryPageSHA18(int portnum, SMALLINT pagenum, uchar *data, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[36];
int address = pagenum << 5;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// create the send block
// Read Memory command
send_block[send_cnt++] = CMD_READ_MEMORY;
// TA1
send_block[send_cnt++] = (uchar)(address & 0xFF);
// TA2
send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF);
// now add the read bytes for data bytes
memset(&send_block[send_cnt], 0x0FF, 32);
send_cnt += 32;
// now send the block
OWASSERT(owBlock(portnum, TRUE, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
// transfer the results
memcpy(data, &send_block[send_cnt - 32], 32);
return TRUE;
}
//----------------------------------------------------------------------
// Read Authenticated Page for DS1963S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - page number to do a read authenticate
// 'data' - buffer to read into from page
// 'sign' - buffer for storing sha computation
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: Value of write cycle counter for the page
// -1 for error
//
int ReadAuthPageSHA18(int portnum, SMALLINT pagenum, uchar *data, uchar *sign, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[56];
short num_verf;
SMALLINT i;
ushort lastcrc16;
int address = pagenum * 32, wcc = -1;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// seed the crc
setcrc16(portnum, 0);
// change number of verification bytes if in overdrive
num_verf = (in_overdrive[portnum & 0x0FF]) ? 10 : 2;
// create the send block
// Read Authenticated Page command
send_block[send_cnt] = CMD_READ_AUTH_PAGE;
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// TA1
send_block[send_cnt] = (uchar)(address & 0xFF);
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// TA2
send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// now add the read bytes for data bytes, counter, and crc16, verification
// for (i = 0; i < (42 + num_verf); i++)
// send_block[send_cnt++] = 0xFF;
memset(&send_block[send_cnt], 0x0FF, 42 + num_verf);
send_cnt += 42 + num_verf;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, -1);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// check the CRC
for (i = resume ? 4 : 3; i < (send_cnt - num_verf); i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, -1);
// check verification
OWASSERT(((send_block[send_cnt - 1] & 0xF0) == 0x50) || ((send_block[send_cnt - 1] & 0xF0) == 0xA0),
OWERROR_NO_COMPLETION_BYTE, -1);
// transfer results
// cnt = 0;
// for (i = send_cnt - 42 - num_verf; i < (send_cnt - 10 - num_verf); i++)
// data[cnt++] = send_block[i];
memcpy(data, &send_block[send_cnt - 42 - num_verf], 32);
wcc = BytesToInt(&send_block[send_cnt - 10 - num_verf], 4);
if (sign != NULL) {
OWASSERT(ReadScratchpadSHA18(portnum, 0, 0, send_block, TRUE), OWERROR_READ_SCRATCHPAD_FAILED, FALSE);
// for(i=0; i<20; i++)
// sign[i] = send_block[i+8];
memcpy(sign, &send_block[8], 20);
}
return wcc;
}
//----------------------------------------------------------------------
// Write Data Page for DS1963S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - page number to write to
// 'data' - buffer to write into page
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Write successfull
// FALSE - error occurred during write.
//
SMALLINT WriteDataPageSHA18(int portnum, SMALLINT pagenum, uchar *data, SMALLINT resume) {
uchar buffer[32];
int addr = pagenum << 5, addr_buff;
uchar es = 0;
OWASSERT(EraseScratchpadSHA18(portnum, addr, resume), OWERROR_ERASE_SCRATCHPAD_FAILED, FALSE);
OWASSERT(WriteScratchpadSHA18(portnum, addr, data, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE);
OWASSERT(ReadScratchpadSHA18(portnum, &addr_buff, &es, buffer, TRUE), OWERROR_READ_SCRATCHPAD_FAILED, FALSE);
// verify that what we read is exactly what we wrote
OWASSERT((addr == addr_buff) && (es == 0x1F) && (memcmp(buffer, data, 32) == 0), OWERROR_READ_SCRATCHPAD_FAILED, FALSE);
OWASSERT(CopyScratchpadSHA18(portnum, addr, 32, TRUE), OWERROR_COPY_SCRATCHPAD_FAILED, FALSE);
return TRUE;
}
//----------------------------------------------------------------------
// Compute sha command based on control_byte and page address.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'control_byte' - control byte used in sha operation
// 'address' - address used in compute sha operation
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - compute sha finished
// FALSE - CRC error, device not present
//
SMALLINT SHAFunction18(int portnum, uchar control_byte, int address, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[18];
int i, num_verf;
ushort lastcrc16;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
setcrc16(portnum, 0);
// change number of verification bytes if in overdrive
num_verf = (in_overdrive[portnum & 0x0FF]) ? 10 : 2;
// Compute SHA Command
send_block[send_cnt] = CMD_COMPUTE_SHA;
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// address 1
send_block[send_cnt] = (uchar)(address & 0xFF);
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// address 2
send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// control byte
send_block[send_cnt] = control_byte;
lastcrc16 = docrc16(portnum, send_block[send_cnt++]);
// now read bytes crc16, and verification
// for (i = 0; i < 2 + num_verf; i++)
// send_block[send_cnt++] = 0xFF;
memset(&send_block[send_cnt], 0x0FF, 2 + num_verf);
send_cnt += 2 + num_verf;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// check the CRC
for (i = resume ? 5 : 4; i < (send_cnt - num_verf); i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
// check verification
OWASSERT(((send_block[send_cnt - 1] & 0xF0) == 0x50) || ((send_block[send_cnt - 1] & 0xF0) == 0xA0),
OWERROR_NO_COMPLETION_BYTE, FALSE);
return TRUE;
}
//----------------------------------------------------------------------
// Copies hidden scratchpad data into specified secret. Resume command
// is used by default.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'secretnum' - secret number to replace with scratchpad data.
//
// Return: TRUE - copy secret succeeded
// FALSE - error or device not present
//
SMALLINT CopySecretSHA18(int portnum, SMALLINT secretnum) {
// change number of verification bytes if in overdrive
SMALLINT num_verf = (in_overdrive[portnum & 0x0FF]) ? 10 : 2;
// each page has 4 secrets, so look at 2 LS bits to
// determine offset in the page.
SMALLINT secret_offset = (secretnum & 3) << 3;
// secrets 0-3 are stored starting at address 0200h
// and 4-7 are stored starting at address 0220h.
int address = (secretnum < 4 ? 0x0200 : 0x0220) + secret_offset;
SMALLINT length = 32 - secret_offset;
SMALLINT send_cnt = 0, i;
uchar send_block[37];
ushort lastcrc16 = 0;
// Since other functions must be called before this one
// that are communicating with the button, resume is assumed.
send_block[send_cnt++] = ROM_CMD_RESUME;
send_block[send_cnt++] = CMD_WRITE_SCRATCHPAD;
send_block[send_cnt++] = (uchar)address;
send_block[send_cnt++] = (uchar)(address >> 8);
// for(i=0; i 32) {
memcpy(&scratchpad[8], &secret[offset + 32], (bytes_left < 47 ? bytes_left - 32 : 15));
}
// write secret data into data page
OWASSERT(WriteDataPageSHA18(portnum, pagenum, data, resume), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
// write secret data into scratchpad
OWASSERT(WriteScratchpadSHA18(portnum, addr, scratchpad, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE);
// perform secret computation
OWASSERT(SHAFunction18(portnum, (uchar)(offset == 0 ? SHA_COMPUTE_FIRST_SECRET : SHA_COMPUTE_NEXT_SECRET), addr, TRUE),
OWERROR_SHA_FUNCTION_FAILED, FALSE);
// copy the resulting secret into secret location
OWASSERT(CopySecretSHA18(portnum, secretnum), OWERROR_COPY_SECRET_FAILED, FALSE);
resume = TRUE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Binds unique secret to DS1963S. bindData must be 32 bytes and
// bindCode must be 15 bytes.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - page number to do a read authenticate
// 'secretnum' - destination secret for computation results
// 'bindData' - the input data written to the data page for unique
// secret computation.
// 'bindCode' - the input data written to the scratchpad for unique
// secret computation.
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - bind successfull
// FALSE - error occurred during secret installation.
//
SMALLINT BindSecretToiButton18(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar *bindData, uchar *bindCode,
SMALLINT resume) {
int addr = pagenum << 5;
uchar scratchpad[32];
memset(scratchpad, 0x00, 32);
memcpy(&scratchpad[8], bindCode, 15);
// write secret data into data page
OWASSERT(WriteDataPageSHA18(portnum, pagenum, bindData, resume), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
// write secret data into scratchpad
OWASSERT(WriteScratchpadSHA18(portnum, addr, scratchpad, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE);
// perform secret computation
OWASSERT(SHAFunction18(portnum, (uchar)SHA_COMPUTE_NEXT_SECRET, addr, TRUE), OWERROR_SHA_FUNCTION_FAILED, FALSE);
// copy the resulting secret into secret location
OWASSERT(CopySecretSHA18(portnum, secretnum), OWERROR_COPY_SECRET_FAILED, FALSE);
return TRUE;
}
w1retap/src/libusblinux300/sha33.c 0000664 0000000 0000000 00000066277 14464462352 0017134 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// sha33.c - Low-level memory and SHA functions for the DS1961S.
//
// Version: 2.10
//
#include "shaib.h"
// this global is in mbshaee.c - necessary for writing to the part
// using the file I/O utilities - yecch...
extern uchar local_secret[8];
//----------------------------------------------------------------------
// Read the scratchpad with CRC16 verification for DS1961S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - pointer to address that is read from scratchpad
// 'es' - pointer to offset byte read from scratchpad
// 'data' - pointer to data buffer read from scratchpad
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - scratch read, address, es, and data returned
// FALSE - error reading scratch, device not present
//
//
SMALLINT ReadScratchpadSHA33(int portnum, int *address, uchar *es, uchar *data, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[16];
SMALLINT i;
ushort lastcrc16 = 0;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
resume = 1; // for addition later
}
// read scratchpad command
send_block[send_cnt++] = CMD_READ_SCRATCHPAD;
// now add the read bytes for data bytes and crc16
memset(&send_block[send_cnt], 0x0FF, 13);
send_cnt += 13;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// calculate CRC16 of result
setcrc16(portnum, 0);
for (i = resume; i < send_cnt; i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
// copy data to return buffers
if (address)
*address = (send_block[2 + resume] << 8) | send_block[1 + resume];
if (es)
*es = send_block[3 + resume];
memcpy(data, &send_block[4 + resume], 8);
// success
return TRUE;
}
//----------------------------------------------------------------------
// Write the scratchpad with CRC16 verification for DS1961S. There must
// be eight bytes worth of data in the buffer.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - address to write data to
// 'data' - data to write
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - write to scratch verified
// FALSE - error writing scratch, device not present, or HIDE
// flag is in incorrect state for address being written.
//
SMALLINT WriteScratchpadSHA33(int portnum, int address, uchar *data, SMALLINT resume) {
uchar send_block[15];
short send_cnt = 0, i;
ushort lastcrc16 = 0;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
setcrc16(portnum, 0);
// write scratchpad command
send_block[send_cnt] = CMD_WRITE_SCRATCHPAD;
docrc16(portnum, send_block[send_cnt++]);
// address 1
send_block[send_cnt] = (uchar)(address & 0xFF);
docrc16(portnum, send_block[send_cnt++]);
// address 2
send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
docrc16(portnum, send_block[send_cnt++]);
// data
for (i = 0; i < 8; i++) {
send_block[send_cnt] = data[i];
docrc16(portnum, send_block[send_cnt++]);
}
// CRC16
send_block[send_cnt++] = 0xFF;
send_block[send_cnt++] = 0xFF;
// PrintHexLabeled("write_scratchpad send_block before", send_block, send_cnt);
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
// PrintHexLabeled("write_scratchpad send_block after", send_block, send_cnt);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// perform CRC16 of last 2 byte in packet
for (i = send_cnt - 2; i < send_cnt; i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
// success
return TRUE;
}
//----------------------------------------------------------------------
// Copy the scratchpad with verification for DS1961S
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - address of destination
// 'MAC' - authentication MAC, required to execute copy scratchpad
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - copy scratch verified
// FALSE - error during copy scratch, device not present, or HIDE
// flag is in incorrect state for address being written.
//
SMALLINT CopyScratchpadSHA33(int portnum, int address, uchar *MAC, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[10];
uchar test;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// copy scratchpad command
send_block[send_cnt++] = CMD_COPY_SCRATCHPAD;
// address 1
send_block[send_cnt++] = (uchar)(address & 0xFF);
// address 2
send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF);
// es
send_block[send_cnt++] = (uchar)((address + 7) & 0x1F);
// verification bytes
// for (i = 0; i < num_verf; i++)
// send_block[send_cnt++] = 0xFF;
// memset(&send_block[send_cnt], 0x0FF, num_verf);
// send_cnt += num_verf;
// now send the block
// PrintHexLabeled("copy_scratchpad send_block before", send_block, send_cnt);
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
// PrintHexLabeled("copy_scratchpad send_block after", send_block, send_cnt);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// wait 2ms while DS1961S computes SHA
msDelay(2);
// now send the MAC
// PrintHexLabeled("copy_scratchpad MAC send_block before", MAC, 20);
OWASSERT(owBlock(portnum, FALSE, MAC, 20), OWERROR_BLOCK_FAILED, FALSE);
// PrintHexLabeled("copy_scratchpad MAC send_block after", MAC, 20);
// now wait 10ms for EEPROM write.
// should do strong pullup here.
msDelay(10);
test = owReadByte(portnum);
if ((test != 0xAA) && (test != 0x55)) {
if (test == 0xFF)
OWERROR(OWERROR_WRITE_PROTECTED);
else if (test == 0x00)
OWERROR(OWERROR_NONMATCHING_MAC);
else
OWERROR(OWERROR_NO_COMPLETION_BYTE);
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Read Authenticated Page for DS1961S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - page number to do a read authenticate
// 'data' - buffer to read into from page
// 'sign' - buffer for storing resulting sha computation
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: Value of write cycle counter for the page
// -1 for error
//
int ReadAuthPageSHA33(int portnum, SMALLINT pagenum, uchar *data, uchar *sign, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[55];
SMALLINT i;
ushort lastcrc16 = 0;
int address = pagenum << 5;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// seed the crc
setcrc16(portnum, 0);
// create the send block
// Read Authenticated Page command
send_block[send_cnt] = CMD_READ_AUTH_PAGE;
docrc16(portnum, send_block[send_cnt++]);
// TA1
send_block[send_cnt] = (uchar)(address & 0xFF);
docrc16(portnum, send_block[send_cnt++]);
// TA2
send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
docrc16(portnum, send_block[send_cnt++]);
// now add the read bytes for data bytes, 0xFF byte, and crc16
memset(&send_block[send_cnt], 0x0FF, 35);
send_cnt += 35;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, -1);
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
debugout(send_block, send_cnt);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// check the CRC
for (i = resume ? 4 : 3; i < send_cnt; i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, -1);
// transfer results
memcpy(data, &send_block[send_cnt - 35], 32);
// now wait for the MAC computation.
// should provide strong pull-up here.
msDelay(2);
// read the MAC
memset(send_block, 0xFF, 23);
OWASSERT(owBlock(portnum, FALSE, send_block, 23), OWERROR_BLOCK_FAILED, -1);
// check CRC of the MAC
setcrc16(portnum, 0);
for (i = 0; i < 22; i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC of the MAC is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, -1);
// check verification
OWASSERT(((send_block[22] & 0xF0) == 0x50) || ((send_block[22] & 0xF0) == 0xA0), OWERROR_NO_COMPLETION_BYTE, -1);
// transfer MAC into buffer
memcpy(sign, send_block, 20);
// no write cycle counter
return 0;
}
//----------------------------------------------------------------------
// Read Memory Page for DS1961S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - page number to do a read authenticate
// 'data' - buffer to read into from page
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Read successfull
// FALSE - error occurred during read.
//
SMALLINT ReadMemoryPageSHA33(int portnum, SMALLINT pagenum, uchar *data, SMALLINT resume) {
short send_cnt = 0;
uchar send_block[36];
int address = pagenum << 5;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// create the send block
// Read Memory command
send_block[send_cnt++] = CMD_READ_MEMORY;
// TA1
send_block[send_cnt++] = (uchar)(address & 0xFF);
// TA2
send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF);
// now add the read bytes for data bytes
memset(&send_block[send_cnt], 0x0FF, 32);
send_cnt += 32;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
// transfer the results
memcpy(data, &send_block[send_cnt - 32], 32);
return TRUE;
}
//----------------------------------------------------------------------
// Loads new system secret directly into secret memory for DS1961S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'secret' - the secret buffer used, must be 8 bytes.
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Load first secret successfull
// FALSE - error occurred during secret installation or the
// the secret is write-protected.
//
SMALLINT LoadFirstSecret33(int portnum, uchar *secret, SMALLINT resume) {
uchar send_block[15], test;
int send_cnt = 0;
// write secret data into scratchpad
OWASSERT(WriteScratchpadSHA33(portnum, 0x80, secret, resume), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE);
send_block[send_cnt++] = ROM_CMD_RESUME;
send_block[send_cnt++] = CMD_READ_SCRATCHPAD;
memset(&send_block[send_cnt], 0xFF, 13);
send_cnt += 13;
// now send the block
OWASSERT(owBlock(portnum, TRUE, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
// compare the contents of what we read with the secret
OWASSERT((memcmp(&send_block[5], secret, 8) == 0), OWERROR_READ_SCRATCHPAD_FAILED, FALSE);
// now copy the scratchpad to the secret location
send_block[1] = SHA33_LOAD_FIRST_SECRET;
// now send the block
OWASSERT(owBlock(portnum, TRUE, send_block, 5), OWERROR_BLOCK_FAILED, FALSE);
// wait 10ms for EEPROM write
msDelay(20);
test = owReadByte(portnum);
if ((test != 0xAA) && (test != 0x55)) {
if (test == 0xFF)
OWERROR(OWERROR_WRITE_PROTECTED);
else if (test == 0x00)
OWERROR(OWERROR_NONMATCHING_MAC);
else
OWERROR(OWERROR_NO_COMPLETION_BYTE);
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Uses Load First Secret to copy the current contents of the scratcpad
// to the specified memory location.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - The address to copy the data to.
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Load first secret successfull
// FALSE - error occurred during secret installation or the
// the secret is write-protected.
//
SMALLINT LoadFirstSecretAddress33(int portnum, int address, SMALLINT resume) {
uchar send_block[15], test;
int send_cnt = 0;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
// now copy the scratchpad to the secret location
send_block[send_cnt++] = SHA33_LOAD_FIRST_SECRET;
send_block[send_cnt++] = (uchar)(address);
send_block[send_cnt++] = (uchar)(address >> 8);
send_block[send_cnt++] = ((address + 7) & 0x01F);
// now send the block
OWASSERT(owBlock(portnum, TRUE, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
// wait 10ms for EEPROM write
msDelay(20);
test = owReadByte(portnum);
if ((test != 0xAA) && (test != 0x55)) {
if (test == 0xFF)
OWERROR(OWERROR_WRITE_PROTECTED);
else if (test == 0x00)
OWERROR(OWERROR_NONMATCHING_MAC);
else
OWERROR(OWERROR_NO_COMPLETION_BYTE);
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Refresh Scratchpad - Loads contents of specified address into
// scratchpad.
//
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'address' - The address to copy the data to.
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Load first secret successfull
// FALSE - error occurred during secret installation or the
// the secret is write-protected.
//
SMALLINT RefreshScratchpad33(int portnum, int address, SMALLINT resume) {
uchar send_block[15];
int send_cnt = 0, i;
ushort lastcrc16 = 0;
if (!resume) {
// access the device
OWASSERT(SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1);
} else {
// transmit RESUME command
send_block[send_cnt++] = ROM_CMD_RESUME;
}
send_block[send_cnt++] = SHA33_REFRESH_SCRATCHPAD;
send_block[send_cnt++] = (uchar)(address);
send_block[send_cnt++] = (uchar)(address >> 8);
memset(&send_block[send_cnt], 0x00, 8); // Don't care data
send_cnt += 8;
send_block[send_cnt++] = 0xFF; // CRC16
send_block[send_cnt++] = 0xFF;
// now send the block
OWASSERT(owBlock(portnum, resume, send_block, send_cnt), OWERROR_BLOCK_FAILED, FALSE);
// check CRC
setcrc16(portnum, 0);
i = (resume ? 1 : 0);
for (i = 0; i < send_cnt; i++)
lastcrc16 = docrc16(portnum, send_block[i]);
// verify CRC of the command is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, -1);
return TRUE;
}
//----------------------------------------------------------------------
// Refresh page - Uses Load First Secret and Refresh Scratchpad to
// 'refresh' the contents of a page.
//
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - the pagenumber to refresh.
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Load first secret successfull
// FALSE - error occurred during secret installation or the
// the secret is write-protected.
//
SMALLINT RefreshPage33(int portnum, SMALLINT pagenum, SMALLINT resume) {
uchar offset;
int address = pagenum * 32;
SMALLINT success = TRUE;
for (offset = 0; offset < 32; offset += 8) {
SMALLINT lsucc;
lsucc = RefreshScratchpad33(portnum, (address + offset), resume);
success = lsucc && success;
if (lsucc) {
lsucc = LoadFirstSecretAddress33(portnum, (address + offset), TRUE);
success = lsucc && success;
}
resume = TRUE;
}
return success;
}
// global for InstallSystemSecret33 and BindSecretToiButton
static uchar currentSecret[8];
//----------------------------------------------------------------------
// Installs new system secret for DS1961S. input_secret must be
// divisible by 47. Then, each block of 47 is split up with 32 bytes
// written to a data page and 8 bytes (of the remaining 15) are
// written to the scratchpad. The unused 7 bytes should be 0xFF for
// compatibility with the 1963S coprocessor (see ReformatSecretFor1961S())
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'pagenum' - page number to do a read authenticate
// 'secretnum' - param ignored, used to keep same calling syntax for
// DS1963S InstallSystemSecret.
// 'input_secret' - the input secret buffer used.
// 'secret_length' - the length of the input secret buffer, divisibly
// by 47.
// 'resume' - if true, device access is resumed using the RESUME
// ROM command (0xA5). Otherwise, a a MATCH ROM is
// used along with the device's entire address number.
//
// Return: TRUE - Install successfull
// FALSE - error occurred during secret installation.
//
SMALLINT InstallSystemSecret33(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar *input_secret, int secret_length,
SMALLINT resume) {
int offset = 0, bytes_left = 0;
uchar data[32], scratchpad[32], MT[64], MAC[20];
int hash[5];
memset(currentSecret, 0x00, 8);
// digest buffer padding
memset(&MT[52], 0xFF, 3);
MT[55] = (uchar)0x80;
memset(&MT[56], 0x00, 6);
MT[62] = (uchar)0x01;
MT[63] = (uchar)0xB8;
// now install the master secret
for (offset = 0; offset < secret_length; offset += 47) {
// clear the buffer
memset(data, 0x0FF, 32);
memset(scratchpad, 0x0FF, 32);
// Determine the amount of bytes remaining to be installed.
bytes_left = secret_length - offset;
// copy input_secret data into page buffer and scratchpad buffer
memcpy(data, &input_secret[offset], (bytes_left < 32 ? bytes_left : 32));
if (bytes_left > 32) {
memcpy(&scratchpad[8], &input_secret[offset + 32], (bytes_left < 47 ? bytes_left - 32 : 15));
}
// -- -- Perform ComputeNextSecret in software -- --
// first four bytes of secret
memcpy(MT, currentSecret, 4);
// page data to replace
memcpy(&MT[4], data, 32);
// contents of scratchpad
memcpy(&MT[36], &scratchpad[8], 15);
// Fix M-P-X control bits
MT[40] = (uchar)(MT[40] & 0x3F);
// last four bytes of secret
memcpy(&MT[48], ¤tSecret[4], 4);
ComputeSHAVM(MT, hash);
HashToMAC(hash, MAC);
memcpy(currentSecret, MAC, 8);
}
// After computing the secret, load it onto the button
OWASSERT(LoadFirstSecret33(portnum, currentSecret, resume), OWERROR_LOAD_FIRST_SECRET_FAILED, FALSE);
// set the secret in mbshaee.c
//-- man I hate globals!
memcpy(local_secret, currentSecret, 8);
return TRUE;
}
//----------------------------------------------------------------------
// BindSecretToiButton(portnum,pageNum,secretNum,bindData,bindCode);
// Only used on initialization, must be called after InstallSystemSecret
SMALLINT BindSecretToiButton33(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar *bindData, uchar *bindCode,
SMALLINT resume) {
uchar MT[64], MAC[20];
int hash[5];
// digest buffer padding
memset(MT, 0xFF, 64);
MT[55] = (uchar)0x80;
memset(&MT[56], 0x00, 6);
MT[62] = (uchar)0x01;
MT[63] = (uchar)0xB8;
// -- -- Perform ComputeNextSecret in software -- --
// first four bytes of secret
memcpy(MT, currentSecret, 4);
// page data to replace
memcpy(&MT[4], bindData, 32);
// contents of scratchpad
memcpy(&MT[40], &bindCode[4], 8);
// Fix M-P-X control bits
MT[40] = (uchar)(MT[40] & 0x3F);
// last four bytes of secret
memcpy(&MT[48], ¤tSecret[4], 4);
ComputeSHAVM(MT, hash);
HashToMAC(hash, MAC);
memcpy(currentSecret, MAC, 8);
// set the secret in mbshaee.c
//-- man I hate globals!
memcpy(local_secret, currentSecret, 8);
OWASSERT(LoadFirstSecret33(portnum, currentSecret, resume), OWERROR_LOAD_FIRST_SECRET_FAILED, FALSE);
return TRUE;
}
// constants used in SHA computation
static const int KTN[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
// calculation used for the SHA MAC
static int NLF(int B, int C, int D, int n) {
if (n < 20)
return ((B & C) | ((~B) & D));
else if (n < 40)
return (B ^ C ^ D);
else if (n < 60)
return ((B & C) | (B & D) | (C & D));
else
return (B ^ C ^ D);
}
//----------------------------------------------------------------------
// computes a SHA given the 64 byte MT digest buffer. The resulting 5
// int values are stored in the given int array, hash.
//
// Note: This algorithm is the SHA-1 algorithm as specified in the
// datasheet for the DS1961S, where the last step of the official
// FIPS-180 SHA routine is omitted (which only involves the addition of
// constant values).
//
// 'MT' - buffer containing the message digest
// 'hash' - result buffer
//
void ComputeSHAVM(uchar *MT, int *hash) {
unsigned int MTword[80];
int i;
int ShftTmp;
int Temp;
for (i = 0; i < 16; i++) {
MTword[i] = ((MT[i * 4] & 0x00FF) << 24) | ((MT[i * 4 + 1] & 0x00FF) << 16) | ((MT[i * 4 + 2] & 0x00FF) << 8) |
(MT[i * 4 + 3] & 0x00FF);
}
for (; i < 80; i++) {
ShftTmp = MTword[i - 3] ^ MTword[i - 8] ^ MTword[i - 14] ^ MTword[i - 16];
MTword[i] = ((ShftTmp << 1) & 0xFFFFFFFE) | ((ShftTmp >> 31) & 0x00000001);
}
hash[0] = 0x67452301;
hash[1] = 0xEFCDAB89;
hash[2] = 0x98BADCFE;
hash[3] = 0x10325476;
hash[4] = 0xC3D2E1F0;
for (i = 0; i < 80; i++) {
ShftTmp = ((hash[0] << 5) & 0xFFFFFFE0) | ((hash[0] >> 27) & 0x0000001F);
Temp = NLF(hash[1], hash[2], hash[3], i) + hash[4] + KTN[i / 20] + MTword[i] + ShftTmp;
hash[4] = hash[3];
hash[3] = hash[2];
hash[2] = ((hash[1] << 30) & 0xC0000000) | ((hash[1] >> 2) & 0x3FFFFFFF);
hash[1] = hash[0];
hash[0] = Temp;
}
}
//----------------------------------------------------------------------
// Converts the 5 int numbers that represent the result of a SHA
// computation into the 20 bytes (with proper byte ordering) that the
// SHA iButton's expect.
//
// 'hash' - result of SHA calculation
// 'MAC' - 20-byte, LSB-first message authentication code for SHA
// iButtons.
//
void HashToMAC(int *hash, uchar *MAC) {
int temp;
SMALLINT i, j, offset;
// iButtons use LSB first, so we have to turn
// the result around a little bit. Instead of
// result A-B-C-D-E, our result is E-D-C-B-A,
// where each letter represents four bytes of
// the result.
for (j = 4; j >= 0; j--) {
temp = hash[j];
offset = (4 - j) * 4;
for (i = 0; i < 4; i++) {
MAC[i + offset] = (uchar)temp;
temp >>= 8;
}
}
}
//----------------------------------------------------------------------
// For DS1961S compatibility, must be a multiple of 47 bytes in length.
// This function FFs out appropriate bytes so that computation is
// identical to secret computation on the DS1963S and the DS1961S.
//
// 'auth_secret' - input secret buffer
// 'secret_length' - length of the secret buffer (must be divisible
// by 47)
//
void ReformatSecretFor1961S(uchar *auth_secret, int secret_length) {
int i;
for (i = 0; i < secret_length; i += 47) {
memset(&auth_secret[i + 32], 0x0FF, 4);
memset(&auth_secret[i + 44], 0x0FF, 3);
}
}
w1retap/src/libusblinux300/sha_chck.c 0000664 0000000 0000000 00000015245 14464462352 0017743 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// sha_chk.c - main function for checking software authentication.
//
#include "ownet.h"
#include "shaib.h"
// file where the hard code data is for authentication
#define SA_Filename "sa_data.cnf"
// local function
SMALLINT FindUserSA(SHAUser *user, FileEntry *fe, SMALLINT doBlocking);
int getNumber(int min, int max);
int main(int argc, char **argv) {
FileEntry fe;
int len;
int i;
uchar authSecret[47];
int authlen = 21;
uchar signSecret[11] = {(uchar)'s', (uchar)'i', (uchar)'g', (uchar)'n', (uchar)' ', (uchar)'s',
(uchar)'e', (uchar)'c', (uchar)'r', (uchar)'e', (uchar)'t'};
int signlen = 11;
int ischars;
SHACopr copr;
SHAUser user;
// could be different ports.
copr.portnum = 0;
user.portnum = 0;
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
if ((copr.portnum = owAcquireEx(argv[1])) < 0) {
printf("Failed to acquire port.\n");
exit(1);
}
user.portnum = copr.portnum;
// MANUALLY SETTING DATA FOR COPROCESSOR
memcpy(copr.serviceFilename, "DLSM", 4);
copr.serviceFilename[4] = (uchar)102;
copr.signPageNumber = (uchar)8;
copr.authPageNumber = (uchar)7;
copr.wspcPageNumber = (uchar)9;
copr.versionNumber = (uchar)1;
memcpy(copr.bindCode, "bindcde", 7);
for (i = 0; i < 8; i++) {
memcpy(&copr.bindData[i * 4], "bind", 4);
}
copr.encCode = 0x01;
copr.ds1961Scompatible = 0x01;
// Prompt for password
printf("Enter up to 47 bytes of the Authentication Secret.\n");
printf(" Data Entry Mode\n");
printf(" (0) Text (single line)\n");
printf(" (1) Hex (XX XX XX XX ...)\n");
len = getData(authSecret, 47, getNumber(0, 1));
// padd the data with spaces or 0's depending on type
if (len < 47) {
for (i = len; i < 47; i++)
authSecret[i] = 0x00;
}
ReformatSecretFor1961S(authSecret, authlen);
copr.ds1961Scompatible = 0x55;
InstallAuthSecretVM(&copr, authSecret, authlen);
InstallSignSecretVM(&copr, signSecret, signlen);
puts("\nStarting SHA Software Authentication\n");
puts("\nPlease place token on the 1-Wire bus.\n");
memcpy(fe.Name, "DLSM", 4);
fe.Ext = 102;
for (;;) {
if (FindUserSA(&user, &fe, FALSE)) {
if (VerifyUser(&copr, &user, TRUE)) {
PrintSerialNum(&user.devAN[0]);
printf(", user data = ");
// print the user data
ischars = TRUE;
for (i = 0; i < 7; i++) {
if ((user.accountFile[i + 22] < 0x20) || (user.accountFile[i + 22] > 0x7E))
ischars = FALSE;
}
for (i = 0; i < 7; i++) {
if (ischars)
printf("%c", user.accountFile[i + 22]);
else
printf("%02X ", user.accountFile[i + 22]);
}
printf(", VALID\n");
FindNewSHA(user.portnum, &user.devAN[0], TRUE);
} else {
PrintSerialNum(&user.devAN[0]);
printf(", invalid\n");
FindNewSHA(user.portnum, &user.devAN[0], TRUE);
}
} else {
printf("NO DEVICE, invalid\n");
FindNewSHA(user.portnum, &user.devAN[0], TRUE);
}
}
owRelease(copr.portnum);
return TRUE;
}
//---------------------------------------------------------------------
// Uses File I/O API to find the user token with a specific
// service file name. Usually 'DSLM.102'.
//
// 'user' - Structure for holding user token information
// 'fe' - pointer to file entry structure, with proper
// service filename.
// 'doBlocking' - if TRUE, method blocks until a user token is found.
//
// Returns: TRUE, found a valid user token
// FALSE, no user token is present
//
SMALLINT FindUserSA(SHAUser *user, FileEntry *fe, SMALLINT doBlocking) {
SMALLINT FoundUser = FALSE;
if (FindNewSHA(user->portnum, user->devAN, TRUE)) {
short handle;
if (owOpenFile(user->portnum, user->devAN, fe, &handle)) {
user->accountPageNumber = fe->Spage;
FoundUser = TRUE;
owCloseFile(user->portnum, user->devAN, handle);
} else {
PrintSerialNum(user->devAN);
printf(" is not a SHA User.");
}
}
for (;;) {
// now get all the SHA iButton parts until we find
// one that has the right file on it.
while (!FoundUser && FindNewSHA(user->portnum, user->devAN, FALSE)) {
short handle;
if (owOpenFile(user->portnum, user->devAN, fe, &handle)) {
user->accountPageNumber = fe->Spage;
FoundUser = TRUE;
owCloseFile(user->portnum, user->devAN, handle);
} else {
PrintSerialNum(user->devAN);
printf(" is not a SHA User.");
}
}
if (FoundUser)
return TRUE;
else if (!doBlocking)
return FALSE;
}
}
/**
* Retrieve user input from the console.
*
* min minimum number to accept
* max maximum number to accept
*
* @return numeric value entered from the console.
*/
int getNumber(int min, int max) {
int value = min, cnt;
int done = FALSE;
do {
cnt = scanf("%d", &value);
if (cnt > 0 && (value > max || value < min)) {
printf("Value (%d) is outside of the limits (%d,%d)\n", value, min, max);
printf("Try again:\n");
} else
done = TRUE;
} while (!done);
return value;
}
w1retap/src/libusblinux300/sha_init.c 0000664 0000000 0000000 00000027365 14464462352 0020004 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// sha_init.c - main function for initializing software authentication
// application.
//
#include "ownet.h"
#include "shaib.h"
// file where the hard code data is for authentication
#define SA_Filename "sha_data.cnf"
// local functions
SMALLINT UpdateServiceDataSA(SHACopr *copr, SHAUser *user, uchar *data);
SMALLINT InstallServiceDataSA(SHACopr *copr, SHAUser *user, uchar *secret, int secret_length, uchar *data);
int getNumber(int min, int max);
static uchar sign_secret[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
// main body of application
int main(int argc, char **argv) {
int i = 0;
SHACopr copr;
SHAUser user;
int len, data_type;
uchar authSecret[47];
int authlen = 21;
uchar signSecret[11] = {(uchar)'s', (uchar)'i', (uchar)'g', (uchar)'n', (uchar)' ', (uchar)'s',
(uchar)'e', (uchar)'c', (uchar)'r', (uchar)'e', (uchar)'t'};
int signlen = 11;
uchar data[7];
copr.portnum = 0;
user.portnum = 0;
puts("\nStarting Software Authentication setup Application\n");
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
if ((copr.portnum = owAcquireEx(argv[1])) < 0) {
printf("Failed to acquire port.\n");
exit(1);
}
user.portnum = copr.portnum;
// MANUALLY SETTING DATA FOR COPROCESSOR
memcpy(copr.serviceFilename, "DLSM", 4);
copr.serviceFilename[4] = (uchar)102;
copr.signPageNumber = (uchar)8;
copr.authPageNumber = (uchar)7;
copr.wspcPageNumber = (uchar)9;
copr.versionNumber = (uchar)1;
memcpy(copr.bindCode, "bindcde", 7);
for (i = 0; i < 8; i++) {
memcpy(&copr.bindData[i * 4], "bind", 4);
}
copr.encCode = 0x01;
copr.ds1961Scompatible = 0x01;
// Prompt for Password and User data
printf("Enter up to 47 bytes of the Authentication Secret.\n");
printf(" Data Entry Mode\n");
printf(" (0) Text (single line)\n");
printf(" (1) Hex (XX XX XX XX ...)\n");
data_type = getNumber(0, 1);
len = getData(authSecret, 47, data_type);
// padd the data with spaces or 0's depending on type
if (len < 47) {
for (i = len; i < 47; i++)
authSecret[i] = 0x00;
}
PrintHex(authSecret, 47);
printf("\n");
printf("Enter up to 7 bytes of user data.\n");
printf(" Data Entry Mode\n");
printf(" (0) Text (single line)\n");
printf(" (1) Hex (XX XX XX XX ...)\n");
data_type = getNumber(0, 1);
len = getData(data, 7, data_type);
// padd the data with spaces or 0's depending on type
if (len < 7) {
for (i = len; i < 7; i++) {
if (data_type == 1)
data[i] = 0x00;
else
data[i] = 0x20;
}
}
PrintHex(data, 7);
printf("\n");
ReformatSecretFor1961S(authSecret, authlen);
// Debug: PrintHex(authSecret, authlen);
printf("\n");
copr.ds1961Scompatible = 0x55;
InstallAuthSecretVM(&copr, authSecret, authlen);
InstallSignSecretVM(&copr, signSecret, signlen);
// Find the token to initialize
puts("\nPlease place user token on the 1-Wire bus.\n");
do {
while (!FindNewSHA(user.portnum, user.devAN, (i == 0))) {
if (owHasErrors()) {
msDelay(10);
}
}
i++;
} while (user.devAN[7] == copr.devAN[7]);
// just check the crc of the two devices
// Initialize the token
printf("Installing Service Data on device: ");
PrintSerialNum(user.devAN);
puts("\n");
if (InstallServiceDataSA(&copr, &user, authSecret, authlen, data)) {
puts("User token successfully set up");
} else {
puts("User token setup failed");
OWERROR_DUMP(stdout);
}
// and we're done
owRelease(copr.portnum);
return 0;
}
//-------------------------------------------------------------------------
// Installs new service data on a user token.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'secret' - the authentication secret to install on user token.
//
// Return: If TRUE, new service installation succeeded.
// If FALSE, an error occurred.
//
SMALLINT InstallServiceDataSA(SHACopr *copr, SHAUser *user, uchar *secret, int secret_length, uchar *data) {
short handle;
int maxwrite;
FileEntry fe;
uchar fullBindCode[15];
// make sure user has a file directory structure
memcpy(fe.Name, copr->serviceFilename, 4);
fe.Ext = copr->serviceFilename[4];
// install master authentication secret
if (user->devAN[0] == 0x18) {
// need to format the device
if (!owFormat(user->portnum, user->devAN))
return FALSE;
// and create an empty stub for his account information
if (!owCreateFile(user->portnum, user->devAN, &maxwrite, &handle, &fe))
return FALSE;
// need to know what page the stub is on
user->accountPageNumber = fe.Spage;
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
OWASSERT(InstallSystemSecret18(user->portnum, user->accountPageNumber, user->accountPageNumber & 7, secret, secret_length,
FALSE),
OWERROR_INSTALL_SECRET_FAILED, FALSE);
} else if ((user->devAN[0] == 0x33) || (user->devAN[0] == 0xB3)) {
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
// because of copy-authorization, we need to install the
// secret first on the DS1961S and _then_ format the system
OWASSERT(InstallSystemSecret33(user->portnum, 0, 0, secret, secret_length, FALSE), OWERROR_INSTALL_SECRET_FAILED, FALSE);
// need to format the device
if (!owFormat(user->portnum, user->devAN))
return FALSE;
// and create an empty stub for his account information
if (!owCreateFile(user->portnum, user->devAN, &maxwrite, &handle, &fe))
return FALSE;
// need to know what page the stub is on
user->accountPageNumber = fe.Spage;
} else {
return FALSE;
}
// format the bind code properly
// first four bytes of bind code
memcpy(fullBindCode, copr->bindCode, 4);
// followed by the pagenumber
fullBindCode[4] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&fullBindCode[5], user->devAN, 7);
// followed by the last 3 bytes of bind code
memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3);
// create a unique secret for iButton
if (user->devAN[0] == 0x18) {
OWASSERT(BindSecretToiButton18(user->portnum, user->accountPageNumber, user->accountPageNumber & 7, copr->bindData,
fullBindCode, TRUE),
OWERROR_BIND_SECRET_FAILED, FALSE);
// do a read just to get value of writecycle counter
user->writeCycleCounter = ReadAuthPageSHA18(user->portnum, user->accountPageNumber, user->accountFile, NULL, TRUE);
} else if ((user->devAN[0] == 0x33) || (user->devAN[0] == 0xB3)) {
OWASSERT(BindSecretToiButton33(user->portnum, user->accountPageNumber, user->accountPageNumber & 7, copr->bindData,
fullBindCode, TRUE),
OWERROR_BIND_SECRET_FAILED, FALSE);
// Call VerifyUser just to get the user's secret in wspc
if (!VerifyUser(copr, user, TRUE))
return FALSE;
}
// set transaction ID
user->accountFile[27] = 0;
user->accountFile[28] = 0;
user->accountFile[29] = 0;
// sign the data with coprocessor and write it out
return UpdateServiceDataSA(copr, user, data);
}
//-------------------------------------------------------------------------
// Updates service data on a user token. This includes signing the
// data if the part is a DS1963S.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
//
// Return: If TRUE, update succeeded.
// If FALSE, an error occurred.
//
SMALLINT UpdateServiceDataSA(SHACopr *copr, SHAUser *user, uchar *data) {
ushort crc16, i;
uchar scratchpad[32];
// make sure length is right.
user->accountFile[0] = 29;
// clear out the old signature and CRC
memcpy(&user->accountFile[2], copr->initSignature, 20);
memset(&user->accountFile[30], 0x00, 2);
// reset data type code
user->accountFile[1] = 0;
for (i = 0; i < 7; i++)
user->accountFile[i + 22] = data[i];
if ((user->devAN[0] == 0x33) || (user->devAN[0] == 0xB3)) {
// --- Set up the scratchpad for signing
memset(scratchpad, 0x00, 32);
// the write cycle counter +1 (since we are about to write this to it)
if (user->writeCycleCounter > 0)
IntToBytes(&scratchpad[8], 4, user->writeCycleCounter + 1);
else
// user doesn't have write cycle counter (DS1961S)
memset(&scratchpad[8], 0x0FF, 4);
// the pagenumber
scratchpad[12] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&scratchpad[13], user->devAN, 7);
// the coprocessor's signing challenge
memcpy(&scratchpad[20], copr->signChlg, 3);
OWASSERT(CreateDataSignatureVM(copr, sign_secret, user->accountFile, scratchpad, &user->accountFile[2], TRUE),
OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE);
}
// add the crc at the end of the data.
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < 30; i++)
crc16 = docrc16(user->portnum, user->accountFile[i]);
crc16 = ~crc16;
user->accountFile[30] = (uchar)crc16;
user->accountFile[31] = (uchar)(crc16 >> 8);
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
if (user->devAN[0] == 0x18) {
// DS1963S - not too tough
OWASSERT(WriteDataPageSHA18(user->portnum, user->accountPageNumber, user->accountFile, FALSE),
OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
} else if ((user->devAN[0] == 0x33) || (user->devAN[0] == 0xB3)) {
OWASSERT(WriteDataPageSHA33(copr, user), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
} else
return FALSE;
return TRUE;
}
/**
* Retrieve user input from the console.
*
* min minimum number to accept
* max maximum number to accept
*
* @return numeric value entered from the console.
*/
int getNumber(int min, int max) {
int value = min, cnt;
int done = FALSE;
do {
cnt = scanf("%d", &value);
if (cnt > 0 && (value > max || value < min)) {
printf("Value (%d) is outside of the limits (%d,%d)\n", value, min, max);
printf("Try again:\n");
} else
done = TRUE;
} while (!done);
return value;
}
w1retap/src/libusblinux300/shaapp.c 0000664 0000000 0000000 00000041425 14464462352 0017453 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// AHAapp.c - This utility debits money from a roving SHA iButton
// (DS1963S) using a coprocessor SHA iButton.
//
// Version: 2.00
// History:
#include
#include
#include
#include "ownet.h"
#include "ibsha33.h"
// mode constants
enum { MD_FIND_ROVING = 0, MD_READ_AUTH, MD_MONEY_VERF, MD_MONEY_CHANGE, MD_MONEY_WRITE, MD_READ_BACK_AUTH, MD_VERIFY_GONE };
// local function prototypes
int ParseData(char *, int, uchar *, int);
// globals
int time_stamp;
// verbose output mode
int VERBOSE = 0;
//----------------------------------------------------------------------
// This is the Main routine for shaapp
//
// Note: This algorithm used is the SHA-1 algorithm as specified in the
// datasheet for the DS1961S, where the last step of the official
// FIPS-180 SHA routine is omitted (which only involves the addition of
// constant values).
//
int main(int argc, char **argv) {
char msg[200];
int portnum = 0;
uchar data[8];
ushort i;
uchar sn[8], secret[8], memory[32];
int rslt, n = 13, done = FALSE, skip;
int reads = 0;
uchar indata[32];
int address;
ushort addr;
uchar es;
char hexstr[32];
// check for required port name
if (argc != 2) {
sprintf(msg, "1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
printf("%s", msg);
return 0;
}
for (i = 0; i < 8; i++) {
secret[i] = 0xFF;
data[i] = 0xFF;
}
if ((portnum = owAcquireEx(argv[1])) < 0)
ExitProg("Did not Acquire port.\n", 1);
else {
rslt = owFirst(portnum, TRUE, FALSE);
owSerialNum(portnum, sn, TRUE);
while (rslt && ((sn[0] != 0xB3) && (sn[0] != 0x33))) {
rslt = owNext(portnum, TRUE, FALSE);
owSerialNum(portnum, sn, TRUE);
}
for (i = 0; i < 8; i++)
printf("%02X ", sn[i]);
printf("\n");
if ((sn[0] == 0xB3) || (sn[0] == 0x33)) {
if (ReadMem(portnum, 128, indata)) {
if (((indata[8] != 0xAA) && (indata[8] != 0x55)) && ((indata[11] != 0xAA) && (indata[11] != 0x55))) {
// Clear all memory to 0xFFh
for (i = 0; i < 16; i++) {
if (!LoadFirSecret(portnum, (ushort)(i * 8), data, 8))
printf("MEMORY ADDRESS %d DIDN'T WRITE\n", i * 8);
}
printf("Current Bus Master Secret Is:\n");
for (i = 0; i < 8; i++)
printf("%02X ", secret[i]);
printf("\n");
} else if ((indata[9] != 0xAA) || (indata[9] != 0x55)) {
printf("Please Enter the Current Secret\n");
printf("AA AA AA AA AA AA AA AA <- Example\n");
scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4], &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12],
&hexstr[14]);
if (!ParseData(hexstr, strlen(hexstr), data, 16))
printf("DIDN'T PARSE\n");
else {
printf("The secret read was:\n");
for (i = 0; i < 8; i++) {
secret[i] = data[i];
printf("%02X ", secret[i]);
data[i] = 0xFF;
}
printf("\n");
}
printf("\n");
if ((indata[13] == 0xAA) || (indata[13] == 0x55))
skip = 4;
else
skip = 0;
for (i = skip; i < 16; i++) {
ReadMem(portnum, (ushort)(((i * 8) / ((ushort)32)) * 32), memory);
if (WriteScratchSHAEE(portnum, (ushort)(i * 8), &data[0], 8))
CopyScratchSHAEE(portnum, (ushort)(i * 8), secret, sn, memory);
}
} else {
printf("Please Enter the Current Secret\n");
printf("AA AA AA AA AA AA AA AA <- Example\n");
scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4], &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12],
&hexstr[14]);
if (!ParseData(hexstr, strlen(hexstr), secret, 16))
printf("DIDN'T PARSE\n");
else {
printf("The secret that was read:\n");
for (i = 0; i < 8; i++) {
printf("%02X ", secret[i]);
}
printf("\n");
}
}
}
do {
printf("PICK AN OPERATION:\n\n");
printf("(1) Read memory\n"); // Reads memory page data
printf("(2) Write scratchpad\n"); // Write to scratch pad
printf("(3) Read scratchpad\n"); // Read scratch pad data
printf("(4) Copy scratchpad\n"); // Copy scratch pad to address
printf("(5) Load First Secret with Address\n"); // Load first secret data
printf("(6) Compute Next Secret\n"); // Compute next secret and
// changes Bus Master secret
printf("(7) Read Auth page\n"); // Read authenticate page
printf("(8) Change/Load Secret Only\n"); // Changes/Loads Secret and
// Bus Master Secret
printf("(9) Change Bus Master Secret\n"); // Only changes Bus Master S.
printf("(10) Write Protect Secret\n"); // Write protect secret
printf("(11) Write Protect pages 0 to 3\n"); // Write protect pages 0 to 3
printf("(12) EPROM mode control for page 1\n"); // EPROM mode for page 1
printf("(13) Write Protect page 0 only\n"); // Write protect page 0.
printf("(14) Print Current Bus Master Secret.\n");
printf("(15) QUIT\n");
scanf("%d", &n);
if (n == 15) {
n = 0; // used to finish off the loop
done = TRUE;
break;
}
switch (n) {
case 1: // Read Memory
printf("\nEnter memory address to read as integer\n");
scanf("%d", &reads);
if (ReadMem(portnum, (ushort)reads, indata)) {
printf("\n");
for (i = 0; i < 8; i++)
printf("%02X ", indata[i]);
printf("\n");
for (i = 8; i < 16; i++)
printf("%02X ", indata[i]);
printf("\n");
for (i = 16; i < 24; i++)
printf("%02X ", indata[i]);
printf("\n");
for (i = 24; i < 32; i++)
printf("%02X ", indata[i]);
printf("\n");
printf("Read Complete\n\n\n");
} else
printf("READ DIDN'T WORK\n\n\n");
break;
case 2: // Write Scratchpad
printf("\nEnter the 8 bytes of data to be written.\n");
printf("AA AA AA AA AA AA AA AA <- Example\n");
scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4], &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12],
&hexstr[14]);
printf("\nNow enter the address as an integer.\n");
scanf("%d", &address);
if (!ParseData(hexstr, strlen(hexstr), data, 16)) {
printf("DIDN'T PARSE\n");
break;
}
ReadMem(portnum, (ushort)((address / ((ushort)32)) * 32), memory);
if (WriteScratchSHAEE(portnum, (ushort)address, data, 8))
printf("Write complete\n\n\n");
else
printf("WRITE DIDN'T WORK\n\n\n");
break;
case 3: // Read Scratchpad
printf("\n");
if (ReadScratchSHAEE(portnum, &addr, &es, data)) {
printf("Address is: %d\n", addr);
printf("E/S Data is: %02X\n", es);
printf("Scratch pad data is:\n");
for (i = 0; i < 8; i++)
printf("%02X ", data[i]);
printf("\n\n\n");
} else
printf("READ DIDN'T WORK\n\n\n");
break;
case 4: // Copy Scratchpad
printf("\nEnter address to copy to as an integer.\n");
scanf("%d", &address);
if (CopyScratchSHAEE(portnum, (ushort)address, secret, sn, memory))
printf("Copy Scratch Pad Complete\n\n\n");
else
printf("COPY DIDN'T WORK\n\n\n");
break;
case 5: // Load First Secret
printf("\nEnter the 8 bytes of data to be written.\n");
printf("AA AA AA AA AA AA AA AA <- Example\n");
scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4], &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12],
&hexstr[14]);
printf("\nEnter the address where you want "
"to load the secret as an integer.\n");
scanf("%d", &address);
if (!ParseData(hexstr, strlen(hexstr), data, 16)) {
printf("DIDN'T PARSE\n");
break;
}
if (LoadFirSecret(portnum, (ushort)address, data, 8)) {
if (address == 128) {
for (i = 0; i < 8; i++)
secret[i] = data[i];
}
printf("Load Complete\n\n\n");
} else
printf("LOAD DIDN'T WORK\n\n\n");
break;
case 6: // Compute Next Secret
printf("\nEnter the address for the page of data to use in computation\n");
scanf("%d", &address);
if (NextSecret(portnum, (ushort)address, secret)) {
for (i = 0; i < 8; i++)
printf("%02X ", secret[i]);
printf("\n");
printf("Next secret is complete\n\n\n");
} else
printf("NEXT SECRET DIDN'T WORK\n\n\n");
break;
case 7: // Read Authenticate SHA Page
printf("\nEnter the 8 bytes of challenge to use.\n");
printf("AA AA AA AA AA AA AA AA <- Example\n");
scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4], &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12],
&hexstr[14]);
printf("\nEnter address of page to read authenticate\n");
scanf("%d", &address);
if (!ParseData(hexstr, strlen(hexstr), data, 16)) {
printf("DIDN'T PARSE\n");
break;
}
if (ReadAuthPageSHAEE(portnum, (ushort)address, secret, sn, indata, data)) {
printf("\n");
for (i = 0; i < 8; i++)
printf("%02X ", indata[i]);
printf("\n");
for (i = 8; i < 16; i++)
printf("%02X ", indata[i]);
printf("\n");
for (i = 16; i < 24; i++)
printf("%02X ", indata[i]);
printf("\n");
for (i = 24; i < 32; i++)
printf("%02X ", indata[i]);
printf("\n\n");
printf("Read Authenticate Complete\n\n\n");
} else
printf("READ DIDN'T WORK\n\n\n");
break;
case 8: // Change/Load new secret
printf("\nEnter 8 byte secret you wish to load/change\n");
printf("AA AA AA AA AA AA AA AA <- Example\n");
scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4], &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12],
&hexstr[14]);
if (!ParseData(hexstr, strlen(hexstr), data, 16)) {
printf("DIDN'T PARSE\n");
break;
}
if (LoadFirSecret(portnum, 128, data, 8)) {
for (i = 0; i < 8; i++)
secret[i] = data[i];
printf("Secret Loaded\n\n\n");
} else
printf("SECRET NOT LOADED\n\n\n");
break;
case 9: // Change Bus Master Secret
printf("\nEnter 8 byte secret you wish to load for Bus Master\n");
printf("AA AA AA AA AA AA AA AA <- Example\n");
scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4], &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12],
&hexstr[14]);
if (!ParseData(hexstr, strlen(hexstr), data, 16)) {
printf("DIDN'T PARSE\n");
break;
} else {
for (i = 0; i < 8; i++)
secret[i] = data[i];
printf("Bus Master Secret Changed.\n");
}
break;
case 10: // Lock Secret
printf("\n");
data[0] = 0xAA;
for (i = 1; i < 8; i++)
data[i] = 0x00;
ReadMem(portnum, 128, memory);
if (WriteScratchSHAEE(portnum, 136, data, 8) && CopyScratchSHAEE(portnum, 136, secret, sn, memory))
printf("Secret Locked\n\n\n");
else
printf("SECRET NOT LOCKED\n\n\n");
break;
case 11: // Write-protect pages 0 to 3
printf("\n");
data[0] = 0x00;
data[1] = 0xAA;
for (i = 2; i < 8; i++)
data[i] = 0x00;
ReadMem(portnum, 128, memory);
if (WriteScratchSHAEE(portnum, 136, data, 8) && CopyScratchSHAEE(portnum, 136, secret, sn, memory))
printf("Pages 0 to 3 write protected\n\n\n");
else
printf("PAGES NOT WRITE PROTECTED\n\n\n");
break;
case 12: // Set page 1 to EPROM mode
printf("\n");
for (i = 0; i < 4; i++)
data[i] = 0x00;
data[4] = 0xAA;
for (i = 5; i < 8; i++)
data[i] = 0x00;
ReadMem(portnum, 128, memory);
if (WriteScratchSHAEE(portnum, 136, data, 8) && CopyScratchSHAEE(portnum, 136, secret, sn, memory))
printf("EPROM mode control activated for page 1.\n\n\n");
else
printf("EPROM PROGRAMMING DIDN'T WORK\n\n\n");
break;
case 13: // Write protect page 0
printf("\n");
for (i = 0; i < 5; i++)
data[i] = 0x00;
data[5] = 0xAA;
for (i = 6; i < 8; i++)
data[i] = 0x00;
ReadMem(portnum, 128, memory);
if (WriteScratchSHAEE(portnum, 136, data, 8) && CopyScratchSHAEE(portnum, 136, secret, sn, memory))
printf("Page 0 Write-protected\n\n\n");
else
printf("NOT WRITE-PROTECTED\n\n\n");
break;
case 14: // Print Current Bus Master Secret
printf("\nThe Current Bus Master Secret is:\n");
for (i = 0; i < 8; i++)
printf("%02X ", secret[i]);
printf("\n\n\n");
break;
default:
break;
}
} while (!done);
} else
printf("DS2432 not found on One Wire Network\n");
owRelease(portnum);
}
return 1;
}
//----------------------------------------------------------------------
// Parse the raw file data in to an array of uchar's. The data must
// be hex characters possible seperated by white space
// 12 34 456789ABCD EF
// FE DC BA 98 7654 32 10
// would be converted to an array of 16 uchars.
// return the array length. If an invalid hex pair is found then the
// return will be 0.
//
// inbuf the input buffer that is to be parsed
// insize the size of the input buffer
// outbuf the parsed data from the input buffer
// maxsize the max size that is to be parsed.
//
// return the length of that data that was parsed
//
int ParseData(char *inbuf, int insize, uchar *outbuf, int maxsize) {
int ps, outlen = 0, gotmnib = 0;
uchar mnib = 0;
// loop until end of data
for (ps = 0; ps < insize; ps++) {
// check for white space
if (isspace(inbuf[ps]))
continue;
// not white space, make sure hex
else if (isxdigit(inbuf[ps])) {
// check if have first nibble yet
if (gotmnib) {
// this is the second nibble
outbuf[outlen++] = (mnib << 4) | ToHex(inbuf[ps]);
gotmnib = 0;
} else {
// this is the first nibble
mnib = ToHex(inbuf[ps]);
gotmnib = 1;
}
} else
return 0;
// if getting to the max return what we have
if ((outlen + 1) >= maxsize)
return outlen;
}
return outlen;
}
w1retap/src/libusblinux300/shacopr.c 0000664 0000000 0000000 00000022365 14464462352 0017640 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// shainitcopr.c - initializes a 1963S as a co-processor.
//
// Version: 2.10
//
#include "ownet.h"
#include "shaib.h"
static void GetBytes(char *msg, uchar *buffer, int len, uchar defValue, SMALLINT printHex);
static int GetSecret(char *name, uchar **secret);
//---------------------------------------------------------------------------
// Finds a DS1963S and initializes it as a coprocessor for SHA eCash systems.
//
// Note: The algorithm used for signing certificates and verifying device
// authenticity is the SHA-1 algorithm as specified in the datasheet for the
// DS1961S/DS2432 and the DS2963S, where the last step of the official
// FIPS-180 SHA routine is omitted (which only involves the addition of
// constant values).
//
int main(int argc, char **argv) {
int lvalue = 0;
SHACopr copr;
int namelen, auxlen;
uchar coprFile[255];
uchar *authSecret, *signSecret;
unsigned int authlen, signlen;
char test[2] = {'y', 0};
#ifdef COPRVM
FILE *fp;
unsigned int len;
#else
FileEntry fe;
int maxwrite = 0;
short handle = 0;
#endif
copr.portnum = 0;
puts("\nStarting SHA initcopr Application\n");
#ifndef COPRVM
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
if ((copr.portnum = owAcquireEx(argv[1])) < 0) {
printf("Failed to acquire port.\n");
exit(1);
}
puts("\nPlease place coprocessor token on the 1-Wire bus.\n");
while (!FindNewSHA(copr.portnum, copr.devAN, FALSE)) {
if (owHasErrors())
msDelay(10);
}
printf("Found device: ");
PrintSerialNum(copr.devAN);
puts("\n");
GetBytes("Enter the name of the coprocessor file (4 letters): ", fe.Name, 4, 0x20, FALSE);
lvalue = 0;
EnterNum("Enter the file extension of the coprocessor file", 3, &lvalue, 0, 255);
fe.Ext = (uchar)lvalue;
printf("\n");
#endif
GetBytes("Enter the name of the account service file (4 letters): ", copr.serviceFilename, 4, 0x20, FALSE);
lvalue = 102;
EnterNum("Enter the file extension of the account service file", 3, &lvalue, 0, 255);
copr.serviceFilename[4] = (uchar)lvalue;
printf("\n");
lvalue = 7;
EnterNum("Enter the authentication page number", 2, &lvalue, 1, 7);
copr.authPageNumber = (uchar)lvalue;
printf("\n");
lvalue = 9;
EnterNum("Enter the workspace page number", 2, &lvalue, 9, 15);
copr.wspcPageNumber = (uchar)lvalue;
printf("\n");
lvalue = 1;
EnterNum("Enter the application version number", 3, &lvalue, 0, 255);
copr.versionNumber = (uchar)lvalue;
printf("\n");
GetBytes("Enter the binding data in text (32 bytes): ", copr.bindData, 32, 0x00, TRUE);
// GetBytes("Enter the binding code in text (7 bytes): ",
// copr.bindCode, 7, 0x00, TRUE);
memset(copr.bindCode, 0xFF, 7);
memset(copr.initSignature, 0x00, 20);
printf("Enter the initial signature in Hex "
"(20 bytes, all 0x00 by default): \n");
getData(copr.initSignature, 20, TRUE);
PrintHex(copr.initSignature, 20);
printf("\n");
memset(coprFile, 0x00, 255);
namelen = EnterString("Enter the name of the service provider", (char *)coprFile, 1, 50);
copr.providerName = malloc(namelen + 1);
memcpy(copr.providerName, coprFile, namelen);
copr.providerName[namelen] = 0;
printf("\n\n");
memset(coprFile, 0x00, 255);
auxlen = EnterString("Enter any auxilliary info", (char *)coprFile, 1, 100);
copr.auxilliaryData = malloc(auxlen + 1);
memcpy(copr.auxilliaryData, coprFile, auxlen);
copr.auxilliaryData[auxlen] = 0;
printf("\n\n");
lvalue = 1;
EnterNum("Enter an encryption code", 3, &lvalue, 0, 255);
copr.encCode = (uchar)lvalue;
printf("\n");
// Set the signing challenge to all zeroes
memset(copr.signChlg, 0x00, 3);
signlen = GetSecret("System Signing Secret", &signSecret);
authlen = GetSecret("System Authentication Secret", &authSecret);
EnterString("Reformat the secret for DS1961S compatibility", test, 1, 1);
if (test[0] == 'y') {
ReformatSecretFor1961S(authSecret, authlen);
PrintHex(authSecret, authlen);
printf("\n");
copr.ds1961Scompatible = 0x55;
}
#ifndef COPRVM
// now the fun begins
copr.signPageNumber = 8;
printf("Installing signing secret on page %d, secret %d, length %d\n", copr.signPageNumber, copr.signPageNumber & 7, signlen);
PrintHex(signSecret, signlen);
if (!InstallSystemSecret18(copr.portnum, copr.signPageNumber, copr.signPageNumber & 7, signSecret, signlen, FALSE)) {
OWERROR_DUMP(stdout);
exit(1);
}
printf("Installing authentication secret on page %d, secret %d, length %d\n", copr.authPageNumber, copr.authPageNumber & 7,
authlen);
PrintHex(authSecret, authlen);
if (!InstallSystemSecret18(copr.portnum, copr.authPageNumber, copr.authPageNumber & 7, authSecret, authlen, TRUE)) {
OWERROR_DUMP(stdout);
exit(1);
}
#endif
memcpy(coprFile, copr.serviceFilename, 5);
coprFile[5] = copr.signPageNumber;
coprFile[6] = copr.authPageNumber;
coprFile[7] = copr.wspcPageNumber;
coprFile[8] = copr.versionNumber;
memcpy(&coprFile[13], copr.bindData, 32);
memcpy(&coprFile[45], copr.bindCode, 7);
memcpy(&coprFile[52], copr.signChlg, 3);
coprFile[55] = namelen;
coprFile[56] = 20;
coprFile[57] = auxlen;
memcpy(&coprFile[58], copr.providerName, namelen);
memcpy(&coprFile[58 + namelen], copr.initSignature, 20);
memcpy(&coprFile[78 + namelen], copr.auxilliaryData, auxlen);
coprFile[78 + namelen + auxlen] = copr.encCode;
coprFile[79 + namelen + auxlen] = copr.ds1961Scompatible;
#ifdef COPRVM
// open up a file, maybe "shaVM.cnf"
fp = fopen(SHACoprFilename, "wb");
if (fp == NULL) {
printf("Error opening file: %s", SHACoprFilename);
exit(1);
}
len = 80 + namelen + auxlen;
if (fwrite(coprFile, 1, len, fp) != len || fwrite((uchar *)&signlen, 1, 1, fp) != 1 ||
fwrite(signSecret, 1, signlen, fp) != signlen || fwrite((uchar *)&authlen, 1, 1, fp) != 1 ||
fwrite(authSecret, 1, authlen, fp) != authlen) {
printf("Could not write coprocessor config file");
exit(1);
}
#else
// delete any old files
if ((!owFormat(copr.portnum, copr.devAN)) || (!owCreateFile(copr.portnum, copr.devAN, &maxwrite, &handle, &fe))) {
OWERROR_DUMP(stdout);
exit(1);
}
printf("File length %d\n", 80 + namelen + auxlen);
PrintHex(coprFile, 80 + namelen + auxlen);
// check for enough space
if (maxwrite > 80 + namelen + auxlen) {
// write the file to the device
if (!owWriteFile(copr.portnum, copr.devAN, handle, coprFile, 80 + namelen + auxlen)) {
OWERROR_DUMP(stdout);
exit(1);
}
} else {
printf("\n\nNot enough room on device!\n");
}
// and we're done
owRelease(copr.portnum);
#endif
// program is about to exit, but we may as well free these
// up anyways...
free(copr.auxilliaryData);
free(copr.providerName);
free(signSecret);
free(authSecret);
printf("Successfully set up coprocessor!\n");
return 0;
}
static int GetSecret(char *name, uchar **secret) {
uchar inputBuffer[255];
int lvalue = 1, length;
printf("How would you like to enter the %s?\n", name);
EnterNum("\n 1) Hex\n 2) Text\n", 1, &lvalue, 1, 2);
lvalue = getData(inputBuffer, 255, (lvalue == 1));
if (lvalue % 47 != 0)
length = ((lvalue / 47) + 1) * 47;
else
length = lvalue;
*secret = malloc(length);
memset(*secret, 0x00, length);
memcpy(*secret, inputBuffer, lvalue);
printf("length=%d\n", length);
PrintHex(*secret, length);
printf("\n");
return length;
}
static void GetBytes(char *msg, uchar *buffer, int len, uchar defValue, SMALLINT printHex) {
memset(buffer, defValue, len);
printf("%s", msg);
getData(buffer, len, FALSE);
if (printHex) {
PrintHex(buffer, len);
} else {
printf(" You entered: '");
PrintChars(buffer, len);
printf("'\n");
}
printf("\n");
}
w1retap/src/libusblinux300/shadbtvm.c 0000664 0000000 0000000 00000110016 14464462352 0020000 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// shadebitvm.c - Transaction-level functions for SHA Debits without a
// hardware coprocessor. Also, this file contains some
// Protocol-level functions to replace their 'hardware-only'
// counterparts..
//
// Version: 2.10
#include "ownet.h"
#include "shaib.h"
#define MAX_RETRY_CNT 255
// static functions
static int GetSecretVM(char *name, uchar **secret);
// static global vars
static uchar sign_secret[8];
static uchar auth_secret[8];
static uchar wspc_secret[8];
//-------------------------------------------------------------------------
// Returns the user's current balance as an int
//
// 'user' - Structure for holding user token information.
//
// Return: Current value of the user's balance.
//
int GetBalance(SHAUser *user) {
int balance = -1;
if (user->devAN[0] == 0x18)
balance = BytesToInt(((DebitFile *)user->accountFile)->balanceBytes, 3);
else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *acctFile = (DebitFile33 *)user->accountFile;
if (acctFile->fileLength == RECORD_A_LENGTH)
balance = BytesToInt(acctFile->balanceBytes_A, 3);
else if (acctFile->fileLength == RECORD_B_LENGTH)
balance = BytesToInt(acctFile->balanceBytes_B, 3);
else
OWERROR(OWERROR_BAD_SERVICE_DATA);
} else
OWERROR(OWERROR_BAD_SERVICE_DATA);
return balance;
}
//-------------------------------------------------------------------------
// Installs new service data on a user token.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'secret' - the authentication secret to install on user token.
//
// Return: If TRUE, new service installation succeeded.
// If FALSE, an error occurred.
//
SMALLINT InstallServiceData(SHACopr *copr, SHAUser *user, uchar *secret, int secret_length, int initialBalance) {
short handle;
int maxwrite;
FileEntry fe;
uchar fullBindCode[15];
// make sure user has a file directory structure
memcpy(fe.Name, copr->serviceFilename, 4);
fe.Ext = copr->serviceFilename[4];
// install master authentication secret
if (user->devAN[0] == 0x18) {
// need to format the device
if (!owFormat(user->portnum, user->devAN))
return FALSE;
// and create an empty stub for his account information
if (!owCreateFile(user->portnum, user->devAN, &maxwrite, &handle, &fe))
return FALSE;
// need to know what page the stub is on
user->accountPageNumber = fe.Spage;
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
OWASSERT(InstallSystemSecret18(user->portnum, user->accountPageNumber, user->accountPageNumber & 7, secret, secret_length,
FALSE),
OWERROR_INSTALL_SECRET_FAILED, FALSE);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
// because of copy-authorization, we need to install the
// secret first on the DS1961S and _then_ format the system
OWASSERT(InstallSystemSecret33(user->portnum, 0, 0, secret, secret_length, FALSE), OWERROR_INSTALL_SECRET_FAILED, FALSE);
// need to format the device
if (!owFormat(user->portnum, user->devAN))
return FALSE;
// and create an empty stub for his account information
if (!owCreateFile(user->portnum, user->devAN, &maxwrite, &handle, &fe))
return FALSE;
// need to know what page the stub is on
user->accountPageNumber = fe.Spage;
} else {
return FALSE;
}
// format the bind code properly
// first four bytes of bind code
memcpy(fullBindCode, copr->bindCode, 4);
// followed by the pagenumber
fullBindCode[4] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&fullBindCode[5], user->devAN, 7);
// followed by the last 3 bytes of bind code
memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3);
// create a unique secret for iButton
if (user->devAN[0] == 0x18) {
DebitFile *accountFile = (DebitFile *)user->accountFile;
OWASSERT(BindSecretToiButton18(user->portnum, user->accountPageNumber, user->accountPageNumber & 7, copr->bindData,
fullBindCode, TRUE),
OWERROR_BIND_SECRET_FAILED, FALSE);
// do a read just to get value of writecycle counter
user->writeCycleCounter = ReadAuthPageSHA18(user->portnum, user->accountPageNumber, user->accountFile, NULL, TRUE);
// setup user account file with initial balance
IntToBytes(accountFile->balanceBytes, 3, initialBalance);
// set transaction ID
accountFile->transID[0] = 0;
accountFile->transID[0] = 0;
} else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *accountFile33 = (DebitFile33 *)user->accountFile;
OWASSERT(BindSecretToiButton33(user->portnum, user->accountPageNumber, 0, copr->bindData, fullBindCode, TRUE),
OWERROR_BIND_SECRET_FAILED, FALSE);
// Call VerifyUser just to get the user's secret in wspc
if (!VerifyUser(copr, user, TRUE))
return FALSE;
// Record A
// setup user account file with initial balance
IntToBytes(accountFile33->balanceBytes_A, 3, initialBalance);
// set transaction ID
accountFile33->transID_A[0] = 0;
accountFile33->transID_A[0] = 0;
// Record B
// setup user account file with initial balance
IntToBytes(accountFile33->balanceBytes_B, 3, initialBalance);
// set transaction ID
accountFile33->transID_B[0] = 0;
accountFile33->transID_B[0] = 0;
}
// sign the data with coprocessor and write it out
return UpdateServiceData(copr, user);
}
//-------------------------------------------------------------------------
// Updates service data on a user token. This includes signing the
// data if the part is a DS1963S.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
//
// Return: If TRUE, update succeeded.
// If FALSE, an error occurred.
//
SMALLINT UpdateServiceData(SHACopr *copr, SHAUser *user) {
ushort crc16, i;
uchar scratchpad[32];
if (user->devAN[0] == 0x18) {
DebitFile *accountFile = (DebitFile *)user->accountFile;
// make sure length is right.
accountFile->fileLength = 29;
// update transaction ID
// doesn't matter what it is, just needs to change
accountFile->transID[0] += 1;
if (accountFile->transID[0] == 0)
accountFile->transID[1] += 1;
// conversion factor - 2 data bytes
accountFile->convFactor[0] = (uchar)0x8B;
accountFile->convFactor[1] = (uchar)0x48;
// clear out the old signature and CRC
memcpy(accountFile->signature, copr->initSignature, 20);
memset(accountFile->crc16, 0x00, 2);
// reset data type code
accountFile->dataTypeCode = 1;
// file doesn't continue on another page
accountFile->contPtr = 0;
// --- Set up the scratchpad for signing
memset(scratchpad, 0x00, 32);
// the write cycle counter +1 (since we are about to write this to it)
if (user->writeCycleCounter > 0)
IntToBytes(&scratchpad[8], 4, user->writeCycleCounter + 1);
else
// user doesn't have write cycle counter (DS1961S)
memset(&scratchpad[8], 0x0FF, 4);
// the pagenumber
scratchpad[12] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&scratchpad[13], user->devAN, 7);
// the coprocessor's signing challenge
memcpy(&scratchpad[20], copr->signChlg, 3);
OWASSERT(CreateDataSignatureVM(copr, sign_secret, user->accountFile, scratchpad, accountFile->signature, TRUE),
OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE);
// add the crc at the end of the data.
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < 30; i++)
crc16 = docrc16(user->portnum, user->accountFile[i]);
crc16 = ~crc16;
accountFile->crc16[0] = (uchar)crc16;
accountFile->crc16[1] = (uchar)(crc16 >> 8);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *accountFile33 = (DebitFile33 *)user->accountFile;
// conversion factor - 2 data bytes
accountFile33->convFactor[0] = (uchar)0x8B;
accountFile33->convFactor[1] = (uchar)0x48;
// reset data type code
accountFile33->dataTypeCode = 1;
if (accountFile33->fileLength == RECORD_A_LENGTH) {
// Switch to Record B
accountFile33->fileLength = RECORD_B_LENGTH;
// update transaction ID
// doesn't matter what it is, just needs to change
accountFile33->transID_B[0] += 1;
if (accountFile33->transID_B[0] == 0)
accountFile33->transID_B[1] += 1;
// file doesn't continue on another page
accountFile33->contPtr_B = 0;
// clear out the old CRC
memset(accountFile33->crc16_B, 0x00, 2);
// add the crc at the end of the data.
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < RECORD_B_LENGTH + 1; i++)
crc16 = docrc16(user->portnum, user->accountFile[i]);
crc16 = ~crc16;
accountFile33->crc16_B[0] = (uchar)crc16;
accountFile33->crc16_B[1] = (uchar)(crc16 >> 8);
} else {
// Switch to Record B
accountFile33->fileLength = RECORD_A_LENGTH;
// update transaction ID
// doesn't matter what it is, just needs to change
accountFile33->transID_A[0] += 1;
if (accountFile33->transID_A[0] == 0)
accountFile33->transID_A[1] += 1;
// file doesn't continue on another page
accountFile33->contPtr_A = 0;
// clear out the old CRC
memset(accountFile33->crc16_A, 0x00, 2);
// add the crc at the end of the data.
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < RECORD_A_LENGTH + 1; i++)
crc16 = docrc16(user->portnum, user->accountFile[i]);
crc16 = ~crc16;
accountFile33->crc16_A[0] = (uchar)crc16;
accountFile33->crc16_A[1] = (uchar)(crc16 >> 8);
}
}
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
if (user->devAN[0] == 0x18) {
// DS1963S - not too tough
OWASSERT(WriteDataPageSHA18(user->portnum, user->accountPageNumber, user->accountFile, FALSE),
OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
OWASSERT(WriteDataPageSHA33(copr, user), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
} else
return FALSE;
return TRUE;
}
//-------------------------------------------------------------------------
// Verifies a user token as a valid member of the system. First, a random
// challenge is generated. Then, the user must answer that challenge.
// The user's response signature is then verified against the proper
// response..
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'doBind' - if true, the user's unique secret is recreated on the
// coprocessor. If this function is called multiple times,
// it is acceptable to skip the bind for all calls after
// the first on the same user token.
//
// Return: If TRUE, user was verified.
// If FALSE, an error occurred or user verification failed.
//
SMALLINT VerifyUser(SHACopr *copr, SHAUser *user, SMALLINT doBind) {
uchar chlg[3];
int randomNum, i;
// Create Challenge
randomNum = rand();
for (i = 0; i < 3; i++) {
chlg[i] = (uchar)randomNum;
randomNum >>= 8;
}
OWASSERT(AnswerChallenge(user, chlg) >= 0, OWERROR_ANSWER_CHALLENGE_FAILED, FALSE);
if (!VerifyAuthResponseVM(copr, user, chlg, doBind)) {
OWERROR(OWERROR_VERIFY_AUTH_RESPONSE_FAILED);
if ((user->devAN[0] & 0x7F) == 0x33)
RefreshPage33(user->portnum, user->accountPageNumber, FALSE);
return FALSE;
}
return TRUE;
}
//-------------------------------------------------------------------------
// Verifies service data on a user token as a valid member of the system.
// Pre-condition: must call verify user first.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
//
// Return: If TRUE, data was verified.
// If FALSE, an error occurred or data verification failed.
//
SMALLINT VerifyData(SHACopr *copr, SHAUser *user) {
uchar scratchpad[32];
DebitFile acctFile;
ushort lastcrc16 = 0;
uchar i;
// Check the CRC of the file
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < user->accountFile[0] + 3; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
if ((user->devAN[0] & 0x7F) == 0x33) {
// save the original file length
uchar origPtr = user->accountFile[0];
SMALLINT validA = FALSE, validB = FALSE, validPtr = FALSE;
// is the file length a valid value
if (origPtr == RECORD_A_LENGTH || origPtr == RECORD_B_LENGTH)
validPtr = TRUE;
// was the crc of the file correct?
if (lastcrc16 == 0xB001) {
// if the header points to a valid record, we're done
if (validPtr) {
// nothing more to check for DS1961S/DS2432, since
// it carries no signed data, we're finished
return TRUE;
}
// header points to neither record A nor B, but
// crc is absolutely correct. that can only mean
// we're looking at something that is the wrong
// size from what was expected, but apparently is
// exactly what was meant to be written. I'm done.
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
// lets try Record A and check the crc
user->accountFile[0] = RECORD_A_LENGTH;
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < user->accountFile[0] + 3; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
if (lastcrc16 == 0xB001)
validA = TRUE;
// lets try Record B and check the crc
user->accountFile[0] = RECORD_B_LENGTH;
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < user->accountFile[0] + 3; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
if (lastcrc16 == 0xB001)
validB = TRUE;
if (validA && validB) {
// Both A & B are valid! And we know that we can only
// get here if the pointer or the header was not valid.
// That means that B was the last updated one but the
// header got hosed and the debit was not finished...
// which means A is the last known good value, let's go with A.
user->accountFile[0] = RECORD_A_LENGTH;
OWASSERT(WriteDataPageSHA33(copr, user), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
return TRUE;
} else if (validA) {
// B is invalid, A is valid. Means A is the last updated one,
// but B is the last known good value. The header was not updated
// to point to A before debit was aborted. Let's go with B
user->accountFile[0] = RECORD_B_LENGTH;
// must fix B's CRC
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < RECORD_B_LENGTH + 1; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
lastcrc16 = ~lastcrc16;
((DebitFile33 *)user->accountFile)->crc16_B[0] = (uchar)lastcrc16;
((DebitFile33 *)user->accountFile)->crc16_B[1] = (uchar)(lastcrc16 >> 8);
OWASSERT(WriteDataPageSHA33(copr, user), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
return TRUE;
} else if (validB) {
// A is invalid, B is valid. Should never ever happen. Something
// got completely hosed. What should happen here?
user->accountFile[0] = origPtr;
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
// neither record contains a valid CRC. What should happen here?
user->accountFile[0] = origPtr;
OWERROR(OWERROR_CRC_FAILED);
return FALSE;
} else {
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
}
memset(scratchpad, 0x00, 32);
if (user->writeCycleCounter > 0)
IntToBytes(&scratchpad[8], 4, user->writeCycleCounter);
else
// user doesn't have write cycle counter (DS1961S)
memset(&scratchpad[8], 0x0FF, 4);
// the pagenumber
scratchpad[12] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&scratchpad[13], user->devAN, 7);
// the coprocessor's signing challenge
memcpy(&scratchpad[20], copr->signChlg, 3);
// make a copy of the account file
memcpy((uchar *)&acctFile, user->accountFile, 32);
// clear out the old signature and CRC
memcpy(acctFile.signature, copr->initSignature, 20);
memset(acctFile.crc16, 0x00, 2);
OWASSERT(CreateDataSignatureVM(copr, sign_secret, (uchar *)&acctFile, scratchpad, ((DebitFile *)user->accountFile)->signature,
FALSE),
OWERROR_MATCH_SERVICE_SIGNATURE_FAILED, FALSE);
return TRUE;
}
//-------------------------------------------------------------------------
// Performs debit of service data on a user token, re-signs the data, and
// writes it back to the user token.
// Pre-condition: must call verify user first.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'debitAmount' - the amount of money to debit from balance in cents.
// 'verifySuccess' - Paranoid double-check of account write by re-calling
// VerifyUser(copr,user)
//
// Return: If TRUE, data was updated.
// If FALSE, an error occurred or couldn't verify success.
//
SMALLINT ExecuteTransaction(SHACopr *copr, SHAUser *user, int debitAmount, SMALLINT verifySuccess) {
SMALLINT success, dataOK = TRUE;
uchar oldAcctData[32], newAcctData[32];
int cnt = MAX_RETRY_CNT;
int balance, oldBalance;
memcpy(oldAcctData, user->accountFile, 32);
if (user->devAN[0] == 0x18) {
DebitFile *accountFile = (DebitFile *)user->accountFile;
oldBalance = BytesToInt(accountFile->balanceBytes, 3);
if (oldBalance <= 0) {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
balance = oldBalance - debitAmount;
IntToBytes(accountFile->balanceBytes, 3, balance);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *accountFile = (DebitFile33 *)user->accountFile;
if (accountFile->fileLength == RECORD_A_LENGTH) {
oldBalance = BytesToInt(accountFile->balanceBytes_A, 3);
if (oldBalance <= 0) {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
balance = oldBalance - debitAmount;
IntToBytes(accountFile->balanceBytes_B, 3, balance);
} else if (accountFile->fileLength == RECORD_B_LENGTH) {
oldBalance = BytesToInt(accountFile->balanceBytes_B, 3);
if (oldBalance <= 0) {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
balance = oldBalance - debitAmount;
IntToBytes(accountFile->balanceBytes_A, 3, balance);
} else {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
}
success = UpdateServiceData(copr, user);
// if write didn't succeeded or if we need to perform
// a verification step anyways, let's double-check what
// the user has on the button.
if (verifySuccess || !success) {
dataOK = FALSE;
// save what the account data is supposed to look like
memcpy(newAcctData, user->accountFile, 32);
do {
// calling verify user re-issues a challenge-response
// and reloads the cached account data in the user object.
// Does not re-bind the user's unique secret
if (VerifyUser(copr, user, FALSE)) {
// compare the user's account data against the working
// copy and the backup copy.
if (memcmp(user->accountFile, newAcctData, 32) == 0) {
// looks like it worked
dataOK = TRUE;
} else if (memcmp(user->accountFile, oldAcctData, 32) == 0) {
// if it matches the backup copy, we didn't write anything
// and the data is still okay, but we didn't do a debit
dataOK = TRUE;
success = FALSE;
OWERROR(OWERROR_SERVICE_DATA_NOT_UPDATED);
} else {
// retry the write
success = UpdateServiceData(copr, user);
// save what the account data is supposed to look like
memcpy(newAcctData, user->accountFile, 32);
}
}
} while (dataOK == FALSE && cnt-- > 0);
}
if (!dataOK) {
// couldn't fix the data after 255 retries
OWERROR(OWERROR_CATASTROPHIC_SERVICE_FAILURE);
success = FALSE;
}
return success;
}
//-------------------------------------------------------------------------
// Verifies the authentication response of a user token without a
// hardware coprocessor.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'chlg' - 3-byte buffer of challenge data.
// 'doBind' - if true, the user's unique secret is recreated on the
// coprocessor. If this function is called multiple times,
// it is acceptable to skip the bind for all calls after
// the first on the same user token.
//
// Return: If TRUE, the user's authentication response matched exactly the
// signature generated by the coprocessor.
// If FALSE, an error occurred or the signature did not match.
//
SMALLINT VerifyAuthResponseVM(SHACopr *copr, SHAUser *user, uchar *chlg, SMALLINT doBind) {
int wcc = user->writeCycleCounter;
uchar scratchpad[32];
uchar fullBindCode[15];
uchar temp_buf[32];
// M-X control byte
uchar MXP = 0x00;
memset(scratchpad, 0x00, 32);
memset(fullBindCode, 0x0FF, 15);
// format the bind code properly
if (user->devAN[0] == 0x18) {
// Format for DS1963S
memcpy(fullBindCode, copr->bindCode, 4);
memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3);
// copy wcc LSB first
IntToBytes(&scratchpad[8], 4, wcc);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
// Leave bindCode FF for DS1961S
// Use AuthenticateHost command
MXP = 0x40;
// the user doesn't have a write cycle counter
memset(&scratchpad[8], 0x0FF, 4);
} else {
OWERROR(OWERROR_WRONG_TYPE);
return FALSE;
}
// the pagenumber
fullBindCode[4] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&fullBindCode[5], user->devAN, 7);
// get the user address and page num from fullBindCode
memcpy(&scratchpad[12], &fullBindCode[4], 8);
// set the same challenge bytes
memcpy(&scratchpad[20], chlg, 3);
// Fix the M-X control bits
scratchpad[12] = (uchar)((scratchpad[12] & 0x3F) | (MXP & 0xC0));
memset(temp_buf, 0x00, 32);
memcpy(&temp_buf[8], fullBindCode, 15);
// install user's unique secret on the wspc secret
// Just like BindSecretToiButton for standard coprocessor
if (doBind) {
OWASSERT(CreateDataSignatureVM(copr, auth_secret, copr->bindData, temp_buf, temp_buf, TRUE), OWERROR_BIND_SECRET_FAILED,
FALSE);
memcpy(wspc_secret, temp_buf, 8);
}
// recreate the signature and verify
OWASSERT(CreateDataSignatureVM(copr, wspc_secret, user->accountFile, scratchpad, user->responseMAC, FALSE),
OWERROR_VERIFY_SIG_FAILED, FALSE);
return TRUE;
}
//-------------------------------------------------------------------------
// Creates a data signature for the given data buffer without a hardware
// coprocessor.
//
// 'copr' - Structure for holding coprocessor information.
// 'data' - data written to the data page to sign
// 'scratchpad' - data written to the scratchpad to sign
// 'signature' - data buffer which is either holding the signature that
// must match exactly what is generated on the coprocessor
// -or- will hold the resulting signature created by the
// coprocessor.
// 'readSignature' - implies whether or not the signature buffer
// receives the contents of the scratchpad or is used to
// match the contents of the scratchpad. If true,
// scratchpad contents are read into the signature buffer.
//
// Return: If TRUE, the user's authentication response matched exactly the
// signature generated by the coprocessor or the signature was
// successfully copied into the return buffer.
// If FALSE, an error occurred or the signature did not match.
//
SMALLINT CreateDataSignatureVM(SHACopr *copr, uchar *secret, uchar *data, uchar *scratchpad, uchar *signature,
SMALLINT readSignature) {
SMALLINT i, j, offset;
int hash[5], temp;
uchar digestBuff[64];
// Set up the 64 byte buffer for computing the digest.
memcpy(digestBuff, secret, 4);
memcpy(&digestBuff[4], data, 32);
memcpy(&digestBuff[36], &scratchpad[8], 12);
memcpy(&digestBuff[48], &secret[4], 4);
memcpy(&digestBuff[52], &scratchpad[20], 3);
// digest buffer padding
digestBuff[55] = (uchar)0x80;
memset(&digestBuff[56], 0x00, 6);
digestBuff[62] = (uchar)0x01;
digestBuff[63] = (uchar)0xB8;
ComputeSHAVM(digestBuff, hash);
// iButtons use LSB first, so we have to turn
// the result around a little bit. Instead of
// result A-B-C-D-E, our result is E-D-C-B-A,
// where each letter represents four bytes of
// the result.
for (j = 4; j >= 0; j--) {
temp = hash[j];
offset = (4 - j) * 4;
for (i = 0; i < 4; i++) {
if (readSignature) {
// reading the signature into a buffer
signature[i + offset] = (uchar)temp;
} else {
// trying to match the signature;
OWASSERT(signature[i + offset] == (uchar)temp, OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE);
}
temp >>= 8;
}
}
// PrintHexLabeled("signature", signature, 20);
return TRUE;
}
//----------------------------------------------------------------------
// Installs new system secret for VM. input_secret must be
// divisible by 47. Then, each block of 47 is split up with 32 bytes
// written to a data page and 15 bytes are written to the scratchpad.
// Then, Compute first secret is called (or compute next if the secret
// is divisible by 47 more than once).
//
// 'copr' - Structure for holding coprocessor information.
// 'input_secret' - the input secret buffer used.
// 'secret_length' - the length of the input secret buffer, divisibly
// by 47.
// 'dst_secret' - the buffer where resulting secret is copied.
//
// Return: TRUE - Install successfull
// FALSE - error occurred during secret installation.
//
SMALLINT InstallSystemSecretVM(SHACopr *copr, uchar *secret, int secret_length, uchar *dst_secret) {
int offset = 0, bytes_left = 0;
uchar data[32], scratchpad[32];
// PrintHexLabeled("Installing secret",secret,secret_length);
for (offset = 0; offset < secret_length; offset += 47) {
// clear the buffer
memset(data, 0x0FF, 32);
memset(scratchpad, 0x0FF, 32);
// Determine the amount of bytes remaining to be installed.
bytes_left = secret_length - offset;
// copy secret data into page buffer and scratchpad buffer
memcpy(data, &secret[offset], (bytes_left < 32 ? bytes_left : 32));
if (bytes_left > 32) {
memcpy(&scratchpad[8], &secret[offset + 32], (bytes_left < 47 ? bytes_left - 32 : 15));
}
// fix the M-X control bits
scratchpad[12] = scratchpad[12] & 0x3F;
// PrintHexLabeled(" using secret",dst_secret,8);
// PrintHexLabeled(" using data",data,32);
// PrintHexLabeled(" using spad",scratchpad,32);
// install user's unique secret on the wspc secret
// Just like BindSecretToiButton for standard coprocessor
OWASSERT(CreateDataSignatureVM(copr, dst_secret, data, scratchpad, scratchpad, TRUE), OWERROR_BIND_SECRET_FAILED, FALSE);
memcpy(dst_secret, scratchpad, 8);
}
return TRUE;
}
//----------------------------------------------------------------------
// Installs new system signing secret for VM. input_secret must be
// divisible by 47. Then, each block of 47 is split up with 32 bytes
// written to a data page and 15 bytes are written to the scratchpad.
// Then, Compute first secret is called (or compute next if the secret
// is divisible by 47 more than once).
//
// 'copr' - Structure for holding coprocessor information.
// 'secretnum' - destination secret for computation results
// 'input_secret' - the input secret buffer used.
// 'secret_length' - the length of the input secret buffer, divisibly
// by 47.
//
// Return: TRUE - Install successfull
// FALSE - error occurred during secret installation.
//
SMALLINT InstallSignSecretVM(SHACopr *copr, uchar *secret, int secret_length) {
int i;
memset(sign_secret, 0x00, 8);
i = InstallSystemSecretVM(copr, secret, secret_length, sign_secret);
return i;
}
//----------------------------------------------------------------------
// Installs new system signing secret for VM. input_secret must be
// divisible by 47. Then, each block of 47 is split up with 32 bytes
// written to a data page and 15 bytes are written to the scratchpad.
// Then, Compute first secret is called (or compute next if the secret
// is divisible by 47 more than once).
// Note: as a side-effect, the random number generator is seeded in this
// function as well.
//
// 'copr' - Structure for holding coprocessor information.
// 'secretnum' - destination secret for computation results
// 'input_secret' - the input secret buffer used.
// 'secret_length' - the length of the input secret buffer, divisibly
// by 47.
//
// Return: TRUE - Install successfull
// FALSE - error occurred during secret installation.
//
SMALLINT InstallAuthSecretVM(SHACopr *copr, uchar *secret, int secret_length) {
int i;
memset(auth_secret, 0x00, 8);
i = InstallSystemSecretVM(copr, secret, secret_length, auth_secret);
// at bare minimum, InstallAuthSecretVM must be called before the
// VM coprocessor can be used. We can take advantage of this fact
// and use this opportunity to seed the random number generator.
srand(((unsigned int)time(NULL)) ^ ((secret[3]) | (secret[5] << 8) | (secret[7] << 16) | (secret[11] << 24)));
// is that random? although deterministic, it's got to be at the
// very least hard to predict. it depends on user input which should
// be kept top secret.
return i;
}
//----------------------------------------------------------------------
// Loads the Coprocessor VM's config info from either a config file or
// an emulated coprocessor.
//
// 'copr' - Structure for holding coprocessor information.
// 'fe' - FileEntry to look for on emulated coprocessor
//
// Return: TRUE - GetCoprocessor successfull
// FALSE - error occurred
//
SMALLINT GetCoprVM(SHACopr *copr, FileEntry *fe) {
FILE *fp;
uchar *signSecret, *authSecret;
int signlen, authlen, len, index;
int lvalue = 1;
char test[2] = {'y', 0};
uchar buffer[255];
printf("How would you like to initialize the VM?");
EnterNum("\n 1) Load VM info from file\n "
"2) Emulate another coprocessor\n",
1, &lvalue, 1, 2);
if (lvalue == 1) {
// open up a file, maybe "shaVM.cnf"
fp = fopen(SHACoprFilename, "rb");
if (fp == NULL) {
printf("file not found: %s\n", SHACoprFilename);
return FALSE;
}
len = fread(buffer, 1, 255, fp);
if (len <= 0) {
printf("Could not read coprocessor config file\n");
return FALSE;
}
index = GetCoprFromRawData(copr, buffer, len);
// get the signing secret
signlen = buffer[index];
signSecret = malloc(signlen);
memcpy(signSecret, &buffer[index + 1], signlen);
// get the authentication secret
index += signlen + 1;
authlen = buffer[index];
authSecret = malloc(authlen);
memcpy(authSecret, &buffer[index + 1], authlen);
} else {
if (!FindCoprSHA(copr, fe)) {
printf("no coprocessor found!\n");
return FALSE;
}
signlen = GetSecretVM("System Signing Secret", &signSecret);
authlen = GetSecretVM("System Authentication Secret", &authSecret);
EnterString("Reformat the secret for DS1961S compatibility", test, 1, 1);
if (test[0] == 'y') {
ReformatSecretFor1961S(authSecret, authlen);
PrintHex(authSecret, authlen);
printf("\n");
copr->ds1961Scompatible = 0x55;
}
}
InstallAuthSecretVM(copr, authSecret, authlen);
InstallSignSecretVM(copr, signSecret, signlen);
free(authSecret);
free(signSecret);
return TRUE;
}
//----------------------------------------------------------------------
// Used for querying the user for secret information
//
// 'name' - type of secret (authentication or signing)
// 'secret' - resulting secret data
//
// Returns: The length of the secret
//
static int GetSecretVM(char *name, uchar **secret) {
uchar inputBuffer[255];
int lvalue = 1, length;
printf("How would you like to enter the %s?\n", name);
EnterNum("\n 1) Hex\n 2) Text\n", 1, &lvalue, 1, 2);
lvalue = getData(inputBuffer, 255, (lvalue == 1));
if (lvalue % 47 != 0)
length = ((lvalue / 47) + 1) * 47;
else
length = lvalue;
*secret = malloc(length);
memset(*secret, 0x00, length);
memcpy(*secret, inputBuffer, lvalue);
printf("length=%d\n", length);
PrintHex(*secret, length);
printf("\n");
return (int)length;
}
//----------------------------------------------------------------------
// Writes the contents of the user's account file to the page specified
// by the user's account page number for DS1961.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
//
// Return: TRUE - Write successfull
// FALSE - error occurred during write.
//
SMALLINT WriteDataPageSHA33(SHACopr *copr, SHAUser *user) {
// DS1961S - a bit tougher
// assumes wspc_secret already contains device's unique secret.
uchar pageContents[32], data[32], scratchpad[32];
uchar MAC[20];
int addr = user->accountPageNumber << 5;
int i;
OWASSERT(ReadMemoryPageSHA33(user->portnum, user->accountPageNumber, pageContents, FALSE), OWERROR_READ_MEMORY_PAGE_FAILED,
FALSE);
for (i = 24; i >= 0; i -= 8) {
if (memcmp(&pageContents[i], &user->accountFile[i], 8) != 0) {
memcpy(data, pageContents, 28);
memcpy(&data[28], &user->accountFile[i], 4);
memcpy(&scratchpad[8], &user->accountFile[i + 4], 4);
scratchpad[12] = (uchar)(user->accountPageNumber & 0x3F);
memcpy(&scratchpad[13], user->devAN, 7);
memset(&scratchpad[20], 0xFF, 3);
OWASSERT(CreateDataSignatureVM(copr, wspc_secret, data, scratchpad, MAC, TRUE), OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE);
OWASSERT(WriteScratchpadSHA33(user->portnum, addr + i, &user->accountFile[i], TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED,
FALSE);
OWASSERT(CopyScratchpadSHA33(user->portnum, addr + i, MAC, TRUE), OWERROR_COPY_SCRATCHPAD_FAILED, FALSE);
memcpy(&pageContents[i], &user->accountFile[i], 8);
}
}
return TRUE;
}
w1retap/src/libusblinux300/shadebit.c 0000664 0000000 0000000 00000056675 14464462352 0017777 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// shadebit.c - Transaction-level functions for SHA Debits without a
// hardware coprocessor. Also, this file contains some
// Protocol-level functions to replace their 'hardware-only'
// counterparts..
//
// Version: 2.10
#include "shaib.h"
#define MAX_RETRY_CNT 255
//-------------------------------------------------------------------------
// Returns the user's current balance as an int
//
// 'user' - Structure for holding user token information.
//
// Return: Current value of the user's balance.
//
int GetBalance(SHAUser *user) {
int balance = -1;
if (user->devAN[0] == 0x18)
balance = BytesToInt(((DebitFile *)user->accountFile)->balanceBytes, 3);
else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *acctFile = (DebitFile33 *)user->accountFile;
if (acctFile->fileLength == RECORD_A_LENGTH)
balance = BytesToInt(acctFile->balanceBytes_A, 3);
else if (acctFile->fileLength == RECORD_B_LENGTH)
balance = BytesToInt(acctFile->balanceBytes_B, 3);
else
OWERROR(OWERROR_BAD_SERVICE_DATA);
} else
OWERROR(OWERROR_BAD_SERVICE_DATA);
return balance;
}
//-------------------------------------------------------------------------
// Installs new service data on a user token.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'secret' - the authentication secret to install on user token.
//
// Return: If TRUE, new service installation succeeded.
// If FALSE, an error occurred.
//
SMALLINT InstallServiceData(SHACopr *copr, SHAUser *user, uchar *secret, int secret_length, int initialBalance) {
short handle;
int maxwrite;
FileEntry fe;
uchar fullBindCode[15];
// make sure user has a file directory structure
memcpy(fe.Name, copr->serviceFilename, 4);
fe.Ext = copr->serviceFilename[4];
// install master authentication secret
if (user->devAN[0] == 0x18) {
// need to format the device
if (!owFormat(user->portnum, user->devAN))
return FALSE;
// and create an empty stub for his account information
if (!owCreateFile(user->portnum, user->devAN, &maxwrite, &handle, &fe))
return FALSE;
// need to know what page the stub is on
user->accountPageNumber = fe.Spage;
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
OWASSERT(InstallSystemSecret18(user->portnum, user->accountPageNumber, user->accountPageNumber & 7, secret, secret_length,
FALSE),
OWERROR_INSTALL_SECRET_FAILED, FALSE);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
// because of copy-authorization, we need to install the
// secret first on the DS1961S and _then_ format the system
OWASSERT(InstallSystemSecret33(user->portnum, 0, 0, secret, secret_length, FALSE), OWERROR_INSTALL_SECRET_FAILED, FALSE);
// need to format the device
if (!owFormat(user->portnum, user->devAN))
return FALSE;
// and create an empty stub for his account information
if (!owCreateFile(user->portnum, user->devAN, &maxwrite, &handle, &fe))
return FALSE;
// need to know what page the stub is on
user->accountPageNumber = fe.Spage;
} else {
return FALSE;
}
// format the bind code properly
// first four bytes of bind code
memcpy(fullBindCode, copr->bindCode, 4);
// followed by the pagenumber
fullBindCode[4] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&fullBindCode[5], user->devAN, 7);
// followed by the last 3 bytes of bind code
memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3);
// create a unique secret for iButton
if (user->devAN[0] == 0x18) {
DebitFile *accountFile = (DebitFile *)user->accountFile;
OWASSERT(BindSecretToiButton18(user->portnum, user->accountPageNumber, user->accountPageNumber & 7, copr->bindData,
fullBindCode, TRUE),
OWERROR_BIND_SECRET_FAILED, FALSE);
// do a read just to get value of writecycle counter
user->writeCycleCounter = ReadAuthPageSHA18(user->portnum, user->accountPageNumber, user->accountFile, NULL, TRUE);
// setup user account file with initial balance
IntToBytes(accountFile->balanceBytes, 3, initialBalance);
// set transaction ID
accountFile->transID[0] = 0;
accountFile->transID[0] = 0;
} else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *accountFile33 = (DebitFile33 *)user->accountFile;
OWASSERT(BindSecretToiButton33(user->portnum, user->accountPageNumber, 0, copr->bindData, fullBindCode, TRUE),
OWERROR_BIND_SECRET_FAILED, FALSE);
// Call VerifyUser just to get the user's secret in wspc
if (!VerifyUser(copr, user, TRUE))
return FALSE;
// Record A
// setup user account file with initial balance
IntToBytes(accountFile33->balanceBytes_A, 3, initialBalance);
// set transaction ID
accountFile33->transID_A[0] = 0;
accountFile33->transID_A[0] = 0;
// Record B
// setup user account file with initial balance
IntToBytes(accountFile33->balanceBytes_B, 3, initialBalance);
// set transaction ID
accountFile33->transID_B[0] = 0;
accountFile33->transID_B[0] = 0;
}
// sign the data with coprocessor and write it out
return UpdateServiceData(copr, user);
}
//-------------------------------------------------------------------------
// Updates service data on a user token. This includes signing the
// data if the part is a DS1963S.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
//
// Return: If TRUE, update succeeded.
// If FALSE, an error occurred.
//
SMALLINT UpdateServiceData(SHACopr *copr, SHAUser *user) {
ushort crc16;
int i;
uchar scratchpad[32];
if (user->devAN[0] == 0x18) {
DebitFile *accountFile = (DebitFile *)user->accountFile;
// make sure length is right.
accountFile->fileLength = 29;
// update transaction ID
// doesn't matter what it is, just needs to change
accountFile->transID[0] += 1;
if (accountFile->transID[0] == 0)
accountFile->transID[1] += 1;
// conversion factor - 2 data bytes
accountFile->convFactor[0] = (uchar)0x8B;
accountFile->convFactor[1] = (uchar)0x48;
// clear out the old signature and CRC
memcpy(accountFile->signature, copr->initSignature, 20);
memset(accountFile->crc16, 0x00, 2);
// reset data type code
accountFile->dataTypeCode = 1;
// file doesn't continue on another page
accountFile->contPtr = 0;
// --- Set up the scratchpad for signing
memset(scratchpad, 0x00, 32);
// the write cycle counter +1 (since we are about to write this to it)
if (user->writeCycleCounter > 0)
IntToBytes(&scratchpad[8], 4, user->writeCycleCounter + 1);
else
// user doesn't have write cycle counter (DS1961S)
memset(&scratchpad[8], 0x0FF, 4);
// the pagenumber
scratchpad[12] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&scratchpad[13], user->devAN, 7);
// the coprocessor's signing challenge
memcpy(&scratchpad[20], copr->signChlg, 3);
OWASSERT(CreateDataSignature(copr, user->accountFile, scratchpad, accountFile->signature, TRUE),
OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE);
// add the crc at the end of the data.
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < 30; i++)
crc16 = docrc16(user->portnum, user->accountFile[i]);
crc16 = ~crc16;
accountFile->crc16[0] = (uchar)crc16;
accountFile->crc16[1] = (uchar)(crc16 >> 8);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *accountFile33 = (DebitFile33 *)user->accountFile;
// conversion factor - 2 data bytes
accountFile33->convFactor[0] = (uchar)0x8B;
accountFile33->convFactor[1] = (uchar)0x48;
// reset data type code
accountFile33->dataTypeCode = 1;
if (accountFile33->fileLength == RECORD_A_LENGTH) {
// Switch to Record B
accountFile33->fileLength = RECORD_B_LENGTH;
// update transaction ID
// doesn't matter what it is, just needs to change
accountFile33->transID_B[0] += 1;
if (accountFile33->transID_B[0] == 0)
accountFile33->transID_B[1] += 1;
// file doesn't continue on another page
accountFile33->contPtr_B = 0;
// clear out the old CRC
memset(accountFile33->crc16_B, 0x00, 2);
// add the crc at the end of the data.
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < RECORD_B_LENGTH + 1; i++)
crc16 = docrc16(user->portnum, user->accountFile[i]);
crc16 = ~crc16;
accountFile33->crc16_B[0] = (uchar)crc16;
accountFile33->crc16_B[1] = (uchar)(crc16 >> 8);
} else {
// Switch to Record B
accountFile33->fileLength = RECORD_A_LENGTH;
// update transaction ID
// doesn't matter what it is, just needs to change
accountFile33->transID_A[0] += 1;
if (accountFile33->transID_A[0] == 0)
accountFile33->transID_A[1] += 1;
// file doesn't continue on another page
accountFile33->contPtr_A = 0;
// clear out the old CRC
memset(accountFile33->crc16_A, 0x00, 2);
// add the crc at the end of the data.
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < RECORD_A_LENGTH + 1; i++)
crc16 = docrc16(user->portnum, user->accountFile[i]);
crc16 = ~crc16;
accountFile33->crc16_A[0] = (uchar)crc16;
accountFile33->crc16_A[1] = (uchar)(crc16 >> 8);
}
}
// set the serial number to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
if (user->devAN[0] == 0x18) {
// DS1963S - not too tough
OWASSERT(WriteDataPageSHA18(user->portnum, user->accountPageNumber, user->accountFile, FALSE),
OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
// DS1961S - a bit tougher
// assumes sign_secret for this coprocessor already has
// the user's unique secret installed
OWASSERT(WriteDataPageSHA33(copr, user), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
} else
return FALSE;
return TRUE;
}
//----------------------------------------------------------------------
// Writes the contents of the user's account file to the page specified
// by the user's account page number for DS1961.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
//
// Return: TRUE - Write successfull
// FALSE - error occurred during write.
//
SMALLINT WriteDataPageSHA33(SHACopr *copr, SHAUser *user) {
uchar pageContents[32], data[32], scratchpad[32], MAC[20];
int addr = user->accountPageNumber << 5;
int i;
OWASSERT(ReadMemoryPageSHA33(user->portnum, user->accountPageNumber, pageContents, FALSE), OWERROR_READ_MEMORY_PAGE_FAILED,
FALSE);
for (i = 24; i >= 0; i -= 8) {
if (memcmp(&pageContents[i], &user->accountFile[i], 8) != 0) {
// PrintHexLabeled("Current Page contents", pageContents, 32);
// PrintHexLabeled(" 8 bytes to replace", &pageContents[i], 8);
// PrintHexLabeled(" with these 8 bytes", &user->accountFile[i], 8);
memcpy(data, pageContents, 28);
memcpy(&data[28], &user->accountFile[i], 4);
memcpy(&scratchpad[8], &user->accountFile[i + 4], 4);
scratchpad[12] = (uchar)(user->accountPageNumber & 0x3F);
memcpy(&scratchpad[13], user->devAN, 7);
memset(&scratchpad[20], 0xFF, 3);
// this function changes the serial number to that of copr
OWASSERT(CreateDataSignature(copr, data, scratchpad, MAC, TRUE), OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE);
// set the serial number back to that of the user
owSerialNum(user->portnum, user->devAN, FALSE);
OWASSERT(WriteScratchpadSHA33(user->portnum, addr + i, &user->accountFile[i], FALSE), OWERROR_WRITE_SCRATCHPAD_FAILED,
FALSE);
OWASSERT(CopyScratchpadSHA33(user->portnum, addr + i, MAC, TRUE), OWERROR_COPY_SCRATCHPAD_FAILED, FALSE);
memcpy(&pageContents[i], &user->accountFile[i], 8);
}
}
return TRUE;
}
//-------------------------------------------------------------------------
// Verifies a user token as a valid member of the system. First, a random
// challenge is generated. Then, the user must answer that challenge.
// The user's response signature is then verified against the proper
// response..
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'doBind' - if true, the user's unique secret is recreated on the
// coprocessor. If this function is called multiple times,
// it is acceptable to skip the bind for all calls after
// the first on the same user token.
//
// Return: If TRUE, user was verified.
// If FALSE, an error occurred or user verification failed.
//
SMALLINT VerifyUser(SHACopr *copr, SHAUser *user, SMALLINT doBind) {
uchar chlg[3];
OWASSERT(CreateChallenge(copr, 1, chlg, 0), OWERROR_CREATE_CHALLENGE_FAILED, FALSE);
OWASSERT(AnswerChallenge(user, chlg) >= 0, OWERROR_ANSWER_CHALLENGE_FAILED, FALSE);
if (!VerifyAuthResponse(copr, user, chlg, doBind)) {
OWERROR(OWERROR_VERIFY_AUTH_RESPONSE_FAILED);
if ((user->devAN[0] & 0x7F) == 0x33)
RefreshPage33(user->portnum, user->accountPageNumber, FALSE);
return FALSE;
}
return TRUE;
}
//-------------------------------------------------------------------------
// Verifies service data on a user token as a valid member of the system.
// Pre-condition: must call verify user first.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
//
// Return: If TRUE, data was verified.
// If FALSE, an error occurred or data verification failed.
//
SMALLINT VerifyData(SHACopr *copr, SHAUser *user) {
uchar scratchpad[32];
DebitFile acctFile;
ushort lastcrc16 = 0, i;
// Check the CRC of the file
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < user->accountFile[0] + 3; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
if ((user->devAN[0] & 0x7F) == 0x33) {
// save the original file length
uchar origPtr = user->accountFile[0];
SMALLINT validA = FALSE, validB = FALSE, validPtr = FALSE;
// is the file length a valid value
if (origPtr == RECORD_A_LENGTH || origPtr == RECORD_B_LENGTH)
validPtr = TRUE;
// was the crc of the file correct?
if (lastcrc16 == 0xB001) {
// if the header points to a valid record, we're done
if (validPtr) {
// nothing more to check for DS1961S/DS2432, since
// it carries no signed data, we're finished
return TRUE;
}
// header points to neither record A nor B, but
// crc is absolutely correct. that can only mean
// we're looking at something that is the wrong
// size from what was expected, but apparently is
// exactly what was meant to be written. I'm done.
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
// lets try Record A and check the crc
user->accountFile[0] = RECORD_A_LENGTH;
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < user->accountFile[0] + 3; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
if (lastcrc16 == 0xB001)
validA = TRUE;
// lets try Record B and check the crc
user->accountFile[0] = RECORD_B_LENGTH;
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < user->accountFile[0] + 3; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
if (lastcrc16 == 0xB001)
validB = TRUE;
if (validA && validB) {
// Both A & B are valid! And we know that we can only
// get here if the pointer or the header was not valid.
// That means that B was the last updated one but the
// header got hosed and the debit was not finished...
// which means A is the last known good value, let's go with A.
user->accountFile[0] = RECORD_A_LENGTH;
OWASSERT(WriteDataPageSHA33(copr, user), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
return TRUE;
} else if (validA) {
// B is invalid, A is valid. Means A is the last updated one,
// but B is the last known good value. The header was not updated
// to point to A before debit was aborted. Let's go with B
user->accountFile[0] = RECORD_B_LENGTH;
// must fix B's CRC
setcrc16(user->portnum, user->accountPageNumber);
for (i = 0; i < RECORD_B_LENGTH + 1; i++)
lastcrc16 = docrc16(user->portnum, user->accountFile[i]);
lastcrc16 = ~lastcrc16;
((DebitFile33 *)user->accountFile)->crc16_B[0] = (uchar)lastcrc16;
((DebitFile33 *)user->accountFile)->crc16_B[1] = (uchar)(lastcrc16 >> 8);
OWASSERT(WriteDataPageSHA33(copr, user), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
return TRUE;
} else if (validB) {
// A is invalid, B is valid. Should never ever happen. Something
// got completely hosed. What should happen here?
user->accountFile[0] = origPtr;
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
// neither record contains a valid CRC. What should happen here?
user->accountFile[0] = origPtr;
OWERROR(OWERROR_CRC_FAILED);
return FALSE;
} else {
// verify CRC16 is correct
OWASSERT(lastcrc16 == 0xB001, OWERROR_CRC_FAILED, FALSE);
}
memset(scratchpad, 0x00, 32);
if (user->writeCycleCounter > 0)
IntToBytes(&scratchpad[8], 4, user->writeCycleCounter);
else
// user doesn't have write cycle counter (DS1961S)
memset(&scratchpad[8], 0x0FF, 4);
// the pagenumber
scratchpad[12] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&scratchpad[13], user->devAN, 7);
// the coprocessor's signing challenge
memcpy(&scratchpad[20], copr->signChlg, 3);
// make a copy of the account file
memcpy((uchar *)&acctFile, user->accountFile, 32);
// clear out the old signature and CRC
memcpy(acctFile.signature, copr->initSignature, 20);
memset(acctFile.crc16, 0x00, 2);
OWASSERT(CreateDataSignature(copr, (uchar *)&acctFile, scratchpad, ((DebitFile *)user->accountFile)->signature, FALSE),
OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE);
return TRUE;
}
//-------------------------------------------------------------------------
// Performs debit of service data on a user token, re-signs the data, and
// writes it back to the user token.
// Pre-condition: must call verify user first.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'debitAmount' - the amount of money to debit from balance in cents.
// 'verifySuccess' - Paranoid double-check of account write by re-calling
// VerifyUser(copr,user)
//
// Return: If TRUE, data was updated.
// If FALSE, an error occurred or couldn't verify success.
//
SMALLINT ExecuteTransaction(SHACopr *copr, SHAUser *user, int debitAmount, SMALLINT verifySuccess) {
SMALLINT success, dataOK = TRUE;
uchar oldAcctData[32], newAcctData[32];
int cnt = MAX_RETRY_CNT;
int balance, oldBalance;
memcpy(oldAcctData, user->accountFile, 32);
if (user->devAN[0] == 0x18) {
DebitFile *accountFile = (DebitFile *)user->accountFile;
oldBalance = BytesToInt(accountFile->balanceBytes, 3);
if (oldBalance <= 0) {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
balance = oldBalance - debitAmount;
IntToBytes(accountFile->balanceBytes, 3, balance);
} else if ((user->devAN[0] & 0x7F) == 0x33) {
DebitFile33 *accountFile = (DebitFile33 *)user->accountFile;
if (accountFile->fileLength == RECORD_A_LENGTH) {
oldBalance = BytesToInt(accountFile->balanceBytes_A, 3);
if (oldBalance <= 0) {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
balance = oldBalance - debitAmount;
IntToBytes(accountFile->balanceBytes_B, 3, balance);
} else if (accountFile->fileLength == RECORD_B_LENGTH) {
oldBalance = BytesToInt(accountFile->balanceBytes_B, 3);
if (oldBalance <= 0) {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
balance = oldBalance - debitAmount;
IntToBytes(accountFile->balanceBytes_A, 3, balance);
} else {
OWERROR(OWERROR_BAD_SERVICE_DATA);
return FALSE;
}
}
success = UpdateServiceData(copr, user);
// if write didn't succeeded or if we need to perform
// a verification step anyways, let's double-check what
// the user has on the button.
if (verifySuccess || !success) {
dataOK = FALSE;
// save what the account data is supposed to look like
memcpy(newAcctData, user->accountFile, 32);
do {
// calling verify user re-issues a challenge-response
// and reloads the cached account data in the user object.
// Does not re-bind the user's unique secret
if (VerifyUser(copr, user, FALSE)) {
// compare the user's account data against the working
// copy and the backup copy.
if (memcmp(user->accountFile, newAcctData, 32) == 0) {
// looks like it worked
dataOK = TRUE;
} else if (memcmp(user->accountFile, oldAcctData, 32) == 0) {
// if it matches the backup copy, we didn't write anything
// and the data is still okay, but we didn't do a debit
dataOK = TRUE;
success = FALSE;
OWERROR(OWERROR_SERVICE_DATA_NOT_UPDATED);
} else {
// retry the write
success = UpdateServiceData(copr, user);
// save what the account data is supposed to look like
memcpy(newAcctData, user->accountFile, 32);
}
}
} while (dataOK == FALSE && cnt-- > 0);
}
if (!dataOK) {
// couldn't fix the data after 255 retries
OWERROR(OWERROR_CATASTROPHIC_SERVICE_FAILURE);
success = FALSE;
}
return success;
}
w1retap/src/libusblinux300/shademo.c 0000664 0000000 0000000 00000013467 14464462352 0017624 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// shadebitdemo.c - main function for debit application.
//
// Version: 2.10
//
#include "ownet.h"
#include "shaib.h"
#include
//------------------------------------------------------------------------------
// Main routine for SHA debit demo application. Finds coprocessor first. Then
// waits for user tokens. When a user token arrives, it is authenticated and
// debited.
//
// Note: The algorithm used for signing certificates and verifying device
// authenticity is the SHA-1 algorithm as specified in the datasheet for the
// DS1961S/DS2432 and the DS2963S, where the last step of the official
// FIPS-180 SHA routine is omitted (which only involves the addition of
// constant values).
//
int main(int argc, char **argv) {
int oflags = 0;
FileEntry fe = {"COPR", 0};
// timing variables
int a, b, c, d, e;
// hold's user's old balance and new balance from acct info
int oldBalance, newBalance;
char inputChar = 0;
SMALLINT foundUser = FALSE;
SHACopr copr;
SHAUser user;
// could be different ports.
copr.portnum = 0;
user.portnum = 0;
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
if ((user.portnum = copr.portnum = owAcquireEx(argv[1])) < 0) {
printf("Failed to acquire port.\n");
exit(1);
}
#ifdef COPRVM
// virtual coprocessor
if (!GetCoprVM(&copr, &fe))
exit(1);
printf("Found coprocessor: EMULATED");
printf("\n Provider: %s\n Aux: %s \n", copr.providerName, copr.auxilliaryData);
#else
// setup file entry struct with the file we are looking for
// memcpy(fe.Name, "COPR", 4);
// fe.Ext = 0;
if (FindCoprSHA(&copr, &fe)) {
printf("Found coprocessor: ");
PrintSerialNum(copr.devAN);
printf("\n Provider: %s\n Aux: %s \n", copr.providerName, copr.auxilliaryData);
} else {
printf("Could not find coprocessor!\n");
exit(1);
}
#endif
puts("\nStarting SHA Debit Application");
puts(" Press 'q' followed by enter or ctrl-c to quit.\n");
puts("\nPlease place user token on the 1-Wire bus.\n");
puts("If user token is currently on the bus, take it off");
puts("the bus now and, after a second delay, put it back on.\n");
// get user account data filename
memcpy(fe.Name, copr.serviceFilename, 4);
fe.Ext = copr.serviceFilename[4];
#ifdef O_NONBLOCK // needed for systems where ctrl-c
// doesn't work, harmless on others
// turn off blocking I/O
if ((oflags = fcntl(0, F_GETFL, 0)) < 0 || fcntl(0, F_SETFL, oflags | O_NONBLOCK) < 0) {
printf("std I/O Failure!\n");
return -1;
}
#endif
for (; inputChar != 'q' && !key_abort();) {
do {
if (owHasErrors()) {
fflush(stdout);
msDelay(100);
}
#ifdef O_NONBLOCK // needed for systems where ctrl-c
// doesn't work, harmless on others
if (fread(&inputChar, 1, 1, stdin) <= 0)
inputChar = '0';
#endif
a = msGettick();
foundUser = FindUserSHA(&user, &fe, FALSE);
} while (!foundUser && inputChar != 'q' && !key_abort());
if (!foundUser)
continue;
b = msGettick();
if (VerifyUser(&copr, &user, TRUE)) {
c = msGettick();
if (VerifyData(&copr, &user)) {
d = msGettick();
oldBalance = GetBalance(&user);
if (ExecuteTransaction(&copr, &user, 50, TRUE)) {
e = msGettick();
newBalance = GetBalance(&user);
puts("\n--------------------------------\n");
puts("Complete Success");
printf("User token: ");
PrintSerialNum(user.devAN);
printf("\noldBalance: $%.2f\n", ((double)oldBalance / 100));
printf("newBalance: $%.2f\n", ((double)newBalance / 100));
printf(" find time: %d ms\n", b - a);
printf(" auth time: %d ms\n", c - b);
printf(" verf time: %d ms\n", d - c);
printf(" exec time: %d ms\n", e - d);
printf("total time: %d ms\n", e - a);
puts("\n--------------------------------\n");
} else {
printf("execute transaction failed\n");
OWERROR_DUMP(stdout);
}
} else {
printf("verify data failed\n");
OWERROR_DUMP(stdout);
}
} else {
printf("verify user failed\n");
OWERROR_DUMP(stdout);
}
}
owRelease(copr.portnum);
return TRUE;
}
w1retap/src/libusblinux300/shaib.c 0000664 0000000 0000000 00000046370 14464462352 0017271 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// shaibutton.c - Protocol-level functions as well as useful utility
// functions for sha applications.
//
// Version: 2.10
//
#include "ownet.h"
#include "shaib.h"
// Global
SMALLINT in_overdrive[MAX_PORTNUM];
//---------------------------------------------------------------------
// Uses File I/O API to find the coprocessor with a specific
// coprocessor file name. Usually 'COPR.0'.
//
// 'copr' - Structure for holding coprocessor information
// 'fe' - pointer to file entry structure, with proper filename.
//
// Returns: TRUE, found a valid coprocessor
// FALSE, no coprocessor is present
//
SMALLINT FindCoprSHA(SHACopr *copr, FileEntry *fe) {
SMALLINT FoundCopr = FALSE;
int data;
// now get all the SHA iButton parts until we find
// one that has the right file on it.
if (FindNewSHA(copr->portnum, copr->devAN, TRUE)) {
do {
short handle;
if (owOpenFile(copr->portnum, copr->devAN, fe, &handle)) {
int length = fe->NumPgs << 5;
uchar *raw = malloc(length * 5);
if (owReadFile(copr->portnum, copr->devAN, handle, raw, length, &length)) {
if (!owCloseFile(copr->portnum, copr->devAN, handle))
return FALSE;
if (raw != 0)
data = GetCoprFromRawData(copr, raw, length);
FoundCopr = TRUE;
}
free(raw);
}
} while (!FoundCopr && FindNewSHA(copr->portnum, copr->devAN, FALSE));
}
return FoundCopr;
}
//---------------------------------------------------------------------
// Extracts coprocessor configuration information from raw data.
// Returns the last unaccessed index.
//
// 'copr' - Structure for holding coprocessor information
// 'raw' - Raw bytes, usually from file stored on disk or on the
// coprocessor itself.
// 'length' - The length of coprocessor data.
//
int GetCoprFromRawData(SHACopr *copr, uchar *raw, int length) {
int i, namelen, siglen, auxlen;
// copy in the name of the user's service file
memcpy(copr->serviceFilename, raw, 5);
// various page numbers
copr->signPageNumber = raw[5];
copr->authPageNumber = raw[6];
copr->wspcPageNumber = raw[7];
// version information
copr->versionNumber = raw[8];
// skip 4 bytes for date info;
// get bind data, bind code, and signing challenge
memcpy(copr->bindData, &raw[13], 32);
memcpy(copr->bindCode, &raw[45], 7);
memcpy(copr->signChlg, &raw[52], 3);
namelen = raw[55];
siglen = raw[56];
auxlen = raw[57];
// read in provider name as null-terminated string
copr->providerName = malloc(namelen + 1);
memcpy(copr->providerName, &raw[58], namelen);
copr->providerName[namelen] = '\0';
// get initial signature
memcpy(copr->initSignature, &raw[58 + namelen], (siglen > 20 ? 20 : siglen));
// read in auxilliary data as null-terminated string
copr->auxilliaryData = malloc(auxlen + 1);
memcpy(copr->auxilliaryData, &raw[58 + namelen + siglen], auxlen);
copr->auxilliaryData[auxlen] = '\0';
// encryption code
i = 58 + namelen + siglen + auxlen;
copr->encCode = raw[i];
// ds1961S compatibility flag - optional
if ((length > i + 1) && (raw[i + 1] != 0))
copr->ds1961Scompatible = TRUE;
else
copr->ds1961Scompatible = FALSE;
return i + 2;
}
//---------------------------------------------------------------------
// Uses File I/O API to find the user token with a specific
// service file name. Usually 'DSLM.102'.
//
// 'user' - Structure for holding user token information
// 'fe' - pointer to file entry structure, with proper
// service filename.
// 'doBlocking' - if TRUE, method blocks until a user token is found.
//
// Returns: TRUE, found a valid user token
// FALSE, no user token is present
//
SMALLINT FindUserSHA(SHAUser *user, FileEntry *fe, SMALLINT doBlocking) {
SMALLINT FoundUser = FALSE;
for (;;) {
// now get all the SHA iButton parts until we find
// one that has the right file on it.
while (!FoundUser && FindNewSHA(user->portnum, user->devAN, FALSE)) {
short handle;
if (owOpenFile(user->portnum, user->devAN, fe, &handle)) {
user->accountPageNumber = fe->Spage;
FoundUser = TRUE;
if (!owCloseFile(user->portnum, user->devAN, handle))
return FALSE;
}
}
if (FoundUser)
return TRUE;
else if (!doBlocking)
return FALSE;
}
}
// final buffer for tracking list of known SHA parts
// only holds the CRC for each part
static uchar ListOfKnownSHA[MAX_PORTNUM][MAX_SHA_IBUTTONS];
static int listIndex = 0;
// intermediate buffer for tracking list of known SHA parts
static uchar listBuffer[MAX_PORTNUM][MAX_SHA_IBUTTONS];
static int indexBuffer = 0;
// holds last state of FindNewSHA
static SMALLINT needsFirst = FALSE;
//---------------------------------------------------------------------
// Finds new SHA iButtons on the given port. Uses 'triple-buffer'
// technique to insure it only finds 'new' buttons.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'devAN' - pointer to buffer for device address
// 'resetList' - if TRUE, final buffer is cleared.
//
// Returns: TRUE, found a new SHA iButton.
// FALSE, no new buttons are present.
//
SMALLINT FindNewSHA(int portnum, uchar *devAN, SMALLINT resetList) {
uchar ROM[8];
uchar tempList[MAX_SHA_IBUTTONS] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int tempIndex = 0, i;
SMALLINT hasDevices = TRUE, completeList = FALSE;
// force back to standard speed
if (MODE_NORMAL != owSpeed(portnum, MODE_NORMAL)) {
OWERROR(OWERROR_LEVEL_FAILED);
return FALSE;
}
in_overdrive[portnum & 0x0FF] = FALSE;
// get first device in list with the specified family
if (needsFirst || resetList) {
hasDevices = owFirst(portnum, TRUE, FALSE);
completeList = TRUE;
if (resetList)
listIndex = 0;
} else {
hasDevices = owNext(portnum, TRUE, FALSE);
}
if (hasDevices) {
do {
// verify correct device type
owSerialNum(portnum, ROM, TRUE);
tempList[tempIndex++] = ROM[7];
// compare crc to complete list of ROMs
for (i = 0; i < listIndex; i++) {
if (ROM[7] == ListOfKnownSHA[portnum & 0x0FF][i])
break;
}
// found no match;
if (i == listIndex) {
// check if correct type and not copr_rom
if ((SHA_FAMILY_CODE == (ROM[0] & 0x7F)) || (SHA33_FAMILY_CODE == (ROM[0] & 0x7F))) {
// save the ROM to the return buffer
owSerialNum(portnum, devAN, TRUE);
ListOfKnownSHA[portnum & 0x0FF][listIndex++] = devAN[7];
return TRUE;
}
}
} while (owNext(portnum, TRUE, FALSE));
}
// depleted the list, start over from beginning next time
needsFirst = TRUE;
if (completeList) {
// known list is triple-buffered, listBuffer is intermediate
// buffer. tempList is the immediate buffer, while
// ListOfKnownSHA is the final buffer.
if ((memcmp(tempList, listBuffer[portnum & 0x0FF], MAX_SHA_IBUTTONS) == 0) && tempIndex == indexBuffer) {
memcpy(ListOfKnownSHA[portnum & 0x0FF], tempList, MAX_SHA_IBUTTONS);
listIndex = tempIndex;
} else {
memcpy(listBuffer[portnum & 0x0FF], tempList, MAX_SHA_IBUTTONS);
indexBuffer = tempIndex;
}
}
return FALSE;
}
//-------------------------------------------------------------------------
// Select the current device and attempt overdrive if possible. Usable
// for both DS1963S and DS1961S.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
//
// Return: TRUE - device selected
// FALSE - device not select
//
SMALLINT SelectSHA(int portnum) {
int rt, cnt = 0;
#ifdef __MC68K__
// Used in when overdrive isn't...Used owVerify for overdrive
rt = owAccess(portnum);
#else
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef DEBUG_DUMP
uchar ROM[8];
int i, mcnt;
char msg[255];
owSerialNum(portnum, ROM, TRUE);
mcnt = sprintf(msg, "\n Device select ");
for (i = 0; i < 8; i++)
mcnt += sprintf(msg + mcnt, "%02X", ROM[i]);
mcnt += sprintf(msg + mcnt, "\n");
printf("%s", msg);
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// loop to access the device and optionally do overdrive
do {
rt = owVerify(portnum, FALSE);
// check not present
if (rt != 1) {
// if in overdrive, drop back
if (in_overdrive[portnum & 0x0FF]) {
// set to normal speed
if (MODE_NORMAL == owSpeed(portnum, MODE_NORMAL))
in_overdrive[portnum & 0x0FF] = FALSE;
}
}
// present but not in overdrive
else if (!in_overdrive[portnum & 0x0FF]) {
// put all devices in overdrive
if (owTouchReset(portnum)) {
if (owWriteByte(portnum, 0x3C)) {
// set to overdrive speed
if (MODE_OVERDRIVE == owSpeed(portnum, MODE_OVERDRIVE))
in_overdrive[portnum & 0x0FF] = TRUE;
}
}
rt = 0;
} else
break;
} while ((rt != 1) && (cnt++ < 3));
#endif
return rt;
}
//-------------------------------------------------------------------------
// Creates a random challenge using the SHA engine of the given
// coprocessor.
//
// 'copr' - Structure for holding coprocessor information.
// 'pagenum' - pagenumber to use for calculation.
// 'chlg' - 3-byte return buffer for challenge.
// 'offset' - offset into resulting MAC to pull challenge data from.
//
// Return: TRUE - create challenge succeeded.
// FALSE - an error occurred.
//
SMALLINT CreateChallenge(SHACopr *copr, SMALLINT pageNum, uchar *chlg, SMALLINT offset) {
uchar scratchpad[32];
int addr = pageNum << 5;
uchar es = 0x1F;
int start = 8;
if (offset > 0 && offset < 17)
start += offset;
// set the serial number
owSerialNum(copr->portnum, copr->devAN, FALSE);
OWASSERT(EraseScratchpadSHA18(copr->portnum, addr, FALSE), OWERROR_ERASE_SCRATCHPAD_FAILED, FALSE);
OWASSERT(SHAFunction18(copr->portnum, SHA_COMPUTE_CHALLENGE, addr, TRUE), OWERROR_SHA_FUNCTION_FAILED, FALSE);
OWASSERT(ReadScratchpadSHA18(copr->portnum, &addr, &es, scratchpad, TRUE), OWERROR_READ_SCRATCHPAD_FAILED, FALSE);
memcpy(chlg, &scratchpad[start], 3);
return TRUE;
}
//-------------------------------------------------------------------------
// Answers a random challenge by performing an authenticated read of the
// user's account information.
//
// 'user' - Structure for holding user token information.
// 'chlg' - 3-byte buffer of challenge data.
//
// Return: the value of the write cycle counter for the account page.
// or -1 if there is an error
//
int AnswerChallenge(SHAUser *user, uchar *chlg) {
int addr = user->accountPageNumber << 5;
user->writeCycleCounter = -1;
memcpy(&user->accountFile[20], chlg, 3);
// set the serial number
owSerialNum(user->portnum, user->devAN, FALSE);
if (user->devAN[0] == 0x18) {
// for the DS1963S
OWASSERT(EraseScratchpadSHA18(user->portnum, addr, FALSE), OWERROR_ERASE_SCRATCHPAD_FAILED, -1);
OWASSERT(WriteScratchpadSHA18(user->portnum, addr, user->accountFile, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, -1);
user->writeCycleCounter =
ReadAuthPageSHA18(user->portnum, user->accountPageNumber, user->accountFile, user->responseMAC, TRUE);
} else if (user->devAN[0] == 0x33 || user->devAN[0] == 0xB3) {
// for the DS1961S
OWASSERT(WriteScratchpadSHA33(user->portnum, addr, &user->accountFile[16], FALSE), OWERROR_WRITE_SCRATCHPAD_FAILED, -1);
user->writeCycleCounter =
ReadAuthPageSHA33(user->portnum, user->accountPageNumber, user->accountFile, user->responseMAC, TRUE);
}
return user->writeCycleCounter;
}
//-------------------------------------------------------------------------
// Verifies the authentication response of a user token.
//
// 'copr' - Structure for holding coprocessor information.
// 'user' - Structure for holding user token information.
// 'chlg' - 3-byte buffer of challenge data.
// 'doBind' - if true, the user's unique secret is recreated on the
// coprocessor. If this function is called multiple times,
// it is acceptable to skip the bind for all calls after
// the first on the same user token.
//
// Return: If TRUE, the user's authentication response matched exactly the
// signature generated by the coprocessor.
// If FALSE, an error occurred or the signature did not match.
//
SMALLINT VerifyAuthResponse(SHACopr *copr, SHAUser *user, uchar *chlg, SMALLINT doBind) {
int addr = copr->wspcPageNumber << 5;
int wcc = user->writeCycleCounter;
uchar sign_cmd;
uchar scratchpad[32];
uchar fullBindCode[15];
memset(scratchpad, 0x00, 32);
memset(fullBindCode, 0x0FF, 15);
// format the bind code properly
if (user->devAN[0] == 0x18) {
// Format for DS1963S
memcpy(fullBindCode, copr->bindCode, 4);
memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3);
// use ValidateDataPage command
sign_cmd = SHA_VALIDATE_DATA_PAGE;
// copy wcc LSB first
if (!IntToBytes(&scratchpad[8], 4, wcc))
OWERROR(OWERROR_NO_ERROR_SET);
} else if (user->devAN[0] == 0x33 || user->devAN[0] == 0xB3) {
// Leave bindCode FF for DS1961S
// Use AuthenticateHost command
sign_cmd = SHA_AUTHENTICATE_HOST;
// the user doesn't have a write cycle counter
memset(&scratchpad[8], 0x0FF, 4);
} else {
OWERROR(OWERROR_WRONG_TYPE);
return FALSE;
}
// the pagenumber
fullBindCode[4] = (uchar)user->accountPageNumber;
// and 7 bytes of the address of current device
memcpy(&fullBindCode[5], user->devAN, 7);
// get the user address and page num from fullBindCode
memcpy(&scratchpad[12], &fullBindCode[4], 8);
// set the same challenge bytes
memcpy(&scratchpad[20], chlg, 3);
// set the serial number to that of the coprocessor
owSerialNum(copr->portnum, copr->devAN, FALSE);
// install user's unique secret on the wspc secret
if (doBind) {
OWASSERT(BindSecretToiButton18(copr->portnum, copr->authPageNumber, copr->wspcPageNumber & 7, copr->bindData, fullBindCode,
FALSE),
OWERROR_BIND_SECRET_FAILED, FALSE);
if (user->devAN[0] == 0x33 || user->devAN[0] == 0xB3) {
// also copy the resulting secret into secret location 0, to
// replace the signing secret. Necessary for producing the
// DS1961S's write-authorization MAC.
OWASSERT(CopySecretSHA18(copr->portnum, 0), OWERROR_COPY_SECRET_FAILED, FALSE);
}
}
// recreate the signature and verify
OWASSERT(WriteDataPageSHA18(copr->portnum, copr->wspcPageNumber, user->accountFile, doBind), OWERROR_WRITE_DATA_PAGE_FAILED,
FALSE);
OWASSERT(WriteScratchpadSHA18(copr->portnum, addr, scratchpad, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE);
OWASSERT(SHAFunction18(copr->portnum, sign_cmd, addr, TRUE), OWERROR_SHA_FUNCTION_FAILED, FALSE);
OWASSERT(MatchScratchpadSHA18(copr->portnum, user->responseMAC, TRUE), OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE);
return TRUE;
}
//-------------------------------------------------------------------------
// Creates a data signature for the given data buffer using the hardware
// coprocessor.
//
// 'copr' - Structure for holding coprocessor information.
// 'data' - data written to the data page to sign
// 'scratchpad' - data written to the scratchpad to sign
// 'signature' - data buffer which is either holding the signature that
// must match exactly what is generated on the coprocessor
// -or- will hold the resulting signature created by the
// coprocessor.
// 'readSignature' - implies whether or not the signature buffer
// receives the contents of the scratchpad or is used to
// match the contents of the scratchpad. If true,
// scratchpad contents are read into the signature buffer.
//
// Return: If TRUE, the user's authentication response matched exactly the
// signature generated by the coprocessor or the signature was
// successfully copied into the return buffer.
// If FALSE, an error occurred or the signature did not match.
//
SMALLINT CreateDataSignature(SHACopr *copr, uchar *data, uchar *scratchpad, uchar *signature, SMALLINT readSignature) {
int addr = copr->signPageNumber << 5;
// set the serial number to that of the coprocessor
owSerialNum(copr->portnum, copr->devAN, FALSE);
OWASSERT(WriteDataPageSHA18(copr->portnum, copr->signPageNumber, data, FALSE), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE);
OWASSERT(WriteScratchpadSHA18(copr->portnum, addr, scratchpad, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE);
OWASSERT(SHAFunction18(copr->portnum, SHA_SIGN_DATA_PAGE, addr, TRUE), OWERROR_SHA_FUNCTION_FAILED, FALSE);
if (readSignature) {
OWASSERT(ReadScratchpadSHA18(copr->portnum, 0, 0, scratchpad, TRUE), OWERROR_READ_SCRATCHPAD_FAILED, FALSE);
} else {
OWASSERT(MatchScratchpadSHA18(copr->portnum, signature, TRUE), OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE);
}
memcpy(signature, &scratchpad[8], 20);
return TRUE;
}
//-------------------------------------------------------------------------
// Decipher the variable Val into a 'len' byte array to set
// LSB First
//
SMALLINT IntToBytes(uchar *byteArray, int len, unsigned int val) {
int i = 0;
for (; i < len; i++) {
byteArray[i] = (uchar)val;
val >>= 8;
}
if (val == 0)
return TRUE;
else
return FALSE;
}
//-------------------------------------------------------------------------
// Decipher the range 'len' of the byte array to an integer
// LSB First
//
int BytesToInt(uchar *byteArray, int len) {
unsigned int val = 0;
int i = (len - 1);
// Concatanate the byte array into one variable.
for (; i >= 0; i--) {
val <<= 8;
val |= (byteArray[i] & 0x00FF);
}
return val;
}
w1retap/src/libusblinux300/shaib.h 0000664 0000000 0000000 00000026030 14464462352 0017265 0 ustar 00root root 0000000 0000000 // shaib.h
#ifndef SHAIBUTTON_H
#define SHAIBUTTON_H
// for ANSI memory commands - memcpy,memcmp,memset
#include
#include
#include "ownet.h"
#include "owfile.h"
// ********************************************************************** //
// DS1963S SHA iButton commands
// ********************************************************************** //
#define SHA_COMPUTE_FIRST_SECRET 0x0F
#define SHA_COMPUTE_NEXT_SECRET 0xF0
#define SHA_VALIDATE_DATA_PAGE 0x3C
#define SHA_SIGN_DATA_PAGE 0xC3
#define SHA_COMPUTE_CHALLENGE 0xCC
#define SHA_AUTHENTICATE_HOST 0xAA
#define CMD_READ_MEMORY 0xF0
#define CMD_MATCH_SCRATCHPAD 0x3C
#define CMD_WRITE_SCRATCHPAD 0x0F
#define CMD_READ_SCRATCHPAD 0xAA
#define CMD_ERASE_SCRATCHPAD 0xC3
#define CMD_COPY_SCRATCHPAD 0x55
#define CMD_READ_AUTH_PAGE 0xA5
#define CMD_COMPUTE_SHA 0x33
#define ROM_CMD_SKIP 0x3C
#define ROM_CMD_RESUME 0xA5
// ********************************************************************** //
// DS1961S SHA iButton commands - rest are shared with above
// ********************************************************************** //
#define SHA33_LOAD_FIRST_SECRET 0x5A
#define SHA33_COMPUTE_NEXT_SECRET 0x33
#define SHA33_REFRESH_SCRATCHPAD 0xA3
// ********************************************************************** //
// other constants
#define SHA_FAMILY_CODE 0x18
#define SHA33_FAMILY_CODE 0x33
// maximum number of buttons to track on the port
#define MAX_SHA_IBUTTONS 16
#define SHACoprFilename "shacopr.cnf"
// ********************************************************************** //
// SHA Device Structures
// ********************************************************************** //
// struct SHACopr
// Holds all information pertinent to SHA coprocessors, as
// well as all of the system parameters for this account
// transaction system.
typedef struct {
// portnum and address of the device
int portnum;
uchar devAN[8];
// name of the account file stored on the user token
uchar serviceFilename[5];
// memory page used for signing certificate data (0 or 8)
uchar signPageNumber;
// memory page used for storing master authentication secret
// and recreating user's unique secret
uchar authPageNumber;
// memory page used for storing user's unique secret
// and verifying the user's authentication response
uchar wspcPageNumber;
// version number of the system
uchar versionNumber;
// Binding information for producing unique secrets
uchar bindCode[7];
uchar bindData[32];
// challenge and signature used when signing account data
uchar signChlg[3];
uchar initSignature[20];
// name of the transaction system provider
uchar *providerName; // variable length
// any other pertinent information
uchar *auxilliaryData; // variable length
// encryption code, used to specify additional encryption
uchar encCode;
// indicates that the master authentication secret was
// padded to match the secret of a DS1961S
uchar ds1961Scompatible;
} SHACopr;
// struct SHAUser
// Holds all information pertinent to SHA user tokens.
// Maintains state between routines for verifying the
// user's authentication response, the account signature,
// and updating the account data.
typedef struct {
// portnum and address of the device
int portnum;
uchar devAN[8];
// page the user's account file is stored on
uchar accountPageNumber;
// Write cycle counter for account page
int writeCycleCounter;
// MAC from Read Authenticated Page command
uchar responseMAC[20];
// 32-byte account file
uchar accountFile[32];
} SHAUser;
// struct DebitFile
// Holds user token account data. Byte-ordering
// matters, so that this is a valid certificate
// as specified by Application Note 151.
typedef struct {
uchar fileLength;
uchar dataTypeCode;
uchar signature[20];
uchar convFactor[2];
uchar balanceBytes[3];
uchar transID[2];
uchar contPtr;
uchar crc16[2];
} DebitFile;
// struct DebitFile33
// Holds user token account data for DS1961S.
// Usese Double octa-byte scheme for dual money
// bytes and a pointer to the valid record.
typedef struct {
// header
uchar fileLength;
uchar dataTypeCode;
uchar convFactor[2];
// dont cares
uchar dontCareBytes1[4];
// record A
uchar balanceBytes_A[3];
uchar transID_A[2];
uchar contPtr_A;
uchar crc16_A[2];
// record B
uchar balanceBytes_B[3];
uchar transID_B[2];
uchar contPtr_B;
uchar crc16_B[2];
// dont cares
uchar dontCareBytes2[8];
} DebitFile33;
// file length used to point at Record A
#define RECORD_A_LENGTH 13
// file length used to point at Record B
#define RECORD_B_LENGTH 21
// ********************************************************************** //
// DS1963S Low-level Functions - defined in sha18.c
// ********************************************************************** //
// General I/O
extern SMALLINT CopySecretSHA18(int portnum, SMALLINT secretnum);
extern SMALLINT ReadScratchpadSHA18(int portnum, int *address, uchar *es, uchar *data, SMALLINT resume);
extern SMALLINT WriteScratchpadSHA18(int portnum, int address, uchar *data, SMALLINT data_len, SMALLINT resume);
extern SMALLINT CopyScratchpadSHA18(int portnum, int address, SMALLINT len, SMALLINT resume);
extern SMALLINT MatchScratchpadSHA18(int portnum, uchar *data, SMALLINT resume);
extern SMALLINT EraseScratchpadSHA18(int portnum, int address, SMALLINT resume);
extern int ReadAuthPageSHA18(int portnum, SMALLINT pagenum, uchar *data, uchar *sign, SMALLINT resume);
extern SMALLINT ReadMemoryPageSHA18(int portnum, SMALLINT pagenum, uchar *data, SMALLINT resume);
extern SMALLINT WriteDataPageSHA18(int portnum, SMALLINT pagenum, uchar *data, SMALLINT resume);
extern SMALLINT SHAFunction18(int portnum, uchar control_byte, int address, SMALLINT resume);
// Secret Installation
extern SMALLINT InstallSystemSecret18(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar *secret, int secret_length,
SMALLINT resume);
extern SMALLINT BindSecretToiButton18(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar *bindData, uchar *bindCode,
SMALLINT resume);
// ********************************************************************** //
// ********************************************************************** //
// DS1961S Low-level Functions - defined in sha33.c
// ********************************************************************** //
// General I/O
extern SMALLINT ReadScratchpadSHA33(int portnum, int *address, uchar *es, uchar *data, SMALLINT resume);
extern SMALLINT WriteScratchpadSHA33(int portnum, int address, uchar *data, SMALLINT resume);
extern SMALLINT CopyScratchpadSHA33(int portnum, int address, uchar *MAC, SMALLINT resume);
extern SMALLINT ReadMemoryPageSHA33(int portnum, SMALLINT pagenum, uchar *data, SMALLINT resume);
extern int ReadAuthPageSHA33(int portnum, SMALLINT pagenum, uchar *data, uchar *sign, SMALLINT resume);
// Secret Installation
extern SMALLINT LoadFirstSecret33(int portnum, uchar *secret, SMALLINT resume);
extern SMALLINT LoadFirstSecretAddress33(int portnum, int address, SMALLINT resume);
extern SMALLINT RefreshScratchpad33(int portnum, int address, SMALLINT resume);
extern SMALLINT RefreshPage33(int portnum, SMALLINT pagenum, SMALLINT resume);
extern SMALLINT InstallSystemSecret33(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar *input_secret, int secret_length,
SMALLINT resume);
extern SMALLINT BindSecretToiButton33(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar *bindData, uchar *bindCode,
SMALLINT resume);
// General Util
extern void ReformatSecretFor1961S(uchar *auth_secret, int secret_length);
extern void ComputeSHAVM(uchar *MT, int *hash);
extern void HashToMAC(int *hash, uchar *MAC);
// ********************************************************************** //
// ********************************************************************** //
// Protocol-Level Functions - defined in shaibutton.c
// ********************************************************************** //
// Finding and accessing SHA iButtons
extern SMALLINT SelectSHA(int portnum);
extern SMALLINT FindNewSHA(int portnum, uchar *devAN, SMALLINT forceFirst);
extern SMALLINT FindUserSHA(SHAUser *user, FileEntry *fe, SMALLINT doBlocking);
extern SMALLINT FindCoprSHA(SHACopr *copr, FileEntry *fe);
extern int GetCoprFromRawData(SHACopr *copr, uchar *raw, int len);
// General Protocol functions for 1963S
extern SMALLINT CreateChallenge(SHACopr *copr, SMALLINT pageNum, uchar *chlg, SMALLINT offset);
extern int AnswerChallenge(SHAUser *user, uchar *chlg);
extern SMALLINT VerifyAuthResponse(SHACopr *copr, SHAUser *user, uchar *chlg, SMALLINT doBind);
extern SMALLINT CreateDataSignature(SHACopr *copr, uchar *data, uchar *scratchpad, uchar *signature, SMALLINT readSignature);
// Useful utility functions
extern SMALLINT IntToBytes(uchar *byteArray, int len, unsigned int val);
extern int BytesToInt(uchar *byteArray, int len);
// ********************************************************************** //
// ********************************************************************** //
// Service-Level Functions - defined in shadebit.c (or shadebitvm.c)
// ********************************************************************** //
extern SMALLINT VerifyUser(SHACopr *copr, SHAUser *user, SMALLINT doBind);
extern SMALLINT VerifyData(SHACopr *copr, SHAUser *user);
extern SMALLINT ExecuteTransaction(SHACopr *copr, SHAUser *user, int debitAmount, SMALLINT verifySuccess);
extern SMALLINT UpdateServiceData(SHACopr *copr, SHAUser *user);
extern SMALLINT InstallServiceData(SHACopr *copr, SHAUser *user, uchar *secret, int secret_length, int balance);
extern SMALLINT WriteDataPageSHA33(SHACopr *copr, SHAUser *user);
extern int GetBalance(SHAUser *user);
// ********************************************************************** //
// ********************************************************************** //
// Service/Protocol-Level Functions - defined in shadebitvm.c
// ********************************************************************** //
extern SMALLINT InstallSystemSecretVM(SHACopr *copr, uchar *secret, int secret_length, uchar *dst_secret);
extern SMALLINT InstallSignSecretVM(SHACopr *copr, uchar *secret, int secret_length);
extern SMALLINT InstallAuthSecretVM(SHACopr *copr, uchar *secret, int secret_length);
extern SMALLINT VerifyAuthResponseVM(SHACopr *copr, SHAUser *user, uchar *chlg, SMALLINT doBind);
extern SMALLINT CreateDataSignatureVM(SHACopr *copr, uchar *secret, uchar *data, uchar *scratchpad, uchar *signature,
SMALLINT readSignature);
extern SMALLINT GetCoprVM(SHACopr *copr, FileEntry *fe);
// ********************************************************************** //
// ********************************************************************** //
// Global - defined in shaibutton.c
extern SMALLINT in_overdrive[MAX_PORTNUM];
// ********************************************************************** //
extern void PrintHexLabeled(char *label, uchar *buffer, int cnt);
extern void ReadChars(uchar *buffer, int len);
#endif // SHAIBUTTON_H
w1retap/src/libusblinux300/sharov.c 0000664 0000000 0000000 00000006407 14464462352 0017502 0 ustar 00root root 0000000 0000000 #include "ownet.h"
#include "shaib.h"
static int GetSecret(char *name, uchar **secret);
//---------------------------------------------------------------------------
// Finds a SHA coprocessor first. Then waits for a SHA iButton. When a SHA
// iButton arrives, it is initialized as a new user token, for use in SHA
// eCash systems.
//
// Note: The algorithm used for signing certificates and verifying device
// authenticity is the SHA-1 algorithm as specified in the datasheet for the
// DS1961S/DS2432 and the DS2963S, where the last step of the official
// FIPS-180 SHA routine is omitted (which only involves the addition of
// constant values).
//
int main(int argc, char **argv) {
int i = 0;
SHACopr copr;
SHAUser user;
FileEntry fe = {"COPR", 0};
uchar *authSecret;
int authlen;
char test[2] = {'y', 0};
int balance;
copr.portnum = 0;
user.portnum = 0;
puts("\nStarting SHA initrov Application\n");
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
if ((user.portnum = copr.portnum = owAcquireEx(argv[1])) < 0) {
printf("Failed to acquire port.\n");
exit(2);
}
#ifdef COPRVM
if (!GetCoprVM(&copr, &fe))
exit(1);
#else
puts("\nPlease place coprocessor token on the 1-Wire bus.\n");
while (!FindCoprSHA(&copr, &fe)) {
if (owHasErrors())
msDelay(10);
}
printf("Found device: ");
PrintSerialNum(copr.devAN);
puts("\n");
#endif
authlen = GetSecret("System Authentication Secret", &authSecret);
EnterString("Reformat the secret for DS1961S compatibility", test, 1, 1);
if (test[0] == 'y') {
ReformatSecretFor1961S(authSecret, authlen);
PrintHex(authSecret, authlen);
printf("\n");
copr.ds1961Scompatible = 0x55;
}
puts("\nPlease place user token on the 1-Wire bus.\n");
do {
while (!FindNewSHA(user.portnum, user.devAN, (i == 0))) {
if (owHasErrors()) {
OWERROR_DUMP(stdout);
msDelay(10);
}
}
i++;
} while (user.devAN[7] == copr.devAN[7]);
// just check the crc of the two devices
balance = 100;
EnterNum("\nInitial Balance in Cents?\n", 5, &balance, 0, 0xFFFFF);
printf("Installing Service Data on device: ");
PrintSerialNum(user.devAN);
puts("\n");
if (InstallServiceData(&copr, &user, authSecret, authlen, (int)balance)) {
puts("User token successfully set up");
} else {
puts("User token setup failed");
OWERROR_DUMP(stdout);
}
// and we're done
owRelease(copr.portnum);
// program is about to exit, but we may as well free these
// up anyways...
free(authSecret);
return 0;
}
static int GetSecret(char *name, uchar **secret) {
uchar inputBuffer[255];
int lvalue = 1, length;
printf("How would you like to enter the %s?\n", name);
EnterNum("\n 1) Hex\n 2) Text\n", 1, &lvalue, 1, 2);
lvalue = getData(inputBuffer, 255, (lvalue == 1));
if (lvalue % 47 != 0)
length = ((lvalue / 47) + 1) * 47;
else
length = lvalue;
*secret = malloc(length);
memset(*secret, 0x00, length);
memcpy(*secret, inputBuffer, lvalue);
printf("length=%d\n", length);
PrintHex(*secret, length);
printf("\n");
return length;
}
w1retap/src/libusblinux300/sht11.h 0000664 0000000 0000000 00000000251 14464462352 0017134 0 ustar 00root root 0000000 0000000 extern int ReadSHT11(int portnum, u_char *ident, float *temp, float *rh);
#define MATCHROM 0x55
#define CONVERTSENSOR 0x44
#define SKIPROM 0xCC
#define READSENSOR 0x45
w1retap/src/libusblinux300/sht11_humid.c 0000664 0000000 0000000 00000010113 14464462352 0020313 0 ustar 00root root 0000000 0000000 #include
#include "ownet.h"
#include "sht11.h"
/*
* From:
* http://www.sensirion.com/pdf/product_information/CRC_Calculation_Humidity_Sensor_E.pdf
*/
static unsigned char CRC[] = {
0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 67, 114, 33, 16, 135, 182, 229, 212,
250, 203, 152, 169, 62, 15, 92, 109, 134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168,
197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, 61, 12, 95, 110, 249, 200, 155, 170,
132, 181, 230, 215, 64, 113, 34, 19, 126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80,
187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 248, 201, 154, 171, 60, 13, 94, 111,
65, 112, 35, 18, 133, 180, 231, 214, 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84,
57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, 252, 205, 158, 175, 56, 9, 90, 107,
69, 116, 39, 22, 129, 176, 227, 210, 191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145,
71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105, 4, 53, 102, 87, 192, 241, 162, 147,
189, 140, 223, 238, 121, 72, 27, 42, 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239,
130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172};
#define NRETRY 3
static inline unsigned char revbits(unsigned char b) {
/*
* Shameless taken from
* http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious
* Devised by Sean Anderson, July 13, 2001.
* Typo spotted and correction supplied by Mike Keith, January 3, 2002.
*/
return ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
}
static int checkcrc(unsigned char *blk, unsigned char crcs[2]) {
int i = 0;
// CRC is made up from the SHT-11 command and data, thusly
crcs[0] = revbits(CRC[((CRC[(CRC[3] ^ blk[2])]) ^ blk[3])]);
crcs[1] = revbits(CRC[((CRC[(CRC[5] ^ blk[7])]) ^ blk[8])]);
if (crcs[0] != blk[4]) {
i |= 1;
}
if (crcs[1] != blk[9]) {
i |= 2;
}
return i;
}
int ReadSHT11(int portnum, u_char *ident, float *temp, float *rh) {
int i, j;
int rv = 0;
int verbose = !!getenv("SHT11_VERBOSE");
for (j = 0; (rv == 0) && (j < NRETRY); j++) {
owTouchReset(portnum);
owTouchByte(portnum, 0x55);
for (i = 0; i < 8; i++) {
owTouchByte(portnum, ident[i]);
}
if (!owTouchByte(portnum, 0x44)) {
if (verbose)
fputs("Failed WritePower 0x44\n", stderr);
return rv;
}
msDelay(300);
owTouchReset(portnum);
owTouchByte(portnum, 0xCC);
{
unsigned char c;
unsigned char blk[10];
c = owTouchByte(portnum, 0x45);
for (i = 0; i < 10; i++) {
c = owTouchByte(portnum, 0xff);
blk[i] = c;
}
if (blk[0] == 'T' && blk[5] == 'H' && blk[1] == '=' && blk[6] == '=') {
int crcres;
unsigned char crcs[2];
if (0 == (crcres = checkcrc(blk, crcs))) {
unsigned short so;
so = (blk[2] << 8) | blk[3];
if (so > 10000) {
fprintf(stderr, "Invalid Temp data %d\n", so);
break;
}
*temp = -40.0 + 0.01 * so;
so = (blk[7] << 8) | blk[8];
if (so < 99 || so > 3338) {
fprintf(stderr, "Invalid RH data %d\n", so);
break;
}
*rh = -4.0 + 0.0405 * so - 0.0000028 * so * so;
rv = 1;
} else if (verbose) {
if (crcres & 1) {
fprintf(stderr, "Temp CRC (%02x) : %02x %02x %02x ", crcs[0], blk[2], blk[3], blk[4]);
}
if (crcres & 2) {
fprintf(stderr, "RH CRC (%02x) : %02x %02x %02x", crcs[1], blk[7], blk[8], blk[9]);
}
fputc('\n', stderr);
}
} else if (verbose) {
fputs("No data signature\n", stderr);
}
}
if (rv == 0)
msDelay(100);
}
owTouchReset(portnum);
return rv;
}
w1retap/src/libusblinux300/swt05.c 0000664 0000000 0000000 00000006655 14464462352 0017167 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//--------------------------------------------------------------------------
//
// swt05.c - Turns DS2405 on/off and reads if it is on/off
// version 2.00
//
// Include Files
#include "ownet.h"
//--------------------------------------------------------------------------
// SUBROUTINE - SetSwitch05
//
// This routine turns the device on or off.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
// OpenCOM to indicate the port number.
// 'SwNum' - The serial number of the swith that is to be turned on or off
// 'seton' - 'TRUE' then it is turned on if off and left alone if already on.
// 'FALSE' turns it off if already on
//
// Returns: TRUE(1): If set is successful
// FALSE(0): If set is not successful
//
int SetSwitch05(int portnum, uchar *SwNum, int seton) {
int compare;
owSerialNum(portnum, &SwNum[0], FALSE);
compare = owVerify(portnum, TRUE);
if ((compare && seton) || (!compare && !seton))
return TRUE;
else if (owAccess(portnum)) {
compare = owVerify(portnum, TRUE);
if ((compare && seton) || (!compare && !seton))
return TRUE;
else
return FALSE;
} else
return FALSE;
}
//--------------------------------------------------------------------------
// SUBROUTINE - ReadSwitch05
//
// This routine reads if the DS2405 device is on or off.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
// OpenCOM to indicate the port number.
// 'SerialNum' - The Serial number of the DS2405 that info is requested on
// 'level' - This is 1 for high and 0 for low level
//
// Returns: TRUE(1): If device is found and active
// FALSE(0): If device is not found and not active or not there
//
int ReadSwitch05(int portnum, uchar *SerialNum, int *level) {
owSerialNum(portnum, &SerialNum[0], FALSE);
if (owVerify(portnum, FALSE)) {
if (owTouchByte(portnum, 0xFF) == 0xFF)
*level = 1;
else
*level = 0;
if (owVerify(portnum, TRUE))
return TRUE;
else
return FALSE;
} else
return FALSE;
}
w1retap/src/libusblinux300/swt05.h 0000664 0000000 0000000 00000003231 14464462352 0017157 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//--------------------------------------------------------------------------
//
// swt05.h - Turns DS2405 on/off and reads if it is on/off
// version 2.00
//
// Local subroutines
int SetSwitch05(int, uchar *, int);
int ReadSwitch05(int, uchar *, int *);
// Constant definitions
#define SWITCH_FAMILY 0x05
w1retap/src/libusblinux300/swt12.c 0000664 0000000 0000000 00000017644 14464462352 0017165 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//--------------------------------------------------------------------------
//
// swt12.c - Modifies Channel A and B and returns info byte data for
// the DS2406 and DS2407.
// version 2.00
// Include files
#include
#include "ownet.h"
#include "swt12.h"
//----------------------------------------------------------------------
// SUBROUTINE - ReadSwitch12
//
// This routine gets the Channel Info Byte and returns it.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
// OpenCOM to indicate the port number.
// 'ClearActivity' - To reset the button
//
// Returns: (-1) If the Channel Info Byte could not be read.
// (Info Byte) If the Channel Info Byte could be read.
//
int ReadSwitch12(int portnum, int ClearActivity) {
int rt = -1; // this is the return value depending if the byte was read
int trans_cnt = 0; // this is the counter for the number of bytes to send
uchar transfer[30]; // this is the whole block of byte info
ushort lastcrc16;
// access and verify it is there
if (owAccess(portnum)) {
// reset CRC
setcrc16(portnum, 0);
// channel access command
transfer[trans_cnt++] = 0xF5;
lastcrc16 = docrc16(portnum, 0xF5);
// control bytes
if (ClearActivity) {
transfer[trans_cnt++] = 0xD5;
lastcrc16 = docrc16(portnum, 0xD5);
} else {
transfer[trans_cnt++] = 0x55;
lastcrc16 = docrc16(portnum, 0x55);
}
transfer[trans_cnt++] = 0xFF;
lastcrc16 = docrc16(portnum, 0xFF);
// read the info byte
transfer[trans_cnt++] = 0xFF;
// dummy data
transfer[trans_cnt++] = 0xFF;
transfer[trans_cnt++] = 0xFF;
transfer[trans_cnt++] = 0xFF;
if (owBlock(portnum, FALSE, transfer, trans_cnt)) {
rt = transfer[3];
// read a dummy read byte and CRC16
lastcrc16 = docrc16(portnum, transfer[trans_cnt - 4]);
lastcrc16 = docrc16(portnum, transfer[trans_cnt - 3]);
lastcrc16 = docrc16(portnum, transfer[trans_cnt - 2]);
lastcrc16 = docrc16(portnum, transfer[trans_cnt - 1]);
if (lastcrc16 != 0xB001)
rt = -1;
}
} else
rt = -1;
return rt;
}
//----------------------------------------------------------------------
// SUBROUTINE - SetSwitch12
//
// This routine sets the channel state of the specified DS2406
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
// OpenCOM to indicate the port number.
// 'SerialNum' - Serial Number of DS2406 to set the switch state
// 'State' - Is a type containing what to set A and/or B to. It
// also contains the other fields that maybe written later
//
// Returns: TRUE(1) State of DS2406 set and verified
// FALSE(0) could not set the DS2406, perhaps device is not
// in contact
//
int SetSwitch12(int portnum, uchar *SerialNum, SwitchProps State) {
ushort st;
int rt = FALSE;
uchar send_block[30];
int send_cnt = 0;
ushort lastcrc16;
setcrc16(portnum, 0);
// set the device serial number to the counter device
owSerialNum(portnum, SerialNum, FALSE);
// access the device
if (owAccess(portnum)) {
// create a block to send that reads the counter
// write status command
send_block[send_cnt++] = 0x55;
lastcrc16 = docrc16(portnum, 0x55);
// address of switch state
send_block[send_cnt++] = 0x07;
lastcrc16 = docrc16(portnum, 0x07);
send_block[send_cnt++] = 0x00;
lastcrc16 = docrc16(portnum, 0x00);
// write state
st = 0x1F;
if (!State.Chan_B)
st |= 0x40;
if (!State.Chan_A)
st |= 0x20;
// more ifs can be added here for the other fields.
send_block[send_cnt++] = (uchar)st;
lastcrc16 = docrc16(portnum, st);
// read CRC16
send_block[send_cnt++] = 0xFF;
send_block[send_cnt++] = 0xFF;
// now send the block
if (owBlock(portnum, FALSE, send_block, send_cnt)) {
// perform the CRC16 on the last 2 bytes of packet
lastcrc16 = docrc16(portnum, send_block[send_cnt - 2]);
lastcrc16 = docrc16(portnum, send_block[send_cnt - 1]);
// verify crc16 is correct
if (lastcrc16 == 0xB001)
rt = TRUE;
}
}
// return the result flag rt
return rt;
}
//----------------------------------------------------------------------
// SUBROUTINE - SwitchStateToString12
//
// This routine uses the info byte to return a string with all the data.
//
// 'infobyte' - This is the information byte data from the hardware.
// 'outstr' - This will be the output string. It gets set in the
// the procedure.
//
// return the length of the string
//
int SwitchStateToString12(int infobyte, char *outstr) {
int cnt = 0;
if (infobyte & 0x40) {
cnt += sprintf(outstr + cnt, "%s", "Channel A and B\n");
if (infobyte & 0x80)
cnt += sprintf(outstr + cnt, "%s", "Supply\n");
else
cnt += sprintf(outstr + cnt, "%s", "No Supply\n");
if (infobyte & 0x20)
cnt += sprintf(outstr + cnt, "%s", "Activity on PIO-B\n");
else
cnt += sprintf(outstr + cnt, "%s", "No activity on PIO-B\n");
if (infobyte & 0x10)
cnt += sprintf(outstr + cnt, "%s", "Activity on PIO-A\n");
else
cnt += sprintf(outstr + cnt, "%s", "No activity on PIO-A\n");
if (infobyte & 0x08)
cnt += sprintf(outstr + cnt, "%s", "Hi level on PIO B\n");
else
cnt += sprintf(outstr + cnt, "%s", "Lo level on PIO B\n");
if (infobyte & 0x04)
cnt += sprintf(outstr + cnt, "%s", "Hi level on PIO A\n");
else
cnt += sprintf(outstr + cnt, "%s", "Lo level on PIO A\n");
if (infobyte & 0x02)
cnt += sprintf(outstr + cnt, "%s", "Channel B off\n");
else
cnt += sprintf(outstr + cnt, "%s", "Channel B on\n");
if (infobyte & 0x01)
cnt += sprintf(outstr + cnt, "%s", "Channel A off\n");
else
cnt += sprintf(outstr + cnt, "%s", "Channel A on\n");
} else {
cnt += sprintf(outstr + cnt, "%s", "Channel A\n");
if (infobyte & 0x80)
cnt += sprintf(outstr + cnt, "%s", "Supply\n");
else
cnt += sprintf(outstr + cnt, "%s", "No Supply\n");
if (infobyte & 0x10)
cnt += sprintf(outstr + cnt, "%s", "Activity on PIO-A\n");
else
cnt += sprintf(outstr + cnt, "%s", "No activity on PIO-A\n");
if (infobyte & 0x04)
cnt += sprintf(outstr + cnt, "%s", "Hi level on PIO A\n");
else
cnt += sprintf(outstr + cnt, "%s", "Lo level on PIO A\n");
if (infobyte & 0x01)
cnt += sprintf(outstr + cnt, "%s", "Channel A off\n");
else
cnt += sprintf(outstr + cnt, "%s", "Channel A on\n");
}
return cnt;
}
w1retap/src/libusblinux300/swt12.h 0000664 0000000 0000000 00000003427 14464462352 0017164 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// Swt12.H - Include file for Switch Library
// Version 2.00
//
// Typedefs
typedef struct tagSRAM {
uchar Supply;
uchar Chan_B;
uchar Chan_A;
uchar Chan_Sel;
uchar Sour_Sel;
uchar Polarity;
} SwitchProps;
// Local subroutines
int ReadSwitch12(int, int);
int SetSwitch12(int, uchar *, SwitchProps);
int SwitchStateToString12(int, char *);
w1retap/src/libusblinux300/swt1f.c 0000664 0000000 0000000 00000023776 14464462352 0017254 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//--------------------------------------------------------------------------
//
// swt1f.c - Does commands on the DS2409 device
// version 2.00
// - future version will have branch of a branch searches
//
// Include files
#include
#include "ownet.h"
#include "swt1f.h"
//----------------------------------------------------------------------
// SUBROUTINE - SetSwitch1F
//
// This routine sets the main and auxilary on and off for DS2409.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'SerialNum' - Serial Number of DS2409 to set the switch state
// 'Swtch' - '0' Sets Main and Auxilary off
// '1' Sets Main on
// '2' Sets Auxilary on
// '3' Read Status Info Byte
// '4' Smart On Main
// 'NumExtra' - The number of extra bytes for a command.
// 'InfoByte' - Returns the info byte and other information depending
// on the command. The InfoByte size changes depending on
// the NumExtra which is buffer length * (NumExtra + 1)
// 'rst' - True then reset the search for devices
// False don't reset search
//
// Returns: TRUE(1) State of DS2409 set and verified
// FALSE(0) could not set the DS2409, perhaps device is not
// in contact
//
int SetSwitch1F(int portnum, uchar *SerialNum, int Swtch, int NumExtra, uchar *InfoByte, int rst) {
int send_cnt, i, cmd;
uchar send_block[50];
if (owAccess(portnum)) {
send_cnt = 0;
// add the match command
send_block[send_cnt++] = 0x55;
for (i = 0; i < 8; i++)
send_block[send_cnt++] = SerialNum[i];
// the command
switch (Swtch) {
case 0: // All lines off
send_block[send_cnt++] = 0x66;
cmd = 0x66;
break;
case 1: // Direct on Main
send_block[send_cnt++] = 0xA5;
cmd = 0xA5;
break;
case 2: // Smart on Auxilary
send_block[send_cnt++] = 0x33;
cmd = 0x33;
break;
case 3: // Status Read/Write
send_block[send_cnt++] = 0x5A;
cmd = 0x5A;
// bytes 0-2: don't care
// bytes 3-4: write control 0 to change status
// byte 5: 0 = auto-control, 1 = manual mode
// byte 6: 0 = main, 1 = auxiliary
// byte 7: value to be written to control output, manual mode only
// 0x00 default value
*InfoByte = 0x00;
send_block[send_cnt++] = *InfoByte;
break;
case 4: // Smart on Main
send_block[send_cnt++] = 0xCC;
cmd = 0xCC;
break;
default:
return FALSE;
}
// extra bytes and confirmation
for (i = 0; i <= NumExtra; i++)
send_block[send_cnt++] = 0xFF;
// send the command string
if (owBlock(portnum, rst, send_block, send_cnt)) {
// returned information for the info byte and command
for (i = 0; i <= NumExtra; i++)
*(InfoByte + (NumExtra - i)) = send_block[send_cnt - (i + 2)];
// Set because for the read/write command the confirmation
// byte is the same as the status byte
if (Swtch == 3)
cmd = send_block[send_cnt - 2];
if (send_block[send_cnt - 1] == cmd)
return TRUE;
}
}
return FALSE;
}
//----------------------------------------------------------------------
// SUBROUTINE = FindBranchDevices
//
// This routine will find all the branches on a certain DS2409 device and
// will return the serial numbers down that branch
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'Branch[8]' - The serial number of the branch to look down
// 'BranchSN[][8]' - The list of serial numbers on the branch
// 'MAXDEVICES' - The Max devices on the branch
// 'MainBr' - True to search down the main branch, False for Aux.
//
// Returns: Returns the number of devices found on the branch
//
int FindBranchDevice(int portnum, uchar *Branch, uchar BranchSN[][8], int MAXDEVICES, int MainBr) {
int NumDevices = 0;
short result;
result = owBranchFirst(portnum, Branch, FALSE, MainBr);
while (result) {
owSerialNum(portnum, BranchSN[NumDevices], TRUE);
NumDevices++;
result = owBranchNext(portnum, Branch, FALSE, MainBr);
}
return NumDevices;
}
//----------------------------------------------------------------------
// SUBROUTINE - owBranchFirst
//
// This routine is used like owFirst but for devices on a branch.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'BrSN' - This is the DS2409 device branch
// 'AlarmD' - True or False, to do Alarm search or false for regular search
// 'FirMain' - True then search main branch, False search Aux. branch
//
// 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 1-Wire Net.
//
int owBranchFirst(int portnum, uchar *BrSN, int AlarmD, int FirMain) {
int smart_main = 4;
int smart_aux = 2;
int numextra = 2;
uchar extra[3];
if (FirMain) {
if (SetSwitch1F(portnum, &BrSN[0], smart_main, numextra, extra, TRUE))
if (extra[2] != 0xFF)
return owFirst(portnum, FALSE, AlarmD);
} else {
if (SetSwitch1F(portnum, &BrSN[0], smart_aux, numextra, extra, TRUE))
if (extra[2] != 0xFF)
return owFirst(portnum, FALSE, AlarmD);
}
return FALSE;
}
//----------------------------------------------------------------------
// SUBROUTINE - owBranchNext
//
// This routine is used like owFirst but for devices on a branch.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'BrSN' - This is the DS2409 device branch
// 'AlarmD' - True or False, to do Alarm search or false for regular search
// 'NextMain' - True then search main branch, False search Aux. branch
//
// 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 1-Wire Net.
//
int owBranchNext(int portnum, uchar *BrSN, int AlarmD, int NextMain) {
int smart_main = 4;
int smart_aux = 2;
int numextra = 2;
uchar extra[3];
if (NextMain) {
if (SetSwitch1F(portnum, &BrSN[0], smart_main, numextra, extra, TRUE))
return owNext(portnum, FALSE, AlarmD);
} else {
if (SetSwitch1F(portnum, &BrSN[0], smart_aux, numextra, extra, TRUE))
return owNext(portnum, FALSE, AlarmD);
}
return FALSE;
}
//----------------------------------------------------------------------
// SUBROUTINE - SwitchStateToString
//
// This routine uses the info byte to return a string with all the data.
//
// 'infobyte' - This is the information byte data from the hardware.
// 'outstr' - This will be the output string. It gets set in the
// the procedure.
//
// Returns - Returns the number of characters in the string
//
int SwitchStateToString1F(int infobyte, char *outstr) {
int cnt = 0;
if (infobyte & 0x80) {
cnt += sprintf(outstr + cnt, "%s", "Manual mode\n");
if (infobyte & 0x40)
cnt += sprintf(outstr + cnt, "%s", "Output transistor on\n");
else
cnt += sprintf(outstr + cnt, "%s", "Output transistor off\n");
} else {
cnt += sprintf(outstr + cnt, "%s", "Auto-control mode\n");
if (infobyte & 0x40)
cnt += sprintf(outstr + cnt, "%s", "Output association with Auxillary\n");
else
cnt += sprintf(outstr + cnt, "%s", "Output association with Main\n");
}
if (infobyte & 0x20)
cnt += sprintf(outstr + cnt, "%s", "Negative edge sensed since inactive on Main\n");
else
cnt += sprintf(outstr + cnt, "%s", "No event on Main\n");
if (infobyte & 0x10)
cnt += sprintf(outstr + cnt, "%s", "Negative edge sensed since inactive on Aux.\n");
else
cnt += sprintf(outstr + cnt, "%s", "No event on Aux.\n");
if (infobyte & 0x08)
cnt += sprintf(outstr + cnt, "%s", "Voltage High on Aux. output\n");
else
cnt += sprintf(outstr + cnt, "%s", "Voltage Low on Aux. output\n");
if (infobyte & 0x04)
cnt += sprintf(outstr + cnt, "%s", "Inactive status of Aux. output\n");
else
cnt += sprintf(outstr + cnt, "%s", "Active status of Aux. output\n");
if (infobyte & 0x02)
cnt += sprintf(outstr + cnt, "%s", "Voltage High on Main output\n");
else
cnt += sprintf(outstr + cnt, "%s", "Voltage Low on Main output\n");
if (infobyte & 0x01)
cnt += sprintf(outstr + cnt, "%s", "Inactive status on Main output\n");
else
cnt += sprintf(outstr + cnt, "%s", "Active status on Main output\n");
return cnt;
}
w1retap/src/libusblinux300/swt1f.h 0000664 0000000 0000000 00000003616 14464462352 0017250 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//--------------------------------------------------------------------------
//
// swt1f.c - Header for the commands on the DS2409 device
//
// Local subroutines
int SetSwitch1F(int, uchar *, int, int, uchar *, int);
int SwitchStateToString1F(int, char *);
int FindBranchDevice(int, uchar *, uchar BranchSN[][8], int, int);
int owBranchFirst(int, uchar *, int, int);
int owBranchNext(int, uchar *, int, int);
// Constant definitions
#define SWITCH_FAMILY 0x1F
#define ALL_LINES_OFF 0
#define DIRECT_MAIN_ON 1
#define AUXILARY_ON 2
#define STATUS_RW 3
w1retap/src/libusblinux300/swtloop.c 0000664 0000000 0000000 00000013446 14464462352 0017710 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//--------------------------------------------------------------------------
//
// swtloop.C - Goes through the testing of the DS2406(DS2407) switch
// Version 2.00
// Include files
#include
#include
#include "ownet.h"
#include "swt12.h"
#include "findtype.h"
// Constant definition
#define SWITCH_FAMILY 0x12
#define MAXDEVICES 15
// local
int getNumber(int min, int max);
//--------------------------------------------------------------------------
// This is the begining of the program that tests the different Channels
int main(int argc, char **argv) {
int i, j, k, n; // loop counters
short test = 0; // info byte data
short clear = 0; // used to clear the button
SwitchProps sw; // used to set Channel A and B
uchar SwitchSN[MAXDEVICES][8]; // the serial numbers for the devices
int num; // for the number of devices present
char out[140]; // used for output of the info byte data
short done = FALSE; // used to indicate the end of the input loop from user
int portnum = 0;
//----------------------------------------
// Introduction header
printf("\n/---------------------------------------------\n");
printf(" swtest - V2.00\n"
" The following is a test to excersize the\n"
" different channels on the DS2406.\n");
printf(" Press any CTRL-C to stop this program.\n\n");
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
// attempt to acquire the 1-Wire Net
if ((portnum = owAcquireEx(argv[1])) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
// success
printf("Port opened: %s\n", argv[1]);
// this is to get the number of the devices and the serial numbers
num = FindDevices(portnum, &SwitchSN[0], SWITCH_FAMILY, MAXDEVICES);
// setting up the first print out for the frist device
owSerialNum(portnum, SwitchSN[0], FALSE);
j = 1;
n = 0;
do {
printf("\n\n");
for (k = 0; k < num; k++) {
printf("%d ", k);
for (i = 7; i >= 0; i--) {
printf("%02X", SwitchSN[k][i]);
}
printf("\n");
}
printf("%d To quit.\n", k);
printf("\n");
printf("Pick a device\n");
n = getNumber(0, num);
if (n == num) {
n = 0; // used to finish off the loop
done = TRUE;
break;
}
owSerialNum(portnum, SwitchSN[n], FALSE);
j = 1;
printf("\n");
test = ReadSwitch12(portnum, clear);
// This looks at the info byte to determine if it is a
// two or one channel device.
if (test & 0x40) {
switch (j) {
case 1:
sw.Chan_A = 0;
sw.Chan_B = 0;
break;
case 2:
sw.Chan_A = 0;
sw.Chan_B = 1;
break;
case 3:
sw.Chan_A = 1;
sw.Chan_B = 0;
break;
case 4:
sw.Chan_A = 1;
sw.Chan_B = 1;
break;
default:
sw.Chan_A = 1;
sw.Chan_B = 1;
j = 0;
break;
}
} else {
switch (j) {
case 1:
sw.Chan_B = 0;
sw.Chan_A = 0;
break;
case 2:
sw.Chan_B = 0;
sw.Chan_A = 1;
break;
default:
sw.Chan_B = 0;
sw.Chan_A = 1;
j = 0;
break;
}
}
if (!SetSwitch12(portnum, SwitchSN[n], sw)) {
msDelay(50);
if (SetSwitch12(portnum, SwitchSN[n], sw))
msDelay(50);
else
printf("Switch not set\n");
}
test = ReadSwitch12(portnum, clear);
printf("\n");
for (i = 7; i >= 0; i--) {
printf("%02X", SwitchSN[n][i]);
}
printf("\n");
SwitchStateToString12(test, out);
printf("%s", out);
j++;
} while (!done);
owRelease(portnum);
printf("Closing port %s.\n", argv[1]);
exit(0);
return 0;
}
/**
* Retrieve user input from the console.
*
* min minimum number to accept
* max maximum number to accept
*
* @return numeric value entered from the console.
*/
int getNumber(int min, int max) {
int value = min, cnt;
int done = FALSE;
do {
cnt = scanf("%d", &value);
if (cnt > 0 && (value > max || value < min)) {
printf("Value (%d) is outside of the limits (%d,%d)\n", value, min, max);
printf("Try again:\n");
} else
done = TRUE;
} while (!done);
return value;
}
w1retap/src/libusblinux300/swtsngl.c 0000664 0000000 0000000 00000007560 14464462352 0017702 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//--------------------------------------------------------------------------
//
// swtsngl.C - Goes through the testing of the DS2405 device
// Version 2.00
//
// Include files
#include
#include
#include "ownet.h"
#include "swt05.h"
#include "findtype.h"
// Constant definitions
#define MAXDEVICES 15
//--------------------------------------------------------------------------
// This is the begining of the program that tests the commands for the
// DS2405
//
int main(int argc, char **argv) {
uchar SwitchSN[MAXDEVICES][8]; // the serial numbers for the devices
short i, j; // loop counters
int num; // for the number of DS2405s
int lev;
int portnum = 0;
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
// attempt to acquire the 1-Wire Net
if ((portnum = owAcquireEx(argv[1])) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
// this is to get the number of the devices and the serial numbers
num = FindDevices(portnum, &SwitchSN[0], SWITCH_FAMILY, MAXDEVICES);
for (i = 0; i < num; i++) {
if (SetSwitch05(portnum, SwitchSN[i], 1)) {
printf("Device ");
for (j = 7; j >= 0; j--)
printf("%02X", SwitchSN[i][j]);
printf(" is active\n");
} else
printf("Error setting device on\n");
if (ReadSwitch05(portnum, SwitchSN[i], &lev)) {
printf("Device ");
for (j = 7; j >= 0; j--)
printf("%02X", SwitchSN[i][j]);
if (lev)
printf(" is active and is high.\n");
else
printf(" is active and is low.\n");
} else
printf("Error reading active device\n");
if (SetSwitch05(portnum, SwitchSN[i], 0)) {
printf("Device ");
for (j = 7; j >= 0; j--)
printf("%02X", SwitchSN[i][j]);
printf(" is not active\n");
} else
printf("Error setting device off\n");
if (!ReadSwitch05(portnum, SwitchSN[i], &lev)) {
printf("Device ");
for (j = 7; j >= 0; j--)
printf("%02X", SwitchSN[i][j]);
if (lev)
printf(" is not active and is high.\n");
else
printf(" is not active and is low.\n");
} else
printf("Error reading nonactive device\n");
}
if (num == 0)
printf("DS2405 not found on the 1-Wire Network.\n");
owRelease(portnum);
printf("Closing port %s.\n", argv[1]);
exit(0);
return 0;
}
w1retap/src/libusblinux300/tcrc.c 0000664 0000000 0000000 00000000441 14464462352 0017123 0 ustar 00root root 0000000 0000000 #include
#include "ownet.h"
int main(int argc, char **argv) {
unsigned char lc, blk[] = {0x54, 0x3d, 0x1a, 0x2b, 0x64, 0x48, 0x3d, 0x05, 0xd5, 0x97};
int i;
setcrc8(0, 0);
for (i = 2; i < 5; i++) {
lc = docrc8(0, blk[i]);
}
printf("CRC %d\n", lc);
return 0;
}
w1retap/src/libusblinux300/temp.c 0000664 0000000 0000000 00000010545 14464462352 0017143 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// temp.c - Application to find and read the 1-Wire Net
// DS1920/DS1820/DS18S20 - temperature measurement.
//
// This application uses the files from the 'Public Domain'
// 1-Wire Net libraries ('general' and 'userial').
//
//
// Version: 2.00
//
#include
#include
#include "ownet.h"
#include "temp10.h"
#include "findtype.h"
// defines
#define MAXDEVICES 20
// Timeout to read temp values
#define TEMPMSECS 1000
// global serial numbers
uchar FamilySN[MAXDEVICES][8];
// variables
int family_code;
//----------------------------------------------------------------------
// Main Test for DS1920/DS1820 temperature measurement
//
int main(int argc, char **argv) {
float current_temp;
int i = 0;
int NumDevices = 0;
int portnum = 0;
//----------------------------------------
// Introduction header
printf("\n/---------------------------------------------\n");
printf(" Temperature application DS1920/DS1820/DS18B20 - Version 1.00 \n"
" The following is a test to exersize a DS1920/DS18[B]20.\n"
" Temperature Find and Read from a: \n"
" DS1920/DS18[B]20 (at least 1)\n\n");
printf(" Press any CTRL-C to stop this program.\n\n");
printf(" Output [Serial Number(s) ........ Temp1(F)] \n\n");
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX),"
"\"DS2490-1\" (Linux USB:1).\n");
exit(1);
}
// attempt to acquire the 1-Wire Net
if ((portnum = owAcquireEx(argv[1])) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
// success
printf("Port opened: %s\n", argv[1]);
// Find the device(s) -- try DS1920/DS1820
NumDevices = FindDevices(portnum, &FamilySN[0], 0x10, MAXDEVICES);
if (NumDevices == 0) { // try DS18B20
NumDevices = FindDevices(portnum, &FamilySN[0], 0x28, MAXDEVICES);
}
if (NumDevices > 0) {
printf("\n");
printf("Device(s) Found: \n");
for (i = 0; i < NumDevices; i++) {
PrintSerialNum(FamilySN[i]);
printf("\n");
}
printf("\n\n");
// (stops on CTRL-C)
do {
// read the temperature and print serial number and temperature
for (i = 0; i < NumDevices; i++) {
if (ReadTemperature(portnum, FamilySN[i], ¤t_temp, TEMPMSECS)) {
PrintSerialNum(FamilySN[i]);
printf(" %5.1fC %5.1fF \n", current_temp, current_temp * 9 / 5 + 32);
// converting temperature from Celsius to Fahrenheit
} else
printf(" Error reading temperature, verify device present:%d\n", (int)owVerify(portnum, FALSE));
}
printf("\n");
} while (!key_abort());
} else
printf("\n\n\nERROR, device DS1920/DS1820 not found!\n");
// release the 1-Wire Net
owRelease(portnum);
printf("Closing port %s.\n", argv[1]);
exit(0);
return 0;
}
w1retap/src/libusblinux300/temp10.c 0000664 0000000 0000000 00000010706 14464462352 0017303 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
// ---------------------------------------------------------------------------
//
// temp10.C - Module to read the DS1920/DS1820 - temperature measurement.
//
// Version: 2.00
//
// ---------------------------------------------------------------------------
//
//
#include "ownet.h"
#include "temp10.h"
//----------------------------------------------------------------------
// Read the temperature of a DS1920/DS1820
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
// OpenCOM to indicate the port number.
// 'SerialNum' - Serial Number of DS1920/DS1820 to read temperature from
// 'Temp ' - pointer to variable where that temperature will be
// returned
//
// Returns: TRUE(1) temperature has been read and verified
// FALSE(0) could not read the temperature, perhaps device is not
// in contact
//
int ReadTemperature(int portnum, uchar *SerialNum, float *Temp, int iwait) {
uchar rt = FALSE;
uchar send_block[30], lastcrc8 = 0;
int send_cnt, tsht, i, loop = 0;
float tmp, cr, cpc;
// set the device serial number to the counter device
owSerialNum(portnum, SerialNum, FALSE);
for (loop = 0; loop < 2; loop++) {
// access the device
if (owAccess(portnum)) {
// send the convert command and start power delivery
if (!owWriteBytePower(portnum, 0x44))
return FALSE;
// sleep for settle time second
msDelay(iwait);
// turn off the 1-Wire Net strong pull-up
if (owLevel(portnum, MODE_NORMAL) != MODE_NORMAL)
return FALSE;
// access the device
if (owAccess(portnum)) {
// create a block to send that reads the temperature
// read scratchpad command
send_cnt = 0;
send_block[send_cnt++] = 0xBE;
// now add the read bytes for data bytes and crc8
for (i = 0; i < 9; i++)
send_block[send_cnt++] = 0xFF;
// now send the block
if (owBlock(portnum, FALSE, send_block, send_cnt)) {
// initialize the CRC8
setcrc8(portnum, 0);
// perform the CRC8 on the last 8 bytes of packet
for (i = send_cnt - 9; i < send_cnt; i++)
lastcrc8 = docrc8(portnum, send_block[i]);
// verify CRC8 is correct
if (lastcrc8 == 0x00) {
if (SerialNum[0] == 0x28) {
short itmp = (send_block[2] << 8) | send_block[1];
tmp = itmp / 16.0;
} else {
// calculate the high-res temperature
tsht = send_block[1] / 2;
if (send_block[2] & 0x01)
tsht |= -128;
tmp = (float)(tsht);
cr = send_block[7];
cpc = send_block[8];
if (((cpc - cr) == 1) && (loop == 0))
continue;
if (cpc == 0)
return FALSE;
else
tmp = tmp - (float)0.25 + (cpc - cr) / cpc;
}
*Temp = tmp;
// success
rt = TRUE;
break;
}
}
}
}
}
// return the result flag rt
return rt;
}
w1retap/src/libusblinux300/temp10.h 0000664 0000000 0000000 00000003232 14464462352 0017304 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
// ---------------------------------------------------------------------------
//
// temp10.h - Header to read the DS1920/DS1820 - temperature measurement.
//
// Version: 2.00
//
// ---------------------------------------------------------------------------
int ReadTemperature(int, uchar *, float *, int);
w1retap/src/libusblinux300/temptest.c 0000664 0000000 0000000 00000004636 14464462352 0020047 0 ustar 00root root 0000000 0000000 #include
#include
#include
#include "ownet.h"
#include "temp10.h"
#include "findtype.h"
#include "swt1f.h"
#include
#define TEMPMSECS 1000
static void w1_make_serial(char *asc, unsigned char *bin) {
int i, j;
for (i = j = 0; i < 8; i++) {
bin[i] = ToHex(asc[j]) << 4;
j++;
bin[i] += ToHex(asc[j]);
j++;
}
}
static void w1_set_coupler(int portnum, uchar *ident, int line) {
uchar a[4];
SetSwitch1F(portnum, ident, line, 2, a, TRUE);
}
static int w1_select_device(int portnum, uchar *serno, uchar *coupler, int line) {
u_char thisdev[8];
int found = 0;
if (coupler) {
w1_set_coupler(portnum, coupler, 0);
w1_set_coupler(portnum, coupler, line);
}
owFamilySearchSetup(portnum, serno[0]);
while (owNext(portnum, TRUE, FALSE)) {
owSerialNum(portnum, thisdev, TRUE);
if (memcmp(thisdev, serno, sizeof(thisdev)) == 0) {
found = 1;
break;
}
}
return found;
}
int main(int argc, char **argv) {
float current_temp;
int portnum = 0;
char *serial = NULL, *dev = NULL;
u_char ident[8];
char *coupler = NULL;
u_char *cident = NULL;
int c;
int bra = 0;
while ((c = getopt(argc, argv, "amc:s:")) != EOF) {
switch (c) {
case 'a':
bra = 2;
break;
case 'm':
bra = 4;
break;
case 's':
serial = strdup(optarg);
break;
case 'c':
coupler = strdup(optarg);
break;
default:
break;
}
}
dev = argv[optind];
if (dev == NULL || serial == NULL) {
fputs("usage: temptest -s serial [-c coupler -a|-m ] device\n"
" device => /dev/ttyS0 or DS2490-1\n",
stderr);
return 0;
}
if ((portnum = owAcquireEx(dev)) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
w1_make_serial(serial, ident);
if (coupler) {
cident = malloc(32);
w1_make_serial(coupler, cident);
}
if (!w1_select_device(portnum, ident, cident, bra)) {
fputs("No dev\n", stderr);
exit(1);
}
if (ReadTemperature(portnum, ident, ¤t_temp, TEMPMSECS)) {
PrintSerialNum(ident);
printf(" %5.1fC %5.1fF \n", current_temp, current_temp * 9 / 5 + 32);
// converting temperature from Celsius to Fahrenheit
} else {
printf(" Error reading temperature, verify device present:%d\n", (int)owVerify(portnum, FALSE));
}
if (coupler) {
w1_set_coupler(portnum, cident, 0);
}
owRelease(portnum);
return 0;
}
w1retap/src/libusblinux300/thermo21.c 0000664 0000000 0000000 00000121077 14464462352 0017642 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// thermo21.c - Thermochron iButton utility functions
//
// Version: 2.00
//
// History:
// 1.03 -> 2.00 Reorganization of Public Domain Kit
// Convert to global CRC utility functions
// Y2K fix.
#include "ownet.h"
#include "thermo21.h"
#include
#include
// Include files for the Palm and Visor
#ifdef __MC68K__
#include
#include
#else
#include
#endif
// Local Function Prototypes
static int ThermoStep(int, ThermoStateType *, ThermoScript *, int *, int *, int *, char *);
static int ReadPages(int, int, int, int *, uchar *);
static int WriteScratch(int, uchar *, int, int);
static int CopyScratch(int, int, int);
static int WriteMemory(int, uchar *, int, int);
// global state information
static int current_speed[MAX_PORTNUM];
// download steps
static ThermoScript Download[] = {{ST_READ_STATUS, "Setup to read the mission status"},
{ST_READ_PAGES, "Read the status page"},
{ST_READ_ALARM, "Setup to read alarm pages"},
{ST_READ_PAGES, "Read the alarm pages"},
{ST_READ_HIST, "Setup to read histogram pages"},
{ST_READ_PAGES, "Read the histogram pages"},
{ST_READ_LOG, "Setup to read log pages"},
{ST_READ_PAGES, "Read the log pages"},
{ST_FINISH, "Finished"}};
// read status only steps
static ThermoScript GetStatus[] = {
{ST_READ_STATUS, "Setup to read the mission status"}, {ST_READ_PAGES, "Read the status page"}, {ST_FINISH, "Finished"}};
// mission steps (assume already did StatusThermo)
static ThermoScript Mission[] = {{ST_CLEAR_SETUP, "Setup clear memory"},
{ST_WRITE_MEM, "Write clear memory bit"},
{ST_CLEAR_MEM, "Clear the memory"},
{ST_READ_STATUS, "Setup to read the mission status"},
{ST_READ_PAGES, "Read the status page"},
{ST_CLEAR_VERIFY, "Verify memory is clear"},
{ST_WRITE_TIME, "Setup to write the real time clock"},
{ST_WRITE_MEM, "Write the real time clock"},
{ST_WRITE_CONTROL, "Setup to write the control"},
{ST_WRITE_MEM, "Write the control"},
{ST_WRITE_RATE, "Setup to write the sample rate to start mission"},
{ST_WRITE_MEM, "Write the sample rate"},
{ST_READ_STATUS, "Read the new mission status"},
{ST_FINISH, "Finished"}};
//--------------------------------------------------------------------------
// The 'DownloadThermo' downloads the specified Thermochron in 'SerialNum'
// and puts the data in the state variable 'ThermoState'. Progress output
// is printed to the specified file 'fp'.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'SerialNum' - Device serial number to download
// 'ThermoState' - pointer to a structure type that holds the raw and
// translated Thermochron data.
// 'fp' - file pointer to print status information to
//
// Returns: TRUE (1) : Thermochron download with raw data in ThermoState
// FALSE (0): not downloaded. Abort due to repeated errors
// or user keypress.
//
int DownloadThermo(int portnum, uchar *SerialNum, ThermoStateType *ThermoState, FILE *fp) {
// set the serial num
owSerialNum(portnum, SerialNum, FALSE);
// run the script and download thermochron
return RunThermoScript(portnum, ThermoState, Download, fp);
}
//--------------------------------------------------------------------------
// The 'ReadThermoStatus' reads the Thermochron status in 'SerialNum'
// and puts the data in the state variable 'ThermoState'. Progress output
// is printed to the specified file 'fp'.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'SerialNum' - Device serial number to download
// 'ThermoState' - pointer to a structure type that holds the raw and
// translated Thermochron data.
// 'fp' - file pointer to print status information to
//
// Returns: TRUE (1) : Thermochron status read with raw data in ThermoState
// FALSE (0): status not read. Abort due to repeated errors
// or user keypress.
//
int ReadThermoStatus(int portnum, uchar *SerialNum, ThermoStateType *ThermoState, FILE *fp) {
// set the serial num
owSerialNum(portnum, SerialNum, FALSE);
// run the script and read status of thermochron
return RunThermoScript(portnum, ThermoState, GetStatus, fp);
}
//--------------------------------------------------------------------------
// The 'MissionThermo' starts a new Thermochron mission on 'SerialNum'
// from the state information provided in 'ThermoState'. Progress output
// is printed to the specified file 'fp'.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'SerialNum' - Device serial number to download
// 'ThermoState' - pointer to a structure type that holds the raw and
// translated Thermochron data.
// 'fp' - file pointer to print status information to
//
// Returns: TRUE (1) : Thermochron missioned
// FALSE (0): not missioned. Abort due to repeated errors
// or user keypress.
//
int MissionThermo(int portnum, uchar *SerialNum, ThermoStateType *ThermoState, FILE *fp) {
// set the serial num
owSerialNum(portnum, SerialNum, FALSE);
// run the script and mission thermochron
return RunThermoScript(portnum, ThermoState, Mission, fp);
}
//--------------------------------------------------------------------------
// Run the specified script. Return TRUE if all steps completed else FALSE.
// Status is printed to file 'fp'.
//
int RunThermoScript(int portnum, ThermoStateType *ThermoState, ThermoScript script[], FILE *fp) {
char msg[256], LastDescription[256], LastMsg[256];
int StepCount, SubStep, ErrorCount, Status;
int last_clear_step = 0;
// reset the step to the begining
StepCount = 0;
SubStep = 0;
ErrorCount = 0;
Status = STATUS_INPROGRESS;
LastDescription[0] = 0;
LastMsg[0] = 0;
// loop to perform all of the steps to download the Thermochron
do {
// switch on the status of the last step done
switch (Status) {
// step complete so go to the next
case STATUS_STEP_COMPLETE:
StepCount++;
SubStep = 0;
ErrorCount = 0;
Status = STATUS_INPROGRESS;
LastDescription[0] = 0;
LastMsg[0] = 0;
break;
// in progress so call again
case STATUS_INPROGRESS:
// record the step position of the last memory clear
// this is in case we need to attempt a clear again
if (script[StepCount].Step == ST_CLEAR_SETUP)
last_clear_step = StepCount;
// print step description if different
if (strcmp(LastDescription, script[StepCount].StepDescription) != 0) {
fprintf(fp, "%s --> ", script[StepCount].StepDescription);
sprintf(LastDescription, "%s", script[StepCount].StepDescription);
}
// perform a step in the job
Status = ThermoStep(portnum, ThermoState, &script[StepCount], &SubStep, &Status, &ErrorCount, msg);
// print results if different
if (strcmp(LastMsg, msg) != 0) {
fprintf(fp, "%s\n", msg);
sprintf(LastMsg, "%s", msg);
} else
fprintf(fp, ".");
break;
// encountered a transient error
case STATUS_ERROR_TRANSIENT:
// check if transient error is a memory clear
if (script[StepCount].Step == ST_CLEAR_VERIFY) {
// put back to starting clear over again
StepCount = last_clear_step;
SubStep = 0;
ErrorCount = 0;
Status = STATUS_INPROGRESS;
break;
}
// if 20 tansient errors in a row then abort
if (ErrorCount > 20)
Status = STATUS_ERROR_HALT;
else
Status = STATUS_INPROGRESS;
break;
// all steps complete
case STATUS_COMPLETE:
fprintf(fp, "End script normally\n");
return TRUE;
// non-recoverable error
case STATUS_ERROR_HALT:
fprintf(fp, "Aborting script due to non-recoverable error\n");
return FALSE;
}
} while (!key_abort());
// key abort
fprintf(fp, "Aborting script due to key press\n");
return FALSE;
}
//----------------------------------------------------------------------
// Use the script to perform a step and return.
//
int ThermoStep(int portnum, ThermoStateType *ThermoState, ThermoScript *StateScript, int *SubStep, int *Status, int *ErrorCount,
char *msg) {
short rslt;
static int read_page_num, read_pages, write_addr, write_len;
static uchar *read_buf, *write_buf;
static uchar tbuf[5];
// do the current step
switch (StateScript->Step) {
// the operation is complete
case ST_FINISH:
sprintf(msg, "Operation complete");
*Status = STATUS_COMPLETE;
break;
// read the mission status page
case ST_READ_STATUS:
read_page_num = STATUS_PAGE;
read_pages = 1;
read_buf = ThermoState->MissStat.status_raw;
sprintf(msg, "Ready to read status page %d", read_page_num);
*Status = STATUS_STEP_COMPLETE;
break;
// set up to read the alarm registers
case ST_READ_ALARM:
read_page_num = 17;
read_pages = 3;
read_buf = ThermoState->AlarmData.alarm_raw;
sprintf(msg, "Ready to read alarm pages %d to %d", read_page_num, read_page_num + read_pages - 1);
*Status = STATUS_STEP_COMPLETE;
break;
// set up to read the histogram data
case ST_READ_HIST:
read_page_num = 64;
read_pages = 4;
read_buf = ThermoState->HistData.hist_raw;
sprintf(msg, "Ready to read histogram pages %d to %d", read_page_num, read_page_num + read_pages - 1);
*Status = STATUS_STEP_COMPLETE;
break;
// set up to read the log data
case ST_READ_LOG:
read_page_num = 128;
read_pages = 64;
read_buf = ThermoState->LogData.log_raw;
sprintf(msg, "Ready to read log pages %d to %d", read_page_num, read_page_num + read_pages - 1);
*Status = STATUS_STEP_COMPLETE;
break;
// read the specified pages
case ST_READ_PAGES:
// check for last page
if (*SubStep == 0)
// set the sub-step to the current page being read
*SubStep = read_page_num;
// read the status page
rslt = ReadPages(portnum, read_page_num, read_pages, SubStep, read_buf);
if (rslt == FALSE) {
sprintf(msg, "Thermochron not on 1-Wire Net");
#ifdef __MC68K__
*Status = STATUS_ERROR_HALT;
#else
*Status = STATUS_INPROGRESS;
#endif
} else {
sprintf(msg, "Pages read from Thermochron");
*Status = STATUS_STEP_COMPLETE;
}
break;
// setup the clear memory
case ST_CLEAR_SETUP:
// create a small buff to write to start the clear memory
tbuf[0] = 0x40;
write_buf = &tbuf[0];
write_len = 1;
write_addr = 0x20E;
sprintf(msg, "Write to setup clear memory");
*Status = STATUS_STEP_COMPLETE;
break;
// clear the memory
case ST_CLEAR_MEM:
// set the clear memory command (not check return because verify)
if (!owAccess(portnum)) {
OWERROR(OWERROR_ACCESS_FAILED);
}
if (!owWriteByte(portnum, 0x3C)) {
OWERROR(OWERROR_WRITE_BYTE_FAILED);
}
msDelay(3);
if (!owTouchReset(portnum)) {
OWERROR(OWERROR_RESET_FAILED);
}
sprintf(msg, "Clear memory command sent");
*Status = STATUS_STEP_COMPLETE;
break;
// clear the memory
case ST_CLEAR_VERIFY:
// look at the memory clear bit
if ((ThermoState->MissStat.status_raw[0x14] & 0x40) == 0x40) {
sprintf(msg, "Memory is clear");
*Status = STATUS_STEP_COMPLETE;
} else {
sprintf(msg, "Memory did NOT clear");
*Status = STATUS_ERROR_TRANSIENT;
}
break;
// setup write time, clock alarm, control, trips
case ST_WRITE_TIME:
// create the write buffer
FormatMission(&ThermoState->MissStat);
write_buf = &ThermoState->MissStat.status_raw[0x00];
write_len = 13;
write_addr = 0x200;
sprintf(msg, "Write time, clock alarm, and trips setup");
*Status = STATUS_STEP_COMPLETE;
break;
// write the control, mission delay and clear flags
case ST_WRITE_CONTROL:
write_buf = &ThermoState->MissStat.status_raw[0x0E];
write_len = 7;
write_addr = 0x20E;
sprintf(msg, "Write control, mission delay, clear flags setup");
*Status = STATUS_STEP_COMPLETE;
break;
case ST_WRITE_RATE:
write_buf = &ThermoState->MissStat.status_raw[0x0D];
write_len = 1;
write_addr = 0x20D;
sprintf(msg, "Write sample rate setup");
*Status = STATUS_STEP_COMPLETE;
break;
// write the specified memory location
case ST_WRITE_MEM:
if (WriteMemory(portnum, write_buf, write_len, write_addr)) {
sprintf(msg, "Memory written to Thermochron");
*Status = STATUS_STEP_COMPLETE;
} else {
sprintf(msg, "Thermochron not on 1-Wire Net");
*Status = STATUS_INPROGRESS;
}
default:
break;
}
return *Status;
}
//----------------------------------------------------------------------
// Read a specified number of pages in overdrive
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
//
int ReadPages(int portnum, int start_pg, int num_pgs, int *last_pg, uchar *finalbuf) {
int skip_overaccess = 0, skip_access = 0;
uchar pkt[60];
int len, i;
uchar SerialNumber[8];
ushort lastcrc16;
// read the rom number
owSerialNum(portnum, SerialNumber, TRUE);
#ifndef __MC68K__
// verify device is in overdrive
if (current_speed[portnum] == MODE_OVERDRIVE) {
if (owVerify(portnum, FALSE))
skip_overaccess = 1;
}
if (!skip_overaccess) {
if (owOverdriveAccess(portnum))
current_speed[portnum] = MODE_OVERDRIVE;
else
current_speed[portnum] = MODE_NORMAL;
}
#endif
// loop while there is pages to read
do {
// create a packet to read a page
len = 0;
setcrc16(portnum, 0);
// optional skip access on subsequent pages
if (!skip_access) {
// match
pkt[len++] = 0x55;
// rom number
for (i = 0; i < 8; i++)
pkt[len++] = SerialNumber[i];
// read memory with crc command
pkt[len] = 0xA5;
lastcrc16 = docrc16(portnum, pkt[len++]);
// address
pkt[len] = (uchar)((*last_pg << 5) & 0xFF);
lastcrc16 = docrc16(portnum, pkt[len++]);
pkt[len] = (uchar)(*last_pg >> 3);
lastcrc16 = docrc16(portnum, pkt[len++]);
}
// set 32 reads for data and 2 for crc
for (i = 0; i < 34; i++)
pkt[len++] = 0xFF;
// send the bytes
if (owBlock(portnum, !skip_access, pkt, len)) {
// calucate the CRC over the last 34 bytes
for (i = 0; i < 34; i++)
lastcrc16 = docrc16(portnum, pkt[len - 34 + i]);
// check crc
if (lastcrc16 == 0xB001) {
// copy the data into the buffer
for (i = 0; i < 32; i++)
finalbuf[i + (*last_pg - start_pg) * 32] = pkt[len - 34 + i];
// change number of pages
*last_pg = *last_pg + 1;
// now skip access
skip_access = TRUE;
} else
return FALSE;
} else
return FALSE;
} while ((*last_pg - start_pg) < num_pgs);
return TRUE;
}
//----------------------------------------------------------------------------}
// Write a memory location. Data must all be on the same page
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
//
int WriteMemory(int portnum, uchar *Buf, int ln, int adr) {
// write to scratch and then copy
if (WriteScratch(portnum, Buf, ln, adr))
return CopyScratch(portnum, ln, adr);
return FALSE;
}
//----------------------------------------------------------------------------}
// Write the scratch pad
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
//
int WriteScratch(int portnum, uchar *Buf, int ln, int adr) {
int i;
uchar pbuf[80];
// check for alarm indicator
if (owAccess(portnum)) {
// construct a packet to send
pbuf[0] = 0x0F; // write scratch command
pbuf[1] = (adr & 0xFF); // address 1
pbuf[2] = ((adr >> 8) & 0xFF); // address 2
// the write bytes
for (i = 0; i < ln; i++)
pbuf[3 + i] = (uchar)(Buf[i]); // data
// perform the block
if (!owBlock(portnum, FALSE, pbuf, ln + 3))
return FALSE;
// Now read back the scratch
if (owAccess(portnum)) {
// construct a packet to send
pbuf[0] = 0xAA; // read scratch command
pbuf[1] = 0xFF; // address 1
pbuf[2] = 0xFF; // address 2
pbuf[3] = 0xFF; // offset
// the write bytes
for (i = 0; i < ln; i++)
pbuf[4 + i] = 0xFF; // data
// perform the block
if (!owBlock(portnum, FALSE, pbuf, ln + 4))
return FALSE;
// read address 1
if (pbuf[1] != (adr & 0xFF))
return FALSE;
// read address 2
if (pbuf[2] != ((adr >> 8) & 0xFF))
return FALSE;
// read the offset
if (pbuf[3] != ((adr + ln - 1) & 0x1F))
return FALSE;
// read and compare the contents
for (i = 0; i < ln; i++) {
if (pbuf[4 + i] != Buf[i])
return FALSE;
}
// success
return TRUE;
}
}
OWERROR(OWERROR_ACCESS_FAILED);
return FALSE;
}
//----------------------------------------------------------------------------}
// Copy the scratch pad
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
//
int CopyScratch(int portnum, int ln, int adr) {
int i;
uchar pbuf[50];
// check for alarm indicator
if (owAccess(portnum)) {
// construct a packet to send
pbuf[0] = 0x55; // copy scratch command
pbuf[1] = (adr & 0xFF); // address 1
pbuf[2] = ((adr >> 8) & 0xFF); // address 2
pbuf[3] = (adr + ln - 1) & 0x1F; // offset
for (i = 0; i <= 9; i++)
pbuf[4 + i] = 0xFF; // result of copy
// perform the block
if (owBlock(portnum, FALSE, pbuf, 14)) {
if ((pbuf[13] == 0x55) || (pbuf[13] == 0xAA))
return TRUE;
}
}
OWERROR(OWERROR_ACCESS_FAILED);
return FALSE;
}
//----------------------------------------------------------------------
// Interpret the Status by looking at the 'raw' portion of the
// mission status structure.
//
void InterpretStatus(MissionStatus *mstatus) {
timedate td, tdtmp;
int offset;
uint tmtmp;
#ifndef __MC68K__
time_t tint;
struct tm *tstruct;
#endif
// mission in progress flag
mstatus->mission_in_progress = (0x20 & mstatus->status_raw[0x14]) >> 5;
// sample rate
mstatus->sample_rate = mstatus->status_raw[0x0D];
// rollover enabled
mstatus->rollover_enable = (0x08 & mstatus->status_raw[0x0E]) >> 3;
// startdelay
mstatus->start_delay = (mstatus->status_raw[0x13] << 8) | mstatus->status_raw[0x12];
// number of samples in this mission
#ifdef __MC68K__
mstatus->mission_samples = (((uint)mstatus->status_raw[0x1C]) * 65536) + (((uint)mstatus->status_raw[0x1B]) * 256) +
((uint)mstatus->status_raw[0x1A]);
#else
mstatus->mission_samples = (mstatus->status_raw[0x1C] << 16) | (mstatus->status_raw[0x1B] << 8) | mstatus->status_raw[0x1A];
#endif
// total number of samples
#ifdef __MC68K__
mstatus->samples_total = (((uint)mstatus->status_raw[0x1F]) * 65536) + (((uint)mstatus->status_raw[0x1E]) * 256) +
((uint)mstatus->status_raw[0x1D]);
#else
mstatus->samples_total = (mstatus->status_raw[0x1F] << 16) | (mstatus->status_raw[0x1E] << 8) | mstatus->status_raw[0x1D];
#endif
// temperature thresholds
mstatus->high_threshold = mstatus->status_raw[0x0C];
mstatus->low_threshold = mstatus->status_raw[0x0B];
// rollover occurred
if ((mstatus->mission_samples > 2048) && mstatus->rollover_enable)
mstatus->rollover_occurred = 1;
else
mstatus->rollover_occurred = 0;
// current real-time clock value
offset = 0x00;
td.second = BCDToBin((uchar)(mstatus->status_raw[offset] & 0x7F));
td.minute = BCDToBin((uchar)(mstatus->status_raw[offset + 1] & 0x7F));
// check for 12 hour mode
if (mstatus->status_raw[offset + 2] & 0x40) {
td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 2] & 0x1F));
// check for PM
if (mstatus->status_raw[offset + 2] & 0x20)
td.hour += 12;
} else
td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 2] & 0x3F));
td.day = BCDToBin((uchar)(mstatus->status_raw[offset + 4] & 0x3F));
td.month = BCDToBin((uchar)(mstatus->status_raw[offset + 5] & 0x1F));
td.year = BCDToBin(mstatus->status_raw[offset + 6]) + 1900;
// check for century bit
if (mstatus->status_raw[offset + 5] & 0x80)
td.year = BCDToBin(mstatus->status_raw[offset + 6]) + 2000; // (2.00)
// convert to seconds since 1970
mstatus->current_time = DateToSeconds(&td);
// date/time when mission started
offset = 0x15;
td.second = (uchar)0;
td.minute = BCDToBin((uchar)(mstatus->status_raw[offset] & 0x7F));
// check for 12 hour mode
if (mstatus->status_raw[offset + 1] & 0x40) {
td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 1] & 0x1F));
// check for PM
if (mstatus->status_raw[offset + 1] & 0x20)
td.hour += 12;
} else
td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 1] & 0x3F));
td.day = BCDToBin((uchar)(mstatus->status_raw[offset + 2] & 0x3F));
td.month = BCDToBin((uchar)(mstatus->status_raw[offset + 3] & 0x1F));
td.year = BCDToBin((uchar)(mstatus->status_raw[offset + 4])); // (2.00)
// (2.00) logic to decide on century of mission stamp
// check if century bit set in mission stamp
if (mstatus->status_raw[offset + 3] & 0x80)
td.year += 2000;
// check in mission in progress
else if (mstatus->mission_in_progress) {
// calculate the mission start year back from real time clock
tmtmp = mstatus->current_time - (mstatus->sample_rate * mstatus->mission_samples * 60);
SecondsToDate(&tdtmp, tmtmp);
td.year = tdtmp.year;
} else {
// mission stopped so get century by year window
if (td.year <= 70)
td.year += 2000;
else
td.year += 1900;
}
// convert to seconds since 1970
if ((td.month == 0) || (td.day == 0))
mstatus->mission_start_time = 0;
else
mstatus->mission_start_time = DateToSeconds(&td);
// download stations time of reading
#ifdef __MC68K__
mstatus->download_time = TimGetSeconds();
#else
time(&tint);
tstruct = localtime(&tint);
td.day = tstruct->tm_mday;
td.month = tstruct->tm_mon + 1; // (1.01)
td.year = tstruct->tm_year + 1900;
td.hour = tstruct->tm_hour;
td.minute = tstruct->tm_min;
td.second = tstruct->tm_sec;
mstatus->download_time = DateToSeconds(&td);
#endif
// skip alarm modes and status for now
}
//--------------------------------------------------------------------------
// Take the Mission Status structure and create new raw data to start
// a new mission.
//
void FormatMission(MissionStatus *mstatus) {
int i;
time_t tint;
#ifndef __MC68K__
struct tm *tstruct;
#else
DateTimePtr tstruct = NULL;
#endif
// clear the buffer
for (i = 0; i < 32; i++)
mstatus->status_raw[i] = 0;
// Real Time Clock
#ifdef __MC68K__
tint = TimGetSeconds();
#else
time(&tint);
#endif
tint++; // add 1 second
#ifdef __MC68K__
TimSecondsToDateTime(tint, tstruct);
#else
tstruct = localtime(&tint);
#endif
// convert to BCD
#ifdef __MC68K__
mstatus->status_raw[0x00] = ToBCD((short)tstruct->second);
mstatus->status_raw[0x01] = ToBCD((short)tstruct->minute);
mstatus->status_raw[0x02] = ToBCD((short)tstruct->hour);
mstatus->status_raw[0x03] = ToBCD((short)(tstruct->weekDay + 1));
mstatus->status_raw[0x04] = ToBCD((short)tstruct->day);
mstatus->status_raw[0x05] = ToBCD((short)(tstruct->month + 1));
if (tstruct->year >= 100)
mstatus->status_raw[0x05] |= 0x80;
mstatus->status_raw[0x06] = ToBCD((short)(tstruct->year % 100));
#else
mstatus->status_raw[0x00] = ToBCD((short)tstruct->tm_sec);
mstatus->status_raw[0x01] = ToBCD((short)tstruct->tm_min);
mstatus->status_raw[0x02] = ToBCD((short)tstruct->tm_hour);
mstatus->status_raw[0x03] = ToBCD((short)(tstruct->tm_wday + 1));
mstatus->status_raw[0x04] = ToBCD((short)tstruct->tm_mday);
mstatus->status_raw[0x05] = ToBCD((short)(tstruct->tm_mon + 1));
if (tstruct->tm_year >= 100)
mstatus->status_raw[0x05] |= 0x80;
mstatus->status_raw[0x06] = ToBCD((short)(tstruct->tm_year % 100));
#endif
// Real Time clock Alarm (leave 0's)
// Low temp alarm
mstatus->status_raw[0x0B] = mstatus->low_threshold;
// High temp alarm
mstatus->status_raw[0x0C] = mstatus->high_threshold;
// sample rate
mstatus->status_raw[0x0D] = mstatus->sample_rate;
// control
mstatus->status_raw[0x0E] = 0x40;
if (mstatus->rollover_enable)
mstatus->status_raw[0x0E] |= 0x08;
// mission start delay
mstatus->status_raw[0x12] = mstatus->start_delay & 0xFF;
mstatus->status_raw[0x13] = (mstatus->start_delay >> 8) & 0xFF;
}
//--------------------------------------------------------------------------
// Convert an integer to a 1 Byte BCD number (99 max)
//
uchar ToBCD(short num) {
uchar rtbyte;
rtbyte = (num - ((num / 10) * 10)) & 0x0F;
rtbyte = rtbyte | ((num / 10) << 4);
return rtbyte;
}
//--------------------------------------------------------------------------
// Take the Mission Status structure and convert to string format
//
void MissionStatusToString(MissionStatus *mstatus, int ConvertToF, char *str) {
int cnt = 0, i;
timedate td;
#ifndef __MC68K__
time_t tint;
struct tm *tstruct;
#else
DateTimePtr tstruct = NULL;
#endif
// title
#ifdef __MC68K__
cnt += sprintf(&str[cnt], "Stat For DS1921:");
#else
cnt += sprintf(&str[cnt], "Mission State\n-------------\n");
cnt += sprintf(&str[cnt], "Serial Number of DS1921: ");
#endif
// serial number
for (i = 7; i >= 0; i--)
cnt += sprintf(&str[cnt], "%02X", mstatus->serial_num[i]);
// mission state
if (mstatus->mission_in_progress)
cnt += sprintf(&str[cnt], "\nMission is in progress\n");
else
cnt += sprintf(&str[cnt], "\nMission is ended\n");
// sample rate
cnt += sprintf(&str[cnt], "Sample rate: %d minute(s)\n", mstatus->sample_rate);
// rollover
cnt += sprintf(&str[cnt], "Roll-Over Enabled: ");
if (mstatus->rollover_enable)
cnt += sprintf(&str[cnt], "yes\n");
else
cnt += sprintf(&str[cnt], "no\n");
cnt += sprintf(&str[cnt], "Roll-Over Occurred: ");
if (mstatus->rollover_occurred)
cnt += sprintf(&str[cnt], "yes\n");
else
cnt += sprintf(&str[cnt], "no\n");
// mission start time
if (mstatus->start_delay == 0) {
SecondsToDate(&td, mstatus->mission_start_time);
if (mstatus->mission_start_time == 0)
cnt += sprintf(&str[cnt], "Mission Start time: not started yet\n");
else
cnt += sprintf(&str[cnt], "Mission Start: %02d/%02d/%04d %02d:%02d:%02d\n", td.month, td.day, td.year, td.hour,
td.minute, td.second);
} else
cnt += sprintf(&str[cnt], "Mission Start time: na\n");
// mission start delay
cnt += sprintf(&str[cnt], "Mission Start delay: %d minute(s)\n", mstatus->start_delay);
// mission samples
cnt += sprintf(&str[cnt], "Mission Samples: %d\n", mstatus->mission_samples);
// device total samples
cnt += sprintf(&str[cnt], "Device total samples: %d\n", mstatus->samples_total);
// temperature display mode
cnt += sprintf(&str[cnt], "Temp displayed in: ");
if (ConvertToF)
cnt += sprintf(&str[cnt], "(Fahrenheit)\n");
else
cnt += sprintf(&str[cnt], "(Celsius)\n");
// thresholds
cnt += sprintf(&str[cnt], "High Threshold: %6.1f\n", TempToFloat(mstatus->high_threshold, ConvertToF));
cnt += sprintf(&str[cnt], "Low Threshold: %6.1f\n", TempToFloat(mstatus->low_threshold, ConvertToF));
// time from D1921
SecondsToDate(&td, mstatus->current_time);
cnt += sprintf(&str[cnt], "Current Real-Time Clock from DS1921: %02d/%02d/%04d %02d:%02d:%02d\n", td.month, td.day, td.year,
td.hour, td.minute, td.second);
#ifndef __MC68K__
// current PC time
time(&tint);
tstruct = localtime(&tint);
cnt += sprintf(&str[cnt], "Current PC Time: %02d/%02d/%04d %02d:%02d:%02d\n", tstruct->tm_mon + 1, tstruct->tm_mday,
tstruct->tm_year + 1900, tstruct->tm_hour, tstruct->tm_min, tstruct->tm_sec);
#endif
// zero terminate string
str[cnt] = 0;
}
//----------------------------------------------------------------------
// Interpret the Histogram by looking at the 'raw' portion of the
// Histogram structure. Store the temperature range values in Celsius.
//
void InterpretHistogram(Histogram *hist) {
int i;
// loop through each bin value
for (i = 0; i < 126; i += 2) { // (2.00)
// get the bin value
hist->bin_count[i / 2] = hist->hist_raw[i] | (hist->hist_raw[i + 1] << 8);
// start value for this bin
hist->start_range[i / 2] = TempToFloat((uchar)((i / 2) << 2), FALSE);
// end value for this bin
hist->end_range[i / 2] = TempToFloat((uchar)(((i / 2) << 2) | 0x03), FALSE);
}
}
//--------------------------------------------------------------------------
// Take the Histogram structure and convert to string format
//
void HistogramToString(Histogram *hist, int ConvertToF, char *str) {
int cnt = 0, i;
// title
cnt += sprintf(&str[cnt], "Temperature Histogram\n---------------------\n"
"Format: [Temp Range, Count] ");
if (ConvertToF)
cnt += sprintf(&str[cnt], "(Fahrenheit)\n");
else
cnt += sprintf(&str[cnt], "(Celsius)\n");
// loop through bins
for (i = 0; i < 63; i++) { // (2.00)
cnt += sprintf(&str[cnt], "%6.1f to %6.1f, %d\n", (ConvertToF) ? CToF(hist->start_range[i]) : hist->start_range[i],
(ConvertToF) ? CToF(hist->end_range[i]) : hist->end_range[i], hist->bin_count[i]);
}
// zero terminate string
str[cnt] = 0;
}
//----------------------------------------------------------------------
// Interpret the Temperature Alarm Event data by looking at the 'raw'
// portion of the TempAlarmEvents structure. Mission Status is needed
// to interpret the events.
//
void InterpretAlarms(TempAlarmEvents *alarm, MissionStatus *mstatus) {
int i;
uint event_mission_count;
uchar duration;
// low events
alarm->num_low = 0;
for (i = 0; i < 48; i += 4) {
// get the mission start count of this event
event_mission_count = (alarm->alarm_raw[i + 2] << 16) | (alarm->alarm_raw[i + 1] << 8) | alarm->alarm_raw[i];
// check if done with low events
if (!event_mission_count)
break;
// get the duration
duration = alarm->alarm_raw[i + 3];
// calculate the start time
alarm->low_start_time[alarm->num_low] =
mstatus->mission_start_time + (event_mission_count - 1) * (mstatus->sample_rate * 60);
// calculate the end time
alarm->low_end_time[alarm->num_low] = alarm->low_start_time[alarm->num_low] + (duration - 1) * (mstatus->sample_rate * 60);
// increment number of low events
alarm->num_low++;
}
// high events
alarm->num_high = 0;
for (i = 48; i < 96; i += 4) {
// get the mission start count of this event
event_mission_count = (alarm->alarm_raw[i + 2] << 16) | (alarm->alarm_raw[i + 1] << 8) | alarm->alarm_raw[i];
// check if done with low events
if (!event_mission_count)
break;
// get the duration
duration = alarm->alarm_raw[i + 3];
// calculate the start time
alarm->high_start_time[alarm->num_high] =
mstatus->mission_start_time + (event_mission_count - 1) * (mstatus->sample_rate * 60);
// calculate the end time
alarm->high_end_time[alarm->num_high] =
alarm->high_start_time[alarm->num_high] + (duration - 1) * (mstatus->sample_rate * 60);
// increment number of low events
alarm->num_high++;
}
}
//--------------------------------------------------------------------------
// Take the Temperature Alarms Events structure and convert to string
// format
//
void AlarmsToString(TempAlarmEvents *alarm, char *str) {
int i, cnt = 0;
timedate td;
// title
cnt += sprintf(&str[cnt], "Temperature Alarms\n------------------\n"
"Format: [(HIGH/LOW), Time/Date Range]\n");
// loop through each low alarm
for (i = 0; i < alarm->num_low; i++) {
cnt += sprintf(&str[cnt], "LOW , ");
// start time
SecondsToDate(&td, alarm->low_start_time[i]);
cnt += sprintf(&str[cnt], " %02d/%02d/%04d %02d:%02d to ", td.month, td.day, td.year, td.hour, td.minute);
// end time
SecondsToDate(&td, alarm->low_end_time[i]);
cnt += sprintf(&str[cnt], " %02d/%02d/%04d %02d:%02d\n", td.month, td.day, td.year, td.hour, td.minute);
}
// loop through each high alarm
for (i = 0; i < alarm->num_high; i++) {
cnt += sprintf(&str[cnt], "HIGH , ");
// start time
SecondsToDate(&td, alarm->high_start_time[i]);
cnt += sprintf(&str[cnt], " %02d/%02d/%04d %02d:%02d to ", td.month, td.day, td.year, td.hour, td.minute);
// end time
SecondsToDate(&td, alarm->high_end_time[i]);
cnt += sprintf(&str[cnt], " %02d/%02d/%04d %02d:%02d\n", td.month, td.day, td.year, td.hour, td.minute);
}
// zero terminate string
str[cnt] = 0;
}
//----------------------------------------------------------------------
// Interpret the Log data by looking at the 'raw'
// portion of the Log structure. Mission Status is needed
// to interpret when the logs occurred.
//
void InterpretLog(Log *log, MissionStatus *mstatus) {
uint loops = 0, overlap = 0, lastlog = 2048, i;
int logcnt = 0;
// check if wrap occurred
if (mstatus->rollover_occurred) {
// calculate the number loops
loops = (mstatus->mission_samples / 2048) - 1;
// calculate the number of overlap
overlap = mstatus->mission_samples % 2048;
log->num_log = 2048;
} else {
log->start_time = mstatus->mission_start_time;
if (mstatus->mission_samples > 2048) // (1.02)
lastlog = 2048;
else
lastlog = mstatus->mission_samples;
log->num_log = (int)lastlog;
}
// set the interval
log->interval = mstatus->sample_rate * 60;
// caluclate the start time of the first log value
log->start_time = mstatus->mission_start_time + loops * 2048 * log->interval + overlap * log->interval;
// loop to fill in the remainder first
for (i = overlap; i < lastlog; i++)
log->temp[logcnt++] = TempToFloat(log->log_raw[i], FALSE);
// loop to get the overlap
for (i = 0; i < overlap; i++)
log->temp[logcnt++] = TempToFloat(log->log_raw[i], FALSE);
}
//--------------------------------------------------------------------------
// Take the Log structure and convert to string
// format
//
void LogToString(Log *log, int ConvertToF, char *str) {
int i, cnt = 0;
uint logtime;
timedate td;
// title
cnt += sprintf(&str[cnt], "Log Data\n--------\n"
"Format: [Time/Date , Temperature] ");
if (ConvertToF)
cnt += sprintf(&str[cnt], "(Fahrenheit)\n");
else
cnt += sprintf(&str[cnt], "(Celsius)\n");
// loop through the logs
logtime = log->start_time;
for (i = 0; i < log->num_log; i++) {
// time
SecondsToDate(&td, logtime);
cnt += sprintf(&str[cnt], "%04d-%02d-%02d %02d:%02d ,", td.year, td.month, td.day, td.hour, td.minute);
// temp
cnt += sprintf(&str[cnt], "%6.1f\n", (ConvertToF) ? CToF(log->temp[i]) : log->temp[i]);
// increment the time
logtime += log->interval;
}
// zero terminate string
str[cnt] = 0;
}
//--------------------------------------------------------------------------
// Convert the raw debug data to a string
//
void DebugToString(MissionStatus *mstatus, TempAlarmEvents *alarm, Histogram *hist, Log *log, char *str) {
int i, cnt = 0;
// title
cnt += sprintf(&str[cnt], "Debug Dump\n----------\nRegister Page:\n");
// reg
for (i = 0; i < 32; i++) {
cnt += sprintf(&str[cnt], "%02X ", mstatus->status_raw[i]);
if (i && (((i + 1) % 16) == 0))
cnt += sprintf(&str[cnt], "\n");
}
// alarms
cnt += sprintf(&str[cnt], "Alarms:\n");
for (i = 0; i < 96; i++) {
cnt += sprintf(&str[cnt], "%02X ", alarm->alarm_raw[i]);
if (i && (((i + 1) % 16) == 0))
cnt += sprintf(&str[cnt], "\n");
}
// histogram
cnt += sprintf(&str[cnt], "Histogram:\n");
for (i = 0; i < 128; i++) {
cnt += sprintf(&str[cnt], "%02X ", hist->hist_raw[i]);
if (i && (((i + 1) % 16) == 0))
cnt += sprintf(&str[cnt], "\n");
}
// log
cnt += sprintf(&str[cnt], "Log:\n");
for (i = 0; i < ((log->num_log > 2048) ? 2048 : log->num_log); i++) {
cnt += sprintf(&str[cnt], "%02X ", log->log_raw[i]);
if (i && (((i + 1) % 16) == 0))
cnt += sprintf(&str[cnt], "\n");
}
// zero terminate string
str[cnt] = 0;
}
//--------------------------------------------------------------------------
// Take one byte BCD value and return binary value
//
uchar BCDToBin(uchar bcd) { return (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F); }
//--------------------------------------------------------------------------
// Take a 4 byte int string and convert it into a timedata structure.
//
static int dm[] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
void SecondsToDate(timedate *td, uint x) {
short tmp, i, j;
uint y;
// check to make sure date is not over 2070 (sanity check)
if (x > 0xBBF81E00L)
x = 0;
y = x / 60;
td->second = (ushort)(x - 60 * y);
x = y / 60;
td->minute = (ushort)(y - 60 * x);
y = x / 24;
td->hour = (ushort)(x - 24 * y);
x = 4 * (y + 731);
td->year = (ushort)(x / 1461);
i = (int)((x - 1461 * (uint)(td->year)) / 4);
td->month = 13;
do {
td->month -= 1;
tmp = (td->month > 2) && ((td->year & 3) == 0) ? 1 : 0;
j = dm[td->month] + tmp;
} while (i < j);
td->day = i - j + 1;
// slight adjustment to algorithm
if (td->day == 0)
td->day = 1;
td->year = (td->year < 32) ? td->year + 68 + 1900 : td->year - 32 + 2000;
}
//--------------------------------------------------------------------------
// DateToSeconds takes a time/date structure and converts it into the
// number of seconds since 1970
//
uint DateToSeconds(timedate *td) {
uint Sv, Bv, Xv;
// convert the date/time values into the 5 byte format used in the touch
if (td->year >= 2000)
Sv = td->year + 32 - 2000;
else
Sv = td->year - 68 - 1900;
if ((td->month > 2) && ((Sv & 3) == 0))
Bv = 1;
else
Bv = 0;
Xv = 365 * (Sv - 2) + (Sv - 1) / 4 + dm[td->month] + td->day + Bv - 1;
Xv = 86400 * Xv + (uint)(td->second) + 60 * ((uint)(td->minute) + 60 * (uint)(td->hour));
return Xv;
}
//--------------------------------------------------------------------------
// Convert from DS1921 termature format to a float
//
//
float TempToFloat(uchar tmp, int ConvertToF) {
float tfloat;
tfloat = (float)((tmp / 2.0) - 40.0);
if (ConvertToF)
return (float)(tfloat * 9.0 / 5.0 + 32.0);
else
return tfloat;
}
//--------------------------------------------------------------------------
// Convert from Celsius to Fahrenheit
//
float CToF(float CVal) { return (float)(CVal * 9.0 / 5.0 + 32.0); }
w1retap/src/libusblinux300/thermo21.h 0000664 0000000 0000000 00000013311 14464462352 0017636 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// thermo.h - Include file for Thermochron demo.
//
// Version: 2.00
//
// History:
// 1.03 -> 2.00 Reorganization of Public Domain Kit
#ifndef THERMO_TYPES
#define THERMO_TYPES
// defines
#define STATUS_PAGE 16
#define THERMO_FAM 0x21
#include
// Typedefs
#ifndef OW_UCHAR
#define OW_UCHAR
typedef unsigned char uchar;
#ifdef WIN32
typedef unsigned short ushort;
typedef unsigned int uint;
#endif
#endif
// structure to hold the mission status
typedef struct {
uchar serial_num[8]; // serial number of thermochron
uchar mission_in_progress; // 1 mission in progres, 0 mission over
uchar sample_rate; // minutes between samples
uchar rollover_enable; // 1 if roll-over enabled
uchar rollover_occurred; // 1 if roll-over occurred
ushort start_delay; // minutes before mission starts
uint mission_start_time; // date/time when mission started
uint current_time; // current real-time clock value
uint download_time; // download stations time of reading
uint mission_samples; // number of samples in this mission
uint samples_total; // total number of samples taken by device
uchar high_threshold; // raw temp of high threshold
uchar low_threshold; // raw temp of low threshold
// skip alarm modes and status for now
uchar status_raw[32];
} MissionStatus;
// structure to hold the histogram data
typedef struct {
ushort bin_count[63]; // counter per bin 0 to 62
float start_range[63]; // start temp range (C) in bin 0 to 62
float end_range[63]; // end temp range (C) in bin 0 to 62
uchar hist_raw[128]; // raw data for histogram
} Histogram;
// structure to hold the histogram data
typedef struct {
int num_low; // number of low events
uint low_start_time[12]; // start time of event 0 to 12
uint low_end_time[12]; // end time of event 0 to 12
int num_high; // number of high events
uint high_start_time[12]; // start time of event 0 to 12
uint high_end_time[12]; // end time of event 0 to 12
uchar alarm_raw[96]; // raw data for alarm events
} TempAlarmEvents;
// structure to hold the log data
typedef struct {
int num_log; // number of logs
float temp[2048]; // temperature log in (C)
uint start_time; // start time of log
int interval; // interval in seconds between logs
uchar log_raw[2048]; // raw data for log
} Log;
// structure to hold all of the thermochron data state
typedef struct {
MissionStatus MissStat; // mission state
Histogram HistData; // histogram data
TempAlarmEvents AlarmData; // temperature alarm event data
Log LogData; // log data
} ThermoStateType;
// type structure to holde time/date
typedef struct {
ushort second;
ushort minute;
ushort hour;
ushort day;
ushort month;
ushort year;
} timedate;
// structure to hold each state in the StateMachine
typedef struct {
int Step;
char StepDescription[50];
} ThermoScript;
#endif
// step constants
enum {
ST_SETUP = 0,
ST_READ_STATUS,
ST_READ_ALARM,
ST_READ_HIST,
ST_READ_LOG,
ST_CLEAR_MEM,
ST_CLEAR_VERIFY,
ST_WRITE_TIME,
ST_WRITE_CONTROL,
ST_WRITE_RATE,
ST_FINISH,
ST_GET_SESSION,
ST_FIND_THERMO,
ST_REL_SESSION,
ST_READ_PAGES,
ST_WRITE_MEM,
ST_CLEAR_SETUP
};
// status contants
enum { STATUS_STEP_COMPLETE, STATUS_COMPLETE, STATUS_INPROGRESS, STATUS_ERROR_HALT, STATUS_ERROR_TRANSIENT };
// Local Function Prototypes
int DownloadThermo(int, uchar *, ThermoStateType *, FILE *);
int ReadThermoStatus(int, uchar *, ThermoStateType *, FILE *);
int MissionThermo(int, uchar *, ThermoStateType *, FILE *);
int RunThermoScript(int, ThermoStateType *, ThermoScript script[], FILE *fp);
void MissionStatusToString(MissionStatus *, int, char *);
void SecondsToDate(timedate *, uint);
uint DateToSeconds(timedate *);
uchar BCDToBin(uchar);
void InterpretStatus(MissionStatus *);
void FormatMission(MissionStatus *);
void InterpretHistogram(Histogram *);
void HistogramToString(Histogram *, int, char *);
void InterpretAlarms(TempAlarmEvents *, MissionStatus *);
void AlarmsToString(TempAlarmEvents *, char *);
void InterpretLog(Log *, MissionStatus *);
void LogToString(Log *, int, char *);
void DebugToString(MissionStatus *, TempAlarmEvents *, Histogram *, Log *, char *);
float TempToFloat(uchar, int);
float CToF(float);
uchar ToBCD(short);
w1retap/src/libusblinux300/thermodl.c 0000664 0000000 0000000 00000015105 14464462352 0020011 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// thermodl.c - This utility uses to download the results of the
// current mission of a DS1921 Thermochron iButton.
//
// Version: 2.00
//
// History:
// 1.03 -> 2.00 Reorganization of Public Domain Kit
// Y2K update, display all histogram bins, debug
// dump. Supports multiple thermochons.
//
#include
#include
#include "ownet.h"
#include "thermo21.h"
#include "findtype.h"
// defines
#define MAXDEVICES 20
// local function prototypes
void PrintResults(ThermoStateType *, FILE *, int);
//----------------------------------------------------------------------
// This is the Main routine for thermodl.
//
int main(int argc, char **argv) {
int Fahrenheit = FALSE, filenum, num, i, j;
FILE *fp;
ThermoStateType ThermoState;
uchar ThermoSN[MAXDEVICES][8]; // the serial numbers for the devices
int portnum = 0;
// check arguments to see if request instruction with '?' or too many
if ((argc < 2) || (argc > 4) || ((argc > 1) && (argv[1][0] == '?' || argv[1][1] == '?')))
ExitProg("\nusage: thermodl 1wire_net_name \n"
" - Thermochron download on the 1-Wire Net port\n"
" - 1wire_net_port required port name\n"
" example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" \n"
" (Linux DS2480),\"1\" (Win32 TMEX)\n"
" - optional output filename\n"
" - optional Fahrenheit mode (default Celsius)\n"
" - version 2.00\n",
1);
// attempt to acquire the 1-Wire Net
if ((portnum = owAcquireEx(argv[1])) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
// success
printf("Port opened: %s\n", argv[1]);
//----------------------------------------
// Introduction
printf("\n/----------------------------------------------\n");
printf(" Find and download DS1921 Thermochron iButton(s)\n"
" Version 2.00\n\n");
// check arguments for temperature conversion and filename
Fahrenheit = FALSE;
filenum = 0;
if (argc >= 3) {
if (argv[2][0] != '/')
filenum = 2;
else if ((argv[2][1] == 'F') || (argv[2][1] == 'f'))
Fahrenheit = TRUE;
if (argc == 4) {
if (argv[3][0] != '/')
filenum = 3;
else if ((argv[3][1] == 'F') || (argv[3][1] == 'f'))
Fahrenheit = TRUE;
}
}
// open the output file
fp = NULL;
if (filenum > 0) {
fp = fopen(argv[filenum], "w+");
if (fp == NULL) {
printf("ERROR, Could not open output file!\n");
exit(1);
} else
printf("File '%s' opened to write mission results.\n", argv[filenum]);
}
// get list of Thermochron's
num = FindDevices(portnum, &ThermoSN[0], THERMO_FAM, MAXDEVICES);
// check if not present or more then 1 present
if (num == 0)
ExitProg("Thermochron not present on 1-Wire\n", 1);
// loop to download each Thermochron
for (i = 0; i < num; i++) {
// set the serial number portion in the thermo state
printf("\nDownloading: ");
for (j = 7; j >= 0; j--) {
ThermoState.MissStat.serial_num[j] = ThermoSN[i][j];
printf("%02X", ThermoSN[i][j]);
}
printf("\n");
// download the Thermochron found
if (DownloadThermo(portnum, &ThermoSN[i][0], &ThermoState, stdout)) {
// interpret the results of the download
InterpretStatus(&ThermoState.MissStat);
InterpretAlarms(&ThermoState.AlarmData, &ThermoState.MissStat);
InterpretHistogram(&ThermoState.HistData);
InterpretLog(&ThermoState.LogData, &ThermoState.MissStat);
// print the output
PrintResults(&ThermoState, fp, Fahrenheit);
} else {
fprintf(fp, "\nError downloading device: ");
for (j = 0; j < 8; j++)
fprintf(fp, "%02X", ThermoSN[i][j]);
fprintf(fp, "\n");
}
}
// close opened file
if (fp != NULL) {
printf("File '%s' closed.\n", argv[filenum]);
fclose(fp);
}
// release the 1-Wire Net
owRelease(portnum);
printf("Closing port %s.\n", argv[1]);
ExitProg("End program normally\n", 0);
return 0;
}
//--------------------------------------------------------------------------
// Prints the mission data optionaly to a file or standard out
//
void PrintResults(ThermoStateType *ThermoState, FILE *fp, int ConvertToF) {
char *str;
// check if need to use standard out
if (fp == NULL)
fp = stdout;
// get big block to use as a buffer
str = malloc(80000);
if (str == NULL) {
printf("Insufficient memory available to print!\n");
return;
}
// mission status
MissionStatusToString(&ThermoState->MissStat, ConvertToF, &str[0]);
fprintf(fp, "\n%s\n", str);
// alarm events
AlarmsToString(&ThermoState->AlarmData, &str[0]);
fprintf(fp, "%s\n", str);
// histogram
HistogramToString(&ThermoState->HistData, ConvertToF, &str[0]);
fprintf(fp, "%s\n", str);
// log data
LogToString(&ThermoState->LogData, ConvertToF, &str[0]);
fprintf(fp, "%s\n", str);
// debug raw data
DebugToString(&ThermoState->MissStat, &ThermoState->AlarmData, &ThermoState->HistData, &ThermoState->LogData, &str[0]);
fprintf(fp, "%s\n", str);
// free the memory block used
free(str);
}
w1retap/src/libusblinux300/thermoms.c 0000664 0000000 0000000 00000017010 14464462352 0020026 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// thermoms.c - This utility mission a DS1921
// Thermochron iButton.
//
// Version: 2.00
//
// History:
// 1.03 -> 2.00 Reorganization of Public Domain Kit. Provide
// defaults on mission selection.
//
#define THERMOCHRON
#include
#include
#include "ownet.h"
#include "thermo21.h"
#include "findtype.h"
// defines
#define MAXDEVICES 20
// local function prototypes
int InputMissionType(ThermoStateType *, int);
//----------------------------------------------------------------------
// This is the Main routine for thermoms.
//
int main(int argc, char **argv) {
int Fahrenheit = FALSE, num, i, j;
char str[800];
ThermoStateType ThermoState;
uchar ThermoSN[MAXDEVICES][8]; // the serial numbers for the devices
int portnum = 0;
// check arguments to see if request instruction with '?' or too many
if ((argc < 2) || (argc > 3) || ((argc > 1) && (argv[1][0] == '?' || argv[1][1] == '?')))
ExitProg("\nusage: thermoms 1wire_net_name \n"
" - Thermochron configuration on the 1-Wire Net port\n"
" - 1wire_net_port required port name\n"
" example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" \n"
" (Linux DS2480),\"1\" (Win32 TMEX)\n"
" - optional Fahrenheit mode (default Celsius)\n"
" - version 2.00\n",
1);
// attempt to acquire the 1-Wire Net
if ((portnum = owAcquireEx(argv[1])) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
// success
printf("Port opened: %s\n", argv[1]);
//----------------------------------------
// Introduction
printf("\n/---------------------------------------------\n");
printf(" Find and mission DS1921 Thermochron iButton(s)\n"
" Version 2.00\n\n");
// check arguments
Fahrenheit = FALSE;
if (argc >= 3) {
if ((argv[2][0] == '/') && ((argv[2][1] == 'F') || (argv[2][1] == 'f')))
Fahrenheit = TRUE;
}
// get list of Thermochron's
num = FindDevices(portnum, &ThermoSN[0], THERMO_FAM, MAXDEVICES);
// check if not present or more then 1 present
if (num == 0)
ExitProg("Thermochron not present on 1-Wire\n", 1);
// loop to mission each Thermochron
for (i = 0; i < num; i++) {
// set the serial number portion in the thermo state
printf("\nRead status of Thermochron: ");
for (j = 7; j >= 0; j--) {
ThermoState.MissStat.serial_num[j] = ThermoSN[i][j];
printf("%02X", ThermoSN[i][j]);
}
printf("\n");
// read Thermochron state
if (ReadThermoStatus(portnum, &ThermoSN[i][0], &ThermoState, stdout)) {
// display mission status
InterpretStatus(&ThermoState.MissStat);
MissionStatusToString(&ThermoState.MissStat, Fahrenheit, &str[0]);
printf("\n%s\n", str);
// ask user mission questions
if (!InputMissionType(&ThermoState, Fahrenheit)) {
printf("Input abort\n");
continue;
}
// run the script to display the thermochron
if (MissionThermo(portnum, &ThermoSN[i][0], &ThermoState, stdout)) {
// read Thermochron state
if (ReadThermoStatus(portnum, &ThermoSN[i][0], &ThermoState, stdout)) {
// display the new mission status
InterpretStatus(&ThermoState.MissStat);
MissionStatusToString(&ThermoState.MissStat, Fahrenheit, &str[0]);
printf("\n%s\n", str);
} else
printf("ERROR reading Thermochon state\n");
} else
printf("ERROR, Thermochon missioning not complete\n");
} else
printf("ERROR reading Thermochon state\n");
}
// release the 1-Wire Net
owRelease(portnum);
printf("\nClosing port %s.\n", argv[1]);
printf("End program normally\n");
exit(0);
return 0;
}
//--------------------------------------------------------------------------
// Prints a message, and the current driver versions.
//
int InputMissionType(ThermoStateType *ThermoState, int ConvertToF) {
int num;
float temp;
// prompt to erase current mission
num = 1;
if (!EnterNum("Erase current mission\n (0) yes\n (1) no\nAnswer:", 1, &num, 0, 1))
return FALSE;
// check for no erase
if (num == 1)
return FALSE;
// prompt for start delay
num = 0;
if (!EnterNum("\nEnter start delay in minutes\n"
"Answer (0 to 65535):",
5, &num, 0, 65535))
return FALSE;
// set in mission status structure
ThermoState->MissStat.start_delay = (ushort)num;
// prompt for sample rate
num = 5;
if (!EnterNum("\nEnter sample rate in minutes\n"
"Answer (1 to 255):",
3, &num, 1, 255))
return FALSE;
// set in mission status structure
ThermoState->MissStat.sample_rate = (uchar)num;
// prompt to erase current mission
num = 0;
if (!EnterNum("Enable roll-over\n (0) yes\n (1) no\nAnswer:", 1, &num, 0, 1))
return FALSE;
// rollover enabled?
ThermoState->MissStat.rollover_enable = (num == 0);
// prompt for high trip
if (ConvertToF) {
num = 80;
if (!EnterNum("\nEnter high temperature threshold in Fahrenheit\n"
"Answer (-40 to 158):",
3, &num, -40, 158))
return FALSE;
temp = (float)((num - 32.0) * 5.0 / 9.0);
} else {
num = 35;
if (!EnterNum("\nEnter high temperature threshold in Celsius\n"
"Answer (-40 to 70):",
3, &num, -40, 70))
return FALSE;
temp = (float)num;
}
// set in mission status structure
ThermoState->MissStat.high_threshold = (uchar)(2 * (temp + 40));
// prompt for low trip
if (ConvertToF) {
num = 32;
if (!EnterNum("\nEnter low temperature threshold in Fahrenheit\n"
"Answer (-40 to 158):",
3, &num, -40, 158))
return FALSE;
temp = (float)((num - 32.0) * 5.0 / 9.0);
} else {
num = 0;
if (!EnterNum("\nEnter low temperature threshold in Celsius\n"
"Answer (-40 to 70):",
3, &num, -40, 70))
return FALSE;
temp = (float)num;
}
// set in mission status structure
ThermoState->MissStat.low_threshold = (uchar)(2 * (temp + 40));
return TRUE;
}
w1retap/src/libusblinux300/time04.c 0000664 0000000 0000000 00000102104 14464462352 0017271 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2001 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.
//---------------------------------------------------------------------------
//
// time04.c - 1-Wire Clock device functions for (DS2404, DS1994, DS1427).
// These functions allow the programmer to:
// write the Real-Time Clock (RTC) (and enable osc),
// write the Clock Alarm (RTCA) (and set alarm flag), and
// optionally write-protect the Clock Alarm.
//
#include "ownet.h"
#include
#include
#include
#include "mbscr.h"
#include "mbnv.h"
#include "time04.h"
// Include files for the Palm and Visor
#ifdef __MC68K__
#include
#include
#else
#include
#endif
// Function Prototypes
// The "getters"
SMALLINT getRTC(int, uchar *, timedate *);
SMALLINT getRTCA(int, uchar *, timedate *);
SMALLINT getControlRegisterBit(int, uchar *, int, SMALLINT *);
SMALLINT getStatusRegisterBit(int, uchar *, int, SMALLINT *);
// The "setters"
SMALLINT setRTC(int, uchar *, uint, SMALLINT);
SMALLINT setRTCFromPC(int, uchar *, SMALLINT);
SMALLINT setOscillator(int, uchar *, SMALLINT);
SMALLINT setRTCA(int, uchar *, uint, SMALLINT);
SMALLINT setRTCAFromPCOffset(int, uchar *, uint, SMALLINT);
SMALLINT setRTCAEnable(int, uchar *, SMALLINT);
SMALLINT setWriteProtectionAndExpiration(int, uchar *, SMALLINT, SMALLINT);
SMALLINT setControlRegister(int, uchar *, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT);
SMALLINT setStatusRegister(int, uchar *, SMALLINT, SMALLINT, SMALLINT);
// The "time conversion" functions
void getPCTime(timedate *);
void SecondsToDate(timedate *, uint);
uint DateToSeconds(timedate *);
// Utility functions
uint uchar_to_bin(uchar *, int);
//----------------------------------------------------------------------
// Retrieves the local time from the 1-Wire Real-Time Clock (RTC)
// in the form of a timedate structure:
//
// typedef struct
// {
// ushort second;
// ushort minute;
// ushort hour;
// ushort day;
// ushort month;
// ushort year;
// } timedate;
//
// Parameters:
// portnum the port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// * td timedate struct to return the time/date.
//
// Returns: TRUE if the read worked
// FALSE if there was an error in reading
//
// * td Returns the time/date in a timedate struct.
//
SMALLINT getRTC(int portnum, uchar *SNum, timedate *td) {
uchar timebuffer[4];
uint timeint = 0;
// read 4 bytes from 1-Wire clock device (memory bank 2)
// starting at address 0x03.
if (!readNV(2, portnum, SNum, 0x03, FALSE, &timebuffer[0], 4)) {
return FALSE;
}
timeint = uchar_to_bin(&timebuffer[0], 4);
SecondsToDate(td, timeint);
return TRUE;
}
//----------------------------------------------------------------------
// Retrieves the Real-Time Clock Alarm (RTCA) "trigger" time from the
// 1-Wire device in the form of a timedate structure:
//
// typedef struct
// {
// ushort second;
// ushort minute;
// ushort hour;
// ushort day;
// ushort month;
// ushort year;
// } timedate;
//
// Parameters:
// portnum the port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// * td Pointer to a timedate struct to return the time/date.
//
// Returns: TRUE if the write worked
// FALSE if there was an error in reading
//
// * td Returns the alarm time/date in a timedate struct.
//
SMALLINT getRTCA(int portnum, uchar *SNum, timedate *td) {
uchar timebuffer[4];
uint timeint = 0;
// read 4 bytes for alarm trigger from 1-Wire clock device (memory bank 2)
// starting at address 0x11.
if (!readNV(2, portnum, SNum, 0x11, FALSE, &timebuffer[0], 4)) {
return FALSE;
}
timeint = uchar_to_bin(&timebuffer[0], 4);
SecondsToDate(td, timeint);
return TRUE;
}
//----------------------------------------------------------------------
// Retrieves a specific bit from the control register of the 1-Wire
// clock. Any one of the 8 control register bits can be retrieved.
// Their definitions can be found on page 9 of the DS1994 datasheet.
// To retrieve a particular bit, please specify one of the following
// tm_04.h defines:
//
// DSEL 0x80 Delay select bit.
// STOPSTART 0x40 STOP/START (in Manual Mode).
// AUTOMAN 0x20 Automatic/Manual Mode.
// OSC 0x10 Oscillator enable (start the clock ticking...)
// RO 0x08 Read only (during expiration: 1 for read-only, 0 for destruct).
// WPC 0x04 Write-Protect cycle counter bit.
// WPI 0x02 Write-Protect interval timer bit.
// WPR 0x01 Write-Protect RTC and clock alarm bit.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device with which to communicate.
// controlbit The desired bit to be returned. (One of the above 8 bits).
// * returnbit A pointer to receive the bit indicated. Will return TRUE or FALSE.
//
// Returns: TRUE if the read worked.
// FALSE if there was an error in reading the control register.
//
// * returnbit Returns TRUE or FALSE. TRUE if the selected bit is
// one and FALSE if the selected bit is a zero.
//
SMALLINT getControlRegisterBit(int portnum, uchar *SNum, int controlbit, SMALLINT *returnbit) {
uchar buf = 0;
// read the control register from 1-Wire clock device (memory bank 2)
// starting at address 0x01.
if (!readNV(2, portnum, SNum, 0x01, FALSE, &buf, 1)) {
return FALSE;
}
// mask off pertinent control bit from the control register
if ((buf & controlbit) > 0) {
*returnbit = TRUE;
} else {
*returnbit = FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Retrieves a specific bit from the status register of the 1-Wire
// clock. Any one of the 6 status register bits (the 2 most significant
// bits are "don't care" bits) can be retrieved. Their definitions can
// be found on page 8 of the DS1994 datasheet. To retrieve a
// particular bit, please specify one of the following tm_04.h defines:
//
// CCEInverse 0x20 Cycle counter alarm trigger (inverse - 0 for on and 1 for off).
// ITEInverse 0x10 Interval Timer alarm trigger (inverse).
// RTEInverse 0x08 RTC alarm trigger (inverse).
// CCF 0x04 Cycle counter alarm indicator.
// ITF 0x02 Interval Timer alarm indicator.
// RTF 0x01 RTC alarm indicator.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device with which to communicate.
// statusbit The desired bit to be returned. (One of the above 8 bits).
// * returnbit A pointer to receive the bit indicated. Will return TRUE or FALSE.
//
// Returns: TRUE if the read worked.
// FALSE if there was an error in reading the status register.
//
// * returnbit Returns TRUE or FALSE. TRUE if the selected bit is
// one and FALSE if the selected bit is a zero.
//
SMALLINT getStatusRegisterBit(int portnum, uchar *SNum, int statusbit, SMALLINT *returnbit) {
uchar buf = 0;
// read the control register from 1-Wire clock device (memory bank 2)
// starting at address 0x00.
if (!readNV(2, portnum, SNum, 0x00, FALSE, &buf, 1)) {
return FALSE;
}
if ((buf & statusbit) > 0) {
*returnbit = TRUE;
} else {
*returnbit = FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Sets the Real-Time clock (RTC) of the 1-Wire device from the
// input parameter settime. The settime parameter should be the
// number of seconds elapsed since Jan. 1, 1970. Also included is
// an option to start or stop the oscillator.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// settime The number of seconds since Jan. 1, 1970 as an unsigned
// int integer.
// OscEnable Sets the Oscillator enable bit of the control register. A
// TRUE will turn the oscillator one and a FALSE will turn
// the oscillator off.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing to the part.
//
SMALLINT setRTC(int portnum, uchar *SNum, uint settime, SMALLINT OscEnable) {
uchar timebuffer[4];
timebuffer[0] = 0;
timebuffer[1] = 0;
timebuffer[2] = 0;
timebuffer[3] = 0;
// convert the number of seconds (settime) into a 4-byte buffer (timebuffer)
memcpy(&timebuffer[0], &settime, 4);
// write 4 bytes to 1-Wire clock device (memory bank 2)
// starting at address 0x03.
if (!writeNV(2, portnum, SNum, 0x03, &timebuffer[0], 4)) {
return FALSE; // write failed
}
if (setOscillator(portnum, SNum, OscEnable) != TRUE) {
return FALSE; // write failed
}
return TRUE;
}
//----------------------------------------------------------------------
// Sets the Real-Time clock (RTC) of the 1-Wire device to the time
// on the PC, with an option to start the oscillator.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// OscEnable Sets the Oscillator enable bit of the control register. A
// TRUE will turn the oscillator one and a FALSE will turn
// the oscillator off.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing to the part.
//
SMALLINT setRTCFromPC(int portnum, uchar *SNum, SMALLINT OscEnable) {
uint timeint = 0;
timedate td;
// get seconds since Jan 1, 1970
getPCTime(&td); // first, get timedate
timeint = DateToSeconds(&td); // convert timedate to seconds since Jan 1, 1970
// write 4 bytes to 1-Wire clock device (memory bank 2)
// starting at address 0x03.
if (setRTC(portnum, SNum, timeint, OscEnable) != TRUE) {
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Sets the oscillator bit in the control register of the 1-Wire
// clock. It can be turned on (1) or off (0).
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// OscEnable Sets the Oscillator enable bit of the control register. A
// TRUE will turn the oscillator one and a FALSE will turn
// the oscillator off.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing to the part.
//
SMALLINT setOscillator(int portnum, uchar *SNum, SMALLINT OscEnable) {
if (setControlRegister(portnum, SNum, -99, -99, -99, OscEnable, -99, -99, -99, -99) == FALSE) {
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Sets the Real-Time clock alarm (RTCA) time of the 1-Wire
// device from the input parameter settime. The settime parameter should be the
// number of seconds elapsed since Jan. 1, 1970. Also included is
// an option to enable or disable the alarm.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// settime The number of seconds since Jan. 1, 1970 as an
// unsigned int integer.
// AlarmEnable Enables/Disables the Real-Time clock alarm. TRUE will
// enable the alarm and FALSE will disable the alarm.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing to the part.
//
SMALLINT setRTCA(int portnum, uchar *SNum, uint setalarm, SMALLINT AlarmEnable) {
uchar timebuffer[4];
timebuffer[0] = 0;
timebuffer[1] = 0;
timebuffer[2] = 0;
timebuffer[3] = 0;
// convert the number of seconds (settime) into a 4-byte buffer (timebuffer)
memcpy(&timebuffer[0], &setalarm, 4);
// write 4 bytes to 1-Wire clock device (memory bank 2)
// starting at address 0x11.
if (!writeNV(2, portnum, SNum, 0x11, &timebuffer[0], 4)) {
return FALSE;
}
if (setRTCAEnable(portnum, SNum, AlarmEnable) != TRUE) {
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Sets the Real-Time clock alarm (RTCA) time on the 1-Wire
// device to the PC's clock with an offset in seconds. Also included
// is an option to enable or disable the alarm.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// PCOffset The number of seconds from the PC's time/date to
// to set the RTCA.
// AlarmEnable Enables/Disables the Real-Time clock alarm. TRUE will
// enable the alarm and FALSE will disable the alarm.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing to the part.
//
SMALLINT setRTCAFromPCOffset(int portnum, uchar *SNum, uint PCOffset, SMALLINT AlarmEnable) {
uint timeint = 0;
timedate td;
// get seconds since Jan 1, 1970
getPCTime(&td); // first, get timedate
timeint = DateToSeconds(&td); // convert timedate to seconds since Jan 1, 1970
// write 4 bytes to 1-Wire clock device (memory bank 2)
// starting at address 0x11.
if (setRTCA(portnum, SNum, (timeint + PCOffset), AlarmEnable) != TRUE) {
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Enables or disables the Real-Time clock alarm on the 1-Wire
// clock. When enabled, the clock will alarm when the alarm
// value is reached. If disabled, the clock will not alarm.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device to communicate.
// AlarmEnable Sets the alarm enable bit of the control
// register. TRUE will enable the alarm and FALSE will
// disable the alarm.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing to the part.
//
SMALLINT setRTCAEnable(int portnum, uchar *SNum, SMALLINT AlarmEnable) {
SMALLINT MyRTENot = FALSE;
// make sure MyRTENot is the inverse of AlarmEnable
if (AlarmEnable == FALSE)
MyRTENot = TRUE;
if (setStatusRegister(portnum, SNum, -99, -99, MyRTENot) == FALSE) {
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Write-Protects the 1-Wire clock so that the real-time clock and alarm
// registers cannot be changed. This function can also be used to set the
// expiration mode on the device. TRUE sets the expiration to read-only,
// meaning that the nv ram of the part becomes read-only after expiration, and
// FALSE sets the expiration to "destruct", meaning only the part's serial
// number can be read (and nothing else) after expiration.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the 1-Wire device.
// RTCProtect Sets the write-protect bit for the real-time clock
// and alarms located in the control register. If set
// to TRUE, the part's Real-Time Clock and Alarm registers
// can no inter be written, including the WPR bit. If
// set to FALSE (if possible), the part will not be write-
// protected.
// RTCAExpire Sets the expiration bit (RO) of the control register.
// If set to TRUE, the part expires and all memory
// becomes read-only. If FALSE, the only thing that can
// be accessed is the 1-Wire Net Address.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing to the part.
//
SMALLINT setWriteProtectionAndExpiration(int portnum, uchar *SNum, SMALLINT RTCProtect, SMALLINT RTCAExpire) {
if (setControlRegister(portnum, SNum, -99, -99, -99, -99, RTCAExpire, -99, -99, RTCProtect) == FALSE) {
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------
// Writes specific bits to the status register of the 1-Wire
// clock. Any of the 3 status register bits (the two most significant
// bits are "don't care" bits and the first three lease significant bits
// are read-only) can be retrieved.
//
// Note: If specific bits are desired to be left alone, place values
// other than TRUE (1) or FALSE (0) in them (such as -99).
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device with which to communicate.
// CCENot Cycle counter alarm trigger (inverse - 0 for on and 1 for off).
// ITENot Interval Timer alarm trigger (inverse).
// RTENot RTC alarm trigger enable (inverse).
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing the status register.
//
//
SMALLINT setStatusRegister(int portnum, uchar *SNum, SMALLINT CCENot, SMALLINT ITENot, SMALLINT RTENot) {
uchar statusregister[1]; // to store status byte
SMALLINT writetopart = FALSE;
statusregister[0] = 0;
// read 1 bytes from 1-Wire clock device (memory bank 2)
// starting at address 0x01. This is the status register.
if (!readNV(2, portnum, SNum, 0x00, FALSE, &statusregister[0], 1)) {
return FALSE;
}
// if necessary, update status register
if (((statusregister[0] & 0x20) > 0) && (CCENot == FALSE)) { // turn CCENot to 0
// The CCENot bit is in the 5th bit position of the status register.
// 'And'ing with 0xDF (223 decimal or 11011111 binary) will
// guarantee a 0-bit in the position.
statusregister[0] = statusregister[0] & 0xDF;
writetopart = TRUE;
}
if (((statusregister[0] & 0x20) == 0) && (CCENot == TRUE)) { // turn CCENot to 1
// The CCENot bit is in the 5th bit position of the status register.
// 'Or'ing with 0x20 (32) will guarantee a 1-bit in the position.
statusregister[0] = statusregister[0] | 0x20;
writetopart = TRUE;
}
if (((statusregister[0] & 0x10) > 0) && (ITENot == FALSE)) { // turn ITENot to 0
// The ITENot bit is in 4th bit position of the status register.
// 'And'ing with 0xEF (239 decimal or 11101111 binary) will
// guarantee a 0-bit in the position.
statusregister[0] = statusregister[0] & 0xEF;
writetopart = TRUE;
}
if (((statusregister[0] & 0x10) == 0) && (ITENot == TRUE)) { // turn ITENot to 1
// The ITENot bit is in 4th bit position (16) of byte.
// 'Or'ing with 0x10 (16) will guarantee a 1-bit in the position.
statusregister[0] = statusregister[0] | 0x10;
writetopart = TRUE;
}
if (((statusregister[0] & 0x08) > 0) && (RTENot == FALSE)) { // turn RTENot to 0
// The RTENot bit is in the 3rd bit position of the status register.
// 'And'ing with 0xF7 (247 decimal or 11110111 binary) will
// guarantee a 0-bit in the position.
statusregister[0] = statusregister[0] & 0xF7;
writetopart = TRUE;
}
if (((statusregister[0] & 0x08) == 0) && (RTENot == TRUE)) { // turn RTENot to 1
// The RTENot bit is in the 3rd bit position of the status register.
// 'Or'ing with 0x08 will guarantee a 1-bit in the position.
statusregister[0] = statusregister[0] | 0x08;
writetopart = TRUE;
}
// write new status register (if any) to part.
if (writetopart == TRUE) {
if (!writeNV(2, portnum, SNum, 0x00, &statusregister[0], 1)) {
return FALSE;
}
}
return TRUE;
}
//----------------------------------------------------------------------
// Writes specific bits to the control register of the 1-Wire
// clock. Any of the 8 control register bits can be written.
//
// Note: If specific bits are desired to be left alone, place values
// other than TRUE (1) or FALSE (0) in them (such as -99)
// when calling the function.
//
// Parameters:
// portnum The port number of the port being used for the
// 1-Wire network.
// SNum The 1-Wire address of the device with which to communicate.
// dsel Delay select bit
// stopstart STOP/START (in Manual Mode).
// automan Automatic/Manual Mode.
// osc Oscillator enable (start the clock ticking...)
// ro Read only (during expiration: 1 for read-only, 0 for destruct).
// wpc Write-Protect cycle counter bit.
// wpi Write-Protect interval timer bit.
// wpr Write-Protect RTC and clock alarm bit.
//
// Returns: TRUE if the write worked.
// FALSE if there was an error in writing the status register.
//
//
SMALLINT setControlRegister(int portnum, uchar *SNum, SMALLINT dsel, SMALLINT startstop, SMALLINT automan, SMALLINT osc,
SMALLINT ro, SMALLINT wpc, SMALLINT wpi, SMALLINT wpr) {
uchar controlregister[2]; // to store both status and control bytes
SMALLINT writetopart = FALSE;
SMALLINT writeprotect = FALSE;
int i = 0;
controlregister[0] = 0;
controlregister[1] = 0;
// read 1 bytes from 1-Wire clock device (memory bank 2)
// starting at address 0x01. This is the control register.
if (!readNV(2, portnum, SNum, 0x00, FALSE, &controlregister[0], 2)) {
return FALSE;
}
// if necessary, update control register
if (((controlregister[1] & 0x80) > 0) && (dsel == FALSE)) { // turn dsel to 0
// The dsel bit is in 7th bit position (MSb) of byte.
// 'And'ing with 0x7F (127 decimal or 01111111 binary) will
// guarantee a 0-bit in the position.
controlregister[1] = controlregister[1] & 0x7F;
writetopart = TRUE;
}
if (((controlregister[1] & 0x80) == 0) && (dsel == TRUE)) { // turn dsel to 1
// The dsel bit is in 7th bit position (MSb) of byte.
// 'Or'ing with 0x80 (16) will guarantee a 1-bit in the position and
// turn the dsel bit to 1.
controlregister[1] = controlregister[1] | 0x80;
writetopart = TRUE;
}
if (((controlregister[1] & 0x40) > 0) && (startstop == FALSE)) { // turn startstop to 0
// The startstop bit is in the 6th bit position of the control register.
// 'And'ing with 0xBF (191 decimal or 10111111 binary) will
// guarantee a 0-bit in the position.
controlregister[1] = controlregister[1] & 0xBF;
writetopart = TRUE;
}
if (((controlregister[1] & 0x40) == 0) && (startstop == TRUE)) { // turn startstop to 1
// The startstop bit is in the 6th bit position of the control register.
// 'Or'ing with 0x40 (64) will guarantee a 1-bit in the position.
controlregister[1] = controlregister[1] | 0x40;
writetopart = TRUE;
}
if (((controlregister[1] & 0x20) > 0) && (automan == FALSE)) { // turn automan to 0
// The automan bit is in the 5th bit position of the control register.
// 'And'ing with 0xDF (223 decimal or 11011111 binary) will
// guarantee a 0-bit in the position.
controlregister[1] = controlregister[1] & 0xDF;
writetopart = TRUE;
}
if (((controlregister[1] & 0x20) == 0) && (automan == TRUE)) { // turn automan to 1
// The automan bit is in the 5th bit position of the control register.
// 'Or'ing with 0x20 (32) will guarantee a 1-bit in the position.
controlregister[1] = controlregister[1] | 0x20;
writetopart = TRUE;
}
if (((controlregister[1] & 0x10) > 0) && (osc == FALSE)) { // turn oscillator off
// The oscillator enable bit is in 4th bit position (16) of byte.
// 'And'ing with 0xEF (239 decimal or 11101111 binary) will
// guarantee a 0-bit in the position and turn the oscillator off.
controlregister[1] = controlregister[1] & 0xEF;
writetopart = TRUE;
}
if (((controlregister[1] & 0x10) == 0) && (osc == TRUE)) { // turn oscillator on
// The oscillator enable bit is in 4th bit position (16) of byte.
// 'Or'ing with 0x10 (16) will guarantee a 1-bit in the position and
// turn the oscillator on.
controlregister[1] = controlregister[1] | 0x10;
writetopart = TRUE;
}
if (((controlregister[1] & 0x08) > 0) && (ro == FALSE)) { // turn ro to 0
// The ro bit is in the 3rd bit position of the control register.
// 'And'ing with 0xF7 (247 decimal or 11110111 binary) will
// guarantee a 0-bit in the position.
controlregister[1] = controlregister[1] & 0xF7;
writetopart = TRUE;
}
if (((controlregister[1] & 0x08) == 0) && (ro == TRUE)) { // turn ro to 1
// The ro bit is in the 3rd bit position of the control register.
// 'Or'ing with 0x08 will guarantee a 1-bit in the position.
controlregister[1] = controlregister[1] | 0x08;
writetopart = TRUE;
}
if (((controlregister[1] & 0x04) > 0) && (wpc == FALSE)) { // turn wpc to 0
// The wpc bit is in the 2nd bit position of the control register.
// 'And'ing with 0xFB (251 decimal or 11111011 binary) will
// guarantee a 0-bit in the position.
controlregister[1] = controlregister[1] & 0xFB;
writeprotect = TRUE;
writetopart = TRUE;
}
if (((controlregister[1] & 0x04) == 0) && (wpc == TRUE)) { // turn wpc to 1
// The wpc bit is in the 2nd bit position of the control register.
// 'Or'ing with 0x04 will guarantee a 1-bit in the position.
controlregister[1] = controlregister[1] | 0x04;
writeprotect = TRUE;
writetopart = TRUE;
}
if (((controlregister[1] & 0x02) > 0) && (wpi == FALSE)) { // turn wpi to 0
// The wpi bit is in the 1st bit position of the control register.
// 'And'ing with 0xFD (253 decimal or 11111101 binary) will
// guarantee a 0-bit in the position.
controlregister[1] = controlregister[1] & 0xFD;
writeprotect = TRUE;
writetopart = TRUE;
}
if (((controlregister[1] & 0x02) == 0) && (wpi == TRUE)) { // turn wpi to 1
// The wpi bit is in the 1st bit position of the control register.
// 'Or'ing with 0x02 will guarantee a 1-bit in the position.
controlregister[1] = controlregister[1] | 0x02;
writeprotect = TRUE;
writetopart = TRUE;
}
if (((controlregister[1] & 0x01) > 0) && (wpr == FALSE)) { // turn wpr to 0
// The wpr bit is in the 0th bit position of the control register.
// 'And'ing with 0xFE (254 decimal or 11111110 binary) will
// guarantee a 0-bit in the position.
controlregister[1] = controlregister[1] & 0xFE;
writeprotect = TRUE;
writetopart = TRUE;
}
if (((controlregister[1] & 0x01) == 0) && (wpr == TRUE)) { // turn wpr to 1
// The wpr bit is in the 0th bit position of the control register.
// 'Or'ing with 0x01 will guarantee a 1-bit in the position.
controlregister[1] = controlregister[1] | 0x01;
writeprotect = TRUE;
writetopart = TRUE;
}
// write new control register (if any) to part.
if (writetopart == TRUE) {
// if writeprotect is true, then copyscratchpad 3 times...
if (writeprotect == TRUE) {
owSerialNum(portnum, SNum, 1);
// write to scratchpad
if (!writeScratchpd(portnum, 0x200, &controlregister[0], 2)) {
return FALSE;
}
// copy the scratchpad 3 times to write protect
for (i = 0; i < 3; i++) {
if (!owAccess(portnum))
return FALSE; // if Access is unsuccessful
if (!((0x55 != (uchar)owTouchByte(portnum, 0x55)) && // sent the copy command
(0x00 != (uchar)owTouchByte(portnum, 0x00)) && // write the target address 1
(0x02 != (uchar)owTouchByte(portnum, 0x02)))) { // write the target address 2
return FALSE;
}
if (i == 0) {
if (!owTouchByte(portnum, 0x01))
return FALSE;
} else {
if (!owTouchByte(portnum, 0x81)) // The AA bit gets set on consecutive
return FALSE; // copyscratchpads (pg. 12 of datasheet)
}
}
} else {
if (!writeNV(2, portnum, SNum, 0x00, &controlregister[0], 2)) {
return FALSE;
}
}
}
return TRUE;
}
//----------------------------------------------------------------------
// Retrieves the local time from the PC
// in the form of a timedate structure:
//
// typedef struct
// {
// ushort second;
// ushort minute;
// ushort hour;
// ushort day;
// ushort month;
// ushort year;
// } timedate;
//
// Parameters:
// * td timedate struct to return the time/date.
//
// Returns:
// * td returns the time/date in a timedate struct.
//
void getPCTime(timedate *td) {
time_t tint = 0; // number of seconds since Jan. 1, 1970
struct tm *tstruct; // structure containing time info
tint = time(NULL); // get seconds since Jan. 1, 1970
tstruct = localtime(&tint); // transform seconds to struct containing date/time info.
// Populate timedate structure
td->day = tstruct->tm_mday;
td->month = tstruct->tm_mon + 1;
td->year = tstruct->tm_year + 1900;
td->hour = tstruct->tm_hour;
td->minute = tstruct->tm_min;
td->second = tstruct->tm_sec;
}
//----------------------------------------------------------------------
// Take a 4-byte int uchar array (consisting of
// the number of seconds elapsed since Jan. 1 1970)
// and convert it into a timedate structure:
//
// typedef struct
// {
// ushort second;
// ushort minute;
// ushort hour;
// ushort day;
// ushort month;
// ushort year;
// } timedate;
//
// Parameters:
// * td timedate struct to return the time/date.
// x the number of seconds elapsed since Jan 1, 1970.
//
// Returns:
// * td returns the time/date in a timedate struct.
//
static int dm[] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
void SecondsToDate(timedate *td, uint x) {
short tmp, i, j;
uint y;
// check to make sure date is not over 2070 (sanity check)
if (x > 0xBBF81E00L)
x = 0;
y = x / 60;
td->second = (ushort)(x - 60 * y);
x = y / 60;
td->minute = (ushort)(y - 60 * x);
y = x / 24;
td->hour = (ushort)(x - 24 * y);
x = 4 * (y + 731);
td->year = (ushort)(x / 1461);
i = (int)((x - 1461 * (uint)(td->year)) / 4);
td->month = 13;
do {
td->month -= 1;
tmp = (td->month > 2) && ((td->year & 3) == 0) ? 1 : 0;
j = dm[td->month] + tmp;
} while (i < j);
td->day = i - j + 1;
// slight adjustment to algorithm
if (td->day == 0)
td->day = 1;
td->year = (td->year < 32) ? td->year + 68 + 1900 : td->year - 32 + 2000;
}
//----------------------------------------------------------------------
// Takes a timedate struct and converts it into
// the number of seconds since Jan. 1, 1970.
//
// typedef struct
// {
// ushort second;
// ushort minute;
// ushort hour;
// ushort day;
// ushort month;
// ushort year;
// } timedate;
//
// Parameters:
// * td timedate struct containing time/date to convert to seconds.
//
// Returns:
// uint the time/date as the number of seconds elapsed since Jan. 1, 1970.
//
uint DateToSeconds(timedate *td) {
uint Sv, Bv, Xv;
// convert the date/time values.
if (td->year >= 2000)
Sv = td->year + 32 - 2000;
else
Sv = td->year - 68 - 1900;
if ((td->month > 2) && ((Sv & 3) == 0))
Bv = 1;
else
Bv = 0;
Xv = 365 * (Sv - 2) + (Sv - 1) / 4 + dm[td->month] + td->day + Bv - 1;
Xv = 86400 * Xv + (uint)(td->second) + 60 * ((uint)(td->minute) + 60 * (uint)(td->hour));
return Xv;
}
//----------------------------------------------------------------------
// Converts a binary uchar buffer into a uint return integer
// number. 'length' indicates the length of the uchar buffer.
//
// Parameters:
// buffer a pointer to the input buffer to convert.
// length the length of the input buffer.
//
// Returns:
// uint the uint integer result.
//
uint uchar_to_bin(uchar *buffer, int length) {
int i;
uint l = 0;
for (i = (length - 1); i >= 0; i--)
l = (l << 8) | (int)(buffer[i]);
return l;
}
w1retap/src/libusblinux300/time04.h 0000664 0000000 0000000 00000006054 14464462352 0017305 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2001 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.
//---------------------------------------------------------------------------
//
// tm_04.c - contains functions for communication to the DS2404/DS1994/DS1427
//
#define TIME_FAM 0x04
// define status register bit locations
#define CCEInverse 0x20
#define ITEInverse 0x10
#define RTEInverse 0x08
#define CCF 0x04
#define ITF 0x02
#define RTF 0x01
// define control register bit locations
#define DSEL 0x80
#define STOPSTART 0x40
#define AUTOMAN 0x20
#define OSC 0x10
#define RO 0x08
#define WPC 0x04
#define WPI 0x02
#define WPR 0x01
// type structure to hold time/date
typedef struct {
ushort second;
ushort minute;
ushort hour;
ushort day;
ushort month;
ushort year;
} timedate;
// Functions
// The "getter" functions
SMALLINT getRTC(int, uchar *, timedate *);
SMALLINT getRTCA(int, uchar *, timedate *);
SMALLINT getControlRegisterBit(int, uchar *, int, SMALLINT *);
SMALLINT getStatusRegisterBit(int, uchar *, int, SMALLINT *);
// The "setters" functions
SMALLINT setRTC(int, uchar *, uint, SMALLINT);
SMALLINT setRTCFromPC(int, uchar *, SMALLINT);
SMALLINT setOscillator(int, uchar *, SMALLINT);
SMALLINT setRTCA(int, uchar *, uint, SMALLINT);
SMALLINT setRTCAFromPCOffset(int, uchar *, uint, SMALLINT);
SMALLINT setRTCAEnable(int, uchar *, SMALLINT);
SMALLINT setWriteProtectionAndExpiration(int, uchar *, SMALLINT, SMALLINT);
SMALLINT setControlRegister(int, uchar *, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT, SMALLINT);
SMALLINT setStatusRegister(int, uchar *, SMALLINT, SMALLINT, SMALLINT);
// The "time conversion" functions
void getPCTime(timedate *);
void SecondsToDate(timedate *, uint);
uint DateToSeconds(timedate *);
// Utility functions
uint uchar_to_bin(uchar *, int);
w1retap/src/libusblinux300/tm_check.c 0000664 0000000 0000000 00000035122 14464462352 0017751 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2001 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.
//---------------------------------------------------------------------------
//
// tm_check.c - A sample program showing how to use the DS1994/DS1427/DS2404
// to secure a software package and tie it to a timed license
// held in the 1-Wire device, basically providing a software timed
// trial.
//
// This program assumes that the 1-Wire device has been initialized
// appropriately by the tm_init program, and continuously polls
// the 1-Wire device to check for a valid license
// and/or part expiration. See pseudocode specification at the
// bottom of this file.
//
#include
#include
#include "ownet.h"
#include "findtype.h"
#include "owfile.h"
#include "time04.h"
#include "memory.h"
#include "string.h"
// defines
#define MAXDEVICES 4
#define MAXTIMEOFFSET 378691201 // about 12 years (should exceed battery life).
// error defines
#define NO_ERROR 1
#define NO_DEVICE 2
#define NO_FILES 3
// local functions
void ComputeSHAVM(uchar *MT, int *hash); // function to compute sha-1
int NLF2(int B, int C, int D, int n); // used by above function to compute sha-1
int getNumber(int min, int max); // help with user input
// constants used in SHA computation to create the new MAC
static const int KTN[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
int main(int argc, char **argv) {
int i = 0;
int j = 0;
int portnum = 0; // port number where 1-Wire net is located
int num = 0; // number of 1-Wire Clock devices found on 1-Wire Net
timedate td; // timedate struct
uint RTCTime = 0; // variable to hold the RTC time in seconds.
uint RTCATime = 0; // variable to hold the RTCA time in seconds.
uint SoftTime = 0; // get "Soft" time with this value.
uchar SoftTimeArray[5]; // holds the soft time in an array of uchar
uchar secret[51]; // holds the secret input by the user.
int secretlength; // secret length in number of bytes.
uchar usertext[51]; // holds the usertext retrieved from 1-Wire file.
int usertextlength; // user text length in number of bytes
uchar inputforsha[64]; // ROM + UserText + SOFTTIME + Secret
int intMAC[5]; // MAC resulting from SHA1 hash as 5 uint integers
uchar MAC[20]; // MAC resulting from SHA1 hash of inputforsha array as a byte array
uchar newMAC[20]; // MAC constructed from ROM + UserText + SOFTTIME + Secret
uchar filedata[76]; // file data
int filedatalength = 0; // length of file data
short filehandle = 0; // handle to 1-Wire file
SMALLINT comparisonerror = FALSE; // boolean for comparing old and new MACs
FileEntry fe; // 1-Wire file info used to create a 1-Wire file
SMALLINT errordetect = NO_ERROR; // flag when an error occurrs in communicating to 1-Wire device
uchar TimeSN[MAXDEVICES][8]; // the serial numbers (1-Wire Net Addresses) for the devices
uint delayTime = 0; // delay between main loop iterations.
uint noDeviceDelayTime = 1000; // delay between no-device loop iterations.
// Make sure we can talk to the part when it is alarming.
// The following variable should always be set when
// communicating to an alarming 1-Wire Clock device.
FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE = TRUE;
// initialize timedate struct
td.day = 0;
td.hour = 0;
td.minute = 0;
td.month = 0;
td.second = 0;
td.year = 0;
// initialize secret and usertext to be full of zeroes
memset(&secret[0], 0x00, 51);
memset(&usertext[0], 0x00, 51);
memset(&SoftTimeArray[0], 0x00, 5);
memset(&inputforsha[0], 0x00, 64);
memset(&intMAC[0], 0x00, 20);
memset(&MAC[0], 0x00, 20);
memset(&newMAC[0], 0x00, 20);
memset(&filedata[0], 0x00, 76);
// initialize file entry.
// Name the file and extension to read in FileEntry struct.
fe.Name[0] = 0x45; //'E'
fe.Name[1] = 0x58; //'X'
fe.Name[2] = 0x50; //'P'
fe.Name[3] = 0x20; // blank
fe.Ext = 0x00;
puts("\nStarting 'Timed Trial' checking program for 1-Wire Clocks\n");
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
// acquire the port
if ((portnum = owAcquireEx(argv[1])) < 0) {
printf("Failed to acquire port.\n");
exit(1);
}
// success
printf("Port opened: %s\n", argv[1]);
// prompt the user to enter the secret
printf("\nPlease enter the secret, either as text or in hexadecimal.\n\n");
printf("Data Entry Mode\n");
printf("(0) Text (single line)\n");
printf("(1) Hex (XX XX XX XX ...)\n");
secretlength = getData(&secret[0], 51, getNumber(0, 1));
// get list of 1-Wire Clock devices
num = FindDevices(portnum, &TimeSN[0], TIME_FAM, MAXDEVICES);
// check if more than 1 present
if (num > 1) {
printf("\nMore than one 1-Wire clock discovered, picking ");
printf("\nthe first device found.\n");
}
// loop to read 1-Wire part and display status.
while (TRUE) {
// put in an extra return
printf("\n");
// get list of 1-Wire Clock devices
num = FindDevices(portnum, &TimeSN[0], TIME_FAM, MAXDEVICES);
// check if Clock not present
if (num == 0) {
printf("NO DEVICE PRESENT");
msDelay((int)noDeviceDelayTime);
continue;
}
// read RTC and RTCA
if (!getRTC(portnum, &TimeSN[0][0], &td)) { // read RTC
errordetect = NO_DEVICE;
}
RTCTime = DateToSeconds(&td); // convert timedate struct to number of seconds
if (!getRTCA(portnum, &TimeSN[0][0], &td)) { // read RTCA
errordetect = NO_DEVICE;
}
RTCATime = DateToSeconds(&td);
// retrieve file from part.
if (!owOpenFile(portnum, &TimeSN[0][0], &fe, &filehandle)) {
errordetect = NO_FILE;
} else if (!owReadFile(portnum, &TimeSN[0][0], filehandle, &filedata[0], 76, &filedatalength)) {
errordetect = NO_FILE;
} else if (!owCloseFile(portnum, &TimeSN[0][0], filehandle)) {
errordetect = NO_FILE;
}
// deal with NO_DEVICE error
if (errordetect == NO_DEVICE || RTCTime < 1) { // some bad RTC reads give RTCTime as 0.
printf("NO DEVICE PRESENT");
errordetect = NO_ERROR;
msDelay((int)noDeviceDelayTime);
continue;
}
// print out the 1-Wire net address of clock
i = 0;
for (j = 7; j >= 0; j--) {
printf("%02X", TimeSN[i][j]);
}
printf(",");
// deal with NO_FILE error
if (errordetect == NO_FILE) {
printf(" Token NOT VALID, no license file");
errordetect = NO_ERROR;
msDelay((int)delayTime);
continue;
}
usertextlength = filedatalength - 25; // 25 is MAC length (20) plus SoftTime length (5)
// parse file to retrieve the user text, the soft expiration time, and the MAC.
memcpy(&usertext[0], &filedata[0], usertextlength); // get usertext
memcpy(&SoftTimeArray[0], &filedata[usertextlength], 5); // get SoftTime as bytes
memcpy(&MAC[0], &filedata[(usertextlength + 5)], 20); // get MAC from file as 20 bytes
// Construct a new MAC with ROM + UserText + SOFTTIME + Secret =>(SHA)=> newMAC
// First, build 64-byte inputforsha array: ROM + UserText + SOFTTIME + Secret
memcpy(&inputforsha[0], &TimeSN[0][0], 8);
memcpy(&inputforsha[8], &usertext[0], usertextlength);
memcpy(&inputforsha[(usertextlength + 8)], &SoftTimeArray[0], 5);
SoftTime = uchar_to_bin(&SoftTimeArray[1], 4); // convert SoftTime to number of seconds
memcpy(&inputforsha[(usertextlength + 13)], &secret, secretlength);
// Create the SHA1 MAC from the inputforsha array
ComputeSHAVM(&inputforsha[0], &intMAC[0]);
// Make new MAC as a byte array from the intMAC int integer array
memcpy(&newMAC[0], &intMAC[0], 20);
// Compare old MAC from clock to new MAC against the entered secret
comparisonerror = FALSE;
for (i = 0; i < 20; i++) {
if (MAC[i] != newMAC[i])
comparisonerror = TRUE;
}
if (comparisonerror == TRUE) {
printf(" Token NOT VALID, secret must be different");
comparisonerror = FALSE; // reset error
} else {
printf(" Token VALID,");
if (RTCTime < SoftTime) {
printf(" License VALID, ");
PrintChars(&usertext[0], usertextlength);
} else {
printf(" License EXPIRED");
if (RTCTime >= RTCATime) {
printf(", Device EXPIRED");
}
}
}
// reset errordetect
errordetect = NO_ERROR;
msDelay((int)delayTime);
}
// release the port
owRelease(portnum);
return 1;
}
//----------------------------------------------------------------------
// computes a SHA given the 64 byte MT digest buffer. The resulting 5
// int values are stored in the given int array, hash.
//
// Note: This algorithm before's the SHA-1 algorithm as specified in the
// datasheet for the DS1961S, where the last step (which only involves
// math with constant values) is omitted.
//
// Parameters:
// MT - pointer to a buffer containing the message digest
// hash - resulting buffer
//
// Returns:
// - see hash variable above
//
void ComputeSHAVM(uchar *MT, int *hash) {
unsigned int MTword[80];
int i;
int ShftTmp;
int Temp;
for (i = 0; i < 16; i++) {
MTword[i] = ((MT[i * 4] & 0x00FF) << 24) | ((MT[i * 4 + 1] & 0x00FF) << 16) | ((MT[i * 4 + 2] & 0x00FF) << 8) |
(MT[i * 4 + 3] & 0x00FF);
}
for (; i < 80; i++) {
ShftTmp = MTword[i - 3] ^ MTword[i - 8] ^ MTword[i - 14] ^ MTword[i - 16];
MTword[i] = ((ShftTmp << 1) & 0xFFFFFFFE) | ((ShftTmp >> 31) & 0x00000001);
}
hash[0] = 0x67452301;
hash[1] = 0xEFCDAB89;
hash[2] = 0x98BADCFE;
hash[3] = 0x10325476;
hash[4] = 0xC3D2E1F0;
for (i = 0; i < 80; i++) {
ShftTmp = ((hash[0] << 5) & 0xFFFFFFE0) | ((hash[0] >> 27) & 0x0000001F);
Temp = NLF2(hash[1], hash[2], hash[3], i) + hash[4] + KTN[i / 20] + MTword[i] + ShftTmp;
hash[4] = hash[3];
hash[3] = hash[2];
hash[2] = ((hash[1] << 30) & 0xC0000000) | ((hash[1] >> 2) & 0x3FFFFFFF);
hash[1] = hash[0];
hash[0] = Temp;
}
}
//----------------------------------------------------------------------
// calculation used for the SHA MAC
//
int NLF2(int B, int C, int D, int n) {
if (n < 20)
return ((B & C) | ((~B) & D));
else if (n < 40)
return (B ^ C ^ D);
else if (n < 60)
return ((B & C) | (B & D) | (C & D));
else
return (B ^ C ^ D);
}
//----------------------------------------------------------------------
// Retrieve user input from the console.
//
// Parameters:
// min minimum number to accept
// max maximum number to accept
//
// Returns:
// numeric value entered from the console.
//
int getNumber(int min, int max) {
int value = min, cnt;
int done = FALSE;
do {
cnt = scanf("%d", &value);
if (cnt > 0 && (value > max || value < min)) {
printf("Value (%d) is outside of the limits (%d,%d)\n", value, min, max);
printf("Try again:\n");
} else
done = TRUE;
} while (!done);
return value;
}
//-------------------------------------------------------------------
//
// PSEUDOCODE SPECIFICATION:
//
// TM_Check - Prompt for Secret. Check for valid token present
// by doing the following:
//
// loop
// {
// if (DS1994 PRESENT)
// {
// print ROM
//
// Read Real-Time Clock (RTC) and Alarm (RTCA)
// Read EXP.000 and extract: UserText, SOFTTIME and MAC
//
// if (failed to read EXP.000)
// {
// print 'Token NOT VALID, no license file'
// continue
// }
//
// Construct a new MAC with
// ROM + UserText + SOFTTIME + Secret =>(SHA)=> MAC'
//
// if (MAC != MAC')
// print 'Token NOT VALID, secret must be different'
// else
// {
// print 'Token VALID'
//
// if (RTC < SOFTTIME)
// print 'License VALID' + UserText
// else
// print 'License EXPIRED'
//
// if (RTC >= RTCA)
// print 'Device EXPIRED'
// }
// }
// else
// print 'NO DEVICE PRESENT'
// }
//
// So the possible output may be:
//
// NO DEVICE PRESENT
// NO DEVICE PRESENT
// 5400000011227704, Token NOT VALID, no license file
// NO DEVICE PRESENT
// NO DEVICE PRESENT
// 1100000055266704, Token NOT VALID, secret must be different
// NO DEVICE PRESENT
// D7000000068C7A04, Token VALID, License VALID, MyTextGoesHere
// D7000000068C7A04, Token VALID, License VALID, MyTextGoesHere
// D7000000068C7A04, Token VALID, License VALID, MyTextGoesHere
// D7000000068C7A04, Token VALID, License EXPIRED
// D7000000068C7A04, Token VALID, License EXPIRED
// D7000000068C7A04, Token VALID, License EXPIRED
// D7000000068C7A04, Token VALID, License EXPIRED, Device EXPIRED
//
w1retap/src/libusblinux300/tm_init.c 0000664 0000000 0000000 00000034617 14464462352 0017647 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2001 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.
//---------------------------------------------------------------------------
//
// tm_init.c - program for initializing software authentication "Timed Trial"
// application using specific 1-Wire clocks (DS1994/DS1427/DS2404).
//
// Once the clock is setup with this program, then the companion
// program, tm_check, can be run to verify the software license.
//
#include
#include
#include "ownet.h"
#include "findtype.h"
#include "owfile.h"
#include "time04.h"
#include "memory.h"
#include "string.h"
// defines
#define MAXDEVICES 4
#define MAXTIMEOFFSET 378691201 // about 12 years.
// External functions
extern void owClearError(void);
// local functions
void ComputeSHAVM(uchar *MT, int *hash);
int NLF2(int B, int C, int D, int n);
int getNumber(int min, int max);
// constants used in SHA computation
static const int KTN[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
/*
TM_Init - Prompt for two expiration time limits.
The first is a hard limit that will 'expire' the device.
This is the value that will go into the Clock Alarm register.
The second expiration is a soft limit that will provide
a license period that does not expire the device. This
soft expiration will be a SHA validated value in a
memory file in the DS1994. Here is how it will work:
1. Prompt for 'hard' device expire limit
(seconds for demo purposes)
2. Prompt for 'soft' license expire limit
3. Prompt for Secret
4. Prompt for User text
(size limit = 64 - 8 - 5 - secretsize)
5. Set the Real-Time clock (RTC) to the PC's time
6. Set the Clock alarm (RTCA) to the 'hard' limit
(Real-Time + hard)
7. Write a SHA validated 'soft' limit in a file.
Create MAC with:
ROM + UserText + SOFTTIME + Secret =>(SHA)=> MAC
Write UserText + SOFTTIME + MAC in a file called EXP.000
8. Optionally set the Real-Time Clock LOCK bit
(command line switch???)
51 + 5 + 20
*/
int main(int argc, char **argv) {
int i = 0;
int j = 0;
char wpparameter[6]; // command line parameter to see if clock should be write-protected
SMALLINT wpenable = FALSE; // if true, then the part gets write-protected
int portnum = 0; // the port on which to communicate to 1-Wire devices
int num = 0; // number of 1-Wire Clock devices
timedate td; // timedate struct
int RTCAOffset = 180; // Real-Time Clock Alarm offset from PC time in seconds (entered by user)
int SoftOffset = 120; // "Soft" clock offset used to calculate expiry time to be placed in RAM of the part.
uint RTCTime = 0; // set RTC with this time in seconds.
uint RTCATime = 0; // set RTCA with this time in seconds.
uint SoftTime = 0; // set "Soft" time with this value.
uchar SoftTimeArray[5]; // holds the soft time in an array of uchar
uchar secret[51]; // holds the secret input by the user.
int secretlength; // secret length in number of bytes.
uchar usertext[51]; // holds the usertext input by the user.
int usertextlength; // user text length in number of bytes
uchar inputforsha[64]; // ROM + UserText + SOFTTIME + Secret
int intMAC[5]; // MAC resulting from SHA1 hash with
uchar MAC[20]; // MAC resulting from SHA1 hash of inputforsha array
uchar filedata[76]; // file data
int filedatalength = 76; // length of file data
short filehandle = 0; // handle to 1-Wire file
int maxwrite; // maximum number of bytes
FileEntry fe; // 1-Wire file info used to create a 1-Wire file
uchar TimeSN[MAXDEVICES][8]; // array to hold the serial numbers for the devices found
// Make sure we can talk to the part when it is alarming.
// The following variable should always be set when
// wanting to communicate to an alarming 1-Wire Clock device.
FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE = TRUE;
// initialize timedate struct
td.day = 0;
td.hour = 0;
td.minute = 0;
td.month = 0;
td.second = 0;
td.year = 0;
// initialize secret and usertext to be full of zeroes
memset(&wpparameter[0], 0x00, 6);
memset(&secret[0], 0x00, 51);
memset(&usertext[0], 0x00, 51);
memset(&SoftTimeArray[0], 0x00, 5);
memset(&inputforsha[0], 0x00, 64);
memset(&intMAC[0], 0x00, 20);
memset(&filedata[0], 0x00, 76);
puts("\nStarting 'Timed Trial' setup Application for 1-Wire Clocks\n");
// check for required port name
if (argc < 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
if (argc == 3) { // possible write-protect switch
sprintf(wpparameter, "-wp");
if (strcmp(argv[2], wpparameter) == 0) {
wpenable = TRUE; // the program will try to write-protect the clock
}
}
// acquire the port
if ((portnum = owAcquireEx(argv[1])) < 0) {
printf("Failed to acquire port.\n");
exit(1);
}
// success
printf("Port opened: %s\n", argv[1]);
// get list of 1-Wire Clock devices
num = FindDevices(portnum, &TimeSN[0], TIME_FAM, MAXDEVICES);
// check if not present or more than 1 present
if (num == 0)
ExitProg("1-Wire Clock not present on 1-Wire\n", 1);
if (num > 1) {
printf("\nMore than 1 1-Wire clock discovered, picking ");
printf("\nthe first device found.\n");
}
// print out the 1-Wire net address of clock
printf("\n1-Wire Address of clock found: ");
i = 0;
for (j = 7; j >= 0; j--) {
printf("%02X", TimeSN[i][j]);
}
printf("\n\n");
// prompt the user for RTCA info
printf("The first step is to set the clock alarm on the 1-Wire device.\n");
printf("The Real-Time Clock Alarm (RTCA) value, 'hard' alarm, will be \n");
printf("an offset from the PC's clock in seconds.\n\n");
// retrieve the real-time clock offset
EnterNum("Please enter the 'hard' offset value: ", 10, &RTCAOffset, 1, MAXTIMEOFFSET);
printf("\nThe number entered is: %i\n", RTCAOffset);
// retrieve the "soft" expiration date offset
printf("\nThe second step is to set an alarm time to be written to the part.\n");
printf("The 'soft' alarm value will also be an offset from the PC's clock\n");
printf("in seconds. Ideally, it should be less than the RTCA offset.\n\n");
EnterNum("Please enter the 'soft' offset value: ", 10, &SoftOffset, 1, MAXTIMEOFFSET);
printf("\nThe number entered is: %i\n", SoftOffset);
// retrieve the secret
printf("\nThe third step is to provide a secret, either as text or in hexadecimal.\n\n");
printf("Please enter the secret (up to 51 bytes)\n");
printf("Data Entry Mode\n");
printf("(0) Text (single line)\n");
printf("(1) Hex (XX XX XX XX ...)\n");
secretlength = getData(&secret[0], 51, getNumber(0, 1));
// retrieve the user text
printf("\nThe fourth step is to provide user text to be stored on the device.\n");
printf("It is general purpose text to be used, for example, as configuration\n");
printf("information for a software application. \n\n");
printf("Please enter the user text (up to %i bytes)\n", (51 - secretlength));
printf("Data Entry Mode\n");
printf("(0) Text (single line)\n");
printf("(1) Hex (XX XX XX XX ...)\n");
usertextlength = getData(&usertext[0], (51 - secretlength), getNumber(0, 1));
// set the RTC and RTCA of 1-Wire device and calculate SoftTime
getPCTime(&td); // get the time from the PC
RTCTime = DateToSeconds(&td); // convert time to seconds since Jan. 1, 1970
if (!setRTC(portnum, &TimeSN[0][0], RTCTime, TRUE)) { // set the RTC of 1-Wire device
printf("\nError in setting the Real-Time Clock, exiting program..\n");
OWERROR_DUMP(stdout);
exit(1);
}
RTCATime = RTCTime + RTCAOffset;
if (!setRTCA(portnum, &TimeSN[0][0], RTCATime, TRUE)) { // set RTCA with offset
printf("\nError in setting the Real-Time Clock alarm, exiting program..\n");
OWERROR_DUMP(stdout);
exit(1);
}
SoftTime = RTCTime + SoftOffset; // calculate Soft time
memcpy(&SoftTimeArray[1], &SoftTime, 4); // convert SoftTime to an array
// build 64-byte inputforsha array: ROM + UserText + SOFTTIME + Secret
memcpy(&inputforsha[0], &TimeSN[0][0], 8);
memcpy(&inputforsha[8], &usertext[0], usertextlength);
memcpy(&inputforsha[(usertextlength + 8)], &SoftTimeArray[0], 5);
memcpy(&inputforsha[(usertextlength + 13)], &secret, secretlength);
// Create the SHA1 MAC from the inputforsha array
ComputeSHAVM(&inputforsha[0], &intMAC[0]);
// Convert SHA1 results to a 20-byte array
memcpy(&MAC[0], &intMAC[0], 20);
// Write UserText + SOFTTIME + MAC in a file called EXP.000
// Name the file and extension in FileEntry struct.
fe.Name[0] = 0x45; //'E'
fe.Name[1] = 0x58; //'X'
fe.Name[2] = 0x50; //'P'
fe.Name[3] = 0x20; // blank
fe.Ext = 0x00;
// Fill in the file buffer to be eventually written to Clock.
memcpy(&filedata[0], &usertext, usertextlength);
memcpy(&filedata[usertextlength], &SoftTimeArray, 5);
memcpy(&filedata[(usertextlength + 5)], &MAC, 20);
filedatalength = usertextlength + 5 + 20;
// format the 1-Wire device, erasing previous file system
if (!owFormat(portnum, &TimeSN[0][0])) {
printf("\nError in formatting 1-Wire Clock's file system, exiting program..\n");
OWERROR_DUMP(stdout);
exit(1);
}
// create file
if (!owCreateFile(portnum, &TimeSN[0][0], &maxwrite, &filehandle, &fe)) {
printf("\nError creating 1-Wire Clock's file system, exiting program..\n");
OWERROR_DUMP(stdout);
exit(1);
}
// write the file
if (!owWriteFile(portnum, &TimeSN[0][0], filehandle, &filedata[0], filedatalength)) {
printf("\nError writing a file to the 1-Wire Clock's file system, exiting program..\n");
OWERROR_DUMP(stderr);
exit(1);
}
// write-protect the part
if (wpenable) {
// retrieve y or n from user
printf("\nYou have selected to write-protect the clock and clock alarm.\n");
printf("When the part alarms, the entire part will become read-only\n");
printf("Are you sure you want to do this? (y or n) ");
j = getkeystroke();
if ((j == 0x79) || (j == 0x59)) {
if (!setWriteProtectionAndExpiration(portnum, &TimeSN[0][0], TRUE, TRUE)) {
printf("\nError trying to write-protect the Real-Time Clock, exiting program...\n");
OWERROR_DUMP(stdout);
exit(1);
}
}
}
printf("\n\nThe part has been successfully set-up!\n\n");
// release the port
owRelease(portnum);
return 1;
}
//----------------------------------------------------------------------
// computes a SHA given the 64 byte MT digest buffer. The resulting 5
// int values are stored in the given int array, hash.
//
// Note: This algorithm before's the SHA-1 algorithm as specified in the
// datasheet for the DS1961S, where the last step (which only involves
// math with constant values) is omitted.
//
// Parameters:
// MT - pointer to a buffer containing the message digest
// hash - resulting buffer
//
// Returns:
// - see hash variable above
//
void ComputeSHAVM(uchar *MT, int *hash) {
unsigned int MTword[80];
int i;
int ShftTmp;
int Temp;
for (i = 0; i < 16; i++) {
MTword[i] = ((MT[i * 4] & 0x00FF) << 24) | ((MT[i * 4 + 1] & 0x00FF) << 16) | ((MT[i * 4 + 2] & 0x00FF) << 8) |
(MT[i * 4 + 3] & 0x00FF);
}
for (; i < 80; i++) {
ShftTmp = MTword[i - 3] ^ MTword[i - 8] ^ MTword[i - 14] ^ MTword[i - 16];
MTword[i] = ((ShftTmp << 1) & 0xFFFFFFFE) | ((ShftTmp >> 31) & 0x00000001);
}
hash[0] = 0x67452301;
hash[1] = 0xEFCDAB89;
hash[2] = 0x98BADCFE;
hash[3] = 0x10325476;
hash[4] = 0xC3D2E1F0;
for (i = 0; i < 80; i++) {
ShftTmp = ((hash[0] << 5) & 0xFFFFFFE0) | ((hash[0] >> 27) & 0x0000001F);
Temp = NLF2(hash[1], hash[2], hash[3], i) + hash[4] + KTN[i / 20] + MTword[i] + ShftTmp;
hash[4] = hash[3];
hash[3] = hash[2];
hash[2] = ((hash[1] << 30) & 0xC0000000) | ((hash[1] >> 2) & 0x3FFFFFFF);
hash[1] = hash[0];
hash[0] = Temp;
}
}
//----------------------------------------------------------------------
// calculation used for the SHA MAC
//
int NLF2(int B, int C, int D, int n) {
if (n < 20)
return ((B & C) | ((~B) & D));
else if (n < 40)
return (B ^ C ^ D);
else if (n < 60)
return ((B & C) | (B & D) | (C & D));
else
return (B ^ C ^ D);
}
//----------------------------------------------------------------------
// Retrieve user input from the console.
//
// Parameters:
// min minimum number to accept
// max maximum number to accept
//
// Returns:
// numeric value entered from the console.
//
int getNumber(int min, int max) {
int value = min, cnt;
int done = FALSE;
do {
cnt = scanf("%d", &value);
if (cnt > 0 && (value > max || value < min)) {
printf("Value (%d) is outside of the limits (%d,%d)\n", value, min, max);
printf("Try again:\n");
} else
done = TRUE;
} while (!done);
return value;
}
w1retap/src/libusblinux300/tstfind.c 0000664 0000000 0000000 00000007364 14464462352 0017656 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// tstfind.C - Test application to search for all 1-Wire devices on 1-Wire
// Net.
//
// Version: 2.00
//
// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
// Removed "ds2480.h", and
// includes because not needed
// Added "ownet.h" include to define TRUE/FALSE
// Prompt to search again
// Changed to use Acquire/Release 1-Wire Net functions
// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for
// multiple ports. Don't stop loop at end of each
// search round.
#include
#include
#include "ownet.h"
//----------------------------------------------------------------------
// Main for tstfind
//
int main(int argc, char **argv) {
int rslt, cnt;
int portnum = 0;
uchar SNum[8];
// check for required port name
if (argc != 2) {
printf("1-Wire Net name required on command line!\n"
" (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
"(Linux DS2480),\"1\" (Win32 TMEX)\n");
exit(1);
}
// attempt to acquire the 1-Wire Net
if ((portnum = owAcquireEx(argv[1])) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
// success
printf("Port opened: %s\n", argv[1]);
//----------------------------------------
// Introduction
printf("\n/---------------------------------------------\n");
printf(" Loop to find all iButton on 1-Wire Net.\n\n");
do {
printf("-------------------- Start of search\n");
cnt = 0;
// find the first device (all devices not just alarming)
rslt = owFirst(portnum, TRUE, FALSE);
while (rslt) {
// print the device number
cnt++;
printf("(%d) ", cnt);
// print the Serial Number of the device just found
owSerialNum(portnum, &SNum[0], TRUE);
// PrintSerialNum(&SNum[0]);
int ii;
for (ii = 0; ii < 8; ii++)
printf("%02X", SNum[ii]);
printf("\n");
// find the next device
rslt = owNext(portnum, TRUE, FALSE);
}
printf("-------------------- End of search\n\n");
} while (!key_abort());
// release the 1-Wire Net
owRelease(portnum);
printf("Closing port %s.\n", argv[1]);
exit(0);
return 0;
}
w1retap/src/libusblinux300/w1find.c 0000664 0000000 0000000 00000003671 14464462352 0017370 0 ustar 00root root 0000000 0000000 #include
#include
#include
#include "ownet.h"
#include "findtype.h"
#include "swt1f.h"
#include "devlist.h"
void listdev(uchar *id) {
w1devs_t *w;
for (w = devlist; w->family; w++) {
if (w->family == id[0]) {
printf("\t%s:%s", (w->dev) ? w->dev : "", w->name);
break;
}
}
}
void showid(uchar *id) {
int i;
for (i = 0; i < 8; i++) {
printf("%02X", id[i]);
}
listdev(id);
printf("\n");
}
void search_coupler(int portnum, uchar *id) {
int j, k, res, line;
uchar a[4];
uchar snum[8];
showid(id);
for (j = 1; j < 3; j++) {
k = 0;
line = (j == 1) ? 4 : 2;
SetSwitch1F(portnum, id, line, 2, a, TRUE);
res = owFirst(portnum, FALSE, FALSE);
while (res) {
k++;
printf("\t(%s.%d) ", (j == 1) ? "Main" : " Aux", k);
owSerialNum(portnum, snum, TRUE);
showid(snum);
SetSwitch1F(portnum, id, line, 2, a, TRUE);
res = owNext(portnum, FALSE, FALSE);
}
}
}
int main(int argc, char **argv) {
int rslt, cnt;
int portnum = 0;
uchar snum[8];
int nc = 0;
uchar cplr[32][8];
if (argc != 2) {
printf("1-Wire device name required "
" (e.g: \"/dev/ttyS0\" (DS2480), \"DS2490-1\" (USB) \n");
exit(1);
}
if ((portnum = owAcquireEx(argv[1])) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
nc = FindDevices(portnum, cplr, SWITCH_FAMILY, 32);
owSkipFamily(portnum);
int j;
for (j = 0; j < nc; j++) { /* for each coupler ... */
uchar a[3];
SetSwitch1F(portnum, cplr[j], 0, 2, a, TRUE); /* turn off switch */
}
cnt = 0;
rslt = owFirst(portnum, TRUE, FALSE);
while (rslt) {
owSerialNum(portnum, snum, TRUE);
if (snum[0] != 0x1f) {
cnt++;
printf("(%d) ", cnt);
showid(snum);
}
rslt = owNext(portnum, TRUE, FALSE);
}
for (j = 0; j < nc; j++) {
cnt++;
printf("(%d) ", cnt);
search_coupler(portnum, cplr[j]);
}
owRelease(portnum);
return 0;
}
w1retap/src/libusblinux300/weather.c 0000664 0000000 0000000 00000047330 14464462352 0017637 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// weather.c - To find what kind of weather station or if it is there.
// There are also modules to find the direction of the weather
// station and read/write output files
//
// Version: 2.00
//
//
// --------------------------------------------------------------------------
#include
#include
#include
#include
#include "ownet.h"
#include "swt12.h"
#include "findtype.h"
#include "weather.h"
#include "atod20.h"
#include "temp10.h"
#include "cnt1d.h"
// defines
#define MAXDEVICES 8
// family codes of devices
#define TEMP_FAMILY 0x10
#define SWITCH_FAMILY 0x12
#define ATOD_FAMILY 0X20
#define COUNT_FAMILY 0x1D
#define DIR_FAMILY 0x01
// misc
#define MAXTEMPS 1
#define MAXSWITCH 1
#define MAXCOUNT 1
#define MAXATOD 1
#define MAXDIR 8
static int conv[8] = {0, 14, 12, 10, 8, 6, 4, 2};
static double conv_table[16][4] = {
{0.06, 4.64, 4.64, 4.64}, {0.06, 0.06, 4.60, 4.60}, {4.64, 0.06, 4.64, 4.64}, {4.62, 0.06, 0.06, 4.60},
{4.64, 4.64, 0.06, 4.64}, {4.60, 4.60, 0.06, 0.06}, {4.64, 4.64, 4.64, 0.06}, {2.36, 4.62, 4.60, 0.06},
{2.38, 4.66, 4.66, 4.66}, {3.20, 3.20, 4.66, 4.64}, {4.66, 2.38, 4.66, 4.66}, {4.66, 3.18, 3.20, 4.64},
{4.66, 4.66, 2.38, 4.66}, {4.66, 4.66, 3.18, 3.18}, {4.66, 4.66, 4.66, 2.38}, {0.06, 4.62, 4.62, 2.34}};
// -------------------------------------------------------------------------
// SUBROUTINE - FindWeather
//
// This routine finds which weather station is attached to the 1-wire
// network and returns the serial numbers for the weather station. If
// it is the new weather station then it is not going to have an DS2401s.
//
// 'ds1820' - This will be the serial number for the DS1820 in the station
// 'ds2423' - This will be the serial number for the DS2423 in the station
// 'dsdir' - This will either be the DS2450 or the DS2406 serial num.
// 'ds2401' - This will be the list of DS2401s if the old weather station.
//
// Returns: TRUE if a weather station is found and the listing of the
// devices file is found or made. FALSE if a weather station
// is not found or the device file is not found or can not be made.
//
int FindSetupWeather(int portnum, WeatherStruct *wet) {
int ret = FALSE;
FILE *fptr;
char filename[] = "ini.txt";
char TempSN[190];
uchar SNs[90];
int i, j;
int num;
char msg[45];
uchar temp[MAXDIR][8];
temp[0][0] = 0x00;
wet->weather_a = FALSE;
wet->weather_b = FALSE;
wet->found_2401 = 0;
wet->found_2423 = FALSE;
wet->found_1820 = FALSE;
wet->found_dir = FALSE;
wet->north = 0;
if ((fptr = fopen(filename, "r")) == NULL) {
printf("error opening file but try to create file\n");
// Create ini.txt if weather station has DS2450
// find the DS1820 temperature
num = FindDevices(portnum, &temp[0], TEMP_FAMILY, MAXTEMPS);
// check if not at least 1 temperature device
if (num == 0)
wet->found_1820 = FALSE;
else {
for (i = 0; i < 8; i++)
wet->ds1820[i] = temp[0][i];
wet->found_1820 = TRUE;
}
// find the DS2450 switch
num = FindDevices(portnum, &temp[0], ATOD_FAMILY, MAXATOD);
// check if not at least 1 switch device
if (num == 0)
wet->found_dir = FALSE;
else {
for (i = 0; i < 8; i++)
wet->dsdir[i] = temp[0][i];
wet->found_dir = TRUE;
}
// find the DS2423 switch
num = FindDevices(portnum, &temp[0], COUNT_FAMILY, MAXCOUNT);
// check if not at least 1 count device
if (num == 0)
wet->found_2423 = FALSE;
else {
for (i = 0; i < 8; i++)
wet->ds2423[i] = temp[0][i];
wet->found_2423 = TRUE;
}
// Create the output file ini.txt
if (wet->found_1820 && wet->found_dir && wet->found_2423) {
if (SetupAtoDControl(portnum, &wet->dsdir[0], &wet->ctrl[0], &msg[0]))
if (WriteAtoD(portnum, FALSE, &wet->dsdir[0], &wet->ctrl[0], 0x08, 0x11)) {
if ((fptr = fopen(filename, "w")) == NULL)
printf("error tring to create file\n");
else {
wet->weather_b = TRUE;
ret = TRUE;
// Printing the Serial number for DS2450
printf("Found DS2450\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->dsdir[i]);
printf("\n");
for (i = 7; i >= 0; i--)
fprintf(fptr, "%02X", wet->dsdir[i]);
fprintf(fptr, "\n");
// Printing the Serial number for DS1820
printf("Found DS1820\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds1820[i]);
printf("\n");
for (i = 7; i >= 0; i--)
fprintf(fptr, "%02X", wet->ds1820[i]);
fprintf(fptr, "\n");
// Printing the Serial number for DS2423
printf("Found DS2423\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds2423[i]);
printf("\n");
for (i = 7; i >= 0; i--)
fprintf(fptr, "%02X", wet->ds2423[i]);
fprintf(fptr, "\n");
// Printing the Default Wind Direction
printf("The Default Wind Direction is 0\n");
fprintf(fptr, "0\n");
}
}
}
} else {
num = fread(TempSN, sizeof(char), 189, fptr);
num = ParseData(TempSN, num, &SNs[0], 90);
if (!wet->weather_a && !wet->weather_b) {
if (SNs[7] == 0x01)
wet->weather_a = TRUE;
else
wet->weather_b = TRUE;
}
j = 0;
while ((SNs[7 + 8 * j] == 0x01) || (SNs[7 + 8 * j] == 0x20) || (SNs[7 + 8 * j] == 0x12) || (SNs[7 + 8 * j] == 0x1D) ||
(SNs[7 + 8 * j] == 0x10)) {
if (SNs[7 + 8 * j] == 0x01) {
for (i = 0; i < 8; i++)
wet->ds2401[wet->found_2401][7 - i] = SNs[8 * j + i];
printf("Found DS2401\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds2401[wet->found_2401][i]);
printf("\n");
wet->found_2401++;
}
if (SNs[7 + 8 * j] == 0x20) {
if (!wet->found_dir) {
for (i = 0; i < 8; i++)
wet->dsdir[7 - i] = SNs[8 * j + i];
owSerialNum(portnum, wet->dsdir, FALSE);
if (!owVerify(portnum, FALSE))
ret = FALSE;
wet->found_dir = TRUE;
printf("Found DS2450\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->dsdir[i]);
printf("\n");
if (!SetupAtoDControl(portnum, wet->dsdir, &wet->ctrl[0], &msg[0]))
return FALSE;
if (!WriteAtoD(portnum, FALSE, wet->dsdir, &wet->ctrl[0], 0x08, 0x11))
return FALSE;
}
}
if (SNs[7 + 8 * j] == 0x12) {
if (!wet->found_dir) {
for (i = 0; i < 8; i++)
wet->dsdir[7 - i] = SNs[8 * j + i];
owSerialNum(portnum, wet->dsdir, FALSE);
if (!owVerify(portnum, FALSE))
ret = FALSE;
wet->found_dir = TRUE;
printf("Found DS2406\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->dsdir[i]);
printf("\n");
}
}
if (SNs[7 + 8 * j] == 0x1D) {
for (i = 0; i < 8; i++)
wet->ds2423[7 - i] = SNs[8 * j + i];
owSerialNum(portnum, wet->ds2423, FALSE);
if (!owVerify(portnum, FALSE))
ret = FALSE;
wet->found_2423 = TRUE;
printf("Found DS2423\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds2423[i]);
printf("\n");
}
if (SNs[7 + 8 * j] == 0x10) {
for (i = 0; i < 8; i++)
wet->ds1820[7 - i] = SNs[8 * j + i];
owSerialNum(portnum, wet->ds1820, FALSE);
if (!owVerify(portnum, FALSE))
ret = FALSE;
wet->found_1820 = TRUE;
printf("Found DS1820\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds1820[i]);
printf("\n");
}
j++;
}
if (wet->weather_a) {
if ((TempSN[0xBB] <= 0x40) && (TempSN[0xBB] >= 0x30))
if ((TempSN[0xBC] <= 0x40) && (TempSN[0xBC] >= 0x30))
wet->north = (TempSN[0xBB] - 0x30) * 10 + (TempSN[0xBC] - 0x30);
else
wet->north = TempSN[0xBB] - 0x30;
else
wet->north = 0;
if (wet->found_dir && wet->found_1820 && wet->found_2423 && (wet->found_2401 == 8))
ret = TRUE;
} else if (wet->weather_b) {
if ((TempSN[0x33] <= 0x40) && (TempSN[0x33] >= 0x30))
if ((TempSN[0x34] <= 0x40) && (TempSN[0x34] >= 0x30))
wet->north = (TempSN[0x33] - 0x30) * 10 + (TempSN[0x34] - 0x30);
else
wet->north = TempSN[0x33] - 0x30;
else
wet->north = 0;
if (wet->found_dir && wet->found_1820 && wet->found_2423)
ret = TRUE;
}
}
if (wet->weather_a || wet->weather_b) {
if (fptr != 0) {
fclose(fptr);
}
}
return ret;
}
// -------------------------------------------------------------------------
// SUBROUTINE - SetupWet
//
// This routine sets up a weather station given the serial numbers for the
// weather station.
//
// Returns: TRUE, if the weather station was setup and FALSE if it was not.
//
int SetupWet(int portnum, WeatherStruct *wet, int nor) {
int i, j;
int ret = FALSE;
char msg[45];
wet->north = nor;
if (wet->weather_b) {
wet->weather_b = TRUE;
wet->weather_a = FALSE;
// Setting up the DS2450
owSerialNum(portnum, wet->dsdir, FALSE);
if (!owVerify(portnum, FALSE)) {
printf("The DS2450 was not found.\n");
return FALSE;
} else {
// Printing the Serial number for DS2450
printf("Set DS2450\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->dsdir[i]);
printf("\n");
}
// Setting up the DS1820
owSerialNum(portnum, wet->ds1820, FALSE);
if (!owVerify(portnum, FALSE)) {
printf("The DS1820 was not found.\n");
return FALSE;
} else {
// Printing the Serial number for DS1820
printf("Set DS1820\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds1820[i]);
printf("\n");
}
// Setting up the DS2423
owSerialNum(portnum, wet->ds2423, FALSE);
if (!owVerify(portnum, FALSE)) {
printf("The DS2423 was not found.\n");
return FALSE;
} else {
// Printing the Serial number for DS2423
printf("Set DS2423\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds2423[i]);
printf("\n");
}
if (SetupAtoDControl(portnum, &wet->dsdir[0], &wet->ctrl[0], &msg[0]))
if (WriteAtoD(portnum, FALSE, &wet->dsdir[0], &wet->ctrl[0], 0x08, 0x11))
ret = TRUE;
} else {
wet->weather_a = TRUE;
wet->weather_b = FALSE;
printf("Set DS2401\n");
for (i = 0; i < 8; i++) {
// Printing the Serial number for DS2401
for (j = 7; j >= 0; j--)
printf("%02X", wet->ds2401[i][j]);
printf("\n");
}
// Setting up the DS2423
owSerialNum(portnum, wet->ds2423, FALSE);
if (!owVerify(portnum, FALSE)) {
printf("The DS2423 was not found.\n");
return FALSE;
} else {
// Printing the Serial number for DS2423
printf("Set DS2423\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds2423[i]);
printf("\n");
}
// Setting up the DS1820
owSerialNum(portnum, wet->ds1820, FALSE);
if (!owVerify(portnum, FALSE)) {
printf("The DS1820 was not found.\n");
return FALSE;
} else {
// Printing the Serial number for DS1820
printf("Set DS1820\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->ds1820[i]);
printf("\n");
}
// Setting up the DS2406
owSerialNum(portnum, wet->dsdir, FALSE);
if (!owVerify(portnum, FALSE)) {
printf("The DS2406 was not found.\n");
return FALSE;
} else {
// Printing the Serial number for DS2406
printf("Set DS2450\n");
for (i = 7; i >= 0; i--)
printf("%02X", wet->dsdir[i]);
printf("\n");
}
ret = TRUE;
}
return ret;
}
// -------------------------------------------------------------------------
// SUBROUTINE - ReadWet
//
// 'temp' - The temperature from the DS1820 in F
// 'dir' - The wind direction from 0-15
// 'revol' - The wind speed in revolutions per second
//
// Returns: TRUE, if the reads were successfull and FALSE if they were not.
//
int ReadWet(int portnum, WeatherStruct *wet, float *temp, int *dir, double *revol) {
int ret = TRUE;
unsigned int start_count = 0, end_count = 0, start_time, end_time;
float current_temp;
// read the current counter
// use this reference to calculate wind speed later
if (!ReadCounter(portnum, &wet->ds2423[0], 15, &start_count)) {
printf("\nError reading counter, verify device present:%d\n", (int)owVerify(portnum, FALSE));
ret = FALSE;
}
// get a time stamp (mS)
start_time = msGettick();
// read the temperature and print in F
if (ReadTemperature(portnum, &wet->ds1820[0], ¤t_temp, 1000))
*temp = current_temp * 9 / 5 + 32;
else {
printf("\nError reading temperature, verify device present:%d\n", (int)owVerify(portnum, FALSE));
ret = FALSE;
}
// read the wind direction
*dir = TrueDir(portnum, wet);
// read the counter again
if (!ReadCounter(portnum, &wet->ds2423[0], 15, &end_count)) {
printf("Error reading counter, verify device present:%d\n", (int)owVerify(portnum, FALSE));
ret = FALSE;
}
// get a time stamp (mS)
end_time = msGettick();
// calculate the wind speed based on the revolutions per second
*revol = (((end_count - start_count) * 1000.0) / (end_time - start_time)) / 2.0;
return ret;
}
// -------------------------------------------------------------------------
// SUBROUTINE - GetDir
//
// This routine looks at the DS2401 serial numbers or the DS2450 volts to
// determine which direction the wind is blowing.
//
// Returns: The direction in a 0-15 order and 16 for no DS2401s found
//
int GetDir(int portnum, WeatherStruct *wet) {
SwitchProps st;
uchar temp_dir[MAXDIR][8];
int i, j;
int numdir = 0;
int firstmatch = 0, secondmatch = 0;
int firstindex = 0;
int found = TRUE;
int ret = 16;
float prslt[4];
temp_dir[0][0] = 0x00;
if (wet->weather_a) {
st.Chan_A = FALSE;
st.Chan_B = TRUE;
if (SetSwitch12(portnum, &wet->dsdir[0], st)) {
numdir = FindDevices(portnum, &temp_dir[0], DIR_FAMILY, MAXDIR);
} else
printf("Error on setting up the switch\n");
if (numdir == 0)
ret = 16;
if (numdir == 2) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++)
if (temp_dir[0][j] != wet->ds2401[i][j]) {
found = FALSE;
break;
} else
found = TRUE;
if (found) {
firstindex = i;
firstmatch = conv[i];
found = FALSE;
break;
}
}
for (i = 0; i < 8; i++) {
if (i != firstindex) {
for (j = 0; j < 8; j++) {
if (temp_dir[1][j] != wet->ds2401[i][j]) {
found = FALSE;
break;
} else
found = TRUE;
}
}
if (found) {
secondmatch = conv[i];
break;
}
}
if (((firstmatch == 0) || (secondmatch == 0)) && ((firstmatch == 14) || (secondmatch == 14)))
ret = 15;
else
ret = (firstmatch + secondmatch) / 2;
}
if (numdir == 1) {
for (i = 0; i < 8; i++) {
found = TRUE;
for (j = 0; j < 8; j++)
if (temp_dir[0][j] != wet->ds2401[i][j])
found = FALSE;
if (found) {
ret = conv[i];
break;
}
}
}
st.Chan_A = FALSE;
st.Chan_B = FALSE;
if (!SetSwitch12(portnum, &wet->dsdir[0], st)) {
msDelay(10);
if (!SetSwitch12(portnum, &wet->dsdir[0], st)) {
printf("Failed to close channel B\n");
}
}
} else if (wet->weather_b) {
// read wind direction for the DS2450 weather station
if (DoAtoDConversion(portnum, FALSE, &wet->dsdir[0])) {
if (ReadAtoDResults(portnum, FALSE, &wet->dsdir[0], &prslt[0], &wet->ctrl[0])) {
for (i = 0; i < 16; i++) {
if (((prslt[0] <= (float)conv_table[i][0] + 0.25) && (prslt[0] >= (float)conv_table[i][0] - 0.25)) &&
((prslt[1] <= (float)conv_table[i][1] + 0.25) && (prslt[1] >= (float)conv_table[i][1] - 0.25)) &&
((prslt[2] <= (float)conv_table[i][2] + 0.25) && (prslt[2] >= (float)conv_table[i][2] - 0.25)) &&
((prslt[3] <= (float)conv_table[i][3] + 0.25) && (prslt[3] >= (float)conv_table[i][3] - 0.25))) {
ret = i;
break;
}
}
} else {
printf("\n");
printf("\nError reading channel, verify device present: %d\n", (int)owVerify(portnum, FALSE));
}
}
}
return ret;
}
// -------------------------------------------------------------------------
// SUBROUTINE - TrueDir
//
// This routine returns the direction given the north direction in 0-15.
//
// Returns: The direction in a 0-15 order with 0 north and clockwise from that.
// 16 is returned for no DS2401s found.
//
int TrueDir(int portnum, WeatherStruct *wet) {
int dir;
int retdir;
dir = GetDir(portnum, wet);
if (dir != 16) {
if ((dir - wet->north) < 0)
retdir = (dir - wet->north + 16);
else
retdir = dir - wet->north;
} else
retdir = 16;
return retdir;
}
//----------------------------------------------------------------------
// Parse the raw file data in to an array of uchar's. The data must
// be hex characters possible seperated by white space
// 12 34 456789ABCD EF
// FE DC BA 98 7654 32 10
// would be converted to an array of 16 uchars.
// return the array length. If an invalid hex pair is found then the
// return will be 0.
//
int ParseData(char *inbuf, int insize, uchar *outbuf, int maxsize) {
int ps, outlen = 0, gotmnib = 0;
uchar mnib = 0;
// loop until end of data
for (ps = 0; ps < insize; ps++) {
// check for white space
if (isspace(inbuf[ps]))
continue;
// not white space, make sure hex
else if (isxdigit(inbuf[ps])) {
// check if have first nibble yet
if (gotmnib) {
// this is the second nibble
outbuf[outlen++] = (mnib << 4) | ToHex(inbuf[ps]);
gotmnib = 0;
} else {
// this is the first nibble
mnib = ToHex(inbuf[ps]);
gotmnib = 1;
}
} else
return 0;
// if getting to the max return what we have
if ((outlen + 1) >= maxsize)
return outlen;
}
return outlen;
}
w1retap/src/libusblinux300/weather.h 0000664 0000000 0000000 00000004215 14464462352 0017637 0 ustar 00root root 0000000 0000000 //---------------------------------------------------------------------------
// Copyright (C) 2000 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.
//---------------------------------------------------------------------------
//
// weather.H - Include file for Weather station struct
// Version 2.00
//
// Typedefs
typedef struct temptag {
uchar dsdir[8];
uchar ds1820[8];
uchar ds2423[8];
uchar ds2401[8][8];
uchar ctrl[16];
int weather_a;
int weather_b;
int found_dir;
int found_1820;
int found_2423;
int found_2401;
int north;
} WeatherStruct;
// local function prototypes
int FindSetupWeather(int portnum, WeatherStruct *wet);
int SetupWet(int portnum, WeatherStruct *wet, int nor);
int ReadWet(int portnum, WeatherStruct *wet, float *temp, int *dir, double *revol);
int GetDir(int portnum, WeatherStruct *wet);
int TrueDir(int portnum, WeatherStruct *wet);
int ParseData(char *inbuf, int insize, uchar *outbuf, int maxsize);
w1retap/src/meson.build 0000664 0000000 0000000 00000002671 14464462352 0015412 0 ustar 00root root 0000000 0000000
wsrcs = files ('w1retap.c', 'w1util.c', 'w1sensors.c', 'w1conf.c')
w1file_src = files('w1file.c')
w1csv_src = files('w1csv.c')
xmllib = dependency('libxml-2.0', required: false)
w1file = shared_module('w1file',
w1file_src,
c_args: '-D_GNU_SOURCE',
dependencies: [
wdeps,
],
include_directories : [ configuration_inc ],
install_dir : pkglibdir,
install : true
)
if xmllib.found()
w1xml_src = files('w1xml.c')
w1xml = shared_module('w1xml',
w1xml_src,
c_args: '-D_GNU_SOURCE',
dependencies: [
wdeps,
xmllib,
],
include_directories : [ configuration_inc ],
install_dir : pkglibdir,
install : true
)
endif
w1csv = shared_module('w1csv',
w1csv_src,
c_args: '-D_GNU_SOURCE',
dependencies: [
wdeps
],
include_directories : [ configuration_inc ],
install_dir : pkglibdir,
install : true
)
w1retap/src/mkrate.sh 0000775 0000000 0000000 00000000073 14464462352 0015064 0 ustar 00root root 0000000 0000000 #!/bin/sh
exec gcc -O2 -Wall -o testrate testrate.c -lm
w1retap/src/mysql/ 0000775 0000000 0000000 00000000000 14464462352 0014407 5 ustar 00root root 0000000 0000000 w1retap/src/mysql/meson.build 0000664 0000000 0000000 00000000734 14464462352 0016555 0 ustar 00root root 0000000 0000000
w1mysql_src = 'w1mysql.c'
w1mysql = shared_module('w1mysql',
w1mysql_src,
c_args: ['-D_GNU_SOURCE' ],
include_directories : configuration_inc,
dependencies: [
have_mysql,
wdeps
],
install_dir : pkglibdir,
install : true
)
w1retap/src/mysql/w1mysql.c 0000664 0000000 0000000 00000022443 14464462352 0016175 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "w1retap.h"
// This forces the bad old way of doing MYSQL inserts, as prepared statements appear to
// fail when loaded dynamically
#if !defined(W1MYSQL_MINVERS)
#define W1MYSQL_MINVERS 9999999
#endif
static void my_params(char *params, char **host, char **dbname, char **user, char **pass) {
char *mp = strdup(params);
char *s0, *s1;
for (s0 = mp; (s1 = strsep(&s0, " "));) {
char t[257], v[257];
if (2 == sscanf(s1, "%256[^=]=%256s", t, v)) {
if (strcmp(t, "dbname") == 0) {
*dbname = strdup(v);
} else if (strcmp(t, "host") == 0) {
*host = strdup(v);
} else if (strcmp(t, "user") == 0) {
*user = strdup(v);
} else if (strcmp(t, "password") == 0) {
*pass = strdup(v);
}
}
}
free(mp);
}
static MYSQL *w1_opendb(char *params) {
MYSQL *conn = NULL;
char *dbname, *user, *password, *host;
host = dbname = user = password = NULL;
my_params(params, &host, &dbname, &user, &password);
conn = mysql_init(NULL);
if (0 == mysql_real_connect(conn, host, user, password, dbname, 0, NULL, 0)) {
perror(mysql_error(conn));
conn = NULL;
}
if (dbname)
free(dbname);
if (user)
free(user);
if (host)
free(host);
if (password)
free(password);
return conn;
}
void w1_init(w1_devlist_t *w1, char *dbnam) {
w1_device_t *devs = NULL;
char *sql = "select * from w1sensors order by device";
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL_FIELD *field;
int n = 0;
int nr = 0;
int nx = 0;
int nn = 0;
int id = -1;
int it = -1;
int ni = 0;
conn = w1_opendb(dbnam);
if (conn && !mysql_query(conn, sql)) {
res = mysql_store_result(conn);
nr = mysql_num_rows(res);
devs = malloc(sizeof(w1_device_t) * nr);
memset(devs, 0, sizeof(w1_device_t) * nr);
for (n = 0; n < nr; n++) {
int j;
char *fnam;
row = mysql_fetch_row(res);
int nf = mysql_num_fields(res);
if (n == 0) {
for (j = 0; j < nf; j++) {
field = mysql_fetch_field_direct(res, j);
fnam = field->name;
if (strcmp(fnam, "device") == 0) {
id = j;
} else if (strcmp(fnam, "type") == 0) {
it = j;
}
if (it != -1 && id != -1)
break;
}
}
nn = w1_get_device_index(devs, ni, row[id], row[it]);
if (nn == -1) {
nx = ni;
ni++;
} else {
nx = nn;
}
for (j = 0; j < nf; j++) {
char *s = row[j];
char *sv = (s && *s) ? strdup(s) : NULL;
field = mysql_fetch_field_direct(res, j);
fnam = field->name;
if (sv)
w1_set_device_data(devs + nx, fnam, sv);
}
w1_enumdevs(devs + nx);
}
w1->numdev = ni;
w1->devs = devs;
mysql_free_result(res);
if (!mysql_query(conn, "select name,value,rmin,rmax from ratelimit")) {
res = mysql_store_result(conn);
int nn = mysql_num_rows(res);
for (n = 0; n < nn; n++) {
row = mysql_fetch_row(res);
char *s = row[0];
short flags = 0;
float roc = 0, rmin = 0, rmax = 0;
if (s && *s) {
char *sv = row[1];
if (sv && *sv) {
roc = strtof(sv, NULL);
flags |= W1_ROC;
}
sv = row[2];
if (sv && *sv) {
rmin = strtof(sv, NULL);
flags |= W1_RMIN;
}
sv = row[3];
if (sv && *sv) {
rmax = strtof(sv, NULL);
flags |= W1_RMAX;
}
}
if (flags) {
w1_sensor_t *sensor;
if (NULL != (sensor = w1_find_sensor(w1, (const char *)s))) {
sensor->flags = flags;
if (flags & W1_ROC)
sensor->roc = roc;
if (flags & W1_RMIN)
sensor->rmin = rmin;
if (flags & W1_RMAX)
sensor->rmax = rmax;
}
}
}
mysql_free_result(res);
}
mysql_close(conn);
}
}
static MYSQL *conn;
#if MYSQL_VERSION_ID > W1MYSQL_MINVERS
static MYSQL_STMT *stmt;
#endif
void w1_cleanup(void) {
if (conn) {
#if MYSQL_VERSION_ID > W1MYSQL_MINVERS
mysql_stmt_close(stmt);
stmt = NULL;
#endif
mysql_close(conn);
conn = NULL;
}
}
void w1_logger(w1_devlist_t *w1, char *params) {
int i = 0;
w1_device_t *devs;
if (access("/tmp/.w1retap.lock", F_OK) == 0) {
return;
}
if (conn == NULL) {
if (w1->verbose)
fprintf(stderr, "mysql version check %d %d\n", MYSQL_VERSION_ID, W1MYSQL_MINVERS);
conn = w1_opendb(params);
#if MYSQL_VERSION_ID > W1MYSQL_MINVERS
mysql_autocommit(conn, 0);
#else
mysql_real_query(conn, "SET AUTOCOMMIT=0", sizeof("SET AUTOCOMMIT=0") - 1);
#endif
}
#if MYSQL_VERSION_ID > W1MYSQL_MINVERS
if (w1->verbose)
fprintf(stderr, "Using prepared statement\n");
if (stmt == NULL) {
const char s[] = "insert into readings(date,name,value) values (?,?,?)";
stmt = mysql_stmt_init(conn);
mysql_stmt_prepare(stmt, s, sizeof(s) - 1);
}
#else
mysql_real_query(conn, "BEGIN", sizeof("BEGIN") - 1);
#endif
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) {
if (devs->init) {
int j;
#if MYSQL_VERSION_ID > W1MYSQL_MINVERS
MYSQL_BIND bind[3];
#endif
for (j = 0; j < devs->ns; j++) {
if (devs->s[j].valid) {
#if MYSQL_VERSION_ID > W1MYSQL_MINVERS
memset(bind, 0, sizeof(bind));
struct tm *tm = NULL;
if (w1->timestamp) {
tm = (w1->force_utc) ? gmtime(&w1->logtime) : localtime(&w1->logtime);
MYSQL_TIME mtm = {0};
mtm.year = tm->tm_year + 1900;
mtm.month = tm->tm_mon + 1;
mtm.day = tm->tm_mday;
mtm.hour = tm->tm_hour;
mtm.minute = tm->tm_min;
mtm.second = tm->tm_sec;
mtm.neg = 0;
mtm.second_part = 0;
mtm.time_type = MYSQL_TIMESTAMP_DATETIME;
bind[0].buffer_type = MYSQL_TYPE_TIMESTAMP;
bind[0].buffer = (char *)&mtm;
bind[0].is_null = (my_bool *)0;
bind[0].buffer_length = sizeof(MYSQL_TIME);
} else {
bind[0].buffer_type = MYSQL_TYPE_LONG;
bind[0].buffer = (char *)&w1->logtime;
bind[0].buffer_length = sizeof(w1->logtime);
bind[0].is_null = (my_bool *)0;
}
bind[1].buffer_type = MYSQL_TYPE_VAR_STRING;
bind[1].buffer = devs->s[j].abbrv;
bind[1].is_null = (my_bool *)0;
bind[1].buffer_length = strlen(bind[1].buffer);
bind[2].buffer_type = MYSQL_TYPE_DOUBLE;
bind[2].buffer = (char *)&devs->s[j].value;
bind[2].is_null = (my_bool *)0;
bind[2].buffer_length = 0;
if (mysql_stmt_bind_param(stmt, bind)) {
fputs("bad bind\n", stderr);
}
if (mysql_stmt_execute(stmt)) {
fprintf(stderr, "execute: %s\n", mysql_error(conn));
fprintf(stderr, "timestamp = %d\n", w1->timestamp);
fprintf(stderr, "logtime = %ld\n", w1->logtime);
if (tm != NULL) {
char tval[64];
strftime(tval, sizeof(tval), "'%F %T'", tm);
fprintf(stderr, "timestamp %s %d\n", tval, w1->force_utc);
}
}
#else
char *q=NULL;
char tval[64];
if (w1->timestamp) {
struct tm *tm;
tm = (w1->force_utc) ? gmtime(&w1->logtime) : localtime(&w1->logtime);
strftime(tval, sizeof(tval), "'%F %T'", tm);
// printf("timestamp %s %d\n", tval, strlen(tval1));
} else {
snprintf(tval, sizeof(tval), "%ld", w1->logtime);
// printf("time_t %s\n", tval);
}
int ntmp = asprintf(&q, "INSERT into readings(date,name,value) VALUES(%s,'%s',%g)", tval, devs->s[j].abbrv, (double)devs->s[j].value);
if (ntmp != -1) {
if (w1->verbose)
printf("SQL:%s\n", q);
if (0 != mysql_real_query(conn, q, strlen(q))) {
const char *mse;
mse = mysql_error(conn);
if (mse) {
syslog(LOG_ERR, "MySQL error %s", mse);
if (w1->verbose)
fprintf(stderr, "Err:%s\n", mse);
}
}
}
free(q);
#endif
}
}
}
}
#if MYSQL_VERSION_ID > W1MYSQL_MINVERS
mysql_commit(conn);
#else
mysql_real_query(conn, "COMMIT", sizeof("COMMIT") - 1);
#endif
}
w1retap/src/odbc/ 0000775 0000000 0000000 00000000000 14464462352 0014151 5 ustar 00root root 0000000 0000000 w1retap/src/odbc/meson.build 0000664 0000000 0000000 00000000701 14464462352 0016311 0 ustar 00root root 0000000 0000000 w1odbc_src = 'w1odbc.c'
w1odbc = shared_module('w1odbc',
w1odbc_src,
c_args: ['-D_GNU_SOURCE' ],
include_directories : configuration_inc,
dependencies: [
have_odbc,
wdeps
],
install_dir : pkglibdir,
install : true
)
w1retap/src/odbc/w1odbc.c 0000664 0000000 0000000 00000021170 14464462352 0015475 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "w1retap.h"
#include
#include
void w1_init(w1_devlist_t *w1, char *params) {
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret;
SQLSMALLINT columns;
const char *sql = "select * from w1sensors order by device";
SQLLEN rows = 0;
w1_device_t *devs = NULL;
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
ret = SQLDriverConnect(dbc, NULL, (unsigned char *)params, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)) {
char cnam[256];
SQLSMALLINT lcnam;
int i;
char **flds, **f;
int id = -1, it = -1;
int nx = 0, ni = 0, nn = 0;
SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
SQLExecDirect(stmt, (unsigned char *)sql, SQL_NTS);
SQLNumResultCols(stmt, &columns);
SQLRowCount(stmt, &rows);
devs = malloc(sizeof(w1_device_t) * rows);
memset(devs, 0, sizeof(w1_device_t) * rows);
flds = malloc((columns * sizeof(char *)));
for (f = flds, i = 0; i < columns; i++, f++) {
SQLDescribeCol(stmt, i + 1, (SQLCHAR *)cnam, sizeof(cnam), &lcnam, NULL, NULL, NULL, NULL);
*f = strdup(cnam);
if (strcmp(cnam, "device") == 0) {
id = i;
} else if (strcmp(cnam, "type") == 0) {
it = i;
}
}
while (SQL_SUCCEEDED(ret = SQLFetch(stmt))) {
int i;
char device[32] = {0};
char type[32] = {0};
SQLLEN indicator;
SQLGetData(stmt, id + 1, SQL_C_CHAR, device, sizeof(device), &indicator);
SQLGetData(stmt, it + 1, SQL_C_CHAR, type, sizeof(type), &indicator);
nn = w1_get_device_index(devs, ni, device, type);
if (nn == -1) {
nx = ni;
ni++;
} else {
nx = nn;
}
for (i = 0; i < columns; i++) {
char buf[512];
ret = SQLGetData(stmt, i + 1, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)) {
char *sv;
if (indicator == SQL_NULL_DATA) {
sv = NULL;
} else {
sv = strdup(buf);
}
if (sv)
w1_set_device_data(devs + nx, flds[i], sv);
}
}
w1_enumdevs(devs + nx);
}
w1->numdev = ni;
w1->devs = devs;
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
for (f = flds, i = 0; i < columns; i++, f++) {
free(*f);
}
free(flds);
SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
ret = SQLExecDirect(stmt, (unsigned char *)"select name,value,rmin,rmax from ratelimit", SQL_NTS);
SQLNumResultCols(stmt, &columns);
SQLRowCount(stmt, &rows);
while (SQL_SUCCEEDED(ret = SQLFetch(stmt))) {
SQLLEN indicator;
char buf[512];
char *s;
short flags = 0;
float roc = 0, rmin = 0, rmax = 0;
ret = SQLGetData(stmt, 1, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)) {
if (indicator == SQL_NULL_DATA) {
s = NULL;
} else {
s = strdup(buf);
ret = SQLGetData(stmt, 2, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)) {
if (indicator != SQL_NULL_DATA) {
roc = strtof(buf, NULL);
flags |= W1_ROC;
}
}
ret = SQLGetData(stmt, 3, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)) {
if (indicator != SQL_NULL_DATA) {
rmin = strtof(buf, NULL);
flags |= W1_RMIN;
}
}
ret = SQLGetData(stmt, 4, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)) {
if (indicator != SQL_NULL_DATA) {
rmax = strtof(buf, NULL);
flags |= W1_RMAX;
}
}
if (flags) {
w1_sensor_t *sensor;
if (NULL != (sensor = w1_find_sensor(w1, (const char *)s))) {
sensor->flags = flags;
if (flags & W1_ROC)
sensor->roc = roc;
if (flags & W1_RMIN)
sensor->rmin = rmin;
if (flags & W1_RMAX)
sensor->rmax = rmax;
}
}
free(s);
}
}
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
}
static SQLHENV env;
static SQLHDBC dbc;
static SQLHSTMT stmt;
void w1_cleanup(void) {
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
dbc = env = stmt = NULL;
}
void w1_logger(w1_devlist_t *w1, char *params) {
w1_device_t *devs = NULL;
int i = 0;
if (env == NULL) {
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
SQLDriverConnect(dbc, NULL, (unsigned char *)params, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
SQLPrepare(stmt, (unsigned char *)"insert into readings(date,name,value) values (?,?,?)", SQL_NTS);
}
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) {
if (devs->init) {
int j;
for (j = 0; j < devs->ns; j++) {
if (devs->s[j].valid) {
SQLLEN psz;
SQL_TIMESTAMP_STRUCT sqlts;
SQLSMALLINT ValueType;
SQLSMALLINT ParameterType;
SQLPOINTER ParameterValuePtr;
if (w1->timestamp) {
struct tm *tm = localtime(&w1->logtime);
sqlts.year = tm->tm_year + 1900;
sqlts.month = tm->tm_mon + 1;
sqlts.day = tm->tm_mday;
sqlts.hour = tm->tm_hour;
sqlts.minute = tm->tm_min;
sqlts.second = tm->tm_sec;
sqlts.fraction = 0;
ValueType = SQL_C_TIMESTAMP;
ParameterType = SQL_TIMESTAMP;
ParameterValuePtr = &sqlts;
psz = sizeof(sqlts);
} else {
ValueType = SQL_C_LONG;
ParameterType = SQL_INTEGER;
ParameterValuePtr = &w1->logtime;
psz = sizeof(&w1->logtime);
}
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, ValueType, ParameterType, 0, 0, ParameterValuePtr, psz, &psz);
psz = strlen(devs->s[j].abbrv);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 0, devs->s[j].abbrv, psz, &psz);
psz = sizeof(float);
SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 0, 0, &devs->s[j].value, psz, &psz);
SQLExecute(stmt);
}
}
}
}
}
#if defined(TESTBIN)
int main() {
w1_devlist_t w = {0}, *w1;
int n;
w1 = &w;
w1_init(w1, "DSN=w1retap");
for (n = 0; n < w1->numdev; n++) {
fprintf(stderr, "%s %s\n", w1->devs[n].serial, w1->devs[n].devtype);
fprintf(stderr, "\t0: %s %s\n", w1->devs[n].s[0].abbrv, w1->devs[n].s[0].name);
fprintf(stderr, "\t1: %s %s\n", w1->devs[n].s[1].abbrv, w1->devs[n].s[1].name);
}
w1->logtime = time(0);
w1->devs[0].init = 1;
w1->devs[0].s[0].valid = 1;
w1->devs[0].s[0].value = 22.22;
w1->devs[1].init = 1;
w1->devs[1].s[0].valid = 1;
w1->devs[1].s[0].value = 69;
w1->devs[1].s[1].valid = 99.0;
w1->devs[1].s[1].value = 18.88;
w1->devs[2].init = 1;
w1->devs[2].s[0].valid = 1;
w1->devs[2].s[0].value = 1001.45;
w1_logger(w1, "DSN=w1retap");
sleep(5);
w1->logtime = time(0);
w1->devs[0].init = 1;
w1->devs[0].s[0].valid = 1;
w1->devs[0].s[0].value = 25.77;
w1->devs[1].init = 1;
w1->devs[1].s[0].valid = 1;
w1->devs[1].s[0].value = 66;
w1->devs[1].s[1].valid = 1;
w1->devs[1].s[1].value = 12.565;
w1->devs[2].init = 0;
w1_logger(w1, "DSN=w1retap");
return 0;
}
#endif
w1retap/src/pgsql/ 0000775 0000000 0000000 00000000000 14464462352 0014370 5 ustar 00root root 0000000 0000000 w1retap/src/pgsql/meson.build 0000664 0000000 0000000 00000000730 14464462352 0016532 0 ustar 00root root 0000000 0000000 w1pgsql_src = 'w1pgsql.c'
w1pgsql = shared_module('w1pgsql',
w1pgsql_src,
c_args: ['-D_GNU_SOURCE' ],
include_directories : configuration_inc,
dependencies: [
have_pq,
wdeps
],
install_dir : pkglibdir,
install : true
)
w1retap/src/pgsql/mktest.sh 0000775 0000000 0000000 00000000425 14464462352 0016237 0 ustar 00root root 0000000 0000000 #!/bin/bash
clang -O2 -g -o pgtest -D PGV=8 -D_GNU_SOURCE=1 -D TESTBIN -I ../libusblinux300/ -I../ \
-I $(pg_config --includedir) \
$(pkg-config gmodule-2.0 --cflags) \
w1pgsql.c ../w1util.c ../w1conf.c -lpq $(pkg-config gmodule-no-export-2.0 --libs)
rm -f w1pgsql.o
w1retap/src/pgsql/w1pgsql.c 0000664 0000000 0000000 00000026250 14464462352 0016137 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "libpq-fe.h"
#include "w1retap.h"
#define VALTPQRY \
"SELECT format_type(a.atttypid, a.atttypmod) FROM pg_class c, pg_attribute a WHERE c.relname = 'readings' AND a.attrelid = " \
"c.oid and a.attname in ('date','wxdata','value')"
#define SENSQRY "select * from w1sensors order by device"
#define RATEQRY "select name,value,rmin,rmax from ratelimit"
static short json = 0;
static short tstamp = 0;
static PGconn *w1_opendb(char *params) {
PGconn *mydb = NULL;
PGresult *res;
mydb = PQconnectdb(params);
if (PQstatus(mydb) != CONNECTION_OK) {
PQfinish(mydb);
mydb = NULL;
} else {
res = PQexec(mydb, VALTPQRY);
if (res && PQresultStatus(res) == PGRES_TUPLES_OK) {
char *s = NULL;
int nn = PQntuples(res);
if (nn > 0) {
int i;
for (i = 0; i < nn; i++) {
s = PQgetvalue(res, i, 0);
if (s && *s) {
if ((0 == strncmp(s, "json", sizeof("json") - 1)) || (0 == strncmp(s, "text", sizeof("text") - 1))) {
json = 1;
} else if (0 == strncmp(s, "timestamp", sizeof("timestamp") - 1)) {
tstamp = 1;
}
}
}
}
}
#ifdef TESTBIN
fprintf(stderr, "json %d, tstamp %d\n", json, tstamp);
#endif
if (res)
PQclear(res);
}
return mydb;
}
void w1_init(w1_devlist_t *w1, char *dbnam) {
w1_device_t *devs = NULL;
PGconn *idb;
PGresult *res;
int n = 0, ni = 0;
idb = w1_opendb(dbnam);
if (idb) {
res = PQexec(idb, SENSQRY);
if (res && PQresultStatus(res) == PGRES_TUPLES_OK) {
int nr = PQntuples(res);
int nfields;
int j;
int nx = 0;
int nn = 0;
int id = -1;
int it = -1;
devs = malloc(sizeof(w1_device_t) * nr);
memset(devs, 0, sizeof(w1_device_t) * nr);
nfields = PQnfields(res);
for (j = 0; j < nfields; j++) {
char *fnam = PQfname(res, j);
if (strcmp(fnam, "device") == 0) {
id = j;
} else if (strcmp(fnam, "type") == 0) {
it = j;
}
if (it != -1 && id != -1)
break;
}
for (n = 0; n < nr; n++) {
nn = w1_get_device_index(devs, ni, PQgetvalue(res, n, id), PQgetvalue(res, n, it));
if (nn == -1) {
nx = ni;
ni++;
} else {
nx = nn;
}
for (j = 0; j < nfields; j++) {
char *fnam = PQfname(res, j);
char *s = PQgetvalue(res, n, j);
char *sv = (s && *s) ? strdup(s) : NULL;
if (sv)
w1_set_device_data(devs + nx, fnam, sv);
}
w1_enumdevs(devs + nx);
}
}
w1->numdev = ni;
w1->devs = devs;
if (res)
PQclear(res);
res = PQexec(idb, RATEQRY);
if (res && PQresultStatus(res) == PGRES_TUPLES_OK) {
float roc = 0, rmin = 0, rmax = 0;
int nn = PQntuples(res);
for (n = 0; n < nn; n++) {
char *s, *sv;
short flags = 0;
s = PQgetvalue(res, n, 0);
if (s && *s) {
sv = PQgetvalue(res, n, 1);
if (sv && *sv) {
roc = strtod(sv, NULL);
flags |= W1_ROC;
}
sv = PQgetvalue(res, n, 2);
if (sv && *sv) {
rmin = strtod(sv, NULL);
flags |= W1_RMIN;
}
sv = PQgetvalue(res, n, 3);
if (sv && *sv) {
rmax = strtod(sv, NULL);
flags |= W1_RMAX;
}
if (flags) {
w1_sensor_t *sensor;
if (NULL != (sensor = w1_find_sensor(w1, (const char *)s))) {
sensor->flags = flags;
if (flags & W1_ROC)
sensor->roc = roc;
if (flags & W1_RMIN)
sensor->rmin = rmin;
if (flags & W1_RMAX)
sensor->rmax = rmax;
}
}
}
}
}
if (res)
PQclear(res);
PQfinish(idb);
}
}
static PGconn *db;
static char *stmt;
static char *stml;
static int retry;
static void db_syslog(char *p) {
char *q = NULL, *qq;
int qa = 0;
if (p) {
if ((q = strdup(p))) {
qa = 1;
if ((qq = strchr(q, '\n'))) {
*qq = 0;
}
}
}
if (q == NULL) {
q = "retry";
}
if (q) {
syslog(LOG_ERR, "psql: %s", q);
}
if (qa)
free(q);
}
static void db_status(char *dbnam) {
if (db == NULL) {
db = w1_opendb(dbnam);
} else if (PQstatus(db) == CONNECTION_BAD) {
PQreset(db);
stmt = NULL;
stml = NULL;
retry++;
} else {
retry = 0;
}
if (db && (retry % 10) == 1) {
db_syslog(PQerrorMessage(db));
}
}
void w1_cleanup(void) {
if (db) {
stmt = NULL;
stml = NULL;
PQfinish(db);
db = NULL;
retry = 0;
}
}
void handle_result(PGresult *res) {
if (res) {
ExecStatusType status = PQresultStatus(res);
if ((status == PGRES_NONFATAL_ERROR) || (status == PGRES_FATAL_ERROR)) {
#if defined(TESTBIN)
puts(PQresultErrorMessage(res));
#else
syslog(LOG_ERR, "psql: %s", PQresultErrorMessage(res));
#endif
}
PQclear(res);
}
}
void w1_logger(w1_devlist_t *w1, char *dbnam) {
int i;
w1_device_t *devs;
PGresult *res = NULL;
if (access("/tmp/.w1retap.lock", F_OK) == 0) {
return;
}
db_status(dbnam);
if (db) {
if (stmt == NULL) {
stmt = "insrt";
if (json == 1) {
res = PQprepare(db, stmt, "insert into readings (date,wxdata) values ($1,$2)", 0, NULL);
} else {
res = PQprepare(db, stmt, "insert into readings (date,name,value) values ($1,$2,$3)", 0, NULL);
}
if (res)
PQclear(res);
}
res = PQexec(db, "begin");
handle_result(res);
char *jstr = NULL;
char *jptr = NULL;
if (json) {
jstr = jptr = malloc(4096);
jptr = stpcpy(jptr, "{");
}
char tval[64];
if (tstamp) {
struct tm *tm;
tm = (w1->force_utc) ? gmtime(&w1->logtime) : localtime(&w1->logtime);
strftime(tval, sizeof(tval), "%F %T%z", tm);
} else {
snprintf(tval, sizeof(tval), "%ld", w1->logtime);
}
int nlog = 0;
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) // for each device
{
if (devs->init) // if the device is initialised
{
int j;
int n;
for (j = 0; j < devs->ns; j++) // for each sensor
{
if (devs->s[j].valid) // if there's a valid reading
{
nlog++;
char *rval = NULL;
if (devs->stype == W1_COUNTER || devs->stype == W1_WINDVANE)
n = asprintf(&rval, "%.0f", devs->s[j].value); // do not include any decimal places for integer values
else
n = asprintf(&rval, "%f", devs->s[j].value); // include default 6 decimal places
if (json) {
n = sprintf(jptr, "\"%s\":%s,", devs->s[j].abbrv, rval);
jptr += n;
} else {
if (devs->s[j].abbrv[0] == '>') {
// store sensor value in a separate named table
char *query;
n = asprintf(&query, "INSERT INTO %s (date, value) VALUES ('%s', '%s')", &devs->s[j].abbrv[1], tval, rval);
res = PQexec(db, query);
handle_result(res);
free(query);
} else {
// store sensor value in the 'readings' table
const char *pvals[3];
pvals[0] = tval;
pvals[1] = devs->s[j].abbrv;
pvals[2] = rval;
res = PQexecPrepared(db, stmt, 3, pvals, NULL, NULL, 0);
handle_result(res);
}
}
free(rval);
}
}
}
}
if (json) {
if (nlog) {
strcpy(jptr - 1, "}");
#if defined(TESTBIN)
fprintf(stderr, "%s\n", jstr);
#endif
const char *pvals[2];
pvals[0] = tval;
pvals[1] = jstr;
res = PQexecPrepared(db, stmt, 2, pvals, NULL, NULL, 0);
handle_result(res);
}
free(jstr);
}
res = PQexec(db, "commit");
handle_result(res);
}
}
void w1_report(w1_devlist_t *w1, char *dbnam) {
PGresult *res;
if (w1->lastmsg) {
db_status(dbnam);
if (db) {
if (stml == NULL) {
stml = "insrl";
res = PQprepare(db, stml, "insert into replog(date,message) values ($1,$2)", 0, NULL);
if (res)
PQclear(res);
}
res = PQexec(db, "begin");
if (res)
PQclear(res);
{
const char *pvals[2];
char tstr[64];
logtimes(w1, w1->logtime, tstr);
pvals[0] = tstr;
pvals[1] = w1->lastmsg;
res = PQexecPrepared(db, stml, 2, pvals, NULL, NULL, 0);
if (res)
PQclear(res);
}
res = PQexec(db, "commit");
if (res)
PQclear(res);
}
}
}
#if defined(TESTBIN)
int main(int argc, char **argv) {
char *auth = "dbname=w1retap user=postgres";
w1_devlist_t w = {0}, *w1;
if (argc == 2) {
auth = argv[1];
}
w1 = &w;
char *p = NULL;
if ((p = getenv("W1RCFILE"))) {
w1->rcfile = strdup(p);
}
read_config(w1);
w1_init(w1, auth);
for (int n = 0; n < w1->numdev; n++) {
fprintf(stderr, "%s %s\n", w1->devs[n].serial, w1->devs[n].devtype);
fprintf(stderr, "\t0: %s %s\n", w1->devs[n].s[0].abbrv, w1->devs[n].s[0].name);
fprintf(stderr, "\t1: %s %s\n", w1->devs[n].s[1].abbrv, w1->devs[n].s[1].name);
}
w1->logtime = time(NULL);
w1->timestamp = 1;
if (w1->numdev > 0) {
w1->logtime = time(0);
w1->devs[0].init = 1;
w1->devs[0].s[0].valid = 1;
w1->devs[0].s[0].value = 22.22;
w1->devs[1].init = 1;
w1->devs[1].s[0].valid = 1;
w1->devs[1].s[0].value = 69;
w1->devs[1].s[1].valid = 99.0;
w1->devs[1].s[1].value = 18.88;
w1->devs[2].init = 1;
w1->devs[2].s[0].valid = 1;
w1->devs[2].s[0].value = 1001.45;
w1_logger(w1, argv[1]);
sleep(5);
w1->logtime = time(0);
w1->devs[0].init = 1;
w1->devs[0].s[0].valid = 1;
w1->devs[0].s[0].value = 25.77;
w1->devs[1].init = 1;
w1->devs[1].s[0].valid = 1;
w1->devs[1].s[0].value = 66;
w1->devs[1].s[1].valid = 1;
w1->devs[1].s[1].value = 12.565;
w1->devs[2].init = 0;
}
w1_logger(w1, auth);
return 0;
}
#endif
w1retap/src/sensors.sql 0000664 0000000 0000000 00000001350 14464462352 0015456 0 ustar 00root root 0000000 0000000 CREATE TABLE ratelimit (
name text,
value double precision,
rmax double precision,
rmin double precision
);
CREATE TABLE readings (
date integer,
name text,
value double precision
);
CREATE TABLE replog (
date timestamp with time zone,
message text
);
CREATE TABLE station (
name text,
stnlat double precision,
stnlong double precision,
altitude real,
location text,
software text,
url text,
wu_user text,
wu_pass text,
rfact double precision,
cwop_user text,
cwop_pass text
);
CREATE TABLE w1sensors (
device text,
type text,
abbrv1 text,
name1 text,
units1 text,
abbrv2 text,
name2 text,
units2 text,
params text
);
w1retap/src/sqlite/ 0000775 0000000 0000000 00000000000 14464462352 0014543 5 ustar 00root root 0000000 0000000 w1retap/src/sqlite/meson.build 0000664 0000000 0000000 00000000741 14464462352 0016707 0 ustar 00root root 0000000 0000000 w1sqlite_src = 'w1sqlite.c'
w1sqlite = shared_module('w1sqlite',
w1sqlite_src,
c_args: ['-D_GNU_SOURCE' ],
include_directories : configuration_inc,
dependencies: [
have_sqlite,
wdeps
],
install_dir : pkglibdir,
install : true
)
w1retap/src/sqlite/w1sqlite.c 0000664 0000000 0000000 00000024736 14464462352 0016474 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "w1retap.h"
static short json;
static short tstamp;
static sqlite3 *w1_opendb(char *dbname) {
sqlite3 *mydb = NULL;
if (sqlite3_open(dbname, &mydb) == SQLITE_OK) {
const char *dbuf;
int sres;
sqlite3_busy_timeout(mydb, 5000);
if (SQLITE_OK == sqlite3_table_column_metadata(mydb, NULL, "readings", "date", &dbuf, NULL, NULL, NULL, NULL)) {
#if defined(TESTBIN)
fprintf(stderr, "t = %s\n", dbuf);
#endif
if (0 == strncmp(dbuf, "timestamp", sizeof("timestamp") - 1)) {
tstamp = 1;
}
}
if (SQLITE_OK == (sres = sqlite3_table_column_metadata(mydb, NULL, "readings", "wxdata", &dbuf, NULL, NULL, NULL, NULL))) {
#if defined(TESTBIN)
fprintf(stderr, "v1 = %s\n", dbuf);
#endif
if (0 == strncmp(dbuf, "text", sizeof("text") - 1) || 0 == strncmp(dbuf, "varchar", sizeof("varchar") - 1) ||
0 == strncmp(dbuf, "char", sizeof("char") - 1))
json = 1;
}
#if defined(TESTBIN)
else {
fprintf(stderr, "**bad res = %d\n", sres);
}
#endif
#if defined(TESTBIN)
fprintf(stderr, "j=%d t=%d\n", json, tstamp);
#endif
} else {
perror(sqlite3_errmsg(mydb));
}
return mydb;
}
#define GETVALUE(__p0, __p1) \
if (nc > __p0) \
__p1 = (rt[offset + __p0]) ? strdup(rt[offset + __p0]) : NULL
void w1_init(w1_devlist_t *w1, char *dbnam) {
w1_device_t *devs = NULL;
char *sql = "select * from w1sensors order by device";
// device,type,abbrv1,name1,units1,abbrv2,name2,units2
sqlite3 *db;
char *err;
int n = 0, nr = 0, nc;
char **rt;
int nx = 0, ni = 0;
db = w1_opendb(dbnam);
if (sqlite3_get_table(db, sql, &rt, &nr, &nc, &err) == SQLITE_OK) {
if (nr > 0 && nc > 0) {
int k;
int nn = 0;
int id = -1;
int it = -1;
devs = malloc(sizeof(w1_device_t) * nr);
memset(devs, 0, sizeof(w1_device_t) * nr);
for (k = 0; k < nc; k++) {
if (strcmp(rt[k], "device") == 0) {
id = k;
} else if (strcmp(rt[k], "type") == 0) {
it = k;
}
if (it != -1 && id != -1)
break;
}
for (n = 0; n < nr; n++) {
nn = w1_get_device_index(devs, ni, rt[(n + 1) * nc + id], rt[(n + 1) * nc + it]);
// fprintf(stderr, "Search for %s %s %d\n", rt[(n+1)*nc + id],rt[(n+1)*nc + it] ,nn);
if (nn == -1) {
nx = ni;
ni++;
} else {
nx = nn;
}
// fprintf(stderr, "Device %d\n", nx);
for (k = 0; k < nc; k++) {
char *fnam = rt[k];
char *s = rt[(n + 1) * nc + k];
char *sv = (s && *s) ? strdup(s) : NULL;
// fprintf(stderr,"set entry %d:%d %s %s\n", k, (devs+nx)->ns, fnam,sv);
if (fnam && sv)
w1_set_device_data(devs + nx, fnam, sv);
}
w1_enumdevs(devs + nx);
}
sqlite3_free_table(rt);
}
} else {
if (err) {
fprintf(stderr, "ERR %s\n", err);
sqlite3_free(err);
}
}
w1->numdev = ni;
w1->devs = devs;
// fprintf(stderr, "read = %d, found = %d\n", ni, nr);
if (sqlite3_get_table(db, "select name,value,rmin,rmax from ratelimit", &rt, &nr, &nc, &err) == SQLITE_OK) {
float roc = 0, rmin = 0, rmax = 0;
if (nr > 0 && nc > 0) {
int offset = 0;
for (n = 0; n < nr; n++) {
char *s = NULL, *sv = NULL;
short flags = 0;
offset += nc;
GETVALUE(0, s);
if (s && *s) {
GETVALUE(1, sv);
if (sv) {
if (*sv) {
roc = strtof(sv, NULL);
flags |= W1_ROC;
}
if (sv)
free(sv);
}
GETVALUE(2, sv);
if (sv) {
if (*sv) {
rmin = strtof(sv, NULL);
flags |= W1_RMIN;
}
if (sv)
free(sv);
}
GETVALUE(3, sv);
if (sv) {
if (*sv) {
rmax = strtof(sv, NULL);
flags |= W1_RMAX;
}
if (sv)
free(sv);
}
if (flags) {
w1_sensor_t *sensor;
if (NULL != (sensor = w1_find_sensor(w1, (const char *)s))) {
sensor->flags = flags;
if (flags & W1_ROC)
sensor->roc = roc;
if (flags & W1_RMIN)
sensor->rmin = rmin;
if (flags & W1_RMAX)
sensor->rmax = rmax;
}
}
}
if (s)
free(s);
}
sqlite3_free_table(rt);
}
} else {
if (err) {
sqlite3_free(err);
}
}
sqlite3_close(db);
}
static sqlite3 *db;
static sqlite3_stmt *stmt;
static sqlite3_stmt *stml;
void w1_cleanup(void) {
if (db) {
if (stmt) {
sqlite3_finalize(stmt);
stmt = NULL;
}
if (stml) {
sqlite3_finalize(stml);
stmt = NULL;
}
sqlite3_close(db);
db = NULL;
}
}
void w1_logger(w1_devlist_t *w1, char *dbnam) {
int i;
w1_device_t *devs;
if (access("/tmp/.w1retap.lock", F_OK) == 0) {
return;
}
if (db == NULL) {
db = w1_opendb(dbnam);
}
if (stmt == NULL) {
char *s;
if (json) {
s = "insert into readings(date,wxdata) values (?,?)";
} else {
s = "insert into readings(date,name,value) values (?,?,?)";
}
sqlite3_prepare_v2(db, s, -1, &stmt, NULL);
}
sqlite3_exec(db, "begin", NULL, NULL, NULL);
char *jstr = NULL;
char *jptr = NULL;
char tval[64];
int nlog = 0;
if (json) {
jstr = jptr = malloc(4096);
jptr = stpcpy(jptr, "{");
}
if (tstamp) {
struct tm *tm;
tm = (w1->force_utc) ? gmtime(&w1->logtime) : localtime(&w1->logtime);
strftime(tval, sizeof(tval), "%F %T%z", tm);
}
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) {
if (devs->init) {
int j;
int n;
for (j = 0; j < devs->ns; j++) {
if (devs->s[j].valid) {
nlog++;
if (json) {
char *rval = NULL;
if (devs->stype == W1_COUNTER || devs->stype == W1_WINDVANE)
n = asprintf(&rval, "%.0f", devs->s[j].value);
else
n = asprintf(&rval, "%f", devs->s[j].value);
n = sprintf(jptr, "\"%s\":%s,", devs->s[j].abbrv, rval);
jptr += n;
free(rval);
} else {
if (tstamp) {
sqlite3_bind_text(stmt, 1, tval, -1, SQLITE_STATIC);
} else {
sqlite3_bind_int(stmt, 1, w1->logtime);
}
sqlite3_bind_text(stmt, 2, devs->s[j].abbrv, -1, SQLITE_STATIC);
sqlite3_bind_double(stmt, 3, (double)devs->s[j].value);
sqlite3_step(stmt);
sqlite3_reset(stmt);
}
}
}
}
}
// fprintf(stderr, "%s json %d timestamp %d nlog %d\n", tval, json, tstamp, nlog);
if (json) {
if (nlog) {
strcpy(jptr - 1, "}");
#if defined(TESTBIN)
fprintf(stderr, "%s\n", jstr);
#endif
if (tstamp) {
sqlite3_bind_text(stmt, 1, tval, -1, SQLITE_STATIC);
} else {
sqlite3_bind_int(stmt, 1, w1->logtime);
}
sqlite3_bind_text(stmt, 2, jstr, -1, NULL);
sqlite3_step(stmt);
}
sqlite3_reset(stmt);
}
sqlite3_exec(db, "commit", NULL, NULL, NULL);
}
void w1_report(w1_devlist_t *w1, char *dbnam) {
if (w1->lastmsg) {
if (db == NULL) {
db = w1_opendb(dbnam);
}
if (stml == NULL) {
const char *tl;
static char s[] = "insert into replog(date,message) values (?,?)";
sqlite3_prepare(db, s, sizeof(s) - 1, &stml, &tl);
}
sqlite3_exec(db, "begin", NULL, NULL, NULL);
{
struct tm *tm;
char tval[64];
tm = localtime(&w1->logtime);
strftime(tval, sizeof(tval), "%F %T%z", tm);
sqlite3_bind_text(stml, 1, tval, -1, SQLITE_STATIC);
}
sqlite3_bind_text(stml, 2, w1->lastmsg, -1, SQLITE_STATIC);
sqlite3_step(stml);
sqlite3_reset(stml);
sqlite3_exec(db, "commit", NULL, NULL, NULL);
}
}
#if defined(TESTBIN)
int main(int argc, char **argv) {
char *dbname = NULL;
w1_devlist_t w = {0}, *w1;
if (argc == 2) {
dbname = argv[1];
}
w1 = &w;
char *p = NULL;
if ((p = getenv("W1RCFILE"))) {
w1->rcfile = strdup(p);
}
read_config(w1);
w1_init(w1, dbname);
for (int n = 0; n < w1->numdev; n++) {
fprintf(stderr, "%s %s\n", w1->devs[n].serial, w1->devs[n].devtype);
fprintf(stderr, "\t0: %s %s\n", w1->devs[n].s[0].abbrv, w1->devs[n].s[0].name);
fprintf(stderr, "\t1: %s %s\n", w1->devs[n].s[1].abbrv, w1->devs[n].s[1].name);
}
w1->logtime = time(NULL);
w1->timestamp = 1;
if (w1->numdev > 0) {
w1->logtime = time(0);
w1->devs[0].init = 1;
w1->devs[0].s[0].valid = 1;
w1->devs[0].s[0].value = 22.22;
w1->devs[1].init = 1;
w1->devs[1].s[0].valid = 1;
w1->devs[1].s[0].value = 69;
w1->devs[1].s[1].valid = 99.0;
w1->devs[1].s[1].value = 18.88;
w1->devs[2].init = 1;
w1->devs[2].s[0].valid = 1;
w1->devs[2].s[0].value = 1001.45;
w1_logger(w1, dbname);
sleep(5);
w1->logtime = time(0);
w1->devs[0].init = 1;
w1->devs[0].s[0].valid = 1;
w1->devs[0].s[0].value = 25.77;
w1->devs[1].init = 1;
w1->devs[1].s[0].valid = 1;
w1->devs[1].s[0].value = 66;
w1->devs[1].s[1].valid = 1;
w1->devs[1].s[1].value = 12.565;
w1->devs[2].init = 0;
}
w1_logger(w1, dbname);
return 0;
}
#endif
w1retap/src/testrate.c 0000664 0000000 0000000 00000012324 14464462352 0015243 0 ustar 00root root 0000000 0000000 #define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#define W1_ROC (1 << 0)
#define W1_RMIN (1 << 1)
#define W1_RMAX (1 << 2)
typedef struct {
char *abbrv;
char *name;
char *units;
double value;
short valid;
short flags;
double rmin;
double rmax;
double roc;
double lval;
time_t ltime;
short reason;
} w1_sensor_t;
typedef struct w1_devlist {
time_t logtime;
short allow_escape;
} w1_devlist_t;
static void w1_replog(w1_devlist_t *w1, const char *fmt, ...) {
va_list va;
char *p;
int nc;
va_start(va, fmt);
if ((nc = vasprintf(&p, fmt, va)) != -1) {
fputs(">>>>> ", stdout);
fputs(p, stdout);
fputc('\n', stdout);
free(p);
}
}
static int w1_validate(w1_devlist_t *w1, w1_sensor_t *s) {
static char *restxt[] = {"OK", "RATE", "MIN", "undef", "MAX"};
int chk = 0;
float act = s->value;
float rate = 0;
s->valid = 1;
if ((s->flags & W1_RMIN) && (s->value < s->rmin)) {
s->value = (s->ltime) ? s->lval : s->rmin;
chk = W1_RMIN;
}
if ((s->flags & W1_RMAX) && (s->value > s->rmax)) {
s->value = (s->ltime) ? s->lval : s->rmax;
chk = W1_RMAX;
}
if (chk == 0 && (s->flags & W1_ROC)) {
if (!(w1->allow_escape == 1 && (s->reason & (W1_RMIN | W1_RMAX)) != 0)) {
if (s->ltime > 0 && s->ltime != w1->logtime) {
rate = fabs(s->value - s->lval) * 60.0 / (w1->logtime - s->ltime);
if (rate > s->roc) {
s->value = s->lval;
chk = W1_ROC;
}
}
}
}
s->reason = chk;
if (chk == 0) {
s->ltime = w1->logtime;
s->lval = s->value;
} else {
w1_replog(w1,
"%s result=%.2f actual=%.2f rate=%.2f prev=%.2f "
"prevtime_t=%d logtime_t=%d reason=%s",
s->abbrv, s->value, act, rate, s->lval, s->ltime, w1->logtime, restxt[chk]);
}
return (int)s->valid;
}
#define STARTSECS 1256243520
int main(void) {
double d;
int n;
w1_devlist_t *w1, xw1 = {.logtime = 0, .allow_escape = 0};
// Minimum is 2
// Maximum is 100.04
// Rate is 7 / min
w1_sensor_t *s, sns = {.abbrv = "OHUM",
.name = "Humidity",
.units = "pct",
.value = -1,
.flags = (W1_ROC | W1_RMIN | W1_RMAX),
.rmin = 2,
.rmax = 100.04,
.roc = 7,
.lval = 0,
.ltime = 0};
s = &sns;
w1 = &xw1;
puts("Start value 0 => min (2)");
w1->logtime = STARTSECS;
puts("Start t0");
d = s->value = 0;
n = w1_validate(w1, s);
assert(s->value == 2.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 4, OK");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 4;
n = w1_validate(w1, s);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 1, use last good value (4)");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 1;
n = w1_validate(w1, s);
assert(s->value == 4.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 0, use last good value (4)");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 0;
n = w1_validate(w1, s);
assert(s->value == 4.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 5, use value (5)");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 5;
n = w1_validate(w1, s);
assert(s->value == 5.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 50, (rate violation) use last good value (5)");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 50;
n = w1_validate(w1, s);
assert(s->value == 5.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 98, OK (much later)");
w1->logtime += 120000;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 98;
n = w1_validate(w1, s);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 100, OK");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 100;
n = w1_validate(w1, s);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 100.5, use last good (100.0)");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 100.5;
n = w1_validate(w1, s);
assert(s->value == 100.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
puts("Value = 120, use last good (100.0)");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 120.0;
n = w1_validate(w1, s);
assert(s->value == 100.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
w1->allow_escape = 1;
puts("Value = 30, use value (even though rate violation)");
w1->logtime += 120;
printf("t0 + %d\n", (int)(w1->logtime - STARTSECS));
d = s->value = 30.0;
n = w1_validate(w1, s);
assert(s->value == 30.0);
printf("** %d read %.2f stored %.2f\n\n", n, d, s->value);
return 0;
}
w1retap/src/w1conf.c 0000664 0000000 0000000 00000007056 14464462352 0014613 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "w1retap.h"
void read_config(w1_devlist_t *w1) {
FILE *fp;
char buf[256];
if (w1->rcfile == NULL) {
w1->rcfile = w1_get_from_home(".config/w1retap/rc");
}
if (w1->rcfile && access(w1->rcfile, R_OK) != 0) {
free(w1->rcfile);
w1->rcfile = NULL;
}
if (w1->rcfile == NULL) {
w1->rcfile = strdup("/etc/default/w1retap");
}
fp = fopen(w1->rcfile, "r");
if (fp) {
while (fgets(buf, sizeof(buf), fp)) {
char lbuf[513];
if (1 == sscanf(buf, "device = %512[^\n]", lbuf)) {
w1->iface = g_strdup(lbuf);
}
// Oh what ugly webs we weave ....
#ifndef TESTBIN
else if (1 == sscanf(buf, "log = %512[^\n]", lbuf)) {
dll_parse(w1, 'l', lbuf);
} else if (1 == sscanf(buf, "init = %512[^\n]", lbuf)) {
dll_parse(w1, 'c', lbuf);
} else if (1 == sscanf(buf, "rep = %512[^\n]", lbuf)) {
dll_parse(w1, 'r', lbuf);
}
#endif
else if (1 == sscanf(buf, "pidfile = %512[^\n]", lbuf)) {
w1->pidfile = g_strdup(lbuf);
} else if (1 == sscanf(buf, "log_time_t = %512[^\n]", lbuf)) {
w1->log_timet = (lbuf[0] == 't' || lbuf[0] == 'T' || lbuf[0] == 'y' || lbuf[0] == 'Y' || lbuf[0] == '1');
} else if (1 == sscanf(buf, "allow_rate_escape = %512[^\n]", lbuf)) {
w1->allow_escape = (lbuf[0] == 't' || lbuf[0] == 'T' || lbuf[0] == 'y' || lbuf[0] == 'Y' || lbuf[0] == '1');
} else if (1 == sscanf(buf, "force_utc = %512[^\n]", lbuf)) {
w1->force_utc = (lbuf[0] == 't' || lbuf[0] == 'T' || lbuf[0] == 'y' || lbuf[0] == 'Y' || lbuf[0] == '1');
} else if (1 == sscanf(buf, "release_if = %512[^\n]", lbuf)) {
w1->release_me = (lbuf[0] == 't' || lbuf[0] == 'T' || lbuf[0] == 'y' || lbuf[0] == 'Y' || lbuf[0] == '1');
} else if (1 == sscanf(buf, "log_delimiter = %512[^\n]", lbuf)) {
if (*lbuf == '\\' && *(lbuf + 1) == 't')
w1->log_delim[0] = '\t';
else
w1->log_delim[0] = *lbuf;
} else if (1 == sscanf(buf, "pressure_reduction_temp = %512[^\n]", lbuf)) {
w1->pres_reduction_temp = malloc(sizeof(double));
*w1->pres_reduction_temp = strtod(lbuf, NULL);
} else {
(void)(sscanf(buf, "delay = %d", &w1->delay) || sscanf(buf, "demonise = %d", &w1->daemonise) ||
sscanf(buf, "altitude = %d", &w1->altitude) || sscanf(buf, "vane_offset = %d", &w1->vane_offset) ||
sscanf(buf, "timestamp = %d", &w1->timestamp) || sscanf(buf, "logtemp = %d", &w1->logtmp) ||
sscanf(buf, "temp_scan = %d", &w1->temp_scan));
}
}
fclose(fp);
} else
fprintf(stderr, "failed to read config\n");
}
w1retap/src/w1csv.c 0000664 0000000 0000000 00000003526 14464462352 0014457 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "w1retap.h"
void w1_logger(w1_devlist_t *w1, char *logfile) {
int i;
char timb[TBUF_SZ];
w1_device_t *devs;
FILE *lfp;
if (logfile == NULL) {
lfp = stdout;
setvbuf(lfp, (char *)NULL, _IOLBF, 0);
} else {
if (*logfile == '|') {
lfp = popen(logfile + 1, "w");
} else {
lfp = fopen(logfile, "a");
}
}
if (lfp == NULL) {
return;
}
logtimes(w1, w1->logtime, timb);
fprintf(lfp, "\"%s\"", timb);
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) {
if (devs->init) {
int j;
for (j = 0; j < devs->ns; j++) {
if (devs->s[j].valid) {
fprintf(lfp, ",\"%s\",%f,\"%s\"", devs->s[j].abbrv, devs->s[j].value, (devs->s[j].units) ? (devs->s[j].units) : "");
}
}
}
}
fputc('\n', lfp);
if (logfile) {
if (*logfile == '|') {
pclose(lfp);
} else {
fclose(lfp);
}
}
}
w1retap/src/w1file.c 0000664 0000000 0000000 00000007036 14464462352 0014603 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "w1retap.h"
void w1_init(w1_devlist_t *w1, char *fname) {
FILE *fp;
int n = 0, nn = 0;
w1_device_t *devs = NULL;
int alldev = 0;
short allocf = 0;
if (fname == NULL) {
fname = w1_get_from_home(".config/w1retap/sensors");
allocf = !!fname;
}
if ((fp = fopen(fname, "r"))) {
char line[256];
while (fgets(line, sizeof(line), fp)) {
int j;
char *s, *p;
if (isalnum(*line)) {
char *serno = NULL;
char *devtype = NULL;
if (NULL != (s = strchr(line, '\n'))) {
*s = 0;
}
for (j = 0, s = line; (p = strsep(&s, "|:")); j++) {
char *sv = (p && *p) ? strdup(p) : NULL;
switch (j) {
case 0:
serno = sv;
break;
case 1:
devtype = sv;
if ((nn = w1_get_device_index(devs, n, serno, devtype)) == -1) {
if (n == alldev) {
alldev += ALLOCDEV;
devs = realloc(devs, sizeof(w1_device_t) * alldev);
memset(devs + n, 0, sizeof(w1_device_t) * ALLOCDEV);
}
nn = n;
n++;
}
w1_set_device_data_index(devs + nn, 0, serno);
w1_set_device_data_index(devs + nn, 1, devtype);
w1_enumdevs(devs + nn);
break;
default:
w1_set_device_data_index(devs + nn, j, sv);
break;
}
}
}
}
fclose(fp);
if (allocf && fname)
free(fname);
} else {
exit(1);
}
w1->numdev = n;
w1->devs = devs;
}
void w1_logger(w1_devlist_t *w1, char *logfile) {
int i;
char timb[TBUF_SZ];
w1_device_t *devs;
FILE *lfp;
if (logfile == NULL) {
lfp = stdout;
setvbuf(lfp, (char *)NULL, _IOLBF, 0);
} else {
if (*logfile == '|') {
lfp = popen(logfile + 1, "w");
} else {
lfp = fopen(logfile, "a");
}
}
if (lfp == NULL) {
return;
}
logtimes(w1, w1->logtime, timb);
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) {
if (devs->init) {
int j;
for (j = 0; j < devs->ns; j++) {
if (devs->s[j].valid) {
fprintf(lfp, "%s%s%s%s%f%s%s", timb, w1->log_delim, devs->s[j].abbrv, w1->log_delim, devs->s[j].value, w1->log_delim,
(devs->s[j].units) ? (devs->s[j].units) : "");
if (w1->log_timet) {
fprintf(lfp, "%s%lld", w1->log_delim, (long long)w1->logtime);
}
fputc('\n', lfp);
}
}
}
}
if (logfile) {
if (*logfile == '|') {
pclose(lfp);
} else {
fclose(lfp);
}
}
}
w1retap/src/w1retap.c 0000664 0000000 0000000 00000035661 14464462352 0015004 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "ownet.h"
#include
#include
#include
#include "w1retap.h"
enum W1_sigflag { W1_NOFLAG = 0, W1_RECONF = (1), W1_READALL = (2), W1_SHOWCF = (4) };
static volatile enum W1_sigflag sigme;
#ifndef HAVE_CLOCK_NANOSLEEP
static inline void nanosub(struct timespec *a, struct timespec *b, struct timespec *result) {
result->tv_sec = a->tv_sec - b->tv_sec;
result->tv_nsec = a->tv_nsec - b->tv_nsec;
if (result->tv_nsec < 0) {
--result->tv_sec;
result->tv_nsec += 1000000000;
}
}
#endif
static void sig_hup(int x) { sigme |= W1_RECONF; }
static void sig_usr1(int x) { sigme |= W1_READALL; }
static void sig_usr2(int x) { sigme |= W1_SHOWCF; }
void w1_replog(w1_devlist_t *w1, const char *fmt, ...) {
static FILE *fp;
va_list va;
char *p;
int nc;
va_start(va, fmt);
if ((nc = vasprintf(&p, fmt, va)) != -1) {
int n;
w1->lastmsg = p;
for (n = 0; n < w1->ndll; n++) {
if (w1->dlls[n].type == 'r' && w1->dlls[n].func) {
(w1->dlls[n].func)(w1, w1->dlls[n].param);
}
}
w1->lastmsg = NULL;
if (w1->repfile) {
if (fp == NULL) {
if (*w1->repfile != '-') {
fp = fopen(w1->repfile, "a");
} else {
fp = stderr;
}
}
if (fp) {
char s[64];
logtimes(w1, w1->logtime, s);
fputs(s, fp);
fputc(' ', fp);
fputs(p, fp);
fputc('\n', fp);
fflush(fp);
}
}
free(p);
}
va_end(va);
}
static void do_init(w1_devlist_t *w1) {
int n;
int done_i = 0;
void (*func)(w1_devlist_t * w1, char *);
for (n = 0; n < w1->ndll; n++) {
if (w1->dlls[n].type == 'c' && done_i == 0) {
if ((g_module_symbol(w1->dlls[n].handle, "w1_init", (void *)&func))) {
(func)(w1, w1->dlls[n].param);
done_i = 1;
} else {
perror("init");
exit(1);
}
} else if (w1->dlls[n].type == 'l') {
if (!(g_module_symbol(w1->dlls[n].handle, "w1_logger", (void *)&w1->dlls[n].func))) {
perror("logger");
exit(1);
}
} else if (w1->dlls[n].type == 'r') {
if (!(g_module_symbol(w1->dlls[n].handle, "w1_report", (void *)&w1->dlls[n].func))) {
fputs("replogger entry point not found\n", stderr);
exit(1);
}
}
}
if (done_i == 0) {
fputs("Init fails: No w1_init() in init= loadable library\n"
"Please check the init= lines in your configuration file\n"
"and the manual entry 'Configuring the W1RETAP software'.\n"
"This is typically a configuration or build error.\n\n"
"You should also check that the required data driver is\n"
"present under $prefix/lib/w1retap/, for example, for sqlite,\n"
"a set of libraries libw1sqlite.so{,.0,.0.0.0} should be present.\n",
stderr);
exit(1);
}
w1_verify_intervals(w1);
w1_initialize_couplers(w1);
}
void init_interfaces(w1_devlist_t *w1) {
if (w1->iface == NULL)
w1->iface = strdup("DS2490-1");
if (w1->portnum == -1) {
if ((w1->portnum = owAcquireEx(w1->iface)) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
if (w1->verbose) {
owShowVersion();
}
}
}
void dll_parse(w1_devlist_t *w1, int typ, char *params) {
char *sep;
char *sofile = NULL;
if (w1->ndll == (MAXDLL - 1)) {
fputs("Too many DLLs\n", stderr);
exit(1);
}
sep = strpbrk(params, ":;=");
if (sep) {
*sep++ = 0;
}
if (*params == '.' || *params == '/') {
sofile = strdup(params);
} else {
sofile = w1_module_build_path(PACKAGE_LIB_DIR, params);
}
if (NULL != (w1->dlls[w1->ndll].handle = g_module_open(sofile, G_MODULE_BIND_LAZY))) {
w1->dlls[w1->ndll].type = typ;
if (sep && *sep) {
w1->dlls[w1->ndll].param = strdup(sep);
}
w1->ndll++;
}
free(sofile);
}
static void cleanup(int n, void *w) {
int i;
w1_devlist_t *w1 = w;
w1_freeup(w1);
for (i = 0; i < w1->ndll; i++) {
if (w1->dlls[i].handle) {
g_module_close(w1->dlls[i].handle);
w1->dlls[i].handle = 0;
}
if (w1->dlls[i].param) {
free(w1->dlls[i].param);
w1->dlls[i].param = NULL;
}
w1->dlls[w1->ndll].type = 0;
}
w1->ndll = 0;
free(w1->rcfile);
w1->rcfile = NULL;
}
/*
static void w1_show_id(uchar *id, char *res)
{
int i;
for(i=0; i<8; i++)
{
sprintf((res+i*2), "%02X", id[i]);
}
}
*/
static void w1_show(w1_devlist_t *w1, int forced) {
if (w1->verbose || forced) {
int i;
if (w1->numdev) {
fputs("Sensors:\n", stderr);
}
for (i = 0; i < w1->numdev; i++) {
int j;
fprintf(stderr, "%s %s (%ds)%s\n", w1->devs[i].serial, w1->devs[i].devtype, w1->devs[i].intvl,
(w1->devs[i].stype == W1_INVALID) ? " !" : "");
if (w1->devs[i].coupler) {
char *branch = (w1->devs[i].coupler->branch == COUPLER_AUX_ON) ? "aux" : "main";
fprintf(stderr, "\tVia coupler: %s, %s\n", w1->devs[i].coupler->coupler_device->serial, branch);
}
if (w1->devs[i].params && w1->devs[i].stype != W1_COUPLER) {
int j;
fputs("\tParameters:", stderr);
for (j = 0; j < w1->devs[i].params->num; j++) {
fprintf(stderr, " %f", w1->devs[i].params->values[j]);
}
fputc('\n', stderr);
}
for (j = 0; j < w1->devs[i].ns; j++) {
if (w1->devs[i].s[j].abbrv) {
fprintf(stderr, "\t%d: %s %s %s", j + 1, w1->devs[i].s[j].abbrv, w1->devs[i].s[j].name,
(w1->devs[i].s[j].units) ? (w1->devs[i].s[j].units) : "");
if (w1->devs[i].s[j].flags & W1_ROC) {
fprintf(stderr, ", %.4f /min", w1->devs[i].s[j].roc);
}
if (w1->devs[i].s[j].flags & W1_RMIN) {
fprintf(stderr, ", min=%.2f", w1->devs[i].s[j].rmin);
}
if (w1->devs[i].s[j].flags & W1_RMAX) {
fprintf(stderr, ", max=%.2f", w1->devs[i].s[j].rmax);
}
fputc('\n', stderr);
}
}
}
if (w1->ndll) {
fputs("Plugins:\n", stderr);
for (i = 0; i < w1->ndll; i++) {
fprintf(stderr, "%2d: %c %s", i, w1->dlls[i].type, g_module_name(w1->dlls[i].handle));
if (w1->dlls[i].param == NULL) {
fprintf(stderr, "\n");
} else {
fprintf(stderr, " => [");
if (strcasestr(w1->dlls[i].param, "password=") == NULL) {
fprintf(stderr, "%s]\n", w1->dlls[i].param);
} else {
char *p, *q;
char *params = strdup(w1->dlls[i].param);
for (p = params;; p = NULL) {
char *tok = strtok_r(p, " ", &q);
if (tok != NULL) {
if (p == NULL) {
fprintf(stderr, " ");
}
if (strncmp(tok, "password=", 9) == 0) {
fprintf(stderr, "password=?");
} else {
fprintf(stderr, "%s", tok);
}
} else {
fprintf(stderr, "]\n");
break;
}
}
free(params);
}
}
}
}
if (w1->altitude) {
fprintf(stderr, "Normalising pressure for %dm\n", w1->altitude);
}
if (w1->vane_offset) {
fprintf(stderr, "Vane offset %d\n", w1->vane_offset);
}
if (w1->logtmp) {
fprintf(stderr, "Log file is %s\n", w1->tmpname);
}
fprintf(stderr, "Interval %ds, cycle %ds\n", w1->delay, w1->cycle);
fprintf(stderr, "Release i/face %d\n", w1->release_me);
if (w1->pres_reduction_temp) {
fprintf(stderr, "Pressure reduction temp %.2f\n", *w1->pres_reduction_temp);
}
if (w1->allow_escape) {
fputs("Allowing rate limit escapes\n", stderr);
}
if (w1->force_utc) {
fputs("dates logged at UTC\n", stderr);
}
}
}
int main(int argc, char **argv) {
struct timeval now = {0};
struct sigaction act = {{0}};
gboolean immed = 0;
gboolean showvers = 0;
gboolean once = 0;
gboolean w1_simul = 0;
int n;
char *p;
GError *error = NULL;
GOptionContext *context;
w1_devlist_t *w1 = calloc(1, sizeof(w1_devlist_t));
GOptionEntry entries[] = {
{"wait", 'w', 0, G_OPTION_ARG_NONE, &immed, "At startup, wait until next interval", NULL},
{"once-only", '1', 0, G_OPTION_ARG_NONE, &once, "Read once and exit", NULL},
{"release-interface", 'R', 0, G_OPTION_ARG_NONE, &w1->release_me, "Release the 1Wire interface between reads", NULL},
{"daemonise", 'd', 0, G_OPTION_ARG_NONE, &w1->daemonise, "Daemonise (background) application", NULL},
{"no-tmp-log", 'T', 0, G_OPTION_ARG_NONE, &w1->logtmp, "Disables /tmp/.w1retap.dat logging", NULL},
{"tmp-log-name", 'l', 0, G_OPTION_ARG_STRING, &w1->tmpname, "Names logging file (/tmp/.w1retap.dat)", "FILE"},
{"interface", 'i', 0, G_OPTION_ARG_STRING, &w1->iface, "Interface device", "DEVICE"},
{"cycle-time", 't', 0, G_OPTION_ARG_INT, &w1->delay, "Time (secs) between device readings", "SECS"},
{"dont-read", 'N', 0, G_OPTION_ARG_NONE, &w1->doread, "Don't read sensors (for debugging)", NULL},
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &w1->verbose, "Verbose messages", NULL},
{"vane-offset", 'o', 0, G_OPTION_ARG_INT, &w1->vane_offset, "Value for N for weather vane (0-15)", "VAL"},
{"version", 'V', 0, G_OPTION_ARG_NONE, &showvers, "Display version number (and exit)", NULL},
{"simulate", 's', 0, G_OPTION_ARG_NONE, &w1_simul, "Simulate readings (for testing, not yet implemented)", NULL},
{"use-utc", 'u', 0, G_OPTION_ARG_NONE, &w1->force_utc, "Store dates as UTC (vice localtime)", NULL},
{"report-log", 'r', 0, G_OPTION_ARG_STRING, &w1->repfile, "Report log file", "FILE"},
{NULL}};
openlog("w1retap", LOG_PID, LOG_USER);
if (!g_module_supported()) {
exit(2);
}
act.sa_flags = SA_RESTART;
sigemptyset(&(act.sa_mask));
act.sa_handler = sig_usr1;
sigaction(SIGUSR1, &act, NULL);
act.sa_handler = sig_usr2;
sigaction(SIGUSR2, &act, NULL);
act.sa_handler = sig_hup;
sigaction(SIGHUP, &act, NULL);
w1->logtmp = 1;
w1->portnum = -1;
w1->log_delim[0] = ' ';
w1->delay = w1->cycle = W1_DEFAULT_INTVL;
w1->temp_scan = 1000;
w1->pres_reduction_temp = NULL;
if ((p = getenv("W1RCFILE"))) {
w1->rcfile = strdup(p);
}
read_config(w1);
context = g_option_context_new("- w1retap");
g_option_context_set_ignore_unknown_options(context, FALSE);
g_option_context_add_main_entries(context, entries, NULL);
if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
if (error != NULL) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
exit(1);
}
}
immed ^= 1; // weird JH logic ...
if (w1->tmpname == NULL) {
w1->tmpname = "/tmp/.w1retap.dat";
}
w1->doread ^= 1;
if (showvers)
w1->verbose = 2;
w1->vane_offset &= 0xf;
if (w1->verbose) {
fputs("w1retap v" VERSION " (c) 2005-2023 Jonathan Hudson\n", stderr);
fputs("Built: " __DATE__ " " __TIME__ " gcc " __VERSION__ "\n", stderr);
if (w1->verbose == 2) {
exit(0);
}
fprintf(stderr, "cfg: read from %s\n", w1->rcfile);
fprintf(stderr, "cfg: delay = %d\n", w1->delay);
fprintf(stderr, "cfg: demonise = %d\n", w1->daemonise);
fprintf(stderr, "cfg: altitude = %d\n", w1->altitude);
fprintf(stderr, "cfg: vane_offset = %d\n", w1->vane_offset);
fprintf(stderr, "cfg: timestamp = %d\n", w1->timestamp);
fprintf(stderr, "cfg: logtemp = %d\n", w1->logtmp);
fprintf(stderr, "cfg: temp_scan = %d\n", w1->temp_scan);
}
do_init(w1);
w1_show(w1, 0);
if (!w1->doread) {
exit(0);
}
init_interfaces(w1);
w1->logtime = time(NULL);
w1_replog(w1, "Startup w1retap v" VERSION);
if (w1->daemonise) {
// preserve redirected log files unless TTYs
int iclose;
iclose = !(isatty(1) && isatty(2));
assert(0 == daemon(0, iclose));
}
if (w1->pidfile) {
FILE *fp;
if (NULL != (fp = fopen(w1->pidfile, "w"))) {
fprintf(fp, "%d\n", getpid());
fclose(fp);
}
free(w1->pidfile);
}
w1_all_couplers_off(w1);
while (1) {
int nv = 0;
if (immed) {
if (w1->verbose)
fputs("reading ...\n", stderr);
nv = w1_read_all_sensors(w1, now.tv_sec);
if (nv) {
for (n = 0; n < w1->ndll; n++) {
if (w1->dlls[n].type == 'l' && w1->dlls[n].func) {
(w1->dlls[n].func)(w1, w1->dlls[n].param);
}
}
if (w1->logtmp && ((now.tv_sec % w1->cycle) == 0)) {
w1_tmpfilelog(w1);
}
}
if (w1->release_me) {
owRelease(w1->portnum);
w1->portnum = -1;
}
}
if (once)
break;
if (w1->delay) {
int ns;
immed = 1;
do {
struct timespec req;
ns = 0;
if (sigme & W1_READALL) {
sigme &= ~W1_READALL;
nv = w1_read_all_sensors(w1, 0);
w1_tmpfilelog(w1);
}
if (sigme & W1_RECONF) {
sigme &= ~W1_RECONF;
cleanup(0, w1);
read_config(w1);
do_init(w1);
w1_show(w1, 0);
init_interfaces(w1);
}
if (sigme & W1_SHOWCF) {
sigme &= ~W1_SHOWCF;
w1_show(w1, 1);
}
if (w1->verbose)
fputs("Waiting ... ", stderr);
gettimeofday(&now, NULL);
#ifdef HAVE_CLOCK_NANOSLEEP
req.tv_sec = (now.tv_sec / w1->delay) * w1->delay + w1->delay;
req.tv_nsec = 0;
ns = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &req, NULL);
#else
struct timespec then, nnow;
then.tv_sec = w1->delay * (1 + now.tv_sec / w1->delay);
then.tv_nsec = 200 * 1000 * 1000; /* ensure tick crossed */
nnow.tv_sec = now.tv_sec;
nnow.tv_nsec = now.tv_usec * 1000;
nanosub(&then, &nnow, &req);
ns = nanosleep(&req, NULL);
#endif
if (ns == 0) {
gettimeofday(&now, NULL);
w1->logtime = now.tv_sec;
if (w1->verbose)
fputs(ctime(&now.tv_sec), stderr);
}
} while ((ns == EINTR) || (ns == -1 && errno == EINTR));
} else {
break;
}
}
return 0;
}
w1retap/src/w1retap.h 0000664 0000000 0000000 00000010322 14464462352 0014774 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _W1FILE_H
#define _W1FILE_H
#include "config.h"
#include
#include
#include
enum W1_type {
W1_INVALID,
W1_TEMP,
W1_HUMID,
W1_PRES,
W1_COUNTER,
W1_BRAY,
W1_SHT11,
W1_COUPLER,
W1_WINDVANE,
W1_DS2438V,
W1_HBBARO,
W1_HIH,
W1_DS2760,
W1_DS2450,
W1_MS_TC,
W1_DS1921,
W1_DS1923,
W1_HBUV,
W1_HBHT
};
enum W1_so_opts { W1_SO_INIT = 1, W1_SO_LOG = 2 };
/* coupler states: see SetSwitch1F() in swt1f.c */
#define COUPLER_UNDEFINED -1
#define COUPLER_ALL_OFF 0 // All lines off
#define COUPLER_MAIN_ON 4 // Smart-On Main
#define COUPLER_AUX_ON 2 // Smart-On Aux
#define W1_ROC (1 << 0)
#define W1_RMIN (1 << 1)
#define W1_RMAX (1 << 2)
#define W1_SEQ (W1_RMAX + 1)
#define ALLOCDEV 8
#define TBUF_SZ 32
#define MAXDLL 16
#define MAXCPL 64
#define ALLOCSENS 8
#define W1_NOP (-1)
#define W1_MIN_INTVL 10
#define W1_DEFAULT_INTVL 120
#define W1_PRT_UNSET (-32678)
typedef struct w1_devlist w1_devlist_t;
typedef struct w1_device w1_device_t;
typedef struct {
int type;
GModule *handle;
void (*func)(w1_devlist_t *, void *);
char *param;
} dlldef_t;
typedef struct {
char *abbrv;
char *name;
char *units;
double value;
short valid;
short flags;
double rmin;
double rmax;
double roc;
double lval;
time_t ltime;
short reason;
} w1_sensor_t;
typedef struct {
int num;
double values[];
} w1_params_t;
typedef struct {
w1_device_t *coupler_device;
short branch;
} w1_coupler_t;
struct w1_device {
char *serial;
char *devtype;
short init;
short ignore;
enum W1_type stype;
w1_sensor_t *s;
unsigned char serno[8];
w1_coupler_t *coupler;
w1_params_t *params;
void *private;
int ns;
int intvl;
};
typedef struct {
int active_lines;
} w1_coupler_private_t;
typedef struct {
unsigned char control[16];
} w1_windvane_private_t;
typedef struct {
char devid[32];
int branch;
w1_device_t *coupler_device;
} w1_couplist_t;
struct w1_devlist {
int numdev;
int ndll;
int delay;
int cycle;
int portnum;
int altitude;
char *iface;
char *rcfile;
char *repfile;
time_t logtime;
dlldef_t dlls[MAXDLL];
gboolean verbose;
gboolean daemonise;
gboolean logtmp;
gboolean doread;
w1_device_t *devs;
char *lastmsg;
int timestamp;
int vane_offset;
char *pidfile;
char *tmpname;
char log_delim[2];
short log_timet;
int temp_scan;
double *pres_reduction_temp;
short allow_escape;
gboolean release_me;
gboolean force_utc;
};
extern void w1_tmpfilelog(w1_devlist_t *);
extern void w1_freeup(w1_devlist_t *);
extern void w1_enumdevs(w1_device_t *);
extern void logtimes(w1_devlist_t *, time_t, char *);
extern char *w1_get_from_home(const char *);
extern void dll_parse(w1_devlist_t *, int, char *);
extern void read_config(w1_devlist_t *);
extern FILE *w1_file_open(char *);
extern w1_sensor_t *w1_find_sensor(w1_devlist_t *, const char *);
extern w1_sensor_t *w1_match_sensor(w1_device_t *, const char *);
extern void w1_replog(w1_devlist_t *, const char *, ...);
extern void w1_set_device_data(w1_device_t *, const char *, char *);
extern void w1_set_device_data_index(w1_device_t *, int, char *);
extern void w1_all_couplers_off(w1_devlist_t *);
extern int w1_read_all_sensors(w1_devlist_t *, time_t);
extern void w1_initialize_couplers(w1_devlist_t *);
extern int w1_get_device_index(w1_device_t *, int, char *, char *);
extern void w1_verify_intervals(w1_devlist_t *);
extern int get_libusb_version(char *buffer, size_t blen);
#endif
w1retap/src/w1sensors.c 0000664 0000000 0000000 00000076045 14464462352 0015366 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "ownet.h"
#include "temp10.h"
#include "atod26.h"
#include "atod20.h"
#include "cnt1d.h"
#include "pressure.h"
#include "sht11.h"
#include "swt1f.h"
#include "ds2760.h"
#include "ds192x.h"
#include "hbuv.h"
#include "hbht.h"
#include "w1retap.h"
#define W1_RETRY 10
// Table from DalSemi application note 755A (page four): http://pdfserv.maxim-ic.com/en/an/app755A.pdf
#define WINDVANE_VCC (1.0) // connected to VCC through pull-up resistor
#define WINDVANE_R2 (WINDVANE_VCC / 2.0) // connected to 50% voltage divider
#define WINDVANE_R1 (WINDVANE_VCC * (2.0 / 3.0)) // connected to 66% voltage divider
#define WINDVANE_GND (0.0) // connected to GND
#define WINDVANE_MAX_ERROR ((WINDVANE_R1 - WINDVANE_R2) / 2.0) // max acceptable error
typedef struct {
float vdd;
float vad;
float vsens;
float temp;
int req;
} ds2438v_t;
enum W1_DS2438_modes { DS2438_VDD = 1, DS2438_VAD = 2, DS2438_VSENS = 4, DS2438_TEMP = 8 };
static float wind_conversion_table[16][4] = {
{WINDVANE_GND, WINDVANE_VCC, WINDVANE_VCC, WINDVANE_VCC}, {WINDVANE_GND, WINDVANE_GND, WINDVANE_VCC, WINDVANE_VCC},
{WINDVANE_VCC, WINDVANE_GND, WINDVANE_VCC, WINDVANE_VCC}, {WINDVANE_VCC, WINDVANE_GND, WINDVANE_GND, WINDVANE_VCC},
{WINDVANE_VCC, WINDVANE_VCC, WINDVANE_GND, WINDVANE_VCC}, {WINDVANE_VCC, WINDVANE_VCC, WINDVANE_GND, WINDVANE_GND},
{WINDVANE_VCC, WINDVANE_VCC, WINDVANE_VCC, WINDVANE_GND}, {WINDVANE_R2, WINDVANE_VCC, WINDVANE_VCC, WINDVANE_GND},
{WINDVANE_R2, WINDVANE_VCC, WINDVANE_VCC, WINDVANE_VCC}, {WINDVANE_R1, WINDVANE_R1, WINDVANE_VCC, WINDVANE_VCC},
{WINDVANE_VCC, WINDVANE_R2, WINDVANE_VCC, WINDVANE_VCC}, {WINDVANE_VCC, WINDVANE_R1, WINDVANE_R1, WINDVANE_VCC},
{WINDVANE_VCC, WINDVANE_VCC, WINDVANE_R2, WINDVANE_VCC}, {WINDVANE_VCC, WINDVANE_VCC, WINDVANE_R1, WINDVANE_R1},
{WINDVANE_VCC, WINDVANE_VCC, WINDVANE_VCC, WINDVANE_R2}, {WINDVANE_GND, WINDVANE_VCC, WINDVANE_VCC, WINDVANE_R2}};
extern int lfd;
static void w1_set_invalid(w1_device_t *w) {
int k;
for (k = 0; k < w->ns; k++) {
w->s[k].valid = 0;
}
}
static void w1_make_serial(char *asc, unsigned char *bin) {
int i, j;
for (i = j = 0; i < 8; i++) {
bin[i] = ToHex(asc[j]) << 4;
j++;
bin[i] += ToHex(asc[j]);
j++;
}
}
static void w1_set_coupler(w1_devlist_t *w1, w1_device_t *w, int active_lines) {
uchar a[4];
w1_coupler_private_t *priv;
if ((w->stype == W1_COUPLER) && w->private) {
priv = (w1_coupler_private_t *)w->private;
if (priv->active_lines != active_lines) {
SetSwitch1F(w1->portnum, w->serno, active_lines, 2, a, TRUE); /* Smart-On command requires 2 extra bytes */
priv->active_lines = active_lines;
}
}
}
static int w1_select_device(w1_devlist_t *w1, w1_device_t *w) {
u_char thisdev[8];
int found = 0, i;
w1_device_t *dev;
/* disconnect both branches of all couplers on the bus */
for (dev = w1->devs, i = 0; i < w1->numdev; i++, dev++) {
if (dev->stype == W1_COUPLER) {
/* avoid turning off the branch we're about to select */
if (!(w->coupler && w->coupler->coupler_device == dev))
w1_set_coupler(w1, dev, COUPLER_ALL_OFF);
}
}
/* turn on our branch. it is important to turn off the other
branches first, to ensure that only one branch is ever active
at any one time */
if (w->coupler)
w1_set_coupler(w1, w->coupler->coupler_device, w->coupler->branch);
/* confirm that the device is present on the bus */
owFamilySearchSetup(w1->portnum, w->serno[0]);
while (owNext(w1->portnum, TRUE, FALSE)) {
owSerialNum(w1->portnum, thisdev, TRUE);
if (memcmp(thisdev, w->serno, sizeof(thisdev)) == 0) {
found = 1;
break;
}
}
return found;
}
static int w1_validate(w1_devlist_t *w1, w1_sensor_t *s) {
static char *restxt[] = {"OK", "RATE", "MIN", "undef", "MAX", "SEQ"};
int chk = 0;
float act = s->value;
float rate = 0;
if ((s->flags & W1_RMIN) && (s->value < s->rmin)) {
s->value = (s->ltime) ? s->lval : s->rmin;
chk = W1_RMIN;
}
if ((s->flags & W1_RMAX) && (s->value > s->rmax)) {
s->value = (s->ltime) ? s->lval : s->rmax;
chk = W1_RMAX;
}
if (chk == 0 && (s->flags & W1_ROC)) {
// if (!(w1->allow_escape == 1 && (s->reason & (W1_RMIN|W1_RMAX)) != 0))
{
if (s->ltime > 0 && s->ltime != w1->logtime) {
rate = fabs(s->value - s->lval) * 60.0 / (w1->logtime - s->ltime);
if (rate > s->roc) {
s->value = s->lval;
chk = W1_ROC;
}
}
}
}
s->reason = chk;
if (chk == 0 && strncmp(s->abbrv, "RGC", 3) == 0) {
/*
w1_replog (w1, "%s result=%.2f actual=%.2f rate=%.2f prev=%.2f "
"prevtime_t=%d logtime_t=%d reason=%s",
s->abbrv, s->value, act, rate,
s->lval, s->ltime, w1->logtime, restxt[chk]);
*/
if (s->value < s->lval) {
s->value = s->lval;
chk = W1_SEQ;
}
}
if (chk == 0) {
s->ltime = w1->logtime;
s->lval = s->value;
s->valid = 1;
} else {
w1_replog(w1,
"%s result=%.2f actual=%.2f rate=%.2f prev=%.2f "
"prevtime_t=%d logtime_t=%d reason=%s",
s->abbrv, s->value, act, rate, s->lval, s->ltime, w1->logtime, restxt[chk]);
s->valid = 0;
}
return (int)s->valid;
}
static int w1_read_temp(w1_devlist_t *w1, w1_device_t *w) {
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
if (w1_select_device(w1, w)) {
float temp;
if (ReadTemperature(w1->portnum, w->serno, &temp, w1->temp_scan)) {
w->s[0].value = temp;
w1_validate(w1, &w->s[0]);
}
} else {
w->s[0].valid = 0;
}
return (w->s[0].valid);
}
static int w1_read_counter(w1_devlist_t *w1, w1_device_t *w) {
unsigned int cnt;
int nv = 0;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
if (w->s[0].abbrv) {
if ((w->s[0].valid = ReadCounter(w1->portnum, w->serno, 14, &cnt))) {
if (w->params && w->params->num >= 1)
cnt += (int)w->params->values[0];
w->s[0].value = cnt;
nv += w1_validate(w1, &w->s[0]);
}
}
if (w->s[1].abbrv) {
if ((w->s[1].valid = ReadCounter(w1->portnum, w->serno, 15, &cnt))) {
if (w->params && w->params->num > 1)
cnt += (int)w->params->values[1];
w->s[1].value = cnt;
nv += w1_validate(w1, &w->s[1]);
}
}
}
return nv;
}
static int w1_read_ds2450(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
char msg[48];
float advolts[4];
uchar ctrl[16];
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
if (SetupAtoDControl(w1->portnum, w->serno, ctrl, msg)) {
fprintf(stderr, "A/D settings found\n%s\n", msg);
} else {
fprintf(stderr, "ERROR, DS2450 set up unsuccessful!\n");
}
DoAtoDConversion(w1->portnum, 0, w->serno);
if (ReadAtoDResults(w1->portnum, 0, w->serno, advolts, ctrl)) {
w1_sensor_t *s;
char adname[4] = "ADA";
int i;
for (i = 0; i < 4; i++) {
*(adname + 2) = 'A' + (char)i;
if ((s = w1_match_sensor(w, adname)) != NULL) {
s->value = advolts[i];
nv += w1_validate(w1, s);
fprintf(stderr, "DS2450 %s %.1f\n", adname, advolts[i]);
}
}
}
}
return nv;
}
static int w1_read_voltages(w1_devlist_t *w1, w1_device_t *w, ds2438v_t *v) {
int nv = 0;
int sel = 1;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
if (v == NULL) {
sel = w1_select_device(w1, w);
}
w1_set_invalid(w);
if (sel) {
float val = -1.0;
w1_sensor_t *s;
s = w1_match_sensor(w, "vdd");
if ((v && (v->req & DS2438_VDD)) || s) {
val = ReadAtoD(w1->portnum, TRUE, w->serno);
if (s) {
if (val != -1.0) {
s->value = val;
nv += w1_validate(w1, s);
} else {
s->valid = 0;
}
}
if (v)
v->vdd = val;
} else {
if (w1_match_sensor(w, "Solar") != NULL) {
float v1;
v1 = ReadAtoD(w1->portnum, TRUE, w->serno);
w1_replog(w1, "Solar vdd %.1f", v1);
}
}
s = w1_match_sensor(w, "vad");
if ((v && (v->req & DS2438_VAD)) || s) {
val = ReadAtoD(w1->portnum, FALSE, w->serno);
if (s) {
if (val != -1.0) {
s->value = val;
nv += w1_validate(w1, s);
} else {
s->valid = 0;
}
}
if (v)
v->vad = val;
}
s = w1_match_sensor(w, "vsens");
if ((v && (v->req & DS2438_VSENS)) || s) {
val = ReadVsens(w1->portnum, w->serno);
if (s) {
if (val != -1.0) {
s->value = val;
nv += w1_validate(w1, s);
} else {
s->valid = 0;
}
}
if (v)
v->vsens = val;
}
s = w1_match_sensor(w, "temp");
if ((v && (v->req & DS2438_TEMP)) || s) {
val = Get_Temperature(w1->portnum, w->serno);
if (val != -1) {
int nv1 = 0;
if (s) {
s->value = val;
nv1 = w1_validate(w1, s);
nv += nv1;
}
if (v && nv1 == 1)
v->temp = val;
}
}
}
return nv;
}
static float pressure_at_msl(float pres, float temp, int altitude) {
#define __CONST_G (9.80665)
#define __CONST_R (287.04)
float kt = temp + 273.15;
float x = (__CONST_G * altitude / (__CONST_R * kt));
pres *= exp(x);
return pres;
}
#define BRAY_SLOPE (35.949367089)
#define BRAY_OFFSET (751.075949363)
static int w1_read_bray(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
int k;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
if (w1_select_device(w1, w)) {
ds2438v_t v = {0};
v.req = DS2438_VAD | DS2438_TEMP;
nv = w1_read_voltages(w1, w, &v);
if (v.vad > 0.0) {
float pres;
double slope, offset;
float ptemp;
if (w->params && w->params->num >= 2) {
slope = w->params->values[0];
offset = w->params->values[1];
ptemp = w->params->values[2];
} else {
slope = BRAY_SLOPE;
offset = BRAY_OFFSET;
ptemp = v.temp;
}
pres = slope * v.vad + offset;
if (w1->verbose) {
fprintf(stderr, "vad %.3f slope %f, offset %f\n", v.vad, slope, offset);
}
if (w1->altitude) {
float prtemp;
if (w1->verbose) {
fprintf(stderr, "raw %f %f %d\n", pres, v.temp, w1->altitude);
}
prtemp = (w1->pres_reduction_temp) ? *w1->pres_reduction_temp : ptemp;
pres = pressure_at_msl(pres, prtemp, w1->altitude);
if (w1->verbose) {
fprintf(stderr, "msl %f \n", pres);
}
}
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "Pres"))) {
s->value = pres;
nv += w1_validate(w1, s);
}
}
} else {
for (k = 0; k < w->ns; k++) {
w->s[k].valid = 0;
}
}
return nv;
}
// Values for MSL
#define INHGHPA 33.863886
#define HB_SLOPE (0.6562 * INHGHPA)
#define HB_OFFSET (26.0827 * INHGHPA)
static int w1_read_hb_pressure(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
ds2438v_t v = {0};
v.req = DS2438_VAD | DS2438_VDD | DS2438_TEMP;
nv = w1_read_voltages(w1, w, &v);
if (v.vad > 0.0) {
float pres;
double slope, offset;
if (w->params && w->params->num == 2) {
slope = w->params->values[0];
offset = w->params->values[1];
} else {
slope = HB_SLOPE;
offset = HB_OFFSET;
}
pres = slope * v.vad + offset;
if (offset < 100.0) {
pres *= 33.863886;
}
if (w1->verbose) {
fprintf(stderr, "vad %.3f, vdd %.3f, slope %.4f, offset %.4f\n", v.vad, v.vdd, slope, offset);
fprintf(stderr, "temp %.2f, pres %.1f hPa\n", v.temp, pres);
}
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "Pres"))) {
s->value = pres;
nv += w1_validate(w1, s);
}
}
}
return nv;
}
static int w1_read_sht11(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
float temp, rh;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
if (ReadSHT11(w1->portnum, w->serno, &temp, &rh)) {
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = temp;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Humidity"))) {
s->value = rh;
nv += w1_validate(w1, s);
}
}
}
return nv;
}
static int w1_read_humidity(w1_devlist_t *w1, w1_device_t *w) {
float humid = 0;
float vddx = 0;
int nv = 0;
char vind = ' ';
ds2438v_t v = {0};
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
v.req = DS2438_VAD | DS2438_VDD | DS2438_TEMP;
nv = w1_read_voltages(w1, w, &v);
vddx = v.vdd;
if (v.vdd > 5.8) {
v.vdd = (float)5.8;
vind = '+';
} else if (v.vdd < 4.0) {
v.vdd = (float)4.0;
vind = '-';
}
humid = (((v.vad / v.vdd) - (0.8 / v.vdd)) / 0.0062) / (1.0546 - 0.00216 * v.temp);
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = v.temp;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Humidity"))) {
s->value = humid;
nv += w1_validate(w1, s);
}
}
if (w->s[0].valid == 0 || w->s[1].valid == 0) {
w1_replog(w1, "readhumid %f %f %f %f %c", vddx, v.vad, v.temp, humid, vind);
}
return nv;
}
static int w1_read_hih(w1_devlist_t *w1, w1_device_t *w) {
float humid = 0, temp = 0;
float vdd = 0, vad = 0;
int nv = 0, nv1 = 0;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
ds2438v_t v = {0};
v.req = DS2438_VAD | DS2438_VDD | DS2438_TEMP;
nv1 = w1_read_voltages(w1, w, &v);
if (nv1 != 0) {
// Shamelessly researched from owfs; ow_2438.c
humid = (v.vad / v.vdd - (0.8 / v.vdd)) / (0.0062 * (1.0305 + 0.000044 * temp + 0.0000011 * v.temp * v.temp));
if (w1->verbose) {
fprintf(stderr, "vdd %f vad %f temp %f rh %f\n", v.vdd, v.vad, v.temp, humid);
}
w1_sensor_t *s;
/*
* Not necessary, done read_voltages
if((s = w1_match_sensor(w, "Temp")))
{
s->value = v.temp;
nv += w1_validate(w1, s);
}
*/
if ((s = w1_match_sensor(w, "Humidity"))) {
if (humid > 100)
humid = 99.9;
s->value = humid;
nv += w1_validate(w1, s);
}
}
if (w->s[0].valid == 0 || w->s[1].valid == 0) {
w1_replog(w1, "hih nv1 %d %d %f %f %f %f", nv1, nv, vdd, vad, temp, humid);
w->s[0].valid = w->s[1].valid = 0;
}
}
return nv;
}
static int w1_read_current(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
ds2438v_t v = {0};
v.req = DS2438_VAD;
nv = w1_read_voltages(w1, w, &v);
if (v.vad > -1.0) {
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "current"))) {
if (v.vad >= 0.2) {
/*
* for voltages .2 and up, response is claimed
* to be linear within +/- 3% at a temperature
* of 23C. .2 volts corresponds to a current
* of 1 Amp. 7.36x -.47 for x > 0.2volts
*/
s->value = (v.vad * 7.36) - 0.47;
} else {
/*
* 9.09x - .8181 for x < 0.2
* This is an adjusted slope that will give zero amps
* at the minimum voltage of 0.09 volts and yield 1 amp
* at 0.2 volts where it will meet up with the
* first equation.
* The readings between 0 and 1 amp may be inaccurate.
*/
s->value = (v.vad * 9.09) - 0.8181;
}
nv += w1_validate(w1, s);
}
}
}
return nv;
}
static int w1_read_pressure(w1_devlist_t *w1, w1_device_t *w) {
float temp, pres;
int nv = 0;
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
if (w1_select_device(w1, w)) {
if (w->init == 1) {
if (Init_Pressure(w1->portnum, w->serno)) {
w->init = 2;
}
}
if (w->init == 2) {
if (ReadPressureValues(w1->portnum, &temp, &pres)) {
if (w1->altitude) {
float prtemp;
prtemp = (w1->pres_reduction_temp) ? *w1->pres_reduction_temp : temp;
pres = pressure_at_msl(pres, prtemp, w1->altitude);
}
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = temp;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Pres"))) {
s->value = pres;
nv += w1_validate(w1, s);
}
} else {
w->init = 0;
}
}
} else {
w->init = 1;
}
return nv;
}
static int w1_read_ds2760(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
ds2760_t v = {0};
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
if (ReadDS2760(w1->portnum, w->serno, &v)) {
w1_sensor_t *s;
if (w1->verbose) {
fprintf(stderr, "ReadDS2760: v %f t %f i %f a %f\n", v.volts, v.temp, v.curr, v.accum);
}
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = v.temp;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Current"))) {
s->value = v.curr;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Volt"))) {
s->value = v.volts;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Accumulator"))) {
s->value = v.accum;
nv += w1_validate(w1, s);
}
}
}
return nv;
}
static int w1_read_ds1923(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
ds1923_t v = {0};
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
if (w->params) {
v.kill = 1;
}
if (ReadDS1923(w1->portnum, w->serno, &v)) {
w1_sensor_t *s;
if (w1->verbose) {
fprintf(stderr, "ReadDS1923: t %f°C rh %f%%\n", v.temp, v.rh);
fflush(stderr);
}
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = v.temp;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Humidity"))) {
s->value = v.rh;
nv += w1_validate(w1, s);
}
} else if (w1->verbose) {
fputs("ReadDS1923 read failed\n", stderr);
fflush(stderr);
}
}
return nv;
}
static int w1_read_ds1921(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
ds1921_t v = {0};
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
if (w->params) {
v.kill = 1;
}
if (ReadDS1921(w1->portnum, w->serno, &v)) {
w1_sensor_t *s;
if (w1->verbose) {
fprintf(stderr, "ReadDS1921: %f°C\n", v.temp);
}
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = v.temp;
nv += w1_validate(w1, s);
}
}
}
return nv;
}
static int w1_read_hbuv(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
hbuv_t hb = {0};
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
int r;
r = HBUV_read_data(w1->portnum, w->serno, &hb);
if (r) {
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = hb.raw_temp * 0.5;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "uv")) || (s = w1_match_sensor(w, "ultra")) || (s = w1_match_sensor(w, "violet"))) {
s->value = hb.raw_uvi * 0.1;
nv += w1_validate(w1, s);
}
}
}
return nv;
}
static int w1_read_hbht(w1_devlist_t *w1, w1_device_t *w) {
int nv = 0;
hbht_res_t hb = {0};
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
w->init = 1;
}
w1_set_invalid(w);
if (w1_select_device(w1, w)) {
int r;
r = HBHT_read_data(w1->portnum, w->serno, &hb);
if (w1->verbose)
fprintf(stderr, "HBHT %d %.1f %.2f\n", r, hb.temp, hb.humid);
if (r) {
w1_sensor_t *s;
if ((s = w1_match_sensor(w, "Temp"))) {
s->value = hb.temp;
nv += w1_validate(w1, s);
}
if ((s = w1_match_sensor(w, "Humidity"))) {
s->value = hb.humid;
nv += w1_validate(w1, s);
}
}
}
return nv;
}
static int w1_read_windvane(w1_devlist_t *w1, w1_device_t *w) {
w1_windvane_private_t *private = NULL;
int i, nv = 0;
char message[80];
float analogue[4];
if (w->init == 0) {
w1_make_serial(w->serial, w->serno);
if (w->private == NULL)
w->private = malloc(sizeof(w1_windvane_private_t));
w->init = 1;
}
private = (w1_windvane_private_t *)w->private;
w->s[0].valid = w->s[1].valid = 0;
if (w1_select_device(w1, w) && (private != NULL)) {
if (w->init == 1) {
if (SetupAtoDControl(w1->portnum, w->serno, private->control, message) &&
WriteAtoD(w1->portnum, FALSE, w->serno, private->control, 0x08, 0x11))
w->init = 2;
}
if (w->init == 2) {
if (DoAtoDConversion(w1->portnum, FALSE, w->serno) &&
ReadAtoDResults(w1->portnum, FALSE, w->serno, analogue, private->control)) {
// In order to read the position of the wind vane, we first scale the readings
// relative to the highest reading (which must be approximately VCC) and then
// search a table of recognised vane positions to match our observation.
float scaled[4], factor = fmaxf(analogue[0], fmaxf(analogue[1], fmaxf(analogue[2], analogue[3])));
for (i = 0; i < 4; i++)
scaled[i] = analogue[i] / factor;
// syslog(LOG_INFO, "Wind vane: analogue: %.4f %.4f %.4f %.4f scaled: %.4f %.4f %.4f %.4f max error %.4f",
// analogue[0], analogue[1], analogue[2], analogue[3], scaled[0], scaled[1], scaled[2], scaled[3],
// WINDVANE_MAX_ERROR);
w->s[0].value = -1;
for (i = 0; i < 16; i++) {
if (((scaled[0] <= wind_conversion_table[i][0] + WINDVANE_MAX_ERROR) &&
(scaled[0] >= wind_conversion_table[i][0] - WINDVANE_MAX_ERROR)) &&
((scaled[1] <= wind_conversion_table[i][1] + WINDVANE_MAX_ERROR) &&
(scaled[1] >= wind_conversion_table[i][1] - WINDVANE_MAX_ERROR)) &&
((scaled[2] <= wind_conversion_table[i][2] + WINDVANE_MAX_ERROR) &&
(scaled[2] >= wind_conversion_table[i][2] - WINDVANE_MAX_ERROR)) &&
((scaled[3] <= wind_conversion_table[i][3] + WINDVANE_MAX_ERROR) &&
(scaled[3] >= wind_conversion_table[i][3] - WINDVANE_MAX_ERROR))) {
w->s[0].value = ((i - w1->vane_offset) & 0xf);
nv += w1_validate(w1, &w->s[0]);
break;
}
}
if (w->s[0].value == -1) // no match found?
syslog(LOG_WARNING, "Wind vane: Unexpected values: v0=%.4f, v1=%.4f, v2=%.4f, v3=%.4f", analogue[0], analogue[1],
analogue[2], analogue[3]);
}
}
}
return nv;
}
void w1_initialize_couplers(w1_devlist_t *w1) {
w1_device_t *w;
int n, b;
int nc = 0;
w1_couplist_t clist[MAXCPL];
w1_coupler_private_t *priv;
for (w = w1->devs, n = 0; n < w1->numdev; n++, w++) {
if (w->stype == W1_COUPLER && nc < MAXCPL) {
char *inuse = calloc(w->ns, sizeof(char));
int empty = 0;
w1_make_serial(w->serial, w->serno);
w->private = calloc(1, sizeof(w1_coupler_private_t));
priv = (w1_coupler_private_t *)w->private;
priv->active_lines = COUPLER_UNDEFINED;
for (b = 0; b < w->ns; b++) {
// fprintf(stderr, "%d/%d: ", b,w->ns);
if (w->s[b].abbrv && w->s[b].name) {
// fprintf(stderr,"%4s %s", w->s[b].abbrv, w->s[b].name);
if ((w->s[b].abbrv[0] == 'M' || w->s[b].abbrv[0] == 'A') && isxdigit(w->s[b].name[0])) {
char *tmp, *p1, *p2;
tmp = strdup(w->s[b].name);
for (p1 = tmp; (p2 = strtok(p1, ", |")); p1 = NULL) {
if (*p2) {
clist[nc].coupler_device = w;
strcpy(clist[nc].devid, p2);
if (w->s[b].abbrv[0] == 'M')
clist[nc].branch = COUPLER_MAIN_ON;
else
clist[nc].branch = COUPLER_AUX_ON;
nc++;
}
}
free(tmp);
inuse[b] = 1;
} else {
empty++;
}
} else {
empty++;
}
// fputc('\n', stderr);
}
if (empty) {
int i, j;
w1_sensor_t *temps = calloc(w->ns - empty, sizeof(w1_sensor_t));
for (i = 0, j = 0; i < w->ns; i++) {
if (inuse[i] == 1) {
memcpy(temps + j, w->s + i, sizeof(w1_sensor_t));
j++;
}
}
void *old = w->s;
w->s = temps;
w->ns -= empty;
free(old);
fprintf(stderr, "(notice) freed up empty branch for %s\n", w->serial);
}
free(inuse);
}
}
int nx;
for (nx = 0; nx < nc; nx++) {
for (w = w1->devs, n = 0; n < w1->numdev; n++, w++) {
if (w->stype != W1_COUPLER && w->coupler == NULL && strcmp(w->serial, clist[nx].devid) == 0) {
w->coupler = (w1_coupler_t *)calloc(1, sizeof(w1_coupler_t));
w->coupler->branch = clist[nx].branch;
w->coupler->coupler_device = clist[nx].coupler_device;
}
}
}
}
void w1_all_couplers_off(w1_devlist_t *w1) {
w1_device_t *w;
int n;
if (w1->doread)
for (w = w1->devs, n = 0; n < w1->numdev; n++, w++)
if (w->stype == W1_COUPLER)
w1_set_coupler(w1, w, COUPLER_ALL_OFF);
}
static int w1_lcm(int a[], int n) {
int i, j, c, amax;
unsigned long prod;
int s = -1;
amax = a[0];
for (i = 0; i < n; i++) {
if (a[i] >= amax) {
amax = a[i];
}
}
for (i = 0, prod = 1; i < n; i++) {
prod = prod * a[i];
}
for (i = amax; i <= prod; i += amax) {
c = 0;
for (j = 0; j < n; j++) {
if (i % a[j] == 0) {
c += 1;
}
}
if (c == n) {
s = i;
break;
}
}
return s;
}
static int _w1_gcd(int m, int n) {
if (n == 0) {
return m;
} else {
return _w1_gcd(n, m % n);
}
}
int w1_gcd(int a[], int n) {
int s = 0;
int i;
for (i = 0; i < n; i++) {
s = _w1_gcd(s, a[i]);
}
return s;
}
void w1_verify_intervals(w1_devlist_t *w1) {
int n;
int mint = w1->delay;
w1_device_t *d;
int *intvls = NULL;
intvls = calloc(w1->numdev, sizeof(int));
for (d = w1->devs, n = 0; n < w1->numdev; n++, d++) {
if (d->intvl) {
if (d->intvl < W1_MIN_INTVL)
d->intvl = W1_MIN_INTVL;
if (d->intvl > w1->delay)
d->intvl = w1->delay;
} else {
d->intvl = w1->delay;
}
if (d->intvl < mint)
mint = d->intvl;
}
w1->delay = mint;
for (d = w1->devs, n = 0; n < w1->numdev; n++, d++) {
d->intvl = (d->intvl / w1->delay) * w1->delay;
if (d->intvl == 0)
d->intvl = w1->delay;
intvls[n] = d->intvl;
}
w1->cycle = w1_lcm(intvls, w1->numdev);
w1->delay = w1_gcd(intvls, w1->numdev);
free(intvls);
}
int w1_read_all_sensors(w1_devlist_t *w1, time_t secs) {
int nv = 0, r;
if (w1->doread) {
w1_device_t *d;
int n;
if (w1->portnum == -1) {
if ((w1->portnum = owAcquireEx(w1->iface)) < 0) {
OWERROR_DUMP(stdout);
exit(1);
}
}
for (d = w1->devs, n = 0; n < w1->numdev; n++, d++) {
int k;
for (k = 0; k < d->ns; k++) {
d->s[k].valid = 0;
}
if (secs == 0 || d->intvl == 0 || ((secs % d->intvl) == 0)) {
int rtry;
for (rtry = 0; rtry < W1_RETRY; rtry++) {
switch (d->stype) {
case W1_TEMP:
r = w1_read_temp(w1, d);
break;
case W1_HUMID:
r = w1_read_humidity(w1, d);
break;
case W1_PRES:
r = w1_read_pressure(w1, d);
break;
case W1_COUNTER:
r = w1_read_counter(w1, d);
break;
case W1_BRAY:
r = w1_read_bray(w1, d);
break;
case W1_HBBARO:
r = w1_read_hb_pressure(w1, d);
break;
case W1_SHT11:
r = w1_read_sht11(w1, d);
break;
case W1_WINDVANE:
r = w1_read_windvane(w1, d);
break;
case W1_DS2438V:
r = w1_read_voltages(w1, d, NULL);
break;
case W1_HIH:
r = w1_read_hih(w1, d);
break;
case W1_DS2760:
r = w1_read_ds2760(w1, d);
break;
case W1_DS2450:
r = w1_read_ds2450(w1, d);
break;
case W1_MS_TC:
r = w1_read_current(w1, d);
break;
case W1_DS1921:
r = w1_read_ds1921(w1, d);
break;
case W1_DS1923:
r = w1_read_ds1923(w1, d);
break;
case W1_HBUV:
r = w1_read_hbuv(w1, d);
break;
case W1_HBHT:
r = w1_read_hbht(w1, d);
break;
case W1_INVALID:
default:
r = -1;
break;
}
if (r != 0)
break;
else {
w1_replog(w1, "retry %d %s", rtry, d->serial);
usleep(50 * 1000);
}
}
if (r >= 0) {
nv += r;
if (r == 0)
syslog(LOG_WARNING, "Failed to read sensor %s (type %s)", d->serial, d->devtype);
}
}
}
/* Put the bus back in a known state */
w1_all_couplers_off(w1);
}
return nv;
}
w1retap/src/w1util.c 0000664 0000000 0000000 00000020612 14464462352 0014634 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "w1retap.h"
char *w1_get_from_home(const char *f) {
char *fname = NULL;
char *p, *q;
if (NULL != f && NULL != (p = getenv("HOME"))) {
fname = malloc(strlen(p) + strlen(f) + 2);
q = stpcpy(fname, p);
*q++ = '/';
stpcpy(q, f);
}
return fname;
}
static w1_params_t *w1_dev_params(char *params) {
w1_params_t *p = NULL;
if (params) {
char *sp = strdup(params);
char *r, *s;
int j = 0;
// specificly use strtok() to elimiate repeated spaces
for (r = sp; (s = strtok(r, "|: ")); j++, r = NULL)
; // NULL loop to count entries;
free(sp);
if (j) {
sp = strdup(params);
// Not sizeof(int) + ... to avoid packing issues (ppc)
p = calloc(1, (sizeof(w1_params_t) + j * sizeof(double)));
p->num = j;
for (j = 0, r = sp; (s = strtok(r, "|: ")); r = NULL, j++) {
p->values[j] = strtod(s, NULL);
}
free(sp);
}
}
return p;
}
w1_sensor_t *w1_find_sensor(w1_devlist_t *w1, const char *s) {
w1_sensor_t *sensor = NULL;
w1_device_t *devs;
int i, j;
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) {
for (j = 0; j < devs->ns; j++) {
if (devs->s[j].abbrv && (0 == strcmp(devs->s[j].abbrv, s))) {
sensor = &devs->s[j];
break;
}
}
}
return sensor;
}
w1_sensor_t *w1_match_sensor(w1_device_t *dev, const char *s) {
w1_sensor_t *sensor = NULL;
int j;
for (j = 0; j < dev->ns; j++) {
if ((dev->s[j].abbrv && (strcasestr(dev->s[j].name, s) || strcasecmp(dev->s[j].abbrv, s) == 0))) {
sensor = &dev->s[j];
break;
}
}
return sensor;
}
int w1_get_device_index(w1_device_t *devs, int ndev, char *serno, char *devtype) {
int i;
int nn = -1;
for (i = 0; i < ndev; i++, devs++) {
if (strcmp(serno, devs->serial) == 0 && (devtype == NULL || strcmp(devtype, devs->devtype) == 0)) {
nn = i;
break;
}
}
return nn;
}
static void w1_alloc_sensor(w1_device_t *w1) {
if ((w1->ns % ALLOCSENS) == 0) {
w1->s = realloc(w1->s, (w1->ns + ALLOCSENS) * sizeof(w1_sensor_t));
memset(w1->s + w1->ns, 0, ALLOCSENS * sizeof(w1_sensor_t));
}
w1->ns += 1;
}
void w1_set_device_data_index(w1_device_t *w1, int idx, char *sv) {
if (sv) {
switch (idx) {
case 0:
w1->serial = sv;
break;
case 1:
w1->devtype = sv;
break;
case 2:
case 5:
w1_alloc_sensor(w1);
w1->s[w1->ns - 1].abbrv = sv;
break;
case 3:
case 6:
w1->s[w1->ns - 1].name = sv;
break;
case 4:
case 7:
w1->s[w1->ns - 1].units = sv;
break;
case 8:
w1->params = w1_dev_params(sv);
free(sv);
break;
case 9:
w1->intvl = strtol(sv, NULL, 10);
free(sv);
break;
default:
free(sv);
break;
}
}
}
void w1_set_device_data(w1_device_t *w1, const char *fnam, char *sv) {
if (0 == strcmp(fnam, "device")) {
w1->serial = sv;
} else if (0 == strcmp(fnam, "type") && w1->devtype == NULL) {
w1->devtype = sv;
} else if ((0 == strcmp(fnam, "abbrv1")) || (0 == strcmp(fnam, "abbrv2"))) {
w1_alloc_sensor(w1);
w1->s[w1->ns - 1].abbrv = sv;
} else if ((0 == strcmp(fnam, "name1")) || (0 == strcmp(fnam, "name2"))) {
w1->s[w1->ns - 1].name = sv;
} else if ((0 == strcmp(fnam, "units1")) || (0 == strcmp(fnam, "units2"))) {
w1->s[w1->ns - 1].units = sv;
} else if (0 == strcmp(fnam, "params")) {
w1->params = w1_dev_params(sv);
free(sv);
} else if (0 == strcmp(fnam, "interval")) {
w1->intvl = strtol(sv, NULL, 10);
free(sv);
} else {
free(sv);
}
}
void w1_enumdevs(w1_device_t *w) {
#define MATCHES(__p1) (strncasecmp(__p1, w->devtype, (sizeof(__p1) - 1)) == 0)
if (MATCHES("TEMPERATURE") || MATCHES("DS1820") || MATCHES("DS18S20")) {
w->stype = W1_TEMP;
} else if (MATCHES("HUMIDITY") || MATCHES("TAI8540")) {
w->stype = W1_HUMID;
} else if (MATCHES("PRESSURE") || MATCHES("TAI8570")) {
w->stype = W1_PRES;
} else if (MATCHES("RAIN") || MATCHES("COUNTER") || MATCHES("TAI8575") || MATCHES("DS2423")) {
w->stype = W1_COUNTER;
} else if (MATCHES("Bray") || MATCHES("MPX4115A")) {
w->stype = W1_BRAY;
} else if (MATCHES("sht11")) {
w->stype = W1_SHT11;
} else if (MATCHES("WINDVANE") || MATCHES("WEATHERVANE") || MATCHES("TAI8515")) {
w->stype = W1_WINDVANE;
} else if (MATCHES("Coupler") || MATCHES("DS2409")) {
w->stype = W1_COUPLER;
} else if (MATCHES("VOLTAGE") || MATCHES("DS2438")) {
w->stype = W1_DS2438V;
} else if (MATCHES("DS2760")) {
w->stype = W1_DS2760;
} else if (MATCHES("DS1921")) {
w->stype = W1_DS1921;
} else if (MATCHES("DS1923")) {
w->stype = W1_DS1923;
} else if (MATCHES("DS2450")) {
w->stype = W1_DS2450;
} else if (MATCHES("HB-BARO") || MATCHES("HB_BARO")) {
w->stype = W1_HBBARO;
} else if (MATCHES("HWHIH") || MATCHES("MS-TH")) {
w->stype = W1_HIH;
} else if (MATCHES("MS-TC")) {
w->stype = W1_MS_TC;
} else if (MATCHES("HB_UV") || MATCHES("HB-UV")) {
w->stype = W1_HBUV;
} else if (MATCHES("HB_HT") || MATCHES("HB-HT")) {
w->stype = W1_HBHT;
}
}
void w1_freeup(w1_devlist_t *w1) {
int i;
w1_device_t *dev = NULL;
void (*func)(void);
for (i = 0; i < w1->ndll; i++) {
if (w1->dlls[i].type == 'l' && NULL != w1->dlls[i].handle) {
if (g_module_symbol(w1->dlls[i].handle, "w1_cleanup", (void *)&func)) {
(func)();
}
}
}
for (dev = w1->devs, i = 0; i < w1->numdev; i++, dev++) {
int i;
if (dev->serial)
free(dev->serial);
if (dev->devtype)
free(dev->devtype);
for (i = 0; i < dev->ns; i++) {
if (dev->s[i].abbrv)
free(dev->s[i].abbrv);
if (dev->s[i].name)
free(dev->s[i].name);
if (dev->s[i].units)
free(dev->s[i].units);
}
if (dev->s)
free(dev->s);
if (dev->coupler)
free(dev->coupler);
if (dev->params)
free(dev->params);
if (dev->private)
free(dev->private);
}
free(w1->devs);
w1->numdev = 0;
w1->devs = NULL;
}
void logtimes(w1_devlist_t *w1, time_t now, char *tbuf) {
struct tm *tm;
tm = (w1->force_utc) ? gmtime(&now) : localtime(&now);
strftime(tbuf, TBUF_SZ, "%FT%T%z", tm);
}
void w1_tmpfilelog(w1_devlist_t *w1) {
char *line;
int n = 0;
int i;
w1_device_t *devs;
line = malloc(((w1->numdev) * 256 + 512));
if (line) {
*line = 0;
for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) {
if (devs->init) {
int j;
for (j = 0; j < devs->ns; j++) {
if (devs->s[j].valid) {
n += sprintf(line + n, "%s=%.2f %s\n", devs->s[j].abbrv, devs->s[j].value,
(devs->s[j].units) ? (devs->s[j].units) : "");
}
}
}
}
if (n) {
char tbuf[TBUF_SZ];
logtimes(w1, w1->logtime, tbuf);
n += sprintf(line + n, "udate=%lld\ndate=%s\n", (long long)w1->logtime, tbuf);
int fd = open(w1->tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0664);
flock(fd, LOCK_EX);
n = write(fd, line, n);
flock(fd, LOCK_UN);
close(fd);
}
free(line);
}
}
FILE *w1_file_open(char *logfile) {
FILE *lfp = NULL;
if (logfile == NULL) {
lfp = stdout;
setvbuf(lfp, (char *)NULL, _IOLBF, 0);
} else {
char md[2] = {"w"}, *pmd;
if (NULL != (pmd = strchr(logfile, ':'))) {
if (*(pmd + 1) == 'a') {
*md = 'a';
*pmd = '\0';
}
}
lfp = fopen(logfile, md);
if (pmd)
*pmd = ':';
}
return lfp;
}
w1retap/src/w1xml.c 0000664 0000000 0000000 00000010030 14464462352 0014450 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2005 Jonathan Hudson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
#include