pax_global_header00006660000000000000000000000064144644623520014524gustar00rootroot0000000000000052 comment=beaabb69e1dfd7f8d947f29c4e2b66ca9b40a8cf w1retap/000077500000000000000000000000001446446235200124535ustar00rootroot00000000000000w1retap/COPYING000066400000000000000000000431101446446235200135050ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. w1retap/README.md000066400000000000000000000074161446446235200137420ustar00rootroot00000000000000## w1retap - One wire sensor logging. w1retap is a system for logging data from a 1-wire weather sensors to either a relational database or files (or combination thereof). w1retap supports any (reasonable) number of following sensors from [AAG Electrónica (AAG)](http://www.aagelectronica.com/), based on [Dallas Semiconductors](http://www.dalsemi.com/) devices. * TAI8520 (DS1820 / DS18S20) Temperature sensors; * TAI8540B (DS2438) Humidity Sensor; * TAI8570 Pressure Sensor; * TAI8575 Rain Gauge; * TAI8515 Weather Station (DS2423,DS18S20,DS2450); * DS2409 Microlan coupler; * DS2490 USB adaptor; * DS2480 Serial adaptor. A number of other sensors, typically "hobby/build your own", are supported: * [SHT11 based humidity sensor](http://home.hetnet.nl/~thomas_7/1Wire/1-WireIOPort.html) * [MPX4115A based pressure sensor](http://home.comcast.net/~andrew.g.miller/barometer/) ('fronted' by DS2438). w1retap is designed to run on the Linux operating system and assumes that the interface between the computer and the 1-wire system is either a DS2490 USB adaptor (aka DS9490R) or a DS2480 RS232 serial adaptor (aka DS9097U-S09). w1retap also runs on FreeBSD. Logging is performed by one or more "plugin" modules, these currently include: Built in Modules: * Text file * CSV file Optional Modules: * Sqlite (version 3) * PostgreSQL * MariaDB (MySQL) * ODBC * XML file Note: You only need to install development packages for the optional storage module(s) you intend to use. Note that for MySQL compatible storage, you need to install one of the MariaDB or MySQL development packages. w1retap meson will detect the installed development package. ### Files: * src: Contains the w1retap software. * src/libusblinux300: The Dallas PD 1-wire SDK (modified to be 64 bit clean and support modern compilers) * doc: Documentation on configuring and using w1retap ## Installation * Development packages for the required storage backend (postgresql / sqlite3 / mariadb (mysql) / odbc / xml). * `libusb-1.0` * `meson` and `ninja` * `glib` / `gio` * C compiler (`gcc` or `clang`) Installation may either be to a user directory or system wide: ``` # user local meson setup _build --buildtype=release --strip --prefix=~/.local # system wide (/usr/bin etc). meson setup _ubuild --buildtype=release --strip --prefix=/usr/ # system wide (/usr/local/bin etc). meson setup _ubuild --buildtype=release --strip --prefix=/usr/local ``` Choose which ever suits; the user local build avoids the need for `sudo` / `doas`. **You may ignore meson "not found" messages for unwanted storage components.** ``` # user local build ninja -C _build #or # system build ninja -C _ubuild ``` ``` # user local install ninja -C _build install #or # system install sudo ninja -C _ubuild install ``` User local / install can be done in one step ``` ninja -C _build install ``` ### Installation paths * The applications `w1retap` and `w1find` are installed to `$prefix/bin/` * The project shared libraries are installed to `$prefix/lib/w1retap/` and the above executables have appropriate `RUNPATH` set. The demonstration / test programs in `src/libusblinux300` are not installed and their `RUNPATH` is set to `$ORIGIN` which means they can be run in-situ (e.g. from the build directory `_build/src/libusblinux300/`). These programs are not installed by default; if it is required to install them: * Copy the executable from `_build/src/libusblinux300/` to the required directory, e.g.: ``` install _build/src/libusblinux300/coupler ~/.local/bin/ ``` * Set `RUNPATH`, e.g: ``` patchelf --set-rpath '$ORIGIN/../lib/w1retap/' ~/.local/bin/coupler` ``` Note that Debian and derivatives may have added an 'arch' path (e.g. `../lib/x86_64-linux-gnu/w1retap/` (c) Jonathan Hudson Unless otherwise indicated, the package is released under the GNU Public Licence. w1retap/contrib/000077500000000000000000000000001446446235200141135ustar00rootroot00000000000000w1retap/contrib/scripts/000077500000000000000000000000001446446235200156025ustar00rootroot00000000000000w1retap/contrib/scripts/README000066400000000000000000000004351446446235200164640ustar00rootroot00000000000000Examples of log=w1file=|/path/to/script scripts to update the database with modified or derived values, or display data on external device. pert-log.rb: Display data on a Pertelian USB LCD device (via pertd2); wetbulb-snow.rb: Derive snow depth and wet bulb values from devices. w1retap/contrib/scripts/pert-log.rb000077500000000000000000000022121446446235200176600ustar00rootroot00000000000000#!/usr/bin/ruby log=nil FIFO='/tmp/pertd2.fifo' if File.pipe?(FIFO) if File.exists?('/tmp/.p.log') log='' end v=Array.new(6) ARGF.each do |l| log << l if log case l when /OTMP0\s+(\S+)\s+/ v[0] = "%5.1f" % $1.to_f when /GHT\s+(\S+)\s+/ v[1] = "%5.1f" % $1.to_f when /OTMP1\s+(\S+)\s+/ v[2] = "%5.1f" % $1.to_f when /OTMP2\s+(\S+)\s+/ v[3] = "%5.1f" % $1.to_f when /STMP1\s+(\S+)\s+/ v[4] = "%5.1f" % $1.to_f when /OPRS\s+(\S+)\s+/ v[5] = "%4.0f" % $1.to_f end end ln='' ln << "line1\n0\n==EOD==\nExtr #{v[0]} GHT #{v[1]}\n==EOD==\n" if(v[0] && v[1]) ln << "line2\n0\n==EOD==\nIntr #{v[2]} Gge #{v[3]}\n==EOD==\n" if(v[2] && v[3]) ln << "line3\n0\n==EOD==\nSoil #{v[4]} Pres #{v[5]}\n==EOD==\n"if(v[4] && v[5]) if ln.size > 0 begin fd=IO.sysopen(FIFO,File::WRONLY|File::NONBLOCK) IO.open(fd,'w') {|f| f.syswrite(ln) } rescue end end if log and log.size > 0 File.open('/tmp/.p.log','w'){|f| f.puts log} end end #12345678901234567890 #Extr xx.x GHT xx.x OTMP0 GHT #Intr xx.x Gge xx.x OTMP1 OTMP2 #Soil xx.x Pres xxxx STMP1 OPRS w1retap/contrib/scripts/wetbulb-snow.rb000077500000000000000000000026121446446235200205630ustar00rootroot00000000000000#!/usr/bin/ruby require 'dbi' include Math # Wet bulb temperature from # # t in °C, rh as % (0-100), pr as hPa def wettemp t,rh,pr e = (rh/100.0) * 0.611*exp(17.27*t/(t+237.3)) td = (116.9+237.3*log(e))/(16.78-log(e)) gamma = 0.000066*pr delta = 4098*e/(td+237.3)**2 tw = ((gamma*t)+(delta*td))/(gamma+delta) [td,tw] end def get_my_cnf u=p=nil File.open(File.join(ENV['HOME'],'.my.cnf')) do |f| f.each do |l| case l when /^user=(\S+)/ u=$1 when /^password=(\S+)/ p=$1 end break if u and p end end [u,p] end ts=t=pr=rh=nil snow=nil dsn = (ARGV[0] || 'dbi:Mysql:sensors-logger:localhost') ARGF.each do |l| case l when /(\S+)\s+AirTemperature\s+(\S+)\s+/ ts = $1 t = $2.to_f when /BrayBarometer\s+(\S+)\s+/ pr = $1.to_f when /RH\s+(\S+)\s+/ rh = $1.to_f when /(\S+)\s+VAD\s+(\S+)\s+/ snow = (10.075-($2.to_f))*24.6062992 ts=$1 unless ts end end if ts and (snow || (t and pr and rh)) user,pass=get_my_cnf if user if t dp,tw = wettemp t,rh,pr db = DBI.connect(dsn,user,pass) db.execute 'insert into readings(date,name,value) values (?,?,?)', ts,'WetBulb',("%.3f" % tw) end if snow db.execute 'insert into readings(date,name,value) values (?,?,?)', ts,'SnowDepth',("%.1f" % snow) end db.disconnect end end w1retap/contrib/solar-conv.rb000077500000000000000000000010451446446235200165260ustar00rootroot00000000000000#!/usr/bin/ruby # -*- coding: utf-8 -*- # Update record to convert HB Solar mV to W/m^2 and Lux values and add to document # format PGSQL. See also ARGF.each do |l| l = l.force_encoding("utf-8") rescue l l.chomp! stamp,name,value,units,timet = l.split(/\t/) if name == 'SOLAR' val = value.to_f wpm2 = val * 2.9682 lux = wpm2 / 0.0079 cmd = "update readings set wxdata['UVWPMSQ']='#{wpm2}', wxdata['UVLUX'] = '#{lux}' where date='#{stamp}';" system "psql wx -c \"#{cmd}\"" break end end w1retap/docs/000077500000000000000000000000001446446235200134035ustar00rootroot00000000000000w1retap/docs/45-w1retap.rules000066400000000000000000000003201446446235200162630ustar00rootroot00000000000000# udev rules file for w1retap2 # SUBSYSTEMS=="usb", GOTO="usb_w1_start" GOTO="usb_w1_end" LABEL="usb_w1_start" ATTRS{idVendor}=="04fa", ATTRS{idProduct}=="2490",GROUP="w1retap",MODE="0664" LABEL="usb_w1_end" w1retap/docs/Makefile000066400000000000000000000014161446446235200150450ustar00rootroot00000000000000 SRC := $(wildcard *.adoc) IMGS = OUTDIR=. OPTPDF=$(OUTDIR)/w1retap.pdf PDF=$(OUTDIR)/w1retap_.pdf ODT=$(OUTDIR)/w1retap.odt HTML=$(OUTDIR)/w1retap.html RES=resources/theme.yml w1OPTS=-a pdf-theme=resources/theme.yml -a pdf-fontsdir=/usr/share/fonts/noto .PHONY: all all: $(OPTPDF) .PHONY: pdf pdf: $(OPTPDF) $(OPTPDF): $(SRC) $(RES) $(IMGS) asciidoctor-pdf $(w1OPTS) -o $(OPTPDF) $(SRC) -hexapdf optimize --compress-pages --force $(OPTPDF) $(OPTPDF) .PHONY: html html: $(HTML) $(HTML): $(SRC) $(RES) $(IMGS) asciidoctor-pdf --backend=html5 -o $(HTML) $(SRC) .PHONY: odt odt: $(ODT) $(ODT): $(SRC) $(RES) $(IMGS) asciidoctor-pdf --backend=docbook -o - $(SRC) | \ pandoc --from docbook --to odt --output $(ODT) - clean: @rm -f w1retap.pdf w1retap.html w1retap.odt w1retap/docs/README.md000066400000000000000000000011071446446235200146610ustar00rootroot00000000000000In order to avoiding forcing the installation of `asciidoctor-pdf`, only the source asciidoc file is installed. `w1retap` [user guide](w1retap.adoc), `asciidoc` format. A Makefile exists here to build the user guide. The PDF may be generated by: ``` asciidoctor-pdf w1retap.adoc ``` or (styled, optimised), recommended: ``` make ``` The `Makefile` generated a PDF; optionally an optimised PDF (optimised requires `hexapdf`, `sudo gem install --no-user-instal hexapdf`). In addition to the default `pdf` target, the `Makefile` also offers a `html` target. ``` make html ``` w1retap/docs/daria.co.uk-multi.sql000066400000000000000000000051531446446235200173560ustar00rootroot00000000000000--- PostreSQL CREATE TABLE w1sensors ( device text NOT NULL, type text, abbrv1 text, name1 text, units1 text, abbrv2 text, name2 text, units2 text, params text, id serial ); INSERT INTO w1sensors VALUES ('21351B0100204F91', 'DS1921', 'IBTN-H', 'iButton Temp', '°C', NULL, NULL, NULL, NULL, 27); INSERT INTO w1sensors VALUES ('105EE02301080039', 'DS1820', 'STMP1', 'Soil Temperature', '°C', NULL, NULL, NULL, NULL, 11); INSERT INTO w1sensors VALUES ('286DA467000000AD', 'DS1820', 'GHT', 'Greenhouse Temperature', '°C', NULL, NULL, NULL, NULL, 12); INSERT INTO w1sensors VALUES ('12FC6B34000000A9', 'TAI8570', 'OPRS', 'Pressure', 'hPa', 'OTMP1', 'House Temperature', '°C', NULL, 13); INSERT INTO w1sensors VALUES ('26378851000000AB', 'TAI8540', 'OHUM', 'Humidity', '%', 'OTMP0', 'Outside Temperature', '°C', NULL, 14); INSERT INTO w1sensors VALUES ('1D9BB10500000089', 'TAI8575', 'RGC0', 'Counter0', 'tips', 'RGC1', 'Counter1', 'tips', NULL, 15); INSERT INTO w1sensors VALUES ('10A942C10008009B', 'DS1820', 'OTMP2', 'Garage Temperature', '°C', NULL, NULL, NULL, NULL, 16); INSERT INTO w1sensors VALUES ('261755B600000060', 'DS2438', 'SOLAR', 'Solar (Vsens)', 'mV', 'VTMP', 'Temperature GHT2', '°C', NULL, 17); INSERT INTO w1sensors VALUES ('1FEDCB0300000000', 'DS2409', 'MAIN', '1D9BB10500000089', NULL, 'AUX', '10A942C10008009B', NULL, NULL, 20); INSERT INTO w1sensors VALUES ('1F1CE7030000009C', 'DS2409', 'MAIN', '105EE02301080039', NULL, NULL, NULL, NULL, NULL, 22); INSERT INTO w1sensors VALUES ('1F1CE7030000009C', 'DS2409', 'MAIN', '286DA467000000AD', NULL, NULL, NULL, NULL, NULL, 23); INSERT INTO w1sensors VALUES ('1F1CE7030000009C', 'DS2409', 'MAIN', '261755B600000060', NULL, NULL, NULL, NULL, NULL, 24); INSERT INTO w1sensors VALUES ('1F1CE7030000009C', 'DS2409', 'MAIN', '1093AEC100080042', NULL, NULL, NULL, NULL, NULL, 25); INSERT INTO w1sensors VALUES ('1F1CE7030000009C', 'DS2409', 'MAIN', '10E3EA23010800C9', NULL, NULL, NULL, NULL, NULL, 26); INSERT INTO w1sensors VALUES ('1093AEC100080042', 'DS1820', 'ITMP2', 'Propagator2 Temperature', '°C', NULL, NULL, NULL, NULL, 18); INSERT INTO w1sensors VALUES ('10E3EA23010800C9', 'DS1820', 'ITMP1', 'Propagator1 Temperature', '°C', NULL, NULL, NULL, NULL, 19); INSERT INTO w1sensors VALUES ('2113DD1800000046', 'DS1921', 'IBTN-G', 'iButton Temp', '°C', NULL, NULL, NULL, NULL, 30); INSERT INTO w1sensors VALUES ('1FF9E60300000093', 'DS2409', 'MAIN', '26378851000000AB', NULL, 'AUX', '109F7724010800F1', NULL, NULL, 21); INSERT INTO w1sensors VALUES ('109F7724010800F1', 'DS1820', 'CFRAME1', 'Cold Frame Temperature', '°C', NULL, NULL, NULL, NULL, 33); w1retap/docs/daria.co.uk-single.sql000066400000000000000000000042731446446235200175070ustar00rootroot00000000000000--- SQLite3 syntax CREATE TABLE w1sensors ( device text NOT NULL, type text, abbrv1 text, name1 text, units1 text, abbrv2 text, name2 text, units2 text, params text, interval integer, id integer primary key AUTOINCREMENT ); INSERT INTO w1sensors VALUES('105EE02301080039','DS1820','STMP1','Soil Temperature','°C',NULL,NULL,NULL,NULL,NULL,11); INSERT INTO w1sensors VALUES('286DA467000000AD','DS1820','GHT','Greenhouse Temperature','°C',NULL,NULL,NULL,NULL,NULL,12); INSERT INTO w1sensors VALUES('12FC6B34000000A9','TAI8570','OPRS','Pressure','hPa','OTMP1','House Temperature','°C',NULL,NULL,13); INSERT INTO w1sensors VALUES('26378851000000AB','TAI8540','OHUM','Humidity','%','OTMP0','Outside Temperature','°C',NULL,NULL,14); INSERT INTO w1sensors VALUES('1D9BB10500000089','TAI8575','RGC0','Counter0','tips','RGC1','Counter1','tips',NULL,NULL,15); INSERT INTO w1sensors VALUES('10A942C10008009B','DS1820','OTMP2','Garage Temperature','°C',NULL,NULL,NULL,NULL,NULL,16); INSERT INTO w1sensors VALUES('261755B600000060','DS2438','SOLAR','Solar (Vsens)','mV','VTMP','Temperature GHT2','°C',NULL,NULL,17); INSERT INTO w1sensors VALUES('1093AEC100080042','DS1820','ITMP2','Propagator2 Temperature','°C',NULL,NULL,NULL,NULL,NULL,18); INSERT INTO w1sensors VALUES('10E3EA23010800C9','DS1820','ITMP1','Propagator1 Temperature','°C',NULL,NULL,NULL,NULL,NULL,19); INSERT INTO w1sensors VALUES('1FEDCB0300000000','DS2409','MAIN','1D9BB10500000089',NULL,'AUX','10A942C10008009B',NULL,NULL,NULL,20); INSERT INTO w1sensors VALUES('1FF9E60300000093','DS2409','MAIN','26378851000000AB',NULL,'AUX','109F7724010800F1',NULL,NULL,NULL,21); INSERT INTO w1sensors VALUES('1F1CE7030000009C','DS2409','MAIN','105EE02301080039 286DA467000000AD 261755B600000060 1093AEC100080042 10E3EA23010800C9',NULL,NULL,NULL,NULL,NULL,NULL,22); INSERT INTO w1sensors VALUES('21351B0100204F91','DS1921','IBTN-H','iButton Temp','°C',NULL,NULL,NULL,NULL,NULL,27); INSERT INTO w1sensors VALUES('2113DD1800000046','DS1921','IBTN-G','iButton Temp','°C',NULL,NULL,NULL,NULL,NULL,30); INSERT INTO w1sensors VALUES('109F7724010800F1','DS1820','CFRAME1','Cold Frame Temperature','°C',NULL,NULL,NULL,NULL,NULL,33); w1retap/docs/daria.co.uk.sql000066400000000000000000000041161446446235200162240ustar00rootroot00000000000000 INSERT INTO station (name, stnlat, stnlong, altitude, location, software, url, wu_user, wu_pass, rfact, cwop_user, cwop_pass) VALUES ('Jonathan & Daria''s Weather Station', 50.915321, -1.53036, 19, 'Netley Marsh', 'w1retap', 'http://www.daria.co.uk/wx/', 'wuser', 'wpass', 0.0105, 'cwopuser', 'cwoppass'); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('286DA467000000AD', 'DS1820', 'GHT', 'Greenhouse Temperature', '°C', NULL, NULL, NULL, NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('10A942C10008009B', 'DS1820', 'OTMP0', 'Outside Temperatue', '°C', NULL, NULL, NULL, NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('1093AEC100080042', 'DS1820', 'XTMP2', 'Garage Temperature', '°C', NULL, NULL, NULL, NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('26378851000000AB', 'TAI8540', 'OHUM', 'Humidity', '%', 'OTMP2', 'Garage Temperature', '°C', NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('12FC6B34000000A9', 'TAI8570', 'OPRS', 'Pressure', 'hPa', 'OTMP1', 'Temperature', '°C', NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('1D9BB10500000089', 'TAI8575', 'RGC0', 'Counter0', ' tips', 'RGC1', 'Counter1', 'tips', NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('GHT', 2.5, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OTMP0', 2.5, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OTMP1', 2.5, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OPRS', 100, 800, 1200); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('RGC0', 50, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('RGC1', 50, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OTMP2', 2.5, -10, 50); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OHUM', 7, 0, 100.04); w1retap/docs/example-rc-file000066400000000000000000000016241446446235200163030ustar00rootroot00000000000000# Init file - examples #device = DS2490-1 #device = /dev/ttyUSB0 altitude = 19 timestamp = 1 log_delimiter = \t log_time_t = Y release_if = Y #pressure_reduction_temp = 15.0 allow_rate_escape = Y init = libw1pgsql.so=dbname=sensors user=luser host=jagular #log = w1mysql=dbname=wx host=arch-test user=luser password=luser #init = libw1mysql.so=dbname=sensors user=luser host=arch-vm #init = w1sqlite=/home/luser/Projects/wxtest/wx.sqlite #init = ./.libs/libw1file.so #init = libw1odbc.so=DSN=w1stn #init = libw1pgsql.so=dbname=w1retap user=luser host=woozle #log = w1pgsql=dbname=sensors user=luser host=localhost log = w1file=/tmp/w1retap.log #log = w1mysql=dbname=w1stn user=w1stn host=tigger password=sososecret #log = w1sqlite=/opt/misc/sensors.db #log = w1xml=/tmp/w1xmls.log #log = w1csv #rep = w1pgsql=dbname=sensors user=luser #rep = w1file=/tmp/w1rep.log pidfile = /tmp/w1retap.pid force_utc = 1 w1retap/docs/hb-rain-cables.txt000066400000000000000000000004021446446235200167070ustar00rootroot00000000000000When we put together the Rain Gauge it is hooked up as follows: The reed switch goes between B and +5v The cable coming into the Rain Gauge has a copper and a silver wire. The copper goes to DQ and the silver goes to GND. Let me know if that helped. Eric w1retap/docs/meson.build000066400000000000000000000001551446446235200155460ustar00rootroot00000000000000install_data([ 'w1retap.adoc', 'example-rc-file'], install_dir : get_option('datadir') / 'doc' / 'w1retap' ) w1retap/docs/mksens.sql000066400000000000000000000012241446446235200154230ustar00rootroot00000000000000CREATE TABLE ratelimit ( name text, value real, rmax real, rmin real ); CREATE TABLE readings ( date integer, name text, value real ); CREATE TABLE replog ( date timestamp with time zone, message text ); CREATE TABLE station ( name text, stnlat real, stnlong real, altitude real, location text, software text, url text, wu_user text, wu_pass text, rfact real, 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/docs/mksenst-mysql.sql000066400000000000000000000017441446446235200167610ustar00rootroot00000000000000drop table if exists ratelimit; CREATE TABLE ratelimit ( name text, value real, rmax real, rmin real ); drop table if exists readings; CREATE TABLE readings ( date timestamp, name text, value real, id integer auto_increment primary key ); drop table if exists replog; CREATE TABLE replog ( id integer auto_increment primary key, date timestamp, message text ); drop table if exists station; CREATE TABLE station ( name text, stnlat real, stnlong real, altitude real, location text, software text, url text, wu_user text, wu_pass text, rfact real, cwop_user text, cwop_pass text, lcdon integer, lcdoff integer ); drop table if exists w1sensors; CREATE TABLE w1sensors ( id integer auto_increment primary key, device text, type text, abbrv1 text, name1 text, units1 text, abbrv2 text, name2 text, units2 text, params text, `interval` integer ); w1retap/docs/mksenst.sql000066400000000000000000000012461446446235200156130ustar00rootroot00000000000000CREATE TABLE ratelimit ( name text, value real, rmax real, rmin real ); CREATE TABLE readings ( date timestamp with time zone, name text, value real ); CREATE TABLE replog ( date timestamp with time zone, message text ); CREATE TABLE station ( name text, stnlat real, stnlong real, altitude real, location text, software text, url text, wu_user text, wu_pass text, rfact real, 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/docs/resources/000077500000000000000000000000001446446235200154155ustar00rootroot00000000000000w1retap/docs/resources/theme.yml000066400000000000000000000202201446446235200172360ustar00rootroot00000000000000font: catalog: # Noto Serif supports Latin, Latin-1 Supplement, Latin Extended-A, Greek, Cyrillic, Vietnamese & an assortment of symbols Noto Sans: normal: NotoSans-Regular.ttf bold: NotoSans-Bold.ttf italic: NotoSans-Italic.ttf bold_italic: NotoSans-BoldItalic.ttf Noto Mono: normal: NotoSansMono-Regular.ttf bold: NotoSansMono-Bold.ttf fallbacks: - Noto Mono page: background_color: ffffff layout: portrait margin: [0.5in, 0.67in, 0.67in, 0.67in] # margin_inner and margin_outer keys are used for recto/verso print margins when media=prepress margin_inner: 0.75in margin_outer: 0.59in size: A4 base: align: justify # color as hex string (leading # is optional) font_color: 333333 # color as RGB array #font_color: [51, 51, 51] # color as CMYK array (approximated) #font_color: [0, 0, 0, 0.92] #font_color: [0, 0, 0, 92%] font_family: Noto Sans # choose one of these font_size/line_height_length combinations #font_size: 14 #line_height_length: 20 #font_size: 11.25 #line_height_length: 18 #font_size: 11.2 #line_height_length: 16 #font_size: 10.5 #line_height_length: 15 # correct line height for Noto Serif metrics #line_height_length: 12 #font_size: 11.25 #line_height_length: 18 font_size: 9 line_height_length: 10 line_height: $base_line_height_length / $base_font_size font_size_large: round($base_font_size * 1.25) font_size_small: round($base_font_size * 0.75) font_size_min: $base_font_size * 0.5 font_style: normal border_color: eeeeee border_radius: 4 border_width: 0.5 # FIXME vertical_rhythm is weird; we should think in terms of ems #vertical_rhythm: $base_line_height_length * 2 / 3 # correct line height for Noto Serif metrics (comes with built-in line height) vertical_rhythm: $base_line_height_length horizontal_rhythm: $base_line_height_length # QUESTION should vertical_spacing be block_spacing instead? vertical_spacing: $vertical_rhythm link: font_color: 428bca # literal is currently used for inline monospaced in prose and table cells literal: font_color: 323234 font_family: Noto Mono font_size_small: round($base_font_size * 0.85) menu_caret_content: " \u203a " heading: align: left #font_color: 181818 font_color: $base_font_color font_family: $base_font_family font_style: bold # h1 is used for part titles (book doctype only) h1_font_size: floor($base_font_size * 2.6) # h2 is used for chapter titles (book doctype only) h2_font_size: floor($base_font_size * 2.15) h3_font_size: round($base_font_size * 1.7) h4_font_size: $base_font_size_large h5_font_size: $base_font_size h6_font_size: $base_font_size_small #line_height: 1.4 # correct line height for Noto Serif metrics (comes with built-in line height) line_height: 1 margin_top: $vertical_rhythm * 0.4 margin_bottom: $vertical_rhythm * 0.9 title_page: align: right logo: top: 10% title: top: 55% font_size: $heading_h1_font_size font_color: 999999 line_height: 0.9 subtitle: font_size: $heading_h3_font_size font_style: bold_italic line_height: 1 authors: margin_top: $base_font_size * 1.25 font_size: $base_font_size_large font_color: 181818 revision: margin_top: $base_font_size * 1.25 block: margin_top: 0 margin_bottom: $vertical_rhythm caption: align: left font_size: $base_font_size * 0.95 font_style: italic # FIXME perhaps set line_height instead of / in addition to margins? margin_inside: $vertical_rhythm / 3 #margin_inside: $vertical_rhythm / 4 margin_outside: 0 lead: font_size: $base_font_size_large line_height: 1.4 abstract: font_color: 5c6266 font_size: $lead_font_size line_height: $lead_line_height font_style: italic first_line_font_style: bold title: align: center font_color: $heading_font_color font_family: $heading_font_family font_size: $heading_h4_font_size font_style: $heading_font_style admonition: column_rule_color: $base_border_color column_rule_width: $base_border_width padding: [0, $horizontal_rhythm, 0, $horizontal_rhythm] #icon: # tip: # name: fa-lightbulb-o # stroke_color: 111111 # size: 24 label: text_transform: uppercase font_style: bold blockquote: font_color: $base_font_color font_size: $base_font_size_large border_color: $base_border_color border_width: 5 # FIXME disable negative padding bottom once margin collapsing is implemented padding: [0, $horizontal_rhythm, $block_margin_bottom * -0.75, $horizontal_rhythm + $blockquote_border_width / 2] cite_font_size: $base_font_size_small cite_font_color: 999999 # code is used for source blocks (perhaps change to source or listing?) code: font_color: $base_font_color font_family: $literal_font_family font_size: ceil($base_font_size) font_size_small: round($base_font_size * 0.75) padding: $code_font_size #line_height: 1.25 # line_gap is an experimental property to control how a background color is applied to an inline block element line_gap: 3.8 background_color: f5f5f5 border_color: cccccc border_radius: $base_border_radius border_width: 0.75 conum: font_family: M+ 1mn font_color: $literal_font_color font_size: $base_font_size line_height: 4 / 3 example: border_color: $base_border_color border_radius: $base_border_radius border_width: 0.75 background_color: ffffff # FIXME reenable padding bottom once margin collapsing is implemented padding: [$vertical_rhythm, $horizontal_rhythm, 0, $horizontal_rhythm] image: align: left prose: margin_top: $block_margin_top margin_bottom: $block_margin_bottom sidebar: background_color: eeeeee border_color: e1e1e1 border_radius: $base_border_radius border_width: $base_border_width # FIXME reenable padding bottom once margin collapsing is implemented padding: [$vertical_rhythm, $vertical_rhythm * 1.25, 0, $vertical_rhythm * 1.25] title: align: center font_color: $heading_font_color font_family: $heading_font_family font_size: $heading_h4_font_size font_style: $heading_font_style thematic_break: border_color: $base_border_color border_style: solid border_width: $base_border_width margin_top: $vertical_rhythm * 0.5 margin_bottom: $vertical_rhythm * 1.5 description_list: term_font_style: bold term_spacing: $vertical_rhythm / 4 description_indent: $horizontal_rhythm * 1.25 outline_list: indent: $horizontal_rhythm * 1.5 #marker_font_color: 404040 # NOTE outline_list_item_spacing applies to list items that do not have complex content item_spacing: $vertical_rhythm / 2 table: background_color: $page_background_color #head_background_color: #head_font_color: $base_font_color head_font_style: bold #body_background_color: body_stripe_background_color: f9f9f9 foot_background_color: f0f0f0 border_color: dddddd border_width: $base_border_width cell_padding: 3 caption: side: bottom toc: indent: $horizontal_rhythm line_height: 1.4 dot_leader: #content: ". " font_color: a9a9a9 #levels: 2 3 # NOTE in addition to footer, header is also supported footer: font_size: $base_font_size_small # NOTE if background_color is set, background and border will span width of page border_color: dddddd border_width: 0.25 height: $base_line_height_length * 2.5 line_height: 1 padding: [$base_line_height_length / 2, 1, 0, 1] vertical_align: top #image_vertical_align: or # additional attributes for content: # * {page-count} # * {page-number} # * {document-title} # * {document-subtitle} # * {chapter-title} # * {section-title} # * {section-or-chapter-title} recto: #columns: "<50% =0% >50%" right: content: '{page-number}' #content: '{section-or-chapter-title} | {page-number}' #content: '{document-title} | {page-number}' #center: # content: '{page-number}' verso: #columns: $footer_recto_columns left: content: $footer_recto_right_content #content: '{page-number} | {chapter-title}' #center: # content: '{page-number}' role: cert: font_family: Noto Mono font_size: round($base_font_size * 0.8) w1retap/docs/systemd/000077500000000000000000000000001446446235200150735ustar00rootroot00000000000000w1retap/docs/systemd/w1retap.service000066400000000000000000000004651446446235200200450ustar00rootroot00000000000000[Unit] Description=w1retap Requires=postgresql.service After=postgresql.service [Service] Type=forking User=w1retap Group=w1retap ExecStart=/usr/bin/w1retap -d -R -t 120 -r /tmp/w1-replog.txt ExecStop=/bin/kill $MAINPID Restart=always ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target w1retap/docs/w1retap.adoc000066400000000000000000001574401446446235200156310ustar00rootroot00000000000000= w1retap Jonathan Hudson :w1retap: https://codeberg.org/stronnag/w1retap[w1retap] == Introduction https://codeberg.org/stronnag/w1retap[w1retap] is a "one-wire" sensor logging application. === Overview {w1retap} supports any number of the following sensors / devices from AAG Electrónica (AAG) based on http://www.dalsemi.com/[Dallas Semiconductors] devices: * TAI8520 (DS1820 / DS18S20) Temperature sensors * TAI8540B (DS2438) Humidity Sensor * TAI8570 Pressure Sensor (DS2406) * TAI8575 Rain Gauge (DS2423 Counter) * TAI8515 Weather Station (DS2423,DS18S20,DS2450) * DS2409 Microlan coupler * DS2760 voltage / current / temperature * DS2450 Quad A/D Converter * DS2490 USB adaptor * DS1921 Thermochron, instantaneous temperature only * DS1923 Hygrochron, instantaneous temperature and humidity only * DS2480 Serial adaptor * LinkUSB adaptor. {w1retap} also supports a number of other sensors, typically "hobby/build your own" and some products from https://hobbyboards.com/[HobbyBoards]: * SHT11 based humidity sensor * MPX4115A based pressure sensor (via DS2438) * MS-TH Humidity sensors (and temperature) based on DS2438 / Honeywell HiH400). This also supports the (old) Hobby Boards Humidity / Temperature sensor * The new Hobby Boards Humidity / Temperature sensor * The Hobby Boards Pressure sensor * The Hobby Boards Solar sensor (and permutations) * The Hobby Boards UltraViolet sensor * The iButton MS-TC Temperature and Current sensor. {w1retap} is flexible in the way that 1-wire sensor data is logged; a system of "plugin" modules allow the user to choose the most appropriate logging method. Currently supported logging modules are: * Sqlite3 * PostgreSQL * MariaDB (MySQL) * ODBC * Text file * CSV file * XML file. {w1retap} is designed to run on the Linux and FreeBSD operating systems and requires that the interface between the computer and the 1-wire system is either a DS2490 USB adaptor or a DS2480 RS232 serial adaptor (or compatible). Porting to any other operating system that supports the above hardware, the GCC 'C' compiler and dynamically loadable modules should also be possible. {w1retap} is known to build and run on arm32, arm64, ia32, riscv64 and x86_64 architectures. A modified Dallas public domain 1-wire SDK is included in its entirety in the project. {w1retap} installation includes a program `w1find` which detects devices on the 1-wire network and may be used as a basis for the sensor configuration table / file. This document is applicable to the {w1retap} 1.5.0 (and later). === Organisation of the w1retap project The {w1retap} project is organised into a number of sub-directories: src:: Contains the {w1retap} source code src/libusblinux300:: Holds the (modified) Dallas PD 1-wire SDK doc:: Documentation on configuring and using {w1retap} contrib/scripts:: Contains some example scripts referenced in this document. === Installation ==== Prerequisite - Choosing the logging method Installation of {w1retap} requires that the software is xref:#_build_process[compiled from source], you may first wish to decide which backend logging modules you are going to use (however the build system will build all those it can on your machine). These are build as loadable modules (shared libraries) and include: [%autowidth] |=== | Usage | Configuration Name | Built Module | Sqlite (version 3) | `w1sqlite` | `libw1sqlite.so` | PostgreSQL| `w1pgsql` | `libw1pgsql.so` | MariaDB, MySQL | `w1mysql` | `libw1mysql.so` | ODBC | `w1odbc` | `libw1odbc.so` | Plain Text | `w1file` | `libw1file.so` | CSV File | `w1csv` | `libw1csv.so` | XML File | `w1xml` | `libw1xml.so` |=== For each of the RDBMS loggers, you will need to have the relevant development package (header files and libraries installed). The file based modules have no external dependencies (other than `libxml2` for `w1xml`), and you can always use `libw1file.so` , as this can also provide fall back configuration data. ==== USB Package It is necessary to install the development package for `libusb-1.0`. ==== Build Process {w1retap} uses `meson` and in theory will detect the features that it can build on your machine. Backends can be installed and configured while {w1retap} is running, so you might as well build all you may ever need, assuming you have the dependencies satisfied. ==== Build and install {w1retap} can be installed to a system directory, or to a user local location. To configure the {w1retap} build, issue one of the following commands (a one-off): ---- # user local meson setup _build --buildtype=release --strip --prefix=~/.local ---- ---- # system wide (/usr/bin etc). meson setup _ubuild --buildtype=release --strip --prefix=/usr/ or # system wide (/usr/local/bin etc) meson setup _ubuild --buildtype=release --strip ---- Then to build and install: ---- # user local build ninja -C _build ninja -C _build install # note if you always wish to install, just use the second command, which builds and installs ---- ---- # system build ninja -C _ubuild # then to install sudo ninja -C _ubuild install ---- === Configuration ==== Configuration Essentials The configuration comprises two areas: * Configuration of the 1-wire sensors. This may be file based or in a relational database; * Configuration of the application. The user running {w1retap} may create a configuration file in their home directory under `.config/w1retap` (`mkdir -p ~/.config/w1retap`), or; * Alternately, a system wide configuration file, `/etc/defaults/w1retap` may be used. The environment variable `W1RCFILE` may define the full path of a configuration file. Use of `W1RCFILE` allows alternate configurations for testing. The `~/.config/w1retap` directory should contain the file `rc` which configures the application and optionally, `sensors` which defines the 1-wire sensors (unless the sensors are defined in a RDBMS). If you are using a data base for logging, it is recommended that you also use it to store the configuration. ==== Creating the database If you're using an RDBMS for logging, create the RDBMS from the `docs/mksens.sql` or `docs/mksenst.sql` (depending on how you which to store timestamps) files, for example: ---- $ sqlite3 /var/tmp/sensors.db < mksens.sql ---- ---- $ psql create database w1retap \c w1retap \i mksenst.sql \q ---- ---- $ mysql create database w1retap use w1retap source mksens.sql quit ---- NOTE: MySQL uses a somewhat strange SQL syntax, and you may need to modify the template files (or the above MySQL example). === Configuration of sensors {w1retap} supports any number of the following sensors from AAG Electrónica (AAG) and others, based on Dallas Semiconductors devices. The following devices require configuration. * TAI8520 (DS1820 / DS18S20) Temperature sensors * TAI8540B (DS2438) Humidity Sensor * TAI8570 Pressure Sensor * TAI8575 Rain Gauge * TAI8515 Weather Station (Wind Vane) * DS2760 voltage / current / temperature * DS2450 Quad A/D Converter * DS2409 Microlan coupler * DS1921 Thermochron, instantaneous temperature only * DS1923 Hygrochron, instantaneous temperature and humidity only * SHT11 Humidity sensor * MPX4115A based pressure sensor ('fronted' by DS2438) * MS-TH Humidity sensors (and temperature) based on DS2438 / Honeywell HiH400). This also supports the Hobby Boards Humidity / Temperature sensor * The Hobby Boards Pressure sensor * The Hobby Boards Solar sensor * The Hobby Boards UV sensor * iButton MS-TC Current / Temperature sensor. Sensors are not completely auto-detected. You need to either populate the w1sensors table in the RDBMS or create a delimited configuration file `~/.config/w1retap/sensors`. The `w1sensors` table and the `~/.config/w1retap/sensors` file both contain the same information, for the table (sqlite3 quoting): ---- CREATE TABLE `w1sensors` ( `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, `device` text NOT NULL, `type` text, `abbrv1` text, `name1` text, `units1` text, `abbrv2` text, `name2` text, `units2` text, `params` text, `interval` integer); ); ---- id:: Optional primary key device:: The device address. If you have sensors from AAG, then the address will be printed on the case, otherwise, you can use the **w1find** program to detect the devices. type:: A description of the sensor type. This defines how {w1retap} will access the device. One of: + * `DS1820` (DS1820/DS18S20/DS1920 Temperature sensors) * `TAI8540` (AAG Humidity sensors) * `TAI8570` (AAG Pressure sensors) * `TAI8575` (AAG Rain Gauge) * `SHT11` (SHT11 Humidity sensors) * `MPX4115A` (“Bray” barometer) * `TAI8515` (“Weather” station) * `DS2409` (Microlan coupler) * `DS2450` (Quad A / D Converter) * `DS2438` (raw voltages) * `HB-BARO` (Hobby Board Barometer) * `MS-TH` or `HWHIH` (MS-TH / Honeywell humidity sensors) * `DS2760` voltage / current / temperature sensor (high-precision li+ battery monitor) * `DS1921` Thermochron * `DS1923` Hygrochron * `MS-TC` (iButton Current / Temperature) * `HB-UV` (Hobby Boards UV) * `HB-HT` (Hobby Boards HT (new board c. 2015)) name:: An arbitrary name of a function of the device. abbrv:: A unique abbreviation (essentially a key) that identifies the device readings in the database. units:: The units that the device records. params:: Any special parameters used by the application to convert readings from the device to meteorological data. This is typically required for some pressure sensors. interval:: Optional, defines the polling interval for the sensor. During early development, it was erroneously assumed that each device supports one or two functions, each of these is identified by an arbitrary name, an arbitrary (but unique) abbreviation and the units of measurement that the device records in. The presence of the abbreviation field determines if that specific function is logged. Where a device supports two or more functions, for example humidity and temperature, or pressure and temperature, then it is a requirement that the 'name' field describes the function. Where a device supports more than two functions, it is just necessary to add any additional definition with the same device name and device type for those additional functions. This allows the voltages from a DS2438 incorporated in a humidity sensor to be logged, or the four functions from a DS2760. TIP: TAI8570 Pressure Sensor. This actually contains two 1-wire devices, we need to specify the address of the "reader" device. As well as being printed on the case, this was the first address found by the `w1find` program. There have been reports that the address printed on the cases of some devices in not the “reader “ device; the solution is simple ... `w1find` will find both addresses, if one doesn't work the try the other one. So a configuration for this device is: [%autowidth] |=== | Key | Value | device | `12FC6B34000000A9` | type | `TAI8570` | abbrv1 | `OPRS` | name1 | `Pressure` | units1 | `hPa` | abbrv2 | `OTMP1` | name2 | `Temperature` | units2 | `°C` |=== This information may either be stored in a database in the w1sensors table, or in the `.config/w1retap/sensors` text file (as : or | delimited values): SQL: ---- INSERT INTO w1sensors VALUES(0,'26378851000000AB','DS2438','OTMP1','House Temperature','°C',NULL,NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES(1,'265066B5000000D2','HB-BARO','OPRS','Pressure','hPa',NULL,NULL,NULL,'22.4077 900.3',NULL); INSERT INTO w1sensors VALUES(2,'105EE02301080039','DS1820','STMP1','Soil Temperature','°C',NULL,NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES(3,'286DA467000000AD','DS1820','GHT','Greenhouse Temperature','°C',NULL,NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES(4,'2665E1F1000000A0','_DS2438_','SOLAR','Solar (Vsens)','mV','SVDD','Solar (vdd)','volts',NULL,NULL); INSERT INTO w1sensors VALUES(5,'10A942C10008009B','DS1820','OTMP2','Garage Temperature','°C', NULL,NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES(6,'1D4A1B0B000000E1','DS2423','RGC1','Counter1','tips', 'RGC0','Counter0','tips','16218 2152',NULL); INSERT INTO w1sensors VALUES(7,'26FD57E700000052','HWHIH','OHUM','Humidity','%','OTMP0','H Temperature','°C',NULL,NULL); INSERT INTO w1sensors VALUES(8,'109F7724010800F1','DS1820','CFRAME1','Cold Frame Temperature','°C',NULL,NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES(10,'1F1CE7030000009C','DS2409','MAIN','265066B5000000D2',NULL,'AUX','105EE02301080039 286DA467000000AD 2665E1F1000000A0',NULL,NULL,NULL); INSERT INTO w1sensors VALUES(11,'1FEDCB0300000000','DS2409','MAIN','1D4A1B0B000000E1',NULL,'AUX','10A942C10008009B',NULL,NULL,NULL); INSERT INTO w1sensors VALUES(12,'1FF9E60300000093','DS2409','MAIN','109F7724010800F1 ',NULL, 'AUX','26FD57E700000052',NULL,NULL,NULL); INSERT INTO w1sensors VALUES(21,'1D9BB10500000089','_TAI8575_','RAIN0','Counter0',' tips','RAIN1','Counter1','tips',NULL,NULL); ---- Note any `type` starting with an underscore is ignored. As a `.config/w1retap/sensors` file: ---- 26378851000000AB|DS2438|OTMP1|House Temperature|°C||||| 265066B5000000D2|HB-BARO|OPRS|Pressure|hPa||||22.4077 900.3| 105EE02301080039|DS1820|STMP1|Soil Temperature|°C||||| 286DA467000000AD|DS1820|GHT|Greenhouse Temperature|°C||||| 2665E1F1000000A0|_DS2438_|SOLAR|Solar (Vsens)|mV|SVDD|Solar (vdd)|volts|| 10A942C10008009B|DS1820|OTMP2|Garage Temperature|°C||||| 1D4A1B0B000000E1|DS2423|RGC1|Counter1|tips|RGC0|Counter0|tips|16218 2152| 26FD57E700000052|HWHIH|OHUM|Humidity|%|OTMP0|H Temperature|°C|| 109F7724010800F1|DS1820|CFRAME1|Cold Frame Temperature|°C||||| 1F1CE7030000009C|DS2409|MAIN|265066B5000000D2||AUX|105EE02301080039 286DA467000000AD 2665E1F1000000A0||| 1FEDCB0300000000|DS2409|MAIN|1D4A1B0B000000E1||AUX|10A942C10008009B||| 1FF9E60300000093|DS2409|MAIN|109F7724010800F1 ||AUX|26FD57E700000052||| 1D9BB10500000089|_TAI8575_|RAIN0|Counter0| tips|RAIN1|Counter1|tips|| ---- Note that the greenhouse temperature sensor only has one function, so the `abbrv2`, `name2` and `unit2` fields are not defined (or `NULL`). Devices incorporating the DS2438 and the DS2760 (_inter alia_) may provide more than the two functions that the {w1retap} database schema appears to permit. This has been addressed in w1retap v1.2.2 and later; when {w1retap} reads the w1sensors table (or configuration file), it will group functions by Device ID and device type. This means that for a DS2760 that supports four functions, we can define the functions using two rows, and all the data will be read in one place, for example: ---- INSERT INTO w1sensors VALUES (NULL, '30EB9B6112000018','DS2760', 'MS_Volts','Moisture Voltage','V','MS_Current','Moisture Current','A',NULL); INSERT INTO w1sensors VALUES (NULL, '30EB9B6112000018','DS2760', 'MS_Temp','Moisture Temperature','°C', 'MS_Accum','Moisture Accumulator','Ahrs',NULL); ---- For a DS2438, there are two options if you want the voltages as well as the 'applied' device (e.g. a TAI8540 humidity sensor); you could just define everything as the 'applied' device, which causes one read of the device, e.g. ---- 42|26378851000000AB|TAI8540|OHUM|Humidity|%|OTMP0|Outside Temperature|°C| 43|26378851000000AB|TAI8540|Vdd|Vdd|V|||| 44|26378851000000AB|TAI8540|Vad|Vad|V|Vsens|Vsens|mV| ---- or as two devices, which is less efficient, as the device is read twice: ---- 17|26378851000000AB|TAI8540|OHUM|Humidity|%|OTMP0|Outside Temperature|°C| 18|26378851000000AB|DS2438|Vdd|Vdd|V|||| 19|26378851000000AB|DS2438|Vad|Vad|V|Vsens|Vsens|mV| ---- ==== Coupler / Parameters For the DS2409 Microlan coupler, HB-Baro or a MPX4115A based pressure sensor, the configuration requires a little more work: Microlan:: For a Microlan device, it is necessary to add an entry for each device that is connected via the coupler. The `w1find` application will display the devices on each branch, but it is necessary to add an entry for each device. For each of these entries, the device field is address of the DS2409 coupler, the abbrv1 field is set to 'MAIN' and the abbrv2 filed is set to 'AUX'. The name1 field is a device id on the main branch, the name2 field is the name of a device on the auxiliary branch. Such an example is shown above. While this is ugly, and an automated tool `w1sensors.rb` with `w1find` can create an initial w1sensors database table template. `w1sensors.rb` is included with {w1retap} 1.24 and later to address this. Alternately, each coupler may be defined once, and the devices on the main and aux branches listed as space separated lists in the abbrv1 and abbrv2 fields respectively. See the `daria.co.uk-single.sql` and `daria.co.uk-multi.sql` listings in the documentation directory. MPX4115A:: In order to convert the voltage readings from the MPX4115A's DS2438 sensor into pressure (which is assumed linear), values of the slope and offset in an equation: + ---- pressure (hPa) = slope x Vout + offset where Vout is the sensed (output) voltage. ---- + These values will depend on the components used and whether an OpAmp is included in the design. By default slope= `35.95` and offset = `751.08`. As these values probably don't work for any real device, “correct for your setup” values may be provided as a set of space separated numbers in the params field (as many as are necessary for any particular device; not limited to the MPX4115A / DS2438 combination). HB-BARO:: The HobbyBoards barometer works in a similar fashion to the MPX4115A 'Bray' device, in that a slope and offset are used to convert the Vad voltage from the DS2438 into a pressure reading. Please note that: + * The device calibration is defined by the vendor in terms of imperial units (inHg), rather than the SI units (hPa) used in the majority of the world, thus; * The default slope and offset in {w1retap} are those from the HB-BARO documentation for sea-level (slope `0.6562`, offset `26.0827`). These, alas, give a value in inHg, which {w1retap} multiplies by `33.863886` to give hPa. * Alternatively, you can specify the parameters in SI (for hPa) by multiplying the vendor supplied values by `33.863886`. This makes correcting the calibration by adjustment of offset (the usual case) simpler, as one merely adds or subtracts the hPa difference from the offset. * The design of the HB-BARO assumes that the altitude correction is embodied in the slope / offset, and {w1retap} does not compensate for altitude (it compensates for altitude and temperature for the other barometer devices); * If you wish to use your own parameters, you must take into account the inHg to hPa conversion factor. For example, if your device, at sea level, consistently over-reads by 6hPa, then you would reduce the offset by (`6.0/33.863886`), giving an offset of `25.90552` compared to the default `26.0827`. If you have specified the calibration values as SI units, then you would just subtract 6 from the SI value (i.e. original offset `883.26`, modified offset `877.26`). In the author's experience, the device is delivered with an accurate calibration voltage, but the offset may need adjusting (by -3 hPa for the author's device); * For purposes of calibration, by adding an additional configuration entry for the measured voltage (Vad), you can use {w1retap} to perform the manufacturer's documented calibration steps (see HobbyBoards' web site). HB Solar:: The Hobby Boards Solar sensor is a DS2438 that provides the output of the photo-diode as the 'Vsens' voltage. With the standard HB device, multiplying the millivolts from {w1retap} by `2.9682` gives W/m^2; albeit possibly an underestimate if you're using parasitic (vice external) power. From a long disappeared internet FAQ: + ---- # The formula to get current thru the sense resistor (current # register volts) / 390 ohms = (sensor current) # Note: asumes a standard Hobby Boards solar sensor The formula to # get solar energy is: (sensor current) * 1157598 = W/M^2 (solar # energy) # Thusly, w/m^2 = milliVolts * 2.9682 ---- + There's an example `contrib/solar-conv.rb` of using a `w1file=` log script to update the database with converted solar `Vsens` as `w/m^2` and `lux`. DS1921:: If a mission is running, the last recorded mission value is returned, if no mission is running, then a forced temperature conversion is run on the device, giving the instantaneous temperature. If the params value for the device is set to a numeric value, then any extant mission is aborted and the instantaneous temperature returned. DS1923:: If the params value for the device is set to a numeric value, then any extant mission is aborted before the device is read. DS2423**, **TAI8575:: The params value may consist of two integers that are _added_ to the readings (so if you want to subtract, make the param values negative). This is useful if you change the counter, but wish to maintain reported values. HB-UV:: The HobbyBoards UV sensor has a number of settings stored in non-volatile memory. These can be set using the `hbuvtest` tool, running `hbuvtest -h` describes how to view or alter the nv-ram settings. HB-HT:: The (new, (2015)) HobbyBoards Humidity and Temperature sensor has a number of settings stored in non-volatile memory. These can be set using the `hbhttest` tool, running `hbhttest -h` describes how to view or alter the nv-ram settings. An example complex configuration with an MPX4115A and DS2409 is: ---- INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('106B89C4000800B9','DS18S20','DS1820 Temp', 'Temperature','°C',NULL,NULL,NULL,NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('264E1169000000B5','MPX4115A','Baro Press','Pressure','hPa', 'Baro Temp','Temperature','°C','34.249672152 762.374681772'); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('01F8A3880E0000A2','SHT11','SHT11 RH','Humidity','%','SHT11 Temp','Temperature','°C',NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('1FCD2D020000007F','DS2409','MAIN','264E1169000000B5',NULL,NULL,NULL,NULL,NULL); INSERT INTO w1sensors (device, type, abbrv1, name1, units1, abbrv2, name2, units2, params) VALUES ('1FCD2D020000007F','DS2409',NULL,NULL,NULL, 'AUX','01F8A3880E0000A2',NULL,NULL); ---- In this example, the final sensor is the Microlan coupler, the name fields define a sensor on each branch. The MPX4115A “Bray” barometer uses specific slope and offset parameters from the params field (c.f. the HB_BARO). The TAI8515 Weather Station from AAG provides temperature and wind speed and direction. These components are provided by three separate one wire devices in the TAI8515, e.g.: ---- 201A1B01000000F8 2450:quad a/d converter-> wind direction 10EF161400080056 18S20:high precision digital thermometer -> air temp 1DA273010000005D 2423:4k ram with counter -> wind speed ---- These devices would be defined by three separate entries in the configuration file, for example: ---- INSERT INTO w1sensors VALUES ('10EF161400080056','DS18S20','DS1820 Temp', 'Temperature','°C', NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES ('201A1B01000000F8','TAI8515','WDIR','Wind Direction', '', NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES ('1DA273010000005D','DS2423','WSPD','Wind Speed', '', NULL,NULL,NULL,NULL); ---- The temperature will be returned in °C, the direction as an integer in the range 0-15, which you must interpret as a direction N,NNE,NE ... NNW etc, and the speed as a counter value. The AAG web site FAQ once provided a formula for converting counts per time interval to wind speed... This https://projects.raspberrypi.org/en/projects/build-your-own-weather-station/5[Raspberry Pi project] offers a calculation that may be a useful starting point. ==== Summary of device type naming The following device 'type' keys are recognised in the w1sensors table or sensors configuration file (second parameter). |=== | Type | Alternative | Deprecated | Function | DS1820 | DS18S20 | Temperature | DS1820,DS18S20, DS1920 temperature | TAI854 | | Humidity | TAI8540 (DS2438 based) Humidity sensor | TAI8570 | | Pressure | TAI8570 Pressure sensor (dual DS2406) | DS2423 | Counter, TAI8575 | RainGauge | DS2423 Counters | MPX4115A | | Bray | Barometer based on MPX4415A (with DS2438) | SHT11 | | | SHT11 based humidity sensor | TAI8515 | Windvane, Weather vane | | AAG Weather station wind direction sensor (DS2450 based) | DS2490 | Coupler | | DS2409 Microlan Coupler | DS2438 | | Voltage | DS2438 as a voltage sensor | HB-BARO | HB_BARO | | Hobby Boards Barometer | MS-TH | HWHIH | | MS-TH Humidity Sensor (also works for Hobby Boards Honeywell HIH4000 based humidity sensor) | DS2760 | | | DS2760 voltage / current / temperature | DS2450 | | | Quad A / D Converter | MS-TC | | | iButton current and temperature | DS1923 | | | DS1923 Hygrochron, instantaneous temperature and humidity only | HB-UV | HB_UV | | Hobby Boards ultra-violet |=== The following device `name` keys are required in order to get data from multi-function sensors stored correctly in the database. The match is partial; the quoted text must occur somewhere in the 'nameN' field. For {w1retap} v1.24 and later, the quoted text may alternately be given precisely as the abbrvN field. The match is case independent in both instances. [%autowidth.stretch] |=== | Device | Name | Usage .2+| MPX4115A / Bray or HB-BARO or TAI8570 | Pres | Pressure Value | Temp | Temperature Value .2+| SHT11 or TAI8540 or MS-TH / HWHIH | Humidity | Humidity Value | Temp | Temperature Value .4+| DS2438 (or TAI8540 or other DS2438 based sensor (Bray, HB-BARO etc)) | Vdd | Supply voltage | Vad | Output voltage | Vsens | Sensed voltage | Temp | Temperature Value .4+| DS2760 | Voltage | Voltage (V) | Current | Current (I) | Accumulator | Amp hour | Temp | Temperature Value .5+| MS-TC (DS2438 based iButton current sensor) (Note 1) | current | Measured current | Vdd | Supply voltage | Vad | Output voltage | vsens | Sensed voltage | Temp | Temperature Value | DS1921 | Temp | Temperature Value .2+| DS1923 | Temp | Temperature Value | Humidity | Humidity Value .4+| HB-UV | Temp | Temperature Value | uv | UV value | ultra | UV value | violet | UV value | DS2450 (Note 2) | ADx | i.e. ADA, ADB, ADC, ADD. |=== Notes 1. MS-TC : Only the current and temperature are useful outputs 2. DS2450 : Two entries are necessary to define all the A/D converters. This is only necessary for a standalone DS2450. The device included in the AGG Wind-vane is read directly by the TAI8515 item. === Database and storage strategies The default database schema writes a record for each reading (a tuple of date, sensor name and the sensor value). From {w1retap} 1.41, it is also possible to use a document oriented strategy with PostgreSQL and SQLite databases. ==== Database storage and performance configurations The author initially ran {w1retap} on a record orientated PostgreSQL implementation, then for six months on mongodb (w1retap 1.4.0, now discontinued), and is now back to PostgreSQL, with a document orientated storage strategy. There are a number of advantages and disadvantages to each scheme, a document oriented strategy greatly reduces the number of records (I have c. 10 sensors, so for sensor pass, that's one record in the document oriented database vice ten in the record orientated store. Likewise, for display, retrieving all records within a set time period requires fewer records to be returned; as a modern scripting languages handle JSON efficiently, this can result in a simpler application. The only downside is perhaps remembering the syntax for retrieving a particular record on a none-timestamped criteria. For example the coldest ever outside temperature reading (OTMP0 here), using the record schema: ---- select * from readings where name='OTMP0' order by value asc limit 1; ---- and the document schema: ---- wx=# select * from readings order by wxdata['OTMP0'] limit 1; 2010-12-26 07:16:00+00 | {"GHT": -6.0625, "OHUM": 93.447586, "OPRS": 1030.93689, "RGC0": 19793, "RGC1": 16219, "OTMP0": -8.0625, "OTMP1": 16.65625, "OTMP2": -3.8125, "SOLAR": 0, "STMP1": 3.0625, "CFRAME1": -5.1875} ---- These days, somewhat equivalent. ==== Configuring the RDBMS record type For a record storage schema, the readings table requires the following: ---- CREATE TABLE readings ( date timestamp with time zone NOT NULL, name text NOT NULL, value double precision , id serial ); ---- For the document oriented schema: ---- CREATE TABLE readings ( date timestamp with time zone NOT NULL, wxdata json ); ---- And optionally ---- CREATE INDEX readings_date ON readings USING btree (date); ALTER TABLE ONLY readings ADD CONSTRAINT reading_sanity UNIQUE (date, name); -- single record ALTER TABLE ONLY readings ADD CONSTRAINT readings_pkey PRIMARY KEY (date); -- document orientated ---- For SQLite, the json data type may be replaced by a type of text. NOTE: The {w1retap} application introspects the readings table at start-up to determine the storage strategy; it is therefore advisable to use the default table and column names as above. ==== Using per-sensor “readings” tables The default database configuration creates a single table `readings` with columns of `date`, `name` (i.e. the `abbrv1` and `abbrv2` values from the `w1sensors` table) and `value`, the actual data which is coerced to a double precision value. Some users may prefer to have a per sensor data (readings) table, which is possible if you use the PostgreSQL database backend (patches for other database backends are welcome). In order to use per-sensor readings tables, it is necessary to: * The `abbrv1/2` field is defined with a leading `>` character. The text after the `>` is taken as the table name; * The table is created with fields of `date` and `value`. For sensors returning integer data (WindVane and Counters), the value field may be an integer type, otherwise it should be double precision. It is possible to mix the 'one monolithic table' and 'one table per sensor' modes, by definition of the `abbrv1`/`abbrv2` fields. === Using w1find to scan the 1-wire bus In order to create the sensor configuration table, `w1sensors`, (or a text file), it is necessary to know the devices on the 1-wire bus. The `w1find` program will find this information. It does not create the configuration table or file, as a particular 1-wire sensor may be employed by a number of different devices; rather it provides a template that the user may edit to her requirement. e.g. For these sensors: ---- w1find DS2490-1 (1) 26378851000000AB 2438:smart battery monitor (2) 817E84240000008B :Serial ID Button (3) 1F1CE7030000009C 2409:microlan coupler (Main.1) 265066B5000000D2 2438:smart battery monitor ( Aux.1) 105EE02301080039 18S20:high precision digital thermometer ( Aux.2) 286DA467000000AD 18B20:programmable resolution digital thermometer (4) 1FF9E60300000093 2409:microlan coupler (Main.1) 109F7724010800F1 18S20:high precision digital thermometer ( Aux.1) 10823BCB010800FB 18S20:high precision digital thermometer ( Aux.2) 26FD57E700000052 2438:smart battery monitor (5) 1FEDCB0300000000 2409:microlan coupler (Main.1) 1D4A1B0B000000E1 2423:4k ram with counter ( Aux.1) 10A942C10008009B 18S20:high precision digital thermometer ---- ==== Using `w1sensors.rb` with `w1find` to create an initial w1sensors database table Configuring the `w1sensors` table requires some care , particularly if you have a large number of sensors, one or more DS2409 couplers, or you are new to one wire devices. This is made more complex by the fact that devices may supply multiple functions, or may serve a function other than the primary function of the device (a DS2438 voltage sensor may serve as a pressure or humidity sensor, a DS2423 counter may serve as the wind speed indicator). The flexibility of one wire devices also means it is very difficult to automatically probe the device chain and ascertain precisely what the function of every device might be, and manual confirmation and final configuration of device functions will be required. It is possible to build an initial configuration for the w1sensors database table (as a set of SQL INSERT statements (or a '|' delimited file with --file-based-config)) using the `w1find` program in conjunction with the `w1sensors.rb` script. The output is written to a file or STDOUT (which may be in turn piped to an RDBMS). Any unrecognised sensors are listed to STDERR. ---- $ w1sensors.rb -? w1sensors.rb [options] [file|stdin] e.g. w1find DS2490-1 | w1sensors.rb -o /tmp/w1_sensors-setup.sql w1find DS2490-1 | w1sensors.rb | sqlite3 sensors.db -f, --file-based-config -o, --output FILE -?, --help Show this message ---- For some old sensors: ---- $ w1find DS2490-1 (1) 105EE02301080039 18S20:high precision digital thermometer (2) 10A942C10008009B 18S20:high precision digital thermometer (3) 286DA467000000AD 18B20:programmable resolution digital thermometer (4) 12FC6B34000000A9 2406:dual addressable switch plus 1k memory (5) 121B4A3400000030 2406:dual addressable switch plus 1k memory (6) 26378851000000AB 2438:smart battery monitor (7) 817E84240000008B :Serial ID Button (8) 1D9BB10500000089 2423:4k ram with counter ---- Piping the results into w1sensors.rb gives the following SQL statements: ---- INSERT into w1sensors values ('105EE02301080039','DS1820','TMP_1','Temperature #1','°C', NULL,NULL,NULL,NULL); INSERT into w1sensors values ('10A942C10008009B','DS1820','TMP_2','Temperature #2','°C', NULL,NULL,NULL,NULL); INSERT into w1sensors values ('286DA467000000AD','DS1820','TMP_3','Temperature #3','°C', NULL,NULL,NULL,NULL); INSERT into w1sensors values ('12FC6B34000000A9','TAI8570','Pressure_4', 'Pressure 4','hPa', 'TMP_4','Temperature #4','°C',NULL); INSERT into w1sensors values ('26378851000000AB','DS2438','VDD_6', 'VDD 6','V', 'TMP_6','Temperature #6','°C',NULL); INSERT into w1sensors values ('26378851000000AB','DS2438','VAD_6', 'VAD 6','V', 'Vsens_6','Vsens #6','mV',NULL); INSERT into w1sensors values ('1D9BB10500000089','TAI8575','CountA_7','CounterA #7','pulses', 'CountB_7','CounterB #7','pulses',NULL); ---- Some editing provides the required `w1sensors` table, noting that the DS2438 is the front end for a TAI8540 humidity sensor. ---- INSERT INTO w1sensors VALUES('105EE02301080039','DS1820','STMP1','Soil Temperature','°C', NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES('286DA467000000AD','DS1820','GHT','Greenhouse Temperature','°C', NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES('12FC6B34000000A9','TAI8570','OPRS','Pressure','hPa', 'OTMP1','Inside Temperature','°C',NULL); INSERT INTO w1sensors VALUES('26378851000000AB','TAI8540','OHUM','Humidity','%', 'OTMP0','Outside Temperature','°C',NULL); INSERT INTO w1sensors VALUES('1D9BB10500000089','TAI8575','RGC0','Counter0','tips', 'RGC1','Counter1','tips',NULL); INSERT INTO w1sensors VALUES('10A942C10008009B','DS1820','OTMP2','Garage Temperature','°C', NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES('1093AEC100080042','__DS1820','ITMP1','Propagator1 Temperature','°C', NULL,NULL,NULL,NULL); INSERT INTO w1sensors VALUES('10E3EA23010800C9','__DS1820','ITMP2','Propagator2 Temperature','°C', NULL,NULL,NULL,NULL); ---- (Note also two seasonal sensors are “commented out” by prefixing the device type with two underscores). === Configuring the w1retap software. The main configuration of the application is done via the `~/.config/w1retap/rc` file (or `/etc/default/w1retap` if the user's file doesn't exist). Some of the options may also be specified on the command line when {w1retap} is invoked. This defines how {w1retap} obtains the sensor configuration and how it performs the data logging, for example: ---- #Init file #init = w1sqlite=/var/tmp/sensors.db #log = w1sqlite=/var/tmp/sensors.db #init = w1odbc=DSN=w1retap init = w1pgsql=dbname=w1retap user=postgres #init = w1file #log = w1xml=/tmp/xmllog.txt #log = w1csv=/tmp/csvlog.txt log = w1pgsql=dbname=w1retap user=postgres log = w1file = |/usr/local/bin/pert-log.rb #log = w1mysql=dbname=w1retap user=jrh host=kanga password=ohsososecret #timestamp = 1 altitude = 19 device = DS2490-1 #device = /dev/ttyS0 ---- Where the keys are: init:: The initialisation data for the sensors, e.g. a database with a `w1sensors` table, or a file. The value part is the name of a plugin and optionally, parameters (see below). log:: The log database to the readings table, or a file for a file data sink. The value part is the name of a plugin and optionally, parameters (see the section <<_log_and_init_options>>). device:: The name of the interface device. For Linux, using the standard USB interface, this defaults to `DS2490-1`, for a serial device `/dev/ttySn` where “n” represents a digit (or `/dev/ttyUSB0` for a USB/Serial adaptor. delay:: The delay between successive reading of the the 1-wire bus. All sensors are read in one hit unless <<_per_sensor_polling_frequency>> is defined. daemonise:: If set to 1, {w1retap} detaches and runs in the background altitude:: If the altitude is defined (in _metres_), above mean sea level (MSL), then pressure readings are normalised to MSL, otherwise you get the raw, uncorrected value. timestamp:: If timestamp is set to a non-zero integer value, then the time of the observation in the database `readings` table (field name `date`) will be stored as SQL TIMESTAMP data. The default is that the `date` field is stored as an integer number of seconds since 01 January 1970, UTC (Unix epoch values, also known as `time_t`). You must ensure that your database table is configured appropriately. If you choose TIMESTAMPs, then you need to consider if this will cause you any time-zone / summer time / daylight saving issues. logtemp:: By default, {w1retap} writes the latest sensor values to a file `/tmp/.w1retap.dat`. If you set logtemp to 0, this file is not updated. The file contains, for each sensor, the abbreviation and value and a time stamp (Unix epoch `time_t` and ISO date format): ---- GHT=23.75 °C OHUM=75.95 % OTMP0=19.50 °C OPRS=1012.97 hPa OTMP1=20.23 °C RGC0=3517.00 tips RGC1=3481.00 tips udate=1122818880 date=2005-07-31T15:08:00+0100 ---- [.text-right] _Just an overcast Sunday afternoon in July_ log_delimter:: The delimiter for `w1file` logs is by default a space. You can override this here, '`\`' escapes are recognised, so '`\t`' is `TAB`. log_time_t:: If set to yes, the final field for `w1file` logs is the time_t (numeric seconds since the epoch) log time. temp_scan:: The time in milliseconds to allow DS1820 type sensors to acquire the temperature before the device is read. By default, {w1retap} uses a conservative value of 1000 (1 second). The data sheet claims the conversion should not exceed 750ms, which is the value the author has used with success. pressure_reduction_temp:: By default, {w1retap} uses a QFF pressure reduction model to reduce the pressure to mean sea level (if the **altitude** key (as above) is defined. If you also set the **pressure_reduction_temp** key to a value in degrees Celsius (°C), then this fixed temperature is used (the QNH model). A value of 15 is the ISA (International Standard Atmosphere) value used for some aviation reports. force_utc:: If set to true, then database and other timestamps are as UTC rather than local time. This setting may be useful if your database is less adept than PostgreSQL in storing time stamps with time zones. Only the first `init` entry is used; multiple `log` entries may be given and are all logged to in the order defined. === Log and Init options For the `log` and `init` options, the information supplied has two parts, separated by an equals sign. The name of the plugin handling that information and any additional information. For a file based plugin, this will be the file name and for a database, the name of the database and any access control parameters. For each plugin, the usage and parameters are: w1file:: This module provides basic file system access for configuration and logging. If used as a `init` parameter, it reads `~/.config/w1retap/sensors` (or supplied filename) for sensor information as described for file based sensor configuration. + ---- init = w1file ---- + ---- init = w1file=/etc/w1sensors.dat ---- + The first case assumes `~/.config/w1retap/sensors` contains the configuration data, the second explicitly reads `/etc/w1sensors.dat`. + If used as a `log` parameter, it writes one entry per line to STDOUT or a supplied file name: + ---- log = w1file log = w1file=/tmp/w1file.log ---- + The data output is in the format (date abbreviation value units): + ---- 2005-07-29T18:11:28+0100 GHT 20.312500 ⁰C 2005-07-29T18:11:28+0100 OHUM 74.050064 % 2005-07-29T18:11:28+0100 OTMP0 17.687500 ⁰C 2005-07-29T18:11:28+0100 OPRS 1009.950562 hPa 2005-07-29T18:11:28+0100 OTMP1 18.510059 ⁰C 2005-07-29T18:11:28+0100 RGC0 3496.000000 tips 2005-07-29T18:11:28+0100 RGC1 3460.000000 tips ---- + If the file name begins with a pipe symbol (|), then it is taken as the name of an application that accepts the data on standard input. This might be used to update the database with derived (calculated) values, or drive an additional display device (e.g. via `pert-log.rb`, which drives a Pertelian LCD display via the `pertd2` program). + ---- log = w1pgsql=dbname=w1retap user=postgres log = w1file=|/usr/local/bin/pert-log.rb ---- + The file `wetbulb-snow.rb` shows how a piped script can be used to update the database with derived values from the current set of readings (wet bulb temperature and snow height). + It should be noted that _piped scripts are run synchronously by the {w1retap} application_. This means that the scripts (in total) should not take longer to execute that the {w1retap} cycle period, and _care must be taken to ensure that the scripts cannot hang or block_ for indefinite periods, as this would cause {w1retap} also to block and subsequent readings would be lost. As an example, the `pert-log.rb` script takes great care to use non-blocking I/O to ensure that any hang writing to the `pertd` FIFO cannot cause the main {w1retap} application to hang. + See also the configuration file `log_delimiter` and `log_time_t` entries, as these can affect the format of this log. w1xml:: This module provides basic file system access for logging only. It writes an XML file to STDOUT or a supplied file name: + ---- log = w1xml log = w1xml=/tmp/w1xml.log ---- + ---- ---- + {w1retap} uses `libxml2` to write out syntactically correct XML. This also means that (a) there is a dependency on `libxml2` and (b) the input, including any values (such as names and units) in the database must be valid UTF-8. The file name may be prefixed with a pipe symbol to pipe the data to another program (as for `w1file`). w1csv:: This module provides basic file system access for logging only. It writes an CSV file to STDOUT or a supplied file name: + ---- log = w1csv log = w1csv=/tmp/w1data.csv ---- + The data output is in the format of a timestamp followed by abbreviations, values and units (all on one line): + ---- "2005-08-01T19:51:45+0100", "GHT", 17.062500, "°C", "OHUM", 96.463608, "%", "OTMP0", 16.250000, "°C", "OPRS", 1017.826843, "hPa", "OTMP1", 16.991602, "°C", "RGC0", 3544.000000, "tips", "RGC1", 3508.000000, "tips" ---- + The file name may be prefixed with a pipe symbol to pipe the data to another program (as for `w1file`). w1sqlite:: This module provides database access for configuration and logging using a https://www.sqlite.org/[Sqlite3] RDBMS. If used as a `init` parameter, it reads the `w1sensors` table for sensor information as described for RDBMS based sensor configuration. + ---- init = w1sqlite=/var/db/sensors.db ---- + The name of the database is a mandatory parameter. + If used as a `log` parameter, it writes data to the readings table. + ---- log = w1sqlite=/var/db/sensors.db ---- + The data is logged as (date, abbreviation, value): + ---- $ sqlite3 /var/tmp/sensors.db SQLite version 3.2.2 Enter ".help" for instructions sqlite> select * from readings order by date desc limit 1; 1122735840|GHT|25.6251122735840|OHUM|87.68514251708981122735840|OTMP0|18.343751122735840|OPRS|1009.779724121091122735840|OTMP1|19.12314414978031122735840|RGC0|34981122735840|RGC1|3462 ---- + Where `date` is the unix epoch time (`time_t`), seconds since 00:00:00 1 Jan 1970 UTC. w1pqsql:: This module provides database system access for configuration and logging using a https://www.postgresql.org/[PostgreSQL] RDBMS. If used as a `init` parameter, it reads the `w1sensors` table for sensor information as described for RDBMS based sensor configuration. + ---- init = w1pgsql=dbname=w1retap user=postgres ---- + The name of the database is a mandatory parameter, followed by optional parameters (`dbname`, `host`, `user`, `password`). + If used as a `log` parameter, it writes data to the `readings` table. + ---- log = w1pgsql=dbname=w1retap user=postgres ---- + By default, the data is logged as (`date` `abbreviation` `value`) [see `sqlite` example]. The Postgresql driver also offers document database and "one table per sensor" support, see <<_configuring_the_rdbms_record_type>> for details. w1mysql:: This module provides database system access for configuration and logging using a https://mariadb.org/[Maria] (or MySQL) RDBMS. If used as a `init` parameter, it reads the `w1sensors` table for sensor information as described for RDBMS based sensor configuration. + ---- init = w1mysql=dbname=w1retap user=w1retap host=kanga ---- + The name of the database is a mandatory parameter, followed by optional parameters `dbname` - name of the database, `user` – username, `password` - user's password, `host` - database server. + If used as a 'log' parameter, it writes data to the `readings` table. + ---- log = w1mysql=dbname=w1retap user=jrh host=kanga` ---- + The data is logged as (`date` `abbreviation` `value`) (see sqlite example). + w1odbc:: This module provides database system access for configuration and logging using https://www.unixodbc.org[ODBC] RDBMS. It may thus be used for any database for which there is no specific {w1retap} module, but you have an ODBC driver. If used as a 'init' parameter, it reads the w1sensors table for sensor information as described for RDBMS based sensor configuration. + ---- init = w1odbc=DSN=W1RETAP ---- + The DSN of the database is a mandatory parameter. + If used as a 'log' parameter, it writes data to the readings table. + ---- log = w1odbc=DSN=W1RETAP ---- + The data is logged as (`date` `abbreviation` `value`) [see sqlite example]. + NOTE: Most operating system libraries will do the right thing such that `w1sqlite` will be tried as `libw1sqlite.so`. Due to the deprecation of the `g_module_find_path()` function with no documented replacement, this should not be relied upon. === Running w1retap {w1retap} is started from the command line (shell script) or as a boot task (e.g. `systemd` etc). Assuming the permissions of the device (usb/serial) allow non-privileged access, it requires no special privileges and may be run from a normal user account. If you are using a USB adaptor, it may be necessary to ensure that your user can access (has read and write access) to the USB device. Please see the udev `45-w1retap.rules` file in the documentation directory (this file may be added to `/etc/udev/rules.d` if desired). {w1retap} accepts the following command options: ---- $ w1retap --help Usage: w1retap [OPTION...] - w1retap Help Options: -h, --help Show help options Application Options: -w, --wait At startup, wait until next interval -1, --once-only Read once and exit -R, --release-interface Release the 1Wire interface between reads -d, --daemonise Daemonise (background) application -T, --no-tmp-log Disables /tmp/.w1retap.dat logging -l, --tmp-log-name=FILE Names logging file (/tmp/.w1retap.dat) -i, --interface=DEVICE Interface device -t, --cycle-time=SECS Time (secs) between device readings -N, --dont-read Don't read sensors (for debugging) -v, --verbose Verbose messages -o, --vane-offset=VAL Value for N for weather vane (0-15) -V, --version Display version number (and exit) -s, --simulate Simulate readings (for testing, not yet implemented) -u, --use-utc Store dates as UTC (vice localtime) -r, --report-log=FILE Report log file ---- Note `w1retap -Nv` will dump out the configuration. ==== Signal Handlers {w1retap} reacts to the following POSIX signals: |=== | Signal | Effect | HUP | Reread the configuration / sensors table | USR1 | Read all sensors immediately | USR2 | print configuration to `stderr` (as `-v` option) |=== === Other Database elements ==== Rate Limiting Occasionally a sensors may give a wildly inaccurate reading. In order to prevent these from polluting the database, a concept of rating limiting is implemented. This requires a table `ratelimit` exists, and contains the sensor abbreviation and the maximum acceptable rate in `units/minute`,`min` and `max` values. For example: ---- CREATE TABLE ratelimit ( name text, value real, rmin real, rmax real ); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('GHT', 2.5, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OTMP0', 2.5, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OTMP1', 2.5, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OPRS', 100, 800, 1200); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('RGC0', 50, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('RGC1', 50, NULL, NULL); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OTMP2', 2.5, -10, 50); INSERT INTO ratelimit (name, value, rmin, rmax) VALUES ('OHUM', 7, 0, 100.04); ---- The values are such that they would not normally be seen, but are less than the obviously bizarre rogue value seen very rarely. ==== Per-sensor polling frequency {w1retap} polls all the sensors at the same frequency, by default 120 seconds, or the `delay` value from the configuration file or the `-t` command line argument. A per-sensor value may be applied, by creating a column in the `w1sensors` table called `interval`. ---- alter table w1sensors add column interval integer; -- postgres, sqlite3 alter table w1sensors add column `interval` int; -- mysql ---- This column should contain the polling interval for that sensor in seconds, where a value other than the default is required, e.g. `update w1sensors set interval=10 where device='286DA467000000AD';`. A few arbitrary rules apply, largely to simplify the implementation: * The minimum interval is 10 seconds (the 'wake up' time) * The maximum interval is the `delay` / `-t SECS` parameter (default 120s) -- the 'cycle' time * If the column is omitted, or the value is NULL or zero, then the default delay value is used * If the /tmp log file is used, it is only written when all sensors are read (the 'cycle' value) * {w1retap} will calculate its wake up value and cycle value, using the highest common factor and lowest common multiple of the individual polling intervals. So if sensors had polling intervals of 10,20,30,40 and 60 seconds, the wake up value would be 10s and the cycle value would be 120s * The algorithms may not be robust in the face of “unreasonable” (by my definition) values, but should work for the majority of reasonable cases. === Summary of configuration While the configuration may seem, at first reading, to be complex or confusing, it is a number of logical steps: * Decide on where you want to store the sensor definition and logged data, a relational database is recommended * Create `~/.config/w1retap/rc` (or `/etc/defaults/w1retap`) defining the sensors (`init=xxxx`), and data logging (`log=xxxx`) configuration * Create any necessary RDBMS tables, using the supplied scripts as a template * Populate the `init=xxxx` definitions, using `w1find`, maybe in conjunction with `w1sensors.rb` * If you are using the USB one wire device, please see the USB configurations in the documentation directory. It will be necessary to install a `udev` rule to manage access to the USB device and add the user to the `w1retap` group, unless you run `w1retap` as root, which is neither necessary nor recommended on Linux. === w1retap dependencies {w1retap} has a few dependencies on other libraries in order to build the software, in particular `glib-2.0` and `libusb-1.0`. If you're using Debian or derivative system, then the following will get you started: ---- apt-get install build-essential libglib2.0-dev libusb-1.0-0-dev libc-dev ---- In addition, you will need the development packages for any database you require, e.g. `libsqlite3-dev`, `libxml2-dev`. === Viewing the data `wplot.rb` (and other) scripts, the Gnome applet and other visualisation tools are no longer distributed by default, these tools demonstrate: * Building a http://www.daria.co.uk/wx/[web page] * Send data to http://www.wunderground.com/global/stations/03865.html[Wunderground.com] and other aggregators * Provided a static http://www.zen35309.zen.co.uk/wx/wx_static.json[JSON document] of current conditions. The latter format is read by the {w1retap} GNOME applet. * Provided a Gnome shell applet. Please ping the author if you’re interested in any additional artefacts mentioned in this document. === Credits Thanks to: * http://zlatograd.com/[Mihail Peltekov] provided `ssh` access to zlatograd.com, which allowed me to develop the DS2480, DS2409, SHT11 and MPX4115A device support. * http://sowerbutts.com[William R Sowerbutts] provided a patch to allow field order independent PgSQL logging, the TAI8515 code and the 'one table per sensor' PgSQL logging code, as well as other patches, including robust DS2409 handling. * Hans van den Boogert kindly donated a Hobby Boards solar sensor. * Leland Helgerson kindly donated a pair of DS1921 ibutton sensors. * Peter Parsons contributed the basis of the MS-TC code. * Andrew Ford lent me a LinkUSB adaptor, which worked out of the box for me (Andrew was not so fortunate, but this is likely a host hardware problem). * Dave Johns lent me a Hobby Boards UV sensor for the development of that interface. * Graeme Gemmill lent me the new Hobby Boards HT sensor for the development of that interface. * Thomas Stewart kindly maintains a Debian package. Other users have provided bug reports, requests for new sensors and other inspiration. Daria Hudson started this by requiring a temperature sensor be fitted in her greenhouse and has graciously allowed me pursue my interest in 1-wire weather stations since then. She also allows me to (ab)use her vanity domain. === Author / contact {w1retap} is (c) mailto:jh+w1retap@daria.co.uk[Jonathan Hudson]. It is released (mainly) under the GNU Public licence. w1retap/docs/w1sensors.rb000077500000000000000000000070171446446235200157040ustar00rootroot00000000000000#!/usr/bin/ruby # -*- coding: utf-8 -*- require 'optparse' ## # Copyright (C) 2008 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. ## # Create an initial w1retap configuration from w1find # # ***** you may need to modify this for your own schema ***** class MakeSensors def initialize @fn=STDOUT.fileno @fbase=nil @idx = 0 ARGV.options do |opt| opt.banner = %Q(#{File.basename($0)} [options] [file|stdin] e.g. w1find DS2490-1 | w1sensors.rb -o /tmp/w1_sensors-setup.sql w1find DS2490-1 | w1sensors.rb | sqlite3 sensors.db) opt.on('-f','--file-based-config'){@fbase=true} opt.on('-o','--output FILE') {|o| fn=o} opt.on('-?', "--help", "Show this message") {puts opt; exit} begin opt.parse! rescue puts opt ; exit end end end def output f,arry,err=nil arry.fill(nil,arry.length..9) str = case @fbase when false,nil @idx += 1 arry.collect! {|x| x.nil? ? 'NULL' : "'#{x}'" } "#{err}INSERT into w1sensors values (#{@idx},#{arry.join(',')});" when true arry.join('|') end f.puts str end def buildconfig last=nil no=1 cl=nil File.open(@fn,'w') do |f| ARGF.each do |l| if m=l.match(/\((.*?)\)\s+(\S+)\s+(\S+?):/) slot=m[1] id=m[2] dev=m[3] slot.strip! cl=nil if l.match(/^\(\d+/) case dev when '2409' cl=id when '18S20','18B20' output f, [id,'DS1820',"TMP_#{no}","Temperature ##{no}",'°C'] when '2423' output f, [id,'TAI8575',"CountA_#{no}","CounterA ##{no}", 'pulses',"CountB_#{no}","CounterB ##{no}",'pulses'] when '2438' output f, [id,'DS2438',"VDD_#{no}", "VDD #{no}",'V',"TMP_#{no}", "Temperature ##{no}",'°C'] output f, [id,'DS2438',"VAD_#{no}", "VAD #{no}",'V',"Vsens_#{no}", "Vsens ##{no}",'mV'] when '2406' if last=='2406' last=nil else output f, [id,'TAI8570',"Pressure_#{no}", "Pressure #{no}",'hPa', "TMP_#{no}","Temperature ##{no}",'°C'] end when '2450' output f, [id,'TAI8515',"WDIR_#{no}","Wind Direction #{no}", ''] when '2760' output f, [id,'DS2760', "MS_Volts_#{no}","Moisture Voltage #{no}",'V', "MS_Current_#{no}","Moisture Current #{no}",'A'] output f, [id,'DS2760', "MS_Temp_#{no}","Moisture Temperature #{no}", '°C',"MS_Accum_#{no}","Moisture Accumulator #{no}",'Ahrs'] when 'HB1WT' output f, [id,'HB???',"HB?? #{no}","Hobbyboards with temperature #{no}", ''] else STDERR.puts "?? #{l}" typ = l.chomp.split(':') output f, [id, dev,"UNK #{no}","UNKNOWN: #{typ[1]} #{no}", ''],'-- ' end if(cl) case slot when /Main/ output f, [cl,'DS2409','MAIN',id] when /Aux/ output f, [cl,'DS2409',nil,nil,nil,'AUX',id] end end last=dev no += 1 end end end end end s=MakeSensors.new s.buildconfig w1retap/meson.build000066400000000000000000000045761446446235200146310ustar00rootroot00000000000000project('w1retap', 'c', version : '1.5.5') prefix = get_option ('prefix') conf = configuration_data() datadir = join_paths (prefix, get_option ('datadir')) pkgdatadir = join_paths (datadir, meson.project_name ()) bindir = join_paths (prefix, get_option ('bindir')) pkglibdir = join_paths (prefix, get_option ('libdir'), meson.project_name ()) localedir = join_paths (prefix, get_option ('localedir')) uname_run = run_command ('uname', check:true) osname = uname_run.stdout().strip() conf = configuration_data () conf.set_quoted('PACKAGE', meson.project_name ()) conf.set_quoted('GETTEXT_PACKAGE', meson.project_name ()) conf.set_quoted('VERSION', meson.project_version ()) conf.set_quoted('PACKAGE_LIB_DIR', pkglibdir) conf.set_quoted('PACKAGE_DATA_DIR', datadir) conf.set_quoted('PACKAGE_LOCALE_DIR', localedir) conf.set_quoted('BIN_DIR', bindir) conf.set_quoted('OSNAME', osname) conf.set('HAVE_NANOSLEEP', 1) configure_file (output : 'config.h', configuration : conf ) configuration_inc = include_directories('.','src') wdeps = [ dependency('glib-2.0'), dependency('gio-2.0'), dependency('gmodule-2.0'), meson.get_compiler('c').find_library('m') ] #libpq sqlite3 odbc have_pq = dependency('libpq', required: false) have_sqlite = dependency('sqlite3', required: false) have_odbc = dependency('odbc', required: false) have_mysql = dependency('mariadb', required: false) if not have_mysql.found() have_mysql = dependency('mysql', required: false) endif subdir('src') subdir('src/libusblinux300') if have_pq.found() subdir('src/pgsql') endif if have_odbc.found() subdir('src/odbc') endif if have_sqlite.found() subdir('src/sqlite') endif if have_mysql.found() subdir('src/mysql') endif subdir('docs') executable( meson.project_name(), wsrcs, dependencies: [ wdeps ], include_directories : [ configuration_inc, 'src/libusblinux300' ], c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: true, ) install_data([ 'README.md'], install_dir : get_option('datadir') / 'doc' / 'w1retap' ) message('Optional Modules:') message(' postgresql : ', have_pq.found()) message(' sqlite : ', have_sqlite.found()) message(' mariadb/mysql : ', have_mysql.found()) message(' odbc : ', have_odbc.found()) message(' xml : ', xmllib.found()) w1retap/src/000077500000000000000000000000001446446235200132425ustar00rootroot00000000000000w1retap/src/libusblinux300/000077500000000000000000000000001446446235200160255ustar00rootroot00000000000000w1retap/src/libusblinux300/README000066400000000000000000000013721446446235200167100ustar00rootroot00000000000000This is the Dallas libusblinux distribution available from ftp://ftp.dalsemi.com/pub/auto_id/public/libusblinux300.tar.gz, modified by Jonathan Hudson for w1retap: * Temperature module supports DS18B20 * Compiles with gcc 4.0 * 64 bit clean * Added pressure.c for AAG TAI8570 pressure module * Added MPX4115A and SHT11 based sensors * Shared library choice of USB or RS232 * Added autoconf/automake for the bits w1retap uses use: make -f makefile.shrlib to build all the Dalsemi stuff. As part of w1retap, this is covered by the GPL, as the generous Dallas licence allows; my changes are dual licenced under the GPL for w1retap, and the Dallas PD licence, if you want to use the Dallas SDK for any other purpose outside of w1retap. w1retap/src/libusblinux300/ReadMe.txt000077500000000000000000000046571446446235200177420ustar00rootroot00000000000000 LIBUSB Linux GCC Build 1-Wire Public Domain Kit V3.00 beta 07/23/04 This is a build of all of the current (3.00) 1-Wire Public Domain demo applications using interface modules to communicate directly with the DS2490 based USB adapters (through libusb) such as the DS9490R/DS9490B on Linux platforms. This build will be of most interest to security conscience applications such as Software Authorization that do not want to go through intermediate software layers (DLLs) to access the USB adapters. This build is not strictly a 'userial' or 'general' build as defined in the 1-Wire Public Domain kit but is somewhere in between. The interface modules were written in a way to take advantage of the features of the DS2490 chip which has built-in 1-Wire search capabilities. For example, instead of constructing the 1-Wire search using single 'bit' operations, it translates owFirst directly into calls to libusb. The main interface modules are: libusbds2490.h libusbds2490.c libusbllnk.c libusbnet.c libusbtran.c libusbses.c usb.h libusb (see included libusb distribution package) Note that the port name to provide on the command line to the demos is in the format DS2490-X where X is a number starting at 1. This is the USB enumeration number. These other files are also required for most applications: crcutil.c ioutil.c owerr.c ownet.h The different demos are documented in the main 1-Wire Public Domain 3.00 kit that can be found here: http://www.ibutton.com/software/1wire/wirekit.html The source and binaries for the demos can be found in this folder. A makefile that can be used to either make individual sample programs or all sample programs is also available in this folder. Use the following command at a terminal prompt to build all of the executables: make linux One of the pre-requisites of this Public Domain Kit build is that "libusb" be present on the computer system where the programs will be run. If "libusb" has not already been installed, then use the libusb distribution archive contained in this folder (libusb-0.1.8.tar.gz). This archive contains all the necessary information on how to build and install the libusb shared library. The libusb sourceforge project can be found here (support for Linux, MacOSX, FreeBSD, etc): http://libusb.sourceforge.net The Win32 port of libusb can be found here: http://libusb-win32.sourceforge.net w1retap/src/libusblinux300/acquire.c000066400000000000000000000130601446446235200176220ustar00rootroot00000000000000#include #include #include #include "ownet.h" #include #include "config.h" void (*msDelay)(int len); int (*msGettick)(void); void (*owShowVersion)(void); SMALLINT (*owFirst)(int portnum, SMALLINT do_reset, SMALLINT alarm_only); SMALLINT (*owNext)(int portnum, SMALLINT do_reset, SMALLINT alarm_only); void (*owSerialNum)(int portnum, uchar *serialnum_buf, SMALLINT do_read); void (*owFamilySearchSetup)(int portnum, SMALLINT search_family); void (*owSkipFamily)(int portnum); SMALLINT (*owAccess)(int portnum); SMALLINT (*owVerify)(int portnum, SMALLINT alarm_only); SMALLINT (*owOverdriveAccess)(int portnum); // external One Wire functions defined in owsesu.c SMALLINT (*owAcquire__)(int portnum, char *port_zstr); int (*owAcquireEx__)(char *port_zstr); void (*owRelease)(int portnum); SMALLINT (*owProgramByte) (int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access); // external One Wire functions from link layer owllu.c SMALLINT (*owTouchReset)(int portnum); SMALLINT (*owTouchBit)(int portnum, SMALLINT sendbit); SMALLINT (*owTouchByte)(int portnum, SMALLINT sendbyte); SMALLINT (*owWriteByte)(int portnum, SMALLINT sendbyte); SMALLINT (*owReadByte)(int portnum); SMALLINT (*owSpeed)(int portnum, SMALLINT new_speed); SMALLINT (*owLevel)(int portnum, SMALLINT new_level); SMALLINT (*owProgramPulse)(int portnum); SMALLINT (*owWriteBytePower)(int portnum, SMALLINT sendbyte); SMALLINT (*owReadBytePower)(int portnum); SMALLINT (*owHasPowerDelivery)(int portnum); SMALLINT (*owHasProgramPulse)(int portnum); SMALLINT (*owHasOverDrive)(int portnum); SMALLINT (*owReadBitPower)(int portnum, SMALLINT applyPowerResponse); // external One Wire functions from transaction layer in owtrnu.c SMALLINT (*owBlock)(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len); SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf); SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf, SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type); SMALLINT (*owProgramByte) (int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access); SMALLINT FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE; static void *handle; char *w1_module_build_path(const char *dir, const char *name) { // Once GLIB actually provides / documents a replacement, the pragmas can be removed #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" return g_module_build_path(dir, name); #pragma GCC diagnostic push } static void loadiolib(char *port) { char *name; if (strncmp(port, "DS2490", sizeof("DS2490") - 1) == 0 || strncmp(port, "USB", sizeof("USB") - 1) == 0) { name = "libw1usb.so"; FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE = TRUE; } else { name = "libw1serial.so"; FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE = FALSE; } char *sofile = w1_module_build_path(PACKAGE_LIB_DIR, name); handle = g_module_open(sofile, G_MODULE_BIND_LOCAL); if (handle == NULL) { const gchar *gerr; gerr = g_module_error(); fprintf(stderr, "Can't open the device library %s\n" "System returned:\n%s\n" "This is typically a build dependency or installation error\n", name, gerr); exit(1); } g_free(sofile); g_module_symbol(handle, "owShowVersion_", (void *)&owShowVersion); g_module_symbol(handle, "msDelay_", (void *)&msDelay); g_module_symbol(handle, "msGettick_", (void *)&msGettick); g_module_symbol(handle, "owHasOverDrive_", (void *)&owHasOverDrive); g_module_symbol(handle, "owHasPowerDelivery_", (void *)&owHasPowerDelivery); g_module_symbol(handle, "owHasProgramPulse_", (void *)&owHasProgramPulse); g_module_symbol(handle, "owLevel_", (void *)&owLevel); g_module_symbol(handle, "owProgramPulse_", (void *)&owProgramPulse); g_module_symbol(handle, "owReadBitPower_", (void *)&owReadBitPower); g_module_symbol(handle, "owReadByte_", (void *)&owReadByte); g_module_symbol(handle, "owReadBytePower_", (void *)&owReadBytePower); g_module_symbol(handle, "owSpeed_", (void *)&owSpeed); g_module_symbol(handle, "owTouchBit_", (void *)&owTouchBit); g_module_symbol(handle, "owTouchByte_", (void *)&owTouchByte); g_module_symbol(handle, "owTouchReset_", (void *)&owTouchReset); g_module_symbol(handle, "owWriteByte_", (void *)&owWriteByte); g_module_symbol(handle, "owWriteBytePower_", (void *)&owWriteBytePower); g_module_symbol(handle, "owAccess_", (void *)&owAccess); g_module_symbol(handle, "owFamilySearchSetup_", (void *)&owFamilySearchSetup); g_module_symbol(handle, "owFirst_", (void *)&owFirst); g_module_symbol(handle, "owNext_", (void *)&owNext); g_module_symbol(handle, "owOverdriveAccess_", (void *)&owOverdriveAccess); g_module_symbol(handle, "owSerialNum_", (void *)&owSerialNum); g_module_symbol(handle, "owSkipFamily_", (void *)&owSkipFamily); g_module_symbol(handle, "owVerify_", (void *)&owVerify); g_module_symbol(handle, "owAcquire_", (void *)&owAcquire__); g_module_symbol(handle, "owAcquireEx_", (void *)&owAcquireEx__); g_module_symbol(handle, "owRelease_", (void *)&owRelease); g_module_symbol(handle, "owBlock_", (void *)&owBlock); g_module_symbol(handle, "owProgramByte_", (void *)&owProgramByte); } int owAcquireEx(char *port_zstr) { if (handle == NULL) { loadiolib(port_zstr); } return owAcquireEx__(port_zstr); } SMALLINT owAcquire(int portnum, char *port_zstr) { if (handle == NULL) { loadiolib(port_zstr); } return owAcquire__(portnum, port_zstr); } w1retap/src/libusblinux300/atod20.c000066400000000000000000000242171446446235200172700ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // atod20.c - Module(s) to do conversion, setup, read, and write // on the DS2450 - 1-Wire Quad A/D Converter. // // // Version: 2.00 // // // -------------------------------------------------------------------------- #include #include "ownet.h" #include "atod20.h" // ------------------------------------------------------------------------- // Setup A to D control data. This is hardcoded to 5.12Volt scale at // 8 bits, but it could be read from a file. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'SerialNum' - Serial Number of device // 'ctrl' - pointer to conrtol data to set (fixed info for now) // 'msg' - poniter to string to return message // int SetupAtoDControl(int portnum, uchar *SerialNum, uchar *ctrl, char *msg) { uchar i; // set the device serial number to the DS2450 device owSerialNum(portnum, SerialNum, FALSE); // setup CONTROL register for (i = 0; i < 8; i += 2) { ctrl[i] = NO_OUTPUT | BITS_8; ctrl[i + 1] = RANGE_512 | ALARM_HIGH_DISABLE | ALARM_LOW_DISABLE; } // setup ALARM register for (i = 8; i < 16; i++) ctrl[i] = 0; // set return value sprintf(msg, "All channels set to 5.12V range at 8 bits"); return TRUE; } //-------------------------------------------------------------------------- // Write A to D with provided buffer. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'try_overdrive' - True(1) if want to try to use overdrive // 'SerialNum' - Serial Number of device // 'ctrl' - pointer to conrtol data to write // 'start_address' - start address to write // 'end_address' - end of address to write // // Returns: TRUE, success, results read ok // FALSE, failure to read // int WriteAtoD(int portnum, int try_overdrive, uchar *SerialNum, uchar *ctrl, int start_address, int end_address) { uchar send_block[50]; uchar i; short send_cnt = 0, flag, address; ushort lastcrc16; // build the first part of the packet to write // reset CRC setcrc16(portnum, 0); send_cnt = 0; // write memory command send_block[send_cnt++] = 0x55; lastcrc16 = docrc16(portnum, 0x55); // address send_block[send_cnt] = (uchar)(start_address & 0xFF); lastcrc16 = docrc16(portnum, send_block[send_cnt++]); send_block[send_cnt] = (uchar)((start_address >> 8) & 0xFF); lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // set the device serial number to the DS2450 device owSerialNum(portnum, SerialNum, FALSE); // select the device if (Select(portnum, try_overdrive)) { // loop to write each byte for (address = start_address; address <= end_address; address++) { // build the packet to write // init CRC on all but first pass if (address != start_address) setcrc16(portnum, address); // data to write send_block[send_cnt] = ctrl[address - start_address]; lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // read CRC16 send_block[send_cnt++] = 0xFF; send_block[send_cnt++] = 0xFF; // echo of byte send_block[send_cnt++] = 0xFF; // send the block flag = owBlock(portnum, FALSE, send_block, send_cnt); // check results of block if (flag == TRUE) { // perform crc16 on last 2 bytes for (i = (send_cnt - 3); i <= (send_cnt - 2); i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify crc16 is correct if ((lastcrc16 != 0xB001) || (send_block[send_cnt - 1] != ctrl[address - start_address])) return FALSE; } else return FALSE; // reset the packet setcrc16(portnum, 0); send_cnt = 0; } } // no device else return FALSE; return TRUE; } // -------------------------------------------------------------------------- // Attempt to do an A to D conversion // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'try_overdrive' - True(1) if want to try to use overdrive // 'SerialNum' - Serial Number of device // // // Returns: TRUE, success, conversion ok // FALSE, failure to do conversion // int DoAtoDConversion(int portnum, int try_overdrive, uchar *SerialNum) { uchar send_block[50]; int i; short send_cnt = 0; ushort lastcrc16; // set the device serial number to the DS2450 device owSerialNum(portnum, SerialNum, FALSE); // access the device if (Select(portnum, try_overdrive)) { setcrc16(portnum, 0); // create a block to send send_block[send_cnt] = 0x3C; lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // input select mask (all channels) send_block[send_cnt] = 0x0F; lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // read-out control send_block[send_cnt] = 0x00; lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // read CRC16 send_block[send_cnt++] = 0xFF; send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, (send_cnt))) { // check the CRC for (i = send_cnt - 2; i < (send_cnt); i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } // if success then apply the strong pullup if (!owWriteBytePower(portnum, ((send_cnt - 1) & 0x1F))) return FALSE; // delay the max time, 6ms msDelay(6); // set the pullup back to normal if (MODE_NORMAL != owLevel(portnum, MODE_NORMAL)) { OWERROR(OWERROR_LEVEL_FAILED); return FALSE; } // check conversion over if (owReadByte(portnum) == 0xFF) return TRUE; } } return FALSE; } //-------------------------------------------------------------------------- // Read A to D results // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'try_overdrive' - True(1) if want to try to use overdrive // 'SerialNum' - Serial Number of device // 'prslt' - pointer to array of 4 floats to return voltage results // 'ctrl' - pointer to conrtol data for reference when calculating // results. // // Returns: TRUE, success, results read ok // FALSE, failure to read // int ReadAtoDResults(int portnum, int try_overdrive, uchar *SerialNum, float *prslt, uchar *ctrl) { uchar i, send_cnt = 0; unsigned int templong; uchar rt = FALSE; uchar send_block[30]; ushort lastcrc16; setcrc16(portnum, 0); // set the device serial number to the DS2450 device owSerialNum(portnum, SerialNum, FALSE); // access the device if (Select(portnum, try_overdrive)) { // create a block to send that reads the DS2450 send_block[send_cnt++] = 0xAA; lastcrc16 = docrc16(portnum, 0xAA); // address block send_block[send_cnt++] = 0x00; send_block[send_cnt++] = 0x00; lastcrc16 = docrc16(portnum, 0x00); lastcrc16 = docrc16(portnum, 0x00); // read the bytes for (i = 0; i < 10; i++) send_block[send_cnt++] = 0xFF; // send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { // perform CRC16 for (i = send_cnt - 10; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 == 0xB001) { // success rt = TRUE; } } // verify read ok if (rt == TRUE) { // convert the value read to floats for (i = 3; i < 11; i += 2) { // (1.01) templong = ((send_block[i + 1] << 8) | send_block[i]) & 0x0000FFFF; prslt[(i - 3) / 2] = (float)((float)(templong / 65535.0) * ((ctrl[(i - 3) + 1] & 0x01) ? 5.12 : 2.56)); // (1.01) } } } return rt; } //-------------------------------------------------------------------------- // Select the current device and attempt overdrive if possible. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // 'try_overdrive' - True(1) if want to try to use overdrive // // Returns: TRUE(1) current device selected // FALSE(0) device not present // int Select(int portnum, int try_overdrive) { static uchar current_speed = MODE_NORMAL; // attempt to do overdrive if (try_overdrive) { // verify device is in overdrive if (current_speed == MODE_OVERDRIVE) { if (owAccess(portnum)) return TRUE; } if (owOverdriveAccess(portnum)) current_speed = MODE_OVERDRIVE; else current_speed = MODE_NORMAL; } return (owAccess(portnum)); } w1retap/src/libusblinux300/atod20.h000066400000000000000000000043571446446235200173000ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // atod20.h - header file for the Module(s) to do conversion, setup, read, // and write on the DS2450 - 1-Wire Quad A/D Converter. // -------------------------------------------------------------------------- // functions defined in atod20.c int SetupAtoDControl(int, uchar *, uchar *, char *); int WriteAtoD(int, int, uchar *, uchar *, int, int); int DoAtoDConversion(int, int, uchar *); int ReadAtoDResults(int, int, uchar *, float *, uchar *); int Select(int, int); // family codes of device(s) #define ATOD_FAM 0x20 // setup #define NO_OUTPUT 0x00 #define OUTPUT_ON 0x80 #define OUTPUT_OFF 0xC0 #define RANGE_512 0x01 #define RANGE_256 0x00 #define ALARM_HIGH_ENABLE 0x08 #define ALARM_LOW_ENABLE 0x04 #define ALARM_HIGH_DISABLE 0x00 #define ALARM_LOW_DISABLE 0x00 #define BITS_16 0x00 #define BITS_8 0x08 w1retap/src/libusblinux300/atod26.c000066400000000000000000000276651446446235200173100ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // atod26.c - Reads the voltage on the 1-Wire of the DS2438. // version 1.00 // // Include Files #include #include "ownet.h" #include "atod26.h" /** * Sets the DS2438 to read Vad or Vdd * * portnum the port number of the port being used for the * 1-Wire Network. * vdd flag indicating weather to read the Vdd or the Vad * SNum the serial number for the part that the read is * to be done on. * * @return 'true' if the read was complete */ int SetupAtoD(int portnum, int vdd, uchar *SNum) { uchar send_block[50]; uchar test; int send_cnt = 0; int i; ushort lastcrc8 = 0; int busybyte; owSerialNum(portnum, SNum, FALSE); // Recall the Status/Configuration page // Recall command send_block[send_cnt++] = 0xB8; // Page to Recall send_block[send_cnt++] = 0x00; if (!owBlock(portnum, FALSE, send_block, send_cnt)) return FALSE; send_cnt = 0; if (owAccess(portnum)) { // Read the Status/Configuration byte // Read scratchpad command send_block[send_cnt++] = 0xBE; // Page for the Status/Configuration byte send_block[send_cnt++] = 0x00; for (i = 0; i < 9; i++) send_block[send_cnt++] = 0xFF; if (owBlock(portnum, FALSE, send_block, send_cnt)) { setcrc8(portnum, 0); for (i = 2; i < send_cnt; i++) lastcrc8 = docrc8(portnum, send_block[i]); if (lastcrc8 != 0x00) return FALSE; } // Block else return FALSE; test = send_block[2] & 0x08; if (((test == 0x08) && vdd) || ((test == 0x00) && !(vdd))) return TRUE; } // Access if (owAccess(portnum)) { send_cnt = 0; // Write the Status/Configuration byte // Write scratchpad command send_block[send_cnt++] = 0x4E; // Write page send_block[send_cnt++] = 0x00; if (vdd) send_block[send_cnt++] = send_block[2] | 0x08; else send_block[send_cnt++] = send_block[2] & 0xF7; for (i = 0; i < 7; i++) send_block[send_cnt++] = send_block[i + 4]; if (owBlock(portnum, FALSE, send_block, send_cnt)) { send_cnt = 0; if (owAccess(portnum)) { // Copy the Status/Configuration byte // Copy scratchpad command send_block[send_cnt++] = 0x48; // Copy page send_block[send_cnt++] = 0x00; if (owBlock(portnum, FALSE, send_block, send_cnt)) { busybyte = owReadByte(portnum); while (busybyte == 0) busybyte = owReadByte(portnum); return TRUE; } // Block } // Access } // Block } // Access return FALSE; } /** * Read the Vdd or the Vad from the DS2438 * * portnum the port number of the port being used for the * 1-Wire Network. * vdd flag indicating weather to read the Vdd or the Vad * SNum the serial number for the part that the read is * to be done on. * * @return the floating point value of Vad or Vdd */ float ReadAtoD(int portnum, int vdd, uchar *SNum) { uchar send_block[50]; int send_cnt = 0; int i; int busybyte; ushort lastcrc8 = 0; ushort volts; float ret = (float)-1.0; int done = TRUE; do { if (SetupAtoD(portnum, vdd, SNum)) { if (owAccess(portnum)) { if (!owWriteByte(portnum, 0xB4)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return ret; } busybyte = owReadByte(portnum); while (busybyte == 0) busybyte = owReadByte(portnum); } if (owAccess(portnum)) { // Recall the Status/Configuration page // Recall command send_block[send_cnt++] = 0xB8; // Page to Recall send_block[send_cnt++] = 0x00; if (!owBlock(portnum, FALSE, send_block, send_cnt)) return ret; } send_cnt = 0; if (owAccess(portnum)) { // Read the Status/Configuration byte // Read scratchpad command send_block[send_cnt++] = 0xBE; // Page for the Status/Configuration byte send_block[send_cnt++] = 0x00; for (i = 0; i < 9; i++) send_block[send_cnt++] = 0xFF; if (owBlock(portnum, FALSE, send_block, send_cnt)) { setcrc8(portnum, 0); for (i = 2; i < send_cnt; i++) lastcrc8 = docrc8(portnum, send_block[i]); if (lastcrc8 != 0x00) return ret; } else return ret; if ((!vdd) && ((send_block[2] & 0x08) == 0x08)) done = FALSE; else done = TRUE; volts = (send_block[6] << 8) | send_block[5]; ret = (float)volts / 100; } // Access } } while (!done); return ret; } /** * Reads the temperature from the DS2438. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part that the read is * to be done on. * * @return the temperature in returned in C. */ double Get_Temperature(int portnum, uchar *SNum) { double ret = -1.0; uchar send_block[50]; int send_cnt = 0; int i; ushort lastcrc8 = 0; owSerialNum(portnum, SNum, FALSE); if (owAccess(portnum)) { // Convert Temperature command if (!owWriteByte(portnum, 0x44)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } } msDelay(10); if (owAccess(portnum)) { // Recall the Status/Configuration page // Recall command send_block[send_cnt++] = 0xB8; // Page to Recall send_block[send_cnt++] = 0x00; if (!owBlock(portnum, FALSE, send_block, send_cnt)) return FALSE; send_cnt = 0; } if (owAccess(portnum)) { // Read the Status/Configuration byte // Read scratchpad command send_block[send_cnt++] = 0xBE; // Page for the Status/Configuration byte send_block[send_cnt++] = 0x00; for (i = 0; i < 9; i++) send_block[send_cnt++] = 0xFF; if (owBlock(portnum, FALSE, send_block, send_cnt)) { setcrc8(portnum, 0); for (i = 2; i < send_cnt; i++) lastcrc8 = docrc8(portnum, send_block[i]); if (lastcrc8 != 0x00) return ret; } else return ret; // JH - fix sign for -ve values short itemp; itemp = ((send_block[4] << 8) | send_block[3]) >> 3; if (itemp & 0x1000) itemp |= ~0xFFF; ret = itemp * 0.03125; } // Access return ret; } /** * Sets the DS2438 to read Vsens * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part that the read is * to be done on. * * @return 'true' if the read was complete */ static int SetupAtoD_vsens(int portnum, uchar *SNum) { uchar send_block[50]; int send_cnt = 0; int i; ushort lastcrc8 = 0; int busybyte; owSerialNum(portnum, SNum, FALSE); // Recall the Status/Configuration page // Recall command send_block[send_cnt++] = 0xB8; // Page to Recall send_block[send_cnt++] = 0x00; if (!owBlock(portnum, FALSE, send_block, send_cnt)) return FALSE; send_cnt = 0; if (owAccess(portnum)) { // Read the Status/Configuration byte // Read scratchpad command send_block[send_cnt++] = 0xBE; // Page for the Status/Configuration byte send_block[send_cnt++] = 0x00; for (i = 0; i < 9; i++) send_block[send_cnt++] = 0xFF; if (owBlock(portnum, FALSE, send_block, send_cnt)) { setcrc8(portnum, 0); for (i = 2; i < send_cnt; i++) lastcrc8 = docrc8(portnum, send_block[i]); if (lastcrc8 != 0x00) return FALSE; } // Block else return FALSE; if (send_block[2] & 0x01) return TRUE; } // Access if (owAccess(portnum)) { send_cnt = 0; // Write the Status/Configuration byte // Write scratchpad command send_block[send_cnt++] = 0x4E; // Write page send_block[send_cnt++] = 0x00; send_block[send_cnt++] = send_block[2] | 0x01; for (i = 0; i < 7; i++) send_block[send_cnt++] = send_block[i + 4]; if (owBlock(portnum, FALSE, send_block, send_cnt)) { send_cnt = 0; if (owAccess(portnum)) { // Copy the Status/Configuration byte // Copy scratchpad command send_block[send_cnt++] = 0x48; // Copy page send_block[send_cnt++] = 0x00; if (owBlock(portnum, FALSE, send_block, send_cnt)) { busybyte = owReadByte(portnum); while (busybyte == 0) busybyte = owReadByte(portnum); return TRUE; } // Block } // Access } // Block } // Access return FALSE; } /** * Read the Vsens from the DS2438 * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part that the read is * to be done on. * * @return the floating point value of Vsens */ float ReadVsens(int portnum, uchar *SNum) { uchar send_block[50]; int send_cnt = 0; int i; int busybyte; ushort lastcrc8 = 0; short curr; float ret = -1.0; if (SetupAtoD_vsens(portnum, SNum)) { if (owAccess(portnum)) { if (!owWriteByte(portnum, 0xB4)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return ret; } busybyte = owReadByte(portnum); while (busybyte == 0) busybyte = owReadByte(portnum); } if (owAccess(portnum)) { // Recall the Status/Configuration page // Recall command send_block[send_cnt++] = 0xB8; // Page to Recall send_block[send_cnt++] = 0x00; if (!owBlock(portnum, FALSE, send_block, send_cnt)) return ret; } send_cnt = 0; if (owAccess(portnum)) { // Read the Status/Configuration byte // Read scratchpad command send_block[send_cnt++] = 0xBE; // Page for the Status/Configuration byte send_block[send_cnt++] = 0x00; for (i = 0; i < 9; i++) send_block[send_cnt++] = 0xFF; if (owBlock(portnum, FALSE, send_block, send_cnt)) { setcrc8(portnum, 0); for (i = 2; i < send_cnt; i++) lastcrc8 = docrc8(portnum, send_block[i]); if (lastcrc8 != 0x00) return ret; } else return ret; curr = (send_block[8] << 8) | send_block[7]; // Can't happen ???????? if (send_block[8] & 0x80) curr |= ~0x3ff; ret = ((float)(curr)*0.2441); #if 0 { int k; fputs("Buffer: ", stderr); for (k = 0; k < 9; k++) { fprintf(stderr, "%02x ", send_block[k]); } fputc('\n', stderr); fprintf(stderr, "Curr = %d %f\n", curr, ret); } #endif } // Access } return ret; } w1retap/src/libusblinux300/atod26.h000066400000000000000000000033241446446235200172770ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // atod26.h - Include file for Smart Battery Monitor demo. // // Version: 2.00 int SetupAtoD(int portnum, int vdd, uchar *); float ReadAtoD(int portnum, int vdd, uchar *); float ReadVsens(int portnum, uchar *); double Get_Temperature(int portnum, uchar *); #define SBATTERY_FAM 0x26 w1retap/src/libusblinux300/atodtst.c000066400000000000000000000112551446446235200176570ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // // atodtst.c - Application for the DS2450 - 1-Wire Quad A/D Converter. // // This application uses the files from the 'Public Domain' MicroLAN // libraries ('general' and 'userial'). // // Version: 2.00 // #include #include #include "ownet.h" #include "atod20.h" #include "findtype.h" // defines #define MAXDEVICES 20 // global serial numbers uchar FamilySN[MAXDEVICES][8]; //---------------------------------------------------------------------- // Main Test for the DS2450 - 1-Wire Quad A/D Converter // int main(int argc, char **argv) { char msg[45]; int NumDevices = 0; int i = 0; int start_address = 0x8; int end_address = 0x11; float prslt[4]; uchar ctrl[16]; int try_overdrive = 0; int portnum = 0; //------------------------------------------------------ // Introduction header printf("\n/---------------------------------------------\n"); printf(" Channels A to D Application - V2.00\n" " The following is a test to excersize a\n" " DS2450 - 1-Wire Quad A/D Converter \n\n"); printf(" Press any CTRL-C to stop this program.\n\n"); printf(" Output [Serial Number(s) ... Channel 'A' Value ... Channel 'B' Value ... \n" " ... Channel 'C' Value ... Channel 'D' Value] \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]); // Find the device(s) NumDevices = FindDevices(portnum, &FamilySN[0], 0x20, MAXDEVICES); if (NumDevices > 0) { printf("\n"); printf("Device(s) Found: \n"); for (i = 0; i < NumDevices; i++) { PrintSerialNum(FamilySN[i]); printf("\n"); if (SetupAtoDControl(portnum, FamilySN[i], &ctrl[0], &msg[0])) { printf("A/D settings found\n %s\n", msg); } else printf("\n\n\n ERROR, device set up unsuccessful!\n"); if (WriteAtoD(portnum, try_overdrive, FamilySN[i], &ctrl[0], start_address, end_address)) { printf("\nA/D settings written"); } else printf("\n\n\n ERROR, device not found!\n"); } } // (stops on CTRL-C) do { // read the current channels for (i = 0; i < NumDevices; i++) { printf("\n\n"); PrintSerialNum(FamilySN[i]); if (!DoAtoDConversion(portnum, try_overdrive, FamilySN[i])) { printf("\nError doing conversion, verify device present: %d\n", (int)owVerify(portnum, FALSE)); } if (ReadAtoDResults(portnum, try_overdrive, FamilySN[i], &prslt[0], &ctrl[0])) { int c = 0; for (c = 0; c < 4; c++) { printf(" %1.3f ", prslt[c]); } } else { printf("\nError reading channel, verify device present: %d\n", (int)owVerify(portnum, FALSE)); } } } while (!key_abort()); // release the 1-Wire Net owRelease(portnum); printf("Closing port %s.\n", argv[1]); exit(0); return 0; } w1retap/src/libusblinux300/braybaro.c000066400000000000000000000077621446446235200200060ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // gethumd.c - This utility gets the Volts for pins Vad and Vdd from the DS2438. // // Version: 2.00 // History: #include #include #include #include "ownet.h" #include "atod26.h" #include "findtype.h" #include "math.h" #define MAXDEVICES 5 #define ONEKBITADD 0x89 #define SLOPE (34.249672152) #define OFFSET (762.374681772) /* 35.949367089 751.075949363 */ 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; } float GetPressure(float Vad, float temp, int alt) { float pres = SLOPE * Vad + OFFSET; return (alt) ? pressure_at_msl(pres, temp, alt) : pres; } 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) { int portnum = 0; float Vdd, Vad; int c, alt = 0; char *dev; char *serial = NULL; u_char ident[8]; int verbose = 0; short dac = 0; while ((c = getopt(argc, argv, "da:s:v")) != EOF) { switch (c) { case 'v': verbose = 1; break; case 's': serial = strdup(optarg); break; case 'a': alt = atoi(optarg); break; case 'd': dac = 1; 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); if (verbose) { int i; fprintf(stderr, "Serial: %s\n", serial); fputs("Ident: ", stderr); for (i = 0; i < 8; i++) { fprintf(stderr, "%02X", ident[i]); } fputc('\n', stderr); fprintf(stderr, "Altitude: %d\n", alt); } Vdd = ReadAtoD(portnum, TRUE, ident); if (Vdd > 5.8) { Vdd = (float)5.8; } else if (Vdd < 4.0) { Vdd = (float)4.0; } Vad = ReadAtoD(portnum, FALSE, ident); printf("VSup %.2f Vout %.2f", Vdd, Vad); if (dac) { fputc('\n', stdout); } else { float temp = Get_Temperature(portnum, ident); float pres = GetPressure(Vad, temp, alt); printf(" Temp %.2f Pressure %.1f\n", temp, pres); } } return 0; } w1retap/src/libusblinux300/cnt1d.c000066400000000000000000000073611446446235200172110ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // cnt1D.c - Module to read the DS2423 - counter. // // Version: 2.00 // // #include "ownet.h" #include "cnt1d.h" //---------------------------------------------------------------------- // Read the counter on a specified page of a DS2423. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'SerialNum' - Serial Number of DS2423 that contains the counter // to be read // 'CounterPage' - page number that the counter is associated with // 'Count' - pointer to variable where that count will be returned // // Returns: TRUE(1) counter has been read and verified // FALSE(0) could not read the counter, perhaps device is not // in contact // SMALLINT ReadCounter(int portnum, uchar *SerialNum, int CounterPage, unsigned int *Count) { uchar rt = FALSE; uchar send_block[30]; uchar send_cnt = 0, i; int address; 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 // read memory and counter command send_block[send_cnt++] = 0xA5; lastcrc16 = docrc16(portnum, 0xA5); // address of last data byte before counter address = (CounterPage << 5) + 31; // (1.02) send_block[send_cnt++] = (uchar)(address & 0xFF); lastcrc16 = docrc16(portnum, (ushort)(address & 0xFF)); send_block[send_cnt++] = (uchar)(address >> 8); lastcrc16 = docrc16(portnum, (ushort)(address >> 8)); // now add the read bytes for data byte,counter,zero bits, crc16 for (i = 0; i < 11; i++) send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { // perform the CRC16 on the last 11 bytes of packet for (i = send_cnt - 11; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 == 0xB001) { // success rt = TRUE; // extract the counter value *Count = 0; for (i = send_cnt - 7; i >= send_cnt - 10; i--) { *Count <<= 8; *Count |= send_block[i]; } } } } // return the result flag rt return rt; } w1retap/src/libusblinux300/cnt1d.h000066400000000000000000000032321446446235200172070ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // cnt1D.h - Header Module to read the DS2423 - counter. // // Version: 2.00 // // exportable functions defined in cnt1d.c SMALLINT ReadCounter(int, uchar *, int, uint *); // family codes of devices #define COUNT_FAMILY 0x1D w1retap/src/libusblinux300/counter.c000066400000000000000000000076651446446235200176660ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // counter.c - Application to read the 1-Wire Net DS2423 - counter. // // 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 "cnt1d.h" #include "findtype.h" // defines #define MAXDEVICES 20 // global serial numbers uchar FamilySN[MAXDEVICES][8]; //---------------------------------------------------------------------- // Main Test for the DS2423 - counter // int main(int argc, char **argv) { int NumDevices = 0; int i; int CounterPage; uint Count; int portnum = 0; //------------------------------------------------------ // Introduction header printf("\n/---------------------------------------------\n"); printf(" Counter Application - V2.00\n" " The following is a test to excersize a\n" " DS2423 - counter \n\n"); printf(" Press any CTRL-C to stop this program.\n\n"); printf(" Output [Serial Number(s) ... Counter Value ... Counter Value ... " "Counter Value ... Counter Value] \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]); // Find the device(s) NumDevices = FindDevices(portnum, &FamilySN[0], 0x1D, 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 current counters for (i = 0; i < NumDevices; i++) { printf("\n"); PrintSerialNum(FamilySN[i]); for (CounterPage = 12; CounterPage <= 15; CounterPage++) { if (ReadCounter(portnum, FamilySN[i], CounterPage, &Count)) { printf(" %10d ", Count); } else printf("\nError reading counter, verify device present:%d\n", (int)owVerify(portnum, FALSE)); } } printf("\n\n"); } while (!key_abort()); } else printf("\n\n\n ERROR, device not found!\n"); // release the 1-Wire Net owRelease(portnum); printf("Closing port %s.\n", argv[1]); exit(0); return 0; } w1retap/src/libusblinux300/coupler.c000066400000000000000000000111121446446235200176360ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // coupler.C - Goes through the testing of the DS2409 device // Version 2.00 // // Include files #include #include #include "ownet.h" #include "findtype.h" #include "swt1f.h" // Constant definitions #define MAXDEVICES 15 //-------------------------------------------------------------------------- // This is the begining of the program that test the commands for the // DS2409 // int main(int argc, char **argv) { uchar SwitchSN[MAXDEVICES][8]; // the serial numbers for the devices short i, j; // loop counters int NumDevices = 0; // used for the number of devices on the branch uchar BranchSN[20][8]; // used for the devices on the main and aux. // branch uchar a[3]; // used for storing info data on the read/write char out[240]; // used for output of the info data 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 FindDevices(portnum, &SwitchSN[0], SWITCH_FAMILY, MAXDEVICES); // this is the main branch device list NumDevices = FindBranchDevice(portnum, SwitchSN[0], &BranchSN[0], MAXDEVICES, TRUE); printf("The device on the main branch\n"); for (j = 0; j < NumDevices; j++) { printf("%d: ", j + 1); for (i = 0; i < 8; i++) printf("%02X", BranchSN[j][i]); printf("\n"); } printf("\n"); // this is the auxilary branch device list NumDevices = FindBranchDevice(portnum, SwitchSN[0], &BranchSN[0], MAXDEVICES, FALSE); printf("The device on the Auxiliary branch\n"); for (j = 0; j < NumDevices; j++) { printf("%d: ", j + 1); for (i = 0; i < 8; i++) printf("%02X", BranchSN[j][i]); printf("\n"); } printf("\n"); // this is to test the all lines off command if (SetSwitch1F(portnum, SwitchSN[0], ALL_LINES_OFF, 0, a, TRUE)) printf("All lines off worked\n"); else printf("All lines off didn't work\n"); // this is to test the direct on main command if (SetSwitch1F(portnum, SwitchSN[0], DIRECT_MAIN_ON, 0, a, TRUE)) printf("Direct main on worked\n"); else printf("Direct main on didn't work\n"); // this is to test the smart auxilary on if (SetSwitch1F(portnum, SwitchSN[0], AUXILARY_ON, 2, a, TRUE)) printf("Auxilary on worked\n"); else printf("Auxilary didn't work\n"); // this is to test the read/write command and print the info. if (SetSwitch1F(portnum, SwitchSN[0], STATUS_RW, 1, a, TRUE)) { printf("Status read write worked and the results are below\n"); SwitchStateToString1F((short)a[1], out); printf("res: %s", out); } else printf("Status read write didn't work"); SetSwitch1F(portnum, SwitchSN[0], DIRECT_MAIN_ON, 0, a, TRUE); // SetSwitch1F(portnum, SwitchSN[0], AUXILARY_ON, 2, a, TRUE); owRelease(portnum); printf("Closing port %s.\n", argv[1]); exit(0); return 0; } w1retap/src/libusblinux300/crcutil.c000066400000000000000000000115761446446235200176500ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // crcutil.c - Keeps track of the CRC for 16 and 8 bit operations // version 2.00 // Include files #include "ownet.h" // Local global variables ushort utilcrc16[MAX_PORTNUM]; uchar utilcrc8[MAX_PORTNUM]; static short oddparity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}; static uchar dscrc_table[] = { 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53}; //-------------------------------------------------------------------------- // Reset crc16 to the value passed in // // 'reset' - data to set crc16 to. // void setcrc16(int portnum, ushort reset) { utilcrc16[portnum] = reset; return; } //-------------------------------------------------------------------------- // Reset crc8 to the value passed in // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'reset' - data to set crc8 to // void setcrc8(int portnum, uchar reset) { utilcrc8[portnum] = reset; return; } //-------------------------------------------------------------------------- // Calculate a new CRC16 from the input data short. Return the current // CRC16 and also update the global variable CRC16. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'data' - data to perform a CRC16 on // // Returns: the current CRC16 // ushort docrc16(int portnum, ushort cdata) { cdata = (cdata ^ (utilcrc16[portnum] & 0xff)) & 0xff; utilcrc16[portnum] >>= 8; if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4]) utilcrc16[portnum] ^= 0xc001; cdata <<= 6; utilcrc16[portnum] ^= cdata; cdata <<= 1; utilcrc16[portnum] ^= cdata; return utilcrc16[portnum]; } //-------------------------------------------------------------------------- // Update the Dallas Semiconductor One Wire CRC (utilcrc8) from the global // variable utilcrc8 and the argument. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'x' - data byte to calculate the 8 bit crc from // // Returns: the updated utilcrc8. // uchar docrc8(int portnum, uchar x) { utilcrc8[portnum] = dscrc_table[utilcrc8[portnum] ^ x]; return utilcrc8[portnum]; } w1retap/src/libusblinux300/devlist.h000066400000000000000000000066251446446235200176610ustar00rootroot00000000000000typedef struct { char *dev; char *name; uchar family; } w1devs_t; w1devs_t devlist[] = {{"2401", "silicon serial number", 1}, {"2411", "silicon serial number Vcc input", 1}, {"1425", "multikey 1153bit secure", 2}, {"2404", "econoram time chip", 4}, {"2405", "Addresable Switch", 5}, {NULL, "4k memory ibutton", 6}, {NULL, "1k memory ibutton", 8}, {"2502", "1k add-only memory", 9}, {NULL, "16k memory ibutton", 0xA}, {"2505", "16k add-only memory", 0x0B}, {NULL, "64k memory ibutton", 0xc}, {"2506", "64k add-only  memory", 0x0F}, {"18S20", "high precision digital thermometer", 0x10}, {"2406", "dual addressable switch plus 1k memory", 0x12}, {"2407", "dual addressable switch plus 1k memory", 0x12}, {"2430A", "256 eeprom", 0x14}, {NULL, "4k Monetary", 0x1A}, {"2436", "battery id/monitor chip", 0x1B}, {"28E04-100", "4k EEPROM with PIO", 0x1C}, {"2423", "4k ram with counter", 0x1D}, {"2409", "microlan coupler", 0x1F}, {"2450", "quad a/d converter", 0x20}, {NULL, "Thermachron", 0x21}, {"1822", "Econo Digital Thermometer", 0x22}, {"2433", "4k eeprom", 0x23}, {"2415", "time chip", 0x24}, {"2438", "smart battery monitor", 0x26}, {"2417", "time chip with interrupt", 0x27}, {"18B20", "programmable resolution digital thermometer", 0x28}, {"2408", "8-channel addressable switch", 0x29}, {"2890", "digital potentiometer", 0x2C}, {"2431", "1k eeprom", 0x2D}, {"2770", "battery monitor and charge controller", 0x2E}, {"2760", "high-precision li+ battery monitor", 0x30}, {"2761", "high precision li+ battery monitor", 0x30}, {"2762", "high precision li+ battery monitor with alerts", 0x30}, {"2720", "efficient addressable single-cell rechargable lithium protection ic", 0x31}, {"2432", "1k protected eeprom with SHA-1", 0x33}, {"2740", "high precision coulomb counter", 0x36}, {NULL, "Password protected 32k eeprom", 0x37}, {"2413", "dual channel addressable switch", 0x3A}, {"2422", "Temperature Logger 8k mem", 0x41}, {"2751", "multichemistry battery fuel gauge", 0x51}, {NULL, "Serial ID Button", 0x81}, {"2404S", "dual port plus time", 0x84}, {"2502-E48 2502-UNW", "48 bit node address chip", 0x89}, {"2505-UNW", "16k add-only uniqueware", 0x8B}, {"2506-UNW", "64k add-only uniqueware", 0x8F}, {"HB1WT", "Hobbyboards with temperature", 0xEE}, {"HB1W", "Hobbyboards without temperature", 0xEF}, {"LCD", "LCD (Swart)", 0xFF}, {NULL, NULL, 0}}; w1retap/src/libusblinux300/ds192x.c000066400000000000000000000205751446446235200172340ustar00rootroot00000000000000#include #include #include #include "ownet.h" #include "humutil.h" #include "ds192x.h" #define CONVERT_TEMPERATURE 0x44 #define STATUS_OFFSET 0x214 #define TEMP_OFFSET 0x211 static int WriteScratch(int, uchar *, int, int); static int CopyScratch(int, int, int); static int WriteMemory(int, uchar *, int, int); #ifdef TESTMAIN #include #include "../../config.h" #define TRACE(params) printf params #define DUMPBLOCK(a, b, c) dumpblock(a, b, c) static void dumpblock(char *label, uchar *block, int size) { int j; fputs(label, stdout); for (j = 0; j < size; j++) { printf(" %02x", block[j]); } fputc('\n', stdout); } #else #define TRACE(params) #define DUMPBLOCK(a, b, c) #endif //----------------------------------------------------------------------------} // 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; } #define READ_MEMORY 0xf0 static int readblock(int portnum, uchar *snum, short offset, uchar *buf) { uchar block[16]; int i = 0; int len = 0; *buf = 0xff; if (owAccess(portnum)) { TRACE(("ds1921: send read\n")); block[len++] = READ_MEMORY; block[len++] = offset & 0xff; block[len++] = (offset & 0xff00) >> 8; block[len++] = 0xff; i = owBlock(portnum, FALSE, block, len); *buf = block[3]; TRACE(("readblock %d \n", i)); DUMPBLOCK("data: ", block, len); } return i; } #define BIT_READY (1 << 7) #define BIT_MIP (1 << 5) #define STS_SIP (1 << 4) int ReadDS1921(int portnum, uchar *snum, ds1921_t *v) { int ret = 0; uchar val[2]; unsigned short id; v->temp = -42; owSerialNum(portnum, snum, FALSE); if ((ret = readblock(portnum, snum, 0x214, val))) { if (val[0] & BIT_MIP) { TRACE(("Mission in progress\n")); if (v->kill) { val[0] = 0; ret = WriteMemory(portnum, val, 1, 0x214); TRACE(("** Mission killed **\n")); } } else { TRACE(("Attempting DS1921\n")); if (owAccess(portnum)) ret = owTouchByte(portnum, 0x44); } if (ret) { for (ret = 0; (ret = readblock(portnum, snum, 0x214, val)) && !(val[0] & BIT_READY);) { msDelay(1); } if ((ret = readblock(portnum, snum, 0x211, val))) { TRACE(("Temp, raw %02x\n", val[0])); id = (*(snum + 5) >> 4) | *(snum + 6) << 4; if (id == 0x4f2) { // 1921H TRACE(("1921H ")); v->temp = val[0] / 8.0 + 14.500; } else if (id == 0x3B2) { // 1921K TRACE(("1921Z ")); v->temp = val[0] / 8.0 - 5.500; } else { TRACE(("1921G? ")); v->temp = val[0] / 2.0 - 40.0; } TRACE(("temp = %f C\n", v->temp)); } } } return ret; } int ReadDS1923(int portnum, uchar *snum, ds1923_t *v) { int ret = 0; uchar state[96]; double val, valsq, error; configLog config = {0}; v->temp = -42; v->rh = 200; if (v->kill) { stopMission(portnum, snum); } // set up config for DS1923 config.configByte = 0x20; TRACE(("Attempting DS1923\n")); if (readDevice(portnum, snum, state, &config)) { TRACE(("Read OK\n")); if (doTemperatureConvert(portnum, snum, state)) { TRACE(("Convert OK\n")); config.useTemperatureCalibration = 1; val = decodeTemperature(&state[12], 2, FALSE, config); valsq = val * val; error = config.tempCoeffA * valsq + config.tempCoeffB * val + config.tempCoeffC; v->temp = val - error; config.useHumidityCalibration = 1; val = decodeHumidity(&state[14], 2, FALSE, config); valsq = val * val; error = config.humCoeffA * valsq + config.humCoeffB * val + config.humCoeffC; v->rh = val - error; if (v->rh < 0.0) v->rh = 0.0; TRACE(("DS1923 result %f C %f %%\n", v->temp, v->rh)); ret = 1; } } return ret; } #ifdef TESTMAIN 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) { int portnum = 0; char *serial21 = NULL; char *serial23 = NULL; u_char ident[8]; int c; char *dev; int n1 = -42, n3 = -42; int dokill = 0; while ((c = getopt(argc, argv, "1:3:k")) != EOF) { switch (c) { case '1': serial21 = strdup(optarg); break; case '3': serial23 = strdup(optarg); break; case 'k': dokill = 1; break; default: break; } } dev = argv[optind]; TRACE(("DS192x tester %s\n", argv[0])); TRACE((__FILE__ " " __DATE__ " " __TIME__ "\n")); TRACE(("Based on w1retap " VERSION "\n")); if (dev == NULL || (serial21 == NULL && serial23 == NULL)) { fprintf(stderr, "Usage: %s -1 DS1921address -3 DS1923address device\n" " device -- DS2490-1 = first USB device\n" " /dev/ttyS0 = first serial port\n" " /dev/ttyUSB0 = USB/serial adaptor\n" "\tyou MUST give one of -1 addr or -3 addr\n" " e.g. %s -1 21F8190100204FC7 -3 410FA8010000005C /dev/ttyS0\n", argv[0], argv[0]); return 0; } if ((portnum = owAcquireEx(dev)) < 0) { fputs("Failed to acquire port.\n", stdout); } else { if (serial21) { ds1921_t v; v.kill = dokill; w1_make_serial(serial21, ident); n1 = ReadDS1921(portnum, ident, &v); } if (serial23) { ds1923_t v; w1_make_serial(serial23, ident); n3 = ReadDS1923(portnum, ident, &v); } } printf("finally %d %d\n", n1, n3); return 0; } #endif w1retap/src/libusblinux300/ds192x.h000066400000000000000000000004161446446235200172310ustar00rootroot00000000000000#ifndef __DS192x_H #define __DS192x_H 1 typedef struct { float rh; float temp; int kill; } ds1923_t; typedef struct { float temp; int kill; } ds1921_t; extern int ReadDS1921(int, uchar *, ds1921_t *); extern int ReadDS1923(int, uchar *, ds1923_t *); #endif w1retap/src/libusblinux300/ds2408lcd.c000066400000000000000000000051011446446235200175750ustar00rootroot00000000000000#include #include #include #include "ownet.h" #include "findtype.h" #include "math.h" #include static void output_byte(int portnum, uchar b) { uchar n, n1; owWriteByte(portnum, (uchar)b); owWriteByte(portnum, (uchar)(~b)); n = owReadByte(portnum); n1 = owReadByte(portnum); if (n != 0xaa) fprintf(stdout, "failed to write %02x %02x %02x\n", b, n, n1); } static void output_char(int portnum, uchar b, short flag) { uchar n; n = b & 0xf0; if (flag) n |= 0x10; output_byte(portnum, n); n = ((b << 4) & 0xf0); if (flag) n |= 0x10; output_byte(portnum, n); } int init_lcd(int portnum, uchar *snum) { uchar b; int rv = -1; owSerialNum(portnum, snum, FALSE); if (owAccess(portnum)) { owWriteByte(portnum, 0xcc); owWriteByte(portnum, 0x8d); owWriteByte(portnum, 0x00); owWriteByte(portnum, 0x04); owTouchReset(portnum); owAccess(portnum); /* a5 */ owWriteByte(portnum, 0xf0); owWriteByte(portnum, 0x8d); owWriteByte(portnum, 0x00); b = owReadByte(portnum); if (b != 0x84) { fputs("Init fails\n", stdout); owTouchReset(portnum); return rv; } owTouchReset(portnum); owAccess(portnum); /* a5 */ owWriteByte(portnum, 0x5a); rv = 0; } return rv; } void prep2display(int portnum) { fputs("Start init disp\n", stdout); output_byte(portnum, 0x30); msDelay(5); output_byte(portnum, 0x30); output_byte(portnum, 0x30); output_byte(portnum, 0x20); output_char(portnum, 0x28, 0); output_char(portnum, 0x0c, 0); output_char(portnum, 0x01, 0); output_char(portnum, 0x06, 0); output_char(portnum, 0x80, 0); } static void set_line(int portnum, int line) { // if(owAccess(portnum)) { uchar c; switch (line) { case 2: c = 0xc0; break; case 3: c = 0x94; case 4: c = 0xd4; break; default: c = 0x80; break; } output_char(portnum, c, 0); } } static void prep_display(int portnum) { owTouchReset(portnum); if (owAccess(portnum)) { owWriteByte(portnum, 0x5a); } msDelay(5); } static void show_text(int portnum, uchar *text) { // if(owAccess(portnum)) { uchar c; while ((c = *text++)) { if (c < ' ') c = ' '; output_char(portnum, c, 1); msDelay(1); } } } int send_text_lcd(int portnum, char *text, int line, int cls) { fputs("Init device\n", stdout); prep_display(portnum); set_line(portnum, line); fprintf(stdout, "Text is %s\n", text); show_text(portnum, (unsigned char *)text); return 0; } w1retap/src/libusblinux300/ds2408lcd.new.c000066400000000000000000000051011446446235200203650ustar00rootroot00000000000000#include #include #include #include "ownet.h" #include "findtype.h" #include "math.h" #include static void output_byte(int portnum, uchar b) { uchar n, n1; owWriteByte(portnum, (uchar)b); owWriteByte(portnum, (uchar)(~b)); n = owReadByte(portnum); n1 = owReadByte(portnum); if (n != 0xaa) fprintf(stdout, "failed to write %02x %02x %02x\n", b, n, n1); } static void output_char(int portnum, uchar b, short flag) { uchar n; n = b & 0xf0; if (flag) n |= 0x10; output_byte(portnum, n); n = ((b << 4) & 0xf0); if (flag) n |= 0x10; output_byte(portnum, n); } int init_lcd(int portnum, uchar *snum) { uchar b; int rv = -1; owSerialNum(portnum, snum, FALSE); if (owAccess(portnum)) { owWriteByte(portnum, 0xcc); owWriteByte(portnum, 0x8d); owWriteByte(portnum, 0x00); owWriteByte(portnum, 0x04); owTouchReset(portnum); owAccess(portnum); /* a5 */ owWriteByte(portnum, 0xf0); owWriteByte(portnum, 0x8d); owWriteByte(portnum, 0x00); b = owReadByte(portnum); if (b != 0x84) { fputs("Init fails\n", stdout); owTouchReset(portnum); return rv; } owTouchReset(portnum); owAccess(portnum); /* a5 */ owWriteByte(portnum, 0x5a); rv = 0; } return rv; } void prep2display(int portnum) { fputs("Start init disp\n", stdout); output_byte(portnum, 0x30); msDelay(5); output_byte(portnum, 0x30); output_byte(portnum, 0x30); output_byte(portnum, 0x20); output_char(portnum, 0x28, 0); output_char(portnum, 0x0c, 0); output_char(portnum, 0x01, 0); output_char(portnum, 0x06, 0); output_char(portnum, 0x80, 0); } static void set_line(int portnum, int line) { // if(owAccess(portnum)) { uchar c; switch (line) { case 2: c = 0xc0; break; case 3: c = 0x94; case 4: c = 0xd4; break; default: c = 0x80; break; } output_char(portnum, c, 0); } } static void prep_display(int portnum) { owTouchReset(portnum); if (owAccess(portnum)) { owWriteByte(portnum, 0x5a); } msDelay(5); } static void show_text(int portnum, uchar *text) { // if(owAccess(portnum)) { uchar c; while ((c = *text++)) { if (c < ' ') c = ' '; output_char(portnum, c, 1); msDelay(1); } } } int send_text_lcd(int portnum, char *text, int line, int cls) { fputs("Init device\n", stdout); prep_display(portnum); set_line(portnum, line); fprintf(stdout, "Text is %s\n", text); show_text(portnum, (unsigned char *)text); return 0; } w1retap/src/libusblinux300/ds2480.h000066400000000000000000000134541446446235200171310ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // DS2480.H - This file contains the DS2480B constants // // Version: 2.00 // // History: 1.02 -> 1.03 Make sure uchar is not defined twice. // // #include "ownet.h" #ifndef __MC68K__ #include #ifndef _WIN32_WCE #include #endif #endif // Mode Commands #define MODE_DATA 0xE1 #define MODE_COMMAND 0xE3 #define MODE_STOP_PULSE 0xF1 // Return byte value #define RB_CHIPID_MASK 0x1C #define RB_RESET_MASK 0x03 #define RB_1WIRESHORT 0x00 #define RB_PRESENCE 0x01 #define RB_ALARMPRESENCE 0x02 #define RB_NOPRESENCE 0x03 #define RB_BIT_MASK 0x03 #define RB_BIT_ONE 0x03 #define RB_BIT_ZERO 0x00 // Masks for all bit ranges #define CMD_MASK 0x80 #define FUNCTSEL_MASK 0x60 #define BITPOL_MASK 0x10 #define SPEEDSEL_MASK 0x0C #define MODSEL_MASK 0x02 #define PARMSEL_MASK 0x70 #define PARMSET_MASK 0x0E #define VERSION_MASK 0x1C // Command or config bit #define CMD_COMM 0x81 #define CMD_CONFIG 0x01 // Function select bits #define FUNCTSEL_BIT 0x00 #define FUNCTSEL_SEARCHON 0x30 #define FUNCTSEL_SEARCHOFF 0x20 #define FUNCTSEL_RESET 0x40 #define FUNCTSEL_CHMOD 0x60 // Bit polarity/Pulse voltage bits #define BITPOL_ONE 0x10 #define BITPOL_ZERO 0x00 #define BITPOL_5V 0x00 #define BITPOL_12V 0x10 // One Wire speed bits #define SPEEDSEL_STD 0x00 #define SPEEDSEL_FLEX 0x04 #define SPEEDSEL_OD 0x08 #define SPEEDSEL_PULSE 0x0C // Data/Command mode select bits #define MODSEL_DATA 0x00 #define MODSEL_COMMAND 0x02 // 5V Follow Pulse select bits (If 5V pulse // will be following the next byte or bit.) #define PRIME5V_TRUE 0x02 #define PRIME5V_FALSE 0x00 // Parameter select bits #define PARMSEL_PARMREAD 0x00 #define PARMSEL_SLEW 0x10 #define PARMSEL_12VPULSE 0x20 #define PARMSEL_5VPULSE 0x30 #define PARMSEL_WRITE1LOW 0x40 #define PARMSEL_SAMPLEOFFSET 0x50 #define PARMSEL_ACTIVEPULLUPTIME 0x60 #define PARMSEL_BAUDRATE 0x70 // Pull down slew rate. #define PARMSET_Slew15Vus 0x00 #define PARMSET_Slew2p2Vus 0x02 #define PARMSET_Slew1p65Vus 0x04 #define PARMSET_Slew1p37Vus 0x06 #define PARMSET_Slew1p1Vus 0x08 #define PARMSET_Slew0p83Vus 0x0A #define PARMSET_Slew0p7Vus 0x0C #define PARMSET_Slew0p55Vus 0x0E // 12V programming pulse time table #define PARMSET_32us 0x00 #define PARMSET_64us 0x02 #define PARMSET_128us 0x04 #define PARMSET_256us 0x06 #define PARMSET_512us 0x08 #define PARMSET_1024us 0x0A #define PARMSET_2048us 0x0C #define PARMSET_infinite 0x0E // 5V strong pull up pulse time table #define PARMSET_16p4ms 0x00 #define PARMSET_65p5ms 0x02 #define PARMSET_131ms 0x04 #define PARMSET_262ms 0x06 #define PARMSET_524ms 0x08 #define PARMSET_1p05s 0x0A #define PARMSET_2p10s 0x0C #define PARMSET_infinite 0x0E // Write 1 low time #define PARMSET_Write8us 0x00 #define PARMSET_Write9us 0x02 #define PARMSET_Write10us 0x04 #define PARMSET_Write11us 0x06 #define PARMSET_Write12us 0x08 #define PARMSET_Write13us 0x0A #define PARMSET_Write14us 0x0C #define PARMSET_Write15us 0x0E // Data sample offset and Write 0 recovery time #define PARMSET_SampOff3us 0x00 #define PARMSET_SampOff4us 0x02 #define PARMSET_SampOff5us 0x04 #define PARMSET_SampOff6us 0x06 #define PARMSET_SampOff7us 0x08 #define PARMSET_SampOff8us 0x0A #define PARMSET_SampOff9us 0x0C #define PARMSET_SampOff10us 0x0E // Active pull up on time #define PARMSET_PullUp0p0us 0x00 #define PARMSET_PullUp0p5us 0x02 #define PARMSET_PullUp1p0us 0x04 #define PARMSET_PullUp1p5us 0x06 #define PARMSET_PullUp2p0us 0x08 #define PARMSET_PullUp2p5us 0x0A #define PARMSET_PullUp3p0us 0x0C #define PARMSET_PullUp3p5us 0x0E // Baud rate bits #define PARMSET_9600 0x00 #define PARMSET_19200 0x02 #define PARMSET_57600 0x04 #define PARMSET_115200 0x06 // DS2480B program voltage available #define DS2480PROG_MASK 0x20 // mode bit flags #define MODE_NORMAL 0x00 #define MODE_OVERDRIVE 0x01 #define MODE_STRONG5 0x02 #define MODE_PROGRAM 0x04 #define MODE_BREAK 0x08 // Versions of DS2480 #define VER_LINK 0x1C #define VER_DS2480 0x08 #define VER_DS2480B 0x0C // exportable functions defined in ds2480ut.c SMALLINT DS2480Detect(int portnum); SMALLINT DS2480ChangeBaud(int portnum, uchar newbaud); // link functions from win32lnk.c or other link files SMALLINT OpenCOM(int portnum, char *port_zstr); int OpenCOMEx(char *port_zstr); void CloseCOM(int portnum); void FlushCOM(int portnum); SMALLINT WriteCOM(int portnum, int outlen, uchar *outbuf); int ReadCOM(int portnum, int inlen, uchar *inbuf); void BreakCOM(int portnum); void SetBaudCOM(int portnum, uchar new_baud); w1retap/src/libusblinux300/ds2480ut.c000066400000000000000000000163371446446235200175000ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ds2480ut.c - DS2480B utility functions. // // Version: 2.01 // // History: 1.00 -> 1.01 Default PDSRC changed from 0.83 to 1.37V/us // in DS2480Detect. Changed to use msDelay instead // of Delay. // 1.01 -> 1.02 Changed global declarations from 'uchar' to 'int'. // Changed DSO/WORT from 7 to 10us in DS2480Detect. // 1.02 -> 1.03 Removed caps in #includes for Linux capatibility // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. Changed W1LT to 8us. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" #include "ds2480.h" // global DS2480B state SMALLINT ULevel[MAX_PORTNUM]; // current DS2480B 1-Wire Net level SMALLINT UBaud[MAX_PORTNUM]; // current DS2480B baud rate SMALLINT UMode[MAX_PORTNUM]; // current DS2480B command or data mode state SMALLINT USpeed[MAX_PORTNUM]; // current DS2480B 1-Wire Net communication speed SMALLINT UVersion[MAX_PORTNUM]; // current DS2480B version //--------------------------------------------------------------------------- // Attempt to resyc and detect a DS2480B // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE - DS2480B detected successfully // FALSE - Could not detect DS2480B // SMALLINT DS2480Detect(int portnum) { uchar sendpacket[10], readbuffer[10]; uchar sendlen = 0; // reset modes UMode[portnum] = MODSEL_COMMAND; UBaud[portnum] = PARMSET_9600; USpeed[portnum] = SPEEDSEL_FLEX; // set the baud rate to 9600 SetBaudCOM(portnum, (uchar)UBaud[portnum]); // send a break to reset the DS2480 BreakCOM(portnum); // delay to let line settle msDelay(2); // flush the buffers FlushCOM(portnum); // send the timing byte sendpacket[0] = 0xC1; if (WriteCOM(portnum, 1, sendpacket) != 1) { OWERROR(OWERROR_WRITECOM_FAILED); return FALSE; } // delay to let line settle msDelay(4); // set the FLEX configuration parameters // default PDSRC = 1.37Vus sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus; // default W1LT = 10us sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write10us; // default DSO/WORT = 8us sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff8us; // construct the command to read the baud rate (to test command block) sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); // also do 1 bit operation (to test 1-Wire block) sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_BIT | UBaud[portnum] | BITPOL_ONE; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the response if (ReadCOM(portnum, 5, readbuffer) == 5) { // look at the baud rate and bit operation // to see if the response makes sense if (((readbuffer[3] & 0xF1) == 0x00) && ((readbuffer[3] & 0x0E) == UBaud[portnum]) && ((readbuffer[4] & 0xF0) == 0x90) && ((readbuffer[4] & 0x0C) == UBaud[portnum])) return TRUE; else OWERROR(OWERROR_DS2480_BAD_RESPONSE); } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); return FALSE; } //--------------------------------------------------------------------------- // Change the DS2480B from the current baud rate to the new baud rate. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'newbaud' - the new baud rate to change to, defined as: // PARMSET_9600 0x00 // PARMSET_19200 0x02 // PARMSET_57600 0x04 // PARMSET_115200 0x06 // // Returns: current DS2480B baud rate. // SMALLINT DS2480ChangeBaud(int portnum, uchar newbaud) { uchar rt = FALSE; uchar readbuffer[5], sendpacket[5], sendpacket2[5]; uchar sendlen = 0, sendlen2 = 0; // see if diffenent then current baud rate if (UBaud[portnum] == newbaud) return UBaud[portnum]; else { // build the command packet // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // build the command sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud; // flush the buffers FlushCOM(portnum); // send the packet if (!WriteCOM(portnum, sendlen, sendpacket)) { OWERROR(OWERROR_WRITECOM_FAILED); rt = FALSE; } else { // make sure buffer is flushed msDelay(5); // change our baud rate SetBaudCOM(portnum, newbaud); UBaud[portnum] = newbaud; // wait for things to settle msDelay(5); // build a command packet to read back baud rate sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen2, sendpacket2)) { // read back the 1 byte response if (ReadCOM(portnum, 1, readbuffer) == 1) { // verify correct baud if (((readbuffer[0] & 0x0E) == (sendpacket[sendlen - 1] & 0x0E))) rt = TRUE; else OWERROR(OWERROR_DS2480_WRONG_BAUD); } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); } } // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); return UBaud[portnum]; } w1retap/src/libusblinux300/ds2760.c000066400000000000000000000075141446446235200171250ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // ds2760.c - Reads the stuff on the 1-Wire of the DS2760. // modified from atod26.c // // Include Files #include #include "ownet.h" #include "ds2760.h" int ReadDS2760(int portnum, uchar *snum, ds2760_t *v) { int ret = 0; uchar send_block[16]; int i; owSerialNum(portnum, snum, FALSE); if (owAccess(portnum)) { send_block[0] = 0x69; // Data command send_block[1] = 0x0c; // offset to first data (volt, current); for (i = 2; i < 8; i++) { *(send_block + i) = 0xff; } if (owBlock(portnum, FALSE, send_block, 8)) { short ival; #ifdef DSDEBUG int k; fputs("ds2760 - got block1: ", stderr); for (k = 0; k < 8; k++) { fprintf(stderr, "%02x ", send_block[k]); } fputc('\n', stderr); #endif /* 10 bit voltage, sign extended as necessary */ ival = (send_block[2] << 3) | (send_block[3] >> 5); if (ival & 0x400) ival |= 0xfc00; v->volts = ival * 0.00488; /* 12 bit current, sign extended as necessary */ ival = (send_block[4] << 5) | (send_block[5] >> 3); #ifdef DSDEBUG fprintf(stderr, "Raw Current1: %04hx ", ival); #endif if (ival & 0x1000) ival |= 0xf000; #ifdef DSDEBUG fprintf(stderr, "Raw Current2: %04hx\n", ival); #endif v->curr = ival * 0.000625; /* 16 bit acculated charge */ ival = (send_block[6] << 8) | send_block[7]; #ifdef DSDEBUG fprintf(stderr, "Raw Accu: %04hx\n", ival); #endif v->accum = ival * 0.00025; owSerialNum(portnum, snum, FALSE); if (owAccess(portnum)) { #ifdef DSDEBUG fprintf(stderr, "owAccess %d\n", iret); #endif send_block[0] = 0x69; // Data command send_block[1] = 0x18; // offset to temp data *(send_block + 2) = *(send_block + 3) = 0xff; if (owBlock(portnum, FALSE, send_block, 4)) { #ifdef DSDEBUG int k; fputs("ds2760 - got block2: ", stderr); for (k = 0; k < 4; k++) { fprintf(stderr, "%02x ", send_block[k]); } fputc('\n', stderr); #endif ival = (send_block[2] << 3) | (send_block[3] >> 5); #ifdef DSDEBUG fprintf(stderr, "Raw Temp1: %04hx ", ival); #endif if (ival & 0x400) ival |= 0xfc00; #ifdef DSDEBUG fprintf(stderr, "Raw Temp2: %04hx\n", ival); #endif v->temp = ival * 0.125; ret = TRUE; } } } } return ret; } w1retap/src/libusblinux300/ds2760.h000066400000000000000000000002671446446235200171300ustar00rootroot00000000000000#ifndef __DS270_H #define __DS270_H 1 typedef struct { float volts; float curr; float accum; float temp; } ds2760_t; extern int ReadDS2760(int, uchar *, ds2760_t *); #endif w1retap/src/libusblinux300/findtype.c000066400000000000000000000055651446446235200200260ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // findtype.c - Test module to find all devices of one type. // // Version: 2.00 // //---------------------------------------------------------------------- // // #include "ownet.h" #include "findtype.h" //---------------------------------------------------------------------- // Search for devices // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'FamilySN' - an array of all the serial numbers with the matching // family code // 'family_code' - the family code of the devices to search for on the // 1-Wire Net // 'MAXDEVICES' - the maximum number of devices to look for with the // family code passed. // // Returns: TRUE(1) success, device type found // FALSE(0) device not found // SMALLINT FindDevices(int portnum, uchar FamilySN[][8], SMALLINT family_code, int MAXDEVICES) { int NumDevices = 0; // find the devices // set the search to first find that family code owFamilySearchSetup(portnum, family_code); // loop to find all of the devices up to MAXDEVICES NumDevices = 0; do { // perform the search if (!owNext(portnum, TRUE, FALSE)) break; owSerialNum(portnum, FamilySN[NumDevices], TRUE); if ((FamilySN[NumDevices][0] & 0x7F) == (family_code & 0x7F)) { NumDevices++; } } while (NumDevices < (MAXDEVICES - 1)); // check if not at least 1 device return NumDevices; } w1retap/src/libusblinux300/findtype.h000066400000000000000000000032361446446235200200240ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // findtype.c - Header for the module to find all devices of one type. // // Version: 2.00 // //---------------------------------------------------------------------- SMALLINT FindDevices(int, uchar FamilySN[][8], SMALLINT, int); w1retap/src/libusblinux300/fish.c000066400000000000000000001237551446446235200171370ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // fish.c - Goes through the testing of the file I/O functions // Version 2.00 // #include #include #include "ownet.h" #include "owfile.h" #include "rawmem.h" #include "mbshaee.h" // Defines for the menu lists #define MAIN_MENU 0 #define VERIFY_MENU 1 #define ENTRY_MENU 2 // Defines for the switch statements for Main Menu #define MAIN_SELECT_DEVICE 0 #define CHANGE_DIR 1 #define MAIN_LIST 2 #define MAIN_LIST_ALL 3 #define MAIN_MKDIR 4 #define MAIN_MKFILE 5 #define MAIN_WRITE_FILE 6 #define MAIN_READ_FILE 7 #define MAIN_DELETE_DIR 8 #define MAIN_DELETE_FILE 9 #define MAIN_RENAME 10 #define MAIN_WRITE_ADDFILE 11 #define MAIN_TERMINATE 12 #define MAIN_FORMAT 13 #define MAIN_QUIT 14 // Format file system on 1-Wire device. #define VERIFY_NO 0 #define VERIFY_YES 1 // Defines for the switch statements for data entry #define MODE_TEXT 0 #define MODE_HEX 1 // Number of devices to list #define MAXDEVICES 10 // Max number for data entry #define MAX_DATA 256 // External functions extern void owClearError(void); // Local functions int menuSelect(int menu); SMALLINT selectDevice(int numDevices, uchar AllDevices[][8]); void printDeviceInfo(int portnum, uchar SNum[8]); int getNumber(int min, int max); int getString(char *write_buff); void listDir(int portnum, uchar *SNum, FileEntry file, int recursive); void file_name(DirectoryPath *, FileEntry *, int); int main(int argc, char **argv) { int len, lentwo, selection; int done = FALSE; int first = TRUE; int portnum = 0; int error; uchar AllSN[MAXDEVICES][8]; int NumDevices; int owd = 0; char msg[132]; char dirname[64]; char answer[4]; char num[4]; DirectoryPath dirpath; FileEntry file; int i, j, cnt, digcnt, maxwrite; short hnd; uchar data[MAX_DATA]; // check for required port name if (argc != 2) { sprintf(msg, "1-Wire Net name required on command line!\n" " (example: \"COM1\" (Win32 DS2480D),\"/dev/cua0\" " "(Linux DS2480D),\"1\" (Win32 TMEX)\n"); printf("%s\n", msg); return 0; } printf("\n1-Wire File Shell for the Public Domain Kit Version 0.00\n"); if ((portnum = owAcquireEx(argv[1])) < 0) { OWERROR_DUMP(stdout); return 0; } else { // loop to do menu do { if (first) { selection = MAIN_SELECT_DEVICE; first = FALSE; } else selection = menuSelect(MAIN_MENU); // Main menu switch (selection) { case MAIN_SELECT_DEVICE: // find all parts // loop to find all of the devices up to MAXDEVICES NumDevices = 0; do { // perform the search if (!owNext(portnum, TRUE, FALSE)) break; owSerialNum(portnum, AllSN[NumDevices], TRUE); NumDevices++; } while (NumDevices < (MAXDEVICES - 1)); if (isJob(portnum, &AllSN[owd][0])) { printf("Would you like to write the programmed job " "before choosing another button?(Y/N)\n"); len = getString(&answer[0]); if ((answer[0] == 'Y') || (answer[0] == 'y')) if (!owDoProgramJob(portnum, &AllSN[owd][0])) OWERROR_DUMP(stderr); } // select a device owd = selectDevice(NumDevices, &AllSN[0]); // display device info printDeviceInfo(portnum, &AllSN[owd][0]); ChangeRom(portnum, &AllSN[owd][0]); break; case MAIN_FORMAT: if (menuSelect(VERIFY_MENU) == VERIFY_YES) { if (!isJob(portnum, &AllSN[owd][0])) owCreateProgramJob(portnum, &AllSN[owd][0]); owClearError(); if (!owFormat(portnum, &AllSN[owd][0])) OWERROR_DUMP(stderr); } break; case CHANGE_DIR: printf("Enter the directory you want to change to from the root " "(/ for root): "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); file.Ext = atoi(&num[0]); i = i + digcnt; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } if (dirname[0] == '.') dirpath.Ref = dirname[i]; if (len > 1) dirpath.NumEntries++; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_LIST: owClearError(); printf("Enter the directory to list on (/ for root): "); // get the directory and create a file on it len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); file.Ext = atoi(&num[0]); i = i + digcnt; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } if (dirname[0] == '.') dirpath.Ref = dirname[i]; if (len > 1) dirpath.NumEntries++; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else // list the files without recursion listDir(portnum, &AllSN[owd][0], file, FALSE); dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_LIST_ALL: // list the files with recursion owClearError(); dirpath.Ref = '0'; dirpath.NumEntries = 0; owChangeDirectory(portnum, &AllSN[owd][0], &dirpath); listDir(portnum, &AllSN[owd][0], file, TRUE); break; case MAIN_MKDIR: printf("Enter the directory to create from "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } else { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!isJob(portnum, &AllSN[owd][0])) owCreateProgramJob(portnum, &AllSN[owd][0]); owClearError(); if (!owCreateDir(portnum, &AllSN[owd][0], &file)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_MKFILE: printf("Enter the file name to create along with path from "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt]) && (digcnt < 5)); num[digcnt - 1] = 0; file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!isJob(portnum, &AllSN[owd][0])) owCreateProgramJob(portnum, &AllSN[owd][0]); owClearError(); if (!owCreateFile(portnum, &AllSN[owd][0], &maxwrite, &hnd, &file)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } else if (!owCloseFile(portnum, &AllSN[owd][0], hnd)) { OWERROR_DUMP(stderr); } } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_WRITE_FILE: printf("Enter the directory and file you would like to write to: "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!isJob(portnum, &AllSN[owd][0])) owCreateProgramJob(portnum, &AllSN[owd][0]); owClearError(); if (menuSelect(ENTRY_MENU) == MODE_TEXT) { len = getData(&data[0], MAX_DATA, FALSE); } else { len = getData(&data[0], MAX_DATA, TRUE); } owClearError(); if (!owOpenFile(portnum, &AllSN[owd][0], &file, &hnd)) { error = owGetErrorNum(); if (error == OWERROR_FILE_NOT_FOUND) { if (!owCreateFile(portnum, &AllSN[owd][0], &maxwrite, &hnd, &file)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } else { if (!owOpenFile(portnum, &AllSN[owd][0], &file, &hnd)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } else if (!owWriteFile(portnum, &AllSN[owd][0], hnd, &data[0], len)) { OWERROR_DUMP(stderr); } } } else { OWERROR(error); OWERROR_DUMP(stderr); } } else if (!owWriteFile(portnum, &AllSN[owd][0], hnd, &data[0], len)) { OWERROR_DUMP(stderr); } } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_READ_FILE: printf("Enter the directory and file you would like to read from: "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!owOpenFile(portnum, &AllSN[owd][0], &file, &hnd)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } else if (!owReadFile(portnum, &AllSN[owd][0], hnd, &data[0], MAX_DATA, &len)) { OWERROR_DUMP(stderr); } else for (i = 0; i < len; i++) printf("%02X ", data[i]); if (!owCloseFile(portnum, &AllSN[owd][0], hnd)) OWERROR_DUMP(stderr); } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_DELETE_DIR: printf("Enter the directory to delete from "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; dirpath.NumEntries++; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!isJob(portnum, &AllSN[owd][0])) owCreateProgramJob(portnum, &AllSN[owd][0]); owClearError(); if (!owRemoveDir(portnum, &AllSN[owd][0], &file)) OWERROR_DUMP(stderr); } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_DELETE_FILE: printf("Enter the file to delete from "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); num[digcnt - 1] = 0; file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!isJob(portnum, &AllSN[owd][0])) { owCreateProgramJob(portnum, &AllSN[owd][0]); owClearError(); } if (!owDeleteFile(portnum, &AllSN[owd][0], &file)) OWERROR_DUMP(stderr); } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_RENAME: printf("Enter the file to rename from : "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); num[digcnt - 1] = 0; file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!isJob(portnum, &AllSN[owd][0])) owCreateProgramJob(portnum, &AllSN[owd][0]); owClearError(); if (!owOpenFile(portnum, &AllSN[owd][0], &file, &hnd)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } else { printf("Enter the name to rename the file: "); len = getString(&dirname[0]); for (i = 0; i < len; i++) { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); num[digcnt - 1] = 0; file.Ext = atoi(&num[0]); i = i + digcnt; } else file.Name[i] = dirname[i]; } if (!owReNameFile(portnum, &AllSN[owd][0], hnd, &file)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } if (!owCloseFile(portnum, &AllSN[owd][0], hnd)) OWERROR_DUMP(stderr); } } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_WRITE_ADDFILE: if (!isJob(portnum, &AllSN[owd][0])) { if (!owCreateProgramJob(portnum, &AllSN[owd][0])) OWERROR_DUMP(stderr); } owClearError(); printf("Enter the file to addfile to create or append to from : "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); num[digcnt - 1] = 0; file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!owOpenFile(portnum, &AllSN[owd][0], &file, &hnd)) { owClearError(); if (!owCreateFile(portnum, &AllSN[owd][0], &maxwrite, &hnd, &file)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } else printf("File was created.\n"); } else { if (menuSelect(ENTRY_MENU) == MODE_TEXT) { len = getData(&data[0], MAX_DATA, FALSE); } else { len = getData(&data[0], MAX_DATA, TRUE); } printf("Do you want to append this data?\n"); lentwo = getString(&answer[0]); if ((answer[0] == 'Y') || (answer[0] == 'y')) { if (!owWriteAddFile(portnum, &AllSN[owd][0], hnd, 1, 0, &data[0], &len)) OWERROR_DUMP(stderr); if (!owCloseFile(portnum, &AllSN[owd][0], hnd)) OWERROR_DUMP(stderr); } else { printf("What offset would you like to start writing the data?\n"); len = getData(&data[0], MAX_DATA, FALSE); if (!owWriteAddFile(portnum, &AllSN[owd][0], hnd, 0, answer[0], &data[0], &len)) OWERROR_DUMP(stderr); if (!owCloseFile(portnum, &AllSN[owd][0], hnd)) OWERROR_DUMP(stderr); } } } dirpath = owGetCurrentDir(portnum, &AllSN[owd][0]); printf("\nThe Current Directory Path is> "); if (dirpath.NumEntries == 0) printf(" "); else { for (i = 0; i < dirpath.NumEntries; i++) { for (j = 0; j < 4; j++) printf("%c", dirpath.Entries[i][j]); printf("/"); } } printf("\n"); break; case MAIN_TERMINATE: printf("Enter the addfile to terminate from : "); len = getString(&dirname[0]); cnt = 0; dirpath.NumEntries = 0; for (i = 0; i < len; i++) { if (dirname[i] != '/') { if ((cnt < 4) && (dirname[i] != '.') && isalnum(dirname[i])) dirpath.Entries[dirpath.NumEntries][cnt++] = dirname[i]; else { if (dirname[i] == '.') { digcnt = 1; do { if (isdigit(dirname[i + digcnt])) { num[digcnt - 1] = dirname[i + digcnt]; digcnt++; } } while (isdigit(dirname[i + digcnt])); num[digcnt - 1] = 0; file.Ext = atoi(&num[0]); i = i + digcnt; for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; } else if ((i + 1) == len) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; cnt = 0; } } } else if (cnt > 0) { for (j = cnt; j < 4; j++) dirpath.Entries[dirpath.NumEntries][cnt++] = ' '; dirpath.NumEntries++; cnt = 0; } else if (dirname[0] == '/') { dirpath.NumEntries = 0; dirpath.Entries[0][0] = '.'; dirpath.Entries[0][1] = ' '; break; } } for (i = 0; i < 4; i++) file.Name[i] = dirpath.Entries[dirpath.NumEntries][i]; if (!owChangeDirectory(portnum, &AllSN[owd][0], &dirpath)) { file_name(&dirpath, &file, FALSE); OWERROR_DUMP(stderr); } else { if (!owOpenFile(portnum, &AllSN[owd][0], &file, &hnd)) { file_name(&dirpath, &file, TRUE); OWERROR_DUMP(stderr); } else { if (!isJob(portnum, &AllSN[owd][0])) { if (!owCreateProgramJob(portnum, &AllSN[owd][0])) OWERROR_DUMP(stderr); } owClearError(); if (!owTerminateAddFile(portnum, &AllSN[owd][0], &file)) { OWERROR_DUMP(stderr); } else printf("File will be terminated once job is programmed.\n"); } } break; case MAIN_QUIT: if (isJob(portnum, &AllSN[owd][0])) { printf("Would you like to write the programmed job " "before choosing another button?(Y/N)\n"); printf("The job will continue and try and write to the \n"); printf("iButton until it is successful or you hit Ctrl-C.\n"); len = getString(&answer[0]); if ((answer[0] == 'Y') || (answer[0] == 'y')) { do { if (!owDoProgramJob(portnum, &AllSN[owd][0])) { OWERROR_DUMP(stderr); } else { done = TRUE; } } while ((!done) || (!key_abort())); } } done = TRUE; break; default: break; } // Main menu switch } while (!done); // loop to do menu owRelease(portnum); } // else for owAcquire return 1; } /** * listDir * * Lists the current files/directories if recursive is FALSE * otherwise list all files and directories * * */ void listDir(int portnum, uchar *SNum, FileEntry file, int recursive) { int done; int i, j; DirectoryPath dirpath[10]; DirectoryPath init; int dir_cnt = 0; init = owGetCurrentDir(portnum, SNum); done = FALSE; do { done = !owNextFile(portnum, SNum, &file); if (file.Name[0] == '.') { done = !owNextFile(portnum, SNum, &file); if (file.Name[0] == '.') done = !owNextFile(portnum, SNum, &file); } if (!done) { if (!(recursive && (file.Ext == 0x7F))) { if (recursive) { printf("|"); for (i = 0; i < (4 * init.NumEntries) + 4; i++) printf("-"); } for (i = 0; i < 4; i++) if (file.Name[i] != ' ') printf("%c", file.Name[i]); } if (file.Ext == 0x7F && !recursive) printf(" \n"); else if (file.Ext == 0x7F) { dirpath[dir_cnt] = owGetCurrentDir(portnum, SNum); for (j = 0; j < 4; j++) dirpath[dir_cnt].Entries[dirpath[dir_cnt].NumEntries][j] = file.Name[j]; dirpath[dir_cnt++].NumEntries++; } else printf(".%03d\n", file.Ext); } } while (!done); done = FALSE; for (i = 0; i < dir_cnt; i++) { owChangeDirectory(portnum, SNum, &dirpath[i]); printf("|"); for (j = 0; j < (4 * dirpath[i].NumEntries) - 1; j++) printf("-"); printf("|"); for (j = 0; j < 4; j++) file.Name[j] = dirpath[i].Entries[dirpath[i].NumEntries - 1][j]; for (j = 0; j < 4; j++) printf("%c", file.Name[j]); printf("\n"); listDir(portnum, SNum, file, recursive); } if (dirpath[dir_cnt - 1].NumEntries == 1) { dirpath[0].Ref = '0'; dirpath[0].NumEntries = 0; owChangeDirectory(portnum, SNum, &dirpath[0]); } if (owHasErrors()) OWERROR_DUMP(stderr); } /** * Create a menu from the provided OneWireContainer * Vector and allow the user to select a device. * * numDevices the number of devices on the 1-Wire. * AllDevices holds all the Serial Numbers on the * 1-Wire. * * @return index of the choosen device. */ SMALLINT selectDevice(int numDevices, uchar AllDevices[][8]) { int i, j; printf("Device Selection\n"); for (i = 0; i < numDevices; i++) { printf("(%d) ", i); for (j = 7; j >= 0; j--) printf("%02X ", AllDevices[i][j]); printf("\n"); } return getNumber(0, numDevices - 1); } //-------- //-------- Menu Methods //-------- /** * Display menu and ask for a selection. * * menu the menu selections. * * @return numberic value entered from the console. */ int menuSelect(int menu) { int length = 0; switch (menu) { case MAIN_MENU: printf("\n"); printf("---- 1-Wire File Shell ----\n"); printf("(0) Select Device\n"); printf("(1) Change Directory\n"); printf("(2) Directory list\n"); printf("(3) Directory list (recursive)\n"); printf("(4) Make Directory\n"); printf("(5) Create empty file \n"); printf("(6) Write data to a file\n"); printf("(7) Read data from a file\n"); printf("(8) Delete 1-Wire directory\n"); printf("(9) Delete 1-Wire file\n"); printf("(10) Rename 1-Wire file\n"); printf("(11) Write or Add to AddFile\n"); printf("(12) Terminate an AddFile\n"); printf("(13) Format filesystem on 1-Wire device\n"); printf("[14]-Quit\n"); length = 14; break; case VERIFY_MENU: printf("\n"); printf("Format file system on 1-Wire device?\n"); printf("(0) NO\n"); printf("(1) YES (delete all files/directories)\n"); length = 1; break; case ENTRY_MENU: printf("\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = 1; break; } printf("\nPlease enter value: "); return getNumber(0, length); } /** * 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; } /** * Retrieve user input from the console in the form of hex or text. * * write_buff the buffer for the data to be written into. * * @return length of array */ int getString(char *write_buff) { char ch; int cnt = 0; int done = FALSE; do { ch = (char)getchar(); if (!isspace(ch)) write_buff[cnt++] = ch; else if ((cnt > 0) && (ch != ' ')) { write_buff[cnt++] = 0; done = TRUE; } } while (!done); return cnt; } //-------- //-------- Display Methods //-------- /** * Display information about the 1-Wire device * * portnum port number for the device * SNum serial number for the device */ void printDeviceInfo(int portnum, uchar SNum[8]) { int i; printf("\n"); printf("*************************************************************************\n"); printf("* Device Name: %s\n", owGetName(&SNum[0])); printf("* Device Address: "); for (i = 7; i >= 0; i--) printf("%02X ", SNum[i]); printf("\n"); printf("* iButton Description: %s\n", owGetDescription(&SNum[0])); printf("*************************************************************************\n"); } /** * Display the correct file structure. */ void file_name(DirectoryPath *dirpath, FileEntry *file, int inc_filename) { int i, j; printf("The file format from the root should look like this:\n"); printf("suba/subb/newf.5\n"); if (dirpath->NumEntries > 0) { printf("This is the path you gave:\n"); for (i = 0; i < dirpath->NumEntries; i++) { for (j = 0; j < 4; j++) { if (dirpath->Entries[i][j] != ' ') printf("%c", dirpath->Entries[i][j]); } printf("/\n"); } } else { printf("No path was read and if '\\' was the first symbol\n"); printf("then no path was read and the file name isn't going\n"); printf("to be valid.\n"); } if (inc_filename) { printf("The file name is:\n"); for (i = 0; i < 4; i++) { if (file->Name[i] != ' ') printf("%c", file->Name[i]); } printf("\n"); } } w1retap/src/libusblinux300/gethumd.c000066400000000000000000000070611446446235200176320ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // gethumd.c - This utility gets the Volts for pins Vad and Vdd from the DS2438. // // Version: 2.00 // History: #include #include "ownet.h" #include "atod26.h" #include "findtype.h" #define MAXDEVICES 5 #define ONEKBITADD 0x89 //---------------------------------------------------------------------- // This is the Main routine for debit // int main(int argc, char **argv) { char msg[200]; int portnum = 0; float Vdd, Vad; double humid, temp; int i; int numbat, cnt = 0; uchar famvolt[MAXDEVICES][8]; // 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; } if ((portnum = owAcquireEx(argv[1])) < 0) { printf("Failed to acquire port.\n"); return 0; } else { do { numbat = FindDevices(portnum, &famvolt[0], SBATTERY_FAM, MAXDEVICES); if (numbat == 0) { if (cnt > 1000) { cnt = 0; printf("No humidity buttons found.\n"); } else { cnt++; } } else { for (i = 0; i < numbat; i++) { Vdd = ReadAtoD(portnum, TRUE, &famvolt[0][0]); if (Vdd > 5.8) { Vdd = (float)5.8; } else if (Vdd < 4.0) { Vdd = (float)4.0; } Vad = ReadAtoD(portnum, FALSE, &famvolt[0][0]); temp = Get_Temperature(portnum, &famvolt[0][0]); humid = (((Vad / Vdd) - 0.16) / 0.0062) / (1.0546 - 0.00216 * temp); if (humid > 100) { humid = 100; } else if (humid < 0) { humid = 0; } printf("\n"); printf("The humidity is: %4.4f\n", humid); printf("Given that the temp was: %2.2f\n", temp); printf("and the volt supply was: %2.2f\n", Vdd); printf("with the volt output was: %2.2f\n", Vad); printf("\n"); } // for loop } } while (!key_abort()); owRelease(portnum); printf("Port released.\n"); } return 1; } w1retap/src/libusblinux300/hbht.c000066400000000000000000000071441446446235200171240ustar00rootroot00000000000000/* * hbht.c -- HobbyBoards UVI interface for w1retap * (c) 2015 Jonathan Hudson * * Depends on the Dallas PD kit, so let's assume their PD licence (or * MIT/X if that works for you) * */ #include #include #include #include "ownet.h" #include "hbht.h" static char debug; static int HBHT_access(int portnum, uchar *serno) { owTouchReset(portnum); msDelay(100); owSerialNum(portnum, serno, FALSE); return owAccess(portnum); } int HBHT_setup(int portnum, uchar *serno, hbht_t *hb, char *params) { int ret = 0; debug = 1; memset(hb, 0, sizeof(*hb)); if (HBHT_access(portnum, serno)) { if (params && *params) { uchar c; short hoff; char *p1, *p2; for (p1 = params; (p2 = strtok(p1, ", ")); p1 = NULL) { if (sscanf(p2, "pf=%hhu", &c)) { HBHT_set_poll_freq(portnum, serno, c); } else if (sscanf(p2, "ho=%hd", &hoff)) { HBHT_set_hum_offset(portnum, serno, hoff); } } } HBHT_read_version(portnum, serno, hb->version); hb->humid_offset = HBHT_get_hum_offset(portnum, serno); hb->poll_freq = HBHT_get_poll_freq(portnum, serno); ret = 1; } return ret; } static void HBHT_set_byteval(int portnum, uchar *snum, uchar act, uchar val) { uchar block[2]; if (HBHT_access(portnum, snum)) { block[0] = act; block[1] = val; owBlock(portnum, FALSE, block, sizeof(block)); } } void HBHT_get_byteval(int portnum, uchar *snum, uchar act, uchar *val) { uchar block[2]; if (HBHT_access(portnum, snum)) { block[0] = act; block[1] = 0xff; if (owBlock(portnum, FALSE, block, sizeof(block))) { *val = block[1]; } } } void HBHT_get_bytes(int portnum, uchar *snum, uchar act, uchar *val, int nval) { uchar block[32]; int i; if (HBHT_access(portnum, snum)) { block[0] = act; for (i = 0; i < nval; i++) { block[1 + i] = 0xff; } if (owBlock(portnum, FALSE, block, 1 + nval)) { for (i = 0; i < nval; i++) { *(val + i) = block[1 + i]; } } } } void HBHT_set_poll_freq(int portnum, uchar *snum, uchar val) { HBHT_set_byteval(portnum, snum, HBHT_SETPOLLFREQ, val); } uchar HBHT_get_poll_freq(int portnum, uchar *snum) { uchar val = 0; HBHT_get_byteval(portnum, snum, HBHT_GETPOLLFREQ, &val); return val; } short HBHT_get_hum_offset(int portnum, uchar *snum) { uchar hoff_raw[2] = {0, 0}; short hoff; HBHT_get_bytes(portnum, snum, HBHT_GETHUMIDOFFSET, hoff_raw, 2); hoff = (hoff_raw[0] | (hoff_raw[1] << 8)); if (debug) fprintf(stderr, "read raw hoff bytes %x %x = %d\n", hoff_raw[0], hoff_raw[1], hoff); return hoff; } void HBHT_set_hum_offset(int portnum, uchar *snum, short hoff) { uchar block[4]; if (HBHT_access(portnum, snum)) { block[0] = HBHT_SETHUMIDOFFSET; block[1] = hoff & 0xff; block[2] = hoff >> 8; owBlock(portnum, FALSE, block, 1 + sizeof(short)); } } void HBHT_read_version(int portnum, uchar *snum, char *vers) { HBHT_get_bytes(portnum, snum, HBHT_READVERSION, (uchar *)vers, 2); } int HBHT_read_data(int portnum, uchar *snum, hbht_res_t *hb) { uchar tchar[2] = {0, 0}; HBHT_get_bytes(portnum, snum, HBHT_GETTEMPERATURE_C, (uchar *)&tchar, 2); hb->temp = (float)((short)(tchar[0] | (tchar[1] << 8))) / 10.0; HBHT_get_bytes(portnum, snum, HBHT_GETCORRHUMID, (uchar *)&tchar, 2); hb->humid = (float)((short)(tchar[0] | (tchar[1] << 8))) / 100.0; if (debug) { fprintf(stderr, "read temp bytes %02x %02x = %.1f\n", tchar[0], tchar[1], hb->temp); fprintf(stderr, "read humid bytes %x %x = %.1f\n", tchar[0], tchar[1], hb->humid); } return 1; } w1retap/src/libusblinux300/hbht.h000066400000000000000000000020741446446235200171260ustar00rootroot00000000000000/* * hbht.h- HobbyBoards 'new' humidity & temperature interface for w1retap * (c) 2015 Jonathan Hudson * * Depends on the Dallas PD kit, so let's assume their PD licence (or * MIT/X if that works for you) * */ #ifndef __HBHT_H #define __HBHT_H 1 typedef struct { short humid_offset; char version[2]; uchar poll_freq; uchar debug; } hbht_t; typedef struct { float temp; float humid; } hbht_res_t; #define HBHT_READVERSION (0x11) #define HBHT_READTYPE (0x12) #define HBHT_GETPOLLFREQ (0x14) #define HBHT_SETPOLLFREQ (0x94) #define HBHT_GETHUMIDOFFSET (0x24) #define HBHT_SETHUMIDOFFSET (0xA4) #define HBHT_GETTEMPERATURE_C (0x40) #define HBHT_GETCORRHUMID (0x21) extern int HBHT_read_data(int, uchar *, hbht_res_t *); extern void HBHT_read_version(int, uchar *, char *); extern int HBHT_setup(int, uchar *, hbht_t *, char *); extern void HBHT_set_hum_offset(int, uchar *, short); extern short HBHT_get_hum_offset(int, uchar *); extern void HBHT_set_poll_freq(int, uchar *, uchar); extern uchar HBHT_get_poll_freq(int, uchar *); #endif w1retap/src/libusblinux300/hbhttest.c000066400000000000000000000075011446446235200200210ustar00rootroot00000000000000#include #include #include #include "ownet.h" #include "findtype.h" #include "swt1f.h" #include #include "hbht.h" 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; } static void usage(void) { fputs("usage: hbhttest -s serial [-c coupler -a|-m ] [-p params] device\n\n" " device => /dev/tty* or DS2490-1\n" " serial => Device serial number\n" " coupler => Coupler serial number (if needed)\n" " -m, -a => indicates coupler branch (_main or _aux)\n" " params => settings for non-volatile RAM\n\n" " The coupler setting are ony needed when the device is accessed\n" " through a DS2409 microlan coupler\n\n" " The params option provides values for non-volatile RAM. These values\n" " only need to be supplied once, or if a change is required.\n" " The option is supplied as a space or comma delimited string\n" " \"pf=POLLFREQ to=TEMPOFFSET\" where:\n" " pf=POLLFREQ supplies POLLFREQ value (as bit flag)\n" " ho=HUMIDOFFSET supplies HUMIDOFFSET as the offset in 1/100%\n" " Please see the vendor documentation for further details\n\n" " e.g. ./hbhttest -s EFnnnnnnnnnnnnnn -c 1Fnnnnnnnnnnnnnn -m \\\n" " -p \"pf=8 ho=40\" DS2490-1\n" " # you can omit not neeeded settings ...\n" " ./hbhttest -s EFnnnnnnnnnnnnnn -p \"ho=42\" DS2490-1\n\n" " The application reports current settings and read values\n", stderr); exit(0); } int main(int argc, char **argv) { int portnum = 0; char *serial = NULL, *dev = NULL; uchar ident[8]; char *coupler = NULL; uchar *cident = NULL; char *params = NULL; int c; int bra = 0; int ret = -1; hbht_t hbht = {0}; hbht_t *hb = &hbht; hbht_res_t hb_res; while ((c = getopt(argc, argv, "amc:s:p:h?")) != EOF) { switch (c) { case 'a': bra = 2; break; case 'm': bra = 4; break; case 's': serial = strdup(optarg); break; case 'c': coupler = strdup(optarg); case 'p': params = strdup(optarg); break; case 'h': case '?': default: usage(); break; } } dev = argv[optind]; if (dev == NULL || serial == NULL) { usage(); } 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); } hb->debug = 1; ret = HBHT_setup(portnum, ident, hb, params); printf("HBUV_setup returns %d\n" "version = %d.%d\n" "humid offset = %d\n" "poll_freq = %d\n", ret, hb->version[1], hb->version[0], hb->humid_offset, hb->poll_freq); ret = HBHT_read_data(portnum, ident, &hb_res); printf("HBUV_read_data returns %d\n" "temp = %.1f ⁰C\n" "humidity = %.1f\n", ret, hb_res.temp, hb_res.humid); if (coupler) { w1_set_coupler(portnum, cident, 0); } owRelease(portnum); return 0; } w1retap/src/libusblinux300/hbuv.c000066400000000000000000000067341446446235200171470ustar00rootroot00000000000000/* * hbuv.c -- HobbyBoards UVI interface for w1retap * (c) 2011 Jonathan Hudson * * Depends on the Dallas PD kit, so let's assume their PD licence (or * MIT/X if that works for you) * */ #include #include #include #include "ownet.h" #include "hbuv.h" int HBUV_setup(int portnum, uchar *serno, hbuv_t *hb, char *params) { int ret = 0; memset(hb, 0, sizeof(*hb)); owSerialNum(portnum, serno, FALSE); if (owAccess(portnum)) { if (params && *params) { char c; char *p1, *p2; for (p1 = params; (p2 = strtok(p1, ", ")); p1 = NULL) { if (sscanf(p2, "uo=%hhd", &c)) { HBUV_set_uvi_offset(portnum, serno, c); } else if (sscanf(p2, "to=%hhd", &c)) { HBUV_set_temp_offset(portnum, serno, c); } else if (sscanf(p2, "case=%hhd", &c)) { if (c != 0) c = 0xff; HBUV_set_case(portnum, serno, (uchar)c); } } } HBUV_read_version(portnum, serno, hb->version); HBUV_get_case(portnum, serno, &hb->has_case); HBUV_get_temp_offset(portnum, serno, &hb->temp_offset); HBUV_get_uvi_offset(portnum, serno, &hb->uvi_offset); ret = 1; } return ret; } static void HBUV_set_byteval(int portnum, uchar *snum, uchar act, uchar val) { uchar block[2]; owSerialNum(portnum, snum, FALSE); if (owAccess(portnum)) { block[0] = act; block[1] = val; owBlock(portnum, FALSE, block, sizeof(block)); } } void HBUV_get_byteval(int portnum, uchar *snum, uchar act, uchar *val) { uchar block[2]; owSerialNum(portnum, snum, FALSE); if (owAccess(portnum)) { block[0] = act; block[1] = 0xff; if (owBlock(portnum, FALSE, block, sizeof(block))) { *val = block[1]; } } } void HBUV_get_bytes(int portnum, uchar *snum, uchar act, uchar *val, int nval) { uchar block[32]; int i; owSerialNum(portnum, snum, FALSE); if (owAccess(portnum)) { block[0] = act; for (i = 0; i < nval; i++) { block[1 + i] = 0xff; } if (owBlock(portnum, FALSE, block, 1 + nval)) { for (i = 0; i < nval; i++) { *(val + i) = block[1 + i]; } } } } void HBUV_set_case(int portnum, uchar *snum, uchar val) { HBUV_set_byteval(portnum, snum, HBUV_SETINCASE, val); } void HBUV_get_case(int portnum, uchar *snum, uchar *val) { HBUV_get_byteval(portnum, snum, HBUV_READINCASE, val); } void HBUV_set_uvi_offset(int portnum, uchar *snum, char val) { HBUV_set_byteval(portnum, snum, HBUV_SETUVIOFFSET, (uchar)val); } void HBUV_get_uvi_offset(int portnum, uchar *snum, char *val) { HBUV_get_byteval(portnum, snum, HBUV_READUVIOFFSET, (uchar *)val); } void HBUV_set_temp_offset(int portnum, uchar *snum, char val) { HBUV_set_byteval(portnum, snum, HBUV_SETTEMPOFFSET, (uchar)val); } void HBUV_get_temp_offset(int portnum, uchar *snum, char *val) { HBUV_get_byteval(portnum, snum, HBUV_READTEMPOFFSET, (uchar *)val); } void HBUV_read_version(int portnum, uchar *snum, char *vers) { HBUV_get_bytes(portnum, snum, HBUV_READVERSION, (uchar *)vers, 2); } int HBUV_read_data(int portnum, uchar *snum, hbuv_t *hb) { uchar uvi = 0; char tchar[2]; int ret = 0; HBUV_get_byteval(portnum, snum, HBUV_READUVI, &uvi); if (uvi == 0xff) { HBUV_get_byteval(portnum, snum, HBUV_READUVI, &uvi); } if (uvi != 0xff) { ret = 1; hb->raw_uvi = (uchar)uvi; HBUV_get_bytes(portnum, snum, HBUV_READTEMPERATURE, (uchar *)&tchar, 2); hb->raw_temp = tchar[0] | (tchar[1] << 8); } return ret; } w1retap/src/libusblinux300/hbuv.h000066400000000000000000000023561446446235200171500ustar00rootroot00000000000000/* * hbuv.h -- HobbyBoards UVI interface for w1retap * (c) 2011 Jonathan Hudson * * Depends on the Dallas PD kit, so let's assume their PD licence (or * MIT/X if that works for you) * */ #ifndef __HBUV_H #define __HBUV_H 1 typedef struct { uchar has_case; char uvi_offset; char temp_offset; unsigned char uv_type; short raw_temp; unsigned char raw_uvi; unsigned char is_valid; char version[2]; } hbuv_t; #define HBUV_READVERSION (0x11) #define HBUV_READTYPE (0x12) #define HBUV_READTEMPERATURE (0x21) #define HBUV_SETTEMPOFFSET (0x22) #define HBUV_READTEMPOFFSET (0x23) #define HBUV_READUVI (0x24) #define HBUV_SETUVIOFFSET (0x25) #define HBUV_READUVIOFFSET (0x26) #define HBUV_SETINCASE (0x27) #define HBUV_READINCASE (0x28) extern int HBUV_read_data(int, uchar *, hbuv_t *); extern void HBUV_read_version(int, uchar *, char *); extern int HBUV_setup(int, uchar *, hbuv_t *, char *); extern void HBUV_set_case(int, uchar *, uchar); extern void HBUV_get_case(int, uchar *, uchar *); extern void HBUV_set_temp_offset(int, uchar *, char); extern void HBUV_get_temp_offset(int, uchar *, char *); extern void HBUV_set_uvi_offset(int, uchar *, char); extern void HBUV_get_uvi_offset(int, uchar *, char *); #endif w1retap/src/libusblinux300/hbuvtest.c000066400000000000000000000101671446446235200200420ustar00rootroot00000000000000#include #include #include #include "ownet.h" #include "findtype.h" #include "swt1f.h" #include #include "hbuv.h" 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; } static void usage(void) { fputs("usage: hbuvtest -s serial [-c coupler -a|-m ] [-p params] device\n\n" " device => /dev/tty* or DS2490-1\n" " serial => Device serial number\n" " coupler => Coupler serial number (if needed)\n" " -m, -a => indicates coupler branch (_main or _aux)\n" " params => settings for non-volatile RAM\n\n" " The coupler setting are ony needed when the device is accessed\n" " through a DS2409 microlan coupler\n\n" " The params option provides values for non-volatile RAM. These values\n" " only need to be supplied once, or if a change is required.\n" " The option is supplied as a space or comma delimited string\n" " \"uo=UVOFFSET to=TEMPOFFSET case=INCASE\" where:\n" " uo=UVOFFSET supplies UVOFFSET as the UVI offset in tenths\n" " to=TEMPOFFSET supplies TEMPOFFSET as the Temp offset in 0.5⁰C\n" " case=INCASE supplies INCASE as the In Case flag\n" " (any non-zero INCASE value sets 0xFF)\n" " Please see the vendor documentation for further details\n\n" " e.g. ./hbuvtest -s EEnnnnnnnnnnnnnn -c 1Fnnnnnnnnnnnnnn -m \\\n" " -p \"uo=7 to=-4 case=1\" DS2490-1\n" " # you can omit not neeeded settings ...\n" " ./hbuvtest -s EEnnnnnnnnnnnnnn -p \"to=42 case=0\" DS2490-1\n\n" " The application reports current settings and read values\n", stderr); exit(0); } int main(int argc, char **argv) { float temp = -999, uvi = -999; int portnum = 0; char *serial = NULL, *dev = NULL; uchar ident[8]; char *coupler = NULL; uchar *cident = NULL; char *params = NULL; int c; int bra = 0; int ret = -1; hbuv_t hbuv = {0}; hbuv_t *hb = &hbuv; while ((c = getopt(argc, argv, "amc:s:p:h?")) != EOF) { switch (c) { case 'a': bra = 2; break; case 'm': bra = 4; break; case 's': serial = strdup(optarg); break; case 'c': coupler = strdup(optarg); case 'p': params = strdup(optarg); break; case 'h': case '?': default: usage(); break; } } dev = argv[optind]; if (dev == NULL || serial == NULL) { usage(); } 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); } ret = HBUV_setup(portnum, ident, hb, params); printf("HBUV_setup returns %d\n" "Version = %d.%d\n" "incase = 0x%02x\n" "temp offset = %d\n" "uvi offset = %d\n", ret, hb->version[0], hb->version[1], hb->has_case, hb->temp_offset, hb->uvi_offset); ret = HBUV_read_data(portnum, ident, hb); temp = hb->raw_temp * 0.5; uvi = hb->raw_uvi / 10.0; printf("HBUV_read_data returns %d\n" "raw temp = 0x%04x\n" "temp = %.1f ⁰C\n" "raw_uvi = 0x%x\n" "UVI = %.1f\n", ret, hb->raw_temp, temp, hb->raw_uvi, uvi); if (coupler) { w1_set_coupler(portnum, cident, 0); } owRelease(portnum); return 0; } w1retap/src/libusblinux300/humalog.c000066400000000000000000000371751446446235200176420ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // owMem.c - Goes through the testing the memory bank for different parts. // Version 2.00 // #include #include #include #include "ownet.h" #include "findtype.h" #include "humutil.h" #include "pw77.h" void selectDevice(int portnum, uchar *SNum); int menuSelect(); int getNumber(int min, int max); SMALLINT getBoolean(); float getFloat(float min, float max); #define HYGRO_START_MISSION 0 #define HYGRO_STOP_MISSION 1 #define HYGRO_DOWNLOAD_DATA 2 #define HYGRO_GET_TEMPERATURE 3 #define HYGRO_GET_DATA 4 #define HYGRO_BM_READ_PASS 5 #define HYGRO_BM_RW_PASS 6 #define HYGRO_READ_PASS 7 #define HYGRO_RW_PASS 8 #define HYGRO_ENABLE_PASS 9 #define HYGRO_DISABLE_PASS 10 #define QUIT 11 int main(int argc, char **argv) { int portnum = 0; int length, i; uchar SNum[8]; uchar state[96]; uchar passw[8]; char msg[256]; SMALLINT done = FALSE; startMissionData settings = {0}; configLog config; double val, valsq, error; // 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\n", msg); return 0; } printf("\n1-Wire Memory utility console application Version 0.01\n"); if ((portnum = owAcquireEx(argv[1])) < 0) { OWERROR_DUMP(stdout); return 0; } else { selectDevice(portnum, &SNum[0]); do { switch (menuSelect()) { case HYGRO_START_MISSION: printf("Enter the sample rate in seconds.\n"); settings.sampleRate = getNumber(1, 982800); printf("Enter start delay in minutes.\n"); settings.startDelay = getNumber(0, 16777215); printf("Enable rollover? (T/F)\n"); settings.enableRollover = getBoolean(); printf("Should the iButton clock be sync'ed with the OS clock? (T/F)\n"); settings.timeSync = getBoolean(); printf("Do you want the temperture channel enabled? (T/F)\n"); settings.tempEnabled = getBoolean(); if (settings.tempEnabled) { printf("Do you want to set a high temperature alarm? (T/F)\n"); settings.highTempAlarm = getBoolean(); if (settings.highTempAlarm) { printf("Enter the temperature for the high alarm.\n"); settings.highTemp = getFloat(-40.0, 125.0); } printf("Do you want to set a low temperature alarm? (T/F)\n"); settings.lowTempAlarm = getBoolean(); if (settings.lowTempAlarm) { printf("Enter the temperature for the low alarm.\n"); if (settings.highTempAlarm) settings.lowTemp = getFloat(-40.0, settings.highTemp); else settings.lowTemp = getFloat(-40.0, 125.0); } printf("Do you want to start mission upon a temperature alarm? (T/F)\n"); settings.tempAlarm = getBoolean(); printf("Do you want the temperatures recorded in high resolution? (T/F)\n"); settings.highTempResolution = getBoolean(); } printf("Do you want the data channel enabled? (T/F)\n"); settings.dataEnabled = getBoolean(); if (settings.dataEnabled) { printf("Do you want to set a high data alarm? (T/F)\n"); settings.highDataAlarm = getBoolean(); if (settings.highDataAlarm) { printf("Enter the integer high alarm percentage.\n"); settings.highData = getFloat(0.0, 100.0); } printf("Do you want to set a low data alarm? (T/F)\n"); settings.lowDataAlarm = getBoolean(); if (settings.lowDataAlarm) { printf("Enter the integer low alarm percentage.\n"); settings.lowData = getFloat(0.0, settings.highData); } printf("Do you want the data recorded at high resolution? (T/F)\n"); settings.highDataResolution = getBoolean(); } if (!startMission(portnum, &SNum[0], settings, &config)) { OWERROR_DUMP(stdout); printf("Error starting mission.\n"); } break; case HYGRO_STOP_MISSION: if (!stopMission(portnum, &SNum[0])) { OWERROR_DUMP(stdout); printf("Error stopping mission.\n"); } break; case HYGRO_DOWNLOAD_DATA: if (readDevice(portnum, &SNum[0], &state[0], &config)) { config.useHumidityCalibration = FALSE; if (!loadMissionResults(portnum, &SNum[0], config)) { OWERROR_DUMP(stdout); printf("error with loading data.\n"); } } else { OWERROR_DUMP(stdout); printf("didn't read device.\n"); } break; case HYGRO_GET_TEMPERATURE: if (readDevice(portnum, &SNum[0], &state[0], &config)) { if (!doTemperatureConvert(portnum, &SNum[0], &state[0])) { OWERROR_DUMP(stdout); } else { printf("Use temperature calibration?\n"); config.useTemperatureCalibration = getBoolean(); if (config.useTemperatureCalibration) { val = decodeTemperature(&state[12], 2, FALSE, config); valsq = val * val; error = config.tempCoeffA * valsq + config.tempCoeffB * val + config.tempCoeffC; val = val - error; printf("The current temperature in C is %f\n", val); } else { printf("The current temperature is %f\n", decodeTemperature(&state[12], 2, FALSE, config)); } } } else { OWERROR_DUMP(stdout); } break; case HYGRO_GET_DATA: if (readDevice(portnum, &SNum[0], &state[0], &config)) { if (!doADConvert(portnum, &SNum[0], &state[0])) { OWERROR_DUMP(stdout); } else { if (config.hasHumidity) { printf("Use humidity calibration?\n"); config.useHumidityCalibration = getBoolean(); if (config.useHumidityCalibration) { val = decodeHumidity(&state[14], 2, FALSE, config); valsq = val * val; error = config.humCoeffA * valsq + config.humCoeffB * val + config.humCoeffC; val = val - error; if (val < 0.0) val = 0.0; printf("The current humidity is %f\n", val); } else { val = decodeHumidity(&state[14], 2, FALSE, config); if (val < 0.0) val = 0.0; printf("The current humidity is %f\n", val); } } else { printf("The current AD voltage reading is %f\n", getADVoltage(&state[14], 2, FALSE, config)); } } } else { OWERROR_DUMP(stdout); } break; case HYGRO_BM_READ_PASS: printf("Enter the 8 byte read only password if less 0x00 will be filled in."); printf("\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = 1; length = getData(&passw[0], 8, getNumber(0, length)); if (length != 8) { for (i = length; i < 8; i++) psw[i] = 0x00; } setBMPassword(&passw[0]); break; case HYGRO_BM_RW_PASS: printf("Enter the 8 byte read/write password if less 0x00 will be filled in."); printf("\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = 1; length = getData(&passw[0], 8, getNumber(0, length)); if (length != 8) { for (i = length; i < 8; i++) psw[i] = 0x00; } setBMPassword(&passw[0]); break; case HYGRO_READ_PASS: printf("Enter the 8 byte read only password if less 0x00 will be filled in."); printf("\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = 1; length = getData(&passw[0], 8, getNumber(0, length)); if (length != 8) { for (i = length; i < 8; i++) psw[i] = 0x00; } if (!setPassword(portnum, &SNum[0], &passw[0], READ_PSW)) OWERROR_DUMP(stderr); break; case HYGRO_RW_PASS: printf("Enter the 8 byte read/write password if less 0x00 will be filled in."); printf("\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = 1; length = getData(&passw[0], 8, getNumber(0, length)); if (length != 8) { for (i = length; i < 8; i++) psw[i] = 0x00; } if (!setPassword(portnum, &SNum[0], &passw[0], READ_WRITE_PSW)) OWERROR_DUMP(stderr); break; case HYGRO_ENABLE_PASS: if (!setPasswordMode(portnum, &SNum[0], ENABLE_PSW)) OWERROR_DUMP(stderr); break; case HYGRO_DISABLE_PASS: if (!setPasswordMode(portnum, &SNum[0], DISABLE_PSW)) OWERROR_DUMP(stderr); break; case QUIT: done = TRUE; default: break; } } while (!done); } return 0; } /** * Create a menu from the provided OneWireContainer * Vector and allow the user to select a device. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number of the hygrochrom */ void selectDevice(int portnum, uchar *SNum) { int i, j; int numDevices = 0; int num; uchar AllDevices[10][8]; // get list of 1-Wire Humalog devices numDevices = FindDevices(portnum, &AllDevices[0], 0x41, 10); if (numDevices == 0) { for (i = 0; i < 8; i++) AllDevices[0][i] = 0x00; numDevices++; } printf("Device Selection\n"); for (i = 0; i < numDevices; i++) { printf("(%d) ", i); for (j = 7; j >= 0; j--) printf("%02X ", AllDevices[i][j]); printf("\n"); } num = getNumber(0, numDevices - 1); for (i = 0; i < 8; i++) SNum[i] = AllDevices[num][i]; } /** * Display menu and ask for a selection. * * menu the menu selections. * * @return numberic value entered from the console. */ int menuSelect() { int length = 0; printf("\n"); printf("Bank Operation Menu\n"); printf("(0) Start new mission.\n"); printf("(1) Stop mission.\n"); printf("(2) Download mission data.\n"); printf("(3) Read the temperature.\n"); printf("(4) Read the humidity or voltage.\n"); printf("(5) Set Bus Master read only password.\n"); printf("(6) Set Bus Master read/write password.\n"); printf("(7) Set device read only password.\n"); printf("(8) Set device read/write password.\n"); printf("(9) Enable the password.\n"); printf("(10) Disable the password.\n"); printf("(11) Quit.\n"); length = 11; printf("\nPlease enter value: "); return getNumber(0, length); } /** * 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; } /** * Retrieve user input from the console. * * @return boolean value entered from the console. */ SMALLINT getBoolean() { char ch; int done = FALSE; SMALLINT ret = FALSE; do { ch = (char)getchar(); if (!isspace(ch)) { if ((ch == 'T') || (ch == 't')) { ret = TRUE; done = TRUE; } else if ((ch == 'F') || (ch == 'f')) { ret = FALSE; done = TRUE; } else { printf("Enter either T or F.\n"); } } } while (!done); return ret; } /** * Retrieve user input from the console. * * @return boolean value entered from the console. */ float getFloat(float min, float max) { int cnt; int done = FALSE; float value; do { cnt = scanf("%f", &value); if ((cnt > 0) && (value > max || value < min)) { printf("Value (%f) is outside of the limits (%f,%f)\n", value, min, max); printf("Try again:\n"); } else { done = TRUE; } } while (!done); if (((int)(value * 10)) % 5 == 0) { value = (float)(((int)(value * 10)) / 10.0); } else { if ((((int)(value * 10)) % 10) < 2) { value = (float)((int)value); } else if ((((int)(value * 10)) % 10) < 8) { value = (float)(((float)((int)value)) + 0.5); } else { value = (float)(((float)((int)value)) + 1.0); } } return value; } /*--------------------------------------------------------------------------- * Copyright (C) 2002 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. *--------------------------------------------------------------------------- */ w1retap/src/libusblinux300/humid.c000066400000000000000000000031361446446235200173020ustar00rootroot00000000000000#include #include "ownet.h" #include "sht11.h" #define MAXDEVICES 20 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 TestScratch(int portnum, u_char *ident) { int i; unsigned char c, buf[33]; owTouchReset(portnum); owTouchByte(portnum, 0x55); for (i = 0; i < 8; i++) { owTouchByte(portnum, ident[i]); } owTouchReset(0xBE); for (i = 0; i < 32; i++) { c = owTouchByte(portnum, 0xff); buf[i] = c; } buf[32] = 0; for (i = 0; i < 32; i++) { printf("%02x ", buf[i]); } fputc('\n', stdout); puts((char *)buf); msDelay(100); owTouchReset(portnum); } int main(int argc, char **argv) { int portnum = 0; u_char serial[8]; float temp = 0, rh = 0; if (argc != 3) { fputs("humids device address\n" " Device: e.g. /dev/ttyS0 or DS2490-1\n" " Default is to read temp / humidity\n" " Environment variables\n" " TEST_SHT11=1 humids device address : Read scratchpad\n" " SHT11_VERBOSE=1 humids device address : More verbosity\n", stderr); exit(1); // e.g. /dev/ttyS0 or DS2490-1 } /* attempt to acquire the 1-Wire Net */ if ((portnum = owAcquireEx(argv[1])) < 0) { OWERROR_DUMP(stdout); exit(1); } w1_make_serial(argv[2], serial); if (getenv("TEST_SHT11")) { TestScratch(portnum, serial); } else { if (ReadSHT11(portnum, serial, &temp, &rh)) { printf("Temp %3.1f RH %3.1f \n", temp, rh); } } return 0; } w1retap/src/libusblinux300/humutil.c000066400000000000000000001154731446446235200176730ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // humutil.c - functions to set mission and mission states for DS1922. // Version 2.00 // #include #include "math.h" #include "humutil.h" #include "mbee77.h" #include "pw77.h" // Temperature resolution in degrees Celsius double temperatureResolution = 0.5; // max and min temperature double maxTemperature = 85, minTemperature = -40; // should we update the Real time clock? SMALLINT updatertc = FALSE; #define MAX_READ_RETRY_CNT 15 // ***************************************************************************** // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Register addresses and control bits // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ***************************************************************************** /** Address of the Real-time Clock Time value*/ #define RTC_TIME 0x200 /** Address of the Real-time Clock Date value*/ #define RTC_DATE 0x203 /** Address of the Sample Rate Register */ #define SAMPLE_RATE 0x206 // 2 bytes, LSB first, MSB no greater than 0x3F /** Address of the Temperature Low Alarm Register */ #define TEMPERATURE_LOW_ALARM_THRESHOLD 0x208 /** Address of the Temperature High Alarm Register */ #define TEMPERATURE_HIGH_ALARM_THRESHOLD 0x209 /** Address of the Data Low Alarm Register */ #define DATA_LOW_ALARM_THRESHOLD 0x20A /** Address of the Data High Alarm Register */ #define DATA_HIGH_ALARM_THRESHOLD 0x20B /** Address of the last temperature conversion's LSB */ #define LAST_TEMPERATURE_CONVERSION_LSB 0x20C /** Address of the last temperature conversion's MSB */ #define LAST_TEMPERATURE_CONVERSION_MSB 0x20D /** Address of the last data conversion's LSB */ #define LAST_DATA_CONVERSION_LSB 0x20E /** Address of the last data conversion's MSB */ #define LAST_DATA_CONVERSION_MSB 0x20F /** Address of Temperature Control Register */ #define TEMPERATURE_CONTROL_REGISTER 0x210 /** Temperature Control Register Bit: Enable Data Low Alarm */ #define TCR_BIT_ENABLE_TEMPERATURE_LOW_ALARM 0x01 /** Temperature Control Register Bit: Enable Data Low Alarm */ #define TCR_BIT_ENABLE_TEMPERATURE_HIGH_ALARM 0x02 /** Address of Data Control Register */ #define DATA_CONTROL_REGISTER 0x211 /** Data Control Register Bit: Enable Data Low Alarm */ #define DCR_BIT_ENABLE_DATA_LOW_ALARM 0x01 /** Data Control Register Bit: Enable Data High Alarm */ #define DCR_BIT_ENABLE_DATA_HIGH_ALARM 0x02 /** Address of Real-Time Clock Control Register */ #define RTC_CONTROL_REGISTER 0x212 /** Real-Time Clock Control Register Bit: Enable Oscillator */ #define RCR_BIT_ENABLE_OSCILLATOR 0x01 /** Real-Time Clock Control Register Bit: Enable High Speed Sample */ #define RCR_BIT_ENABLE_HIGH_SPEED_SAMPLE 0x02 /** Address of Mission Control Register */ #define MISSION_CONTROL_REGISTER 0x213 /** Mission Control Register Bit: Enable Temperature Logging */ #define MCR_BIT_ENABLE_TEMPERATURE_LOGGING 0x01 /** Mission Control Register Bit: Enable Data Logging */ #define MCR_BIT_ENABLE_DATA_LOGGING 0x02 /** Mission Control Register Bit: Set Temperature Resolution */ #define MCR_BIT_TEMPERATURE_RESOLUTION 0x04 /** Mission Control Register Bit: Set Data Resolution */ #define MCR_BIT_DATA_RESOLUTION 0x08 /** Mission Control Register Bit: Enable Rollover */ #define MCR_BIT_ENABLE_ROLLOVER 0x10 /** Mission Control Register Bit: Start Mission on Temperature Alarm */ #define MCR_BIT_START_MISSION_ON_TEMPERATURE_ALARM 0x20 /** Address of Alarm Status Register */ #define ALARM_STATUS_REGISTER 0x214 /** Alarm Status Register Bit: Temperature Low Alarm */ #define ASR_BIT_TEMPERATURE_LOW_ALARM 0x01 /** Alarm Status Register Bit: Temperature High Alarm */ #define ASR_BIT_TEMPERATURE_HIGH_ALARM 0x02 /** Alarm Status Register Bit: Data Low Alarm */ #define ASR_BIT_DATA_LOW_ALARM 0x04 /** Alarm Status Register Bit: Data High Alarm */ #define ASR_BIT_DATA_HIGH_ALARM 0x08 /** Alarm Status Register Bit: Battery On Reset */ #define ASR_BIT_BATTERY_ON_RESET 0x80 /** Address of General Status Register */ #define GENERAL_STATUS_REGISTER 0x215 /** General Status Register Bit: Sample In Progress */ #define GSR_BIT_SAMPLE_IN_PROGRESS 0x01 /** General Status Register Bit: Mission In Progress */ #define GSR_BIT_MISSION_IN_PROGRESS 0x02 /** General Status Register Bit: Conversion In Progress */ #define GSR_BIT_CONVERSION_IN_PROGRESS 0x04 /** General Status Register Bit: Memory Cleared */ #define GSR_BIT_MEMORY_CLEARED 0x08 /** General Status Register Bit: Waiting for Temperature Alarm */ #define GSR_BIT_WAITING_FOR_TEMPERATURE_ALARM 0x10 /** General Status Register Bit: Forced Conversion In Progress */ #define GSR_BIT_FORCED_CONVERSION_IN_PROGRESS 0x20 /** Address of the Mission Start Delay */ #define MISSION_START_DELAY 0x216 // 3 bytes, LSB first /** Address of the Mission Timestamp Time value*/ #define MISSION_TIMESTAMP_TIME 0x219 /** Address of the Mission Timestamp Date value*/ #define MISSION_TIMESTAMP_DATE 0x21C /** Address of Device Configuration Register */ #define DEVICE_CONFIGURATION_BYTE 0x226 // 1 byte, alternating ones and zeroes indicates passwords are enabled /** Address of the Password Control Register. */ #define PASSWORD_CONTROL_REGISTER 0x227 // 8 bytes, write only, for setting the Read Access Password /** Address of Read Access Password. */ #define READ_ACCESS_PASSWORD 0x228 // 8 bytes, write only, for setting the Read Access Password /** Address of the Read Write Access Password. */ #define READ_WRITE_ACCESS_PASSWORD 0x230 // 3 bytes, LSB first /** Address of the Mission Sample Count */ #define MISSION_SAMPLE_COUNT 0x220 // 3 bytes, LSB first /** Address of the Device Sample Count */ #define DEVICE_SAMPLE_COUNT 0x223 // first year that calendar starts counting years from #define FIRST_YEAR_EVER 2000 // maximum size of the mission log #define MISSION_LOG_SIZE 8192 // mission log size for odd combination of resolutions (i.e. 8-bit temperature // & 16-bit data or 16-bit temperature & 8-bit data #define ODD_MISSION_LOG_SIZE 7680 #define TEMPERATURE_CHANNEL 0 #define DATA_CHANNEL 1 /** 1-Wire command for Clear Memory With Password */ #define CLEAR_MEMORY_PW_COMMAND 0x96 /** 1-Wire command for Start Mission With Password */ #define START_MISSION_PW_COMMAND 0xCC /** 1-Wire command for Stop Mission With Password */ #define STOP_MISSION_PW_COMMAND 0x33 /** 1-Wire command for Forced Conversion */ #define FORCED_CONVERSION 0x55 // ***************************************************************************** // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Sensor read/write // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ***************************************************************************** /** * Retrieves the 1-Wire device sensor state. This state is * returned as a byte array. Pass this byte array to the 'get' * and 'set' methods. If the device state needs to be changed then call * the 'writeDevice' to finalize the changes. * * @return 1-Wire device sensor state */ SMALLINT readDevice(int portnum, uchar *SNum, uchar *buffer, configLog *config) { int i; int retryCnt = MAX_READ_RETRY_CNT; uchar temp_buff[96]; // reference humidities that the calibration was calculated over double ref1 = 20.0, ref2 = 60.0, ref3 = 90.0; // the average value for each reference point double read1 = 0.0, read2 = 0.0, read3 = 0.0; // the average error for each reference point double error1 = 0.0, error2 = 0.0, error3 = 0.0; double ref1sq, ref2sq, ref3sq; config->adDeviceBits = 10; config->adReferenceVoltage = 5.02; do { if (readPageCRCEE77(0, portnum, SNum, 16, &temp_buff[0]) && readPageCRCEE77(0, portnum, SNum, 17, &temp_buff[32]) && readPageCRCEE77(0, portnum, SNum, 18, &temp_buff[64])) { for (i = 0; i < 96; i++) buffer[i] = temp_buff[i]; } else { retryCnt++; } } while (retryCnt < MAX_READ_RETRY_CNT); switch (config->configByte) { case 0x00: config->lowTemp = -40; config->highTemp = 125; break; case 0x20: config->lowTemp = -40; config->highTemp = 125; config->hasHumidity = TRUE; break; case 0x40: config->lowTemp = -40; config->highTemp = 125; break; case 0x60: config->lowTemp = 0; config->highTemp = 125; break; default: config->lowTemp = -40; config->highTemp = 125; break; } if (config->hasHumidity) { config->useHumidityCalibration = TRUE; ref1 = decodeHumidity(&buffer[72], 2, TRUE, *config); read1 = decodeHumidity(&buffer[74], 2, TRUE, *config); error1 = read1 - ref1; ref2 = decodeHumidity(&buffer[76], 2, TRUE, *config); read2 = decodeHumidity(&buffer[78], 2, TRUE, *config); error2 = read2 - ref2; ref3 = decodeHumidity(&buffer[80], 2, TRUE, *config); read3 = decodeHumidity(&buffer[82], 2, TRUE, *config); error3 = read3 - ref3; ref1sq = ref1 * ref1; ref2sq = ref2 * ref2; ref3sq = ref3 * ref3; config->humCoeffB = ((ref2sq - ref1sq) * (error3 - error1) + ref3sq * (error1 - error2) + ref1sq * (error2 - error1)) / ((ref2sq - ref1sq) * (ref3 - ref1) + (ref3sq - ref1sq) * (ref1 - ref2)); config->humCoeffA = (error2 - error1 + config->humCoeffB * (ref1 - ref2)) / (ref2sq - ref1sq); config->humCoeffC = error1 - config->humCoeffA * ref1sq - config->humCoeffB * ref1; } config->useTemperatureCalibration = TRUE; ref2 = decodeHumidity(&buffer[64], 2, TRUE, *config); read2 = decodeHumidity(&buffer[66], 2, TRUE, *config); error2 = read2 - ref2; ref3 = decodeHumidity(&buffer[68], 2, TRUE, *config); read3 = decodeHumidity(&buffer[70], 2, TRUE, *config); error3 = read3 - ref3; ref1 = 60.0; error1 = error2; read1 = ref1 + error1; ref1sq = ref1 * ref1; ref2sq = ref2 * ref2; ref3sq = ref3 * ref3; config->tempCoeffB = ((ref2sq - ref1sq) * (error3 - error1) + ref3sq * (error1 - error2) + ref1sq * (error2 - error1)) / ((ref2sq - ref1sq) * (ref3 - ref1) + (ref3sq - ref1sq) * (ref1 - ref2)); config->tempCoeffA = (error2 - error1 + config->tempCoeffB * (ref1 - ref2)) / (ref2sq - ref1sq); config->tempCoeffC = error1 - config->tempCoeffA * ref1sq - config->tempCoeffB * ref1; config->useTempCalforHumidity = FALSE; return TRUE; } /** * Writes the 1-Wire device sensor state that * have been changed by 'set' methods. Only the state registers that * changed are updated. This is done by referencing a field information * appended to the state data. * * @param state 1-Wire device sensor state * */ SMALLINT writeDevice(int portnum, uchar *SNum, uchar *state, SMALLINT updatertc) { int start = 0; int str_add = 0; if (getFlag(portnum, SNum, GENERAL_STATUS_REGISTER, GSR_BIT_MISSION_IN_PROGRESS)) { printf("get flag error.\n"); return FALSE; } start = updatertc ? 0 : 6; str_add = start + 512; if (!writeEE77(0, portnum, SNum, str_add, &state[start], (64 - start))) { printf("writing error.\n"); return FALSE; } return TRUE; } /** * Reads a single byte from the DS1922. Note that the preferred manner * of reading from the DS1922 Thermocron is through the readDevice() * method or through the MemoryBank objects returned in the * getMemoryBanks() method. * * memAddr the address to read from (in the range of 0x200-0x21F) */ uchar readByte(int portnum, uchar *SNum, int memAddr) { uchar buffer[32]; int page; page = memAddr / 32; readPageCRCEE77(0, portnum, SNum, page, &buffer[0]); return buffer[memAddr % 32]; } /** * Gets the status of the specified flag from the specified register. * This method actually communicates with the Thermocron. To improve * performance if you intend to make multiple calls to this method, * first call readDevice() and use the * getFlag(int, byte, byte[]) method instead.

* * The DS1922 Thermocron has two sets of flags. One set belongs * to the control register. When reading from the control register, * valid values for bitMask. * * @param register address of register containing the flag (valid values * are CONTROL_REGISTER and STATUS_REGISTER) * @param bitMask the flag to read (see above for available options) * * @return the status of the flag, where true * signifies a "1" and false signifies a "0" */ SMALLINT getFlag(int portnum, uchar *SNum, int reg, uchar bitMask) { return ((readByte(portnum, SNum, reg) & bitMask) != 0); } /** *

Sets the status of the specified flag in the specified register. * If a mission is in progress a OneWireIOException will be thrown * (one cannot write to the registers while a mission is commencing). This method * is the preferred manner of setting the DS1922 status and control flags. * The method writeDevice() must be called to finalize * changes to the device. Note that multiple 'set' methods can * be called before one call to writeDevice().

* *

For more information on valid values for the bitMask * parameter, see the {@link #getFlag(int,byte) getFlag(int,byte)} method.

* * @param register address of register containing the flag (valid values * are CONTROL_REGISTER and STATUS_REGISTER) * @param bitMask the flag to read (see {@link #getFlag(int,byte) getFlag(int,byte)} * for available options) * @param flagValue new value for the flag (true is logic "1") * @param state current state of the device returned from readDevice() */ void setFlag(int reg, uchar bitMask, SMALLINT flagValue, uchar *state) { uchar flags; reg = reg & 0x3F; flags = state[reg]; if (flagValue) flags = (uchar)(flags | bitMask); else flags = (uchar)(flags & ~(bitMask)); // write the regs back state[reg] = flags; } // ***************************************************************************** // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // DS1922 Device Specific Functions // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ***************************************************************************** /** * Stops the currently running mission. * */ SMALLINT stopMission(int portnum, uchar *SNum) { int i; uchar buffer[10]; if (!getFlag(portnum, SNum, GENERAL_STATUS_REGISTER, GSR_BIT_MISSION_IN_PROGRESS)) { OWERROR(OWERROR_HYGRO_STOP_MISSION_UNNECESSARY); return FALSE; } if (owAccess(portnum)) { buffer[0] = STOP_MISSION_PW_COMMAND; for (i = 0; i < 8; i++) buffer[i + 1] = psw[i]; buffer[9] = 0xFF; if (!owBlock(portnum, FALSE, &buffer[0], 10)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } if (getFlag(portnum, SNum, GENERAL_STATUS_REGISTER, GSR_BIT_MISSION_IN_PROGRESS)) { OWERROR(OWERROR_HYGRO_STOP_MISSION_ERROR); return FALSE; } return TRUE; } /** * Erases the log memory from this missioning device. */ SMALLINT clearMemory(int portnum, uchar *SNum) { int i; uchar buffer[10]; if (owAccess(portnum)) { buffer[0] = CLEAR_MEMORY_PW_COMMAND; for (i = 0; i < 8; i++) buffer[i + 1] = psw[i]; buffer[9] = 0xFF; if (!owBlock(portnum, FALSE, &buffer[0], 10)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // wait 2 ms for Clear Memory to comlete msDelay(2); if (!getFlag(portnum, SNum, GENERAL_STATUS_REGISTER, GSR_BIT_MEMORY_CLEARED)) { printf("error.\n"); // "OneWireContainer41-Clear Memory failed. Check read/write password."); return FALSE; } } return TRUE; } // ***************************************************************************** // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Mission Interface Functions // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ***************************************************************************** /** * Begins a new mission on this missioning device. * * @param sampleRate indicates the sampling rate, in seconds, that * this missioning device should log samples. * @param missionStartDelay indicates the amount of time, in seconds, * that should pass before the mission begins. * @param rolloverEnabled if false, this device will stop * recording new samples after the data log is full. Otherwise, * it will replace samples starting at the beginning. * @param syncClock if true, the real-time clock of this * missioning device will be synchronized with the current time * according to this java.util.Date. * @param startUponTempAlarm if true, the mission will begin * after a temperature alarm has occurred. */ SMALLINT startMission(int portnum, uchar *SNum, startMissionData set, configLog *config) { int i; time_t tint; struct tm *tstruct; uchar buffer[10]; uchar state[96]; int sampleRate; sampleRate = set.sampleRate; if (getFlag(portnum, SNum, GENERAL_STATUS_REGISTER, GSR_BIT_MISSION_IN_PROGRESS)) { printf("get flag error.\n"); return FALSE; } else { if (!readDevice(portnum, SNum, &state[0], config)) { printf("read device error.\n"); return FALSE; } } setFlag(MISSION_CONTROL_REGISTER, MCR_BIT_ENABLE_TEMPERATURE_LOGGING, set.tempEnabled, &state[0]); setFlag(MISSION_CONTROL_REGISTER, MCR_BIT_ENABLE_DATA_LOGGING, set.dataEnabled, &state[0]); setFlag(MISSION_CONTROL_REGISTER, MCR_BIT_TEMPERATURE_RESOLUTION, set.highTempResolution, &state[0]); setFlag(MISSION_CONTROL_REGISTER, MCR_BIT_DATA_RESOLUTION, set.highDataResolution, &state[0]); if (set.tempAlarm) { setFlag(MISSION_CONTROL_REGISTER, MCR_BIT_START_MISSION_ON_TEMPERATURE_ALARM, set.tempAlarm, &state[0]); } else { setFlag(MISSION_CONTROL_REGISTER, MCR_BIT_START_MISSION_ON_TEMPERATURE_ALARM, set.tempAlarm, &state[0]); } if (set.highTempAlarm) { setFlag(TEMPERATURE_CONTROL_REGISTER, TCR_BIT_ENABLE_TEMPERATURE_HIGH_ALARM, set.highTempAlarm, &state[0]); state[TEMPERATURE_HIGH_ALARM_THRESHOLD & 0x3F] = (uchar)((set.highTemp * 2) + 82); } else { setFlag(TEMPERATURE_CONTROL_REGISTER, TCR_BIT_ENABLE_TEMPERATURE_HIGH_ALARM, set.highTempAlarm, &state[0]); } if (set.lowTempAlarm) { setFlag(TEMPERATURE_CONTROL_REGISTER, TCR_BIT_ENABLE_TEMPERATURE_LOW_ALARM, set.lowTempAlarm, &state[0]); state[TEMPERATURE_LOW_ALARM_THRESHOLD & 0x3F] = (uchar)((set.lowTemp * 2) + 82); } else { setFlag(TEMPERATURE_CONTROL_REGISTER, TCR_BIT_ENABLE_TEMPERATURE_LOW_ALARM, set.lowTempAlarm, &state[0]); } if (set.highDataAlarm) { setFlag(DATA_CONTROL_REGISTER, DCR_BIT_ENABLE_DATA_HIGH_ALARM, set.highDataAlarm, &state[0]); state[DATA_HIGH_ALARM_THRESHOLD & 0x3F] = (uchar)(((int)(((((((1 - config->humCoeffB) - sqrt(((config->humCoeffB - 1) * (config->humCoeffB - 1)) - 4 * config->humCoeffA * (config->humCoeffC + set.highData))) / (2 * config->humCoeffA)) * .0307) + .958) * ((1 << config->adDeviceBits) - 1)) / config->adReferenceVoltage) & 0x3FC) >> (config->adDeviceBits - 8)); } else { setFlag(DATA_CONTROL_REGISTER, DCR_BIT_ENABLE_DATA_HIGH_ALARM, set.highDataAlarm, &state[0]); } if (set.lowDataAlarm) { setFlag(DATA_CONTROL_REGISTER, DCR_BIT_ENABLE_DATA_LOW_ALARM, set.lowDataAlarm, &state[0]); state[DATA_LOW_ALARM_THRESHOLD & 0x3F] = (uchar)(((int)(((((((1 - config->humCoeffB) - sqrt(((config->humCoeffB - 1) * (config->humCoeffB - 1)) - 4 * config->humCoeffA * (config->humCoeffC + set.lowData))) / (2 * config->humCoeffA)) * .0307) + .958) * ((1 << config->adDeviceBits) - 1)) / config->adReferenceVoltage) & 0x3FC) >> (config->adDeviceBits - 8)); } else { setFlag(DATA_CONTROL_REGISTER, DCR_BIT_ENABLE_DATA_LOW_ALARM, set.lowDataAlarm, &state[0]); } if (sampleRate % 60 == 0 || sampleRate > 0x03FFF) { // convert to minutes sampleRate = (sampleRate / 60) & 0x03FFF; setFlag(RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_HIGH_SPEED_SAMPLE, FALSE, &state[0]); } else { setFlag(RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_HIGH_SPEED_SAMPLE, TRUE, &state[0]); } state[6] = (uchar)(sampleRate & 0x00FF); state[7] = (uchar)((sampleRate & 0x3F00) >> 8); state[22] = (uchar)(set.startDelay & 0x00FF); state[23] = (uchar)((set.startDelay & 0x3F00) >> 8); setFlag(MISSION_CONTROL_REGISTER, MCR_BIT_ENABLE_ROLLOVER, set.enableRollover, &state[0]); if (set.timeSync) { time(&tint); tint++; tstruct = localtime(&tint); setTime(RTC_TIME & 0x3F, tstruct->tm_hour, tstruct->tm_min, tstruct->tm_sec, FALSE, &state[0]); setDate(RTC_DATE & 0x3F, tstruct->tm_year, (tstruct->tm_mon + 1), tstruct->tm_mday, &state[0]); if (!getFlag(portnum, SNum, RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_OSCILLATOR)) { setFlag(RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_OSCILLATOR, TRUE, &state[0]); } } else if (!getFlag(portnum, SNum, RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_OSCILLATOR)) { // System.out.println("Enabling Oscillator"); setFlag(RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_OSCILLATOR, TRUE, &state[0]); } // System.out.println("Clearing memory"); clearMemory(portnum, SNum); // System.out.println("Updating Device state"); if (!writeDevice(portnum, SNum, state, TRUE)) { return FALSE; } // System.out.println("Starting mission"); if (owAccess(portnum)) { buffer[0] = START_MISSION_PW_COMMAND; for (i = 0; i < 8; i++) buffer[i + 1] = psw[i]; buffer[9] = 0xFF; if (!owBlock(portnum, FALSE, &buffer[0], 10)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } return TRUE; } /** * Loads the results of the currently running mission. Must be called * before all mission result/status methods. */ SMALLINT loadMissionResults(int portnum, uchar *SNum, configLog config) { uchar state[96]; uchar page[8192]; configLog tempConfig; uchar upper, lower; double val, valsq, error, humCal, tempVal; int timeOffset; int month, day, year = 0; int hour, min, sec; int tempone, temptwo, tempthr; int pm = 0, i; int sampleCnt = 0; int sampleRate = 0; int tempBytes = 0; int dataBytes = 0; int maxSamples = 0; int wrapCount = 0; int offsetDepth = 0; int temperatureLogSize = 0; // default size of the log, could be different if using an odd // sample size combination. // check for rollover FILE *fidTemp; FILE *fidData; // read the register contents if (!readDevice(portnum, SNum, &state[0], &tempConfig)) { printf("read device error.\n"); return FALSE; } // get the number of samples tempone = (int)(state[32] & 0x0000FF); temptwo = (int)(state[33] << 8) & 0x00FF00; tempthr = (int)(state[34] << 16) & 0xFF0000; sampleCnt = tempone + temptwo + tempthr; if (sampleCnt == 0) { printf("No, samples yet for this mission.\n"); return FALSE; } // sample rate, in seconds tempone = (int)(state[SAMPLE_RATE & 0x3F] & 0x00FF); temptwo = (int)((state[(SAMPLE_RATE & 0x3F) + 1] << 8) & 0xFF00); sampleRate = tempone + temptwo; if (!getFlag(portnum, SNum, RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_HIGH_SPEED_SAMPLE)) // if sample rate is in minutes, convert to seconds sampleRate = sampleRate * 60; // get day lower = state[MISSION_TIMESTAMP_DATE & 0x3F]; upper = ((lower >> 4) & 0x0f); lower = (lower & 0x0f); day = upper * 10 + lower; // get month lower = state[(MISSION_TIMESTAMP_DATE & 0x3F) + 1]; upper = ((lower >> 4) & 0x01); lower = (lower & 0x0f); month = upper * 10 + lower; // get year if ((state[(MISSION_TIMESTAMP_DATE & 0x3F) + 1] & 0x80) == 0x80) year = 100; lower = state[(MISSION_TIMESTAMP_DATE & 0x3F) + 2]; upper = ((lower >> 4) & 0x0f); lower = (lower & 0x0f); year = upper * 10 + lower + FIRST_YEAR_EVER + year; // get seconds lower = state[MISSION_TIMESTAMP_TIME & 0x3F]; upper = ((lower >> 4) & 0x07); lower = (lower & 0x0f); sec = (int)lower + (int)upper * 10; // get minutes lower = state[(MISSION_TIMESTAMP_TIME & 0x3F) + 1]; upper = ((lower >> 4) & 0x07); lower = (lower & 0x0f); min = (int)lower + (int)upper * 10; // get hours lower = state[(MISSION_TIMESTAMP_TIME & 0x3F) + 2]; upper = ((lower >> 4) & 0x07); lower = (lower & 0x0f); if ((upper & 0x04) != 0) { // extract the AM/PM byte (PM is indicated by a 1) if ((upper & 0x02) > 0) pm = 12; // isolate the 10s place upper &= 0x01; } hour = (int)(upper * 10) + (int)lower + (int)pm; // figure out how many bytes for each temperature sample // if it's being logged, add 1 to the size if (getFlag(portnum, SNum, MISSION_CONTROL_REGISTER, MCR_BIT_ENABLE_TEMPERATURE_LOGGING)) { tempBytes += 1; // if it's 16-bit resolution, add another 1 to the size if (getFlag(portnum, SNum, MISSION_CONTROL_REGISTER, MCR_BIT_TEMPERATURE_RESOLUTION)) tempBytes += 1; } // figure out how many bytes for each data sample // if it's being logged, add 1 to the size if (getFlag(portnum, SNum, MISSION_CONTROL_REGISTER, MCR_BIT_ENABLE_DATA_LOGGING)) { dataBytes += 1; // if it's 16-bit resolution, add another 1 to the size if (getFlag(portnum, SNum, MISSION_CONTROL_REGISTER, MCR_BIT_DATA_RESOLUTION)) dataBytes += 1; } // figure max number of samples switch (tempBytes + dataBytes) { case 1: maxSamples = 8192; break; case 2: maxSamples = 4096; break; case 3: maxSamples = 2560; break; case 4: maxSamples = 2048; break; default: case 0: // assert! should never, ever get here break; } if (getFlag(portnum, SNum, MISSION_CONTROL_REGISTER, MCR_BIT_ENABLE_ROLLOVER) && (sampleCnt > maxSamples)) { // intentional assignment wrapCount = sampleCnt / maxSamples; offsetDepth = sampleCnt % maxSamples; sampleCnt = maxSamples; } // DEBUG: For bad SOICS if (!getFlag(portnum, SNum, MISSION_CONTROL_REGISTER, MCR_BIT_ENABLE_ROLLOVER) && (sampleCnt > maxSamples)) { printf("Device Error: rollover was not enabled, but it did occur.\n"); return FALSE; } // figure out where the temperature bytes end, that's where // the data bytes begin temperatureLogSize = tempBytes * maxSamples; // calculate first log entry time offset, in seconds timeOffset = ((wrapCount * maxSamples) + offsetDepth) * sampleRate; if ((tempBytes * sampleCnt) > 0) { for (i = 0; i < ((tempBytes * sampleCnt / 32) + ((tempBytes * sampleCnt % 32) > 0 ? 1 : 0)); i++) { if (!readPageCRCEE77(2, portnum, SNum, i + 128, &page[i * 32])) return FALSE; } fidTemp = fopen("temp.log", "a+"); fprintf(fidTemp, "mission start date and time: %d/%d/%d %d:%d:%d \n", month, day, year, hour, min, sec); fprintf(fidTemp, "time offset(s), temperature reading(C)\n"); for (i = 0; i < sampleCnt; i++) { fprintf(fidTemp, "%d, ", timeOffset + i * sampleRate); if (config.useTemperatureCalibration) { val = decodeTemperature(&page[(offsetDepth + i * tempBytes) % maxSamples], tempBytes, TRUE, config); valsq = val * val; error = config.tempCoeffA * valsq + config.tempCoeffB * val + config.tempCoeffC; val = val - error; fprintf(fidTemp, "%f \n", val); } else { fprintf(fidTemp, "%f \n", decodeTemperature(&page[(offsetDepth + i * tempBytes) % maxSamples], tempBytes, TRUE, config)); } } fflush(fidTemp); fclose(fidTemp); printf("The temperature data is in temp.log file.\n"); } if ((sampleCnt * dataBytes) > 0) { for (i = 0; i < ((dataBytes * sampleCnt / 32) + ((dataBytes * sampleCnt % 32) > 0 ? 1 : 0)); i++) { if (!readPageCRCEE77(2, portnum, SNum, ((temperatureLogSize / 32) + i + 128), &page[temperatureLogSize + i * 32])) return FALSE; } fidData = fopen("data.log", "a+"); fprintf(fidData, "mission start date and time: %d/%d/%d %d:%d:%d \n", month, day, year, hour, min, sec); fprintf(fidData, "time offset(s), data reading(percentage humidity or Volts)\n"); for (i = 0; i < sampleCnt; i++) { fprintf(fidData, "%d, ", timeOffset + i * sampleRate); if (config.hasHumidity) { if (config.useHumidityCalibration) { val = decodeHumidity(&page[temperatureLogSize + ((offsetDepth + i * dataBytes) % maxSamples)], dataBytes, FALSE, config); valsq = val * val; error = config.humCoeffA * valsq + config.humCoeffB * val + config.humCoeffC; val = val - error; if (config.useTempCalforHumidity) { tempVal = val; if ((temperatureLogSize > 0) && config.useTemperatureCalibration) { val = decodeTemperature(&page[temperatureLogSize + ((offsetDepth + i * tempBytes) % maxSamples)], tempBytes, TRUE, config); valsq = val * val; error = config.tempCoeffA * valsq + config.tempCoeffB * val + config.tempCoeffC; humCal = val - error; } else if (temperatureLogSize > 0) { humCal = decodeTemperature(&page[temperatureLogSize + ((offsetDepth + i * tempBytes) % maxSamples)], tempBytes, TRUE, config); } else humCal = 25.0; if (humCal <= 15) val = ((tempVal * 0.0307 + 0.958) - (0.8767 - 0.0035 * humCal + 0.000043 * humCal * humCal)) / (0.035 + 0.000067 * humCal - 0.000002 * humCal * humCal); else val = ((tempVal * 0.0307 + 0.958) - (0.8767 - 0.0035 * humCal + 0.000043 * humCal * humCal)) / (0.0317 + 0.000067 * humCal - 0.000002 * humCal * humCal); } if (val < 0.0) val = 0.0; fprintf(fidData, "%f \n", val); } else { val = decodeHumidity(&page[temperatureLogSize + ((offsetDepth + i * dataBytes) % maxSamples)], dataBytes, FALSE, config); if (val < 0.0) val = 0.0; fprintf(fidData, "%f \n", val); } } else { fprintf(fidData, "%f \n", getADVoltage(&page[temperatureLogSize + (offsetDepth + i * dataBytes) % maxSamples], dataBytes, FALSE, config)); } } fflush(fidData); fclose(fidData); printf("The humidity percentage or voltage is in data.log file.\n"); } return TRUE; } // ***************************************************************************** // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Temperature Interface Functions // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ***************************************************************************** /** * Performs a temperature conversion. Use the state * information to calculate the conversion time. * * @param state byte array with device state information * */ SMALLINT doTemperatureConvert(int portnum, uchar *SNum, uchar *state) { uchar buffer[2]; /* check for mission in progress */ if (getFlag(portnum, SNum, GENERAL_STATUS_REGISTER, GSR_BIT_MISSION_IN_PROGRESS)) { printf("Can't force temperature read during a mission.\n"); return FALSE; } owSerialNum(portnum, SNum, FALSE); if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // perform the conversion buffer[0] = (uchar)FORCED_CONVERSION; buffer[1] = 0xFF; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, &buffer[0], 2)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } msDelay(750); // grab the data state[LAST_TEMPERATURE_CONVERSION_LSB & 0x3F] = readByte(portnum, SNum, LAST_TEMPERATURE_CONVERSION_LSB); state[LAST_TEMPERATURE_CONVERSION_MSB & 0x3F] = readByte(portnum, SNum, LAST_TEMPERATURE_CONVERSION_MSB); return TRUE; } // ***************************************************************************** // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // A-to-D Interface Functions // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ***************************************************************************** /** * Performs a voltage conversion on one specified channel. * Use the method getADVoltage(int,byte[]) to read * the result of this conversion, using the same channel * argument as this method uses. * * @param channel channel number in the range [0 to (getNumberADChannels() - 1)] * @param state current state of the device returned from readDevice() */ SMALLINT doADConvert(int portnum, uchar *SNum, uchar *state) { uchar buffer[2]; /* check for mission in progress */ if (getFlag(portnum, SNum, GENERAL_STATUS_REGISTER, GSR_BIT_MISSION_IN_PROGRESS)) { printf("Can't force temperature read during a mission.\n"); return FALSE; } /* check that the RTC is running */ if (!getFlag(portnum, SNum, RTC_CONTROL_REGISTER, RCR_BIT_ENABLE_OSCILLATOR)) { printf("Can't force A/D conversion if the oscillator is not enabled.\n"); return FALSE; } owSerialNum(portnum, SNum, FALSE); if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // perform the conversion buffer[0] = (uchar)FORCED_CONVERSION; buffer[1] = 0xFF; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, &buffer[0], 2)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } msDelay(750); // grab the data state[LAST_DATA_CONVERSION_LSB & 0x3F] = readByte(portnum, SNum, LAST_DATA_CONVERSION_LSB); state[LAST_DATA_CONVERSION_MSB & 0x3F] = readByte(portnum, SNum, LAST_DATA_CONVERSION_MSB); return TRUE; } double getADVoltage(uchar *data, int length, SMALLINT reverse, configLog config) { double dval; // get the 10-bit value of vout int ival = 0; if (reverse && length == 2) { ival = ((data[0] & 0x0FF) << (config.adDeviceBits - 8)); ival |= ((data[1] & 0x0FF) >> (16 - config.adDeviceBits)); } else if (length == 2) { ival = ((data[1] & 0x0FF) << (config.adDeviceBits - 8)); ival |= ((data[0] & 0x0FF) >> (16 - config.adDeviceBits)); } else { ival = ((data[0] & 0x0FF) << (config.adDeviceBits - 8)); } dval = (ival * config.adReferenceVoltage) / (1 << config.adDeviceBits); return dval; } //-------- //-------- Clock 'set' Methods //-------- /** * Set the time in the DS1922 time register format. */ void setTime(int timeReg, int hours, int minutes, int seconds, SMALLINT AMPM, uchar *state) { uchar upper, lower; /* format in bytes and write seconds */ upper = (uchar)(((seconds / 10) << 4) & 0xf0); lower = (uchar)((seconds % 10) & 0x0f); state[timeReg++] = (uchar)(upper | lower); /* format in bytes and write minutes */ upper = (uchar)(((minutes / 10) << 4) & 0xf0); lower = (uchar)((minutes % 10) & 0x0f); state[timeReg++] = (uchar)(upper | lower); /* format in bytes and write hours/(12/24) bit */ if (AMPM) { upper = 0x04; if (hours > 11) upper = (uchar)(upper | 0x02); // this next logic simply checks for a decade hour if (((hours % 12) == 0) || ((hours % 12) > 9)) upper = (uchar)(upper | 0x01); if (hours > 12) hours = hours - 12; if (hours == 0) lower = 0x02; else lower = (uchar)((hours % 10) & 0x0f); } else { upper = (uchar)(hours / 10); lower = (uchar)(hours % 10); } upper = (uchar)((upper << 4) & 0xf0); lower = (uchar)(lower & 0x0f); state[timeReg] = (uchar)(upper | lower); } /** * Set the current date in the DS1922's real time clock. * * year - The year to set to, i.e. 2001. * month - The month to set to, i.e. 1 for January, 12 for December. * day - The day of month to set to, i.e. 1 to 31 in January, 1 to 30 in April. */ void setDate(int timeReg, int year, int month, int day, uchar *state) { uchar upper, lower; /* write the day byte (the upper holds 10s of days, lower holds single days) */ upper = (uchar)(((day / 10) << 4) & 0xf0); lower = (uchar)((day % 10) & 0x0f); state[timeReg++] = (uchar)(upper | lower); /* write the month bit in the same manner, with the MSBit indicating the century (1 for 2000, 0 for 1900) */ upper = (uchar)(((month / 10) << 4) & 0xf0); lower = (uchar)((month % 10) & 0x0f); state[timeReg++] = (uchar)(upper | lower); // now write the year year = year + 1900; year = year - FIRST_YEAR_EVER; if (year > 100) { state[timeReg - 1] |= 0x80; year -= 100; } upper = (uchar)(((year / 10) << 4) & 0xf0); lower = (uchar)((year % 10) & 0x0f); state[timeReg] = (uchar)(upper | lower); } /** * helper method for decoding temperature values */ double decodeTemperature(uchar *data, int length, SMALLINT reverse, configLog config) { double whole, fraction = 0; if (reverse && length == 2) { fraction = ((data[1] & 0x0FF) / 512.0); whole = (data[0] & 0x0FF) / 2.0 + (config.lowTemp - 1); } else if (length == 2) { fraction = ((data[0] & 0x0FF) / 512.0); whole = (data[1] & 0x0FF) / 2.0 + (config.lowTemp - 1); } else { whole = (data[0] & 0x0FF) / 2.0 + (config.lowTemp - 1); } return whole + fraction; } /** * helper method for decoding humidity values */ double decodeHumidity(uchar *data, int length, SMALLINT reverse, configLog config) { double val; // get the 10-bit value of Vout val = getADVoltage(data, length, reverse, config); // convert Vout to a humidity reading // this formula is from HIH-3610 sensor datasheet val = (val - .958) / .0307; return val; } w1retap/src/libusblinux300/humutil.h000066400000000000000000000066121446446235200176720ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // humutil.h - header file for humachron functions. // Version 2.00 // #include "ownet.h" typedef struct { int sampleRate; int startDelay; SMALLINT enableRollover; SMALLINT timeSync; SMALLINT tempEnabled; SMALLINT dataEnabled; SMALLINT highDataResolution; SMALLINT highTempAlarm; SMALLINT lowTempAlarm; SMALLINT highDataAlarm; SMALLINT lowDataAlarm; SMALLINT tempAlarm; SMALLINT highTempResolution; float highTemp; float lowTemp; float highData; float lowData; } startMissionData; typedef struct { int highTemp; int lowTemp; uchar configByte; SMALLINT hasHumidity; SMALLINT useHumidityCalibration; SMALLINT useTemperatureCalibration; SMALLINT useTempCalforHumidity; int adDeviceBits; double adReferenceVoltage; double humCoeffA; double humCoeffB; double humCoeffC; double tempCoeffA; double tempCoeffB; double tempCoeffC; } configLog; SMALLINT startMission(int portnum, uchar *SNum, startMissionData set, configLog *config); SMALLINT readDevice(int portnum, uchar *SNum, uchar *buffer, configLog *config); SMALLINT getFlag(int portnum, uchar *SNum, int reg, uchar bitMask); uchar readByte(int portnum, uchar *SNum, int memAddr); void setFlag(int reg, uchar bitMask, SMALLINT flagValue, uchar *state); void setTime(int timeReg, int hours, int minutes, int seconds, SMALLINT AMPM, uchar *state); void setDate(int timeReg, int year, int month, int day, uchar *state); SMALLINT stopMission(int portnum, uchar *SNum); double decodeHumidity(uchar *data, int length, SMALLINT reverse, configLog config); double getADVoltage(uchar *state, int length, SMALLINT reverse, configLog config); SMALLINT loadMissionResults(int portnum, uchar *SNum, configLog config); SMALLINT doADConvert(int portnum, uchar *SNum, uchar *state); SMALLINT doTemperatureConvert(int portnum, uchar *SNum, uchar *state); // void setADVoltage(double voltage, uchar *data, int length); double decodeTemperature(uchar *data, int length, SMALLINT reverse, configLog config); w1retap/src/libusblinux300/ibsha33.h000066400000000000000000000114261446446235200174360ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ibsha33.h - Include file for SHA iButton (DS2432) // // Version: 2.00 // #include #include #include // Typedefs #ifndef OW_UCHAR #define OW_UCHAR typedef unsigned char uchar; #ifdef WIN32 typedef unsigned short ushort; typedef unsigned int uint; #endif #endif // output level contants #define LV_ALWAYS 2 #define LV_OPTIONAL 1 #define LV_VERBOSE 0 // SHA iButton commands #define SHA_COMPUTE_FIRST_SCRT 0x0F #define SHA_COMPUTE_NEXT_SCRT 0xF0 #define SHA_VALIDATE_PAGE 0x3C #define SHA_SIGN_PAGE 0xC3 #define SHA_COMPUTE_CHALLENGE 0xCC #define SHA_AUTHENTICATE_HOST 0xAA #define CMD_READ_MEMORY 0xF0 #define CMD_MATCH_SCRATCH 0x3C #define CMD_WRITE_SCRATCH 0x0F #define CMD_READ_SCRATCH 0xAA #define CMD_ERASE_SCRATCH 0xC3 #define CMD_COPY_SCRATCH 0x55 #define CMD_READ_AUTH_PAGE 0xA5 #define CMD_COMPUTE_SHA 0x33 // other #define IB_ROVING 0 #define IB_COPR 1 #define SHA_FAM 0x18 #define MAX_TRANS_ERROR 5 // exit codes #define EXIT_SUCCESS 0 #define EXIT_ERROR 1 #define EXIT_ERROR_WRITE 2 #define EXIT_ERROR_MONEY_SCRT 3 #define EXIT_ERROR_AUTH_SCRT 4 #define EXIT_ERROR_NO_SHA 5 // certificate typedef struct { ushort obj_descriptor; // descriptor of object 0x0501 uchar obj_len; // object length uchar pkt_len; // packet length ushort trans_id; // transaction id ushort code_mult; // monetary unit code & multiplier uchar balance[3]; // monetary balance (should be 3 bytes) uchar money_mac[20]; // monetary mac uchar cert_type; // certificate type & algorithm uchar pkt_cont_ptr; // packet continuation pointer uchar inv_crc[2]; uint write_cycle_cnt; // write cycle counter uchar money_page; // monetary page uchar serial_num[7]; // ibutton serial number (no CRC8) char file_name[4]; // file name of account uchar file_ext; // file extension of account uchar rom_id[8]; // device rom ID uchar auth_mac[20]; // authentication mac uchar constant_data[20]; // system constant data char user_data[29]; // fixed user data } eCertificate; // structure to hold each state in the StateMachine typedef struct { int Step; char StepDescription[50]; } Script; // structure to hold transaction state typedef struct { short portnum[2]; // 1-wire port numbers for co-processor/roving int dev; // current device select co-processor(1)/roving(0) uchar copr_rom[8]; // co-processor rom number uchar rov_rom[8]; // roving rom number uchar provider[5]; // provider file name (on roving); uchar copr_file[5]; // co-processor info filename char user_data[255]; // user information buffer // secret pages int c_mmaster_scrt, c_amaster_scrt, c_udevice_scrt; int r_udevice_scrt, t_udevice_scrt; // internal state of sha engine ushort address; uchar sha_cmd; uint target_secret; uchar randnum[3]; uchar temp_buffer[64]; int buf_len; } TransState; // Function Prototypes int ReadScratchSHAEE(int, ushort *, uchar *, uchar *); int WriteScratchSHAEE(int, ushort, uchar *, int); int ReadMem(int, ushort, uchar *); int LoadFirSecret(int, ushort, uchar *, int); int CopyScratchSHAEE(int, ushort, uchar *, uchar *, uchar *); int NextSecret(int, ushort, uchar *); int ReadAuthPageSHAEE(int, ushort, uchar *, uchar *, uchar *, uchar *); int SelectSHAEE(int); void ComputeSHAEE(unsigned int *, int *, int *, int *, int *, int *); int KTN(int); int NLF(int, int, int, int); w1retap/src/libusblinux300/ibsha33o.c000066400000000000000000000534641446446235200176200ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ibsha33o.C - SHA-iButton utility functions // // Version: 2.00 // History: // #include #include "ownet.h" #include "ibsha33.h" // globals int in_overdrive[MAX_PORTNUM]; //---------------------------------------------------------------------- // Read the scratchpad with CRC16 verification // // '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 // // Return: TRUE - scratch read, address, es, and data returned // FALSE - error reading scratch, device not present // // int ReadScratchSHAEE(int portnum, ushort *address, uchar *es, uchar *data) { short send_cnt = 0; uchar send_block[50]; int i; ushort lastcrc16 = 0; // access the device if (SelectSHAEE(portnum) == 1) { // read scratchpad command send_block[send_cnt++] = 0xAA; // now add the read bytes for data bytes and crc16 for (i = 0; i < 13; i++) send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { // copy data to return buffers *address = (send_block[2] << 8) | send_block[1]; *es = send_block[3]; // calculate CRC16 of result setcrc16(portnum, 0); for (i = 0; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 == 0xB001) { for (i = 0; i < 8; i++) data[i] = send_block[4 + i]; // success return TRUE; } else printf("ERROR DUE TO CRC %04X\n", lastcrc16); } } return FALSE; } //---------------------------------------------------------------------- // Write the scratchpad with CRC16 verification. 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 // // Return: TRUE - write to scratch verified // FALSE - error writing scratch, device not present, or HIDE // flag is in incorrect state for address being written. // int WriteScratchSHAEE(int portnum, ushort address, uchar *data, int data_len) { uchar send_block[50]; short send_cnt = 0, i; ushort lastcrc16; // access the device if (SelectSHAEE(portnum) == 1) { setcrc16(portnum, 0); // write scratchpad command send_block[send_cnt] = 0x0F; 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++]); } // CRC16 send_block[send_cnt++] = 0xFF; send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { // 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 if (lastcrc16 == 0xB001) return TRUE; else printf("ERROR DUE TO CRC %04X\n", lastcrc16); } } return FALSE; } //---------------------------------------------------------------------- // Read the memory pages. // // '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 // 'data' - pointer data buffer read from memory // // Return: TRUE - read was successful // FALSE - error reading memory // int ReadMem(int portnum, ushort address, uchar *data) { uchar send_block[64]; short send_cnt = 0, i, j; // access the device if (SelectSHAEE(portnum) == 1) { // read memory command send_block[send_cnt++] = 0xF0; // address 1 send_block[send_cnt++] = (uchar)(address & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); // data for (i = 0; i < 32; i++) send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { for (j = 3; j < send_cnt; j++) data[j - 3] = send_block[j]; return TRUE; } } return FALSE; } //---------------------------------------------------------------------- // Loads data into memory without a copy scratchpad // // '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 // 'secret' - pointer to secret data to be loaded // 'data_len' - length of data // // Return: TRUE - load first secret was successful // FALSE - error loading secret // // int LoadFirSecret(int portnum, ushort address, uchar *secret, int data_len) { ushort tempadd; uchar es, data[8], test; uchar send_block[32]; int send_cnt = 0; uchar mem[32]; if (ReadMem(portnum, 128, mem)) { if ((mem[8] == 0xAA) || (mem[8] == 0x55)) { printf("SECRET IS WRITE PROTECTED CAN NOT LOAD FIRST SECRET\n"); return FALSE; } if (((address < 32)) && (((mem[9] == 0xAA) || (mem[9] == 0x55)) || ((mem[13] == 0xAA) || (mem[13] == 0x55)))) { printf("PAGE 0 IS WRITE PROTECTED\n"); return FALSE; } if (((address < 128)) && ((mem[9] == 0xAA) || (mem[9] == 0x55))) { printf("PAGE 0 TO 3 WRITE PROTECTED\n"); return FALSE; } } if (WriteScratchSHAEE(portnum, address, secret, data_len) && ReadScratchSHAEE(portnum, &tempadd, &es, data)) { // access the device if (SelectSHAEE(portnum) == 1) { // write scratchpad command send_block[send_cnt++] = 0x5A; // address 1 send_block[send_cnt++] = (uchar)(tempadd & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((tempadd >> 8) & 0xFF); // ending address with data status send_block[send_cnt++] = es; if (owBlock(portnum, FALSE, send_block, send_cnt)) { // 10ms delay for writing first secret msDelay(10); test = owReadByte(portnum); if ((test == 0xAA) || (test == 0x55)) return TRUE; else printf("ERROR DUE TO INVALID LOAD\n"); } } } else printf("ERROR DUE TO READ/WRITE\n"); return FALSE; } //---------------------------------------------------------------------- // Copy the scratchpad with verification. Send the MAC to the part. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'address' - address of destination // 'secret' - secret data // 'sn' - serial number of part // 'memory' - the memory on the given page to copy to // // Return: TRUE - copy scratch verified // FALSE - error during copy scratch, device not present, or HIDE // flag is in incorrect state for address being written. // int CopyScratchSHAEE(int portnum, ushort address, uchar *secret, uchar *sn, uchar *memory) { short send_cnt = 0; ushort tmpadd; uchar send_block[80]; int i; uchar scratch[8], es, test; unsigned MT[64]; int A, B, C, D, E; int Temp; for (i = 0; i < 4; i++) MT[i] = secret[i]; for (i = 4; i < 32; i++) MT[i] = memory[i - 4]; if (ReadScratchSHAEE(portnum, &tmpadd, &es, &scratch[0])) { for (i = 32; i < 40; i++) MT[i] = scratch[i - 32]; } else { printf("ERROR DUE TO READING SCRATCH PAD DATA\n"); return FALSE; } MT[40] = (address & 0xf0) >> 5; for (i = 41; i < 48; i++) MT[i] = sn[i - 41]; for (i = 48; i < 52; i++) MT[i] = secret[i - 44]; for (i = 52; i < 55; i++) MT[i] = 0xff; MT[55] = 0x80; for (i = 56; i < 62; i++) MT[i] = 0x00; MT[62] = 0x01; MT[63] = 0xB8; ComputeSHAEE(MT, &A, &B, &C, &D, &E); // access the device if (SelectSHAEE(portnum) == 1) { // Copy command send_block[send_cnt++] = 0x55; // address 1 send_block[send_cnt++] = (uchar)(tmpadd & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((tmpadd >> 8) & 0xFF); // ending address with data status send_block[send_cnt++] = es; if (owBlock(portnum, FALSE, send_block, send_cnt)) { send_cnt = 0; // sending MAC Temp = E; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); // printf("%02X",send_block[send_cnt-1]); Temp >>= 8; } // printf("\n"); Temp = D; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); // printf("%02X",send_block[send_cnt-1]); Temp >>= 8; } // printf("\n"); Temp = C; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); // printf("%02X",send_block[send_cnt-1]); Temp >>= 8; } // printf("\n"); Temp = B; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); // printf("%02X",send_block[send_cnt-1]); Temp >>= 8; } // printf("\n"); Temp = A; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); // printf("%02X",send_block[send_cnt-1]); Temp >>= 8; } // printf("\n"); msDelay(2); if (owBlock(portnum, FALSE, send_block, send_cnt)) { msDelay(10); test = owReadByte(portnum); if ((test == 0xAA) || (test == 0x55)) return TRUE; else { if (test == 0xFF) printf("THAT AREA OF MEMORY IS WRITE-PROTECTED.\n"); else if (test == 0x00) printf("ERROR DUE TO NOT MATCHING MAC.\n"); } } } } return FALSE; } //---------------------------------------------------------------------- // Calculate the next secret using the current one. // // '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 // 'secret' - pointer to current secret and returns new secret // // Return: TRUE - next secret calculated correctly // FALSE - error calculating next secret // // int NextSecret(int portnum, ushort address, uchar *secret) { int i; unsigned MT[64]; int A, B, C, D, E; int Temp; uchar memory[32], scratch[8], es; ushort tmpadd; uchar send_block[32]; int send_cnt = 0; for (i = 0; i < 8; i++) scratch[i] = 0x00; if (!WriteScratchSHAEE(portnum, address, scratch, 8)) return FALSE; for (i = 0; i < 4; i++) MT[i] = secret[i]; if (ReadMem(portnum, (ushort)((address / ((ushort)32)) * 32), memory)) for (i = 4; i < 36; i++) MT[i] = memory[i - 4]; else { printf("ERROR DUE TO READING MEMORY PAGE DATA\n"); return FALSE; } for (i = 36; i < 40; i++) MT[i] = 0xFF; if (ReadScratchSHAEE(portnum, &tmpadd, &es, scratch)) { MT[40] = scratch[0] & 0x3F; for (i = 41; i < 48; i++) MT[i] = scratch[i - 40]; for (i = 48; i < 52; i++) MT[i] = secret[i - 44]; } else { printf("ERROR DUT TO READING SCRATCH PAD DATA\n"); return FALSE; } for (i = 52; i < 55; i++) MT[i] = 0xFF; MT[55] = 0x80; for (i = 56; i < 62; i++) MT[i] = 0x00; MT[62] = 0x01; MT[63] = 0xB8; ComputeSHAEE(MT, &A, &B, &C, &D, &E); Temp = E; for (i = 0; i < 4; i++) { secret[i] = (uchar)(Temp & 0x000000FF); // printf("%02X",secret[i]); Temp >>= 8; } // printf("\n"); Temp = D; for (i = 0; i < 4; i++) { secret[i + 4] = (uchar)(Temp & 0x000000FF); // printf("%02X",secret[i+4]); Temp >>= 8; } // printf("\n"); // access the device if (SelectSHAEE(portnum) == 1) { // Next Secret command send_block[send_cnt++] = 0x33; // address 1 send_block[send_cnt++] = (uchar)(address & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); if (owBlock(portnum, FALSE, send_block, send_cnt)) { msDelay(12); if (ReadScratchSHAEE(portnum, &tmpadd, &es, scratch)) { for (i = 0; i < 8; i++) if (scratch[i] != 0xAA) { printf("ERROR IN SCRATCHPAD DATA BEING 0xAA\n"); return FALSE; } return TRUE; } } } return FALSE; } //---------------------------------------------------------------------- // Read Authenticated Page. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'address' - address of page to do a read authenticate // 'secret' - current secret // 'SerNum' - serial number for the part // 'data' - buffer to how data read from page // 'challenge' - the challenge that is to be written to the scratchpad // // Return: TRUE - read sucessfull // FALSE - CRC error, device not present // int ReadAuthPageSHAEE(int portnum, ushort address, uchar *secret, uchar *SerNum, uchar *data, uchar *challenge) { short send_cnt = 0; uchar send_block[80]; int i; int A, B, C, D, E; int Temp; unsigned MT[64]; uchar memory[32], scratch[8], es; ushort tmpadd; ushort lastcrc16; if (!WriteScratchSHAEE(portnum, address, challenge, 8)) return FALSE; for (i = 0; i < 4; i++) MT[i] = secret[i]; if (ReadMem(portnum, (ushort)((address / ((ushort)32)) * 32), memory)) for (i = 4; i < 36; i++) MT[i] = memory[i - 4]; else { printf("ERROR DUE TO READING MEMORY PAGE DATA\n"); return FALSE; } for (i = 36; i < 40; i++) MT[i] = 0xFF; if (ReadScratchSHAEE(portnum, &tmpadd, &es, scratch)) { MT[40] = (0x40 | (uchar)(((tmpadd << 3) & 0x08) | (uchar)((tmpadd >> 5) & 0x07))); for (i = 41; i < 48; i++) MT[i] = SerNum[i - 41]; for (i = 48; i < 52; i++) MT[i] = secret[i - 44]; for (i = 52; i < 55; i++) MT[i] = scratch[i - 48]; } else { printf("ERROR DUT TO READING SCRATCH PAD DATA\n"); return FALSE; } MT[55] = 0x80; for (i = 56; i < 62; i++) MT[i] = 0x00; MT[62] = 0x01; MT[63] = 0xB8; ComputeSHAEE(MT, &A, &B, &C, &D, &E); // access the device if (SelectSHAEE(portnum) == 1) { setcrc16(portnum, 0); // Read Authenticated Command send_block[send_cnt] = 0xA5; lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // address 1 send_block[send_cnt] = (uchar)(tmpadd & 0xFF); lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // address 2 send_block[send_cnt] = (uchar)((tmpadd >> 8) & 0xFF); lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // data + FF byte for (i = 0; i < 35; i++) send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { // calculate CRC16 of result for (i = 3; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 != 0xB001) { printf("FIRST CRC TEST FAILED %04X\n", lastcrc16); return FALSE; } for (i = 3; i < 35; i++) data[i - 3] = send_block[i]; send_cnt = 0; for (i = 0; i < 22; i++) send_block[send_cnt++] = 0xFF; if (owBlock(portnum, FALSE, send_block, send_cnt)) { // calculate CRC16 of result setcrc16(portnum, 0); for (i = 0; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 != 0xB001) { printf("SECOND CRC TEST FAILED %04X\n", lastcrc16); return FALSE; } send_cnt = 0; Temp = E; for (i = 0; i < 4; i++) { if (send_block[send_cnt++] != (uchar)(Temp & 0x000000FF)) { printf("COMPARING MAC FAILED\n"); return FALSE; } Temp >>= 8; } Temp = D; for (i = 0; i < 4; i++) { if (send_block[send_cnt++] != (uchar)(Temp & 0x000000FF)) { printf("COMPARING MAC FAILED\n"); return FALSE; } Temp >>= 8; } Temp = C; for (i = 0; i < 4; i++) { if (send_block[send_cnt++] != (uchar)(Temp & 0x000000FF)) { printf("COMPARING MAC FAILED\n"); return FALSE; } Temp >>= 8; } Temp = B; for (i = 0; i < 4; i++) { if (send_block[send_cnt++] != (uchar)(Temp & 0x000000FF)) { printf("COMPARING MAC FAILED\n"); return FALSE; } Temp >>= 8; } Temp = A; for (i = 0; i < 4; i++) { if (send_block[send_cnt++] != (uchar)(Temp & 0x000000FF)) { printf("COMPARING MAC FAILED\n"); return FALSE; } Temp >>= 8; } return TRUE; } } } return FALSE; } //-------------------------------------------------------------------------- // Select the current device and attempt overdrive if possible. // // '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 // int SelectSHAEE(int portnum) { int rt, cnt = 0; // 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]) { // set to normal speed if (MODE_NORMAL != owSpeed(portnum, MODE_NORMAL)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } in_overdrive[portnum] = FALSE; } } // present but not in overdrive else if (!in_overdrive[portnum]) { // put all devices in overdrive if (owTouchReset(portnum)) { if (owWriteByte(portnum, 0x3C)) { // set to overdrive speed if (MODE_OVERDRIVE != owSpeed(portnum, MODE_OVERDRIVE)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } in_overdrive[portnum] = TRUE; } } rt = 0; } else break; } while ((rt != 1) && (cnt++ < 3)); return rt; } //---------------------------------------------------------------------- // Compute the 160-bit MAC // // 'MT' - input data // 'A' - part of the 160 bits // 'B' - part of the 160 bits // 'C' - part of the 160 bits // 'D' - part of the 160 bits // 'E' - part of the 160 bits // // 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). // // void ComputeSHAEE(unsigned int *MT, int *A, int *B, int *C, int *D, int *E) { unsigned int MTword[80]; int i; int ShftTmp; int Temp; for (i = 0; i < 16; i++) MTword[i] = (MT[i * 4] << 24) | (MT[i * 4 + 1] << 16) | (MT[i * 4 + 2] << 8) | MT[i * 4 + 3]; for (i = 16; i < 80; i++) { ShftTmp = MTword[i - 3] ^ MTword[i - 8] ^ MTword[i - 14] ^ MTword[i - 16]; MTword[i] = ((ShftTmp << 1) & 0xfffffffe) | ((ShftTmp >> 31) & 0x00000001); } *A = 0x67452301; *B = 0xefcdab89; *C = 0x98badcfe; *D = 0x10325476; *E = 0xc3d2e1f0; for (i = 0; i < 80; i++) { ShftTmp = ((*A << 5) & 0xffffffe0) | ((*A >> 27) & 0x0000001f); Temp = NLF(*B, *C, *D, i) + *E + KTN(i) + MTword[i] + ShftTmp; *E = *D; *D = *C; *C = ((*B << 30) & 0xc0000000) | ((*B >> 2) & 0x3fffffff); *B = *A; *A = Temp; } } // calculation used for the MAC int KTN(int n) { if (n < 20) return 0x5a827999; else if (n < 40) return 0x6ed9eba1; else if (n < 60) return 0x8f1bbcdc; else return 0xca62c1d6; } // calculation used for the MAC 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); } w1retap/src/libusblinux300/ibshaut.c000066400000000000000000000150131446446235200176300ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ibshaut.c - Utility functions for SHA iButton applications // // Version: 2.00 // History: // #include "ownet.h" #include "ibsha18.h" // external functions extern int ReadUDP_SHA(int, ushort, uchar *, int *); extern int WritePage(int, uchar *, int, TransState *); extern int EnterString(char *, char *, int, int); extern int EnterNum(char *, int, int *, int, int); extern int ToHex(char ch); // local function prototypes int PrintHeader(char *); void output_status(int, char *); int GetSeviceProviderSettings(int, char *, uchar *, int, uchar *); int GetRovingSettings(uchar *, uint *); // globals extern int VERBOSE; extern FILE *fp; //-------------------------------------------------------------------------- // Prints a message, and the current driver versions. Return TRUE // driver version were found and FALSE if not. // int PrintHeader(char *title) { char msg[512]; int rt = TRUE; // print a header with driver version info sprintf(msg, "\n%s\n", title); output_status(LV_ALWAYS, msg); output_status(LV_ALWAYS, "Dallas Semiconductor Corporation\n"); output_status(LV_ALWAYS, "Copyright (C) 1992-2000\n\n"); output_status(LV_ALWAYS, "Press CTRL-C to end program\n\n"); return rt; } //-------------------------------------------------------------------------- // output status message // void output_status(int level, char *st) { // skip null strings if (st[0] == 0) return; // check if in verbose mode if ((level >= LV_ALWAYS) || VERBOSE) { printf("%s", st); if (fp != NULL) fprintf(fp, "%s", st); } } //---------------------------------------------------------------------- // Get the settings for the Service Provider // int GetSeviceProviderSettings(int get_sp, char *sp_name, uchar *auth_secret, int get_money, uchar *money_secret) { char temp[255]; int i, len, cnt; // instructions output_status(LV_ALWAYS, "Default values specified in ()\n" "Hit (CTRL-C or ESCAPE and then ENTER) to abort\n"); // service provider name if (get_sp) { sprintf(sp_name, "DLSM"); len = EnterString("\nEnter the service provider name", sp_name, 1, 4); if (len < 0) return FALSE; else { // file with spaces to make easier on compare for (i = len; i < 4; i++) sp_name[i] = ' '; sp_name[4] = 0; sprintf(temp, "Service provider name selected: %s\n", sp_name); output_status(LV_ALWAYS, temp); } } // auth secret sprintf(temp, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); len = EnterString("\nEnter service provider AUTHENTICATE secret (hex)\n", temp, 2, 64); if (len < 0) return FALSE; else { // convert to byte array with FF padding for (i = 0; i < len; i += 2) { auth_secret[i / 2] = ToHex(temp[i]) << 4; auth_secret[i / 2] |= ToHex(temp[i + 1]); } for (i = len; i < 64; i += 2) auth_secret[i / 2] = 0xFF; cnt = sprintf(temp, "Service provider AUTHENTICATE secret entered (hex):\n "); for (i = 0; i < 32; i++) cnt += sprintf(temp + cnt, "%02X", auth_secret[i]); cnt += sprintf(temp + cnt, "\n"); output_status(LV_ALWAYS, temp); } // money secret if (get_money) { sprintf(temp, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); len = EnterString("\nEnter service provider MONEY secret (hex)\n", temp, 2, 64); if (len < 0) return FALSE; else { // convert to byte array with FF padding for (i = 0; i < len; i += 2) { money_secret[i / 2] = ToHex(temp[i]) << 4; money_secret[i / 2] |= ToHex(temp[i + 1]); } for (i = len; i < 64; i += 2) money_secret[i / 2] = 0xFF; cnt = sprintf(temp, "Service provider MONEY secret entered (hex):\n "); for (i = 0; i < 32; i++) cnt += sprintf(temp + cnt, "%02X", money_secret[i]); cnt += sprintf(temp + cnt, "\n"); output_status(LV_ALWAYS, temp); } } return TRUE; } //---------------------------------------------------------------------- // Get the settings for the Service Provider // int GetRovingSettings(uchar *rov_information, uint *money) { char temp[255]; int i, len; // instructions output_status(LV_ALWAYS, "Default values specified in ()\n" "Hit (CTRL-C or ESCAPE and then ENTER) to abort\n"); // user information rov_information[29] = 0; len = EnterString("\nEnter roving user fixed information\n", (char *)rov_information, 0, 28); if (len < 0) return FALSE; else { rov_information[len] = 0; sprintf(temp, "Roving user fixed information: %s\n", rov_information); output_status(LV_ALWAYS, temp); // pad the user information with spaces up to 28 characters for (i = len; i < 28; i++) rov_information[i] = ' '; // pad rest with zeros (money page) for (i = 28; i < 56; i++) rov_information[i] = 0; } // money (1.02) change to dollars if (!EnterNum("\nEnter the starting money balance (in US dollars)\n", 5, (int *)money, 0, 99999)) return FALSE; else { sprintf(temp, "Starting balance: $%ld US\n", *money); output_status(LV_ALWAYS, temp); } return TRUE; } w1retap/src/libusblinux300/initcopr.c000066400000000000000000000175341446446235200200320ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // initcopr.c - This utility initializes the SHA iButton // (DS1963S) as a coprocessor. // // Version: 2.00 // History: // #include "ownet.h" #include "ibsha18.h" // external function prototypes extern int PrintHeader(char *); extern void output_status(int, char *); extern int GetSeviceProviderSettings(int, char *, uchar *, int, uchar *); extern int WriteFileSHA(uchar *, uchar *, int, uchar *, TransState *); extern void ExitProg(char *, int); extern int owAcquire(int, char *); extern void owRelease(int); extern int CreateAuthSecret(uchar *, TransState *); extern int CreateMoneySecret(uchar *, TransState *); extern int SelectCoProcessor(TransState *); extern int FindSHA(uchar *, TransState *); extern int getkeystroke(void); // verbose output mode int VERBOSE = 0; // file for output FILE *fp; //---------------------------------------------------------------------- // This is the Main routine for initcopr // int main(int argc, char **argv) { int filenum; char msg[200]; uchar auth_secret[65], money_secret[65]; int cnt, exit_code, i; uchar buf[6], flname[6], page_map[1]; TransState ts; // check arguments to see if request instruction with '?' or too many if ((argc > 4) || (argc < 2) || ((argc > 1) && (argv[1][0] == '?' || argv[1][1] == '?'))) ExitProg("\nusage: initcopr 1wire_net_name \n" " - initialize a coprocessor SHA iButton on specified\n" " 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 show verbose output (default not shown)\n" " - version 2.00\n", EXIT_ERROR); // attempt to acquire the 1-Wire Net ts.portnum[IB_ROVING] = 0; if (!owAcquire(ts.portnum[IB_ROVING], argv[1])) { OWERROR_DUMP(stdout); exit(1); } // hard code CO_PROCESSOR port to be the same ts.portnum[IB_COPR] = ts.portnum[IB_ROVING]; // print the header info if (!PrintHeader("InitCoPr Version 2.00")) ExitProg("No driver found\n", EXIT_ERROR); // check arguments VERBOSE = FALSE; filenum = 0; if (argc >= 3) { if (argv[2][0] != '/') filenum = 2; else if ((argv[2][1] == 'V') || (argv[2][1] == 'v')) VERBOSE = TRUE; if (argc == 4) { if (argv[3][0] != '/') filenum = 3; else if ((argv[3][1] == 'V') || (argv[3][1] == 'v')) VERBOSE = TRUE; } } // open the output file fp = NULL; if (filenum > 0) { fp = fopen(argv[filenum], "wb"); if (fp == NULL) { printf("ERROR, Could not open output file!\n"); exit(EXIT_ERROR); } else printf("File '%s' opened to write data.\n\n", argv[filenum]); } // set the default pages used for secrets (will be written to copr) ts.c_mmaster_scrt = 0; // co-processor money master secret ts.c_amaster_scrt = 1; // co-processor auth master secret ts.c_udevice_scrt = 2; // co-processor unique device secret(calculated) ts.r_udevice_scrt = 5; // roving unique device secret ts.t_udevice_scrt = 4; // till unique device secret sprintf((char *)(&ts.copr_file[0]), "COPR"); // prompt for service provider settings output_status(LV_ALWAYS, "Enter information to create the co-processor SHA" " iButton for a service\n"); if (!GetSeviceProviderSettings(TRUE, (char *)ts.provider, auth_secret, TRUE, money_secret)) ExitProg("Aborted entering the provider settings, end program\n", EXIT_ERROR); // create the data for the TMEX file sprintf((char *)flname, "%s", ts.copr_file); // first 4 letters, service name sprintf((char *)buf, "%s", ts.provider); buf[4] = 102; // extension of SHA money file buf[5] = ts.c_mmaster_scrt; // money master secret number buf[6] = ts.c_amaster_scrt; // auth master secret number buf[7] = ts.c_udevice_scrt; // unique device secret(calculated) page_map[0] = 1; // page map for only 1 file page // get warning output_status(LV_ALWAYS, "\n** Warning SHA iButton on 1-Wire will be overwritten!!\n (Press ENTER to continue)\n"); getkeystroke(); // select co-processor port if (SelectCoProcessor(&ts)) { output_status(LV_ALWAYS, "** 1-Wire port for co-processor selected\n"); // find the first available SHA iButton if (FindSHA(&ts.copr_rom[0], &ts)) { // loop to print ROM of device found cnt = sprintf(msg, "** SHA iButton found: "); for (i = 7; i >= 0; i--) cnt += sprintf(msg + cnt, "%02X", ts.copr_rom[i]); sprintf(msg + cnt, "\n"); output_status(LV_ALWAYS, msg); // create the authentication secret if (CreateAuthSecret(&auth_secret[0], &ts)) { output_status(LV_ALWAYS, "** Authenticate secret created\n"); // create the money secret if (CreateMoneySecret(&money_secret[0], &ts)) { output_status(LV_ALWAYS, "** Money secret created\n"); // coprocessor is already current device if (WriteFileSHA(flname, buf, 8, page_map, &ts)) { output_status(LV_ALWAYS, "** Co-processor info file created\n"); exit_code = EXIT_SUCCESS; } else { output_status(LV_ALWAYS, "ERROR, Could not write Co-processor info file\n"); exit_code = EXIT_ERROR_WRITE; } } else { output_status(LV_ALWAYS, "ERROR, Could not create money secret\n"); exit_code = EXIT_ERROR_MONEY_SCRT; } } else { output_status(LV_ALWAYS, "ERROR, Could not create authorization secret\n"); exit_code = EXIT_ERROR_AUTH_SCRT; } } else { output_status(LV_ALWAYS, "ERROR, Could not find a SHA iButton\n"); exit_code = EXIT_ERROR_NO_SHA; } } else { output_status(LV_ALWAYS, "ERROR, Could not select co-processor 1-Wire\n"); exit_code = EXIT_ERROR; } // release the 1-Wire Net owRelease(ts.portnum[IB_ROVING]); sprintf(msg, "Closing port %s.\n", argv[1]); output_status(LV_ALWAYS, msg); // close opened file if ((fp != NULL) && (fp != stdout)) { printf("File '%s' closed.\n", argv[filenum]); fclose(fp); } // check on result of operation if (exit_code) { OWERROR_DUMP(stdout); printf("ERROR reported (%d), end program\n", exit_code); } else printf("End program normally\n"); // end the program exit(exit_code); return exit_code; } w1retap/src/libusblinux300/initrov.c000066400000000000000000000260251446446235200176700ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // initrov.c - This utility initializes roving SHA iButtons // (DS1963S). // // Version: 2.00 // History: // #include "ownet.h" #include "ibsha18.h" // external function prototypes extern SMALLINT owAcquire(int, char *); extern void owRelease(int); extern int PrintHeader(char *); extern void output_status(int, char *); extern int EnterString(char *, char *, int, int); extern int ToHex(char); extern int GetSeviceProviderSettings(int, char *, uchar *, int, uchar *); extern int GetRovingSettings(uchar *, uint *); extern int WriteFileSHA(uchar *, uchar *, int, uchar *, TransState *); extern void ExitProg(char *, int); extern int CreateAuthSecret(uchar *, TransState *); extern int FindSHA(uchar *, TransState *); extern int SelectRoving(TransState *); extern int CreateUniqueDeviceSecret(uchar *, TransState *); extern int ReadAuth(eCertificate *, TransState *); extern int WriteMoney(eCertificate *, TransState *); extern int FindCoprocessor(TransState *); extern int VerifyMoney(eCertificate *, TransState *); extern int getkeystroke(void); extern int key_abort(void); // local function int CreateRovingSHA(uchar *, uchar *, uint, char *, TransState *); // verbose output mode int VERBOSE = 0; // file for output FILE *fp; //---------------------------------------------------------------------- // This is the Main routine for initrov // int main(int argc, char **argv) { int filenum; char msg[300]; uchar auth_secret[85], dmmy[85]; int cnt, exit_code, i; uint money; uchar rov_information[128]; TransState ts; // check arguments to see if request instruction with '?' or too many if ((argc > 4) || (argc < 2) || ((argc > 1) && (argv[1][0] == '?' || argv[1][1] == '?'))) ExitProg("\nusage: initrov 1wire_net_name \n" " - initialize a roving SHA iButton on specified\n" " 1-Wire Net port,\n" " co-processor SHA iButton must be present\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 show verbose output (default not shown)\n" " - version 2.00\n", EXIT_ERROR); // attempt to acquire the 1-Wire Net ts.portnum[IB_ROVING] = 0; if (!owAcquire(ts.portnum[IB_ROVING], argv[1])) { OWERROR_DUMP(stdout); exit(1); } // hard code CO_PROCESSOR port to be the same ts.portnum[IB_COPR] = ts.portnum[IB_ROVING]; // print the header info if (!PrintHeader("InitRov Version 2.00")) ExitProg("No driver found\n", EXIT_ERROR); // check arguments VERBOSE = FALSE; filenum = 0; if (argc >= 3) { if (argv[2][0] != '/') filenum = 2; else if ((argv[2][1] == 'V') || (argv[2][1] == 'v')) VERBOSE = TRUE; if (argc == 4) { if (argv[3][0] != '/') filenum = 3; else if ((argv[3][1] == 'V') || (argv[3][1] == 'v')) VERBOSE = TRUE; } } // open the output file fp = NULL; if (filenum > 0) { fp = fopen(argv[filenum], "wb"); if (fp == NULL) { printf("ERROR, Could not open output file!\n"); exit(EXIT_ERROR); } else printf("File '%s' opened to write data.\n\n", argv[filenum]); } // run the script find the co-processor sprintf((char *)(&ts.copr_file[0]), "COPR"); if (FindCoprocessor(&ts)) { // loop to print ROM of device found cnt = sprintf(msg, "** Co-processor SHA iButton found: "); for (i = 7; i >= 0; i--) cnt += sprintf(msg + cnt, "%02X", ts.copr_rom[i]); cnt += sprintf(msg + cnt, "\n** Provider file: "); for (i = 0; i < 4; i++) cnt += sprintf(msg + cnt, "%c", ts.provider[i]); cnt += sprintf(msg + cnt, ".%d\n", ts.provider[4]); cnt += sprintf(msg + cnt, "** Money master secret page: %d\n", ts.c_mmaster_scrt); cnt += sprintf(msg + cnt, "** Auth master secret page: %d\n", ts.c_amaster_scrt); cnt += sprintf(msg + cnt, "** Unique device (calculated) secret page: %d\n", ts.c_udevice_scrt); output_status(LV_ALWAYS, msg); exit_code = EXIT_SUCCESS; } else ExitProg("ERROR, could not find co-processor on 1-Wire Net, end program\n", EXIT_ERROR); // prompt for service provider settings output_status(LV_ALWAYS, "\n\nEnter provider information to create the roving SHA iButton\n"); if (!GetSeviceProviderSettings(FALSE, (char *)ts.provider, auth_secret, FALSE, dmmy)) ExitProg("Aborted entering the provider settings, end program\n", EXIT_ERROR); // destination roving page (fixed pages for demo) ts.r_udevice_scrt = 5; // roving unique device secret // default info and money sprintf((char *)rov_information, "no info"); money = 1000; // loop to create roving SHA iButtons do { // create roving SHA exit_code = CreateRovingSHA(&auth_secret[0], &rov_information[0], money, &msg[0], &ts); output_status(LV_ALWAYS, msg); // print clear result if (exit_code == EXIT_SUCCESS) output_status(LV_ALWAYS, "\n-------------\n SUCCESS\n-------------\n"); else if (exit_code != EXIT_ERROR) output_status(LV_ALWAYS, "\n-------------\n ERROR\n-------------\n"); } while ((exit_code != EXIT_ERROR) && !key_abort()); // release the 1-Wire Net owRelease(ts.portnum[IB_ROVING]); sprintf(msg, "Closing port %s.\n", argv[1]); output_status(LV_ALWAYS, msg); // close opened file if ((fp != NULL) && (fp != stdout)) { printf("File '%s' closed.\n", argv[filenum]); fclose(fp); } // check on result of operation if (exit_code) printf("ERROR reported (%d), end program\n", exit_code); else printf("End program normally\n"); // end the program exit(exit_code); return exit_code; } //-------------------------------------------------------------------------- // Find and create a roving sha iButtons // int CreateRovingSHA(uchar *auth_secret, uchar *rov_information, uint money, char *msg, TransState *ts) { int rt = EXIT_SUCCESS, cnt = 0, i; uint ul; uchar page_map[5]; eCertificate ec; // place in loop for easy cleanup on error for (;;) { // prompt for the roving information if (!GetRovingSettings(rov_information, &money)) { cnt += sprintf(msg + cnt, "Aborted entering the roving settings, end program\n"); rt = EXIT_ERROR; break; } // give warning output_status(LV_ALWAYS, "\n** Warning (non-Copr) SHA iButton on 1-Wire will be overwritten!!\n" " (Press ENTER to continue)\n\n"); getkeystroke(); // select roving port if (SelectRoving(ts)) cnt += sprintf(msg + cnt, "** 1-Wire port for roving selected\n"); else { cnt += sprintf(msg + cnt, "ERROR, Could not select co-processor 1-Wire\n"); rt = EXIT_ERROR; break; } // find the first available (non-Copr) SHA iButton ts->user_data[0] = 0; if (FindSHA(&ts->rov_rom[0], ts)) { // loop to print ROM of device found cnt += sprintf(msg + cnt, "** SHA iButton found: "); for (i = 7; i >= 0; i--) cnt += sprintf(msg + cnt, "%02X", ts->rov_rom[i]); cnt += sprintf(msg + cnt, "\n"); // set page map for money file page_map[0] = ts->r_udevice_scrt; page_map[1] = ts->r_udevice_scrt + 8; } else { cnt += sprintf(msg + cnt, "ERROR, Could not find a SHA iButton\n"); rt = EXIT_ERROR_NO_SHA; break; } // create the authentication secret if (CreateUniqueDeviceSecret(&auth_secret[0], ts)) cnt += sprintf(msg + cnt, "** Uniqued device secret created\n"); else { cnt += sprintf(msg + cnt, "ERROR, Could not create authorization secret\n"); rt = EXIT_ERROR_AUTH_SCRT; break; } // write the money/info file (with invalid money to start) if (WriteFileSHA(ts->provider, rov_information, 56, page_map, ts)) cnt += sprintf(msg + cnt, "** Roving info file created\n"); else { cnt += sprintf(msg + cnt, "ERROR, Could not write roving info file\n"); rt = EXIT_ERROR_WRITE; break; } // read auth money page (to get counters/rom in ec) if (ReadAuth(&ec, ts)) { cnt += sprintf(msg + cnt, "** Money page read to get counter\n"); // put correct money value in cert ul = money * 100; // (1.02) for (i = 0; i < 3; i++) { ec.balance[i] = (uchar)(ul & 0xFF); ul >>= 8; } // increment counter ec.write_cycle_cnt++; // set transaction ID ec.trans_id = 0x1234; // code mult ec.code_mult = 0x8B48; // US Dollars with 10^-2 multiplier (1.02) } else { cnt += sprintf(msg + cnt, "ERROR, could not read auth money page\n" " Auth secret provide may be incorrect!!\n"); rt = EXIT_ERROR_WRITE; break; } // write real money if (WriteMoney(&ec, ts)) cnt += sprintf(msg + cnt, "** Money written\n"); else { cnt += sprintf(msg + cnt, "ERROR, Could not write money\n"); rt = EXIT_ERROR_WRITE; break; } // read auth money page (to get copr to do unique secret) if (ReadAuth(&ec, ts)) cnt += sprintf(msg + cnt, "** Money page authenticate read\n"); else { cnt += sprintf(msg + cnt, "ERROR, could not read auth money page\n" " Auth secret provide may be incorrect!!\n"); rt = EXIT_ERROR_WRITE; break; } // verify money (sanity check) if (VerifyMoney(&ec, ts)) cnt += sprintf(msg + cnt, "** Money contents verified\n"); else { cnt += sprintf(msg + cnt, "ERROR, could not verify money\n"); rt = EXIT_ERROR_WRITE; break; } break; } return rt; } w1retap/src/libusblinux300/ioutil.c000066400000000000000000000212441446446235200175010ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ioutil.c - I/O Utility functions // // Version: 2.00 // History: // #include #include #include #include #include #include "ownet.h" #ifdef __MC68K__ #include #include #endif // External functions extern int key_abort(void); // typedef typedef void Sigfunc(int); #ifndef __MC68K__ static void sig_ctrlc(int signo); #else int key_aborted = FALSE; #endif // global state of interrupt static int got_interrupt = 0; //---------------------------------------------------------------------- // Enter a string // Leave the same if no characters entered // int EnterString(char *msg, char *buf, int min, int max) { int len, deflen; char ch, defbuf[80]; // check for abort if (key_abort()) return -1; // remember the start length deflen = strlen(buf); if (deflen < 80) strcpy(defbuf, buf); else defbuf[0] = 0; // prompt if (deflen < 30) printf("%s (%s): ", msg, buf); else printf("%s (%s):\n", msg, buf); // loop to get the file len = 0; for (;;) { // get a key ch = getkeystroke(); // check for abort if (key_abort()) return -1; // check the backspace key if (ch == 0x08) { if (len > 0) { // got a valid backspace len--; printf("\x008 \x008"); } } // escape key else if (ch == 0x1B) { printf("\n"); return -1; } // caraige return if (ch == 0x0A) { // check for special case (keep default) if ((len == 0) && (deflen > min)) { sprintf(buf, "%s", defbuf); printf("\n"); return deflen; } else if (len < min) continue; else { printf("\n"); return len; } } // valid key else if (len < max) { printf("%c", ch); // record the char buf[len++] = ch; } } } //---------------------------------------------------------------------- // Enter a decimal string and convert it to an unsigned int // Prompt again if not within min/max inclusive. // int EnterNum(char *msg, int numchars, int *value, int min, int max) { short tmp, cnt, isneg = FALSE; char ch; // check for abort if (key_abort()) return FALSE; // loop while not in correct range do { printf("%s (%d): ", msg, *value); // loop for each character read cnt = 0; for (;;) { ch = getkeystroke(); // check for abort if (key_abort()) return FALSE; // negative flag if (ch == '-') { if (!isneg) { isneg = TRUE; printf("-"); cnt++; } } // backspace if (ch == 0x08) { if (cnt) { if (isneg && (cnt == 1)) isneg = FALSE; else *value /= 10; printf("%c %c", ch, ch); cnt--; } } // escape if (ch == 0x1B) { printf(" Aborted\n\n"); return FALSE; } // enter if (ch == 0x0A) { printf("\n"); break; } // number else if ((ch >= '0') && (ch <= '9')) { if (cnt == 0) *value = 0; if (cnt < numchars) { printf("%c", ch); tmp = ch - 0x30; *value *= 10; *value += tmp; cnt++; } } } if (isneg) *value = -*value; } while ((*value < min) || (*value > max)); return TRUE; } //---------------------------------------------------------------------- // Enter a hex string and convert it to an unsigned int // (1-8) characters // int EnterHex(char *msg, int numchars, uint *value) { int tmp, cnt; int ch; // prompt printf("%s (enter hex, up to %d chars):", msg, numchars); *value = 0; cnt = 0; do { ch = getkeystroke(); if (ch == 0x08) { printf("%c %c", ch, ch); if (cnt) cnt--; } else if (ch == 0x1B) { printf(" Aborted\n\n"); return FALSE; } // caraige return else if (ch == 0x0A) { printf("\n"); return TRUE; } else { tmp = ToHex((char)ch); if (tmp) { printf("%c", ch); *value <<= 4; *value |= tmp; cnt++; } } } while (cnt < numchars); printf("\n"); return TRUE; } //------------------------------------------------------------------------ // Convert 1 hex character to binary. If not a hex character then // return 0. // int ToHex(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - 0x30; else if ((ch >= 'A') && (ch <= 'F')) return ch - 0x37; else if ((ch >= 'a') && (ch <= 'f')) return ch - 0x57; else return 0; } //------------------------------------------------------------------------ // Get a character // int getkeystroke(void) { return fgetc(stdin); } //------------------------------------------------------------------------ // Check if key abort has occurred // int key_abort(void) { #ifdef __MC68K__ EventType event; EvtGetEvent(&event, 1); if (event.eType == penDownEvent) key_aborted = TRUE; return key_aborted; #else #ifdef _WINDOWS return FALSE; #else static int didsetup = 0; if (!didsetup) { if (signal(SIGINT, sig_ctrlc) == SIG_ERR) printf("could not setup ctrl-c handler\n"); didsetup = 1; } return got_interrupt; #endif #endif } #ifndef __MC68K__ //------------------------------------------------------------------------ // Key abort interrupt handler // static void sig_ctrlc(int signo) { // set abort flag got_interrupt = 1; // print warning (may take awhile to abort) printf("<< CTRL-C key abort >>"); } #endif //------------------------------------------------------------------------ // Print message and exit program // void ExitProg(char *msg, int exit_code) { #ifndef __MC68K__ printf("%s\n", msg); exit(exit_code); #else // Add code to print exit criteria for Palm/Visor #endif } /** * Retrieve user input from the console in the form of hex or text. * * write_buff the buffer for the data to be written into. * max_len the max length of the data * gethex tells whether the data is hex * * @return length of arra. */ int getData(uchar *write_buff, int max_len, SMALLINT gethex) { char ch; char hexchar[3]; int cnt = 0; int done = FALSE; if (!gethex) { do { ch = (char)getchar(); if (!isspace(ch) && cnt < max_len) write_buff[cnt++] = (uchar)ch; else if (ch == ' ' && cnt < max_len) write_buff[cnt++] = (uchar)ch; else if (cnt > 0) done = TRUE; } while (!done); } else { hexchar[2] = 0; do { ch = (char)getchar(); if (!isspace(ch)) { hexchar[0] = ch; hexchar[1] = (char)getchar(); if (cnt < max_len) write_buff[cnt++] = (uchar)strtol(&hexchar[0], NULL, 16); } else if ((ch != ' ') && (cnt > 0)) done = TRUE; } while (!done); } return cnt; } void PrintHex(uchar *buffer, int cnt) { int i; for (i = 0; i < cnt; i++) { if ((i & 15) == 0) printf("\n %02X", buffer[i]); else printf(".%02X", buffer[i]); } printf("\n"); } void PrintChars(uchar *buffer, int cnt) { int i; for (i = 0; i < cnt; i++) { printf("%c", buffer[i]); } } void PrintSerialNum(uchar *buffer) { int i; for (i = 7; i >= 0; i--) { printf("%02X", buffer[i]); } } w1retap/src/libusblinux300/jib96.c000066400000000000000000001312331446446235200171170ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // Module Name: Jib API // // Description: API for executing methods on the iButton for Java and // for executing the iButton Command Processor. // // Filename: jib96.c // // Dependant Files: jib96.h // // Version: 1.00 (based on jibapi.c V1.24) // // Comments: - "iButton with Java" API. // // Notes: - The format for all values passed to or from the // iButton's Command Processor are "Little Endian". The // format for values passed to/from an applet's process // method are determined by the applet's author. // - Not all commands in this API version are supported in // older firmware revisions of the Java Button. // #include "jib96.h" // globals to this module static ushort g_LastError = ERR_ISO_NORMAL_00; static CMDPACKET g_CmdPacket; static RETPACKET g_RetPacket; static ushort g_ExecTimeMS = 64; static ushort g_MinTimeMS = 0; static RESPONSEAPDU g_ResponseAPDU; static JIBMASTERPIN g_MasterPIN = {0, {0, 0, 0, 0, 0, 0, 0, 0}}; //-------------------------------------------------------------------------- // Sets the default execution time. // void SetDefaultExecTime(ushort p_ExecTimeMS) { g_ExecTimeMS = p_ExecTimeMS; } //-------------------------------------------------------------------------- // Sends a generic command APDU to the iButton // @param portnum is the port number where the device is // @param p_lpCommandAPDU is configured by the caller // @param p_ExecTimeMS is the estimated runtime in // milliseconds. Valid runtimes range from 64 milliseconds to just under // 4 seconds (4000 ms). Invalid runtimes will be adjusted up or down // as necessary. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SendAPDU(int portnum, LPCOMMANDAPDU p_lpCommandAPDU, ushort p_ExecTimeMS) { ushort l_Error; ushort l_RecvLen; ushort l_Delay = 0; memset((uchar *)&g_ResponseAPDU, 0, sizeof(g_ResponseAPDU)); if (p_ExecTimeMS) { l_Delay = (p_ExecTimeMS + g_MinTimeMS) / 250; if (l_Delay > 0x0F) l_Delay = 0x0F; } if (!p_lpCommandAPDU) { SetJiBError(g_ResponseAPDU.SW); return &g_ResponseAPDU; } g_CmdPacket.CmdByte = 137; g_CmdPacket.GroupID = 0; // add 3 bytes for the packet header g_CmdPacket.Len = 3 + sizeof(p_lpCommandAPDU->Header); memcpy(g_CmdPacket.CmdData, p_lpCommandAPDU->Header, sizeof(p_lpCommandAPDU->Header)); g_CmdPacket.CmdData[g_CmdPacket.Len++ - 3] = p_lpCommandAPDU->Lc; if (p_lpCommandAPDU->Lc) { if (!p_lpCommandAPDU->Data) { SetJiBError(g_ResponseAPDU.SW); return &g_ResponseAPDU; } memcpy(g_CmdPacket.CmdData + g_CmdPacket.Len - 3, // CmdData is 3 bytes into structure p_lpCommandAPDU->Data, p_lpCommandAPDU->Lc); g_CmdPacket.Len += p_lpCommandAPDU->Lc; } g_CmdPacket.CmdData[g_CmdPacket.Len++ - 3] = p_lpCommandAPDU->Le; l_Error = SendCiBMessage(portnum, (uchar *)&(g_CmdPacket.Len), (ushort)(g_CmdPacket.Len + 1), (uchar)l_Delay); if (!l_Error) { l_RecvLen = sizeof(g_RetPacket); // Read the devices response l_Error = RecvCiBMessage(portnum, (uchar *)&(g_RetPacket.CSB), &l_RecvLen); if (!l_Error) { // fill in the response APDU if (l_RecvLen >= 5) g_ResponseAPDU.Len = l_RecvLen - 5; // subtract two for SW, three for the header else g_ResponseAPDU.Len = 0; g_ResponseAPDU.Data = g_RetPacket.CmdData; g_ResponseAPDU.SW = ((ushort)(g_RetPacket.CmdData[g_ResponseAPDU.Len]) << 8) + g_RetPacket.CmdData[g_ResponseAPDU.Len + 1]; } } if (!l_Error) { if (!g_RetPacket.CSB) SetJiBError(g_ResponseAPDU.SW); else SetJiBError(g_RetPacket.CSB); } else { g_ResponseAPDU.SW = ERR_COMM_FAILURE; SetJiBError(ERR_COMM_FAILURE); } return &g_ResponseAPDU; } //-------------------------------------------------------------------------- // Sets the Master PIN variable that is sent to the iButton with commands // that require a PIN. This command does not set the iButton's Master PIN. // void SetPIN(LPJIBMASTERPIN p_lpMasterPIN) { if (p_lpMasterPIN) if (p_lpMasterPIN->Len <= MAX_PIN_SIZE) memcpy(&g_MasterPIN, p_lpMasterPIN, sizeof(JIBMASTERPIN)); } //-------------------------------------------------------------------------- // Runs the process method on the selected applet. Valid CLA, INS, P1 and P2 // values are chosen by the applet writer. CLA, INS, P1 and P2 values used // by the API and/or the iButton Command Processor are reserved. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU Process(int portnum, uchar p_CLA, uchar p_INS, uchar p_P1, uchar p_P2, uchar p_Lc, uchar *p_lpData, ushort p_RunTimeMS) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = p_CLA; l_CommandAPDU.INS = p_INS; l_CommandAPDU.P1 = p_P1; l_CommandAPDU.P2 = p_P2; l_CommandAPDU.Lc = p_Lc; l_CommandAPDU.Data = p_lpData; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, p_RunTimeMS); } //-------------------------------------------------------------------------- // Selects an applet to be active on the iButton. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // NOTE: The iButton will return an error if the string is not in the // range 5 to 16 bytes (inclusive). // LPRESPONSEAPDU Select(int portnum, LPAID p_lpAID) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_SELECT; l_CommandAPDU.INS = JIB_APDU_INS_SELECT; l_CommandAPDU.P1 = JIB_APDU_P1_SELECT; l_CommandAPDU.P2 = JIB_APDU_UNUSED; l_CommandAPDU.Lc = p_lpAID->Len; l_CommandAPDU.Data = p_lpAID->Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Issues a master erase of the iButton // @return A ResponseAPDU object containing the response apdu sent by the // iButton. // SW = 0x9000 indicates success. // LPRESPONSEAPDU MasterErase(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 0; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 1); l_CommandAPDU.Data = (uchar *)&g_MasterPIN; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // @return A ResponseAPDU that contains the amount of free RAM. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetFreeRam(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 1; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // @return A ResponseAPDU that contains the amount of free RAM. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetFreeRamPerBank(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_STATS; l_CommandAPDU.P2 = 1; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // @return A ResponseAPDU containing the Firmware Version String. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetFirmwareVersionString(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Reads the ephemeral garbage collection mode. // @return The ResponseAPDU containing the value of the ephemeral garbage // Collector. A value of 1 indicates the garbage collector is // turned on. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetEphemeralGCMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 2; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the mode of the ephemeral garbage collector. Setting the mode to // 1 turns the collector on, setting it to 0 turns the collector off. // If the iButton is password protected, setPIN() should be called before // invoking this method. // Parameter: p_Mode 1 - turn the collector on, // 0 - turn the collector off. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetEphemeralGCMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 2; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Reads the applet garbage collection mode. // @return The ResponseAPDU containing the mode of the applet garbage // Collector. A value of 1 indicates the garbage collector is // turned on. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetAppletGCMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 3; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the mode of the applet garbage collector. Setting the mode to 1 // turns the collector on, setting it to 0 turns the collector off. // If the iButton is password protected, setPIN() should be called before // invoking this method. // Parameter: p_Mode 1 - turn the collector on, // 0 - turn the collector off. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetAppletGCMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 3; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Returns the mode of the CommandPIN. If a value of 1 is returned by // the iButton, PINs are required to perform all Admistrative commands. // @return The ResponseAPDU containing the mode of the CommandPIN. // A value of 1 indicates a PIN is required for all Administrative // commands. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetCommandPINMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 4; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the mode of the CommandPIN. Setting the mode to 1 indicates the // the iButton should require a PIN for all Administrative commands. // Parameter: p_Mode 1 - set the CommandPIN mode to require a PIN for // all Administrative commands. // 0 - set the CommandPIN mode to not require a PIN // for Administrative commands. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetCommandPINMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 4; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Returns the mode of the LoadPIN. If a value of 1 is returned by the // iButton, PINs are required to load applets. // @return The ResponseAPDU containing the mode of the LoadPIN. // A value of 1 indicates a PIN is required for loading applets // into the iButton. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetLoadPINMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 5; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the mode of the LoadPIN. Setting the mode to 1 indicates the // iButton should require a PIN for all applets loads. // Parameter: p_Mode 1 - set the LoadPIN mode to require a PIN for applet // load. // 0 - set the LoadPIN mode to not require a PIN for // applet load. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetLoadPINMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 5; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // @return The ResponseAPDU containing the restore mode. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetRestoreMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 6; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Setting the mode to 1 enables restoration of fields to previous values // if a transaction was interrupted. // Parameter: p_Mode 1 - Allow restoration. // 0 - Do not allow restoration. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetRestoreMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 6; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Gets the Exception mode of the iButton. If the mode is 1, then VM // exceptions are thrown. If the mode is 0, then VM exceptions are not // thrown. // @return The ResponseAPDU containing the Exception mode. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetExceptionMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 7; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the Exception mode of the iButton. If the mode is 1, then VM // exceptions are thrown. If the mode is 0, then VM exceptions are not // thrown. // Parameter: p_Mode 1 - set the Exception mode to allow VM thrown // exceptions. // 0 - set the Exception mode to not allow the VM to // throw exceptions. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetExceptionMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 7; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Gets the ISOException mode of the iButton. If the mode is 1, // ISOExceptions are handled differently from all other exceptions. // Instead of returning 0x6f00 for an uncaught ISOException, the reason is // returned in the SW. If the mode is 0, ISOExceptions are handled like // all other exceptions. // @return The ResponseAPDU containing the ISOException mode. // SW = 0x9000 indicates success. // NOTE: Requires Firmware Version 1.00 or greater. // LPRESPONSEAPDU GetISOExceptionMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 8; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the ISOException mode of the iButton. If the mode is 1, // ISOExceptions are handled differently from all other exceptions. // Instead of returning 0x6f00 for an uncaught ISOException, the reason is // returned in the SW. If the mode is 0, ISOExceptions are handled like // all other exceptions. // Parameter: p_Mode 1 - set the ISOException mode. // 0 - clear the ISOException mode. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // NOTE: Requires Firmware Version 1.00 or greater. // LPRESPONSEAPDU SetISOExceptionMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 8; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Gets the Error Reporting mode of the iButton. If the mode is 1, // GetLastJCREError will return the error byte indicating the reason for // the last "Java Card Runtime Environment" thrown error. // @return The ResponseAPDU containing the Error Reporting mode. // SW = 0x9000 indicates success. // NOTE: Requires Firmware Version 1.00 or greater. // LPRESPONSEAPDU GetErrorReportMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 9; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the Error Report mode of the iButton. If the mode is 1, // GetLastJCREError will return the error byte indicating the reason for // the last "Java Card Runtime Environment" thrown error. // Parameter: p_Mode 1 - set the Error Report mode to. // 0 - set the Error Report mode to. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // NOTE: Requires Firmware Version 1.00 or greater. // LPRESPONSEAPDU SetErrorReportMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 9; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Gets the size of the iButton's Commit Buffer. // @return The ResponseAPDU containing the size of the iButton's commit // buffer in bytes. The ResponseAPDU's data field will contain two // bytes representing the size (short). // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetCommitBufferSize(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x0A; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Gets the number of fields in the iButton's Commit Buffer. // @return The ResponseAPDU containing the size of the iButton's commit // buffer in number of fields. The ResponseAPDU's data field will // contain two bytes representing the size (short). // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetCommitBufferFields(int portnum) { LPRESPONSEAPDU l_lpResponseAPDU; short l_BufferSize; l_lpResponseAPDU = GetCommitBufferSize(portnum); if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) return l_lpResponseAPDU; l_BufferSize = ((short)l_lpResponseAPDU->Data[0] & 0xff) + ((short)l_lpResponseAPDU->Data[1] << 8); l_BufferSize /= COMMIT_BUFFER_BYTES_PER_FIELD; l_lpResponseAPDU->Data[0] = (uchar)(l_BufferSize & 0xff); l_lpResponseAPDU->Data[1] = (uchar)(l_BufferSize >> 8); return l_lpResponseAPDU; } //-------------------------------------------------------------------------- // Sets the iButtons CommitBufferSize. The value passed in is rounded up // by the iButton to the nearest multiple of COMMIT_BUFFER_ucharS_PER_FIELD. // Parameter: p_SizeInBytes the new size of the commit buffer in bytes. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetCommitBufferSize(int portnum, short p_SizeInBytes) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 0x0A; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 3); // PIN Length + PIN Data + size l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = (uchar)(p_SizeInBytes & 0xff); l_Data[g_MasterPIN.Len + 2] = (uchar)(p_SizeInBytes >> 8); return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Calculates the number of bytes that is needed to store p_NumberOfFields // fields in the commit buffer and resizes the buffer accordingly. // Parameter: p_NumberOfFields - the new size of the commit buffer using // number of fields. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetCommitBufferFields(int portnum, short p_NumberOfFields) { LPRESPONSEAPDU l_lpResponseAPDU; short l_BufferSize; l_BufferSize = p_NumberOfFields * COMMIT_BUFFER_BYTES_PER_FIELD; l_lpResponseAPDU = SetCommitBufferSize(portnum, l_BufferSize); return l_lpResponseAPDU; } //-------------------------------------------------------------------------- // Reads the Answer to Reset from the iButton, as defined in ISO7816-5 // @return Response APDU that contains the iButton's ATR. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetATR(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x0B; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Reads the Real Time Clock of the iButton. // @return The ResponseAPDU containing the value of the Real Time Clock. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetRealTimeClock(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x0C; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Reads random bytes from the iButton. The maximum number of bytes that // can be reads is MAX_RECEIVE - APDU overhead. // Parameter: p_NumBytes - the number of random bytes to read from the // iButton. // @return Response APDU that contains the requested number of random // bytes. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetRandomBytes(int portnum, short p_NumBytes) { uchar l_Data[2]; uchar l_RecvData[MAX_RECEIVE]; uchar *l_Offset = l_RecvData; COMMANDAPDU l_CommandAPDU; LPRESPONSEAPDU l_lpResponseAPDU; short l_NumBytes = p_NumBytes; // .03 Bug workaround if (!p_NumBytes) { g_ResponseAPDU.Len = 0; g_ResponseAPDU.SW = ERR_ISO_NORMAL_00; return &g_ResponseAPDU; } if (p_NumBytes > (MAX_RECEIVE - (sizeof(RESPONSEAPDU) - sizeof(uchar *)))) { g_ResponseAPDU.Len = 0; g_ResponseAPDU.SW = ERR_API_INVALID_PARAMETER; return &g_ResponseAPDU; } l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x0D; l_CommandAPDU.Lc = 2; l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; // can only generate 110 bytes per APDU while (l_NumBytes > 110) { l_Data[0] = (uchar)120; l_Data[1] = (uchar)0; l_lpResponseAPDU = SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) return l_lpResponseAPDU; memcpy(l_Offset, l_lpResponseAPDU->Data, 120); l_Offset += 120; l_NumBytes -= 120; } l_Data[0] = (uchar)(l_NumBytes & 0xff); l_Data[1] = (uchar)(l_NumBytes >> 8); l_lpResponseAPDU = SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) return l_lpResponseAPDU; if (p_NumBytes > 120) { memcpy(l_Offset, l_lpResponseAPDU->Data, l_NumBytes); memcpy(l_lpResponseAPDU->Data, l_RecvData, p_NumBytes); l_lpResponseAPDU->Len = (ushort)p_NumBytes; } return l_lpResponseAPDU; } //-------------------------------------------------------------------------- // Returns the AID of the applet with the given number. Each applet stored // on the iButton is assigned a number(0 - 15). A directory structure of // applets on an iButton can be built by calling this method iteratively // with parameter values from 0 to 15. // NOTE: - AIDs are not guaranteed to be stored in contiguous locations. // Therefore an exaustive search through all numbers 0 - 15 is // required to enumerate all applets on the iButton. // - Version 32 and below used 2 bytes for the AID length. Later // versions use 1 byte. // Parameter: p_AIDNum - the number of the applet to retrieve the AID. // @return Response APDU containing the AID of the applet requested. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetAIDByNumber(int portnum, uchar p_AIDNum) { COMMANDAPDU l_CommandAPDU; LPRESPONSEAPDU l_lpResponseAPDU; uchar l_Buff[21]; // max AID length +Java Array length + SW length l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x0E; l_CommandAPDU.Lc = 1; l_CommandAPDU.Data = &p_AIDNum; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; l_lpResponseAPDU = SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); if (l_lpResponseAPDU) { if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { // .03 firmware bug workaround if (l_lpResponseAPDU->SW != 0x8453) { // AID not found SW if (l_lpResponseAPDU->Data) { // remove Java array length memcpy(l_Buff, l_lpResponseAPDU->Data, 0x12); l_lpResponseAPDU->Data[0] = l_Buff[0]; memcpy(l_lpResponseAPDU->Data + 1, l_Buff + 2, 0x10); // now set the correct length l_lpResponseAPDU->Len = (ushort)l_Buff[0] + 1; // insert the happy response l_lpResponseAPDU->SW = ERR_ISO_NORMAL_00; } else { // data not valid l_lpResponseAPDU->Len = 0; // insert the unhappy response l_lpResponseAPDU->SW = ERR_COMM_FAILURE; } } } else l_lpResponseAPDU->Len = (ushort)l_lpResponseAPDU->Data[0] + 1; } return l_lpResponseAPDU; } //-------------------------------------------------------------------------- // If Error Reporting Mode is enabled, the error byte indicating the reason // for the last JCRE thrown error is returned. Otherwise an error is // returned in the SW (see: GetErrorReportMode,SetErrorReportMode). // @return The ResponseAPDU containing the Error Reporting mode. // SW = 0x9000 indicates success. // NOTE: Requires Firmware Version 1.00 or greater. // LPRESPONSEAPDU GetLastJCREError(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x0F; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // // @return . // NOTE: Requires Firmware Version 1.10 or greater. // LPRESPONSEAPDU GetAllAIDs(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x10; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // // @return . // NOTE: Requires Firmware Version 1.10 or greater. // LPRESPONSEAPDU GetActivationTimeRemaining(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x11; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // // @return . // NOTE: Requires Firmware Version 1.10 or greater. // LPRESPONSEAPDU GetVerifyLoadWithIdMode(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_INFO; l_CommandAPDU.P2 = 0x12; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // // @return . // NOTE: Requires Firmware Version 1.10 or greater. // LPRESPONSEAPDU SetVerifyLoadWithIdMode(int portnum, uchar p_Mode) { uchar l_Data[32]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 0x12; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); // PIN Length + PIN Data + Mode Byte l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_Mode; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Gets the number of Power On Resets the device has experienced since the // last master erase. // @return Response APDU containing the number of POR since the last // master erase. // SW = 0x9000 indicates success. // LPRESPONSEAPDU GetPORCount(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_STATS; l_CommandAPDU.P2 = 0; l_CommandAPDU.Lc = 0; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Sets the master PIN of the iButton. A call to SetPIN with the old PIN // is required before this method can be called. The PIN to be set is // passed in. // Parameter: p_lpNewMasterPin the new PIN for the iButton // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU SetMasterPIN(int portnum, LPJIBMASTERPIN p_lpNewMasterPin) { uchar l_Data[2 * (MAX_PIN_SIZE + 1)]; COMMANDAPDU l_CommandAPDU; LPRESPONSEAPDU l_lpResponseAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_ADMIN; l_CommandAPDU.P2 = 1; // PIN Length + PIN Data + PIN Length + PIN Data l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + p_lpNewMasterPin->Len + 2); l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; // copy current PIN memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); // copy new PIN memcpy(l_Data + g_MasterPIN.Len + 1, p_lpNewMasterPin, p_lpNewMasterPin->Len + 1); l_lpResponseAPDU = SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); // go ahead and set the local PIN if the command succeeded if (l_lpResponseAPDU->SW == (ushort)0x9000) SetPIN(p_lpNewMasterPin); return l_lpResponseAPDU; } //-------------------------------------------------------------------------- // Deletes the currently selected Applet. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU DeleteSelectedApplet(int portnum) { COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_AID; l_CommandAPDU.P2 = 0; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 1); l_CommandAPDU.Data = (uchar *)&g_MasterPIN; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Deletes Applet number p_AppletNumber. // Parameter: p_AppletNumber - number of the applet to be deleted. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU DeleteAppletByNumber(int portnum, uchar p_AppletNumber) { uchar l_Data[MAX_PIN_SIZE + 2]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_AID; l_CommandAPDU.P2 = 1; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + 2); l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); l_Data[g_MasterPIN.Len + 1] = p_AppletNumber; return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Deletes the Applet with AID p_lpAID. // Parameter: p_lpAID - AID of the applet to be deleted. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU DeleteAppletByAID(int portnum, LPAID p_lpAID) { uchar l_Data[MAX_PIN_SIZE + MAX_AID_SIZE + 2]; COMMANDAPDU l_CommandAPDU; l_CommandAPDU.CLA = JIB_APDU_CLA_COMMAND_PROC; l_CommandAPDU.INS = JIB_APDU_INS_COMMAND_PROC; l_CommandAPDU.P1 = JIB_APDU_P1_COMMAND_AID; l_CommandAPDU.P2 = 2; l_CommandAPDU.Lc = (uchar)(g_MasterPIN.Len + p_lpAID->Len + 2); l_CommandAPDU.Data = l_Data; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; memcpy(l_Data, (uchar *)&g_MasterPIN, g_MasterPIN.Len + 1); memcpy(l_Data + g_MasterPIN.Len + 1, p_lpAID, p_lpAID->Len + 1); return SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } //-------------------------------------------------------------------------- // Loads the applet stored in p_lpAppletBuffer. // Parameter: p_lpAppletBuffer - Buffer containing the applet (ASSUMPTION: // Buffer was previously loaded with the // contents of a .JiB "dot JiB" file). // p_AppletLen - Length of the applet in the buffer. // p_lpAID - Pointer the the applet's AID. // @return The ResponseAPDU containing the Status Word of the response. // SW = 0x9000 indicates success. // LPRESPONSEAPDU LoadApplet(int portnum, uchar *p_lpAppletBuffer, uint p_AppletLen, LPAID p_lpAID) { uchar *l_lpData, *l_lpOffset; COMMANDAPDU l_CommandAPDU; LPRESPONSEAPDU l_lpResponseAPDU; uint l_BufferSize = p_AppletLen + sizeof(AID) + sizeof(JIBMASTERPIN); uint l_PacketSize; // make sure AID length fits if (p_lpAID->Len > MAX_AID_SIZE) { g_ResponseAPDU.Len = 0; g_ResponseAPDU.SW = ERR_API_INVALID_PARAMETER; return &g_ResponseAPDU; } if (!(l_lpOffset = (l_lpData = malloc(l_BufferSize)))) { g_ResponseAPDU.Len = 0; g_ResponseAPDU.SW = ERR_API_MEMORY_ALLOCATION; return &g_ResponseAPDU; } memset(l_lpData, 0, l_BufferSize); // copy the master pin first memcpy(l_lpOffset, (uchar *)&g_MasterPIN, sizeof(g_MasterPIN)); l_lpOffset += sizeof(g_MasterPIN); l_PacketSize = sizeof(g_MasterPIN); // copy the AID memcpy(l_lpOffset, (uchar *)p_lpAID, p_lpAID->Len + 1); memset(l_lpOffset + p_lpAID->Len + 1, 0, sizeof(AID) - (p_lpAID->Len + 1)); l_lpOffset += sizeof(AID); l_PacketSize += sizeof(AID); // copy the applet memcpy(l_lpOffset, p_lpAppletBuffer, p_AppletLen); l_PacketSize += p_AppletLen; l_lpOffset = l_lpData; l_CommandAPDU.CLA = JIB_APDU_CLA_LOAD_APPLET; l_CommandAPDU.INS = JIB_APDU_INS_LOAD_APPLET; l_CommandAPDU.P1 = JIB_APDU_P1_LOAD_APPLET; l_CommandAPDU.P2 = JIB_APDU_UNUSED; l_CommandAPDU.Lc = (uchar)((l_PacketSize > MAX_APDU_SIZE) ? MAX_APDU_SIZE : l_PacketSize); l_CommandAPDU.Data = l_lpOffset; l_CommandAPDU.Le = JIB_APDU_LE_DEFAULT; l_lpResponseAPDU = SendAPDU(portnum, &l_CommandAPDU, (ushort)((l_CommandAPDU.Lc == MAX_APDU_SIZE) ? 64 : g_ExecTimeMS)); if ((l_lpResponseAPDU->SW == ERR_ISO_NORMAL_00) || (l_lpResponseAPDU->SW != ERR_NEXT_LOAD_PACKET_EXPECTED)) { free(l_lpData); return l_lpResponseAPDU; } l_lpOffset += MAX_APDU_SIZE; l_PacketSize -= MAX_APDU_SIZE; l_CommandAPDU.P1 = JIB_APDU_P1_CONTINUE_LOAD; while (l_PacketSize > MAX_APDU_SIZE) { l_CommandAPDU.Data = l_lpOffset; l_lpResponseAPDU = SendAPDU(portnum, &l_CommandAPDU, (ushort)((l_lpResponseAPDU->SW == ERR_NEXT_LOAD_PACKET_EXPECTED) ? 64 : g_ExecTimeMS)); l_lpOffset += MAX_APDU_SIZE; l_PacketSize -= MAX_APDU_SIZE; if ((l_lpResponseAPDU->SW == ERR_ISO_NORMAL_00) || (l_lpResponseAPDU->SW != ERR_NEXT_LOAD_PACKET_EXPECTED)) break; } if (l_PacketSize) { l_CommandAPDU.Lc = (uchar)l_PacketSize; l_CommandAPDU.Data = l_lpOffset; l_lpResponseAPDU = SendAPDU(portnum, &l_CommandAPDU, g_ExecTimeMS); } free(l_lpData); return l_lpResponseAPDU; } //-------------------------------------------------------------------------- // // Set new error code. // void SetJiBError(ushort p_Error) { g_LastError = g_ResponseAPDU.SW = p_Error; } //-------------------------------------------------------------------------- // // Get error code. // ushort GetJiBError() { return g_LastError; } w1retap/src/libusblinux300/jib96.h000066400000000000000000000233531446446235200171270ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // #include "ownet.h" #include #define MAX_SEND 255 // Maximum send buffer size #define MAX_RECEIVE 2048 // Maximum receive buffer size #define MAX_JIB_NUM 16 // Maximum number of CiBs on system #define MAX_BUF_SIZE 256 #define MAX_PIN_SIZE 8 #define MAX_AID_SIZE 16 // maximum data bytes that can be sent in a single packet #define MAX_APDU_SIZE 114 #define JIB_APDU_CLA_COMMAND_PROC (uchar)0xd0 #define JIB_APDU_CLA_LOAD_APPLET (uchar)0xd0 #define JIB_APDU_CLA_SELECT (uchar)0x00 #define JIB_APDU_INS_COMMAND_PROC (uchar)0x95 #define JIB_APDU_INS_LOAD_APPLET (uchar)0xa6 #define JIB_APDU_INS_SELECT (uchar)0xa4 #define JIB_APDU_P1_LOAD_APPLET (uchar)0x01 #define JIB_APDU_P1_CONTINUE_LOAD (uchar)0x02 #define JIB_APDU_P1_SELECT (uchar)0x04 #define JIB_APDU_P1_COMMAND_ADMIN (uchar)0x00 #define JIB_APDU_P1_COMMAND_INFO (uchar)0x01 #define JIB_APDU_P1_COMMAND_STATS (uchar)0x02 #define JIB_APDU_P1_COMMAND_AID (uchar)0x03 #define JIB_APDU_LE_DEFAULT (uchar)0x00 #define JIB_APDU_UNUSED (uchar)0x00 // API communication error codes #define ERR_NO_JIBS_FOUND 0xF000 #define ERR_BAD_JIB_ROM 0xF100 #define ERR_JIB_NOT_FOUND 0xF200 #define ERR_ADAPTER_NOT_FOUND 0xF300 #define ERR_COMM_FAILURE 0xF400 // General API Errors #define ERR_API_INVALID_PARAMETER 0xFA00 #define ERR_API_MEMORY_ALLOCATION 0xFA01 // ISO Errors & JiB Errors #define ERR_ISO_NORMAL_00 0x9000 #define ERR_NEXT_LOAD_PACKET_EXPECTED 0x6301 #define COMMIT_BUFFER_BYTES_PER_FIELD 0x09 //--------------------------------------------------------------------------- // For the current CIB implementation, the maximum outbound or inbound // message size is 128 bytes, and the header (FIFO) data is always 8 bytes // long for all transactions. #define SEGSIZE 128 // Max seg size that we can send to the device #define HEADERSIZE 8 // Size of a comm layer header packet #define CIB_FC 0x16 #define MAX_CIB_NUM 16 #define FIFO_LEN 8 // Communications Layer OWMS Status Codes - #define CE_RESET 0 #define CE_MSGINCOMP 1 #define CE_BADSEQ 2 #define CE_BUFOVERRUN 3 #define CE_BADCKSUM 4 #define CE_HDRSIZE 5 #define CE_DATASIZE 6 #define CE_BADCRC 7 #define CE_DURATION 8 #define CE_FIFONOTEMPTY 9 #define CE_STANDBY 10 #define CE_RESPONSERDY 11 #define CE_RESPINCOMP 12 #define CE_NOHEADER 13 #define CE_MESSAGEOK 15 #define CE_FIRSTBIRTH 29 #define CE_CIREEXEC 30 #define CE_CMDINCOMP 31 #define CE_BPOR 0x40 // Buferred POR bit in OWMS status byte // Function Error Return Codes #define ER_NOROOM 2 // No room in outbound FIFO for a message header #define ER_POR 3 // Constant POR status from device #define ER_ACCESS 4 // Error trying to access device #define ER_COLLIDE 5 // One-Wire Collision Error #define ER_ACK 6 // Failure to get device acknowledge bit #define ER_CRC 7 // CRC test failed #define ER_CHECKSUM 8 // Checksum test failed #define ER_NOHEADER 9 // No header found (no message to read) #define ER_BADHEADER 10 // Bad header form or length #define ER_HDRCRC 11 // Header crc does not match data segment crc #define ER_SEQUENCE 12 // Segments arrived out of sequence or missing #define ER_OVERRUN 13 // Inbound message overflowed buffer limit #define ER_COPRUN 14 // Co-Processor Will Not Complete #define ER_RERUN 15 // Prior command will not complete #define ER_ADAPTER 16 // Bad adapter selection // Error Group Codes #define ER_SENDDATA 0x10 // Error in sending segment data #define ER_SENDHDR 0x20 // Error in sending a segment header #define ER_GETSTATUS 0X30 // Error in geting status #define ER_SENDSTATUS 0x40 // Error in sending status command #define ER_SENDRUN 0x50 // Error in sending run command #define ER_SENDRESET 0x60 // Error in sending reset command #define ER_SENDINT 0x70 // Error in sending interrupt command #define ER_RECVHDR 0x80 // Error in unload of segment header #define ER_RECVDATA 0x90 // Error in unload of segment data #define ER_COMMERROR 0xA0 // Comm Error response from device // One-Wire Command Codes - #define OW_MICRORUN 0x87 #define OW_MICROINTERRUPT 0x77 #define OW_MICRORESET 0xDD #define OW_STATUSREAD 0xE1 #define OW_STATUSWRITE 0xD2 #define OW_IPRREAD 0xAA #define OW_IPRWRITE 0x0F #define OW_FIFOREAD 0x22 #define OW_FIFOWRITE 0x2D // CiB One-Wire Release sequence values - #define RS_MICRORUN 0x5D73 #define RS_MICROINTERRUPT 0x6D43 #define RS_MICRORESET 0x92BC #define RS_STATUSWRITE 0x517F #define RS_FIFOREAD 0x624C #define RS_FIFOWRITE 0x9DB3 #define LSB(a) (uchar)((a)&0xFF) #define MSB(a) (uchar)(((a)&0xFF00) >> 8) //--------------------------------------------------------------------------- // Structure definitions // typedef struct _FIFORDWR { uchar Cmd; uchar Len; uchar FIFOBuf[8]; } FIFORDWR; typedef struct _CMDPACKET { uchar Len; uchar CmdByte; uchar GroupID; uchar CmdData[MAX_SEND]; } CMDPACKET; // Firmware return packet typedef struct _RETPACKET { uchar CSB; uchar GroupID; uchar DataLen; uchar CmdData[MAX_RECEIVE]; } RETPACKET; // Command APDU typedef struct _COMMANDAPDU { uchar Header[4]; uchar Lc; uchar *Data; uchar Le; } COMMANDAPDU, *LPCOMMANDAPDU; // Field access defines #define CLA Header[0] #define INS Header[1] #define P1 Header[2] #define P2 Header[3] // Response APDU typedef struct _RESPONSEAPDU { ushort Len; uchar *Data; ushort SW; } RESPONSEAPDU, *LPRESPONSEAPDU; // iButton Master PIN typedef struct _JIBMASTERPIN { uchar Len; uchar Data[MAX_PIN_SIZE]; } JIBMASTERPIN, *LPJIBMASTERPIN; // Applet AID typedef struct _AID { uchar Len; uchar Data[MAX_AID_SIZE]; } AID, *LPAID; // API Commands #ifdef __cplusplus extern "C" { #endif // raw communication functions ushort SendCiBMessage(int portnum, uchar *mp, ushort mlen, uchar ExecTime); ushort RecvCiBMessage(int portnum, uchar *mp, ushort *bufsize); void SetMinRunTime(ushort MR); // device specific functions void SetDefaultExecTime(ushort p_ExecTimeMS); LPRESPONSEAPDU SendAPDU(int portnum, LPCOMMANDAPDU p_lpCommandAPDU, ushort p_ExecTimeMS); void SetPIN(LPJIBMASTERPIN p_lpMasterPIN); LPRESPONSEAPDU Process(int portnum, uchar p_CLA, uchar p_INS, uchar p_P1, uchar p_P2, uchar p_Lc, uchar *p_lpData, ushort p_RunTimeMS); LPRESPONSEAPDU Select(int portnum, LPAID p_lpAID); LPRESPONSEAPDU MasterErase(int portnum); LPRESPONSEAPDU GetFreeRam(int portnum); LPRESPONSEAPDU GetFreeRamPerBank(int portnum); LPRESPONSEAPDU GetFirmwareVersionString(int portnum); LPRESPONSEAPDU GetEphemeralGCMode(int portnum); LPRESPONSEAPDU SetEphemeralGCMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetAppletGCMode(int portnum); LPRESPONSEAPDU SetAppletGCMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetCommandPINMode(int portnum); LPRESPONSEAPDU SetCommandPINMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetLoadPINMode(int portnum); LPRESPONSEAPDU SetLoadPINMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetRestoreMode(int portnum); LPRESPONSEAPDU SetRestoreMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetExceptionMode(int portnum); LPRESPONSEAPDU SetExceptionMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetISOExceptionMode(int portnum); LPRESPONSEAPDU SetISOExceptionMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetErrorReportMode(int portnum); LPRESPONSEAPDU SetErrorReportMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetCommitBufferSize(int portnum); LPRESPONSEAPDU GetCommitBufferFields(int portnum); LPRESPONSEAPDU SetCommitBufferSize(int portnum, short p_SizeInBytes); LPRESPONSEAPDU SetCommitBufferFields(int portnum, short p_NumberOfFields); LPRESPONSEAPDU GetATR(int portnum); LPRESPONSEAPDU GetRealTimeClock(int portnum); LPRESPONSEAPDU GetRandomBytes(int portnum, short p_NumBytes); LPRESPONSEAPDU GetAIDByNumber(int portnum, uchar p_AIDNum); LPRESPONSEAPDU GetLastJCREError(int portnum); LPRESPONSEAPDU GetAllAIDs(int portnum); LPRESPONSEAPDU GetActivationTimeRemaining(int portnum); LPRESPONSEAPDU GetVerifyLoadWithIdMode(int portnum); LPRESPONSEAPDU SetVerifyLoadWithIdMode(int portnum, uchar p_Mode); LPRESPONSEAPDU GetPORCount(int portnum); LPRESPONSEAPDU SetMasterPIN(int portnum, LPJIBMASTERPIN p_lpNewMasterPin); LPRESPONSEAPDU DeleteSelectedApplet(int portnum); LPRESPONSEAPDU DeleteAppletByNumber(int portnum, uchar p_AppletNumber); LPRESPONSEAPDU DeleteAppletByAID(int portnum, LPAID p_lpAID); LPRESPONSEAPDU LoadApplet(int portnum, uchar *p_lpAppletBuffer, uint p_AppletLen, LPAID p_lpAID); void SetJiBError(ushort p_Error); ushort GetJiBError(); #ifdef __cplusplus } #endif w1retap/src/libusblinux300/jib96o.c000066400000000000000000001126051446446235200173000ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // Module Name: JibComm // // Description: Low-level Java-Powered iButton Communication // // Filename: jib96o.c // // Dependant Files: jib96.h // // Version: 1.00 (based on cibcomm.c Ver 2.206) // // #include "ownet.h" #include "jib96.h" // defines #define STREAM_OVERHEAD 4 #define ME_RUNTIME 12 #define SLEEP_PAD 6 // exportable functions // ushort SendCiBMessage(int, uchar *, ushort, uchar); // ushort RecvCiBMessage(int, uchar *, ushort *); // void SetMinRunTime(ushort); // local functions static uchar SendSegment(int, uchar *, uchar *, ushort, ushort *); static uchar SendData(int, uchar *, uchar, ushort *); static uchar SendHeader(int, uchar, uchar *, ushort, uchar, ushort *); static uchar GetStatus(int, uchar *, uchar *, uchar *, uchar *); static uchar SendStatus(int, uchar); static uchar SendRun(int); static uchar SendReset(int); static uchar SendInterrupt(int); static uchar RecvHeader(int, uchar *, ushort *, ushort *, uchar *, ushort *); static uchar RecvData(int, uchar *, uchar, ushort, ushort *, uchar); static uchar ReleaseSequence(int, ushort); static uchar CheckCRC(int, ushort); static uchar CheckStreamCRC(uchar *, int, ushort); static void TimeDelay(int, uchar); static ushort CRC16TGen(uchar, ushort); static void GenCRC16Table(); static ushort CRC16(uchar, ushort); static ushort CRC16Buf(uchar *, ushort, ushort); static void GenCRC16CorrectionTable(); static ushort GetCRC16Correction(uchar); // globals static ushort MinRun = 96; static int StreamLen = 0; static uchar StreamBuff[256 + STREAM_OVERHEAD]; static uchar LastSegment = FALSE; static ushort CRCTable[256]; static ushort CRCCorrectionTable[140]; static uchar PowerOn = FALSE; static uchar didsetup = FALSE; //-------------------------------------------------------------------------- // // Top-Level function to send a message to the CiB // // portnum = port number the device is on // mp = Pointer to message string // mlen = Length of message (bytes) // ExecTime = Estimated execution time (0-15, where 0 = minimum) // // return = Error code, or zero if all went well // ushort SendCiBMessage(int portnum, uchar *mp, ushort mlen, uchar ExecTime) { uchar ETime; // Temp value for ExecTime uchar Retry; // Retry counter uchar seg; // Current segment number uchar InFree; // Inbound FIFO bytes available uchar OutUsed; // Outbound FIFO bytes used uchar owms; // micro status uchar cpst; // Co-Processor status ushort checksum = 0; // checksum accumulator ushort sum = 0; // Temporary checksum store uchar error; // check for setup if (!didsetup) { didsetup = TRUE; GenCRC16Table(); GenCRC16CorrectionTable(); } seg = 127; // Start with no segment number done ExecTime &= 0xFF; ETime = (uchar)ExecTime; // Set-up a Retry loop for (Retry = 0; Retry < 3; Retry++) { while (1) { // Get the status from the device if ((error = GetStatus(portnum, &InFree, &OutUsed, &owms, &cpst)) != 0) break; // See if a POR has occurred and treat it as an error if so if (owms & CE_BPOR) { error = ER_POR; break; } // See if the co-processor was running when we stopped if (cpst & 1) { // Send the time value to the CIB if ((error = SendStatus(portnum, ETime)) != 0) break; // Execute the co-processor and allow it to finish up if ((error = SendRun(portnum)) != 0) break; TimeDelay(portnum, (uchar)(ETime + SLEEP_PAD)); } else { // If the co-processor is not running, then // Work around for 0 owms if (!(owms & 0x7f) && !OutUsed) owms = 0x3F; // See if the previous command has not yet been completed if ((owms & 0x20) || ((owms & 0x1F) == CE_FIRSTBIRTH) || (owms == 0x1F)) { // If Operation does not finish double previous time until 8 // then increment by one until max time (15 = 3.75 s +64 ms) 9/25 CIM if (ETime == 0) ETime++; else if (ETime < 8) ETime <<= 1; else if ((ETime >= 8) && (ETime < 15)) ETime++; else ETime = 15; // if we don't allow a First Birthday (FB) to complete // we can end up in an infinite POR loop - FBs // currently take on the order of 1.5 Seconds if ((owms & 0x1F) == CE_FIRSTBIRTH) { // Send the time value to the CIB if ((error = SendStatus(portnum, ME_RUNTIME)) != 0) break; } else { // Send the time value to the CIB if ((error = SendStatus(portnum, ETime)) != 0) break; } // Execute the micro and allow it to finish up if ((error = SendRun(portnum)) != 0) break; if ((owms & 0x1F) == CE_FIRSTBIRTH) { TimeDelay(portnum, ME_RUNTIME); TimeDelay(portnum, 1); } else { // Wait for whatever we did above to finish up // don't forget the extra pad for the coprocessor alarm TimeDelay(portnum, (uchar)(ETime + SLEEP_PAD)); } } else { // See if the device has room for new command. Error if not if (InFree < HEADERSIZE) { error = ER_NOROOM; break; } // If the segment we're about to send is not the FIRST one, // check the status to see if we had any comm errors on the last // (Errors left over from prior uses don't concern us!) if (seg != 127) { if (((owms & 31) > 1) & ((owms & 31) < 8)) { error = (uchar)((owms & 31) | ER_COMMERROR); break; } } // If the segment number MS bit = 1, then we're done if (seg & 128) { // Successful exit return 0; } // When we have finished a segment, go to the next segment seg++; seg = (uchar)(seg & 127); // If about to send First segment, clear checksum accumulator checksum = seg ? checksum + sum : 0; // For each new segment that we attempt to send out, we start a // temporary checksum in 'sum' with the current checksum value. // If the segment transfer fails, we will not have added // anything to the actual checksum so we can try again sum = checksum; // Send out the next segment if ((error = SendSegment(portnum, &seg, mp, mlen, &sum)) != 0) break; // Now we have loaded the data segment into IPR register and // the header for it into the FIFO. Next set the execution time // if it's the last message segment, and the execute the message if (seg & 128) { ETime = (uchar)ExecTime; if ((error = SendStatus(portnum, ETime)) != 0) break; } else ETime = 0; // Send the run-interrupt command to the device if ((error = SendInterrupt(portnum)) != 0) break; } TimeDelay(portnum, ETime); } } // End of forever loop // Save the error cause ETime = error; // If we had an error and broke out of the loop, reset the micro if ((error = SendReset(portnum)) != 0) break; // Send the time value to the CIB if ((error = SendStatus(portnum, (uchar)(Retry ? (Retry << 1) : 1))) != 0) break; // Then allow it to run and report a completion status if ((error = SendRun(portnum)) != 0) break; // See if a little run time will cure the problem that caused the reset TimeDelay(portnum, (uchar)((Retry ? (Retry << 1) : 1) + SLEEP_PAD)); // We always begin again at the start (segment 0) after an error seg = 127; // Restore the original error cause code error = ETime; } // End of Retry loop // Error-return if we failed all the retries return error; } //-------------------------------------------------------------------------- // // Send out one (specific) segment of the message to the device // // portnum = port number the device is on // pseg = Pointer to current segment number (0 = First) // mp = Pointer to message string // msglen = Length of message string (bytes) // psum = Pointer to checksum accumulator // // return = Error code, or zero if all went well // uchar SendSegment(int portnum, uchar *pseg, uchar *mp, ushort msglen, ushort *psum) { uchar seglen; // Length of segment we're sending ushort indexx; // Offset of segment we're sending uchar remain; // Bytes remaining before this seg uchar *segstart; // Start of segment in message uchar error; // Offset of next segment to send indexx = (ushort)(*pseg * SEGSIZE); // Computer how much data remains unsent to the device remain = (uchar)(msglen - indexx); // Length of segment remaining send // Limit the segment size to that which is allowed in this device if (remain > SEGSIZE) { // If remain is bigger than max, send max seglen = SEGSIZE; } else { // If remain will fit, wrap it up seglen = remain; // Flag this as the last segment *pseg |= 128; } // Define the point in the message where this segment begins segstart = mp + indexx; // Send out the segment data to the device if ((error = SendData(portnum, segstart, seglen, psum)) != 0) return error; // Send out the header to the device if ((error = SendHeader(portnum, *pseg, segstart, remain, seglen, psum)) != 0) return error; return 0; } //-------------------------------------------------------------------------- // // Send out the data portion of a message segment to the device // // portnum = port number the device is on // mp = Pointer to segment in the message string // seglen = length of this segment // psum = Pointer to checksum accumulator // // return = Error code, or zero if all went well // uchar SendData(int portnum, uchar *mp, uchar seglen, ushort *psum) { uchar Retry, error; uchar i; ushort crc; // Now try (and Retry) to output the data without error for (Retry = 0; Retry < 3; Retry++) { while (1) { // Send out the data segment to the device and compute the crc // and checksum as it goes out StreamLen = 0; StreamBuff[StreamLen++] = OW_IPRWRITE; StreamBuff[StreamLen++] = seglen; for (i = 0; i < seglen; i++) StreamBuff[StreamLen++] = mp[i]; // set up the crc bytes // CHECK FOR BLIVET StreamBuff[StreamLen++] = 0xff; StreamBuff[StreamLen++] = 0xff; if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owBlock(portnum, FALSE, StreamBuff, StreamLen)) { error = ER_ACCESS; break; } crc = CRC16Buf(StreamBuff, 0, (ushort)(StreamLen - 2)); // Check the returning CRC from the device if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, crc)) != 0) { if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, (ushort)(crc ^ GetCRC16Correction(sizeof(crc))))) != 0) break; StreamBuff[2] &= 0x0FE; } for (i = 0; i < seglen; i++) mp[i] = StreamBuff[i + 2]; for (i = 0; i < seglen; i++) *psum += mp[i]; // If all has gone well, return with AOK status return 0; } } // If we've retried and failed, return with failure status return (uchar)(error | ER_SENDDATA); } //-------------------------------------------------------------------------- // // Send out the header portion of a message segment to the device // // portnum = port number the device is on // seg = Segment number to send out (0-127) // mp = Pointer to segment in message string // remain = Number of bytes remaining, including this segment // psum = Pointer to checksum accumulator // // return = Error code, or zero if all went well // uchar SendHeader(int portnum, uchar seg, uchar *mp, ushort remain, uchar seglen, ushort *psum) { ushort crc, segcrc; uchar Retry, error; FIFORDWR FB; ushort i; // We must compute the data segment's CRC for the header // This includes the segment length value segcrc = CRC16(seglen, 0); segcrc = CRC16Buf(mp, segcrc, seglen); // Now try (and Retry) sending the header to the device for (Retry = 0; Retry < 3; Retry++) { while (1) { if (!owAccess(portnum)) { error = ER_ACCESS; break; } FB.Cmd = OW_FIFOWRITE; FB.Len = FIFO_LEN; FB.FIFOBuf[0] = seg; FB.FIFOBuf[1] = seglen; FB.FIFOBuf[2] = LSB(remain); FB.FIFOBuf[3] = MSB(remain); FB.FIFOBuf[4] = LSB(segcrc); FB.FIFOBuf[5] = MSB(segcrc); for (i = 0; i < 6; i++) *psum += FB.FIFOBuf[i]; FB.FIFOBuf[6] = LSB(*psum); FB.FIFOBuf[7] = MSB(*psum); if (!owBlock(portnum, FALSE, &FB.Cmd, 10)) { error = ER_ACCESS; break; } crc = CRC16Buf(&FB.Cmd, 0, sizeof(FB)); // // Add the checksum bytes to the checksum for subsequent segments // (Uses segcrc because it's handy!) segcrc = *psum; *psum += LSB(segcrc); *psum += MSB(segcrc); // Check the returning CRC from the device if ((error = CheckCRC(portnum, crc)) != 0) break; // Send the release sequence and check the ACK bit if ((error = ReleaseSequence(portnum, RS_FIFOWRITE)) != 0) break; // If all went well, return with OK status return 0; } } // If we retried and failed, return with failure status return (uchar)(error | ER_SENDHDR); } //-------------------------------------------------------------------------- // // Return the device status values - // // portnum = port number the device is on // InFree = Pointer to status = Number of free bytes in FIFO // OutUsed = Pointer to status = Number of bytes waiting in FIFO // owms = Pointer to status = One-Wire Micro Status byte // cpst = Pointer to status = Co-Processor Status Byte // // return = Error code, or zero if all went well // uchar GetStatus(int portnum, uchar *InFree, uchar *OutUsed, uchar *owms, uchar *cpst) { uchar IOBuf[5]; uchar Retry, error; ushort crc; int i; for (Retry = 0; Retry < 3; Retry++) { while (1) { StreamLen = 0; StreamBuff[StreamLen++] = OW_STATUSREAD; // CHECK FOR BLIVET for (i = 0; i < 6; i++) // 2 for CRC read StreamBuff[StreamLen++] = 0xff; if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owBlock(portnum, FALSE, StreamBuff, StreamLen)) { error = ER_ACCESS; break; } crc = CRC16Buf(StreamBuff, 0, (ushort)(StreamLen - 2)); if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, crc)) != 0) { if (!(StreamBuff[1] & 1)) break; StreamBuff[1] &= 0xFE; crc = CRC16Buf(StreamBuff, 0, (ushort)(StreamLen - 2)); if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, crc)) != 0) break; } for (i = 0; i < 5; i++) IOBuf[i] = StreamBuff[i]; *InFree = IOBuf[1]; *OutUsed = IOBuf[2]; *owms = IOBuf[3]; *cpst = IOBuf[4]; // If success, return an AOK status return 0; } } // If we've re-tried and failed, return a failure status return (uchar)(error | ER_GETSTATUS); } //-------------------------------------------------------------------------- // // Send the owus byte (timing value) to the device - // // portnum = port number the device is on // owus = One-Wire Uart Status byte // // return = Error code, or zero if all went well // uchar SendStatus(int portnum, uchar owus) { uchar Retry, error; ushort crc; for (Retry = 0; Retry < 3; Retry++) { while (1) { if (!owAccess(portnum)) { error = ER_ACCESS; break; } crc = 0; crc = CRC16((uchar)owTouchByte(portnum, OW_STATUSWRITE), crc); crc = CRC16((uchar)owTouchByte(portnum, owus), crc); if ((error = CheckCRC(portnum, crc)) != 0) break; if ((error = ReleaseSequence(portnum, RS_STATUSWRITE)) != 0) break; // If all is well, exit with OK status return 0; } } // If retries failed, return with failure status return (uchar)(error | ER_SENDSTATUS); } //-------------------------------------------------------------------------- // // The SendRun function sends the micro-run command to the device // // portnum = port number the device is on // return = Error code, or zero if all went well // uchar SendRun(int portnum) { uchar Retry, error; for (Retry = 0; Retry < 3; Retry++) { while (1) { if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owWriteByte(portnum, OW_MICRORUN)) { error = ER_ACCESS; break; } // Issue the release sequence code if ((error = ReleaseSequence(portnum, RS_MICRORUN)) != 0) break; // If all went well, return with AOK status return 0; } } // If errors occurred return error status return (uchar)(error | ER_SENDRUN); } //-------------------------------------------------------------------------- // // The SendReset function sends the micro-reset command to the device // // portnum = port number the device is on // return = Error code, or zero if all went well // uchar SendReset(int portnum) { uchar Retry, error; for (Retry = 0; Retry < 3; Retry++) { while (1) { if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owWriteByte(portnum, OW_MICRORESET)) { error = ER_ACCESS; break; } if ((error = ReleaseSequence(portnum, RS_MICRORESET)) != 0) break; // If all went well, return w/o error return 0; } } return (uchar)(error | ER_SENDRESET); } //-------------------------------------------------------------------------- // // The SendInterrupt function sends the micro-interrupt command to the device // // portnum = port number the device is on // return = Error code, or zero if all went well // uchar SendInterrupt(int portnum) { uchar Retry, error; for (Retry = 0; Retry < 3; Retry++) { while (1) { if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owWriteByte(portnum, OW_MICROINTERRUPT)) { error = ER_ACCESS; break; } if ((error = ReleaseSequence(portnum, RS_MICROINTERRUPT)) != 0) break; return 0; } } return (uchar)(error | ER_SENDINT); } //-------------------------------------------------------------------------- // // Return Message Function - // // portnum = port number the device is on // mp = Current Pointer to message buffer string // bufsize = Number of bytes in provided buffer space // // return = Error code, or zero if all went well // ushort RecvCiBMessage(int portnum, uchar *mp, ushort *bufsize) { uchar ETime = 0; // Temporary time value uchar *mbuf; // Start of message buffer uchar InFree; // Inbound FIFO bytes available uchar OutUsed; // Outbound FIFO bytes used uchar owms; // micro status uchar cpst; // Co-Processor status uchar seg = 0; // Current segment number ushort hdrcrc = 0; // Crc from header ushort hdrsum = 0; // Checksum from header ushort checksum; // Running checksum of the message ushort sum = 0; // Temporary checksum store uchar size = 0; // Size of current segment ushort msglen; // Length of message received so far uchar oldseg; // Prior segment number for checking order uchar Retry, error; uchar JavaiButton = 0; checksum = msglen = 0; // Remember where the buffer starts mbuf = mp; // Set up a loop to try (and Retry) getting a message from the device for (Retry = 0; Retry < 6; Retry++) { // When we Retry, Retry from the top oldseg = 0xFF; while (1) { // Get the device status and see if there is a segment there to read if ((error = GetStatus(portnum, &InFree, &OutUsed, &owms, &cpst)) != 0) break; // See if a POR has occurred and treat it as an error if so if (owms & CE_BPOR) { error = ER_POR; break; } // See if the co-processor was running when we stopped if ((cpst & 1) != 0) { // Send the time value to the CIB if ((error = SendStatus(portnum, ETime)) != 0) break; // Execute the co-processor and allow it to finish up if ((error = SendRun(portnum)) != 0) break; // Compute a delay time to complete ETime = (uchar)(cpst >> 4); // Wait for whatever we did above to finish up TimeDelay(portnum, (uchar)(ETime + SLEEP_PAD)); } else { // If the co-processor is not running, then // See if the previous command has not yet been completed if (owms & 0x20) { // // Decide on a time value to complete the prior operation - // For now, we'll send back 1/2 of the status value as a time - ETime = (uchar)((owms & 0x1F) >> 1); if (ETime == 0) ETime++; // // if we don't allow a First Birthday (FB) to complete // we can end up in an infinite POR loop - FBs // currently take on the order of 1.5 Seconds if ((owms & 0x1F) == CE_FIRSTBIRTH) { // Send the time value to the CIB if ((error = SendStatus(portnum, ME_RUNTIME)) != 0) break; } else { // Send the time value to the CIB if ((error = SendStatus(portnum, ETime)) != 0) break; } // Execute the micro and allow it to finish up if ((error = SendRun(portnum)) != 0) break; // // wait an extra 1.5 seconds to compensate for first birthday. if ((owms & 0x1F) == CE_FIRSTBIRTH) { TimeDelay(portnum, ME_RUNTIME); TimeDelay(portnum, 1); } else { // Wait for whatever we did above to finish up TimeDelay(portnum, ETime); } } } // See if there's a segment header waiting for us if (OutUsed == 0) { error = ER_NOHEADER; break; } // See if the header is valid (ie: the correct length) if (OutUsed != HEADERSIZE) { error = ER_BADHEADER; break; } // Read the header in from the device if ((error = RecvHeader(portnum, &seg, &hdrcrc, &hdrsum, &size, &sum)) != 0) break; // See if this is the first segment of a new message if (((seg & 127) == 0) && (!JavaiButton)) { // When we get the first segment of a new message we must // initialize everything msglen = checksum = 0; oldseg = 0; mp = mbuf; } else { if (JavaiButton) { checksum = 0; seg = oldseg = 0; } // See if the segments are in proper order else if (++oldseg != (seg & 127)) { error = CE_BADSEQ; break; } } // See if the new message data would overrun the buffer if ((msglen + size) > *bufsize) { error = ER_OVERRUN; break; } // Make sum equal the whole progressive checksum including header checksum += sum; // Read in the segment data if ((error = RecvData(portnum, mp, size, hdrcrc, &sum, JavaiButton)) != 0) break; // If the message data came in OK then update values checksum += sum; // Keep the end-to-end checksum current if (!JavaiButton) { msglen += size; // Keep track of the size of the message mp += size; // Advance the message pointer } else { msglen += (ushort)(size - 3); // Keep track of the size of the message mp += size - 3; // Advance the message pointer } // Verify the progressive checksum value if (hdrsum != checksum) { error = ER_CHECKSUM; break; } // Keep the running sum correct checksum += LSB(hdrsum); checksum += MSB(hdrsum); // // See if this was the last message segment. If it was, then we // return with AOK status, and rcvd message size replaces bufsize. if (LastSegment && (owms != 14)) { *bufsize = msglen; return 0; } else if (owms == 14) { JavaiButton = 1; if ((error = SendStatus(portnum, 1)) != 0) break; if (SendRun(portnum) != 0) break; TimeDelay(portnum, 2); } else { // Send the time value to the CIB if ((error = SendStatus(portnum, 2)) != 0) break; // Allow the micro to run and bring up our next segment if (SendRun(portnum) != 0) break; TimeDelay(portnum, 2 + SLEEP_PAD); } } // Send the time value to the CIB if ((error = SendStatus(portnum, (uchar)(Retry ? (Retry << 1) : 1))) != 0) break; // If we have any failure, we must alow the micro to run or we // may not recover from it if (SendRun(portnum) == 0) { TimeDelay(portnum, (uchar)((Retry ? (Retry << 1) : 1) + SLEEP_PAD)); } } // Return with error status if retries exhausted return error; } //-------------------------------------------------------------------------- // // Read a header (FIFO) from the device - // // portnum = port number the device is on // seg = Pointer to segment number from the device // hdrcrc = CRC-16 of the segment data area from the header // hdrsum = Running checksum result from the header // size = Segment data area size from the header // sum = Checksum of the header bytes // // return = Error code, or zero if all went well // uchar RecvHeader(int portnum, uchar *seg, ushort *hdrcrc, ushort *hdrsum, uchar *size, ushort *sum) { ushort owcrc; ushort i; FIFORDWR FB; uchar Retry, error; for (Retry = 0; Retry < 3; Retry++) { while (1) { FB.Cmd = OW_FIFOREAD; FB.Len = FIFO_LEN; // CHECK FOR BLIVET // write 0xff's to stream buff directly memset(FB.FIFOBuf, 0xFF, 8); StreamLen = 0; memcpy(StreamBuff, &FB, sizeof(FB)); StreamLen += 10; // set up crc StreamBuff[StreamLen++] = 0xff; StreamBuff[StreamLen++] = 0xff; if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owBlock(portnum, FALSE, StreamBuff, StreamLen)) { error = ER_ACCESS; break; } memcpy(&FB, StreamBuff, sizeof(FB)); owcrc = CRC16Buf(&FB.Cmd, 0, sizeof(FB)); if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, owcrc)) != 0) { if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, (ushort)(owcrc ^ GetCRC16Correction(10)))) != 0) break; FB.FIFOBuf[0] &= 0x0FE; } *sum = 0; for (i = 0; i < 6; i++) *sum += FB.FIFOBuf[i]; *seg = FB.FIFOBuf[0]; *size = FB.FIFOBuf[1]; *hdrcrc = (ushort)((FB.FIFOBuf[5] << 8) | FB.FIFOBuf[4]); *hdrsum = (ushort)(FB.FIFOBuf[7] << 8) | FB.FIFOBuf[6]; if (((*seg) & 128) == 128) LastSegment = TRUE; else LastSegment = FALSE; if ((error = ReleaseSequence(portnum, RS_FIFOREAD)) != 0) break; // If all went well, return OK status return 0; } } // If retries exhautsed, return error status return (uchar)(error | ER_RECVHDR); } //-------------------------------------------------------------------------- // // Return the segment data from the device // // portnum = port number the device is on // mp = Pointer to message buffer next available position // size = Size of message segment (from header) // hdrcrc = CRC-16 of the data segment from header // sum = Checksum accumulator for segment data // // return = Error code, or zero if all went well // uchar RecvData(int portnum, uchar *mp, uchar size, ushort hdrcrc, ushort *sum, uchar JavaiButton) { uchar *mstart; ushort crc, owcrc, cksum, n; int i; uchar Retry, error; uchar *TempArray; mstart = mp; for (Retry = 0; Retry < 3; Retry++) { while (1) { // Get the current buffer pointer mp = mstart; crc = CRC16(size, 0); // Initialize the local checksum accumulator cksum = 0; if (!JavaiButton) { StreamLen = 0; StreamBuff[StreamLen++] = OW_IPRREAD; StreamBuff[StreamLen++] = size; // CHECK FOR BLIVET for (i = 0; i < size + 2; i++) // 2 for crc read StreamBuff[StreamLen++] = 0xff; if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owBlock(portnum, FALSE, StreamBuff, StreamLen)) { error = ER_ACCESS; break; } owcrc = CRC16Buf(StreamBuff, 0, (ushort)(size + 2)); // Check the returning CRC values against what we received if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, owcrc)) != 0) { // fix for bit blivet if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, (ushort)(owcrc ^ GetCRC16Correction((uchar)(size + 2))))) != 0) break; StreamBuff[2] &= 0xFE; } for (i = 0; i < size; i++) mp[i] = StreamBuff[i + 2]; crc = CRC16Buf(StreamBuff + 1, 0, (ushort)(size + 1)); for (n = 0; n < size; n++) cksum += mp[n]; // See if the CRC of the data matches what we expected as-per header if (hdrcrc != crc) { error = ER_HDRCRC; break; } // Since we've been successful, update the checksum and return AOK *sum = cksum; return 0; } // if(!JavaiButton) else { if (!(TempArray = malloc((size)*2))) { error = ER_OVERRUN; break; } StreamLen = 0; StreamBuff[StreamLen++] = OW_IPRREAD; StreamBuff[StreamLen++] = size; // CHECK FOR BLIVET for (i = 0; i < size + 2; i++) // 2 for crc read StreamBuff[StreamLen++] = 0xff; if (!owAccess(portnum)) { error = ER_ACCESS; break; } if (!owBlock(portnum, FALSE, StreamBuff, StreamLen)) { error = ER_ACCESS; free(TempArray); break; } owcrc = CRC16Buf(StreamBuff, 0, (ushort)(size + 2)); // Check the returning CRC values against what we received if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, owcrc)) != 0) { if ((error = CheckStreamCRC(StreamBuff, StreamLen - 2, (ushort)(owcrc ^ GetCRC16Correction((uchar)(size + 2))))) != 0) break; StreamBuff[2] &= 0x0FE; } for (i = 0; i < size; i++) TempArray[i] = StreamBuff[i + 2]; crc = CRC16Buf(StreamBuff + 1, 0, (ushort)(size + 1)); for (n = 0; n < size; n++) cksum += TempArray[n]; // See if the CRC of the data matches what we expected as-per header if (hdrcrc != crc) { error = ER_HDRCRC; free(TempArray); TempArray = NULL; break; } // Since we've been successful, update the checksum and return AOK *sum = cksum; if (size > 2) memcpy(mp, TempArray + 3, size - 3); free(TempArray); return 0; } // else } // for } // for Retry // If retries failed, return the error status return (uchar)(error | ER_RECVDATA); } //-------------------------------------------------------------------------- // // Issue the release sequence to the device and check the ACK response // // portnum = port number the device is on // rscode = Release sequence code (command specific) // // return = Error code, or zero if all went well // uchar ReleaseSequence(int portnum, ushort rscode) { uchar IOBuf[20]; ushort rslt; IOBuf[0] = LSB(rscode); IOBuf[1] = MSB(rscode); if (!owBlock(portnum, FALSE, IOBuf, 2)) { return ER_ACCESS; } if ((rscode == RS_MICRORUN) || (rscode == RS_MICROINTERRUPT)) { PowerOn = TRUE; rslt = !owReadBitPower(portnum, 0); } else rslt = owTouchBit(portnum, 1); // ACK bit from device (should be zero) if (!rslt) return 0; else return ER_ACK; } //-------------------------------------------------------------------------- // // Check the returning crc bytes against the crc provided (expected) // // portnum = port number the device is on // crc = CRC16 result of received bytes from device // // return = Error code, or zero if all went well // uchar CheckCRC(int portnum, ushort crc) { uchar IOBuf[2]; // CHECK FOR BLIVET IOBuf[0] = IOBuf[1] = 0xFF; if (!owBlock(portnum, FALSE, IOBuf, 2)) { return ER_ACCESS; } // Verify the CRC LS byte response if (IOBuf[0] != (uchar)~LSB(crc)) if ((IOBuf[0] & 0x0FE) != (uchar)~LSB(crc)) return ER_CRC; // Verify the CRC MS byte response if (IOBuf[1] != (uchar)~MSB(crc)) return ER_CRC; return 0; } //-------------------------------------------------------------------------- // // Check the returning crc bytes in stream buffer bp against the crc provided // (expected) - // // data = pointer to stream buffer // offset = offset to first SRS byte // crc = CRC16 result of received bytes from device // // return = Error code, or zero if all went well // uchar CheckStreamCRC(uchar *data, int offset, ushort crc) { if (data[offset] != (LSB(crc) ^ 0xFF)) { return ER_CRC; } if (data[offset + 1] != (MSB(crc) ^ 0xFF)) { return ER_CRC; } return 0; } //-------------------------------------------------------------------------- // // Produce a time delay as-per et - // // return = None // void TimeDelay(int portnum, uchar et) { msDelay(et * 250 + MinRun); if (PowerOn) { PowerOn = FALSE; if (MODE_NORMAL != owLevel(portnum, MODE_NORMAL)) { OWERROR(OWERROR_LEVEL_FAILED); } } } //-------------------------------------------------------------------------- // // CRC16 generation. Used here only for table generation. // ushort CRC16TGen(uchar x, ushort crc) { uchar bit; uchar n; for (n = 0; n < 8; n++) { bit = (uchar)((crc ^ x) & 1); crc >>= 1; if (bit) crc ^= 0xA001; x >>= 1; } return crc; } //-------------------------------------------------------------------------- // // Generate 256 word table for CRC16 lookup. // void GenCRC16Table() { ushort i; for (i = 0; i < 256; ++i) CRCTable[i] = CRC16TGen((uchar)i, 0); GenCRC16CorrectionTable(); } //-------------------------------------------------------------------------- // // Fast CRC16 generation. // ushort CRC16(uchar x, ushort crc) { return CRCTable[(crc ^ x) & 0xFF] ^ crc >> 8; } //-------------------------------------------------------------------------- // // Compute CRC16 of buffer pointed to by bp. // ushort CRC16Buf(uchar *bp, ushort crc, ushort Count) { ushort i; for (i = 0; i < Count; i++) crc = CRCTable[(crc ^ bp[i]) & 0xFF] ^ crc >> 8; return crc; } //-------------------------------------------------------------------------- // // Compute CRC16 correctionTable // void GenCRC16CorrectionTable() { int l_i, l_Size = sizeof(CRCCorrectionTable) / sizeof(ushort); ushort l_CurrentCRC = 0; memset(CRCCorrectionTable, 0, sizeof(CRCCorrectionTable)); CRCCorrectionTable[2] = CRC16(1, l_CurrentCRC); for (l_i = 3; l_i < l_Size; l_i++) { CRCCorrectionTable[l_i] = CRC16(0, CRCCorrectionTable[l_i - 1]); } } //-------------------------------------------------------------------------- // // Get CRC16 correction value // ushort GetCRC16Correction(uchar p_Length) { if (p_Length > sizeof(CRCCorrectionTable) / sizeof(ushort)) return 0; if (p_Length < 1) return 0; return CRCCorrectionTable[p_Length - 1]; } //-------------------------------------------------------------------------- // void SetMinRunTime(ushort MR) { MinRun = MR; } w1retap/src/libusblinux300/jibload.c000066400000000000000000000160271446446235200176030ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // jibload.c - Load a JiBLet to the Java-powered iButton(s) found on // the 1-Wire // // version 3.00 Beta // #include "jib96.h" #include "ownet.h" #include #define MAXDEVICES 10 // external functions extern SMALLINT FindDevices(int, uchar FamilySN[][8], SMALLINT, int); extern void PrintSerialNum(uchar *); // local prototypes void LoadJiB(int portnum, uchar *dev, char *filename, int MasterEraseFirst, int ClearLoadPINMode); int ProcessCommandLine(int p_ArgC, char **p_lpArgV, uchar *MasterEraseFirst, uchar *ClearLoadPINMode); uint GetFileToLoad(char *p_FileName, uchar *p_FileBuffer, uint p_Len); //-------------------------------------------------------------------------- // Main to load a JiBlet into a JiB // int main(int argc, char *argv[]) { uchar MasterEraseFirst = FALSE; uchar ClearLoadPINMode = FALSE; int i, portnum = 0, NumDevices; uchar FamilySN[MAXDEVICES][8]; printf("\nLoadJiB version 3.00B\n\n"); // see if another port is desired if ((argc < 3) || (!ProcessCommandLine(argc, argv, &MasterEraseFirst, &ClearLoadPINMode))) { printf("\nUsage: LoadJiB port filename [-e] [-l] [-h]\n"); printf(" port: required port name\n"); printf(" filename: filename of JiBlet to load\n"); printf(" -e: Master erase first\n"); printf(" -l: Clear Load PIN mode\n"); printf(" -h: Display usage\n\n"); exit(0); } // 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) NumDevices = FindDevices(portnum, &FamilySN[0], 0x16, MAXDEVICES); if (NumDevices > 0) { printf("\n"); printf("JiB(s) Found: \n"); for (i = 0; i < NumDevices; i++) { PrintSerialNum(FamilySN[i]); printf("\n"); } printf("\n\n"); // loop through the devices and do a test on each for (i = 0; i < NumDevices; i++) LoadJiB(portnum, FamilySN[i], argv[2], MasterEraseFirst, ClearLoadPINMode); } else printf("No JiB's Found!\n"); // release the 1-Wire Net owRelease(portnum); printf("Closing port %s.\n", argv[1]); exit(0); return 0; } //-------------------------------------------------------------------------- // Check command parameters for flags // int ProcessCommandLine(int p_ArgC, char **p_lpArgV, uchar *MasterEraseFirst, uchar *ClearLoadPINMode) { int l_i; // start looking at parameters after the two required ones for (l_i = 3; l_i < p_ArgC; l_i++) { // check for flag designator if ((p_lpArgV[l_i][0] == '/') || (p_lpArgV[l_i][0] == '-')) { // master erase first? if ((p_lpArgV[l_i][1] == 'e') || (p_lpArgV[l_i][1] == 'E')) *MasterEraseFirst = TRUE; // clear load pin to use signatures if ((p_lpArgV[l_i][1] == 'l') || (p_lpArgV[l_i][1] == 'L')) *ClearLoadPINMode = TRUE; // usage request if ((p_lpArgV[l_i][1] == 'h') || (p_lpArgV[l_i][1] == 'H')) return FALSE; } } return TRUE; } //-------------------------------------------------------------------------- // Read the file into the supplied buffer. // uint GetFileToLoad(char *p_FileName, uchar *p_FileBuffer, uint p_Len) { FILE *l_InFile; uint l_BytesRead = 0, l_ReadSize = 0; if (!(l_InFile = fopen(p_FileName, "r+b"))) { perror("Couldn't open file"); return FALSE; } while ((l_ReadSize = fread(p_FileBuffer + l_BytesRead, 1, p_Len - l_BytesRead, l_InFile)) > 0) { l_BytesRead += l_ReadSize; } fclose(l_InFile); return l_BytesRead; } //-------------------------------------------------------------------------- // Load the jib files into the iButton // void LoadJiB(int portnum, uchar *dev, char *filename, int MasterEraseFirst, int ClearLoadPINMode) { LPRESPONSEAPDU l_lpResponseAPDU; uchar l_FileName[260], l_FileBuff[4096]; AID l_CurrentAID; uint filelen; // select the device and put in overdrive printf("Device: "); PrintSerialNum(dev); printf("\n"); owSerialNum(portnum, dev, 0); if (!owOverdriveAccess(portnum)) printf("ERROR, could not get device in overdrive!\n"); // make sure there is time for hashing and a signature verification SetDefaultExecTime(800); if (MasterEraseFirst) { printf("Master Erasing Button: "); l_lpResponseAPDU = MasterErase(portnum); if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) printf("\nMaster Erase Failed with SW = 0x%04hX\n", l_lpResponseAPDU->SW); else printf("OK\n"); } if (ClearLoadPINMode) { printf("Clearing Load By PIN: "); l_lpResponseAPDU = SetLoadPINMode(portnum, 0); if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) printf("\nClear Load PIN Mode Failed with SW = 0x%04hX\n", l_lpResponseAPDU->SW); else printf("OK\n"); } printf("Loading %s: ", filename); // read the file and load if found filelen = GetFileToLoad(filename, l_FileBuff, sizeof(l_FileBuff)); if (filelen > 0) { // assume the filename less extension is the AID l_CurrentAID.Len = strlen(filename) - strlen(".jib"); // unless, of course, that's too large if (l_CurrentAID.Len > MAX_AID_SIZE) l_CurrentAID.Len = MAX_AID_SIZE; memcpy(l_CurrentAID.Data, filename, l_CurrentAID.Len); l_lpResponseAPDU = LoadApplet(portnum, l_FileBuff, filelen, &l_CurrentAID); if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { strncpy((char *)l_FileName, filename, l_CurrentAID.Len); l_FileName[l_CurrentAID.Len] = 0; printf("\nLoad of %s Failed with SW = 0x%04hX\n", l_FileName, l_lpResponseAPDU->SW); } else printf("OK\n"); } else printf("\nFile %s failed to open.\n", filename); } w1retap/src/libusblinux300/jibmodpw.c000066400000000000000000000167331446446235200200160ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // jibmodpw.c - test teh a JiBLet TestModPow on a Java Powered iButton // // version 3.00 Beta // #include "jib96.h" #include #include #include "ownet.h" #define MAXDEVICES 10 #define LOAD_UNLOAD_TIME 500 #define EXECUTE_TIME 1500 // external functions extern SMALLINT FindDevices(int, uchar FamilySN[][8], SMALLINT, int); extern void PrintSerialNum(uchar *); extern int key_abort(void); // local prototypes uchar *getRandData(uchar p_Len, uchar *p_lpData); uchar CycleTest(int portnum, uchar *dev); // globals int g_NumCompletions = 0, g_NumFailures = 0; //-------------------------------------------------------------------------- // Main for the Jib test // int main(int argc, char **argv) { int i, portnum = 0, NumDevices; uchar FamilySN[MAXDEVICES][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]); // initialize the random number generator srand((unsigned)time(NULL)); // Find the device(s) NumDevices = FindDevices(portnum, &FamilySN[0], 0x16, MAXDEVICES); if (NumDevices > 0) { printf("\n"); printf("JiB(s) Found: \n"); for (i = 0; i < NumDevices; i++) { PrintSerialNum(FamilySN[i]); printf("\n"); } printf("\n\n"); do { // loop through the devices and do a test on each for (i = 0; i < NumDevices; i++) CycleTest(portnum, FamilySN[i]); } while (!key_abort()); } else printf("No JiB's Found!\n"); // release the 1-Wire Net owRelease(portnum); printf("Closing port %s.\n", argv[1]); exit(0); return 0; } //-------------------------------------------------------------------------- // Get random numbers // uchar *getRandData(uchar p_Len, uchar *p_lpData) { int i; p_lpData[0] = p_Len; for (i = 1; i <= p_Len; i++) p_lpData[i] = (uchar)rand(); p_lpData[1] |= 0x80; return p_lpData; } //-------------------------------------------------------------------------- // This is a simple function to verify the coprocessor functions using // the JiBlet TestModExp.jib. // NOTE: TestModExp must be loaded and selected before executing this function. // uchar CycleTest(int portnum, uchar *dev) { LPRESPONSEAPDU l_lpResponseAPDU; uchar l_RefBuffer[256]; uchar l_Message[129], l_Modulus[129], l_Exponent[129]; uchar l_i; // select the device and put in overdrive printf("\nDevice: "); PrintSerialNum(dev); printf("\n"); owSerialNum(portnum, dev, 0); if (!owOverdriveAccess(portnum)) printf("ERROR, could not get device in overdrive!\n"); // read the firmware string // l_lpResponseAPDU = GetFirmwareVersionString(portnum); if (l_lpResponseAPDU) { if (l_lpResponseAPDU->SW == (ushort)0x9000) { // trim out the length byte // memcpy(l_RefBuffer, l_lpResponseAPDU->Data + 1, l_lpResponseAPDU->Len - 1); // zero terminate the string // l_RefBuffer[l_lpResponseAPDU->Len - 1] = 0; printf("Firmware: %s\n", l_RefBuffer); } else printf("GetFirmwareVersionString Error: SW = %4.4X", l_lpResponseAPDU->SW); } printf("Loading Message\n"); l_lpResponseAPDU = Process(portnum, 0x80, 0x00, 0, 0, 128, getRandData(127, l_Message), LOAD_UNLOAD_TIME); if (l_lpResponseAPDU->SW != (ushort)0x9000) { printf("Load Message failed with SW = %04x\n", l_lpResponseAPDU->SW); return FALSE; } printf("Loading Exponent\n"); l_lpResponseAPDU = Process(portnum, 0x80, 0x01, 0, 0, 128, getRandData(127, l_Exponent), LOAD_UNLOAD_TIME); if (l_lpResponseAPDU->SW != (ushort)0x9000) { printf("Load Exponent failed with SW = %04x\n", l_lpResponseAPDU->SW); return FALSE; } // make the modulus 1 byte larger than the exponent and message to insure that it is larger // without actually doing a "big number" compare (a quick cheat). printf("Loading Modulus\n"); l_lpResponseAPDU = Process(portnum, 0x80, 0x02, 0, 0, 129, getRandData(128, l_Modulus), LOAD_UNLOAD_TIME); if (l_lpResponseAPDU->SW != (ushort)0x9000) { printf("Load Modulus failed with SW = %04x\n", l_lpResponseAPDU->SW); return FALSE; } printf("Performing Exponentiation\n"); l_lpResponseAPDU = Process(portnum, 0x80, 0x03, 0, 0, 0, NULL, EXECUTE_TIME); if (l_lpResponseAPDU->SW != (ushort)0x9000) { printf("Exponentiation failed with SW = %04x\n", l_lpResponseAPDU->SW); return FALSE; } printf("Performing Read\n"); l_lpResponseAPDU = Process(portnum, 0x80, 0x04, 0, 0, 0, NULL, LOAD_UNLOAD_TIME); if (l_lpResponseAPDU->SW != (ushort)0x9000) { printf("Read failed with SW = %04x\n", l_lpResponseAPDU->SW); return FALSE; } memcpy(l_RefBuffer, l_lpResponseAPDU->Data, l_lpResponseAPDU->Len); printf("Performing Verification\n"); l_lpResponseAPDU = Process(portnum, 0x80, 0x03, 0, 0, 0, NULL, EXECUTE_TIME); if (l_lpResponseAPDU->SW != (ushort)0x9000) { printf("Verification failed with SW = %04x\n", l_lpResponseAPDU->SW); return FALSE; } printf("Performing Verification Read\n"); l_lpResponseAPDU = Process(portnum, 0x80, 0x04, 0, 0, 0, NULL, LOAD_UNLOAD_TIME); if (l_lpResponseAPDU->SW != (ushort)0x9000) { printf("Read failed with SW = %04x\n", l_lpResponseAPDU->SW); return FALSE; } printf("Result: "); for (l_i = 0; l_i < l_lpResponseAPDU->Len; l_i++) { if (!(l_i % 16)) printf("\n"); printf("%02X ", l_lpResponseAPDU->Data[l_i]); } printf("\n"); g_NumCompletions++; if (!memcmp(l_RefBuffer, l_lpResponseAPDU->Data, l_lpResponseAPDU->Len)) { printf("Buffer matches reference\nCompleted Iterations: %d, Failures: %d, Percent Failures: %2.2f\n", g_NumCompletions, g_NumFailures, (double)g_NumFailures / g_NumCompletions * 100); } else { printf("Buffer does NOT match reference\nIterations: %d, Failures: %d\n", g_NumCompletions, ++g_NumFailures); } return TRUE; } w1retap/src/libusblinux300/jibtest.c000066400000000000000000000246121446446235200176420ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // jibtest.c - Test each Java-powered iButton found on the 1-Wire // // version 3.00B // #include "jib96.h" #include "ownet.h" #define MAXDEVICES 10 // local functions static void TestJiB(int portnum, uchar *dev); extern SMALLINT FindDevices(int, uchar FamilySN[][8], SMALLINT, int); // global serial numbers uchar FamilySN[MAXDEVICES][8]; //-------------------------------------------------------------------------- // Main for the Jib test // int main(int argc, char *argv[]) { int portnum = 0, i; SMALLINT NumDevices; printf("\nJiBTest, Java Powered iButton HW/SW Tester, Version 3.00B\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]); // Find the device(s) NumDevices = FindDevices(portnum, &FamilySN[0], 0x16, MAXDEVICES); if (NumDevices > 0) { printf("\n"); printf("JiB(s) Found: \n"); for (i = 0; i < NumDevices; i++) { PrintSerialNum(FamilySN[i]); printf("\n"); } printf("\n\n"); // loop through the devices and do a test on each for (i = 0; i < NumDevices; i++) TestJiB(portnum, FamilySN[i]); } // release the 1-Wire Net owRelease(portnum); printf("Closing port %s.\n", argv[1]); exit(0); return 0; } //-------------------------------------------------------------------------- // Run the Java-powered Button through most of the read functions. // void TestJiB(int portnum, uchar *dev) { char l_Buff[256]; int l_FailureCount = 0, l_TestCount = 0, l_AppletNum, l_CurrentOffset = 0, l_CurrentLength = 0; uint l_FreeRam = 0; LPRESPONSEAPDU l_lpResponseAPDU; // select the device and put in overdrive printf(" Device: "); PrintSerialNum(dev); printf("\n"); owSerialNum(portnum, dev, 0); if (!owOverdriveAccess(portnum)) { printf("ERROR, could not get device in overdrive!\n"); l_FailureCount++; } l_TestCount++; // Get Firmware Version String l_lpResponseAPDU = GetFirmwareVersionString(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Firmware Version", l_lpResponseAPDU->SW); l_FailureCount++; } else { // trim out the length byte memcpy(l_Buff, l_lpResponseAPDU->Data, l_lpResponseAPDU->Len); memcpy(l_lpResponseAPDU->Data, l_Buff + 1, --(l_lpResponseAPDU->Len)); // zero terminate the strings l_lpResponseAPDU->Data[l_lpResponseAPDU->Len] = 0; printf(" Firmware Version String: %s\n", l_lpResponseAPDU->Data); } // Get Real-Time Clock l_lpResponseAPDU = GetRealTimeClock(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Real Time Clock", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf("Real Time Clock (1 of 2): 0x%08X\n", ((uint)l_lpResponseAPDU->Data[3] << 24) + ((uint)l_lpResponseAPDU->Data[2] << 16) + ((uint)l_lpResponseAPDU->Data[1] << 8) + l_lpResponseAPDU->Data[0]); } // Get Free RAM l_lpResponseAPDU = GetFreeRam(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Free RAM", l_lpResponseAPDU->SW); l_FailureCount++; } else { l_FreeRam = ((ushort)l_lpResponseAPDU->Data[1] << 8) + l_lpResponseAPDU->Data[0]; if (l_lpResponseAPDU->Len > 2) l_FreeRam += ((uint)l_lpResponseAPDU->Data[2] << 16); printf(" Free RAM: %d bytes\n", l_FreeRam); } // Get Power On Reset Count l_lpResponseAPDU = GetPORCount(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "POR Count", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf(" Power On Resets: %hd\n", ((ushort)l_lpResponseAPDU->Data[1] << 8) + l_lpResponseAPDU->Data[0]); } // Get Ephemeral GC Mode l_lpResponseAPDU = GetEphemeralGCMode(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Ephemeral GC Mode", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf(" Ephemeral GC: %s\n", l_lpResponseAPDU->Data[0] ? "On" : "Off"); } // Get Applet GC Mode l_lpResponseAPDU = GetAppletGCMode(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Applet GC Mode", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf(" Applet GC: %s\n", l_lpResponseAPDU->Data[0] ? "On" : "Off"); } // Get Restore Mode l_lpResponseAPDU = GetRestoreMode(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Restore Mode", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf(" Restore Mode: %s\n", l_lpResponseAPDU->Data[0] ? "Enabled" : "Disabled"); } // Get Exception Mode l_lpResponseAPDU = GetExceptionMode(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Exception Mode", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf(" Exception Mode: %s\n", l_lpResponseAPDU->Data[0] ? "Enabled" : "Disabled"); } // Get Commit Buffer Size l_lpResponseAPDU = GetCommitBufferSize(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Commit Buffer Size", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf(" Commit Buffer Size: %hd bytes", ((ushort)l_lpResponseAPDU->Data[1] << 8) + l_lpResponseAPDU->Data[0]); } // Get Commit Buffer Fields l_lpResponseAPDU = GetCommitBufferFields(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("\n%s Test Failed with SW = 0x%04hX\n", "Commit Buffer Fields", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf(" -> %hd fields\n", ((ushort)l_lpResponseAPDU->Data[1] << 8) + l_lpResponseAPDU->Data[0]); } // Get Real-Time Clock l_lpResponseAPDU = GetRealTimeClock(portnum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { printf("%s Test Failed with SW = 0x%04hX\n", "Real Time Clock", l_lpResponseAPDU->SW); l_FailureCount++; } else { printf("Real Time Clock (2 of 2): 0x%08X\n", ((uint)l_lpResponseAPDU->Data[3] << 24) + ((uint)l_lpResponseAPDU->Data[2] << 16) + ((uint)l_lpResponseAPDU->Data[1] << 8) + l_lpResponseAPDU->Data[0]); } printf(" Installed Applets:\n"); if (!(dev[0] & (uchar)0x80)) { // quick test for crusty firmware // Enumerate all applets for (l_AppletNum = 0; l_AppletNum < 16; l_AppletNum++) { l_lpResponseAPDU = GetAIDByNumber(portnum, (uchar)l_AppletNum); l_TestCount++; if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { // Not an error if no applet is installed at this position if (l_lpResponseAPDU->SW != 0x8453) { printf("%s Test Failed with SW = 0x%04hX\n", "Get AID", l_lpResponseAPDU->SW); l_FailureCount++; } } else { if (l_lpResponseAPDU->Len) { // trim out the length byte memcpy(l_Buff, l_lpResponseAPDU->Data + 1, (int)l_lpResponseAPDU->Data[0]); // zero terminate the string l_Buff[*(uchar *)l_lpResponseAPDU->Data] = 0; printf("%24c%2d) %s\n", ' ', l_AppletNum, l_Buff); } } } } else { // can get all AIDS in single APDU l_TestCount++; l_lpResponseAPDU = GetAllAIDs(portnum); if (l_lpResponseAPDU->SW != ERR_ISO_NORMAL_00) { if (l_lpResponseAPDU->SW != 0x8453) { printf("%s Test Failed with SW = 0x%04hX\n", "Get All AIDs", l_lpResponseAPDU->SW); l_FailureCount++; } else printf("%24c No Applets found\n", ' '); } else { while ((unsigned)l_CurrentOffset < l_lpResponseAPDU->Len) { l_AppletNum = l_lpResponseAPDU->Data[l_CurrentOffset++]; l_CurrentLength = l_lpResponseAPDU->Data[l_CurrentOffset++]; memcpy(l_Buff, l_lpResponseAPDU->Data + l_CurrentOffset, l_CurrentLength); // zero terminate the string l_Buff[l_CurrentLength] = 0; l_CurrentOffset += l_CurrentLength; printf("%24c%2d) %s\n", ' ', l_AppletNum, l_Buff); } } } if (l_FailureCount) printf("\n%d of %d tests failed! Check Hardware and Driver (if applicable) Installation\n\n", l_FailureCount, l_TestCount); else printf("\nHardware Installation Ok!\n\n"); } w1retap/src/libusblinux300/lcdtest.c000066400000000000000000000057061446446235200176430ustar00rootroot00000000000000#include #include #include #include #include "ownet.h" #include "findtype.h" #include "swt1f.h" extern int send_text_lcd(int, char *, int, int); extern int init_lcd(int, uchar *); 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) { int portnum = 0; char *serial = NULL, *txt1 = NULL, *txt2 = 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:1:2:")) != 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; case '1': txt1 = strdup(optarg); break; case '2': txt2 = strdup(optarg); break; default: break; } } dev = argv[optind]; if (dev == NULL || serial == NULL) { fputs("usage: lcdtest -s serial -1 \"Line 1\" -2 \"Line 2\" device\n" " device => /dev/ttyS0 or DS2490-1\n", stderr); return 0; } if ((portnum = owAcquireEx(dev)) < 0) { fputs("Failed to acquire port.\n", stderr); return 0; } else { 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 (txt1 == NULL) { // 0123456789012345" txt1 = "w1retap LCD test"; } if (txt2 == NULL) { time_t now; struct tm *tm; now = time(NULL); tm = localtime(&now); txt2 = malloc(20); strftime(txt2, 20, "%FT%H:%M", tm); } int i, rv0, rv00 = 0, rv1, rv2 = 0; rv0 = init_lcd(portnum, ident); rv1 = send_text_lcd(portnum, txt1, 1, 1); rv00 = init_lcd(portnum, ident); rv2 = send_text_lcd(portnum, txt2, 2, 0); fputs("---", stdout); for (i = 0; i < 16; i++) { printf("%01x", i); } fputs("---\n", stdout); printf("1: %s => %d\n2: %s => %d\n", txt1, rv1, txt2, rv2); printf("%d %d\n", rv0, rv00); if (coupler) { w1_set_coupler(portnum, cident, 0); } } return 0; } w1retap/src/libusblinux300/libusbds2490.c000066400000000000000000000307551446446235200203310ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2004 Dallas Semiconductor MAXIM 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 MAXIM // shall not be used except as stated in the Dallas Semiconductor MAXIM // Branding Policy. //--------------------------------------------------------------------------- // // libusblds2490.c - DS2490 utility functions for Windows. // (Requires libusb http://libusb.sourceforge.net // or http://libusb-win32.sourceforge.net) // // Version: // #include "ownet.h" #include #include "libusbds2490.h" // handles for the USB ports extern struct libusb_device_handle *usb_dev_handle_list[MAX_PORTNUM]; // global DS2490 state SMALLINT USBLevel[MAX_PORTNUM]; SMALLINT USBSpeed[MAX_PORTNUM]; SMALLINT USBVersion[MAX_PORTNUM]; SMALLINT USBVpp[MAX_PORTNUM]; //--------------------------------------------------------------------------- // Attempt to resync and detect a DS2490 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE - DS2490 detected successfully // FALSE - Could not detect DS2490 // SMALLINT DS2490Detect(libusb_device_handle *hDevice) { SMALLINT present, vpp; SETUP_PACKET setup; // reset the DS2490 DS2490Reset(hDevice); // set the strong pullup duration to infinite setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_SET_DURATION | COMM_IM; setup.Index = 0x0000; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver libusb_control_transfer(hDevice, setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); // set the 12V pullup duration to 512us setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_SET_DURATION | COMM_IM | COMM_TYPE; setup.Index = 0x0040; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver libusb_control_transfer(hDevice, setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); // disable strong pullup, but leave program pulse enabled (faster) setup.RequestTypeReservedBits = 0x40; setup.Request = MODE_CMD; setup.Value = MOD_PULSE_EN; setup.Index = ENABLEPULSE_PRGE; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver libusb_control_transfer(hDevice, setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); // return result of short check return DS2490ShortCheck(hDevice, &present, &vpp); } //--------------------------------------------------------------------------- // Check to see if there is a short on the 1-Wire bus. Used to stop // communication with the DS2490 while the short is in effect to not // overrun the buffers. // // '*present' - flag set (1) if device presence detected // '*vpp' - flag set (1) if Vpp programming voltage detected // // Returns: TRUE - DS2490 1-Wire is NOT shorted // FALSE - Could not detect DS2490 or 1-Wire shorted // SMALLINT DS2490ShortCheck(libusb_device_handle *hDevice, SMALLINT *present, SMALLINT *vpp) { STATUS_PACKET status; uchar nResultRegisters = 0; uchar i; // get the result registers (if any) if (!DS2490GetStatus(hDevice, &status, &nResultRegisters)) { return FALSE; } // get vpp present flag *vpp = ((status.StatusFlags & STATUSFLAGS_12VP) != 0); // Check for short if (status.CommBufferStatus != 0) { return FALSE; } else { // check for short for (i = 0; i < nResultRegisters; i++) { // check for SH bit (0x02), ignore 0xA5 if (status.CommResultCodes[i] & COMMCMDERRORRESULT_SH) { // short detected return FALSE; } } } // check for No 1-Wire device condition *present = TRUE; // loop through result registers for (i = 0; i < nResultRegisters; i++) { // only check for error conditions when the condition is not a ONEWIREDEVICEDETECT if (status.CommResultCodes[i] != ONEWIREDEVICEDETECT) { // check for NRS bit (0x01) if (status.CommResultCodes[i] & COMMCMDERRORRESULT_NRS) { // empty bus detected *present = FALSE; } } } return TRUE; } //--------------------------------------------------------------------------- // Stop any on-going pulses // // Returns: TRUE - pulse stopped // FALSE - Could not stop pulse // SMALLINT DS2490HaltPulse(libusb_device_handle *hDevice) { STATUS_PACKET status; uchar nResultRegisters; SETUP_PACKET setup; SMALLINT ret; int limit; // set a time limit limit = msGettick() + 300; // loop until confirm pulse has ended or timeout do { // HalExecWhenIdle, Resume Execution to stop an infinite pulse // HalExecWhenIdle setup.RequestTypeReservedBits = 0x40; setup.Request = CONTROL_CMD; setup.Value = CTL_HALT_EXE_IDLE; setup.Index = 0x00; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(hDevice, setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure break; } // Resume Execution setup.RequestTypeReservedBits = 0x40; setup.Request = CONTROL_CMD; setup.Value = CTL_RESUME_EXE; setup.Index = 0x00; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(hDevice, setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure break; } // read the status to see if the pulse has been stopped if (!DS2490GetStatus(hDevice, &status, &nResultRegisters)) { // failure break; } else { // check the SPU flag if ((status.StatusFlags & STATUSFLAGS_SPUA) == 0) { // success // disable both pulse types setup.RequestTypeReservedBits = 0x40; setup.Request = MODE_CMD; setup.Value = MOD_PULSE_EN; setup.Index = 0; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(hDevice, setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); return TRUE; } } } while (limit > msGettick()); return FALSE; } //--------------------------------------------------------------------------- // Description: Gets the status of the DS2490 device // Input: hDevice - the handle to the DS2490 device // pStatus - the Status Packet to be filled with data // pResultSize - the number of result register codes returned // // Returns: FALSE on failure, TRUE on success // SMALLINT DS2490GetStatus(libusb_device_handle *hDevice, STATUS_PACKET *status, uchar *pResultSize) { // buffer to retrieve status uchar buffer[32]; SMALLINT i = 0; int res = 0; int actlen = 0; // initialize buffer memset(buffer, 0, sizeof(buffer)); // get status buffer // bufferlength = usb_bulk_read(hDevice,DS2490_EP1,(char *)buffer,sizeof(buffer),TIMEOUT_LIBUSB); res = libusb_interrupt_transfer(hDevice, DS2490_EP1, buffer, sizeof(buffer), &actlen, TIMEOUT_LIBUSB); if (res < 0) { OWERROR(OWERROR_ADAPTER_ERROR); return FALSE; } // make status packet from return buffer status->EnableFlags = buffer[0]; status->OneWireSpeed = buffer[1]; status->StrongPullUpDuration = buffer[2]; status->ProgPulseDuration = buffer[3]; status->PullDownSlewRate = buffer[4]; status->Write1LowTime = buffer[5]; status->DSOW0RecoveryTime = buffer[6]; status->Reserved1 = buffer[7]; status->StatusFlags = buffer[8]; status->CurrentCommCmd1 = buffer[9]; status->CurrentCommCmd2 = buffer[10]; status->CommBufferStatus = buffer[11]; status->WriteBufferStatus = buffer[12]; status->ReadBufferStatus = buffer[13]; status->Reserved2 = buffer[14]; status->Reserved3 = buffer[15]; // take care for CommResultCodes (if they exist) if (actlen > 15) { for (i = 0; i < 16; i++) { status->CommResultCodes[i] = buffer[16 + i]; } *pResultSize = actlen - 16; // This should be the size of CommResultCodes... } else { pResultSize = 0; } return TRUE; } //--------------------------------------------------------------------------- // Description: Perfroms a hardware reset of the DS2490 equivalent to a // power-on reset // Input: hDevice - the handle to the DS2490 device // Returns: FALSE on failure, TRUE on success // Error Codes: DS2490COMM_ERR_USBDEVICE // SMALLINT DS2490Reset(libusb_device_handle *hDevice) { SETUP_PACKET setup; SMALLINT ret = 0; // setup for reset setup.RequestTypeReservedBits = 0x40; setup.Request = CONTROL_CMD; setup.Value = CTL_RESET_DEVICE; setup.Index = 0x00; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(hDevice, setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { OWERROR(OWERROR_ADAPTER_ERROR); return FALSE; } return TRUE; } //--------------------------------------------------------------------------- // Description: Reads data from EP3 // Input: hDevice - the handle to the DS2490 device // buffer - the size must be >= nBytes // pnBytes - the number of bytes to read from the device // Returns: FALSE on failure, TRUE on success // SMALLINT DS2490Read(libusb_device_handle *hDevice, uchar *buffer, ushort *pnBytes) { // Synchronous read: int nBytes = *pnBytes; int err = 0; // read err = libusb_bulk_transfer(hDevice, // handle DS2490_EP3, // which endpoint to read from buffer, // buffer to contain read results nBytes, // number of bytes to read &nBytes, TIMEOUT_LIBUSB); // libusb timeout if (err < 0) { OWERROR(OWERROR_ADAPTER_ERROR); return FALSE; } else { *pnBytes = (ushort)nBytes; return TRUE; } } //--------------------------------------------------------------------------- // Description: Writes data to EP2 // Input: hDevice - the handle to the DS2490 device // buffer - the size must be >= nBytes // pnBytes - the number of bytes to write to the device // Returns: FALSE on failure, TRUE on success // SMALLINT DS2490Write(libusb_device_handle *hDevice, uchar *buffer, ushort *pnBytes) { // Synchronous write: // assume enough room for write int nBytes = *pnBytes; int err = 0; // write err = libusb_bulk_transfer(hDevice, // handle DS2490_EP2, // which endpoint to write buffer, // buffer to write to endpoint nBytes, // number of bytes to write &nBytes, TIMEOUT_LIBUSB); // libusb timeout if (err < 0) { OWERROR(OWERROR_ADAPTER_ERROR); return FALSE; } else { *pnBytes = (ushort)nBytes; return TRUE; } } w1retap/src/libusblinux300/libusbds2490.h000066400000000000000000000251511446446235200203300ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2004 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. //--------------------------------------------------------------------------- // #ifndef _ds2490comm_h_ #define _ds2490comm_h_ #include "libusb.h" /** EP1 -- control read */ #define DS2490_EP1 0x81 /** EP2 -- bulk write */ #define DS2490_EP2 0x02 /** EP3 -- bulk read */ #define DS2490_EP3 0x83 // Error codes #define DS2490COMM_ERR_NOERROR 0 // an error has not yet been encountered #define DS2490COMM_ERR_GETLASTERROR 1 // use GetLastError() for more information #define DS2490COMM_ERR_RESULTREGISTERS 2 // use DS2490COMM_GetLastResultRegister() for more info #define DS2490COMM_ERR_USBDEVICE 3 // error from USB device driver #define DS2490COMM_ERR_READWRITE 4 // an I/O error occurred while communicating w/ device #define DS2490COMM_ERR_TIMEOUT 5 // an operation timed out before completion #define DS2490COMM_ERR_INCOMPLETEWRITE 6 // not all data could be sent for output #define DS2490COMM_ERR_INCOMPLETEREAD 7 // not all data could be received for an input #define DS2490COMM_ERR_INITTOUCHBYTE 8 // the touch byte thread could not be started #define g_DS2490COMM_LAST_SHORTEDBUS 9 // 1Wire bus shorted on #define g_DS2490COMM_LAST_EMPTYBUS 10 // 1Wire bus empty #define IOCTL_INBUF_SIZE 512 #define IOCTL_OUTBUF_SIZE 512 #define TIMEOUT_PER_BYTE 15 // 1000 modified 4/27/00 BJV #define TIMEOUT_LIBUSB 5000 // Definition is taken from DDK typedef struct __attribute__((__packed__)) _USB_DEVICE_DESCRIPTOR { uchar bLength; uchar bDescriptorType; ushort bcdUSB; ushort bDeviceClass; uchar bDeviceSubClass; uchar bDeviceProtocol; uchar bMaxPacketSize0; ushort idVendor; ushort idProduct; ushort bcdDevice; uchar iManufacturer; uchar iProduct; uchar iSerialNumber; uchar bNumConfigurations; } USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; // IOCTL codes #define DS2490_IOCTL_VENDOR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) #define DS2490_IOCTL_STATUS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) #define DS2490_IOCTL_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) // Device Information is put here typedef struct __attribute__((__packed__)) _USB_DEVICE_INFO { uint DriverVersion; USB_DEVICE_DESCRIPTOR Descriptor; uchar Unit; } USB_DEVICE_INFO, *PUSB_DEVICE_INFO; // Setup packet typedef struct __attribute__((__packed__)) _SETUP_PACKET { // Only for vendor specifc bits for COMM commands. uchar RequestTypeReservedBits; // The Request byte uchar Request; // The Value byte ushort Value; // The Index byte ushort Index; // The length of extra Data In or Out ushort Length; // Does the extra data go In, or Out? SMALLINT DataOut; // If there is extra data In, it goes here. uchar DataInBuffer[0]; } SETUP_PACKET, *PSETUP_PACKET; // Request byte, Command Type Code Constants #define CONTROL_CMD 0x00 #define COMM_CMD 0x01 #define MODE_CMD 0x02 #define TEST_CMD 0x03 // // Value field, Control commands // // Control Command Code Constants #define CTL_RESET_DEVICE 0x0000 #define CTL_START_EXE 0x0001 #define CTL_RESUME_EXE 0x0002 #define CTL_HALT_EXE_IDLE 0x0003 #define CTL_HALT_EXE_DONE 0x0004 #define CTL_CANCEL_CMD 0x0005 #define CTL_CANCEL_MACRO 0x0006 #define CTL_FLUSH_COMM_CMDS 0x0007 #define CTL_FLUSH_RCV_BUFFER 0x0008 #define CTL_FLUSH_XMT_BUFFER 0x0009 #define CTL_GET_COMM_CMDS 0x000A // // Value field COMM Command options // // COMM Bits (bitwise or into COMM commands to build full value byte pairs) // Byte 1 #define COMM_TYPE 0x0008 #define COMM_SE 0x0008 #define COMM_D 0x0008 #define COMM_Z 0x0008 #define COMM_CH 0x0008 #define COMM_SM 0x0008 #define COMM_R 0x0008 #define COMM_IM 0x0001 // Byte 2 #define COMM_PS 0x4000 #define COMM_PST 0x4000 #define COMM_CIB 0x4000 #define COMM_RTS 0x4000 #define COMM_DT 0x2000 #define COMM_SPU 0x1000 #define COMM_F 0x0800 #define COMM_ICP 0x0200 #define COMM_RST 0x0100 // Read Straight command, special bits #define COMM_READ_STRAIGHT_NTF 0x0008 #define COMM_READ_STRAIGHT_ICP 0x0004 #define COMM_READ_STRAIGHT_RST 0x0002 #define COMM_READ_STRAIGHT_IM 0x0001 // // Value field COMM Command options (0-F plus assorted bits) // #define COMM_ERROR_ESCAPE 0x0601 #define COMM_SET_DURATION 0x0012 #define COMM_BIT_IO 0x0020 #define COMM_PULSE 0x0030 #define COMM_1_WIRE_RESET 0x0042 #define COMM_BYTE_IO 0x0052 #define COMM_MATCH_ACCESS 0x0064 #define COMM_BLOCK_IO 0x0074 #define COMM_READ_STRAIGHT 0x0080 #define COMM_DO_RELEASE 0x6092 #define COMM_SET_PATH 0x00A2 #define COMM_WRITE_SRAM_PAGE 0x00B2 #define COMM_WRITE_EPROM 0x00C4 #define COMM_READ_CRC_PROT_PAGE 0x00D4 #define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 #define COMM_SEARCH_ACCESS 0x00F4 // Mode Command Code Constants // Enable Pulse Constants #define ENABLEPULSE_PRGE 0x01 // strong pull-up #define ENABLEPULSE_SPUE 0x02 // programming pulse // 1Wire Bus Speed Setting Constants #define ONEWIREBUSSPEED_REGULAR 0x00 #define ONEWIREBUSSPEED_FLEXIBLE 0x01 #define ONEWIREBUSSPEED_OVERDRIVE 0x02 // // Value field Mode Commands options // #define MOD_PULSE_EN 0x0000 #define MOD_SPEED_CHANGE_EN 0x0001 #define MOD_1WIRE_SPEED 0x0002 #define MOD_STRONG_PU_DURATION 0x0003 #define MOD_PULLDOWN_SLEWRATE 0x0004 #define MOD_PROG_PULSE_DURATION 0x0005 #define MOD_WRITE1_LOWTIME 0x0006 #define MOD_DSOW0_TREC 0x0007 // // This is the status structure as returned by DS2490_IOCTL_STATUS. // typedef struct __attribute__((__packed__)) _STATUS_PACKET { uchar EnableFlags; uchar OneWireSpeed; uchar StrongPullUpDuration; uchar ProgPulseDuration; uchar PullDownSlewRate; uchar Write1LowTime; uchar DSOW0RecoveryTime; uchar Reserved1; uchar StatusFlags; uchar CurrentCommCmd1; uchar CurrentCommCmd2; uchar CommBufferStatus; // Buffer for COMM commands uchar WriteBufferStatus; // Buffer we write to uchar ReadBufferStatus; // Buffer we read from uchar Reserved2; uchar Reserved3; // There may be up to 16 bytes here, or there may not. uchar CommResultCodes[16]; } STATUS_PACKET, *PSTATUS_PACKET; // // STATUS FLAGS // // Enable Flags #define ENABLEFLAGS_SPUE 0x01 // if set Strong Pull-up to 5V enabled #define ENABLEFLAGS_PRGE 0x02 // if set 12V programming pulse enabled #define ENABLEFLAGS_SPCE 0x04 // if set a dynamic 1-Wire bus speed change through Comm. Cmd. enabled // Device Status Flags #define STATUSFLAGS_SPUA 0x01 // if set Strong Pull-up is active #define STATUSFLAGS_PRGA 0x02 // if set a 12V programming pulse is being generated #define STATUSFLAGS_12VP 0x04 // if set the external 12V programming voltage is present #define STATUSFLAGS_PMOD 0x08 // if set the DS2490 powered from USB and external sources #define STATUSFLAGS_HALT 0x10 // if set the DS2490 is currently halted #define STATUSFLAGS_IDLE 0x20 // if set the DS2490 is currently idle // Result Registers #define ONEWIREDEVICEDETECT 0xA5 // 1-Wire device detected on bus #define COMMCMDERRORRESULT_NRS \ 0x01 // if set 1-WIRE RESET did not reveal a Presence Pulse or SET PATH did not get a Presence Pulse from the branch to be // connected #define COMMCMDERRORRESULT_SH \ 0x02 // if set 1-WIRE RESET revealed a short on the 1-Wire bus or the SET PATH couln not connect a branch due to short #define COMMCMDERRORRESULT_APP 0x04 // if set a 1-WIRE RESET revealed an Alarming Presence Pulse #define COMMCMDERRORRESULT_VPP \ 0x08 // if set during a PULSE with TYPE=1 or WRITE EPROM command the 12V programming pulse not seen on 1-Wire bus #define COMMCMDERRORRESULT_CMP \ 0x10 // if set there was an error reading confirmation byte of SET PATH or WRITE EPROM was unsuccessful #define COMMCMDERRORRESULT_CRC \ 0x20 // if set a CRC occurred for one of the commands: WRITE SRAM PAGE, WRITE EPROM, READ EPROM, READ CRC PROT PAGE, or READ // REDIRECT PAGE W/CRC #define COMMCMDERRORRESULT_RDP 0x40 // if set READ REDIRECT PAGE WITH CRC encountered a redirected page #define COMMCMDERRORRESULT_EOS 0x80 // if set SEARCH ACCESS with SM=1 ended sooner than expected with too few ROM IDs // Strong Pullup #define SPU_MULTIPLE_MS 128 #define SPU_DEFAULT_CODE 512 / SPU_MULTIPLE_MS // default Strong pullup value // Programming Pulse #define PRG_MULTIPLE_US 8 // Programming Pulse Time Multiple (Time = PRG_MULTIPLE_US * DurationCode) #define PRG_DEFAULT_CODE 512 / PRG_MULTIPLE_US // default Programming pulse value // Support functions SMALLINT DS2490Detect(libusb_device_handle *hDevice); SMALLINT DS2490GetStatus(libusb_device_handle *hDevice, STATUS_PACKET *status, uchar *pResultSize); SMALLINT DS2490ShortCheck(libusb_device_handle *hDevice, SMALLINT *present, SMALLINT *vpp); SMALLINT DS2490Reset(libusb_device_handle *hDevice); SMALLINT DS2490Read(libusb_device_handle *hDevice, uchar *buffer, ushort *pnBytes); SMALLINT DS2490Write(libusb_device_handle *hDevice, uchar *buffer, ushort *pnBytes); SMALLINT DS2490HaltPulse(libusb_device_handle *hDevice); SMALLINT AdapterRecover(int portnum); #endif // _ds2490comm_h_ w1retap/src/libusblinux300/libusbllnk.c000066400000000000000000000531501446446235200203360ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2004 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. //--------------------------------------------------------------------------- // // libusbwlnk.c - USB (DS2490) 1-Wire Public Domain low-level functions // http://libusb.sourceforge.net or // http://libusb-win32.sourceforge.net // // Version: 3.00 // #include "ownet.h" #include "libusbds2490.h" #include #include // DS2490 state info extern SMALLINT USBSpeed[MAX_PORTNUM]; extern SMALLINT USBLevel[MAX_PORTNUM]; extern struct libusb_device_handle *usb_dev_handle_list[MAX_PORTNUM]; extern SMALLINT USBVpp[MAX_PORTNUM]; //-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE(1): presense pulse(s) detected, device(s) reset // FALSE(0): no presense pulses detected // SMALLINT owTouchReset_(int portnum) { SETUP_PACKET setup; SMALLINT present, vpp; SMALLINT ret = 0; // make sure strong pullup is not on if (USBLevel[portnum] == MODE_STRONG5) owLevel(portnum, MODE_NORMAL); // construct command setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE; setup.Index = (USBSpeed[portnum] == MODE_OVERDRIVE) ? ONEWIREBUSSPEED_OVERDRIVE : ONEWIREBUSSPEED_FLEXIBLE; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_RESET_FAILED); AdapterRecover(portnum); return FALSE; } else { // extra delay for alarming DS1994/DS2404 complience if ((FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE) && (USBSpeed[portnum] != MODE_OVERDRIVE)) msDelay(5); // success, check for shorts if (DS2490ShortCheck(usb_dev_handle_list[portnum], &present, &vpp)) { USBVpp[portnum] = vpp; return present; } else { OWERROR(OWERROR_OW_SHORTED); // short occuring msDelay(300); AdapterRecover(portnum); return FALSE; } } } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and return the // result 1 bit read from the 1-Wire Net. The parameter 'sendbit' // least significant bit is used and the least significant bit // of the result is the return bit. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'sendbit' - the least significant bit is the bit to send // // Returns: 0: 0 bit read from sendbit // 1: 1 bit read from sendbit // SMALLINT owTouchBit_(int portnum, SMALLINT sendbit) { SETUP_PACKET setup; ushort nBytes; uchar buf[2]; SMALLINT ret = 0; // make sure strong pullup is not on if (USBLevel[portnum] == MODE_STRONG5) owLevel(portnum, MODE_NORMAL); // set to do touchbit setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_BIT_IO | COMM_IM | ((sendbit) ? COMM_D : 0); setup.Index = 0; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return 0; } else { // success, read the result nBytes = 1; if (DS2490Read(usb_dev_handle_list[portnum], buf, &nBytes)) return buf[0]; else { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return 0; } } } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // SMALLINT owTouchByte_(int portnum, SMALLINT sendbyte) { SETUP_PACKET setup; ushort nBytes; uchar buf[2]; SMALLINT ret = 0; // make sure strong pullup is not on if (USBLevel[portnum] == MODE_STRONG5) owLevel(portnum, MODE_NORMAL); // set to do touchbyte setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_BYTE_IO | COMM_IM; setup.Index = sendbyte & 0xFF; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return 0; } else { // success, read the result nBytes = 1; if (DS2490Read(usb_dev_handle_list[portnum], buf, &nBytes)) return buf[0]; else { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return 0; } } } //-------------------------------------------------------------------------- // Send 8 bits of communication to the MicroLAN and verify that the // 8 bits read from the MicroLAN is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // SMALLINT owWriteByte_(int portnum, SMALLINT sendbyte) { return (owTouchByte(portnum, sendbyte) == sendbyte) ? TRUE : FALSE; } //-------------------------------------------------------------------------- // Send 8 bits of read communication to the 1-Wire Net and and return the // result 8 bits read from the 1-Wire Net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE: 8 bytes read from 1-Wire Net // FALSE: the 8 bytes were not read // SMALLINT owReadByte_(int portnum) { return owTouchByte(portnum, 0xFF); } //-------------------------------------------------------------------------- // Set the 1-Wire Net communucation speed. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'new_speed' - new speed defined as // MODE_NORMAL 0x00 // MODE_OVERDRIVE 0x01 // // Returns: current 1-Wire Net speed // SMALLINT owSpeed_(int portnum, SMALLINT new_speed) { SETUP_PACKET setup; SMALLINT ret = 0; // set to change the speed setup.RequestTypeReservedBits = 0x40; setup.Request = MODE_CMD; setup.Value = MOD_1WIRE_SPEED; setup.Index = ((new_speed == MODE_OVERDRIVE) ? ONEWIREBUSSPEED_OVERDRIVE : ONEWIREBUSSPEED_FLEXIBLE) & 0x00FF; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return USBSpeed[portnum]; } else { // success, read the result USBSpeed[portnum] = new_speed; return new_speed; } } //-------------------------------------------------------------------------- // Set the 1-Wire Net line level. The values for new_level are // as follows: // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'new_level' - new level defined as // MODE_NORMAL 0x00 // MODE_STRONG5 0x02 // MODE_PROGRAM 0x04 (not supported in this version) // MODE_BREAK 0x08 (not supported in chip) // // Returns: current 1-Wire Net level // SMALLINT owLevel_(int portnum, SMALLINT new_level) { SETUP_PACKET setup; SMALLINT ret = 0; // Turn off infinite strong pullup? if ((new_level == MODE_NORMAL) && (USBLevel[portnum] == MODE_STRONG5)) { if (DS2490HaltPulse(usb_dev_handle_list[portnum])) USBLevel[portnum] = MODE_NORMAL; } // Turn on infinite strong5 pullup? else if ((new_level == MODE_STRONG5) && (USBLevel[portnum] == MODE_NORMAL)) { // assume duration set to infinite during setup of device // enable the pulse setup.RequestTypeReservedBits = 0x40; setup.Request = MODE_CMD; setup.Value = MOD_PULSE_EN; setup.Index = ENABLEPULSE_SPUE; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return USBLevel[portnum]; } // start the pulse setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_PULSE | COMM_IM; setup.Index = 0; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return USBLevel[portnum]; } else { // success, read the result USBLevel[portnum] = new_level; return new_level; } } // unsupported else if (new_level != USBLevel[portnum]) { OWERROR(OWERROR_FUNC_NOT_SUP); return USBLevel[portnum]; } // success, return the current level return USBLevel[portnum]; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE successful // FALSE program voltage not available // SMALLINT owProgramPulse_(int portnum) { SETUP_PACKET setup; SMALLINT ret = 0; // check if Vpp available if (!USBVpp[portnum]) return FALSE; // make sure strong pullup is not on if (USBLevel[portnum] == MODE_STRONG5) owLevel(portnum, MODE_NORMAL); // send the pulse (already enabled) setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_PULSE | COMM_IM | COMM_TYPE; setup.Index = 0; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } else return TRUE; } //-------------------------------------------------------------------------- // Description: // Delay for at least 'len' ms // void msDelay_(int len) { struct timespec s; // Set aside memory space on the stack s.tv_sec = len / 1000; s.tv_nsec = (len - (s.tv_sec * 1000)) * 1000000; nanosleep(&s, NULL); } //-------------------------------------------------------------------------- // Get the current millisecond tick count. Does not have to represent // an actual time, it just needs to be an incrementing timer. // int msGettick_(void) { struct timezone tmzone; struct timeval tmval; int ms; gettimeofday(&tmval, &tmzone); ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000; return ms; } //-------------------------------------------------------------------------- // Send and recieve 8 bits of communication to the 1-Wire Net. // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net to strong pullup // power delivery. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: Byte read: byte read (or echo if write) // 0: failure // SMALLINT owTouchBytePower(int portnum, SMALLINT sendbyte) { SETUP_PACKET setup; ushort nBytes; uchar buf[2]; SMALLINT ret = 0; // make sure strong pullup is not on if (USBLevel[portnum] == MODE_STRONG5) owLevel(portnum, MODE_NORMAL); // enable the strong pullup pulse setup.RequestTypeReservedBits = 0x40; setup.Request = MODE_CMD; setup.Value = MOD_PULSE_EN; setup.Index = ENABLEPULSE_SPUE; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } // set to do touchbyte with the SPU immediatly after setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_BYTE_IO | COMM_IM | COMM_SPU; setup.Index = sendbyte & 0xFF; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } else { // now strong pullup is enabled USBLevel[portnum] = MODE_STRONG5; // success, read the result nBytes = 1; if (DS2490Read(usb_dev_handle_list[portnum], buf, &nBytes)) return buf[0]; else { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } } } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // SMALLINT owWriteBytePower_(int portnum, SMALLINT sendbyte) { return (owTouchBytePower(portnum, sendbyte) == sendbyte); } //-------------------------------------------------------------------------- // Read 8 bits of communication from the 1-Wire net and provide strong // pullup power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: byte read // SMALLINT owReadBytePower_(int portnum) { return owTouchBytePower(portnum, 0xFF); } //-------------------------------------------------------------------------- // Read 1 bit of communication from the 1-Wire net and verify that the // response matches the 'applyPowerResponse' bit and apply power delivery // to the 1-Wire net. Note that some implementations may apply the power // first and then turn it off if the response is incorrect. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'applyPowerResponse' - 1 bit response to check, if correct then start // power delivery // // Returns: TRUE: bit written and response correct, strong pullup now on // FALSE: response incorrect // SMALLINT owReadBitPower_(int portnum, SMALLINT applyPowerResponse) { SETUP_PACKET setup; ushort nBytes; uchar buf[2]; SMALLINT ret = 0; // make sure strong pullup is not on if (USBLevel[portnum] == MODE_STRONG5) owLevel(portnum, MODE_NORMAL); // enable the strong pullup pulse setup.RequestTypeReservedBits = 0x40; setup.Request = MODE_CMD; setup.Value = MOD_PULSE_EN; setup.Index = ENABLEPULSE_SPUE; setup.Length = 0x00; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } // set to do touchbit setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D; setup.Index = 0; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } else { // now strong pullup is enabled USBLevel[portnum] = MODE_STRONG5; // success, read the result nBytes = 1; if (DS2490Read(usb_dev_handle_list[portnum], buf, &nBytes)) { // check response if (buf[0] != applyPowerResponse) { owLevel(portnum, MODE_NORMAL); return FALSE; } else return TRUE; } else { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } } } //-------------------------------------------------------------------------- // This procedure indicates wether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE because all userial adapters have over drive. // SMALLINT owHasPowerDelivery_(int portnum) { return TRUE; } //-------------------------------------------------------------------------- // This procedure indicates wether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE because all userial adapters have over drive. // SMALLINT owHasOverDrive_(int portnum) { return TRUE; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE program volatage available // FALSE program voltage not available // SMALLINT owHasProgramPulse_(int portnum) { owTouchReset(portnum); return USBVpp[portnum]; } //-------------------------------------------------------------------------- // Attempt to recover communication with the DS2490 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // indicate the port number. // // Returns: TRUE DS2490 recover successfull // FALSE failed to recover // SMALLINT AdapterRecover(int portnum) { // detect DS2490 and set it up if (DS2490Detect(usb_dev_handle_list[portnum])) { USBSpeed[portnum] = MODE_NORMAL; // current DS2490 1-Wire Net communication speed USBLevel[portnum] = MODE_NORMAL; // current DS2490 1-Wire Net level return TRUE; } else { OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); return FALSE; } } w1retap/src/libusblinux300/libusbnet.c000066400000000000000000000444631446446235200201730ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2004 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. //--------------------------------------------------------------------------- // // libusblnet.C - USB (DS2490) 1-Wire Public Domain API for network functions // for libusb Windows. (Requires libusb http://libusb.sourceforge.net // or http://libusb-win32.sourceforge.net) // // Version: 3.00 // // #include "ownet.h" #include "libusbds2490.h" // local functions defined in ownetu.c static SMALLINT bitacc(SMALLINT, SMALLINT, SMALLINT, uchar *); // external extern struct libusb_device_handle *usb_dev_handle_list[MAX_PORTNUM]; // global variables for this module to hold search state information static int LastDiscrepancy[MAX_PORTNUM]; static int LastFamilyDiscrepancy[MAX_PORTNUM]; static uchar LastDevice[MAX_PORTNUM]; uchar SerialNum[MAX_PORTNUM][8]; //-------------------------------------------------------------------------- // The 'owFirst' finds the first device on the 1-Wire Net This function // contains one parameter 'alarm_only'. When // 'alarm_only' is TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0 // // Returns: TRUE (1) : when a 1-Wire device was found and it's // Serial Number placed in the global SerialNum[portnum] // FALSE (0): There are no devices on the 1-Wire Net. // SMALLINT owFirst_(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { // reset the search state LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return owNext(portnum, do_reset, alarm_only); } //-------------------------------------------------------------------------- // The 'owNext' function does a general search. This function // continues from the previos search state. The search state // can be reset by using the 'owFirst' function. // This function contains one parameter 'alarm_only'. // When 'alarm_only' is TRUE (1) the find alarm command // 0xEC is sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0 // // Returns: TRUE (1) : when a 1-Wire device was found and it's // Serial Number placed in the global SerialNum[portnum] // FALSE (0): when no new device was found. Either the // last search was the last device or there // are no devices on the 1-Wire Net. // SMALLINT owNext_(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { SETUP_PACKET setup; short rt = FALSE, i, ResetSearch = FALSE; uchar rom_buf[16]; uchar ret_buf[16]; ushort buf_len; uchar lastcrc8; ushort nBytes = 8; int limit; STATUS_PACKET status; uchar nResult; SMALLINT ret = 0; // if the last call was the last one if (LastDevice[portnum]) { // reset the search LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return FALSE; } // check if reset first is requested if (do_reset) { // reset the 1-wire // extra reset if last part was a DS1994/DS2404 (due to alarm) if ((SerialNum[portnum][0] & 0x7F) == 0x04) owTouchReset(portnum); // if there are no parts on 1-wire, return FALSE if (!owTouchReset(portnum)) { // reset the search LastDiscrepancy[portnum] = 0; LastFamilyDiscrepancy[portnum] = 0; OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // build the rom number to put to the USB chip for (i = 0; i < 8; i++) rom_buf[i] = SerialNum[portnum][i]; // take into account LastDiscrepancy if (LastDiscrepancy[portnum] != 0xFF) { if (LastDiscrepancy[portnum] > 0) bitacc(WRITE_FUNCTION, 1, (short)(LastDiscrepancy[portnum] - 1), rom_buf); for (i = LastDiscrepancy[portnum]; i < 64; i++) bitacc(WRITE_FUNCTION, 0, i, rom_buf); } // put the ROM ID in EP2 nBytes = 8; if (!DS2490Write(usb_dev_handle_list[portnum], rom_buf, &nBytes)) { AdapterRecover(portnum); return FALSE; } // setup for search command call setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; // the number of devices to read (1) with the search command setup.Index = 0x0100 | (((alarm_only) ? 0xEC : 0xF0) & 0x00FF); setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure AdapterRecover(portnum); return FALSE; } // set a time limit limit = msGettick() + 200; // loop to wait on EP3 ready (device will go idle) do { // read the status to see if the pulse has been stopped if (!DS2490GetStatus(usb_dev_handle_list[portnum], &status, &nResult)) { // failure break; } else { // look for any fail conditions for (i = 0; i < nResult; i++) { // only check for error conditions when the condition is not a ONEWIREDEVICEDETECT if (status.CommResultCodes[i] != ONEWIREDEVICEDETECT) { // failure break; } } } } while (((status.StatusFlags & STATUSFLAGS_IDLE) == 0) && (limit > msGettick())); // check results of the waite for idel if ((status.StatusFlags & STATUSFLAGS_IDLE) == 0) { AdapterRecover(portnum); return FALSE; } // check for data if (status.ReadBufferStatus > 0) { // read the load buf_len = 16; if (!DS2490Read(usb_dev_handle_list[portnum], ret_buf, &buf_len)) { AdapterRecover(portnum); return FALSE; } // success, get rom and desrepancy LastDevice[portnum] = (buf_len == 8); // extract the ROM (and check crc) setcrc8(portnum, 0); for (i = 0; i < 8; i++) { SerialNum[portnum][i] = ret_buf[i]; lastcrc8 = docrc8(portnum, ret_buf[i]); } // crc OK and family code is not 0 if (!lastcrc8 && SerialNum[portnum][0]) { // loop through the descrepancy to get the pointers for (i = 0; i < 64; i++) { // if descrepancy if (bitacc(READ_FUNCTION, 0, i, &ret_buf[8]) && (bitacc(READ_FUNCTION, 0, i, &ret_buf[0]) == 0)) { LastDiscrepancy[portnum] = i + 1; } } rt = TRUE; } else { ResetSearch = TRUE; rt = FALSE; } } // check if need to reset search if (ResetSearch) { LastDiscrepancy[portnum] = 0xFF; LastDevice[portnum] = FALSE; for (i = 0; i < 8; i++) SerialNum[portnum][i] = 0; } return rt; } //-------------------------------------------------------------------------- // The 'owSerialNum' function either reads or sets the SerialNum buffer // that is used in the search functions 'owFirst' and 'owNext'. // This function contains two parameters, 'serialnum_buf' is a pointer // to a buffer provided by the caller. 'serialnum_buf' should point to // an array of 8 unsigned chars. The second parameter is a flag called // 'do_read' that is TRUE (1) if the operation is to read and FALSE // (0) if the operation is to set the internal SerialNum buffer from // the data in the provided buffer. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'serialnum_buf' - buffer to that contains the serial number to set // when do_read = FALSE (0) and buffer to get the serial // number when do_read = TRUE (1). // 'do_read' - flag to indicate reading (1) or setting (0) the current // serial number. // void owSerialNum_(int portnum, uchar *serialnum_buf, SMALLINT do_read) { uchar i; // read the internal buffer and place in 'serialnum_buf' if (do_read) { for (i = 0; i < 8; i++) serialnum_buf[i] = SerialNum[portnum][i]; } // set the internal buffer from the data in 'serialnum_buf' else { for (i = 0; i < 8; i++) SerialNum[portnum][i] = serialnum_buf[i]; } } //-------------------------------------------------------------------------- // Setup the search algorithm to find a certain family of devices // the next time a search function is called 'owNext'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'search_family' - family code type to set the search algorithm to find // next. // void owFamilySearchSetup_(int portnum, SMALLINT search_family) { uchar i; // set the search state to find search_family type devices SerialNum[portnum][0] = search_family; for (i = 1; i < 8; i++) SerialNum[portnum][i] = 0; LastDiscrepancy[portnum] = 64; LastFamilyDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; } //-------------------------------------------------------------------------- // Set the current search state to skip the current family code. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // void owSkipFamily_(int portnum) { // set the Last discrepancy to last family discrepancy LastDiscrepancy[portnum] = LastFamilyDiscrepancy[portnum]; // clear the last family discrpepancy LastFamilyDiscrepancy[portnum] = 0; // check for end of list if (LastDiscrepancy[portnum] == 0) LastDevice[portnum] = TRUE; } //-------------------------------------------------------------------------- // The 'owAccess' function resets the 1-Wire and sends a MATCH Serial // Number command followed by the current SerialNum code. After this // function is complete the 1-Wire device is ready to accept device-specific // commands. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE (1) : reset indicates present and device is ready // for commands. // FALSE (0): reset does not indicate presence or echos 'writes' // are not correct. // SMALLINT owAccess_(int portnum) { uchar sendpacket[9]; uchar i; // reset the 1-wire if (owTouchReset(portnum)) { // create a buffer to use with block function // match Serial Number command 0x55 sendpacket[0] = 0x55; // Serial Number for (i = 1; i < 9; i++) sendpacket[i] = SerialNum[portnum][i - 1]; // send/recieve the transfer buffer if (owBlock(portnum, FALSE, sendpacket, 9)) { // verify that the echo of the writes was correct for (i = 1; i < 9; i++) if (sendpacket[i] != SerialNum[portnum][i - 1]) return FALSE; if (sendpacket[0] != 0x55) { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } else return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // reset or match echo failed return FALSE; } //---------------------------------------------------------------------- // The function 'owVerify' verifies that the current device // is in contact with the 1-Wire Net. // Using the find alarm command 0xEC will verify that the device // is in contact with the 1-Wire Net and is in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'alarm_only' - TRUE (1) the find alarm command 0xEC // is sent instead of the normal search // command 0xF0. // // Returns: TRUE (1) : when the 1-Wire device was verified // to be on the 1-Wire Net // with alarm_only == FALSE // or verified to be on the 1-Wire Net // AND in an alarm state when // alarm_only == TRUE. // FALSE (0): the 1-Wire device was not on the // 1-Wire Net or if alarm_only // == TRUE, the device may be on the // 1-Wire Net but in a non-alarm state. // SMALLINT owVerify_(int portnum, SMALLINT alarm_only) { uchar i, sendlen = 0, goodbits = 0, cnt = 0, s, tst; uchar sendpacket[50]; // construct the search rom if (alarm_only) sendpacket[sendlen++] = 0xEC; // issue the alarming search command else sendpacket[sendlen++] = 0xF0; // issue the search command // set all bits at first for (i = 1; i <= 24; i++) sendpacket[sendlen++] = 0xFF; // now set or clear apropriate bits for search for (i = 0; i < 64; i++) bitacc(WRITE_FUNCTION, bitacc(READ_FUNCTION, 0, i, &SerialNum[portnum][0]), (int)((i + 1) * 3 - 1), &sendpacket[1]); // send/recieve the transfer buffer if (owBlock(portnum, TRUE, sendpacket, sendlen)) { // check results to see if it was a success for (i = 0; i < 192; i += 3) { tst = (bitacc(READ_FUNCTION, 0, i, &sendpacket[1]) << 1) | bitacc(READ_FUNCTION, 0, (int)(i + 1), &sendpacket[1]); s = bitacc(READ_FUNCTION, 0, cnt++, &SerialNum[portnum][0]); if (tst == 0x03) { // no device on line goodbits = 0; // number of good bits set to zero break; // quit } if (((s == 0x01) && (tst == 0x02)) || ((s == 0x00) && (tst == 0x01))) // correct bit goodbits++; // count as a good bit } // check too see if there were enough good bits to be successful if (goodbits >= 8) return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); // block fail or device not present return FALSE; } //---------------------------------------------------------------------- // Perform a overdrive MATCH command to select the 1-Wire device with // the address in the ID data register. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE: If the device is present on the 1-Wire Net and // can do overdrive then the device is selected. // FALSE: Device is not present or not capable of overdrive. // // *Note: This function could be converted to send DS2480 // commands in one packet. // SMALLINT owOverdriveAccess_(int portnum) { uchar sendpacket[8]; uchar i, bad_echo = FALSE; // make sure normal level owLevel(portnum, MODE_NORMAL); // force to normal communication speed owSpeed(portnum, MODE_NORMAL); // call the 1-Wire Net reset function if (owTouchReset(portnum)) { // send the match command 0x69 if (owWriteByte(portnum, 0x69)) { // switch to overdrive communication speed owSpeed(portnum, MODE_OVERDRIVE); // create a buffer to use with block function // Serial Number for (i = 0; i < 8; i++) sendpacket[i] = SerialNum[portnum][i]; // send/recieve the transfer buffer if (owBlock(portnum, FALSE, sendpacket, 8)) { // verify that the echo of the writes was correct for (i = 0; i < 8; i++) if (sendpacket[i] != SerialNum[portnum][i]) bad_echo = TRUE; // if echo ok then success if (!bad_echo) return TRUE; else OWERROR(OWERROR_WRITE_VERIFY_FAILED); } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_WRITE_BYTE_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // failure, force back to normal communication speed owSpeed(portnum, MODE_NORMAL); return FALSE; } //-------------------------------------------------------------------------- // Bit utility to read and write a bit in the buffer 'buf'. // // 'op' - operation (1) to set and (0) to read // 'state' - set (1) or clear (0) if operation is write (1) // 'loc' - bit number location to read or write // 'buf' - pointer to array of bytes that contains the bit // to read or write // // Returns: 1 if operation is set (1) // 0/1 state of bit number 'loc' if operation is reading // static SMALLINT bitacc(SMALLINT op, SMALLINT state, SMALLINT loc, uchar *buf) { SMALLINT nbyt, nbit; nbyt = (loc / 8); nbit = loc - (nbyt * 8); if (op == WRITE_FUNCTION) { if (state) buf[nbyt] |= (0x01 << nbit); else buf[nbyt] &= ~(0x01 << nbit); return 1; } else return ((buf[nbyt] >> nbit) & 0x01); } w1retap/src/libusblinux300/libusbses.c000066400000000000000000000172171446446235200201740ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2004 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. //--------------------------------------------------------------------------- // // libusblses.c - Acquire and release a Session on the 1-Wire Net using the // USB interface DS2490. (Requires libusb // http://libusb.sourceforge.net or // http://libusb-win32.sourceforge.net) // // // Version: 3.00 // // History: // #include "ownet.h" #include "libusbds2490.h" #include #include #include // local functions static void DS2490Discover(void); // handles to USB ports libusb_device_handle *usb_dev_handle_list[MAX_PORTNUM]; // struct usb_dev_handle *usb_dev_handle_list[MAX_PORTNUM]; struct libusb_device *usb_dev_list[MAX_PORTNUM]; int usb_num_devices = -1; static SMALLINT usbhnd_init = 0; //--------------------------------------------------------------------------- // Attempt to acquire a 1-Wire net using a USB port and a DS2490 based // adapter. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'port_zstr' - zero terminated port name. For this platform // use format 'DS2490-X' where X is the port number. // // Returns: TRUE - success, USB port opened // SMALLINT owAcquire_(int portnum, char *port_zstr) { int retportnum = 0; retportnum = owAcquireEx(port_zstr); if ((retportnum < 0) || (retportnum != portnum)) { // Failure from owAcquireEx or from not matching port numbers. return FALSE; } return TRUE; } //--------------------------------------------------------------------------- // Attempt to acquire the specified 1-Wire net. // // 'port_zstr' - zero terminated port name. For this platform // use format 'DS2490-X' where X is the port number. // // Returns: port number or -1 if not successful in setting up the port. // int owAcquireEx_(char *port_zstr) { int portnum = -1; if (strncasecmp(port_zstr, "DS2490", 6) == 0 || strncmp(port_zstr, "USB", 3) == 0) { char *q0 = strdup(port_zstr); char *q = q0; strsep(&q, ":-"); if (q != NULL && *q != 0) { portnum = strtol(q, NULL, 10); } else { portnum = 1; } free(q0); } if (portnum < 1) { OWERROR(OWERROR_PORTNUM_ERROR); return -1; } if (!usbhnd_init) { // check to see the USB bus has been setup properly // discover all DS2490s on USB bus... DS2490Discover(); usbhnd_init = 1; } // check to see if the portnumber is valid if ((usb_num_devices < portnum) || (portnum == 0)) { // error - Attempted to select invalid port number OWERROR(OWERROR_LIBUSB_NO_ADAPTER_FOUND); return -1; } // check to see if opening the device is valid if (usb_dev_handle_list[portnum] != NULL) { // error - USB Device already open OWERROR(OWERROR_LIBUSB_DEVICE_ALREADY_OPENED); return -1; } // open the device int err = libusb_open(usb_dev_list[portnum], &usb_dev_handle_list[portnum]); if (err < 0) { // Failed to open usb device OWERROR(OWERROR_LIBUSB_OPEN_FAILED); return -1; } libusb_set_auto_detach_kernel_driver(usb_dev_handle_list[portnum], 1); // if (libusb_has_capability(LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER) >= 0 ) { // err = libusb_detach_kernel_driver(usb_dev_handle_list[portnum], 0); //} // set the configuration if (libusb_set_configuration(usb_dev_handle_list[portnum], 1)) { // Failed to set configuration OWERROR(OWERROR_LIBUSB_SET_CONFIGURATION_ERROR); libusb_close(usb_dev_handle_list[portnum]); // close handle return -1; } // claim the interface if (libusb_claim_interface(usb_dev_handle_list[portnum], 0)) { // Failed to claim interface OWERROR(OWERROR_LIBUSB_CLAIM_INTERFACE_ERROR); libusb_close(usb_dev_handle_list[portnum]); // close handle return -1; } // set the alt interface int rc; if ((rc = libusb_set_interface_alt_setting(usb_dev_handle_list[portnum], 0, 3))) { // Failed to set altinterface OWERROR(OWERROR_LIBUSB_SET_ALTINTERFACE_ERROR); libusb_release_interface(usb_dev_handle_list[portnum], 0); // release interface libusb_close(usb_dev_handle_list[portnum]); // close handle return -1; } // clear USB endpoints before doing anything with them. libusb_clear_halt(usb_dev_handle_list[portnum], DS2490_EP3); libusb_clear_halt(usb_dev_handle_list[portnum], DS2490_EP2); libusb_clear_halt(usb_dev_handle_list[portnum], DS2490_EP1); // verify adapter is working if (!AdapterRecover(portnum)) { libusb_release_interface(usb_dev_handle_list[portnum], 0); // release interface libusb_close(usb_dev_handle_list[portnum]); // close handle return -1; } // reset the 1-Wire owTouchReset(portnum); return portnum; } //--------------------------------------------------------------------------- // Release the port previously acquired a 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // void owRelease_(int portnum) { libusb_release_interface(usb_dev_handle_list[portnum], 0); libusb_close(usb_dev_handle_list[portnum]); usb_dev_handle_list[portnum] = NULL; } static libusb_device **dev_list = NULL; static libusb_context *ctx; void __attribute__((destructor)) w1usb_tear_down(void) { for (int i = 0; i < usb_num_devices; i++) { if (usb_dev_handle_list[i] != NULL) { libusb_release_interface(usb_dev_handle_list[i], 0); libusb_close(usb_dev_handle_list[i]); usb_dev_handle_list[i] = NULL; } } libusb_free_device_list(dev_list, 0); libusb_exit(ctx); } void owShowVersion_(void) { const struct libusb_version *v = libusb_get_version(); fprintf(stderr, "libusb: %d.%d.%d.%d\n", v->major, v->minor, v->micro, v->nano); } //--------------------------------------------------------------------------- // Discover all DS2490s on bus // void DS2490Discover(void) { // initialize USB subsystem libusb_init(&ctx); usb_num_devices = 0; int n = libusb_get_device_list(ctx, &dev_list); for (int i = 0; i < n; i++) { libusb_device *dev = dev_list[i]; struct libusb_device_descriptor desc; int err; err = libusb_get_device_descriptor(dev, &desc); if (err >= 0) { if (desc.idVendor == 0x04FA && desc.idProduct == 0x2490) { usb_dev_list[++usb_num_devices] = dev; } } } } w1retap/src/libusblinux300/libusbtran.c000066400000000000000000000215351446446235200203440ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2004 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. //--------------------------------------------------------------------------- // // libusbltran.C - USB (DS2490) transport functions for 1-Wire Public Domain. // (Requires libusb http://libusb.sourceforge.net or // http://libusb-win32.sourceforge.net) // // Version: 3.00 // #include "ownet.h" #include "libusbds2490.h" // handles to USB ports extern struct libusb_device_handle *usb_dev_handle_list[MAX_PORTNUM]; //-------------------------------------------------------------------------- // The 'owBlock' transfers a block of data to and from the // 1-Wire Net with an optional reset at the begining of communication. // The result is returned in the same buffer. // // 'do_reset' - cause a owTouchReset to occure at the begining of // communication TRUE(1) or not FALSE(0) // 'tran_buf' - pointer to a block of unsigned // chars of length 'TranferLength' that will be sent // to the 1-Wire Net // 'tran_len' - length in bytes to transfer // // Supported devices: all // // Returns: TRUE (1) : The optional reset returned a valid // presence (do_reset == TRUE) or there // was no reset required. // FALSE (0): The reset did not return a valid prsence // (do_reset == TRUE). // // The maximum tran_length is (160) // SMALLINT owBlock_(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len) { SETUP_PACKET setup; STATUS_PACKET status; SMALLINT command_issued = FALSE; ushort bytes_index = 0; ushort nBytesLeft = tran_len; ushort block_len; ushort block_write; ushort loopcount; SMALLINT ret = 0; uchar dmmy = 0; // check if need to do a owTouchReset first if (do_reset) { if (!owTouchReset(portnum)) return FALSE; } // check for a block too big if (tran_len > 192) { OWERROR(OWERROR_BLOCK_TOO_BIG); return FALSE; } // loop to write in blocks of 64 while (nBytesLeft > 0) { // Put the bytes of data in EP2 (Warning: do not overfill EP2 FIFO) // Let's begin by sending 64 bytes to EP2, then send the vendor command (EP0), // followed by additional data (while monitoring EP2 FIFO). if (nBytesLeft > 64) block_len = 64; else block_len = nBytesLeft; // fill EP2 block_write = block_len; if (!DS2490Write(usb_dev_handle_list[portnum], &tran_buf[bytes_index], &block_write)) { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } // check for write incomplete if (block_write != block_len) { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } // check for one time send of block IO command if (!command_issued) { // send vendor command setup.RequestTypeReservedBits = 0x40; setup.Request = COMM_CMD; setup.Value = COMM_BLOCK_IO | COMM_IM | COMM_F; setup.Index = tran_len; setup.Length = 0; setup.DataOut = FALSE; // call the libusb driver ret = libusb_control_transfer(usb_dev_handle_list[portnum], setup.RequestTypeReservedBits, setup.Request, setup.Value, setup.Index, NULL, setup.Length, TIMEOUT_LIBUSB); if (ret < 0) { // failure OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } command_issued = TRUE; } // check whether device idle, block_len bytes ready for read // and wait for byte's arrival if necessary loopcount = 200; do { if (!DS2490GetStatus(usb_dev_handle_list[portnum], &status, &dmmy)) { AdapterRecover(portnum); return FALSE; } msDelay(1); } while (!(status.StatusFlags & STATUSFLAGS_IDLE) && (status.ReadBufferStatus < block_len) && (loopcount-- > 0)); // check for timeout if ((loopcount == 0) && (status.ReadBufferStatus < block_len)) { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } // read response on previous write block_write = block_len; if (!DS2490Read(usb_dev_handle_list[portnum], &tran_buf[bytes_index], &block_write)) { AdapterRecover(portnum); return FALSE; } // check for read incomplete if (block_write != block_len) { OWERROR(OWERROR_ADAPTER_ERROR); AdapterRecover(portnum); return FALSE; } // adjust buffer's pointers nBytesLeft = nBytesLeft - block_len; bytes_index = bytes_index + block_len; } return TRUE; } //-------------------------------------------------------------------------- // Write a byte to an EPROM 1-Wire device. // // Supported devices: crc_type=0(CRC8) // DS1982 // crc_type=1(CRC16) // DS1985, DS1986, DS2407 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'write_byte' - byte to program // 'addr' - address of byte to program // 'write_cmd' - command used to write (0x0F reg mem, 0x55 status) // 'crc_type' - CRC used (0 CRC8, 1 CRC16) // 'do_access' - Flag to access device for each byte // (0 skip access, 1 do the access) // WARNING, only use do_access=0 if programing the NEXT // byte immediatly after the previous byte. // // Returns: >=0 success, this is the resulting byte from the program // effort // -1 error, device not connected or program pulse voltage // not available // SMALLINT owProgramByte_(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access) { ushort lastcrc16; uchar lastcrc8; // optionally access the device if (do_access) { if (!owAccess(portnum)) { OWERROR(OWERROR_ACCESS_FAILED); return -1; } // send the write command if (!owWriteByte(portnum, write_cmd)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // send the address if (!owWriteByte(portnum, addr & 0xFF) || !owWriteByte(portnum, addr >> 8)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } } // send the data to write if (!owWriteByte(portnum, write_byte)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // read the CRC if (crc_type == 0) { // calculate CRC8 if (do_access) { setcrc8(portnum, 0); docrc8(portnum, (uchar)write_cmd); docrc8(portnum, (uchar)(addr & 0xFF)); docrc8(portnum, (uchar)(addr >> 8)); } else setcrc8(portnum, (uchar)(addr & 0xFF)); docrc8(portnum, (uchar)write_byte); // read and calculate the read crc lastcrc8 = docrc8(portnum, (uchar)owReadByte(portnum)); // crc should now be 0x00 if (lastcrc8 != 0) { OWERROR(OWERROR_CRC_FAILED); return -1; } } else { // CRC16 if (do_access) { setcrc16(portnum, 0); docrc16(portnum, (ushort)write_cmd); docrc16(portnum, (ushort)(addr & 0xFF)); docrc16(portnum, (ushort)(addr >> 8)); } else setcrc16(portnum, (ushort)addr); docrc16(portnum, (ushort)write_byte); // read and calculate the read crc docrc16(portnum, (ushort)owReadByte(portnum)); lastcrc16 = docrc16(portnum, (ushort)owReadByte(portnum)); // crc should now be 0xB001 if (lastcrc16 != 0xB001) return -1; } // send the program pulse if (!owProgramPulse(portnum)) { OWERROR(OWERROR_PROGRAM_PULSE_FAILED); return -1; } // read back and return the resulting byte return owReadByte(portnum); } w1retap/src/libusblinux300/linuxlnk.c000066400000000000000000000311051446446235200200350ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // linuxlnk.C - COM functions required by MLANLL.C, MLANTRNU, MLANNETU.C and // MLanFile.C for MLANU to communicate with the DS2480 based // Universal Serial Adapter 'U'. Fill in the platform specific code. // // Version: 1.02 // // History: 1.00 -> 1.01 Added function msDelay. // // 1.01 -> 1.02 Changed to generic OpenCOM/CloseCOM for easier // use with other platforms. // //-------------------------------------------------------------------------- // Copyright (C) 1998 Andrea Chambers and University of Newcastle upon Tyne, // All Rights Reserved. //-------------------------------------------------------------------------- // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE UNIVERSITY OF NEWCASTLE UPON TYNE OR ANDREA CHAMBERS // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //--------------------------------------------------------------------------- // // LinuxLNK.C - COM functions required by MLANLLU.C, MLANTRNU.C, MLANNETU.C // and MLanFile.C for MLANU to communicate with the DS2480 based // Universal Serial Adapter 'U'. Platform specific code. // // Version: 2.01 // History: 1.02 -> 1.03 modifications by David Smiczek // Changed to use generic OpenCOM/CloseCOM // Pass port name to OpenCOM instead of hard coded // Changed msDelay to handle long delays // Reformatted to look like 'TODO.C' // Added #include "ds2480.h" to use constants. // Added function SetBaudCOM() // Added function msGettick() // Removed delay from WriteCOM(), used tcdrain() // Added wait for byte available with timeout using // select() in ReadCOM() // // 1.03 -> 2.00 Support for multiple ports. Include "ownet.h". Use // 'uchar'. Reorder functions. Provide correct // return values to OpenCOM. Replace 'makeraw' call. // Should now be POSIX. // 2.00 -> 2.01 Added support for owError library. // #include #include #include #include #include #include #include #include #include #include "ds2480.h" #include "ownet.h" // LinuxLNK global int fd[MAX_PORTNUM]; SMALLINT fd_init; struct termios origterm; //--------------------------------------------------------------------------- // Attempt to open a com port. Keep the handle in ComID. // Set the starting baud rate to 9600. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will // be used to indicate the port number desired when calling // all other functions in this library. // // // Returns: the port number if it was succesful otherwise -1 // int OpenCOMEx(char *port_zstr) { int i; int portnum; if (!fd_init) { for (i = 0; i < MAX_PORTNUM; i++) fd[i] = 0; fd_init = 1; } // check to find first available handle slot for (portnum = 0; portnum < MAX_PORTNUM; portnum++) { if (!fd[portnum]) break; } OWASSERT(portnum < MAX_PORTNUM, OWERROR_PORTNUM_ERROR, -1); if (!OpenCOM(portnum, port_zstr)) { return -1; } return portnum; } //--------------------------------------------------------------------------- // Attempt to open a com port. // Set the starting baud rate to 9600. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will // be used to indicate the port number desired when calling // all other functions in this library. // // 'port_zstr' - zero terminate port name. For this platform // use format COMX where X is the port number. // // // Returns: TRUE(1) - success, COM port opened // FALSE(0) - failure, could not open specified port // SMALLINT OpenCOM(int portnum, char *port_zstr) { struct termios t; // see man termios - declared as above int rc; if (!fd_init) { int i; for (i = 0; i < MAX_PORTNUM; i++) fd[i] = 0; fd_init = 1; } OWASSERT(portnum < MAX_PORTNUM && portnum >= 0 && !fd[portnum], OWERROR_PORTNUM_ERROR, FALSE); fd[portnum] = open(port_zstr, O_RDWR | O_NONBLOCK); if (fd[portnum] < 0) { OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED); return FALSE; // changed (2.00), used to return fd; } rc = tcgetattr(fd[portnum], &t); if (rc < 0) { int tmp; tmp = errno; close(fd[portnum]); errno = tmp; OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); return FALSE; // changed (2.00), used to return rc; } cfsetospeed(&t, B9600); cfsetispeed(&t, B9600); // Get terminal parameters. (2.00) removed raw tcgetattr(fd[portnum], &t); // Save original settings. origterm = t; // Set to non-canonical mode, and no RTS/CTS handshaking t.c_iflag &= ~(BRKINT | ICRNL | IGNCR | INLCR | INPCK | ISTRIP | IXON | IXOFF | PARMRK); t.c_iflag |= IGNBRK | IGNPAR; t.c_oflag &= ~(OPOST); t.c_cflag &= ~(CRTSCTS | CSIZE | HUPCL | PARENB); t.c_cflag |= (CLOCAL | CS8 | CREAD); t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG); t.c_cc[VMIN] = 0; t.c_cc[VTIME] = 3; rc = tcsetattr(fd[portnum], TCSAFLUSH, &t); tcflush(fd[portnum], TCIOFLUSH); if (rc < 0) { int tmp; tmp = errno; close(fd[portnum]); errno = tmp; OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); return FALSE; // changed (2.00), used to return rc; } return TRUE; // changed (2.00), used to return fd; } //--------------------------------------------------------------------------- // Closes the connection to the port. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void CloseCOM(int portnum) { // restore tty settings tcsetattr(fd[portnum], TCSAFLUSH, &origterm); FlushCOM(portnum); close(fd[portnum]); fd[portnum] = 0; } //-------------------------------------------------------------------------- // Write an array of bytes to the COM port, verify that it was // sent out. Assume that baud rate has been set. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will // be used to indicate the port number desired when calling // all other functions in this library. // Returns 1 for success and 0 for failure // SMALLINT WriteCOM(int portnum, int outlen, uchar *outbuf) { long count = outlen; int i = write(fd[portnum], outbuf, outlen); tcdrain(fd[portnum]); return (i == count); } //-------------------------------------------------------------------------- // Read an array of bytes to the COM port, verify that it was // sent out. Assume that baud rate has been set. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'outlen' - number of bytes to write to COM port // 'outbuf' - pointer ot an array of bytes to write // // Returns: TRUE(1) - success // FALSE(0) - failure // int ReadCOM(int portnum, int inlen, uchar *inbuf) { fd_set filedescr; struct timeval tval; int cnt; // loop to wait until each byte is available and read it for (cnt = 0; cnt < inlen; cnt++) { // set a descriptor to wait for a character available FD_ZERO(&filedescr); FD_SET(fd[portnum], &filedescr); // set timeout to 10ms tval.tv_sec = 0; tval.tv_usec = 10000; // if byte available read or return bytes read if (select(fd[portnum] + 1, &filedescr, NULL, NULL, &tval) != 0) { if (read(fd[portnum], &inbuf[cnt], 1) != 1) return cnt; } else return cnt; } // success, so return desired length return inlen; } //--------------------------------------------------------------------------- // Description: // flush the rx and tx buffers // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void FlushCOM(int portnum) { tcflush(fd[portnum], TCIOFLUSH); } //-------------------------------------------------------------------------- // Description: // Send a break on the com port for at least 2 ms // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void BreakCOM(int portnum) { int duration = 0; // see man termios break may be tcsendbreak(fd[portnum], duration); // too long } //-------------------------------------------------------------------------- // Set the baud rate on the com port. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'new_baud' - new baud rate defined as // PARMSET_9600 0x00 // PARMSET_19200 0x02 // PARMSET_57600 0x04 // PARMSET_115200 0x06 // void SetBaudCOM(int portnum, uchar new_baud) { struct termios t; int rc; speed_t baud = 0; // read the attribute structure rc = tcgetattr(fd[portnum], &t); if (rc < 0) { close(fd[portnum]); return; } // convert parameter to linux baud rate switch (new_baud) { case PARMSET_9600: baud = B9600; break; case PARMSET_19200: baud = B19200; break; case PARMSET_57600: baud = B57600; break; case PARMSET_115200: baud = B115200; break; } // set baud in structure cfsetospeed(&t, baud); cfsetispeed(&t, baud); // change baud on port rc = tcsetattr(fd[portnum], TCSAFLUSH, &t); if (rc < 0) close(fd[portnum]); } //-------------------------------------------------------------------------- // Get the current millisecond tick count. Does not have to represent // an actual time, it just needs to be an incrementing timer. // int msGettick_(void) { struct timezone tmzone; struct timeval tmval; long ms; gettimeofday(&tmval, &tmzone); ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000; return ms; } //-------------------------------------------------------------------------- // Description: // Delay for at least 'len' ms // void msDelay_(int len) { struct timespec s; // Set aside memory space on the stack s.tv_sec = len / 1000; s.tv_nsec = (len - (s.tv_sec * 1000)) * 1000000; nanosleep(&s, NULL); } w1retap/src/libusblinux300/mbappreg.c000066400000000000000000000750501446446235200177750ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // mbAppReg.c - Reads and writes to memory locations for the AppReg memory bank. // version 1.00 // // Include Files #include "ownet.h" #include "mbappreg.h" // General command defines #define READ_MEMORY_COMMAND 0xC3 #define WRITE_MEMORY_COMMAND 0x99 #define COPY_LOCK_COMMAND 0x5A #define READ_STATUS_COMMAND 0x66 #define VALIDATION_KEY 0xA5 #define LOCKED_FLAG 0xFC // Local defines #define SIZE 8 #define PAGE_LENGTH 8 // Global variables char *bankDescriptionAR = "Application register, non-volatile when locked."; SMALLINT writeVerificationAR = TRUE; SMALLINT generalPurposeMemoryAR = TRUE; SMALLINT readWriteAR = TRUE; SMALLINT writeOnceAR = FALSE; SMALLINT readOnlyAR = FALSE; SMALLINT nonVolatileAR = FALSE; SMALLINT needsProgramPulseAR = FALSE; SMALLINT needsPowerDeliveryAR = TRUE; SMALLINT hasExtraInfoAR = TRUE; SMALLINT extraInfoLengthAR = 1; char *extraInfoDescAR = "Page Locked Flag"; SMALLINT pageAutoCRCAR = FALSE; SMALLINT canRedirectPageAR = FALSE; SMALLINT canLockPageAR = TRUE; SMALLINT canLockRedirecPageAR = FALSE; /** * Read memory in the current 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 readPagePackeAppRegt() method or have * the 1-Wire device provide the CRC as in readPageCRCAppReg(). readPageCRCAppReg() * however is not supported on all memory types, see 'hasPageAutoCRCAppReg()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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 read is * to be done on. * str_add starting physical address * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array to place read data into * len length in bytes to read * * @return 'true' if the read was complete */ SMALLINT readAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) { uchar raw_buf[2]; int i; // check if read exceeds memory if ((str_add + len) > PAGE_LENGTH) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // start the read raw_buf[0] = READ_MEMORY_COMMAND; raw_buf[1] = str_add & 0xFF; if (!owBlock(portnum, FALSE, raw_buf, 2)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } for (i = 0; i < len; i++) buff[i] = 0xFF; if (!owBlock(portnum, FALSE, buff, len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Write memory in the current bank. It is recommended that * when writing data that some structure in the data is created * to provide error free reading back with readAppReg(). Or the * method 'writePagePacketAppReg()' could be used which automatically * wraps the data in a length and CRC. * * When using on Write-Once devices care must be taken to write into * into empty space. If writeAppReg() 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 write is * to be done on. * str_add starting address * buff byte array containing data to write * len length in bytes to write * * @return 'true' if the write was complete. */ SMALLINT writeAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) { uchar raw_buf[64]; int i; // return if nothing to do if (len == 0) return TRUE; // check if power delivery is available /* if(!owDeliverPower()) { OWERROR(OWERROR_NO_POWER_DELIVERY); return FALSE; }*/ // check if write exceeds memory if ((str_add + len) > PAGE_LENGTH) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // start the write raw_buf[0] = WRITE_MEMORY_COMMAND; raw_buf[1] = str_add & 0xFF; for (i = 0; i < len; i++) raw_buf[i + 2] = buff[i]; if (!owBlock(portnum, FALSE, raw_buf, len + 2)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // check for write verification if (writeVerificationAR) { // read back if (!readAppReg(bank, portnum, SNum, str_add, TRUE, raw_buf, len)) { return FALSE; } // compare for (i = 0; i < len; i++) { if (raw_buf[i] != buff[i]) { OWERROR(OWERROR_READ_BACK_INCORRECT); return FALSE; } } } return TRUE; } /** * Read page in the current 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 * readPagePacketAppReg() method or have the 1-Wire device provide the * CRC as in readPageCRCAppReg(). readPageCRCAppReg() however is not * supported on all memory types, see 'hasPageAutoCRCAppReg()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageAppReg(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { // check if for valid page if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } // do the read if (!readAppReg(bank, portnum, SNum, page * PAGE_LENGTH, TRUE, buff, PAGE_LENGTH)) return FALSE; return TRUE; } /** * Read page with extra information in the current 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 * readPagePacketAppReg() method or have the 1-Wire device provide the * CRC as in readPageCRCAppReg(). readPageCRCAppReg() however is not * supported on all memory types, see 'hasPageAutoCRCAppReg()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoAppReg()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraAppReg(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } // read the page data if (!readAppReg(bank, portnum, SNum, page * PAGE_LENGTH, TRUE, buff, PAGE_LENGTH)) return FALSE; // read the extra information (status) if (!readStatus(portnum, extra)) { OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE); return FALSE; } return TRUE; } /** * Read page with extra information in the current 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 * readPagePacket() method or have the 1-Wire device provide the * CRC as in readPageCRC(). readPageCRC() however is not * supported on all memory types, see 'hasPageAutoCRC()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'haveExtraInfo()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCAppReg(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { // read the page data if (!readAppReg(bank, portnum, SNum, page * PAGE_LENGTH, TRUE, read_buff, PAGE_LENGTH)) return FALSE; // read the extra information (status) if (!readStatus(portnum, extra)) { OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE); return FALSE; } return TRUE; } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCAppReg()'. * * 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. * page the page to be read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff) { OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketAppReg(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH]; ushort lastcrc16 = 0; int i; // read the entire page data if (!readAppReg(bank, portnum, SNum, page, rd_cont, raw_buf, PAGE_LENGTH)) { return FALSE; } // check if length is realistic if ((raw_buf[0] > (PAGE_LENGTH - 2)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressAppReg(bank, SNum) / PAGE_LENGTH) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { *len = (int)raw_buf[0]; // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketAppReg()' for a description of the packet structure. * See the method 'hasExtraInfoAppReg()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraAppReg(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { uchar raw_buf[32]; int i; ushort lastcrc16 = 0; // check if current bank is not scratchpad bank, or not page 0 if (!hasExtraInfoAppReg(bank, SNum)) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } // read the entire page data if (!readAppReg(bank, portnum, SNum, page * PAGE_LENGTH, TRUE, raw_buf, PAGE_LENGTH)) { return FALSE; } // check if length is realistic if ((raw_buf[0] > (PAGE_LENGTH - 2)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressAppReg(bank, SNum) / PAGE_LENGTH) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { *len = (int)raw_buf[0]; if (!readStatus(portnum, extra)) { OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE); return FALSE; } // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Write a Universal Data Packet. See the method 'readPagePacketAppReg()' * 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. * page the page the packet is being written to. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketAppReg(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[PAGE_LENGTH]; ushort crc = 0; int i; // make sure length does not exceed max if ((len > (PAGE_LENGTH - 2)) || (len <= 0)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } raw_buf[0] = (uchar)len; for (i = 0; i < len; i++) raw_buf[i + 1] = buff[i]; setcrc16(portnum, (ushort)((getStartingAddressAppReg(bank, SNum) / PAGE_LENGTH) + page)); for (i = 0; i < len + 1; i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = (uchar)~crc & 0xFF; raw_buf[len + 2] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (!writeAppReg(bank, portnum, SNum, page * PAGE_LENGTH, raw_buf, len + 3)) return FALSE; return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesAppReg(SMALLINT bank, uchar *SNum) { return 1; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeAppReg(SMALLINT bank, uchar *SNum) { return SIZE; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressAppReg(SMALLINT bank, uchar *SNum) { return 0; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthAppReg(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionAppReg(SMALLINT bank, uchar *SNum) { return bankDescriptionAR; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemoryAppReg(SMALLINT bank, uchar *SNum) { return generalPurposeMemoryAR; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteAppReg(SMALLINT bank, int portnum, uchar *SNum) { return readWriteAR; } /** * 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. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlyAppReg(SMALLINT bank, int portnum, uchar *SNum) { return readOnlyAR; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceAppReg(SMALLINT bank, int portnum, uchar *SNum) { return writeOnceAR; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileAppReg(SMALLINT bank, uchar *SNum) { return nonVolatileAR; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseAppReg(SMALLINT bank, uchar *SNum) { return needsProgramPulseAR; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliveryAppReg(SMALLINT bank, uchar *SNum) { return needsPowerDeliveryAR; } /** * 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoAppReg(SMALLINT bank, uchar *SNum) { return hasExtraInfoAR; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoAppReg()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthAppReg(SMALLINT bank, uchar *SNum) { return extraInfoLengthAR; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoAppReg()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescAppReg(SMALLINT bank, uchar *SNum) { return extraInfoDescAR; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCAppReg()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCAppReg(SMALLINT bank, uchar *SNum) { return pageAutoCRCAR; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthAppReg(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH - 3; } //-------- //-------- OTPMemoryBank query methods //-------- /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageAppReg(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageAppReg(SMALLINT bank, uchar *SNum) { return TRUE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageAppReg(SMALLINT bank, uchar *SNum) { return FALSE; } //-------- //-------- OTPMemoryBank I/O methods //-------- /** * Lock the specifed page in the current memory bank. Not supported * by all devices. See the method 'canLockPage()'. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * page the page to be used. * * @return 'true' if page is locked. */ SMALLINT lockPageAppReg(int portnum, int page, uchar *SNum) { // select the device owSerialNum(portnum, SNum, FALSE); if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // do the copy/lock sequence if (!(owWriteByte(portnum, COPY_LOCK_COMMAND) && owWriteByte(portnum, VALIDATION_KEY))) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } // read back to verify if (!isPageLockedAppReg(portnum, page, SNum)) { OWERROR(OWERROR_READ_BACK_NOT_VALID); return FALSE; } return TRUE; } /** * Query to see if the specified page is locked. * See the method 'canLockPage()'. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * page the page to be used. * * @return 'true' if page is locked. */ SMALLINT isPageLockedAppReg(int portnum, int page, uchar *SNum) { uchar extra[2]; // check if for valid page if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } // read status and return result if (!readStatus(portnum, &extra[0])) { OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE); return FALSE; } if (extra[0] == LOCKED_FLAG) return TRUE; return FALSE; } /** * Redirect the specifed page in the current memory bank to a new page. * Not supported by all devices. See the method 'canRedirectPage()'. * * portnum the port number of the port being used for the * 1-Wire Network. * page the page to be redirect * newPage the new page to be redirected to * SNum the serial number for the part. * * @return 'true' if page is redirected. */ SMALLINT redirectPageAppReg(int portnum, int page, int newPage, uchar *SNum) { OWERROR(OWERROR_PAGE_REDIRECTION_NOT_SUPPORTED); return FALSE; } /** * Gets the page redirection of the specified page. * Not supported by all devices. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * page the page to be used. * * @return where the redirected page is. */ SMALLINT getRedirectedPageAppReg(int portnum, int page, uchar *SNum) { return 0; } /** * Lock the redirection option for the specifed page in the current * memory bank. Not supported by all devices. See the method * 'canLockRedirectPage()'. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * page the page to be used. * * @return 'true' if redirected page is locked. */ SMALLINT lockRedirectPageAppReg(int portnum, int page, uchar *SNum) { // only needs to be implemented if supported by hardware OWERROR(OWERROR_LOCK_REDIRECTION_NOT_SUPPORTED); return FALSE; } /** * Query to see if the specified page has redirection locked. * Not supported by all devices. See the method 'canRedirectPage()'. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * page the page to be used. * * @return return 'true' if redirection is locked for this page */ SMALLINT isRedirectPageLockedAppReg(int portnum, int page, uchar *SNum) { return FALSE; } //-------- //-------- Bank specific methods //-------- /** * Read the status register for this memory bank. * * portnum the port number of the port being used for the * 1-Wire Network. * extra the extra information * * @return 'true' if the status was read. * */ SMALLINT readStatus(int portnum, uchar *extra) { // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // do the read status sequence if (!owWriteByte(portnum, READ_STATUS_COMMAND)) return FALSE; // validation key if (!owWriteByte(portnum, 0x00)) return FALSE; extra[0] = owReadByte(portnum); return TRUE; } w1retap/src/libusblinux300/mbappreg.h000066400000000000000000000104501446446235200177730ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ownet.h - Include file for 1-Wire Net library // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT readAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len); SMALLINT writeAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT readPageAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCAppReg(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff); SMALLINT readPagePacketAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPagePacketExtraAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT writePagePacketAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT getNumberPagesAppReg(SMALLINT bank, uchar *SNum); int getSizeAppReg(SMALLINT bank, uchar *SNum); int getStartingAddressAppReg(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthAppReg(SMALLINT bank, uchar *SNum); char *getBankDescriptionAppReg(SMALLINT bank, uchar *SNum); SMALLINT isGeneralPurposeMemoryAppReg(SMALLINT bank, uchar *SNum); SMALLINT isReadWriteAppReg(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceAppReg(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadOnlyAppReg(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isNonVolatileAppReg(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseAppReg(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliveryAppReg(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoAppReg(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthAppReg(SMALLINT bank, uchar *SNum); char *getExtraInfoDescAppReg(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthAppReg(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCAppReg(SMALLINT bank, uchar *SNum); // OTP SMALLINT canRedirectPageAppReg(SMALLINT bank, uchar *SNum); SMALLINT canLockPageAppReg(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageAppReg(SMALLINT bank, uchar *SNum); // Local functions SMALLINT readStatus(int portnum, uchar *extra); // OTP Local functions SMALLINT lockPageAppReg(int portnum, int page, uchar *SNum); SMALLINT isPageLockedAppReg(int portnum, int page, uchar *SNum); SMALLINT redirectPageAppReg(int portnum, int page, int newPage, uchar *SNum); SMALLINT isPageRedirectedAppReg(int portnum, int page, uchar *SNum); SMALLINT getRedirectPageAppReg(int portnum, int page, uchar *SNum); SMALLINT lockRedirectPageAppReg(int portnum, int page, uchar *SNum); w1retap/src/libusblinux300/mbee.c000066400000000000000000000660761446446235200171200ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c - Reads and writes to memory locations for the EE memory bank. // version 1.00 // // Include Files #include "ownet.h" #include "mbee.h" // General command defines #define READ_MEMORY_COMMAND 0xF0 #define WRITE_SCRATCHPAD_COMMAND 0x0F #define READ_SCRATCHPAD_COMMAND 0xAA #define COPY_SCRATCHPAD_COMMAND 0x55 // Local defines #define SIZE 32 #define PAGE_LENGTH 32 // Global variables char *bankDescription = "Main Memory"; SMALLINT writeVerification = TRUE; SMALLINT generalPurposeMemory = TRUE; SMALLINT readWrite = TRUE; SMALLINT writeOnce = FALSE; SMALLINT readOnly = FALSE; SMALLINT nonVolatile = TRUE; SMALLINT needsProgramPulse = FALSE; SMALLINT needsPowerDelivery = TRUE; SMALLINT hasExtraInfo = FALSE; SMALLINT extraInfoLength = 0; char *extraInfoDesc = ""; SMALLINT pageAutoCRC = FALSE; /** * Read memory in the current 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 readPagePacketEE() method or have * the 1-Wire device provide the CRC as in readPageCRCEE(). readPageCRCEE() * however is not supported on all memory types, see 'hasPageAutoCRCEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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 read is * to be done on. * str_add starting physical address * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array to place read data into * len length in bytes to read * * @return 'true' if the read was complete */ SMALLINT readEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) { int i; uchar raw_buf[2]; // check if read exceeds memory if ((str_add + len) > SIZE) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build start reading memory block raw_buf[0] = READ_MEMORY_COMMAND; raw_buf[1] = (uchar)str_add & 0xFF; // do the first block for command, address if (!owBlock(portnum, FALSE, raw_buf, 2)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // pre-fill readBuf with 0xFF for (i = 0; i < len; i++) buff[i] = 0xFF; // send the block if (!owBlock(portnum, FALSE, buff, len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Write memory in the current bank. It is recommended that * when writing data that some structure in the data is created * to provide error free reading back with readEE(). Or the * method 'writePagePacketEE()' could be used which automatically * wraps the data in a length and CRC. * * When using on Write-Once devices care must be taken to write into * into empty space. If write() 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 write is * to be done on. * str_add starting address * buff byte array containing data to write * len length in bytes to write * * @return 'true' if the write was complete. */ SMALLINT writeEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) { int i; uchar raw_buf[64]; // return if nothing to do if (len == 0) return TRUE; // check if power delivery is available if (!owHasPowerDelivery(portnum)) { OWERROR(OWERROR_POWER_NOT_AVAILABLE); return FALSE; } // check if write exceeds memory if ((str_add + len) > SIZE) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); // write the page of data to scratchpad if (!writeScratchpad(portnum, str_add, buff, len)) return FALSE; // read the data back for verification if (!readScratchpad(portnum, raw_buf, str_add, PAGE_LENGTH)) return FALSE; // check to see if the same for (i = 0; i < len; i++) if (raw_buf[i] != buff[i]) { OWERROR(OWERROR_READ_SCRATCHPAD_VERIFY); return FALSE; } // do the copy if (!copyScratchpad(portnum)) return FALSE; // check on write verification if (writeVerification) { // read back to verify if (!readEE(bank, portnum, SNum, str_add, FALSE, buff, len)) return FALSE; for (i = 0; i < len; i++) if (raw_buf[i] != buff[i]) { OWERROR(OWERROR_READ_VERIFY_FAILED); return FALSE; } } return TRUE; } /** * Read page in the current 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 * readPagePacketEE() method or have the 1-Wire device provide the * CRC as in readPageCRCEE(). readPageCRCEE() however is not * supported on all memory types, see 'hasPageAutoCRCEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } return readEE(bank, portnum, SNum, page, rd_cont, buff, PAGE_LENGTH); } /** * Read page with extra information in the current 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 * readPagePacketEE() method or have the 1-Wire device provide the * CRC as in readPageCRCEE(). readPageCRCEE() however is not * supported on all memory types, see 'hasPageAutoCRCEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoEE()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * See the method 'hasPageAutoCRC()'. * See the method 'haveExtraInfo()' for a description of the optional * extra information. * * 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. * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { OWERROR(OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCEE()'. * * 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. * page the page to read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH]; ushort lastcrc16 = 0; int i; // read the scratchpad, discard extra information if (!readEE(bank, portnum, SNum, page, rd_cont, raw_buf, PAGE_LENGTH)) return FALSE; // check if length is realistic if ((raw_buf[0] > (PAGE_LENGTH - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressEE(bank, SNum) / PAGE_LENGTH) + page)); for (i = 0; i < raw_buf[0] + 3; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketEE()' for a description of the packet structure. * See the method 'hasExtraInfoEE()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { OWERROR(OWERROR_PG_PACKET_WITHOUT_EXTRA); return FALSE; } /** * Write a Universal Data Packet. See the method 'readPagePacketEE()' * 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. * page the page the packet is being written to. * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[64]; int i; ushort crc = 0; // make sure length does not exceed max if ((len > (PAGE_LENGTH - 3)) || (len <= 0)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } // construct the packet to write raw_buf[0] = (uchar)len; for (i = 1; i < len + 1; i++) raw_buf[i] = buff[i - 1]; setcrc16(portnum, (ushort)((getStartingAddressEE(bank, SNum) / PAGE_LENGTH) + page)); for (i = 0; i < len + 1; i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = (uchar)~crc & 0xFF; raw_buf[len + 2] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (!writeEE(bank, portnum, SNum, page * PAGE_LENGTH, raw_buf, len + 3)) return FALSE; return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesEE(SMALLINT bank, uchar *SNum) { return 1; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeEE(SMALLINT bank, uchar *SNum) { return SIZE; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressEE(SMALLINT bank, uchar *SNum) { return 0; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthEE(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionEE(SMALLINT bank, uchar *SNum) { return bankDescription; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemoryEE(SMALLINT bank, uchar *SNum) { return generalPurposeMemory; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteEE(SMALLINT bank, int portnum, uchar *SNum) { return readWrite; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceEE(SMALLINT bank, int portnum, uchar *SNum) { return writeOnce; } /** * 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. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlyEE(SMALLINT bank, int portnum, uchar *SNum) { return readOnly; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileEE(SMALLINT bank, uchar *SNum) { return nonVolatile; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseEE(SMALLINT bank, uchar *SNum) { return needsProgramPulse; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliveryEE(SMALLINT bank, uchar *SNum) { return needsPowerDelivery; } /** * 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoEE(SMALLINT bank, uchar *SNum) { return hasExtraInfo; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoEE()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthEE(SMALLINT bank, uchar *SNum) { return extraInfoLength; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoEE()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescEE(SMALLINT bank, uchar *SNum) { return extraInfoDesc; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCEE()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCEE(SMALLINT bank, uchar *SNum) { return pageAutoCRC; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthEE(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH - 3; } //-------- //-------- Bank specific methods //-------- /** * Read the scratchpad page of memory from the device * This method reads and returns the entire scratchpad after the byte * offset regardless of the actual ending offset * * portnum the port number used to reference the port * readBuf byte array to place read data into * length of array is always pageLength. * startAddr address to start to read from scratchPad * len length in bytes to read * * @return 'true' if read scratch pad was successful */ SMALLINT readScratchpad(int portnum, uchar *readBuf, int startAddr, int len) { int i; uchar raw_buf[2]; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build first block raw_buf[0] = READ_SCRATCHPAD_COMMAND; raw_buf[1] = startAddr; // do the first block for address if (!owBlock(portnum, FALSE, raw_buf, 2)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // build the next block for (i = 0; i < len; i++) readBuf[i] = 0xFF; // send second block to read data, return result if (!owBlock(portnum, FALSE, readBuf, len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Write to the scratchpad page of memory device. * * portnum the port number used to reference the port * startAddr starting address * writeBuf byte array containing data to write * len length in bytes to write * * @return 'true' if the write to scratch pad was successful */ SMALLINT writeScratchpad(int portnum, int startAddr, uchar *writeBuf, int len) { int i; uchar raw_buf[64]; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block to send raw_buf[0] = WRITE_SCRATCHPAD_COMMAND; raw_buf[1] = startAddr & 0xFF; for (i = 2; i < len + 2; i++) raw_buf[i] = writeBuf[i - 2]; // send second block to read data, return result if (!owBlock(portnum, FALSE, raw_buf, len + 2)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Copy the scratchpad page to memory. * * portnum the port number used to reference the port * * @return 'true' if the copy scratchpad was successful */ SMALLINT copyScratchpad(int portnum) { // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // copy scratch if (!owWriteByte(portnum, COPY_SCRATCHPAD_COMMAND)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } // send command and setup strong pullup if (!owWriteBytePower(portnum, 0xA5)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } // delay for 10ms msDelay(10); // disable power if (MODE_NORMAL != owLevel(portnum, MODE_NORMAL)) { OWERROR(OWERROR_LEVEL_FAILED); return FALSE; } return TRUE; } /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageEE(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageEE(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageEE(SMALLINT bank, uchar *SNum) { return FALSE; } w1retap/src/libusblinux300/mbee.h000066400000000000000000000100561446446235200171100ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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 "ownet.h" // Local function definitions SMALLINT readEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len); SMALLINT writeEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT readPageEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPagePacketEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPagePacketExtraEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT writePagePacketEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT getNumberPagesEE(SMALLINT bank, uchar *SNum); int getSizeEE(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthEE(SMALLINT bank, uchar *SNum); int getStartingAddressEE(SMALLINT bank, uchar *SNum); char *getBankDescriptionEE(SMALLINT bank, uchar *SNum); SMALLINT isGeneralPurposeMemoryEE(SMALLINT bank, uchar *SNum); SMALLINT isReadWriteEE(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceEE(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadOnlyEE(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isNonVolatileEE(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseEE(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliveryEE(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoEE(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthEE(SMALLINT bank, uchar *SNum); char *getExtraInfoDescEE(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthEE(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCEE(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageEE(SMALLINT bank, uchar *SNum); SMALLINT canLockPageEE(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageEE(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageAppReg(SMALLINT bank, uchar *SNum); SMALLINT canLockPageAppReg(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageAppReg(SMALLINT bank, uchar *SNum); // Local functions SMALLINT writeScratchpad(int portnum, int startAddr, uchar *writeBuf, int len); SMALLINT readScratchpad(int portnum, uchar *readBuf, int startAddr, int len); SMALLINT copyScratchpad(int portnum); w1retap/src/libusblinux300/mbee77.c000066400000000000000000001040741446446235200172650ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2003 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. //-------------------------------------------------------------------------- // // mbEE77.c - Reads and writes to memory locations for the EE memory bank // for the DS1977. // version 1.00 // // Include Files #include "ownet.h" #include "mbee77.h" #include "mbscrx77.h" #include "pw77.h" // General command defines #define READ_MEMORY_PSW_COMMAND 0x69 #define WRITE_SCRATCHPAD_COMMAND 0x0F #define READ_SCRATCHPAD_COMMAND 0xAA #define COPY_SCRATCHPAD_COMMAND 0x55 // Local defines #define SIZE 32768 #define PAGE_LENGTH 64 #define PAGE_LENGTH_HYGRO 32 // Global variables char *bankDescription77 = "Main Memory"; SMALLINT writeVerification77 = TRUE; SMALLINT generalPurposeMemory77 = TRUE; SMALLINT readWrite77 = TRUE; SMALLINT writeOnce77 = FALSE; SMALLINT readOnly77 = FALSE; SMALLINT nonVolatile77 = TRUE; SMALLINT needsProgramPulse77 = FALSE; SMALLINT needsPowerDelivery77 = TRUE; SMALLINT hasExtraInfo77 = FALSE; SMALLINT extraInfoLength77 = 0; char *extraInfoDesc77 = ""; SMALLINT pageAutoCRC77 = FALSE; // used to 'enable' passwords uchar ENABLE_BYTE = 0xAA; // used to 'disable' passwords uchar DISABLE_BYTE = 0x00; /** * Read memory in the current 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 readPagePacketEE() method or have * the 1-Wire device provide the CRC as in readPageCRCEE(). readPageCRCEE() * however is not supported on all memory types, see 'hasPageAutoCRCEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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 read is * to be done on. * psw 8 byte password * str_add starting physical address * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array to place read data into * len length in bytes to read * * @return 'true' if the read was complete */ SMALLINT readEEPsw77(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) { SMALLINT i, j, send_len = 0, finished; uchar raw_buf[15]; uchar temp[64]; int pgs, extra, add; for (i = 0; i < len; i++) buff[i] = 0xFF; // check if read exceeds memory if ((str_add + len) > SIZE) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } // set serial number of device to read owSerialNum(portnum, SNum, FALSE); // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // command, address, offset, password (except last byte) if (SNum[0] == 0x37) raw_buf[send_len++] = READ_MEMORY_PSW_COMMAND; else raw_buf[send_len++] = 0x66; raw_buf[send_len++] = str_add & 0xFF; raw_buf[send_len++] = ((str_add & 0xFFFF) >> 8) & 0xFF; for (i = 0; i < 8; i++) raw_buf[send_len++] = psw[i]; // do the first block for command, address. password if (SNum[0] == 0x37) { if (!owBlock(portnum, FALSE, raw_buf, (send_len - 1))) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (!owWriteBytePower(portnum, raw_buf[(send_len - 1)])) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } msDelay(10); owLevel(portnum, MODE_NORMAL); } else { if (!owBlock(portnum, FALSE, raw_buf, send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } // pre-fill readBuf with 0xFF finished = FALSE; if (SNum[0] == 0x37) { pgs = len / PAGE_LENGTH; extra = len % PAGE_LENGTH; add = PAGE_LENGTH - (str_add % PAGE_LENGTH); } else { pgs = len / PAGE_LENGTH_HYGRO; extra = len % PAGE_LENGTH_HYGRO; add = PAGE_LENGTH_HYGRO - (str_add % PAGE_LENGTH_HYGRO); } if ((len < PAGE_LENGTH) && (SNum[0] == 0x37)) { if (((str_add % PAGE_LENGTH) > ((str_add + len) % PAGE_LENGTH)) && (((str_add + len) % PAGE_LENGTH) != 0)) { for (i = 0; i < add; i++) buff[i] = 0xFF; if (!owBlock(portnum, FALSE, &buff[0], add)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } raw_buf[0] = owReadByte(portnum); raw_buf[1] = owReadBytePower(portnum); msDelay(10); owLevel(portnum, MODE_NORMAL); for (i = add; i < len; i++) buff[i] = 0xFF; if (!owBlock(portnum, FALSE, &buff[add], extra)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } finished = TRUE; } else { for (i = 0; i < len; i++) buff[i] = 0xFF; if (!owBlock(portnum, FALSE, &buff[0], len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } finished = TRUE; } } for (i = 0; i < pgs; i++) { if (SNum[0] != 0x37) { if (i == 0) { for (j = 0; j < add; j++) buff[j] = 0xFF; if (!owBlock(portnum, FALSE, &buff[0], add)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } raw_buf[0] = owReadByte(portnum); raw_buf[1] = owReadByte(portnum); } else { for (j = (add + (i - 1) * PAGE_LENGTH_HYGRO); j < (add + i * PAGE_LENGTH_HYGRO); j++) buff[j] = 0xFF; if (!owBlock(portnum, FALSE, &buff[add + (i - 1) * PAGE_LENGTH_HYGRO], PAGE_LENGTH_HYGRO)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } raw_buf[0] = owReadByte(portnum); raw_buf[1] = owReadByte(portnum); } } else { if (i == 0) { for (j = 0; j < add; j++) buff[j] = 0xFF; if (!owBlock(portnum, FALSE, &buff[0], add)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } raw_buf[0] = owReadByte(portnum); raw_buf[1] = owReadBytePower(portnum); msDelay(10); owLevel(portnum, MODE_NORMAL); } else { for (j = (add + ((i - 1) * PAGE_LENGTH)); j < (add + (i * PAGE_LENGTH)); j++) buff[j] = 0xFF; if (!owBlock(portnum, FALSE, &buff[(add + ((i - 1) * PAGE_LENGTH))], PAGE_LENGTH)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } raw_buf[0] = owReadByte(portnum); raw_buf[1] = owReadBytePower(portnum); msDelay(10); owLevel(portnum, MODE_NORMAL); } } } if (SNum[0] != 0x37) { for (j = 0; j < PAGE_LENGTH_HYGRO; j++) temp[j] = 0xFF; for (i = (add + (pgs * PAGE_LENGTH_HYGRO)); i < len; i++) buff[i] = 0xFF; // send second block to read data, return result if (!owBlock(portnum, FALSE, &temp[0], PAGE_LENGTH_HYGRO)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } for (i = (add + ((pgs - 1) * PAGE_LENGTH_HYGRO)); i < len; i++) buff[i] = temp[j - (add + ((pgs - 1) * PAGE_LENGTH_HYGRO))]; } else { if (!finished) { for (j = 0; j < PAGE_LENGTH; j++) temp[j] = 0xFF; if (!owBlock(portnum, FALSE, &temp[0], PAGE_LENGTH)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } for (j = (add + ((pgs - 1) * PAGE_LENGTH)); j < len; j++) buff[j] = temp[j - (add + ((pgs - 1) * PAGE_LENGTH))]; } } return TRUE; } /** * Write memory in the current bank. It is recommended that * when writing data that some structure in the data is created * to provide error free reading back with readEE(). Or the * method 'writePagePacketEE()' could be used which automatically * wraps the data in a length and CRC. * * When using on Write-Once devices care must be taken to write into * into empty space. If write() 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 write is * to be done on. * psw 8 byte password * str_add starting address * buff byte array containing data to write * len length in bytes to write * * !!!!!!!!!!!!!MUST FIT ON PAGE RIGHT NOW!!!!!!!!!!!!! * * @return 'true' if the write was complete. */ SMALLINT writeEE77(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) { uchar raw_buf[64], extra[5]; SMALLINT i; int startx, nextx, abs_addr, pl, room_left; int endingOffset, numBytes; uchar wr_buff[256]; // return if nothing to do if (len == 0) return TRUE; // check if power delivery is available if (!owHasPowerDelivery(portnum)) { OWERROR(OWERROR_POWER_NOT_AVAILABLE); return FALSE; } // check if write exceeds memory if ((str_add + len) > SIZE) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); for (i = 0; i < len; i++) wr_buff[i] = buff[i]; if (SNum[0] != 0x37) { endingOffset = str_add + len; numBytes = getPageLengthEE77(bank, SNum) - (endingOffset & 0x1F); if (!readEEPsw77(bank, portnum, SNum, endingOffset, FALSE, &wr_buff[len], numBytes)) return FALSE; } // loop while still have pages to write startx = 0; nextx = 0; abs_addr = getStartingAddressEE77(bank, SNum) + str_add; pl = getPageLengthEE77(bank, SNum); do { // calculate room left in current page room_left = pl - ((abs_addr + startx) % pl); // check if block left will cross end of page if ((len - startx) > room_left) nextx = startx + room_left; else nextx = len; // write the page of data to scratchpad writeScratchPadEx77(portnum, SNum, (abs_addr + startx), &wr_buff[startx], nextx - startx); // read to verify ok if (!readScratchPadCRC77(portnum, SNum, &raw_buf[0], pl, &extra[0])) return FALSE; // check to see if the same for (i = 0; i < (nextx - startx); i++) { if (raw_buf[i] != wr_buff[i + startx]) { OWERROR(OWERROR_READ_SCRATCHPAD_VERIFY); return FALSE; } } // check to make sure that the address is correct if ((((extra[0] & 0x00FF) | ((extra[1] << 8) & 0x00FF00)) & 0x00FFFF) != (abs_addr + startx)) { OWERROR(OWERROR_READ_SCRATCHPAD_VERIFY); return FALSE; } // do the copy copyScratchPadPsw77(portnum, SNum, (abs_addr + startx), (nextx - startx), psw); // point to next index startx = nextx; } while (nextx < len); return TRUE; } /** * Read page in the current 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 * readPagePacketEE() method or have the 1-Wire device provide the * CRC as in readPageCRCEE(). readPageCRCEE() however is not * supported on all memory types, see 'hasPageAutoCRCEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * psw 8 byte password * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { return readPageCRCEE77(bank, portnum, SNum, page, buff); } /** * Read page with extra information in the current 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 * readPagePacketEE() method or have the 1-Wire device provide the * CRC as in readPageCRCEE(). readPageCRCEE() however is not * supported on all memory types, see 'hasPageAutoCRCEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoEE()' for a description of the optional * extra information some devices have. * * 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. * psw 8 byte password * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * See the method 'hasPageAutoCRC()'. * See the method 'haveExtraInfo()' for a description of the optional * extra information. * * 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. * psw 8 byte password * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCEE77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCEE()'. * * 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. * psw 8 byte password * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCEE77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { SMALLINT i, send_len = 0, lsCRC16; uchar raw_buf[15]; int str_add; ushort lastcrc16; // check if not continuing on the next page /* if (!rd_cont) {*/ // set serial number of device to read owSerialNum(portnum, SNum, FALSE); // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // command, address, offset, password (except last byte) raw_buf[send_len++] = READ_MEMORY_PSW_COMMAND; if (SNum[0] == 0x37) { str_add = page * PAGE_LENGTH; } else { str_add = page * PAGE_LENGTH_HYGRO; } raw_buf[send_len++] = str_add & 0xFF; raw_buf[send_len++] = ((str_add & 0xFFFF) >> 8) & 0xFF; // calculate the CRC16 setcrc16(portnum, 0); for (i = 0; i < send_len; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); for (i = 0; i < 8; i++) raw_buf[send_len++] = psw[i]; if (SNum[0] == 0x37) { // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, (send_len - 1))) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // send last byte of password and enable strong pullup if (!owWriteBytePower(portnum, psw[7])) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } } else { if (!owBlock(portnum, FALSE, raw_buf, send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } /* } // get the next page else { // previous read left last CRC16 byte to read before next page owReadBytePower(portnum); // calculate the CRC16 setcrc16(portnum,0); }*/ // set the read bytes if (SNum[0] == 0x37) { // delay for read to complete msDelay(5); //????????5 could be 2 // turn off strong pullup owLevel(portnum, MODE_NORMAL); for (i = 0; i < PAGE_LENGTH; i++) buff[i] = 0xFF; } else { for (i = 0; i < PAGE_LENGTH_HYGRO; i++) buff[i] = 0xFF; } // read the data if (SNum[0] == 0x37) { if (!owBlock(portnum, FALSE, buff, PAGE_LENGTH)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { if (!owBlock(portnum, FALSE, buff, PAGE_LENGTH_HYGRO)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } // read the first CRC16 byte lsCRC16 = owReadByte(portnum); // calculate CRC on data read if (SNum[0] == 0x37) { for (i = 0; i < PAGE_LENGTH; i++) lastcrc16 = docrc16(portnum, buff[i]); } else { for (i = 0; i < PAGE_LENGTH_HYGRO; i++) lastcrc16 = docrc16(portnum, buff[i]); } // check lsByte of the CRC if ((lastcrc16 & 0xFF) != (~lsCRC16 & 0xFF)) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * psw 8 byte password * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH]; ushort lastcrc16 = 0; int i; // read the page if (!readPageCRCEE77(bank, portnum, SNum, page, raw_buf)) return FALSE - 1; // check if length is realistic if (SNum[0] == 0x37) { if ((raw_buf[0] > (PAGE_LENGTH - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } } else { if ((raw_buf[0] > (PAGE_LENGTH_HYGRO - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } } // verify the CRC is correct setcrc16(portnum, (ushort)page); for (i = 0; i < raw_buf[0] + 3; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketEE()' for a description of the packet structure. * See the method 'hasExtraInfoEE()' for a description of the optional * extra information some devices have. * * 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. * psw 8 byte password * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { OWERROR(OWERROR_PG_PACKET_WITHOUT_EXTRA); return FALSE; } /** * Write a Universal Data Packet. See the method 'readPagePacketEE()' * 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. * psw 8 byte password * page the page the packet is being written to. * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketEE77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[PAGE_LENGTH]; int i; ushort crc = 0; // make sure length does not exceed max if (SNum[0] == 0x37) { if ((len > (PAGE_LENGTH - 3)) || (len <= 0)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } } else { if ((len > (PAGE_LENGTH_HYGRO - 3)) || (len <= 0)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } } // construct the packet to write raw_buf[0] = (uchar)len; for (i = 1; i < len + 1; i++) raw_buf[i] = buff[i - 1]; if (SNum[0] == 0x37) setcrc16(portnum, (ushort)((getStartingAddressEE77(bank, SNum) / PAGE_LENGTH) + page)); else setcrc16(portnum, (ushort)((getStartingAddressEE77(bank, SNum) / PAGE_LENGTH_HYGRO) + page)); for (i = 0; i < len + 1; i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = (uchar)~crc & 0xFF; raw_buf[len + 2] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (SNum[0] == 0x37) { if (!writeEE77(bank, portnum, SNum, page * PAGE_LENGTH, raw_buf, len + 3)) return FALSE; } else { if (!writeEE77(bank, portnum, SNum, page * PAGE_LENGTH_HYGRO, raw_buf, len + 3)) return FALSE; } return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesEE77(SMALLINT bank, uchar *SNum) { return 511; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeEE77(SMALLINT bank, uchar *SNum) { return SIZE; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressEE77(SMALLINT bank, uchar *SNum) { return 0; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthEE77(SMALLINT bank, uchar *SNum) { if (SNum[0] == 0x37) return PAGE_LENGTH; else return PAGE_LENGTH_HYGRO; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionEE77(SMALLINT bank, uchar *SNum) { return bankDescription77; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemoryEE77(SMALLINT bank, uchar *SNum) { return generalPurposeMemory77; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteEE77(SMALLINT bank, int portnum, uchar *SNum) { return readWrite77; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceEE77(SMALLINT bank, int portnum, uchar *SNum) { return writeOnce77; } /** * 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. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlyEE77(SMALLINT bank, int portnum, uchar *SNum) { return readOnly77; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileEE77(SMALLINT bank, uchar *SNum) { return nonVolatile77; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseEE77(SMALLINT bank, uchar *SNum) { return needsProgramPulse77; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliveryEE77(SMALLINT bank, uchar *SNum) { return needsPowerDelivery77; } /** * 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoEE77(SMALLINT bank, uchar *SNum) { return hasExtraInfo77; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoEE()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthEE77(SMALLINT bank, uchar *SNum) { return extraInfoLength77; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoEE()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescEE77(SMALLINT bank, uchar *SNum) { return extraInfoDesc77; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCEE()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCEE77(SMALLINT bank, uchar *SNum) { return pageAutoCRC77; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthEE77(SMALLINT bank, uchar *SNum) { if (SNum[0] == 0x37) return PAGE_LENGTH - 3; else return PAGE_LENGTH_HYGRO - 3; } //-------- //-------- Bank specific methods //-------- /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageEE77(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageEE77(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageEE77(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT needPassword(int portnum, uchar *SNum) { uchar passone[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; uchar passtwo[8] = {0x01, 0x02, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08}; if (verifyPassword(portnum, SNum, &passone[0], READ_WRITE_PSW) && verifyPassword(portnum, SNum, &passtwo[0], READ_WRITE_PSW)) { return FALSE; } return TRUE; } w1retap/src/libusblinux300/mbee77.h000066400000000000000000000077241446446235200172760ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbEE77.h - Include memory bank EE functions for the DS1977. // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT readEEPsw77(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len); SMALLINT writeEE77(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT readPageEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCEE77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCEE77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPagePacketEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPagePacketExtraEE77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT writePagePacketEE77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len); SMALLINT getNumberPagesEE77(SMALLINT bank, uchar *SNum); int getSizeEE77(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthEE77(SMALLINT bank, uchar *SNum); int getStartingAddressEE77(SMALLINT bank, uchar *SNum); char *getBankDescriptionEE77(SMALLINT bank, uchar *SNum); SMALLINT isGeneralPurposeMemoryEE77(SMALLINT bank, uchar *SNum); SMALLINT isReadWriteEE77(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceEE77(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadOnlyEE77(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isNonVolatileEE77(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseEE77(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliveryEE77(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoEE77(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthEE77(SMALLINT bank, uchar *SNum); char *getExtraInfoDescEE77(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthEE77(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCEE77(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageEE77(SMALLINT bank, uchar *SNum); SMALLINT canLockPageEE77(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageEE77(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageAppReg(SMALLINT bank, uchar *SNum); SMALLINT canLockPageAppReg(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageAppReg(SMALLINT bank, uchar *SNum); SMALLINT needPassword(int portnum, uchar *SNum); w1retap/src/libusblinux300/mbeprom.c000066400000000000000000001411611446446235200176360ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbEPROM.c - Include memory bank EPROM functions. // // Version: 2.10 // // Include Files #include "ownet.h" #include "mbeprom.h" // general command defines #define READ_MEMORY_COMMAND_EPROM 0xF0 #define MAIN_READ_PAGE_COMMAND_EPROM 0xA5 #define STATUS_READ_PAGE_COMMAND_EPROM 0xAA #define MAIN_WRITE_COMMAND_EPROM 0x0F #define STATUS_WRITE_COMMAND_EPROM 0x55 // Local defines #define SIZE_EPROM 2048 #define PAGE_LENGTH_EPROM 32 // Global variables char *bankDescription_eprom = "Main Memory"; SMALLINT writeVerification_eprom = TRUE; SMALLINT generalPurposeMemory_eprom = TRUE; SMALLINT readWrite_eprom = FALSE; SMALLINT writeOnce_eprom = TRUE; SMALLINT readOnly_eprom = FALSE; SMALLINT nonVolatile_eprom = TRUE; SMALLINT needsProgramPulse_eprom = TRUE; SMALLINT needsPowerDelivery_eprom = FALSE; SMALLINT hasExtraInfo_eprom = TRUE; SMALLINT extraInfoLength_eprom = 1; char *extraInfoDesc_eprom = "Inverted redirection page"; SMALLINT pageAutoCRC_eprom = TRUE; SMALLINT lockOffset = 0; SMALLINT lockRedirectOffset = 0; SMALLINT canredirectPage = FALSE; SMALLINT canlockPage = FALSE; SMALLINT canlockRedirectPage = FALSE; SMALLINT numPages = 64; SMALLINT CRCbytes = 2; /** * Read memory in the current 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 readPagePacketEPROM() method or have * the 1-Wire device provide the CRC as in readPageCRCEPROM(). readPageCRCEPROM() * however is not supported on all memory types, see 'hasPageAutoCRCEPROM()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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 read is * to be done on. * str_add starting physical address * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array to place read data into * len length in bytes to read * * @return 'true' if the read was complete */ SMALLINT readEPROM(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) { int i; int start_pg, end_pg, num_bytes, pg; uchar raw_buf[256]; // check if read exceeds memory if ((str_add + len) > getSizeEPROM(bank, SNum)) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } // check if status memory if (readPageWithCRC(bank, SNum) == STATUS_READ_PAGE_COMMAND_EPROM) { // no regular read memory so must use readPageCRC start_pg = str_add / getPageLengthEPROM(bank, SNum); end_pg = ((str_add + len) / getPageLengthEPROM(bank, SNum)) - 1; if (((str_add + len) % getPageLengthEPROM(bank, SNum)) > 0) end_pg++; // loop to read the pages for (pg = start_pg; pg <= end_pg; pg++) if (!readPageCRCEPROM(bank, portnum, SNum, pg, &raw_buf[(pg - start_pg) * getPageLengthEPROM(bank, SNum)])) { return FALSE; } // extract out the data for (i = 0; i < len; i++) buff[i] = raw_buf[i]; } // regular memory so use standard read memory command else { // see if need to access the device if (!rd_cont) { // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build start reading memory block raw_buf[0] = READ_MEMORY_COMMAND_EPROM; raw_buf[1] = (str_add + getStartingAddressEPROM(bank, SNum)) & 0xFF; raw_buf[2] = (((str_add + getStartingAddressEPROM(bank, SNum)) & 0xFFFF) >> 8) & 0xFF; raw_buf[3] = 0xFF; // check if get a 1 byte crc in a normal read. if (SNum[0] == 0x09) num_bytes = 4; else num_bytes = 3; // do the first block for command, address if (!owBlock(portnum, FALSE, raw_buf, num_bytes)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } // pre-fill readBuf with 0xFF for (i = 0; i < len; i++) buff[i] = 0xFF; // send second block to read data, return result if (!owBlock(portnum, FALSE, buff, len)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } } return TRUE; } /** * Write memory in the current bank. It is recommended that * when writing data that some structure in the data is created * to provide error free reading back with readEPROM(). Or the * method 'writePagePacketEPROM()' could be used which automatically * wraps the data in a length and CRC. * * When using on Write-Once devices care must be taken to write into * into empty space. If write() 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 write is * to be done on. * str_add starting address * buff byte array containing data to write * len length in bytes to write * * @return 'true' if the write was complete. */ SMALLINT writeEPROM(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) { int i; int result; SMALLINT write_continue; int crc_type; int verify[256]; // return if nothing to do if (len == 0) return TRUE; // check if power delivery is available if (!owHasProgramPulse(portnum)) { OWERROR(OWERROR_NO_PROGRAM_PULSE); return FALSE; } // check if trying to write read only bank if (isReadOnlyEPROM(bank, portnum, SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } for (i = 0; i < len; i++) { verify[0] = writeVerify(bank, portnum, SNum, ((str_add + i + getStartingAddressEPROM(bank, SNum)) / getPageLengthEPROM(bank, SNum))); if (isPageLocked(bank, portnum, SNum, (str_add + i + getStartingAddressEPROM(bank, SNum)) / getPageLengthEPROM(bank, SNum))) { OWERROR(OWERROR_PAGE_LOCKED); return FALSE; } } // check if write exceeds memory if ((str_add + len) > (getPageLengthEPROM(bank, SNum) * getNumberPagesEPROM(bank, SNum))) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } // loop while still have bytes to write write_continue = TRUE; crc_type = numCRCbytes(bank, SNum) - 1; for (i = 0; i < len; i++) { result = owProgramByte(portnum, buff[i], str_add + i + getStartingAddressEPROM(bank, SNum), writeMemCmd(bank, SNum), crc_type, write_continue); if (verify[i]) { if ((result == -1) || ((uchar)result != buff[i])) { OWERROR(OWERROR_READBACK_EPROM_FAILED); return FALSE; } else write_continue = FALSE; } } return TRUE; } /** * Read page in the current 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 * readPagePacketEPROM() method or have the 1-Wire device provide the * CRC as in readPageCRCEPROM(). readPageCRCEPROM() however is not * supported on all memory types, see 'hasPageAutoCRCEPROM()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { uchar extra[1]; if (hasPageAutoCRCEPROM(bank, SNum)) { if (!readPageExtraCRCEPROM(bank, portnum, SNum, page, buff, extra)) return FALSE; } else { if (!readEPROM(bank, portnum, SNum, (page * getPageLengthEPROM(bank, SNum)), FALSE, buff, getPageLengthEPROM(bank, SNum))) return FALSE; } return TRUE; } /** * Read page with extra information in the current 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 * readPagePacketEPROM() method or have the 1-Wire device provide the * CRC as in readPageCRCEPROM(). readPageCRCEPROM() however is not * supported on all memory types, see 'hasPageAutoCRCEPROM()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoEPROM()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { // check if current bank is not scratchpad bank, or not page 0 if (!hasExtraInfoEPROM(bank, SNum)) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } return readPageExtraCRCEPROM(bank, portnum, SNum, page, buff, extra); } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * See the method 'hasPageAutoCRCEPROM()'. * See the method 'haveExtraInfoEPROM()' for a description of the optional * extra information. * * 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. * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { int i, len = 0, lastcrc = 0, addr, extractPnt; uchar raw_buf[PAGE_LENGTH_EPROM + 6]; owSerialNum(portnum, SNum, FALSE); // only needs to be implemented if supported by hardware if (!hasPageAutoCRCEPROM(bank, SNum)) { OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; } // check if read exceeds memory if (page > (getNumberPagesEPROM(bank, SNum))) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build start reading memory block with: command, address, (extraInfo?), (crc?) len = 3 + getExtraInfoLengthEPROM(bank, SNum); if (crcAfterAdd(bank, SNum)) { len += numCRCbytes(bank, SNum); } for (i = 0; i < len; i++) raw_buf[i] = 0xFF; raw_buf[0] = readPageWithCRC(bank, SNum); addr = page * getPageLengthEPROM(bank, SNum) + getStartingAddressEPROM(bank, SNum); raw_buf[1] = addr & 0xFF; raw_buf[2] = ((addr & 0xFFFF) >> 8) & 0xFF; // do the first block if (!owBlock(portnum, FALSE, &raw_buf[0], len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // check CRC if (numCRCbytes(bank, SNum) == 2) { setcrc16(portnum, 0); for (i = 0; i < len; i++) lastcrc = docrc16(portnum, raw_buf[i]); } else { setcrc8(portnum, 0); for (i = 0; i < len; i++) lastcrc = docrc8(portnum, raw_buf[i]); } if ((getExtraInfoLengthEPROM(bank, SNum) > 0) || (crcAfterAdd(bank, SNum))) { // check CRC if (numCRCbytes(bank, SNum) == 2) { if (lastcrc != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } else { if (lastcrc != 0) { return FALSE; } } lastcrc = 0; // extract the extra information extractPnt = len - getExtraInfoLengthEPROM(bank, SNum) - numCRCbytes(bank, SNum); if (getExtraInfoLengthEPROM(bank, SNum)) for (i = extractPnt; i < (extractPnt + getExtraInfoLengthEPROM(bank, SNum)); i++) extra[i - extractPnt] = raw_buf[i]; } // pre-fill with 0xFF for (i = 0; i < (getPageLengthEPROM(bank, SNum) + numCRCbytes(bank, SNum)); i++) raw_buf[i] = 0xFF; // send block to read data + crc if (!owBlock(portnum, FALSE, &raw_buf[0], (getPageLengthEPROM(bank, SNum) + numCRCbytes(bank, SNum)))) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // check the CRC if (numCRCbytes(bank, SNum) == 2) { setcrc16(portnum, (ushort)lastcrc); for (i = 0; i < (getPageLengthEPROM(bank, SNum) + numCRCbytes(bank, SNum)); i++) lastcrc = docrc16(portnum, raw_buf[i]); if (lastcrc != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } else { setcrc8(portnum, (uchar)lastcrc); for (i = 0; i < (getPageLengthEPROM(bank, SNum) + numCRCbytes(bank, SNum)); i++) lastcrc = docrc8(portnum, raw_buf[i]); if (lastcrc != 0) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } // extract the page data for (i = 0; i < getPageLengthEPROM(bank, SNum); i++) { read_buff[i] = raw_buf[i]; } return TRUE; } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCEPROM()'. * * 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. * page the page to read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { uchar extra[1]; return readPageExtraCRCEPROM(bank, portnum, SNum, page, buff, extra); } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH_EPROM]; uchar extra[1]; ushort lastcrc16 = 0; int i; // read entire page with read page CRC if (!readPageExtraCRCEPROM(bank, portnum, SNum, page, &raw_buf[0], &extra[0])) return FALSE; // check if length is realistic if ((raw_buf[0] & 0xFF) > getMaxPacketDataLengthEPROM(bank, SNum)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressEPROM(bank, SNum) / PAGE_LENGTH_EPROM) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 0; i < raw_buf[0]; i++) buff[i] = raw_buf[i + 1]; // return the length *len = raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketEPROM()' for a description of the packet structure. * See the method 'hasExtraInfoEPROM()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { uchar raw_buf[PAGE_LENGTH_EPROM]; ushort lastcrc16 = 0; int i; // check if current bank is not scratchpad bank, or not page 0 if (!hasExtraInfoEPROM(bank, SNum)) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } // read entire page with read page CRC if (!readPageExtraCRCEPROM(bank, portnum, SNum, page, raw_buf, extra)) return FALSE; // check if length is realistic if ((raw_buf[0] & 0xFF) > getMaxPacketDataLengthEPROM(bank, SNum)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressEPROM(bank, SNum) / PAGE_LENGTH_EPROM) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 0; i < raw_buf[0]; i++) buff[i] = raw_buf[i + 1]; // return the length *len = raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Write a Universal Data Packet. See the method 'readPagePacketEPROM()' * 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. * page the page the packet is being written to. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[PAGE_LENGTH_EPROM]; int crc = 0, i; // make sure length does not exceed max if (len > getMaxPacketDataLengthEPROM(bank, SNum)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // see if this bank is general read/write if (!isGeneralPurposeMemoryEPROM(bank, SNum)) { OWERROR(OWERROR_NOT_GENERAL_PURPOSE); return FALSE; } // construct the packet to write raw_buf[0] = (uchar)len; for (i = 0; i < len; i++) raw_buf[i + 1] = buff[i]; setcrc16(portnum, (ushort)((getStartingAddressEPROM(bank, SNum) / PAGE_LENGTH_EPROM) + page)); for (i = 0; i < len + 1; i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = ~crc & 0xFF; raw_buf[len + 2] = ((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (!writeEPROM(bank, portnum, SNum, page * getPageLengthEPROM(bank, SNum) + getStartingAddressEPROM(bank, SNum), &raw_buf[0], len + 3)) return FALSE; return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesEPROM(SMALLINT bank, uchar *SNum) { int pages = numPages; switch (SNum[0]) { case 0x09: if (bank == 0) pages = 4; else if (bank == 1) pages = 1; break; case 0x0B: if ((bank == 1) || (bank == 2) || (bank == 3)) pages = 1; else if (bank == 4) pages = 8; break; case 0x0F: if (bank == 0) pages = 256; else if ((bank == 1) || (bank == 2)) pages = 4; else if (bank == 3) pages = 3; else if (bank == 4) pages = 32; break; case 0x12: if (bank == 0) pages = 4; else if (bank == 1) pages = 1; break; case 0x13: if (bank == 0) pages = 16; else if (bank == 4) pages = 2; else if ((bank == 1) || (bank == 2) || (bank == 3)) pages = 1; break; default: pages = numPages; break; } return pages; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeEPROM(SMALLINT bank, uchar *SNum) { int size = SIZE_EPROM; switch (SNum[0]) { case 0x09: if (bank == 0) size = 128; else if (bank == 1) size = 8; break; case 0x0B: if ((bank == 1) || (bank == 2) || (bank == 3)) size = 8; else if (bank == 4) size = 64; break; case 0x0F: if (bank == 0) size = 8192; else if ((bank == 1) || (bank == 2)) size = 32; else if (bank == 3) size = 24; else if (bank == 4) size = 256; break; case 0x12: if (bank == 0) size = 128; else if (bank == 1) size = 8; break; case 0x13: if (bank == 0) size = 512; else if (bank == 4) size = 16; else if ((bank == 1) || (bank == 2) || (bank == 3)) size = 8; break; default: size = SIZE_EPROM; break; } return size; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressEPROM(SMALLINT bank, uchar *SNum) { int addr = 0; switch (SNum[0]) { case 0x0B: if (bank == 2) addr = 32; else if (bank == 3) addr = 64; else if (bank == 4) addr = 256; break; case 0x0F: if (bank == 2) addr = 32; else if (bank == 3) addr = 64; else if (bank == 4) addr = 256; break; case 0x13: if (bank == 2) addr = 32; else if (bank == 3) addr = 64; else if (bank == 4) addr = 256; break; default: addr = 0; break; } return addr; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthEPROM(SMALLINT bank, uchar *SNum) { int len = PAGE_LENGTH_EPROM; switch (SNum[0]) { case 0x09: if (bank == 1) len = 8; break; case 0x0B: if ((bank > 0) && (bank < 5)) len = 8; case 0x0F: if ((bank > 0) && (bank < 5)) len = 8; break; case 0x12: if (bank == 1) len = 8; break; case 0x13: if ((bank > 0) && (bank < 5)) len = 8; break; default: len = PAGE_LENGTH_EPROM; break; } return len; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionEPROM(SMALLINT bank, uchar *SNum) { switch (SNum[0]) { case 0x09: if (bank == 1) return "Write protect pages and page redirection"; break; case 0x0B: if (bank == 1) return "Write protect pages"; else if (bank == 2) return "Write protect redirection"; else if (bank == 3) return "Bitmap of used pages for file structure"; else if (bank == 4) return "Page redirection bytes"; break; case 0x0F: if (bank == 1) return "Write protect pages"; else if (bank == 2) return "Write protect redirection"; else if (bank == 3) return "Bitmap of used pages for file structure"; else if (bank == 4) return "Pages redirection bytes"; break; case 0x12: if (bank == 1) return "Write protect pages, page redirection, switch control"; break; case 0x13: if (bank == 1) return "Write protect pages"; else if (bank == 2) return "Write protect redirection"; else if (bank == 3) return "Bitmap of used pages for file structure"; else if (bank == 4) return "Page redirection bytes"; break; default: return bankDescription_eprom; } return bankDescription_eprom; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemoryEPROM(SMALLINT bank, uchar *SNum) { int gp_mem = generalPurposeMemory_eprom; switch (SNum[0]) { case 0x09: if (bank == 1) gp_mem = FALSE; break; case 0x0B: if ((bank > 0) && (bank < 5)) gp_mem = FALSE; case 0x0F: if ((bank > 0) && (bank < 5)) gp_mem = FALSE; break; case 0x12: if (bank == 1) gp_mem = FALSE; break; case 0x13: if ((bank > 0) && (bank < 5)) gp_mem = FALSE; break; default: gp_mem = generalPurposeMemory_eprom; break; } return gp_mem; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteEPROM(SMALLINT bank, int portnum, uchar *SNum) { return readWrite_eprom; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceEPROM(SMALLINT bank, int portnum, uchar *SNum) { return writeOnce_eprom; } /** * 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. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlyEPROM(SMALLINT bank, int portnum, uchar *SNum) { return readOnly_eprom; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileEPROM(SMALLINT bank, uchar *SNum) { return nonVolatile_eprom; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseEPROM(SMALLINT bank, uchar *SNum) { return needsProgramPulse_eprom; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliveryEPROM(SMALLINT bank, uchar *SNum) { return needsPowerDelivery_eprom; } /** * 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoEPROM(SMALLINT bank, uchar *SNum) { SMALLINT hasExtra = hasExtraInfo_eprom; switch (SNum[0]) { case 0x09: hasExtra = FALSE; break; case 0x0B: if ((bank > 0) && (bank < 5)) hasExtra = FALSE; break; case 0x0F: if ((bank > 0) && (bank < 5)) hasExtra = FALSE; break; case 0x12: if (bank == 1) hasExtra = FALSE; break; case 0x13: if ((bank > 0) && (bank < 5)) hasExtra = FALSE; break; default: hasExtra = hasExtraInfo_eprom; break; } return hasExtra; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoEPROM()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthEPROM(SMALLINT bank, uchar *SNum) { SMALLINT len = extraInfoLength_eprom; switch (SNum[0]) { case 0x09: len = 0; break; case 0x0B: if ((bank > 0) && (bank < 5)) len = 0; break; case 0x0F: if ((bank > 0) && (bank < 5)) len = 0; break; case 0x12: if (bank == 1) len = 0; break; case 0x13: if ((bank > 0) && (bank < 5)) len = 0; break; default: len = extraInfoLength_eprom; break; } return len; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoEPROM()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescEPROM(SMALLINT bank, uchar *SNum) { switch (SNum[0]) { case 0x09: return " "; break; case 0x0B: if ((bank > 0) && (bank < 5)) return " "; break; case 0x0F: if ((bank > 0) && (bank < 5)) return " "; break; case 0x12: if (bank == 1) return " "; break; case 0x13: if ((bank > 0) && (bank < 5)) return " "; break; default: return extraInfoDesc_eprom; } return extraInfoDesc_eprom; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCEPROM()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCEPROM(SMALLINT bank, uchar *SNum) { return pageAutoCRC_eprom; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthEPROM(SMALLINT bank, uchar *SNum) { return getPageLengthEPROM(bank, SNum) - 3; } //-------- //-------- OTPMemoryBank I/O methods //-------- /** * Lock the specifed page in the current memory bank. Not supported * by all devices. See the method 'canLockPageEPROM()'. * * 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. * page the page to be locked * * @return true if the page was locked * false otherwise */ SMALLINT lockPage(SMALLINT bank, int portnum, uchar *SNum, int page) { int nbyt, nbit; SMALLINT write_bank; uchar wr_byte[1]; // setting the bank to write // and since all the page lock info is in // bank 1 for all the EPROM parts. write_bank = 1; if (isPageLocked(write_bank, portnum, SNum, page)) { OWERROR(OWERROR_PAGE_ALREADY_LOCKED); return FALSE; } // create byte to write to mlLock to lock page nbyt = (page >> 3); nbit = page - (nbyt << 3); wr_byte[0] = (uchar) ~(0x01 << nbit); // write the lock bit if (!writeEPROM(write_bank, portnum, SNum, nbyt + lockOffset, wr_byte, 1)) return FALSE; // read back to verify if (!isPageLocked(write_bank, portnum, SNum, page)) { OWERROR(OWERROR_READ_BACK_NOT_VALID); return FALSE; } return TRUE; } /** * Query to see if the specified page is locked. * See the method 'canLockPage()'. * * 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. * page the page to check if locked * * @return true if page locked. */ SMALLINT isPageLocked(SMALLINT bank, int portnum, uchar *SNum, int page) { int pg_len, read_pg, index, nbyt, nbit; SMALLINT read_bank; uchar read_buf[PAGE_LENGTH_EPROM]; // setting the bank to read for information // and since all the page lock info is in // bank 1 for all the EPROM parts. read_bank = 1; // read page that locked bit is on pg_len = getPageLengthEPROM(read_bank, SNum); read_pg = (page + lockOffset) / (pg_len * 8); if (!readPageCRCEPROM(read_bank, portnum, SNum, read_pg, read_buf)) return FALSE; // return boolean on locked bit index = (page + lockOffset) - (read_pg * 8 * pg_len); nbyt = (index >> 3); nbit = index - (nbyt << 3); return !(((read_buf[nbyt] >> nbit) & 0x01) == 0x01); } /** * Redirect the specifed page in the current memory bank to a new page. * Not supported by all devices. See the method 'canRedirectPage()'. * * 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. * page the page to be locked * newPage new page number to redirect to * * @return true if the page was redirected */ SMALLINT redirectPage(SMALLINT bank, int portnum, uchar *SNum, int page, int newPage) { uchar wr_byte[1]; // create byte to redirect page SMALLINT write_bank; if (isRedirectPageLocked(bank, portnum, SNum, page)) { OWERROR(OWERROR_REDIRECTED_PAGE); return FALSE; } // setting the bank to write switch (SNum[0]) { case 0x09: case 0x12: write_bank = 1; break; case 0x0B: case 0x0F: case 0x13: write_bank = 4; break; default: write_bank = 4; break; } wr_byte[0] = (uchar)~newPage; // write the redirection byte if (!writeEPROM(write_bank, portnum, SNum, page + redirectOffset(bank, SNum), wr_byte, 1)) return FALSE; return TRUE; } /** * Gets the page redirection of the specified page. * Not supported by all devices. * * 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. * page number of page check for redirection * * @return the new page number or 0 if not redirected */ SMALLINT getRedirectedPage(SMALLINT bank, int portnum, uchar *SNum, int page) { int pg_len, read_pg; SMALLINT read_bank; uchar read_buf[PAGE_LENGTH_EPROM]; // setting the bank to read for information switch (SNum[0]) { case 0x09: case 0x12: read_bank = 1; break; case 0x0B: case 0x0F: case 0x13: read_bank = 4; break; default: read_bank = 4; break; } // read page that redirect byte is on pg_len = getPageLengthEPROM(read_bank, SNum); read_pg = (page + redirectOffset(bank, SNum)) / pg_len; if (!readPageCRCEPROM(read_bank, portnum, SNum, read_pg, read_buf)) return FALSE; // return page return (SMALLINT)(~read_buf[(page + redirectOffset(bank, SNum)) % pg_len] & 0x000000FF); } /** * Lock the redirection option for the specifed page in the current * memory bank. Not supported by all devices. See the method * 'canLockRedirectPage()'. * * 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. * page number of page to redirect * * @return true if the redirected page is locked. */ SMALLINT lockRedirectPage(SMALLINT bank, int portnum, uchar *SNum, int page) { int nbyt, nbit; SMALLINT write_bank; uchar wr_byte[1]; if (isRedirectPageLocked(bank, portnum, SNum, page)) { OWERROR(OWERROR_LOCKING_REDIRECTED_PAGE_AGAIN); return FALSE; } // setting the bank to write switch (SNum[0]) { case 0x0B: case 0x0F: case 0x13: write_bank = 2; break; default: write_bank = 0; break; } // create byte to write to mlLock to lock page nbyt = (page >> 3); nbit = page - (nbyt << 3); wr_byte[0] = (uchar) ~(0x01 << nbit); // write the lock bit if (!writeEPROM(write_bank, portnum, SNum, nbyt + lockRedirectOffset, wr_byte, 1)) return FALSE; // read back to verify if (!isRedirectPageLocked(bank, portnum, SNum, page) || (write_bank == 0)) { OWERROR(OWERROR_COULD_NOT_LOCK_REDIRECT); return FALSE; } return TRUE; } /** * Query to see if the specified page has redirection locked. * Not supported by all devices. See the method 'canRedirectPage()'. * * 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. * page number of page to check for redirection * * @return true if redirection is locked for this page */ SMALLINT isRedirectPageLocked(SMALLINT bank, int portnum, uchar *SNum, int page) { int pg_len, read_pg, index, nbyt, nbit; SMALLINT read_bank; uchar read_buf[PAGE_LENGTH_EPROM]; // setting the bank to read for information switch (SNum[0]) { case 0x0B: case 0x0F: case 0x13: read_bank = 2; break; default: return FALSE; } // read page that lock redirect bit is on pg_len = getPageLengthEPROM(read_bank, SNum); read_pg = (page + lockRedirectOffset) / (pg_len * 8); if (!readPageCRCEPROM(read_bank, portnum, SNum, read_pg, read_buf)) return FALSE; // return boolean on lock redirect bit index = (page + lockRedirectOffset) - (read_pg * 8 * pg_len); nbyt = (index >> 3); nbit = index - (nbyt << 3); return !(((read_buf[nbyt] >> nbit) & 0x01) == 0x01); } /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageEPROM(SMALLINT bank, uchar *SNum) { SMALLINT canRedirect = canredirectPage; switch (SNum[0]) { case 0x09: if (bank == 0) canRedirect = TRUE; break; case 0x0B: if (bank == 0) canRedirect = TRUE; break; case 0x0F: if (bank == 0) canRedirect = TRUE; break; case 0x12: if (bank == 0) canRedirect = TRUE; break; case 0x13: if (bank == 0) canRedirect = TRUE; break; default: canRedirect = canredirectPage; break; } return canRedirect; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageEPROM(SMALLINT bank, uchar *SNum) { SMALLINT canLock = canlockPage; switch (SNum[0]) { case 0x09: if (bank == 0) canLock = TRUE; break; case 0x0B: if (bank == 0) canLock = TRUE; break; case 0x0F: if (bank == 0) canLock = TRUE; break; case 0x12: if (bank == 0) canLock = TRUE; break; case 0x13: if (bank == 0) canLock = TRUE; break; default: canLock = canlockPage; break; } return canLock; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageEPROM(SMALLINT bank, uchar *SNum) { SMALLINT lockRedirect = canlockRedirectPage; switch (SNum[0]) { case 0x0B: if (bank == 0) lockRedirect = TRUE; break; case 0x0F: if (bank == 0) lockRedirect = TRUE; break; case 0x13: if (bank == 0) lockRedirect = TRUE; break; default: lockRedirect = canlockRedirectPage; break; } return lockRedirect; } //-------- //-------- Local functions //-------- /** * Send the command for writing to memory for a device given * the memory bank and serial number. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return the command for writing to the memory bank. */ uchar writeMemCmd(SMALLINT bank, uchar *SNum) { uchar command = MAIN_WRITE_COMMAND_EPROM; switch (SNum[0]) { case 0x09: if (bank == 1) command = STATUS_WRITE_COMMAND_EPROM; break; case 0x0B: if ((bank > 0) && (bank < 5)) command = STATUS_WRITE_COMMAND_EPROM; break; case 0x0F: if ((bank > 0) && (bank < 5)) command = STATUS_WRITE_COMMAND_EPROM; break; case 0x12: if (bank == 1) command = STATUS_WRITE_COMMAND_EPROM; break; case 0x13: if ((bank > 0) && (bank < 5)) command = STATUS_WRITE_COMMAND_EPROM; break; default: command = MAIN_WRITE_COMMAND_EPROM; break; } return command; } /** * Get the number of CRC bytes for the device. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return the number of CRC bytes. */ SMALLINT numCRCbytes(SMALLINT bank, uchar *SNum) { SMALLINT numbytes = CRCbytes; switch (SNum[0]) { case 0x09: if ((bank == 0) || (bank == 1)) numbytes = 1; break; default: numbytes = CRCbytes; break; } return numbytes; } /** * Get the status of the page the pages write verification * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if write verification is used and * false if it is not used. */ SMALLINT writeVerify(SMALLINT bank, int portnum, uchar *SNum, int page) { if (isPageLocked(bank, portnum, SNum, page) || isRedirectPageLocked(bank, portnum, SNum, page)) return FALSE; return writeVerification_eprom; } /** * Get crc after sending command,address * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if crc is can be gotten after sending command,address * false otherwise */ SMALLINT crcAfterAdd(SMALLINT bank, uchar *SNum) { SMALLINT crcAfter = TRUE; switch (SNum[0]) { case 0x0B: if ((bank > 0) && (bank < 5)) crcAfter = FALSE; break; case 0x0F: if ((bank > 0) && (bank < 5)) crcAfter = FALSE; break; case 0x12: if (bank == 1) crcAfter = FALSE; break; case 0x13: if ((bank > 0) && (bank < 5)) crcAfter = FALSE; break; default: crcAfter = TRUE; break; } return crcAfter; } /** * Get the byte command for reading the page with crc. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return the byte command for reading the page */ uchar readPageWithCRC(SMALLINT bank, uchar *SNum) { uchar readPage = MAIN_READ_PAGE_COMMAND_EPROM; switch (SNum[0]) { case 0x09: if (bank == 0) readPage = 0xC3; else if (bank == 1) readPage = STATUS_READ_PAGE_COMMAND_EPROM; break; case 0x0B: if ((bank > 0) && (bank < 5)) readPage = STATUS_READ_PAGE_COMMAND_EPROM; break; case 0x0F: if ((bank > 0) && (bank < 5)) readPage = STATUS_READ_PAGE_COMMAND_EPROM; break; case 0x12: if (bank == 1) readPage = STATUS_READ_PAGE_COMMAND_EPROM; break; case 0x13: if ((bank > 0) && (bank < 5)) readPage = STATUS_READ_PAGE_COMMAND_EPROM; break; default: readPage = MAIN_READ_PAGE_COMMAND_EPROM; break; } return readPage; } /** * Get the offset into the redirection status information. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return the offset into the redirection status */ SMALLINT redirectOffset(SMALLINT bank, uchar *SNum) { int offset = 0; switch (SNum[0]) { case 0x09: if (bank == 0) offset = 1; break; case 0x12: if (bank == 0) offset = 1; break; default: offset = 0; break; } return offset; } w1retap/src/libusblinux300/mbeprom.h000066400000000000000000000110651446446235200176420ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbEPROM.h - Include memory bank EPROM functions. // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT readEPROM(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len); SMALLINT writeEPROM(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT readPageEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCEPROM(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPagePacketEPROM(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPagePacketExtraEPROM(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT writePagePacketEPROM(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT getNumberPagesEPROM(SMALLINT bank, uchar *SNum); int getSizeEPROM(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthEPROM(SMALLINT bank, uchar *SNum); int getStartingAddressEPROM(SMALLINT bank, uchar *SNum); char *getBankDescriptionEPROM(SMALLINT bank, uchar *SNum); SMALLINT isGeneralPurposeMemoryEPROM(SMALLINT bank, uchar *SNum); SMALLINT isReadWriteEPROM(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceEPROM(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadOnlyEPROM(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isNonVolatileEPROM(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseEPROM(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliveryEPROM(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoEPROM(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthEPROM(SMALLINT bank, uchar *SNum); char *getExtraInfoDescEPROM(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthEPROM(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCEPROM(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageEPROM(SMALLINT bank, uchar *SNum); SMALLINT canLockPageEPROM(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageEPROM(SMALLINT bank, uchar *SNum); // Local functions uchar writeMemCmd(SMALLINT bank, uchar *SNum); SMALLINT numCRCbytes(SMALLINT bank, uchar *SNum); SMALLINT writeVerify(SMALLINT bank, int portnum, uchar *SNum, int page); SMALLINT crcAfterAdd(SMALLINT bank, uchar *SNum); uchar readPageWithCRC(SMALLINT bank, uchar *SNum); SMALLINT isRedirectPageLocked(SMALLINT bank, int portnum, uchar *SNum, int page); SMALLINT lockRedirectPage(SMALLINT bank, int portnum, uchar *SNum, int page); SMALLINT getRedirectedPage(SMALLINT bank, int portnum, uchar *SNum, int page); SMALLINT redirectPage(SMALLINT bank, int portnum, uchar *SNum, int page, int newPage); SMALLINT isPageLocked(SMALLINT bank, int portnum, uchar *SNum, int page); SMALLINT lockPage(SMALLINT bank, int portnum, uchar *SNum, int page); SMALLINT redirectOffset(SMALLINT bank, uchar *SNum); w1retap/src/libusblinux300/mbnv.c000066400000000000000000001031061446446235200171340ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // mbNV.c - Reads and writes to memory locations for the NV memory bank. // version 1.00 // // Include Files #include "ownet.h" #include "mbnv.h" #include "mbscr.h" #include "mbscree.h" #include "mbscrex.h" #include "mbscrcrc.h" #include "mbsha.h" #include "mbnvcrc.h" // General command defines #define READ_MEMORY_COMMAND_NV 0xF0 // Local defines #define PAGE_LENGTH_NV 32 #define SIZE_NV 512 // Global variables char *bankDescriptionNV = "Main Memory"; SMALLINT writeVerificationNV = TRUE; SMALLINT generalPurposeMemoryNV = TRUE; SMALLINT readWriteNV = TRUE; SMALLINT writeOnceNV = FALSE; SMALLINT readOnlyNV = FALSE; SMALLINT nonVolatileNV = TRUE; SMALLINT needProgramPulseNV = FALSE; SMALLINT needPowerDeliveryNV = FALSE; SMALLINT ExtraInfoNV = FALSE; SMALLINT extraInfoLengthNV = 0; char *extraInfoDescNV = ""; SMALLINT pageAutoCRCNV = FALSE; /** * Read memory in the current 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 readPagePacketNV() method or have * the 1-Wire device provide the CRC as in readPageCRCNV(). readPageCRCNV() * however is not supported on all memory types, see 'hasPageAutoCRCNV()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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 read is * to be done on. * str_add starting physical address * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array to place read data into * len length in bytes to read * * @return 'true' if the read was complete */ SMALLINT readNV(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) { int i, addr, pgs, extra; uchar raw_buf[PAGE_LENGTH_NV]; // check if read exceeds memory if ((str_add + len) > getSizeNV(bank, SNum)) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } // see if need to access the device if (!rd_cont) { owSerialNum(portnum, SNum, FALSE); // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build start reading memory block addr = str_add + getStartingAddressNV(bank, SNum); raw_buf[0] = READ_MEMORY_COMMAND_NV; raw_buf[1] = addr & 0xFF; raw_buf[2] = ((addr & 0xFFFF) >> 8) & 0xFF; // do the first block for command, address if (!owBlock(portnum, FALSE, raw_buf, 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } // pre-fill readBuf with 0xFF pgs = len / PAGE_LENGTH_NV; extra = len % PAGE_LENGTH_NV; for (i = 0; i < (pgs * PAGE_LENGTH_NV) + extra; i++) buff[i] = 0xFF; // send second block to read data, return result if (!owBlock(portnum, FALSE, buff, len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Write memory in the current bank. It is recommended that * when writing data that some structure in the data is created * to provide error free reading back with readNV(). Or the * method 'writePagePacketNV()' could be used which automatically * wraps the data in a length and CRC. * * When using on Write-Once devices care must be taken to write into * into empty space. If write() 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 write is * to be done on. * str_add starting address * buff byte array containing data to write * len length in bytes to write * * @return 'true' if the write was complete. */ SMALLINT writeNV(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) { int i, room_left, startx, nextx, addr, pl; uchar raw_buf[PAGE_LENGTH_NV]; uchar extra[PAGE_LENGTH_NV]; // return if nothing to do if (len == 0) return TRUE; owSerialNum(portnum, SNum, FALSE); // check if write exceeds memory if ((str_add + len) > getSizeNV(bank, SNum)) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } // check if trying to write read only bank if (isReadOnlyNV(bank, portnum, SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // loop while still have pages to write startx = 0; nextx = 0; addr = getStartingAddressNV(bank, SNum) + str_add; pl = PAGE_LENGTH_NV; do { // calculate room left in current page room_left = pl - ((addr + startx) % pl); // check if block left will cross end of page if ((len - startx) > room_left) nextx = startx + room_left; else nextx = len; // write the page of data to scratchpad switch (SNum[0] & 0x7F) { case 0x18: if (bank == 3) { if (!writeScratchpd(portnum, addr + startx, &buff[startx], nextx - startx)) return FALSE; } else if (!writeScratchPadSHA(portnum, addr + startx, &buff[startx], nextx - startx)) return FALSE; break; case 0x21: if (!writeScratchPadEx(portnum, addr + startx, &buff[startx], nextx - startx)) return FALSE; break; case 0x23: if (!writeScratchPadEE(portnum, addr + startx, &buff[startx], nextx - startx)) return FALSE; break; default: if (!writeScratchpd(portnum, addr + startx, &buff[startx], nextx - startx)) return FALSE; break; } // read to verify ok switch (SNum[0] & 0x7F) { case 0x18: if (bank == 3) { if (!readScratchpdExtra(portnum, raw_buf, pl, extra)) return FALSE; } else if (!readScratchPadCRC(portnum, raw_buf, pl, extra)) return FALSE; break; case 0x21: if (!readScratchPadCRC(portnum, raw_buf, pl, extra)) return FALSE; break; default: if (!readScratchpdExtra(portnum, raw_buf, pl, extra)) return FALSE; break; } // check to see if the same for (i = 0; i < (nextx - startx); i++) if (raw_buf[i] != buff[i + startx]) { OWERROR(OWERROR_READ_SCRATCHPAD_VERIFY); return FALSE; } // check to make sure that the address is correct // added the first unsigned jpe if ((unsigned)(((extra[0] & 0x00FF) | ((extra[1] << 8) & 0x00FF00)) & 0x00FFFF) != (unsigned)(addr + startx)) { OWERROR(OWERROR_ADDRESS_READ_BACK_FAILED); return FALSE; } // do the copy switch (SNum[0] & 0x7F) { case 0x18: if (bank == 3) { if (!copyScratchpd(portnum, addr + startx, nextx - startx)) return FALSE; } else if (!copyScratchPadSHA(portnum, addr + startx, nextx - startx)) return FALSE; break; case 0x1A: if (!copyScratchPadEx(portnum, addr + startx, nextx - startx)) return FALSE; break; case 0x21: if (!copyScratchPadCRC(portnum, addr + startx, nextx - startx)) return FALSE; break; case 0x23: if (!copyScratchPadEE(portnum, addr + startx, nextx - startx)) return FALSE; break; default: if (!copyScratchpd(portnum, addr + startx, nextx - startx)) return FALSE; break; } // point to next index startx = nextx; } while (nextx < len); return TRUE; } /** * Read page in the current 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 * readPagePacketNV() method or have the 1-Wire device provide the * CRC as in readPageCRCNV(). readPageCRCNV() however is not * supported on all memory types, see 'hasPageAutoCRCNV()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageNV(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { if (((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) || (SNum[0] == 0x21)) return readPageNVCRC(bank, portnum, SNum, page, rd_cont, buff); if ((page < 0) || (page > getNumberPagesNV(bank, SNum))) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } return readNV(bank, portnum, SNum, page * PAGE_LENGTH_NV, rd_cont, buff, PAGE_LENGTH_NV); } /** * Read page with extra information in the current 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 * readPagePacketNV() method or have the 1-Wire device provide the * CRC as in readPageCRCNV(). readPageCRCNV() however is not * supported on all memory types, see 'hasPageAutoCRCNV()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoNV()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraNV(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { if (((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) || (SNum[0] == 0x21)) return readPageExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, extra); OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * See the method 'hasPageAutoCRC()'. * See the method 'haveExtraInfo()' for a description of the optional * extra information. * * 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. * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCNV(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { if (((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) || (SNum[0] == 0x21)) return readPageExtraCRCNVCRC(bank, portnum, SNum, page, read_buff, extra); OWERROR(OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCNV()'. * * 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. * page the page to read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCNV(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { if (((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) || (SNum[0] == 0x21)) return readPageCRCNVCRC(bank, portnum, SNum, page, buff); OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketNV(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH_NV]; ushort lastcrc16 = 0; int i; // read the page if (!readPageNV(bank, portnum, SNum, page, rd_cont, &raw_buf[0])) return FALSE; // check if length is realistic if ((raw_buf[0] > getMaxPacketDataLengthNV(bank, SNum)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressNV(bank, SNum) / PAGE_LENGTH_NV) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketNV()' for a description of the packet structure. * See the method 'hasExtraInfoNV()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraNV(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { if (((SNum[0] == 0x18) && (bank != 3)) || (SNum[0] == 0x1A) || (SNum[0] == 0x1D) || (SNum[0] == 0x21)) return readPagePacketExtraNVCRC(bank, portnum, SNum, page, rd_cont, buff, len, extra); OWERROR(OWERROR_PG_PACKET_WITHOUT_EXTRA); return FALSE; } /** * Write a Universal Data Packet. See the method 'readPagePacketNV()' * 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. * page the page the packet is being written to. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketNV(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[PAGE_LENGTH_NV]; int i; ushort crc = 0; // make sure length does not exceed max if (len > getMaxPacketDataLengthNV(bank, SNum)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } // see if this bank is general read/write if (!isGeneralPurposeMemoryNV(bank, SNum)) { OWERROR(OWERROR_NOT_GENERAL_PURPOSE); return FALSE; } // construct the packet to write raw_buf[0] = (uchar)len; for (i = 1; i < (len + 1); i++) raw_buf[i] = buff[i - 1]; setcrc16(portnum, (ushort)((getStartingAddressNV(bank, SNum) / PAGE_LENGTH_NV) + page)); for (i = 0; i < (len + 1); i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = (uchar)~crc & 0xFF; raw_buf[len + 2] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (!writeNV(bank, portnum, SNum, page * PAGE_LENGTH_NV, &raw_buf[0], len + 3)) return FALSE; return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesNV(SMALLINT bank, uchar *SNum) { int pages = 16; switch (SNum[0] & 0x7F) { case 0x04: if (bank == 1) pages = 16; else if (bank == 2) pages = 1; else if (bank == 3) pages = 3; break; case 0x08: pages = 4; break; case 0x0A: pages = 64; break; case 0x0C: pages = 256; break; case 0x18: if (bank == 3) pages = 3; else if (bank == 2) pages = 8; else if (bank == 1) pages = 8; break; case 0x1A: if (bank == 2) pages = 4; else if (bank == 1) pages = 12; break; case 0x1D: if (bank >= 2) pages = 2; else if (bank == 1) pages = 12; break; case 0x21: if (bank == 5) pages = 64; else if (bank == 4) pages = 4; else if (bank == 3) pages = 3; else if (bank == 2) pages = 1; break; case 0x23: if (bank == 1) pages = 16; break; default: pages = 16; break; } return pages; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeNV(SMALLINT bank, uchar *SNum) { int size = 512; switch (SNum[0] & 0x7F) { case 0x04: if (bank == 1) size = 512; else if (bank == 2) size = 32; else if (bank == 3) size = 96; break; case 0x06: size = 512; break; case 0x08: size = 128; break; case 0x0A: size = 2048; break; case 0x0C: size = 8192; break; case 0x18: if (bank == 3) size = 96; else if (bank == 2) size = 256; else if (bank == 1) size = 256; break; case 0x1A: if (bank == 2) size = 128; else if (bank == 1) size = 384; break; case 0x1D: if (bank <= 3) size = 64; else if (bank == 1) size = 384; break; case 0x21: if (bank == 5) size = 2048; else if (bank == 4) size = 128; else if (bank == 3) size = 96; else if (bank == 2) size = 32; break; case 0x23: if (bank == 1) size = 512; else if (bank == 2) size = 32; break; default: size = 512; break; } return size; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressNV(SMALLINT bank, uchar *SNum) { int start = 0; switch (SNum[0] & 0x7F) { case 0x04: if (bank == 2) start = 512; break; case 0x18: if (bank == 3) start = 608; else if (bank == 2) start = 256; break; case 0x1A: if (bank == 2) start = 384; break; case 0x1D: if (bank == 3) start = 448; else if (bank == 2) start = 384; break; case 0x21: if (bank == 5) start = 4096; else if (bank == 4) start = 2048; else if (bank == 3) start = 544; else if (bank == 2) start = 512; break; default: start = 0; break; } return start; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthNV(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH_NV; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionNV(SMALLINT bank, uchar *SNum) { switch (SNum[0] & 0x7F) { case 0x04: if (bank == 2) return "Clock/Alarm registers."; break; case 0x18: if (bank == 3) return "Write cycle counters and PRNG counter."; else if (bank == 2) return "Memory with write cycle counter."; break; case 0x1A: if (bank == 2) return "Memory with write cycle counter."; break; case 0x1D: if (bank == 3) return "Memory with externally triggered counter."; else if (bank == 2) return "Memory with write cycle counter."; break; case 0x21: if (bank == 5) return "Temperature log."; else if (bank == 4) return "Temperature Histogram."; else if (bank == 3) return "Alarm time stamps."; else if (bank == 2) return "Register control."; break; default: return bankDescriptionNV; } return bankDescriptionNV; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemoryNV(SMALLINT bank, uchar *SNum) { SMALLINT gp = generalPurposeMemoryNV; switch (SNum[0] & 0x7F) { case 0x04: if (bank == 2) gp = FALSE; break; case 0x18: if (bank == 3) return FALSE; break; case 0x21: if (bank == 5) gp = FALSE; else if (bank == 4) gp = FALSE; else if (bank == 3) gp = FALSE; else if (bank == 2) gp = FALSE; break; default: gp = generalPurposeMemoryNV; break; } return gp; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteNV(SMALLINT bank, int portnum, uchar *SNum) { SMALLINT rw = readWriteNV; switch (SNum[0] & 0x7F) { case 0x18: if (bank == 3) rw = FALSE; break; case 0x21: if (bank == 5) rw = FALSE; else if (bank == 4) rw = FALSE; else if (bank == 3) rw = FALSE; break; default: rw = readWriteNV; } return rw; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceNV(SMALLINT bank, int portnum, uchar *SNum) { return writeOnceNV; } /** * 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. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlyNV(SMALLINT bank, int portnum, uchar *SNum) { SMALLINT ro = readOnlyNV; switch (SNum[0] & 0x7F) { case 0x18: if (bank == 3) ro = TRUE; break; case 0x21: if (bank == 5) ro = TRUE; else if (bank == 4) ro = TRUE; else if (bank == 3) ro = TRUE; break; default: ro = readOnlyNV; break; } return ro; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileNV(SMALLINT bank, uchar *SNum) { return nonVolatileNV; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseNV(SMALLINT bank, uchar *SNum) { return needProgramPulseNV; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliveryNV(SMALLINT bank, uchar *SNum) { return needPowerDeliveryNV; } /** * 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoNV(SMALLINT bank, uchar *SNum) { SMALLINT extra = ExtraInfoNV; switch (SNum[0] & 0x7F) { case 0x18: if ((bank == 2) || (bank == 1)) extra = TRUE; break; case 0x1A: if ((bank == 2) || (bank == 1)) extra = TRUE; break; case 0x1D: if ((bank == 3) || (bank == 2)) extra = TRUE; break; default: extra = ExtraInfoNV; break; } return extra; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoNV()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthNV(SMALLINT bank, uchar *SNum) { SMALLINT len = 0; switch (SNum[0] & 0x7F) { case 0x18: if (bank == 2) len = 8; else if (bank == 1) len = 8; break; case 0x1A: if (bank == 2) len = 8; else if (bank == 1) len = 8; break; case 0x1D: if (bank == 3) len = 8; else if (bank == 2) len = 8; break; default: len = extraInfoLengthNV; break; } return len; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoNV()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescNV(SMALLINT bank, uchar *SNum) { switch (SNum[0] & 0x7F) { case 0x18: if (bank == 2) return "Write cycle counter."; break; case 0x1A: if (bank == 2) return "Write cycle counter."; break; case 0x1D: if (bank == 2) return "Write cycle counter."; else if (bank == 3) return "Externally triggered counter."; break; default: return extraInfoDescNV; } return extraInfoDescNV; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCNV()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCNV(SMALLINT bank, uchar *SNum) { SMALLINT autoCRC = pageAutoCRCNV; switch (SNum[0] & 0x7F) { case 0x18: if ((bank == 1) || (bank == 2)) autoCRC = TRUE; break; case 0x1A: if ((bank == 1) || (bank == 2)) autoCRC = TRUE; break; case 0x1D: if ((bank > 0) && (bank < 4)) autoCRC = TRUE; break; case 0x21: if ((bank > 0) && (bank < 6)) autoCRC = TRUE; break; default: autoCRC = pageAutoCRCNV; break; } return autoCRC; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthNV(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH_NV - 3; } /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageNV(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageNV(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageNV(SMALLINT bank, uchar *SNum) { return FALSE; } w1retap/src/libusblinux300/mbnv.h000066400000000000000000000072471446446235200171520ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ownet.h - Include file for 1-Wire Net library // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT readNV(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len); SMALLINT writeNV(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT readPageNV(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraNV(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCNV(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCNV(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPagePacketNV(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPagePacketExtraNV(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT writePagePacketNV(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len); SMALLINT getNumberPagesNV(SMALLINT bank, uchar *SNum); int getSizeNV(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthNV(SMALLINT bank, uchar *SNum); int getStartingAddressNV(SMALLINT bank, uchar *SNum); char *getBankDescriptionNV(SMALLINT bank, uchar *SNum); SMALLINT isGeneralPurposeMemoryNV(SMALLINT bank, uchar *SNum); SMALLINT isReadWriteNV(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceNV(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadOnlyNV(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isNonVolatileNV(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseNV(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliveryNV(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoNV(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthNV(SMALLINT bank, uchar *SNum); char *getExtraInfoDescNV(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthNV(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCNV(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageNV(SMALLINT bank, uchar *SNum); SMALLINT canLockPageNV(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageNV(SMALLINT bank, uchar *SNum); w1retap/src/libusblinux300/mbnvcrc.c000066400000000000000000000275651446446235200176420ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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 files #include "ownet.h" #include "mbnv.h" #include "mbnvcrc.h" // general command defines #define READ_MEMORY_COMMAND 0xF0 #define WRITE_SCRATCHPAD_COMMAND 0x0F #define READ_SCRATCHPAD_COMMAND 0xAA #define COPY_SCRATCHPAD_COMMAND 0x55 #define READ_PAGE_WITH_CRC 0xA5 // Local defines #define SIZE_NVCRC 32 #define PAGE_LENGTH_NVCRC 32 // Global variables SMALLINT pageAutoCRCNVCRC = TRUE; SMALLINT readContinuePossible = TRUE; /** * Read page in the current 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). * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { uchar extra[8]; return readCRC(bank, portnum, SNum, page, rd_cont, buff, extra, getExtraInfoLengthNV(bank, SNum)); } /** * Read page with extra information in the current 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). * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { if (!hasExtraInfoNV(bank, SNum)) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } return readCRC(bank, portnum, SNum, page, rd_cont, buff, extra, getExtraInfoLengthNV(bank, SNum)); } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * * 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. * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { return readCRC(bank, portnum, SNum, page, FALSE, read_buff, extra, getExtraInfoLengthNV(bank, SNum)); } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. * * 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. * page the page to read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { uchar extra[8]; return readCRC(bank, portnum, SNum, page, FALSE, buff, extra, getExtraInfoLengthNV(bank, SNum)); } /** * Read a Universal Data Packet and extra information. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { uchar raw_buf[PAGE_LENGTH_NVCRC]; int i; ushort lastcrc16 = 0; // read entire page with read page CRC if (!readCRC(bank, portnum, SNum, page, rd_cont, raw_buf, extra, getExtraInfoLengthNV(bank, SNum))) return FALSE; // check if length is realistic if (raw_buf[0] > getMaxPacketDataLengthNV(bank, SNum)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressNV(bank, SNum) / PAGE_LENGTH_NVCRC) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 1; i < (raw_buf[0] + 1); i++) buff[i - 1] = raw_buf[i]; // return the length *len = raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * If not extra information available then just call with extraLength=0. * * 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. * page page number to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * readPagePacket() continious where the last one * stopped and it is inside a * 'beginExclusive/endExclusive' block. * readBuf byte array to put data read. Must have at least * 'getMaxPacketDataLength()' elements. * extra byte array to put extra info read into * extra_len length of extra information * * return TRUE if the read is successful. */ SMALLINT readCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *readBuf, uchar *extra, int extra_len) { int i; int addr; uchar raw_buf[3]; uchar read_buf[50]; ushort lastcrc16 = 0; owSerialNum(portnum, SNum, FALSE); // only needs to be implemented if supported by hardware if (!hasPageAutoCRCNV(bank, SNum)) { OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; } // check if read exceeds memory if (page > getNumberPagesNV(bank, SNum)) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } // see if need to access the device if (!rd_cont || !readPossible(bank, SNum)) { // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build start reading memory block raw_buf[0] = READ_PAGE_WITH_CRC; addr = page * PAGE_LENGTH_NVCRC + getStartingAddressNV(bank, SNum); raw_buf[1] = addr & 0xFF; raw_buf[2] = ((addr & 0xFFFF) >> 8) & 0xFF; // perform CRC16 on first part setcrc16(portnum, lastcrc16); for (i = 0; i < 3; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); // do the first block for command, TA1, TA2 if (!owBlock(portnum, FALSE, raw_buf, 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } // pre-fill with 0xFF for (i = 0; i < 50; i++) read_buf[i] = 0xFF; // send block to read data + extra info? + crc if (!owBlock(portnum, FALSE, read_buf, PAGE_LENGTH_NVCRC + extra_len + 2 + numVerifyBytes(bank, SNum))) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // check the CRC setcrc16(portnum, lastcrc16); for (i = 0; i < (PAGE_LENGTH_NVCRC + extra_len + 2); i++) lastcrc16 = docrc16(portnum, read_buf[i]); if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } // extract the page data for (i = 0; i < PAGE_LENGTH_NVCRC; i++) readBuf[i] = read_buf[i]; // optional extract the extra info if (extra_len != 0) for (i = 0; i < extra_len; i++) extra[i] = read_buf[i + PAGE_LENGTH_NVCRC]; return TRUE; } /** * Checks to see if a read is possible of a certian area of a device * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * return TRUE if the read can be done */ SMALLINT readPossible(SMALLINT bank, uchar *SNum) { SMALLINT possible = FALSE; switch (SNum[0]) { case 0x18: if (bank == 2) possible = FALSE; else if (bank == 1) possible = FALSE; break; case 0x1D: if (bank == 2) possible = FALSE; break; default: possible = TRUE; break; } return possible; } /** * Gives the number of verification bytes for the device. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * return the number of verification bytes a certain device has */ SMALLINT numVerifyBytes(SMALLINT bank, uchar *SNum) { SMALLINT verify = 0; switch (SNum[0]) { case 0x18: if (bank == 2) verify = 8; else if (bank == 1) verify = 8; break; case 0x1D: if (bank == 2) verify = 8; else if (bank == 1) verify = 8; break; default: verify = 0; break; } return verify; } w1retap/src/libusblinux300/mbnvcrc.h000066400000000000000000000046451446446235200176410ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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 "ownet.h" // Local function definitions SMALLINT readPageNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPagePacketExtraNVCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); // Internal functions SMALLINT readCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *readBuf, uchar *extra, int extra_len); SMALLINT readPossible(SMALLINT bank, uchar *SNum); SMALLINT numVerifyBytes(SMALLINT bank, uchar *SNum); w1retap/src/libusblinux300/mbscr.c000066400000000000000000001002031446446235200172730ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // mbSCR.c - Reads and writes to memory locations for the Scratch memory bank. // version 1.00 // // Include Files #include "ownet.h" #include "mbscr.h" #include "mbscree.h" #include "mbscrex.h" #include "mbscrcrc.h" #include "mbsha.h" // General command defines #define READ_MEMORY_COMMAND 0xF0 #define WRITE_SCRATCHPAD_COMMAND 0x0F #define READ_SCRATCHPAD_COMMAND 0xAA #define COPY_SCRATCHPAD_COMMAND 0x55 // Local defines #define SIZE_SCR 32 #define PAGE_LENGTH_SCR 32 // Global variables char *bankDescriptionSCR = "Scratchpad"; SMALLINT writeVerificationSCR = TRUE; SMALLINT generalPurposeMemorySCR = FALSE; SMALLINT readWriteSCR = TRUE; SMALLINT writeOnceSCR = FALSE; SMALLINT readOnlySCR = FALSE; SMALLINT nonVolatileSCR = FALSE; SMALLINT needProgramPulseSCR = FALSE; SMALLINT needPowerDeliverySCR = FALSE; SMALLINT ExtraInfoSCR = TRUE; SMALLINT extraInfoLengthSCR = 3; char *extraInfoDescSCR = "Target address, offset"; SMALLINT pageAutoCRCSCR = FALSE; /** * Read memory in the current 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 readPagePacketScratch() method or have * the 1-Wire device provide the CRC as in readPageCRCScratch(). readPageCRCScratch() * however is not supported on all memory types, see 'hasPageAutoCRCScratch()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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 read is * to be done on. * str_add starting physical address * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array to place read data into * len length in bytes to read * * @return 'true' if the read was complete */ SMALLINT readScratch(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) { uchar extra[3]; uchar read_buf[PAGE_LENGTH_SCR]; int i; // check if read exceeds memory if ((str_add + len) > getSizeScratch(bank, SNum)) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); // read the scratchpad, discard extra information switch (SNum[0]) { case 0x18: case 0x21: if (!readScratchPadCRC(portnum, read_buf, len + str_add, extra)) return FALSE; break; default: if (!readScratchpd(portnum, read_buf, len + str_add)) return FALSE; break; } for (i = str_add; i < (len + str_add); i++) buff[i - str_add] = read_buf[i]; return TRUE; } /** * Write memory in the current bank. It is recommended that * when writing data that some structure in the data is created * to provide error free reading back with readScratch(). Or the * method 'writePagePacketScratch()' could be used which automatically * wraps the data in a length and CRC. * * When using on Write-Once devices care must be taken to write into * into empty space. If write() 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 write is * to be done on. * str_add starting address * buff byte array containing data to write * len length in bytes to write * * @return 'true' if the write was complete. */ SMALLINT writeScratch(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) { int i; uchar raw_buf[PAGE_LENGTH_SCR]; uchar extra[3]; // return if nothing to do if (len == 0) return TRUE; // check if write exceeds memory if (len > getSizeScratch(bank, SNum)) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); // write the page of data to scratchpad switch (SNum[0]) { case 0x18: if (!writeScratchPadSHA(portnum, str_add, buff, len)) return FALSE; break; case 0x21: if (!writeScratchPadEx(portnum, str_add, buff, len)) return FALSE; break; case 0x23: if (!writeScratchPadEE(portnum, str_add, buff, len)) return FALSE; break; default: if (!writeScratchpd(portnum, str_add, buff, len)) return FALSE; break; } // read to verify ok switch (SNum[0]) { case 0x18: case 0x21: if (readScratchPadCRC(portnum, raw_buf, PAGE_LENGTH_SCR, extra)) return FALSE; break; default: if (!readScratchpdExtra(portnum, raw_buf, PAGE_LENGTH_SCR, extra)) return FALSE; break; } // check to see if the same for (i = 0; i < len; i++) if (raw_buf[i] != buff[i]) { OWERROR(OWERROR_READ_SCRATCHPAD_VERIFY); return FALSE; } // check to make sure that the address is correct if ((((extra[0] & 0x00FF) | ((extra[1] << 8) & 0x00FF00)) & 0x00FFFF) != str_add) { OWERROR(OWERROR_ADDRESS_READ_BACK_FAILED); return FALSE; } return TRUE; } /** * Read page in the current 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 * readPagePacketScratch() method or have the 1-Wire device provide the * CRC as in readPageCRCScratch(). readPageCRCScratch() however is not * supported on all memory types, see 'hasPageAutoCRCScratch()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length in bytes to write * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageScratch(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } return readScratch(bank, portnum, SNum, page, rd_cont, buff, PAGE_LENGTH_SCR); } /** * Read page with extra information in the current 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 * readPagePacketScratch() method or have the 1-Wire device provide the * CRC as in readPageCRCScratch(). readPageCRCScratch() however is not * supported on all memory types, see 'hasPageAutoCRCScratch()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoScratch()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * len length in bytes to write * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraScratch(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { // check if read exceeds memory if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } owSerialNum(portnum, SNum, FALSE); // read the scratchpad, discard extra information switch (SNum[0]) { case 0x18: case 0x21: if (!readPageExtraScratchCRC(bank, portnum, SNum, page, FALSE, buff, extra)) return FALSE; break; default: if (!readScratchpdExtra(portnum, buff, PAGE_LENGTH_SCR, extra)) return FALSE; break; } return TRUE; } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * See the method 'hasPageAutoCRC()'. * See the method 'haveExtraInfo()' for a description of the optional * extra information. * * 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. * page the page to read * buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCScratch(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { switch (SNum[0]) { case 0x21: case 0x18: if (!readPageExtraScratchCRC(bank, portnum, SNum, page, FALSE, read_buff, extra)) return FALSE; break; default: OWERROR(OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED); return FALSE; break; } return TRUE; } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCScratch()'. * * 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. * page the page to read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCScratch(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { switch (SNum[0]) { case 0x21: case 0x18: if (!readPageScratchCRC(bank, portnum, SNum, page, FALSE, buff)) return FALSE; break; default: OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; break; } return TRUE; } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketScratch(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH_SCR]; int i; ushort lastcrc16 = 0; // read the scratchpad, discard extra information if (!readScratch(bank, portnum, SNum, 0, rd_cont, raw_buf, PAGE_LENGTH_SCR)) return FALSE; // check if length is realistic if ((raw_buf[0] > (PAGE_LENGTH_SCR - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressScratch(bank, SNum) / PAGE_LENGTH_SCR) + page)); for (i = 0; i < raw_buf[0] + 3; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketScratch()' for a description of the packet structure. * See the method 'hasExtraInfoScratch()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraScratch(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { uchar raw_buf[PAGE_LENGTH_SCR]; int i; ushort lastcrc16 = 0; // read the scratchpad, discard extra information switch (SNum[0]) { case 0x18: case 0x21: if (readScratchPadCRC(portnum, &raw_buf[0], page, extra)) return FALSE; break; default: if (!readScratchpdExtra(portnum, &raw_buf[0], page, extra)) return FALSE; } // check if length is realistic if ((raw_buf[0] > (PAGE_LENGTH_SCR - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressScratch(bank, SNum) / PAGE_LENGTH_SCR) + page)); for (i = 0; i < raw_buf[0] + 3; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Write a Universal Data Packet. See the method 'readPagePacketScratch()' * 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. * page the page the packet is being written to. * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketScratch(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[64]; int i; ushort crc = 0; // make sure length does not exceed max if ((len > (PAGE_LENGTH_SCR - 3)) || (len <= 0)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } // see if this bank is general read/write if (!isGeneralPurposeMemoryScratch(bank, SNum)) { OWERROR(OWERROR_NOT_GENERAL_PURPOSE); return FALSE; } // construct the packet to write raw_buf[0] = (uchar)len + 3; for (i = 1; i < len + 1; i++) raw_buf[i] = buff[i - 1]; setcrc16(portnum, (ushort)((getStartingAddressScratch(bank, SNum) / PAGE_LENGTH_SCR) + page)); for (i = 0; i < len + 1; i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = (uchar)~crc & 0xFF; raw_buf[len + 2] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (!writeScratch(bank, portnum, SNum, page, raw_buf, len + 3)) return FALSE; return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesScratch(SMALLINT bank, uchar *SNum) { return 1; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeScratch(SMALLINT bank, uchar *SNum) { return SIZE_SCR; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressScratch(SMALLINT bank, uchar *SNum) { return 0; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthScratch(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH_SCR; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionScratch(SMALLINT bank, uchar *SNum) { switch (SNum[0]) { case 0x18: return getBankDescriptionScratchSHA(bank, SNum); break; case 0x1A: case 0x1D: return getBankDescriptionScratchEx(bank, SNum); break; case 0x23: return getBankDescriptionScratchCRC(bank, SNum); break; default: return bankDescriptionSCR; break; } return "No description given."; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemoryScratch(SMALLINT bank, uchar *SNum) { return generalPurposeMemorySCR; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteScratch(SMALLINT bank, int portnum, uchar *SNum) { return readWriteSCR; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceScratch(SMALLINT bank, int portnum, uchar *SNum) { return writeOnceSCR; } /** * Query to see if current memory bank is read only. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlyScratch(SMALLINT bank, int portnum, uchar *SNum) { return readOnlySCR; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileScratch(SMALLINT bank, uchar *SNum) { return nonVolatileSCR; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseScratch(SMALLINT bank, uchar *SNum) { return needProgramPulseSCR; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliveryScratch(SMALLINT bank, uchar *SNum) { SMALLINT ret; switch (SNum[0]) { case 0x23: ret = TRUE; break; default: ret = needPowerDeliverySCR; 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoScratch(SMALLINT bank, uchar *SNum) { return ExtraInfoSCR; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoScratch()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthScratch(SMALLINT bank, uchar *SNum) { return extraInfoLengthSCR; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoScratch()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescScratch(SMALLINT bank, uchar *SNum) { return extraInfoDescSCR; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCScratch()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCScratch(SMALLINT bank, uchar *SNum) { SMALLINT ret; switch (SNum[0]) { case 0x21: case 0x18: ret = hasPageAutoCRCScratchCRC(bank, SNum); break; default: ret = pageAutoCRCSCR; break; } return ret; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthScratch(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH_SCR - 3; } //-------- //-------- Bank specific methods //-------- /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageScratch(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageScratch(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageScratch(SMALLINT bank, uchar *SNum) { return FALSE; } //-------- //-------- ScratchPad methods //-------- /** * Read the scratchpad page of memory from a NV device * This method reads and returns the entire scratchpad after the byte * offset regardless of the actual ending offset * * portnum the port number of the port being used for the * 1-Wire Network. * readBuf byte array to place read data into * length of array is always pageLength. * str_add offset into readBuf to pug data * len length in bytes to read * extraInfo byte array to put extra info read into * (TA1, TA2, e/s byte) * length of array is always extraInfoLength. * Can be 'null' if extra info is not needed. * * @return 'true' if reading scratch pad was successfull. */ SMALLINT readScratchpd(int portnum, uchar *buff, int len) { int i; uchar raw_buf[4]; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build first block raw_buf[0] = READ_SCRATCHPAD_COMMAND; for (i = 1; i < extraInfoLengthSCR + 1; i++) raw_buf[i] = 0xFF; // do the first block for TA1, TA2, and E/S if (!owBlock(portnum, FALSE, raw_buf, extraInfoLengthSCR + 1)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // build the next block for (i = 0; i < len; i++) buff[i] = 0xFF; // send second block to read data, return result if (!owBlock(portnum, FALSE, buff, len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Read the scratchpad page of memory from a NV device * This method reads and returns the entire scratchpad after the byte * offset regardless of the actual ending offset * * portnum the port number of the port being used for the * 1-Wire Network. * readBuf byte array to place read data into * length of array is always pageLength. * str_add offset into readBuf to pug data * len length in bytes to read * extraInfo byte array to put extra info read into * (TA1, TA2, e/s byte) * length of array is always extraInfoLength. * Can be 'null' if extra info is not needed. * * @return 'true' if reading scratch pad was successfull. */ SMALLINT readScratchpdExtra(int portnum, uchar *buff, int len, uchar *extra) { int i; uchar raw_buf[PAGE_LENGTH_SCR + 4]; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build first block raw_buf[0] = READ_SCRATCHPAD_COMMAND; for (i = 1; i < extraInfoLengthSCR + 1; i++) raw_buf[i] = 0xFF; // do the first block for TA1, TA2, and E/S if (!owBlock(portnum, FALSE, raw_buf, extraInfoLengthSCR + 1)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } for (i = 0; i < len; i++) buff[i] = 0xFF; if (!owBlock(portnum, FALSE, buff, len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } for (i = 1; i < extraInfoLengthSCR + 1; i++) extra[i - 1] = raw_buf[i]; return TRUE; } /** * Write to the scratchpad page of memory a NV device. * * @param startAddr starting address * @param writeBuf byte array containing data to write * @param offset offset into readBuf to place data * @param len length in bytes to write * * @return 'true' if writing was successful */ SMALLINT writeScratchpd(int portnum, int str_add, uchar *writeBuf, int len) { uchar raw_buf[PAGE_LENGTH_SCR + 3]; int i; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block to send raw_buf[0] = WRITE_SCRATCHPAD_COMMAND; raw_buf[1] = (uchar)str_add & 0xFF; raw_buf[2] = (uchar)((str_add & 0xFFFF) >> 8) & 0xFF; for (i = 0; i < len; i++) raw_buf[i + 3] = writeBuf[i]; // send block, return result if (!owBlock(portnum, FALSE, &raw_buf[0], len + 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Copy the scratchpad page to memory. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * len length in bytes that was written already * * @return 'true' if the coping was successful. */ SMALLINT copyScratchpd(int portnum, int str_add, int len) { uchar raw_buf[5]; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block to send raw_buf[0] = COPY_SCRATCHPAD_COMMAND; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; raw_buf[3] = (str_add + len - 1) & 0x1F; raw_buf[4] = 0xFF; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, 5)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if ((raw_buf[4] & 0x0F0) != 0) { OWERROR(OWERROR_COPY_SCRATCHPAD_NOT_FOUND); return FALSE; } return TRUE; } w1retap/src/libusblinux300/mbscr.h000066400000000000000000000102431446446235200173040ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCR.h - Memory bank class for the Scratchpad section of NVRAM iButtons and // 1-Wire devices. // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT readScratch(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len); SMALLINT writeScratch(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT readPageScratch(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraScratch(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCScratch(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCScratch(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPagePacketScratch(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPagePacketExtraScratch(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT writePagePacketScratch(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len); SMALLINT getNumberPagesScratch(SMALLINT bank, uchar *SNum); int getSizeScratch(SMALLINT bank, uchar *SNum); int getStartingAddressScratch(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthScratch(SMALLINT bank, uchar *SNum); char *getBankDescriptionScratch(SMALLINT bank, uchar *SNum); SMALLINT isGeneralPurposeMemoryScratch(SMALLINT bank, uchar *SNum); SMALLINT isReadWriteScratch(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceScratch(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadOnlyScratch(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isNonVolatileScratch(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseScratch(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliveryScratch(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoScratch(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthScratch(SMALLINT bank, uchar *SNum); char *getExtraInfoDescScratch(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthScratch(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCScratch(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageScratch(SMALLINT bank, uchar *SNum); SMALLINT canLockPageScratch(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageScratch(SMALLINT bank, uchar *SNum); // Scratchpad functions SMALLINT writeScratchpd(int portnum, int str_add, uchar *writeBuf, int len); SMALLINT readScratchpd(int portnum, uchar *buff, int len); SMALLINT readScratchpdExtra(int portnum, uchar *buff, int len, uchar *extra); SMALLINT copyScratchpd(int portnum, int str_add, int len); w1retap/src/libusblinux300/mbscrcrc.c000066400000000000000000000204051446446235200177700ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCRCRC.h - Memory bank class for the Scratchpad section of NVRAM iButtons and // 1-Wire devices. // // Version: 2.10 // // Include Files #include "ownet.h" #include "mbscrcrc.h" #include "mbscr.h" // general command defines #define READ_SCRATCHPAD_COMMAND_CRC 0xAA #define COPY_SCRATCHPAD_COMMAND_CRC 0x55 // Local defines #define SIZE_SCRATCH_CRC 32 #define PAGE_LENGTH_SCRATCH_CRC 32 /** * Read page in the current 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). * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageScratchCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { uchar extra[3]; if (!readPageExtraScratchCRC(bank, portnum, SNum, page, rd_cont, buff, &extra[0])) return FALSE; return TRUE; } /** * Read page with extra information in the current 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. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraScratchCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { // only needs to be implemented if supported by hardware if (!hasPageAutoCRCScratch(bank, SNum)) { OWERROR(OWERROR_CRC_NOT_SUPPORTED); return FALSE; } // check if read exceeds memory if (page > getNumberPagesScratch(bank, SNum)) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } owSerialNum(portnum, SNum, FALSE); // read the scratchpad if (!readScratchPadCRC(portnum, buff, PAGE_LENGTH_SCRATCH_CRC, extra)) return FALSE; return TRUE; } /** * Read the scratchpad page of memory from a NV device * This method reads and returns the entire scratchpad after the byte * offset regardless of the actual ending offset. * * NOTE: If tring to just read the last byte of the scratch pad the * read will not work. It is an error in the hardware. It is * currently being looked at and will be resolved soon. * * portnum the port number of the port being used for the * 1-Wire Network. * buff byte array to place read data into * length of array is always pageLength. * len length in bytes to read * extra byte array to put extra info read into * (TA1, TA2, e/s byte) * length of array is always extraInfoLength. * Can be 'null' if extra info is not needed. * * @return 'true' if reading scratch pad was successfull. */ SMALLINT readScratchPadCRC(int portnum, uchar *buff, int len, uchar *extra) { int i, num_crc, addr; uchar raw_buf[38]; ushort lastcrc16 = 0; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block raw_buf[0] = READ_SCRATCHPAD_COMMAND_CRC; for (i = 1; i < 38; i++) raw_buf[i] = 0xFF; // send block, command + (extra) + page data + CRC if (!owBlock(portnum, FALSE, raw_buf, len + 6)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // get the starting offset to see when the crc will show up addr = raw_buf[1]; addr = (addr | ((raw_buf[2] << 8) & 0xFF00)) & 0xFFFF; num_crc = 35 - (addr & 0x001F) + 3; // check crc of entire block setcrc16(portnum, 0); for (i = 0; i < num_crc; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } // extract the extra info for (i = 1; i < 4; i++) extra[i - 1] = raw_buf[i]; // extract the page data for (i = 4; i < 36; i++) buff[i - 4] = raw_buf[i]; return TRUE; } /** * Copy the scratchpad page to memory. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * len length in bytes that was written already * * @return 'true' if the coping was successful. */ SMALLINT copyScratchPadCRC(int portnum, int str_add, int len) { uchar raw_buf[6]; int i; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } raw_buf[0] = COPY_SCRATCHPAD_COMMAND_CRC; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; raw_buf[3] = (str_add + len - 1) & 0x1F; for (i = 4; i < 6; i++) raw_buf[i] = 0xFF; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, 6)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (((raw_buf[5] & 0x0F0) != 0xA0) && ((raw_buf[5] & 0x0F0) != 0x50)) { OWERROR(OWERROR_COPY_SCRATCHPAD_NOT_FOUND); return FALSE; } return TRUE; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionScratchCRC(SMALLINT bank, uchar *SNum) { return "Scratchpad with CRC"; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCScratch()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCScratchCRC(SMALLINT bank, uchar *SNum) { return TRUE; } w1retap/src/libusblinux300/mbscrcrc.h000066400000000000000000000042171446446235200200000ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCRCRC.h - Memory bank class for the Scratchpad section of NVRAM iButtons and // 1-Wire devices. // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT readPageScratchCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraScratchCRC(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readScratchPadCRC(int portnum, uchar *buff, int len, uchar *extra); SMALLINT copyScratchPadCRC(int portnum, int str_add, int len); char *getBankDescriptionScratchCRC(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCScratchCRC(SMALLINT bank, uchar *SNum); w1retap/src/libusblinux300/mbscree.c000066400000000000000000000107561446446235200176220ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCREE.c - Memory bank class for the Scratchpad section of EEPROM iButtons and // 1-Wire devices. // // Version: 2.10 // // Include Files #include "mbscree.h" // general command defines #define WRITE_SCRATCHPAD_COMMAND 0x0F #define COPY_SCRATCHPAD_COMMAND 0x55 // Local defines #define SIZE_SCRATCH_EE 32 #define PAGE_LENGTH_SCRATCH_EE 32 /** * Write to the scratchpad page of memory a 23 family device. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * writeBuf byte array containing data to write * len length in bytes to write * * @return 'true' if writing was successful */ SMALLINT writeScratchPadEE(int portnum, int str_add, uchar *writeBuf, int len) { uchar raw_buf[PAGE_LENGTH_SCRATCH_EE + 5]; int send_len = 0; int i; ushort lastcrc16 = 0; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block to send raw_buf[0] = WRITE_SCRATCHPAD_COMMAND; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; for (i = 3; i < len + 3; i++) raw_buf[i] = writeBuf[i - 3]; // check if full page (can utilize CRC) if (((str_add + len) % PAGE_LENGTH_SCRATCH_EE) == 0) { for (i = len + 3; i < len + 5; i++) raw_buf[i] = 0xFF; send_len = PAGE_LENGTH_SCRATCH_EE + 5; } else send_len = len + 3; // send block, return result if (!owBlock(portnum, FALSE, raw_buf, send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (send_len == (PAGE_LENGTH_SCRATCH_EE + 5)) { // verify the CRC is correct setcrc16(portnum, 0); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } return TRUE; } /** * Copy the scratchpad page to memory of a 23h device. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * len length in bytes that was written already * * @return 'true' if the coping was successful. */ SMALLINT copyScratchPadEE(int portnum, int str_add, int len) { uchar raw_buf[3]; SMALLINT rslt = 0; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block to send raw_buf[0] = COPY_SCRATCHPAD_COMMAND; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (!owWriteBytePower(portnum, ((str_add + len - 1) & 0x1F))) return FALSE; msDelay(5); rslt = owLevel(portnum, MODE_NORMAL); if (MODE_NORMAL != rslt) return FALSE; rslt = owReadByte(portnum); if (((uchar)(rslt & 0x0F0) != (uchar)0xA0) && ((uchar)(rslt & 0x0F0) != (uchar)0x50)) { OWERROR(OWERROR_COPY_SCRATCHPAD_NOT_FOUND); return FALSE; } return TRUE; } w1retap/src/libusblinux300/mbscree.h000066400000000000000000000033771446446235200176300ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCREE.h - Memory bank class for the Scratchpad section of EEPROM iButtons and // 1-Wire devices. // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT writeScratchPadEE(int portnum, int str_add, uchar *writeBuf, int len); SMALLINT copyScratchPadEE(int portnum, int str_add, int len); w1retap/src/libusblinux300/mbscrex.c000066400000000000000000000112461446446235200176400ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCREx.h - Memory bank class for the Scratchpad section of NVRAM iButtons and // 1-Wire devices. // // Version: 2.10 // // Include Files #include "ownet.h" #include "mbscrex.h" // general command defines #define WRITE_SCRATCHPAD_COMMAND_EX 0x0F #define COPY_SCRATCHPAD_COMMAND_EX 0x5A // Local defines #define SIZE_SCRATCH_EX 32 #define PAGE_LENGTH_SCRATCH_EX 32 /** * Write to the scratchpad page of memory a NV device. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * writeBuf byte array containing data to write * len length in bytes to write * * @return 'true' if writing was successful */ SMALLINT writeScratchPadEx(int portnum, int str_add, uchar *writeBuf, int len) { int send_len = 0; int i; uchar raw_buf[37]; ushort lastcrc16 = 0; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block to send raw_buf[0] = WRITE_SCRATCHPAD_COMMAND_EX; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; for (i = 3; i < len + 3; i++) raw_buf[i] = writeBuf[i - 3]; // check if full page (can utilize CRC) // if (((str_add+len) % PAGE_LENGTH_SCRATCH_EX) == 0) if (len == PAGE_LENGTH_SCRATCH_EX) { for (i = len + 3; i < len + 5; i++) raw_buf[i] = 0xFF; send_len = PAGE_LENGTH_SCRATCH_EX + 5; } else send_len = len + 3; // send block, return result if (!owBlock(portnum, FALSE, raw_buf, send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (send_len == (PAGE_LENGTH_SCRATCH_EX + 5)) { // verify the CRC is correct setcrc16(portnum, 0); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } return TRUE; } /** * Copy the scratchpad page to memory. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * len length in bytes that was written already * * @return 'true' if the coping was successful. */ SMALLINT copyScratchPadEx(int portnum, int str_add, int len) { uchar raw_buf[6]; int i; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } raw_buf[0] = COPY_SCRATCHPAD_COMMAND_EX; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; raw_buf[3] = (str_add + len - 1) & 0x1F; for (i = 4; i < 6; i++) raw_buf[i] = 0xFF; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, 6)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (((raw_buf[5] & 0x0F0) != 0xA0) && ((raw_buf[5] & 0x0F0) != 0x50)) { OWERROR(OWERROR_COPY_SCRATCHPAD_NOT_FOUND); return FALSE; } return TRUE; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionScratchEx(SMALLINT bank, uchar *SNum) { return "Scratchpad Ex"; } w1retap/src/libusblinux300/mbscrex.h000066400000000000000000000034741446446235200176510ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCREx.h - Memory bank class for the Scratchpad section of NVRAM iButtons and // 1-Wire devices. // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT writeScratchPadEx(int pornum, int str_add, uchar *writeBuf, int len); SMALLINT copyScratchPadEx(int portnum, int str_add, int len); char *getBankDescriptionScratchEx(SMALLINT bank, uchar *SNum); w1retap/src/libusblinux300/mbscrx77.c000066400000000000000000000755761446446235200176710ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCRx77.h - Memory bank class for the Scratchpad section of DS1977 // // Version: 2.10 // // Include Files #include "ownet.h" #include "mbscrx77.h" #include "pw77.h" // general command defines #define WRITE_SCRATCHPAD_COMMAND_EX 0x0F #define COPY_SCRATCHPAD_CMD_PW 0x99 #define READ_SCRATCHPAD_COMMAND_CRC 0xAA #define MATCH_COMMAND 0x55 // Local defines #define SIZE_SCRATCH_EX 64 #define PAGE_LENGTH_SCRATCH_EX 64 #define SIZE_SCRATCH_EX_HYGRO 32 #define PAGE_LENGTH_SCRATCH_HYGRO 32 SMALLINT generalPurposeMemorySCREx77 = FALSE; SMALLINT readWriteSCREx77 = TRUE; SMALLINT writeOnceSCREx77 = FALSE; SMALLINT readOnlySCREx77 = FALSE; SMALLINT nonVolatileSCREx77 = FALSE; SMALLINT needProgramPulseSCREx77 = FALSE; SMALLINT needPowerDeliverySCREx77 = TRUE; SMALLINT ExtraInfoSCREx77 = TRUE; SMALLINT extraInfoLengthSCREx77 = 4; char *extraInfoDescSCREx77 = "Address, Ending offset and Data Status"; SMALLINT pageAutoCRCScratchEx77 = TRUE; /** * Write to the scratchpad page of memory a NV device. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * str_add starting address * writeBuf byte array containing data to write * len length in bytes to write * * @return 'true' if writing was successful */ SMALLINT writeScratchPadEx77(int portnum, uchar *SNum, int str_add, uchar *writeBuf, int len) { int send_len = 0; int i, checkcrc = FALSE; uchar raw_buf[85]; ushort lastcrc16 = 0; if (SNum[0] != 0x37) { if (((str_add + len) & 0x1F) != 0) { OWERROR(OWERROR_EOP_WRITE_SCRATCHPAD_FAILED); return FALSE; } } // reset if (!owTouchReset(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // add match command raw_buf[send_len++] = MATCH_COMMAND; for (i = 0; i < 8; i++) raw_buf[send_len++] = SNum[i]; // build block to send raw_buf[send_len++] = WRITE_SCRATCHPAD_COMMAND_EX; raw_buf[send_len++] = str_add & 0xFF; raw_buf[send_len++] = ((str_add & 0xFFFF) >> 8) & 0xFF; for (i = 0; i < len; i++) raw_buf[send_len++] = writeBuf[i]; // check if full page (can utilize CRC) if (SNum[0] == 0x37) { if (((str_add + len) % PAGE_LENGTH_SCRATCH_EX) == 0) { for (i = 0; i < 2; i++) raw_buf[send_len++] = 0xFF; checkcrc = TRUE; } } else { if (((str_add + len) % PAGE_LENGTH_SCRATCH_HYGRO) == 0) { for (i = 0; i < 2; i++) raw_buf[send_len++] = 0xFF; checkcrc = TRUE; } } // send block, return result if (!owBlock(portnum, FALSE, raw_buf, send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // verify echo of bytes was correct for (i = 12; i < send_len - (checkcrc ? 2 : 0); i++) { if (raw_buf[i] != writeBuf[i - 12]) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } // check if crc is available if (checkcrc) { // verify the CRC is correct setcrc16(portnum, 0); for (i = 9; i < send_len; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } return TRUE; } /** * Read the scratchpad page of memory from a NV device * This method reads and returns the entire scratchpad after the byte * offset regardless of the actual ending offset. * * NOTE: If tring to just read the last byte of the scratch pad the * read will not work. It is an error in the hardware. It is * currently being looked at and will be resolved soon. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * buff byte array to place read data into * length of array is always pageLength. * len length in bytes to read * extra byte array to put extra info read into * (TA1, TA2, e/s byte) * length of array is always extraInfoLength. * Can be 'null' if extra info is not needed. * * @return 'true' if reading scratch pad was successfull. */ SMALLINT readScratchPadCRC77(int portnum, uchar *SNum, uchar *buff, int len, uchar *extra) { int i, num_crc, addr, send_len = 0, addr_offset; uchar raw_buf[110]; ushort lastcrc16 = 0; // reset if (!owTouchReset(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // add match command raw_buf[send_len++] = MATCH_COMMAND; for (i = 0; i < 8; i++) raw_buf[send_len++] = SNum[i]; // build block raw_buf[send_len++] = READ_SCRATCHPAD_COMMAND_CRC; addr_offset = send_len; if (SNum[0] == 0x37) { for (i = 0; i < 69; i++) raw_buf[send_len++] = 0xFF; } else { for (i = 0; i < 37; i++) raw_buf[send_len++] = 0xFF; } // send block, command + (extra) + page data + CRC if (!owBlock(portnum, FALSE, &raw_buf[0], send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // get the starting offset to see when the crc will show up addr = raw_buf[addr_offset]; addr = (addr | ((raw_buf[addr_offset + 1] << 8) & 0xFF00)) & 0xFFFF; if (SNum[0] == 0x37) { num_crc = 76 - (addr & 0x003F) + 3; } else { num_crc = 44 - (addr & 0x001F) + 3; } // check crc of entire block (minus match) setcrc16(portnum, 0); for (i = addr_offset - 1; i < num_crc; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } // extract the extra info for (i = addr_offset; i < (addr_offset + 4); i++) extra[i - addr_offset] = raw_buf[i]; // extract the page data if (SNum[0] == 0x37) { for (i = (addr_offset + 3); i < ((addr_offset + 3) + 64); i++) buff[i - (addr_offset + 3)] = raw_buf[i]; } else { for (i = (addr_offset + 3); i < ((addr_offset + 3) + 32); i++) buff[i - (addr_offset + 3)] = raw_buf[i]; } return TRUE; } /** * Copy the scratchpad page to memory. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part. * str_add starting address * len length in bytes that was written already * * @return 'true' if the coping was successful. */ SMALLINT copyScratchPadPsw77(int portnum, uchar *SNum, int str_add, int len, uchar *psw) { uchar raw_buf[25]; SMALLINT i, send_len = 0, rslt; if (SNum[0] != 0x37) { if (((str_add + len) & 0x1F) != 0) { OWERROR(OWERROR_EOP_COPY_SCRATCHPAD_FAILED); return FALSE; } } // reset if (!owTouchReset(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // add match command raw_buf[send_len++] = MATCH_COMMAND; for (i = 0; i < 8; i++) raw_buf[send_len++] = SNum[i]; // command, address, offset, password (except last byte) raw_buf[send_len++] = COPY_SCRATCHPAD_CMD_PW; raw_buf[send_len++] = str_add & 0xFF; raw_buf[send_len++] = ((str_add & 0xFFFF) >> 8) & 0xFF; if (SNum[0] == 0x37) raw_buf[send_len++] = (str_add + len - 1) & 0x3F; else raw_buf[send_len++] = (str_add + len - 1) & 0x1F; for (i = 0; i < 7; i++) raw_buf[send_len++] = psw[i]; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // send last byte of password and enable strong pullup if (!owWriteBytePower(portnum, psw[7])) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } // delay for copy to complete msDelay(10); //????????10, could be 5 // check result rslt = owReadByte(portnum); if (((rslt & 0xF0) != 0xA0) && ((rslt & 0xF0) != 0x50)) { OWERROR(OWERROR_COPY_SCRATCHPAD_NOT_FOUND); return FALSE; } return TRUE; } /** * Read page in the current 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 * readPagePacketScratch() method or have the 1-Wire device provide the * CRC as in readPageCRCScratch(). readPageCRCScratch() however is not * supported on all memory types, see 'hasPageAutoCRCScratch()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { uchar extra[4]; if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } if (SNum[0] == 0x37) return readScratchPadCRC77(portnum, SNum, buff, PAGE_LENGTH_SCRATCH_EX, extra); else return readScratchPadCRC77(portnum, SNum, buff, PAGE_LENGTH_SCRATCH_HYGRO, extra); } /** * Read page with extra information in the current 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 * readPagePacketScratch() method or have the 1-Wire device provide the * CRC as in readPageCRCScratch(). readPageCRCScratch() however is not * supported on all memory types, see 'hasPageAutoCRCScratch()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoScratch()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { // check if read exceeds memory if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } // read the scratchpad if (SNum[0] == 0x37) return readScratchPadCRC77(portnum, SNum, buff, PAGE_LENGTH_SCRATCH_EX, extra); else return readScratchPadCRC77(portnum, SNum, buff, PAGE_LENGTH_SCRATCH_HYGRO, extra); } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * See the method 'hasPageAutoCRC()'. * See the method 'haveExtraInfo()' for a description of the optional * extra information. * * 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. * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { // check if read exceeds memory if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } if (SNum[0] == 0x37) return readScratchPadCRC77(portnum, SNum, read_buff, PAGE_LENGTH_SCRATCH_EX, extra); else return readScratchPadCRC77(portnum, SNum, read_buff, PAGE_LENGTH_SCRATCH_HYGRO, extra); } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCScratch()'. * * 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. * page the page to read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { uchar extra[4]; // check if read exceeds memory if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } if (SNum[0] == 0x37) return readScratchPadCRC77(portnum, SNum, buff, PAGE_LENGTH_SCRATCH_EX, extra); else return readScratchPadCRC77(portnum, SNum, buff, PAGE_LENGTH_SCRATCH_HYGRO, extra); } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH_SCRATCH_EX]; uchar extra[4]; int i; ushort lastcrc16 = 0; // check if read exceeds memory if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } // read the scratchpad, discard extra information if (SNum[0] == 0x37) { if (!readScratchPadCRC77(portnum, SNum, raw_buf, PAGE_LENGTH_SCRATCH_EX, extra)) return FALSE; } else { if (!readScratchPadCRC77(portnum, SNum, raw_buf, PAGE_LENGTH_SCRATCH_HYGRO, extra)) return FALSE; } // check if length is realistic if (SNum[0] == 0x37) { if ((raw_buf[0] > (PAGE_LENGTH_SCRATCH_EX - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } } else { if ((raw_buf[0] > (PAGE_LENGTH_SCRATCH_HYGRO - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } } // verify the CRC is correct if (SNum[0] == 0x37) { setcrc16(portnum, (ushort)((getStartingAddressScratchEx77(bank, SNum) / PAGE_LENGTH_SCRATCH_EX) + page)); } else { setcrc16(portnum, (ushort)((getStartingAddressScratchEx77(bank, SNum) / PAGE_LENGTH_SCRATCH_HYGRO) + page)); } for (i = 0; i < raw_buf[0] + 3; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketScratch()' for a description of the packet structure. * See the method 'hasExtraInfoScratch()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { uchar raw_buf[PAGE_LENGTH_SCRATCH_EX]; int i; ushort lastcrc16 = 0; // check if read exceeds memory if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } // read the scratchpad if (SNum[0] == 0x37) { if (!readScratchPadCRC77(portnum, SNum, raw_buf, PAGE_LENGTH_SCRATCH_EX, extra)) return FALSE; } else { if (!readScratchPadCRC77(portnum, SNum, raw_buf, PAGE_LENGTH_SCRATCH_HYGRO, extra)) return FALSE; } // check if length is realistic if (SNum[0] == 0x37) { if ((raw_buf[0] > (PAGE_LENGTH_SCRATCH_EX - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } } else { if ((raw_buf[0] > (PAGE_LENGTH_SCRATCH_HYGRO - 3)) || (raw_buf[0] <= 0)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } } // verify the CRC is correct if (SNum[0] == 0x37) { setcrc16(portnum, (ushort)((getStartingAddressScratchEx77(bank, SNum) / PAGE_LENGTH_SCRATCH_EX) + page)); } else { setcrc16(portnum, (ushort)((getStartingAddressScratchEx77(bank, SNum) / PAGE_LENGTH_SCRATCH_HYGRO) + page)); } for (i = 0; i < raw_buf[0] + 3; i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0xB001) { // extract the data out of the packet for (i = 1; i < raw_buf[0] + 1; i++) buff[i - 1] = raw_buf[i]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Write a Universal Data Packet. See the method 'readPagePacketScratch()' * 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. * page the page the packet is being written to. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[64]; int i; ushort crc = 0; // check if read exceeds memory if (page != 0) { OWERROR(OWERROR_INVALID_PAGE_NUMBER); return FALSE; } // make sure length does not exceed max if (SNum[0] == 0x37) { if ((len > (PAGE_LENGTH_SCRATCH_EX - 3)) || (len <= 0)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } } else { if ((len > (PAGE_LENGTH_SCRATCH_HYGRO - 3)) || (len <= 0)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } } // see if this bank is general read/write if (!isGeneralPurposeMemoryScratchEx77(bank, SNum)) { OWERROR(OWERROR_NOT_GENERAL_PURPOSE); return FALSE; } // construct the packet to write raw_buf[0] = (uchar)len; for (i = 1; i < len + 1; i++) raw_buf[i] = buff[i - 1]; if (SNum[0] == 0x37) { setcrc16(portnum, (ushort)((getStartingAddressScratchEx77(bank, SNum) / PAGE_LENGTH_SCRATCH_EX) + page)); } else { setcrc16(portnum, (ushort)((getStartingAddressScratchEx77(bank, SNum) / PAGE_LENGTH_SCRATCH_HYGRO) + page)); } for (i = 0; i < len + 1; i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = (uchar)~crc & 0xFF; raw_buf[len + 2] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (!writeScratchPadEx77(portnum, SNum, 0, raw_buf, len)) return FALSE; return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesScratchEx77(SMALLINT bank, uchar *SNum) { return 1; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeScratchEx77(SMALLINT bank, uchar *SNum) { return SIZE_SCRATCH_EX; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressScratchEx77(SMALLINT bank, uchar *SNum) { return 0; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthScratchEx77(SMALLINT bank, uchar *SNum) { if (SNum[0] == 0x37) return PAGE_LENGTH_SCRATCH_EX; else return PAGE_LENGTH_SCRATCH_HYGRO; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemoryScratchEx77(SMALLINT bank, uchar *SNum) { return generalPurposeMemorySCREx77; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteScratchEx77(SMALLINT bank, int portnum, uchar *SNum) { return readWriteSCREx77; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceScratchEx77(SMALLINT bank, int portnum, uchar *SNum) { return writeOnceSCREx77; } /** * 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. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlyScratchEx77(SMALLINT bank, int portnum, uchar *SNum) { return readOnlySCREx77; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileScratchEx77(SMALLINT bank, uchar *SNum) { return nonVolatileSCREx77; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseScratchEx77(SMALLINT bank, uchar *SNum) { return needProgramPulseSCREx77; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliveryScratchEx77(SMALLINT bank, uchar *SNum) { return needPowerDeliverySCREx77; } /** * 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoScratchEx77(SMALLINT bank, uchar *SNum) { return ExtraInfoSCREx77; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoScratch()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthScratchEx77(SMALLINT bank, uchar *SNum) { return extraInfoLengthSCREx77; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoScratch()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescScratchEx77(SMALLINT bank, uchar *SNum) { return extraInfoDescSCREx77; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCScratch()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCScratchEx77(SMALLINT bank, uchar *SNum) { return pageAutoCRCScratchEx77; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthScratchEx77(SMALLINT bank, uchar *SNum) { if (SNum[0] == 0x37) return PAGE_LENGTH_SCRATCH_EX - 3; else return PAGE_LENGTH_SCRATCH_HYGRO - 3; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionScratchEx77(SMALLINT bank, uchar *SNum) { return "Scratchpad Ex"; } //-------- //-------- Bank specific methods //-------- /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageScratchEx77(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageScratchEx77(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageScratchEx77(SMALLINT bank, uchar *SNum) { return FALSE; } w1retap/src/libusblinux300/mbscrx77.h000066400000000000000000000100341446446235200176500ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSCRx77.h - Memory bank class for the Scratchpad section of DS1977 // // Version: 2.10 // #include "ownet.h" // Local function definitions SMALLINT writeScratchPadEx77(int pornum, uchar *SNum, int str_add, uchar *writeBuf, int len); SMALLINT readScratchPadCRC77(int portnum, uchar *SNum, uchar *buff, int len, uchar *extra); SMALLINT copyScratchPadPsw77(int portnum, uchar *SNum, int str_add, int len, uchar *psw); char *getBankDescriptionScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT canLockPageScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCScratchEx77(SMALLINT bank, uchar *SNum); char *getExtraInfoDescScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliveryScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT isNonVolatileScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT isReadOnlyScratchEx77(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceScratchEx77(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadWriteScratchEx77(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isGeneralPurposeMemoryScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthScratchEx77(SMALLINT bank, uchar *SNum); int getStartingAddressScratchEx77(SMALLINT bank, uchar *SNum); int getSizeScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT getNumberPagesScratchEx77(SMALLINT bank, uchar *SNum); SMALLINT writePagePacketScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len); SMALLINT readPagePacketExtraScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT readPagePacketScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPageCRCScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPageExtraCRCScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageExtraScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageScratchEx77(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); w1retap/src/libusblinux300/mbsha.c000066400000000000000000000123101446446235200172600ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSHA.h - Memory bank class for the Scratchpad section of SHA iButtons and // 1-Wire devices. // // Version: 2.00 // // History: 1.02 -> 1.03 Make sure uchar is not defined twice. // 1.03 -> 2.00 Changed 'MLan' to 'ow'. // // Include Files #include "ownet.h" #include "mbsha.h" // general command defines #define ERASE_SCRATCHPAD_COMMAND_SHA 0xC3 #define WRITE_SCRATCHPAD_COMMAND_SHA 0x0F #define COPY_SCRATCHPAD_COMMAND_SHA 0x55 // Local defines #define SIZE_SCRATCH_SHA 32 #define PAGE_LENGTH_SCRATCH_SHA 32 /** * Write to the scratchpad page of memory a NV device. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * writeBuf byte array containing data to write * len length in bytes to write * * @return 'true' if writing was successful */ SMALLINT writeScratchPadSHA(int portnum, int str_add, uchar *writeBuf, int len) { uchar raw_buf[37]; int sendlen = 0; int i; ushort lastcrc16 = 0; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // erase the scratchpad raw_buf[0] = ERASE_SCRATCHPAD_COMMAND_SHA; for (i = 1; i < 9; i++) raw_buf[i] = 0xFF; if (!owBlock(portnum, FALSE, raw_buf, 9)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (((raw_buf[8] & 0x0F0) != 0xA0) && ((raw_buf[8] & 0x0F0) != 0x50)) { OWERROR(OWERROR_ERASE_SCRATCHPAD_NOT_FOUND); return FALSE; } // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build block to send raw_buf[0] = WRITE_SCRATCHPAD_COMMAND_SHA; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; for (i = 3; i < len + 3; i++) raw_buf[i] = writeBuf[i - 3]; // check if full page (can utilize CRC) if (((str_add + len) % PAGE_LENGTH_SCRATCH_SHA) == 0) { raw_buf[len + 3] = 0xFF; raw_buf[len + 4] = 0xFF; sendlen = len + 5; } else sendlen = len + 3; // send block, return result if (!owBlock(portnum, FALSE, raw_buf, sendlen)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // check crc if (sendlen == len + 5) { setcrc16(portnum, 0); for (i = 0; i < (len + 5); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } return TRUE; } /** * Copy the scratchpad page to memory. * * portnum the port number of the port being used for the * 1-Wire Network. * str_add starting address * len length in bytes that was written already * * @return 'true' if the coping was successful. */ SMALLINT copyScratchPadSHA(int portnum, int str_add, int len) { uchar raw_buf[6]; int i; // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } raw_buf[0] = COPY_SCRATCHPAD_COMMAND_SHA; raw_buf[1] = str_add & 0xFF; raw_buf[2] = ((str_add & 0xFFFF) >> 8) & 0xFF; raw_buf[3] = (str_add + len - 1) & 0x1F; for (i = 4; i < 6; i++) raw_buf[i] = 0xFF; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, 6)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } if (((raw_buf[5] & 0x0F0) != 0xA0) && ((raw_buf[5] & 0x0F0) != 0x50)) { OWERROR(OWERROR_COPY_SCRATCHPAD_NOT_FOUND); return FALSE; } return TRUE; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionScratchSHA(int bank, uchar *SNum) { return "Scratchpad with CRC and auto-hide"; } w1retap/src/libusblinux300/mbsha.h000066400000000000000000000036511446446235200172750ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mbSHA.h - Memory bank class for the Scratchpad section of SHA iButtons and // 1-Wire devices. // // Version: 2.00 // // History: 1.02 -> 1.03 Make sure uchar is not defined twice. // 1.03 -> 2.00 Changed 'MLan' to 'ow'. // #include "ownet.h" // Local function definitions SMALLINT writeScratchPadSHA(int portnum, int str_add, uchar *writeBuf, int len); SMALLINT copyScratchPadSHA(int portnum, int str_add, int len); char *getBankDescriptionScratchSHA(int bank, uchar *SNum); w1retap/src/libusblinux300/mbshaee.c000066400000000000000000001404041446446235200176000ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // mbSHAEE.c - Reads and writes to memory locations for the SHAEE memory bank. // version 1.00 // // Include Files #include "ownet.h" #include "mbshaee.h" int KTN(int n); int NLF(int B, int C, int D, int n); // General command defines #define READ_MEMORY_SHAEE 0xF0 #define WRITE_SCRATCHPAD_SHAEE 0x0F #define READ_SCRATCHPAD_SHAEE 0xAA #define LOAD_FIRST_SECRET_SHAEE 0x5A #define COPY_SCRATCHPAD_SHAEE 0x55 #define READ_AUTH_PAGE_SHAEE 0xA5 #define NEXT_SECRET_SHAEE 0x33 // Local defines #define PAGE_LENGTH_SHAEE 32 #define SIZE_SHAEE_MB_0_1 32 #define SIZE_SHAEE_MB_2 32 // Global variables char *bankDescriptionSHAEE = ""; SMALLINT writeVerificationSHAEE = TRUE; SMALLINT generalPurposeMemorySHAEE = TRUE; SMALLINT readWriteSHAEE = TRUE; // check memory status SMALLINT writeOnceSHAEE = FALSE; // check memory status SMALLINT readOnlySHAEE = FALSE; // check memory status SMALLINT nonVolatileSHAEE = TRUE; SMALLINT needProgramPulseSHAEE = FALSE; SMALLINT needPowerDeliverySHAEE = FALSE; SMALLINT ExtraInfoSHAEE = TRUE; // memory status page doesn't, so check bank SMALLINT extraInfoLengthSHAEE = 20; char *extraInfoDescSHAEE = "The MAC for the SHA Engine"; SMALLINT pageAutoCRCSHAEE = TRUE; // memory status page doesn't, so check bank // Global variables to write and read from part uchar local_secret[8]; uchar challenge[8]; uchar currentSN[8]; int checked = FALSE; uchar status[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /** * Read memory in the current 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 readPagePacketSHAEE() method or have * the 1-Wire device provide the CRC as in readPageCRCSHAEE(). readPageCRCSHAEE() * however is not supported on all memory types, see 'hasPageAutoCRCSHAEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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 read is * to be done on. * str_add starting physical address * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array to place read data into * len length in bytes to read * * @return 'true' if the read was complete */ SMALLINT readSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len) { int i; int addr; uchar raw_buf[3]; // check if read exceeds memory if ((str_add + len) > (PAGE_LENGTH_SHAEE * getNumberPagesSHAEE(bank, SNum))) { OWERROR(OWERROR_READ_OUT_OF_RANGE); return FALSE; } // see if need to access the device if (!rd_cont) { // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // build start reading memory block addr = str_add + getStartingAddressSHAEE(bank, SNum); raw_buf[0] = READ_MEMORY_SHAEE; raw_buf[1] = addr & 0xFF; raw_buf[2] = ((addr & 0xFFFF) >> 8) & 0xFF; // do the first block for command, address if (!owBlock(portnum, FALSE, raw_buf, 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } // pre-fill readBuf with 0xFF for (i = 0; i < len; i++) buff[i] = 0xFF; if (!owBlock(portnum, FALSE, buff, len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } return TRUE; } /** * Write memory in the current bank. It is recommended that * when writing data that some structure in the data is created * to provide error free reading back with readSHAEE(). Or the * method 'writePagePacketSHAEE()' could be used which automatically * wraps the data in a length and CRC. * * When using on Write-Once devices care must be taken to write into * into empty space. If write() 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 write is * to be done on. * str_add starting address * buff byte array containing data to write * len length in bytes to write * * @return 'true' if the write was complete. */ SMALLINT writeSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len) { int i, room_left; int startx, nextx, abs_addr, pl; uchar raw_buf[8]; uchar extra[20]; uchar memory[64]; // return if nothing to do if (len == 0) return TRUE; // check if write exceeds memory if ((str_add + len) > getSizeSHAEE(bank, SNum)) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } // check if trying to write read only bank if (isReadOnlySHAEE(bank, portnum, SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // loop while still have pages to write startx = 0; nextx = 0; // (start and next index into writeBuf) pl = 8; abs_addr = getStartingAddressSHAEE(bank, SNum) + str_add; if (!readSHAEE(bank, portnum, SNum, (str_add / PAGE_LENGTH_SHAEE) * PAGE_LENGTH_SHAEE, FALSE, memory, PAGE_LENGTH_SHAEE)) return FALSE; do { // calculate room left in current page room_left = pl - ((abs_addr + startx) % pl); // check if block left will cross end of page if ((len - startx) > room_left) nextx = startx + room_left; else nextx = len; if ((str_add + startx) >= PAGE_LENGTH_SHAEE) { if (!readSHAEE(bank, portnum, SNum, ((str_add + startx) / PAGE_LENGTH_SHAEE) * PAGE_LENGTH_SHAEE, FALSE, memory, PAGE_LENGTH_SHAEE)) return FALSE; } if ((str_add + startx) >= PAGE_LENGTH_SHAEE) for (i = 0; i < 8; i++) raw_buf[i] = memory[((((startx + str_add) / 8) * 8) - 32) + i]; else for (i = 0; i < 8; i++) raw_buf[i] = memory[(((startx + str_add) / 8) * 8) + i]; if ((nextx - startx) == 8) for (i = 0; i < 8; i++) raw_buf[i] = buff[startx + i]; else if (((str_add + nextx) % 8) == 0) for (i = 0; i < (8 - ((str_add + startx) % 8)); i++) raw_buf[((str_add + startx) % 8) + i] = buff[startx + i]; else for (i = 0; i < (((str_add + nextx) % 8) - ((str_add + startx) % 8)); i++) raw_buf[((str_add + startx) % 8) + i] = buff[startx + i]; // write the page of data to scratchpad if (!writeSpad(portnum, abs_addr + startx + room_left - 8, raw_buf, 8)) return FALSE; // Copy data from scratchpad into memory if (abs_addr > 127) for (i = 0; i < 8; i++) memory[i] = local_secret[i]; if (!copySpad(portnum, abs_addr + startx + room_left - 8, SNum, extra, memory)) return FALSE; // the status page starts on 136 if ((abs_addr + startx + room_left - 8) == 136) { for (i = 0; i < 8; i++) status[i] = memory[i]; for (i = 0; i < 8; i++) currentSN[i] = SNum[i]; checked = TRUE; } if (str_add >= PAGE_LENGTH_SHAEE) for (i = 0; i < 8; i++) memory[((((startx + str_add) / 8) * 8) - 32) + i] = raw_buf[i]; else for (i = 0; i < 8; i++) memory[(((startx + str_add) / 8) * 8) + i] = raw_buf[i]; // point to next index startx = nextx; } while (nextx < len); return TRUE; } /** * Read page in the current 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 * readPagePacketSHAEE() method or have the 1-Wire device provide the * CRC as in readPageCRCSHAEE(). readPageCRCSHAEE() however is not * supported on all memory types, see 'hasPageAutoCRCSHAEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff) { return readSHAEE(bank, portnum, SNum, page * PAGE_LENGTH_SHAEE, FALSE, buff, PAGE_LENGTH_SHAEE); } /** * Read page with extra information in the current 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 * readPagePacketSHAEE() method or have the 1-Wire device provide the * CRC as in readPageCRCSHAEE(). readPageCRCSHAEE() however is not * supported on all memory types, see 'hasPageAutoCRCSHAEE()'. * If neither is an option then this method could be called more * then once to at least verify that the same thing is read consistantly. * See the method 'hasExtraInfoSHAEE()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra) { int addr; if (!hasExtraInfoSHAEE(bank, SNum)) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } // build start reading memory block addr = page * PAGE_LENGTH_SHAEE; if (!ReadAuthPage(bank, portnum, addr, SNum, buff, extra)) return FALSE; return TRUE; } /** * Read a complete memory page with CRC verification provided by the * device with extra information. Not supported by all devices. * See the method 'hasPageAutoCRC()'. * See the method 'haveExtraInfo()' for a description of the optional * extra information. * * 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. * page the page to read * read_buff byte array containing data that was read. * extra the extra information * * @return - returns '0' if the read page wasn't completed with extra info. * '1' if the operation is complete. */ SMALLINT readPageExtraCRCSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra) { int addr; if (!hasPageAutoCRCSHAEE(bank, SNum)) { OWERROR(OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } // build start reading memory block addr = page * PAGE_LENGTH_SHAEE; if (!ReadAuthPage(bank, portnum, addr, SNum, read_buff, extra)) return FALSE; return TRUE; } /** * Read a complete memory page with CRC verification provided by the * device. Not supported by all devices. See the method * 'hasPageAutoCRCSHAEE()'. * * 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. * page the page to read * buff byte array containing data that was read * * @return - returns '0' if the read page wasn't completed. * '1' if the operation is complete. */ SMALLINT readPageCRCSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff) { return readSHAEE(bank, portnum, SNum, page * PAGE_LENGTH_SHAEE, FALSE, buff, PAGE_LENGTH_SHAEE); } /** * Read 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. This is structure is * used by this method to verify the data but is not returned, only * the data payload is returned. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len) { uchar raw_buf[PAGE_LENGTH_SHAEE]; ushort lastcrc16 = 0; int i; // read the page if (!readPageSHAEE(bank, portnum, SNum, page, rd_cont, &raw_buf[0])) return FALSE; // check if length is realistic if ((raw_buf[0] & 0x00FF) > getMaxPacketDataLengthSHAEE(bank, SNum)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } else if (raw_buf[0] == 0) { *len = raw_buf[0]; return TRUE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressSHAEE(bank, SNum) / PAGE_LENGTH_SHAEE) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0x0000B001) { // extract the data out of the packet for (i = 0; i < raw_buf[0]; i++) buff[i] = raw_buf[i + 1]; // extract the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Read a Universal Data Packet and extra information. See the * method 'readPagePacketSHAEE()' for a description of the packet structure. * See the method 'hasExtraInfoSHAEE()' for a description of the optional * extra information some devices have. * * 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. * page the page to read * rd_cont if 'true' then device read is continued without * re-selecting. This can only be used if the new * read() continious where the last one led off * and it is inside a 'beginExclusive/endExclusive' * block. * buff byte array containing data that was read. * len length of the packet * extra extra information * * @return - returns '0' if the read page packet wasn't completed * '1' if the operation is complete. */ SMALLINT readPagePacketExtraSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra) { uchar raw_buf[PAGE_LENGTH_SHAEE]; int addr; int i; ushort lastcrc16 = 0; if (!hasExtraInfoSHAEE(bank, SNum)) { OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED); return FALSE; } addr = page * PAGE_LENGTH_SHAEE; // read the page if (!ReadAuthPage(bank, portnum, addr, SNum, &raw_buf[0], extra)) return FALSE; // check if length is realistic if ((raw_buf[0] & 0x00FF) > getMaxPacketDataLengthSHAEE(bank, SNum)) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } else if (raw_buf[0] == 0) { *len = raw_buf[0]; return TRUE; } // verify the CRC is correct setcrc16(portnum, (ushort)((getStartingAddressSHAEE(bank, SNum) / PAGE_LENGTH_SHAEE) + page)); for (i = 0; i < (raw_buf[0] + 3); i++) lastcrc16 = docrc16(portnum, raw_buf[i]); if (lastcrc16 == 0x0000B001) { // extract the data out of the packet for (i = 0; i < raw_buf[0]; i++) buff[i] = raw_buf[i + 1]; // return the length *len = (int)raw_buf[0]; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } return TRUE; } /** * Write a Universal Data Packet. See the method 'readPagePacketSHAEE()' * 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. * page the page the packet is being written to. * buff byte array containing data that to write. * len length of the packet * * @return - returns '0' if the write page packet wasn't completed * '1' if the operation is complete. */ SMALLINT writePagePacketSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff, int len) { uchar raw_buf[PAGE_LENGTH_SHAEE]; ushort crc = 0; int i; // make sure length does not exceed max if (len > getMaxPacketDataLengthSHAEE(bank, SNum)) { OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE); return FALSE; } // see if this bank is general read/write if (!isGeneralPurposeMemorySHAEE(bank, SNum)) { OWERROR(OWERROR_NOT_GENERAL_PURPOSE); return FALSE; } // construct the packet to write raw_buf[0] = (uchar)len; for (i = 0; i < len; i++) raw_buf[i + 1] = buff[i]; // calculate crc setcrc16(portnum, (ushort)((getStartingAddressSHAEE(bank, SNum) / PAGE_LENGTH_SHAEE) + page)); for (i = 0; i < (len + 1); i++) crc = docrc16(portnum, raw_buf[i]); raw_buf[len + 1] = (uchar)~crc & 0xFF; raw_buf[len + 2] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; // write the packet, return result if (!writeSHAEE(bank, portnum, SNum, page * PAGE_LENGTH_SHAEE, raw_buf, len + 3)) return FALSE; return TRUE; } /** * Query to get the number of pages in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of pages in current memory bank */ SMALLINT getNumberPagesSHAEE(SMALLINT bank, uchar *SNum) { SMALLINT pages; if (bank == 2) pages = 2; else pages = 1; return pages; } /** * Query to get the memory bank size in bytes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return memory bank size in bytes. */ int getSizeSHAEE(SMALLINT bank, uchar *SNum) { int size; if (bank == 2) size = 64; else size = 32; return size; } /** * Query to get the starting physical address of this bank. Physical * banks are sometimes sub-divided into logical banks due to changes * in attributes. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return physical starting address of this logical bank. */ int getStartingAddressSHAEE(SMALLINT bank, uchar *SNum) { int start = 0; switch (bank) { case 0: start = 0; break; case 1: start = 32; break; case 2: start = 64; break; case 3: start = 128; break; default: start = 0; break; } return start; } /** * Query to get page length in bytes in current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return page length in bytes in current memory bank */ SMALLINT getPageLengthSHAEE(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH_SHAEE; } /** * Query to see get a string description of the current memory bank. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return String containing the memory bank description */ char *getBankDescriptionSHAEE(SMALLINT bank, uchar *SNum) { switch (bank) { case 0: return "Page Zero with write protection."; break; case 1: return "Page One with EPROM mode and write protection."; break; case 2: return "Page Two and Three with write protection."; break; case 3: return "Status Page that contains the secret and the status."; break; default: return bankDescriptionSHAEE; break; } return bankDescriptionSHAEE; } /** * Query to see if the current memory bank is general purpose * user memory. If it is NOT then it is Memory-Mapped and writing * values to this memory will 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. * * @return 'true' if current memory bank is general purpose */ SMALLINT isGeneralPurposeMemorySHAEE(SMALLINT bank, uchar *SNum) { SMALLINT gp = generalPurposeMemorySHAEE; if (bank == 3) gp = FALSE; return gp; } /** * Query to see if current memory bank is read/write. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank is read/write */ SMALLINT isReadWriteSHAEE(SMALLINT bank, int portnum, uchar *SNum) { SMALLINT rw = readWriteSHAEE; int i; for (i = 0; i < 8; i++) { if (SNum[i] != currentSN[i]) { checked = FALSE; break; } } if (!checked) { for (i = 0; i < 8; i++) currentSN[i] = SNum[i]; if (!readSHAEE(3, portnum, SNum, 8, FALSE, &status[0], 8)) return FALSE; checked = TRUE; } switch (bank) { case 0: if (((status[1] == 0xAA) || (status[1] == 0x55)) || ((status[5] == 0xAA) || (status[5] == 0x55))) rw = FALSE; break; case 1: if ((status[5] == 0xAA) || (status[5] == 0x55)) rw = FALSE; break; case 2: if ((status[5] == 0xAA) || (status[5] == 0x55)) rw = FALSE; break; case 3: rw = FALSE; break; default: rw = readWriteSHAEE; break; } return rw; } /** * Query to see if current memory bank is write 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. * * @return 'true' if current memory bank can only be written once */ SMALLINT isWriteOnceSHAEE(SMALLINT bank, int portnum, uchar *SNum) { SMALLINT once = writeOnceSHAEE; SMALLINT same = FALSE; int i; if (bank == 1) { for (i = 0; i < 8; i++) { if (SNum[i] == currentSN[i]) { if (i == 7) same = TRUE; } else { checked = FALSE; break; } } if (!checked && !same) { for (i = 0; i < 8; i++) currentSN[i] = SNum[i]; if (!readSHAEE(3, portnum, SNum, 8, FALSE, &status[0], 8)) return FALSE; if ((status[4] == 0xAA) || (status[4] == 0x55)) { checked = TRUE; once = TRUE; } } else { if ((status[4] == 0xAA) || (status[4] == 0x55)) once = TRUE; } } return once; } /** * 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. * * @return 'true' if current memory bank can only be read */ SMALLINT isReadOnlySHAEE(SMALLINT bank, int portnum, uchar *SNum) { SMALLINT ro = readOnlySHAEE; int i; for (i = 0; i < 8; i++) { if (SNum[i] != currentSN[i]) { checked = FALSE; break; } } if (!checked) { for (i = 0; i < 8; i++) currentSN[i] = SNum[i]; if (!readSHAEE(3, portnum, SNum, 8, FALSE, &status[0], 8)) return FALSE; checked = TRUE; } switch (bank) { case 0: if (((status[1] == 0xAA) || (status[1] == 0x55)) || ((status[5] == 0xAA) || (status[5] == 0x55))) ro = TRUE; break; case 1: if ((status[1] == 0xAA) || (status[1] == 0x55)) ro = TRUE; break; case 2: if ((status[1] == 0xAA) || (status[1] == 0x55)) ro = TRUE; break; default: ro = readOnlySHAEE; break; } return ro; } /** * 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. * * @return 'true' if current memory bank non volatile. */ SMALLINT isNonVolatileSHAEE(SMALLINT bank, uchar *SNum) { return nonVolatileSHAEE; } /** * Query to see if current memory bank pages need the adapter to * have a 'ProgramPulse' in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires a 'ProgramPulse'. */ SMALLINT needsProgramPulseSHAEE(SMALLINT bank, uchar *SNum) { return needProgramPulseSHAEE; } /** * Query to see if current memory bank pages need the adapter to * have a 'PowerDelivery' feature in order to write to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if writing to the current memory bank pages * requires 'PowerDelivery'. */ SMALLINT needsPowerDeliverySHAEE(SMALLINT bank, uchar *SNum) { return needPowerDeliverySHAEE; } /** * 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. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return true if reading the this memory bank's * pages provides extra information */ SMALLINT hasExtraInfoSHAEE(SMALLINT bank, uchar *SNum) { SMALLINT extra = ExtraInfoSHAEE; if (bank == 3) extra = FALSE; return extra; } /** * Query to get the length in bytes of extra information that * is read when read a page in the current memory bank. See * 'hasExtraInfoSHAEE()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return number of bytes in Extra Information read when reading * pages in the current memory bank. */ SMALLINT getExtraInfoLengthSHAEE(SMALLINT bank, uchar *SNum) { SMALLINT len = extraInfoLengthSHAEE; if (bank == 3) len = 0; return len; } /** * Query to get a string description of what is contained in * the Extra Informationed return when reading pages in the current * memory bank. See 'hasExtraInfoSHAEE()'. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return string describing extra information. */ char *getExtraInfoDescSHAEE(SMALLINT bank, uchar *SNum) { if (bank == 3) return ""; return extraInfoDescSHAEE; } /** * Query to see if current memory bank pages can be read with * the contents being verified by a device generated CRC. * This is used to see if the 'ReadPageCRCSHAEE()' can be used. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank can be read with self * generated CRC. */ SMALLINT hasPageAutoCRCSHAEE(SMALLINT bank, uchar *SNum) { SMALLINT autoCRC = pageAutoCRCSHAEE; if (bank == 3) autoCRC = FALSE; return autoCRC; } /** * Query to get Maximum data page length in bytes for a packet * read or written in the current memory bank. See the 'ReadPagePacket()' * and 'WritePagePacket()' methods. This method is only usefull * if the current memory bank is general purpose memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return max packet page length in bytes in current memory bank */ SMALLINT getMaxPacketDataLengthSHAEE(SMALLINT bank, uchar *SNum) { return PAGE_LENGTH_SHAEE - 3; } /** * Query to see if current memory bank pages can be redirected * to another pages. This is mostly 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. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canRedirectPageSHAEE(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages can be locked. A * locked page would prevent any changes to the memory. * * bank to tell what memory bank of the ibutton to use. * SNum the serial number for the part. * * @return 'true' if current memory bank pages can be redirected * to a new page. */ SMALLINT canLockPageSHAEE(SMALLINT bank, uchar *SNum) { return FALSE; } /** * Query to see if current memory bank pages 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. * * @return 'true' if current memory bank pages can be locked from * being redirected to a new page. */ SMALLINT canLockRedirectPageSHAEE(SMALLINT bank, uchar *SNum) { return FALSE; } // ------------------------ // Extras // ------------------------ /** * Write to the Scratch Pad, which is a max of 8 bytes. * * portnum the port number of the port being used for the * 1-Wire Network. * addr the address to write the data to * out_buf byte array to write into scratch pad * len length of the write data * * @return - returns 'TRUE' if scratch pad was written correctly * and 'FALSE' if not. */ SMALLINT writeSpad(int portnum, int addr, uchar *out_buf, int len) { uchar send_block[64]; ushort lastcrc16 = 0; int i, cnt; cnt = 0; // access the device if (owAccess(portnum)) { send_block[cnt++] = WRITE_SCRATCHPAD_SHAEE; send_block[cnt++] = addr & 0xFF; send_block[cnt++] = ((addr & 0xFFFF) >> 8) & 0xFF; for (i = 0; i < len; i++) send_block[cnt++] = out_buf[i]; send_block[cnt++] = 0xFF; send_block[cnt++] = 0xFF; if (!owBlock(portnum, FALSE, send_block, cnt)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // verify the CRC is correct setcrc16(portnum, 0); for (i = 0; i < cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); if (lastcrc16 != 0x0000B001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return TRUE; } /** * Copy what is in the Sratch Pad, which is a max of 8 bytes to a certain * address in memory. * * portnum the port number of the port being used for the * 1-Wire Network. * addr the address to copy the data to * SNum the serial number for the part. * extra_buf byte array to write the calculated MAC * memory byte array for memory of the page to be copied to * * @return - returns 'TRUE' if the scratch pad was copied correctly * and 'FALSE' if not. */ SMALLINT copySpad(int portnum, int addr, uchar *SNum, uchar *extra_buf, uchar *memory) { short send_cnt = 0; ushort tmpadd; uchar send_block[80]; int i; uchar scratch[8], es, test; unsigned MT[64]; int A, B, C, D, E; int Temp; for (i = 0; i < 4; i++) MT[i] = local_secret[i]; for (i = 4; i < 32; i++) MT[i] = memory[i - 4]; if (readSpad(portnum, &tmpadd, &es, scratch)) for (i = 32; i < 40; i++) MT[i] = scratch[i - 32]; else return FALSE; MT[40] = (addr & 0xf0) >> 5; for (i = 41; i < 48; i++) MT[i] = SNum[i - 41]; for (i = 48; i < 52; i++) MT[i] = local_secret[i - 44]; for (i = 52; i < 55; i++) MT[i] = 0xff; MT[55] = 0x80; for (i = 56; i < 62; i++) MT[i] = 0x00; MT[62] = 0x01; MT[63] = 0xB8; ComputeSHA(MT, &A, &B, &C, &D, &E); // access the device if (owAccess(portnum)) { // Copy command send_block[send_cnt++] = 0x55; // address 1 send_block[send_cnt++] = (uchar)(tmpadd & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((tmpadd >> 8) & 0xFF); // ending address with data status send_block[send_cnt++] = es; if (owBlock(portnum, FALSE, send_block, send_cnt)) { send_cnt = 0; // sending MAC Temp = E; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); extra_buf[i] = send_block[send_cnt - 1]; Temp >>= 8; } Temp = D; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); extra_buf[i] = send_block[send_cnt - 1]; Temp >>= 8; } Temp = C; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); extra_buf[i] = send_block[send_cnt - 1]; Temp >>= 8; } Temp = B; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); extra_buf[i] = send_block[send_cnt - 1]; Temp >>= 8; } Temp = A; for (i = 0; i < 4; i++) { send_block[send_cnt++] = (uchar)(Temp & 0x000000FF); extra_buf[i] = send_block[send_cnt - 1]; Temp >>= 8; } msDelay(2); if (owBlock(portnum, FALSE, send_block, send_cnt)) { msDelay(10); test = owReadByte(portnum); if ((test == 0xAA) || (test == 0x55)) return TRUE; else { if (test == 0xFF) { OWERROR(OWERROR_WRITE_PROTECTED); return FALSE; } else if (test == 0x00) { OWERROR(OWERROR_NONMATCHING_MAC); return FALSE; } } } OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } else { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return FALSE; } /** * Read from the Scratch Pad, which is a max of 8 bytes. * * portnum number 0 to MAX_PORTNUM-1. This number is provided to * indicate the symbolic port number. * addr the address to read the data * es offset byte read from scratchpad * data data buffer read from scratchpad * * @return - returns 'TRUE' if the scratch pad was read correctly * and 'FALSE' if not */ SMALLINT readSpad(int portnum, ushort *addr, uchar *es, uchar *data) { short send_cnt = 0; uchar send_block[50]; int i; ushort lastcrc16 = 0; // access the device if (owAccess(portnum)) { // read scratchpad command send_block[send_cnt++] = 0xAA; // now add the read bytes for data bytes and crc16 for (i = 0; i < 13; i++) send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { // copy data to return buffers *addr = (send_block[2] << 8) | send_block[1]; *es = send_block[3]; // calculate CRC16 of result setcrc16(portnum, 0); for (i = 0; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 == 0xB001) { for (i = 0; i < 8; i++) data[i] = send_block[4 + i]; // success return TRUE; } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } } else { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return FALSE; } /** * Reads authenticated page. * * portnum number 0 to MAX_PORTNUM-1. This number is provided to * indicate the symbolic port number. * addr address of the data to be read along with Physical address * SNum the serial number for the part. * data the data read from the address * extra the MAC calculated for this function * * @return - returns 'TRUE' if the page was read and had the correct MAC * and 'FALSE' if not. */ SMALLINT ReadAuthPage(SMALLINT bank, int portnum, int addr, uchar *SNum, uchar *data, uchar *extra) { short send_cnt = 0; uchar send_block[80]; int i; ushort lastcrc16; if (!writeSpad(portnum, addr, &challenge[0], 8)) return FALSE; // access the device if (owAccess(portnum)) { setcrc16(portnum, 0); // Read Authenticated Command send_block[send_cnt] = 0xA5; lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // address 1 send_block[send_cnt] = (uchar)(addr & 0xFF); lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // address 2 send_block[send_cnt] = (uchar)((addr >> 8) & 0xFF); lastcrc16 = docrc16(portnum, send_block[send_cnt++]); // data + FF byte for (i = 0; i < 35; i++) send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum, FALSE, send_block, send_cnt)) { // calculate CRC16 of result for (i = 3; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } for (i = 3; i < 35; i++) data[i - 3] = send_block[i]; send_cnt = 0; for (i = 0; i < 22; i++) send_block[send_cnt++] = 0xFF; // Delay for MAC msDelay(2); if (owBlock(portnum, FALSE, send_block, send_cnt)) { // calculate CRC16 of result setcrc16(portnum, 0); for (i = 0; i < send_cnt; i++) lastcrc16 = docrc16(portnum, send_block[i]); // verify CRC16 is correct if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return FALSE; } for (i = 0; i < 20; i++) extra[i] = send_block[i]; return TRUE; } else { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return FALSE; } /** * Loads data into memory without a copy scratchpad * * portnum number 0 to MAX_PORTNUM-1. This number is provided to * indicate the symbolic port number. * addr address of the data to be read along with Physical address * SNum the serial number for the part. * secret the load first secret data * data_len the length of the secret. * * @return - returns 'TRUE' if load first secret worked * and 'FALSE' if not. */ SMALLINT loadFirstSecret(int portnum, int addr, uchar *SNum, uchar *secret, int data_len) { ushort tempadd; uchar es, data[8], test; uchar send_block[32]; int send_cnt = 0; uchar mem[32]; int i; if (readSHAEE(3, portnum, SNum, 0, FALSE, mem, 16)) { if ((mem[8] == 0xAA) || (mem[8] == 0x55)) { OWERROR(OWERROR_WRITE_PROTECT_SECRET); return FALSE; } if (((addr < 32)) && (((mem[9] == 0xAA) || (mem[9] == 0x55)) || ((mem[13] == 0xAA) || (mem[13] == 0x55)))) { OWERROR(OWERROR_WRITE_PROTECT); return FALSE; } if (((addr < 128)) && ((mem[9] == 0xAA) || (mem[9] == 0x55))) { OWERROR(OWERROR_WRITE_PROTECT); return FALSE; } } if (writeSpad(portnum, addr, secret, data_len) && readSpad(portnum, &tempadd, &es, data)) { // access the device if (owAccess(portnum)) { // write scratchpad command send_block[send_cnt++] = 0x5A; // address 1 send_block[send_cnt++] = (uchar)(tempadd & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((tempadd >> 8) & 0xFF); // ending address with data status send_block[send_cnt++] = es; if (owBlock(portnum, FALSE, send_block, send_cnt)) { // 10ms delay for writing first secret msDelay(10); test = owReadByte(portnum); if ((test == 0xAA) || (test == 0x55)) { if (addr == 128) { for (i = 0; i < 8; i++) local_secret[i] = secret[i]; } return TRUE; } else { OWERROR(OWERROR_LOAD_FIRST_SECRET); return FALSE; } } else { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } } return FALSE; } /** * Calculate the next secret using the current one. * * portnum number 0 to MAX_PORTNUM-1. This number is provided to * indicate the symbolic port number. * addr address of the data to be read along with Physical address * SNum the serial number for the part. * secret the load first secret data * * @return - returns 'TRUE' if the next secret was calculated correctly * and 'FALSE' if not. */ SMALLINT computeNextSecret(int portnum, int addr, uchar *SNum, uchar *secret) { int i; unsigned MT[64]; int A, B, C, D, E; int Temp; uchar memory[32], scratch[8], es; ushort tmpadd; uchar send_block[32]; int send_cnt = 0; SMALLINT bank = 0; for (i = 0; i < 8; i++) scratch[i] = 0x00; if (!writeSpad(portnum, addr, scratch, 8)) return FALSE; for (i = 0; i < 4; i++) MT[i] = local_secret[i]; if (addr < 32) bank = 0; else if ((addr > 31) && (addr < 64)) bank = 1; else if ((addr > 63) && (addr < 128)) bank = 2; if (readSHAEE(bank, portnum, SNum, (addr / ((ushort)32)) * 32, FALSE, memory, 32)) for (i = 4; i < 36; i++) MT[i] = memory[i - 4]; else return FALSE; for (i = 36; i < 40; i++) MT[i] = 0xFF; if (readSpad(portnum, &tmpadd, &es, scratch)) { MT[40] = scratch[0] & 0x3F; for (i = 41; i < 48; i++) MT[i] = scratch[i - 40]; for (i = 48; i < 52; i++) MT[i] = local_secret[i - 44]; } else return FALSE; for (i = 52; i < 55; i++) MT[i] = 0xFF; MT[55] = 0x80; for (i = 56; i < 62; i++) MT[i] = 0x00; MT[62] = 0x01; MT[63] = 0xB8; ComputeSHA(MT, &A, &B, &C, &D, &E); Temp = E; for (i = 0; i < 4; i++) { secret[i] = (uchar)(Temp & 0x000000FF); //\\//\\//\\//\\// DEBUG: printing out what the next secret is. // printf("%02X",secret[i]); //\\//\\//\\//\\// DEBUG: printing out what the next secret is. Temp >>= 8; } //\\//\\//\\//\\// DEBUG: printing out what the next secret is. // printf("\n"); //\\//\\//\\//\\// DEBUG: printing out what the next secret is. Temp = D; for (i = 0; i < 4; i++) { secret[i + 4] = (uchar)(Temp & 0x000000FF); //\\//\\//\\//\\// DEBUG: printing out what the next secret is. // printf("%02X",secret[i+4]); //\\//\\//\\//\\// DEBUG: printing out what the next secret is. Temp >>= 8; } //\\//\\//\\//\\// DEBUG: printing out what the next secret is. // printf("\n"); //\\//\\//\\//\\// DEBUG: printing out what the next secret is. // access the device if (owAccess(portnum)) { // Next Secret command send_block[send_cnt++] = 0x33; // address 1 send_block[send_cnt++] = (uchar)(addr & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((addr >> 8) & 0xFF); if (owBlock(portnum, FALSE, send_block, send_cnt)) { msDelay(12); if (readSpad(portnum, &tmpadd, &es, scratch)) { for (i = 0; i < 8; i++) if (scratch[i] != 0xAA) { OWERROR(OWERROR_COMPUTE_NEXT_SECRET); return FALSE; } for (i = 0; i < 8; i++) local_secret[i] = secret[i]; return TRUE; } } else { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return FALSE; } /** * This function set the bus master secret, which is used in * calculating the MAC that is sent to the part for different * operations. * * new_secret is the new bus master secret to be set. */ void setBusMasterSecret(uchar *new_secret) { int i; for (i = 0; i < 8; i++) local_secret[i] = new_secret[i]; } /** * This function returns what the current bus master secret is. * * return_secret is used to copy what the current bus master * secret is. */ void returnBusMasterSecret(uchar *return_secret) { int i; for (i = 0; i < 8; i++) return_secret[i] = local_secret[i]; } /** * This function set the challenge, which resides in the * scratch pad for doing a read authenticate page command. * * new_challenge this is what the new challenge is going * to be set to. */ void setChallenge(uchar *new_challenge) { int i; for (i = 0; i < 8; i++) challenge[i] = new_challenge[i]; } //---------------------------------------------------------------------- // Compute the 160-bit MAC // // 'MT' - input data // 'A' - part of the 160 bits // 'B' - part of the 160 bits // 'C' - part of the 160 bits // 'D' - part of the 160 bits // 'E' - part of the 160 bits // // void ComputeSHA(unsigned int *MT, int *A, int *B, int *C, int *D, int *E) { unsigned int MTword[80]; int i; int ShftTmp; int Temp; for (i = 0; i < 16; i++) MTword[i] = (MT[i * 4] << 24) | (MT[i * 4 + 1] << 16) | (MT[i * 4 + 2] << 8) | MT[i * 4 + 3]; for (i = 16; i < 80; i++) { ShftTmp = MTword[i - 3] ^ MTword[i - 8] ^ MTword[i - 14] ^ MTword[i - 16]; MTword[i] = ((ShftTmp << 1) & 0xfffffffe) | ((ShftTmp >> 31) & 0x00000001); } *A = 0x67452301; *B = 0xefcdab89; *C = 0x98badcfe; *D = 0x10325476; *E = 0xc3d2e1f0; for (i = 0; i < 80; i++) { ShftTmp = ((*A << 5) & 0xffffffe0) | ((*A >> 27) & 0x0000001f); Temp = NLF(*B, *C, *D, i) + *E + KTN(i) + MTword[i] + ShftTmp; *E = *D; *D = *C; *C = ((*B << 30) & 0xc0000000) | ((*B >> 2) & 0x3fffffff); *B = *A; *A = Temp; } } // calculation used for the MAC int KTN(int n) { if (n < 20) return 0x5a827999; else if (n < 40) return 0x6ed9eba1; else if (n < 60) return 0x8f1bbcdc; else return 0xca62c1d6; } // calculation used for the MAC 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); } w1retap/src/libusblinux300/mbshaee.h000066400000000000000000000113131446446235200176010ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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 "ownet.h" // general command defines #define READ_MEMORY_COMMAND 0xF0 #define WRITE_SCRATCHPAD_COMMAND 0x0F #define READ_SCRATCHPAD_COMMAND 0xAA #define COPY_SCRATCHPAD_COMMAND 0x55 // Local defines #define SIZE_SHAEE 32 #define PAGE_LENGTH_SHAEE 32 // Local function definitions SMALLINT readSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int len); SMALLINT writeSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT readPageSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff); SMALLINT readPageExtraSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, SMALLINT rd_cont, uchar *buff, uchar *extra); SMALLINT readPageExtraCRCSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *read_buff, uchar *extra); SMALLINT readPageCRCSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff); SMALLINT readPagePacketSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len); SMALLINT readPagePacketExtraSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, SMALLINT rd_cont, uchar *buff, int *len, uchar *extra); SMALLINT writePagePacketSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add, uchar *buff, int len); SMALLINT getNumberPagesSHAEE(SMALLINT bank, uchar *SNum); int getSizeSHAEE(SMALLINT bank, uchar *SNum); SMALLINT getPageLengthSHAEE(SMALLINT bank, uchar *SNum); int getStartingAddressSHAEE(SMALLINT bank, uchar *SNum); char *getBankDescriptionSHAEE(SMALLINT bank, uchar *SNum); SMALLINT isGeneralPurposeMemorySHAEE(SMALLINT bank, uchar *SNum); SMALLINT isReadWriteSHAEE(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isWriteOnceSHAEE(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isReadOnlySHAEE(SMALLINT bank, int portnum, uchar *SNum); SMALLINT isNonVolatileSHAEE(SMALLINT bank, uchar *SNum); SMALLINT needsProgramPulseSHAEE(SMALLINT bank, uchar *SNum); SMALLINT needsPowerDeliverySHAEE(SMALLINT bank, uchar *SNum); SMALLINT hasExtraInfoSHAEE(SMALLINT bank, uchar *SNum); SMALLINT getExtraInfoLengthSHAEE(SMALLINT bank, uchar *SNum); char *getExtraInfoDescSHAEE(SMALLINT bank, uchar *SNum); SMALLINT getMaxPacketDataLengthSHAEE(SMALLINT bank, uchar *SNum); SMALLINT hasPageAutoCRCSHAEE(SMALLINT bank, uchar *SNum); SMALLINT canRedirectPageSHAEE(SMALLINT bank, uchar *SNum); SMALLINT canLockPageSHAEE(SMALLINT bank, uchar *SNum); SMALLINT canLockRedirectPageSHAEE(SMALLINT bank, uchar *SNum); SMALLINT loadFirstSecret(int portnum, int addr, uchar *SNum, uchar *secret, int data_len); SMALLINT computeNextSecret(int portnum, int addr, uchar *SNum, uchar *secret); void setBusMasterSecret(uchar *new_secret); void setChallenge(uchar *new_challenge); void returnBusMasterSecret(uchar *return_secret); // Local functions SMALLINT writeSpad(int portnum, int addr, uchar *out_buf, int len); SMALLINT readSpad(int portnum, ushort *addr, uchar *es, uchar *data); SMALLINT copySpad(int portnum, int addr, uchar *SNum, uchar *extra_buf, uchar *memory); SMALLINT ReadAuthPage(SMALLINT bank, int portnum, int addr, uchar *SNum, uchar *data, uchar *extra); void ComputeSHA(unsigned int *MT, int *A, int *B, int *C, int *D, int *E); w1retap/src/libusblinux300/memutil.c000066400000000000000000000657671446446235200176720ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // owMem.c - Goes through the testing the memory bank for different parts. // Version 2.00 // #define DEBUG 1 #include #include #include "ownet.h" #include "rawmem.h" #include "mbshaee.h" #include "mbeprom.h" #include "mbee77.h" #include "pw77.h" // Defines for the menu lists #define MAIN_MENU 0 #define BANK_MENU 1 #define ENTRY_MENU 2 // Defines for the switch statements for Main Menu #define MAIN_SELECT_DEVICE 0 #define MAIN_QUIT 1 // Defines for the switch statements for Memory Bank #define BANK_INFO 0 #define BANK_READ_BLOCK 1 #define BANK_READ_PAGE 2 #define BANK_READ_UDP 3 #define BANK_WRITE_BLOCK 4 #define BANK_WRITE_UDP 5 #define BANK_NEW_BANK 6 #define BANK_MAIN_MENU 7 #define BANK_BM_READ_PASS 8 #define BANK_BM_RW_PASS 9 #define BANK_READ_PASS 10 #define BANK_RW_PASS 11 #define BANK_ENABLE_PASS 12 #define BANK_DISABLE_PASS 13 // Defines for the switch statements for data entry #define MODE_TEXT 0 #define MODE_HEX 1 // Number of devices to list #define MAXDEVICES 10 // Max number for data entry #define MAX_LEN 256 // Local functions int menuSelect(int menu, uchar *SNum); SMALLINT selectDevice(int numDevices, uchar AllDevices[][8]); void printDeviceInfo(int portnum, uchar SNum[8]); SMALLINT selectBank(SMALLINT bank, uchar *SNum); void displayBankInformation(SMALLINT bank, int portnum, uchar SNum[8]); int getNumber(int min, int max); SMALLINT dumpBankBlock(SMALLINT bank, int portnum, uchar SNum[8], int addr, int len); SMALLINT dumpBankPage(SMALLINT bank, int portnum, uchar SNum[8], int pg); SMALLINT dumpBankPagePacket(SMALLINT bank, int portnum, uchar SNum[8], int pg); SMALLINT bankWriteBlock(SMALLINT bank, int portnum, uchar SNum[8], int addr, uchar *data, int length); SMALLINT bankWritePacket(SMALLINT bank, int portnum, uchar SNum[8], int pg, uchar *data, int length); SMALLINT optionSHAEE(SMALLINT bank, int portnum, uchar *SNum); // Global necessary for screenio int VERBOSE; uchar AllSN[MAXDEVICES][8]; int main(int argc, char **argv) { int len, addr, page, answer, i; int done = FALSE; SMALLINT bank = 1; uchar data[552]; int portnum = 0; uchar AllSN[MAXDEVICES][8]; int NumDevices; int owd; char msg[132]; // 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\n", msg); return 0; } printf("\n1-Wire Memory utility console application Version 0.01\n"); if ((portnum = owAcquireEx(argv[1])) < 0) { OWERROR_DUMP(stdout); return 0; } else { // loop to do menu do { // Main menu switch (menuSelect(MAIN_MENU, &AllSN[0][0])) { case MAIN_SELECT_DEVICE: // find all parts // loop to find all of the devices up to MAXDEVICES NumDevices = 0; do { // perform the search if (!owNext(portnum, TRUE, FALSE)) break; owSerialNum(portnum, AllSN[NumDevices], TRUE); NumDevices++; } while (NumDevices < (MAXDEVICES - 1)); /* for test devices without a serial number if(NumDevices == 0) { for(i=0;i<8;i++) AllSN[0][i] = 0x00; NumDevices++; }*/ // select a device owd = selectDevice(NumDevices, &AllSN[0]); // display device info printDeviceInfo(portnum, &AllSN[owd][0]); // select a bank bank = selectBank(bank, &AllSN[owd][0]); if ((AllSN[owd][0] == 0x33) || (AllSN[owd][0] == 0xB3)) bank = optionSHAEE(bank, portnum, &AllSN[owd][0]); // display bank information displayBankInformation(bank, portnum, &AllSN[owd][0]); // loop on bank menu do { switch (menuSelect(BANK_MENU, &AllSN[owd][0])) { case BANK_INFO: // display bank information displayBankInformation(bank, portnum, &AllSN[owd][0]); break; case BANK_READ_BLOCK: // read a block printf("Enter the address to start reading: "); addr = getNumber(0, (owGetSize(bank, &AllSN[owd][0]) - 1)); printf("\n"); printf("Enter the length of data to read: "); len = getNumber(0, owGetSize(bank, &AllSN[owd][0])); printf("\n"); if (!dumpBankBlock(bank, portnum, &AllSN[owd][0], addr, len)) OWERROR_DUMP(stderr); break; case BANK_READ_PAGE: printf("Enter the page number to read: "); page = getNumber(0, (owGetNumberPages(bank, &AllSN[owd][0]) - 1)); printf("\n"); if (!dumpBankPage(bank, portnum, &AllSN[owd][0], page)) OWERROR_DUMP(stderr); break; case BANK_READ_UDP: printf("Enter the page number to read: "); page = getNumber(0, (owGetNumberPages(bank, &AllSN[owd][0]) - 1)); printf("\n"); if (!dumpBankPagePacket(bank, portnum, &AllSN[owd][0], page)) OWERROR_DUMP(stderr); break; case BANK_WRITE_BLOCK: // write a block printf("Enter the address to start writing: "); addr = getNumber(0, (owGetSize(bank, &AllSN[owd][0]) - 1)); if (menuSelect(ENTRY_MENU, &AllSN[owd][0]) == MODE_TEXT) len = getData(data, MAX_LEN, MODE_TEXT); else len = getData(data, MAX_LEN, MODE_HEX); if (!bankWriteBlock(bank, portnum, &AllSN[owd][0], addr, data, len)) { OWERROR_DUMP(stderr); break; } if (owCanRedirectPage(bank, &AllSN[owd][0])) { printf("Enter if you want to redirect page (0 no, 1 yes): "); answer = getNumber(0, 1); if (answer) { printf("What page would you like to redirect:"); page = getNumber(0, 255); printf("Where would you like to redirect:"); addr = getNumber(0, 255); if (!redirectPage(bank, portnum, &AllSN[owd][0], page, addr)) { OWERROR_DUMP(stderr); break; } } } if (owCanLockPage(bank, &AllSN[owd][0])) { printf("Enter if you want to lock page (0 no, 1 yes):"); answer = getNumber(0, 1); if (answer) { printf("What page would you like to lock?"); page = getNumber(0, 255); if (!lockPage(bank, portnum, &AllSN[owd][0], page)) { OWERROR_DUMP(stderr); break; } } } if (owCanLockRedirectPage(bank, &AllSN[owd][0])) { printf("Enter if you want to lock redirected page (0 no, 1 yes):"); answer = getNumber(0, 1); if (answer) { printf("Which redirected page do you want to lock:"); page = getNumber(0, 255); if (!lockRedirectPage(bank, portnum, &AllSN[owd][0], page)) { OWERROR_DUMP(stderr); break; } } } break; case BANK_WRITE_UDP: printf("Enter the page number to write a UDP to: "); page = getNumber(0, (owGetNumberPages(bank, &AllSN[owd][0]) - 1)); if (menuSelect(ENTRY_MENU, &AllSN[owd][0]) == MODE_TEXT) len = getData(data, MAX_LEN, MODE_TEXT); else len = getData(data, MAX_LEN, MODE_HEX); if (!bankWritePacket(bank, portnum, &AllSN[owd][0], page, data, len)) OWERROR_DUMP(stderr); break; case BANK_BM_READ_PASS: printf("Enter the 8 byte read only password if less 0x00 will be filled in."); if (menuSelect(ENTRY_MENU, &AllSN[owd][0]) == MODE_TEXT) len = getData(data, 8, MODE_TEXT); else len = getData(data, 8, MODE_HEX); if (len != 8) { for (i = len; i < 8; i++) data[i] = 0x00; } if (!owSetBMReadOnlyPassword(portnum, &AllSN[owd][0], data)) OWERROR_DUMP(stderr); break; case BANK_BM_RW_PASS: printf("Enter the 8 byte read/write password if less 0x00 will be filled in."); if (menuSelect(ENTRY_MENU, &AllSN[owd][0]) == MODE_TEXT) len = getData(data, 8, MODE_TEXT); else len = getData(data, 8, MODE_HEX); if (len != 8) { for (i = len; i < 8; i++) data[i] = 0x00; } if (!owSetBMReadWritePassword(portnum, &AllSN[owd][0], data)) OWERROR_DUMP(stderr); break; case BANK_READ_PASS: printf("Enter the 8 byte read only password if less 0x00 will be filled in."); if (menuSelect(ENTRY_MENU, &AllSN[owd][0]) == MODE_TEXT) len = getData(data, 8, MODE_TEXT); else len = getData(data, 8, MODE_HEX); if (len != 8) { for (i = len; i < 8; i++) data[i] = 0x00; } if (!owSetReadOnlyPassword(portnum, &AllSN[owd][0], data)) OWERROR_DUMP(stderr); break; case BANK_RW_PASS: printf("Enter the 8 byte read/write password if less 0x00 will be filled in."); if (menuSelect(ENTRY_MENU, &AllSN[owd][0]) == MODE_TEXT) len = getData(data, 8, MODE_TEXT); else len = getData(data, 8, MODE_HEX); if (len != 8) { for (i = len; i < 8; i++) data[i] = 0x00; } if (!owSetReadWritePassword(portnum, &AllSN[owd][0], data)) OWERROR_DUMP(stderr); break; case BANK_ENABLE_PASS: if (!owSetPasswordMode(portnum, &AllSN[owd][0], ENABLE_PSW)) OWERROR_DUMP(stderr); break; case BANK_DISABLE_PASS: if (!owSetPasswordMode(portnum, &AllSN[owd][0], DISABLE_PSW)) OWERROR_DUMP(stderr); break; case BANK_NEW_BANK: // select a bank bank = selectBank(bank, &AllSN[owd][0]); if ((AllSN[owd][0] == 0x33) || (AllSN[owd][0] == 0xB3)) bank = optionSHAEE(bank, portnum, &AllSN[owd][0]); // display bank information displayBankInformation(bank, portnum, &AllSN[owd][0]); break; case BANK_MAIN_MENU: done = TRUE; break; } } while (!done); done = FALSE; break; case MAIN_QUIT: done = TRUE; break; } // Main menu switch } while (!done); // loop to do menu owRelease(portnum); } // else for owAcquire return 1; } //-------- //-------- Read methods //-------- /** * Read a block from a memory bank and print in hex * * bank MemoryBank to read a block from * portnum port number * SNum the serial number for the device * addr address to start reading from * len length of data to read * * @return 'true' if the dumping of the memory bank * worked. */ SMALLINT dumpBankBlock(SMALLINT bank, int portnum, uchar SNum[8], int addr, int len) { uchar read_buf[8000]; // make larger if the data being read is larger int i; if (!owRead(bank, portnum, SNum, addr, FALSE, &read_buf[0], len)) return FALSE; for (i = 0; i < len; i++) printf("%02X ", read_buf[i]); printf("\n"); return TRUE; } /** * Read a page from a memory bank and print in hex * * bank MemoryBank to read a page from * portnum port number * SNum The serial number of the device to read. * pg page to read * * @return 'true' if the bank page was dumped. */ SMALLINT dumpBankPage(SMALLINT bank, int portnum, uchar SNum[8], int pg) { uchar read_buf[64]; uchar extra_buf[32]; int i; int result; // read a page (use the most verbose and secure method) if (owHasPageAutoCRC(bank, SNum)) { if (owHasExtraInfo(bank, SNum)) result = owReadPageExtraCRC(bank, portnum, &SNum[0], pg, &read_buf[0], &extra_buf[0]); else result = owReadPageCRC(bank, portnum, &SNum[0], pg, &read_buf[0]); } else { if (owHasExtraInfo(bank, SNum)) result = owReadPageExtra(bank, portnum, &SNum[0], pg, FALSE, &read_buf[0], &extra_buf[0]); else result = owReadPage(bank, portnum, &SNum[0], pg, FALSE, &read_buf[0]); } if (!result) return FALSE; printf("Page %d: ", pg); for (i = 0; i < owGetPageLength(bank, SNum); i++) printf("%02X ", read_buf[i]); printf("\n"); if (owHasExtraInfo(bank, SNum)) { printf("Extra: "); for (i = 0; i < owGetExtraInfoLength(bank, SNum); i++) printf("%02X ", extra_buf[i]); printf("\n"); } return TRUE; } /** * Read a page packet from a memory bank and print in hex * * bank PagedMemoryBank to read a page from * portnum port number * SNum The serial number of the device to read. * pg page to read * * @return 'true' if the bank page packet was dumped. */ SMALLINT dumpBankPagePacket(SMALLINT bank, int portnum, uchar SNum[8], int pg) { uchar read_buf[32]; uchar extra_buf[32]; int read_rslt; int i; // read a page packet (use the most verbose method) if (owHasExtraInfo(bank, SNum)) { if (!owReadPagePacketExtra(bank, portnum, &SNum[0], pg, FALSE, &read_buf[0], &read_rslt, &extra_buf[0])) return FALSE; } else if (!owReadPagePacket(bank, portnum, &SNum[0], pg, FALSE, &read_buf[0], &read_rslt)) return FALSE; printf("Packet %d, len %d\n", pg, read_rslt); for (i = 0; i < read_rslt; i++) printf("%02X ", read_buf[i]); printf("\n"); if (owHasExtraInfo(bank, SNum)) { printf("Extra: "); for (i = 0; i < owGetExtraInfoLength(bank, SNum); i++) printf("%02X ", extra_buf[i]); printf("\n"); } return TRUE; } //-------- //-------- Write methods //-------- /** * Write a block of data with the provided MemoryBank. * * bank MemoryBank to write block to * portnum port number for the device. * SNum serial number for the device. * addr address to start the write. * data data to write in a byte array * length length of the data to be written * * @return 'true' if the write worked. */ SMALLINT bankWriteBlock(SMALLINT bank, int portnum, uchar SNum[8], int addr, uchar *data, int length) { if (!owWrite(bank, portnum, SNum, addr, data, length)) return FALSE; printf("\nWrote block length %d at addr %d\n", length, addr); return TRUE; } /** * Write a UDP packet to the specified page in the * provided PagedMemoryBank. * * bank PagedMemoryBank to write packet to * portnum port number for the device * SNum serial number for the device * pg page number to write packet to * data data to write in a byte array * length length of the data to be written * * @return 'true' if the packet was written. */ SMALLINT bankWritePacket(SMALLINT bank, int portnum, uchar SNum[8], int pg, uchar *data, int length) { if (!owWritePagePacket(bank, portnum, SNum, pg, data, length)) return FALSE; printf("\n"); printf("wrote packet length %d on page %d\n", length, pg); return TRUE; } //-------- //-------- Menu methods //-------- /** * Create a menu from the provided OneWireContainer * Vector and allow the user to select a device. * * numDevices the number of devices on the 1-Wire. * AllDevices holds all the Serial Numbers on the * 1-Wire. * * @return index of the choosen device. */ SMALLINT selectDevice(int numDevices, uchar AllDevices[][8]) { int i, j; printf("Device Selection\n"); for (i = 0; i < numDevices; i++) { printf("(%d) ", i); for (j = 7; j >= 0; j--) printf("%02X ", AllDevices[i][j]); printf("\n"); } return getNumber(0, numDevices - 1); } /** * Create a menu of memory banks from the provided OneWireContainer * allow the user to select one. * * bank the memory bank to be used. * SNum The serial number for the chosen device. * * @return MemoryBank memory bank selected */ SMALLINT selectBank(SMALLINT bank, uchar *SNum) { int i; int numberBanks = 0; printf("Memory Bank Selection for "); for (i = 7; i >= 0; i--) printf("%02X ", SNum[i]); printf("\n"); numberBanks = owGetNumberBanks(SNum[0]); // get the banks for (i = 0; i < numberBanks; i++) { printf("(%d) %s\n", i, owGetBankDescription((SMALLINT)i, SNum)); } if ((SNum[0] == 0x33) || (SNum[0] == 0xB3)) { printf("(%d) Load First Secret.\n", numberBanks++); printf("(%d) Compute Next Secret.\n", numberBanks++); printf("(%d) Change Bus Master Secret.\n", numberBanks++); printf("(%d) Lock Secret.\n", numberBanks++); printf("(%d) Input new challenge for Read Authenticate.\n", numberBanks++); printf("(%d) Write Protect page 0-3.\n", numberBanks++); printf("(%d) Set Page 1 to EPROM mode.\n", numberBanks++); printf("(%d) Write Protect Page 0.\n", numberBanks++); printf("(%d) Print Current Bus Master Secret.\n", numberBanks++); } return getNumber(0, numberBanks - 1); } //-------- //-------- Menu Methods //-------- /** * Display menu and ask for a selection. * * menu the menu selections. * * @return numberic value entered from the console. */ int menuSelect(int menu, uchar *SNum) { int length = 0; switch (menu) { case MAIN_MENU: printf("\n"); printf("MainMenu 1-Wire Memory Demo\n"); printf("(0) Select Device\n"); printf("(1) Quit\n"); length = 1; break; case BANK_MENU: printf("\n"); printf("Bank Operation Menu\n"); printf("(0) Get Bank information\n"); printf("(1) Read Block\n"); printf("(2) Read Page\n"); printf("(3) Read Page UDP packet\n"); printf("(4) Write Block\n"); printf("(5) Write UDP packet\n"); printf("(6) GOTO MemoryBank Menu\n"); printf("(7) GOTO MainMenu\n"); if (owNeedPassword(SNum)) { printf("(8) Set Bus Master read only password.\n"); printf("(9) Set Bus Master read/write password.\n"); printf("(10) Set device read only password.\n"); printf("(11) Set device read/write password.\n"); printf("(12) Enable the password.\n"); printf("(13) Disable the password.\n"); length = 13; } else { length = 7; } break; case ENTRY_MENU: printf("\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = 1; break; } printf("\nPlease enter value: "); return getNumber(0, length); } /** * 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; } /** * Extra options for the DS2432 * * bank the memory bank to be used. * portnum port number for the device * SNum The serial number for the chosen device. * * @return numeric value entered from the console. */ SMALLINT optionSHAEE(SMALLINT bank, int portnum, uchar *SNum) { int done = FALSE; int try_again = FALSE; int addr, len; uchar data[64]; int i; do { switch (bank) { case 0: case 1: case 2: case 3: done = TRUE; break; case 4: // Load First Secret printf("Enter the address for loading first secret: "); addr = getNumber(0, 152); printf("Enter the Load First Secret data: "); if (menuSelect(ENTRY_MENU, SNum) == MODE_TEXT) len = getData(data, MAX_LEN, MODE_TEXT); else len = getData(data, MAX_LEN, MODE_HEX); if (!loadFirstSecret(portnum, addr, SNum, &data[0], len)) OWERROR_DUMP(stderr); break; case 5: // Compute Next Secret printf("Enter the address for computing next secret: "); addr = getNumber(0, 128); if (!computeNextSecret(portnum, addr, SNum, &data[0])) OWERROR_DUMP(stderr); printf("The new secret is: "); for (i = 0; i < 8; i++) printf("%02X ", data[i]); printf("\n"); break; case 6: // Change Bus Master Secret printf("Enter the new Bus Master Secret: "); try_again = FALSE; do { if (menuSelect(ENTRY_MENU, SNum) == MODE_TEXT) len = getData(data, MAX_LEN, MODE_TEXT); else len = getData(data, MAX_LEN, MODE_HEX); if (len != 8) { printf("The secret is 8 bytes long try again: "); try_again = TRUE; } else try_again = FALSE; } while (try_again); setBusMasterSecret(&data[0]); break; case 7: // Lock Secret data[0] = 0xAA; if (!bankWriteBlock(3, portnum, SNum, 8, data, 1)) { OWERROR_DUMP(stderr); break; } break; case 8: // Input new challenge for Read Authenticate printf("Enter the New Challenge: "); try_again = FALSE; do { if (menuSelect(ENTRY_MENU, SNum) == MODE_TEXT) len = getData(data, MAX_LEN, MODE_TEXT); else len = getData(data, MAX_LEN, MODE_HEX); if (len != 8) { printf("The challenge is 8 bytes long try again: "); try_again = TRUE; } else try_again = FALSE; } while (try_again); setChallenge(&data[0]); break; case 9: // Write Protect page 0-3 data[0] = 0x00; if (!bankWriteBlock(3, portnum, SNum, 9, data, 1)) { OWERROR_DUMP(stderr); break; } break; case 10: // Set Page 1 to EEPROM mode data[0] = 0xAA; for (i = 5; i < 8; i++) data[i] = 0x00; if (!bankWriteBlock(3, portnum, SNum, 12, data, 1)) { OWERROR_DUMP(stderr); break; } break; case 11: // Write Protect Page 0 data[0] = 0xAA; if (!bankWriteBlock(3, portnum, SNum, 13, data, 1)) { OWERROR_DUMP(stderr); break; } break; case 12: // Print Current Bus Master Secret returnBusMasterSecret(&data[0]); printf("The current Bus Master Secret is: "); for (i = 0; i < 8; i++) printf("%02X ", data[i]); printf("\n"); break; default: done = TRUE; break; } if (!done) { printf("\n"); bank = selectBank(bank, SNum); } } while (!done); return bank; } //-------- //-------- Display Methods //-------- /** * Display information about the 1-Wire device * * portnum port number for the device * SNum serial number for the device */ void printDeviceInfo(int portnum, uchar SNum[8]) { int i; printf("\n"); printf("*************************************************************************\n"); printf("* Device Name: %s\n", owGetName(&SNum[0])); // printf("* Device Other Names: %s\n", owGetAlternateNames(portnum,&SNum[0]); printf("* Device Address: "); for (i = 7; i >= 0; i--) printf("%02X ", SNum[i]); printf("\n"); printf("* iButton Description: %s\n", owGetDescription(&SNum[0])); printf("*************************************************************************\n"); /* System.out.println( "* Device Max speed: " + ((owd.getMaxSpeed() == DSPortAdapter.SPEED_OVERDRIVE) ? "Overdrive" : "Normal"));*/ } /** * Display the information about the current memory back provided. * * portnum port number for the device * SNum serial number for the device */ void displayBankInformation(SMALLINT bank, int portnum, uchar SNum[8]) { printf("\n"); printf("|------------------------------------------------------------------------\n"); printf("| Bank: %s\n", owGetBankDescription(bank, SNum)); printf("| Size: %d starting at physical address %d\n", owGetSize(bank, SNum), owGetStartingAddress(bank, SNum)); printf("| Features: "); if (owIsReadWrite(bank, portnum, SNum)) printf("Read/Write "); if (owIsWriteOnce(bank, portnum, SNum)) printf("Write-once "); if (owIsReadOnly(bank, portnum, SNum)) printf("Read-only "); if (owIsGeneralPurposeMemory(bank, SNum)) printf("general-purpose "); else printf("not-general-purpose "); if (owIsNonVolatile(bank, SNum)) printf("non-volatile\n"); else printf("volatile\n"); if (owNeedsProgramPulse(bank, SNum)) printf("|\tneeds-program-pulse \n"); if (owNeedsPowerDelivery(bank, SNum)) printf("|\tneeds-power-delivery \n"); printf("| Pages: %d pages of length %d bytes ", owGetNumberPages(bank, SNum), owGetPageLength(bank, SNum)); if (owIsGeneralPurposeMemory(bank, SNum)) printf("giving %d bytes Packet data payload", owGetMaxPacketDataLength(bank, SNum)); printf("\n| Page Features: "); if (owHasPageAutoCRC(bank, SNum)) printf("page-device-CRC "); if (owCanRedirectPage(bank, SNum)) printf("pages-redirectable "); if (owCanLockPage(bank, SNum)) printf("pages-lockable \n"); if ((owCanLockPage(bank, SNum)) && (owCanLockRedirectPage(bank, SNum))) printf("|\tredirection-lockable\n"); else if (owCanLockRedirectPage(bank, SNum)) printf("redirection-lockable."); if (!owCanLockPage(bank, SNum)) printf("\n"); if (owHasExtraInfo(bank, SNum)) printf("| Extra information for each page: %s length %d\n", owGetExtraInfoDesc(bank, SNum), owGetExtraInfoLength(bank, SNum)); printf("|------------------------------------------------------------------------\n\n"); } w1retap/src/libusblinux300/meson.build000066400000000000000000000173221446446235200201740ustar00rootroot00000000000000w1common_src = files('owerr.c', 'ioutil.c', 'crcutil.c', 'acquire.c') w1serial_src = files('ds2480ut.c', 'linuxlnk.c', 'owllu.c', 'ownetu.c', 'owsesu.c', 'owtrnu.c') w1usb_src = files('libusbllnk.c', 'libusbds2490.c', 'libusbnet.c', 'libusbses.c', 'libusbtran.c') owfat_src = files('mbappreg.c', 'mbeprom.c', 'mbnvcrc.c', 'mbscrcrc.c', 'mbscrex.c', 'mbshaee.c', 'mbee.c', 'mbee77.c', 'mbnv.c', 'mbscr.c', 'mbscree.c', 'mbscrx77.c', 'mbsha.c', 'pw77.c', 'rawmem.c', 'owfile.c', 'owpgrw.c', 'owprgm.c', 'owcache.c', 'temp10.c', 'atod26.c', 'screenio.c', 'cnt1d.c', 'swt12.c', 'pressure.c', 'sht11_humid.c', 'swt1f.c', 'atod20.c', 'ds2408lcd.c', 'ds2760.c', 'humutil.c', 'ds192x.c', 'hbuv.c', 'hbht.c' ) libusb = dependency('libusb-1.0') owfat = static_library('owfat', owfat_src, include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE', ], install : false) w1common = shared_library('w1common', w1common_src, include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], version: '0.0.0', dependencies: [ wdeps ], install_dir : pkglibdir, install : true ) w1usb = shared_library('w1usb', w1usb_src, c_args: ['-D_GNU_SOURCE' ], version: '0.0.0', dependencies: [ wdeps, libusb ], link_with : w1common, install_dir : pkglibdir, install : true ) w1serial = shared_library('w1serial', w1serial_src, c_args: ['-D_GNU_SOURCE', ], version: '0.0.0', dependencies: [ wdeps ], link_with : w1common, install_dir : pkglibdir, install : true ) w1find_src = files('w1find.c', 'findtype.c') executable( 'w1find', w1find_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: true, ) braybaro_src = files('braybaro.c', 'atod26.c', 'screenio.c', 'findtype.c', ) executable( 'braybaro', braybaro_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) temp_src = files('temp.c', 'findtype.c', ) executable( 'temp', temp_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) gethumd_src = files('gethumd.c', 'findtype.c', ) executable( 'gethumd', gethumd_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) coupler_src = files('coupler.c', 'findtype.c', ) executable( 'coupler', coupler_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) humids_src = files('humid.c', ) executable( 'humids', humids_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE', ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) setds2409_src = files('setds2409.c', ) executable( 'setds2409', setds2409_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) counter_src = files('counter.c', 'findtype.c', ) executable( 'counter', counter_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) mweather_src = files('mweather.c', 'findtype.c', 'weather.c', ) executable( 'mweather', mweather_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) lcdtest_src = files('lcdtest.c', 'findtype.c', ) executable( 'lcdtest', lcdtest_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) atodtst_src = files('atodtst.c', 'findtype.c', ) executable( 'atodtst', atodtst_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false, ) humalog_src = files('humalog.c', 'findtype.c', ) executable( 'humalog', humalog_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) thermoms_src = files('thermoms.c', 'findtype.c', 'thermo21.c', ) executable( 'thermoms', thermoms_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) thermodl_src = files('thermodl.c', 'findtype.c', 'thermo21.c', ) executable( 'thermodl', thermodl_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false, ) ds192xtest_src = files('ds192x.c', ) executable( 'ds192xtest', ds192xtest_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE', '-DTESTMAIN=1' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) hbuvtest_src = files('hbuvtest.c', ) executable( 'hbuvtest', hbuvtest_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) hbhttest_src = files('hbhttest.c', ) executable( 'hbhttest', hbhttest_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) temptest_src = files('temptest.c', ) executable( 'temptest', temptest_src, dependencies: [ wdeps ], include_directories : configuration_inc, c_args: ['-D_GNU_SOURCE' ], link_with : [ owfat, w1common ], export_dynamic: true, install_rpath : pkglibdir, install: false ) w1retap/src/libusblinux300/mkds192xtest.sh000077500000000000000000000012061446446235200206450ustar00rootroot00000000000000#!/bin/bash set -x DATE=$(date +%F) NAME=ds192xtest PROG=$NAME.$DATE if [ -e /usr/lib/w1retap/libw1common.so.0 ] then LDPATH=/usr/lib/w1retap elif [ -e /usr/local/lib/w1retap/libw1common.so.0 ] then LDPATH=/usr/local/lib/w1retap/ else echo "No obvious library path" exit fi rm -f $NAME.* gcc -DHAVE_CONFIG_H -I. -I../.. -Wall -D_GNU_SOURCE=1 -I . \ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -Werror \ -DTESTMAIN=1 -g -O2 -c -o ${NAME}.o ds192x.c gcc -g -O2 -rdynamic -Wl,--export-dynamic -lgmodule-2.0 -lglib-2.0 \ -o $PROG $NAME.o findtype.o -L . -L $LDPATH -lowfat -lw1common -lrt -lm \ -Wl,-rpath -Wl,$LDPATH w1retap/src/libusblinux300/mweather.c000066400000000000000000000152771446446235200200210ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // mweather.c - Test application to read the 1-Wire Ney Weather Station. // The weather station consists of the following devices // on the trunk of the 1-Wire Net: // DS1820 - temperature measurement // DS2423 - counter for reading wind speed (page 15) // DS2450 - isolate wind direction. // DS2406 - switch to isolate 8 DS2401's for wind // direction on channel B. // // Commented out is an example on how to setup two weather stations. // #include #include #include #include "ownet.h" #include "swt12.h" #include "weather.h" #include "cnt1d.h" #include "temp10.h" // defines #define FALSE 0 #define TRUE 1 // misc #define MAX2401 8 // local funcitons // global serial numbers of Weather Station devices uchar TempSN[8], CountSN[8], SwitchSN[8], DS2401[MAX2401][8]; //---------------------------------------------------------------------- // Main Test for Weather Station // int main(int argc, char **argv) { WeatherStruct weather1; // WeatherStruct weather1 = { {0x20, 0x7A, 0x01, 0x01, 0x00, 0x00, 0x00, 0xFA}, // {0x10, 0x2B, 0x75, 0x36, 0x00, 0x00, 0x00, 0x4B}, // {0x1D, 0xEE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFD} }; // WeatherStruct weather2 = { {0x12, 0x69, 0xBE, 0x06, 0x00, 0x00, 0x00, 0x30}, // {0x10, 0x7C, 0x8E, 0x15, 0x00, 0x00, 0x00, 0xCE}, // {0x1D, 0xCF, 0x33, 0x00, 0x00, 0x00, 0x00, 0xB2}, // { {0x01, 0xD0, 0x57, 0x00, 0x02, 0x00, 0x00, 0x72}, // {0x01, 0x01, 0x79, 0x73, 0x02, 0x00, 0x00, 0xFB}, // {0x01, 0x34, 0xAB, 0x73, 0x02, 0x00, 0x00, 0x20}, // {0x01, 0x3D, 0x82, 0x73, 0x02, 0x00, 0x00, 0xBD}, // {0x01, 0x3D, 0x82, 0x73, 0x02, 0x00, 0x00, 0x1E}, // {0x01, 0x6F, 0xB1, 0x73, 0x02, 0x00, 0x00, 0x37}, // {0x01, 0xCC, 0x57, 0x00, 0x02, 0x00, 0x00, 0x54}, // {0x01, 0xD4, 0x57, 0x00, 0x02, 0x00, 0x00, 0xAE} } }; time_t tint; struct tm *tstruct; float current_temp; double revolution_sec; int direction; int portnum; //---------------------------------------- // Introduction header printf("\n/---------------------------------------------\n"); printf(" NWeather - V2.00\n" " The following is a test to excersize the two\n" " 1-Wire Net Weather Station containing\n" " DS1820 - temperature measurement (at least 1)\n" " DS2423 - counter for reading wind speed (page 15)\n" " DS2450 - Isolate direction for wind\n" " or the\n" " DS2406 - switch to isolate 8 DS2401's for wind\n" " direction on channel B.\n"); printf(" Press any CTRL-C to stop this program.\n\n"); printf("Output [Time, Temp1(F),Temp2(F).., Direction Serial Number(s), " "Wind speed(MPH)]\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]); // Setting up the DS2450 weather station // if(SetupWet(portnum, &weather1, 5)) // { // if(ReadWet(portnum, &weather1, ¤t_temp, &direction, &revolution_sec)) // { // time(&tint); // tstruct = localtime(&tint); // printf("%02d:%02d:%02d,",tstruct->tm_hour,tstruct->tm_min,tstruct->tm_sec); // printf("%5.1f, ",current_temp); // printf("%02d,",direction); // printf("%5.1f\n",revolution_sec); // } // } // Setting up the DS2406 weather station // if(SetupWet(portnum, &weather2, 5)) // { // if(ReadWet(portnum, &weather2, ¤t_temp, &direction, &revolution_sec)) // { // time(&tint); // tstruct = localtime(&tint); // printf("%02d:%02d:%02d,",tstruct->tm_hour,tstruct->tm_min,tstruct->tm_sec); // printf("%5.1f, ",current_temp); // printf("%02d,",direction); // printf("%5.1f\n",revolution_sec); // } // } // If setting up the DS2406 in this program uncomment the weather2 code // and change the weather1 to weather2 in the following code if (FindSetupWeather(portnum, &weather1)) { printf("The Found Weather Station\n"); do { if (ReadWet(portnum, &weather1, ¤t_temp, &direction, &revolution_sec)) { time(&tint); tstruct = localtime(&tint); printf("%02d:%02d:%02d,", tstruct->tm_hour, tstruct->tm_min, tstruct->tm_sec); printf("%5.1f, ", current_temp); printf("%02d,", direction); printf("%5.1f\n", revolution_sec); } } while (TRUE); //! key_abort()); } // release the 1-Wire Net owRelease(portnum); printf("Closing port %s.\n", argv[1]); exit(0); return 0; } w1retap/src/libusblinux300/owcache.c000066400000000000000000000246571446446235200176200ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // owCache.c - Stores the latest buttons information for faster access // version 1.00 // // Include Files #include "ownet.h" #include "owfile.h" // global data space static Dentry Space[DEPTH]; // data space for page entries static uchar Hash[DEPTH]; // table to hold pointer to space static uchar BitMap[DEPTH]; // record of space available //-------------------------------------------------------------------------- // Initialize the data hash values // void InitDHash(void) { short i; // set all the pointers to the empty state for (i = 0; i < DEPTH; i++) { Hash[i] = 0xFF; BitMap[i] = 0xFF; Space[i].Fptr = 0xFF; Space[i].Bptr = 0xFF; Space[i].Hptr = 0xFF; } } //-------------------------------------------------------------------------- // The hashing function takes the data provided and returns a hash // number in the range 0 to DEPTH-1. // // SNum the serial number for the part that the read is // to be done on. // page the page that is being added or looked for // // returns the hash number of the given data // uchar HashFunction(uchar *SNum, int page) { uint h; uchar tmp_page; tmp_page = (uchar)page; h = (SNum[1] << 12) | (SNum[2] << 8) | (SNum[7] << 4) | tmp_page; return (uchar)(h % DEPTH); } //-------------------------------------------------------------------------- // Find a empty page in Space and return its pointer. First look at the // expected spot. If an empty or expired page is not found then search // thru the pages. If one cannot be found then void the oldest one. // // hashnum the number of the page that might be empty. // // return the space location // uchar FindNew(uchar hashnum) { uint tm, otm; static uchar spot = 0; // spot pointer uchar t = 0xFF; uchar oldest, i; // if current spot is empty then use that if (BitMap[spot] == 0xFF) t = spot; // not empty so first try and find an empty spot in bitmap else { // get the current time tm = msGettick(); // set the oldest time to the current spot otm = Space[spot].Tstamp; oldest = spot; // check to see if spot is void if (tm > Space[spot].Tstamp) { FreePage(spot); t = spot; } else { // loop through all of the bitmap for (i = 0; i < DEPTH; i++) { if (BitMap[i] == 0xFF) { // check for empty t = i; break; } else if (tm > Space[i].Tstamp) { // check for expired FreePage((uchar)i); t = i; break; } else if (Space[i].Tstamp < otm) { // find oldest otm = Space[i].Tstamp; oldest = i; } } // check to see if not found one if (i == DEPTH) { // free the current spot FreePage(oldest); t = oldest; } } } // set next spot to the current spot + 1 spot = (spot == (DEPTH - 1)) ? 0 : spot + 1; // set the bitmap to say where the page is going BitMap[t] = hashnum; // return the space location return t; } //-------------------------------------------------------------------------- // Add a page to the hash table. If the page is already in the hash table // it is updated and a new time stamp is given. If the page is new then // it is added to the table. The data in buf is put in the page and the // Space location number is returned. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // pg the page to add // buf the buffer of the page data // len len of data for the page // // return the space number for the new page // uchar AddPage(int portnum, uchar *SNum, PAGE_TYPE pg, uchar *buf, int len) { uchar hs, p = 0xFF; short i = 0, m; PAGE_TYPE page; int tlen; uchar cache_page[32]; page = pg; // attempt to see if page already there if (!FindPage(portnum, SNum, &page, (uchar)(len & 0x80), FALSE, &cache_page[0], &tlen, &p)) return FALSE; if (p == 0xFF) { // page not found so add one hs = HashFunction(SNum, page); p = FindNew(hs); // attach the device to the chain (if there is one) // no other page in hash location if (Hash[hs] == 0xFF) { Hash[hs] = p; // hash p to new page Space[p].Fptr = 0xFF; // np front p to nothing Space[p].Bptr = 0xFF; // np back p to nothing Space[p].Hptr = hs; // np hash p to hash location } // some other page already there else { // insert as first page Space[p].Fptr = Hash[hs]; // np front p to old first page Space[Hash[hs]].Bptr = p; // old first page back p to np Hash[hs] = p; // hash p to np Space[p].Hptr = hs; // np hash p to hash location } // set the page number Space[p].Page = page; // set the rom for (i = 0; i < 8; i++) Space[p].ROM[i] = SNum[i]; } // set the data Space[p].Data[0] = len; m = ((len & 0x1F) <= 0x1D) ? (len & 0x1F) : 0; for (i = 0; i < m; i++) Space[p].Data[i + 1] = buf[i]; // set the time stamp limit of X seconds Space[p].Tstamp = msGettick() + CACHE_TIMEOUT; // (3.10) // return the Space number of the new page return p; } //-------------------------------------------------------------------------- // Search the hash cache to find the page discribed by the rom and page. // If it is found and it has not expired, then return its Space number // or 0xFF if it can not be found. 'mflag' is the memory section flag // where 0x00 is normal memory space and 0x80 is status memory space. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // page the page to start looking // mflag the flag to compare in looking for the right page // time the expired time to check // buf the buffer of the page data // len the length of the data on the page // space_num the space number in the table for the data of the page // // return true if the page data was found // SMALLINT FindPage(int portnum, uchar *SNum, PAGE_TYPE *page, uchar mflag, uchar time, uchar *buf, int *len, uchar *space_num) { static uchar DidInit = 0; uchar hs, ptr = 0xFF; short i = 0; uint tm; // initialize the file page cache (DSS 3.11) automatically if (!DidInit) { InitDHash(); DidInit = 1; } hs = HashFunction(SNum, *page); // if not empty if (Hash[hs] != 0xFF) { // get the current time tm = msGettick(); ptr = Hash[hs]; // point to first at hash spot do { // check to see if this record is expired if (time) { if (tm > Space[ptr].Tstamp) { ptr = FreePage(ptr); continue; // skip to loop check } } // check to see if this page is the correct one (and correct mem space) if ((Space[ptr].Page == *page) && (mflag == (Space[ptr].Data[0] & 0x80))) { for (i = 0; i < 8; i++) if (Space[ptr].ROM[i] != SNum[i]) break; if (i == 8) break; } // point to next page at hash location ptr = Space[ptr].Fptr; } while (ptr != 0xFF); } // check if need to copy over the data if (ptr != 0xFF) { if ((Space[ptr].Data[0] & 0x1F) <= 0x1D) { *len = Space[ptr].Data[0]; for (i = 1; i <= (*len & 0x1F); i++) buf[i - 1] = Space[ptr].Data[i]; } else ptr = 0xFF; } // check result if (ptr == 0xFF) return FALSE; *space_num = ptr; return TRUE; } //-------------------------------------------------------------------------- // Free's the page number passed to it. Fixes pointers in the Hash // structure. Returns the next device in the hash structure unless this // is the last page in the hash location and return 0xFF. // // ptr the hash location of the data // // return the next page // uchar FreePage(uchar ptr) { uchar hsptr; // get the hash location hsptr = Space[ptr].Hptr; // if chained if (Space[ptr].Fptr != 0xFF) { // check if first in chain if (Hash[hsptr] == ptr) { Hash[hsptr] = Space[ptr].Fptr; // set hash p to next in ch Space[Hash[hsptr]].Bptr = hsptr; // set next in chain p to hash BitMap[ptr] = 0xFF; // free page ptr = Hash[hsptr]; // change current p } // middle of chain else { // previous in ch p to next in ch Space[Space[ptr].Bptr].Fptr = Space[ptr].Fptr; // next in ch p to prevoious in ch Space[Space[ptr].Fptr].Bptr = Space[ptr].Bptr; BitMap[ptr] = 0xFF; // free page ptr = Space[Space[ptr].Bptr].Fptr; // change current p } } // if first and only on hash spot else if (Hash[hsptr] == ptr) { Hash[hsptr] = 0xFF; // have hash p to nothing BitMap[ptr] = 0xFF; // free page ptr = 0xFF; // point to nothing } // else last in a chain else { // previous in ch p to nothing Space[Space[ptr].Bptr].Fptr = 0xFF; BitMap[ptr] = 0xFF; // free page ptr = 0xFF; // point to nothing } return 0xFF; // return the next page or nothing } w1retap/src/libusblinux300/owerr.c000066400000000000000000000324551446446235200173400ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // owerr.c - Library functions for error handling with 1-Wire library // // Version: 1.00 // #include #ifndef _WIN32_WCE #include #endif #include "ownet.h" #ifndef SIZE_OWERROR_STACK #ifdef SMALL_MEMORY_TARGET // for small memory, only hole 1 error #define SIZE_OWERROR_STACK 1 #else #define SIZE_OWERROR_STACK 10 #endif #endif //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- // Error Struct for holding error information. // In DEBUG, this will also hold the line number and filename. typedef struct { int owErrorNum; #ifdef DEBUG int lineno; char *filename; #endif } owErrorStruct; // Ring-buffer used for stack. // In case of overflow, deepest error is over-written. static owErrorStruct owErrorStack[SIZE_OWERROR_STACK]; // Stack pointer to top-most error. static int owErrorPointer = 0; //--------------------------------------------------------------------------- // Functions Definitions //--------------------------------------------------------------------------- int owGetErrorNum(void); void owClearError(void); int owHasErrors(void); #ifdef DEBUG void owRaiseError(int, int, char *); #else void owRaiseError(int); #endif #ifndef SMALL_MEMORY_TARGET void owPrintErrorMsg(FILE *); void owPrintErrorMsgStd(); char *owGetErrorMsg(int); #endif //-------------------------------------------------------------------------- // The 'owGetErroNum' returns the error code of the top-most error on the // error stack. NOTE: This function has the side effect of popping the // current error off the stack. All successive calls to 'owGetErrorNum' // will further clear the error stack. // // For list of error codes, see 'ownet.h' // // Returns: int : The error code of the top-most error on the stack // int owGetErrorNum(void) { int i = owErrorStack[owErrorPointer].owErrorNum; owErrorStack[owErrorPointer].owErrorNum = 0; if (!owErrorPointer) owErrorPointer = SIZE_OWERROR_STACK - 1; else owErrorPointer = (owErrorPointer - 1); return i; } //-------------------------------------------------------------------------- // The 'owClearError' clears all the errors. // void owClearError(void) { owErrorStack[owErrorPointer].owErrorNum = 0; } //-------------------------------------------------------------------------- // The 'owHasErrors' is a boolean test function which tests whether or not // a valid error is waiting on the stack. // // Returns: TRUE (1) : When there are errors on the stack. // FALSE (0): When stack's errors are set to 0, or NO_ERROR_SET. // int owHasErrors(void) { if (owErrorStack[owErrorPointer].owErrorNum) return 1; // TRUE else return 0; // FALSE } #ifdef DEBUG //-------------------------------------------------------------------------- // The 'owRaiseError' is the method for raising an error onto the error // stack. // // Arguments: int err - the error code you wish to raise. // int lineno - DEBUG only - the line number where it was raised // char* filename - DEBUG only - the file name where it occured. // void owRaiseError(int err, int lineno, char *filename) { owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; owErrorStack[owErrorPointer].owErrorNum = err; owErrorStack[owErrorPointer].lineno = lineno; owErrorStack[owErrorPointer].filename = filename; } #else //-------------------------------------------------------------------------- // The 'owRaiseError' is the method for raising an error onto the error // stack. // // Arguments: int err - the error code you wish to raise. // void owRaiseError(int err) { owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; owErrorStack[owErrorPointer].owErrorNum = err; } #endif // SMALL_MEMORY_TARGET - embedded microcontrollers, where these // messaging functions might not make any sense. #ifndef SMALL_MEMORY_TARGET // Array of meaningful error messages to associate with codes. // Not used on targets with low memory (i.e. PIC). static char *owErrorMsg[123] = { /*000*/ "No Error Was Set", /*001*/ "No Devices found on 1-Wire Network", /*002*/ "1-Wire Net Reset Failed", /*003*/ "Search ROM Error: Couldn't locate next device on 1-Wire", /*004*/ "Access Failed: Could not select device", /*005*/ "DS2480B Adapter Not Detected", /*006*/ "DS2480B: Wrong Baud", /*007*/ "DS2480B: Bad Response", /*008*/ "Open COM Failed", /*009*/ "Write COM Failed", /*010*/ "Read COM Failed", /*011*/ "Data Block Too Large", /*012*/ "Block Transfer failed", /*013*/ "Program Pulse Failed", /*014*/ "Program Byte Failed", /*015*/ "Write Byte Failed", /*016*/ "Read Byte Failed", /*017*/ "Write Verify Failed", /*018*/ "Read Verify Failed", /*019*/ "Write Scratchpad Failed", /*020*/ "Copy Scratchpad Failed", /*021*/ "Incorrect CRC Length", /*022*/ "CRC Failed", /*023*/ "Failed to acquire a necessary system resource", /*024*/ "Failed to initialize system resource", /*025*/ "Data too long to fit on specified device.", /*026*/ "Read exceeds memory bank end.", /*027*/ "Write exceeds memory bank end.", /*028*/ "Device select failed", /*029*/ "Read Scratch Pad verify failed.", /*030*/ "Copy scratchpad complete not found", /*031*/ "Erase scratchpad complete not found", /*032*/ "Address read back from scrachpad was incorrect", /*033*/ "Read page with extra-info not supported by this memory bank", /*034*/ "Read page packet with extra-info not supported by this memory bank", /*035*/ "Length of packet requested exceeds page size", /*036*/ "Invalid length in packet", /*037*/ "Program pulse required but not available", /*038*/ "Trying to access a read-only memory bank", /*039*/ "Current bank is not general purpose memory", /*040*/ "Read back from write compare is incorrect, page may be locked", /*041*/ "Invalid page number for this memory bank", /*042*/ "Read page with CRC not supported by this memory bank", /*043*/ "Read page with CRC and extra-info not supported by this memory bank", /*044*/ "Read back from write incorrect, could not lock page", /*045*/ "Read back from write incorrect, could not lock redirect byte", /*046*/ "The read of the status was not completed.", /*047*/ "Page redirection not supported by this memory bank", /*048*/ "Lock Page redirection not supported by this memory bank", /*049*/ "Read back byte on EPROM programming did not match.", /*050*/ "Can not write to a page that is locked.", /*051*/ "Can not lock a redirected page that has already been locked.", /*052*/ "Trying to redirect a locked redirected page.", /*053*/ "Trying to lock a page that is already locked.", /*054*/ "Trying to write to a memory bank that is write protected.", /*055*/ "Error due to not matching MAC.", /*056*/ "Memory Bank is write protected.", /*057*/ "Secret is write protected, can not Load First Secret.", /*058*/ "Error in Reading Scratchpad after Computing Next Secret.", /*059*/ "Load Error from Loading First Secret.", /*060*/ "Power delivery required but not available", /*061*/ "Not a valid file name.", /*062*/ "Unable to Create a Directory in this part.", /*063*/ "That file already exists.", /*064*/ "The directory is not empty.", /*065*/ "The wrong type of part for this operation.", /*066*/ "The max len for this file is too small.", /*067*/ "This is not a write once bank.", /*068*/ "The file can not be found.", /*069*/ "There is not enough space available.", /*070*/ "There is not a page to match that bit in the bitmap.", /*071*/ "There are no jobs for EPROM parts.", /*072*/ "Function not supported to modify attributes.", /*073*/ "Handle is not in use.", /*074*/ "Tring to read a write only file.", /*075*/ "There is no handle available for use.", /*076*/ "The directory provided is an invalid directory.", /*077*/ "Handle does not exist.", /*078*/ "Serial Number did not match with current job.", /*079*/ "Can not program EPROM because a non-EPROM part on the network.", /*080*/ "Write protect redirection byte is set.", /*081*/ "There is an inappropriate directory length.", /*082*/ "The file has already been terminated.", /*083*/ "Failed to read memory page of iButton part.", /*084*/ "Failed to match scratchpad of iButton part.", /*085*/ "Failed to erase scratchpad of iButton part.", /*086*/ "Failed to read scratchpad of iButton part.", /*087*/ "Failed to execute SHA function on SHA iButton.", /*088*/ "SHA iButton did not return a status completion byte.", /*089*/ "Write data page failed.", /*090*/ "Copy secret into secret memory pages failed.", /*091*/ "Bind unique secret to iButton failed.", /*092*/ "Could not install secret into user token.", /*093*/ "Transaction Incomplete: signature did not match.", /*094*/ "Transaction Incomplete: could not sign service data.", /*095*/ "User token did not provide a valid authentication response.", /*096*/ "Failed to answer a challenge on the user token.", /*097*/ "Failed to create a challenge on the coprocessor.", /*098*/ "Transaction Incomplete: service data was not valid.", /*099*/ "Transaction Incomplete: service data was not updated.", /*100*/ "Unrecoverable, catastrophic service failure occured.", /*101*/ "Load First Secret from scratchpad data failed.", /*102*/ "Failed to match signature of user's service data.", /*103*/ "Subkey out of range for the DS1991.", /*104*/ "Block ID out of range for the DS1991", /*105*/ "Password is enabled", /*106*/ "Password is invalid", /*107*/ "This memory bank has no read only password", /*108*/ "This memory bank has no read/write password", /*109*/ "1-Wire is shorted", /*110*/ "Error communicating with 1-Wire adapter", /*111*/ "CopyScratchpad failed: Ending Offset must go to end of page", /*112*/ "WriteScratchpad failed: Ending Offset must go to end of page", /*113*/ "Mission can not be stopped while one is not in progress", /*114*/ "Error stopping the mission", /*115*/ "Port number is outside (0,MAX_PORTNUM) interval", /*116*/ "Level of the 1-Wire was not changed", /*117*/ "Could not open usb port through libusb", /*118*/ "Libusb DS2490 port already opened", /*119*/ "Failed to set libusb configuration", /*120*/ "Failed to claim libusb interface", /*121*/ "Failed to set libusb altinterface", /*122*/ "No adapter found at this port number"}; char *owGetErrorMsg(int err) { return owErrorMsg[err]; } #ifndef __C51__ //-------------------------------------------------------------------------- // The 'owPrintErrorMsg' is the method for printing an error from the stack. // The destination for the print is specified by the argument, fileno, which // can be stderr, stdout, or a log file. In non-debug mode, the output is // of the form: // Error num: Error msg // // In debug-mode, the output is of the form: // Error num: filename line#: Error msg // // NOTE: This function has the side-effect of popping the error off the stack. // // Arguments: FILE*: the destination for printing. // void owPrintErrorMsg(FILE *filenum) { #ifdef DEBUG int l = owErrorStack[owErrorPointer].lineno; char *f = owErrorStack[owErrorPointer].filename; int err = owGetErrorNum(); fprintf(filenum, "Error %d: %s line %d: %s\r\n", err, f, l, owErrorMsg[err]); #else int err = owGetErrorNum(); fprintf(filenum, "Error %d: %s\r\n", err, owErrorMsg[err]); #endif } #endif //__C51__ // Same as above, except uses default printf output void owPrintErrorMsgStd() { #ifdef DEBUG int l = owErrorStack[owErrorPointer].lineno; char *f = owErrorStack[owErrorPointer].filename; int err = owGetErrorNum(); printf("Error %d: %s line %d: %s\r\n", err, f, l, owErrorMsg[err]); #else int err = owGetErrorNum(); printf("Error %d: %s\r\n", err, owErrorMsg[err]); #endif } #endif w1retap/src/libusblinux300/owfile.c000066400000000000000000002474501446446235200174720ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // owFile.c - Contains the main file functions for the 1-Wire Public Domain // Kit // // version 1.00 // #include #include #include "owfile.h" #include "rawmem.h" #include "mbeprom.h" // External Function Prototypes extern void owClearError(void); // Globals uchar LastFile; // 1 FileInfo Han[5]; // 60 CurrentDirectory CD; // 69 uchar Internal; // 1 // Page_WR in file layer PAGE_TYPE LastPage; // 1 uchar FPage; // 1 ushort buflen; // 2 char mxpgs; // 1 char BadRec; // 1 uchar current[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //-------------------------------------------------------------------------- // Create a sub-directory. Note that a sub-directory is created empty // and only an empty sub-directory can be removed. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // DirName the file information that is to be created. // // Returns: 1(SUCCESS) : Operation successful // 0(FAILURE) : error // SMALLINT owCreateDir(int portnum, uchar *SNum, FileEntry *DirName) { uchar nwdir[] = {0xAA, 0, 'R', 'O', 'O', 'T', 0, 0}; short i; PAGE_TYPE pg; SMALLINT bytes_written = 0; DirectoryPath reset; // check for a valid session device if (!ValidRom(portnum, SNum)) return FALSE; if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // check to see if filename passed is valid if (!Valid_FileName(DirName)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // get the starting page if (CD.ne == 0) pg = 0; else pg = CD.Entry[CD.ne - 1].page; // check to see if there is any room for another sub-directory if (CD.ne == 10) { OWERROR(OWERROR_XUNABLE_TO_CREATE_DIR); return FALSE; } // fill the file handle 4 for (i = 0; i < 4; i++) Han[4].Name[i] = DirName->Name[i]; Han[4].Ext = 0x7F; Han[4].Read = FALSE; // create the new sub-directory page // search through directory to verify file not found if (FindDirectoryInfo(portnum, SNum, &pg, &Han[4])) { OWERROR(OWERROR_REPEAT_FILE); return FALSE; } // if starting page is not 0 then is not default root so change if (pg != 0) { for (i = 0; i < 4; i++) nwdir[i + 2] = CD.Entry[CD.ne - 1].name[i]; nwdir[6] = CD.Entry[CD.ne - 1].page; } // Set the internal flag Internal = TRUE; // use the writefile command to accomplish this task if (!owWriteFile(portnum, SNum, 4, nwdir, FILE_NAME_LEN)) return FALSE; // turn off the shorternal flag Internal = FALSE; // check success of write if (bytes_written < 0) return FALSE; // reset current directory reset.Ref = '0'; reset.NumEntries = 0; if (!owChangeDirectory(portnum, SNum, &reset)) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // Remove a sub-directory. Note that a sub-directory is created empty // and only an empty sub-directory can be removed. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // DirName the file information that is to be removed. // // Returns: 1(SUCCESS) : Operation successful // 0(FAILURE) : error // SMALLINT owRemoveDir(int portnum, uchar *SNum, FileEntry *DirName) { uchar buf[64], BM[32], pgbuf[32], p, jobBM[32]; short e, i, j; PAGE_TYPE pg = CD.Entry[CD.ne - 2].page; PAGE_TYPE rpg, tpg; int len = 0; uchar pgjobstat; SMALLINT bank = 1; DirectoryPath reset; // check for a valid session device if (!ValidRom(portnum, SNum)) return FALSE; if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // check to see if filename passed is valid if (!Valid_FileName(DirName)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // fill the file handle 4 for (i = 0; i < 4; i++) Han[4].Name[i] = DirName->Name[i]; Han[4].Ext = 0x7F; Han[4].Read = FALSE; // search through directory to verify file not found if (!FindDirectoryInfo(portnum, SNum, &pg, &Han[4])) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Han[4].Spage, &len)) return FALSE; // check for empty if ((len != 8) || (buf[len - 1] != 0)) { OWERROR(OWERROR_DIRECTORY_NOT_EMPTY); return FALSE; } // Set the internal flag Internal = TRUE; // use the deletefile command to accomplish this task // check for special case of extension 100 if (Han[4].Ext == 100 && (!owIsWriteOnce(bank, portnum, SNum))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // check to see if this entry is read only if (Han[4].Attrib == 0x01 && Han[4].Ext != 0x7F) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check existing open files with same the name // automatically close the file for (i = 0; i < 4; i++) { if (Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != Han[4].Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == Han[4].Ext)) { Han[i].Name[0] = 0; // release the handle break; } } } // get the bitmap so that it can be adjusted if (!ReadBitMap(portnum, SNum, &BM[0])) return FALSE; // check for addfile if (Han[4].Ext == 100) { tpg = Han[4].Spage; for (i = 0; i < 256; i++) { // read a page in the file if (!ExtendedRead_Page(portnum, SNum, &pgbuf[0], tpg)) return FALSE; // check if only in buffer // or non written buffered eprom page if (isJob(portnum, SNum)) { // see if page set to write but has not started yet pgjobstat = isJobWritten(portnum, SNum, tpg); if ((pgjobstat == PJOB_ADD) && (pgjobstat != PJOB_START)) { // clear the job if (!setJobWritten(portnum, SNum, tpg, PJOB_NONE)) return FALSE; // clear this page in the bitmap if clear in original if (!getOrigBM(portnum, SNum, &jobBM[0])) return FALSE; if (!(jobBM[tpg / 8] & (0x01 << (tpg % 8)))) if (!BitMapChange(portnum, SNum, (uchar)tpg, 0, &BM[0])) return FALSE; } } // get continuation pointer tpg = pgbuf[29]; if (tpg == 0xFF) break; } } // regular file else { // read the file to eliminate the bits in the bitmap if (!ExtRead(portnum, SNum, &buf[0], Han[4].Spage, -1, TRUE, &BM[0], &len)) return FALSE; } // read the directory page to see what the situation is if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Han[4].Dpage, &len)) return FALSE; // check for inappropriate directory length if ((len - 1) % 7) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // get number of entries e = len / 7; // check for condition that this is last enty in a directory packet if (e == 1) { // remember the current pages pointer p = buf[len - 1]; // read the previous page to change its continuation pointer if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Han[4].PDpage, &len)) return FALSE; // set the prev dir page cont ptr to current page cont ptr buf[len - 1] = p; // clear this page in the bitmap if (!BitMapChange(portnum, SNum, Han[4].Dpage, 0, &BM[0])) return FALSE; // set the page number to write rpg = Han[4].PDpage; } // must keep this page and just remove the entry else { // remember the current pages pointer p = buf[len - 1]; // shift directory page over to remove the entry for (i = Han[4].Offset; i < (len - 7); i++) buf[i] = buf[i + 7]; // reduce the lenght of the directory page by 1 entry len -= 7; // set the continuation page buf[len - 1] = p; // set the page number to write rpg = Han[4].Dpage; } // write the directory page needed if (!Write_Page(portnum, SNum, &buf[0], rpg, len)) return FALSE; else { if (!BitMapChange(portnum, SNum, Han[4].Spage, 0, &BM[0])) return FALSE; } // update the bitmap if (!WriteBitMap(portnum, SNum, &BM[0])) return FALSE; // turn off the internal flag Internal = FALSE; // reset current directory reset.Ref = '0'; reset.NumEntries = 0; if (!owChangeDirectory(portnum, SNum, &reset)) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // Write a file by reference to a hnd. Buffer and // length are provided. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file // buf the information to write to the file // len the len of the information to be written // // Returns: TRUE File Write successful // FALSE File Write a failure // SMALLINT owWriteFile(int portnum, uchar *SNum, short hnd, uchar *buf, int len) { uchar BM[32], dbuf[32], tbuf[32]; short i, j; int dlen, templen; PAGE_TYPE next, avail, tpg, dpg, pg; PAGE_TYPE fpg = 0, prefpg = 0; uchar pgbuf[32]; uchar newpg[32]; int flag, preflag = FALSE; FileEntry Dmmy; uchar *ptr; SMALLINT bank, mavail; FileInfo Info; int new_entry = TRUE; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if handle valid number if ((hnd > 3 || hnd < 0) && (Internal == FALSE)) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see if hnd provided is valid file reference if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } bank = getBank(portnum, SNum, Han[hnd].Spage, REGMEM); // check to see if hnd is a write reference if (owIsReadOnly(bank, portnum, SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check if this is an addfile if (Han[hnd].Ext == 100) { templen = len; if (!owWriteAddFile(portnum, SNum, hnd, APPEND, 0, buf, &templen)) return FALSE; } // get the bitmap to find empties and to adjust if (!ReadBitMap(portnum, SNum, &BM[0])) return FALSE; // check to see if file to write is too long (not take into account directory) if ((Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) { // check if longer then page or some other file already got the page if ((len > 28) || (BM[Han[hnd].Spage / 8] & (0x01 << (Han[hnd].Spage % 8)))) { if (len != 0) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } } } mavail = GetMaxWrite(portnum, SNum, &BM[0]); if (mavail == 0 || len > mavail) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // try to find an empty spot in the directory if (!ReadNumEntry(portnum, SNum, -1, &Dmmy, &dpg)) return FALSE; // read the directory page indicated to see if it has space or is the last tpg = (uchar)dpg; if (!Read_Page(portnum, SNum, &dbuf[0], REGMEM, &tpg, &dlen)) return FALSE; for (i = 0; i < 4; i++) Info.Name[i] = Han[hnd].Name[i]; Info.Ext = Han[hnd].Ext; // special case for first directory page i = 7; // check to see if first dir page is a valid dir if ((dbuf[0] != 0xAA) && (dbuf[1] != 0) && (dlen > 29)) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } else if ((dbuf[0] != 0xAA) || (dbuf[1] != 0)) { i = 0; } // loop through each directory entry to find FInfo // loop to search through directory pages do { // read a page in the directory if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &fpg, &flag)) return FALSE; // if have a good read then search inside page for EntNum if (flag > 0) { // special case for first directory page i = 0; if (fpg == 0) { i = 7; // check to see if first dir page is a valid dir if (pgbuf[0] != 0xAA || pgbuf[1] != 0) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } } // loop through each directory entry to find FInfo for (; i < flag; i += 7) { for (j = 0; j < 4; j++) // compare file name if ((toupper(pgbuf[i + j]) != Info.Name[j]) && !((pgbuf[i + j] == 0x20) && (Info.Name[j] == 0xCC))) break; if ((j != 4) || ((pgbuf[i + 4] & 0x7F) != Info.Ext)) continue; // loop if not match Han[hnd].Spage = pgbuf[i + 5]; Han[hnd].Ext = pgbuf[i + 4] & 0x7F; Han[hnd].NumPgs = (len / 28) + ((len % 28) ? 1 : 0); pgbuf[i + 6] = Han[hnd].NumPgs; Han[hnd].Attrib = (pgbuf[i + 4] & 0x80) ? 1 : 0; if (Han[hnd].Ext == 0x7F) Han[hnd].Attrib <<= 1; Han[hnd].Dpage = (uchar)dpg; Han[hnd].Offset = (uchar)i; new_entry = FALSE; for (i = 0; i < flag; i++) newpg[i] = pgbuf[i]; preflag = flag; prefpg = fpg; break; } // poshort to next page fpg = pgbuf[flag - 1]; } else return FALSE; // return error } while (fpg); // in light of the directory page read check space again if (dlen == 29) mavail -= 28; if (mavail <= 0 || len > mavail) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // Record where the file begins if ((Han[hnd].Ext != 101) && (Han[hnd].Ext != 102) && (new_entry)) { FindEmpties(portnum, SNum, &BM[0], &avail, &next); Han[hnd].Spage = avail; } // write the file in the available space if ((Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) { // Monitary file exception // copy the data in to a temp buffer and add a continuation pointer for (i = 0; i < len; i++) tbuf[i] = buf[i]; tbuf[i] = 0; // write the page if (!Write_Page(portnum, SNum, &tbuf[0], Han[hnd].Spage, (len + 1))) return FALSE; // set the bitmap page taken if (!BitMapChange(portnum, SNum, Han[hnd].Spage, 1, &BM[0])) return FALSE; } else { if (!ExtWrite(portnum, SNum, Han[hnd].Spage, &buf[0], len, &BM[0])) return FALSE; } if (new_entry) { // construct the new directory entry Han[hnd].NumPgs = (Internal) ? 0 : ((len / 28) + ((len % 28) ? 1 : 0)); // don't allow external zero number of pages unless a directory if ((!Han[hnd].NumPgs) && (Han[hnd].Ext != 0x7F)) Han[hnd].NumPgs = 1; Han[hnd].Attrib = 0; // get an empty page FindEmpties(portnum, SNum, &BM[0], &avail, &next); // check to see if need to write a new directory page if (dlen == 29) { // write the new page if (!Write_Page(portnum, SNum, (uchar *)&Han[hnd], avail, 8)) return FALSE; // set the bitmap to account for this new directory page if (!BitMapChange(portnum, SNum, avail, 1, &BM[0])) return FALSE; // change the exhisting directory page continuation pointer dbuf[dlen - 1] = avail; } // add the new directory entry to exhisting directory page else { // remember the continuation pointer pg = dbuf[dlen - 1]; // get a pointer shorto the handle ptr = (uchar *)&Han[hnd]; // loop to add the new entry for (i = 0; i < 7; i++) dbuf[dlen - 1 + i] = ptr[i]; // adjust the length of the directory page dlen += 7; // correct the continuation pointer dbuf[dlen - 1] = pg; } } // special case of dir page == 0 and local bitmap if ((dpg == 0) && (dbuf[2] & 0x80)) { // update the local bitmap for (i = 0; i < 2; i++) dbuf[3 + i] = BM[i]; dbuf[5] = 0; dbuf[6] = 0; } // non page 0 or non local bitmap else { // write the bitmap if (!WriteBitMap(portnum, SNum, &BM[0])) return FALSE; } // now rewrite the directory page if (new_entry) { if (!Write_Page(portnum, SNum, &dbuf[0], dpg, dlen)) return FALSE; } else { if (!Write_Page(portnum, SNum, &newpg[0], prefpg, preflag)) return FALSE; } // free the file handle if (len != 0) Han[hnd].Name[0] = 0; return TRUE; } //-------------------------------------------------------------------------- // Deletes an indicated file. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // flname the name and information of the file to delete // // return: TRUE : file deleted // FALSE : error // SMALLINT owDeleteFile(int portnum, uchar *SNum, FileEntry *flname) { short e, i, j; uchar BM[32], buf[32], p; uchar pgbuf[34]; int len, err; PAGE_TYPE pg = 0, tpg; FileInfo Info; SMALLINT bank = 1; DirectoryPath reset; uchar pgjobstat; uchar jobBM[32]; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if filename passed is valid if ((Valid_FileName(flname) == FALSE) || (((flname->Ext & 0x7F) == 0x7F) && (Internal == FALSE))) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check for special case of extension 100 if (flname->Ext == 100 && (!owIsWriteOnce(bank, portnum, SNum))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne - 1].page; // copy filename over to info packet for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to find the location of the file name if (!FindDirectoryInfo(portnum, SNum, &pg, &Info)) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } // check to see if this entry is read only if (Info.Attrib == 0x01 && Info.Ext != 0x7F) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check existing open files with same the name (3.10) // automatically close the file for (i = 0; i < 4; i++) { if (Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != flname->Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == flname->Ext)) { Han[i].Name[0] = 0; // release the handle break; } } } // get the bitmap so that it can be adjusted if (!ReadBitMap(portnum, SNum, BM)) return FALSE; // check for addfile if (Info.Ext == 100) { tpg = Info.Spage; for (i = 0; i < 256; i++) { // read a page in the file if (!ExtendedRead_Page(portnum, SNum, &pgbuf[0], tpg)) return FALSE; // check if only in buffer // or non written buffered eprom page if (isJob(portnum, SNum)) { // see if page set to write but has not started yet pgjobstat = isJobWritten(portnum, SNum, tpg); if ((pgjobstat == PJOB_ADD) && (pgjobstat != PJOB_START)) { // clear the job if (!setJobWritten(portnum, SNum, tpg, PJOB_NONE)) return FALSE; // clear this page in the bitmap if clear in original if (!getOrigBM(portnum, SNum, &jobBM[0])) return FALSE; if (!(jobBM[tpg / 8] & (0x01 << (tpg % 8)))) if (!BitMapChange(portnum, SNum, (uchar)tpg, 0, &BM[0])) return FALSE; } } // get continuation pointer tpg = pgbuf[29]; if (tpg == 0xFF) break; } } // regular file else { owClearError(); // read the file to eliminate the bits in the bitmap if (!ExtRead(portnum, SNum, &buf[0], Info.Spage, -1, TRUE, BM, &len)) { if (!BitMapChange(portnum, SNum, Info.Spage, 0, BM)) return FALSE; err = owGetErrorNum(); if (err != OWERROR_INVALID_PACKET_LENGTH) { OWERROR(err); return FALSE; } } } // read the directory page to see what the situation is if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Info.Dpage, &len)) return FALSE; // check for inappropriate directory length if ((len - 1) % 7) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // get number of entries e = len / 7; // check for condition that this is last enty in a directory packet if (e == 1) { // remember the current pages pointer p = buf[len - 1]; // read the previous page to change its continuation pointer if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Info.PDpage, &len)) return FALSE; // set the prev dir page cont ptr to current page cont ptr buf[len - 1] = p; // clear this page in the bitmap if (!BitMapChange(portnum, SNum, Info.Dpage, 0, BM)) return FALSE; // set the page number to write pg = Info.PDpage; } // must keep this page and just remove the entry else { // remember the current pages pointer p = buf[len - 1]; // shift directory page over to remove the entry for (i = Info.Offset; i < (len - 7); i++) buf[i] = buf[i + 7]; // reduce the lenght of the directory page by 1 entry len -= 7; // set the continuation page buf[len - 1] = p; // set the page number to write pg = Info.Dpage; } // write the directory page needed if (!Write_Page(portnum, SNum, &buf[0], pg, len)) return FALSE; else { if (!BitMapChange(portnum, SNum, Info.Spage, 0, &BM[0])) return FALSE; } // update the bitmap if (!WriteBitMap(portnum, SNum, BM)) return FALSE; // reset current directory reset.Ref = '0'; reset.NumEntries = 0; if (!owChangeDirectory(portnum, SNum, &reset)) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // Changes the attributes of a file. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // attr the attribute to change // flname the file name on which the attribute is to be changed // // return: TRUE : file attribute changed // FALSE : error // SMALLINT owAttribute(int portnum, uchar *SNum, short attr, FileEntry *flname) { uchar buf[32]; short i; PAGE_TYPE pg = 0; FileInfo Info; int len; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if filename passed is valid if (!Valid_FileName(flname)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check to see if this attribute is supported if ((((flname->Ext & 0x7F) == 0x7F) && ((attr != 0x02) && (attr != 0))) || (((flname->Ext & 0x7F) != 0x7F) && ((attr != 0x01) && (attr != 0)))) { OWERROR(OWERROR_FUNC_NOT_SUP); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne - 1].page; // copy filename over to info packet for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to find the location of the name if (!FindDirectoryInfo(portnum, SNum, &pg, &Info)) return FALSE; // check to see if the attribute already matches the entry if (Info.Attrib == attr) return TRUE; // read the directory page that the entry to change is in if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Info.Dpage, &len)) return FALSE; // exchange the new attribute for the old if (attr) buf[4 + Info.Offset] |= 0x80; // set attr bit else buf[4 + Info.Offset] = (buf[4 + Info.Offset] | 0x80) ^ 0x80; // clear attr bit // write back the directory page with the new name if (!Write_Page(portnum, SNum, &buf[0], Info.Dpage, len)) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // Change the name of a file that has been opened with the file handle // 'hnd'. The new name in 'flname'. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file to rename // flname the renamed file name // // return: TRUE : filename changed // FALSE : error // SMALLINT owReNameFile(int portnum, uchar *SNum, short hnd, FileEntry *flname) { uchar buf[32]; short i, j; PAGE_TYPE pg = 0; FileInfo Info; int len; SMALLINT bank; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if handle valid number if (hnd > 3 || hnd < 0) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see if filename passed is valid if (!Valid_FileName(flname) || (flname->Ext & 0x80) || (flname->Ext > 100) || ((flname->Ext == 100) && (Han[hnd].Ext != 100)) || ((flname->Ext != 100) && (Han[hnd].Ext == 100))) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check to see if hnd provided is valid file reference if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } bank = getBank(portnum, SNum, Han[hnd].Spage, REGMEM); // check to see if hnd is a write reference if (owIsReadOnly(bank, portnum, SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne - 1].page; // copy filename over to NewFile for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to see if new name is already in list if (FindDirectoryInfo(portnum, SNum, &pg, &Info)) { // file name already exists Han[hnd].Name[0] = 0; // release the handle return FALSE; } // read the directory page that the entry to change is in if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Han[hnd].Dpage, &len)) return FALSE; // exchange the new name for the old for (j = 0; j < 4; j++) buf[j + Han[hnd].Offset] = flname->Name[j]; buf[Han[hnd].Offset + 4] = flname->Ext; // check to keep attribute the same as old if (Han[hnd].Attrib) buf[Han[hnd].Offset + 4] |= 0x80; // write back the directory page with the new name if (!Write_Page(portnum, SNum, &buf[0], Han[hnd].Dpage, len)) return FALSE; Han[hnd].Name[0] = 0; // release handle on success return TRUE; } //-------------------------------------------------------------------------- // Read a file by reference to a handle. Buffer and // max length are provided. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file // buf the information to that was read // maxlen the max length of the buffer that stores the // read data // fl_len the len of the data read // // return: TRUE : file read // FLASE : error // SMALLINT owReadFile(int portnum, uchar *SNum, short hnd, uchar *buf, int maxlen, int *fl_len) { short len, i; uchar BM[32], pg; uchar pgbuf[64]; SMALLINT bank; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if handle valid number if (hnd > 3 || hnd < 0) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see if hnd provided is valid file reference if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } bank = getBank(portnum, SNum, Han[hnd].Spage, REGMEM); // check to see if hnd is a write reference if (owIsReadOnly(bank, portnum, SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check for open 'add' file exception if (((Han[hnd].Ext == 100) && (Han[hnd].NumPgs == 0)) || (Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) { pg = Han[hnd].Spage; len = 0; for (;;) { for (i = 0; i < 32; i++) pgbuf[i] = 0xFF; // read a page in the file if (!ExtendedRead_Page(portnum, SNum, &pgbuf[0], pg)) return FALSE; // Monitary File if ((Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) { if ((pgbuf[0] > 29) || ((pgbuf[0] + 7) > maxlen)) { OWERROR(OWERROR_BUFFER_TOO_SMALL); return FALSE; } // copy the counter/tamper to the end of the expected data for (i = 0; i < owGetExtraInfoLength(bank, SNum); i++) buf[i + pgbuf[0] - 1] = pgbuf[i + 32]; break; } // AddFile else { if ((len + 28) > maxlen) { OWERROR(OWERROR_BUFFER_TOO_SMALL); return FALSE; } for (i = 1; i <= 28; i++) buf[len++] = pgbuf[i]; pg = pgbuf[29]; if (pg == 0xFF) { for (i = 29; i > 0; i--) if (pgbuf[i] != 0xFF) { *fl_len = len - (29 - i - 1); break; } if (i == 0) *fl_len = len - 28; return TRUE; } } } } // if not a non-terminated addfile if (!((Han[hnd].Ext == 100) && (Han[hnd].NumPgs == 0))) { if (!ExtRead(portnum, SNum, &buf[0], Han[hnd].Spage, maxlen, FALSE, BM, fl_len)) return FALSE; } return TRUE; } //-------------------------------------------------------------------------- // Opens a file by first verifying that the file exists on the device and // to assign a handle. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // flname the name of the file and info. to open // hnd the assigned handle // // return: TRUE : file found // FALSE : error // SMALLINT owOpenFile(int portnum, uchar *SNum, FileEntry *flname, short *hnd) { short i, hn = 0; PAGE_TYPE pg = 0; SMALLINT bank = 1; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if filename passed is valid if (!Valid_FileName(flname) || ((flname->Ext & 0x7F) > 102)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check for special case of extension 100 (2.10) if (((flname->Ext == 100) && (!owIsWriteOnce(bank, portnum, SNum))) || ((flname->Ext == 101) && ((SNum[0] == 0x1A) || (SNum[0] == 0x1C) || (SNum[0] == 0x1D)))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // find a handle for (i = 0; i < 4; i++) if (Han[i].Name[0] == 0) { hn = i; break; } else if ((Han[i].Name[0] != 0) && (i == 3)) { OWERROR(OWERROR_HANDLE_NOT_AVAIL); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne - 1].page; // copy the filename to the open handle for (i = 0; i < 4; i++) Han[hn].Name[i] = flname->Name[i]; Han[hn].Ext = flname->Ext & 0x7F; // search through directory to find file to open if (!FindDirectoryInfo(portnum, SNum, &pg, &Han[hn])) { Han[hn].Name[0] = 0; // release the handle OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } // set the read flag Han[hn].Read = 1; // setting extra information flname->Spage = Han[hn].Spage; flname->NumPgs = Han[hn].NumPgs; // return the handle number *hnd = hn; return TRUE; } //-------------------------------------------------------------------------- // Formats a touch memory. Supports local and remote bitmap. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // // return: TURE : touch memory formatted // FALSE : error // SMALLINT owFormat(int portnum, uchar *SNum) { uchar nwdir[] = {0xAA, 0, 0x80, 0x01, 0, 0, 0, 0, 0}; uchar bm[34], temp_buff[34]; short cnt; int i, j, len; int maxP, findagain; SMALLINT bank = 1; PAGE_TYPE bitmap, eprom, next, last = 0; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // zero the bitmap for (i = 0; i < 34; i++) bm[i] = 0; // invalidate current directory of device on this com port CD.ne = 0; maxP = maxPages(portnum, SNum); // check for file bitmap if ((maxP > 32) || (owIsWriteOnce(bank, portnum, SNum))) { // tweek the standard directory for remote bitmap nwdir[2] = 0x00; // bitmap control byte nwdir[3] = 0x00; // reset bitmap if ((SNum[0] == 0x0A) || (SNum[0] == 0x0C) || (SNum[0] == 0x21)) { bitmap = 1; nwdir[5] = bitmap; // page address of bitmap } else if ((SNum[0] == 0x0B) || (SNum[0] == 0x0F) || (SNum[0] == 0x13)) { bitmap = 8; nwdir[5] = bitmap; // page address of bitmap } else { bitmap = 0; nwdir[5] = bitmap; } // get eprom exception if ((!owIsWriteOnce(bank, portnum, SNum)) || (SNum[0] == 0x21) || (SNum[0] == 0x14)) nwdir[6] = (maxP > 223) ? 2 : 1; // pages in bitmap else { cnt = ((maxP + 1) / 8) + (((maxP + 1) % 8) ? 1 : 0); nwdir[6] = (cnt / 8) + ((cnt % 8) ? 1 : 0); } // zero the bitmap for (i = 0; i < 34; i++) bm[i] = 0; // set the pages to be used in the bitmap if ((!owIsWriteOnce(bank, portnum, SNum)) || (SNum[0] == 0x21) || (SNum[0] == 0x14)) // nvram so bitmap is in regular space bm[0] = (nwdir[6] == 1) ? 0x03 : 0x07; else // must be an eprom so bitmap does not take up regular memory space bm[0] = 0x01; // write a null in page 0 before anything else if (!Write_Page(portnum, SNum, &nwdir[0], 0, 0)) return FALSE; // depending on type, bitmap may be in different places if ((!owIsWriteOnce(bank, portnum, SNum)) || (SNum[0] == 0x14) || (SNum[0] == 0x18) || (SNum[0] == 0x23)) { // calculate length and continuation pointers if (bm[0] == 0x07) { // set the continuation pointer bm[28] = bitmap + 1; // set length i = 29; } else // set length i = (maxP + 1) / 8 + 1; // write the first bitmap page if (!Write_Page(portnum, SNum, bm, bitmap, i)) return FALSE; // optionally write the second bitmap page if (bm[0] == 0x07) { i = (maxP + 1) / 8 - 27; if (!Write_Page(portnum, SNum, &bm[29], (PAGE_TYPE)(bitmap + 1), i)) return FALSE; } } // eprom so set page 0 in bitmap // not set bitmap on format else { // set the page 0 just in case it has not been set if (!ReadBitMap(portnum, SNum, bm)) return FALSE; // try to clear all possible buffer pages for (i = 0; i < maxP; i++) if (!BitMapChange(portnum, SNum, (uchar)i, 0, bm)) return FALSE; } } if (owIsWriteOnce(bank, portnum, SNum)) { bank = 0; eprom = 0; if (Read_Page(portnum, SNum, &temp_buff[0], REGMEM, &eprom, &len)) { if ((eprom != 0) && (last == 0)) last = eprom; FindEmpties(portnum, SNum, bm, &eprom, &next); findagain = FALSE; do { if (last == eprom) { findagain = TRUE; if (!BitMapChange(portnum, SNum, eprom, 1, bm)) return FALSE; if (!WriteBitMap(portnum, SNum, bm)) return FALSE; } else { if (owReadPage(bank, portnum, SNum, eprom, FALSE, &temp_buff[0])) { for (j = 0; j < owGetPageLength(bank, SNum); j++) if (temp_buff[j] != 0xFF) { findagain = TRUE; break; } if (j == owGetPageLength(bank, SNum)) { findagain = FALSE; if (owCanRedirectPage(bank, SNum)) { if (!redirectPage(bank, portnum, SNum, last, eprom)) return FALSE; } if (!Write_Page(portnum, SNum, &nwdir[0], (PAGE_TYPE)eprom, 8)) return FALSE; if (!BitMapChange(portnum, SNum, eprom, 1, bm)) return FALSE; if (!WriteBitMap(portnum, SNum, bm)) return FALSE; } else { if (!BitMapChange(portnum, SNum, eprom, 1, bm)) return FALSE; if (!WriteBitMap(portnum, SNum, bm)) return FALSE; } } } if (findagain) { FindEmpties(portnum, SNum, bm, &eprom, &next); if (eprom == last) { return FALSE; } else { if (owCanRedirectPage(bank, SNum)) { if (!redirectPage(bank, portnum, SNum, last, eprom)) return FALSE; } } } } while (findagain); } else { if (!Write_Page(portnum, SNum, &nwdir[0], eprom, 8)) return FALSE; if (!BitMapChange(portnum, SNum, eprom, 1, bm)) return FALSE; if (!WriteBitMap(portnum, SNum, bm)) return FALSE; } } else { if (!Write_Page(portnum, SNum, &nwdir[0], 0, 8)) return FALSE; if (!BitMapChange(portnum, SNum, 0, 1, bm)) return FALSE; if (!WriteBitMap(portnum, SNum, bm)) return FALSE; } for (i = 0; i < 4; i++) if (!owCloseFile(portnum, SNum, (short)i)) OWERROR(OWERROR_FILE_NOT_FOUND); owClearError(); return TRUE; } //-------------------------------------------------------------------------- // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // FE the infomation of the first file/dir found // // return: FALSE error or no files found // 204 if first found // SMALLINT owFirstFile(int portnum, uchar *SNum, FileEntry *FE) { PAGE_TYPE pg; // check device type if (!ValidRom(portnum, SNum)) return FALSE; LastFile = 0; // reset the file counter // check to see if in a sub-directory, if yes then return '.' if (CD.ne > 0) { FE->Name[0] = '.'; FE->Name[1] = ' '; FE->Name[2] = ' '; FE->Name[3] = ' '; FE->Ext = 0x7F; FE->Spage = CD.Entry[CD.ne - 1].page; FE->NumPgs = 0; FE->Attrib = CD.Entry[CD.ne - 1].attrib; // attempt to read the bitmap if (!ReadBitMap(portnum, SNum, &FE->BM[0])) return FALSE; } // not sub-directory else { // read the part of the directory to find the first file if (!ReadNumEntry(portnum, SNum, 1, FE, &pg)) return FALSE; } LastFile += 1; // update the file counter return FIRST_FOUND; // don't know how many now so return max } //-------------------------------------------------------------------------- // Find next file and put it shorto the string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // FE the infomation of the first file/dir found // // return: TRUE : file found // FALSE : no file found, error // SMALLINT owNextFile(int portnum, uchar *SNum, FileEntry *FE) { PAGE_TYPE pg, page; // check for a first reference if (!LastFile) return owFirstFile(portnum, SNum, FE); // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if the directory is valid pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne - 1].page; ; // check to see if in a sub-directory, if yes and LastFile = 1 then return '..' if ((CD.ne > 0) && (LastFile == 1)) { FE->Name[0] = '.'; FE->Name[1] = '.'; FE->Name[2] = ' '; FE->Name[3] = ' '; FE->Ext = 0x7F; // check for root exception for previous directory if (CD.ne == 1) { FE->Spage = 0; FE->Attrib = 0; } // must be at least 2 levels deep so previous is not root else { FE->Spage = CD.Entry[CD.ne - 2].page; FE->Attrib = CD.Entry[CD.ne - 2].attrib; } FE->NumPgs = 0; // attempt to read the bitmap if (!ReadBitMap(portnum, SNum, &FE->BM[0])) return FALSE; } // not (sub-directory and not back reference) else { // read the part of the directory to find the next file // figure the entry number if in sub-directory pg = (CD.ne > 0) ? LastFile - 1 : LastFile + 1; owClearError(); if (!ReadNumEntry(portnum, SNum, pg, FE, &page)) { if (owGetErrorNum() == OWERROR_FILE_NOT_FOUND) { LastFile = 0; // reset the file counter return FALSE; } else if (!owHasErrors()) { LastFile = 0; return FALSE; } else return FALSE; } } LastFile += 1; // update the file counter return TRUE; } //-------------------------------------------------------------------------- // Get the current directory path // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // // returns the current directory path // DirectoryPath owGetCurrentDir(int portnum, uchar *SNum) { DirectoryPath retpath; int i, j; retpath.NumEntries = CD.ne; // set the number of directory levels retpath.Ref = '\\'; // symbol for root // loop to copy each entry for (i = 0; i < CD.ne; i++) for (j = 0; j < 4; j++) retpath.Entries[i][j] = CD.Entry[i].name[j]; return retpath; } //-------------------------------------------------------------------------- // owChangeDirectory // // Set or read the current directory. The 'Operation' flag tells what the // operation will be. If 'Operation' is 1 then the working directory is read. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // CDBuf the directory to change to // // return: TRUE : directory set or read successfully // FALSE: error // // SMALLINT owChangeDirectory(int portnum, uchar *SNum, DirectoryPath *CDBuf) { short i, j; uchar ROM[8]; CurrentDirectory TCD; uchar pg = 0; FileInfo fbuf; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if new directory is a reference from current directory if (CDBuf->Ref == '.') TCD = CD; // copy current directory // else starting from root with an empty directory else TCD.ne = 0; // loop through new directory and verify each level for (i = 0; i < CDBuf->NumEntries; i++) { // check for a back reference if (CDBuf->Entries[i][0] == '.' && CDBuf->Entries[i][1] == '.') { // reference TCD back a level if possible if (TCD.ne > 0) TCD.ne--; else { OWERROR(OWERROR_INVALID_DIRECTORY); return FALSE; } } // check for non-current reference else if (!(CDBuf->Entries[i][0] == '.')) { //) // add the forward reference to TCD for (j = 0; j < 4; j++) { TCD.Entry[TCD.ne].name[j] = toupper(CDBuf->Entries[i][j]); fbuf.Name[j] = TCD.Entry[TCD.ne].name[j]; // also copy to temp buffer } TCD.Entry[TCD.ne].page = 0; // zero the page reference fbuf.Ext = 0x7F; // set the extention to directory // read the current level to verify new level is valid pg = (TCD.ne > 0) ? TCD.Entry[TCD.ne - 1].page : 0; // search through the next layer for the entry if (!FindDirectoryInfo(portnum, SNum, &pg, &fbuf)) { OWERROR(OWERROR_INVALID_DIRECTORY); return FALSE; } // remember the page that this level starts on TCD.Entry[TCD.ne].page = fbuf.Spage; // also remember the attribute of the directory TCD.Entry[TCD.ne].attrib = fbuf.Attrib; // since this level is a success go to next TCD.ne++; } } // success CD = TCD; // get the current ROM ROM[0] = 0; owSerialNum(portnum, &ROM[0], TRUE); // set the rom for (i = 0; i < 8; i++) CD.DRom[i] = ROM[i]; return TRUE; } //-------------------------------------------------------------------------- // Create a file by first verifying that the file does not exist on the // device and to assign a handle to it for writing. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // maxwrite the max that can be written // hnd the handle of the file created // flname the name and information for the file // // return: TRUE : file created // FALSE : error // SMALLINT owCreateFile(int portnum, uchar *SNum, int *maxwrite, short *hnd, FileEntry *flname) { short hn, flag, j; uchar i; PAGE_TYPE pg = 0, avail, next; uchar BM[32], pgbuf[52]; SMALLINT bank = 1; int maxP; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if filename passed is valid if (!Valid_FileName(flname) || (flname->Ext > 102)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check for special case of extension 100 if ((flname->Ext == 100) && (!owIsWriteOnce(bank, portnum, SNum))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // check for special case of extension 101 if ((flname->Ext == 101) && ((SNum[0] != 0x1A) && (SNum[0] != 0x1C) && (SNum[0] != 0x1D))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // check existing open files to with same name for (i = 0; i < 4; i++) { if (Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != flname->Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == flname->Ext)) { OWERROR(OWERROR_REPEAT_FILE); // file already exists return FALSE; } } } hn = -1; // find a handle for (i = 0; i < 4; i++) if (Han[i].Name[0] == 0) { hn = i; break; } if (hn == -1) { OWERROR(OWERROR_HANDLE_NOT_AVAIL); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne - 1].page; // copy the filename to the open handle for (i = 0; i < 4; i++) Han[hn].Name[i] = flname->Name[i]; Han[hn].Ext = flname->Ext; // clear other parts of structure (3.10) Han[hn].Spage = 0; Han[hn].NumPgs = 0; Han[hn].Attrib = 0; // search through directory to find file to open owClearError(); if (!FindDirectoryInfo(portnum, SNum, &pg, &Han[hn])) { if (owGetErrorNum() == OWERROR_FILE_NOT_FOUND) { Han[hn].Name[0] = 0; return FALSE; } } else { Han[hn].Name[0] = 0; OWERROR(OWERROR_REPEAT_FILE); return FALSE; } // clear the read flag Han[hn].Read = 0; // read the bitmap to calculate the maxwrite if (!ReadBitMap(portnum, SNum, BM)) { Han[hn].Name[0] = 0; return FALSE; } maxP = maxPages(portnum, SNum); // if monitary file if ((flname->Ext == 101) || (flname->Ext == 102)) { // fill all pages except monitary pages if (SNum[0] == 0x18) { flag = 7; } else { flag = (maxP + 1) / 4; if (flag < 3) flag = 3; } for (i = 0; i <= (maxP - flag); i++) { if (!BitMapChange(portnum, SNum, i, 1, BM)) { Han[hn].Name[0] = 0; return FALSE; } } // also set any pages used in open (101) files for (i = 0; i < 4; i++) if ((Han[i].Name[0] != 0) && ((Han[i].Ext == 101) || (Han[i].Ext == 102)) && (hn != i)) { if (!BitMapChange(portnum, SNum, Han[i].Spage, 1, BM)) { Han[hn].Name[0] = 0; return FALSE; } } // check if any space flag = GetMaxWrite(portnum, SNum, BM); if (flag < 28) { Han[hn].Name[0] = 0; // release the handle OWERROR(OWERROR_OUT_OF_SPACE); // return error code return FALSE; } // get a page FindEmpties(portnum, SNum, BM, &avail, &next); flname->Spage = avail; // for user to use Han[hn].Spage = avail; // for driver // read the page to get the counter for user if (!ExtendedRead_Page(portnum, SNum, &pgbuf[0], avail)) { Han[hn].Name[0] = 0; return FALSE; } // copy the counter/tamper into the bitmap for user if (SNum[0] == 0x18) { for (i = 0; i < 8; i++) flname->BM[i] = pgbuf[i + 32]; } else if ((SNum[0] == 0x33) || (SNum[0] == 0xB3)) { for (i = 0; i < 8; i++) flname->BM[i] = 0x00; } *maxwrite = 28; } else { // count empty pages in bitmap flag = GetMaxWrite(portnum, SNum, BM); if (flag > 28) flag -= 28; *maxwrite = flag; } pgbuf[0] = 0xAA; pgbuf[1] = 0; if (!owWriteFile(portnum, SNum, hn, &pgbuf[0], 0)) { Han[hn].Name[0] = 0; return FALSE; } // return the handle number *hnd = hn; return TRUE; } //-------------------------------------------------------------------------- // Close a file by freeing up its handle. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file to close // // return: TRUE : file closed // FALSE : error // SMALLINT owCloseFile(int portnum, uchar *SNum, short hnd) { // check that the handle is in the correct range if ((hnd < 4) && (hnd >= 0) && (Han[hnd].Name[0] != 0)) Han[hnd].Name[0] = 0; // zero first byte of handle area else { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; // error for handle does not exist } return TRUE; } //-------------------------------------------------------------------------- // Search throuch the directory of the device for the entry 'flname' and // return the page number to the caller. Also copy shorto standard 'FileInfo' // format at DirEntry. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // pg the next or current page // FInfo the file information that was gotten // // returns: // TRUE : directory page number was found // FALSE : error // SMALLINT FindDirectoryInfo(int portnum, uchar *SNum, PAGE_TYPE *pg, FileInfo *FInfo) { short i, j; uchar pgbuf[30]; PAGE_TYPE tpg, ppage, spg; int flag = 0; // start previouse page as current page ppage = *pg; spg = *pg; // loop to search through directory pages do { // read a page in the directory tpg = *pg; if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &tpg, &flag)) return FALSE; // if have a good read then search inside page for EntNum if (flag > 0) { // special case for first directory page i = 0; if (*pg == spg) { i = 7; // check to see if first dir page is a valid dir if (pgbuf[0] != 0xAA || pgbuf[1] != 0) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } } // loop through each directory entry to find FInfo for (; i < flag; i += 7) { for (j = 0; j < 4; j++) // compare file name if ((toupper(pgbuf[i + j]) != FInfo->Name[j]) && !((pgbuf[i + j] == 0x20) && (FInfo->Name[j] == 0xCC))) break; if ((j != 4) || ((pgbuf[i + 4] & 0x7F) != FInfo->Ext)) continue; // loop if not match // must be a match at this poshort // get the extension FInfo->Ext = pgbuf[i + 4] & 0x7F; // get the start page FInfo->Spage = pgbuf[i + 5]; // number of pages FInfo->NumPgs = pgbuf[i + 6]; // get the readonly/hidden flag FInfo->Attrib = (pgbuf[i + 4] & 0x80) ? 1 : 0; // shift attribute if his hidded flag if (FInfo->Ext == 0x7F) FInfo->Attrib <<= 1; // remember the page entry found FInfo->Dpage = *pg; // remember the offset of entry in directory FInfo->Offset = (uchar)i; // previouse directory page FInfo->PDpage = ppage; // return the current page number return TRUE; } // poshort to next page ppage = *pg; *pg = pgbuf[flag - 1]; } else return FALSE; // return error } while (*pg); // return failure to find directory entry return FALSE; } //-------------------------------------------------------------------------- // Read the directory to find the EntNum entry and load its value shorto // the FileEntry. If the entry number 'EntNum' is -1 then instead of looking // for an entry number, this function is looking for empty directory place. // If an empty place is not found then the last page of the directory is // returned. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // EntNum the entry number // FEntry the file entry number information // pg the page for the data // // Returns: // TRUE : entry found // FALSE : error // SMALLINT ReadNumEntry(int portnum, uchar *SNum, short EntNum, FileEntry *FEntry, PAGE_TYPE *pg) { uchar pgbuf[30]; int firstpg; short EntCnt = 0, i, j, tw; int len = 0; // set the entry to null FEntry->Name[0] = 0; // check to see if CD is still valid and get the starting page of working dir *pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne - 1].page; firstpg = TRUE; // loop to search through directory pages do { // read a page in the directory if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, pg, &len)) return FALSE; // special case for first directory page tw = 0; if (firstpg) { firstpg = FALSE; tw = 1; // check to see if first dir page is a valid dir if (pgbuf[0] != 0xAA || pgbuf[1] != 0 || len < 7) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } } // check to see if searching for an empty spot if (EntNum == -1) { // if the length is less then 4*7+1 or last page if ((len < 29) || (pgbuf[len - 1] == 0)) return TRUE; // return the page number spot found on } // check to see if EntNum is in this page else if ((EntCnt + (len / 7) - tw) >= EntNum) { // then get it j = (EntNum - EntCnt + tw - 1) * 7; // copy the name,extension,startpage,numpages,attributes for (i = 0; i < 4; i++) FEntry->Name[i] = pgbuf[j + i]; FEntry->Ext = pgbuf[j + 4] & 0x7F; FEntry->Spage = pgbuf[j + 5]; FEntry->NumPgs = pgbuf[j + 6]; FEntry->Attrib = (pgbuf[j + 4] & 0x80) ? 1 : 0; if (FEntry->Ext == 0x7F) FEntry->Attrib <<= 1; break; } // get the pointer to the next page *pg = pgbuf[len - 1]; // for the end of the list of dir and files if (*pg == 0) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } // increment the EntCnt EntCnt += ((len / 7) - tw); } while (*pg && (len > 0)); // attempt to read the bitmap if (!ReadBitMap(portnum, SNum, &FEntry->BM[0])) return FALSE; // check status if (!FEntry->Name[0]) { if (!*pg) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } else { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } } return TRUE; } //-------------------------------------------------------------------------- // Write the bitmap for the current device from the Bmap buffer. // The bitmap could be local or remote. The first page of the device // is read to determine the Bitmap type and location. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // Bmap the bitmap to be written // // Return: TRUE : bitmap written successfully // FALSE : error // // SMALLINT WriteBitMap(int portnum, uchar *SNum, uchar *Bmap) { short i, j, b, flag; int len, maxP, mBcnt; uchar pgbuf[32]; PAGE_TYPE pg = 0, tpg; SMALLINT bank = 1; // depending on type, bitmap may be in different places if (!owIsWriteOnce(bank, portnum, SNum)) { // read the first page to get local bitmap or address of bitmap file if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &pg, &len)) return FALSE; // make sure is a directory if (pgbuf[0] != 0xAA || pgbuf[1] != 0x00) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } maxP = maxPages(portnum, SNum); // get the number of bytes in bitmap b = maxP / 8; b += ((maxP % 8) ? 1 : 0); // check for local bitmap if (pgbuf[2] & 0x80) { // check for impossible number of pages local if (maxP > 32) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // first zero out the existing bitmap for (i = 3; i <= 6; i++) pgbuf[i] = 0; // copy the new bitmap over for (i = 0; i < b; i++) pgbuf[i + 3] = Bmap[i]; } // remote bitmap else { // (2.00Bug) else was missing in 2.00 tpg = pgbuf[5]; // remote bitmap location maxP = maxPages(portnum, SNum); // check for 2 page bitmap if (maxP > 224) { // 2 pages so read the first page to get continuation if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &tpg, &len)) return FALSE; // sanity check if (len != 29) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // get the continuation page pg = pgbuf[len - 1]; // check and copy over flag = 0; for (i = 0; i < (len - 1); i++) { if (pgbuf[i] != Bmap[i]) { flag = 1; pgbuf[i] = Bmap[i]; } } // write back the first bitmap page if it has changed if (flag) { // write the first page of the bitmap if (!Write_Page(portnum, SNum, &pgbuf[0], tpg, len)) return FALSE; } // create the second page for (i = 0; i < (b - 28); i++) pgbuf[i] = Bmap[i + 28]; pgbuf[i] = 0; // end continuation page pointer // set the new length len = b - 27; } else { // (2.00Bug) this else and code for 1 page bitmap files was missing pg = pgbuf[5]; // remote bitmap location // copy the new bitmap over for (i = 0; i < b; i++) pgbuf[i] = Bmap[i]; len = b + 1; // get the correct length pgbuf[b] = 0; // end continuation page pointer } } // loop to write a page of the bitmap if (!Write_Page(portnum, SNum, &pgbuf[0], pg, len)) return FALSE; } // Else this is a an program job else { // is there a job that has been opened then read from buffer and not the part if (isJob(portnum, SNum)) { maxP = maxPages(portnum, SNum); ; // bitmap is in the status memory // get number of status bytes needed mBcnt = (maxP / 8) + (((maxP % 8) > 0) ? 1 : 0); // loop to copy from the programjob buffer for (i = 0; i < mBcnt; i++) { // set the program job if (!setProgramJob(portnum, SNum, Bmap[i], i)) return FALSE; // check to see if this nullifies any previous page writes for (j = 0; j < 8; j++) { // if the bitmap is empty then don't write anything there if (!((Bmap[i] >> j) & 0x01)) if (!setJobWritten(portnum, SNum, (PAGE_TYPE)(i * 8 + j), PJOB_NONE)) return FALSE; } } return TRUE; } else { // error condition, should never happen here OWERROR(OWERROR_NO_PROGRAM_JOB); return FALSE; } } return TRUE; } //-------------------------------------------------------------------------- // Read the bitmap from the current device and place it in the Bmap buffer. // The bitmap could be local or remote. The first page of the device // is read to determine the Bitmap type and location. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // Bmap the returned bit map // // Return: TRUE : bitmap read // FALSE : error // // SMALLINT ReadBitMap(int portnum, uchar *SNum, uchar *Bmap) { short i, j, l, flag, mBcnt; uchar pgbuf[32], tpg = 0, pg; SMALLINT bank = 1; int page = 0; int len = 0; int maxP = 0; // depending on type, bitmap may be in different places if (!owIsWriteOnce(bank, page, SNum)) { // read the first page to get local bitmap or address of bitmap file if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &tpg, &len)) return FALSE; // make sure is a directory if (pgbuf[0] != 0xAA || pgbuf[1] != 0x00) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // check for local bitmap if (pgbuf[2] & 0x80) { // its local, but does this make sense for this size of device maxP = maxPages(portnum, SNum); if (maxP > 32) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // clear out bitmap for (i = 0; i <= len - 1; i++) Bmap[i] = 0; // copy over the local bitmap for (i = 0; i <= maxP / 8; i++) Bmap[i] = pgbuf[i + 3]; // return true return TRUE; } // must be remote else { pg = pgbuf[5]; // remote bitmap location // read the first page of the bitmap if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &pg, &len)) return FALSE; maxP = maxPages(portnum, SNum); // check size and continuation pointers to make sure they are valid if (((maxP > 224) && ((len != 29) || (pgbuf[len - 1] == 0))) || ((maxP <= 224) && (((maxP + 1) / 8 != (len - 1)) || (pgbuf[len - 1] != 0)))) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // copy bitmap over to the buffer for (i = 0; i < (len - 1); i++) Bmap[i] = pgbuf[i]; // check to see if need a second bitmap page if (pgbuf[len - 1]) { // get the page number from the continuation pointer pg = pgbuf[len - 1]; // read the second page of the bitmap if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &pg, &len)) return FALSE; // check if size of rest of bitmap makes sense if ((27 + len) != ((maxP + 1) / 8)) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // copy rest of bitmap to buffer for (i = 0; i < (len - 1); i++) Bmap[28 + i] = pgbuf[i]; return TRUE; } return TRUE; } } // DS1982/DS2405A type program else if (owIsWriteOnce(bank, page, SNum)) { if ((SNum[0] == 0x0B) || (SNum[0] == 0x0F)) { maxP = maxPages(portnum, SNum); mBcnt = ((maxP + 1) / 8) + ((((maxP + 1) % 8) > 0) ? 1 : 0); l = (mBcnt / 8) + (((mBcnt % 8) > 0) ? 1 : 0); // check for the an Program Job flag = FALSE; if (isJob(portnum, SNum)) { // loop to copy from the programjob buffer if (!getProgramJob(portnum, SNum, &Bmap[0], mBcnt)) return FALSE; flag = TRUE; } // read from the part if (!flag) { // loop through the number of bitmap pages for (i = 0; i < l; i++) { // read stat mem page tpg = i + 8; if (!Read_Page(portnum, SNum, &pgbuf[0], STATUSMEM, &tpg, &len)) return FALSE; // check results if (len == 8) { // copy bitmap read shorto buffer for (j = 0; j < 8; j++) if (j <= mBcnt) Bmap[j + i * 8] = ~pgbuf[j]; else break; // quit the loop because done } else return FALSE; } } return TRUE; } else { // is there a job that has been opened then read from buffer and not the part if (isJob(portnum, SNum)) { // to copy from the programjob buffer if (!getProgramJob(portnum, SNum, &Bmap[0], 1)) return FALSE; return TRUE; } tpg = 0; // bitmap is in the status memory page 0, byte if (!Read_Page(portnum, SNum, &pgbuf[0], STATUSMEM, &tpg, &len)) return FALSE; // check result of status read if (len == 8) { Bmap[0] = (~(pgbuf[0] >> 4)) & 0x0F; return TRUE; } } } else OWERROR(OWERROR_WRONG_TYPE); return FALSE; } //-------------------------------------------------------------------------- // Calculate and return the numbers of bytes available to write in the // current device. Note that the value is adjusted for the contingency // that the addition of a new file in the directory may make the directory // a page longer. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // BM the bitmap for the part // // return the number of bytes available to the File I/O // SMALLINT GetMaxWrite(int portnum, uchar *SNum, uchar *BM) { uchar t = 0; short bcnt = 0, cnt = 0, i; int maxP = 0; SMALLINT ret = 0; maxP = maxPages(portnum, SNum); // loop through each page bit for (i = 0; i <= maxP; i++) { // check if it is time to get the next bm byte if ((i % 8) == 0) t = BM[bcnt++]; // check for empty pages if (!(t & 0x01)) cnt++; // look at next page t >>= 1; } if (((cnt + 1) * 28) > (maxP * 28)) ret = cnt * 28; else ret = (cnt + 1) * 28; // don't take shorto acount the effect of a new directory page return ret; } //-------------------------------------------------------------------------- // Check to see if the serial number being used is the current one. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // // returns 'true' if it is the current serial number // otherwise 'false' // SMALLINT ValidRom(int portnum, uchar *SNum) { int i; uchar check[8]; if (current[0] == 0x00) { for (i = 0; i < 8; i++) current[i] = SNum[i]; owSerialNum(portnum, &SNum[0], FALSE); } else { owSerialNum(portnum, &check[0], TRUE); for (i = 0; i < 8; i++) if (check[i] != SNum[i]) return FALSE; } return TRUE; } //-------------------------------------------------------------------------- // Do bit manipulation to the provided bitmap. Change the 'BitNum' bit to // the 'State'. This function needs Handle and D to check the max page // number and see if clearing a bit is possible (Eprom). // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // BitNum the bit number to be changed // State the state of the bit to be changed to // BM the pointer to the bit map that is changed // // This function returns: // TRUE : operation is ok for this device // FALSE : could not do operation because incompatible with // device type // SMALLINT BitMapChange(int portnum, uchar *SNum, uchar BitNum, uchar State, uchar *BM) { PAGE_TYPE maxP; SMALLINT bank = 1; int page = 0; maxP = maxPages(portnum, SNum); // check for a not possible request if (BitNum > maxP) { OWERROR(OWERROR_TOO_LARGE_BITNUM); return FALSE; } // check for the clearing of an eprom device (not possible) if (owIsWriteOnce(bank, page, SNum)) { if (State == 0) { // check if only in buffer // or non written buffered eprom page if (isJob(portnum, SNum)) { // see if page set to write but has not started yet if ((isJobWritten(portnum, SNum, BitNum) == PJOB_WRITE) && ((isJobWritten(portnum, SNum, BitNum) & PJOB_START) != PJOB_START)) { if (!setJobWritten(portnum, SNum, BitNum, PJOB_NONE)) return FALSE; BM[BitNum / 8] = (BM[BitNum / 8] | (0x01 << (BitNum % 8))) ^ (0x01 << (BitNum % 8)); } } else return TRUE; } else BM[BitNum / 8] |= (0x01 << (BitNum % 8)); } // NVRAM else { // depending on the state do the opertion if (State) BM[BitNum / 8] |= (0x01 << (BitNum % 8)); else BM[BitNum / 8] = (BM[BitNum / 8] | (0x01 << (BitNum % 8))) ^ (0x01 << (BitNum % 8)); } return TRUE; } //-------------------------------------------------------------------------- // Function to decide if the filename passed to it is valid. // // flname the filename // // return TRUE if the filename is legal // SMALLINT Valid_FileName(FileEntry *flname) { uchar i; // loop to check if filename is valid and convert to upper case for (i = 0; i < 4; i++) if (!isalnum(flname->Name[i]) && !strrchr(" !#$%&'-@^_`{}~", flname->Name[i])) return FALSE; else flname->Name[i] = toupper(flname->Name[i]); // convert to upper case return TRUE; } //-------------------------------------------------------------------------- // Function to search through the provided bitmap 'BM' and return the // first 'avail'able page and the 'next' available page. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // BM the bit map // avail the available page for File I/O // next the next page that is available for File I/O // void FindEmpties(int portnum, uchar *SNum, uchar *BM, PAGE_TYPE *avail, PAGE_TYPE *next) { uchar First = 1, t = 0, i, bcnt = 0; int tmp_pgs = maxPages(portnum, SNum); // set available and next available to 0 *avail = 0; *next = 0; // loop through all of the pages in the bitmap for (i = 0; i <= tmp_pgs; i++) { // check if it is time to get the next bm byte if ((i % 8) == 0) t = BM[bcnt++]; // check for empty pages if (!(t & 0x01)) { if (First) { *avail = i; First = 0; } else { *next = i; return; } } // look at next page t >>= 1; } } //-------------------------------------------------------------------------- // This function returns the maximum number of pages that can be used for // the file I/O operations. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // // This function returns: The number of pages for File I/O // // int maxPages(int portnum, uchar *SNum) { SMALLINT bank = 1; SMALLINT i; int tmp_pgs = 0; if (owIsWriteOnce(bank, portnum, SNum)) { for (i = 0; i < owGetNumberBanks(SNum[0]); i++) { if (owIsNonVolatile(i, SNum) && owIsGeneralPurposeMemory(i, SNum)) { tmp_pgs = tmp_pgs + owGetNumberPages(i, SNum); } } } else { for (i = 0; i < owGetNumberBanks(SNum[0]); i++) { if (owIsNonVolatile(i, SNum) && owIsGeneralPurposeMemory(i, SNum) && owIsReadWrite(i, portnum, SNum)) { tmp_pgs = tmp_pgs + owGetNumberPages(i, SNum); } } } return (tmp_pgs - 1); } //-------------------------------------------------------------------------- // Change the current rom // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // void ChangeRom(int portnum, uchar *SNum) { int i; for (i = 0; i < 8; i++) current[i] = SNum[i]; owSerialNum(portnum, &SNum[0], FALSE); } //-------------------------------------------------------------------------- // gets the last page of the data // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // PAGE_TYPE getLastPage(int portnum, uchar *SNum) { return LastPage; } // hnd could be just create with TMCreateFile or it could be an existing // file that was opened with TMOpenAddFile // length are provided. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle for the file // operation the operation to be performed on the file // offset the offset for the buffer of data // buf the data to be added. // len the length of the data to be added // // Returns: TRUE File Write successful return number of bytes written // FALSE File Write a failure, error // SMALLINT owWriteAddFile(int portnum, uchar *SNum, short hnd, short operation, short offset, uchar *buf, int *len) { uchar BM[32], pgbuf[34]; int i, cnt = 0, mavail, dlen, offcnt; short spot, op; PAGE_TYPE next, avail, tpg, pg, dpg; FileEntry Dmmy; uchar *ptr; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if handle valid number if (hnd > 3 || hnd < 0) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see that hnd is valid if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } // check to see if extension is 100 if (Han[hnd].Ext != 100) { OWERROR(OWERROR_FUNC_NOT_SUP); return FALSE; } // check to see if the file is aleady terminated if (Han[hnd].NumPgs != 0) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } // get the bitmap to find empties if needed if (!ReadBitMap(portnum, SNum, &BM[0])) return FALSE; // get current empty space on device mavail = GetMaxWrite(portnum, SNum, &BM[0]); // check to see if this is a new file or an existing file // file already exist if (Han[hnd].Read == 1) { // start at starting page of the opened file pg = Han[hnd].Spage; offcnt = -1; // loop to search through file pages for (;;) { // read a page in the file if (!owReadPageExtraCRC(0, portnum, SNum, pg, &pgbuf[0], &pgbuf[32])) return FALSE; // check for an already terminated file if (pgbuf[0] != 0xFF) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } // append if (operation == APPEND) { // check to see this is the last page if (pgbuf[29] == 0xFF) { for (spot = 28; spot >= 0; spot--) if (pgbuf[spot] != 0xFF) break; if (spot <= 0) spot = 1; else spot++; // 'spot' is the spot to append to on page 'pg' break; } } // offset else { // loop to look for the spot for (spot = 1; spot <= 28; spot++) { if (++offcnt == offset) break; } // check to see if got to the offset point or out of pages if (offcnt == offset || pgbuf[29] == 0xFF) break; } // then try the next page in the chain pg = pgbuf[29]; } } // file is new so have to add to directory else { // try to find an empty spot in the directory if (!ReadNumEntry(portnum, SNum, -1, &Dmmy, &dpg)) return FALSE; // read the directory page indicated to see if it has space or is the last // loop while error during read up to 3 count cnt = 0; tpg = (uchar)dpg; if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &tpg, &dlen)) return FALSE; // in light of the directory page read check space again if (dlen == 29) mavail -= 28; if (mavail < 0 || *len > mavail) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // Record where the file begins FindEmpties(portnum, SNum, &BM[0], &avail, &next); Han[hnd].Spage = avail; // set the bitmap to claim this page if (!BitMapChange(portnum, SNum, avail, 1, &BM[0])) return FALSE; // construct the new directory entry Han[hnd].NumPgs = 0; Han[hnd].Attrib = 0; // check to see if need to write a new directory page if (dlen == 29) { // get an empty page for the new directory page FindEmpties(portnum, SNum, &BM[0], &avail, &next); // write the new page if (!Write_Page(portnum, SNum, (uchar *)&Han[hnd], avail, 8)) return FALSE; // set the bitmap to account for this new directory page if (!BitMapChange(portnum, SNum, avail, 1, &BM[0])) return FALSE; // change the exhisting directory page continuation pointer pgbuf[dlen - 1] = avail; } // add the new directory entry to exhisting directory page else { // remember the continuation pointer pg = pgbuf[dlen - 1]; // get a pointer into the handle ptr = (uchar *)&Han[hnd]; // loop to add the new entry for (i = 0; i < 7; i++) pgbuf[dlen - 1 + i] = ptr[i]; // adjust the length of the directory page dlen += 7; // correct the continuation pointer pgbuf[dlen - 1] = pg; } // special case of dir page == 0 and local bitmap if ((dpg == 0) && (pgbuf[2] & 0x80)) { // update the local bitmap for (i = 0; i < 2; i++) pgbuf[3 + i] = BM[i]; pgbuf[5] = 0; pgbuf[6] = 0; } // non page 0 or non local bitmap else { // write the bitmap if (!WriteBitMap(portnum, SNum, &BM[0])) return FALSE; } // now rewrite the directory page if (!Write_Page(portnum, SNum, &pgbuf[0], dpg, dlen)) return FALSE; pg = Han[hnd].Spage; spot = 1; offcnt = 0; } // check to see if need to add some blank pages (except for pointer) if (operation == 0 && offcnt != offset) { // start on 'pg' and add pages until get to offset for (;;) { // loop to look for the spot for (; spot <= 28; spot++) { if (offcnt == offset) break; offcnt++; } // check to see if got to the offset point or out of pages if (offcnt == offset) break; // else get another page FindEmpties(portnum, SNum, &BM[0], &avail, &next); // decrement the number of pages available mavail -= 28; if (mavail < 0 || avail == 0xFF) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // write the pointer byte if (!WriteJobByte(portnum, SNum, pg, 29, avail, 0)) return FALSE; // set bitmap to claim that new page if (!BitMapChange(portnum, SNum, avail, 1, &BM[0])) return FALSE; pg = avail; spot = 1; offcnt++; } } // Now should be able to write data at 'spot' on page 'pg' if ((*len != 0) && (Han[hnd].Ext == 100)) { cnt = 0; for (;;) { // get the 'zeros' flag op = (operation == APPEND) ? 0 : 1; // set bitmap to claim the page if (!BitMapChange(portnum, SNum, pg, 1, &BM[0])) return FALSE; // loop to write the rest of the page or until done for (; spot <= 28; spot++) { // write a byte to the program job list if (!WriteJobByte(portnum, SNum, pg, spot, buf[cnt++], op)) return FALSE; // check to see if done if (cnt >= *len) { // first write the bitmap before ending with success if (!WriteBitMap(portnum, SNum, &BM[0])) return FALSE; // reset read flag so could read file now Han[hnd].Read = 1; return TRUE; } } // data more than one page. spot = 1; FindEmpties(portnum, SNum, &BM[0], &avail, &next); if (!WriteJobByte(portnum, SNum, pg, 29, avail, 0)) return FALSE; pg = avail; } } else { if (!BitMapChange(portnum, SNum, pg, 1, &BM[0])) return FALSE; else if (!setJobWritten(portnum, SNum, pg, PJOB_ADD)) return FALSE; return TRUE; } // set the redirection byte // else get another page FindEmpties(portnum, SNum, &BM[0], &avail, &next); // decrement the number of pages available mavail -= 28; if (mavail < 0 || avail == 0xFF) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // write the pointer byte if (!WriteJobByte(portnum, SNum, pg, 29, avail, 0)) return FALSE; pg = avail; spot = 1; return TRUE; } //-------------------------------------------------------------------------- // Terminate an 'add' file by adding the length and CRC16 bytes to each // page. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // flname the file to be written to the part // // return: TRUE : 'add' file terminated // FALSE: error // SMALLINT owTerminateAddFile(int portnum, uchar *SNum, FileEntry *flname) { short i, j; uchar pgbuf[34], buf[32], pgcnt; PAGE_TYPE pg = 0; int flag; FileInfo Info; // check device type if (!ValidRom(portnum, SNum)) return FALSE; // check to see if filename passed is valid if ((Valid_FileName(flname) == 0) || ((flname->Ext & 0x7F) != 100)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check existing open files with same the name (3.10) // automatically close the file for (i = 0; i < 4; i++) { if (Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != flname->Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == flname->Ext)) { Han[i].Name[0] = 0; // release the handle break; } } } // depending on the directory set the first page to look for entry if (CD.ne == 0) pg = 0; else pg = CD.Entry[CD.ne - 1].page; // copy filename over to info packet for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to find the location of the file name if (!FindDirectoryInfo(portnum, SNum, &pg, &Info)) return FALSE; // check to see if the file is aleady terminated if (Info.NumPgs != 0) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } pg = Info.Spage; pgcnt = 0; for (;;) { // loop while error during read up to 3 count if (!owReadPageExtraCRC(0, portnum, SNum, pg, &pgbuf[0], &pgbuf[32])) return FALSE; // read success, check to see if already terminated if (pgbuf[0] != 0xFF || pgbuf[30] != 0xFF || pgbuf[31] != 0xFF || pgbuf[32] != 0xFF) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } // count the page pgcnt++; // terminte the page in the program job if (!TerminatePage(portnum, SNum, pg, &pgbuf[0])) return FALSE; // check for end of file if (pgbuf[29] == 0xFF) { // write the last page pointer to 0 if (!WriteJobByte(portnum, SNum, pg, 29, 0x00, 0)) return FALSE; break; } // get the next page in the list pg = pgbuf[29]; } // read the directory page that the entry to change length if (!Read_Page(portnum, SNum, &buf[0], REGMEM, &Info.Dpage, &flag)) return FALSE; // set the number of pages in the buffer for the file buf[Info.Offset + 6] = pgcnt; // write back the directory page with the new name if (!Write_Page(portnum, SNum, &buf[0], Info.Dpage, flag)) return FALSE; return TRUE; } w1retap/src/libusblinux300/owfile.h000066400000000000000000000171711446446235200174720ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // owFile.h - Contains the types and constants for file I/O. // // version 1.00 // #include "ownet.h" #ifndef OWFILE_H #define OWFILE_H #define MAX_NUM_PGS \ 256 // this is for max pages part might have // increase if you are going to use parts // with more than 256 pages. #define PAGE_TYPE uchar // change if the page number can be > 256 #define FILE_NAME_LEN 7 // the length of a new file #define FIRST_FOUND 204 // don't know how many now so return max // Used in internal function Read_Page and page cache #define STATUSMEM 0x80 #define REDIRMEM 0x40 #define REGMEM 0 #define DEPTH 254 #define CACHE_TIMEOUT 8000 // Directory options #define SET_DIR 0 #define READ_DIR 1 // program Job constants #define PJOB_NONE 0 #define PJOB_WRITE 1 #define PJOB_REDIR 2 #define PJOB_ADD 3 #define PJOB_TERM 4 #define PJOB_START 0x80 #define PJOB_MASK 0x7F #define APPEND 1 // external file information structure typedef struct { uchar Name[4]; // 4 uchar Ext; // 1 uchar Spage; // 1 uchar NumPgs; // 1 uchar Attrib; // 1 uchar BM[32]; // 32 } FileEntry; // structure use when reading or changing the current directory typedef struct { uchar NumEntries; // number of entries in path 0-10 char Ref; // reference character '\' or '.' char Entries[10][4]; // sub-directory entry names } DirectoryPath; // internal file information structure typedef struct { uchar Name[4]; // 4 File/Directory name uchar Ext; // 1 File/Directory extension uchar Spage; // 1 Start page uchar NumPgs; // 1 Number of pages uchar Attrib; // 1 Attribute 0x01 for readonly 0x02 for hidden uchar Dpage; // 1 Directory page this entry is in uchar Offset; // 1 Byte offset into directory page of entry uchar Read; // 1 Read = 1 if opened and 0 if created uchar PDpage; // 1 Previous directory page number } FileInfo; // current directory structure typedef struct { uchar ne; // number of entries struct { uchar name[4]; // name and extention of the sub-directory PAGE_TYPE page; // page the subdirectory starts on uchar attrib; // attribute of the directory } Entry[10]; uchar DRom[8]; // rom that this directory is valid for } CurrentDirectory; // structure to hold the program job list ~ 7977 bytes typedef struct { uchar ERom[8]; // rom of the program job target uchar EBitmap[32]; // bit map kept for uchar OrgBitmap[32]; // original bitmap struct { uchar wr; // flag to indicate this page needs to be written PAGE_TYPE len; // length of data uchar data[29]; // data to write uchar bm[4]; // bitmap for bytes to write } Page[MAX_NUM_PGS]; // 256 possible jobs } ProgramJob; // type to hold a data entry in the DHash typedef struct { uchar ROM[8]; // rom of device page is from uint Tstamp; // time stamp when page void uchar Fptr; // forward pointer to next entry in chain uchar Bptr; // back pointer to previous entry in chain uchar Hptr; // hash pointer to hash position PAGE_TYPE Page; // page number uchar Data[32]; // page data including length uchar Redir; // redirection page } Dentry; #endif // OWFILE_H // function prototypes for owcache.c void InitDHash(void); uchar AddPage(int portnum, uchar *SNum, PAGE_TYPE pg, uchar *buf, int len); SMALLINT FindPage(int portnum, uchar *SNum, PAGE_TYPE *page, uchar mflag, uchar time, uchar *buf, int *len, uchar *space_num); uchar FreePage(uchar ptr); // function prototypes for owfile.c SMALLINT owFirstFile(int, uchar *, FileEntry *); SMALLINT owNextFile(int, uchar *, FileEntry *); SMALLINT owOpenFile(int, uchar *, FileEntry *, short *); SMALLINT owCreateFile(int, uchar *, int *, short *, FileEntry *); SMALLINT owCloseFile(int, uchar *, short); SMALLINT owReadFile(int, uchar *, short, uchar *, int, int *); SMALLINT owRemoveDir(int, uchar *, FileEntry *); SMALLINT owWriteFile(int, uchar *, short, uchar *, int); SMALLINT owDeleteFile(int, uchar *, FileEntry *); SMALLINT owFormat(int, uchar *); SMALLINT owAttribute(int, uchar *, short, FileEntry *); SMALLINT owReNameFile(int, uchar *, short, FileEntry *); SMALLINT owChangeDirectory(int, uchar *, DirectoryPath *); SMALLINT owCreateDir(int, uchar *, FileEntry *); DirectoryPath owGetCurrentDir(int, uchar *); SMALLINT owWriteAddFile(int, uchar *, short, short, short, uchar *, int *); SMALLINT owTerminateAddFile(int, uchar *, FileEntry *); SMALLINT ReadBitMap(int, uchar *, uchar *); SMALLINT WriteBitMap(int, uchar *, uchar *); SMALLINT ReadNumEntry(int, uchar *, short, FileEntry *, PAGE_TYPE *); SMALLINT GetMaxWrite(int, uchar *, uchar *); SMALLINT FindDirectoryInfo(int, uchar *, PAGE_TYPE *, FileInfo *); SMALLINT ValidRom(int, uchar *); SMALLINT BitMapChange(int, uchar *, uchar, uchar, uchar *); SMALLINT Valid_FileName(FileEntry *); void FindEmpties(int, uchar *, uchar *, PAGE_TYPE *, PAGE_TYPE *); int maxPages(int, uchar *); void ChangeRom(int portnum, uchar *SNum); PAGE_TYPE getLastPage(int, uchar *); // function prototypes for owpgrw.c SMALLINT Read_Page(int portnum, uchar *SNum, uchar *buff, uchar flag, PAGE_TYPE *pg, int *len); SMALLINT Write_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE page, int len); SMALLINT ExtWrite(int portnum, uchar *SNum, uchar strt_page, uchar *file, int fllen, uchar *BM); SMALLINT ExtRead(int portnum, uchar *SNum, uchar *file, int start_page, int maxlen, uchar del, uchar *BM, int *fl_len); SMALLINT ExtendedRead_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE pg); // function prototypes for owprgm.c SMALLINT owCreateProgramJob(int, uchar *); SMALLINT owDoProgramJob(int, uchar *); SMALLINT isJob(int, uchar *); SMALLINT isJobWritten(int, uchar *, PAGE_TYPE); SMALLINT getJobData(int, uchar *, PAGE_TYPE, uchar *, int *); SMALLINT setJobData(int, uchar *, PAGE_TYPE, uchar *, int); SMALLINT setJobWritten(int, uchar *, PAGE_TYPE, SMALLINT); SMALLINT getOrigBM(int, uchar *, uchar *); SMALLINT setProgramJob(int, uchar *, uchar, int); SMALLINT getProgramJob(int, uchar *, uchar *, int); SMALLINT WriteJobByte(int, uchar *, PAGE_TYPE, short, uchar, short); SMALLINT TerminatePage(int, uchar *, short, uchar *); w1retap/src/libusblinux300/owllu.c000066400000000000000000000605651446446235200173470ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // owLLU.C - Link Layer 1-Wire Net functions using the DS2480/DS2480B (U) // serial interface chip. // // Version: 3.00 // // History: 1.00 -> 1.01 DS2480 version number now ignored in // owTouchReset. // 1.02 -> 1.03 Removed caps in #includes for Linux capatibility // Removed #include // Add #include "ownet.h" to define TRUE,FALSE // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // Added owReadBitPower and owWriteBytePower // Added support for THE LINK // Updated owLevel to match AN192 // #include "ownet.h" #include "ds2480.h" int dodebug = 0; // external globals extern SMALLINT ULevel[MAX_PORTNUM]; // current DS2480B 1-Wire Net level extern SMALLINT UBaud[MAX_PORTNUM]; // current DS2480B baud rate extern SMALLINT UMode[MAX_PORTNUM]; // current DS2480B command or data mode state extern SMALLINT USpeed[MAX_PORTNUM]; // current DS2480B 1-Wire Net communication speed extern SMALLINT UVersion[MAX_PORTNUM]; // current DS2480B version // new global for DS1994/DS2404/DS1427. If TRUE, puts a delay in owTouchReset to compensate for alarming clocks. SMALLINT FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE = FALSE; // default owTouchReset to quickest response. // local varable flag, true if program voltage available static SMALLINT ProgramAvailable[MAX_PORTNUM]; //-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE(1): presense pulse(s) detected, device(s) reset // FALSE(0): no presense pulses detected // // WARNING: Without setting the above global (FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE) // to TRUE, this routine will not function correctly on some // Alarm reset types of the DS1994/DS1427/DS2404 with // Rev 1,2, and 3 of the DS2480/DS2480B. // // SMALLINT owTouchReset_(int portnum) { uchar readbuffer[10], sendpacket[10]; uchar sendlen = 0; if (dodebug) printf("\nRST "); //?????????????? // make sure normal level owLevel(portnum, MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // construct the command sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_RESET | USpeed[portnum]); // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 1 byte response if (ReadCOM(portnum, 1, readbuffer) == 1) { // make sure this byte looks like a reset byte if (((readbuffer[0] & RB_RESET_MASK) == RB_PRESENCE) || ((readbuffer[0] & RB_RESET_MASK) == RB_ALARMPRESENCE)) { // check if programming voltage available ProgramAvailable[portnum] = ((readbuffer[0] & 0x20) == 0x20); UVersion[portnum] = (readbuffer[0] & VERSION_MASK); // only check for alarm pulse if DS2404 present and not using THE LINK if ((FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE) && (UVersion[portnum] != VER_LINK)) { msDelay(5); // delay 5 ms to give DS1994 enough time FlushCOM(portnum); } return TRUE; } else OWERROR(OWERROR_RESET_FAILED); } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return FALSE; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and return the // result 1 bit read from the 1-Wire Net. The parameter 'sendbit' // least significant bit is used and the least significant bit // of the result is the return bit. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbit' - the least significant bit is the bit to send // // Returns: 0: 0 bit read from sendbit // 1: 1 bit read from sendbit // SMALLINT owTouchBit_(int portnum, SMALLINT sendbit) { uchar readbuffer[10], sendpacket[10]; uchar sendlen = 0; // make sure normal level owLevel(portnum, MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // construct the command sendpacket[sendlen] = (sendbit != 0) ? BITPOL_ONE : BITPOL_ZERO; sendpacket[sendlen++] |= CMD_COMM | FUNCTSEL_BIT | USpeed[portnum]; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the response if (ReadCOM(portnum, 1, readbuffer) == 1) { // interpret the response if (((readbuffer[0] & 0xE0) == 0x80) && ((readbuffer[0] & RB_BIT_MASK) == RB_BIT_ONE)) return 1; else return 0; } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return 0; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // SMALLINT owWriteByte_(int portnum, SMALLINT sendbyte) { return (owTouchByte(portnum, sendbyte) == (0xff & sendbyte)) ? TRUE : FALSE; } //-------------------------------------------------------------------------- // Send 8 bits of read communication to the 1-Wire Net and and return the // result 8 bits read from the 1-Wire Net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: 8 bits read from 1-Wire Net // SMALLINT owReadByte_(int portnum) { return owTouchByte(portnum, (SMALLINT)0xFF); } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and return the // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' // least significant 8 bits are used and the least significant 8 bits // of the result is the return byte. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: 8 bits read from sendbyte // SMALLINT owTouchByte_(int portnum, SMALLINT sendbyte) { uchar readbuffer[10], sendpacket[10]; uchar sendlen = 0; // make sure normal level owLevel(portnum, MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_DATA) { UMode[portnum] = MODSEL_DATA; sendpacket[sendlen++] = MODE_DATA; } // add the byte to send sendpacket[sendlen++] = (uchar)sendbyte; // check for duplication of data that looks like COMMAND mode if (sendbyte == (SMALLINT)MODE_COMMAND) sendpacket[sendlen++] = (uchar)sendbyte; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 1 byte response if (ReadCOM(portnum, 1, readbuffer) == 1) { if (dodebug) printf("%02X ", readbuffer[0]); //?????????????? // return the response return (int)readbuffer[0]; } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return 0; } //-------------------------------------------------------------------------- // Set the 1-Wire Net communucation speed. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'new_speed' - new speed defined as // MODE_NORMAL 0x00 // MODE_OVERDRIVE 0x01 // // Returns: current 1-Wire Net speed // SMALLINT owSpeed_(int portnum, SMALLINT new_speed) { uchar sendpacket[5]; uchar sendlen = 0; uchar rt = FALSE; // check if change from current mode if (((new_speed == MODE_OVERDRIVE) && (USpeed[portnum] != SPEEDSEL_OD)) || ((new_speed == MODE_NORMAL) && (USpeed[portnum] != SPEEDSEL_FLEX))) { if (new_speed == MODE_OVERDRIVE) { // check for unsupported mode in THE LINK if (UVersion[portnum] == VER_LINK) OWERROR(OWERROR_FUNC_NOT_SUP); // if overdrive then switch to higher baud else if (DS2480ChangeBaud(portnum, MAX_BAUD) == MAX_BAUD) { USpeed[portnum] = SPEEDSEL_OD; rt = TRUE; } } else if (new_speed == MODE_NORMAL) { // else normal so set to 9600 baud if (DS2480ChangeBaud(portnum, PARMSET_9600) == PARMSET_9600) { USpeed[portnum] = SPEEDSEL_FLEX; rt = TRUE; } } // if baud rate is set correctly then change DS2480 speed if (rt) { // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // proceed to set the DS2480 communication speed sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed[portnum]; // send the packet if (!WriteCOM(portnum, sendlen, sendpacket)) { OWERROR(OWERROR_WRITECOM_FAILED); rt = FALSE; // lost communication with DS2480 then reset DS2480Detect(portnum); } } } // return the current speed return (USpeed[portnum] == SPEEDSEL_OD) ? MODE_OVERDRIVE : MODE_NORMAL; } //-------------------------------------------------------------------------- // Set the 1-Wire Net line level. The values for new_level are // as follows: // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'new_level' - new level defined as // MODE_NORMAL 0x00 // MODE_STRONG5 0x02 // MODE_PROGRAM 0x04 // MODE_BREAK 0x08 (not supported) // // Returns: current 1-Wire Net level // SMALLINT owLevel_(int portnum, SMALLINT new_level) { uchar sendpacket[10], readbuffer[10]; uchar sendlen = 0; uchar rt = FALSE; // check if need to change level if (new_level != ULevel[portnum]) { // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // check if just putting back to normal if (new_level == MODE_NORMAL) { // stop pulse command sendpacket[sendlen++] = MODE_STOP_PULSE; // add the command to begin the pulse WITHOUT prime sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; // stop pulse command sendpacket[sendlen++] = MODE_STOP_PULSE; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 2 byte response if (ReadCOM(portnum, 2, readbuffer) == 2) { // check response byte if (((readbuffer[0] & 0xE0) == 0xE0) && ((readbuffer[1] & 0xE0) == 0xE0)) { rt = TRUE; ULevel[portnum] = MODE_NORMAL; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); } // set new level else { // strong 5 volts if (new_level == MODE_STRONG5) { // set the SPUD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; // add the command to begin the pulse sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V; } // 12 volts else if (new_level == MODE_PROGRAM) { // check if programming voltage available if (!ProgramAvailable[portnum]) return MODE_NORMAL; // set the PPD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_infinite; // add the command to begin the pulse sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_12V; } // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 1 byte response from setting time limit if (ReadCOM(portnum, 1, readbuffer) == 1) { // check response byte if ((readbuffer[0] & 0x81) == 0) { ULevel[portnum] = new_level; rt = TRUE; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); } // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); } // return the current level return ULevel[portnum]; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE successful // FALSE program voltage not available // SMALLINT owProgramPulse_(int portnum) { uchar sendpacket[10], readbuffer[10]; uchar sendlen = 0; // check if programming voltage available if (!ProgramAvailable[portnum]) return FALSE; // make sure normal level owLevel(portnum, MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // set the SPUD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us; // pulse command sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 2 byte response if (ReadCOM(portnum, 2, readbuffer) == 2) { // check response byte if (((readbuffer[0] | CMD_CONFIG) == (CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us)) && ((readbuffer[1] & 0xFC) == (0xFC & (CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE)))) return TRUE; } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return FALSE; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant bit) // // Returns: TRUE: bytes written and echo was the same, strong pullup now on // FALSE: echo was not the same // SMALLINT owWriteBytePower_(int portnum, SMALLINT sendbyte) { uchar sendpacket[10], readbuffer[10]; uchar sendlen = 0; uchar rt = FALSE; uchar i, temp_byte; if (dodebug) printf("P%02X ", sendbyte); //?????????????? // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // set the SPUD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; // construct the stream to include 8 bit commands with the last one // enabling the strong-pullup temp_byte = sendbyte; for (i = 0; i < 8; i++) { sendpacket[sendlen++] = ((temp_byte & 0x01) ? BITPOL_ONE : BITPOL_ZERO) | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | ((i == 7) ? PRIME5V_TRUE : PRIME5V_FALSE); temp_byte >>= 1; } // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 9 byte response from setting time limit if (ReadCOM(portnum, 9, readbuffer) == 9) { // check response if ((readbuffer[0] & 0x81) == 0) { // indicate the port is now at power delivery ULevel[portnum] = MODE_STRONG5; // reconstruct the echo byte temp_byte = 0; for (i = 0; i < 8; i++) { temp_byte >>= 1; temp_byte |= (readbuffer[i + 1] & 0x01) ? 0x80 : 0; } if (temp_byte == sendbyte) rt = TRUE; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); return rt; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant bit) // // Returns: TRUE: bytes written and echo was the same, strong pullup now on // FALSE: echo was not the same // SMALLINT owReadBytePower_(int portnum) { uchar sendpacket[10], readbuffer[10]; uchar sendlen = 0; uchar rt = FALSE; uchar i, temp_byte; // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // set the SPUD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; // construct the stream to include 8 bit commands with the last one // enabling the strong-pullup temp_byte = 0xFF; for (i = 0; i < 8; i++) { sendpacket[sendlen++] = ((temp_byte & 0x01) ? BITPOL_ONE : BITPOL_ZERO) | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | ((i == 7) ? PRIME5V_TRUE : PRIME5V_FALSE); temp_byte >>= 1; } // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 9 byte response from setting time limit if (ReadCOM(portnum, 9, readbuffer) == 9) { // check response if ((readbuffer[0] & 0x81) == 0) { // indicate the port is now at power delivery ULevel[portnum] = MODE_STRONG5; // reconstruct the return byte temp_byte = 0; for (i = 0; i < 8; i++) { temp_byte >>= 1; temp_byte |= (readbuffer[i + 1] & 0x01) ? 0x80 : 0; } rt = TRUE; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); if (dodebug) printf("PFF%02X ", temp_byte); //?????????????? return temp_byte; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and verify that the // response matches the 'applyPowerResponse' bit and apply power delivery // to the 1-Wire net. Note that some implementations may apply the power // first and then turn it off if the response is incorrect. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'applyPowerResponse' - 1 bit response to check, if correct then start // power delivery // // Returns: TRUE: bit written and response correct, strong pullup now on // FALSE: response incorrect // SMALLINT owReadBitPower_(int portnum, SMALLINT applyPowerResponse) { uchar sendpacket[3], readbuffer[3]; uchar sendlen = 0; uchar rt = FALSE; // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // set the SPUD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; // enabling the strong-pullup after bit sendpacket[sendlen++] = BITPOL_ONE | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | PRIME5V_TRUE; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 2 byte response from setting time limit if (ReadCOM(portnum, 2, readbuffer) == 2) { // check response to duration set if ((readbuffer[0] & 0x81) == 0) { // indicate the port is now at power delivery ULevel[portnum] = MODE_STRONG5; // check the response bit if ((readbuffer[1] & 0x01) == applyPowerResponse) rt = TRUE; else owLevel(portnum, MODE_NORMAL); return rt; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); return rt; } //-------------------------------------------------------------------------- // This procedure indicates whether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE because all userial adapters have over drive. // SMALLINT owHasPowerDelivery_(int portnum) { return TRUE; } //-------------------------------------------------------------------------- // This procedure indicates wether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE because all userial adapters have over drive. // SMALLINT owHasOverDrive_(int portnum) { return TRUE; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE program volatage available // FALSE program voltage not available SMALLINT owHasProgramPulse_(int portnum) { return ProgramAvailable[portnum]; } w1retap/src/libusblinux300/ownet.h000066400000000000000000000403361446446235200173400ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ownet.h - Include file for 1-Wire Net library // // Version: 2.10 // // History: 1.02 -> 1.03 Make sure uchar is not defined twice. // 1.03 -> 2.00 Changed 'MLan' to 'ow'. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #pragma once //--------------------------------------------------------------// // Target Specific Information //--------------------------------------------------------------// //--------------------------------------------------------------// // Handhelds (PalmOS, WinCE) //--------------------------------------------------------------// #ifdef __MC68K__ // MC68K is the type of processor in the PILOT // Metrowerk's CodeWarrior defines this symbol #include #ifndef strcmp #include #define strcmp StrCompare #endif #endif #ifdef _WIN32_WCE // All of our projects had this flag defined by default (_WIN32_WCE), // but I'm not 100% positive that this is _the_ definitive // flag to use to identify a WinCE system. #include "WinCElnk.h" #endif #ifdef _WIN32_WCE #ifndef FILE #define FILE int extern int sprintf(char *buffer, char *format, ...); extern void fprintf(FILE *fp, char *format, ...); extern void printf(char *format, ...); #endif #endif #ifdef __MC68K__ #include #endif #if !defined(_WIN32_WCE) && !defined(__MC68K__) #include #endif #ifdef __C51__ #define FILE int #define exit(c) return typedef unsigned int ushort; #define SMALLINT uchar #endif //--------------------------------------------------------------// // Common Includes to ownet applications //--------------------------------------------------------------// #include #include //--------------------------------------------------------------// // Typedefs //--------------------------------------------------------------// #ifndef SMALLINT // // purpose of smallint is for compile-time changing of formal // parameters and return values of functions. For each target // machine, an integer is alleged to represent the most "simple" // number representable by that architecture. This should, in // most cases, produce optimal code for that particular arch. // BUT... The majority of compilers designed for embedded // processors actually keep an int at 16 bits, although the // architecture might only be comfortable with 8 bits. // The default size of smallint will be the same as that of // an integer, but this allows for easy overriding of that size. // // NOTE: // In all cases where a smallint is used, it is assumed that // decreasing the size of this integer to something as low as // a single byte _will_not_ change the functionality of the // application. e.g. a loop counter that will iterate through // several kilobytes of data should not be SMALLINT. The most // common place you'll see smallint is for boolean return types. // #define SMALLINT int #endif // setting max baud #ifdef _WINDOWS // 0x02 = PARAMSET_19200 #define MAX_BAUD 0x02 #else // 0x06 = PARMSET_115200 #define MAX_BAUD 0x06 #endif #ifndef OW_UCHAR #define OW_UCHAR typedef unsigned char uchar; #ifdef __CYGWIN__ //&& GCC // ushort already defined in CygWin, in sys/types.h #include #else #if defined(_WIN32) || defined(WIN32) || defined(__MC68K__) || defined(_WIN32_WCE) || defined(_DOS) || defined(_WINDOWS) typedef unsigned short ushort; #endif #endif #ifdef __sun__ #include #endif #ifdef SDCC // intent of ushort is 2 bytes unsigned. // for ds390 in sdcc, an int, not a short, // is 2 bytes. typedef unsigned int ushort; #endif #endif #ifndef __USE_MISC typedef unsigned int uint; #endif // general defines #define WRITE_FUNCTION 1 #define READ_FUNCTION 0 // error codes // todo: investigate these and replace with new Error Handling library #define READ_ERROR -1 #define INVALID_DIR -2 #define NO_FILE -3 #define WRITE_ERROR -4 #define WRONG_TYPE -5 #define FILE_TOO_BIG -6 // Misc #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #ifndef MAX_PORTNUM #define MAX_PORTNUM 16 #endif // mode bit flags #define MODE_NORMAL 0x00 #define MODE_OVERDRIVE 0x01 #define MODE_STRONG5 0x02 #define MODE_PROGRAM 0x04 #define MODE_BREAK 0x08 // Output flags #define LV_ALWAYS 2 #define LV_OPTIONAL 1 #define LV_VERBOSE 0 //--------------------------------------------------------------// // Error handling //--------------------------------------------------------------// extern int owGetErrorNum(void); extern int owHasErrors(void); // Clears the stack. #define OWERROR_CLEAR() \ while (owHasErrors()) \ owGetErrorNum(); #ifdef DEBUG // Raises an exception with extra debug info #define OWERROR(err) owRaiseError(err, __LINE__, __FILE__) extern void owRaiseError(int, int, char *); #define OWASSERT(s, err, ret) \ if (!(s)) { \ owRaiseError((err), __LINE__, __FILE__); \ return (ret); \ } #else // Raises an exception with just the error code #define OWERROR(err) owRaiseError(err) extern void owRaiseError(int); #define OWASSERT(s, err, ret) \ if (!(s)) { \ owRaiseError((err)); \ return (ret); \ } #endif #ifdef SMALL_MEMORY_TARGET #define OWERROR_DUMP(fileno) /*no-op*/ ; #else // Prints the stack out to the given file. #define OWERROR_DUMP(fileno) \ while (owHasErrors()) \ owPrintErrorMsg(fileno); extern void owPrintErrorMsg(FILE *); extern void owPrintErrorMsgStd(); extern char *owGetErrorMsg(int); #endif #define OWERROR_NO_ERROR_SET 0 #define OWERROR_NO_DEVICES_ON_NET 1 #define OWERROR_RESET_FAILED 2 #define OWERROR_SEARCH_ERROR 3 #define OWERROR_ACCESS_FAILED 4 #define OWERROR_DS2480_NOT_DETECTED 5 #define OWERROR_DS2480_WRONG_BAUD 6 #define OWERROR_DS2480_BAD_RESPONSE 7 #define OWERROR_OPENCOM_FAILED 8 #define OWERROR_WRITECOM_FAILED 9 #define OWERROR_READCOM_FAILED 10 #define OWERROR_BLOCK_TOO_BIG 11 #define OWERROR_BLOCK_FAILED 12 #define OWERROR_PROGRAM_PULSE_FAILED 13 #define OWERROR_PROGRAM_BYTE_FAILED 14 #define OWERROR_WRITE_BYTE_FAILED 15 #define OWERROR_READ_BYTE_FAILED 16 #define OWERROR_WRITE_VERIFY_FAILED 17 #define OWERROR_READ_VERIFY_FAILED 18 #define OWERROR_WRITE_SCRATCHPAD_FAILED 19 #define OWERROR_COPY_SCRATCHPAD_FAILED 20 #define OWERROR_INCORRECT_CRC_LENGTH 21 #define OWERROR_CRC_FAILED 22 #define OWERROR_GET_SYSTEM_RESOURCE_FAILED 23 #define OWERROR_SYSTEM_RESOURCE_INIT_FAILED 24 #define OWERROR_DATA_TOO_LONG 25 #define OWERROR_READ_OUT_OF_RANGE 26 #define OWERROR_WRITE_OUT_OF_RANGE 27 #define OWERROR_DEVICE_SELECT_FAIL 28 #define OWERROR_READ_SCRATCHPAD_VERIFY 29 #define OWERROR_COPY_SCRATCHPAD_NOT_FOUND 30 #define OWERROR_ERASE_SCRATCHPAD_NOT_FOUND 31 #define OWERROR_ADDRESS_READ_BACK_FAILED 32 #define OWERROR_EXTRA_INFO_NOT_SUPPORTED 33 #define OWERROR_PG_PACKET_WITHOUT_EXTRA 34 #define OWERROR_PACKET_LENGTH_EXCEEDS_PAGE 35 #define OWERROR_INVALID_PACKET_LENGTH 36 #define OWERROR_NO_PROGRAM_PULSE 37 #define OWERROR_READ_ONLY 38 #define OWERROR_NOT_GENERAL_PURPOSE 39 #define OWERROR_READ_BACK_INCORRECT 40 #define OWERROR_INVALID_PAGE_NUMBER 41 #define OWERROR_CRC_NOT_SUPPORTED 42 #define OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED 43 #define OWERROR_READ_BACK_NOT_VALID 44 #define OWERROR_COULD_NOT_LOCK_REDIRECT 45 #define OWERROR_READ_STATUS_NOT_COMPLETE 46 #define OWERROR_PAGE_REDIRECTION_NOT_SUPPORTED 47 #define OWERROR_LOCK_REDIRECTION_NOT_SUPPORTED 48 #define OWERROR_READBACK_EPROM_FAILED 49 #define OWERROR_PAGE_LOCKED 50 #define OWERROR_LOCKING_REDIRECTED_PAGE_AGAIN 51 #define OWERROR_REDIRECTED_PAGE 52 #define OWERROR_PAGE_ALREADY_LOCKED 53 #define OWERROR_WRITE_PROTECTED 54 #define OWERROR_NONMATCHING_MAC 55 #define OWERROR_WRITE_PROTECT 56 #define OWERROR_WRITE_PROTECT_SECRET 57 #define OWERROR_COMPUTE_NEXT_SECRET 58 #define OWERROR_LOAD_FIRST_SECRET 59 #define OWERROR_POWER_NOT_AVAILABLE 60 #define OWERROR_XBAD_FILENAME 61 #define OWERROR_XUNABLE_TO_CREATE_DIR 62 #define OWERROR_REPEAT_FILE 63 #define OWERROR_DIRECTORY_NOT_EMPTY 64 #define OWERROR_WRONG_TYPE 65 #define OWERROR_BUFFER_TOO_SMALL 66 #define OWERROR_NOT_WRITE_ONCE 67 #define OWERROR_FILE_NOT_FOUND 68 #define OWERROR_OUT_OF_SPACE 69 #define OWERROR_TOO_LARGE_BITNUM 70 #define OWERROR_NO_PROGRAM_JOB 71 #define OWERROR_FUNC_NOT_SUP 72 #define OWERROR_HANDLE_NOT_USED 73 #define OWERROR_FILE_WRITE_ONLY 74 #define OWERROR_HANDLE_NOT_AVAIL 75 #define OWERROR_INVALID_DIRECTORY 76 #define OWERROR_HANDLE_NOT_EXIST 77 #define OWERROR_NONMATCHING_SNUM 78 #define OWERROR_NON_PROGRAM_PARTS 79 #define OWERROR_PROGRAM_WRITE_PROTECT 80 #define OWERROR_FILE_READ_ERR 81 #define OWERROR_ADDFILE_TERMINATED 82 #define OWERROR_READ_MEMORY_PAGE_FAILED 83 #define OWERROR_MATCH_SCRATCHPAD_FAILED 84 #define OWERROR_ERASE_SCRATCHPAD_FAILED 85 #define OWERROR_READ_SCRATCHPAD_FAILED 86 #define OWERROR_SHA_FUNCTION_FAILED 87 #define OWERROR_NO_COMPLETION_BYTE 88 #define OWERROR_WRITE_DATA_PAGE_FAILED 89 #define OWERROR_COPY_SECRET_FAILED 90 #define OWERROR_BIND_SECRET_FAILED 91 #define OWERROR_INSTALL_SECRET_FAILED 92 #define OWERROR_VERIFY_SIG_FAILED 93 #define OWERROR_SIGN_SERVICE_DATA_FAILED 94 #define OWERROR_VERIFY_AUTH_RESPONSE_FAILED 95 #define OWERROR_ANSWER_CHALLENGE_FAILED 96 #define OWERROR_CREATE_CHALLENGE_FAILED 97 #define OWERROR_BAD_SERVICE_DATA 98 #define OWERROR_SERVICE_DATA_NOT_UPDATED 99 #define OWERROR_CATASTROPHIC_SERVICE_FAILURE 100 #define OWERROR_LOAD_FIRST_SECRET_FAILED 101 #define OWERROR_MATCH_SERVICE_SIGNATURE_FAILED 102 #define OWERROR_KEY_OUT_OF_RANGE 103 #define OWERROR_BLOCK_ID_OUT_OF_RANGE 104 #define OWERROR_PASSWORDS_ENABLED 105 #define OWERROR_PASSWORD_INVALID 106 #define OWERROR_NO_READ_ONLY_PASSWORD 107 #define OWERROR_NO_READ_WRITE_PASSWORD 108 #define OWERROR_OW_SHORTED 109 #define OWERROR_ADAPTER_ERROR 110 #define OWERROR_EOP_COPY_SCRATCHPAD_FAILED 111 #define OWERROR_EOP_WRITE_SCRATCHPAD_FAILED 112 #define OWERROR_HYGRO_STOP_MISSION_UNNECESSARY 113 #define OWERROR_HYGRO_STOP_MISSION_ERROR 114 #define OWERROR_PORTNUM_ERROR 115 #define OWERROR_LEVEL_FAILED 116 #define OWERROR_LIBUSB_OPEN_FAILED 117 #define OWERROR_LIBUSB_DEVICE_ALREADY_OPENED 118 #define OWERROR_LIBUSB_SET_CONFIGURATION_ERROR 119 #define OWERROR_LIBUSB_CLAIM_INTERFACE_ERROR 120 #define OWERROR_LIBUSB_SET_ALTINTERFACE_ERROR 121 #define OWERROR_LIBUSB_NO_ADAPTER_FOUND 122 // libloader extern int owAcquireEx(char *port_zstr); extern SMALLINT owAcquire(int portnum, char *port_zstr); // One Wire functions defined in ownetu.c extern SMALLINT (*owFirst)(int portnum, SMALLINT do_reset, SMALLINT alarm_only); extern SMALLINT (*owNext)(int portnum, SMALLINT do_reset, SMALLINT alarm_only); extern void (*owSerialNum)(int portnum, uchar *serialnum_buf, SMALLINT do_read); extern void (*owFamilySearchSetup)(int portnum, SMALLINT search_family); extern void (*owSkipFamily)(int portnum); extern SMALLINT (*owAccess)(int portnum); extern SMALLINT (*owVerify)(int portnum, SMALLINT alarm_only); extern SMALLINT (*owOverdriveAccess)(int portnum); // external One Wire functions defined in owsesu.c extern SMALLINT (*owAcquire__)(int portnum, char *port_zstr); extern int (*owAcquireEx__)(char *port_zstr); extern void (*owRelease)(int portnum); // external One Wire functions defined in findtype.c // SMALLINT FindDevices(int,uchar FamilySN[][8],SMALLINT,int); // external One Wire functions from link layer owllu.c extern SMALLINT (*owTouchReset)(int portnum); extern SMALLINT (*owTouchBit)(int portnum, SMALLINT sendbit); extern SMALLINT (*owTouchByte)(int portnum, SMALLINT sendbyte); extern SMALLINT (*owWriteByte)(int portnum, SMALLINT sendbyte); extern SMALLINT (*owReadByte)(int portnum); extern SMALLINT (*owSpeed)(int portnum, SMALLINT new_speed); extern SMALLINT (*owLevel)(int portnum, SMALLINT new_level); extern SMALLINT (*owProgramPulse)(int portnum); extern SMALLINT (*owWriteBytePower)(int portnum, SMALLINT sendbyte); extern SMALLINT (*owReadBytePower)(int portnum); extern SMALLINT (*owHasPowerDelivery)(int portnum); extern SMALLINT (*owHasProgramPulse)(int portnum); extern SMALLINT (*owHasOverDrive)(int portnum); extern SMALLINT (*owReadBitPower)(int portnum, SMALLINT applyPowerResponse); // external One Wire functions from transaction layer in owtrnu.c extern SMALLINT (*owBlock)(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len); extern SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf); extern SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf, SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type); extern SMALLINT (*owProgramByte)(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access); // link functions extern void (*msDelay)(int len); extern int (*msGettick)(void); extern void (*owShowVersion)(void); // ioutil.c functions prototypes extern int EnterString(char *msg, char *buf, int min, int max); extern int EnterNum(char *msg, int numchars, int *value, int min, int max); extern int EnterHex(char *msg, int numchars, uint *value); extern int ToHex(char ch); extern int getkeystroke(void); extern int key_abort(void); extern void ExitProg(char *msg, int exit_code); extern int getData(uchar *write_buff, int max_len, SMALLINT gethex); extern void PrintHex(uchar *buffer, int cnt); extern void PrintChars(uchar *buffer, int cnt); extern void PrintSerialNum(uchar *buffer); // external functions defined in crcutil.c extern void setcrc16(int portnum, ushort reset); extern ushort docrc16(int portnum, ushort cdata); extern void setcrc8(int portnum, uchar reset); extern uchar docrc8(int portnum, uchar x); extern char *w1_module_build_path(const char *dir, const char *name); extern SMALLINT FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE; w1retap/src/libusblinux300/ownetu.c000066400000000000000000000456471446446235200175320ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // owNetU.C - Network functions for 1-Wire Net devices // using the DS2480/DS2480B (U) serial interface chip. // // Version: 2.01 // // 1.02 -> 1.03 Removed caps in #includes for Linux capatibility // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // Updated search functions to be consistent with AN192 // #include "ownet.h" #include "ds2480.h" // local functions defined in ownetu.c static SMALLINT bitacc(SMALLINT, SMALLINT, SMALLINT, uchar *); // global variables for this module to hold search state information static int LastDiscrepancy[MAX_PORTNUM]; static int LastFamilyDiscrepancy[MAX_PORTNUM]; static uchar LastDevice[MAX_PORTNUM]; uchar SerialNum[MAX_PORTNUM][8]; // external globals extern int UMode[MAX_PORTNUM]; extern SMALLINT USpeed[MAX_PORTNUM]; //-------------------------------------------------------------------------- // The 'owFirst' finds the first device on the 1-Wire Net This function // contains one parameter 'alarm_only'. When // 'alarm_only' is TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0 // // Returns: TRUE (1) : when a 1-Wire device was found and it's // Serial Number placed in the global SerialNum // FALSE (0): There are no devices on the 1-Wire Net. // SMALLINT owFirst_(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { // reset the search state LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return owNext(portnum, do_reset, alarm_only); } //-------------------------------------------------------------------------- // The 'owNext' function does a general search. This function // continues from the previos search state. The search state // can be reset by using the 'owFirst' function. // This function contains one parameter 'alarm_only'. // When 'alarm_only' is TRUE (1) the find alarm command // 0xEC is sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0 // // Returns: TRUE (1) : when a 1-Wire device was found and it's // Serial Number placed in the global SerialNum // FALSE (0): when no new device was found. Either the // last search was the last device or there // are no devices on the 1-Wire Net. // SMALLINT owNext_(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { uchar last_zero, pos; uchar tmp_serial_num[8]; uchar readbuffer[20], sendpacket[40]; uchar i, sendlen = 0; uchar lastcrc8; // if the last call was the last one if (LastDevice[portnum]) { // reset the search LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return FALSE; } // check if reset first is requested if (do_reset) { // reset the 1-wire // if there are no parts on 1-wire, return FALSE if (!owTouchReset(portnum)) { // reset the search LastDiscrepancy[portnum] = 0; LastFamilyDiscrepancy[portnum] = 0; OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // build the command stream // call a function that may add the change mode command to the buff // check if correct mode if (UMode[portnum] != MODSEL_DATA) { UMode[portnum] = MODSEL_DATA; sendpacket[sendlen++] = MODE_DATA; } // search command if (alarm_only) sendpacket[sendlen++] = 0xEC; // issue the alarming search command else sendpacket[sendlen++] = 0xF0; // issue the search command // change back to command mode UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; // search mode on sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHON | USpeed[portnum]); // change back to data mode UMode[portnum] = MODSEL_DATA; sendpacket[sendlen++] = MODE_DATA; // set the temp Last Descrep to none last_zero = 0; // add the 16 bytes of the search pos = sendlen; for (i = 0; i < 16; i++) sendpacket[sendlen++] = 0; // only modify bits if not the first search if (LastDiscrepancy[portnum] != 0) { // set the bits in the added buffer for (i = 0; i < 64; i++) { // before last discrepancy if (i < (LastDiscrepancy[portnum] - 1)) bitacc(WRITE_FUNCTION, bitacc(READ_FUNCTION, 0, i, &SerialNum[portnum][0]), (short)(i * 2 + 1), &sendpacket[pos]); // at last discrepancy else if (i == (LastDiscrepancy[portnum] - 1)) bitacc(WRITE_FUNCTION, 1, (short)(i * 2 + 1), &sendpacket[pos]); // after last discrepancy so leave zeros } } // change back to command mode UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; // search OFF sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed[portnum]); // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the 1 byte response if (ReadCOM(portnum, 17, readbuffer) == 17) { // interpret the bit stream for (i = 0; i < 64; i++) { // get the SerialNum bit bitacc(WRITE_FUNCTION, bitacc(READ_FUNCTION, 0, (short)(i * 2 + 1), &readbuffer[1]), i, &tmp_serial_num[0]); // check LastDiscrepancy if ((bitacc(READ_FUNCTION, 0, (short)(i * 2), &readbuffer[1]) == 1) && (bitacc(READ_FUNCTION, 0, (short)(i * 2 + 1), &readbuffer[1]) == 0)) { last_zero = i + 1; // check LastFamilyDiscrepancy if (i < 8) LastFamilyDiscrepancy[portnum] = i + 1; } } // do dowcrc setcrc8(portnum, 0); for (i = 0; i < 8; i++) lastcrc8 = docrc8(portnum, tmp_serial_num[i]); // check results if ((lastcrc8 != 0) || (LastDiscrepancy[portnum] == 63) || (tmp_serial_num[0] == 0)) { // error during search // reset the search LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; OWERROR(OWERROR_SEARCH_ERROR); return FALSE; } // successful search else { // set the last discrepancy LastDiscrepancy[portnum] = last_zero; // check for last device if (LastDiscrepancy[portnum] == 0) LastDevice[portnum] = TRUE; // copy the SerialNum to the buffer for (i = 0; i < 8; i++) SerialNum[portnum][i] = tmp_serial_num[i]; // set the count return TRUE; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); // reset the search LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return FALSE; } //-------------------------------------------------------------------------- // The 'owSerialNum' function either reads or sets the SerialNum buffer // that is used in the search functions 'owFirst' and 'owNext'. // This function contains two parameters, 'serialnum_buf' is a pointer // to a buffer provided by the caller. 'serialnum_buf' should point to // an array of 8 unsigned chars. The second parameter is a flag called // 'do_read' that is TRUE (1) if the operation is to read and FALSE // (0) if the operation is to set the internal SerialNum buffer from // the data in the provided buffer. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'serialnum_buf' - buffer to that contains the serial number to set // when do_read = FALSE (0) and buffer to get the serial // number when do_read = TRUE (1). // 'do_read' - flag to indicate reading (1) or setting (0) the current // serial number. // void owSerialNum_(int portnum, uchar *serialnum_buf, SMALLINT do_read) { uchar i; // read the internal buffer and place in 'serialnum_buf' if (do_read) { for (i = 0; i < 8; i++) serialnum_buf[i] = SerialNum[portnum][i]; } // set the internal buffer from the data in 'serialnum_buf' else { for (i = 0; i < 8; i++) SerialNum[portnum][i] = serialnum_buf[i]; } } //-------------------------------------------------------------------------- // Setup the search algorithm to find a certain family of devices // the next time a search function is called 'owNext'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'search_family' - family code type to set the search algorithm to find // next. // void owFamilySearchSetup_(int portnum, SMALLINT search_family) { uchar i; // set the search state to find search_family type devices SerialNum[portnum][0] = search_family; for (i = 1; i < 8; i++) SerialNum[portnum][i] = 0; LastDiscrepancy[portnum] = 64; LastFamilyDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; } //-------------------------------------------------------------------------- // Set the current search state to skip the current family code. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void owSkipFamily_(int portnum) { // set the Last discrepancy to last family discrepancy LastDiscrepancy[portnum] = LastFamilyDiscrepancy[portnum]; // clear the last family discrpepancy LastFamilyDiscrepancy[portnum] = 0; // check for end of list if (LastDiscrepancy[portnum] == 0) LastDevice[portnum] = TRUE; } //-------------------------------------------------------------------------- // The 'owAccess' function resets the 1-Wire and sends a MATCH Serial // Number command followed by the current SerialNum code. After this // function is complete the 1-Wire device is ready to accept device-specific // commands. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE (1) : reset indicates present and device is ready // for commands. // FALSE (0): reset does not indicate presence or echos 'writes' // are not correct. // SMALLINT owAccess_(int portnum) { uchar sendpacket[9]; uchar i; // reset the 1-wire if (owTouchReset(portnum)) { // create a buffer to use with block function // match Serial Number command 0x55 sendpacket[0] = 0x55; // Serial Number for (i = 1; i < 9; i++) sendpacket[i] = SerialNum[portnum][i - 1]; // send/recieve the transfer buffer if (owBlock(portnum, FALSE, sendpacket, 9)) { // verify that the echo of the writes was correct for (i = 1; i < 9; i++) if (sendpacket[i] != SerialNum[portnum][i - 1]) return FALSE; if (sendpacket[0] != 0x55) { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } else return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // reset or match echo failed return FALSE; } //---------------------------------------------------------------------- // The function 'owVerify' verifies that the current device // is in contact with the 1-Wire Net. // Using the find alarm command 0xEC will verify that the device // is in contact with the 1-Wire Net and is in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'alarm_only' - TRUE (1) the find alarm command 0xEC // is sent instead of the normal search // command 0xF0. // // Returns: TRUE (1) : when the 1-Wire device was verified // to be on the 1-Wire Net // with alarm_only == FALSE // or verified to be on the 1-Wire Net // AND in an alarm state when // alarm_only == TRUE. // FALSE (0): the 1-Wire device was not on the // 1-Wire Net or if alarm_only // == TRUE, the device may be on the // 1-Wire Net but in a non-alarm state. // SMALLINT owVerify_(int portnum, SMALLINT alarm_only) { uchar i, sendlen = 0, goodbits = 0, cnt = 0, s, tst; uchar sendpacket[50]; // construct the search rom if (alarm_only) sendpacket[sendlen++] = 0xEC; // issue the alarming search command else sendpacket[sendlen++] = 0xF0; // issue the search command // set all bits at first for (i = 1; i <= 24; i++) sendpacket[sendlen++] = 0xFF; // now set or clear apropriate bits for search for (i = 0; i < 64; i++) bitacc(WRITE_FUNCTION, bitacc(READ_FUNCTION, 0, i, &SerialNum[portnum][0]), (int)((i + 1) * 3 - 1), &sendpacket[1]); // send/recieve the transfer buffer if (owBlock(portnum, TRUE, sendpacket, sendlen)) { // check results to see if it was a success for (i = 0; i < 192; i += 3) { tst = (bitacc(READ_FUNCTION, 0, i, &sendpacket[1]) << 1) | bitacc(READ_FUNCTION, 0, (int)(i + 1), &sendpacket[1]); s = bitacc(READ_FUNCTION, 0, cnt++, &SerialNum[portnum][0]); if (tst == 0x03) { // no device on line goodbits = 0; // number of good bits set to zero break; // quit } if (((s == 0x01) && (tst == 0x02)) || ((s == 0x00) && (tst == 0x01))) // correct bit goodbits++; // count as a good bit } // check too see if there were enough good bits to be successful if (goodbits >= 8) return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); // block fail or device not present return FALSE; } //---------------------------------------------------------------------- // Perform a overdrive MATCH command to select the 1-Wire device with // the address in the ID data register. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE: If the device is present on the 1-Wire Net and // can do overdrive then the device is selected. // FALSE: Device is not present or not capable of overdrive. // // *Note: This function could be converted to send DS2480 // commands in one packet. // SMALLINT owOverdriveAccess_(int portnum) { uchar sendpacket[8]; uchar i, bad_echo = FALSE; // make sure normal level owLevel(portnum, MODE_NORMAL); // force to normal communication speed owSpeed(portnum, MODE_NORMAL); // call the 1-Wire Net reset function if (owTouchReset(portnum)) { // send the match command 0x69 if (owWriteByte(portnum, 0x69)) { // switch to overdrive communication speed owSpeed(portnum, MODE_OVERDRIVE); // create a buffer to use with block function // Serial Number for (i = 0; i < 8; i++) sendpacket[i] = SerialNum[portnum][i]; // send/recieve the transfer buffer if (owBlock(portnum, FALSE, sendpacket, 8)) { // verify that the echo of the writes was correct for (i = 0; i < 8; i++) if (sendpacket[i] != SerialNum[portnum][i]) bad_echo = TRUE; // if echo ok then success if (!bad_echo) return TRUE; else OWERROR(OWERROR_WRITE_VERIFY_FAILED); } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_WRITE_BYTE_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // failure, force back to normal communication speed owSpeed(portnum, MODE_NORMAL); return FALSE; } //-------------------------------------------------------------------------- // Bit utility to read and write a bit in the buffer 'buf'. // // 'op' - operation (1) to set and (0) to read // 'state' - set (1) or clear (0) if operation is write (1) // 'loc' - bit number location to read or write // 'buf' - pointer to array of bytes that contains the bit // to read or write // // Returns: 1 if operation is set (1) // 0/1 state of bit number 'loc' if operation is reading // static SMALLINT bitacc(SMALLINT op, SMALLINT state, SMALLINT loc, uchar *buf) { SMALLINT nbyt, nbit; nbyt = (loc / 8); nbit = loc - (nbyt * 8); if (op == WRITE_FUNCTION) { if (state) buf[nbyt] |= (0x01 << nbit); else buf[nbyt] &= ~(0x01 << nbit); return 1; } else return ((buf[nbyt] >> nbit) & 0x01); } w1retap/src/libusblinux300/owpgrw.c000066400000000000000000000331321446446235200175200ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // owPgRW.c - Reads and writes pages for the File I/O operations. // version 1.00 // // Include Files #include "owfile.h" #include "rawmem.h" //-------------------------------------------------------------------------- // Read_Page: // // Read a default data structure page from the current Touch Memory. // The record will be placed shorto a (uchar) memory location // starting at the location poshorted to by (buf). This function will // read a page out of normal memory (flag = REGMEM) or a status memory // page out of an eprom (flag = STATUSMEM). If the page being read is // redirected as in an eprom device then the page value passes by referece // is changed to match the new page. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // flag tells weather to read regular memory or status memory // buff location for data read // page page number to read packet from // len the length of the data read // // return TRUE if the data was read correctly // SMALLINT Read_Page(int portnum, uchar *SNum, uchar *buff, uchar flag, PAGE_TYPE *pg, int *len) { SMALLINT bank; PAGE_TYPE page; int jobopen = FALSE; int cnt = 0; uchar extra[3], space; uchar temp_buff[32]; uchar rd_buf[2]; int i; // Are program jobs possible // is there a job that has been opened and is this a regular memory read if (isJob(portnum, SNum)) jobopen = TRUE; // loop while redirected for (cnt = 0; cnt <= 256; cnt++) { // if an program job is open then check there for page if (jobopen && (flag != STATUSMEM)) { if (getJobData(portnum, SNum, *pg, buff, len)) { return TRUE; } } // nope so look for page in cache if (FindPage(portnum, SNum, pg, flag, TRUE, buff, len, &space)) { if (*len == 0x41) { *pg = buff[0]; } else if (flag != STATUSMEM) { return TRUE; } } bank = getBank(portnum, SNum, *pg, flag); page = getPage(portnum, SNum, *pg, flag); // nope so get it from the part // if the page is in the status memory then call read status if (flag == STATUSMEM) { if (owIsWriteOnce(bank, portnum, SNum) && owHasExtraInfo(bank, SNum)) { if (!owReadPageExtraCRC(bank, portnum, SNum, page, &temp_buff[0], &extra[0])) { if (extra[0] == 0xFF) return FALSE; } } else { if (owHasPageAutoCRC(bank, SNum)) { if (!owReadPageCRC(bank, portnum, SNum, page, &temp_buff[0])) return FALSE; } else { if (!owReadPage(bank, portnum, SNum, page, FALSE, &temp_buff[0])) return FALSE; } extra[0] = 0xFF; } if (extra[0] != 0xFF) { rd_buf[0] = ~extra[0]; AddPage(portnum, SNum, *pg, &rd_buf[0], STATUSMEM); *pg = (PAGE_TYPE)rd_buf[0]; continue; } else { *len = 8; for (i = 0; i < *len; i++) buff[i] = temp_buff[i]; AddPage(portnum, SNum, *pg, &buff[0], STATUSMEM); // AddPage(portnum,SNum,*pg,&buff[0],*len); // AddPage(portnum,SNum,*pg,&buff[0],0x41); return TRUE; } } // else call on the regular readpack function else { *len = 0; if (owIsWriteOnce(bank, portnum, SNum) && owHasExtraInfo(bank, SNum)) { if (!owReadPagePacketExtra(bank, portnum, SNum, page, FALSE, &temp_buff[0], len, &extra[0])) { if (extra[0] == 0xFF) return FALSE; } } else { if (owHasPageAutoCRC(bank, SNum)) { if (!owReadPageCRC(bank, portnum, SNum, page, &temp_buff[0])) return FALSE; } else { if (!owReadPage(bank, portnum, SNum, page, FALSE, &temp_buff[0])) return FALSE; } extra[0] = 0xFF; } if (extra[0] != 0xFF) { rd_buf[0] = ~extra[0]; AddPage(portnum, SNum, *pg, &rd_buf[0], REDIRMEM); *pg = (PAGE_TYPE)rd_buf[0]; continue; } else { if (*len > 0) { if (*len > 32) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } for (i = 0; i < (*len); i++) buff[i] = temp_buff[i]; } else { if (temp_buff[0] > 32) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } for (i = 1; i < (temp_buff[0] + 1); i++) buff[i - 1] = temp_buff[i]; *len = temp_buff[0]; } AddPage(portnum, SNum, *pg, &buff[0], *len); return TRUE; } } } // could not find the page return FALSE; } //-------------------------------------------------------------------------- // Write_Page: // // Write a page to a Touch Memory at a provided location (pg). // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // buff location of the write data // pg page number to write the packet // len the length of the packet // SMALLINT Write_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE pg, int len) { SMALLINT bank; PAGE_TYPE page; // check for length too long for a page if (len > 29) { OWERROR(OWERROR_INVALID_PACKET_LENGTH); return FALSE; } // Are program jobs possible // is there a job that has been opened if (isJob(portnum, SNum)) { if (setJobData(portnum, SNum, pg, buff, len)) return TRUE; } bank = getBank(portnum, SNum, pg, REGMEM); page = getPage(portnum, SNum, pg, REGMEM); if (!owWritePagePacket(bank, portnum, SNum, page, buff, len)) return FALSE; else { AddPage(portnum, SNum, pg, buff, len); } return TRUE; } //-------------------------------------------------------------------------- // ExtWrite writes an extended file at a location. The bitmap bits are // set each time a pages is written and verified. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // strt_page the page to start the extended write // file location of the file to write // fllen the length of the file // BM the bitmap // // return TRUE if the write was successful. // SMALLINT ExtWrite(int portnum, uchar *SNum, uchar strt_page, uchar *file, int fllen, uchar *BM) { int pgs = 0; int len = 0; PAGE_TYPE avail, next; uchar WrStr[32]; int i, j; if (fllen == 0) { if (!BitMapChange(portnum, SNum, strt_page, 1, BM)) return FALSE; return TRUE; } // calculate number of universal pages in file pgs = fllen / 28; if (fllen % 28 || !fllen) pgs++; // find available page and next available page FindEmpties(portnum, SNum, BM, &avail, &next); if (avail == 0) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } next = avail; avail = strt_page; // loop to write each page of the file for (i = 0; i < pgs; i++) { // check to see if next chunk is last chunk and adjust size len = fllen - (i * 28); if (len > 28) len = 28; // copy next chuck to write buffer for (j = 0; j < len; j++) WrStr[j] = file[(i * 28) + j]; // add the continuation pointer if (i == (pgs - 1)) WrStr[len] = (uchar)0; else WrStr[len] = (uchar)next; // write the page if (!Write_Page(portnum, SNum, &WrStr[0], avail, (len + 1))) return FALSE; // set the page just written to in bitmap BM if (!BitMapChange(portnum, SNum, avail, 1, BM)) return FALSE; // find available page and next available page FindEmpties(portnum, SNum, BM, &avail, &next); if ((avail == 0) && ((pgs - 1) != i)) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } } // must be completed because it has made it this far return TRUE; } //---------------------------------------------------------------------- // ExtRead, reads extended file structure files. It is designed such // that if a file is contiguous then it is not reset between the reading // of each page packet. The bitmap BM has a page bit cleared when a // page is read correctly. The varialbe maxlen is the max number of // bytes that can be fit into the buffer 'buf'. If maxlen is set to // -1 then the file is read but it is not copied over into buf. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // file location of the file to write // start_page the starting page for the file // maxlen the maximum length the file buffer can handle // del tell weather to delete the file or not. // BM the bitmap // fl_len the length of the file that was read // // return TRUE if the read was successful // SMALLINT ExtRead(int portnum, uchar *SNum, uchar *file, int start_page, int maxlen, uchar del, uchar *BM, int *fl_len) { SMALLINT bank; int done = FALSE; int buff_len = 0; PAGE_TYPE pg; uchar pgbuf[34]; int len = 0; int i; int flag; pg = start_page; // loop to read in pages of the extended file do { if (!Read_Page(portnum, SNum, &pgbuf[0], REGMEM, &pg, &len)) return FALSE; // add page segment to buffer if (maxlen != -1) { // don't add to buff in maxlen is -1 if ((buff_len + len) > maxlen) { OWERROR(OWERROR_BUFFER_TOO_SMALL); return FALSE; } for (i = 0; i < (len - 1); i++) file[buff_len++] = pgbuf[i]; } bank = getBank(portnum, SNum, pg, REGMEM); // flag to indicate that the page should be cleared in the BM flag = FALSE; // do if have a NVRAM device if (owIsReadWrite(bank, portnum, SNum) && owIsGeneralPurposeMemory(bank, SNum)) flag = TRUE; // or non written buffered eprom page if (isJob(portnum, SNum)) { // see if page set to write but has not started yet if (isJobWritten(portnum, SNum, pg) && del) { flag = TRUE; } } // clear bit in bitmap if (flag) { if (!BitMapChange(portnum, SNum, pg, 0, BM)) return FALSE; } // check on continuation pointer if (pgbuf[len - 1] == 0) { *fl_len = buff_len; done = TRUE; // all done } else pg = pgbuf[len - 1]; } while (!done); return TRUE; } //-------------------------------------------------------------------------- // ExtendedRead_Page: // // Read a extended page from the current Eprom Touch Memory. // The record will be placed into a (uchar) memory location // starting at the location pointed to by (buf). This function will // read a page out of normal memory. If the page being read is // redirected then an error is returned // The following return codes will be provided to the caller: // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // buff the buffer for the data that was read // pg the page that starts the read // // return TRUE if the read was successful. // SMALLINT ExtendedRead_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE pg) { SMALLINT bank; PAGE_TYPE page; uchar extra[20]; int len, i; bank = getBank(portnum, SNum, pg, REGMEM); page = getPage(portnum, SNum, pg, REGMEM); if (!owIsWriteOnce(bank, portnum, SNum) && ((SNum[0] != 0x18) && (SNum[0] != 0x33) && (SNum[0] != 0xB3))) { OWERROR(OWERROR_NOT_WRITE_ONCE); return FALSE; } // check on the program job to see if this page is in it if (isJob(portnum, SNum)) { if (getJobData(portnum, SNum, pg, &buff[1], &len)) { return TRUE; } } if (owIsWriteOnce(bank, portnum, SNum)) { if (!owReadPageExtraCRC(bank, portnum, SNum, page, &buff[0], &extra[0])) return FALSE; } else { if (!owReadPageExtra(bank, portnum, SNum, page, FALSE, &buff[0], &extra[0])) return FALSE; for (i = 0; i < owGetExtraInfoLength(bank, SNum); i++) buff[i + 32] = extra[i]; extra[0] = 0xFF; } if (extra[0] != 0xFF) { OWERROR(OWERROR_REDIRECTED_PAGE); return FALSE; } return TRUE; } w1retap/src/libusblinux300/owprgm.c000066400000000000000000000664141446446235200175170ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // owprgm.c - This source file contains the EPROM Program routines. // version 1.00 // // Include Files #include "ownet.h" #include "owfile.h" #include "rawmem.h" #include "mbeprom.h" #include // global paramters SMALLINT job_started = FALSE; ProgramJob job; //-------------------------------------------------------------------------- // Start an programming job. This function assumes that the Garbage bag D // is at least 11049 bytes long. This function check to see if the // current device is of the correct type. It reads the bitmap of the // device for reference during accumulation of Program write jobs. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the job part to be executed on. // // Returns: TRUE program job created // FALSE error // SMALLINT owCreateProgramJob(int portnum, uchar *SNum) { SMALLINT bank = 1; short i, j; // Make sure there is no current job job_started = FALSE; // check the device type if (!owIsWriteOnce(bank, portnum, SNum)) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // flush all of the cached pages InitDHash(); // read the bitmap if (!ReadBitMap(portnum, SNum, &job.EBitmap[0])) return FALSE; // keep the original bitmap for (i = 0; i < 32; i++) job.OrgBitmap[i] = job.EBitmap[i]; // clear all the job pages for (i = 0; i < MAX_NUM_PGS; i++) { job.Page[i].wr = PJOB_NONE; // clear bits in each page for (j = 0; j < 29; j++) job.Page[i].data[j] = 0xFF; } // record the current rom for (i = 0; i < 8; i++) job.ERom[i] = SNum[i]; // Set the job to true job_started = TRUE; return TRUE; } //-------------------------------------------------------------------------- // Do an program job. This function assumes that the Garbage back D // is at least 11049 bytes long. This function check to see if the // current device is of the correct type. It reads the bitmap of the // device for reference during accumulation of Program write jobs. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the job part to be executed on. // // Returns: TURE program job created // FALSE error // SMALLINT owDoProgramJob(int portnum, uchar *SNum) { uchar BM[32], WPBM[32], RWPBM[32], pgbuf[32], RDB[256], tpg; uchar tmpBM[4]; short i, j, l, Bcnt = 0, mBcnt, xtra, pg, inflp = 0, redit; uchar ROM[8]; SMALLINT bank = 1; PAGE_TYPE page = 0; int maxp = 0; int flag; PAGE_TYPE bmpg, rdpg; uchar buff[5]; memset(tmpBM, 0xFF, 4); // checks to see if the ROM number has changed for (i = 0; i < 8; i++) if (job.ERom[i] != SNum[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } // Make sure there is a job open if (job_started != TRUE) { OWERROR(OWERROR_NO_PROGRAM_JOB); return FALSE; } // Make sure that only eproms are on the line l = TRUE; // flag to see if operation is ok flag = owFirst(portnum, TRUE, FALSE); while (flag) { // check the family code owSerialNum(portnum, &ROM[0], TRUE); if (!owIsWriteOnce(bank, portnum, &ROM[0])) { l = FALSE; break; } // look for next device flag = owNext(portnum, FALSE, FALSE); } // restore the rom number for (i = 0; i < 8; i++) ROM[i] = job.ERom[i]; owSerialNum(portnum, &ROM[0], FALSE); // check for fail if (l == FALSE) { OWERROR(OWERROR_NON_PROGRAM_PARTS); return FALSE; } // flush all of the cached pages InitDHash(); maxp = maxPages(portnum, SNum); // read the write protect bits and redirect write protect bits // and redirection bytes if (owIsWriteOnce(bank, portnum, &ROM[0]) && ((ROM[0] == 0x0B) || (ROM[0] == 0x0F))) { // DS1985,DS1986 for (i = 0; i < 32; i++) BM[i] = job.OrgBitmap[i]; // get number of status bytes needed mBcnt = ((maxp + 1) / 8) + ((((maxp + 1) % 8) > 0) ? 1 : 0); // get number of pages to get that many bytes l = (mBcnt / 8) + ((mBcnt % 8) > 0 ? 1 : 0); // loop through the number of write protect bitmap pages for (i = 0; i < l; i++) { // read stat mem page tpg = (uchar)i + 8; if (!Read_Page(portnum, &ROM[0], &pgbuf[0], STATUSMEM, &tpg, &flag)) return FALSE; if (flag == 8) { // copy bitmap read for (j = 0; j < 8; j++) if (Bcnt <= mBcnt) WPBM[Bcnt++] = ~pgbuf[j]; else break; } else return TRUE; } // loop through the number of redirection write protect bitmap pages Bcnt = 0; for (i = 0; i < l; i++) { // read stat mem page tpg = i + 4; if (!Read_Page(portnum, &ROM[0], &pgbuf[0], STATUSMEM, &tpg, &flag)) return FALSE; // check results if (flag == 8) { // copy bitmap read buffer for (j = 0; j < 8; j++) if (Bcnt <= mBcnt) RWPBM[Bcnt++] = ~pgbuf[j]; else break; } else return TRUE; } // read the redirection bytes (mBcnt number of pages in redirection) Bcnt = 0; for (i = 0; i < mBcnt; i++) { // read stat mem page tpg = i + 32; if (!Read_Page(portnum, &ROM[0], &pgbuf[0], STATUSMEM, &tpg, &flag)) return FALSE; // check results if (flag == 8) { // copy bitmap read shorto buffer for (j = 0; j < 8; j++) if (Bcnt <= maxp) RDB[Bcnt++] = ~pgbuf[j]; else break; // quit the loop because done } else return TRUE; } } else if (owIsWriteOnce(bank, portnum, &ROM[0])) { // read status memory page 0 tpg = 0; if (!Read_Page(portnum, &ROM[0], &pgbuf[0], STATUSMEM, &tpg, &flag)) return FALSE; // check result of status read if (flag == 8) { // extract the bitmap BM[0] = ~(pgbuf[0] >> 4) & 0x0F; // extract the write protect bitmap WPBM[0] = (~pgbuf[0]) & 0x0F; // extract the redirection write protect RWPBM[0] = 0; // there are non in the DS1982 // extract the redirection bytes for (i = 0; i < 4; i++) RDB[i] = ~(pgbuf[i + 1]); } else return TRUE; } else { OWERROR(OWERROR_NON_PROGRAM_PARTS); return FALSE; } // flush all of the cached pages InitDHash(); // loop through all of the pages and check too see how many pages need to // be re-directed. From that see if there is enough room on the device // to do all of the desired operations // Count the extra-pages for later xtra = maxp + 1; for (i = 0; i <= maxp; i++) { // if the page is aleady taken then subtract 2 pages if ((job.Page[i].wr & PJOB_MASK) == PJOB_WRITE) // (2.01) xtra -= (((BM[i / 8] >> (i % 8)) & 0x01) ? 2 : 1); else if ((BM[i / 8] >> (i % 8)) & 0x01) xtra--; } // check to see if the changes will really fit on the devices if (xtra < 0) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // loop to write each page that has an eprom job for (i = 0; i <= maxp; i++) { // check for an infinite loop (if redirection point to each other) if (inflp++ > 20480) { OWERROR(OWERROR_PROGRAM_WRITE_PROTECT); return FALSE; } // check the type of operation (1 = page write, 2 redirection) // page write if ((job.Page[i].wr & PJOB_MASK) == PJOB_WRITE || (job.Page[i].wr & PJOB_MASK) == PJOB_TERM) { // flag the says we are going to re-direct to this page redit = FALSE; pg = -1; // check to see if this page is already re-directed if (RDB[i] != 0x00) { // get the page and redirect pg = RDB[i]; redit = TRUE; // check to see if this could be real if ((job.Page[pg].wr & PJOB_MASK) != PJOB_NONE) { OWERROR(OWERROR_PROGRAM_WRITE_PROTECT); return FALSE; } } // not re-directed else { // if write protected set or bitmap says already used then write // redirection byte and change the Program job to an empty page // only redirect this is a JOB_WRITE job if (((WPBM[i / 8] >> (i % 8)) & 0x01) || (((BM[i / 8] >> (i % 8)) & 0x01) && ((job.Page[i].wr & PJOB_MASK) == PJOB_WRITE))) { // check if the write-protect redirection byte is set if ((RWPBM[i / 8] >> (i % 8)) & 0x01) { OWERROR(OWERROR_PROGRAM_WRITE_PROTECT); return FALSE; } // able to be re-directed so do it else redit = TRUE; } // ok so write the page else { // construct the page to write for (j = 0; j <= job.Page[i].len; j++) pgbuf[j] = job.Page[i].data[j]; // set this page as having an attempt made to programming job.Page[getLastPage(portnum, SNum)].wr |= PJOB_START; bank = getBank(portnum, SNum, (PAGE_TYPE)i, REGMEM); page = getPage(portnum, SNum, (PAGE_TYPE)i, REGMEM); if (!owWritePagePacket(bank, portnum, SNum, page, &pgbuf[0], job.Page[i].len)) return FALSE; // check to see if the bitmap is not set if (!(BM[i / 8] & (0x01 << (i % 8)))) { // set the bitmap bit for this page // EPROM1/EPROM3 exception if ((ROM[0] == 0x0B) || (ROM[0] == 0x0F)) { // set to 8 for status memory pages and reserved pages bmpg = 8; if (!owRead(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, (i / 8), FALSE, buff, 1)) return FALSE; tmpBM[i / 8] = buff[0]; tmpBM[i / 8] &= ~(0x01 << i % 8); if (!owWrite(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, (i / 8), &tmpBM[i / 8], 1)) return FALSE; // if(owProgramByte(portnum,(~(0x01 << (i%8))),(0x40+(i/8)),0x55,1,TRUE) == -1) // return FALSE; } else { // set to 0 for status memory pages bmpg = 0; if (!owRead(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, 0, FALSE, buff, 1)) return FALSE; tmpBM[i / 8] = buff[0]; tmpBM[i / 8] &= ~(0x01 << (i + 4)); if (!owWrite(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, 0, &tmpBM[i / 8], 1)) return FALSE; // if(owProgramByte(portnum,(~(0x01 << (i+4))),0,0x55,0,TRUE) == -1) // return FALSE; } // update the bitmap if (!BitMapChange(portnum, SNum, (uchar)i, 1, &BM[0])) return FALSE; // clear this Program job job.Page[i].wr = PJOB_NONE; } } } // check to see if need to re-direct the page if (redit == TRUE) { // find an empty page in the Program job and bitmap if (pg == -1) { for (j = 1; j <= maxp; j++) { // loop for a spot that is free in the bitmap, has not // Program job on it, can be redirected, and is not write // protected. if (!((BM[j / 8] >> (j % 8)) & 0x01) && ((job.Page[j].wr & PJOB_MASK) == PJOB_NONE) && (RDB[j] == 0x00) && !((WPBM[j / 8] >> (j % 8)) & 0x01) && !((RWPBM[j / 8] >> (j % 8)) & 0x01)) { pg = j; break; } } // check to see if one was found, if not then we are out of space if (pg == -1) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } } // change the Program job to reflect the change job.Page[pg].wr = PJOB_WRITE; job.Page[pg].len = job.Page[i].len; // copy the data to the new job location for (j = 0; j < job.Page[i].len; j++) job.Page[pg].data[j] = job.Page[i].data[j]; // change the old job page to a redirect job job.Page[i].data[0] = (uchar)pg; // redirection page job.Page[i].wr = PJOB_REDIR; // write redireciton job // optionally set back the loop if the new page is before // the current page i--; if (pg < i) i = pg - 1; // loop back continue; } } // redirection write else if ((job.Page[i].wr & PJOB_MASK) == PJOB_REDIR) { // get the re-direction byte from the page data pg = job.Page[i].data[0]; // check for redirection write protect with incorrect rdb // or not possible write if ((((RWPBM[i / 8] >> (i % 8)) & 0x01) && (RDB[i] != pg)) || ((RDB[i] | pg) ^ pg)) { OWERROR(OWERROR_PROGRAM_WRITE_PROTECT); return FALSE; } // write the redirection byte and set the bitmap // EPROM1/EPROM3 exception if ((ROM[0] == 0x0B) || (ROM[0] == 0x0F)) { // set to 8 for status memory pages and reserved pages for bitmap bmpg = 8; // set to for redirection pages rdpg = 32; if (!owRead(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, (i / 8), FALSE, buff, 1)) return FALSE; tmpBM[i / 8] = buff[0]; tmpBM[i / 8] &= ~(0x01 << i % 8); if ((!redirectPage(getBank(portnum, SNum, rdpg, STATUSMEM), portnum, SNum, i, pg)) || (!owWrite(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, (i / 8), &tmpBM[i / 8], 1))) return FALSE; // if((owProgramByte(portnum,(~pg),(0x100+i),0x55,1,TRUE) == -1) // ||(owProgramByte(portnum,(~(0x01 << (i%8))),(0x40+(i/8)),0x55,1,TRUE) == -1)) // return FALSE; } else { // set to 0 for status memory pages bmpg = 0; if (!owRead(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, 0, FALSE, buff, 1)) return FALSE; tmpBM[i / 8] = buff[0]; tmpBM[i / 8] &= ~(0x01 << (i + 4)); tmpBM[i / 8] &= (~pg); if ((!redirectPage(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, i, pg)) || (!owWrite(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, 0, &tmpBM[i / 8], 1))) return FALSE; // if((owProgramByte(portnum,(~pg),(1+i),0x55,0,TRUE) == -1) // ||(owProgramByte(portnum,(~(0x01 << (i+4))),0,0x55,0,TRUE) == -1)) // return FALSE; } if (!BitMapChange(portnum, SNum, (uchar)i, 1, &BM[0])) return FALSE; // clear this Program job job.Page[i].wr = PJOB_NONE; } // overwrite add file page else if ((job.Page[i].wr & PJOB_MASK) == PJOB_ADD) { for (j = 1; j <= 29; j++) { // check to see if this byte needs to be programmed if (job.Page[i].bm[j / 8] & (0x01 << (j % 8))) { // write the byte if ((ROM[0] == 0x0B) || (ROM[0] == 0x0F)) { if (owProgramByte(portnum, job.Page[i].data[j - 1], ((i << 5) + j), 0x0F, 1, TRUE) == -1) return FALSE; } else { if (owProgramByte(portnum, job.Page[i].data[j - 1], ((i << 5) + j), 0x0F, 0, TRUE) == -1) return FALSE; } } } // check to see if the bitmap is not set if (!(BM[i / 8] & (0x01 << (i % 8)))) { // set the bitmap bit for this page // EPROM1/EPROM3 exception if ((ROM[0] == 0x0B) || (ROM[0] == 0x0F)) { // set to 8 for status memory pages and reserved pages bmpg = 8; if (!owRead(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, (i / 8), FALSE, buff, 1)) return FALSE; tmpBM[i / 8] = buff[0]; tmpBM[i / 8] &= ~(0x01 << i % 8); if (!owWrite(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, (i / 8), &tmpBM[i / 8], 1)) return FALSE; // if(owProgramByte(portnum,(~(0x01 << (i%8))),(0x40+(i/8)),0x55,1,TRUE) == -1) // return FALSE; } else { // set to 0 for status memory pages bmpg = 0; if (!owRead(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, 0, FALSE, buff, 1)) return FALSE; tmpBM[i / 8] = buff[0]; tmpBM[i / 8] &= ~(0x01 << (i + 4)); if (!owWrite(getBank(portnum, SNum, bmpg, STATUSMEM), portnum, SNum, 0, &tmpBM[i / 8], 1)) return FALSE; // if(owProgramByte(portnum,(~(0x01 << (i+4))),0,0x55,0,TRUE) == -1) // return FALSE; } if (!BitMapChange(portnum, SNum, (uchar)i, 1, &BM[0])) return FALSE; } // clear this Program job job.Page[i].wr = PJOB_NONE; } } // turn off the Program job job_started = FALSE; // finished return TRUE; } //-------------------------------------------------------------------------- // Indicates if a job has already been initialized and waiting to be // written. // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // // return: TRUE : job started // FALSE : no jobs // SMALLINT isJob(int portnum, uchar *SNum) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { return FALSE; } return job_started; } //------------------------------------------------------------------------- // Indicates weather a page needs to be written // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // pg the page that is checked to see if it needs to // be written. // // return: TRUE: page needs to be written // FALSE: doesn't need to be written // SMALLINT isJobWritten(int portnum, uchar *SNum, PAGE_TYPE pg) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } return job.Page[pg].wr; } //------------------------------------------------------------------------- // Sets the status for the job on that page // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // pg the page that is checked to see if it needs to // be written. // status the status that the page is being set to. // // return: TRUE: page needs to be written // FALSE: doesn't need to be written // SMALLINT setJobWritten(int portnum, uchar *SNum, PAGE_TYPE pg, SMALLINT status) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } job.Page[pg].wr = status; return TRUE; } //------------------------------------------------------------------------- // The purpose is to get the original bitmap. // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // BM the bitmap to set to the original bitmap. // // return: TRUE: page needs to be written // FALSE: doesn't need to be written // SMALLINT getOrigBM(int portnum, uchar *SNum, uchar *BM) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } for (i = 0; i < 32; i++) BM[i] = job.OrgBitmap[i]; return TRUE; } //------------------------------------------------------------------------- // Gets the page data of the job // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // page the page that the data is gotten from. // buff the buffer to store the data on that page // len the len of the data for that page // // return: TRUE: page needs to be written // FALSE: doesn't need to be written // SMALLINT getJobData(int portnum, uchar *SNum, PAGE_TYPE page, uchar *buff, int *len) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } if (job.Page[page].wr != PJOB_NONE) { for (i = 0; i < job.Page[page].len; i++) buff[i] = job.Page[page].data[i]; *len = job.Page[page].len; } else { return FALSE; } return TRUE; } //------------------------------------------------------------------------- // Sets the page data for that page in the job // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // pg the page that the data is set on. // buff the buffer of the data to be programmed // len the len of the data for that page // // return: TRUE: page needs to be written // FALSE: doesn't need to be written // SMALLINT setJobData(int portnum, uchar *SNum, PAGE_TYPE pg, uchar *buff, int len) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } for (i = 0; i < len; i++) job.Page[pg].data[i] = buff[i]; job.Page[pg].len = len; if (len > 0) { job.Page[pg].wr = PJOB_WRITE; } return TRUE; } //------------------------------------------------------------------------- // Sets a certain job for programming. // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // value the value to set in the bitmap. // spot the spot to set the bitmap. // // return: TRUE: page needs to be written // FALSE: doesn't need to be written // SMALLINT setProgramJob(int portnum, uchar *SNum, uchar value, int spot) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } job.EBitmap[spot] = value; return TRUE; } //------------------------------------------------------------------------- // Gets a certain number of bitmap job programming starting from the first // value in the array. // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // BM the array of values for the bitmap. // spots the number of spots copied. // // return: TRUE: page needs to be written // FALSE: doesn't need to be written // SMALLINT getProgramJob(int portnum, uchar *SNum, uchar *BM, int spots) { int i; for (i = 0; i < 8; i++) if (SNum[i] != job.ERom[i]) { OWERROR(OWERROR_NONMATCHING_SNUM); return FALSE; } for (i = 0; i < spots; i++) BM[i] = job.EBitmap[i]; return TRUE; } //-------------------------------------------------------------------------- // Write a byte into the Job space directly // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // pg the page to write the byte // spot the spot on the page to write the byte // wbyte the byte that is to be written // // return TRUE if the write was successful. // SMALLINT WriteJobByte(int portnum, uchar *SNum, PAGE_TYPE pg, short spot, uchar wbyte, short zeros) { uchar pgbuf[34]; short i; if (!isJob(portnum, SNum)) if (!owCreateProgramJob(portnum, SNum)) return FALSE; // check to see if this page is not in the job yet if ((job.Page[pg].wr & PJOB_MASK) == PJOB_NONE) { for (i = 0; i < 32; i++) pgbuf[i] = 0xFF; // read the page first if (!ExtendedRead_Page(portnum, SNum, &pgbuf[0], pg)) return FALSE; // copy the page contents into the job file for (i = 0; i < 29; i++) job.Page[pg].data[i] = pgbuf[i + 1]; // zero the bitmap for the page for (i = 0; i < 4; i++) job.Page[pg].bm[i] = 0; } // set the program job type (overwrite) if (((job.Page[pg].wr & PJOB_MASK) != PJOB_ADD) && ((job.Page[pg].wr & PJOB_MASK) != PJOB_TERM)) job.Page[pg].wr = PJOB_ADD; // set the bitmap to mark this byte as one to program job.Page[pg].bm[spot / 8] |= (0x01 << (spot % 8)); // depending on 'zeros' set the byte to write if (zeros) job.Page[pg].data[spot - 1] = (uchar) ~(~job.Page[pg].data[spot - 1] | ~wbyte); else job.Page[pg].data[spot - 1] = (uchar)wbyte; return TRUE; } //-------------------------------------------------------------------------- // Set the program job to terminate that page provided in the buffer. The // page data is provided to prevent it from being read twice since the calling // function will read the page to see if it is already terminated. // // portnum the port number of the port being used for the // 1-Wire Network // SNum the serial number for the part that the read is // to be done on. // pg the page to terminate // pgbuf the data to write to the terminated page // // return TRUE if the page was terminated // SMALLINT TerminatePage(int portnum, uchar *SNum, short pg, uchar *pgbuf) { short i; // page is not in job if ((job.Page[pg].wr & PJOB_MASK) == PJOB_NONE) { // copy the page contents into the job file for (i = 0; i < 29; i++) job.Page[pg].data[i] = pgbuf[i + 1]; // zero the bitmap for the page for (i = 0; i < 4; i++) job.Page[pg].bm[i] = 0; } // error file is already being written to else if (((job.Page[pg].wr & PJOB_MASK) != PJOB_ADD) && ((job.Page[pg].wr & PJOB_MASK) != PJOB_TERM)) return FALSE; // set the length to max since we do not know where the end really is in an add file job.Page[pg].len = 29; // set the job to a terminate job job.Page[pg].wr = PJOB_TERM; return TRUE; } w1retap/src/libusblinux300/owsesu.c000066400000000000000000000075241446446235200175260ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // owSesU.C - Acquire and release a Session on the 1-Wire Net. // // Version: 2.01 // // History: 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" #include "ds2480.h" //--------------------------------------------------------------------------- // Attempt to acquire a 1-Wire net using a com port and a DS2480 based // adapter. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'port_zstr' - zero terminated port name. For this platform // use format COMX where X is the port number. // // Returns: TRUE - success, COM port opened // // exportable functions defined in ownetu.c SMALLINT owAcquire_(int portnum, char *port_zstr) { // attempt to open the communications port if (OpenCOM(portnum, port_zstr) < 0) { OWERROR(OWERROR_OPENCOM_FAILED); return FALSE; } // detect DS2480 if (!DS2480Detect(portnum)) { CloseCOM(portnum); OWERROR(OWERROR_DS2480_NOT_DETECTED); return FALSE; } return TRUE; } //--------------------------------------------------------------------------- // Attempt to acquire a 1-Wire net using a com port and a DS2480 based // adapter. // // 'port_zstr' - zero terminated port name. For this platform // use format COMX where X is the port number. // // Returns: valid handle, or -1 if an error occurred // // exportable functions defined in ownetu.c // int owAcquireEx_(char *port_zstr) { int portnum; // attempt to open the communications port if ((portnum = OpenCOMEx(port_zstr)) < 0) { OWERROR(OWERROR_OPENCOM_FAILED); return -1; } // detect DS2480 if (!DS2480Detect(portnum)) { CloseCOM(portnum); OWERROR(OWERROR_DS2480_NOT_DETECTED); return -1; } return portnum; } //--------------------------------------------------------------------------- // Release the previously acquired a 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void owRelease_(int portnum) { CloseCOM(portnum); } void owShowVersion_(void) {} w1retap/src/libusblinux300/owtrnu.c000066400000000000000000000447531446446235200175440ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // owTranU.C - Transport functions for 1-Wire Net // using the DS2480B (U) serial interface chip. // // Version: 2.01 // // History: 1.02 -> 1.03 Removed caps in #includes for Linux capatibility // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added support for owError library // 2.01 -> 2.10 Added SMALLINT for small processors and error // handling plus the raw memory utilities. // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" #include "ds2480.h" // external defined in ds2480ut.c extern SMALLINT UBaud[MAX_PORTNUM]; extern SMALLINT UMode[MAX_PORTNUM]; extern SMALLINT USpeed[MAX_PORTNUM]; extern uchar SerialNum[MAX_PORTNUM][8]; // local static functions static SMALLINT Write_Scratchpad(int, uchar *, int, SMALLINT); static SMALLINT Copy_Scratchpad(int, int, SMALLINT); //-------------------------------------------------------------------------- // The 'owBlock' transfers a block of data to and from the // 1-Wire Net with an optional reset at the begining of communication. // The result is returned in the same buffer. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - cause a owTouchReset to occure at the begining of // communication TRUE(1) or not FALSE(0) // 'tran_buf' - pointer to a block of unsigned // chars of length 'tran_len' that will be sent // to the 1-Wire Net // 'tran_len' - length in bytes to transfer // Supported devices: all // // Returns: TRUE (1) : The optional reset returned a valid // presence (do_reset == TRUE) or there // was no reset required. // FALSE (0): The reset did not return a valid prsence // (do_reset == TRUE). // // The maximum tran_length is (160) // SMALLINT owBlock_(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len) { uchar sendpacket[320]; uchar sendlen = 0, i; // check for a block too big if (tran_len > 160) { OWERROR(OWERROR_BLOCK_TOO_BIG); return FALSE; } // check if need to do a owTouchReset first if (do_reset) { if (!owTouchReset(portnum)) { OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // construct the packet to send to the DS2480 // check if correct mode if (UMode[portnum] != MODSEL_DATA) { UMode[portnum] = MODSEL_DATA; sendpacket[sendlen++] = MODE_DATA; } // add the bytes to send for (i = 0; i < tran_len; i++) { sendpacket[sendlen++] = tran_buf[i]; // check for duplication of data that looks like COMMAND mode if (tran_buf[i] == MODE_COMMAND) sendpacket[sendlen++] = tran_buf[i]; } // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum, sendlen, sendpacket)) { // read back the response if (ReadCOM(portnum, tran_len, tran_buf) == tran_len) return TRUE; else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return FALSE; } //-------------------------------------------------------------------------- // Read a Universal Data Packet from a standard NVRAM iButton // and return it in the provided buffer. The page that the // packet resides on is 'start_page'. Note that this function is limited // to single page packets. The buffer 'read_buf' must be at least // 29 bytes long. // // The Universal Data Packet always start on page boundaries but // can end anywhere. The length is the number of data bytes not // including the length byte and the CRC16 bytes. There is one // length byte. The CRC16 is first initialized to the starting // page number. This provides a check to verify the page that // was intended is being read. The CRC16 is then calculated over // the length and data bytes. The CRC16 is then inverted and stored // low byte first followed by the high byte. // // Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982, // DS1985, DS1986, DS2407, and DS1971. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_access' - flag to indicate if an 'owAccess' should be // peformed at the begining of the read. This may // be FALSE (0) if the previous call was to read the // previous page (start_page-1). // 'start_page' - page number to start the read from // 'read_buf' - pointer to a location to store the data read // // Returns: >=0 success, number of data bytes in the buffer // -1 failed to read a valid UDP // // SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf) { uchar i, length, sendlen = 0, head_len = 0; uchar sendpacket[50]; ushort lastcrc16; // check if access header is done // (only use if in sequention read with one access at begining) if (do_access) { // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // read memory command sendpacket[sendlen++] = 0xF0; // write the target address sendpacket[sendlen++] = ((start_page << 5) & 0xFF); sendpacket[sendlen++] = (start_page >> 3); // check for DS1982 exception (redirection byte) if (SerialNum[portnum][0] == 0x09) sendpacket[sendlen++] = 0xFF; // record the header length head_len = sendlen; } // read the entire page length byte for (i = 0; i < 32; i++) sendpacket[sendlen++] = 0xFF; // send/recieve the transfer buffer if (owBlock(portnum, do_access, sendpacket, sendlen)) { // seed crc with page number setcrc16(portnum, (ushort)start_page); // attempt to read UDP from sendpacket length = sendpacket[head_len]; docrc16(portnum, (ushort)length); // verify length is not too large if (length <= 29) { // loop to read packet including CRC for (i = 0; i < length; i++) { read_buf[i] = sendpacket[i + 1 + head_len]; docrc16(portnum, read_buf[i]); } // read and compute the CRC16 docrc16(portnum, sendpacket[i + 1 + head_len]); lastcrc16 = docrc16(portnum, sendpacket[i + 2 + head_len]); // verify the CRC16 is correct if (lastcrc16 == 0xB001) return length; // return number of byte in record else OWERROR(OWERROR_CRC_FAILED); } else OWERROR(OWERROR_INCORRECT_CRC_LENGTH); } else OWERROR(OWERROR_BLOCK_FAILED); // failed block or incorrect CRC return -1; } //-------------------------------------------------------------------------- // Write a Universal Data Packet onto a standard NVRAM 1-Wire device // on page 'start_page'. This function is limited to UDPs that // fit on one page. The data to write is provided as a buffer // 'write_buf' with a length 'write_len'. // // The Universal Data Packet always start on page boundaries but // can end anywhere. The length is the number of data bytes not // including the length byte and the CRC16 bytes. There is one // length byte. The CRC16 is first initialized to the starting // page number. This provides a check to verify the page that // was intended is being read. The CRC16 is then calculated over // the length and data bytes. The CRC16 is then inverted and stored // low byte first followed by the high byte. // // Supported devices: is_eprom=0 // DS1992, DS1993, DS1994, DS1995, DS1996 // is_eprom=1, crc_type=0(CRC8) // DS1982 // is_eprom=1, crc_type=1(CRC16) // DS1985, DS1986, DS2407 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'start_page' - page number to write packet to // 'write_buf' - pointer to buffer containing data to write // 'write_len' - number of data byte in write_buf // 'is_eprom' - flag set if device is an EPROM (1 EPROM, 0 NVRAM) // 'crc_type' - if is_eprom=1 then indicates CRC type // (0 CRC8, 1 CRC16) // // Returns: TRUE(1) success, packet written // FALSE(0) failure to write, contact lost or device locked // SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf, SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type) { uchar construct_buffer[32]; uchar i, buffer_cnt = 0, start_address, do_access; ushort lastcrc16 = 0; // check to see if data too long to fit on device if (write_len > 29) return FALSE; // seed crc with page number setcrc16(portnum, (ushort)start_page); // set length byte construct_buffer[buffer_cnt++] = (uchar)(write_len); docrc16(portnum, (ushort)write_len); // fill in the data to write for (i = 0; i < write_len; i++) { lastcrc16 = docrc16(portnum, write_buf[i]); construct_buffer[buffer_cnt++] = write_buf[i]; } // add the crc construct_buffer[buffer_cnt++] = (uchar)(~(lastcrc16 & 0xFF)); construct_buffer[buffer_cnt++] = (uchar)(~((lastcrc16 & 0xFF00) >> 8)); // check if not EPROM if (!is_eprom) { // write the page if (!Write_Scratchpad(portnum, construct_buffer, start_page, buffer_cnt)) { OWERROR(OWERROR_WRITE_SCRATCHPAD_FAILED); return FALSE; } // copy the scratchpad if (!Copy_Scratchpad(portnum, start_page, buffer_cnt)) { OWERROR(OWERROR_COPY_SCRATCHPAD_FAILED); return FALSE; } // copy scratch pad was good then success return TRUE; } // is EPROM else { // calculate the start address start_address = ((start_page >> 3) << 8) | ((start_page << 5) & 0xFF); do_access = TRUE; // loop to program each byte for (i = 0; i < buffer_cnt; i++) { if (owProgramByte(portnum, construct_buffer[i], start_address + i, 0x0F, crc_type, do_access) != construct_buffer[i]) { OWERROR(OWERROR_PROGRAM_BYTE_FAILED); return FALSE; } do_access = FALSE; } return TRUE; } } //-------------------------------------------------------------------------- // Write a byte to an EPROM 1-Wire device. // // Supported devices: crc_type=0(CRC8) // DS1982 // crc_type=1(CRC16) // DS1985, DS1986, DS2407 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'write_byte' - byte to program // 'addr' - address of byte to program // 'write_cmd' - command used to write (0x0F reg mem, 0x55 status) // 'crc_type' - CRC used (0 CRC8, 1 CRC16) // 'do_access' - Flag to access device for each byte // (0 skip access, 1 do the access) // WARNING, only use do_access=0 if programing the NEXT // byte immediatly after the previous byte. // // Returns: >=0 success, this is the resulting byte from the program // effort // -1 error, device not connected or program pulse voltage // not available // SMALLINT owProgramByte_(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access) { ushort lastcrc16; uchar lastcrc8; // optionally access the device if (do_access) { if (!owAccess(portnum)) { OWERROR(OWERROR_ACCESS_FAILED); return -1; } // send the write command if (!owWriteByte(portnum, write_cmd)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // send the address if (!owWriteByte(portnum, addr & 0xFF) || !owWriteByte(portnum, addr >> 8)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } } // send the data to write if (!owWriteByte(portnum, write_byte)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // read the CRC if (crc_type == 0) { // calculate CRC8 if (do_access) { setcrc8(portnum, 0); docrc8(portnum, (uchar)write_cmd); docrc8(portnum, (uchar)(addr & 0xFF)); docrc8(portnum, (uchar)(addr >> 8)); } else setcrc8(portnum, (uchar)(addr & 0xFF)); docrc8(portnum, (uchar)write_byte); // read and calculate the read crc lastcrc8 = docrc8(portnum, (uchar)owReadByte(portnum)); // crc should now be 0x00 if (lastcrc8 != 0) { OWERROR(OWERROR_CRC_FAILED); return -1; } } else { // CRC16 if (do_access) { setcrc16(portnum, 0); docrc16(portnum, (ushort)write_cmd); docrc16(portnum, (ushort)(addr & 0xFF)); docrc16(portnum, (ushort)(addr >> 8)); } else setcrc16(portnum, (ushort)addr); docrc16(portnum, (ushort)write_byte); // read and calculate the read crc docrc16(portnum, (ushort)owReadByte(portnum)); lastcrc16 = docrc16(portnum, (ushort)owReadByte(portnum)); // crc should now be 0xB001 if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return -1; } } // send the program pulse if (!owProgramPulse(portnum)) { OWERROR(OWERROR_PROGRAM_PULSE_FAILED); return -1; } // read back and return the resulting byte return owReadByte(portnum); } //-------------------------------------------------------------------------- // Write the scratchpad of a standard NVRam device such as the DS1992,3,4 // and verify its contents. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'write_buf' - pointer to buffer containing data to write // 'start_page' - page number to write packet to // 'write_len' - number of data byte in write_buf // // Returns: TRUE(1) success, the data was written and verified // FALSE(0) failure, the data could not be written // // SMALLINT Write_Scratchpad(int portnum, uchar *write_buf, int start_page, SMALLINT write_len) { uchar i, sendlen = 0; uchar sendpacket[50]; // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // write scratchpad command sendpacket[sendlen++] = 0x0F; // write the target address sendpacket[sendlen++] = ((start_page << 5) & 0xFF); sendpacket[sendlen++] = (start_page >> 3); // write packet bytes for (i = 0; i < write_len; i++) sendpacket[sendlen++] = write_buf[i]; // send/recieve the transfer buffer if (owBlock(portnum, TRUE, sendpacket, sendlen)) { // now attempt to read back to check sendlen = 0; // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // read scratchpad command sendpacket[sendlen++] = 0xAA; // read the target address, offset and data for (i = 0; i < (write_len + 3); i++) sendpacket[sendlen++] = 0xFF; // send/recieve the transfer buffer if (owBlock(portnum, TRUE, sendpacket, sendlen)) { // check address and offset of scratchpad read if ((sendpacket[10] != ((start_page << 5) & 0xFF)) || (sendpacket[11] != (start_page >> 3)) || (sendpacket[12] != (write_len - 1))) { OWERROR(OWERROR_READ_VERIFY_FAILED); return FALSE; } // verify each data byte for (i = 0; i < write_len; i++) if (sendpacket[i + 13] != write_buf[i]) { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } // must have verified return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_BLOCK_FAILED); // failed a block tranfer return FALSE; } //-------------------------------------------------------------------------- // Copy the contents of the scratchpad to its intended nv ram page. The // page and length of the data is needed to build the authorization bytes // to copy. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'start_page' - page number to write packet to // 'write_len' - number of data bytes that are being copied // // Returns: TRUE(1) success // FALSE(0) failure // SMALLINT Copy_Scratchpad(int portnum, int start_page, SMALLINT write_len) { uchar i, sendlen = 0; uchar sendpacket[50]; // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // copy scratchpad command sendpacket[sendlen++] = 0x55; // write the target address sendpacket[sendlen++] = ((start_page << 5) & 0xFF); sendpacket[sendlen++] = (start_page >> 3); sendpacket[sendlen++] = write_len - 1; // read copy result sendpacket[sendlen++] = 0xFF; // send/recieve the transfer buffer if (owBlock(portnum, TRUE, sendpacket, sendlen)) { // check address and offset of scratchpad read if ((sendpacket[10] != ((start_page << 5) & 0xFF)) || (sendpacket[11] != (start_page >> 3)) || (sendpacket[12] != (write_len - 1)) || (sendpacket[13] & 0xF0)) { OWERROR(OWERROR_READ_VERIFY_FAILED); return FALSE; } else return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); // failed a block tranfer return FALSE; } w1retap/src/libusblinux300/pressure.c000066400000000000000000000302521446446235200200430ustar00rootroot00000000000000/* * pressure.c -- TAI8570 interface for w1retap * (c) 2005 Jonathan Hudson * * Substansially derived from the tai8570.c file in the archive * tai8570sjm102_300.zip archive available from * http://oww.sourceforge.net/download/tai8570sjm102_300.zip via * http://www.aagelectronica.com/aag/ * tai8570.c * * tai8570.c contains the following notice: * ------------------------------------------------- * tai8570.c * Version 1.02 * * Simon Melhuish * http://melhuish.info/simon/ * http://oww.sourceforge.net/ * * Derived from source by AAG * ------------------------------------------------- * * Other parts derived from the Dallas PD kit, so let's assume their * PD licence. * * Jonathan Hudson removed unused code, reformatted to his favourite * layout and added API entries suitable for w1retap. * */ #include #include #include #include #include "ownet.h" #include "swt12.h" #include "owfile.h" /** * * @author Aitor */ #define SEC_READW4 "111011010000" #define SEC_READW2 "111010110000" #define SEC_READW1 "111010101000" #define SEC_READW3 "111011001000" #define SEC_READD1 "11110100000" #define SEC_READD2 "11110010000" #define SEC_RESET "101010101010101000000" typedef unsigned char byte; typedef int bool; #define false 0 #define true 1 static u_char SwitchSN[2][8]; static int reader = -1, writer; static char SW1[20], SW2[20], SW3[20], SW4[20]; static byte CFG_READ = (byte)0xEC; // '11101100' Configuración de lectura para DS2407 static byte CFG_WRITE = (byte)0x8C; // '10001100' Configuración de Escritura para DS2407 static byte CFG_READPULSE = (byte)0xC8; // '11001000' Configuración de lectura de Pulso de conversion para DS2407 static int C1 = 0, C2 = 0, C3 = 0, C4 = 0, C5 = 0, C6 = 0; static int D1 = 0, D2 = 0; static void SendPressureBit(int portnum, bool i); static bool CheckConversion(int portnum); //---------------------------------------------------------------------- // SUBROUTINE - WriteSwitch12 - Adapted from SetSwitch12 Dallas code // // 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 // 'st' - Config byte to write // // Returns: TRUE(1) State of DS2406 set and verified // FALSE(0) could not set the DS2406, perhaps device is not // in contact // int WriteSwitch12(int portnum, uchar *SerialNum, ushort st) { int rt = FALSE; uchar send_block[30]; int send_cnt = 0; 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; docrc16(portnum, 0x55); // address of switch state send_block[send_cnt++] = 0x07; docrc16(portnum, 0x07); send_block[send_cnt++] = 0x00; docrc16(portnum, 0x00); send_block[send_cnt++] = (uchar)st; 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 docrc16(portnum, send_block[send_cnt - 2]); // verify crc16 is correct if (docrc16(portnum, send_block[send_cnt - 1]) == 0xB001) rt = TRUE; } } // return the result flag rt return rt; } // Open (i.e. o/p goes high) the channel A switch static int OpenA(int portnum, uchar *SerialNum) { byte I = 0XFF, res = 0; int Ind = 5; do { owSerialNum(portnum, SerialNum, FALSE); I = ReadSwitch12(portnum, false); WriteSwitch12(portnum, SerialNum, I | 0X20); I = ReadSwitch12(portnum, false); Ind--; res = (I & 0XDF); if (res != 0) return true; } while (Ind > 0); return (Ind > 0); } // Open (i.e. o/p goes high) the channel B switch static int OpenB(int portnum, uchar *SerialNum) { byte I = 0XFF, res = 0; int Ind = 5; do { owSerialNum(portnum, SerialNum, FALSE); I = ReadSwitch12(portnum, false); WriteSwitch12(portnum, SerialNum, I | 0X40); I = ReadSwitch12(portnum, false); Ind--; res = (I & 0XBF); if (res != 0) return true; } while (Ind > 0); return (Ind > 0); } // Open B (data in/out) on both reader and writer static bool OpenPIOS_B(int portnum) { if (!OpenB(portnum, SwitchSN[reader])) return FALSE; if (!OpenB(portnum, SwitchSN[writer])) return FALSE; return TRUE; } // Open A (clock) on both reader and writer static bool OpenPIOS_A(int portnum) { if (!OpenA(portnum, SwitchSN[reader])) return FALSE; if (!OpenA(portnum, SwitchSN[writer])) return FALSE; return TRUE; } // Send a Channel Access command sequence static int ChannelAccess(int portnum, uchar *SerialNum, byte AChanC1, byte AChanC2, byte *ACInfo) { owSerialNum(portnum, SerialNum, FALSE); if (!owAccess(portnum)) { fprintf(stderr, "owAccess failed in ChannelAccess\n"); return false; } owTouchByte(portnum, 0XF5); owTouchByte(portnum, AChanC1); owTouchByte(portnum, AChanC2); *ACInfo = owTouchByte(portnum, 0XFF); return true; } //--------------------------------------------------------------------------- static int ConfigWrite(int portnum) { byte ACInfo = 0; return ChannelAccess(portnum, SwitchSN[writer], CFG_WRITE, 0xFF, &ACInfo); } //--------------------------------------------------------------------------- static int ConfigRead(int portnum) { byte ACInfo = 0; return ChannelAccess(portnum, SwitchSN[reader], CFG_READ, 0xFF, &ACInfo); } //--------------------------------------------------------------------------- static int ConfigReadPulse(int portnum) { byte ACInfo = 0; return ChannelAccess(portnum, SwitchSN[reader], CFG_READPULSE, 0xFF, &ACInfo); } static bool WritePressureSensor(int portnum, char *Cmd) { bool rslt = false; int lng, i; lng = strlen(Cmd); if (ConfigWrite(portnum)) { for (i = 0; i < lng; i++) { if (Cmd[i] == '0') SendPressureBit(portnum, false); else SendPressureBit(portnum, true); } SendPressureBit(portnum, false); rslt = true; } return rslt; } static void SendPressureBit(int portnum, bool i) { if (i) owTouchByte(portnum, 0x0e); else owTouchByte(portnum, 0x04); } /******************************************************/ static bool ReadPressureBit(int portnum) { int res = 0; res = owReadByte(portnum); res &= 0x80; owWriteByte(portnum, 0xfa); return (res != 0); } /******************************************************/ static char *ReadPressureSensor(int portnum, byte CountBit) { static char StringBuffer[64]; int i; strcpy(StringBuffer, ""); if (ConfigRead(portnum)) { for (i = 0; i < CountBit; i++) { if (ReadPressureBit(portnum)) strcat(StringBuffer, "1"); else strcat(StringBuffer, "0"); } } else { fprintf(stderr, "ConfigRead failed\n"); } return StringBuffer; } /******************************************************/ static bool PressureReset(int portnum) { bool rsl = false; if (!OpenPIOS_A(portnum)) return false; // Inspired by AAG C++ version if (!ConfigWrite(portnum)) return false; // Inspired by AAG C++ version rsl = WritePressureSensor(portnum, SEC_RESET); return rsl; } /******************************************************/ static char *ReadSensorValueStr(int portnum, char *cmd, char *Lect) { Lect[0] = '\0'; if (!OpenPIOS_A(portnum)) return FALSE; if (WritePressureSensor(portnum, cmd)) { if (!OpenPIOS_A(portnum)) return FALSE; strcpy(Lect, ReadPressureSensor(portnum, (byte)16)); OpenPIOS_B(portnum); } else { fprintf(stderr, "WritePressureSensor failed\n"); } return Lect; } /******************************************************/ static int ReadSensorValue(int portnum, char *Comm) { char Lect[30]; int Res = 0; int i = 0; Lect[0] = 0; if (!PressureReset(portnum)) return 0; if (!WritePressureSensor(portnum, Comm)) return 0; if (!CheckConversion(portnum)) return 0; if (!OpenPIOS_A(portnum)) return 0; strcpy(Lect, ReadPressureSensor(portnum, 16)); if (!OpenPIOS_B(portnum)) return 0; if (strlen(Lect) != 16) return 0; for (i = 0; i < 16; i++) { Res = (Res << 1); if (Lect[i] == '1') ++Res; } return Res; } static bool CheckConversion(int portnum) { int i; if (!ConfigReadPulse(portnum)) { fprintf(stderr, "ConfigReadPulse failed in CheckConversion\n"); return false; } for (i = 0; i < 100; i++) if (!owTouchBit(portnum, 1)) break; return (i < 100); } /******************************************************/ static bool ReadSensor_Calibration(int portnum) { int uno = 1, im = 0, Count = 0; int i = 0; int Lect = false; char SW11[20] = "0", SW22[20] = "0", SW33[20] = "0", SW44[20] = "0"; do { if (!PressureReset(portnum)) return false; ReadSensorValueStr(portnum, SEC_READW1, SW1); ReadSensorValueStr(portnum, SEC_READW2, SW2); ReadSensorValueStr(portnum, SEC_READW3, SW3); ReadSensorValueStr(portnum, SEC_READW4, SW4); if (strlen(SW1) != 16) return false; if (strlen(SW2) != 16) return false; if (strlen(SW3) != 16) return false; if (strlen(SW4) != 16) return false; Lect = ((strcmp(SW1, SW11) == 0) && (strcmp(SW2, SW22) == 0)) && ((strcmp(SW3, SW33) == 0) && (strcmp(SW4, SW44) == 0)); strcpy(SW11, SW1); strcpy(SW22, SW2); strcpy(SW33, SW3); strcpy(SW44, SW4); Count++; } while ((Count < 5) && (Lect == false)); C1 = 0; C2 = 0; C3 = 0; C4 = 0; C5 = 0; C6 = 0; for (i = 14; i >= 0; i--) { if (SW1[i] == '1') { C1 = C1 | (uno << (14 - i)); } } for (i = 9; i >= 0; i--) { if (SW2[i] == '1') C5 = C5 | (uno << (9 - i)); } if (SW1[15] == '1') C5 = C5 | (uno << (10)); for (i = 15; i >= 10; i--) { if (SW2[i] == '1') C6 = C6 | (uno << (15 - i)); } for (i = 9; i >= 0; i--) { if (SW3[i] == '1') C4 = C4 | (uno << (9 - i)); } for (i = 9; i >= 0; i--) { if (SW4[i] == '1') C3 = C3 | (uno << (9 - i)); } im = 0; for (i = 15; i >= 10; i--) { if (SW4[i] == '1') C2 = C2 | (uno << (im)); im++; } for (i = 15; i >= 10; i--) { if (SW3[i] == '1') C2 = C2 | (uno << (im)); im++; } return true; } /******************************************************/ int ReadPressureValues(int portnum, float *temp, float *pressure) { double DT, OFF, SENSE, X; D1 = ReadSensorValue(portnum, SEC_READD1); D2 = ReadSensorValue(portnum, SEC_READD2); DT = D2 - ((8 * C5) + 20224.0); OFF = C2 * 4 + (((C4 - 512) * DT) / 4096); SENSE = 24576 + C1 + ((C3 * DT) / 1024); X = ((SENSE * (D1 - 7168)) / 16384) - OFF; *pressure = 250.0 + X / 32; *temp = 20.0 + ((DT * (C6 + 50)) / 10240); return true; } static int find_press_roles(int portnum, u_char *serno) { int found = 0, fl_len; short hnd; FileEntry fe; uchar buf[100]; int j; for (j = 0; j < 2 && found == 0; j++) { reader = writer = -1; memcpy(SwitchSN[0], serno, sizeof(SwitchSN[0])); owSerialNum(portnum, SwitchSN[0], FALSE); memset(&fe, 0, sizeof(fe)); memcpy(fe.Name, "8570", 4); found = owOpenFile(portnum, SwitchSN[0], &fe, &hnd); if (found) { int info; owReadFile(portnum, SwitchSN[0], hnd, buf, 99, &fl_len); owSerialNum(portnum, SwitchSN[0], false); owCloseFile(portnum, SwitchSN[0], hnd); info = ReadSwitch12(portnum, false); if (info == -1) { fprintf(stderr, "Unable to read info byte\n"); found = 0; } else { if ((info & 0x80) == 0) { reader = 0; writer = 1; } else { reader = 1; writer = 0; } memcpy(SwitchSN[1], buf, sizeof(SwitchSN[1])); } } } return found; } int Init_Pressure(int portnum, u_char *serno) { int iscalib = false; if (find_press_roles(portnum, serno)) { if (ReadSensor_Calibration(portnum)) { iscalib = true; } } return iscalib; } w1retap/src/libusblinux300/pressure.h000066400000000000000000000002001446446235200200360ustar00rootroot00000000000000extern int Init_Pressure(int portnum, u_char *serno); extern int ReadPressureValues(int portnum, float *temp, float *pressure); w1retap/src/libusblinux300/ps02.c000066400000000000000000000314621446446235200167630ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ps02.c - contains functions for communication to the DS1991 // #include "ownet.h" #include "ps02.h" // Global of codes uchar pscodes[9][8]; /** * Sets up the block codes for the copy scratchpad command. * * @param codes a 2 dimensional array [9][8] to contain the * codes. */ void initBlockCodes() { pscodes[8][0] = 0x56; // ALL 64 bytes address 0x00 to 0x3F pscodes[8][1] = 0x56; pscodes[8][2] = 0x7F; pscodes[8][3] = 0x51; pscodes[8][4] = 0x57; pscodes[8][5] = 0x5D; pscodes[8][6] = 0x5A; pscodes[8][7] = 0x7F; pscodes[0][0] = 0x9A; // identifier (block 0) pscodes[0][1] = 0x9A; pscodes[0][2] = 0xB3; pscodes[0][3] = 0x9D; pscodes[0][4] = 0x64; pscodes[0][5] = 0x6E; pscodes[0][6] = 0x69; pscodes[0][7] = 0x4C; pscodes[1][0] = 0x9A; // password (block 1) pscodes[1][1] = 0x9A; pscodes[1][2] = 0x4C; pscodes[1][3] = 0x62; pscodes[1][4] = 0x9B; pscodes[1][5] = 0x91; pscodes[1][6] = 0x69; pscodes[1][7] = 0x4C; pscodes[2][0] = 0x9A; // address 0x10 to 0x17 (block 2) pscodes[2][1] = 0x65; pscodes[2][2] = 0xB3; pscodes[2][3] = 0x62; pscodes[2][4] = 0x9B; pscodes[2][5] = 0x6E; pscodes[2][6] = 0x96; pscodes[2][7] = 0x4C; pscodes[3][0] = 0x6A; // address 0x18 to 0x1F (block 3) pscodes[3][1] = 0x6A; pscodes[3][2] = 0x43; pscodes[3][3] = 0x6D; pscodes[3][4] = 0x6B; pscodes[3][5] = 0x61; pscodes[3][6] = 0x66; pscodes[3][7] = 0x43; pscodes[4][0] = 0x95; // address 0x20 to 0x27 (block 4) pscodes[4][1] = 0x95; pscodes[4][2] = 0xBC; pscodes[4][3] = 0x92; pscodes[4][4] = 0x94; pscodes[4][5] = 0x9E; pscodes[4][6] = 0x99; pscodes[4][7] = 0xBC; pscodes[5][0] = 0x65; // address 0x28 to 0x2F (block 5) pscodes[5][1] = 0x9A; pscodes[5][2] = 0x4C; pscodes[5][3] = 0x9D; pscodes[5][4] = 0x64; pscodes[5][5] = 0x91; pscodes[5][6] = 0x69; pscodes[5][7] = 0xB3; pscodes[6][0] = 0x65; // address 0x30 to 0x37 (block 6) pscodes[6][1] = 0x65; pscodes[6][2] = 0xB3; pscodes[6][3] = 0x9D; pscodes[6][4] = 0x64; pscodes[6][5] = 0x6E; pscodes[6][6] = 0x96; pscodes[6][7] = 0xB3; pscodes[7][0] = 0x65; // address 0x38 to 0x3F (block 7) pscodes[7][1] = 0x65; pscodes[7][2] = 0x4C; pscodes[7][3] = 0x62; pscodes[7][4] = 0x9B; pscodes[7][5] = 0x91; pscodes[7][6] = 0x96; pscodes[7][7] = 0xB3; } /** * Writes the data to the scratchpad from the given address. * * portnum the port number of the port being used for the * 1-Wire network. * addr address to begin writing. Must be between * 0x00 and 0x3F. * data data to write. * len the length of the data to write * * return: TRUE if the write worked * FALSE if there was an error in writing */ SMALLINT writeScratchpad(int portnum, int addr, uchar *data, int len) { int dataRoom, i; uchar buffer[96]; if (owAccess(portnum)) { // confirm that data will fit if (addr > 0x3F) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } dataRoom = 0x3F - addr + 1; if (dataRoom < len) { OWERROR(OWERROR_DATA_TOO_LONG); return FALSE; } buffer[0] = (uchar)WRITE_SCRATCHPAD_COMMAND; buffer[1] = (uchar)(addr | 0xC0); buffer[2] = (uchar)(~buffer[1]); for (i = 0; i < len; i++) buffer[i + 3] = data[i]; // send command block if ((len + 3) > 64) { if (!owBlock(portnum, FALSE, buffer, 64)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } else if (!owBlock(portnum, FALSE, &buffer[64], 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else if (!owBlock(portnum, FALSE, buffer, len + 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return TRUE; } /** * Reads the entire scratchpad. * * portnum the port number of the port being used for the * 1-Wire Network * data the data that was read from the scratchpad. * * return TRUE if the data was read without an error * */ SMALLINT readScratchpad(int portnum, uchar *data) { uchar buffer[96]; int i; if (owAccess(portnum)) { buffer[0] = READ_SCRATCHPAD_COMMAND; buffer[1] = 0xC0; // Starting address of scratchpad buffer[2] = 0x3F; for (i = 3; i < 67; i++) buffer[i] = 0xFF; // send command block if (!owBlock(portnum, FALSE, buffer, 64)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } else if (!owBlock(portnum, FALSE, &buffer[64], 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } for (i = 0; i < 64; i++) data[i] = buffer[i + 3]; } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return TRUE; } /** * Writes the data from the scratchpad to the specified block or * blocks. Note that the write will erase the data from the * scratchpad. * * portnum the port number of the port being used for the * 1-Wire Network. * key subkey being written * passwd password for the subkey being written * blockNum number of the block to be copied (see page 7 of the * DS1991 data sheet) block 0-7, or 8 to copy all 64 bytes. * * return TRUE if the copy scratchpad was successful. */ SMALLINT copyScratchpad(int portnum, int key, uchar *passwd, int blockNum) { uchar buffer[96]; int i; if (owAccess(portnum)) { // confirm that input is OK if ((key < 0) || (key > 2)) { OWERROR(OWERROR_KEY_OUT_OF_RANGE); return FALSE; } if ((blockNum < 0) || (blockNum > 8)) { OWERROR(OWERROR_BLOCK_ID_OUT_OF_RANGE); return FALSE; } buffer[0] = COPY_SCRATCHPAD_COMMAND; buffer[1] = (uchar)(key << 6); buffer[2] = (uchar)(~buffer[1]); // set up block selector code for (i = 0; i < 8; i++) buffer[i + 3] = pscodes[blockNum][i]; // set up password for (i = 0; i < 8; i++) buffer[i + 11] = passwd[i]; // send command block if (!owBlock(portnum, FALSE, buffer, 19)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return TRUE; } /** * Reads the subkey requested with the given key name and password. * Note that this method allows for reading from the subkey data * only which starts at address 0x10 within a key. It does not allow * reading from any earlier address within a key because the device * cannot be force to allow reading the password. This is why the * subkey number is or-ed with 0x10 in creating the address in bytes * 1 and 2 of the sendBlock. * * portnum the port number of the port being used for the * 1-Wire Network. * data buffer of length 64 into which to write the data * key number indicating the key to be read: 0, 1, or 2 * passwd password of destination subkey * * return: TRUE if reading the subkey was successful. */ SMALLINT readSubkey(int portnum, uchar *data, int key, uchar *passwd) { uchar buffer[96]; int i; if (owAccess(portnum)) { // confirm key within legal parameters if (key > 0x03) { OWERROR(OWERROR_KEY_OUT_OF_RANGE); return FALSE; } buffer[0] = READ_SUBKEY_COMMAND; buffer[1] = (uchar)((key << 6) | 0x10); buffer[2] = (uchar)(~buffer[1]); // prepare buffer to receive for (i = 3; i < 67; i++) buffer[i] = 0xFF; // insert password data for (i = 0; i < 8; i++) buffer[i + 11] = passwd[i]; // send command block if (!owBlock(portnum, FALSE, buffer, 64)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } else if (!owBlock(portnum, FALSE, &buffer[64], 3)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // create block to send back for (i = 0; i < 64; i++) data[i] = buffer[i + 3]; } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return TRUE; } /** * Writes a new identifier and password to the secure subkey iButton * * portnum the port number of the port being used for the * 1-Wire Network. * key number indicating the key to be read: 0, 1, or 2 * oldName identifier of the key used to confirm the correct * key's password to be changed. Must be exactly length 8. * newName identifier to be used for the key with the new * password. Must be exactly length 8. * newPasswd new password for destination subkey. Must be * exactly length 8. * * return TRUE if the write was successful */ SMALLINT writePassword(int portnum, int key, uchar *oldName, uchar *newName, uchar *newPasswd) { uchar buffer[96]; int i; if (owAccess(portnum)) { // confirm key names and passwd within legal parameters if (key > 0x03) { OWERROR(OWERROR_KEY_OUT_OF_RANGE); return FALSE; } buffer[0] = WRITE_PASSWORD_COMMAND; buffer[1] = (uchar)(key << 6); buffer[2] = (uchar)(~buffer[1]); // prepare buffer to receive 8 bytes of the identifier for (i = 3; i < 11; i++) buffer[i] = 0xFF; if (!owBlock(portnum, FALSE, buffer, 11)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // prepare same subkey identifier for confirmation for (i = 0; i < 8; i++) buffer[i] = buffer[i + 3]; // prepare new subkey identifier for (i = 0; i < 8; i++) buffer[i + 8] = newName[i]; // prepare new password for writing for (i = 0; i < 8; i++) buffer[i + 16] = newPasswd[i]; // send command block if (!owBlock(portnum, FALSE, buffer, 24)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return TRUE; } /** * Writes new data to the secure subkey * * portnum the port number of the port being used for the * 1-Wire Network. * key number indicating the key to be written: 0, 1, or 2 * addr address to start writing at ( 0x00 to 0x3F ) * passwd passwird for the subkey * data data to be written * len the length of the data to be written * * return TRUE if the write was successful */ SMALLINT writeSubkey(int portnum, int key, int addr, uchar *passwd, uchar *data, int len) { uchar buffer[96]; int i; if (owAccess(portnum)) { // confirm key names and passwd within legal parameters if (key > 0x03) { OWERROR(OWERROR_KEY_OUT_OF_RANGE); return FALSE; } if ((addr < 0x00) || (addr > 0x3F)) { OWERROR(OWERROR_WRITE_OUT_OF_RANGE); return FALSE; } buffer[0] = WRITE_SUBKEY_COMMAND; buffer[1] = (uchar)((key << 6) | addr); buffer[2] = (uchar)(~buffer[1]); // prepare buffer to receive 8 bytes of the identifier for (i = 3; i < 11; i++) buffer[i] = 0xFF; // prepare same subkey identifier for confirmation for (i = 0; i < 8; i++) buffer[i + 11] = passwd[i]; // prepare data to write for (i = 0; i < len; i++) buffer[i + 19] = data[i]; // send command block if (len + 19 > 64) { if (!owBlock(portnum, FALSE, &buffer[0], 64)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } else if (!owBlock(portnum, FALSE, &buffer[64], (len + 19) - 64)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } else { if (!owBlock(portnum, FALSE, buffer, len + 19)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } } } else { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } return TRUE; } w1retap/src/libusblinux300/ps02.h000066400000000000000000000047001446446235200167630ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ps02.c - contains functions for communication to the DS1991 // /** * DS1991 Write Scratchpad Command */ #define WRITE_SCRATCHPAD_COMMAND 0x96; /** * DS1991 Read Scratchpad Command */ #define READ_SCRATCHPAD_COMMAND 0x69; /** * DS1991 Copy Scratchpad Command */ #define COPY_SCRATCHPAD_COMMAND 0x3C; /** * DS1991 Write Password Command */ #define WRITE_PASSWORD_COMMAND 0x5A; /** * DS1991 Write SubKey Command */ #define WRITE_SUBKEY_COMMAND 0x99; /** * DS1991 Read SubKey Command */ #define READ_SUBKEY_COMMAND 0x66; // functions void initBlockCodes(void); SMALLINT writeScratchpad(int portnum, int addr, uchar *data, int len); SMALLINT readScratchpad(int portnum, uchar *data); SMALLINT copyScratchpad(int portnum, int key, uchar *passwd, int blockNum); SMALLINT readSubkey(int portnum, uchar *data, int key, uchar *passwd); SMALLINT writePassword(int portnum, int key, uchar *oldName, uchar *newName, uchar *newPasswd); SMALLINT writeSubkey(int portnum, int key, int addr, uchar *passwd, uchar *data, int len); w1retap/src/libusblinux300/ps_check.c000066400000000000000000000213021446446235200177460ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ps_check.c - main function for checking software authentication // application. // #include "ownet.h" #include "ps02.h" #include "findtype.h" // file where the hard code data is for authentication #define MAXDEVICES 4 // local functions void ComputeSHAVM(uchar *MT, int *hash); int NLF(int B, int C, int D, int n); SMALLINT CheckPS(int portnum, uchar *SNum, uchar *MT, int key, uchar *data); int getNumber(int min, int max); // constants used in SHA computation static const int KTN[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; int main(int argc, char **argv) { int i = 0, j; int portnum = 0; int length; int random; uchar data[64]; uchar MT[64]; uchar falsMT[64]; int test_time; int NumDevices = 0; uchar AllSN[MAXDEVICES][8]; puts("\nStarting Software Authentication checking 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 ((portnum = owAcquireEx(argv[1])) < 0) { printf("Failed to acquire port.\n"); exit(1); } printf("Enter the 8 byte secret you want to use for the data.\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = getData(&MT[0], 8, getNumber(0, 1)); if (length < 8) { for (i = length; i < 8; i++) MT[i] = 0x00; } printf("Enter the 8 byte ID you want to use for the data.\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = getData(&MT[8], 8, getNumber(0, 1)); if (length < 8) { for (i = length; i < 8; i++) MT[i + 8] = 0x00; } printf("\n"); test_time = msGettick() + 3000; for (;;) { NumDevices = FindDevices(portnum, AllSN, 0x02, MAXDEVICES); if (NumDevices <= 0) { printf("NO DEVICE, invalid. %d\n", NumDevices); } else { for (i = 0; i < NumDevices; i++) { if (test_time <= msGettick()) { PrintSerialNum(&AllSN[0][0]); do { random = (int)msGettick() % 3; } while ((random < 0) || (random > 3)); if (CheckPS(portnum, &AllSN[0][0], MT, random, data)) { printf(", valid.\n"); if ((data[16] + 17) > 33) { for (j = 17; j < 33; j++) printf("%02X ", data[j]); printf("\n"); } else { for (j = 17; j < (data[16] + 17); j++) printf("%02X ", data[j]); printf("\n"); } if ((data[16] + 17) > 49) { for (j = 33; j < 49; j++) printf("%02X ", data[j]); printf("\n"); for (j = 49; j < (data[16] + 17); j++) printf("%02X ", data[j]); printf("\n"); } else { for (j = 33; j < (data[16] + 17); j++) printf("%02X ", data[j]); printf("\n"); } printf("\n"); } else { printf(", invalid.\n"); OWERROR_DUMP(stdout); } test_time = msGettick() + 3000; } else { for (i = 0; i < 16; i++) falsMT[i] = (uchar)msGettick() % 256; random = (int)msGettick() % 3; random = CheckPS(portnum, &AllSN[0][0], falsMT, random, data); } } } } 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. // // '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; } } // calculation used for the SHA MAC 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); } SMALLINT CheckPS(int portnum, uchar *SNum, uchar *MT, int key, uchar *data) { int i, j; int temp; int hash[5]; uchar pass[8]; uchar ID[8]; uchar tempMT[64]; uchar psxor[4]; ushort crc; for (i = 0; i < 16; i++) tempMT[i] = MT[i]; tempMT[16] = 0x2D; for (i = 17; i < 62; i++) { tempMT[i] = (uchar)i; } setcrc16(portnum, (ushort)key); for (i = 16; i < 62; i++) crc = docrc16(portnum, tempMT[i]); tempMT[62] = (uchar)~crc & 0xFF; tempMT[63] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; ComputeSHAVM(tempMT, hash); temp = hash[0]; for (i = 0; i < 4; i++) { pass[i] = (uchar)temp; tempMT[i + 8] = pass[i]; temp >>= 8; } temp = hash[1]; for (i = 4; i < 8; i++) { pass[i] = (uchar)temp; tempMT[i + 8] = pass[i]; temp >>= 8; } temp = hash[2]; for (i = 0; i < 4; i++) { ID[i] = (uchar)temp; tempMT[i] = ID[i]; temp >>= 8; } temp = hash[3]; for (i = 4; i < 8; i++) { ID[i] = (uchar)temp; tempMT[i] = ID[i]; temp >>= 8; } temp = hash[4]; for (i = 0; i < 4; i++) { psxor[i] = (uchar)temp; temp >>= 8; } owSerialNum(portnum, SNum, FALSE); if (!readSubkey(portnum, data, key, pass)) { return FALSE; } for (i = 0; i < 4; i++) for (j = 0; j < 12; j++) { data[i * 12 + j + 16] = (~psxor[i] & data[i * 12 + j + 16]) | (psxor[i] & ~data[i * 12 + j + 16]); } setcrc16(portnum, (ushort)key); for (i = 0; i < (data[16] + 3); i++) crc = docrc16(portnum, data[i + 16]); if (crc == 0xB001) { return TRUE; } else { OWERROR(OWERROR_CRC_FAILED); 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/ps_init.c000066400000000000000000000224111446446235200176360ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // ps_init.c - main function for initializing software authentication // application. // #include "ownet.h" #include "ps02.h" #include "findtype.h" // file where the hard code data is for authentication #define MAXDEVICES 4 // local functions void ComputeSHAVM(uchar *MT, int *hash); int NLF(int B, int C, int D, int n); SMALLINT ConvertPS(int portnum, uchar *MT, int key, int len); int getNumber(int min, int max); // constants used in SHA computation static const int KTN[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; int main(int argc, char **argv) { int i = 0; int portnum = 0; int length; uchar MT[96]; 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 ((portnum = owAcquireEx(argv[1])) < 0) { printf("Failed to acquire port.\n"); exit(1); } printf("Enter the 8 byte secret you want to use for the data.\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = getData(&MT[0], 8, getNumber(0, 1)); if (length < 8) { for (i = length; i < 8; i++) MT[i] = 0x00; } printf("Enter the 8 byte ID you want to use for the data.\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = getData(&MT[8], 8, getNumber(0, 1)); if (length < 8) { for (i = length; i < 8; i++) MT[i + 8] = 0x00; } printf("Enter the 45 byte data you want to use.\n"); printf("Data Entry Mode\n"); printf("(0) Text (single line)\n"); printf("(1) Hex (XX XX XX XX ...)\n"); length = getData(&MT[16], 45, getNumber(0, 1)); if (length < 45) { for (i = length; i < 45; i++) MT[i + 16] = 0x00; } // initialize the block codes for the DS1991 initBlockCodes(); // for the first secret, id and data if (!ConvertPS(portnum, MT, 0, length)) OWERROR_DUMP(stderr); // for the second secret, id and data if (!ConvertPS(portnum, MT, 1, length)) OWERROR_DUMP(stderr); // for the third secret, id and data if (!ConvertPS(portnum, MT, 2, length)) OWERROR_DUMP(stderr); // 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. // // '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; } } // calculation used for the SHA MAC 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); } SMALLINT ConvertPS(int portnum, uchar *MT, int key, int len) { int i, j; int temp; int hash[5]; uchar secret[8]; uchar ID[8]; uchar psxor[4]; uchar oldName[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uchar data[64]; ushort crc = 0; int NumDevices; uchar AllSN[MAXDEVICES][8]; uchar tempMT[64]; uchar MTtwo[64]; for (i = 0; i < 64; i++) { tempMT[i] = MT[i]; MTtwo[i] = MT[i]; } MTtwo[16] = (uchar)len; for (i = 16; i < len + 16; i++) MTtwo[i + 1] = tempMT[i]; setcrc16(portnum, (ushort)key); for (i = 0; i < len + 1; i++) { crc = docrc16(portnum, MTtwo[i + 16]); } MTtwo[len + 17] = (uchar)~crc & 0xFF; MTtwo[len + 18] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; tempMT[16] = 0x2D; for (i = 17; i < 62; i++) { tempMT[i] = (uchar)i; } setcrc16(portnum, (ushort)key); for (i = 16; i < 62; i++) crc = docrc16(portnum, tempMT[i]); tempMT[62] = (uchar)~crc & 0xFF; tempMT[63] = (uchar)((~crc & 0xFFFF) >> 8) & 0xFF; ComputeSHAVM(tempMT, hash); temp = hash[0]; for (i = 0; i < 4; i++) { secret[i] = (uchar)temp; tempMT[i + 8] = secret[i]; temp >>= 8; } temp = hash[1]; for (i = 4; i < 8; i++) { secret[i] = (uchar)temp; tempMT[i + 8] = secret[i]; temp >>= 8; } temp = hash[2]; for (i = 0; i < 4; i++) { ID[i] = (uchar)temp; tempMT[i] = ID[i]; temp >>= 8; } temp = hash[3]; for (i = 4; i < 8; i++) { ID[i] = (uchar)temp; tempMT[i] = ID[i]; temp >>= 8; } temp = hash[4]; for (i = 0; i < 4; i++) { psxor[i] = (uchar)temp; for (j = 0; j < 12; j++) { tempMT[i * 12 + j + 16] = (~psxor[i] & MTtwo[i * 12 + j + 16]) | (psxor[i] & ~MTtwo[i * 12 + j + 16]); } temp >>= 8; } NumDevices = FindDevices(portnum, AllSN, 0x02, MAXDEVICES); if (NumDevices == 0) { printf("Please place the DS1991 on the 1-Wire Network.\n"); for (;;) { NumDevices = FindDevices(portnum, AllSN, 0x02, MAXDEVICES); if (NumDevices > 0) { msDelay(10); break; } } } for (i = 0; i < NumDevices; i++) { owSerialNum(portnum, &AllSN[i][0], FALSE); if (!writePassword(portnum, key, oldName, ID, secret)) { return FALSE; } if (writeScratchpad(portnum, 0, tempMT, 64)) { if (readScratchpad(portnum, data)) { for (j = 0; j < 64; j++) { if (tempMT[j] != data[j]) { OWERROR(OWERROR_READ_SCRATCHPAD_VERIFY); return FALSE; } } } else return FALSE; if (!copyScratchpad(portnum, key, secret, 8)) return FALSE; /* The write sub key is commented out so the write scratchpad, read scratchpad and copy scracthpad may be use to copy the data into the subkey. if(!writeSubkey(portnum,key,16,secret,data,48)) { OWERROR_DUMP(stderr); printf("the writing of the data didn't work.\n"); } else { */ if (!readSubkey(portnum, &data[0], key, secret)) { return FALSE; } else { for (j = 0; j < 64; j++) { if (tempMT[j] != data[j]) { OWERROR(OWERROR_READ_VERIFY_FAILED); return 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/pw77.c000066400000000000000000000137041446446235200170020ustar00rootroot00000000000000//--------------------------------------------------------------------------- // Copyright (C) 2003 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. //-------------------------------------------------------------------------- // // pw77.c - Password functions for the DS1977. // version 1.00 // // Include Files #include "ownet.h" #include "mbee77.h" #include "pw77.h" #include "mbscrx77.h" #define READ_PSW_ADDRESS 0x7FC0 #define READWRITE_PSW_ADDRESS 0x7FC8 #define CONTROL_PSW_ADDRESS 0x7FD0 #define VERIFY_PSW_COMMAND 0xC3 #define PASSWORD_PAGE 511 #define PASSWORD_OFFSET 16 #define PAGE_LEN 64 uchar psw[8]; /** * Set the READ or READ/WRITE password and verify it was written correctly. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part that the read is * to be done on. * psw 8 byte password to be use to write the password location * setpsw Data to set 8 byte password * type Password type designator: (0) READ (1) READ/WRITE * * @return 'true' if the read was complete */ SMALLINT setPassword(int portnum, uchar *SNum, uchar *setpsw, int type) { int addr = ((type == READ_PSW) ? READ_PSW_ADDRESS : READWRITE_PSW_ADDRESS); SMALLINT i; uchar buf[64]; // make sure that passwords are disabled if (readPageCRCEE77(1, portnum, SNum, PASSWORD_PAGE, buf)) { // check byte if (buf[PASSWORD_OFFSET] == 0xAA) { OWERROR(OWERROR_PASSWORDS_ENABLED); return FALSE; } } else { OWERROR(OWERROR_CRC_FAILED); return FALSE; } // write the new password if (writeEE77(1, portnum, SNum, addr, setpsw, 8)) { // clear the scratchpad so no one can see it sitting there for (i = 0; i < PAGE_LEN; i++) buf[i] = 0; writeScratchPadEx77(portnum, SNum, 0, buf, PAGE_LEN); // verify password was written correctly if (verifyPassword(portnum, SNum, setpsw, type)) return TRUE; else { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } } OWERROR(OWERROR_WRITE_DATA_PAGE_FAILED); return FALSE; } /** * Set the READ or READ/WRITE password and verify it was written correctly. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part that the read is * to be done on. * setpsw Data to set 8 byte password * type Password type designator: (0) READ (1) READ/WRITE * * @return 'true' if the read was complete */ SMALLINT verifyPassword(int portnum, uchar *SNum, uchar *setpsw, int type) { SMALLINT i, send_len = 0; uchar raw_buf[15]; int addr = ((type == READ_PSW) ? READ_PSW_ADDRESS : READWRITE_PSW_ADDRESS); // set serial number of device to read owSerialNum(portnum, SNum, FALSE); // select the device if (!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // command, address, offset, password (except last byte) raw_buf[send_len++] = VERIFY_PSW_COMMAND; raw_buf[send_len++] = addr & 0xFF; raw_buf[send_len++] = ((addr & 0xFFFF) >> 8) & 0xFF; for (i = 0; i < 7; i++) raw_buf[send_len++] = setpsw[i]; // send block (check copy indication complete) if (!owBlock(portnum, FALSE, raw_buf, send_len)) { OWERROR(OWERROR_BLOCK_FAILED); return FALSE; } // send last byte of password and enable strong pullup if (!owWriteBytePower(portnum, setpsw[7])) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } // delay for read to complete msDelay(5); // turn off strong pullup owLevel(portnum, MODE_NORMAL); // read the confirmation byte if (owReadByte(portnum) != 0xAA) { OWERROR(OWERROR_READ_VERIFY_FAILED); return FALSE; } return TRUE; } /** * Enable or disabled passwords. * * portnum the port number of the port being used for the * 1-Wire Network. * SNum the serial number for the part that the read is * to be done on. * setpsw Data to set 8 byte password * mode Mode designator: (0) DISABLED (1) ENABLED * * @return 'true' if the read was complete */ SMALLINT setPasswordMode(int portnum, uchar *SNum, int mode) { uchar buf[2]; // verify that the psw given is the correct READ/WRITE password if (verifyPassword(portnum, SNum, psw, READ_WRITE_PSW)) { // write or clear buf[0] = (mode == ENABLE_PSW) ? 0xAA : 0; if (writeEE77(1, portnum, SNum, CONTROL_PSW_ADDRESS, buf, 1)) return TRUE; else { OWERROR(OWERROR_WRITE_BYTE_FAILED); return FALSE; } } else { OWERROR(OWERROR_PASSWORD_INVALID); return FALSE; } } /** * Set the read-only or read/write password for all the memory * bank functions. * * pw Data to set 8 byte password */ void setBMPassword(uchar *pw) { int i; for (i = 0; i < 8; i++) psw[i] = pw[i]; } w1retap/src/libusblinux300/pw77.h000066400000000000000000000036711446446235200170110ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // pw77.h - Include password functions for the DS1977. // // Version: 1.00 // #include "ownet.h" // includes to specify which password #define READ_PSW 0 #define READ_WRITE_PSW 1 #define ENABLE_PSW 1 #define DISABLE_PSW 0 extern uchar psw[8]; // Local function definitions SMALLINT setPassword(int portnum, uchar *SNum, uchar *setpsw, int type); SMALLINT verifyPassword(int portnum, uchar *SNum, uchar *psw, int type); SMALLINT setPasswordMode(int portnum, uchar *SNum, int mode); void setBMPassword(uchar *pw); w1retap/src/libusblinux300/rawmem.c000066400000000000000000002523341446446235200174720ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- // // read_write.c - Reads and writes to memory locations of different buttons. // version 1.00 // // Include Files #include #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.h000066400000000000000000000104551446446235200174730ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000070341446446235200200040ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000025501446446235200176340ustar00rootroot00000000000000 // 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.c000066400000000000000000000705121446446235200171220ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000662771446446235200171340ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000152451446446235200177430ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000273651446446235200200040ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000414251446446235200174530ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000223651446446235200176400ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000001100161446446235200200000ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000566751446446235200177770ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000134671446446235200176240ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000463701446446235200172710ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000260301446446235200172650ustar00rootroot00000000000000// 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.c000066400000000000000000000064071446446235200175020ustar00rootroot00000000000000#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.h000066400000000000000000000002511446446235200171340ustar00rootroot00000000000000extern 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.c000066400000000000000000000101131446446235200203130ustar00rootroot00000000000000#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.c000066400000000000000000000066551446446235200171670ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000032311446446235200171570ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000176441446446235200171650ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000034271446446235200171640ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000237761446446235200172540ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000036161446446235200172500ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000134461446446235200177100ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000075601446446235200177020ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000004411446446235200171230ustar00rootroot00000000000000#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.c000066400000000000000000000105451446446235200171430ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000107061446446235200173030ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000032321446446235200173040ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000046361446446235200200470ustar00rootroot00000000000000#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.c000066400000000000000000001210771446446235200176420ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000133111446446235200176360ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000151051446446235200200110ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000170101446446235200200260ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000001021041446446235200172710ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000060541446446235200173050ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000351221446446235200177510ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000346171446446235200176470ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000073641446446235200176560ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.c000066400000000000000000000036711446446235200173700ustar00rootroot00000000000000#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.c000066400000000000000000000473301446446235200176370ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.h000066400000000000000000000042151446446235200176370ustar00rootroot00000000000000//--------------------------------------------------------------------------- // 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.build000066400000000000000000000026711446446235200154120ustar00rootroot00000000000000 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.sh000077500000000000000000000000731446446235200150640ustar00rootroot00000000000000#!/bin/sh exec gcc -O2 -Wall -o testrate testrate.c -lm w1retap/src/mysql/000077500000000000000000000000001446446235200144075ustar00rootroot00000000000000w1retap/src/mysql/meson.build000066400000000000000000000007341446446235200165550ustar00rootroot00000000000000 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.c000066400000000000000000000224431446446235200161750ustar00rootroot00000000000000/* * 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/000077500000000000000000000000001446446235200141515ustar00rootroot00000000000000w1retap/src/odbc/meson.build000066400000000000000000000007011446446235200163110ustar00rootroot00000000000000w1odbc_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.c000066400000000000000000000211701446446235200154750ustar00rootroot00000000000000/* * 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/000077500000000000000000000000001446446235200143705ustar00rootroot00000000000000w1retap/src/pgsql/meson.build000066400000000000000000000007301446446235200165320ustar00rootroot00000000000000w1pgsql_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.sh000077500000000000000000000004251446446235200162370ustar00rootroot00000000000000#!/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.c000066400000000000000000000262501446446235200161370ustar00rootroot00000000000000/* * 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.sql000066400000000000000000000013501446446235200154560ustar00rootroot00000000000000CREATE 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/000077500000000000000000000000001446446235200145435ustar00rootroot00000000000000w1retap/src/sqlite/meson.build000066400000000000000000000007411446446235200167070ustar00rootroot00000000000000w1sqlite_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.c000066400000000000000000000247361446446235200164740ustar00rootroot00000000000000/* * 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.c000066400000000000000000000123241446446235200152430ustar00rootroot00000000000000#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.c000066400000000000000000000070561446446235200146130ustar00rootroot00000000000000/* * 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.c000066400000000000000000000035261446446235200144570ustar00rootroot00000000000000/* * 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.c000066400000000000000000000070361446446235200146030ustar00rootroot00000000000000/* * 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.c000066400000000000000000000356611446446235200150040ustar00rootroot00000000000000/* * 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.h000066400000000000000000000103221446446235200147740ustar00rootroot00000000000000/* * 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.c000066400000000000000000000760451446446235200153660ustar00rootroot00000000000000/* * 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.c000066400000000000000000000206121446446235200146340ustar00rootroot00000000000000/* * 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.c000066400000000000000000000100301446446235200144500ustar00rootroot00000000000000/* * 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 #ifdef HAVE_LIBXML2 #include #include #define XMLENC "utf-8" void w1_logger(w1_devlist_t *w1, char *logfile) { int i; char timb[TBUF_SZ]; w1_device_t *devs; FILE *lfp; xmlTextWriterPtr writer; xmlBufferPtr buf; 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; } buf = xmlBufferCreate(); if (buf) { writer = xmlNewTextWriterMemory(buf, 0); if (writer) { logtimes(w1, w1->logtime, timb); if (0 == xmlTextWriterStartDocument(writer, NULL, XMLENC, NULL)) { xmlTextWriterSetIndent(writer, 1); xmlTextWriterStartElement(writer, BAD_CAST "report"); xmlTextWriterWriteAttribute(writer, BAD_CAST "timestamp", BAD_CAST timb); xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "unixepoch", "%lld", (long long)w1->logtime); 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) { xmlTextWriterStartElement(writer, BAD_CAST "sensor"); xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST devs->s[j].abbrv); xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "value", "%.4f", devs->s[j].value); xmlTextWriterWriteAttribute(writer, BAD_CAST "units", BAD_CAST((devs->s[j].units) ? (devs->s[j].units) : "")); xmlTextWriterEndElement(writer); } } } } xmlTextWriterEndDocument(writer); fwrite(buf->content, 1, buf->use, lfp); if (logfile) { if (*logfile == '|') { pclose(lfp); } else { fclose(lfp); } } } } xmlBufferFree(buf); } } #else 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); fputs("\n", lfp); fprintf(lfp, "\n", timb, (long long)w1->logtime); for (devs = w1->devs, i = 0; i < w1->numdev; i++, devs++) { if (devs->init) { int j; for (j = 0; j < 2; j++) { if (devs->s[j].valid) { fprintf(lfp, " \n", devs->s[j].abbrv, devs->s[j].value, (devs->s[j].units) ? (devs->s[j].units) : ""); } } } } fputs("\n", lfp); if (logfile) { if (*logfile == '|') { pclose(lfp); } else { fclose(lfp); } } } #endif w1retap/src/wtest.c000066400000000000000000000066531446446235200145660ustar00rootroot00000000000000/* * 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 #define W1_ROC (1 << 0) #define W1_RMIN (1 << 1) #define W1_RMAX (1 << 2) #define ALLOCDEV 8 #define TBUF_SZ 32 #define MAXDLL 16 typedef struct w1_devlist w1_devlist_t; typedef struct { char *abbrv; char *name; char *units; float value; short valid; short flags; float rmin; float rmax; float roc; float lval; time_t ltime; } w1_sensor_t; typedef struct { char *serial; char *devtype; short init; w1_sensor_t s[2]; } w1_device_t; struct w1_devlist { int numdev; int ndll; int delay; int portnum; char *iface; char *rcfile; char *repfile; time_t logtime; short verbose; short daemonise; short logtmp; short doread; w1_device_t *devs; }; static int w1_validate(w1_devlist_t *w1, w1_sensor_t *s) { int chk = 0; s->valid = 1; if ((s->flags & W1_RMIN) && (s->value < s->rmin)) { s->value = (s->ltime) ? s->lval : s->rmin; chk = 1; } if ((s->flags & W1_RMAX) && (s->value > s->rmax)) { s->value = (s->ltime) ? s->lval : s->rmax; chk = 1; } if (chk == 0 && (s->flags & W1_ROC)) { if (s->ltime > 0 && s->ltime != w1->logtime) { float rate = fabs(s->value - s->lval) * 60.0 / (w1->logtime - s->ltime); if (rate > s->roc) { s->valid = 0; puts("Range Fails"); #if 1 if (w1->repfile) { FILE *rfp; if (NULL != (rfp = fopen(w1->repfile, "a"))) { char buf[80]; logtimes(w1->logtime, buf); fprintf(rfp, "%s %s %.2f %.2f %.2f %d %d\n", buf, s->abbrv, s->value, rate, s->lval, s->ltime, w1->logtime); fclose(rfp); } } #endif s->value = s->lval; } } if (s->valid) { s->ltime = w1->logtime; s->lval = s->value; } } (int)s->valid; } int main(void) { w1_devlist_t w = {0}, *w1; w1_device_t devs[1] = {0}; float tvals[] = {1013, 1013.5, 700, 700, 700, 1014}; w1 = &w; w1->numdev = 1; w1->devs = devs; w1->devs[0].init = 1; w1->devs[0].s[0].flags = 7; w1->devs[0].s[0].roc = 100; w1->devs[0].s[0].rmin = 800; w1->devs[0].s[0].rmax = 1200; int n; time_t tt = time(0); for (n = 0; n < sizeof(tvals) / sizeof(float); n++) { w1->devs[0].s[0].value = tvals[n]; w1->logtime = tt + n * 120; w1_validate(w1, &w1->devs[0].s[0]); printf("%d: Test: %.1f Value: %.1f valid: %d lval: %.1f" " tim: %d ltim %d\n", n, tvals[n], w1->devs[0].s[0].value, w1->devs[0].s[0].valid, w1->devs[0].s[0].lval, w1->logtime, w1->devs[0].s[0].ltime); } }