From fd6bb20116127f6ac903d4b03abac72a49baa1ae Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Sat, 27 Apr 2019 22:20:21 +0100 Subject: fish --- 70.txt | 177 ++++++++++ COPYING | 340 +++++++++++++++++++ Makefile | 147 +++++++++ README | 112 +++++++ TODO | 23 ++ changelog | 88 +++++ datafile | 41 +++ datalink.h | 266 +++++++++++++++ datalink_macros.h | 100 ++++++ datalink_private.h | 63 ++++ dataread.l | 57 ++++ dataread.y | 619 +++++++++++++++++++++++++++++++++++ dl_add_to_list.c | 37 +++ dl_anniv_by_date.c | 34 ++ dl_anniv_by_label.c | 28 ++ dl_app_by_datetime.c | 39 +++ dl_app_by_label.c | 28 ++ dl_docrc.c | 52 +++ dl_fill_pack_ascii.c | 40 +++ dl_free_download.c | 65 ++++ dl_init_download.c | 607 ++++++++++++++++++++++++++++++++++ dl_init_watch.c | 150 +++++++++ dl_item_ok.c | 306 ++++++++++++++++++ dl_new_item.c | 48 +++ dl_new_list.c | 38 +++ dl_pack_ascii.c | 59 ++++ dl_pack_char.c | 42 +++ dl_pack_digit.c | 42 +++ dl_pack_phone.c | 55 ++++ dl_pack_size.c | 34 ++ dl_phone_by_label.c | 28 ++ dl_send_data.c | 897 +++++++++++++++++++++++++++++++++++++++++++++++++++ dl_set_error.c | 27 ++ dl_set_warn.c | 27 ++ dl_sizeof_item.c | 103 ++++++ dl_sizeof_list.c | 34 ++ dl_sort.c | 83 +++++ dl_string_ok.c | 44 +++ dl_todo_by_label.c | 28 ++ dl_todo_by_prio.c | 27 ++ dl_write_save.c | 153 +++++++++ doc/datalink.ps | 228 +++++++++++++ doc/usage | 115 +++++++ send_data.c | 93 ++++++ serblink.1 | 51 +++ serblink.c | 208 ++++++++++++ settime.1 | 77 +++++ settime.c | 156 +++++++++ setwatch.1 | 77 +++++ setwatch.c | 444 +++++++++++++++++++++++++ sgiglblink.c | 264 +++++++++++++++ svgablink.1 | 51 +++ svgablink.c | 171 ++++++++++ vt.c | 196 +++++++++++ 54 files changed, 7319 insertions(+) create mode 100644 70.txt create mode 100644 COPYING create mode 100644 Makefile create mode 100644 README create mode 100644 TODO create mode 100644 changelog create mode 100644 datafile create mode 100644 datalink.h create mode 100644 datalink_macros.h create mode 100644 datalink_private.h create mode 100644 dataread.l create mode 100644 dataread.y create mode 100644 dl_add_to_list.c create mode 100644 dl_anniv_by_date.c create mode 100644 dl_anniv_by_label.c create mode 100644 dl_app_by_datetime.c create mode 100644 dl_app_by_label.c create mode 100644 dl_docrc.c create mode 100644 dl_fill_pack_ascii.c create mode 100644 dl_free_download.c create mode 100644 dl_init_download.c create mode 100644 dl_init_watch.c create mode 100644 dl_item_ok.c create mode 100644 dl_new_item.c create mode 100644 dl_new_list.c create mode 100644 dl_pack_ascii.c create mode 100644 dl_pack_char.c create mode 100644 dl_pack_digit.c create mode 100644 dl_pack_phone.c create mode 100644 dl_pack_size.c create mode 100644 dl_phone_by_label.c create mode 100644 dl_send_data.c create mode 100644 dl_set_error.c create mode 100644 dl_set_warn.c create mode 100644 dl_sizeof_item.c create mode 100644 dl_sizeof_list.c create mode 100644 dl_sort.c create mode 100644 dl_string_ok.c create mode 100644 dl_todo_by_label.c create mode 100644 dl_todo_by_prio.c create mode 100644 dl_write_save.c create mode 100644 doc/datalink.ps create mode 100644 doc/usage create mode 100644 send_data.c create mode 100644 serblink.1 create mode 100644 serblink.c create mode 100644 settime.1 create mode 100644 settime.c create mode 100644 setwatch.1 create mode 100644 setwatch.c create mode 100644 sgiglblink.c create mode 100644 svgablink.1 create mode 100644 svgablink.c create mode 100644 vt.c 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. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. 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 + and David Fries + +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 , 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 + +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 + +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 + +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 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 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 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 +#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 7/11/99 + * - Added support for the Timex Datalink Ironman Triathlon + */ +#include +#include +#include +#include +#include +#include +#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 NAME +%left STRING +%left INTEGER +%left TIME +%left DATE + +%type 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 +#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 +#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 +#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 +#include +#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 +#include +#include +#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 +#include +#include +#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 +#include +#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 +#include +#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 +#include +#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 + +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 + +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 +#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 +#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 +#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 +#include +#include +#include +#include +#include +#include +#include +#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 +#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 +#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 +#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 +#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 +#include + +#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 + +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 +#include +#include +#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 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 +.br +.B serblink +.RI +.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\fP and +.\" \fI\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 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 , +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 + * + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#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 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\fP and +.\" \fI\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 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 , +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 7/11/99 + * - Added support for the Timex Datalink Ironman Triathlon + */ + +#include +#include +#include +#include +#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 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\fP and +.\" \fI\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 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 , +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 7/11/99 + * - Added support for the Timex Datalink Ironman Triathlon + */ + +#include +#include +#include +#include +#include +#include +#include + +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 \n"); + printf + ("\tIronman support added by David Fries \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, ×, &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 + * + * 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 +#include +#include +#include +#include +#include + +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 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 +.br +.B serblink +.RI +.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\fP and +.\" \fI\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 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 , +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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include + +#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()); +} -- cgit v1.2.3