aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfishsoupisgood <github@madingley.org>2019-04-27 22:20:21 +0100
committerfishsoupisgood <github@madingley.org>2019-04-27 22:20:21 +0100
commitfd6bb20116127f6ac903d4b03abac72a49baa1ae (patch)
tree22e1e44fad2f844096f2d79bef9262112b45158c
downloaddatalink-fd6bb20116127f6ac903d4b03abac72a49baa1ae.tar.gz
datalink-fd6bb20116127f6ac903d4b03abac72a49baa1ae.tar.bz2
datalink-fd6bb20116127f6ac903d4b03abac72a49baa1ae.zip
fish
-rw-r--r--70.txt177
-rw-r--r--COPYING340
-rw-r--r--Makefile147
-rw-r--r--README112
-rw-r--r--TODO23
-rw-r--r--changelog88
-rw-r--r--datafile41
-rw-r--r--datalink.h266
-rw-r--r--datalink_macros.h100
-rw-r--r--datalink_private.h63
-rw-r--r--dataread.l57
-rw-r--r--dataread.y619
-rw-r--r--dl_add_to_list.c37
-rw-r--r--dl_anniv_by_date.c34
-rw-r--r--dl_anniv_by_label.c28
-rw-r--r--dl_app_by_datetime.c39
-rw-r--r--dl_app_by_label.c28
-rw-r--r--dl_docrc.c52
-rw-r--r--dl_fill_pack_ascii.c40
-rw-r--r--dl_free_download.c65
-rw-r--r--dl_init_download.c607
-rw-r--r--dl_init_watch.c150
-rw-r--r--dl_item_ok.c306
-rw-r--r--dl_new_item.c48
-rw-r--r--dl_new_list.c38
-rw-r--r--dl_pack_ascii.c59
-rw-r--r--dl_pack_char.c42
-rw-r--r--dl_pack_digit.c42
-rw-r--r--dl_pack_phone.c55
-rw-r--r--dl_pack_size.c34
-rw-r--r--dl_phone_by_label.c28
-rw-r--r--dl_send_data.c897
-rw-r--r--dl_set_error.c27
-rw-r--r--dl_set_warn.c27
-rw-r--r--dl_sizeof_item.c103
-rw-r--r--dl_sizeof_list.c34
-rw-r--r--dl_sort.c83
-rw-r--r--dl_string_ok.c44
-rw-r--r--dl_todo_by_label.c28
-rw-r--r--dl_todo_by_prio.c27
-rw-r--r--dl_write_save.c153
-rw-r--r--doc/datalink.ps228
-rw-r--r--doc/usage115
-rw-r--r--send_data.c93
-rw-r--r--serblink.151
-rw-r--r--serblink.c208
-rw-r--r--settime.177
-rw-r--r--settime.c156
-rw-r--r--setwatch.177
-rw-r--r--setwatch.c444
-rw-r--r--sgiglblink.c264
-rw-r--r--svgablink.151
-rw-r--r--svgablink.c171
-rw-r--r--vt.c196
54 files changed, 7319 insertions, 0 deletions
diff --git a/70.txt b/70.txt
new file mode 100644
index 0000000..3022cb9
--- /dev/null
+++ b/70.txt
@@ -0,0 +1,177 @@
+The latest version of the document, and other info including my test
+data and decoding program, can be found at
+http://csgrad.cs.vt.edu/~tjohnson/timex/
+
+This version is incomplete (not because I cut out information, but because
+I don't know).
+
+Disclaimer:
+I am not associated with Timex in any way, OTHER than wanting to use their
+datalink watch on a civilized OS (read: Unix). All this info has been
+discovered by watching the behavior of the FREELY AVAILABLE software
+found on the Timex WWW server. (http://www.timex.com)
+
+Timex and DataLink are trademarks of Timex.
+
+If you buy, or would buy, a DataLink watch because of the availabilty of
+this information, please email me. I would like to give Timex a count of
+the number of customers this information has generated. Perhaps that
+will inspire them to be more open in the future.
+
+-Tommy Johnson
+tjohnson@bobdbob.com
+http://csgrad.cs.vt.edu/~tjohnson/
+
+Physical level:
+The serial data is drawn on the display as a series of 9 horizontal
+lines. It is convered to serial by the raster scanning the image, one
+word per frame. The top line is always on, it functions as a start
+bit. This is why LCD's don't work: they are not scanned in the same
+order.
+
+The words are transfered least significant bit first, bright lines are
+zero, dark lines are one.
+
+The sync signal is the word 0x55 a great many times. After the 0x55's,
+there are 40 0xAA's, followed by data in packets.
+
+The packets are seperated by 6 empty frames (no start bit either).
+
+Logical level:
+
+The data is sent in packets from 4 to 32 bytes long.
+byte 1 - length
+byte 2 - type
+ 0x20 - START1 (one)
+ 0x30 - TIME (several)
+ 0x60 - START2 counts? (one)
+ 0x61 - DATA1 (several)
+ 0x62 - END1 (one)
+ 0x50 - ALARM (several)
+ 0x70 - ???? (several, alternating with ALARM)
+ 0x31 - ????
+ 0x21 - END2 (one)
+ In DATA1 and ALARM packets, byte 3 is the packet number
+ (starting at 1)
+
+byte len-1 - check 0
+byte len - check 1 checksum of come kind
+
+I havn't the foggiest idea what the function for the checksum is. 16 bit CRC?
+
+Next Logical level:
+The packets are sent in this order:
+(from here on, byte 1 is byte 3 in the above list)
+
+one packet type START1 0x20
+byte 1 - 0
+byte 2 - 0
+byte 3 - 1
+Unknown, may be a protocol version, or magic number. I have never seen
+these numbers change in all my test data.
+
+zero or more packet type TIME 0x30
+byte 1 - timezone (the watch has two timezones, 1 or 2)
+byte 2 - hour
+byte 3 - minute
+byte 4 - month
+byte 5 - day
+byte 6 -
+byte 7 -
+byte 8 -
+byte 9 -
+byte 10 -
+To indicate the timezone, the computer converts, and just sends a time.
+
+one packet type START2 0x60
+byte 1 - number of DATA1 packets to follow
+
+number from packet START2 packets type DATA1 0x20
+In the first DATA1 packet, the first 15 bytes are:
+byte 1 - sequence number (1)
+byte 2,3 - start address of appointments
+byte 4,5 - start address of todos
+byte 6,7 - start address of phone numbers
+byte 8,9 - start address of aniversaries
+byte 10 - number of appointments
+byte 11 - number of todos
+byte 12 - number of phone numbers
+byte 13 - number of aniversaries
+byte 14 - 0x60 ?
+byte 15 - how long to beep early, in 5 minute units
+
+In the rest of the DATA1 packets, there are variable length records of the
+following formats, there is no padding to fill the DATA1 packets evenly.
+byte 10 appointments
+byte 11 todos
+byte 12 phone numbers
+byte 14 aniversaries
+
+one packet type END1
+No data, just a checksum
+
+zero or five ALARM packets, one per alarm. If an alarm is inaudable, its
+ALARM packet is followed by a 0x70 packet.
+Alarms are in ALARM packets.
+byte 1 - count, 1 to 5
+byte 2 - hour
+byte 3 - minute
+byte 4 - month Set to 0 for every month
+byte 5 - day Set to 0 for every day
+byte 6-13 - label, in watch char set, 1 char per byte (NOT packed)
+byte 14 - 1 if audible, 0 otherwise
+
+type 0x70 packet:
+byte 1 - 0 ?
+byte 2 - number of the preceding alarm + 0x61 ?????
+byte 3 - 0 ?
+
+zero or one packet type 0x31
+No idea. but it only shows up when the time is set.
+
+one packet type END2 0x21
+
+Thats it.
+
+char set for labels is: (6 bits per char)
+0-9 : digits
+10-36: letters
+37-63: symbols:
+space !"#$%&'()*+,-./;\
+divide =
+bell (image, not sound)
+?
+
+These 4 record types are found in DATA1 packets:
+
+An appointment:
+byte 1 - length
+byte 2 - month
+byte 3 - day
+byte 4 - time
+ bits are: 16 8 4 2 1 0.5 0.25 hours
+byte 5-len-1- label
+ 6 bits per char, packed 4 chars to 3 bytes
+ 11000000
+ 22221111
+ 33333322
+byte len - 0xFC ?
+
+A ToDo:
+byte 1 - length
+byte 2 - priority
+byte 3-len-1 - label same as appointment
+byte len - 0xFD ?
+
+A Phone number:
+byte 1 - length
+byte 2-6 - phone number, 4 bits per digit, LSnibble first
+byte 7-len-1 - label same as appointment
+byte len - 0xF ?
+
+An anniversary:
+byte 1 - length
+byte 2 - month
+byte 3 - day
+byte 4-len-1 - label same as appointment
+byte len - 0xFC ?
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..22a7c9e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,147 @@
+# Do not modify this - modify PREFIX (below) instead. This is used by
+# package manages such as that for Debian.
+DESTDIR =
+
+
+# Edit the parameters below for your needs.
+
+PREFIX=$(DESTDIR)/usr/local
+BINDIR=$(PREFIX)/bin
+LIBDIR=$(PREFIX)/lib
+MANDIR=$(PREFIX)/man
+INCDIR=$(PREFIX)/include
+
+CC = gcc
+#CFLAGS = -Wall -g -DBINDIR=\"$(BINDIR)\"
+CFLAGS = -O2 -DBINDIR=\"$(BINDIR)\"
+
+PORT = /dev/ttyS0
+
+ENGINES = svgablink serblink
+
+RANLIB = echo
+#RANLIB = ranlib
+
+# Do not edit below here, no user serviceable parts.
+
+SRC = dl_add_to_list.c dl_anniv_by_date.c dl_anniv_by_label.c \
+ dl_app_by_datetime.c dl_app_by_label.c dl_docrc.c dl_fill_pack_ascii.c \
+ dl_free_download.c dl_init_download.c dl_init_watch.c dl_item_ok.c \
+ dl_new_item.c dl_new_list.c dl_pack_ascii.c dl_pack_char.c \
+ dl_pack_digit.c dl_pack_phone.c dl_pack_size.c dl_phone_by_label.c \
+ dl_send_data.c dl_set_error.c dl_set_warn.c dl_sizeof_item.c \
+ dl_sizeof_list.c dl_sort.c dl_string_ok.c dl_todo_by_label.c \
+ dl_todo_by_prio.c dl_write_save.c
+
+OBJ = dl_add_to_list.o dl_anniv_by_date.o dl_anniv_by_label.o \
+ dl_app_by_datetime.o dl_app_by_label.o dl_docrc.o dl_fill_pack_ascii.o \
+ dl_free_download.o dl_init_download.o dl_init_watch.o dl_item_ok.o \
+ dl_new_item.o dl_new_list.o dl_pack_ascii.o dl_pack_char.o \
+ dl_pack_digit.o dl_pack_phone.o dl_pack_size.o dl_phone_by_label.o \
+ dl_send_data.o dl_set_error.o dl_set_warn.o dl_sizeof_item.o \
+ dl_sizeof_list.o dl_sort.o dl_string_ok.o dl_todo_by_label.o \
+ dl_todo_by_prio.o dl_write_save.o \
+ parse.o dl_read_save.o
+
+SVGASRC = svgablink.c vt.c send_data.c
+SERSRC = serblink.c
+
+SVGAOBJ = svgablink.o vt.o send_data.o
+SEROBJ = serblink.o
+
+YACC = bison -y -p dl_ -oy.tab.c
+LEX = flex -Pdl_ -olex.yy.c
+
+.PHONY: all clean
+
+all: depend libdatalink.so.1 settime setwatch $(ENGINES)
+
+libdatalink.a: $(OBJ)
+ rm -f $@
+ ar qv $@ $(OBJ)
+
+libdatalink.so.1: $(OBJ)
+ rm -f $@
+ $(CC) -shared -o $@ $(OBJ) $(CFLAGS)
+ $(RANLIB) $@
+
+dl_read_save.c: dataread.y
+ $(YACC) -d dataread.y
+ mv y.tab.c $@
+
+parse.c: dataread.l dl_read_save.c y.tab.h
+ $(LEX) dataread.l
+ mv lex.yy.c $@
+
+depend: parse.c dl_read_save.c
+ makedepend -f- -o.o $(CFLAGS) $(SRC) $(SVGASRC) $(SERSRC) > depend
+ @echo "Dependencies have been made, re-run make to build"
+ @false
+
+serblink.o: $(SERSRC)
+ $(CC) -c $(CFLAGS) -DPORT=\"$(PORT)\" $(SERSRC)
+
+serblink: $(SEROBJ)
+ rm -f $@
+ $(CC) $(CFLAGS) -o $@ $(SEROBJ)
+
+svgablink: $(SVGAOBJ)
+ rm -f $@
+ $(CC) $(CFLAGS) -o $@ $(SVGAOBJ) -lvga
+
+settime.o: settime.c
+ $(CC) $(CFLAGS) -I. -c settime.c
+
+setwatch.o: setwatch.c
+ $(CC) $(CFLAGS) -I. -c setwatch.c
+
+settime: settime.o libdatalink.a
+ $(CC) $(CFLAGS) -o $@ settime.o -L. -ldatalink
+
+setwatch: setwatch.o libdatalink.a
+ $(CC) $(CFLAGS) -o $@ setwatch.o -L. -ldatalink
+
+cvt: cvt.o
+ $(CC) $(CFLAGS) -o $@
+
+install: all
+ mkdir -p $(BINDIR) $(MANDIR)/man1
+ install -o root -g video -m 4750 svgablink $(BINDIR)
+ install -o root -g root -m 755 serblink $(BINDIR)
+ install -o root -g root -m 755 setwatch $(BINDIR)
+ install -o root -g root -m 755 settime $(BINDIR)
+ install -o root -g root -m 644 setwatch.1 $(MANDIR)/man1
+ install -o root -g root -m 644 settime.1 $(MANDIR)/man1
+ install -o root -g root -m 644 svgablink.1 $(MANDIR)/man1
+ install -o root -g root -m 644 serblink.1 $(MANDIR)/man1
+
+install-devel: install
+ mkdir -p $(LIBDIR) $(INCDIR)
+ install -o root -g root -m 555 libdatalink.so.1 $(LIBDIR)
+ install -o root -g bin -m 555 libdatalink.a $(LIBDIR)
+ install -o root -g bin -m 444 datalink.h $(INCDIR)
+
+uninstall:
+ rm -f $(BINDIR)/svgablink
+ rm -f $(BINDIR)/serblink
+ rm -f $(BINDIR)/setwatch
+ rm -f $(BINDIR)/settime
+ rm -f $(MANDIR)/man1/setwatch.1
+ rm -f $(MANDIR)/man1/settime.1
+ rm -f $(MANDIR)/man1/svgablink.1
+ rm -f $(MANDIR)/man1/serblink.1
+ rm -f $(LIBDIR)/libdatalink.so.1
+ rm -f $(LIBDIR)/libdatalink.a
+ rm -f $(INCDIR)/datalink.h
+
+clean:
+ rm -f $(OBJ) libdatalink.a libdatalink.so.1 Makefile.bak
+ rm -f $(SVGAOBJ) $(SEROBJ)
+ rm -f parse.c dl_read_save.c y.tab.h
+ rm -f settime.o setwatch.o cvt.o
+ rm -f settime setwatch cvt $(ENGINES)
+ rm -f depend
+
+# The next line was used for makedepend
+include depend
+# DO NOT DELETE
diff --git a/README b/README
new file mode 100644
index 0000000..0c9e0f4
--- /dev/null
+++ b/README
@@ -0,0 +1,112 @@
+Copyright 1996-2002 - Karl R. Hakimian <hakimian@aha.com>
+ and David Fries <dfries@mail.win.org>
+
+This is the README file for the datalink library.
+
+This software is in no way associated with or supported by Timex. Do
+not contact them for help with this software.
+
+Datalink 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.
+
+Datalink 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 datalink (see COPYING); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+==========================================================================
+
+This is the datalink library for Linux. It uses the SVGAlib to send data
+to the Timex DataLink watches. You will need SVGAlib installed and the
+development headers and libraries for SVGAlib to compile against.
+
+The original author is Karl R. Hakimian <hakimian@eecs.wsu.edu>, I have
+extended the program to work with the Timex DataLink Ironman Triathlon
+watch. I do not have the ability to test the original model 70 or model 150
+watches and I have only tested the SVGA output program. The original
+watches and serblink (serial blink) program may have been broken with
+my code changes, I have no way to test them.
+
+The watch has a Motorola 6805 microprocessor in it with the ability of the
+model 150 or 150s version to write and run programs on the watch.
+
+Compiling:
+Type make depend to make the dependences.
+ $ make depend
+Then just type `make` on the command line.
+ $ make
+
+Installing:
+Type `make install` on the command line.
+ % make install
+The default locations of the installed programs are:
+
+/usr/local/lib/libdatalink.so.1
+/usr/local/lib/libdatalink.a
+/usr/local/include/datalink.h
+/usr/local/bin/svgablink
+/usr/local/bin/serblink
+/usr/local/bin/setwatch
+
+Please note that the svgablink must be installed setuid root to use
+the SVGAlib and change to graphics mode. If you install as root
+the default is to install setuid root. If you are concerned about
+security I suggest you have it setuid root and executable by
+the group and not executable by the world. Include only those
+in the group who has a reason to run the program and you trust.
+I do not know how much the original author has put into making
+it secure, I know I haven't done anything along those lines.
+If you have patches to fix any problems please email me (David).
+
+Running:
+The short version:
+ Copy datafile from the source directory, make any changes.
+Hit mode on your watch until you get to the "COMM READY V4.0" screen.
+Run setwatch with the following arguements `setwatch -all datafile`.
+If you have the model 70 or model 150 you have to add the option
+-model150 or -150, or -model70 or -70 to the setwatch program.
+The long version:
+ Make a directory called .datalink in your home directory,
+copy the datalink file from the source directory to that directory,
+follow above directions adding any of the options to send specific
+data to the watch. Find all bugs, fix all bugs, send all patches
+to me (David).
+
+Suggestions:
+ I have found my 15" monitor seems to send the data without
+any problems, but my 19" monitor tends to corrupt some of the phone
+data. All of the packets have crc data in them, but the watch does not
+indicate the data is bad, so check to make sure everything was transfered
+correctly. I may need to add code to adjust the spacing of the lines
+on the monitor, I'm not sure what the problem is here.
+ Running anything in the background can cause the program to not
+function correctly. SVGAlib appears to be polling the video card to
+determine when the verticle sync occurs and if it misses it because
+something else is running the watch may not get the data correctly.
+I don't know how much of a problem this is, I just noticed it on
+development of my additions.
+ Improvements, suggestions, patches, comments e-mail me. I am
+also interested in how many people find this useful, please e-mail
+if you just plan to use it, I would like to hear from you.
+ If you work for Timex or have any influence, I would like
+some documentation on these watches. I have none. I am aware
+there is a software development kit that Timex put out, but I am
+also told it contains only information on how to use their equivalent
+of the datalink library. I do not need this. I need documentation
+of the protocol and watch capabilities, that is what I need. The
+protocol was decoded by taking a light sensitive circuit, placing it
+in from of a CRT screen that was flashing data from the Timex software,
+recording it with a sound card, and useing software I wrote to
+turn it back into data. Then figuring out by hand what it means.
+ When doing any transfers the chronograph and timer is stopped.
+This is just so you know.
+
+David Fries
+dfries@mail.win.org
+August 25, 1999
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..c91e44c
--- /dev/null
+++ b/TODO
@@ -0,0 +1,23 @@
+Document the Ironman protocol
+add options in the datafile parser to
+ -set the watch model
+ -set the order of phone entries
+ -set the spacing of the lines
+ -set all other options that can be specified on the commandline
+being able to abort a transfer while the screen is flashing would be nice
+
+figure out why just sending alarms will corrupt the phone entries
+(later entries like 17 or so)
+
+Mon Jan 22 22:38:50 CST 2001
+question from a user,
+I can't seem to move fast enough for me to put my watch in front of the
+screen before your program starts sending data to the watch...
+
+How about showing the initializing sequence (the many bars on the screen
+that makes DataLink go beeping while in COMM mode), then wait for a key
+to be pressed before actually sending the data?
+
+probably not a bad idea to show the sync signal until the user initiates
+the data mode, also possibly have an option for the time to wait while
+displaying the sync signal
diff --git a/changelog b/changelog
new file mode 100644
index 0000000..0c1eef9
--- /dev/null
+++ b/changelog
@@ -0,0 +1,88 @@
+07-21-2002:
+ -Fixed the setwatch options of -app and +app to say appointments
+ instead of wristapp.
+ -setwatch was trying to run svgablink with -150S instead of -150s
+ -The -file (for creating a DEBUGOUTPUT) was broken, fixed.
+07-17-2002: aka 1.0.0
+ -Added header files for libc functions we are already using,
+ but weren't including the proper header files.
+ -Switched to using tmpfile instead of tmpnam for the temporary
+ file, this will fix the compiler warnings.
+ -The newer bison required a semicolon and would not compile
+ until it was added.
+ -Replaced tmpnam() with mkstemp() because the compiler gave
+ warnings about tmpnam being a possible security hole.
+ -Dependency information now goes in the file depend and will be
+ calculated if the file doesn't exist.
+-- David Fries <dfries@mail.win.org>
+
+12-16-2001:
+ -Changed license to GPL (with permission from all 4 authors).
+ -Added info to readme about GPL and about lack of support from Timex.
+ -Created manpages for svgablink, serblink, setwatch, and settime
+ They still need work - I'll get to it when I can.
+ -Changed settime default to ironman for consistency w/ setwatch.
+ -Fixed apparent missing semicolon in dataread.y.
+ -Added DESTDIR to Makefile to be more friendly with Debian packaging.
+ -Split Makefile "install" rule into "install" (for basic datalink
+ user requirements) and "install-devel" for items needed only for
+ development.
+ -Added Makefile "uninstall" rule.
+-- Steaphan Greene <stea@cs.binghamton.edu>
+
+02-14-2001:
+The changes listed below from Frank Denis were incorporated with exception
+of the time of the week information, I'll have to look into that later.
+More important user visible changes are as follows,
+ It will now only search in the users path for serblink and svgablink
+ not any hard-coded paths. Previous behavior was to try
+ the user path and if it wasn't found, try executing
+ the program in the current working directory.
+ settime is now installed by default and will accept a command line for
+ the different types of watches
+ For me, svgablink no longer hangs on exit
+-- David Fries <dfries@mail.win.org>
+
+02-04-2001:
+I don't see the problem with the day of week. I'm reverting back to
+the previous code. Will have to investigate sometime. On my watch
+the code is correct as it used to be (and is now again).
+-- David Fries
+
+04-22-2000:
+Fixed a bug with the day of the week that was shifted by one. Please report
+if it broke something.
+-- Frank Denis
+
+04-20-2000:
+Fixed the path to svgablink.
+The datalink 150 S protocol was implemented but the "-150s" option was
+rejected in setwatch. Fixed.
+-- Frank Denis
+
+04-17-2000:
+Add support for Datalink 150 S watches
+-- Frank Denis
+
+
+04-14-2000:
+Lots, lots, lots of cleanups to the source code in order to make it compile
+on modern compilers.
+-- Frank Denis
+
+
+01-05-2000:
+Added a patch from Scottie Shore <sshore@escape.ca> for a Y2K problem.
+As localtime(3) reads,
+ tm_year
+ The number of years since 1900.
+The watch is expecting the last two digits and displays A0 for the year instead of 00. Fix is to take the year % 100.
+-- David Fries
+
+
+12-11-1999:
+Added a patch from Danilo Fiorenzano <danilo@telusplanet.net> to
+Added new function "maxPriority()" to switch to SCHED_RR kernel scheduling
+policy at maximum priority and lock all pages into real memory, in order
+to improve timing accuracy.
+-- David Fries
diff --git a/datafile b/datafile
new file mode 100644
index 0000000..f270d3a
--- /dev/null
+++ b/datafile
@@ -0,0 +1,41 @@
+#time_adjust = 5
+
+# valid characters 0-9, A-Z, space, !"#$%&'()*+,-./:\ (division sign) = (bell symbol) ?
+# alarm #, Month/Day, 24 hour time, "label", on/off
+# 1-10, 0/0 anytime; 0/day a day per month; mon/day that day, hh:mm, "up to 16 characters and special values", on/off 1/0
+alarm = 1, 0/0, 20:55, "DS9", 1
+alarm = 2, 0/0, 19:55, "Voyager", 1
+alarm = 3, 0/0, 12:53, "no idea", 0
+
+# timer #, "hh:mm:ss", "8 char label" repeat, chron ; only one of repeat or chron can be true
+# the time is treated as a string to get the seconds, so it must have quotes
+timer = 1, "12:34:11", "test 123", 0, 0
+timer = 2, "00:15", "15 mins.", 1, 0
+timer = 3, "00:30", "30 mins.", 0, 1
+
+phone = "111111111111", "000000000000000"
+phone = "9119119111 W", "call me"
+phone = "5093363720 C", "Garren"
+
+# appointment (model 70 and 150)
+# appointment = MM/DD/YY, hh:mm:ss, "15 char message"
+#appointment = 10/29/99, 14:30, "this is a test"
+# do appointments not take a year?
+appointment = 10/29, 14:30, "this is a test"
+
+# chrono label and number of laps, "8 char label", laps range from 2 to 50
+# default entry
+#chron = " Chrono", 8
+chron = " Chrono 8", 8
+
+# hourly chime, button beep
+system = 0, 0
+
+# timezone, timezone #, 3 characters label, offset from system clock in minutes, hour format 1=12hour, 2=24hour, date format US=0
+timezone = 1, "ABC", 0, 1, 0
+timezone = 2, "CBS", 0, 2, 0
+
+#wristapp = "~/.datalink/timer13.app"
+#wristapp = "~/.datalink/melody17.app"
+#melody = "~/.datalink/mainline.spc"
+#melody = "~/src/watch/xx"
diff --git a/datalink.h b/datalink.h
new file mode 100644
index 0000000..ab6f2d7
--- /dev/null
+++ b/datalink.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __DATALINK_H__
+#define __DATALINK_H__
+
+typedef struct time_s
+{
+ unsigned char tz_num;
+ unsigned char hours;
+ unsigned char minutes;
+ unsigned char seconds;
+ unsigned char month;
+ unsigned char day;
+ unsigned char year;
+ unsigned char dow; /* Day Of the Week */
+ unsigned char hour_fmt;
+ unsigned char date_fmt;
+ unsigned char download;
+ int offset;
+ char *label;
+} Time, *TimePtr;
+
+typedef struct alarm_s
+{
+ unsigned char alarm_num;
+ unsigned char hours;
+ unsigned char minutes;
+ unsigned char month;
+ unsigned char day;
+ char *label;
+ unsigned char audible;
+} Alarm, *AlarmPtr;
+
+typedef struct chron_s
+{
+ unsigned char chron_laps;
+ int memused;
+ char *label;
+} Chron, *ChronPtr;
+
+typedef struct timer_s
+{
+ unsigned char timer_num;
+ unsigned char hours;
+ unsigned char minutes;
+ unsigned char second;
+ unsigned char repeat;
+ unsigned char chron;
+ char *label;
+} Timer, *TimerPtr;
+
+typedef struct system_s
+{
+ unsigned char chime;
+ unsigned char beep;
+} System, *SystemPtr;
+
+typedef struct appointment_s
+{
+ unsigned char month;
+ unsigned char day;
+ unsigned char time;
+ char *label;
+} Appointment, *AppointmentPtr;
+
+typedef struct phone_s
+{
+ char *number;
+ char *label;
+} Phone, *PhonePtr;
+
+typedef struct todo_s
+{
+ unsigned char priority;
+ char *label;
+} ToDo, *ToDoPtr;
+
+typedef struct anniversary_s
+{
+ unsigned char month;
+ unsigned char day;
+ char *label;
+} Anniversary, *AnniversaryPtr;
+
+typedef struct wristapp_s
+{
+ int len;
+ unsigned char *data;
+} WristApp, *WristAppPtr;
+
+typedef struct melody_s
+{
+ int len;
+ unsigned char *data;
+} Melody, *MelodyPtr;
+
+typedef struct item_s
+{
+ struct item_s *next;
+ int type;
+ union
+ {
+ Time time;
+ Alarm alarm;
+ Chron chron;
+ Timer timer;
+ System sys;
+ Appointment app;
+ Phone phone;
+ ToDo todo;
+ Anniversary anniv;
+ System system;
+ WristApp wristapp;
+ Melody melody;
+ }
+ data;
+}
+Item, *ItemPtr;
+
+typedef struct list_s
+{
+ ItemPtr first;
+ ItemPtr last;
+ int download;
+ int count;
+} List, *ListPtr;
+
+typedef struct watch_info_s
+{
+ int dl_device; /* Device to download to. */
+ int max_tz;
+ int max_alarms;
+ int max_apps;
+ int max_chrons;
+ int max_phones;
+ int max_timers;
+ int max_todos;
+ int max_annivs;
+ int max_system;
+ int max_wristapp;
+ int max_melody;
+ int max_tzlen;
+ int max_mem; /* Memory available. */
+ int mem_size; /* Memory used. */
+ int max_str; /* Max string length for this device. */
+ int max_alarm_str; /* Max string length for an alarm on this device. */
+ int max_chron_str; /* Max string length for the cron on this device. */
+ int max_phone_str; /* Max string length for a phone on this device. */
+ int max_timer_str; /* Max string length for the timer on this device. */
+ int max_wristapp_len;
+ int max_mel_len;
+ int pre_notification_time;
+ int time_adjust;
+ List times;
+ List alarms;
+ List chron;
+ List timers;
+ List system;
+ List apps;
+ List phones;
+ List todos;
+ List annivs;
+ List wristapp;
+ List melody;
+} WatchInfo, *WatchInfoPtr;
+
+/* defines */
+
+#ifndef NULL
+#define NULL 0l
+#endif
+
+/* Item types */
+#define DL_NO_TYPE 0
+#define DL_TIME_TYPE 1
+#define DL_ALARM_TYPE 2
+#define DL_APP_TYPE 3
+#define DL_PHONE_TYPE 4
+#define DL_TODO_TYPE 5
+#define DL_ANNIV_TYPE 6
+#define DL_SYSTEM_TYPE 7
+#define DL_WRISTAPP_TYPE 8
+#define DL_MELODY_TYPE 9
+#define DL_TIMER_TYPE 10
+#define DL_CHRON_TYPE 11
+#define DL_MAX_TYPE 12
+
+/* Output types */
+#define NO_OUTPUT 0
+#define SVGA_BLINK 1
+#define SER_BLINK 2
+#define BLINK_FILE 3
+
+/* Watch types */
+#define NO_WATCH 0
+#define DATALINK_70 1
+#define DATALINK_150 2
+#define DATALINK_150S 3
+#define DATALINK_IRONMAN 4
+
+#define DEF_LPTRANSINFO 1
+
+extern int (*dl_error_proc) (char *);
+extern int (*dl_warn_proc) (char *);
+
+/* Function definitions. */
+
+void dl_add_to_list(ListPtr, ItemPtr);
+int dl_anniv_by_date(ItemPtr, ItemPtr);
+int dl_anniv_by_label(ItemPtr, ItemPtr);
+int dl_app_by_datetime(ItemPtr, ItemPtr);
+int dl_app_by_label(ItemPtr, ItemPtr);
+unsigned short int dl_docrc(unsigned char *);
+void dl_fill_pack_ascii(unsigned char *, unsigned char *, int, char);
+void dl_free_download(void);
+int dl_init_download(WatchInfoPtr, ListPtr, ListPtr, ListPtr, ListPtr,
+ ListPtr, ListPtr, ListPtr, ListPtr, ListPtr, ListPtr,
+ ListPtr);
+WatchInfoPtr dl_init_watch(int);
+int dl_item_ok(WatchInfoPtr, ItemPtr);
+ItemPtr dl_new_item(WatchInfoPtr, int);
+ListPtr dl_new_list(void);
+int dl_pack_ascii(unsigned char *, unsigned char *);
+int dl_pack_char(char);
+int dl_pack_digit(char);
+void dl_pack_phone(unsigned char *, unsigned char *, int);
+int dl_pack_size(char *);
+int dl_phone_by_label(ItemPtr, ItemPtr);
+WatchInfoPtr dl_read_save(char *, int, ListPtr *, ListPtr *, ListPtr *,
+ ListPtr *, ListPtr *, ListPtr *, ListPtr *,
+ ListPtr *, ListPtr *, ListPtr *, ListPtr *);
+int dl_send_data(WatchInfoPtr, int);
+void dl_set_error(int (*)());
+void dl_set_warn(int (*)());
+int dl_sizeof_item(WatchInfoPtr, ItemPtr);
+int dl_sizeof_list(WatchInfoPtr, ListPtr);
+int dl_sort(ListPtr, int (*)());
+int dl_string_ok(char *, int);
+int dl_todo_by_label(ItemPtr, ItemPtr);
+int dl_todo_by_prio(ItemPtr, ItemPtr);
+int dl_write_save(char *, char *, char *);
+
+int open_vt();
+void close_vt(int oldvt);
+int send_data(int type, unsigned char **packets, int npckts);
+
+#endif /* __DATALINK_H__ */
diff --git a/datalink_macros.h b/datalink_macros.h
new file mode 100644
index 0000000..8dbc9b4
--- /dev/null
+++ b/datalink_macros.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * SVGA Macros for sending data to the datalink watch.
+ *
+ * Modified by David Fries <dfries@mail.win.org> 7/11/99
+ * - Added support for the Timex Datalink Ironman Triathlon
+ * - Modified the screen position and only send half the initial sync signals
+ *
+ */
+
+// This defines which line to start field 1 at
+#define START1 70
+// The line to start field 2 at
+#define START2 255
+// the distance between lines in each field
+#define SPACE 15
+
+#define WRITE_BYTE1(sb, byte) { \
+ int pos = START1; \
+ register int mask = 0x1; \
+ if (sb) \
+ vga_drawscanline(pos, white); \
+ else \
+ vga_drawscanline(pos, black); \
+ pos += SPACE; \
+ while (mask < 0xff) { \
+ if (mask&byte) \
+ vga_drawscanline(pos, black); \
+ else \
+ vga_drawscanline(pos, white); \
+ pos += SPACE; \
+ mask = mask << 1; \
+ } \
+}
+
+#define WRITE_BYTE2(sb, byte) { \
+ int pos = START2; \
+ register int mask = 1; \
+ if (sb) \
+ vga_drawscanline(pos, white); \
+ else \
+ vga_drawscanline(pos, black); \
+ pos += SPACE; \
+ while (mask < 0xff) { \
+ if (mask&byte) \
+ vga_drawscanline(pos, black); \
+ else \
+ vga_drawscanline(pos, white); \
+ pos += SPACE; \
+ mask = mask << 1; \
+ } \
+}
+
+#define END_PACKET { \
+ vga_waitretrace(); \
+ WRITE_BYTE1(0, 0xff) \
+ WRITE_BYTE2(0, 0xff) \
+ {int i; for (i = 0; i < (10+((type==DATALINK_IRONMAN)?2:0)); i++) \
+ vga_waitretrace();} \
+}
+
+/* how many syncs to give to begin with, was 400 */
+#define SYNC { \
+ register int i; \
+ for (i = 0; i < 200; i++) { \
+ vga_waitretrace(); \
+ WRITE_BYTE1(1, 0x55) \
+ WRITE_BYTE2(1, 0x55) \
+ } \
+ END_PACKET \
+}
+
+#define DATASTART { \
+ register int i; \
+ for (i = 0; i < 50; i++) { \
+ vga_waitretrace(); \
+ WRITE_BYTE1(1, 0xAA) \
+ } \
+ END_PACKET \
+}
diff --git a/datalink_private.h b/datalink_private.h
new file mode 100644
index 0000000..2c95692
--- /dev/null
+++ b/datalink_private.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __DATALINK_PRIVATE_H__
+#define __DATALINK_PRIVATE_H__
+
+typedef struct download_s
+{
+ int num_times;
+ TimePtr times;
+ int num_alarms;
+ AlarmPtr alarms;
+ int num_chron;
+ int max_chron_str;
+ ChronPtr chron;
+ int num_timers;
+ TimerPtr timers;
+ int memory;
+ int num_apps;
+ int app_size;
+ int pre_notification_time;
+ AppointmentPtr apps;
+ int num_todos;
+ int todo_size;
+ ToDoPtr todos;
+ int max_alarm_str;
+ int max_phone_str;
+ int max_timer_str;
+ int num_phones;
+ int phone_size;
+ PhonePtr phones;
+ int num_annivs;
+ int anniv_size;
+ AnniversaryPtr annivs;
+ int num_system;
+ SystemPtr system;
+ int num_wristapp;
+ WristAppPtr wristapp;
+ int num_melody;
+ MelodyPtr melody;
+} Download, *DownloadPtr;
+
+extern Download dl_download_data;
+
+#endif /* __DATALINK_PRIVATE_H__ */
diff --git a/dataread.l b/dataread.l
new file mode 100644
index 0000000..b452ef7
--- /dev/null
+++ b/dataread.l
@@ -0,0 +1,57 @@
+%{
+#include <string.h>
+#include "y.tab.h"
+int line_num = 1;
+%}
+%option noyywrap
+%%
+
+\"[^"\n]* {
+ if (dl_text[yyleng - 1] == '\\')
+ yymore();
+ else {
+ strcpy(dl_lval.string,&yytext[1]);
+
+ if (input() != '"') {
+ fprintf(stderr,"EOL found inside \" on line %d\n",line_num);
+ return(-1);
+ }
+ return(STRING);
+ }
+ };
+[a-zA-Z][a-zA-Z0-9.-_]* {
+ strcpy(dl_lval.string, yytext);
+ return(NAME);
+ };
+[0-9]{1,2}[:][0-9]{1,2}[:][0-9]{1,2} {
+ return(TIME);
+ };
+[0-9]{1,2}[:][0-9]{1,2} {
+ sprintf(dl_lval.string, "%s:00", yytext);
+ return(TIME);
+ };
+[0-9]{1,2}[/][0-9]{1,2}[/][0-9]{1,4} {
+ return(DATE);
+ };
+[0-9]{1,2}[/][0-9]{1,2} {
+ sprintf(dl_lval.string, "%s/00", yytext);
+ return(DATE);
+ };
+[0-9]+ {
+ dl_lval.integer = atoi(yytext);
+ return(INTEGER);
+ };
+-[0-9]+ {
+ dl_lval.integer = atoi(yytext);
+ return(INTEGER);
+ };
+[\[\]{}(),:=] {return(yytext[0]);};
+\n {line_num++; return(yytext[0]);};
+\\\n ;
+[ \t]* ;
+#.* ;
+. {
+ fprintf(stderr,"Bad datalink save file (%s).\n", yytext);
+ return(BAD);
+};
+%%
diff --git a/dataread.y b/dataread.y
new file mode 100644
index 0000000..218f51f
--- /dev/null
+++ b/dataread.y
@@ -0,0 +1,619 @@
+%{
+ /*
+ *
+ * Modified by David Fries <dfries@mail.win.org> 7/11/99
+ * - Added support for the Timex Datalink Ironman Triathlon
+ */
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "datalink.h"
+
+extern int line_num;
+
+#define ALARM 0
+#define APP 1
+#define PHONE 2
+#define TODO 3
+#define ANNIV 4
+#define SYSTEM 5
+#define WRISTAPP 6
+#define MELODY 7
+#define TIMEZONE 8
+#define DATA 9
+#define INTVAL 10
+#define TIMER 11
+#define CHRON 12
+#define NUMLISTS 13
+
+int dl_error(char *s);
+
+static ListPtr *lists = NULL;
+static ItemPtr ip = NULL;
+static char buf[1024];
+static int hour, minute, second, month, day, year;
+static int repeat, chron;
+static int prio, audible, chime, beep, pos;
+static int val, tfmt, dfmt;
+static char msg[64];
+static char phnum[64];
+static WatchInfoPtr wi;
+static int watch_type;
+
+%}
+%token NAME INTEGER STRING TIME DATE BAD
+
+%union {
+ char string[1024];
+ int integer;
+}
+
+%left <string> NAME
+%left <string> STRING
+%left <integer> INTEGER
+%left <string> TIME
+%left <string> DATE
+
+%type <integer> value
+
+%%
+
+data : item
+ | data item
+ ;
+
+item : NAME '=' value '\n'
+{
+ int fd;
+ char file[1024];
+ unsigned char mask;
+ int min;
+ struct stat sbuf;
+ int l;
+ int i;
+
+ if (!lists) {
+ wi = dl_init_watch(watch_type);
+
+ if ((lists = (ListPtr *)calloc(NUMLISTS, sizeof(ListPtr))) == NULL) {
+ dl_error("Could not allocate List list.");
+ return(-1);
+ }
+
+ for (i = 0; i < NUMLISTS; i++) {
+
+ if (!(lists[i] = dl_new_list())) {
+ dl_error("Could not allocate item list.");
+ return(-1);
+ }
+
+ }
+
+ }
+
+ switch ($3) {
+ case ALARM:
+
+ if (strcmp($1, "alarm")) {
+ sprintf(buf, "Bad entry, %s = alarm.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_ALARM_TYPE))) {
+ dl_error("Could not allocate alarm item.");
+ return(-1);
+ }
+
+ ip->data.alarm.alarm_num = pos;
+ ip->data.alarm.hours = hour;
+ ip->data.alarm.minutes = minute;
+ ip->data.alarm.month = month;
+ ip->data.alarm.day = day;
+ ip->data.alarm.audible = audible;
+ l = strlen(msg);
+
+ if (l > wi->max_alarm_str)
+ l = wi->max_alarm_str;
+
+ if ((ip->data.alarm.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate alarm label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.alarm.label, msg, l);
+ ip->data.alarm.label[l] = '\0';
+ dl_add_to_list(lists[ALARM], ip);
+ break;
+
+ case CHRON:
+ if (strcmp($1, "chron")) {
+ sprintf(buf, "Bad entry, %s = chron.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_CHRON_TYPE))) {
+ dl_error("Could not allocate chron item.");
+ return(-1);
+ }
+
+ ip->data.chron.chron_laps = pos;
+ l = strlen(msg);
+
+ if (l > wi->max_chron_str)
+ l = wi->max_chron_str;
+
+ if ((ip->data.chron.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate chron label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.chron.label, msg, l);
+ ip->data.chron.label[l] = '\0';
+ dl_add_to_list(lists[CHRON], ip);
+ break;
+
+ case TIMER:
+ if (strcmp($1, "timer")) {
+ sprintf(buf, "Bad entry, %s = timer.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_TIMER_TYPE))) {
+ dl_error("Could not allocate timer item.");
+ return(-1);
+ }
+
+ ip->data.timer.timer_num = pos;
+ ip->data.timer.hours = hour;
+ ip->data.timer.minutes = minute;
+ ip->data.timer.second = second;
+ ip->data.timer.repeat = repeat;
+ ip->data.timer.chron = chron;
+ l = strlen(msg);
+
+ if (l > wi->max_timer_str)
+ l = wi->max_timer_str;
+
+ if ((ip->data.timer.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate timer label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.timer.label, msg, l);
+ ip->data.timer.label[l] = '\0';
+ dl_add_to_list(lists[TIMER], ip);
+ break;
+ case APP:
+
+ if (strcmp($1, "appointment")) {
+ sprintf(buf, "Bad entry, %s = appointment.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_APP_TYPE))) {
+ dl_error("Could not allocate appointment item.");
+ return(-1);
+ }
+
+ ip->data.app.month = month;
+ ip->data.app.day = day;
+ minute = hour*60+minute;
+ ip->data.app.time = 0;
+
+ for (min = 960, mask = 0x40; mask; mask >>= 1, min /= 2) {
+
+ if (minute >= min) {
+ ip->data.app.time |= mask;
+ minute -= min;
+ }
+
+ }
+
+ l = strlen(msg);
+
+ if (l > wi->max_str)
+ l = wi->max_str;
+
+ if ((ip->data.app.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate appointment label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.app.label, msg, l);
+ ip->data.app.label[l] = '\0';
+ dl_add_to_list(lists[APP], ip);
+ break;
+ case PHONE:
+
+ if (strcmp($1, "phone")) {
+ sprintf(buf, "Bad entry, %s = phone.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_PHONE_TYPE))) {
+ dl_error("Could not allocate phone item.");
+ return(-1);
+ }
+
+ l = strlen(phnum);
+
+ if (l > wi->max_phone_str)
+ l = wi->max_phone_str;
+
+ if ((ip->data.phone.number = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate phone number.");
+ return(-1);
+ }
+
+ strncpy(ip->data.phone.number, phnum, l);
+ ip->data.phone.number[l] = '\0';
+
+ l = strlen(msg);
+
+ if (l > wi->max_str)
+ l = wi->max_str;
+
+ if ((ip->data.phone.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate phone label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.phone.label, msg, l);
+ ip->data.phone.label[l] = '\0';
+ dl_add_to_list(lists[PHONE], ip);
+ break;
+ case TODO:
+
+ if (strcmp($1, "todo")) {
+ sprintf(buf, "Bad entry, %s = todo.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_TODO_TYPE))) {
+ dl_error("Could not allocate todo item.");
+ return(-1);
+ }
+
+ ip->data.todo.priority = prio;
+ l = strlen(msg);
+
+ if (l > wi->max_str)
+ l = wi->max_str;
+
+ if ((ip->data.todo.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate todo label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.todo.label, msg, l);
+ ip->data.todo.label[l] = '\0';
+ dl_add_to_list(lists[TODO], ip);
+ break;
+ case ANNIV:
+
+ if (strcmp($1, "anniversary")) {
+ sprintf(buf, "Bad entry, %s = anniversary.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_ANNIV_TYPE))) {
+ dl_error("Could not allocate anniversary item.");
+ return(-1);
+ }
+
+ ip->data.anniv.month = month;
+ ip->data.anniv.day = day;
+
+ l = strlen(msg);
+
+ if (l > wi->max_str)
+ l = wi->max_str;
+
+ if ((ip->data.anniv.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate anniversary label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.anniv.label, msg, l);
+ ip->data.anniv.label[l] = '\0';
+ dl_add_to_list(lists[ANNIV], ip);
+ break;
+ case SYSTEM:
+
+ if (strcmp($1, "system")) {
+ sprintf(buf, "Bad entry, %s = system.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_SYSTEM_TYPE))) {
+ dl_error("Could not allocate system item.");
+ return(-1);
+ }
+
+ ip->data.system.chime = chime;
+ ip->data.system.beep = beep;
+ dl_add_to_list(lists[SYSTEM], ip);
+ break;
+ case DATA:
+
+ if (*msg == '~')
+ sprintf(file, "%s%s", getenv("HOME"), &msg[1]);
+ else
+ strcpy(file, msg);
+
+ if ((fd = open(file, O_RDONLY)) < 0) {
+ sprintf(buf, "Could not open %s for reading %s.", file, $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (fstat(fd, &sbuf) < 0) {
+ sprintf(buf, "Could not stat %s for %s.", file, $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (strcmp($1, "wristapp") == 0) {
+
+ if (!(ip = dl_new_item(wi, DL_WRISTAPP_TYPE))) {
+ dl_error("Could not allocate system item.");
+ return(-1);
+ }
+
+ }
+ else if (strcmp($1, "melody") == 0) {
+
+ if (!(ip = dl_new_item(wi, DL_MELODY_TYPE))) {
+ dl_error("Could not allocate system item.");
+ return(-1);
+ }
+
+ }
+ else {
+ sprintf(buf, "Bad entry, %s = string.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ ip->data.wristapp.len = sbuf.st_size;
+
+ if ((ip->data.wristapp.data = (char *)malloc(sbuf.st_size)) == NULL) {
+ sprintf(buf, "Could not allocate data for %s.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (read(fd, ip->data.wristapp.data, sbuf.st_size) != sbuf.st_size) {
+ sprintf(buf, "Could not read data for %s from %s.", $1, file);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (strcmp($1, "wristapp") == 0)
+ dl_add_to_list(lists[WRISTAPP], ip);
+ else
+ dl_add_to_list(lists[MELODY], ip);
+
+ break;
+ case INTVAL:
+
+ if (strcmp($1, "time_adjust") == 0) {
+ wi->time_adjust = val;
+ }
+ else if (strcmp($1, "pre_notification_time") == 0) {
+ wi->pre_notification_time = val;
+ }
+ else {
+ sprintf(buf, "Bad entry, %s = intval.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ break;
+ case TIMEZONE:
+
+ if (strcmp($1, "timezone")) {
+ sprintf(buf, "Bad entry, %s = timezone.", $1);
+ dl_error(buf);
+ return(-1);
+ }
+
+ if (!(ip = dl_new_item(wi, DL_TIME_TYPE))) {
+ dl_error("Could not allocate timezone item.");
+ return(-1);
+ }
+
+ l = strlen(msg);
+
+ if (l > wi->max_tzlen)
+ l = wi->max_tzlen;
+
+ if ((ip->data.time.label = (char *)malloc(l + 1)) == NULL) {
+ dl_error("Could not allocate timezone label.");
+ return(-1);
+ }
+
+ strncpy(ip->data.time.label, msg, l);
+ ip->data.time.label[l] = '\0';
+ ip->data.time.offset = minute;
+ ip->data.time.tz_num = pos;
+ ip->data.time.month = 1;
+ ip->data.time.day = 1;
+ ip->data.time.hour_fmt = tfmt;
+ ip->data.time.date_fmt = dfmt;
+ dl_add_to_list(lists[TIMEZONE], ip);
+ break;
+ default:
+ dl_error("Internal Error, unknown type.");
+ return(-1);
+ }
+
+}
+ | '\n'
+ ;
+
+value : INTEGER ',' DATE ',' TIME ',' STRING ',' INTEGER
+ /* Alarm */
+ {
+ pos = $1;
+ sscanf($3, "%d/%d/%d", &month, &day, &year);
+ sscanf($5, "%d:%d:%d", &hour, &minute, &second);
+ strcpy(msg, $7);
+ audible = $9;
+ $$ = ALARM;
+ }
+
+ | INTEGER ',' STRING ',' STRING ',' INTEGER ',' INTEGER
+ /* Timer */
+ {
+ pos = $1;
+ sscanf($3, "%d:%d:%d", &hour, &minute, &second);
+ strcpy(msg, $5);
+ repeat = $7;
+ chron = $9;
+ $$ = TIMER;
+ }
+
+ | STRING ',' INTEGER
+ /* Chron */
+ {
+ strcpy(msg, $1);
+ pos = $3;
+ $$ = CHRON;
+ }
+
+ | DATE ',' TIME ',' STRING
+ /* Appointment */
+ {
+ sscanf($1, "%d/%d/%d", &month, &day, &year);
+ sscanf($3, "%d:%d:%d", &hour, &minute, &second);
+ strcpy(msg, $5);
+ $$ = APP;
+ }
+ | INTEGER ',' STRING
+ /* To do */
+ {
+ prio = $1;
+ strcpy(msg, $3);
+ $$ = TODO;
+ }
+ | STRING ',' STRING
+ /* Phone */
+ {
+ strcpy(phnum, $1);
+ strcpy(msg, $3);
+ $$ = PHONE;
+ }
+ | DATE ',' STRING
+ /* Anniversary */
+ {
+ sscanf($1, "%d/%d/%d", &month, &day, &year);
+ strcpy(msg, $3);
+ $$ = ANNIV;
+ }
+ | INTEGER ',' INTEGER
+ /* System */
+ {
+ chime = $1;
+ beep = $3;
+ $$ = SYSTEM;
+ }
+ | INTEGER ',' STRING ',' INTEGER ',' INTEGER ',' INTEGER
+ /* Timezone */
+ {
+ pos = $1;
+ strcpy(msg, $3);
+ minute = $5;
+ tfmt = $7;
+ dfmt = $9;
+ $$ = TIMEZONE;
+ }
+ | STRING
+ {
+ strcpy(msg, $1);
+ $$ = DATA;
+ }
+ | INTEGER
+ {
+ val = $1;
+ $$ = INTVAL;
+ }
+ ;
+
+%%
+int dl_error(char *s)
+{
+ char buf[1024];
+
+ snprintf(buf, sizeof buf,"%s on line %d.",s,line_num);
+ (*dl_error_proc)(buf);
+ return 0;
+}
+
+extern FILE *dl_in;
+
+WatchInfoPtr
+dl_read_save(datafile, type, times, alarms, chron, timers, apps, todos,
+ phones, annivs, system, wristapp, melody)
+char *datafile;
+int type;
+ListPtr *times;
+ListPtr *alarms;
+ListPtr *chron;
+ListPtr *timers;
+ListPtr *apps;
+ListPtr *todos;
+ListPtr *phones;
+ListPtr *annivs;
+ListPtr *system;
+ListPtr *wristapp;
+ListPtr *melody;
+{
+ char file[1024];
+ char buf[1024];
+ int r;
+
+ if (*datafile == '~')
+ sprintf(file, "%s%s", getenv("HOME"), &datafile[1]);
+ else
+ strcpy(file, datafile);
+
+ watch_type = type;
+
+ if ((dl_in = fopen(file,"r")) == NULL) {
+ sprintf(buf,"Could not open %s for reading.", file);
+ (*dl_error_proc)(buf);
+ return(NULL);
+ }
+
+ r = dl_parse();
+ fclose(dl_in);
+
+ if (r)
+ return(NULL);
+
+ *alarms = lists[ALARM];
+ *chron = lists[CHRON];
+ *timers = lists[TIMER];
+ *apps = lists[APP];
+ *phones = lists[PHONE];
+ *todos = lists[TODO];
+ *annivs = lists[ANNIV];
+ *system = lists[SYSTEM];
+ *wristapp = lists[WRISTAPP];
+ *melody = lists[MELODY];
+ *times = lists[TIMEZONE];
+ free(lists);
+ return(wi);
+}
diff --git a/dl_add_to_list.c b/dl_add_to_list.c
new file mode 100644
index 0000000..e129653
--- /dev/null
+++ b/dl_add_to_list.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+
+void dl_add_to_list(ListPtr list, ItemPtr item)
+{
+
+ if (list->last)
+ {
+ list->last = list->last->next = item;
+ list->count++;
+ } else
+ {
+ list->first = list->last = item;
+ list->count = 1;
+ }
+
+}
diff --git a/dl_anniv_by_date.c b/dl_anniv_by_date.c
new file mode 100644
index 0000000..1764d80
--- /dev/null
+++ b/dl_anniv_by_date.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+
+int dl_anniv_by_date(ItemPtr a, ItemPtr b)
+{
+ int r;
+
+ r = a->data.anniv.month - b->data.anniv.month;
+
+ if (r)
+ return (r);
+
+ return (a->data.anniv.day - b->data.anniv.day);
+}
diff --git a/dl_anniv_by_label.c b/dl_anniv_by_label.c
new file mode 100644
index 0000000..c2ae29e
--- /dev/null
+++ b/dl_anniv_by_label.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+
+int dl_anniv_by_label(ItemPtr a, ItemPtr b)
+{
+ return (strcmp(a->data.anniv.label, b->data.anniv.label));
+}
diff --git a/dl_app_by_datetime.c b/dl_app_by_datetime.c
new file mode 100644
index 0000000..07bffa9
--- /dev/null
+++ b/dl_app_by_datetime.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+
+int dl_app_by_datetime(ItemPtr a, ItemPtr b)
+{
+ int r;
+
+ r = a->data.app.month - b->data.app.month;
+
+ if (r)
+ return (r);
+
+ r = a->data.app.day - b->data.app.day;
+
+ if (r)
+ return (r);
+
+ return (a->data.app.time - b->data.app.time);
+}
diff --git a/dl_app_by_label.c b/dl_app_by_label.c
new file mode 100644
index 0000000..e4f2ee9
--- /dev/null
+++ b/dl_app_by_label.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+
+int dl_app_by_label(ItemPtr a, ItemPtr b)
+{
+ return (strcmp(a->data.app.label, b->data.app.label));
+}
diff --git a/dl_docrc.c b/dl_docrc.c
new file mode 100644
index 0000000..18a6cca
--- /dev/null
+++ b/dl_docrc.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* crc lookup table */
+static unsigned short int crc16_table[16] = {
+ 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
+ 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
+};
+
+unsigned short int dl_docrc(unsigned char *data)
+{
+ int i;
+ unsigned short int t;
+ unsigned short int crc = 0;
+ int l;
+
+ l = data[0] - 2;
+
+ for (i = 0; i < l; i++)
+ {
+ t = crc16_table[crc & 0xF];
+ crc = (crc >> 4) & 0x0FFF;
+ crc = crc ^ t ^ crc16_table[data[i] & 0xF];
+
+ /* upper 4 bits */
+ t = crc16_table[crc & 0xF];
+ crc = (crc >> 4) & 0x0FFF;
+ crc = crc ^ t ^ crc16_table[(data[i] >> 4) & 0xF];
+ }
+
+ data[l++] = crc >> 8;
+ data[l] = crc & 0xff;
+ return (crc);
+}
diff --git a/dl_fill_pack_ascii.c b/dl_fill_pack_ascii.c
new file mode 100644
index 0000000..cc73634
--- /dev/null
+++ b/dl_fill_pack_ascii.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+
+void dl_fill_pack_ascii(unsigned char * to, unsigned char * from, int size,
+ char fill)
+{
+ int l = strlen(from);
+ int i;
+
+ if (l > size)
+ l = size;
+
+ for (i = 0; i < l; i++)
+ to[i] = dl_pack_char(from[i]);
+
+ for (i = l; i < size; i++)
+ to[i] = dl_pack_char(fill);
+
+}
diff --git a/dl_free_download.c b/dl_free_download.c
new file mode 100644
index 0000000..cfd69a7
--- /dev/null
+++ b/dl_free_download.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "datalink.h"
+#include "datalink_private.h"
+
+
+void dl_free_download()
+{
+/* Free up old download structure if it exists. */
+ if (dl_download_data.times)
+ free(dl_download_data.times);
+
+ if (dl_download_data.alarms)
+ free(dl_download_data.alarms);
+
+ if (dl_download_data.timers)
+ free(dl_download_data.timers);
+
+ if (dl_download_data.apps)
+ free(dl_download_data.apps);
+
+ if (dl_download_data.chron)
+ free(dl_download_data.chron);
+
+ if (dl_download_data.phones)
+ free(dl_download_data.phones);
+
+ if (dl_download_data.todos)
+ free(dl_download_data.todos);
+
+ if (dl_download_data.annivs)
+ free(dl_download_data.annivs);
+
+ if (dl_download_data.system)
+ free(dl_download_data.system);
+
+ if (dl_download_data.wristapp)
+ free(dl_download_data.wristapp);
+
+ if (dl_download_data.melody)
+ free(dl_download_data.melody);
+
+ memset((char *) &dl_download_data, 0, sizeof(Download));
+}
diff --git a/dl_init_download.c b/dl_init_download.c
new file mode 100644
index 0000000..92dc9c8
--- /dev/null
+++ b/dl_init_download.c
@@ -0,0 +1,607 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "datalink.h"
+#include "datalink_private.h"
+
+int
+dl_init_download(WatchInfoPtr wi, ListPtr times, ListPtr alarms,
+ ListPtr chron, ListPtr timers, ListPtr apps, ListPtr todos,
+ ListPtr phones, ListPtr annivs, ListPtr system, ListPtr wristapp,
+ ListPtr melody)
+{
+ ItemPtr ip;
+ char buf[1024];
+ int i;
+ int last_warn = 0;
+
+/* Free up old download structure if it exists. */
+ dl_free_download();
+
+ dl_download_data.memory = 0;
+ dl_download_data.app_size = 0;
+ dl_download_data.phone_size = 0;
+ dl_download_data.todo_size = 0;
+ dl_download_data.anniv_size = 0;
+ dl_download_data.pre_notification_time = wi->pre_notification_time;
+ dl_download_data.max_alarm_str = wi->max_alarm_str;
+ dl_download_data.max_timer_str = wi->max_timer_str;
+ dl_download_data.max_phone_str = wi->max_phone_str;
+ dl_download_data.max_chron_str = wi->max_chron_str;
+
+/* Count and verify items. */
+ if (times && times->download)
+ {
+
+ for (i = 0, ip = times->first; ip; ip = ip->next, i++)
+ {
+
+ if (!ip->data.time.tz_num)
+ ip->data.time.tz_num = i + 1;
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad time item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_tz)
+ return ((*dl_error_proc)
+ ("Too many time items."));
+
+ }
+
+ if (i != times->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Time count value incorrect.");
+ times->count = i;
+ }
+
+ }
+
+ if (chron && chron->download)
+ {
+
+ for (i = 0, ip = chron->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad chron item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_chrons)
+ return ((*dl_error_proc)
+ ("Too many chron items."));
+
+ }
+
+ if (i != chron->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Chron count value incorrect.");
+ chron->count = i;
+ }
+
+ }
+
+ if (alarms && alarms->download)
+ {
+
+ for (i = 0, ip = alarms->first; ip; ip = ip->next, i++)
+ {
+
+ if (!ip->data.alarm.alarm_num)
+ ip->data.alarm.alarm_num = i + 1;
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad alarm item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_alarms)
+ return ((*dl_error_proc)
+ ("Too many alarm items."));
+
+ }
+
+ if (i != alarms->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Alarm count value incorrect.");
+ alarms->count = i;
+ }
+
+ }
+
+ if (timers && timers->download)
+ {
+
+ for (i = 0, ip = timers->first; ip; ip = ip->next, i++)
+ {
+
+ if (!ip->data.timer.timer_num)
+ ip->data.timer.timer_num = i + 1;
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad timer item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_timers)
+ return ((*dl_error_proc)
+ ("Too many timer items."));
+
+ }
+
+ if (i != timers->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Timer count value incorrect.");
+ timers->count = i;
+ }
+
+ }
+
+ if (apps && apps->download)
+ {
+
+ for (i = 0, ip = apps->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad appointment item #%d",
+ i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_apps)
+ return ((*dl_error_proc)
+ ("Too many appointment items."));
+
+ dl_download_data.memory += dl_sizeof_item(wi, ip);
+ dl_download_data.app_size +=
+ dl_sizeof_item(wi, ip);
+ }
+
+ if (i != apps->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Appointment count value incorrect.");
+ apps->count = i;
+ }
+
+ }
+
+ if (todos && todos->download)
+ {
+
+ for (i = 0, ip = todos->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad todo item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_todos)
+ return ((*dl_error_proc)
+ ("Too many todo items."));
+
+ dl_download_data.memory += dl_sizeof_item(wi, ip);
+ dl_download_data.todo_size +=
+ dl_sizeof_item(wi, ip);
+ }
+
+ if (i != todos->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("To Do count value incorrect.");
+ todos->count = i;
+ }
+
+ }
+
+ if (phones && phones->download)
+ {
+
+ for (i = 0, ip = phones->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad phone item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_phones)
+ return ((*dl_error_proc)
+ ("Too many phone items."));
+
+ dl_download_data.memory += dl_sizeof_item(wi, ip);
+ dl_download_data.phone_size +=
+ dl_sizeof_item(wi, ip);
+ }
+
+ if (i != phones->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Phone count value incorrect.");
+ phones->count = i;
+ }
+
+ }
+
+ if (annivs && annivs->download)
+ {
+
+ for (i = 0, ip = annivs->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad anniversary item #%d",
+ i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_annivs)
+ return ((*dl_error_proc)
+ ("Too many anniversary items."));
+
+ dl_download_data.memory += dl_sizeof_item(wi, ip);
+ dl_download_data.anniv_size +=
+ dl_sizeof_item(wi, ip);
+ }
+
+ if (i != annivs->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Anniversary count value incorrect.");
+ annivs->count = i;
+ }
+
+ }
+
+ if (system && system->download)
+ {
+
+ for (i = 0, ip = system->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad sytem item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_system)
+ return ((*dl_error_proc)
+ ("Too many sytem items."));
+
+ }
+
+ if (i != system->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("System count value incorrect.");
+ system->count = i;
+ }
+
+ }
+
+ if (wristapp && wristapp->download)
+ {
+
+ for (i = 0, ip = wristapp->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad wristapp item #%d",
+ i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_wristapp)
+ return ((*dl_error_proc)
+ ("Too many wristapp items."));
+
+ }
+
+ if (i != wristapp->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("WristApp count value incorrect.");
+ wristapp->count = i;
+ }
+
+ }
+
+ if (melody && melody->download)
+ {
+
+ for (i = 0, ip = melody->first; ip; ip = ip->next, i++)
+ {
+
+ if (!dl_item_ok(wi, ip))
+ {
+ sprintf(buf, "Bad melody item #%d", i + 1);
+ return ((*dl_error_proc) (buf));
+ }
+
+ if (i >= wi->max_melody)
+ return ((*dl_error_proc)
+ ("Too many melody items."));
+
+ }
+
+ if (i != melody->count)
+ {
+ last_warn =
+ (*dl_warn_proc)
+ ("Melody count value incorrect.");
+ melody->count = i;
+ }
+
+ }
+
+/* Check to see if memory usage has been exceeded. */
+
+ if (dl_download_data.memory > wi->max_mem)
+ return ((*dl_error_proc) ("Too much data."));
+
+/* OK. We know we have valid data that will fit in the watch. Allocate
+ download structure. */
+
+ if (times && times->download)
+ {
+
+ if ((dl_download_data.times =
+ (TimePtr) calloc(times->count, sizeof(Time))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate time download data."));
+
+ dl_download_data.num_times = times->count;
+
+ for (i = 0, ip = times->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.times[i],
+ (char *) &ip->data.time, sizeof(Time));
+ }
+
+ }
+
+ if (chron && chron->download)
+ {
+
+ if ((dl_download_data.chron =
+ (ChronPtr) calloc(chron->count,
+ sizeof(Chron))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate chron download data."));
+
+ dl_download_data.num_chron = chron->count;
+
+ for (i = 0, ip = chron->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.chron[i],
+ (char *) &ip->data.chron, sizeof(Chron));
+ dl_download_data.chron[i].memused =
+ 14 + 4 * dl_download_data.chron[i].chron_laps;
+ }
+
+ }
+
+ if (alarms && alarms->download)
+ {
+
+ if ((dl_download_data.alarms =
+ (AlarmPtr) calloc(alarms->count,
+ sizeof(Alarm))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate alarm download data."));
+
+ dl_download_data.num_alarms = alarms->count;
+
+ for (i = 0, ip = alarms->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.alarms[i],
+ (char *) &ip->data.alarm, sizeof(Alarm));
+ }
+
+ }
+
+ if (timers && timers->download)
+ {
+
+ if ((dl_download_data.timers =
+ (TimerPtr) calloc(timers->count,
+ sizeof(Timer))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate timer download data."));
+
+ dl_download_data.num_timers = timers->count;
+
+ for (i = 0, ip = timers->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.timers[i],
+ (char *) &ip->data.timer, sizeof(Timer));
+ }
+
+ }
+
+ if (apps && apps->download)
+ {
+
+ if ((dl_download_data.apps =
+ (AppointmentPtr) calloc(apps->count,
+ sizeof(Appointment))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate appointment download data."));
+
+ dl_download_data.num_apps = apps->count;
+
+ for (i = 0, ip = apps->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.apps[i],
+ (char *) &ip->data.app,
+ sizeof(Appointment));
+ }
+
+ }
+
+ if (todos && todos->download)
+ {
+
+ if ((dl_download_data.todos =
+ (ToDoPtr) calloc(todos->count, sizeof(ToDo))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate todo download data."));
+
+ dl_download_data.num_todos = todos->count;
+
+ for (i = 0, ip = todos->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.todos[i],
+ (char *) &ip->data.todo, sizeof(ToDo));
+ }
+
+ }
+
+ if (phones && phones->download)
+ {
+
+ if ((dl_download_data.phones =
+ (PhonePtr) calloc(phones->count,
+ sizeof(Phone))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate phone download data."));
+
+ dl_download_data.num_phones = phones->count;
+
+ for (i = 0, ip = phones->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.phones[i],
+ (char *) &ip->data.phone, sizeof(Phone));
+ }
+
+ }
+
+ if (annivs && annivs->download)
+ {
+
+ if ((dl_download_data.annivs =
+ (AnniversaryPtr) calloc(annivs->count,
+ sizeof(Anniversary))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate anniversary download data."));
+
+ dl_download_data.num_annivs = annivs->count;
+
+ for (i = 0, ip = annivs->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.annivs[i],
+ (char *) &ip->data.anniv,
+ sizeof(Anniversary));
+ }
+
+ }
+
+ if (system && system->download)
+ {
+
+ if ((dl_download_data.system =
+ (SystemPtr) calloc(system->count,
+ sizeof(System))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate system download data."));
+
+ dl_download_data.num_system = system->count;
+
+ for (i = 0, ip = system->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.system[i],
+ (char *) &ip->data.system, sizeof(System));
+ }
+
+ }
+
+ if (wristapp && wristapp->download)
+ {
+
+ if ((dl_download_data.wristapp =
+ (WristAppPtr) calloc(wristapp->count,
+ sizeof(WristApp))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate wristapp download data."));
+
+ dl_download_data.num_wristapp = wristapp->count;
+
+ for (i = 0, ip = wristapp->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.wristapp[i],
+ (char *) &ip->data.wristapp,
+ sizeof(WristApp));
+ }
+
+ }
+
+ if (melody && melody->download)
+ {
+
+ if ((dl_download_data.melody =
+ (MelodyPtr) calloc(melody->count,
+ sizeof(Melody))) == NULL)
+ return ((*dl_error_proc)
+ ("Can't allocate melody download data."));
+
+ dl_download_data.num_melody = melody->count;
+
+ for (i = 0, ip = melody->first; ip; ip = ip->next, i++)
+ {
+ memcpy((char *) &dl_download_data.melody[i],
+ (char *) &ip->data.melody, sizeof(Melody));
+ }
+
+ }
+
+ return (0);
+}
diff --git a/dl_init_watch.c b/dl_init_watch.c
new file mode 100644
index 0000000..9cfc929
--- /dev/null
+++ b/dl_init_watch.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "datalink.h"
+#include "datalink_private.h"
+
+int (*dl_error_proc) (char *);
+int (*dl_warn_proc) (char *);
+
+Download dl_download_data = { 0 };
+
+int dl_default_error(char *msg)
+{
+ fprintf(stderr, "ERROR: %s\n", msg);
+ return (-1);
+}
+
+int dl_default_warn(char *msg)
+{
+ fprintf(stderr, "WARNING: %s\n", msg);
+ return (1);
+}
+
+WatchInfoPtr dl_init_watch(int type)
+{
+ WatchInfoPtr result;
+
+ if (!dl_error_proc)
+ dl_error_proc = dl_default_error;
+
+ if (!dl_warn_proc)
+ dl_warn_proc = dl_default_warn;
+
+ if ((result = (WatchInfoPtr) malloc(sizeof(WatchInfo))) == NULL)
+ {
+ (*dl_error_proc) ("Could not allocate WatchInfo structure.");
+ return (NULL);
+ }
+
+ memset((char *) result, 0, sizeof(WatchInfo));
+
+ switch (type)
+ {
+ case DATALINK_70:
+ result->dl_device = type;
+ result->max_tz = 2;
+ result->max_alarms = 5;
+ result->max_chrons = 0;
+ result->max_chron_str = 0;
+ result->max_apps = 255;
+ result->max_phones = 255;
+ result->max_timers = 0;
+ result->max_todos = 255;
+ result->max_annivs = 255;
+ result->max_system = 1;
+ result->max_wristapp = 0;
+ result->max_melody = 0;
+ result->max_tzlen = 3;
+ result->max_mem = 850;
+ result->mem_size = 0;
+ result->max_str = 15;
+ result->max_alarm_str = 8;
+ result->max_phone_str = 12;
+ result->max_timer_str = 0;
+ result->max_wristapp_len = 0;
+ result->max_mel_len = 0;
+ result->pre_notification_time = 0;
+ result->time_adjust = 9;
+ break;
+ case DATALINK_150:
+ case DATALINK_150S:
+ result->dl_device = type;
+ result->max_tz = 2;
+ result->max_alarms = 5;
+ result->max_chrons = 0;
+ result->max_chron_str = 0;
+ result->max_apps = 255;
+ result->max_phones = 255;
+ result->max_timers = 0;
+ result->max_todos = 255;
+ result->max_annivs = 255;
+ result->max_system = 1;
+ result->max_wristapp = 1;
+ result->max_melody = 1;
+ result->max_tzlen = 3;
+ result->max_mem = 2048;
+ result->mem_size = 0;
+ result->max_str = 31;
+ result->max_alarm_str = 8;
+ result->max_phone_str = 12;
+ result->max_timer_str = 0;
+ result->max_wristapp_len = 742;
+ result->max_mel_len = 64;
+ result->pre_notification_time = 0;
+ result->time_adjust = 9;
+ break;
+ case DATALINK_IRONMAN:
+ result->dl_device = type;
+ result->max_tz = 2;
+ result->max_alarms = 10;
+ result->max_chrons = 1;
+ result->max_apps = 0;
+ result->max_phones = 255;
+ result->max_timers = 5;
+ result->max_todos = 0;
+ result->max_annivs = 0;
+ result->max_system = 1;
+ result->max_wristapp = 0;
+ result->max_melody = 0;
+ result->max_tzlen = 3;
+ result->max_mem = 850;
+ result->mem_size = 0;
+ result->max_str = 15;
+ result->max_alarm_str = 16;
+ result->max_chron_str = 8;
+ result->max_phone_str = 12;
+ result->max_timer_str = 8;
+ result->max_wristapp_len = 0;
+ result->max_mel_len = 0;
+ result->pre_notification_time = 0;
+ result->time_adjust = 9;
+ break;
+ default:
+ (*dl_error_proc) ("Unknown watch type.");
+ return (NULL);
+ }
+
+ return (result);
+}
diff --git a/dl_item_ok.c b/dl_item_ok.c
new file mode 100644
index 0000000..ef919f6
--- /dev/null
+++ b/dl_item_ok.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "datalink.h"
+#include "datalink_private.h"
+
+
+int dl_item_ok(WatchInfoPtr wi, ItemPtr ip)
+{
+ char buf[1024];
+
+ switch (ip->type)
+ {
+ case DL_TIME_TYPE:
+
+ if (ip->data.time.tz_num < 1
+ || ip->data.time.tz_num > wi->max_tz)
+ {
+ sprintf(buf, "Bad time zone number #%d",
+ ip->data.time.tz_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.time.hours > 23)
+ {
+ sprintf(buf, "Bad hour in time #%d",
+ ip->data.time.tz_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.time.minutes > 59)
+ {
+ sprintf(buf, "Bad minute in time #%d",
+ ip->data.time.tz_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.time.month < 1 || ip->data.time.month > 12)
+ {
+ sprintf(buf, "Bad month in time #%d",
+ ip->data.time.tz_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.time.day < 1 || ip->data.time.day > 31)
+ {
+ sprintf(buf, "Bad day in time #%d",
+ ip->data.time.tz_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (!dl_string_ok(ip->data.time.label, wi->max_str))
+ {
+ sprintf(buf, "Bad characters in label in time #%d",
+ ip->data.time.tz_num);
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_ALARM_TYPE:
+
+ if (ip->data.alarm.alarm_num < 1 ||
+ ip->data.alarm.alarm_num > wi->max_alarms)
+ {
+ sprintf(buf, "Bad alarm number #%d",
+ ip->data.alarm.alarm_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.alarm.hours > 23)
+ {
+ sprintf(buf, "Bad hour in alarm #%d",
+ ip->data.alarm.alarm_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.alarm.minutes > 59)
+ {
+ sprintf(buf, "Bad minute in alarm #%d",
+ ip->data.alarm.alarm_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.alarm.month > 12)
+ {
+ sprintf(buf, "Bad month in alarm #%d",
+ ip->data.alarm.alarm_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.alarm.day > 31)
+ {
+ sprintf(buf, "Bad day in alarm #%d",
+ ip->data.alarm.alarm_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (!dl_string_ok(ip->data.alarm.label, wi->max_alarm_str))
+ {
+ sprintf(buf, "Bad string in alarm #%d",
+ ip->data.alarm.alarm_num);
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_TIMER_TYPE:
+
+ if (ip->data.timer.timer_num < 1 ||
+ ip->data.timer.timer_num > wi->max_timers)
+ {
+ sprintf(buf, "Bad timer number #%d",
+ ip->data.timer.timer_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.timer.hours > 99)
+ {
+ sprintf(buf, "Bad hour in timer #%d",
+ ip->data.timer.timer_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.timer.minutes > 59)
+ {
+ sprintf(buf, "Bad minute in timer #%d",
+ ip->data.timer.timer_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.timer.second > 59)
+ {
+ sprintf(buf, "Bad second in timer #%d",
+ ip->data.timer.timer_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.timer.repeat != 0
+ && ip->data.timer.repeat != 1)
+ {
+ sprintf(buf, "Bad repeat in timer #%d",
+ ip->data.timer.timer_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.timer.chron != 0 && ip->data.timer.chron != 1)
+ {
+ sprintf(buf, "Bad chron in timer #%d",
+ ip->data.timer.timer_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.timer.chron && ip->data.timer.repeat)
+ {
+ sprintf(buf,
+ "Can't do repeat and chron at the end of a timer, in timer #%d",
+ ip->data.timer.timer_num);
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (!dl_string_ok(ip->data.timer.label, wi->max_timer_str))
+ {
+ sprintf(buf, "Bad string in timer #%d",
+ ip->data.timer.timer_num);
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_APP_TYPE:
+
+ if (ip->data.app.month < 1 || ip->data.app.month > 12)
+ {
+ sprintf(buf, "Bad month in appointment.");
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.app.day < 1 || ip->data.app.day > 31)
+ {
+ sprintf(buf, "Bad day in appointment.");
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.app.time > 0x7f)
+ {
+ sprintf(buf, "Bad time in appointment.");
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (!dl_string_ok(ip->data.app.label, wi->max_str))
+ {
+ sprintf(buf,
+ "Bad characters in label in appointment.");
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_CHRON_TYPE:
+
+ if (!dl_string_ok(ip->data.chron.label, wi->max_chron_str))
+ {
+ sprintf(buf, "Bad characters in label in chron.");
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_PHONE_TYPE:
+
+ if (!dl_string_ok
+ (ip->data.phone.number, wi->max_phone_str))
+ {
+ sprintf(buf, "Bad characters in phone number.");
+ (*dl_warn_proc) (buf);
+ }
+
+ if (!dl_string_ok(ip->data.phone.label, wi->max_str))
+ {
+ sprintf(buf, "Bad characters in label in phone.");
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_TODO_TYPE:
+
+ if (!dl_string_ok(ip->data.todo.label, wi->max_str))
+ {
+ sprintf(buf, "Bad characters in label in todo.");
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_ANNIV_TYPE:
+
+ if (ip->data.anniv.month < 1 || ip->data.anniv.month > 12)
+ {
+ sprintf(buf, "Bad month in anniversary.");
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (ip->data.anniv.day < 1 || ip->data.anniv.day > 31)
+ {
+ sprintf(buf, "Bad day in anniversary.");
+ (*dl_error_proc) (buf);
+ return (0);
+ }
+
+ if (!dl_string_ok(ip->data.anniv.label, wi->max_str))
+ {
+ sprintf(buf,
+ "Bad characters in label in anniversary.");
+ (*dl_warn_proc) (buf);
+ }
+
+ break;
+ case DL_SYSTEM_TYPE:
+ break;
+ case DL_WRISTAPP_TYPE:
+ break;
+ case DL_MELODY_TYPE:
+ break;
+ default:
+ (*dl_error_proc) ("Unknown type");
+ return (0);
+ }
+
+ return (1);
+}
diff --git a/dl_new_item.c b/dl_new_item.c
new file mode 100644
index 0000000..ec0908b
--- /dev/null
+++ b/dl_new_item.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "datalink.h"
+
+ItemPtr dl_new_item(WatchInfoPtr wi, int type)
+{
+ ItemPtr ni;
+
+/* Since there is only one supported device, wi is not used. */
+
+ if (type <= DL_NO_TYPE && type > DL_MAX_TYPE)
+ {
+ (*dl_error_proc) ("Unknown type, can't allocate.");
+ return (NULL);
+ }
+
+ if ((ni = (ItemPtr) malloc(sizeof(Item))) == NULL)
+ {
+ (*dl_error_proc) ("Could not allocate item.");
+ return (NULL);
+ }
+
+ memset((char *) ni, 0, sizeof(Item));
+
+ ni->type = type;
+ return (ni);
+}
diff --git a/dl_new_list.c b/dl_new_list.c
new file mode 100644
index 0000000..495f915
--- /dev/null
+++ b/dl_new_list.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "datalink.h"
+
+ListPtr dl_new_list()
+{
+ ListPtr nl;
+
+ if ((nl = (ListPtr) malloc(sizeof(List))) == NULL)
+ {
+ (*dl_error_proc) ("Could not allocate new list.");
+ return (NULL);
+ }
+
+ memset((char *) nl, 0, sizeof(List));
+ return (nl);
+}
diff --git a/dl_pack_ascii.c b/dl_pack_ascii.c
new file mode 100644
index 0000000..fe8f08d
--- /dev/null
+++ b/dl_pack_ascii.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+
+int dl_pack_ascii(unsigned char *to, unsigned char *from)
+{
+ int c;
+ int p = 0;
+ int o = 0;
+
+ while (*from)
+ {
+
+ if (o == 0)
+ {
+ to[p] = dl_pack_char(*from);
+ o = 6;
+ from++;
+ continue;
+ }
+
+ c = dl_pack_char(*from);
+ to[p] |= c << o;
+ to[++p] = c >> (8 - o);
+ o = (o + 6) % 8;
+ from++;
+ }
+
+ if (o)
+ {
+ to[p] |= 0x3f << o;
+ to[++p] = 0x3f >> (8 - o);
+ o = (o + 6) % 8;
+ if (o)
+ p++;
+ } else
+ to[p++] = 0x3f;
+
+ return (p);
+}
diff --git a/dl_pack_char.c b/dl_pack_char.c
new file mode 100644
index 0000000..1e9cbe4
--- /dev/null
+++ b/dl_pack_char.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <ctype.h>
+
+int dl_pack_char(char c)
+{
+ c = toupper(c);
+
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+
+ if (c >= 'A' && c <= 'Z')
+ return (10 + c - 'A');
+
+ if (c >= ' ' && c < '0')
+ return (36 + c - ' ');
+
+
+ if (c >= ':' && c <= '~')
+ return (26 + c - ' ');
+
+ return (0x3f);
+}
diff --git a/dl_pack_digit.c b/dl_pack_digit.c
new file mode 100644
index 0000000..d874240
--- /dev/null
+++ b/dl_pack_digit.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <ctype.h>
+
+int dl_pack_digit(char c)
+{
+ int i;
+
+ c = toupper(c);
+
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+
+ for (i = 0; i < 6; i++)
+ {
+
+ if (c == "CFHPW "[i])
+ return (i + 10);
+
+ }
+
+ return (0xf);
+}
diff --git a/dl_pack_phone.c b/dl_pack_phone.c
new file mode 100644
index 0000000..6023961
--- /dev/null
+++ b/dl_pack_phone.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+
+void dl_pack_phone(unsigned char *to, unsigned char *from, int len)
+{
+ int i;
+ int l;
+
+ l = strlen(from);
+
+ if (l > len)
+ l = len;
+
+ for (i = 0; i < l; i++)
+ {
+
+ if (i & 1)
+ *to++ |= dl_pack_digit(from[i]) << 4;
+ else
+ *to = dl_pack_digit(from[i]);
+
+ }
+
+ for (i = l; i < len; i++)
+ {
+
+ if (i & 1)
+ *to++ |= dl_pack_digit(' ') << 4;
+ else
+ *to = dl_pack_digit(' ');
+
+ }
+
+}
diff --git a/dl_pack_size.c b/dl_pack_size.c
new file mode 100644
index 0000000..b4a4521
--- /dev/null
+++ b/dl_pack_size.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+#include "datalink_private.h"
+
+int dl_pack_size(char *string)
+{
+ int size;
+ int l;
+
+ l = (strlen(string) + 1) * 3;
+ size = (l % 4) ? l / 4 + 1 : l / 4;
+ return (size);
+}
diff --git a/dl_phone_by_label.c b/dl_phone_by_label.c
new file mode 100644
index 0000000..de30ce8
--- /dev/null
+++ b/dl_phone_by_label.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+
+int dl_phone_by_label(ItemPtr a, ItemPtr b)
+{
+ return (strcmp(a->data.phone.label, b->data.phone.label));
+}
diff --git a/dl_send_data.c b/dl_send_data.c
new file mode 100644
index 0000000..3dfa12e
--- /dev/null
+++ b/dl_send_data.c
@@ -0,0 +1,897 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <limits.h>
+#include "datalink.h"
+#include "datalink_private.h"
+
+#define MAX_PCKT 38
+
+#define TIME_70 0x30
+#define DSTART_70 0x60
+#define DATA_70 0x61
+#define DEND_70 0x62
+
+static unsigned char start1[] = { 7, 0x20, 0, 0, 3, 0, 0 };
+static unsigned char datablock1[] = { 0x20, 0x70, 0x02, 0x40,
+ 0x05, 0xa9, 0x22, 0x5f,
+ 0xe6, 0xb2, 0xe8, 0xbb,
+ 0xe7, 0xb2, 0xe8, 0xbb,
+ 0xe7, 0xbb, 0xe8, 0xb2,
+ 0xe7, 0xb2, 0x5c, 0xa3,
+ 0x09, 0x26, 0xed, 0x15,
+ 0xa9, 0x01, 0x00, 0x00
+};
+static unsigned char datablock2[] = { 0x14, 0x70, 0x02, 0x5a,
+ 0xa9, 0x02, 0x14, 0xa9,
+ 0xb6, 0xa9, 0xa4, 0x07,
+ 0x47, 0xb7, 0xa9, 0xcc,
+ 0x74, 0x6f, 0x00, 0x00
+};
+static unsigned char time[] = { 17, 0x32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0
+};
+static unsigned char dstart[] = { 5, 0x93, 0, 0, 0 };
+static unsigned char dinfo[] = { 20, 0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+static unsigned char dspace[] = { 4, 0x91, 0, 0 };
+static unsigned char dend[] = { 5, 0x92, 0, 0, 0 };
+static unsigned char blank_alarm[] = { 18, 0x50, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+static unsigned char timer[] =
+ { 0x11, 0x43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char sysinfo[] = { 6, 0x71, 0, 0, 0, 0 };
+static unsigned char end1[] = { 4, 0x21, 0, 0 };
+
+static unsigned char pre60[] = { 6, 0x23, 2, 0x40, 0, 0 };
+static unsigned char numdatapackets[] = { 5, 0x60, 0, 0, 0 };
+
+int _write_data(int fd, unsigned char *buf, unsigned char *data, int size,
+ int *pnum, int type, WatchInfoPtr wi)
+{
+ int bytes_left;
+
+ while (*buf + size > MAX_PCKT - 2)
+ {
+ bytes_left = *buf + size - MAX_PCKT + 2;
+ memcpy(&buf[buf[0]], data, size - bytes_left);
+ buf[0] = MAX_PCKT;
+ dl_docrc(buf);
+
+ if (write(fd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write data to tmp file."));
+
+ data += size - bytes_left;
+ size = bytes_left;
+
+ memcpy(buf, dspace, *dspace);
+
+ if (wi->dl_device == DATALINK_70)
+ buf[1] = DATA_70;
+
+ buf[2] = type;
+ buf[3] = (*pnum)++;
+ }
+
+ if (!size)
+ return (0);
+
+ memcpy(&buf[buf[0]], data, size);
+ buf[0] += size;
+ return (1);
+}
+
+/* TODO: If there is any errors we currently leak a file descriptor,
+ * it might be nice to close the file first.
+ */
+int dl_send_data(WatchInfoPtr wi, int type)
+{
+ char fname[PATH_MAX];
+ char * tmpdir;
+ char * template="/datalink_XXXXXX";
+ unsigned char buf[64];
+ unsigned char data[64];
+ unsigned short addr = 0x0236;
+ char *protocol;
+ AppointmentPtr ap;
+ ToDoPtr tp;
+ PhonePtr pp;
+ AnniversaryPtr anp;
+ WristAppPtr wristapp;
+ SystemPtr sys;
+ MelodyPtr melody;
+ int ofd;
+ int i;
+ int pnum;
+ int pid;
+ int status;
+ int ret=0;
+ int p;
+
+ if (type == BLINK_FILE)
+ {
+ strcpy(fname, "DEBUGOUTPUT");
+ if ((ofd = open(fname,
+ O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
+ {
+ sprintf(buf, "Can't open %s for writing.", fname);
+ return ((*dl_error_proc) (buf));
+ }
+ }
+ else
+ {
+ /* Try to get the directory for a temporary file from
+ * the envinronment variable TMPDIR
+ * Try P_tmpdir if that fails
+ * Fallback to /tmp if need be
+ */
+ if(tmpdir=getenv("TMPDIR"))
+ if(strlen(tmpdir)+strlen(template)+1 >= PATH_MAX)
+ tmpdir=0; // invalid path, string too long
+ if(!tmpdir)
+ {
+ #ifdef P_tmpdir
+ tmpdir=P_tmpdir;
+ #else
+ tmpdir="/tmp";
+ #endif
+ }
+ strcpy(fname, tmpdir);
+ strcat(fname, template);
+ if ((ofd = mkstemp(fname)) == -1)
+ {
+ sprintf(buf, "Can't open %s for writing.", fname);
+ return ((*dl_error_proc) (buf));
+ }
+ }
+
+ memcpy(buf, start1, *start1);
+
+ if (wi->dl_device == DATALINK_70)
+ {
+ buf[4] = 1;
+ }
+ else if (wi->dl_device == DATALINK_IRONMAN)
+ {
+ buf[4] = 9;
+ }
+ else if (wi->dl_device == DATALINK_150S)
+ {
+ buf[4] = 4;
+ }
+
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write start to tmp file."));
+
+ if (wi->dl_device == DATALINK_IRONMAN)
+ {
+ memcpy(buf, datablock1, *datablock1);
+ dl_docrc(buf);
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write start block1 to tmp file."));
+
+ memcpy(buf, datablock2, *datablock1);
+ dl_docrc(buf);
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write start block2 to tmp file."));
+ }
+
+
+ for (i = 0; i < dl_download_data.num_times; i++)
+ {
+ memcpy(buf, time, *time);
+ p = 2;
+ if (wi->dl_device == DATALINK_IRONMAN)
+ {
+ buf[0] = 0x0e;
+ buf[1] = 0x30;
+ }
+
+ buf[p++] = dl_download_data.times[i].tz_num;
+
+ if (wi->dl_device == DATALINK_150 ||
+ wi->dl_device == DATALINK_150S)
+ buf[p++] = dl_download_data.times[i].seconds;
+
+ if (wi->dl_device == DATALINK_IRONMAN)
+ {
+ buf[p++] = dl_download_data.times[i].hours;
+ buf[p++] = dl_download_data.times[i].minutes;
+ buf[p++] = dl_download_data.times[i].month;
+ buf[p++] = dl_download_data.times[i].day;
+ buf[p++] = dl_download_data.times[i].year;
+ buf[p++] = dl_download_data.times[i].dow;
+ buf[p++] = dl_download_data.times[i].seconds;
+ } else
+ {
+ buf[p++] = dl_download_data.times[i].hours;
+ buf[p++] = dl_download_data.times[i].minutes;
+ buf[p++] = dl_download_data.times[i].month;
+ buf[p++] = dl_download_data.times[i].day;
+ buf[p++] = dl_download_data.times[i].year;
+ buf[p++] =
+ dl_pack_char(dl_download_data.
+ times[i].label[0]);
+ buf[p++] =
+ dl_pack_char(dl_download_data.
+ times[i].label[1]);
+ buf[p++] =
+ dl_pack_char(dl_download_data.
+ times[i].label[2]);
+ buf[p++] = dl_download_data.times[i].dow - 1;
+ }
+
+ if (wi->dl_device == DATALINK_150 ||
+ wi->dl_device == DATALINK_150 ||
+ wi->dl_device == DATALINK_IRONMAN)
+ {
+ buf[p++] = dl_download_data.times[i].hour_fmt;
+ buf[p++] =
+ dl_download_data.times[i].date_fmt & 0xFF;
+ }
+
+ if (wi->dl_device == DATALINK_70)
+ buf[1] = TIME_70;
+
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write time to tmp file."));
+
+ }
+
+ if (wi->dl_device != DATALINK_IRONMAN && dl_download_data.memory)
+ {
+ memcpy(buf, dstart, *dstart);
+ buf[2] = 1;
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write dstart to tmp file."));
+
+ memcpy(buf, dinfo, *dinfo);
+ buf[2] = 1;
+ buf[3] = dl_download_data.memory / (MAX_PCKT - 6);
+
+ if (dl_download_data.memory % (MAX_PCKT - 6))
+ buf[3]++;
+
+ buf[12] = dl_download_data.num_apps;
+ buf[13] = dl_download_data.num_todos;
+ buf[14] = dl_download_data.num_phones;
+ buf[15] = dl_download_data.num_annivs;
+ buf[4] = (addr >> 8) & 0xff;
+ buf[5] = addr & 0xff;
+ addr += dl_download_data.app_size;
+ buf[6] = (addr >> 8) & 0xff;
+ buf[7] = addr & 0xff;
+ addr += dl_download_data.todo_size;
+ buf[8] = (addr >> 8) & 0xff;
+ buf[9] = addr & 0xff;
+ addr += dl_download_data.phone_size;
+ buf[10] = (addr >> 8) & 0xff;
+ buf[11] = addr & 0xff;
+ buf[16] = 0x62;
+ buf[17] = dl_download_data.pre_notification_time / 5;
+ if (!buf[17])
+ buf[17] = 0xff;
+
+ if (wi->dl_device == DATALINK_70)
+ buf[1] = DATA_70;
+
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write dinfo to tmp file."));
+
+ pnum = 1;
+ memcpy(buf, dspace, *dspace);
+
+ if (wi->dl_device == DATALINK_70)
+ buf[1] = DATA_70;
+
+ buf[2] = 1;
+ buf[3] = pnum++;
+
+ for (i = 0; i < dl_download_data.num_apps; i++)
+ {
+ ap = &dl_download_data.apps[i];
+ data[0] = dl_pack_size(ap->label);
+ data[1] = ap->month;
+ data[2] = ap->day;
+ data[3] = ap->time;
+
+ if (data[0] != dl_pack_ascii(&data[4], ap->label))
+ return ((*dl_error_proc)
+ ("ERROR Bad pack_ascii.\n"));
+
+ *data += 4;
+
+ if (!_write_data
+ (ofd, buf, data, *data, &pnum, 1, wi))
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ for (i = 0; i < dl_download_data.num_todos; i++)
+ {
+ tp = &dl_download_data.todos[i];
+ data[0] = dl_pack_size(tp->label);
+ data[1] = tp->priority;
+
+ if (data[0] != dl_pack_ascii(&data[2], tp->label))
+ return ((*dl_error_proc)
+ ("ERROR Bad pack_ascii.\n"));
+
+ *data += 2;
+
+ if (!_write_data
+ (ofd, buf, data, *data, &pnum, 1, wi))
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ for (i = 0; i < dl_download_data.num_phones; i++)
+ {
+ pp = &dl_download_data.phones[i];
+ data[0] = dl_pack_size(pp->label);
+ dl_pack_phone(&data[1], pp->number,
+ dl_download_data.max_phone_str);
+
+ if (data[0] != dl_pack_ascii(&data[7], pp->label))
+ {
+ printf("ERROR Bad pack_ascii.\n");
+ exit(-1);
+ }
+
+ *data += dl_download_data.max_phone_str / 2;
+ (*data)++;
+
+ if (!_write_data
+ (ofd, buf, data, *data, &pnum, 1, wi))
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ for (i = 0; i < dl_download_data.num_annivs; i++)
+ {
+ anp = &dl_download_data.annivs[i];
+ data[0] = dl_pack_size(anp->label);
+ data[1] = anp->month;
+ data[2] = anp->day;
+
+ if (data[0] != dl_pack_ascii(&data[3], anp->label))
+ {
+ printf("ERROR Bad pack_ascii.\n");
+ exit(-1);
+ }
+
+ *data += 4;
+
+ if (!_write_data
+ (ofd, buf, data, *data, &pnum, 1, wi))
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ *buf += 2;
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ memcpy(buf, dend, *dend);
+ buf[2] = 1;
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ if (wi->dl_device == DATALINK_IRONMAN && dl_download_data.chron)
+ {
+ /* The memdata is a where all the data is stored and when all the
+ * information to be sent that inclues the chron label and laps, and the
+ * phone data. The information is broken up into packets and sent one at
+ * a time.
+ */
+ /* should be overkill, don't know the right value */
+#define maxdatasize 4096
+ char memdata[maxdatasize] = { 0 };
+ int p = 0;
+ int labelsize;
+ int packets;
+ int offset = 0;
+ int size;
+
+ for (i = 0; i < dl_download_data.num_chron; i++)
+ {
+ memdata[p++] = 0;
+ memdata[p++] = 0xe;
+ memdata[p++] = 0;
+#warning TODO has dl_download_data.chron[i].memused been initalized
+ memdata[p++] = dl_download_data.chron[i].memused;
+ memdata[p++] =
+ dl_download_data.chron[i].chron_laps;
+ if (dl_download_data.num_phones)
+ memdata[p++] = dl_download_data.num_phones;
+ else
+ memdata[p++] = 0;
+ dl_fill_pack_ascii(&memdata[p],
+ dl_download_data.chron[i].label,
+ dl_download_data.max_chron_str,
+ ' ');
+ p += 8;
+ }
+
+ for (i = 0; i < dl_download_data.num_phones; i++)
+ {
+ pp = &dl_download_data.phones[i];
+ labelsize = dl_pack_size(pp->label);
+ /* This is the size taken up by this phone entry,
+ * the size of the label + 6 for the digits and
+ * one for this byte
+ */
+ memdata[p++] = labelsize + 7;
+ dl_pack_phone(&memdata[p], pp->number,
+ dl_download_data.max_phone_str);
+ p += 6;
+
+ if (labelsize !=
+ dl_pack_ascii(&memdata[p], pp->label))
+ {
+ printf("ERROR Bad pack_ascii.\n");
+ exit(-1);
+ }
+ p += labelsize;
+ }
+
+ if (p > maxdatasize)
+ {
+ printf
+ ("Error buffer overflow, too much data or too small of buffer\n");
+ exit(-1);
+ }
+
+ /* set how many packets it will take to send the data, there are up
+ * to 32 bytes per packet, 27 of those are data bytes */
+ packets = p / 27 + (p % 27 ? 1 : 0);
+
+ /* packet before the one that lists how many data packets to send */
+ memcpy(buf, pre60, *pre60);
+ dl_docrc(buf);
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ /* send the packet that lists how many data packets are to follow */
+ memcpy(buf, numdatapackets, *numdatapackets);
+ buf[2] = packets;
+ dl_docrc(buf);
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ for (i = 0; i < packets; i++)
+ {
+ if (i < packets - 1)
+ buf[0] = 32;
+ else
+ buf[0] = p - 27 * (packets - 1) + 5;
+ size = buf[0] - 5;
+ buf[1] = 0x61;
+ buf[2] = i + 1;
+ buf[3] = i;
+ memcpy(&buf[3], &memdata[offset], size);
+ dl_docrc(buf);
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+ offset += size;
+ }
+
+ buf[0] = 4;
+ buf[1] = 0x62;
+ dl_docrc(buf);
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ /*
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return((*dl_error_proc)("Can't write to tmp file."));
+ */
+ for (i = 0; i < p; i++)
+ {
+#ifdef DEBUGGING_FILE
+ printf(" 0x%0.2x",
+ 0xff & ((unsigned int) memdata[i]));
+#endif /* DEBUGGING_FILE */
+ if (!p % 8)
+ printf("\n");
+ }
+ }
+
+ /* timezone label packet for IRONMAN watch */
+ if (wi->dl_device == DATALINK_IRONMAN)
+ for (i = 0; i < dl_download_data.num_times; i++)
+ {
+ p = 0;
+ buf[p++] = 8;
+ buf[p++] = 0x31;
+
+ buf[p++] = dl_download_data.times[i].tz_num;
+ buf[p++] =
+ dl_pack_char(dl_download_data.
+ times[i].label[0]);
+ buf[p++] =
+ dl_pack_char(dl_download_data.
+ times[i].label[1]);
+ buf[p++] =
+ dl_pack_char(dl_download_data.
+ times[i].label[2]);
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write timezone label to tmp file."));
+ }
+
+
+
+ for (i = 0; i < dl_download_data.num_alarms; i++)
+ {
+ /* blank out buf with the blank_alarm data template,
+ * *blank_alarm gives the first byte of the alarm data
+ * and also the lenght which tells how much to copy
+ */
+ memcpy(buf, blank_alarm, *blank_alarm);
+ buf[2] = dl_download_data.alarms[i].alarm_num;
+ buf[3] = dl_download_data.alarms[i].hours;
+ buf[4] = dl_download_data.alarms[i].minutes;
+ buf[5] = dl_download_data.alarms[i].month;
+ buf[6] = dl_download_data.alarms[i].day;
+ if (wi->dl_device == DATALINK_IRONMAN)
+ {
+ buf[7] = dl_download_data.alarms[i].audible;
+ dl_fill_pack_ascii(&buf[8],
+ dl_download_data.
+ alarms[i].label,
+ dl_download_data.max_alarm_str,
+ ' ');
+ buf[0] = 0x1a;
+ buf[1] = 0x50;
+ } else
+ {
+ dl_fill_pack_ascii(&buf[7],
+ dl_download_data.
+ alarms[i].label,
+ dl_download_data.max_alarm_str,
+ ' ');
+ buf[15] = dl_download_data.alarms[i].audible;
+ }
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ for (i = 0; i < dl_download_data.num_timers; i++)
+ {
+ memcpy(buf, timer, *timer);
+ buf[2] = dl_download_data.timers[i].timer_num;
+ buf[3] = dl_download_data.timers[i].hours;
+ buf[4] = dl_download_data.timers[i].minutes;
+ buf[5] = dl_download_data.timers[i].second;
+ buf[6] = dl_download_data.timers[i].repeat;
+ buf[6] |= dl_download_data.timers[i].chron << 1;
+
+ dl_fill_pack_ascii(&buf[7],
+ dl_download_data.timers[i].label,
+ dl_download_data.max_timer_str, ' ');
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ if (dl_download_data.num_wristapp)
+ {
+ wristapp = dl_download_data.wristapp;
+ memcpy(buf, dstart, *dstart);
+ buf[2] = 2;
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ memcpy(buf, dinfo, *dinfo);
+ buf[2] = 2;
+ buf[3] = wristapp->len / (MAX_PCKT - 6);
+
+ if (wristapp->len % (MAX_PCKT - 6))
+ buf[3]++;
+
+ buf[4] = 1;
+ *buf = 7;
+
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ memcpy(buf, dspace, *dspace);
+
+ if (wi->dl_device == DATALINK_70)
+ buf[1] = DATA_70;
+
+ pnum = 1;
+ buf[2] = 2;
+ buf[3] = pnum++;
+
+ if (!_write_data
+ (ofd, buf, wristapp->data, wristapp->len, &pnum, 2,
+ wi))
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ if (*buf != 4)
+ {
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ memcpy(buf, dend, *dend);
+ buf[2] = 2;
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ if (dl_download_data.num_melody)
+ {
+ melody = dl_download_data.melody;
+ memcpy(buf, dstart, *dstart);
+ buf[2] = 3;
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ memcpy(buf, dinfo, *dinfo);
+ buf[2] = 3;
+ buf[3] = melody->len / (MAX_PCKT - 6);
+
+ if (melody->len % (MAX_PCKT - 6))
+ buf[3]++;
+
+ buf[4] = 0xff - melody->len;
+ *buf = 7;
+
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ memcpy(buf, dspace, *dspace);
+
+ if (wi->dl_device == DATALINK_70)
+ buf[1] = DATA_70;
+
+ pnum = 1;
+ buf[2] = 3;
+ buf[3] = pnum++;
+
+ if (!_write_data
+ (ofd, buf, melody->data, melody->len, &pnum, 3, wi))
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ if (*buf != 4)
+ {
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ memcpy(buf, dend, *dend);
+ buf[2] = 3;
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ if (dl_download_data.num_system)
+ {
+ sys = dl_download_data.system;
+ memcpy(buf, sysinfo, *sysinfo);
+ if (wi->dl_device == DATALINK_IRONMAN)
+ {
+ buf[0] = 5;
+ buf[1] = 0x32;
+ buf[2] = sys->chime;
+ buf[2] |= sys->beep << 1;
+ } else
+ {
+ buf[2] = sys->chime;
+ buf[3] = sys->beep;
+ }
+
+ dl_docrc(buf);
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc)
+ ("Can't write to tmp file."));
+
+ }
+
+ memcpy(buf, end1, *end1);
+ dl_docrc(buf);
+
+ if (write(ofd, buf, *buf) != *buf)
+ return ((*dl_error_proc) ("Can't write to tmp file."));
+
+ close(ofd);
+
+ switch (type)
+ {
+ case BLINK_FILE:
+ ret = 0;
+ break;
+ case SVGA_BLINK:
+
+ switch ((pid = fork()))
+ {
+ case -1:
+ return ((*dl_error_proc)
+ ("Could not execute svga blink engine."));
+ return (-1);
+ case 0: /* Child */
+ /* execute svgablink useing the version of
+ * exec that will search the users active path,
+ * if it isn't there (we can't run it).
+ */
+ switch(wi->dl_device)
+ {
+ case DATALINK_IRONMAN:
+ protocol="-ironman";
+ break;
+ case DATALINK_150:
+ protocol="-150";
+ break;
+ case DATALINK_150S:
+ protocol="-150s";
+ break;
+ case DATALINK_70:
+ protocol="-70";
+ break;
+ default:
+ (*dl_error_proc)
+ ("Don't know what watch for svgablink.");
+ exit(-1);
+ }
+ execlp("svgablink", "svgablink", protocol, fname, NULL);
+
+ (*dl_error_proc)
+ ("Could not execute svga blink engine.");
+ exit(-1);
+ default:
+
+ if (waitpid(pid, &status, 0) < 0)
+ perror("waitpid");
+
+ (void) unlink(fname);
+
+ if (WIFEXITED(status))
+ ret = WEXITSTATUS(status);
+ else
+ ret = -1;
+
+ break;
+ }
+
+ break;
+ case SER_BLINK:
+
+ switch ((pid = fork()))
+ {
+ case -1:
+ return ((*dl_error_proc)
+ ("Could not fork child for serial blink engine."));
+ return (-1);
+ case 0: /* Child */
+ /* execute serblink useing the version of
+ * exec that will search the users active path,
+ * if it isn't there (we can't run it).
+ */
+ execlp("serblink", "serblink", fname, NULL);
+
+
+ (*dl_error_proc)
+ ("Could not execute serial blink engine.");
+ exit(-1);
+ default:
+
+ if (waitpid(pid, &status, 0) < 0)
+ perror("waitpid");
+
+ (void) unlink(fname);
+
+ if (WIFEXITED(status))
+ ret = WEXITSTATUS(status);
+ else
+ ret = -1;
+
+ break;
+ }
+
+ break;
+ }
+
+ return (ret);
+}
diff --git a/dl_set_error.c b/dl_set_error.c
new file mode 100644
index 0000000..17268c4
--- /dev/null
+++ b/dl_set_error.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+
+void dl_set_error(int (*func)())
+{
+ dl_error_proc = func;
+}
diff --git a/dl_set_warn.c b/dl_set_warn.c
new file mode 100644
index 0000000..7c4aebb
--- /dev/null
+++ b/dl_set_warn.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+
+void dl_set_warn(int (*func) ())
+{
+ dl_warn_proc = func;
+}
diff --git a/dl_sizeof_item.c b/dl_sizeof_item.c
new file mode 100644
index 0000000..0cdb22b
--- /dev/null
+++ b/dl_sizeof_item.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+#include "datalink_private.h"
+
+int dl_sizeof_item(WatchInfoPtr wi, ItemPtr item)
+{
+ int size;
+ int l;
+
+ switch (item->type)
+ {
+ case DL_TIME_TYPE:
+ size = 0;
+ break;
+ case DL_ALARM_TYPE:
+ size = 0;
+ break;
+ case DL_APP_TYPE:
+ l = strlen(item->data.app.label);
+
+ if (l > wi->max_str)
+ {
+
+
+ (void) (*dl_warn_proc) ("Appointment label too long.");
+ l = wi->max_str;
+ }
+
+ size = dl_pack_size(item->data.app.label) + 4;
+ break;
+ case DL_PHONE_TYPE:
+ l = strlen(item->data.app.label);
+
+ if (l > wi->max_str)
+ {
+ (void) (*dl_warn_proc) ("Phone label too long.");
+ l = wi->max_str;
+ }
+
+ size = dl_pack_size(item->data.app.label) + 1;
+ size += wi->max_phone_str / 2;
+ break;
+ case DL_TODO_TYPE:
+ l = strlen(item->data.app.label);
+
+ if (l > wi->max_str)
+ {
+ (void) (*dl_warn_proc) ("Todo label too long.");
+ l = wi->max_str;
+ }
+
+ size = dl_pack_size(item->data.app.label) + 2;
+ break;
+ case DL_ANNIV_TYPE:
+ l = strlen(item->data.app.label);
+
+ if (l > wi->max_str)
+ {
+
+
+ (void) (*dl_warn_proc) ("Anniversary label too long.");
+ l = wi->max_str;
+ }
+
+ size = dl_pack_size(item->data.app.label) + 4;
+ break;
+ case DL_SYSTEM_TYPE:
+ size = 0;
+ break;
+ case DL_WRISTAPP_TYPE:
+ size = 0;
+ break;
+ case DL_MELODY_TYPE:
+ size = 0;
+ break;
+ default:
+ size = 0;
+ (void) (*dl_error_proc) ("Unknown type");
+ }
+
+ return (size);
+}
diff --git a/dl_sizeof_list.c b/dl_sizeof_list.c
new file mode 100644
index 0000000..9324ddd
--- /dev/null
+++ b/dl_sizeof_list.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+#include "datalink_private.h"
+
+int dl_sizeof_list(WatchInfoPtr wi, ListPtr list)
+{
+ ItemPtr ip;
+ int size = 0;
+
+ for (ip = list->first; ip; ip = ip->next)
+ size += dl_sizeof_item(wi, ip);
+
+ return (size);
+}
diff --git a/dl_sort.c b/dl_sort.c
new file mode 100644
index 0000000..729158e
--- /dev/null
+++ b/dl_sort.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include "datalink.h"
+
+int dl_sort(ListPtr list, int (*cmp_proc) ())
+{
+ ListPtr nl;
+ ItemPtr ip;
+ ItemPtr ni;
+ ItemPtr si;
+ ItemPtr pi;
+
+ if ((nl = dl_new_list()) == NULL)
+ return ((*dl_error_proc) ("List alloc error."));
+
+ for (ip = list->first; ip; ip = ni)
+ {
+ ni = ip->next;
+
+ for (pi = NULL, si = nl->first; si; si = si->next)
+ {
+
+ if ((*cmp_proc) (ip, si) >= 0)
+ {
+ pi = si;
+ continue;
+ }
+
+ if (pi)
+ {
+ ip->next = pi->next;
+ pi->next = ip;
+ } else
+ {
+ ip->next = nl->first;
+ nl->first = ip;
+ }
+
+ nl->count++;
+
+ if (!nl->last)
+ {
+ nl->last = ip;
+ ip->next = NULL;
+ }
+
+ break;
+
+ }
+
+ if (!si)
+ {
+ dl_add_to_list(nl, ip);
+ ip->next = NULL;
+ }
+
+ }
+
+ list->first = nl->first;
+ list->last = nl->last;
+ free(nl);
+ return 0;
+}
diff --git a/dl_string_ok.c b/dl_string_ok.c
new file mode 100644
index 0000000..b57f12f
--- /dev/null
+++ b/dl_string_ok.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+
+int dl_string_ok(char *string, int maxl)
+{
+ int i;
+ int l;
+
+ l = strlen(string);
+
+ if (l > maxl)
+ return (0);
+
+ for (i = 0; i < l; i++)
+ {
+
+ if (string[i] < ' ' || string[i] > '~')
+ return (0);
+
+ }
+
+ return (1);
+}
diff --git a/dl_todo_by_label.c b/dl_todo_by_label.c
new file mode 100644
index 0000000..44d2f1c
--- /dev/null
+++ b/dl_todo_by_label.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "datalink.h"
+
+int dl_todo_by_label(ItemPtr a, ItemPtr b)
+{
+ return (strcmp(a->data.todo.label, b->data.todo.label));
+}
diff --git a/dl_todo_by_prio.c b/dl_todo_by_prio.c
new file mode 100644
index 0000000..c46c8f3
--- /dev/null
+++ b/dl_todo_by_prio.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "datalink.h"
+
+int dl_todo_by_prio(ItemPtr a, ItemPtr b)
+{
+ return (a->data.todo.priority - b->data.todo.priority);
+}
diff --git a/dl_write_save.c b/dl_write_save.c
new file mode 100644
index 0000000..feeea86
--- /dev/null
+++ b/dl_write_save.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "datalink.h"
+#include "datalink_private.h"
+
+int dl_write_save(char *datafile, char *wristappfile, char *melodyfile)
+{
+ FILE *fp;
+ char bakfile[1024];
+ int last_warn = 0;
+ TimePtr tip;
+ AlarmPtr alp;
+ AppointmentPtr ap;
+ ToDoPtr tp;
+ PhonePtr pp;
+ AnniversaryPtr anp;
+ SystemPtr sp;
+ int hour, min;
+ int i;
+
+/* Create backup of old datafile. */
+
+ sprintf(bakfile, "%s.bak", datafile);
+ (void) unlink(bakfile);
+
+ if (link(datafile, bakfile) < 0)
+ last_warn = (*dl_warn_proc) ("Could not make backup.");
+
+ (void) unlink(datafile);
+
+ if ((fp = fopen(datafile, "w")) == NULL)
+ return ((*dl_error_proc) ("Could not write save file."));
+
+ fprintf(fp,
+ "# Data Link save file created by the datalink library.\n\n");
+
+/* Save each type of data. */
+
+ for (i = 0; i < dl_download_data.num_times; i++)
+ {
+ tip = &dl_download_data.times[i];
+ fprintf(fp, "timezone = %d, \"%s\", %d, %d, %d\n",
+ tip->tz_num, tip->label, tip->offset,
+ tip->hour_fmt, tip->date_fmt);
+ }
+
+ if (dl_download_data.num_times)
+ fprintf(fp, "\n");
+
+ for (i = 0; i < dl_download_data.num_alarms; i++)
+ {
+ alp = &dl_download_data.alarms[i];
+ fprintf(fp,
+ "alarm = %d, %02d/%02d, %02d:%02d, \"%s\", %d\n",
+ alp->alarm_num, alp->month, alp->day, alp->hours,
+ alp->minutes, alp->label, alp->audible);
+ }
+
+ if (dl_download_data.num_alarms)
+ fprintf(fp, "\n");
+
+ for (i = 0; i < dl_download_data.num_apps; i++)
+ {
+ ap = &dl_download_data.apps[i];
+ min = 0;
+
+ for (i = 1; i < 0xFF; i <<= 1)
+ {
+
+ if ((i & ap->time))
+ min += i * 15;
+
+ }
+
+ hour = min / 60;
+ min = hour * 60;
+
+ fprintf(fp, "appointment = %02d/%02d, %02d:%02d, \"%s\"\n",
+ ap->month, ap->day, hour, min, ap->label);
+ }
+
+ if (dl_download_data.num_apps)
+ fprintf(fp, "\n");
+
+ for (i = 0; i < dl_download_data.num_todos; i++)
+ {
+ tp = &dl_download_data.todos[i];
+ fprintf(fp, "todo = %d, \"%s\"\n", tp->priority,
+ tp->label);
+ }
+
+ if (dl_download_data.num_todos)
+ fprintf(fp, "\n");
+
+ for (i = 0; i < dl_download_data.num_phones; i++)
+ {
+ pp = &dl_download_data.phones[i];
+ fprintf(fp, "phone = \"%s\", \"%s\"\n", pp->number,
+ pp->label);
+ }
+
+ if (dl_download_data.num_phones)
+ fprintf(fp, "\n");
+
+ for (i = 0; i < dl_download_data.num_annivs; i++)
+ {
+ anp = &dl_download_data.annivs[i];
+ fprintf(fp, "anniversary = %02d/%02d, \"%s\"\n",
+ anp->month, anp->day, anp->label);
+ }
+
+ if (dl_download_data.num_annivs)
+ fprintf(fp, "\n");
+
+ for (i = 0; i < dl_download_data.num_system; i++)
+ {
+ sp = &dl_download_data.system[i];
+ fprintf(fp, "system = %d, %d\n", sp->chime, sp->beep);
+ }
+
+ if (dl_download_data.num_system)
+ fprintf(fp, "\n");
+
+ if (wristappfile && *wristappfile)
+ fprintf(fp, "wristapp = \"%s\"\n\n", wristappfile);
+
+ if (melodyfile && *melodyfile)
+ fprintf(fp, "melody = \"%s\"\n\n", melodyfile);
+
+ return (last_warn);
+}
diff --git a/doc/datalink.ps b/doc/datalink.ps
new file mode 100644
index 0000000..91c9798
--- /dev/null
+++ b/doc/datalink.ps
@@ -0,0 +1,228 @@
+%!PS-Adobe-2.0
+%%Title: datalink.fig
+%%Creator: fig2dev Version 3.1 Patchlevel 1
+%%CreationDate: Sat Oct 12 15:13:51 1996
+%%For: protius@keman (Tommy Johnson,Ivers 226,4192,4192)
+%%Orientation: Portrait
+%%BoundingBox: 47 168 565 623
+%%Pages: 1
+%%BeginSetup
+%%IncludeFeature: *PageSize Letter
+%%EndSetup
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {} def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+-79.0 661.5 translate
+1 -1 scale
+
+/clp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+ /DrawEllipse {
+ /endangle exch def
+ /startangle exch def
+ /yrad exch def
+ /xrad exch def
+ /y exch def
+ /x exch def
+ /savematrix mtrx currentmatrix def
+ x y tr xrad yrad sc 0 0 1 startangle endangle arc
+ closepath
+ savematrix setmatrix
+ } def
+
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+%%EndProlog
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+/Times-Roman findfont 180.00 scalefont setfont
+2325 8175 m
+gs 1 -1 sc (Drawn with XFig 3.1 patch level 4. ) col-1 show gr
+7.500 slw
+% Polyline
+n 2850 1650 m 3900 1650 l gs col-1 s gr
+% Polyline
+n 2850 2100 m 3900 2100 l gs col-1 s gr
+% Polyline
+n 2850 2550 m 3900 2550 l gs col-1 s gr
+% Polyline
+n 3900 1650 m 3900 2550 l gs col-1 s gr
+% Polyline
+n 3900 1650 m 4950 1650 l 4950 2625 l gs col-1 s gr
+% Polyline
+n 4800 2625 m 5100 2625 l gs col-1 s gr
+% Polyline
+n 4800 2625 m 4950 2850 l 5100 2625 l gs col-1 s gr
+% Polyline
+n 4800 2850 m 5100 2850 l gs col-1 s gr
+% Polyline
+n 4950 2850 m 4950 3375 l 4725 3600 l gs col-1 s gr
+% Polyline
+n 4725 3750 m 4950 3975 l gs col-1 s gr
+% Polyline
+n 4725 3450 m 4725 3525 l 4725 3900 l gs col-1 s gr
+% Polyline
+n 4725 3675 m 3975 3675 l gs col-1 s gr
+% Polyline
+n 3975 3675 m 3900 3600 l 3825 3750 l 3750 3600 l 3675 3750 l 3600 3600 l
+ 3525 3750 l 3450 3675 l gs col-1 s gr
+% Polyline
+n 3450 3675 m 2925 3675 l gs col-1 s gr
+% Polyline
+n 4275 3675 m 4275 4125 l gs col-1 s gr
+% Polyline
+n 4125 4125 m 4425 4125 l gs col-1 s gr
+% Polyline
+n 4125 4200 m 4425 4200 l gs col-1 s gr
+% Polyline
+n 4275 4200 m 4275 4500 l 4950 4500 l gs col-1 s gr
+% Polyline
+n 4950 3975 m 4950 4950 l 2925 4950 l gs col-1 s gr
+% Polyline
+n 4875 3900 m 4800 3900 l gs col-1 s gr
+% Polyline
+n 4875 3900 m 4875 3825 l gs col-1 s gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 1725 m
+gs 1 -1 sc (DSR) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 2175 m
+gs 1 -1 sc (CD) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 2625 m
+gs 1 -1 sc (DTR) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 3750 m
+gs 1 -1 sc (TD) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 5025 m
+gs 1 -1 sc (GND) col-1 show gr
+/Times-Roman findfont 150.00 scalefont setfont
+3600 3525 m
+gs 1 -1 sc (10K) col-1 show gr
+/Times-Roman findfont 150.00 scalefont setfont
+3825 4275 m
+gs 1 -1 sc (1uf) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 6225 m
+gs 1 -1 sc (The data is transmitted at 115200 bps, well above the) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 6450 m
+gs 1 -1 sc (Timex baud rate, to allow the rather odd word format to) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 6675 m
+gs 1 -1 sc (be generated. However the start bits of the 115200) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 6900 m
+gs 1 -1 sc (data are still present, and confuse the watch. So the) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 7125 m
+gs 1 -1 sc (resistor and capacitor filter out the start bits, which) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 7350 m
+gs 1 -1 sc (are much shorter than the real data bits.) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 5775 m
+gs 1 -1 sc (Theory: ) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+2400 6000 m
+gs 1 -1 sc (Tie DSR, CD, DTR togather to form a null-modem.) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 4425 m
+gs 1 -1 sc (Timex and Datalink are registered trademarks) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 4650 m
+gs 1 -1 sc (of the Timex Corp.) col-1 show gr
+/Times-Roman findfont 150.00 scalefont setfont
+5175 2850 m
+gs 1 -1 sc (LED) col-1 show gr
+/Times-Roman findfont 360.00 scalefont setfont
+2100 900 m
+gs 1 -1 sc (Extra Cheesy Timex Datalink) col-1 show gr
+/Times-Roman findfont 360.00 scalefont setfont
+2700 1320 m
+gs 1 -1 sc (Serial Port Interface) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 2025 m
+gs 1 -1 sc (Developed by Tommy Johnson) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 2250 m
+gs 1 -1 sc (See http://csgrad.cs.vt.edu/~tjohnson/ for more) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 2475 m
+gs 1 -1 sc (info.) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 2850 m
+gs 1 -1 sc (I am not affiliated with Timex. This was developed) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 3075 m
+gs 1 -1 sc (without support from Timex. They DO NOT support) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+6675 3300 m
+gs 1 -1 sc (it, DO NOT ask them questions about it.) col-1 show gr
+% Ellipse
+n 4725 3675 300 300 0 360 DrawEllipse gs col-1 s gr
+
+showpage
+%%Page: 1 1
+$F2psEnd
+restore
diff --git a/doc/usage b/doc/usage
new file mode 100644
index 0000000..5c60df9
--- /dev/null
+++ b/doc/usage
@@ -0,0 +1,115 @@
+#include <datalink.h>
+
+WatchInfoPtr dl_init_watch(int which_watch);
+
+ which_watch is currently only DATALINK_150;
+
+ returns a pointer to a new WatchInfo pointer, NULL on error. If there
+ is an error, dl_error_proc will also be called. dl_error_proc can be
+ set with dl_set_error
+
+ItemPtr dl_new_item(WatchInfoPtr wi, int type);
+
+ wi is the WatchInfoPtr returned by dl_init_watch.
+ type can be one of
+ DL_TIME_TYPE for time packet
+ DL_ALARM_TYPE for alarm packet
+ DL_APP_TYPE for appointment packet
+ DL_PHONE_TYPE for phone packet
+ DL_TODO_TYPE for todo packet
+ DL_ANNIV_TYPE for anniversary packet
+ DL_SYSTEM_TYPE for system packet
+ DL_WRISTAPP_TYPE for wristapp packet
+ DL_MELODY_TYPE for melody packet
+
+ dl_new_item allocate an item structure and initializes it with the item
+ type supplied.
+
+ returns a pointer to a new item, NULL on error. If there is an error,
+ dl_error_proc will also be called. dl_error_proc can be set with
+ dl_set_error
+
+int dl_init_download(WatchInfoPtr wi, List times, List alarms,
+ List apps, List phones, List todos, List annivs,
+ List system, List wristapp, List melody);
+
+ wi is the WatchInfoPtr returned by dl_init_watch. times is the list
+ of times to download. alarams is the list of alarms to download, apps
+ is the list of appointments to download, phones is the list of phone
+ numbers to download, todos is the list of todo items to download,
+ annivs is the list of anniversaries to download, system is the list of
+ system data to download, wristapp is the list of wristapps to download
+ and melody is the list of melodies to download. Currently, system,
+ wristapp and melody can only be a list of 1 item.
+
+ dl_init_download will check the validity of the data being
+ downloaded to the watch. If everything is ready for the download,
+ dl_init_download will copy all of the data in preparation for a call
+ to dl_send_data.
+
+ If there are any problems with the data, depending on the severity,
+ dl_error_proc or dl_warn_proc will be called and the value of that
+ call will be retuned from dl_init_download.
+
+int dl_send_data(int device);
+
+ device is the type of output device to use in the download to
+ (SVGA_BLINK, SER_BLINK, PACKET_FILE).
+
+ dl_send_data will send the data prepared by dl_init_download using the
+ the selected blink engine. On error dl_error_proc is called and its
+ return value is returned.
+
+int dl_sizeof_item(ItemPtr item);
+
+ item is the item that you want to get a size of. The size is how
+ much of the database space in the watch that will be taken up by the
+ item. For Time, Alarm, System, WristApp, and Melody packets, the size
+ is 0.
+
+int dl_sizeof_list(List list);
+
+ list is a list of item that you want to get a size of. The size is how
+ much of the database space in the watch that will be taken up by the
+ item. For Time, Alarm, System, WristApp, and Melody packets, the size
+ is 0.
+
+int dl_item_ok(WatchInfoPtr wi, ItemPtr item);
+
+ wi is the WatchInfoPtr returned by dl_init_watch. times is the list
+ item is the item returned from dl_new_item that has had the data
+ portion filled by the calling application.
+
+ returns 1 if the item is OK, 0 otherwise.
+
+void dl_free_download()
+
+ free up space allocated for a download by dl_init_download.
+
+WatchInfoPtr dl_read_save(char *file, ListPtr *alarms, ListPtr *apps,
+ ListPtr *phones, ListPtr *todos, ListPtr *annivs, ListPtr *system,
+ ListPtr *wristapp, ListPtr *melody);
+
+ Initialize a watch structure with the contects of file. Return a watch
+ info structure and the lists.
+
+int dl_write_save(char *file, char *wristappfile, char *melodyfile);
+
+ Save the contents of a download to a reloadable file. dl_write_save
+ must be called after dl_init_download. file is the file to write the
+ save to. wristappfile is the file that the selected wristapp can be
+ read from. melodyfile is the file that the selected melody scheme can
+ be read from.
+
+int dl_pack_ascii(char *to, char *from);
+
+ Pack the characters in from into to using the watch character set.
+
+void dl_pack_fill_ascii(char *to, char *from, int size, char fill);
+
+ Pack the characters in from into to using the watch character
+ set. This is packed one character perl byte (unlike dl_pack_ascii).
+
+char dl_pack_char(char c);
+
+ Convert c into the watch characters set.
diff --git a/send_data.c b/send_data.c
new file mode 100644
index 0000000..1e91d4a
--- /dev/null
+++ b/send_data.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <vga.h>
+#include "datalink.h"
+#include "datalink_macros.h"
+
+int send_data(int type, unsigned char **packets, int npckts)
+{
+ int i;
+ register int j;
+ register unsigned char byte;
+ unsigned char white[80];
+ unsigned char black[80];
+ int inc = (type == DATALINK_70) ? 1 : 2;
+
+ for (i = 0; i < 80; i++)
+ {
+ white[i] = 0xff;
+ black[i] = 0x00;
+ }
+
+/* Become root to set vga mode. */
+ seteuid(0);
+ vga_init();
+
+/* This is redundant - vga_init() should do this itself... */
+/* but there's no harm in being sure */
+ seteuid(getuid());
+
+#ifdef MACH64_HACK
+/* For some reason, the latest mach 64 svga driver requires root on the
+ next call even though vga_init gave up root privileges. */
+ seteuid(0);
+#endif
+ vga_setmode(G640x480x2);
+#ifdef MACH64_HACK
+ seteuid(getuid());
+#endif
+
+ SYNC DATASTART for (i = 0; i < npckts; i++)
+ {
+
+ for (j = 0; j <= *packets[i]; j += inc)
+ {
+ vga_waitretrace();
+ byte = packets[i][j];
+ WRITE_BYTE1(1, byte) if (type == DATALINK_70)
+ continue;
+
+ if (j + 1 == packets[i][0])
+ WRITE_BYTE2(0, 0xff)
+ else
+ {
+ byte = packets[i][j + 1];
+ WRITE_BYTE2(1, byte)}
+
+ }
+
+ END_PACKET}
+
+#ifdef MACH64_HACK
+/* For some reason, the latest mach 64 svga driver requires root on the
+ next call even though vga_init gave up root privileges. */
+ seteuid(0);
+#endif
+ vga_setmode(TEXT);
+#ifdef MACH64_HACK
+ seteuid(getuid());
+#endif
+
+ return 0;
+}
diff --git a/serblink.1 b/serblink.1
new file mode 100644
index 0000000..1e5c748
--- /dev/null
+++ b/serblink.1
@@ -0,0 +1,51 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH DATALINK 1 "December 1, 2001"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+svgablink, serblink \- programs to send raw data to your Timex Datalink watch
+.SH SYNOPSIS
+.B svgablink
+.RI <DATA_FILE>
+.br
+.B serblink
+.RI <DATA_FILE>
+.SH DESCRIPTION
+This manual page documents briefly the
+.B svgablink
+and
+.B serblink
+commands.
+This manual page was written for the Debian GNU/Linux distribution
+because the original programs do not have manual pages.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBsvgablink\fP and \fBserblink\fP are programs that send data to the
+screen or serial transmitter (respectively) to communicate with a Timex
+Datalink watch. They are used by the programs "setwatch" and "settime".
+.SH "SEE ALSO"
+setwatch(1), settime(1).
+.SH AUTHOR
+The original datalink software was written by Karl R. Hakimian.
+.PP
+David Fries <dfries@mail.win.org> added support for the Ironman Datalink to
+the datalink software and now is the maintainer. http://datalink.fries.net/
+is the current home.
+.PP
+This manual page was written by Steaphan Greene <stea@cs.binghamton.edu>,
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/serblink.c b/serblink.c
new file mode 100644
index 0000000..9ca9fdc
--- /dev/null
+++ b/serblink.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 1996-2002 - Tommy Johnson <tjohnson@bobdbob.com>
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Unix implementation of the Timex Datalink protocol using an LED on a serial
+ * port. (see datalink.ps)
+ *
+ * See http://csgrad.cs.vt.edu/~tjohnson/ for more info.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#ifdef linux
+#define cfsetspeed cfsetospeed
+#endif
+
+#ifndef PORT
+#define PORT "/dev/ttyd1"
+#endif
+
+void sendbyte(int fil, unsigned char dat)
+#define ZERO "\0xff\0\0\0\0\0"
+#define ONE "\0\0\0\0\0\0"
+#define LEN 6
+{
+ static int frame = 0;
+ char buff[1024];
+ int c = 0;
+ int i;
+ memcpy(&buff[c], ZERO, LEN);
+ c += LEN;
+ for (i = 0; i < 8; i++)
+ {
+ memcpy(&buff[c], (dat & 1) ? ONE : ZERO, LEN);
+ c += LEN - (i & 1); /* CHEESY! the baud rate dosn't quite */
+ /* match, so alternate too long and too */
+ /* short. */
+ dat >>= 1; /* and... IT WORKS... (shudder) */
+ }
+ for (i = 0; i < (frame ? 12 : 4); i++)
+ {
+ memcpy(&buff[c], ONE, LEN);
+ c += LEN;
+ }
+ frame = !frame; /* a frame is 2 words, which would have been on */
+ /* a single CRT frame (different inter-word pause) */
+
+ write(fil, buff, c);
+}
+
+/* For pauses between packets: */
+static void __pause(int fil, int count)
+{
+ char buff[8192];
+ int i, c;
+
+ c = 0;
+ for (i = 0; i < (count * LEN); i++)
+ buff[c++] = 0x0;
+ write(fil, buff, c);
+}
+
+#undef ZERO
+#undef ONE
+#undef LEN
+
+int main(int argc, char **argv)
+{
+ int port;
+ int data;
+ struct termios old, new;
+ int i, j, len, plen;
+ unsigned char buff[4096];
+ char fil[1024];
+ char device[1024];
+
+ setpriority(PRIO_PROCESS, 0, -20); /* pauses will screwup the timing */
+
+ strcpy(fil, "DEBUGOUTPUT");
+ strcpy(device, PORT); /* defaults */
+
+#ifdef OTHERCMDLINE
+ while ((c = getopt(argc, argv, "h?d:f:")) != -1)
+ {
+ switch (c)
+ {
+ case 'h':
+ case '?':
+ fprintf(stderr,
+ "%s [-d device] [-f file]\n"
+ "Transmitt a file to a Timex Datalink watch useing an LED on a serial\n"
+ "port. Timex does not support this product, DO NOT ask them questions about\n"
+ "it. See http://csgrad.cs.vt.edu/~tjohnson/ for more info.\n"
+ "Version $Id: serblink.c,v 1.6 2002/07/10 04:14:22 david Exp $\n",
+ argv[0]);
+ exit(0);
+ break;
+ case 'd':
+ strcpy(device, optarg);
+ break;
+ case 'f':
+ strcpy(fil, optarg);
+ break;
+ }
+ }
+#else
+ if (argc == 2)
+ strcpy(fil, argv[1]);
+ else
+ {
+ fprintf(stderr,
+ "%s file\nTransmitt a file to a Timex Datalink watch useing an LED on a serial\n"
+ "port. Timex does not support this product, DO NOT ask them questions about\n"
+ "it. See http://csgrad.cs.vt.edu/~tjohnson/ for more info.\n"
+ "Version $Id: serblink.c,v 1.6 2002/07/10 04:14:22 david Exp $\n",
+ argv[0]);
+ exit(0);
+ }
+#endif
+
+ data = open(fil, O_RDONLY);
+ if (!data)
+ {
+ perror("open datafile failed:");
+ exit(1);
+ }
+ len = read(data, buff, 4096);
+ close(data);
+ printf("data length:%d\n", len);
+
+ port = open(device, O_RDWR);
+ if (port < 0)
+ {
+ perror("open of device failed:");
+ exit(1);
+ }
+
+ if (tcgetattr(port, &old) < 0)
+ {
+ perror("tcgetattr failed:");
+ exit(1);
+ }
+ new = old;
+ cfsetspeed(&new, B115200);
+ if (tcsetattr(port, TCSANOW, &new) < 0)
+ {
+ perror("tcsetattr failed:");
+ exit(1);
+ }
+#if 0
+ while (1)
+ __pause(port, 20); /* used for hardware debugging */
+#endif
+ printf("sync1\n");
+ for (i = 0; i < 500; i++)
+ {
+ sendbyte(port, 0x55);
+ if (!(i % 100))
+ printf("%d\n", 5 - (i / 100));
+ }
+ for (i = 0; i < 50; i++)
+ sendbyte(port, 0xAA);
+ printf("sync2\n");
+ i = 0;
+ do
+ {
+ plen = buff[i];
+ printf("%d\n", plen);
+ for (j = 0; j < plen; j++)
+ sendbyte(port, buff[i++]);
+ if (plen & 1)
+ sendbyte(port, 0);
+ __pause(port, 240);
+ }
+ while (i < len);
+
+ __pause(port, 240);
+ tcsetattr(port, TCSADRAIN, &new);
+ sleep(1);
+ close(port);
+ return 0;
+}
diff --git a/settime.1 b/settime.1
new file mode 100644
index 0000000..31a065a
--- /dev/null
+++ b/settime.1
@@ -0,0 +1,77 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH DATALINK 1 "December 1, 2001"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+setwatch, settime \- programs to send data to your Timex Datalink watch
+.SH SYNOPSIS
+.B setwatch
+.RI [ WATCH_TYPE ]\ [ OPTIONS ]\ [ DATAFILE ]
+.br
+.B settime
+.RI [ WATCH_TYPE ]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B setwatch
+and
+.B settime
+commands.
+This manual page was written for the Debian GNU/Linux distribution
+because the original programs do not have manual pages.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBsetwatch\fP is the main program in the datalink suite that can send
+data to your Timex Datalink watch. It can send all types of data used
+by these watches.
+.PP
+\fBsettime\fP is a simple utility that will just update the time on your
+watch. It will only accept a watch-type argument (defaulting to
+-ironman) and sends just the time.
+.SH WATCH_TYPE
+.TP
+.B \-\-help
+Show summary of options.
+.TP
+.B \-ironman
+Use if you have an Ironman Datalink watch. This is the default.
+.TP
+.B \-70, \-\-model70
+Use if you have a model 70 watch.
+.TP
+.B \-150s, \-\-model150
+Use if you have a model 150 watch.
+.TP
+.B \-150, \-\-model150s
+Use if you have a model 150s watch.
+.SH OPTIONS
+Run "setwatch -help" for options summary.
+.SH DATAFILE
+By default, the datafile will be loaded from ~/.datalink/datafile. Just
+copy the example file (/usr/doc/datalink/datafile) to this location and
+edit it as you please before running setwatch. Note that if you specify
+no options, nothing will happen. Perhaps you want to try the -all
+option to start.
+.SH AUTHOR
+The original datalink software was written by Karl R. Hakimian.
+.PP
+David Fries <dfries@mail.win.org> added support for the Ironman Datalink to
+the datalink software and now is the maintainer. http://datalink.fries.net/
+is the current home.
+.PP
+This manual page was written by Steaphan Greene <stea@cs.binghamton.edu>,
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/settime.c b/settime.c
new file mode 100644
index 0000000..7361599
--- /dev/null
+++ b/settime.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* settime: Example of Linux SDK for Timex watch. */
+/* Written by Karl R. Hakimian 10/3/96 */
+/* */
+/* Now warranty expressed or implied, use it as you see fit. */
+ /*
+ *
+ * Modified by David Fries <dfries@mail.win.org> 7/11/99
+ * - Added support for the Timex Datalink Ironman Triathlon
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include "datalink.h"
+
+extern char *tzname[];
+
+int set_time(WatchInfoPtr wi)
+{
+ time_t now;
+ struct tm *now_s;
+ ListPtr times;
+ ItemPtr tp;
+ int isdst;
+
+ now = time(NULL) + 9; /* Offset for sending to watch. */
+ now_s = localtime(&now);
+ isdst = (now_s->tm_isdst > 0) ? 1 : 0;
+
+ times = dl_new_list();
+ times->download = 1;
+ tp = dl_new_item(wi, DL_TIME_TYPE);
+
+ tp->data.time.hours = now_s->tm_hour;
+ tp->data.time.minutes = now_s->tm_min;
+ tp->data.time.seconds = now_s->tm_sec;
+ tp->data.time.month = now_s->tm_mon + 1;
+ tp->data.time.day = now_s->tm_mday;
+ tp->data.time.year = now_s->tm_year;
+/* TODO: investigate, see change log */
+ tp->data.time.dow = (now_s->tm_wday + 6) % 7;
+ tp->data.time.hour_fmt = 1;
+ tp->data.time.download = 1;
+ tp->data.time.label = tzname[isdst];
+ dl_add_to_list(times, tp);
+
+ if (isdst)
+ now -= 60 * 60;
+ else
+ now += 60 * 60;
+
+ now_s = localtime(&now);
+
+ tp = dl_new_item(wi, DL_TIME_TYPE);
+
+ tp->data.time.hours = now_s->tm_hour;
+ tp->data.time.minutes = now_s->tm_min;
+ tp->data.time.seconds = now_s->tm_sec;
+ tp->data.time.month = now_s->tm_mon + 1;
+ tp->data.time.day = now_s->tm_mday;
+ tp->data.time.year = now_s->tm_year;
+/* TODO: investigate, see change log */
+ tp->data.time.dow = (now_s->tm_wday + 6) % 7;
+ tp->data.time.hour_fmt = 1;
+ tp->data.time.download = 1;
+ tp->data.time.label = tzname[1 - isdst];
+ dl_add_to_list(times, tp);
+
+ dl_init_download(wi, times, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ return (0);
+}
+
+int my_error_proc(char *msg)
+{
+ fprintf(stderr, "ERROR: %s\n", msg);
+ exit(-1);
+}
+
+int my_warn_proc(char *msg)
+{
+ fprintf(stderr, "WARNING: %s\n", msg);
+ return (0);
+}
+
+int main( int argc, char ** argv)
+{
+ WatchInfoPtr wi;
+
+/*
+ Use my error proc to exit on error and my warn proc to ignore warnings
+*/
+ dl_set_error(my_error_proc);
+ dl_set_warn(my_error_proc);
+
+ if(argc==2)
+ {
+ if(!strcmp("-model70",argv[1])||!strcmp("-70",argv[1]))
+ wi = dl_init_watch(DATALINK_70);
+ else
+ if(!strcmp("-model150",argv[1])||!strcmp("-150",argv[1]))
+ wi = dl_init_watch(DATALINK_150);
+ else
+ if(!strcmp("-model150s",argv[1])||!strcmp("-150s",argv[1]))
+ wi = dl_init_watch(DATALINK_150S);
+ else
+ if(!strcmp("-ironman",argv[1]))
+ wi = dl_init_watch(DATALINK_IRONMAN);
+ else
+ {
+ printf("Usage: %s [ -model70 | -70 | -model70 | "
+ "-150 | -model150 | -model150s | -150s |"
+ " -ironman]\nVersion "
+ "$Id: settime.c,v 1.13 2002/07/10 04:23:23 david Exp $\n", argv[0]);
+ printf("The default is -model150 "
+ "if none is specified\n");
+ exit(1);
+ }
+ }
+ else
+ {
+ wi = dl_init_watch(DATALINK_IRONMAN);
+ }
+/*
+ Set the time.
+*/
+ if (set_time(wi))
+ exit(-1);
+/*
+ Send it to the watch
+*/
+ dl_send_data(wi, SVGA_BLINK);
+ return 0;
+}
diff --git a/setwatch.1 b/setwatch.1
new file mode 100644
index 0000000..8efdfe7
--- /dev/null
+++ b/setwatch.1
@@ -0,0 +1,77 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH DATALINK 1 "December 1, 2001"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+setwatch, settime \- programs to send data to your Timex Datalink watch
+.SH SYNOPSIS
+.B setwatch
+.RI [ WATCH_TYPE ]\ [ OPTIONS ]\ [ DATAFILE ]
+.br
+.B settime
+.RI [ WATCH_TYPE ]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B setwatch
+and
+.B settime
+commands.
+This manual page was written for the Debian GNU/Linux distribution
+because the original programs do not have manual pages.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBsetwatch\fP is the main program in the datalink suite that can send
+data to your Timex Datalink watch. It can send all types of data used
+by these watches.
+.PP
+\fBsettime\fP is a simple utility that will just update the time on your
+watch. It will only accept a watch-type argument (defaulting to
+-ironman) and sends just the time.
+.SH WATCH_TYPE
+.TP
+.B \-\-help
+Show summary of options.
+.TP
+.B \-ironman
+Use if you have an Ironman Datalink watch. This is the default.
+.TP
+.B \-70, \-\-model70
+Use if you have a model 70 watch.
+.TP
+.B \-150s, \-\-model150
+Use if you have a model 150 watch.
+.TP
+.B \-150, \-\-model150s
+Use if you have a model 150s watch.
+.SH OPTIONS
+Run "setwatch -help" for options summary.
+.SH DATAFILE
+By default, the datafile will be loaded from ~/.datalink/datafile. Just
+copy the example file (perhaps installed as /usr/doc/datalink/datafile?)
+to this location and edit it as you please before running setwatch.
+Note that if you specify no options, nothing will happen. Perhaps you
+want to try the -all option to start.
+.SH AUTHOR
+The original datalink software was written by Karl R. Hakimian.
+.PP
+David Fries <dfries@mail.win.org> added support for the Ironman Datalink to
+the datalink software and now is the maintainer. http://datalink.fries.net/
+is the current home.
+.PP
+This manual page was written by Steaphan Greene <stea@cs.binghamton.edu>,
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/setwatch.c b/setwatch.c
new file mode 100644
index 0000000..93a9364
--- /dev/null
+++ b/setwatch.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * setwatch: Example of Linux SDK for Timex watch.
+ * Written by Karl R. Hakimian 10/3/96
+ *
+ * Modified by David Fries <dfries@mail.win.org> 7/11/99
+ * - Added support for the Timex Datalink Ironman Triathlon
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <datalink.h>
+
+int my_error_proc(char *msg)
+{
+ fprintf(stderr, "ERROR: %s\n", msg);
+ exit(-1);
+}
+
+int my_warn_proc(char *msg)
+{
+ fprintf(stderr, "WARNING: %s\n", msg);
+ return (0);
+}
+
+ListPtr set_time(WatchInfoPtr wi, ListPtr times)
+{
+ time_t now;
+ time_t tztime;
+ struct tm *time_s;
+ ItemPtr tp;
+ int isdst;
+ int i;
+
+ now = time(NULL) + wi->time_adjust; /* Offset for sending to watch. */
+ time_s = localtime(&now);
+ isdst = (time_s->tm_isdst) ? 1 : 0;
+
+ if (!times->count)
+ {
+ tp = dl_new_item(wi, DL_TIME_TYPE);
+ tp->data.time.label = tzname[isdst];
+ tp->data.time.offset = timezone / 60;
+ tp->data.time.offset =
+ (isdst) ? (timezone / 60) - 60 : (timezone / 60);
+ tp->data.time.hour_fmt = 1;
+ dl_add_to_list(times, tp);
+ tp = dl_new_item(wi, DL_TIME_TYPE);
+ tp->data.time.label = tzname[1 - isdst];
+ tp->data.time.offset =
+ (isdst) ? (timezone / 60) : (timezone / 60) - 60;
+ tp->data.time.hour_fmt = 1;
+ dl_add_to_list(times, tp);
+ }
+
+ for (i = 0, tp = times->first; i < times->count;
+ i++, tp = tp->next)
+ {
+
+ if (!*tp->data.time.label)
+ {
+ tp->data.time.label = tzname[isdst];
+ tp->data.time.offset = timezone / 60;
+ }
+
+ tztime = now - tp->data.time.offset * 60;
+ time_s = localtime(&tztime);
+ tp->data.time.hours = time_s->tm_hour;
+ tp->data.time.minutes = time_s->tm_min;
+ tp->data.time.seconds = time_s->tm_sec;
+ tp->data.time.month = time_s->tm_mon + 1;
+ tp->data.time.day = time_s->tm_mday;
+ tp->data.time.year = time_s->tm_year % 100;
+ /* TODO: investigate, see change log about day of week */
+ tp->data.time.dow = (time_s->tm_wday + 6) % 7;
+ tp->data.time.download = 1;
+#ifdef DEBUGGING
+ printf("now %d, offset %d, dz %d, timezone %d\n", now,
+ tp->data.time.offset, time_s->tm_isdst, timezone);
+ printf("%d:%d:%d %d/%d/%d DOW %d\n", time_s->tm_hour,
+ time_s->tm_min, time_s->tm_sec, time_s->tm_mon + 1,
+ time_s->tm_mday, time_s->tm_year,
+ (time_s->tm_wday + 6) % 7);
+#endif
+
+ }
+
+ return (times);
+}
+
+void Usage()
+{
+ printf("DataLink Library Karl Hakimian <hakimian@eecs.wsu.edu>\n");
+ printf
+ ("\tIronman support added by David Fries <dfries@mail.win.org>\n");
+ printf("Usage: datalink [watch type] [options] [datafile]\n");
+ printf
+ ("watchtype (ironman is default, must be specified before other options)\n");
+ printf(" -model70\t use if you have this watch\n");
+ printf(" -70\t use if you have this watch\n");
+ printf(" -model70\t use if you have this watch\n");
+ printf(" -150\t use if you have this watch\n");
+ printf(" -model150\t use if you have this watch\n");
+ printf(" -150s\t use if you have this watch\n");
+ printf(" -model150s\t use if you have this watch\n");
+ printf(" -ironman\t use if you have this watch\n");
+ printf("options:\n");
+ printf("\tNot all options are available for all watches\n");
+ printf
+ ("\tIf you specify any of the send only... options following\n");
+ printf("\twill affect what other data is also sent\n");
+ printf("\tYou must specify at least one option to send data.\n");
+ printf(" -all\tsend all data to watch\n");
+ printf(" -db\tsend only database information\n");
+ printf(" -db\talso send database information\n");
+ printf(" -time\tonly send time information\n");
+ printf(" +time\talso send time information\n");
+ printf(" -alarm\tonly send alarm information\n");
+ printf(" +alarm\talso send alarm information\n");
+ printf(" -timer\tonly send timer information\n");
+ printf(" +timer\talso send timer information\n");
+ printf(" -wristapp\tonly send wristapp information\n");
+ printf(" +wristapp\talso send wristapp information\n");
+ printf(" -app\tonly send appointment information\n");
+ printf(" +app\talso send appointment information\n");
+ printf(" -melody\tonly send melody information\n");
+ printf(" +melody\talso send melody information\n");
+ printf(" -phone\tonly send phone information\n");
+ printf(" +phone\talso send phone information\n");
+ printf(" -chron\tonly send chronograph information\n");
+ printf(" +chron\talso send chronograph information\n");
+ printf
+ (" -system\tonly send system (hour/button beep) information\n");
+ printf
+ (" +system\talso send system (hour/button beep) information\n");
+ printf(" -reset\n");
+ printf(" +reset\n");
+ printf(" -sort-app-by-datetime\n");
+ printf(" -sort-app-by-label\n");
+ printf(" -sort-todo-by-label\n");
+ printf(" -sort-todo-by-prio\n");
+ printf(" -sort-phone\n");
+ printf(" -sort-anniv-by-date\n");
+ printf(" -sort-anniv-by-label\n");
+ printf(" -file\t dump data to DEBUGOUTPUT and do not display\n");
+ printf(" -serial\t send with the serial link\n");
+ printf
+ ("datafile: If not specified ~/.datalink/datafile is used\n");
+ printf
+ (" If any option is after the datafile, it will be ignored\n");
+ printf("Version $Id: setwatch.c,v 1.25 2002/07/21 23:04:49 david Exp $\n");
+}
+
+// ability to set the time
+#define TIME 0x001
+// ability to send alarms
+#define ALARM 0x002
+// ability to set appointments
+#define APP 0x004
+// ability to send todo
+#define TODO 0x008
+// ability to send phone list
+#define PHONE 0x010
+// ability to set anniversary
+#define ANNIV 0x020
+// ability to set key beep and hour beep
+#define SYSTEM 0x040
+// ability to send a program
+#define WRISTAPP 0x080
+// ability to set the beep sound
+#define MELODY 0x100
+// ability to preset timers and label
+#define TIMER 0x200
+// ability to set the lap count and label
+#define CHRON 0x400
+
+/* All would be 0x755 */
+#define ALL70 0x07F
+#define ALL150 0x1FF
+#define ALLIRONMAN 0x653
+#define DB 0x03C
+/*
+#define DEFAULT 0x03F
+*/
+#define DEFAULT 0
+
+int main(int argc, char **argv)
+{
+ char *prog = argv[0];
+ WatchInfoPtr wi;
+ ListPtr times, alarms, chron, timers, apps, todos, phones, annivs;
+ ListPtr system, wristapp, melody;
+ char datafile[1024];
+ int output = SVGA_BLINK;
+ int flags = DEFAULT;
+ int (*app_sort) () = dl_app_by_datetime;
+ int (*todo_sort) () = dl_todo_by_prio;
+ int (*phone_sort) () = dl_phone_by_label;
+ int (*anniv_sort) () = dl_anniv_by_date;
+ int type = DATALINK_IRONMAN;
+
+ while (argc > 1 && (*argv[1] == '-' || *argv[1] == '+'))
+ {
+
+ if (strcmp("-all", argv[1]) == 0)
+ {
+ if (type == DATALINK_70)
+ flags = ALL70;
+ if (type == DATALINK_150 || type == DATALINK_150S)
+ flags = ALL150;
+ if (type == DATALINK_IRONMAN)
+ flags = ALLIRONMAN;
+ } else if (strcmp("-db", argv[1]) == 0)
+ flags = DB;
+ else if (strcmp("+db", argv[1]) == 0)
+ flags |= DB;
+ else if (strcmp("-time", argv[1]) == 0)
+ flags = TIME;
+ else if (strcmp("+time", argv[1]) == 0)
+ flags |= TIME;
+ else if (strcmp("-alarm", argv[1]) == 0)
+ flags = ALARM;
+ else if (strcmp("+alarm", argv[1]) == 0)
+ flags |= ALARM;
+ else if (strcmp("-timer", argv[1]) == 0)
+ flags = TIMER;
+ else if (strcmp("+timer", argv[1]) == 0)
+ flags |= TIMER;
+ else if (strcmp("-wristapp", argv[1]) == 0)
+ flags = WRISTAPP;
+ else if (strcmp("+wristapp", argv[1]) == 0)
+ flags |= WRISTAPP;
+ else if (strcmp("-app", argv[1]) == 0)
+ flags = WRISTAPP;
+ else if (strcmp("+app", argv[1]) == 0)
+ flags |= WRISTAPP;
+ else if (strcmp("-melody", argv[1]) == 0)
+ flags = MELODY;
+ else if (strcmp("+melody", argv[1]) == 0)
+ flags |= MELODY;
+ /* on IRONMAN to send phone information we must
+ * also send chron information
+ */
+ else if (strcmp("-phone", argv[1]) == 0)
+ flags = PHONE | CHRON;
+ else if (strcmp("+phone", argv[1]) == 0)
+ flags |= PHONE | CHRON;
+ else if (strcmp("-chron", argv[1]) == 0)
+ flags = CHRON;
+ else if (strcmp("+chron", argv[1]) == 0)
+ flags |= CHRON;
+ else if (strcmp("-system", argv[1]) == 0)
+ flags = SYSTEM;
+ else if (strcmp("+system", argv[1]) == 0)
+ flags |= SYSTEM;
+ else if (strcmp("-reset", argv[1]) == 0)
+ {
+ flags = 0;
+ app_sort = todo_sort = phone_sort = anniv_sort =
+ NULL;
+ } else if (strcmp("-sort-app-by-datetime", argv[1]) == 0)
+ app_sort = dl_app_by_datetime;
+ else if (strcmp("-sort-app-by-label", argv[1]) == 0)
+ app_sort = dl_app_by_label;
+ else if (strcmp("-sort-todo-by-label", argv[1]) == 0)
+ todo_sort = dl_todo_by_label;
+ else if (strcmp("-sort-todo-by-prio", argv[1]) == 0)
+ todo_sort = dl_todo_by_prio;
+ else if (strcmp("-sort-phone", argv[1]) == 0)
+ phone_sort = dl_phone_by_label;
+ else if (strcmp("-sort-anniv-by-date", argv[1]) == 0)
+ anniv_sort = dl_anniv_by_date;
+ else if (strcmp("-sort-anniv-by-label", argv[1]) == 0)
+ anniv_sort = dl_anniv_by_label;
+ else if (strcmp("-file", argv[1]) == 0)
+ output = BLINK_FILE;
+ else if (strcmp("-serial", argv[1]) == 0)
+ output = SER_BLINK;
+ else if (strcmp("-model70", argv[1]) == 0)
+ type = DATALINK_70;
+ else if (strcmp("-70", argv[1]) == 0)
+ type = DATALINK_70;
+ else if (strcmp("-model150", argv[1]) == 0)
+ type = DATALINK_150;
+ else if (strcmp("-150", argv[1]) == 0)
+ type = DATALINK_150;
+ else if (strcmp("-model150s", argv[1]) == 0)
+ type = DATALINK_150S;
+ else if (strcmp("-150s", argv[1]) == 0)
+ type = DATALINK_150S;
+ else if (strcmp("-ironman", argv[1]) == 0)
+ type = DATALINK_IRONMAN;
+ else if (strcmp("--help", argv[1]) == 0)
+ {
+ Usage();
+ exit(-1);
+ } else if (strcmp("-h", argv[1]) == 0)
+ {
+ Usage();
+ exit(-1);
+ } else
+ {
+ fprintf(stderr, "%s: Unknown option (%s).\n", prog,
+ argv[1]);
+ Usage();
+ exit(-1);
+ }
+
+ argc--;
+ argv++;
+ }
+
+ if (flags&ALARM && !(flags&PHONE))
+ {
+ printf("Warning: Sending alarm information has been known to "
+ "corrupt the phone list on the watch, please check "
+ "and add +phone if you find this is the case.\n");
+ }
+
+ if (flags == DEFAULT)
+ {
+ Usage();
+ printf("**************** ERROR ****************\n");
+ printf
+ ("Error: the given options specify that no data be sent to the watch\n");
+ exit(-1);
+ }
+
+ if (argc == 2)
+ strcpy(datafile, argv[1]);
+ else if (argc > 2)
+ {
+ fprintf(stderr, "Usage: %s [datafile]\n", argv[0]);
+ exit(-1);
+ } else
+ {
+ strcpy(datafile, getenv("HOME"));
+ strcat(datafile, "/");
+ strcat(datafile, ".datalink/datafile");
+ }
+/*
+ Use my error proc to exit on error and my warn proc to ignore warnings
+*/
+ dl_set_error(my_error_proc);
+ dl_set_warn(my_warn_proc);
+
+ wi = dl_read_save(datafile, type, &times, &alarms, &chron, &timers,
+ &apps, &todos, &phones, &annivs, &system,
+ &wristapp, &melody);
+
+/* Mark for download. */
+
+ if ((flags & CHRON) && chron->count)
+ chron->download = 1;
+
+ if ((flags & ALARM) && alarms->count)
+ alarms->download = 1;
+
+ if ((flags & TIMER) && timers->count)
+ timers->download = 1;
+
+ if ((flags & APP) && apps->count)
+ {
+ apps->download = 1;
+
+ if (app_sort)
+ dl_sort(apps, app_sort);
+
+ }
+
+ if ((flags & TODO) && todos->count)
+ {
+ todos->download = 1;
+
+ if (todo_sort)
+ dl_sort(todos, todo_sort);
+
+ }
+
+ if ((flags & PHONE) && phones->count)
+ {
+ phones->download = 1;
+
+ if (phone_sort)
+ dl_sort(phones, phone_sort);
+
+ }
+
+ if ((flags & ANNIV) && annivs->count)
+ {
+ annivs->download = 1;
+
+ if (anniv_sort)
+ dl_sort(annivs, anniv_sort);
+
+ }
+
+ if ((flags & SYSTEM) && system->count)
+ system->download = 1;
+
+ if ((flags & WRISTAPP) && wristapp->count)
+ wristapp->download = 1;
+
+ if ((flags & MELODY) && melody->count)
+ melody->download = 1;
+
+ if ((flags & TIME))
+ {
+ times = set_time(wi, times);
+ times->download = 1;
+ } else
+ times = NULL;
+/*
+ Send it to the watch
+*/
+ dl_init_download(wi, times, alarms, chron, timers, apps, todos,
+ phones, annivs, system, wristapp, melody);
+ dl_send_data(wi, output);
+ return 0;
+}
diff --git a/sgiglblink.c b/sgiglblink.c
new file mode 100644
index 0000000..63f5492
--- /dev/null
+++ b/sgiglblink.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright 1997-2002 - Harold Zatz <hzatz@alumni.caltech.edu>
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * sgiglblink: SGI / Open GL program from writing to Timex datalink watches
+ * Note the Open GL implimentation must support switching the buffers durring
+ * the vertical retrace. This program is SGI specific in the way it selects a
+ * 60Hz screen refresh. Alternate code just doesn't exist.
+ */
+
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <signal.h>
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+struct packet
+{
+ char *data;
+ unsigned char size;
+ struct packet *next;
+};
+
+static int attribList[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
+
+Display *display;
+Window window;
+int width;
+int height;
+
+#define SPACE 28
+
+send(int sync0, unsigned char b0, int sync1, unsigned char b1)
+{
+ unsigned int mask = 1, scanline = 150;
+
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColor3f(1.0, 1.0, 1.0);
+ glBegin(GL_LINES);
+
+ if (sync0)
+ {
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ } else
+ scanline += 2;
+
+ scanline += SPACE;
+
+ while (mask != 256)
+ {
+ if (!(b0 & mask))
+ {
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ } else
+ scanline += 2;
+
+ mask <<= 1;
+ scanline += SPACE;
+ }
+
+ mask = 1;
+ scanline = 598;
+
+ if (sync1)
+ {
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ } else
+ scanline += 2;
+
+ scanline += SPACE;
+
+ while (mask != 256)
+ {
+ if (!(b1 & mask))
+ {
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ glVertex2d(0, height - scanline);
+ glVertex2d(width - 1, height - scanline++);
+ } else
+ scanline += 2;
+
+ mask <<= 1;
+ scanline += SPACE;
+ }
+
+ glEnd();
+
+ glXSwapBuffers(display, window);
+}
+
+main(int argc, char **argv)
+{
+ int fd, status, i;
+ unsigned char size;
+ struct packet *last = 0, *cur, *first = 0;
+ XVisualInfo *visualInfo;
+ XEvent event;
+ XSetWindowAttributes attribs;
+ GLXContext context;
+
+ /* Check proper number of args. */
+ if (argc != 2)
+ {
+ fprintf(stderr, "Usage: %s data_file\n", argv[0]);
+ exit(-1);
+ }
+
+ /* Open the data file. */
+ if ((fd = open(argv[1], O_RDONLY)) == -1)
+ {
+ fprintf(stderr, "Could not open %s for reading.\n",
+ argv[1]);
+ exit(-1);
+ }
+
+ /* Build some packets. */
+ while (status = read(fd, &size, 1) == 1)
+ {
+ cur = (struct packet *) malloc(sizeof(struct packet));
+
+ if (cur == 0)
+ {
+ fprintf(stderr,
+ "Could not allocate packet memory.\n");
+ exit(-1);
+ }
+
+ cur->data = (char *) malloc(size);
+ cur->data[0] = size;
+ if (read(fd, cur->data + 1, size - 1) != size - 1)
+ {
+ fprintf(stderr, "Could not read packet data.\n");
+ exit(-1);
+ }
+
+ if (cur == 0)
+ {
+ fprintf(stderr,
+ "Could not allocate packet data memory.\n");
+ exit(-1);
+ }
+
+ cur->size = size;
+ cur->next = 0;
+
+ if (last)
+ last->next = cur;
+ else
+ first = cur;
+
+ last = cur;
+ }
+
+ if (status != 0)
+ {
+ fprintf(stderr, "File error reading from %s.\n", argv[1]);
+ exit(-1);
+ }
+
+ close(fd);
+
+ /* Build a window. */
+ display = XOpenDisplay(0);
+ if (!display)
+ {
+ fprintf(stderr, "Can't open display\n");
+ exit(-1);
+ }
+
+ /* Set the monitor to a 60 Hz scanrate. */
+ system("/usr/gfx/setmon -n 60HZ");
+
+ /* Get a visual. */
+ visualInfo = glXChooseVisual(display, 0, attribList);
+
+ /* Get a colormap for that visual. */
+ attribs.colormap = XCreateColormap(display,
+ DefaultRootWindow(display),
+ visualInfo->visual, AllocNone);
+
+ /* We want no borders. */
+ attribs.border_pixel = 0;
+
+ /* We don't want the window manager mucking with us. */
+ attribs.override_redirect = 1;
+
+ width = XDisplayWidth(display, 0);
+ height = XDisplayHeight(display, 0);
+
+ /* Build a window filling the display in that visual. */
+ window = XCreateWindow(display, DefaultRootWindow(display),
+ 0, 0, width, height, 0,
+ visualInfo->depth, InputOutput,
+ visualInfo->visual,
+ CWBorderPixel | CWColormap |
+ CWOverrideRedirect, &attribs);
+
+ /* Build a gl context. */
+ context = glXCreateContext(display, visualInfo, 0, True);
+ glXMakeCurrent(display, window, context);
+ glOrtho(0, width - 1, 0, height - 1, 0, 1);
+
+ /* Map and raise the window. */
+ XMapRaised(display, window);
+ XFlush(display);
+
+ /* Send sync stuff... */
+ for (i = 0; i < 400; i++)
+ send(1, 0x55, 1, 0x55);
+
+ for (i = 0; i < 10; i++)
+ send(0, 0xff, 0, 0xff);
+
+ for (i = 0; i < 50; i++)
+ send(1, 0xaa, 0, 0xff);
+
+ for (i = 0; i < 10; i++)
+ send(0, 0xff, 0, 0xff);
+
+ /* Send the packets. */
+ for (cur = first; cur; cur = cur->next)
+ {
+ for (i = 0; i < cur->size; i += 2)
+ if (i - 1 == cur->size)
+ send(1, cur->data[i], 0, 0xff);
+ else
+ send(1, cur->data[i], 1, cur->data[i + 1]);
+
+ for (i = 0; i < 10; i++)
+ send(0, 0xff, 0, 0xff);
+ }
+
+ /* Set the monitor back to a 72 Hz scanrate. */
+ system("/usr/gfx/setmon -n 72HZ");
+}
diff --git a/svgablink.1 b/svgablink.1
new file mode 100644
index 0000000..1e5c748
--- /dev/null
+++ b/svgablink.1
@@ -0,0 +1,51 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH DATALINK 1 "December 1, 2001"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+svgablink, serblink \- programs to send raw data to your Timex Datalink watch
+.SH SYNOPSIS
+.B svgablink
+.RI <DATA_FILE>
+.br
+.B serblink
+.RI <DATA_FILE>
+.SH DESCRIPTION
+This manual page documents briefly the
+.B svgablink
+and
+.B serblink
+commands.
+This manual page was written for the Debian GNU/Linux distribution
+because the original programs do not have manual pages.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBsvgablink\fP and \fBserblink\fP are programs that send data to the
+screen or serial transmitter (respectively) to communicate with a Timex
+Datalink watch. They are used by the programs "setwatch" and "settime".
+.SH "SEE ALSO"
+setwatch(1), settime(1).
+.SH AUTHOR
+The original datalink software was written by Karl R. Hakimian.
+.PP
+David Fries <dfries@mail.win.org> added support for the Ironman Datalink to
+the datalink software and now is the maintainer. http://datalink.fries.net/
+is the current home.
+.PP
+This manual page was written by Steaphan Greene <stea@cs.binghamton.edu>,
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/svgablink.c b/svgablink.c
new file mode 100644
index 0000000..185a2ca
--- /dev/null
+++ b/svgablink.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Linux version of Timex/Microsoft SDK for Timex datalink watches making use
+ * of the svga library to select a graphic mode and draw on it.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fcntl.h>
+#include <signal.h>
+#include <sched.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "datalink.h"
+
+static void maxPriority();
+
+int main(int argc, char **argv)
+{
+ int oldvt;
+ unsigned char **data;
+ char buf[256];
+ int fd;
+ unsigned char size;
+ int n;
+ int p = 0;
+ int type = DATALINK_IRONMAN;
+
+/* Drop down to user privileges until we need root privs. */
+ seteuid(getuid());
+
+ while (argc > 1 && *argv[1] == '-')
+ {
+
+ if (strcmp(argv[1], "-ironman") == 0
+ || strcmp(argv[1], "-modelironman") == 0)
+ type = DATALINK_IRONMAN;
+ else
+ if (strcmp(argv[1], "-150") == 0
+ || strcmp(argv[1], "-model150") == 0)
+ type = DATALINK_150;
+ else
+ if (strcmp(argv[1], "-150s") == 0
+ || strcmp(argv[1], "-model150s") == 0)
+ type = DATALINK_150S;
+ else
+ if (strcmp(argv[1], "-70") == 0
+ || strcmp(argv[1], "-model70") == 0)
+ type = DATALINK_70;
+ else
+ {
+ fprintf(stderr, "Unknown option %s.\n", argv[1]);
+ fprintf(stderr, "Usage: %s [ -ironman | -modelironman | -150 | -model150 | -150s | \n"
+ "\t-model150s | -70 | -model70 ] datafile\n"
+ "Version $Id: svgablink.c,v 1.12 2002/07/10 04:27:08 david Exp $\n", argv[0]);
+ exit(-1);
+ }
+
+ argc--;
+ argv++;
+ }
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "Usage: %s data_file\n", argv[0]);
+ exit(-1);
+ }
+
+ if ((data = (unsigned char **) calloc(sizeof(unsigned char *),
+ 1024)) == NULL)
+ {
+ fprintf(stderr, "Could not allocate data array.\n");
+ exit(-1);
+ }
+
+/* Open data file */
+ if ((fd = open(argv[1], O_RDONLY)) < 0)
+ {
+ fprintf(stderr, "Could not open %s for reading.\n",
+ argv[1]);
+ exit(-1);
+ }
+
+/* Read in packets. */
+ while ((n = read(fd, &size, 1)) == 1)
+ {
+ size--;
+
+ if ((n = read(fd, buf, size)) != size)
+ break;
+
+ size++;
+
+ if ((data[p] = (char *) malloc(size)) == NULL)
+ {
+ fprintf(stderr,
+ "Could not allocate data buffer.\n");
+ exit(-1);
+ }
+
+ *data[p] = size;
+ memcpy(&data[p++][1], buf, size - 1);
+ };
+
+ if (n != 0)
+ {
+ fprintf(stderr, "File error reading from %s\n", argv[1]);
+ fprintf(stderr, "%d, %d, %d\n", n, size, p);
+ exit(-1);
+ }
+
+/* We need to detach from the terminal and our parent may need to wait for us
+ time to fork a child. */
+
+ switch (fork())
+ {
+ case 0:
+ break;
+ case -1:
+ perror("fork");
+ exit(-1);
+ default:
+ exit(0);
+ }
+
+/* The rest of this needs to be as root, open_vt, will raise privileges */
+
+ if ((oldvt = open_vt()) == -1)
+ exit(-1);
+
+ maxPriority();
+ send_data(type, data, p);
+ close_vt(oldvt);
+ return 0;
+}
+
+
+static void maxPriority()
+{
+ struct sched_param scp;
+
+ memset(&scp, '\0', sizeof(scp));
+ scp.sched_priority = sched_get_priority_max(SCHED_RR);
+ if (sched_setscheduler(0, SCHED_RR, &scp) < 0)
+ fprintf(stderr, "WARNING: Cannot set RR-scheduler.\n");
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0)
+ fprintf(stderr, "WARNING: Cannot disable paging.\n");
+
+}
diff --git a/vt.c b/vt.c
new file mode 100644
index 0000000..084a072
--- /dev/null
+++ b/vt.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright 1996-2002 - Karl R. Hakimian and David Fries
+ *
+ * This file is part of datalink.
+ *
+ * Datalink 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.
+ *
+ * Datalink 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 datalink (see COPYING); if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Linux version of Timex/Microsoft SDK for Timex datalink watches.
+ * SVGA needs a terminal when going to graphics mode. This will take
+ * care of that.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/vt.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+
+#define VTFMT "/dev/tty%d"
+
+int open_vt()
+{
+ struct vt_stat vts;
+ int fd;
+ int newvt;
+ char buf[1024];
+
+/* Need to become root again to deal with vt's */
+ seteuid(0);
+
+ if ((fd = open("/dev/tty", O_RDWR)) == -1)
+ {
+ perror("open");
+ return (-1);
+ }
+
+/* See if we are on a VT. */
+ if (ioctl(fd, VT_GETSTATE, &vts) == 0)
+ {
+ close(fd);
+ return (0);
+ }
+
+/* We are not on a VT, switch to one. */
+ close(fd);
+
+ if ((fd = open("/dev/tty0", O_RDWR)) == -1)
+ {
+ perror("open");
+ return (-1);
+ }
+
+/* Get info on current vt. */
+ if (ioctl(fd, VT_GETSTATE, &vts) == -1)
+ {
+ perror("VT_GETSTATE");
+ return (-1);
+ }
+
+/* Open a new vt. */
+ if (ioctl(fd, VT_OPENQRY, &newvt) == -1)
+ {
+ perror("VT_OPENQRY");
+ return (-1);
+ }
+
+ if (newvt == -1)
+ {
+ fprintf(stderr, "No free vts to open\n");
+ return (-1);
+ }
+
+/* Make the new vt, the active vt. */
+ if (ioctl(fd, VT_ACTIVATE, newvt) == -1)
+ {
+ perror("VT_ACTIVATE");
+ return (-1);
+ }
+
+ if (ioctl(fd, VT_WAITACTIVE, newvt) == -1)
+ {
+ perror("VT_WAITACTIVE");
+ return (-1);
+ }
+
+ close(fd);
+ close(2);
+ close(1);
+ close(0);
+/*
+ Detach from controlling terminal here so that we can get a new
+ controlling terminal.
+*/
+ setsid();
+ sprintf(buf, VTFMT, newvt);
+ (void) open(buf, O_RDWR);
+ (void) open(buf, O_RDWR);
+ (void) open(buf, O_RDWR);
+
+/* No longer need root privs - drop them*/
+ seteuid(getuid());
+
+ return (vts.v_active);
+}
+
+void close_vt(int oldvt)
+{
+ int fd;
+ struct vt_stat vts;
+ struct vt_mode VT;
+ int vt;
+
+ if (!oldvt)
+ return;
+
+/* Need to become root again to deal with vt's */
+ seteuid(0);
+
+/* SVGA lib sets the tty change mode to require a call back.
+ * We aren't in graphics mode, so set it back to auto.
+ */
+ if( ioctl(0, VT_GETMODE, &VT) == -1)
+ {
+ perror("VT_GETMODE");
+ return;
+ }
+
+ VT.mode = VT_AUTO;
+ if( ioctl(0, VT_SETMODE, &VT)== -1)
+ {
+ perror("VT_SETMODE");
+ return;
+ }
+
+/* Get info on current vt. */
+ if (ioctl(0, VT_GETSTATE, &vts) == -1)
+ {
+ perror("VT_GETSTATE");
+ return;
+ }
+
+ vt = vts.v_active;
+
+/* Switch back to previous vt. */
+
+ if (ioctl(0, VT_ACTIVATE, oldvt) == -1)
+ {
+ perror("VT_ACTIVATE");
+ return;
+ }
+
+ if (ioctl(0, VT_WAITACTIVE, oldvt) == -1)
+ {
+ perror("VT_WAITACTIVE");
+ return;
+ }
+
+ close(0);
+ close(1);
+ close(2);
+ setsid();
+
+/* Open current vt. */
+ if ((fd = open("/dev/tty0", O_RDWR)) == -1)
+ {
+ perror("open");
+ return;
+ }
+
+/* Free up our old vt. */
+ if (ioctl(fd, VT_DISALLOCATE, vt) == -1)
+ {
+ perror("VT_DISALLOCATE");
+ return;
+ }
+
+ close(fd);
+
+/* No longer need root privs - drop them*/
+ seteuid(getuid());
+}