summaryrefslogtreecommitdiffstats
path: root/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock
diff options
context:
space:
mode:
Diffstat (limited to 'debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock')
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.am91
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.in1037
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/address.c313
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/appinfo.c119
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/blob.c173
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/bluetooth.c830
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/calendar.c737
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/cmp.c655
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/connect.c126
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/contact.c586
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/darwinusb.c1968
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/datebook.c485
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/debug.c242
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/dlp.c4911
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/expense.c481
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/freebsdusb.c460
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/hinote.c180
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/inet.c595
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/libusb.c605
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/linuxusb.c400
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/location.c805
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/mail.c683
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/md5.c240
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/memo.c186
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/money.c268
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/net.c715
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/notepad.c265
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/padp.c971
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/palmpix.c1815
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-buffer.c117
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-file.c1531
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-header.c63
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/serial.c717
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/slp.c657
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/socket.c1694
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/sys.c372
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/syspkt.c1031
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/threadsafe.c70
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/todo.c293
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/unixserial.c745
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/usb.c1099
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/utils.c413
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/veo.c165
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/versamail.c394
44 files changed, 30303 insertions, 0 deletions
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.am b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.am
new file mode 100644
index 00000000..e5b11162
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.am
@@ -0,0 +1,91 @@
+INCLUDES = \
+ -I../include \
+ -I$(top_srcdir)/include
+
+bluetooth_FILES = \
+ bluetooth.c
+
+serial_FILES = \
+ unixserial.c
+serial_SOURCE = unixserial.c
+
+usb_FILES = \
+ usb.c \
+ libusb.c \
+ linuxusb.c \
+ freebsdusb.c \
+ darwinusb.c
+
+if WITH_LIBUSB
+usb_SOURCE = usb.c libusb.c
+endif
+
+if WITH_LINUXUSB
+usb_SOURCE = usb.c linuxusb.c
+endif
+
+if WITH_FREEBSDUSB
+usb_SOURCE = usb.c freebsdusb.c
+endif
+
+if WITH_DARWINUSB
+usb_SOURCE = usb.c darwinusb.c
+endif
+
+if WITH_BLUEZ
+bluetooth_SOURCE = bluetooth.c
+endif
+
+lib_LTLIBRARIES = libpisock.la
+
+# All new sources MUST be added here, or anything
+# building against libpisock will fail!
+libpisock_la_SOURCES = \
+ $(bluetooth_SOURCE) \
+ $(serial_SOURCE) \
+ $(usb_SOURCE) \
+ address.c \
+ appinfo.c \
+ connect.c \
+ contact.c \
+ cmp.c \
+ datebook.c \
+ debug.c \
+ dlp.c \
+ expense.c \
+ hinote.c \
+ inet.c \
+ location.c \
+ blob.c \
+ calendar.c \
+ mail.c \
+ md5.c \
+ memo.c \
+ money.c \
+ net.c \
+ notepad.c \
+ padp.c \
+ palmpix.c \
+ pi-buffer.c \
+ pi-file.c \
+ pi-header.c \
+ serial.c \
+ slp.c \
+ sys.c \
+ socket.c \
+ syspkt.c \
+ threadsafe.c \
+ todo.c \
+ utils.c \
+ veo.c \
+ versamail.c
+
+# Including PTHREAD_CFLAGS here is a dirty ugly kluge. It works.
+libpisock_la_LIBADD = \
+ @usb_libs@ @PTHREAD_LIBS@ @PTHREAD_CFLAGS@ @BLUEZ_LIBS@
+
+libpisock_la_LDFLAGS = \
+ -export-dynamic -version-info $(PISOCK_CURRENT):$(PISOCK_REVISION):$(PISOCK_AGE)
+libpisock_la_CFLAGS = $(PIC_LIBS) @PTHREAD_CFLAGS@ @BLUEZ_CFLAGS@
+
+EXTRA_DIST = $(bluetooth_FILES) $(serial_FILES) $(usb_FILES)
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.in b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.in
new file mode 100644
index 00000000..d7a3c539
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/Makefile.in
@@ -0,0 +1,1037 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = libpisock
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/bluez.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/python.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/tcl.m4 \
+ $(top_srcdir)/m4/threads.m4 \
+ $(top_srcdir)/m4/vl_lib_readline.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h \
+ $(top_builddir)/include/pi-md5.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libpisock_la_DEPENDENCIES =
+am__libpisock_la_SOURCES_DIST = bluetooth.c unixserial.c usb.c \
+ darwinusb.c freebsdusb.c libusb.c linuxusb.c address.c \
+ appinfo.c connect.c contact.c cmp.c datebook.c debug.c dlp.c \
+ expense.c hinote.c inet.c location.c blob.c calendar.c mail.c \
+ md5.c memo.c money.c net.c notepad.c padp.c palmpix.c \
+ pi-buffer.c pi-file.c pi-header.c serial.c slp.c sys.c \
+ socket.c syspkt.c threadsafe.c todo.c utils.c veo.c \
+ versamail.c
+@WITH_BLUEZ_TRUE@am__objects_1 = libpisock_la-bluetooth.lo
+am__objects_2 = libpisock_la-unixserial.lo
+@WITH_DARWINUSB_FALSE@@WITH_FREEBSDUSB_FALSE@@WITH_LIBUSB_FALSE@@WITH_LINUXUSB_TRUE@am__objects_3 = libpisock_la-usb.lo \
+@WITH_DARWINUSB_FALSE@@WITH_FREEBSDUSB_FALSE@@WITH_LIBUSB_FALSE@@WITH_LINUXUSB_TRUE@ libpisock_la-linuxusb.lo
+@WITH_DARWINUSB_FALSE@@WITH_FREEBSDUSB_FALSE@@WITH_LIBUSB_TRUE@am__objects_3 = libpisock_la-usb.lo \
+@WITH_DARWINUSB_FALSE@@WITH_FREEBSDUSB_FALSE@@WITH_LIBUSB_TRUE@ libpisock_la-libusb.lo
+@WITH_DARWINUSB_FALSE@@WITH_FREEBSDUSB_TRUE@am__objects_3 = libpisock_la-usb.lo \
+@WITH_DARWINUSB_FALSE@@WITH_FREEBSDUSB_TRUE@ libpisock_la-freebsdusb.lo
+@WITH_DARWINUSB_TRUE@am__objects_3 = libpisock_la-usb.lo \
+@WITH_DARWINUSB_TRUE@ libpisock_la-darwinusb.lo
+am_libpisock_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3) libpisock_la-address.lo \
+ libpisock_la-appinfo.lo libpisock_la-connect.lo \
+ libpisock_la-contact.lo libpisock_la-cmp.lo \
+ libpisock_la-datebook.lo libpisock_la-debug.lo \
+ libpisock_la-dlp.lo libpisock_la-expense.lo \
+ libpisock_la-hinote.lo libpisock_la-inet.lo \
+ libpisock_la-location.lo libpisock_la-blob.lo \
+ libpisock_la-calendar.lo libpisock_la-mail.lo \
+ libpisock_la-md5.lo libpisock_la-memo.lo libpisock_la-money.lo \
+ libpisock_la-net.lo libpisock_la-notepad.lo \
+ libpisock_la-padp.lo libpisock_la-palmpix.lo \
+ libpisock_la-pi-buffer.lo libpisock_la-pi-file.lo \
+ libpisock_la-pi-header.lo libpisock_la-serial.lo \
+ libpisock_la-slp.lo libpisock_la-sys.lo libpisock_la-socket.lo \
+ libpisock_la-syspkt.lo libpisock_la-threadsafe.lo \
+ libpisock_la-todo.lo libpisock_la-utils.lo libpisock_la-veo.lo \
+ libpisock_la-versamail.lo
+libpisock_la_OBJECTS = $(am_libpisock_la_OBJECTS)
+libpisock_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libpisock_la_CFLAGS) \
+ $(CFLAGS) $(libpisock_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libpisock_la_SOURCES)
+DIST_SOURCES = $(am__libpisock_la_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
+CAT_ENTRY_END = @CAT_ENTRY_END@
+CAT_ENTRY_START = @CAT_ENTRY_START@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DOCBOOK_ROOT = @DOCBOOK_ROOT@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+GREP = @GREP@
+ICONV_CFLAGS = @ICONV_CFLAGS@
+ICONV_LIBS = @ICONV_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVA = @JAVA@
+JAVABASE = @JAVABASE@
+JAVAC = @JAVAC@
+JAVA_VERSION = @JAVA_VERSION@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PIC_LIBS = @PIC_LIBS@
+PILOT_LINK_MAJOR = @PILOT_LINK_MAJOR@
+PILOT_LINK_MINOR = @PILOT_LINK_MINOR@
+PILOT_LINK_PATCH = @PILOT_LINK_PATCH@
+PILOT_LINK_VERS = @PILOT_LINK_VERS@
+PISOCK_AGE = @PISOCK_AGE@
+PISOCK_CURRENT = @PISOCK_CURRENT@
+PISOCK_REVISION = @PISOCK_REVISION@
+PISYNC_AGE = @PISYNC_AGE@
+PISYNC_CURRENT = @PISYNC_CURRENT@
+PISYNC_REVISION = @PISYNC_REVISION@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_CFLAGS = @PNG_CFLAGS@
+PNG_LIBS = @PNG_LIBS@
+POPT_INCLUDES = @POPT_INCLUDES@
+POPT_LIBS = @POPT_LIBS@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTHON = @PYTHON@
+PYTHON_CFLAGS = @PYTHON_CFLAGS@
+PYTHON_H = @PYTHON_H@
+PYTHON_LIBS = @PYTHON_LIBS@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RL_LIBS = @RL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TCLSH_PROG = @TCLSH_PROG@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_DEFS = @TCL_DEFS@
+TCL_EXTRA_CFLAGS = @TCL_EXTRA_CFLAGS@
+TCL_INCLUDES = @TCL_INCLUDES@
+TCL_LD_FLAGS = @TCL_LD_FLAGS@
+TCL_LIBS = @TCL_LIBS@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_SHLIB_LD_LIBS = @TCL_SHLIB_LD_LIBS@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+VERSION = @VERSION@
+WISH_PROG = @WISH_PROG@
+XML_CATALOG = @XML_CATALOG@
+XSLTPROC = @XSLTPROC@
+XSLTPROC_FLAGS = @XSLTPROC_FLAGS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_F77 = @ac_ct_F77@
+acx_pthread_config = @acx_pthread_config@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+usb_libs = @usb_libs@
+INCLUDES = \
+ -I../include \
+ -I$(top_srcdir)/include
+
+bluetooth_FILES = \
+ bluetooth.c
+
+serial_FILES = \
+ unixserial.c
+
+serial_SOURCE = unixserial.c
+usb_FILES = \
+ usb.c \
+ libusb.c \
+ linuxusb.c \
+ freebsdusb.c \
+ darwinusb.c
+
+@WITH_DARWINUSB_TRUE@usb_SOURCE = usb.c darwinusb.c
+@WITH_FREEBSDUSB_TRUE@usb_SOURCE = usb.c freebsdusb.c
+@WITH_LIBUSB_TRUE@usb_SOURCE = usb.c libusb.c
+@WITH_LINUXUSB_TRUE@usb_SOURCE = usb.c linuxusb.c
+@WITH_BLUEZ_TRUE@bluetooth_SOURCE = bluetooth.c
+lib_LTLIBRARIES = libpisock.la
+
+# All new sources MUST be added here, or anything
+# building against libpisock will fail!
+libpisock_la_SOURCES = \
+ $(bluetooth_SOURCE) \
+ $(serial_SOURCE) \
+ $(usb_SOURCE) \
+ address.c \
+ appinfo.c \
+ connect.c \
+ contact.c \
+ cmp.c \
+ datebook.c \
+ debug.c \
+ dlp.c \
+ expense.c \
+ hinote.c \
+ inet.c \
+ location.c \
+ blob.c \
+ calendar.c \
+ mail.c \
+ md5.c \
+ memo.c \
+ money.c \
+ net.c \
+ notepad.c \
+ padp.c \
+ palmpix.c \
+ pi-buffer.c \
+ pi-file.c \
+ pi-header.c \
+ serial.c \
+ slp.c \
+ sys.c \
+ socket.c \
+ syspkt.c \
+ threadsafe.c \
+ todo.c \
+ utils.c \
+ veo.c \
+ versamail.c
+
+
+# Including PTHREAD_CFLAGS here is a dirty ugly kluge. It works.
+libpisock_la_LIBADD = \
+ @usb_libs@ @PTHREAD_LIBS@ @PTHREAD_CFLAGS@ @BLUEZ_LIBS@
+
+libpisock_la_LDFLAGS = \
+ -export-dynamic -version-info $(PISOCK_CURRENT):$(PISOCK_REVISION):$(PISOCK_AGE)
+
+libpisock_la_CFLAGS = $(PIC_LIBS) @PTHREAD_CFLAGS@ @BLUEZ_CFLAGS@
+EXTRA_DIST = $(bluetooth_FILES) $(serial_FILES) $(usb_FILES)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpisock/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libpisock/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libpisock.la: $(libpisock_la_OBJECTS) $(libpisock_la_DEPENDENCIES)
+ $(libpisock_la_LINK) -rpath $(libdir) $(libpisock_la_OBJECTS) $(libpisock_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-address.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-appinfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-blob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-bluetooth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-calendar.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-cmp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-connect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-contact.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-darwinusb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-datebook.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-dlp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-expense.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-freebsdusb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-hinote.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-inet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-libusb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-linuxusb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-location.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-mail.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-md5.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-memo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-money.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-net.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-notepad.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-padp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-palmpix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-pi-buffer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-pi-file.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-pi-header.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-serial.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-slp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-socket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-sys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-syspkt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-threadsafe.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-todo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-unixserial.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-usb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-veo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpisock_la-versamail.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libpisock_la-bluetooth.lo: bluetooth.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-bluetooth.lo -MD -MP -MF $(DEPDIR)/libpisock_la-bluetooth.Tpo -c -o libpisock_la-bluetooth.lo `test -f 'bluetooth.c' || echo '$(srcdir)/'`bluetooth.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-bluetooth.Tpo $(DEPDIR)/libpisock_la-bluetooth.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bluetooth.c' object='libpisock_la-bluetooth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-bluetooth.lo `test -f 'bluetooth.c' || echo '$(srcdir)/'`bluetooth.c
+
+libpisock_la-unixserial.lo: unixserial.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-unixserial.lo -MD -MP -MF $(DEPDIR)/libpisock_la-unixserial.Tpo -c -o libpisock_la-unixserial.lo `test -f 'unixserial.c' || echo '$(srcdir)/'`unixserial.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-unixserial.Tpo $(DEPDIR)/libpisock_la-unixserial.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='unixserial.c' object='libpisock_la-unixserial.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-unixserial.lo `test -f 'unixserial.c' || echo '$(srcdir)/'`unixserial.c
+
+libpisock_la-usb.lo: usb.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-usb.lo -MD -MP -MF $(DEPDIR)/libpisock_la-usb.Tpo -c -o libpisock_la-usb.lo `test -f 'usb.c' || echo '$(srcdir)/'`usb.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-usb.Tpo $(DEPDIR)/libpisock_la-usb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='usb.c' object='libpisock_la-usb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-usb.lo `test -f 'usb.c' || echo '$(srcdir)/'`usb.c
+
+libpisock_la-darwinusb.lo: darwinusb.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-darwinusb.lo -MD -MP -MF $(DEPDIR)/libpisock_la-darwinusb.Tpo -c -o libpisock_la-darwinusb.lo `test -f 'darwinusb.c' || echo '$(srcdir)/'`darwinusb.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-darwinusb.Tpo $(DEPDIR)/libpisock_la-darwinusb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='darwinusb.c' object='libpisock_la-darwinusb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-darwinusb.lo `test -f 'darwinusb.c' || echo '$(srcdir)/'`darwinusb.c
+
+libpisock_la-freebsdusb.lo: freebsdusb.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-freebsdusb.lo -MD -MP -MF $(DEPDIR)/libpisock_la-freebsdusb.Tpo -c -o libpisock_la-freebsdusb.lo `test -f 'freebsdusb.c' || echo '$(srcdir)/'`freebsdusb.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-freebsdusb.Tpo $(DEPDIR)/libpisock_la-freebsdusb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='freebsdusb.c' object='libpisock_la-freebsdusb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-freebsdusb.lo `test -f 'freebsdusb.c' || echo '$(srcdir)/'`freebsdusb.c
+
+libpisock_la-libusb.lo: libusb.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-libusb.lo -MD -MP -MF $(DEPDIR)/libpisock_la-libusb.Tpo -c -o libpisock_la-libusb.lo `test -f 'libusb.c' || echo '$(srcdir)/'`libusb.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-libusb.Tpo $(DEPDIR)/libpisock_la-libusb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libusb.c' object='libpisock_la-libusb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-libusb.lo `test -f 'libusb.c' || echo '$(srcdir)/'`libusb.c
+
+libpisock_la-linuxusb.lo: linuxusb.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-linuxusb.lo -MD -MP -MF $(DEPDIR)/libpisock_la-linuxusb.Tpo -c -o libpisock_la-linuxusb.lo `test -f 'linuxusb.c' || echo '$(srcdir)/'`linuxusb.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-linuxusb.Tpo $(DEPDIR)/libpisock_la-linuxusb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='linuxusb.c' object='libpisock_la-linuxusb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-linuxusb.lo `test -f 'linuxusb.c' || echo '$(srcdir)/'`linuxusb.c
+
+libpisock_la-address.lo: address.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-address.lo -MD -MP -MF $(DEPDIR)/libpisock_la-address.Tpo -c -o libpisock_la-address.lo `test -f 'address.c' || echo '$(srcdir)/'`address.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-address.Tpo $(DEPDIR)/libpisock_la-address.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='address.c' object='libpisock_la-address.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-address.lo `test -f 'address.c' || echo '$(srcdir)/'`address.c
+
+libpisock_la-appinfo.lo: appinfo.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-appinfo.lo -MD -MP -MF $(DEPDIR)/libpisock_la-appinfo.Tpo -c -o libpisock_la-appinfo.lo `test -f 'appinfo.c' || echo '$(srcdir)/'`appinfo.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-appinfo.Tpo $(DEPDIR)/libpisock_la-appinfo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='appinfo.c' object='libpisock_la-appinfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-appinfo.lo `test -f 'appinfo.c' || echo '$(srcdir)/'`appinfo.c
+
+libpisock_la-connect.lo: connect.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-connect.lo -MD -MP -MF $(DEPDIR)/libpisock_la-connect.Tpo -c -o libpisock_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-connect.Tpo $(DEPDIR)/libpisock_la-connect.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='connect.c' object='libpisock_la-connect.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
+
+libpisock_la-contact.lo: contact.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-contact.lo -MD -MP -MF $(DEPDIR)/libpisock_la-contact.Tpo -c -o libpisock_la-contact.lo `test -f 'contact.c' || echo '$(srcdir)/'`contact.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-contact.Tpo $(DEPDIR)/libpisock_la-contact.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='contact.c' object='libpisock_la-contact.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-contact.lo `test -f 'contact.c' || echo '$(srcdir)/'`contact.c
+
+libpisock_la-cmp.lo: cmp.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-cmp.lo -MD -MP -MF $(DEPDIR)/libpisock_la-cmp.Tpo -c -o libpisock_la-cmp.lo `test -f 'cmp.c' || echo '$(srcdir)/'`cmp.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-cmp.Tpo $(DEPDIR)/libpisock_la-cmp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cmp.c' object='libpisock_la-cmp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-cmp.lo `test -f 'cmp.c' || echo '$(srcdir)/'`cmp.c
+
+libpisock_la-datebook.lo: datebook.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-datebook.lo -MD -MP -MF $(DEPDIR)/libpisock_la-datebook.Tpo -c -o libpisock_la-datebook.lo `test -f 'datebook.c' || echo '$(srcdir)/'`datebook.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-datebook.Tpo $(DEPDIR)/libpisock_la-datebook.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='datebook.c' object='libpisock_la-datebook.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-datebook.lo `test -f 'datebook.c' || echo '$(srcdir)/'`datebook.c
+
+libpisock_la-debug.lo: debug.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-debug.lo -MD -MP -MF $(DEPDIR)/libpisock_la-debug.Tpo -c -o libpisock_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-debug.Tpo $(DEPDIR)/libpisock_la-debug.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='debug.c' object='libpisock_la-debug.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c
+
+libpisock_la-dlp.lo: dlp.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-dlp.lo -MD -MP -MF $(DEPDIR)/libpisock_la-dlp.Tpo -c -o libpisock_la-dlp.lo `test -f 'dlp.c' || echo '$(srcdir)/'`dlp.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-dlp.Tpo $(DEPDIR)/libpisock_la-dlp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dlp.c' object='libpisock_la-dlp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-dlp.lo `test -f 'dlp.c' || echo '$(srcdir)/'`dlp.c
+
+libpisock_la-expense.lo: expense.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-expense.lo -MD -MP -MF $(DEPDIR)/libpisock_la-expense.Tpo -c -o libpisock_la-expense.lo `test -f 'expense.c' || echo '$(srcdir)/'`expense.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-expense.Tpo $(DEPDIR)/libpisock_la-expense.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='expense.c' object='libpisock_la-expense.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-expense.lo `test -f 'expense.c' || echo '$(srcdir)/'`expense.c
+
+libpisock_la-hinote.lo: hinote.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-hinote.lo -MD -MP -MF $(DEPDIR)/libpisock_la-hinote.Tpo -c -o libpisock_la-hinote.lo `test -f 'hinote.c' || echo '$(srcdir)/'`hinote.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-hinote.Tpo $(DEPDIR)/libpisock_la-hinote.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hinote.c' object='libpisock_la-hinote.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-hinote.lo `test -f 'hinote.c' || echo '$(srcdir)/'`hinote.c
+
+libpisock_la-inet.lo: inet.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-inet.lo -MD -MP -MF $(DEPDIR)/libpisock_la-inet.Tpo -c -o libpisock_la-inet.lo `test -f 'inet.c' || echo '$(srcdir)/'`inet.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-inet.Tpo $(DEPDIR)/libpisock_la-inet.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='inet.c' object='libpisock_la-inet.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-inet.lo `test -f 'inet.c' || echo '$(srcdir)/'`inet.c
+
+libpisock_la-location.lo: location.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-location.lo -MD -MP -MF $(DEPDIR)/libpisock_la-location.Tpo -c -o libpisock_la-location.lo `test -f 'location.c' || echo '$(srcdir)/'`location.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-location.Tpo $(DEPDIR)/libpisock_la-location.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='location.c' object='libpisock_la-location.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-location.lo `test -f 'location.c' || echo '$(srcdir)/'`location.c
+
+libpisock_la-blob.lo: blob.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-blob.lo -MD -MP -MF $(DEPDIR)/libpisock_la-blob.Tpo -c -o libpisock_la-blob.lo `test -f 'blob.c' || echo '$(srcdir)/'`blob.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-blob.Tpo $(DEPDIR)/libpisock_la-blob.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='blob.c' object='libpisock_la-blob.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-blob.lo `test -f 'blob.c' || echo '$(srcdir)/'`blob.c
+
+libpisock_la-calendar.lo: calendar.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-calendar.lo -MD -MP -MF $(DEPDIR)/libpisock_la-calendar.Tpo -c -o libpisock_la-calendar.lo `test -f 'calendar.c' || echo '$(srcdir)/'`calendar.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-calendar.Tpo $(DEPDIR)/libpisock_la-calendar.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='calendar.c' object='libpisock_la-calendar.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-calendar.lo `test -f 'calendar.c' || echo '$(srcdir)/'`calendar.c
+
+libpisock_la-mail.lo: mail.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-mail.lo -MD -MP -MF $(DEPDIR)/libpisock_la-mail.Tpo -c -o libpisock_la-mail.lo `test -f 'mail.c' || echo '$(srcdir)/'`mail.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-mail.Tpo $(DEPDIR)/libpisock_la-mail.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mail.c' object='libpisock_la-mail.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-mail.lo `test -f 'mail.c' || echo '$(srcdir)/'`mail.c
+
+libpisock_la-md5.lo: md5.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-md5.lo -MD -MP -MF $(DEPDIR)/libpisock_la-md5.Tpo -c -o libpisock_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-md5.Tpo $(DEPDIR)/libpisock_la-md5.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='md5.c' object='libpisock_la-md5.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c
+
+libpisock_la-memo.lo: memo.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-memo.lo -MD -MP -MF $(DEPDIR)/libpisock_la-memo.Tpo -c -o libpisock_la-memo.lo `test -f 'memo.c' || echo '$(srcdir)/'`memo.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-memo.Tpo $(DEPDIR)/libpisock_la-memo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='memo.c' object='libpisock_la-memo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-memo.lo `test -f 'memo.c' || echo '$(srcdir)/'`memo.c
+
+libpisock_la-money.lo: money.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-money.lo -MD -MP -MF $(DEPDIR)/libpisock_la-money.Tpo -c -o libpisock_la-money.lo `test -f 'money.c' || echo '$(srcdir)/'`money.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-money.Tpo $(DEPDIR)/libpisock_la-money.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='money.c' object='libpisock_la-money.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-money.lo `test -f 'money.c' || echo '$(srcdir)/'`money.c
+
+libpisock_la-net.lo: net.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-net.lo -MD -MP -MF $(DEPDIR)/libpisock_la-net.Tpo -c -o libpisock_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-net.Tpo $(DEPDIR)/libpisock_la-net.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='net.c' object='libpisock_la-net.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c
+
+libpisock_la-notepad.lo: notepad.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-notepad.lo -MD -MP -MF $(DEPDIR)/libpisock_la-notepad.Tpo -c -o libpisock_la-notepad.lo `test -f 'notepad.c' || echo '$(srcdir)/'`notepad.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-notepad.Tpo $(DEPDIR)/libpisock_la-notepad.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='notepad.c' object='libpisock_la-notepad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-notepad.lo `test -f 'notepad.c' || echo '$(srcdir)/'`notepad.c
+
+libpisock_la-padp.lo: padp.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-padp.lo -MD -MP -MF $(DEPDIR)/libpisock_la-padp.Tpo -c -o libpisock_la-padp.lo `test -f 'padp.c' || echo '$(srcdir)/'`padp.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-padp.Tpo $(DEPDIR)/libpisock_la-padp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='padp.c' object='libpisock_la-padp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-padp.lo `test -f 'padp.c' || echo '$(srcdir)/'`padp.c
+
+libpisock_la-palmpix.lo: palmpix.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-palmpix.lo -MD -MP -MF $(DEPDIR)/libpisock_la-palmpix.Tpo -c -o libpisock_la-palmpix.lo `test -f 'palmpix.c' || echo '$(srcdir)/'`palmpix.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-palmpix.Tpo $(DEPDIR)/libpisock_la-palmpix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='palmpix.c' object='libpisock_la-palmpix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-palmpix.lo `test -f 'palmpix.c' || echo '$(srcdir)/'`palmpix.c
+
+libpisock_la-pi-buffer.lo: pi-buffer.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-pi-buffer.lo -MD -MP -MF $(DEPDIR)/libpisock_la-pi-buffer.Tpo -c -o libpisock_la-pi-buffer.lo `test -f 'pi-buffer.c' || echo '$(srcdir)/'`pi-buffer.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-pi-buffer.Tpo $(DEPDIR)/libpisock_la-pi-buffer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pi-buffer.c' object='libpisock_la-pi-buffer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-pi-buffer.lo `test -f 'pi-buffer.c' || echo '$(srcdir)/'`pi-buffer.c
+
+libpisock_la-pi-file.lo: pi-file.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-pi-file.lo -MD -MP -MF $(DEPDIR)/libpisock_la-pi-file.Tpo -c -o libpisock_la-pi-file.lo `test -f 'pi-file.c' || echo '$(srcdir)/'`pi-file.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-pi-file.Tpo $(DEPDIR)/libpisock_la-pi-file.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pi-file.c' object='libpisock_la-pi-file.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-pi-file.lo `test -f 'pi-file.c' || echo '$(srcdir)/'`pi-file.c
+
+libpisock_la-pi-header.lo: pi-header.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-pi-header.lo -MD -MP -MF $(DEPDIR)/libpisock_la-pi-header.Tpo -c -o libpisock_la-pi-header.lo `test -f 'pi-header.c' || echo '$(srcdir)/'`pi-header.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-pi-header.Tpo $(DEPDIR)/libpisock_la-pi-header.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pi-header.c' object='libpisock_la-pi-header.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-pi-header.lo `test -f 'pi-header.c' || echo '$(srcdir)/'`pi-header.c
+
+libpisock_la-serial.lo: serial.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-serial.lo -MD -MP -MF $(DEPDIR)/libpisock_la-serial.Tpo -c -o libpisock_la-serial.lo `test -f 'serial.c' || echo '$(srcdir)/'`serial.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-serial.Tpo $(DEPDIR)/libpisock_la-serial.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='serial.c' object='libpisock_la-serial.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-serial.lo `test -f 'serial.c' || echo '$(srcdir)/'`serial.c
+
+libpisock_la-slp.lo: slp.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-slp.lo -MD -MP -MF $(DEPDIR)/libpisock_la-slp.Tpo -c -o libpisock_la-slp.lo `test -f 'slp.c' || echo '$(srcdir)/'`slp.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-slp.Tpo $(DEPDIR)/libpisock_la-slp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='slp.c' object='libpisock_la-slp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-slp.lo `test -f 'slp.c' || echo '$(srcdir)/'`slp.c
+
+libpisock_la-sys.lo: sys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-sys.lo -MD -MP -MF $(DEPDIR)/libpisock_la-sys.Tpo -c -o libpisock_la-sys.lo `test -f 'sys.c' || echo '$(srcdir)/'`sys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-sys.Tpo $(DEPDIR)/libpisock_la-sys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sys.c' object='libpisock_la-sys.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-sys.lo `test -f 'sys.c' || echo '$(srcdir)/'`sys.c
+
+libpisock_la-socket.lo: socket.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-socket.lo -MD -MP -MF $(DEPDIR)/libpisock_la-socket.Tpo -c -o libpisock_la-socket.lo `test -f 'socket.c' || echo '$(srcdir)/'`socket.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-socket.Tpo $(DEPDIR)/libpisock_la-socket.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='socket.c' object='libpisock_la-socket.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-socket.lo `test -f 'socket.c' || echo '$(srcdir)/'`socket.c
+
+libpisock_la-syspkt.lo: syspkt.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-syspkt.lo -MD -MP -MF $(DEPDIR)/libpisock_la-syspkt.Tpo -c -o libpisock_la-syspkt.lo `test -f 'syspkt.c' || echo '$(srcdir)/'`syspkt.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-syspkt.Tpo $(DEPDIR)/libpisock_la-syspkt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='syspkt.c' object='libpisock_la-syspkt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-syspkt.lo `test -f 'syspkt.c' || echo '$(srcdir)/'`syspkt.c
+
+libpisock_la-threadsafe.lo: threadsafe.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-threadsafe.lo -MD -MP -MF $(DEPDIR)/libpisock_la-threadsafe.Tpo -c -o libpisock_la-threadsafe.lo `test -f 'threadsafe.c' || echo '$(srcdir)/'`threadsafe.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-threadsafe.Tpo $(DEPDIR)/libpisock_la-threadsafe.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='threadsafe.c' object='libpisock_la-threadsafe.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-threadsafe.lo `test -f 'threadsafe.c' || echo '$(srcdir)/'`threadsafe.c
+
+libpisock_la-todo.lo: todo.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-todo.lo -MD -MP -MF $(DEPDIR)/libpisock_la-todo.Tpo -c -o libpisock_la-todo.lo `test -f 'todo.c' || echo '$(srcdir)/'`todo.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-todo.Tpo $(DEPDIR)/libpisock_la-todo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='todo.c' object='libpisock_la-todo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-todo.lo `test -f 'todo.c' || echo '$(srcdir)/'`todo.c
+
+libpisock_la-utils.lo: utils.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-utils.lo -MD -MP -MF $(DEPDIR)/libpisock_la-utils.Tpo -c -o libpisock_la-utils.lo `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-utils.Tpo $(DEPDIR)/libpisock_la-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils.c' object='libpisock_la-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-utils.lo `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+
+libpisock_la-veo.lo: veo.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-veo.lo -MD -MP -MF $(DEPDIR)/libpisock_la-veo.Tpo -c -o libpisock_la-veo.lo `test -f 'veo.c' || echo '$(srcdir)/'`veo.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-veo.Tpo $(DEPDIR)/libpisock_la-veo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='veo.c' object='libpisock_la-veo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-veo.lo `test -f 'veo.c' || echo '$(srcdir)/'`veo.c
+
+libpisock_la-versamail.lo: versamail.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -MT libpisock_la-versamail.lo -MD -MP -MF $(DEPDIR)/libpisock_la-versamail.Tpo -c -o libpisock_la-versamail.lo `test -f 'versamail.c' || echo '$(srcdir)/'`versamail.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpisock_la-versamail.Tpo $(DEPDIR)/libpisock_la-versamail.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='versamail.c' object='libpisock_la-versamail.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpisock_la_CFLAGS) $(CFLAGS) -c -o libpisock_la-versamail.lo `test -f 'versamail.c' || echo '$(srcdir)/'`versamail.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-libLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/address.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/address.c
new file mode 100644
index 00000000..46ae49a3
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/address.c
@@ -0,0 +1,313 @@
+/*
+ * $Id: address.c,v 1.30 2006/11/22 22:52:25 adridg Exp $
+ *
+ * address.c: Translate Pilot address book data formats
+ * (c) 1996, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-macros.h"
+#include "pi-address.h"
+
+#define hi(x) (((x) >> 4) & 0x0f)
+#define lo(x) ((x) & 0x0f)
+#define pair(x,y) (((x) << 4) | (y))
+
+/***********************************************************************
+ *
+ * Function: free_Address
+ *
+ * Summary: Free the members of an address structure
+ *
+ * Parameters: Address_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Address(Address_t *addr)
+{
+ int i;
+
+ for (i = 0; i < 19; i++)
+ if (addr->entry[i]) {
+ free(addr->entry[i]);
+ addr->entry[i] = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_Address
+ *
+ * Summary: Fill in the address structure based on the raw record
+ * data
+ *
+ * Parameters: Address_t*, pi_buffer_t *buf
+ *
+ * Returns: -1 on error, 0 on success
+ *
+ ***********************************************************************/
+int
+unpack_Address(Address_t *addr, const pi_buffer_t *buf, addressType type)
+{
+ unsigned long contents,
+ v;
+ size_t ofs;
+
+ if (type != address_v1)
+ /* Don't support anything else yet */
+ return -1;
+
+ if (buf == NULL || buf->data == NULL || buf->used < 9)
+ return -1;
+
+ /* get_byte(buffer); gapfill */
+ addr->showPhone = hi(get_byte(buf->data + 1));
+ addr->phoneLabel[4] = lo(get_byte(buf->data + 1));
+ addr->phoneLabel[3] = hi(get_byte(buf->data + 2));
+ addr->phoneLabel[2] = lo(get_byte(buf->data + 2));
+ addr->phoneLabel[1] = hi(get_byte(buf->data + 3));
+ addr->phoneLabel[0] = lo(get_byte(buf->data + 3));
+
+ contents = get_long(buf->data + 4);
+
+ /* get_byte(buf->data+8) offset */
+
+ ofs = 9;
+
+ /* if(flag & 0x1) {
+ addr->lastname = strdup((buf->data + ofs);
+ ofs += strlen((buf->data + ofs)) + 1;
+ } else {
+ addr->lastname = 0;
+ } */
+
+ for (v = 0; v < 19; v++) {
+ if (contents & (1 << v)) {
+ if ((buf->used - ofs) < 1)
+ return 0;
+ addr->entry[v] = strdup((char *) (buf->data + ofs));
+ ofs += strlen(addr->entry[v]) + 1;
+ } else {
+ addr->entry[v] = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_Address
+ *
+ * Summary: Fill in the raw address record data based on the
+ * address structure
+ *
+ * Parameters: Address_t*, pi_buffer_t *buf of record, record type
+ *
+ * Returns: -1 on error, 0 on success.
+ *
+ ***********************************************************************/
+int
+pack_Address(const Address_t *addr, pi_buffer_t *buf, addressType type)
+{
+ unsigned int l,
+ destlen = 9;
+
+ unsigned char *buffer;
+ unsigned long contents,
+ v,
+ phoneflag;
+
+ unsigned char offset;
+
+ if (addr == NULL || buf == NULL)
+ return -1;
+
+ if (type != address_v1)
+ /* Don't support anything else yet */
+ return -1;
+
+ for (v = 0; v < 19; v++)
+ if (addr->entry[v] && strlen(addr->entry[v]))
+ destlen += strlen(addr->entry[v]) + 1;
+
+ pi_buffer_expect (buf, destlen);
+ buf->used = destlen;
+
+ buffer = buf->data + 9;
+ phoneflag = 0;
+ contents = 0;
+ offset = 0;
+
+ for (v = 0; v < 19; v++) {
+ if (addr->entry[v] && strlen(addr->entry[v])) {
+ if (v == entryCompany)
+ offset =
+ (unsigned char) (buffer - buf->data) - 8;
+ contents |= (1 << v);
+ l = strlen(addr->entry[v]) + 1;
+ memcpy(buffer, addr->entry[v], l);
+ buffer += l;
+ }
+ }
+
+ phoneflag = ((unsigned long) addr->phoneLabel[0]) << 0;
+ phoneflag |= ((unsigned long) addr->phoneLabel[1]) << 4;
+ phoneflag |= ((unsigned long) addr->phoneLabel[2]) << 8;
+ phoneflag |= ((unsigned long) addr->phoneLabel[3]) << 12;
+ phoneflag |= ((unsigned long) addr->phoneLabel[4]) << 16;
+ phoneflag |= ((unsigned long) addr->showPhone) << 20;
+
+ set_long(buf->data, phoneflag);
+ set_long(buf->data + 4, contents);
+ set_byte(buf->data + 8, offset);
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_AddressAppInfo
+ *
+ * Summary: Fill in the app info structure based on the raw app
+ * info data
+ *
+ * Parameters: AddressAppInfo_t*, char * to record, record length
+ *
+ * Returns: The necessary length of the buffer if record is NULL,
+ * or 0 on error, the length of the data used from the
+ * buffer otherwise
+ *
+ ***********************************************************************/
+int
+unpack_AddressAppInfo(AddressAppInfo_t *ai, const unsigned char *record, size_t len)
+{
+ size_t i,
+ destlen = 4 + 16 * 22 + 2 + 2;
+
+ unsigned char *start = record;
+ unsigned long r;
+
+ ai->type = address_v1;
+
+ i = unpack_CategoryAppInfo(&ai->category, record, len);
+ if (!record)
+ return i + destlen;
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+
+ if (len < destlen)
+ return 0;
+
+ r = get_long(record);
+ for (i = 0; i < 22; i++)
+ ai->labelRenamed[i] = !!(r & (1 << i));
+
+ record += 4;
+ memcpy(ai->labels, record, 16 * 22);
+ record += 16 * 22;
+ ai->country = get_short(record);
+ record += 2;
+ ai->sortByCompany = get_byte(record);
+ record += 2;
+
+ for (i = 3; i < 8; i++)
+ strcpy(ai->phoneLabels[i - 3], ai->labels[i]);
+ for (i = 19; i < 22; i++)
+ strcpy(ai->phoneLabels[i - 19 + 5], ai->labels[i]);
+
+ return (record - start);
+}
+
+/***********************************************************************
+ *
+ * Function: pack_AddressAppInfo
+ *
+ * Summary: Fill in the raw app info record data based on the app
+ * info structure
+ *
+ * Parameters: AddressAppInfo_t*, char * to record, record length
+ *
+ * Returns: The length of the buffer required if record is NULL,
+ * or 0 on error, the length of the data used from the
+ * buffer otherwise
+ *
+ ***********************************************************************/
+int
+pack_AddressAppInfo(const AddressAppInfo_t *ai, unsigned char *record, size_t len)
+{
+ int i;
+ size_t destlen = 4 + 16 * 22 + 2 + 2;
+ unsigned char *pos = record;
+ unsigned long r;
+
+ i = pack_CategoryAppInfo(&ai->category, record, len);
+ if (!record)
+ return destlen + i;
+ if (!i)
+ return i;
+
+ pos += i;
+ len -= i;
+
+ for (i = 3; i < 8; i++)
+ strcpy(ai->phoneLabels[i - 3], ai->labels[i]);
+ for (i = 19; i < 22; i++)
+ strcpy(ai->phoneLabels[i - 19 + 5], ai->labels[i]);
+
+ memset(pos, 0, destlen);
+
+ r = 0;
+ for (i = 0; i < 22; i++)
+ if (ai->labelRenamed[i])
+ r |= (1 << i);
+ set_long(pos, r);
+ pos += 4;
+
+ memcpy(pos, ai->labels, 16 * 22);
+ pos += 16 * 22;
+ set_short(pos, ai->country);
+ pos += 2;
+ set_byte(pos, ai->sortByCompany);
+ pos += 2;
+
+ for (i = 3; i < 8; i++)
+ strcpy(ai->phoneLabels[i - 3], ai->labels[i]);
+ for (i = 19; i < 22; i++)
+ strcpy(ai->phoneLabels[i - 19 + 5], ai->labels[i]);
+
+ return (pos - record);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/appinfo.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/appinfo.c
new file mode 100644
index 00000000..b89d9604
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/appinfo.c
@@ -0,0 +1,119 @@
+/*
+ * $Id: appinfo.c,v 1.19 2006/11/22 22:52:25 adridg Exp $
+ *
+ * appinfo.c: Translate Pilot category info
+ *
+ * Copyright (c) 1996, 1997, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-macros.h"
+#include "pi-appinfo.h"
+
+/***********************************************************************
+ *
+ * Function: unpack_CategoryAppInfo
+ *
+ * Summary: Unpack the AppInfo block from record into the structure
+ *
+ * Parameters: CategoryAppInfo_t*, char* to record, record length
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+unpack_CategoryAppInfo(CategoryAppInfo_t *ai, const unsigned char *record, size_t len)
+{
+ int i,
+ rec;
+
+ if (len < 2 + 16 * 16 + 16 + 4)
+ return 0;
+ rec = get_short(record);
+ for (i = 0; i < 16; i++) {
+ if (rec & (1 << i))
+ ai->renamed[i] = 1;
+ else
+ ai->renamed[i] = 0;
+ }
+ record += 2;
+ for (i = 0; i < 16; i++) {
+ memcpy(ai->name[i], record, 16);
+ record += 16;
+ }
+ memcpy(ai->ID, record, 16);
+ record += 16;
+ ai->lastUniqueID = get_byte(record);
+ record += 4;
+ return 2 + 16 * 16 + 16 + 4;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_CategoryAppInfo
+ *
+ * Summary: Pack the AppInfo structure
+ *
+ * Parameters: CategoryAppInfo_t*, char* to record, record length
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+pack_CategoryAppInfo(const CategoryAppInfo_t *ai, unsigned char *record, size_t len)
+{
+ int i,
+ rec;
+
+ unsigned char *start = record;
+
+ if (!record) {
+ return 2 + 16 * 16 + 16 + 4;
+ }
+ if (len < (2 + 16 * 16 + 16 + 4))
+ return 0; /* not enough room */
+ rec = 0;
+ for (i = 0; i < 16; i++) {
+ if (ai->renamed[i])
+ rec |= (1 << i);
+ }
+ set_short(record, rec);
+ record += 2;
+ for (i = 0; i < 16; i++) {
+ memcpy(record, ai->name[i], 16);
+ record += 16;
+ }
+ memcpy(record, ai->ID, 16);
+ record += 16;
+ set_byte(record, ai->lastUniqueID);
+ record++;
+ set_byte(record, 0); /* gapfill */
+ set_short(record + 1, 0); /* gapfill */
+ record += 3;
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/blob.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/blob.c
new file mode 100644
index 00000000..af8fc93b
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/blob.c
@@ -0,0 +1,173 @@
+/*
+ * $Id: blob.c,v 1.1 2009/02/22 08:09:00 nicholas Exp $
+ *
+ * pi-blob.h - Support for blobs that appear in some palm databases.
+ *
+ * (c) 2008, Jon Schewe & Judd Montgomery
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-blob.h"
+
+/***********************************************************************
+ *
+ * Function: free_Blob
+ *
+ * Summary: Frees members of the blob structure
+ *
+ * Parameters: Blob_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Blob(Blob_t *blob)
+{
+ if(NULL != blob->data) {
+ free(blob->data);
+ blob->data = NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: dup_Blob
+ *
+ * Summary: Allocate memory for a new blob that is a duplicate of this one and copy the data into it
+ *
+ * Parameters: Blob_t*
+ *
+ * Returns: Blob_t* or NULL if there isn't enough memory and errno is set to ENOMEM
+ *
+ ***********************************************************************/
+Blob_t*
+dup_Blob(const Blob_t *blob)
+{
+ if(NULL == blob) {
+ return NULL;
+ }
+
+ Blob_t *retval = (Blob_t*)malloc(sizeof(Blob_t));
+ if(NULL == retval) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ memcpy(retval->type, blob->type, 4);
+ retval->length = blob->length;
+ if(blob->length > 0) {
+ retval->data = (uint8_t *)malloc(blob->length);
+ if(NULL == retval->data) {
+ errno = ENOMEM;
+ return NULL;
+ } else {
+ memcpy(retval->data, blob->data, blob->length);
+ }
+ } else {
+ retval->data = NULL;
+ }
+ return retval;
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_Blob
+ *
+ * Summary: Unpack a blob starting at position in data
+ *
+ * Parameters: Blob_t*, unsigned char*, size_t
+ *
+ * Returns: the number of bytes read or -1 on error
+ *
+ ***********************************************************************/
+int
+unpack_Blob_p(Blob_t *blob, const unsigned char *data, const size_t position) {
+ size_t localPosition = position;
+
+ memcpy(blob->type, (char *)data+localPosition, 4);
+ localPosition += 4;
+ //printf("blob->type = %c %c %c %c\n", blob->type[0], blob->type[1], blob->type[2], blob->type[3]);
+ blob->length = get_short(data+localPosition);
+ localPosition += 2;
+ if(blob->length > 0) {
+ //printf("blob->length = %d\n", blob->length);
+ blob->data = (uint8_t *)malloc(blob->length);
+ if(NULL == blob->data) {
+ printf("Malloc failed!\n");
+ return -1;
+ } else {
+ memcpy(blob->data, data+localPosition, blob->length);
+ }
+ localPosition += blob->length;
+ }
+
+ return localPosition - position;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_Blob
+ *
+ * Summary: Pack a blob into the specified buffer
+ *
+ * Parameters: Blob_t*, pi_buffer_t*
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ ***********************************************************************/
+int
+pack_Blob(const Blob_t *blob, pi_buffer_t *buf) {
+ size_t offset;
+
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used + 6 + blob->length);
+ buf->used = buf->used + 6 + blob->length;
+
+ memcpy(buf->data+offset, blob->type, 4);
+ offset += 4;
+
+ set_short(buf->data+offset, blob->length);
+ offset += 2;
+
+ memcpy(buf->data+offset, blob->data, blob->length);
+ offset += blob->length;
+
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/bluetooth.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/bluetooth.c
new file mode 100644
index 00000000..1da4d821
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/bluetooth.c
@@ -0,0 +1,830 @@
+/*
+ * bluetooth.c: Interface layer to bluetooth HotSync connections
+ * using the Bluez stack (http://www.bluez.org/)
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 2005, Florent Pillet
+ * Copyright (c) 2004, Paul Evans <leonerd@leonerd.org.uk>
+ * Copyright (c) 2005, Bastien Nocera <hadess@hadess.net>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h> /* Needed for Redhat 6.x machines */
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-socket.h"
+#include "pi-bluetooth.h"
+#include "pi-cmp.h"
+#include "pi-net.h"
+#include "pi-error.h"
+#include "pi-serial.h"
+#include "pi-util.h"
+
+#ifdef OS2
+#include <sys/select.h>
+#endif
+
+/* Declare prototypes */
+static int pi_bluetooth_open(struct pi_socket *ps, struct pi_sockaddr *addr,
+ int addrlen);
+static int pi_bluetooth_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_bluetooth_bind(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_bluetooth_listen(pi_socket_t *ps, int backlog);
+static int pi_bluetooth_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen);
+static int pi_bluetooth_getsockopt(pi_socket_t *ps, int level,
+ int option_name, void *option_value,
+ size_t *option_len);
+static int pi_bluetooth_setsockopt(pi_socket_t *ps, int level,
+ int option_name, const void *option_value,
+ size_t *option_len);
+static int pi_bluetooth_close(pi_socket_t *ps);
+static int pi_bluetooth_flush(pi_socket_t *ps, int flags);
+static ssize_t pi_bluetooth_write(struct pi_socket *ps,
+ const unsigned char *buf, size_t len, int flags);
+static ssize_t pi_bluetooth_read(struct pi_socket *ps,
+ pi_buffer_t *buf, size_t len, int flags);
+
+extern int pi_socket_init(pi_socket_t *ps);
+
+/* SDP Helper functions */
+/*
+ * Copyright (C) 2004 Edd Dumbill <edd@usefulinc.com>
+ * Copyright (C) 2005 Bastien Nocera <hadess@hadess.net>
+ * Mostly borrowed from BlueZ
+ *
+ * Copyright (C) 2001-2002 Nokia Corporation
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2002-2005 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
+ * Copyright (C) 2002-2003 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ */
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+typedef struct {
+ char *name;
+ char *provider;
+ char *desc;
+
+ unsigned int class;
+ unsigned int profile;
+ unsigned int channel;
+} svc_info_t;
+
+#define HOTSYNC_CHANNEL 22
+
+static unsigned char hotsync_uuid[] = {
+ 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
+ 0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C
+};
+
+static int
+add_hotsync(sdp_session_t *session,
+ sdp_record_t *rec,
+ bdaddr_t *interface,
+ svc_info_t *si,
+ uint32_t *handle,
+ int *channel_ret)
+{
+ sdp_record_t record;
+ sdp_list_t *root, *svclass, *proto;
+ uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
+ uint8_t channel = HOTSYNC_CHANNEL;
+
+ memset(&record, 0, sizeof(record));
+ record.handle = 0xffffffff;
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(&record, root);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto = sdp_list_append(proto, sdp_list_append(
+ sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
+
+ sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
+
+ sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
+ svclass = sdp_list_append(NULL, &svclass_uuid);
+ sdp_set_service_classes(&record, svclass);
+
+ sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
+
+ if (sdp_device_record_register(session, interface, &record, 0) < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "bluetooth: service record registration failed\n"));
+ return -1;
+ }
+
+ *handle = record.handle;
+ *channel_ret = HOTSYNC_CHANNEL;
+ return 0;
+}
+
+static int
+register_sdp (uint32_t *handle, int *channel, sdp_session_t **sess)
+{
+ svc_info_t si;
+ bdaddr_t interface;
+
+ bacpy (&interface, BDADDR_ANY);
+ *sess = sdp_connect (&interface, BDADDR_LOCAL, 0);
+
+ if (*sess == NULL)
+ return -1;
+ memset (&si, 0, sizeof(si));
+ si.name = "HOTSYNC";
+ return add_hotsync (*sess, 0, &interface, &si, handle, channel);
+}
+
+static int
+deregister_sdp(uint32_t handle, sdp_session_t *sess)
+{
+ uint32_t range = 0x0000ffff;
+ sdp_list_t *attr;
+ sdp_record_t *rec;
+ bdaddr_t interface;
+
+ if (!sess)
+ return 0;
+
+ bacpy(&interface, BDADDR_ANY);
+
+ attr = sdp_list_append(0, &range);
+ rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
+ sdp_list_free(attr, 0);
+ if (!rec) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "bluetooth: service record not found\n"));
+ sdp_close(sess);
+ return -1;
+ }
+ if (sdp_record_unregister(sess, rec)) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "bluetooth: failed to unregister service record: %s\n",
+ strerror(errno)));
+ sdp_close(sess);
+ return -1;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "bluetooth: service record deleted\n"));
+ sdp_close(sess);
+ return 0;
+}
+
+/* Protocol Functions */
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_bluetooth_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ ASSERT (prot != NULL);
+
+ new_prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ if (new_prot != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+ new_prot->data = NULL;
+ }
+
+ return new_prot;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_bluetooth_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT (prot != NULL);
+ if (prot != NULL)
+ free(prot);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_bluetooth_protocol (pi_device_t *dev)
+{
+ pi_protocol_t *prot;
+ struct pi_bluetooth_data *data;
+
+ ASSERT (dev != NULL);
+
+ prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ data = (struct pi_bluetooth_data *)(dev->data);
+
+ if (prot != NULL) {
+ prot->level = PI_LEVEL_DEV;
+ prot->dup = pi_bluetooth_protocol_dup;
+ prot->free = pi_bluetooth_protocol_free;
+ prot->read = pi_bluetooth_read;
+ prot->write = pi_bluetooth_write;
+ prot->flush = pi_bluetooth_flush;
+ prot->getsockopt = pi_bluetooth_getsockopt;
+ prot->setsockopt = pi_bluetooth_setsockopt;
+ prot->data = NULL;
+ }
+
+ return prot;
+}
+
+/* Device Functions */
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_register_hotsync_sdp
+ *
+ * Summary: Gets on which channel the HOTSYNC service is, and
+ * registers it if necessary
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ **********************************************************************/
+static void
+pi_bluetooth_register_hotsync_sdp (struct pi_bluetooth_data *data)
+{
+ if (register_sdp (&data->handle, &data->channel, &data->sess) < 0) {
+ data->channel = -1;
+ data->handle = 0;
+ data->sess = NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_unregister_hotsync_sdp
+ *
+ * Summary: Removes the HOTSYNC service
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ **********************************************************************/
+static void
+pi_bluetooth_unregister_hotsync_sdp (struct pi_bluetooth_data *data)
+{
+ if (data->handle != 0)
+ deregister_sdp (data->handle, data->sess);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_device_free
+ *
+ * Summary: frees an existing pi_device struct
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_bluetooth_device_free (pi_device_t *dev)
+{
+ struct pi_bluetooth_data *data;
+
+ ASSERT (dev != NULL);
+
+ if (dev->data) {
+ data = dev->data;
+ pi_bluetooth_unregister_hotsync_sdp (data);
+ if (data->device)
+ free (data->device);
+ free(dev->data);
+ }
+ free(dev);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_open
+ *
+ * Summary: Open a new BlueTooth RFCOMM socket
+ *
+ * Parameters: None
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ **********************************************************************/
+static int
+pi_bluetooth_open(struct pi_socket *ps, struct pi_sockaddr *addr, int addrlen)
+{
+ int fd, flags;
+ struct pi_bluetooth_data *data = ps->device->data;
+
+ pi_bluetooth_register_hotsync_sdp (data);
+ /* If we didn't manage to create an SDP record, force channel 22 and try
+ * again */
+ if (data->channel < 0) {
+ fprintf (stderr, "didn't manage to get a channel\n");
+ data->channel = 22;
+ }
+
+ if ((fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0)
+ return -1;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) != -1) {
+ flags &= ~O_NONBLOCK;
+ fcntl(fd, F_SETFL, flags);
+ }
+
+ if (pi_socket_setsd(ps, fd) < 0)
+ return -1;
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_device
+ *
+ * Summary: creates and inits pi_device struct instance
+ *
+ * Parameters: device type
+ *
+ * Returns: pi_device_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_device_t*
+pi_bluetooth_device (int type)
+{
+ pi_device_t *dev;
+ struct pi_bluetooth_data *data;
+
+ dev = (pi_device_t *) malloc(sizeof (pi_device_t));
+ if (dev == NULL)
+ return NULL;
+
+ data = (struct pi_bluetooth_data *) malloc(sizeof (struct pi_bluetooth_data));
+ if (data == NULL) {
+ free(dev);
+ return NULL;
+ }
+
+ dev->free = pi_bluetooth_device_free;
+ dev->protocol = pi_bluetooth_protocol;
+ dev->bind = pi_bluetooth_bind;
+ dev->listen = pi_bluetooth_listen;
+ dev->accept = pi_bluetooth_accept;
+ dev->connect = pi_bluetooth_connect;
+ dev->close = pi_bluetooth_close;
+
+ data->timeout = 0;
+ dev->data = data;
+
+ return dev;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_connect
+ *
+ * Summary: Connect socket to a given address
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen)
+{
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ if (( ps->type == PI_SOCK_STREAM &&
+ ps->cmd == PI_CMD_CMP) &&
+ cmp_tx_handshake(ps) < 0)
+ {
+ pi_close(ps->sd);
+ return -1;
+ }
+ ps->state = PI_SOCK_CONN_INIT;
+ ps->command = 0;
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_bind
+ *
+ * Summary: Bind address to a local socket
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ struct pi_sockaddr *pa = (struct pi_sockaddr *) addr;
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+ char *device = pa->pi_device;
+ struct sockaddr_rc bindaddr;
+
+ if (pi_bluetooth_open(ps, pa, addrlen) == -1)
+ return -1; /* errno already set */
+
+ data->device = strdup (device);
+
+ bindaddr.rc_family = AF_BLUETOOTH;
+ bacpy(&bindaddr.rc_bdaddr, BDADDR_ANY);
+ bindaddr.rc_channel = data->channel;
+
+ if (bind(ps->sd, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ return -1;
+ }
+
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_listen
+ *
+ * Summary: Prepare for incoming connections
+ *
+ * Parameters: pi_socket*, backlog
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int pi_bluetooth_listen(pi_socket_t *ps, int backlog)
+{
+ // FIXME: no result is actually being taken into account
+ listen(ps->sd, 10);
+ ps->state = PI_SOCK_LISTEN;
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_accept_rfcomm
+ *
+ * Summary: Accept an incoming connection and associate it with an
+ * RFCOMM serial device
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_accept_rfcomm(struct pi_socket *ps, const char *device, struct sockaddr_rc *peeraddr, unsigned int *peeraddrlen)
+{
+ int rfcommfd;
+
+ rfcommfd = accept(ps->sd, (struct sockaddr *)peeraddr, peeraddrlen);
+ if (rfcommfd < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ return -1;
+ }
+
+ /* Check whether we need to really accept this connection */
+ if (device[0] != '\0' && strcmp (device, "any") != 0) {
+ bdaddr_t tmp;
+ if (str2ba (device, &tmp) < 0) {
+ close (rfcommfd);
+ return -1;
+ }
+ if (bacmp (&tmp, &(peeraddr->rc_bdaddr)) != 0) {
+ close (rfcommfd);
+ return -1;
+ }
+ }
+
+ return rfcommfd;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_accept
+ *
+ * Summary: Accept an incoming connection
+ *
+ * Parameters: pi_socket*, sockaddr*
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+ struct sockaddr_rc peeraddr;
+ unsigned int peeraddrlen = sizeof(peeraddr);
+ int sd;
+
+ /* Wait for data */
+ sd = pi_bluetooth_accept_rfcomm(ps, data->device, &peeraddr, &peeraddrlen);
+ if (sd < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ return -1;
+ }
+
+ if (pi_socket_setsd(ps, sd) < 0)
+ return -1;
+ pi_socket_init(ps);
+
+ if (ps->type == PI_SOCK_STREAM) {
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if (cmp_rx_handshake(ps, 0, 0) < 0)
+ return -1;
+ break;
+ case PI_CMD_NET:
+ if (net_rx_handshake(ps) < 0)
+ return -1;
+ break;
+ }
+
+ ps->dlprecord = 0;
+ }
+
+ data->timeout = 0;
+ ps->command = 0;
+ ps->state = PI_SOCK_CONN_ACCEPT;
+
+ return ps->sd;
+}
+
+static int
+pi_bluetooth_flush(pi_socket_t *ps, int flags)
+{
+ char buf[256];
+ int fl;
+
+ if (flags & PI_FLUSH_INPUT) {
+ if ((fl = fcntl(ps->sd, F_GETFL, 0)) != -1) {
+ fcntl(ps->sd, F_SETFL, fl | O_NONBLOCK);
+ while (read(ps->sd, buf, sizeof(buf)) > 0)
+ ;
+ fcntl(ps->sd, F_SETFL, fl);
+ }
+ }
+ return 0;
+}
+
+static ssize_t
+pi_bluetooth_read(struct pi_socket *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ int rbuf;
+ struct pi_bluetooth_data *data = (struct pi_bluetooth_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ if (pi_buffer_expect (buf, len) == NULL)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ if (data->timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ select(ps->sd + 1, &ready, 0, 0, &t);
+ }
+
+ /* If data is available in time, read it */
+ if (FD_ISSET(ps->sd, &ready)) {
+ if (flags == PI_MSG_PEEK && len > 256)
+ len = 256;
+ rbuf = read(ps->sd, buf->data + buf->used, len);
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN, "DEV RX BlueTooth timeout\n"));
+ pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ return -1;
+ }
+ buf->used += rbuf;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV RX bluetooth %d bytes\n", rbuf));
+
+ return rbuf;
+}
+
+static ssize_t
+pi_bluetooth_write(struct pi_socket *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int total,
+ nwrote;
+ struct pi_bluetooth_data *data = (struct pi_bluetooth_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ total = len;
+ while (total > 0) {
+ if (data->timeout == 0)
+ select(ps->sd + 1, 0, &ready, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ select(ps->sd + 1, 0, &ready, 0, &t);
+ }
+ if (!FD_ISSET(ps->sd, &ready)) {
+ pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ return -1;
+ }
+ nwrote = write(ps->sd, buf, len);
+ if (nwrote < 0) {
+ pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ return -1;
+ }
+ total -= nwrote;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV TX bluetooth %d bytes\n", len));
+ return len;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+
+ if (option_name == PI_DEV_TIMEOUT) {
+ if (*option_len < sizeof (data->timeout)) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ return -1;
+ }
+ memcpy (option_value, &data->timeout, sizeof (data->timeout));
+ *option_len = sizeof (data->timeout);
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_setsockopt
+ *
+ * Summary: set options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+
+ if (option_name == PI_DEV_TIMEOUT) {
+ if (*option_len != sizeof (data->timeout)) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ return -1;
+ }
+ memcpy (&data->timeout, option_value, sizeof (data->timeout));
+ }
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_close
+ *
+ * Summary: Close a connection, destroy the socket
+ *
+ * Parameters: pi_socket*
+ *
+ * Returns: always 0 for success
+ *
+ ***********************************************************************/
+static int pi_bluetooth_close(pi_socket_t *ps)
+{
+ if (ps->laddr) {
+ free(ps->laddr);
+ ps->laddr = NULL;
+ }
+
+ if (ps->raddr) {
+ free(ps->raddr);
+ ps->raddr = NULL;
+ }
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/calendar.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/calendar.c
new file mode 100644
index 00000000..404f1054
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/calendar.c
@@ -0,0 +1,737 @@
+/*
+ * $Id: calendar.c,v 1.4 2010-01-17 00:38:47 judd Exp $
+ *
+ * calendar.c - Support for PalmOne Calendar application (CalendarDB-PDat),
+ * this is a copy of datebook.c with the calendar fields added.
+ *
+ * (c) 2008, Jon Schewe
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-calendar.h"
+
+#define alarmFlag 64
+#define repeatFlag 32
+#define noteFlag 16
+#define exceptFlag 8
+#define descFlag 4
+#define locFlag 2
+
+/***********************************************************************
+ *
+ * Function: new_CalendarEvent
+ *
+ * Summary: Create empty calendar event
+ *
+ * Parameters: CalendarEvent_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+new_CalendarEvent(CalendarEvent_t *a)
+{
+ int i = 0;
+
+ a->event = 0;
+ a->begin.tm_hour = 0;
+ a->begin.tm_min = 0;
+ a->begin.tm_sec = 0;
+ a->begin.tm_year = 2000;
+ a->begin.tm_mon = 0;
+ a->begin.tm_mday = 0;
+ a->begin.tm_isdst = -1;
+ a->end.tm_hour = 0;
+ a->end.tm_min = 0;
+ a->end.tm_sec = 0;
+ a->end.tm_year = 2000;
+ a->end.tm_mon = 0;
+ a->end.tm_mday = 0;
+ a->end.tm_isdst = -1;
+ a->alarm = 0;
+ a->advance = 0;
+ a->advanceUnits = 0;
+ a->repeatType = 0;
+ a->repeatForever = 0;
+ a->repeatEnd.tm_hour = 0;
+ a->repeatEnd.tm_min = 0;
+ a->repeatEnd.tm_sec = 0;
+ a->repeatEnd.tm_year = 2000;
+ a->repeatEnd.tm_mon = 0;
+ a->repeatEnd.tm_mday = 0;
+ a->repeatEnd.tm_isdst = -1;
+
+ a->repeatFrequency = 0;
+ a->repeatDay = 0;
+ for (i = 0; i < 7; i++) {
+ a->repeatDays[i] = 0;
+ }
+ a->repeatWeekstart = 0;
+ a->exceptions = 0;
+ a->exception = NULL;
+ a->description = NULL;
+ a->note = NULL;
+ a->location = NULL;
+ a->tz = NULL;
+
+ /* initialize the blobs to NULL */
+ for (i=0; i<MAX_BLOBS; i++) {
+ a->blob[i]=NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: copy_CalendarEvent
+ *
+ * Summary: Copy the data from one calendar event to another. The destination
+ * calendar event must already be cleared, either by creating new or by
+ * calling free_CalendarEvent on it first.
+ *
+ * Parameters: CalendarEvent_t*, CalendarEvent_t*
+ *
+ * Returns: int -1 on failure (errno will be set), 0 on success
+ *
+ ***********************************************************************/
+int
+copy_CalendarEvent(const CalendarEvent_t *source, CalendarEvent_t *dest)
+{
+ int i = 0;
+
+ dest->event = source->event;
+ memcpy(&(dest->begin), &(source->begin), sizeof(struct tm));
+ memcpy(&(dest->end), &(source->end), sizeof(struct tm));
+ dest->alarm = source->alarm;
+ dest->advance = source->advance;
+ dest->advanceUnits = source->advanceUnits;
+ dest->repeatType = source->repeatType;
+ dest->repeatForever = source->repeatForever;
+ memcpy(&(dest->repeatEnd), &(source->repeatEnd), sizeof(struct tm));
+
+ dest->repeatFrequency = source->repeatFrequency;
+ dest->repeatDay = source->repeatDay;
+ for (i = 0; i < 7; i++) {
+ dest->repeatDays[i] = source->repeatDays[i];
+ }
+ dest->repeatWeekstart = source->repeatWeekstart;
+ dest->exceptions = source->exceptions;
+ if(source->exceptions > 0) {
+ dest->exception = (struct tm*)malloc(source->exceptions * sizeof(struct tm));
+ if(NULL == dest->exception) {
+ errno = ENOMEM;
+ return -1;
+ }
+ for(i=0; i<source->exceptions; i++) {
+ memcpy(&(dest->exception[i]), &(source->exception[i]), sizeof(struct tm));
+ }
+ }
+ if(NULL != source->description) {
+ dest->description = strdup(source->description);
+ } else {
+ dest->description = NULL;
+ }
+ if(NULL != source->note) {
+ dest->note = strdup(source->note);
+ } else {
+ dest->note = NULL;
+ }
+ if(NULL != source->location) {
+ dest->location = strdup(source->location);
+ } else {
+ dest->location = NULL;
+ }
+
+ /* copy the blobs */
+ for (i=0; i<MAX_BLOBS; i++) {
+ if(source->blob[i] != NULL) {
+ dest->blob[i] = dup_Blob(source->blob[i]);
+ if(NULL == dest->blob[i]) {
+ return -1;
+ }
+ } else {
+ dest->blob[i] = NULL;
+ }
+ }
+
+ if(source->tz != NULL) {
+ dest->tz = dup_Timezone(source->tz);
+ if(NULL == dest->tz) {
+ return -1;
+ }
+ } else {
+ dest->tz = NULL;
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: free_CalendarEvent
+ *
+ * Summary: Frees members of the calendar event structure
+ *
+ * Parameters: CalendarEvent_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_CalendarEvent(CalendarEvent_t *a)
+{
+ int i;
+
+ if (a->exception != NULL) {
+ free(a->exception);
+ a->exception = NULL;
+ }
+
+ if (a->description != NULL) {
+ free(a->description);
+ a->description = NULL;
+ }
+
+ if (a->note != NULL) {
+ free(a->note);
+ a->note = NULL;
+ }
+
+ if(a->location != NULL) {
+ free(a->location);
+ a->location = NULL;
+ }
+
+ if(NULL != a->tz) {
+ free_Timezone(a->tz);
+ free(a->tz);
+ }
+
+ for(i=0; i<MAX_BLOBS; ++i) {
+ if(NULL != a->blob[i]) {
+ free_Blob(a->blob[i]);
+
+ free(a->blob[i]);
+ a->blob[i] = NULL;
+ }
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_CalendarEvent
+ *
+ * Summary: Fill in the calendar event structure based on the raw
+ * record data
+ *
+ * Parameters: CalendarEvent_t*, pi_buffer_t * of buffer, calendarType
+ *
+ * Returns: -1 on fail, 0 on success
+ *
+ ***********************************************************************/
+int
+unpack_CalendarEvent(CalendarEvent_t *a, const pi_buffer_t *buf, calendarType type)
+{
+ int iflags,
+ j,
+ destlen,
+ i,
+ result;
+ unsigned char *p2;
+ unsigned long d;
+
+ destlen = 8;
+
+ if (type != calendar_v1)
+ return -1;
+
+ if (buf == NULL || buf->data == NULL || buf->used < destlen) {
+ return -1;
+ }
+
+ a->begin.tm_hour = get_byte(buf->data);
+ a->begin.tm_min = get_byte(buf->data + 1);
+ a->begin.tm_sec = 0;
+ d = (unsigned short int) get_short(buf->data + 4);
+ a->begin.tm_year = (d >> 9) + 4;
+ a->begin.tm_mon = ((d >> 5) & 15) - 1;
+ a->begin.tm_mday = d & 31;
+ a->begin.tm_isdst = -1;
+ a->end = a->begin;
+
+ a->end.tm_hour = get_byte(buf->data + 2);
+ a->end.tm_min = get_byte(buf->data + 3);
+
+ if (get_short(buf->data) == 0xffff) {
+ a->event = 1;
+ a->begin.tm_hour = 0;
+ a->begin.tm_min = 0;
+ a->end.tm_hour = 0;
+ a->end.tm_min = 0;
+ } else {
+ a->event = 0;
+ }
+
+ mktime(&a->begin);
+ mktime(&a->end);
+
+ iflags = get_byte(buf->data + 6);
+
+ /* buf->data+7 is gapfill */
+
+ p2 = (unsigned char *) buf->data + 8;
+
+ if (iflags & alarmFlag) {
+ a->alarm = 1;
+ a->advance = get_byte(p2);
+ p2 += 1;
+ a->advanceUnits = get_byte(p2);
+ p2 += 1;
+
+ } else {
+ a->alarm = 0;
+ a->advance = 0;
+ a->advanceUnits = 0;
+ }
+
+ if (iflags & repeatFlag) {
+ int i,
+ on;
+
+ a->repeatType = (enum calendarRepeatType) get_byte(p2);
+ p2 += 2;
+ d = (unsigned short int) get_short(p2);
+ p2 += 2;
+ if (d == 0xffff)
+ a->repeatForever = 1; /* repeatEnd is invalid */
+ else {
+ a->repeatEnd.tm_year = (d >> 9) + 4;
+ a->repeatEnd.tm_mon = ((d >> 5) & 15) - 1;
+ a->repeatEnd.tm_mday = d & 31;
+ a->repeatEnd.tm_min = 0;
+ a->repeatEnd.tm_hour = 0;
+ a->repeatEnd.tm_sec = 0;
+ a->repeatEnd.tm_isdst = -1;
+ mktime(&a->repeatEnd);
+ a->repeatForever = 0;
+ }
+ a->repeatFrequency = get_byte(p2);
+ p2++;
+ on = get_byte(p2);
+ p2++;
+ a->repeatDay = (enum calendarDayOfMonthType) 0;
+ for (i = 0; i < 7; i++)
+ a->repeatDays[i] = 0;
+
+ if (a->repeatType == calendarRepeatMonthlyByDay)
+ a->repeatDay = (enum calendarDayOfMonthType) on;
+ else if (a->repeatType == calendarRepeatWeekly)
+ for (i = 0; i < 7; i++)
+ a->repeatDays[i] = !!(on & (1 << i));
+ a->repeatWeekstart = get_byte(p2);
+ p2++;
+ p2++;
+ } else {
+ int i;
+
+ a->repeatType = (enum calendarRepeatType) 0;
+ a->repeatForever = 1; /* repeatEnd is invalid */
+ a->repeatFrequency = 0;
+ a->repeatDay = (enum calendarDayOfMonthType) 0;
+ for (i = 0; i < 7; i++)
+ a->repeatDays[i] = 0;
+ a->repeatWeekstart = 0;
+ }
+
+ if (iflags & exceptFlag) {
+ a->exceptions = get_short(p2);
+ p2 += 2;
+ a->exception = malloc(sizeof(struct tm) * a->exceptions);
+
+ for (j = 0; j < a->exceptions; j++, p2 += 2) {
+ d = (unsigned short int) get_short(p2);
+ a->exception[j].tm_year = (d >> 9) + 4;
+ a->exception[j].tm_mon = ((d >> 5) & 15) - 1;
+ a->exception[j].tm_mday = d & 31;
+ a->exception[j].tm_hour = 0;
+ a->exception[j].tm_min = 0;
+ a->exception[j].tm_sec = 0;
+ a->exception[j].tm_isdst = -1;
+ mktime(&a->exception[j]);
+ }
+
+ } else {
+ a->exceptions = 0;
+ a->exception = 0;
+ }
+
+ if (iflags & descFlag) {
+ a->description = strdup((char *)p2);
+ p2 += strlen((char *)p2) + 1;
+ } else
+ a->description = 0;
+
+ if (iflags & noteFlag) {
+ a->note = strdup((char *)p2);
+ p2 += strlen((char *)p2) + 1;
+ } else {
+ a->note = 0;
+ }
+
+ if (iflags & locFlag) {
+ a->location = strdup((char *)p2);
+ p2 += strlen((char *)p2) + 1;
+ } else {
+ a->location = 0;
+ }
+
+ /* initialize the blobs to NULL */
+ for (i=0; i<MAX_BLOBS; ++i) {
+ a->blob[i]=NULL;
+ }
+
+ if(p2 - buf->data < buf->used) {
+ uint8_t blob_count;
+
+ /* read the blobs */
+ a->tz = NULL;
+ for(blob_count = 0; buf->used - (p2 - buf->data) > 6; ++blob_count) {
+ if(blob_count >= MAX_BLOBS) {
+ /* too many blobs were found */
+ printf("Error, found more than %d blobs: %d\n", MAX_BLOBS, blob_count);
+ return -1;
+ }
+
+ a->blob[blob_count] = (Blob_t *)malloc(sizeof(Blob_t));
+ result = unpack_Blob_p(a->blob[blob_count], p2, 0);
+ if(-1 == result) {
+ return -1;
+ } else {
+ p2 += result;
+ }
+ //printf("DEBUG: record %s read in blob[%d] of size %d\n", a->description, blob_count, a->blob[blob_count]->length);
+
+ /* if it's a timezone blob store it */
+ if (0 == memcmp(a->blob[blob_count]->type, BLOB_TYPE_CALENDAR_TIMEZONE_ID, 4)) {
+ int result;
+ if(NULL != a->tz) {
+ printf("Warning: Found more than one timezone blob! Freeing the previous one and starting again\n");
+ free_Timezone(a->tz);
+ free(a->tz);
+ }
+ a->tz = (Timezone_t *)malloc(sizeof(Timezone_t));
+ result = unpack_Timezone_p(a->tz, a->blob[blob_count]->data, 0);
+ if(-1 == result) {
+ printf("Error unpacking timezone blob\n");
+ return -1;
+ } else if(result != a->blob[blob_count]->length) {
+ printf("Read the wrong number of bytes for a timezone expected %d but was %d\n", a->blob[blob_count]->length, result);
+ return -1;
+ }
+
+ }
+ }
+ if(p2 - buf->data < buf->used) {
+ printf("Extra data found %ld bytes\n", (buf->used - (p2 - buf->data)));
+ return -1;
+ }
+ } else {
+ a->tz = NULL;
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_CalendarEvent
+ *
+ * Summary: Fill in the raw calendar event record data based on the
+ * calendar event structure.
+ *
+ * Parameters: CalendarEvent_t*, pi_buffer_t*, calendarType
+ *
+ * Returns: -1 on error (bad arguments, mostyle) or 0 on success.
+ * The buffer is sized to accomodate the required data.
+ *
+ ***********************************************************************/
+int
+pack_CalendarEvent(const CalendarEvent_t *a, pi_buffer_t *buf, calendarType type)
+{
+ int iflags,
+ destlen = 8;
+ char *pos;
+
+ if (type != calendar_v1)
+ return -1;
+
+ if (a == NULL || buf == NULL)
+ return -1;
+
+ if (a->alarm)
+ destlen += 2;
+ if (a->repeatType)
+ destlen += 8;
+ if (a->exceptions)
+ destlen += 2 + 2 * a->exceptions;
+ if (a->note)
+ destlen += strlen(a->note) + 1;
+ if (a->description)
+ destlen += strlen(a->description) + 1;
+ if (a->location)
+ destlen += strlen(a->location) + 1;
+
+ pi_buffer_expect (buf, destlen);
+ buf->used = destlen;
+
+ set_byte(buf->data, a->begin.tm_hour);
+ set_byte(buf->data + 1, a->begin.tm_min);
+ set_byte(buf->data + 2, a->end.tm_hour);
+ set_byte(buf->data + 3, a->end.tm_min);
+ set_short(buf->data + 4,
+ ((a->
+ begin.tm_year - 4) << 9) | ((a->begin.tm_mon +
+ 1) << 5) | a->begin.
+ tm_mday);
+
+ if (a->event) {
+ set_long(buf->data, 0xffffffff);
+ }
+
+ iflags = 0;
+
+ pos = (char *) buf->data + 8;
+
+ if (a->alarm) {
+ iflags |= alarmFlag;
+
+ set_byte(pos, a->advance);
+ set_byte(pos + 1, a->advanceUnits);
+ pos += 2;
+ }
+
+ if (a->repeatType) {
+ int i,
+ on;
+
+ iflags |= repeatFlag;
+
+ if (a->repeatType == calendarRepeatMonthlyByDay)
+ on = a->repeatDay;
+ else if (a->repeatType == calendarRepeatWeekly) {
+ on = 0;
+ for (i = 0; i < 7; i++)
+ if (a->repeatDays[i])
+ on |= 1 << i;
+ } else
+ on = 0;
+
+ set_byte(pos, a->repeatType);
+ set_byte(pos + 1, 0);
+ pos += 2;
+
+ if (a->repeatForever)
+ set_short(pos, 0xffff);
+ else
+ set_short(pos,
+ ((a->
+ repeatEnd.tm_year -
+ 4) << 9) | ((a->repeatEnd.tm_mon +
+ 1) << 5) | a->repeatEnd.
+ tm_mday);
+
+ pos += 2;
+
+ set_byte(pos, a->repeatFrequency);
+ pos++;
+ set_byte(pos, on);
+ pos++;
+ set_byte(pos, a->repeatWeekstart);
+ pos++;
+ set_byte(pos, 0);
+ pos++;
+ }
+
+ if (a->exceptions) {
+ int i;
+
+ iflags |= exceptFlag;
+
+ set_short(pos, a->exceptions);
+ pos += 2;
+
+ for (i = 0; i < a->exceptions; i++, pos += 2)
+ set_short(pos,
+ ((a->
+ exception[i].tm_year -
+ 4) << 9) | ((a->exception[i].tm_mon +
+ 1) << 5) | a->
+ exception[i].tm_mday);
+ }
+
+ if (a->description != NULL) {
+ iflags |= descFlag;
+
+ strcpy(pos, a->description);
+ pos += strlen(pos) + 1;
+ }
+
+ if (a->note != NULL) {
+ iflags |= noteFlag;
+
+ strcpy(pos, a->note);
+ pos += strlen(pos) + 1;
+ }
+
+ if (a->location != NULL) {
+ iflags |= locFlag;
+
+ strcpy(pos, a->location);
+ pos += strlen(pos) + 1;
+ }
+
+ set_byte(buf->data + 6, iflags);
+ set_byte(buf->data + 7, 0); /* gapfill */
+
+ /* Calendar stuff */
+ uint8_t blob_index;
+
+ //write out the blobs
+ for(blob_index = 0; blob_index < MAX_BLOBS; ++blob_index) {
+ if(NULL != a->blob[blob_index]) {
+ pack_Blob(a->blob[blob_index], buf);
+ }
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_CalendarAppInfo
+ *
+ * Summary: Fill in the app info structure based on the raw app
+ * info data
+ *
+ * Parameters: CalendarAppInfo_t*, char* to record, record length
+ *
+ * Returns: 0 on error, the length of the data used from the
+ * buffer otherwise
+ *
+ ***********************************************************************/
+int
+unpack_CalendarAppInfo(CalendarAppInfo_t *ai, pi_buffer_t *buf)
+{
+ int i;
+ int len;
+ unsigned char *record;
+ int used;
+
+ len = buf->used;
+ record = buf->data;
+ used = unpack_CategoryAppInfo(&ai->category, record, len);
+ if (!used)
+ return 0;
+ record += used;
+ len -= used;
+ if (len < 2)
+ return 0;
+ ai->startOfWeek = get_byte(record);
+ // alignment byte
+ record += 2;
+ used += 2;
+
+ for(i=0; i<18; ++i) {
+ ai->internal[i] = get_byte(record);
+ record++;
+ used++;
+ }
+ ai->type = calendar_v1;
+
+ return used;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_CalendarAppInfo
+ *
+ * Summary: Fill in the raw app info record data based on the app
+ * info structure
+ *
+ * Parameters: AppointmentAppInfo*, char* to buffer, buffer length
+ *
+ * Returns: The length of the buffer required if record is NULL,
+ * or 0 on error, the length of the data used from the
+ * buffer otherwise
+ *
+ ***********************************************************************/
+int
+pack_CalendarAppInfo(const CalendarAppInfo_t *ai, pi_buffer_t *buf)
+{
+ int i;
+ int len;
+ unsigned char *record;
+
+ if (!buf) {
+ return 298;
+ }
+
+ /* AppInfo size should be 298, 300 will do */
+ len = 300;
+ pi_buffer_expect(buf, 300);
+ buf->used = pack_CategoryAppInfo(&ai->category, buf->data, buf->allocated);
+ if (!buf->used)
+ return 0;
+ record = buf->data + buf->used;
+ len -= buf->used;
+ if (len < 2)
+ return 0;
+ set_short(record, 0);
+ set_byte(record, ai->startOfWeek);
+ record += 2;
+ buf->used += 2;
+
+ for(i=0; i<18; ++i) {
+ set_byte(record, ai->internal[i]);
+ record ++;
+ buf->used ++;
+ }
+
+ return (record - buf->data);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/cmp.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/cmp.c
new file mode 100644
index 00000000..e2f5f357
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/cmp.c
@@ -0,0 +1,655 @@
+/*
+ * $Id: cmp.c,v 1.41 2006/11/07 21:13:24 adridg Exp $
+ *
+ * cmp.c: Pilot Connection Management Protocol
+ *
+ * Copyright (c) 1996, Kenneth Albanowski.
+ * Copyright (c) 1999, Tilo Christ
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-socket.h"
+#include "pi-padp.h"
+#include "pi-cmp.h"
+#include "pi-error.h"
+
+/* Declare prototypes */
+static int cmp_flush(pi_socket_t *ps, int flags);
+static int cmp_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len);
+static int cmp_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len);
+
+static pi_protocol_t *cmp_protocol_dup (pi_protocol_t *prot);
+static void cmp_protocol_free (pi_protocol_t *prot);
+
+/* Protocol Functions */
+/***********************************************************************
+ *
+ * Function: cmp_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+cmp_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ struct pi_cmp_data *data,
+ *new_data;
+
+ new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ new_data = (struct pi_cmp_data *)malloc (sizeof (struct pi_cmp_data));
+
+ if ( (new_prot != NULL) && (new_data != NULL) ) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+
+ data = (struct pi_cmp_data *)prot->data;
+ new_data->type = data->type;
+ new_data->flags = data->flags;
+ new_data->version = data->version;
+ new_data->baudrate = data->baudrate;
+
+ new_prot->data = new_data;
+
+ } else if (new_prot != NULL) {
+ free(new_prot);
+ new_prot = NULL;
+ } else if (new_data != NULL) {
+ free(new_data);
+ new_data = NULL;
+ }
+
+ return new_prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+cmp_protocol_free (pi_protocol_t *prot)
+{
+ if (prot != NULL) {
+ if (prot->data != NULL)
+ free(prot->data);
+ free(prot);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: void
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_protocol_t*
+cmp_protocol (void)
+{
+ pi_protocol_t *prot;
+ struct pi_cmp_data *data;
+
+ prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ data = (struct pi_cmp_data *)malloc (sizeof (struct pi_cmp_data));
+
+ if (prot != NULL && data != NULL) {
+ prot->level = PI_LEVEL_CMP;
+ prot->dup = cmp_protocol_dup;
+ prot->free = cmp_protocol_free;
+ prot->read = cmp_rx;
+ prot->write = cmp_tx;
+ prot->flush = cmp_flush;
+ prot->getsockopt = cmp_getsockopt;
+ prot->setsockopt = cmp_setsockopt;
+
+ data->type = 0;
+ data->flags = 0;
+ data->version = 0;
+ data->baudrate = 0;
+
+ prot->data = data;
+
+ } else if (prot != NULL) {
+ free(prot);
+ prot = NULL;
+ } else if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+
+ return prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_rx_handshake
+ *
+ * Summary: establishes RX handshake
+ *
+ * Parameters: pi_socket_t*, baudrate, hirate enable
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+int
+cmp_rx_handshake(pi_socket_t *ps, int establishrate,
+ int establishhighrate)
+{
+ pi_protocol_t *prot;
+ struct pi_cmp_data *data;
+ pi_buffer_t *buf;
+ int bytes;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_cmp_data *)prot->data;
+
+ /* Read the cmp packet */
+ buf = pi_buffer_new (PI_CMP_HEADER_LEN);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ bytes = cmp_rx(ps, buf, PI_CMP_HEADER_LEN, 0);
+
+ pi_buffer_free (buf);
+ if (bytes < 0)
+ return bytes;
+
+ if ((data->version & 0xFF00) == 0x0100) {
+ if (establishrate != -1) {
+ if (establishrate > data->baudrate) {
+ if (establishhighrate) {
+ LOG((PI_DBG_CMP, PI_DBG_LVL_INFO,
+ "CMP Establishing higher rate %ul (%ul)\n",
+ establishrate, data->baudrate));
+ data->baudrate = establishrate;
+ }
+ } else {
+ data->baudrate = establishrate;
+ }
+ }
+
+ if ((bytes = cmp_init(ps, data->baudrate)) < 0)
+ return bytes;
+ } else {
+ /* 0x80 means the comm version wasn't compatible */
+ LOG((PI_DBG_CMP, PI_DBG_LVL_ERR, "CMP Incompatible Version\n"));
+ cmp_abort(ps, 0x80);
+ errno = ECONNREFUSED;
+ return pi_set_error(ps->sd, PI_ERR_PROT_INCOMPATIBLE);
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_tx_handshake
+ *
+ * Summary: establishes TX handshake
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: >= 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+int
+cmp_tx_handshake(pi_socket_t *ps)
+{
+ pi_protocol_t *prot;
+ struct pi_cmp_data *data;
+ int result;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_cmp_data *)prot->data;
+
+ if ((result = cmp_wakeup(ps, 38400)) < 0) /* Assume box can't go over 38400 */
+ return result;
+
+ if ((result = cmp_rx(ps, NULL, 0, 0)) < 0)
+ return result; /* failed to read, errno already set */
+
+ switch (data->type) {
+ case PI_CMP_TYPE_INIT:
+ return 0;
+ case PI_CMP_TYPE_ABRT:
+ LOG((PI_DBG_CMP, PI_DBG_LVL_NONE,
+ "CMP Aborted by other end\n"));
+ errno = -EIO;
+ return pi_set_error(ps->sd, PI_ERR_PROT_ABORTED);
+ }
+
+ return PI_ERR_PROT_INCOMPATIBLE;
+
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_tx
+ *
+ * Summary: Transmit CMP Packets
+ *
+ * Parameters: pi_socket_t*, char* to buf, buf length, flags
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+ssize_t
+cmp_tx(pi_socket_t *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int bytes,
+ type;
+ size_t size;
+ pi_protocol_t *prot,
+ *next;
+ struct pi_cmp_data *data;
+ unsigned char cmp_buf[PI_CMP_HEADER_LEN];
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_cmp_data *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_CMP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ type = padData;
+ size = sizeof(type);
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_TYPE, &type, &size);
+
+ set_byte(&cmp_buf[PI_CMP_OFFSET_TYPE], data->type);
+ set_byte(&cmp_buf[PI_CMP_OFFSET_FLGS], data->flags);
+ set_short(&cmp_buf[PI_CMP_OFFSET_VERS], data->version > PI_CMP_VERSION ? PI_CMP_VERSION : data->version);
+ set_short(&cmp_buf[PI_CMP_OFFSET_RESV], 0);
+ set_long(&cmp_buf[PI_CMP_OFFSET_BAUD], data->baudrate);
+
+ CHECK(PI_DBG_CMP, PI_DBG_LVL_INFO, cmp_dump(cmp_buf, 1));
+
+ bytes = next->write(ps, cmp_buf, PI_CMP_HEADER_LEN, flags);
+ if (bytes < 10)
+ return (bytes < 0) ? bytes : pi_set_error(ps->sd, PI_ERR_PROT_ABORTED);
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: cmp_rx
+ *
+ * Summary: Receive CMP packets
+ *
+ * Parameters: None
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+ssize_t
+cmp_rx(pi_socket_t *ps, pi_buffer_t *msg, size_t len, int flags)
+{
+ int bytes;
+ pi_protocol_t *prot,
+ *next;
+ struct pi_cmp_data *data;
+
+ LOG((PI_DBG_CMP, PI_DBG_LVL_DEBUG, "CMP RX len=%d flags=0x%02x\n",
+ len, flags));
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_cmp_data *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_CMP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ bytes = next->read(ps, msg, len, flags);
+ if (bytes < 10)
+ return pi_set_error(ps->sd, (bytes < 0) ? bytes : PI_ERR_PROT_ABORTED);
+
+ CHECK(PI_DBG_CMP, PI_DBG_LVL_INFO, cmp_dump(msg->data, 0));
+
+ data->type = get_byte(&msg->data[PI_CMP_OFFSET_TYPE]);
+ data->flags = get_byte(&msg->data[PI_CMP_OFFSET_FLGS]);
+ data->version = get_short(&msg->data[PI_CMP_OFFSET_VERS]);
+ data->baudrate = get_long(&msg->data[PI_CMP_OFFSET_BAUD]);
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: cmp_flush
+ *
+ * Summary: Flush input and output buffers
+ *
+ * Parameters: pi_socket_t*, flags
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+cmp_flush(pi_socket_t *ps, int flags)
+{
+ pi_protocol_t *prot,
+ *next;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_CMP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ return next->flush(ps, flags);
+}
+
+/***********************************************************************
+ *
+ * Function: cmp_init
+ *
+ * Summary: Initialize the socket for CMP transmission
+ *
+ * Parameters: pi_socket_t*, baudrate
+ *
+ * Returns: Number of packets transmitted
+ *
+ ***********************************************************************/
+int
+cmp_init(pi_socket_t *ps, int baudrate)
+{
+ pi_protocol_t *prot;
+ struct pi_cmp_data *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+ data = (struct pi_cmp_data *)prot->data;
+
+ data->type = PI_CMP_TYPE_INIT;
+ data->flags = CMP_FL_LONG_PACKET_SUPPORT;
+ if (baudrate != 9600)
+ data->flags = CMP_FL_CHANGE_BAUD_RATE;
+ data->baudrate = baudrate;
+
+ return cmp_tx(ps, NULL, 0, 0);
+}
+
+/***********************************************************************
+ *
+ * Function: cmp_abort
+ *
+ * Summary: Abort a CMP session in progress
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: Number of PADP packets transmitted or negative on error
+ *
+ ***********************************************************************/
+int
+cmp_abort(pi_socket_t *ps, int reason)
+{
+ pi_protocol_t *prot;
+ struct pi_cmp_data *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_cmp_data *)prot->data;
+ data->type = PI_CMP_TYPE_ABRT;
+ data->flags = reason;
+
+ LOG((PI_DBG_CMP, PI_DBG_LVL_NONE, "CMP ABORT\n"));
+
+ return cmp_tx (ps, NULL, 0, 0);
+}
+
+/***********************************************************************
+ *
+ * Function: cmp_wakeup
+ *
+ * Summary: Wakeup the CMP listener process
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: Number of PADP packets transmitted or negative on error
+ *
+ ***********************************************************************/
+int
+cmp_wakeup(pi_socket_t *ps, int maxbaud)
+{
+ pi_protocol_t *prot;
+ struct pi_cmp_data *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_cmp_data *)prot->data;
+ data->type = PI_CMP_TYPE_WAKE;
+ data->flags = 0;
+ data->version = PI_CMP_VERSION;
+ data->baudrate = maxbaud;
+
+ return cmp_tx(ps, NULL, 0, 0);
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+cmp_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ struct pi_cmp_data *data;
+
+ (void) level;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_CMP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+ data = (struct pi_cmp_data *)prot->data;
+
+ switch (option_name) {
+ case PI_CMP_TYPE:
+ if (*option_len != sizeof (data->type))
+ goto error;
+ memcpy (option_value, &data->type,
+ sizeof (data->type));
+ *option_len = sizeof (data->type);
+ break;
+
+ case PI_CMP_FLAGS:
+ if (*option_len != sizeof (data->flags))
+ goto error;
+ memcpy (option_value, &data->flags,
+ sizeof (data->flags));
+ *option_len = sizeof (data->flags);
+ break;
+
+ case PI_CMP_VERS:
+ if (*option_len != sizeof (data->version))
+ goto error;
+ memcpy (option_value, &data->version,
+ sizeof (data->version));
+ *option_len = sizeof (data->version);
+ break;
+
+ case PI_CMP_BAUD:
+ if (*option_len != sizeof (data->baudrate))
+ goto error;
+ memcpy (option_value, &data->baudrate,
+ sizeof (data->baudrate));
+ *option_len = sizeof (data->baudrate);
+ break;
+ }
+
+ return 0;
+
+ error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_setsockopt
+ *
+ * Summary: set options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+cmp_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ struct pi_padp_data *data;
+
+ (void) level;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_PADP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+ data = (struct pi_padp_data *)prot->data;
+
+ if (option_name == PI_PADP_TYPE) {
+ if (*option_len != sizeof (data->type))
+ goto error;
+ memcpy (&data->type, option_value,
+ sizeof (data->type));
+ *option_len = sizeof (data->type);
+ }
+
+ return 0;
+
+ error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmp_dump
+ *
+ * Summary: Dump the CMP packet frames
+ *
+ * Parameters: char* to cmp packet, TX boolean
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+cmp_dump(const unsigned char *cmp, int rxtx)
+{
+ char *type;
+
+ (void) rxtx;
+
+ switch (get_byte(&cmp[PI_CMP_OFFSET_TYPE])) {
+ case PI_CMP_TYPE_WAKE:
+ type = "WAKE";
+ break;
+ case PI_CMP_TYPE_INIT:
+ type = "INIT";
+ break;
+ case PI_CMP_TYPE_ABRT:
+ type = "ABRT";
+ break;
+ default:
+ type = "UNK";
+ break;
+ }
+
+ LOG((PI_DBG_CMP, PI_DBG_LVL_NONE,
+ "CMP %s %s Type: 0x%02x Flags: 0x%02x Version: 0x%04x Baud: %d\n",
+ rxtx ? "TX" : "RX", type,
+ get_byte(&cmp[PI_CMP_OFFSET_TYPE]),
+ get_byte(&cmp[PI_CMP_OFFSET_FLGS]),
+ get_long(&cmp[PI_CMP_OFFSET_VERS]),
+ get_long(&cmp[PI_CMP_OFFSET_BAUD])));
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/connect.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/connect.c
new file mode 100644
index 00000000..711c3d4e
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/connect.c
@@ -0,0 +1,126 @@
+/*
+ * $Id: connect.c,v 1.60 2006/10/12 14:21:22 desrod Exp $
+ *
+ * connect.c: Palm Serial, USB, IR connection routines
+ *
+ * Copyright (c) 2001, David A. Desrosiers
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "pi-socket.h"
+#include "pi-dlp.h"
+#include "pi-header.h"
+
+/***********************************************************************
+ *
+ * Function: pilot_connect [DEPRECATED]
+ *
+ * Summary: Connect to a Palm device.
+ *
+ * Parameters: port. Communications port through which the Palm device is
+ * connected.
+ *
+ * Returns: Socket descriptor of type 'client_sd', if successful.
+ * Returns 1, if the connection can not be established.
+ *
+ * 'port' is allowed to be NULL for the pi_bind call because pi_bind will
+ * check your PILOTPORT environment variable. If port is NULL and the
+ * attempt to connect fails for any reason, we simply assume the user didn't
+ * provide one, because pilot_connect doesn't have a way of knowing, for the
+ * time being.
+ *
+ * This function is deprecated because it doesn't really belong in libpisock.
+ * It will remain at least until it has been properly replaced.
+ *
+ ***********************************************************************/
+int
+pilot_connect(const char *port)
+{
+ int sd = -1, /* Socket, formerly parent/client_socket */
+ result;
+
+ struct SysInfo sys_info;
+
+ fprintf(stderr, "\n");
+ fprintf(stderr," DEPRECATED: The application is calling pilot_connect()\n");
+ if ((sd = pi_socket(PI_AF_PILOT,
+ PI_SOCK_STREAM, PI_PF_DLP)) < 0) {
+ fprintf(stderr, "\n Unable to create socket '%s'\n", port);
+ return -1;
+ }
+
+ result = pi_bind(sd, port);
+
+ if (result < 0) {
+ if (port == NULL)
+ fprintf(stderr, " No port specified\n");
+ else
+ fprintf(stderr, " Unable to bind to port: %s\n", port);
+
+ fprintf(stderr, " Please use --help for more information\n\n");
+ return result;
+ }
+
+ if (isatty(fileno(stdout))) {
+ printf("\n Listening for incoming connection on %s... ",
+ port);
+ fflush(stdout);
+ }
+
+ if (pi_listen(sd, 1) < 0) {
+ fprintf(stderr, "\n Error listening on %s\n", port);
+ pi_close(sd);
+ return -1;
+ }
+
+ sd = pi_accept(sd, 0, 0);
+ if (sd < 0) {
+ fprintf(stderr, "\n Error accepting data on %s\n", port);
+ pi_close(sd);
+ return -1;
+ }
+
+ if (isatty(fileno(stdout))) {
+ printf("connected!\n\n");
+ }
+
+ if (dlp_ReadSysInfo(sd, &sys_info) < 0) {
+ fprintf(stderr, "\n Error read system info on %s\n", port);
+ pi_close(sd);
+ return -1;
+ }
+
+ dlp_OpenConduit(sd);
+ return sd;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/contact.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/contact.c
new file mode 100644
index 00000000..7748fe01
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/contact.c
@@ -0,0 +1,586 @@
+/* $Id: contact.c,v 1.20 2009/02/23 11:59:16 nicholas Exp $ */
+
+/*******************************************************************************
+ * contact.c: Translate Palm contact data formats
+ * Derived from a module of J-Pilot http://jpilot.org (jp-contact.c 1.10)
+ *
+ * Rewrite Copyright 2006, 2007 Judd Montgomery
+ * Rewrite Copyright 2004, 2005 Joseph Carter
+ * Copyright 2003, 2004 Judd Montgomery
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-macros.h"
+#include "pi-contact.h"
+
+
+/***********************************************************************
+ *
+ * Function: free_Contact
+ *
+ * Summary: Free the members of a contact structure
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+void free_Contact(struct Contact *c)
+{
+ int i;
+
+ for (i = 0; i < NUM_CONTACT_ENTRIES; i++)
+ if (c->entry[i])
+ free(c->entry[i]);
+ for (i = 0; i < MAX_CONTACT_BLOBS; i++) {
+ if (c->blob[i]) {
+ if (c->blob[i]->data)
+ free(c->blob[i]->data);
+
+ free(c->blob[i]);
+ }
+ }
+
+ if (c->picture) free(c->picture);
+}
+
+#define hi(x) (((x) >> 4) & 0x0f)
+#define lo(x) ((x) & 0x0f)
+#define pair(x,y) (((x) << 4) | (y))
+
+/***********************************************************************
+ *
+ * Function: unpack_Contact
+ *
+ * Summary: Fill in the contact structure based on the raw record
+ * data
+ *
+ * Parameters: None
+ *
+ * Returns: -1 on error,
+ * The length of the data used from the buffer on success
+ *
+ ***********************************************************************/
+int unpack_Contact(struct Contact *c, pi_buffer_t *buf, contactsType type)
+{
+ unsigned long contents1;
+ unsigned long contents2;
+ unsigned char *Pbuf, *record;
+ int i, field_num, len;
+ unsigned int packed_date;
+ unsigned int blob_count;
+
+ if (buf == NULL || buf->data == NULL || buf->used < 17)
+ return -1;
+
+ if (type != contacts_v10 && type != contacts_v11) {
+ /* Don't support anything else yet */
+ return -1;
+ }
+
+ record = Pbuf = buf->data;
+ len = buf->used;
+
+ for (i=0; i<MAX_CONTACT_BLOBS; i++) {
+ c->blob[i]=NULL;
+ }
+ c->picture=NULL;
+
+ c->showPhone = hi(get_byte(Pbuf));
+ c->phoneLabel[6] = lo(get_byte(Pbuf));
+ c->phoneLabel[5] = hi(get_byte(Pbuf + 1));
+ c->phoneLabel[4] = lo(get_byte(Pbuf + 1));
+ c->phoneLabel[3] = hi(get_byte(Pbuf + 2));
+ c->phoneLabel[2] = lo(get_byte(Pbuf + 2));
+ c->phoneLabel[1] = hi(get_byte(Pbuf + 3));
+ c->phoneLabel[0] = lo(get_byte(Pbuf + 3));
+
+ c->addressLabel[2] = lo(get_byte(Pbuf + 4));
+ c->addressLabel[1] = hi(get_byte(Pbuf + 5));
+ c->addressLabel[0] = lo(get_byte(Pbuf + 5));
+
+ c->IMLabel[1] = hi(get_byte(Pbuf + 7));
+ c->IMLabel[0] = lo(get_byte(Pbuf + 7));
+
+ contents1 = get_long(record + 8);
+ contents2 = get_long(record + 12);
+
+ /* c->companyOffset = get_byte(record + 16); */
+
+ Pbuf += 17;
+ len -= 17;
+
+ field_num=0;
+
+ for (i = 0; i < 28; i++, field_num++) {
+ if (contents1 & (1 << i)) {
+ if (len < 1)
+ return 0;
+ c->entry[field_num] = strdup((char *) Pbuf);
+ Pbuf += strlen((char *) Pbuf) + 1;
+ len -= strlen(c->entry[field_num]) + 1;
+ } else {
+ c->entry[field_num] = 0;
+ }
+ }
+ for (i = 0; i < 11; i++, field_num++) {
+ if (contents2 & (1 << i)) {
+ if (len < 1)
+ return 0;
+ c->entry[field_num] = strdup((char *) Pbuf);
+ Pbuf += strlen((char *) Pbuf) + 1;
+ len -= strlen(c->entry[field_num]) + 1;
+ } else {
+ c->entry[field_num] = 0;
+ }
+ }
+
+ /* I think one of these is a birthday flag and one is an alarm flag.
+ * Since both are always set there is no way to know which is which.
+ * It could be something like a flag for advanceUnits also. */
+ if ((contents2 & 0x0800) || (contents2 & 0x1000)) {
+ c->birthdayFlag = 1;
+ if (len < 1)
+ return 0;
+ packed_date = get_short(Pbuf);
+ c->birthday.tm_year = ((packed_date & 0xFE00) >> 9) + 4;
+ c->birthday.tm_mon = ((packed_date & 0x01E0) >> 5) - 1;
+ c->birthday.tm_mday = (packed_date & 0x001F);
+ c->birthday.tm_hour = 0;
+ c->birthday.tm_min = 0;
+ c->birthday.tm_sec = 0;
+ c->birthday.tm_isdst= -1;
+ mktime(&c->birthday);
+ /* 2 bytes and a zero padding byte */
+ len -= 3;
+ Pbuf += 3;
+ c->advanceUnits = get_byte(Pbuf);
+ len--;
+ Pbuf++;
+ } else {
+ c->birthdayFlag = 0;
+ }
+
+ if (contents2 & 0x2000) {
+ c->reminder = 1;
+ if (len < 1)
+ return 0;
+ c->advance = get_byte(Pbuf);
+ len -= 1;
+ Pbuf += 1;
+ } else {
+ c->reminder = 0;
+ c->advance = 0;
+ }
+
+ /* A blob of size zero would take 6 bytes */
+ blob_count=0;
+ while (len >= 6) {
+ if (blob_count >= MAX_CONTACT_BLOBS) {
+ /* Too many blobs were found. */
+ return (Pbuf - record);
+ }
+ c->blob[blob_count] = malloc(sizeof(struct ContactBlob));
+ strncpy(c->blob[blob_count]->type, (char *)Pbuf, 4);
+ c->blob[blob_count]->length = get_short(Pbuf+4);
+ c->blob[blob_count]->data = malloc(c->blob[blob_count]->length);
+ if (c->blob[blob_count]->data) {
+ memcpy(c->blob[blob_count]->data, Pbuf+6, c->blob[blob_count]->length);
+ }
+ if (! strncmp(c->blob[blob_count]->type, BLOB_TYPE_PICTURE_ID, 4)) {
+ if (!(c->picture)) {
+ c->picture = malloc(sizeof(struct ContactPicture));
+ }
+ c->picture->dirty = get_short(c->blob[blob_count]->data);
+ c->picture->length = c->blob[blob_count]->length - 2;
+ c->picture->data = c->blob[blob_count]->data + 2;
+ }
+
+ Pbuf += 6;
+ len -= 6;
+ Pbuf += c->blob[blob_count]->length;
+ len -= c->blob[blob_count]->length;
+ blob_count++;
+ }
+
+ return (Pbuf - record);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_Contact
+ *
+ * Summary: Fill in the raw contact record data based on the
+ * contact structure
+ *
+ * Parameters: None
+ *
+ * Returns: -1 on error
+ * The length of the buffer used on success
+ *
+ ***********************************************************************/
+int pack_Contact(struct Contact *c, pi_buffer_t *buf, contactsType type)
+{
+ int l, destlen = 17;
+
+ unsigned char *Pbuf, *record;
+ unsigned long contents1, contents2;
+ int i;
+ unsigned int field_i;
+ unsigned long phoneflag;
+ unsigned long typesflag;
+ unsigned short packed_date;
+ int companyOffset = 0;
+
+ if (c == NULL || buf == NULL)
+ return -1;
+
+ if (type != contacts_v10 && type != contacts_v11) {
+ /* Don't support anything else yet */
+ return -1;
+ }
+
+ for (i = 0; i < NUM_CONTACT_ENTRIES; i++) {
+ if (c->entry[i]) {
+ destlen += (strlen(c->entry[i]) + 1);
+ }
+ }
+ if (c->birthdayFlag) {
+ destlen += 3;
+ if (c->reminder) {
+ destlen += 2;
+ } else {
+ destlen += 1;
+ }
+ }
+
+ /* Check for blobs */
+ for (i=0; i<MAX_CONTACT_BLOBS; i++) {
+ if (c->blob[i]) {
+ destlen += c->blob[i]->length + 6;
+ }
+ }
+
+ pi_buffer_expect(buf, destlen);
+
+ record = buf->data;
+
+ Pbuf = record + 17;
+ phoneflag = 0;
+ typesflag = 0;
+ contents1 = contents2 = 0;
+
+ field_i = 0;
+ for (i = 0; i < 28; i++, field_i++) {
+ if (c->entry[field_i] && strlen(c->entry[field_i])) {
+ contents1 |= (1 << i);
+ l = strlen(c->entry[field_i]) + 1;
+ memcpy(Pbuf, c->entry[field_i], l);
+ Pbuf += l;
+ }
+ }
+ for (i = 0; i < 11; i++, field_i++) {
+ if (c->entry[field_i] && strlen(c->entry[field_i])) {
+ contents2 |= (1 << i);
+ l = strlen(c->entry[field_i]) + 1;
+ memcpy(Pbuf, c->entry[field_i], l);
+ Pbuf += l;
+ }
+ }
+
+ phoneflag = (((unsigned long) c->phoneLabel[0]) & 0xF) << 0;
+ phoneflag |= (((unsigned long) c->phoneLabel[1]) & 0xF) << 4;
+ phoneflag |= (((unsigned long) c->phoneLabel[2]) & 0xF) << 8;
+ phoneflag |= (((unsigned long) c->phoneLabel[3]) & 0xF) << 12;
+ phoneflag |= (((unsigned long) c->phoneLabel[4]) & 0xF) << 16;
+ phoneflag |= (((unsigned long) c->phoneLabel[5]) & 0xF) << 20;
+ phoneflag |= (((unsigned long) c->phoneLabel[6]) & 0xF) << 24;
+ phoneflag |= (((unsigned long) c->showPhone) & 0xF) << 28;
+
+ typesflag = (((unsigned long) c->IMLabel[0]) & 0xF) << 0;
+ typesflag |= (((unsigned long) c->IMLabel[1]) & 0xF) << 4;
+ typesflag |= (((unsigned long) c->addressLabel[0]) & 0xF) << 16;
+ typesflag |= (((unsigned long) c->addressLabel[1]) & 0xF) << 20;
+ typesflag |= (((unsigned long) c->addressLabel[2]) & 0xF) << 24;
+
+ if (c->birthdayFlag) {
+ contents2 |= 0x1800;
+ packed_date = (((c->birthday.tm_year - 4) << 9) & 0xFE00) |
+ (((c->birthday.tm_mon+1) << 5) & 0x01E0) |
+ (c->birthday.tm_mday & 0x001F);
+ set_short(Pbuf, packed_date);
+ Pbuf += 2;
+ set_byte(Pbuf, 0); /* padding byte in birthday date */
+ Pbuf += 1;
+ if (c->reminder) {
+ contents2 |= 0x2000;
+ set_byte(Pbuf, c->advanceUnits);
+ Pbuf += 1;
+ set_byte(Pbuf, c->advance);
+ Pbuf += 1;
+ } else {
+ set_byte(Pbuf, 0);
+ Pbuf += 1;
+ }
+ }
+
+ set_long(record, phoneflag);
+ set_long(record + 4, typesflag);
+ set_long(record + 8, contents1);
+ set_long(record + 12, contents2);
+ /* companyOffset is the offset from itself to the company field,
+ * or zero if no company field. Its not useful to us at all. */
+ if (c->entry[2]) {
+ companyOffset++;
+ if (c->entry[0]) companyOffset += strlen(c->entry[0]) + 1;
+ if (c->entry[1]) companyOffset += strlen(c->entry[1]) + 1;
+ }
+ set_byte(record + 16, companyOffset);
+
+ /* Pack blobs */
+ for (i=0; i<MAX_CONTACT_BLOBS; i++) {
+ if (c->blob[i]) {
+ memcpy(Pbuf, c->blob[i]->type, 4);
+ Pbuf += 4;
+ set_short(Pbuf, c->blob[i]->length);
+ Pbuf += 2;
+ memcpy(Pbuf, c->blob[i]->data, c->blob[i]->length);
+ Pbuf += c->blob[i]->length;
+ }
+ }
+ buf->used = Pbuf - record;
+
+ return (buf->used);
+}
+
+
+/***********************************************************************
+ *
+ * Function: Contact_add_blob
+ *
+ * Summary: Add a blob record to a Contact Record
+ *
+ * Parameters: None
+ *
+ * Returns: 0 on success
+ * 1 on other error
+ *
+ ***********************************************************************/
+int Contact_add_blob(struct Contact *c, struct ContactBlob *blob)
+{
+ int i;
+
+ for (i=0; i<MAX_CONTACT_BLOBS; i++) {
+ if (c->blob[i]) {
+ continue;
+ }
+
+ c->blob[i] = malloc(sizeof(struct ContactBlob));
+ if (!c->blob[i]) return EXIT_FAILURE;
+
+ c->blob[i]->data = malloc(blob->length);
+ strncpy(c->blob[i]->type, blob->type, 4);
+ c->blob[i]->length = blob->length;
+ strncpy((char *)c->blob[i]->data, (char *)blob->data, blob->length);
+ return EXIT_SUCCESS;
+ }
+
+ return EXIT_FAILURE;
+}
+
+
+/***********************************************************************
+ *
+ * Function: Contact_add_picture
+ *
+ * Summary: Add a picture blob record to a Contact Record
+ * This will add a blob, but not touch the picture structure
+ * of the contact record
+ *
+ * Parameters: None
+ *
+ * Returns: 0 on success
+ * 1 on other error
+ *
+ ***********************************************************************/
+int Contact_add_picture(struct Contact *c, struct ContactPicture *p)
+{
+ int i;
+
+ if ((!p) || (p->length<1) || (!p->data)) {
+ return EXIT_FAILURE;
+ }
+ for (i=0; i<MAX_CONTACT_BLOBS; i++) {
+ if (c->blob[i]) {
+ continue;
+ }
+
+ c->blob[i] = malloc(sizeof(struct ContactBlob));
+ if (!c->blob[i]) return EXIT_FAILURE;
+
+ c->blob[i]->data = malloc(p->length + 2);
+ strncpy(c->blob[i]->type, BLOB_TYPE_PICTURE_ID, 4);
+ c->blob[i]->length = p->length + 2;
+ set_short(c->blob[i]->data, p->dirty);
+ memcpy(c->blob[i]->data + 2, p->data, p->length);
+ return EXIT_SUCCESS;
+ }
+
+ return EXIT_FAILURE;
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_ContactAppInfo
+ *
+ * Summary: Fill in the app info structure based on the raw app
+ * info data
+ *
+ * Parameters: None
+ *
+ * Returns: -1 on error
+ * The length of data used from the buffer on success
+ *
+ ***********************************************************************/
+int unpack_ContactAppInfo(struct ContactAppInfo *ai, pi_buffer_t *buf)
+{
+ int i, j, destlen;
+ unsigned char *start, *Pbuf;
+ int len;
+
+ start = Pbuf = buf->data;
+ len = buf->used;
+ if (len == 1092) {
+ ai->type = contacts_v10;
+ ai->num_labels = NUM_CONTACT_V10_LABELS;
+ ai->numCustoms = 9; /* not sure - but pi-contact.h <= 1.11 had 9 all the time */
+ } else if (len == 1156) {
+ ai->type = contacts_v11;
+ ai->num_labels = NUM_CONTACT_V11_LABELS;
+ ai->numCustoms = 9; /* not sure - but pi-contact.h <= 1.11 had 9 all the time */
+ } else {
+ fprintf(stderr, "contact.c: unpack_ContactAppInfo: ContactAppInfo size of %d incorrect\n", len);
+ return -1;
+ }
+
+ /* 278 app info, 26 unknown, labels, county, sortBy */
+ destlen = 278 + 26 + (16 * ai->num_labels) + 2 + 2;
+ if (buf->used < destlen)
+ return -1;
+
+ i = unpack_CategoryAppInfo(&ai->category, start, len);
+ if (!i)
+ return i;
+ Pbuf += i;
+
+ memcpy(ai->internal, Pbuf, 26);
+ Pbuf += 26;
+ memcpy(ai->labels, Pbuf, 16 * ai->num_labels);
+ Pbuf += 16 * ai->num_labels;
+ ai->country = get_byte(Pbuf);
+ Pbuf += 2;
+ ai->sortByCompany = get_byte(Pbuf);
+ Pbuf += 2;
+
+ /* These are the fields that go in drop down menus */
+ for (i = 4, j = 0; i < 11; i++, j++) {
+ strcpy(ai->phoneLabels[j], ai->labels[i]);
+ }
+ strcpy(ai->phoneLabels[j], ai->labels[40]);
+
+ for (i = 0; i < ai->numCustoms; i++) {
+ strcpy(ai->customLabels[i], ai->labels[14 + i]);
+ }
+
+ strcpy(ai->addrLabels[0], ai->labels[23]);
+ strcpy(ai->addrLabels[1], ai->labels[28]);
+ strcpy(ai->addrLabels[2], ai->labels[33]);
+
+ strcpy(ai->IMLabels[0], ai->labels[41]);
+ strcpy(ai->IMLabels[1], ai->labels[42]);
+ strcpy(ai->IMLabels[2], ai->labels[43]);
+ strcpy(ai->IMLabels[3], ai->labels[44]);
+ strcpy(ai->IMLabels[4], ai->labels[45]);
+
+ return (Pbuf - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: free_ContactAppInfo
+ *
+ * Summary: Unallocate dynamically sized parts of ContactAppInfo
+ * (However, there are now none - provided for source compatibility)
+ *
+ * Parameters: struct ContactAppInfo *ai
+ *
+ * Returns: None
+ *
+ ***********************************************************************/
+void free_ContactAppInfo (struct ContactAppInfo *ai)
+{
+}
+
+/***********************************************************************
+ *
+ * Function: pack_ContactAppInfo
+ *
+ * Summary: Fill in the raw app info record data based on the
+ * ContactAppInfo structure
+ *
+ * Parameters: None
+ *
+ * Returns: -1 on error
+ * The length of the data used from the buffer on success.
+ *
+ ***********************************************************************/
+int pack_ContactAppInfo(struct ContactAppInfo *ai, pi_buffer_t *buf)
+{
+ int destlen;
+
+ if (buf == NULL || buf->data == NULL)
+ return -1;
+
+ /* 278 app info, 26 unknown, labels, country, sortBy */
+ destlen = 278 + 26 + (16 * ai->num_labels) + 2 + 2;
+
+ pi_buffer_expect(buf, destlen);
+
+ buf->used = pack_CategoryAppInfo(&ai->category, buf->data, buf->allocated);
+ if (buf->used != 278)
+ return -1;
+
+ pi_buffer_append(buf, ai->internal, 26);
+
+ pi_buffer_append(buf, ai->labels, 16 * ai->num_labels);
+
+ set_byte(buf->data + buf->used++, ai->country);
+ /* Unknown field */
+ set_byte(buf->data + buf->used++, 0x00);
+
+ set_byte(buf->data + buf->used++, ai->sortByCompany);
+ /* Unknown field */
+ set_byte(buf->data + buf->used++, 0x00);
+
+ return (buf->used);
+}
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/darwinusb.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/darwinusb.c
new file mode 100644
index 00000000..1cccc4ad
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/darwinusb.c
@@ -0,0 +1,1968 @@
+/*
+ * $Id: darwinusb.c,v 1.66 2006/11/09 10:26:21 fpillet Exp $
+ *
+ * darwinusb.c: I/O support for Darwin (Mac OS X) USB
+ *
+ * Copyright (c) 2004-2006, Florent Pillet.
+ *
+ * libpisock interface modeled after linuxusb.c by Jeff Dionne and
+ * Kenneth Albanowski
+ * Some structures & defines extracted from Linux "visor.c",
+ * which is Copyright (C) 1999 - 2003 Greg Kroah-Hartman (greg@kroah.com)
+ * KLSI adapter (PalmConnect USB) support implemented thanks for the
+ * Linux implementation made by Utz-Uwe Haus (haus@uuhaus.de)
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Theory of operation
+ *
+ * Darwin IOKit is different from traditional unix i/o. It is much more
+ * structured, and also more complex.
+ *
+ * One of the strengths of IOKit is IOUSBLib which allows talking to USB
+ * devices directly from userland code, without the need to write a driver.
+ * This is the way we do it here.
+ *
+ * Here is what we do:
+ * - We start a separate thread which will handle the USB communications. The
+ * main (controlling) thread exposes start, stop, poll, read and write
+ * functions. These function take care of controlling the USB thread.
+ * - We register for "device added" notifications. These notifications are
+ * sent by the IOKit to registered clients when a new device shows up. We
+ * use a matching dictionary to restrict the devices we're interested in to
+ * USB devices (IOUSBDevice class)
+ * - When we get notified that a new device showed up, we check the USB vendor
+ * ID and product ID and only accept those that are known to be Palm OS
+ * devices
+ * - We then examine the device interfaces and select the pipes we're going to
+ * use for input and output.
+ * - We register for notifications coming from the device. When the device
+ * goes away, our notification callback is called and we can cleanly close
+ * things.
+ * - Once everything is initialized, we fire a first "read" from the read
+ * pipe. Subsequent reads are fired directly from the previous read's
+ * completion routine [1].
+ * - In case the thread or application is aborted, the IOKit will clean things
+ * up for us.
+ *
+ * [1] Reading is done asynchronously and in a chained way: we fire a read
+ * with ReadPipeAsync(). Once the read completes (or fails), our
+ * completion routine is called. As long as the read is not "aborted"
+ * (which means the device has been disconnected), we fire another read
+ * from the read_completion() function.
+ *
+ * All read data fills a buffer which is independantly consumed by the
+ * main thread. This way, we get the maximum read throughput by making
+ * sure that any data received from the device is fetched as soon as
+ * possible and made available to the main thread.
+ *
+ * Writes, in the contrary, are synchronous for now. I can make them async
+ * as well, though I have not explored the implications for the libpisock
+ * code yet. This could speed things up a bit as well, though.
+ */
+
+#include <mach/mach.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOMessage.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <CoreFoundation/CFByteOrder.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-usb.h"
+#include "pi-util.h"
+
+/* Define this to make debug logs include USB debug info */
+#ifdef PI_DEBUG
+ #define DEBUG_USB 1
+#endif
+#undef DEBUG_USB /* comment out to leave debug enabled */
+
+/* Macro to log more information when debugging USB. Note that this is for
+ * my own use, mostly, as the info logged is primarily being used to
+ * debug complex thread/usb issues
+ */
+#ifdef DEBUG_USB
+ #define ULOG(a) LOG(a)
+#else
+ #define ULOG(a) do {} while(0)
+#endif
+
+/* These values are somewhat tricky. Priming reads with a size of exactly one
+ * USB packet works best (no timeouts). Probably best to leave these as they are.
+ */
+#define MAX_AUTO_READ_SIZE 4096
+#define AUTO_READ_SIZE 64
+
+/* Options */
+#if HAVE_PTHREAD
+static int accept_multiple_simultaneous_connections = 1; /* enabled by default when compiling with --enable-threads */
+#else
+static int accept_multiple_simultaneous_connections = 0; /* disabled by default, set to 1 to enable */
+#endif
+
+/* IOKit interface */
+static IONotificationPortRef usb_notify_port;
+static io_iterator_t usb_device_added_iter;
+
+/* RunLoop / threading management */
+static CFRunLoopRef usb_run_loop = 0;
+static pthread_mutex_t usb_run_loop_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t usb_thread_ready_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t usb_thread_ready_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t usb_connections_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t usb_connection_added_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t usb_thread = 0;
+
+/* Device interface linked list */
+typedef struct usb_connection_t
+{
+ struct usb_connection_t *next; /* linked list */
+ struct pi_socket *ps; /* the pilot-link socket we're associated with (if already paired) */
+
+ /* refcount management */
+ pthread_mutex_t ref_count_mutex;
+ int ref_count;
+
+ IOUSBInterfaceInterface190 **interface; /* IOUSBInterface190 is 1.9.0 available on OS X 10.2 and later */
+ IOUSBDeviceInterface **device;
+ io_object_t device_notification; /* for device removal */
+
+ unsigned short vendorID; /* connected USB device vendor ID */
+ unsigned short productID; /* connected USB device product ID */
+ unsigned short dev_flags; /* copy of the flags from the acceptedDevices structure */
+
+ int opened; /* set to != 0 if the connection is opened */
+ int device_present;
+ int read_pending; /* set to 1 when a prime_read() has been issued and the read_completion() has not been called yet */
+ int in_pipe_ref; /* pipe for reads */
+ int in_pipe_bulk_size; /* max packet size of bulk packets on input */
+ int out_pipe_ref; /* pipe for writes */
+ int out_pipe_bulk_size; /* size of bulk packets on the out pipe (used when talking with a PalmConnect USB serial adapter) */
+
+ /* these provide hints about the size of the next read */
+ int auto_read_size; /* if != 0, prime reads to the input pipe to get data permanently */
+ int read_ahead_size; /* when waiting for big chunks of data, used as a hint to make bigger read requests */
+ int last_read_ahead_size; /* also need this to properly compute the size of the next read */
+
+ unsigned long total_bytes_read; /* total number of bytes received since connection was opened */
+ unsigned long total_bytes_written; /* total number of bytes sent since connection was opened */
+
+ pthread_mutex_t read_queue_mutex;
+ pthread_cond_t read_queue_data_avail_cond;
+ char *read_queue; /* stores completed reads, grows by 64k chunks */
+ size_t read_queue_size;
+ size_t read_queue_used;
+
+ char read_buffer[MAX_AUTO_READ_SIZE];
+} usb_connection_t;
+
+static usb_connection_t *usb_connections = NULL; /* linked list of active connections */
+
+/* USB control requests we send to the devices
+ * Got them from linux/drivers/usb/serial/visor.h
+ */
+#define GENERIC_REQUEST_BYTES_AVAILABLE 0x01
+#define GENERIC_CLOSE_NOTIFICATION 0x02
+#define VISOR_GET_CONNECTION_INFORMATION 0x03
+#define PALM_GET_EXT_CONNECTION_INFORMATION 0x04
+
+/* Structures defining the info a device returns
+ * Got them from linux/drivers/usb/serial/visor.h
+ */
+typedef struct
+{
+ UInt16 num_ports;
+ struct
+ {
+ UInt8 port_function_id;
+ UInt8 port;
+ } connections[8];
+} visor_connection_info;
+
+/* struct visor_connection_info.connection[x].port defines: */
+#define VISOR_ENDPOINT_1 0x01
+#define VISOR_ENDPOINT_2 0x02
+
+/* struct visor_connection_info.connection[x].port_function_id defines: */
+#define VISOR_FUNCTION_GENERIC 0x00
+#define VISOR_FUNCTION_DEBUGGER 0x01
+#define VISOR_FUNCTION_HOTSYNC 0x02
+#define VISOR_FUNCTION_CONSOLE 0x03
+#define VISOR_FUNCTION_REMOTE_FILE_SYS 0x04
+
+typedef struct
+{
+ UInt8 num_ports;
+ UInt8 endpoint_numbers_different;
+ UInt16 reserved1;
+ struct
+ {
+ UInt32 port_function_id;
+ UInt8 port;
+ UInt8 endpoint_info;
+ UInt16 reserved;
+ } connections[8];
+} palm_ext_connection_info;
+
+/* PalmConnect USB specific information
+ * Extracted from Linux kl5kusb105 Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de>
+ * Using documentation Utz-Uwe provided
+ */
+enum {
+ /* Values for KLSI_GET/SET_COMM_DESCRIPTOR */
+ KLSI_BAUD_115200 = 0,
+ KLSI_BAUD_57600 = 1,
+ KLSI_BAUD_38400 = 2,
+ KLSI_BAUD_28800 = 3,
+ KLSI_BAUD_19200 = 4,
+ KLSI_BAUD_14400 = 5,
+ KLSI_BAUD_9600 = 6,
+ KLSI_BAUD_7200 = 7,
+ KLSI_BAUD_4800 = 8,
+ KLSI_BAUD_2400 = 9,
+ KLSI_BAUD_1200 = 10,
+ KLSI_BAUD_600 = 11,
+ KLSI_BAUD_230400 = 12,
+
+ KLSI_PARITY_NONE = 0,
+ KLSI_PARITY_ODD = 1,
+ KLSI_PARITY_EVEN = 2,
+ KLSI_PARITY_MARK = 3,
+
+ KLSI_STOPBITS_0 = 0,
+ KLSI_STOPBITS_2 = 2,
+
+ /* Handshake values for KLSI_GET_HANDSHAKE_LINES */
+ KLSI_GETHS_DCD = 0x80, /* Data Carrier Detect */
+ KLSI_GETHS_RI = 0x40, /* Ring Indicator */
+ KLSI_GETHS_DSR = 0x20, /* Data Set Ready */
+ KLSI_GETHS_CTS = 0x10, /* Clear To Send */
+
+ /* Handshake values for KLST_SET_HANDSHAKE_LINES */
+ KLSI_SETHS_RTS = 0x02, /* Ready To Send */
+ KLSI_SETHS_DTR = 0x01, /* Data Terminal Ready */
+
+ /* Flow control values */
+ KLSI_FLOW_USE_RTS = 0x01, /* use RTS/CTS */
+ KLSI_FLOW_USE_DSR = 0x02, /* use DSR/CD */
+ KLSI_FLOW_USE_XON = 0x04 /* use XON/XOFF */
+};
+
+#define KLSI_GET_COMM_DESCRIPTOR 0
+#define KLSI_SET_COMM_DESCRIPTOR 1
+#define KLSI_GET_HANDSHAKE_LINES 2
+#define KLSI_SET_HANDSHAKE_LINES 3
+#define KLSI_GET_FLOWCONTROL 4
+#define KLSI_SET_FLOWCONTROL 5
+
+typedef struct
+{
+ unsigned char DCBLength __attribute__((packed));
+ unsigned char BaudRateIndex __attribute__((packed));
+ unsigned char DataBits __attribute__((packed));
+ unsigned char Parity __attribute__((packed));
+ unsigned char StopBits __attribute__((packed));
+} klsi_port_settings;
+
+/* Some vendor and product codes we use */
+#define VENDOR_SONY 0x054c
+#define VENDOR_KEYSPAN 0x06cd
+#define VENDOR_HANDSPRING 0x082d
+#define VENDOR_PALMONE 0x0830
+#define VENDOR_TAPWAVE 0x12ef
+#define PRODUCT_PALMCONNECT_USB 0x0080
+#define PRODUCT_HANDSPRING_VISOR 0x0100
+#define PRODUCT_SONY_CLIE_3_5 0x0038
+
+/* This table helps us determine whether a connecting USB device is
+ * one we'd like to talk to. Don't forget to update it as new
+ * devices come out. To accept ALL the devices from a vendor, add
+ * an entry with the vendorID and 0xFFFF as productID.
+ */
+
+#define FLAG_ANSWERS_CONN_INFO 0x0001 /* device is known to answer connection information requests */
+#define FLAG_USE_FIRST_PAIR 0x0002 /* thanks to dumb programmers at Palm, the connection information doesn't match the actual pipes being used. If this flag is set, always try to use the first endoints pair */
+#define FLAG_USE_SECOND_PAIR 0x0004 /* ditto */
+#define FLAG_ANSWERS_PALM_CONN_INFO 0x0008 /* means that if the device doesn't answer PALM_EXT_CONNECTION_INFORMATION, don't try the visor variant (for stupid PalmOne handhelds) */
+#define FLAG_REJECT 0x8000 /* device is known but not supported yet */
+
+static struct {
+ unsigned short vendorID;
+ unsigned short productID;
+ unsigned short flags;
+}
+acceptedDevices[] = {
+ /* Sony */
+ {0x054c, 0x0038}, /* Sony Palm OS 3.5 devices, S300 */
+ {0x054c, 0x0066}, /* Sony T, S320, SJ series, and other Palm OS 4.0 devices */
+ {0x054c, 0x0095}, /* Sony S360 */
+ {0x054c, 0x000a}, /* Sony NR and other Palm OS 4.1 devices */
+ {0x054c, 0x009a}, /* Sony NR70V/U */
+ {0x054c, 0x00da}, /* Sony NX */
+ {0x054c, 0x00e9}, /* Sony NZ */
+ {0x054c, 0x0144}, /* Sony UX */
+ {0x054c, 0x0169}, /* Sony TJ */
+
+ /* Keyspan serial-to-USB PDA adapter */
+ {0x06cd, 0x0103, FLAG_REJECT}, /* ID sent by an adapter which firmware has not been uploaded yet */
+ {0x06cd, 0x0104, FLAG_REJECT}, /* ID sent by an adapter with proper firmware uploaded */
+
+ /* AlphaSmart */
+ {0x081e, 0xdf00}, /* Dana */
+
+ /* HANDSPRING (vendor 0x082d) */
+ {0x082d, 0x0100}, /* Visor */
+ {0x082d, 0x0200}, /* Treo */
+ {0x082d, 0x0300, FLAG_ANSWERS_CONN_INFO}, /* Treo 600 */
+
+ /* PalmOne, Palm Inc */
+ {0x0830, 0x0001, FLAG_ANSWERS_CONN_INFO}, /* m500 */
+ {0x0830, 0x0002, FLAG_ANSWERS_CONN_INFO}, /* m505 */
+ {0x0830, 0x0003, FLAG_ANSWERS_CONN_INFO}, /* m515 */
+ {0x0830, 0x0010},
+ {0x0830, 0x0011},
+ {0x0830, 0x0020}, /* i705 */
+ {0x0830, 0x0030},
+ {0x0830, 0x0031}, /* Tungsten|W */
+ {0x0830, 0x0040}, /* m125 */
+ {0x0830, 0x0050}, /* m130 */
+ {0x0830, 0x0051},
+ {0x0830, 0x0052},
+ {0x0830, 0x0053},
+ {0x0830, 0x0060, FLAG_ANSWERS_CONN_INFO}, /* Tungsten series, Zire 71 */
+ {0x0830, 0x0061, FLAG_ANSWERS_PALM_CONN_INFO | FLAG_USE_FIRST_PAIR}, /* Zire 22, 31, 72, T|5, T|X, LifeDrive, Treo 650 -- for T|X and LD, they don't answer to the PALM_EXT_CONNECTION_INFORMATION control code. In this case we revert to using the first pair of pipes */
+ {0x0830, 0x0062},
+ {0x0830, 0x0063},
+ {0x0830, 0x0070, FLAG_ANSWERS_CONN_INFO}, /* Zire */
+ {0x0830, 0x0071},
+ {0x0830, 0x0080}, /* palmOne serial adapter */
+ {0x0830, 0x0099},
+ {0x0830, 0x0100},
+
+ /* GARMIN */
+ {0x091e, 0x0004}, /* IQUE 3600 */
+
+ /* Kyocera */
+ {0x0c88, 0x0021}, /* 7135 Smartphone */
+ {0x0c88, 0xa226}, /* 6035 Smartphone */
+
+ /* Tapwave */
+ {0x12ef, 0x0100, FLAG_ANSWERS_CONN_INFO}, /* Zodiac, Zodiac2 */
+
+ /* ACEECA */
+ {0x4766, 0x0001}, /* MEZ1000 */
+
+ /* Fossil */
+ {0x0e67, 0x0002}, /* Abacus wrist PDA */
+
+ /* Samsung */
+ {0x04e8, 0x8001} /* I330 */
+};
+
+
+/* local prototypes */
+static int change_refcount(usb_connection_t *c, int increment);
+static void stop_listening(usb_connection_t *c);
+static IOReturn control_request (IOUSBDeviceInterface **dev, UInt8 requestType, UInt8 request, UInt16 value, UInt16 index, void *pData, UInt16 maxReplyLength);
+static void device_added (void *refCon, io_iterator_t iterator);
+static void device_notification (usb_connection_t *connexion, io_service_t service, natural_t messageType, void *messageArgument);
+static void read_completion (usb_connection_t *connexion, IOReturn result, void *arg0);
+static int accepts_device (unsigned short vendor, unsigned short product, unsigned short *flags);
+static IOReturn configure_device (IOUSBDeviceInterface **dev, unsigned short vendor, unsigned short product, unsigned short flags, int *port_number, int *input_pipe_number, int *output_pipe_number, int *pipe_info_retrieved);
+static IOReturn find_interfaces (usb_connection_t *usb, IOUSBDeviceInterface **dev, unsigned short vendor, unsigned short product, unsigned short accept_flags, int port_number, int input_pipe_number, int output_pipe_number, int pipe_info_retrieved);
+static int prime_read (usb_connection_t *connexion);
+static IOReturn read_visor_connection_information (IOUSBDeviceInterface **dev, int *port_number, int *input_pipe, int *output_pipe);
+static IOReturn decode_generic_connection_information(palm_ext_connection_info *ci, int *port_number, int *input_pipe, int *output_pipe);
+static IOReturn read_generic_connection_information (IOUSBDeviceInterface **dev, int *port_number, int *input_pipe_number, int *output_pipe_number);
+static IOReturn klsi_set_portspeed(IOUSBDeviceInterface **dev, int speed);
+
+
+/***************************************************************************/
+/* */
+/* GLOBAL DARWINUSB OPTIONS FOR CLIENT CODE */
+/* */
+/***************************************************************************/
+void
+darwinusb_setoptions(int multiple_connections_support)
+{
+ accept_multiple_simultaneous_connections = multiple_connections_support;
+}
+
+
+/***************************************************************************/
+/* */
+/* CONNECTIONS LINKED LIST MANAGEMENT */
+/* */
+/***************************************************************************/
+static void
+add_connection(usb_connection_t *c)
+{
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: adding connection %p to linked list\n", c));
+ pthread_mutex_lock(&usb_connections_mutex);
+ c->next = usb_connections;
+ usb_connections = c;
+ //pthread_cond_signal(&usb_connection_added_cond);
+ pthread_mutex_unlock(&usb_connections_mutex);
+}
+
+static int
+remove_connection(usb_connection_t *c)
+{
+ /* remove the connection from the linked list if it exists
+ * and return != 0. Otherwise return 0. Don't free the
+ * connection structure or variables.
+ */
+ usb_connection_t *previous = NULL, *elem;
+ pthread_mutex_lock(&usb_connections_mutex);
+ elem = usb_connections;
+ while (elem && elem != c)
+ {
+ previous = elem;
+ elem = elem->next;
+ }
+ if (elem)
+ {
+ if (previous)
+ previous->next = elem->next;
+ else
+ usb_connections = elem->next;
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: removed connection %p from linked list\n", c));
+ }
+ pthread_mutex_unlock(&usb_connections_mutex);
+ return elem != NULL;
+}
+
+static int
+device_already_in_use(IOUSBDeviceInterface **device)
+{
+ usb_connection_t *elem;
+ pthread_mutex_lock(&usb_connections_mutex);
+ elem = usb_connections;
+ while (elem != NULL && elem->device != device)
+ elem = elem->next;
+ pthread_mutex_unlock(&usb_connections_mutex);
+ return elem != NULL;
+}
+
+static usb_connection_t*
+connection_for_socket(pi_socket_t *ps)
+{
+ /* if there is no active connection associated with this socket,
+ * try to associate the first unassociated connection
+ */
+ usb_connection_t *c = ((pi_usb_data_t *)ps->device->data)->ref;
+ if (change_refcount(c, +1) > 0)
+ return c;
+
+ pthread_mutex_lock(&usb_connections_mutex);
+ c = usb_connections;
+ while (c && (c->ps != NULL || c->opened == 0 || c->total_bytes_read == 0)) /* skip connections which are being disposed of (opened=0) */
+ c = c->next;
+ if (change_refcount(c, +1) <= 0)
+ c = NULL;
+ else
+ {
+ c->ps = ps;
+ ((pi_usb_data_t *)ps->device->data)->ref = c;
+ }
+ pthread_mutex_unlock(&usb_connections_mutex);
+ return c;
+}
+
+static int
+change_refcount(usb_connection_t *c, int increment)
+{
+ /* update the refcount on the connection structure. If the refcount becomes
+ * zero, call the stop_listening() function
+ */
+ int rc;
+ if (c == NULL)
+ return 0;
+ if (pthread_mutex_lock(&c->ref_count_mutex) != 0)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: connection %p, can't lock ref_count_mutex (ref_count=%d)\n",c,c->ref_count_mutex));
+ return 0;
+ }
+ rc = c->ref_count = c->ref_count + increment;
+ if (rc < 0)
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: connection %p's refcount became < 0 (%d)\n", c, c->ref_count));
+ if (rc == 0)
+ {
+ if (remove_connection(c))
+ stop_listening(c);
+ }
+ else
+ pthread_mutex_unlock(&c->ref_count_mutex);
+ return rc;
+}
+
+/***************************************************************************/
+/* */
+/* INTERNAL ROUTINES */
+/* */
+/***************************************************************************/
+static int
+start_listening(void)
+{
+ mach_port_t masterPort;
+ CFMutableDictionaryRef matchingDict;
+ CFRunLoopSourceRef runLoopSource;
+ kern_return_t kr;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: start_listening for connections\n"));
+
+ /* first create a master_port for my task */
+ kr = IOMasterPort (MACH_PORT_NULL, &masterPort);
+ if (kr || !masterPort)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: couldn't create a master IOKit Port(%08x)\n", kr));
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+ /* Set up the matching criteria for the devices we're interested in
+ * Interested in instances of class IOUSBDevice and its subclasses
+ * Since we are supporting many USB devices, we just get notifications
+ * for all USB devices and sort out the ones that we want later.
+ */
+ matchingDict = IOServiceMatching (kIOUSBDeviceClassName);
+ if (!matchingDict)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: can't create a USB matching dictionary\n"));
+ mach_port_deallocate (mach_task_self(), masterPort);
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+ /* Create a notification port and add its run loop event source to our run loop
+ * This is how async notifications get set up.
+ */
+ usb_notify_port = IONotificationPortCreate (masterPort);
+ runLoopSource = IONotificationPortGetRunLoopSource (usb_notify_port);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
+
+ /* Set up a notifications to be called when a raw device is first matched by I/O Kit */
+ kr = IOServiceAddMatchingNotification (
+ usb_notify_port,
+ kIOFirstMatchNotification,
+ matchingDict,
+ device_added,
+ NULL,
+ &usb_device_added_iter);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: added service matching notification (kr=0x%08lx)\n", kr));
+
+ /* Iterate once to get already-present devices and arm the notification */
+ device_added (NULL, usb_device_added_iter);
+
+ /* Now done with the master_port */
+ mach_port_deallocate (mach_task_self(), masterPort);
+
+ return 0;
+}
+
+static void
+stop_listening(usb_connection_t *c)
+{
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: stop_listening for connection %p\n",c));
+
+ c->opened = 0;
+ c->in_pipe_ref = 0;
+ c->out_pipe_ref = 0;
+
+ if (c->ps)
+ {
+ /* we do this because if the connection abruptly ends before pilot-link notices,
+ * we want to avoid pi_close() trying to do a dlp_EndOfSync()
+ */
+ c->ps->state = PI_SOCK_CLOSE;
+ if (c->ps->device != NULL && c->ps->device->data != NULL)
+ ((pi_usb_data_t *)c->ps->device->data)->ref = NULL;
+ }
+ c->ps = NULL;
+
+ if (c->device_notification)
+ {
+ IOObjectRelease (c->device_notification);
+ c->device_notification = 0;
+ }
+
+ if (c->interface)
+ {
+ (*c->interface)->USBInterfaceClose (c->interface);
+ (*c->interface)->Release(c->interface);
+ c->interface = NULL;
+ }
+
+ if (c->device)
+ {
+ (*c->device)->USBDeviceClose (c->device);
+ (*c->device)->Release(c->device);
+ c->device = NULL;
+ }
+
+ pthread_mutex_destroy(&c->read_queue_mutex);
+ pthread_mutex_destroy(&c->ref_count_mutex);
+ free(c);
+}
+
+static void *
+usb_thread_run(void *foo)
+{
+ if (start_listening() == 0)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: usb_thread_run, starting...\n"));
+
+ /* obtain the CFRunLoop for this thread */
+ pthread_mutex_lock(&usb_run_loop_mutex);
+ usb_run_loop = CFRunLoopGetCurrent();
+ pthread_mutex_unlock(&usb_run_loop_mutex);
+
+ /* signal main thread that init was successful */
+ pthread_mutex_lock(&usb_thread_ready_mutex);
+ pthread_cond_broadcast(&usb_thread_ready_cond);
+ pthread_mutex_unlock(&usb_thread_ready_mutex);
+
+ CFRunLoopRun();
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: usb_thread_run, done with runloop\n"));
+
+ pthread_mutex_lock(&usb_run_loop_mutex);
+ usb_run_loop = 0;
+ pthread_mutex_unlock(&usb_run_loop_mutex);
+
+ if (usb_device_added_iter)
+ {
+ IOObjectRelease (usb_device_added_iter);
+ usb_device_added_iter = 0;
+ }
+
+ if (usb_notify_port)
+ {
+ IONotificationPortDestroy(usb_notify_port);
+ usb_notify_port = NULL;
+ }
+
+ /* decrement the refcount of each structure. If there
+ * was a pending read, decrement once more since
+ * prime_read() increments the refcount
+ */
+ usb_connection_t *elem, *next, *prev = NULL;
+ pthread_mutex_lock(&usb_connections_mutex);
+ elem = usb_connections;
+ while (elem != NULL)
+ {
+ next = elem->next;
+ pthread_mutex_lock(&elem->ref_count_mutex);
+ elem->ref_count--;
+ if (elem->read_pending)
+ elem->ref_count--;
+ if (elem < 0)
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: while stopping usb_thread, connection %p's refcount became < 0 (%d)", elem, elem->ref_count));
+ if (elem == 0)
+ {
+ if (prev != NULL)
+ prev->next = next;
+ else
+ usb_connections = next;
+ stop_listening(elem);
+ elem = NULL;
+ }
+ else
+ {
+ pthread_mutex_unlock(&elem->ref_count_mutex);
+ prev = elem;
+ }
+ }
+ pthread_mutex_unlock(&usb_connections_mutex);
+
+ usb_thread = 0;
+ usb_run_loop = NULL;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: usb_thread_run, exited.\n"));
+ }
+ else
+ {
+ /* signal main thread that init failed */
+ usb_thread = 0;
+ usb_run_loop = NULL;
+ pthread_mutex_lock(&usb_thread_ready_mutex);
+ pthread_cond_signal(&usb_thread_ready_cond);
+ pthread_mutex_unlock(&usb_thread_ready_mutex);
+ }
+ return NULL;
+}
+
+static void
+device_added (void *refCon, io_iterator_t iterator)
+{
+ kern_return_t kr;
+ io_service_t ioDevice;
+ IOCFPlugInInterface **plugInInterface = NULL;
+ IOUSBDeviceInterface **dev = NULL;
+ HRESULT res;
+ SInt32 score;
+ UInt16 vendor, product;
+ unsigned short accept_flags;
+ int port_number = 0xff,
+ input_pipe_number = 0xff,
+ output_pipe_number = 0xff,
+ pipe_info_retrieved = 0;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: device_added\n"));
+
+ while ((ioDevice = IOIteratorNext (iterator)))
+ {
+ if (usb_connections != NULL && !accept_multiple_simultaneous_connections)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: new device plugged but we already have a running connection\n"));
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ kr = IOCreatePlugInInterfaceForService (ioDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
+ if (kr != kIOReturnSuccess || !plugInInterface)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: -> unable to create a plugin (kr=0x%08x)\n", kr));
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ res = (*plugInInterface)->QueryInterface (plugInInterface, CFUUIDGetUUIDBytes (kIOUSBDeviceInterfaceID), (LPVOID *)&dev);
+ (*plugInInterface)->Release (plugInInterface);
+ if (res || !dev)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: couldn't create a device interface (res=0x%08x)\n", (int) res));
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ /* make sure this device is not already being handled (this may happen
+ * with some handhelds that reconnect immediately after disconnecting, like the T5)
+ */
+ if (device_already_in_use(dev))
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: device %p already in use, skipping it\n"));
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ kr = (*dev)->GetDeviceVendor (dev, &vendor);
+ kr = (*dev)->GetDeviceProduct (dev, &product);
+ if (accepts_device(vendor, product, &accept_flags) == 0)
+ {
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: not accepting device (vendor=0x%04x product=0x%04x)\n", vendor, product));
+ (*dev)->Release(dev);
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: Accepted USB device, vendor: 0x%04x product: 0x%04x\n", vendor, product));
+
+ kr = (*dev)->USBDeviceOpen (dev);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to open device (kr=0x%08x)\n", kr));
+ (*dev)->Release(dev);
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ /* configure the device and query for its preferred I/O pipes */
+ kr = configure_device (dev, vendor, product, accept_flags, &port_number, &input_pipe_number, &output_pipe_number, &pipe_info_retrieved);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, (kr == kIOReturnNotReady)
+ ? "darwinusb: device not ready to synchonize\n"
+ : "darwinusb: unable to configure device (kr=0x%08x)\n", kr));
+ (*dev)->USBDeviceClose (dev);
+ (*dev)->Release (dev);
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ /* allocate and initialize the USB connection structure */
+ usb_connection_t *c = malloc(sizeof(usb_connection_t));
+ if (c == NULL)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "out of memory"));
+ (*dev)->USBDeviceClose (dev);
+ (*dev)->Release (dev);
+ IOObjectRelease (ioDevice);
+ break;
+ }
+
+ memset(c, 0, sizeof(usb_connection_t));
+ c->auto_read_size = AUTO_READ_SIZE;
+ c->device = dev;
+ c->ref_count = 1;
+ c->opened = 1;
+ c->device_present = 1;
+ c->vendorID = vendor;
+ c->productID = product;
+ c->dev_flags = accept_flags;
+
+ /* try to locate the pipes we need to talk to the device */
+ kr = find_interfaces(c, dev, vendor, product, accept_flags, port_number, input_pipe_number, output_pipe_number, pipe_info_retrieved);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to find interfaces (kr=0x%08x)\n", kr));
+ free(c);
+ (*dev)->USBDeviceClose (dev);
+ (*dev)->Release (dev);
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+
+ /* Just like with service matching notifications, we need to create an event source and add it
+ * to our run loop in order to receive async completion notifications.
+ */
+ CFRunLoopSourceRef runLoopSource;
+ kr = (*c->interface)->CreateInterfaceAsyncEventSource (c->interface, &runLoopSource);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: Unable to create async event source (%08x)\n", kr));
+ free(c);
+ (*dev)->USBDeviceClose (dev);
+ (*dev)->Release (dev);
+ IOObjectRelease (ioDevice);
+ continue;
+ }
+ CFRunLoopAddSource (CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "darwinusb: USBConnection %p OPENED c->in_pipe_ref=%d c->out_pipe_ref=%d\n",c,c->in_pipe_ref,c->out_pipe_ref));
+
+ /* Register for an interest notification for this device,
+ * so we get notified when it goes away
+ */
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: registering for disconnect notification\n"));
+ kr = IOServiceAddInterestNotification(
+ usb_notify_port,
+ ioDevice,
+ kIOGeneralInterest,
+ (IOServiceInterestCallback)device_notification,
+ (void *)c,
+ &c->device_notification);
+ IOObjectRelease(ioDevice);
+
+ /* add the device to our linked list, then only start reading data
+ * (order of operations matters here to avoid race conditions)
+ */
+ pthread_mutex_init(&c->read_queue_mutex, NULL);
+ pthread_mutex_init(&c->ref_count_mutex, NULL);
+ pthread_cond_init(&c->read_queue_data_avail_cond, NULL);
+
+ add_connection(c);
+ prime_read(c);
+ }
+}
+
+static IOReturn
+configure_device(IOUSBDeviceInterface **di,
+ unsigned short vendor,
+ unsigned short product,
+ unsigned short flags,
+ int *port_number,
+ int *input_pipe_number,
+ int *output_pipe_number,
+ int *pipe_info_retrieved)
+{
+ UInt8 numConf, conf, deviceClass;
+ IOReturn kr;
+ IOUSBConfigurationDescriptorPtr confDesc;
+
+ /* Get the device class. Most handhelds are registered as composite devices
+ * and therefore already opened & configured by OS X drivers! It seems that
+ * reconfiguring them as we did before is what caused some Sony devices to
+ * refuse talking to us.
+ */
+ kr = (*di)->GetDeviceClass (di, &deviceClass);
+ if (kr != kIOReturnSuccess)
+ return kr;
+
+ if (deviceClass != kUSBCompositeClass)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: Not a composite device: performing confiuration\n"));
+
+ kr = (*di)->GetNumberOfConfigurations (di, &numConf);
+ if (!numConf)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: device has zero configurations!\n"));
+ return -1;
+ }
+
+ /* try all possible configurations if the first one fails
+ * (shouldn't happen in most cases though)
+ */
+ for (conf=0; conf < numConf; conf++)
+ {
+ kr = (*di)->GetConfigurationDescriptorPtr(di, 0, &confDesc);
+ if (kr)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to get config descriptor for index %d (err=%08x numConf=%d)\n",
+ 0, kr, (int)numConf));
+ continue;
+ }
+
+ kr = (*di)->SetConfiguration(di, confDesc->bConfigurationValue);
+ if (kr == kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: successfully set configuration %d\n",(int)confDesc->bConfigurationValue));
+ break;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to set configuration to value %d (err=%08x numConf=%d)\n",
+ (int)confDesc->bConfigurationValue, kr, (int)numConf));
+ }
+ if (conf == numConf)
+ return kr;
+ }
+
+ if (vendor == VENDOR_PALMONE && product == PRODUCT_PALMCONNECT_USB)
+ {
+ kr = klsi_set_portspeed(di, 9600);
+ *input_pipe_number = 0x01;
+ *output_pipe_number = 0x02;
+ *pipe_info_retrieved = 1;
+ return kr;
+ }
+
+ /* Try reading pipe information. Most handhelds support a control request that returns info about the ports and
+ * pipes. We first try the generic control code, and if it doesn't work we try the Visor one which seems to be
+ * supported by some devices Also, we can detect that a T5 / LifeDrive is in "wait" mode
+ * (device appears on USB but not synchronizing) and in this case we return a kIOReturnNotReady code.
+ */
+ kr = read_generic_connection_information (di, port_number, input_pipe_number, output_pipe_number);
+ if (kr != kIOReturnSuccess && kr != kIOReturnNotReady && !(flags & FLAG_ANSWERS_PALM_CONN_INFO))
+ kr = read_visor_connection_information (di, port_number, input_pipe_number, output_pipe_number);
+ if (kr == kIOReturnNotReady)
+ return kr;
+
+ /* With some devices (Palm) we need to hardcode the location of the pipes to use
+ * because the Palm engineers had the good idea to mismatch the connection information data
+ * and the actual pipes to use
+ */
+ if (flags & (FLAG_USE_FIRST_PAIR | FLAG_USE_SECOND_PAIR))
+ {
+ *pipe_info_retrieved = 1;
+ return kIOReturnSuccess;
+ }
+
+ /* For device which we know return connection information, we want it to be returned to
+ * consider the device alive
+ */
+ if (kr != kIOReturnSuccess && (flags & FLAG_ANSWERS_CONN_INFO))
+ return kIOReturnNotReady;
+
+ *pipe_info_retrieved = (kr == kIOReturnSuccess);
+
+ /* query bytes available. Not that we really care, but most devices expect to receive this
+ * before they agree on talking to us.
+ */
+ if (vendor != VENDOR_TAPWAVE)
+ {
+ unsigned char ba[2];
+ kr = control_request (di, 0xc2, GENERIC_REQUEST_BYTES_AVAILABLE, 0, 0, &ba[0] , 2);
+ if (kr != kIOReturnSuccess)
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: GENERIC_REQUEST_BYTES_AVAILABLE failed (err=%08x)\n", kr));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "GENERIC_REQUEST_BYTES_AVAILABLE returns 0x%02x%02x\n", ba[0], ba[1]));
+ }
+
+ return kIOReturnSuccess;
+}
+
+static IOReturn
+find_interfaces(usb_connection_t *c,
+ IOUSBDeviceInterface **di,
+ unsigned short vendor,
+ unsigned short product,
+ unsigned short accept_flags,
+ int port_number,
+ int input_pipe_number,
+ int output_pipe_number,
+ int pipe_info_retrieved)
+{
+ IOReturn kr;
+ io_iterator_t iterator;
+ io_service_t usbInterface;
+ HRESULT res;
+ SInt32 score;
+ UInt8 intfClass, intfSubClass, intfNumEndpoints;
+ int pipeRef, pass;
+ IOUSBFindInterfaceRequest request;
+ IOCFPlugInInterface **plugInInterface = NULL;
+ UInt8 direction, number, transferType, interval;
+ UInt16 maxPacketSize;
+
+ request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
+ request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
+ request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
+ request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
+
+ kr = (*di)->CreateInterfaceIterator (di, &request, &iterator);
+
+ while ((usbInterface = IOIteratorNext (iterator)))
+ {
+ kr = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
+ kr = IOObjectRelease (usbInterface); // done with the usbInterface object now that I have the plugin
+ if (kr != kIOReturnSuccess || !plugInInterface)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to create a plugin (%08x)\n", kr));
+ continue;
+ }
+
+ /* we have the interface plugin: we now need the interface interface */
+ res = (*plugInInterface)->QueryInterface (plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID *) &c->interface);
+ (*plugInInterface)->Release (plugInInterface); /* done with this */
+ if (res || c->interface == NULL)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: couldn't create an IOUSBInterfaceInterface (%08x)\n", (int) res));
+ continue;
+ }
+
+ /* get the interface class and subclass */
+ kr = (*c->interface)->GetInterfaceClass (c->interface, &intfClass);
+ kr = (*c->interface)->GetInterfaceSubClass (c->interface, &intfSubClass);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: interface class %d, subclass %d\n", intfClass, intfSubClass));
+
+ /* Now open the interface. This will cause the pipes to be instantiated that are
+ * associated with the endpoints defined in the interface descriptor.
+ */
+ kr = (*c->interface)->USBInterfaceOpen (c->interface);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to open interface (%08x)\n", kr));
+ (*c->interface)->Release (c->interface);
+ c->interface = NULL;
+ continue;
+ }
+
+ kr = (*c->interface)->GetNumEndpoints (c->interface, &intfNumEndpoints);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to get number of endpoints (%08x)\n", kr));
+ (*c->interface)->USBInterfaceClose (c->interface);
+ (*c->interface)->Release (c->interface);
+ c->interface = NULL;
+ continue;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: interface has %d endpoints\n", intfNumEndpoints));
+
+ /* If device didn't answer to the connection_information request,
+ * try to read a preamble sent by the device. This is sent by devices which chipsets
+ * don't support the vendor control endpoint requests. Look for the first pipe on
+ * which a preamble is available.
+ */
+ if (!pipe_info_retrieved)
+ {
+ int reqTimeout;
+ int preambleFound = 0;
+ for (reqTimeout = 100; reqTimeout <= 300 && !preambleFound; reqTimeout += 100)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: checking for pipe_info sent by device with timeout %dms\n",reqTimeout));
+ for (pipeRef = 1; pipeRef <= intfNumEndpoints; pipeRef++)
+ {
+ kr = (*c->interface)->GetPipeProperties (c->interface, pipeRef, &direction, &number,
+ &transferType, &maxPacketSize, &interval);
+ if (kr != kIOReturnSuccess)
+ continue;
+ if (direction == kUSBIn)
+ {
+ UInt32 size = sizeof(c->read_buffer)-1;
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: trying pipe %d type=%d\n", pipeRef, (int)transferType));
+ if (transferType == kUSBBulk)
+ kr = (*c->interface)->ReadPipeTO (c->interface, pipeRef, &c->read_buffer, &size, reqTimeout, 250);
+ else
+ kr = (*c->interface)->ReadPipe (c->interface, pipeRef, &c->read_buffer, &size);
+
+ if (kr == kIOReturnSuccess && size >= 8)
+ {
+ /* got something! */
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: got %d bytes there!\n", (int)size));
+ CHECK(PI_DBG_DEV, PI_DBG_LVL_DEBUG, pi_dumpdata(c->read_buffer, size));
+ if (!memcmp(c->read_buffer, "VNDR10", 6))
+ {
+ /* VNDR version 1.0 */
+ palm_ext_connection_info ci;
+ memcpy(&ci, &c->read_buffer[6], sizeof(ci));
+ decode_generic_connection_information(&ci, &port_number, &input_pipe_number, &output_pipe_number);
+ preambleFound = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Locate the pipes we're going to use for reading and writing.
+ * We have four chances to find the right pipes:
+ * 1. If we got a hint from the device with input/output pipes, we try this one first.
+ * 2. If we didn't get both pipes, try using the port number hint. There is at least one recent
+ * device (LifeDrive) on which the port_number hint is actually an endpoint pair index.
+ * The code below tries to cope with that.
+ * 3. If we're still missing one or two pipes, give a second try looking for pipes with a
+ * 64 bytes transfer size
+ * 4. Finally of this failed, forget about the transfer size and take the first ones that
+ * come (i.e. Tungsten W has a 64 bytes IN pipe and a 32 bytes OUT pipe).
+ */
+ for (pass=1; pass <= 4 && (c->in_pipe_ref==0 || c->out_pipe_ref==0); pass++)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: pass %d looking for pipes, port_number=0x%02x, input_pipe_number=0x%02x, output_pipe_number=0x%02x\n",
+ pass, port_number, input_pipe_number, output_pipe_number));
+ c->in_pipe_ref = 0;
+ c->out_pipe_ref = 0;
+
+ int input_pipes_seen = 0;
+ int output_pipes_seen = 0;
+
+ for (pipeRef = 1; pipeRef <= intfNumEndpoints; pipeRef++)
+ {
+ kr = (*c->interface)->GetPipeProperties (c->interface, pipeRef, &direction, &number,
+ &transferType, &maxPacketSize, &interval);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: unable to get properties of pipe %d (kr=0x%08x)\n", pipeRef, kr));
+ }
+ else
+ {
+ int pair_index = (direction == kUSBIn) ? ++input_pipes_seen : ++output_pipes_seen;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "darwinusb: pipe %d: direction=0x%02x, number=0x%02x, transferType=0x%02x, maxPacketSize=%d, interval=0x%02x, pair_index=%d\n",
+ pipeRef,(int)direction,(int)number,(int)transferType,(int)maxPacketSize,(int)interval,pair_index));
+ if (c->in_pipe_ref == 0 &&
+ direction == kUSBIn &&
+ transferType == kUSBBulk)
+ {
+ if ((pass == 1 && input_pipe_number != 0xff && number == input_pipe_number) ||
+ (pass == 1 && port_number == 0xff && input_pipe_number == 0xff && (accept_flags & FLAG_USE_FIRST_PAIR)) ||
+ (pass == 2 && port_number != 0xff && number == port_number) ||
+ (pass == 3 && ((port_number != 0xff && pair_index == port_number) || (port_number == 0xff && (maxPacketSize == 64 || maxPacketSize == 512)))) ||
+ pass == 4)
+ c->in_pipe_ref = pipeRef;
+ c->in_pipe_bulk_size = maxPacketSize;
+ }
+ else if (c->out_pipe_ref == 0 &&
+ direction == kUSBOut &&
+ transferType == kUSBBulk)
+ {
+ if ((pass == 1 && output_pipe_number != 0xff && number == output_pipe_number) ||
+ (pass == 1 && port_number == 0xff && input_pipe_number == 0xff && (accept_flags & FLAG_USE_FIRST_PAIR)) ||
+ (pass == 2 && port_number != 0xff && number == port_number) ||
+ (pass == 3 && ((port_number != 0xff && pair_index == port_number) || (port_number == 0xff && (maxPacketSize == 64 || maxPacketSize == 512)))) ||
+ pass == 4)
+ {
+ c->out_pipe_ref = pipeRef;
+ c->out_pipe_bulk_size = maxPacketSize;
+ }
+ }
+ }
+ }
+ }
+
+ if (c->in_pipe_ref && c->out_pipe_ref)
+ return kIOReturnSuccess;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: couldn't find any suitable pipes pair on this interface\n"));
+ (*c->interface)->USBInterfaceClose (c->interface);
+ (*c->interface)->Release (c->interface);
+ c->interface = NULL;
+ c->in_pipe_ref = 0;
+ c->out_pipe_ref = 0;
+ }
+
+ return c->interface==NULL ? -1 : kIOReturnSuccess;
+}
+
+static IOReturn
+control_request(IOUSBDeviceInterface **dev, UInt8 requestType, UInt8 request, UInt16 value, UInt16 index, void *pData, UInt16 maxReplyLength)
+{
+ IOReturn kr;
+ IOUSBDevRequest req;
+ void *pReply = pData;
+
+ if (!pReply && maxReplyLength)
+ pReply = malloc(maxReplyLength);
+
+ req.bmRequestType = requestType; /* i.e. 0xc2=kUSBIn, kUSBVendor, kUSBEndpoint */
+ req.bRequest = request;
+ req.wValue = value;
+ req.wIndex = index;
+ req.wLength = maxReplyLength;
+ req.pData = pReply;
+ req.wLenDone = 0;
+
+ kr = (*dev)->DeviceRequest (dev, &req);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: control_request(0x%02x) wLenDone=%d kr=0x%08lx\n", (int)request, req.wLenDone, kr));
+
+ if (pReply && !pData)
+ free (pReply);
+
+ return kr;
+}
+
+static IOReturn
+read_visor_connection_information (IOUSBDeviceInterface **dev, int *port_number, int *input_pipe, int *output_pipe)
+{
+ int i;
+ kern_return_t kr;
+ visor_connection_info ci;
+
+ memset(&ci, 0, sizeof(ci));
+ kr = control_request (dev, 0xc2, VISOR_GET_CONNECTION_INFORMATION, 0, 0, &ci, sizeof(ci));
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: VISOR_GET_CONNECTION_INFORMATION failed (err=%08x)\n", kr));
+ }
+ else
+ {
+ CHECK(PI_DBG_DEV, PI_DBG_LVL_DEBUG, pi_dumpdata((const char *)&ci, sizeof(ci)));
+ ci.num_ports = CFSwapInt16LittleToHost(ci.num_ports); /* number of ports is little-endian */
+ if (ci.num_ports > 8)
+ ci.num_ports = 8;
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: VISOR_GET_CONNECTION_INFORMATION, num_ports=%d\n", ci.num_ports));
+ kr = kIOReturnNotReady;
+ for (i=0; i < ci.num_ports; i++)
+ {
+ char *function_str;
+ switch (ci.connections[i].port_function_id)
+ {
+ case VISOR_FUNCTION_GENERIC:
+ function_str = "GENERIC";
+ break;
+ case VISOR_FUNCTION_DEBUGGER:
+ function_str = "DEBUGGER";
+ break;
+ case VISOR_FUNCTION_HOTSYNC:
+ function_str = "HOTSYNC";
+ if (port_number)
+ *port_number = ci.connections[i].port;
+ kr = kIOReturnSuccess;
+ break;
+ case VISOR_FUNCTION_CONSOLE:
+ function_str = "CONSOLE";
+ break;
+ case VISOR_FUNCTION_REMOTE_FILE_SYS:
+ function_str = "REMOTE_FILE_SYSTEM";
+ break;
+ default:
+ function_str = "UNKNOWN";
+ break;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port_function_id=0x%02x (%s)\n", i, ci.connections[i].port_function_id, function_str));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port=%d\n", i, ci.connections[i].port));
+ }
+ }
+ return kr;
+}
+
+static IOReturn
+decode_generic_connection_information(palm_ext_connection_info *ci, int *port_number, int *input_pipe, int *output_pipe)
+{
+ int i;
+
+ CHECK(PI_DBG_DEV, PI_DBG_LVL_DEBUG, pi_dumpdata((const char *)ci, sizeof(palm_ext_connection_info)));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: decode_generic_connection_information num_ports=%d, endpoint_numbers_different=%d\n", ci->num_ports, ci->endpoint_numbers_different));
+
+ for (i=0; i < ci->num_ports; i++)
+ {
+ UInt32 port_function_id = CFSwapInt32LittleToHost(ci->connections[i].port_function_id);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port_function_id=0x%08lx ('%4.4s')\n", i, port_function_id, (char*)&port_function_id));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port=%d\n", i, ci->connections[i].port));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] endpoint_info=%d (0x%02x)\n", i, ci->connections[i].endpoint_info, (int)ci->connections[i].endpoint_info));
+ if (port_function_id == 'rfsL')
+ {
+ /* This is a T5 in USB connected but not synchronizing:
+ * don't bother trying to talk to it
+ */
+ return kIOReturnNotReady;
+ }
+ if (port_function_id == 'sync' || port_function_id == 'ppp_')
+ {
+ /* we found the port/pipes to use for synchronization
+ * If endpoint_numbers_different is != 0, then the number of each
+ * endpoint to use for IN and OUT is stored in endpoint_info.
+ * Otherwise, the port number (same for both endpoints) is in
+ * port.
+ */
+ if (!ci->endpoint_numbers_different)
+ {
+ if (port_number)
+ *port_number = ci->connections[i].port;
+ }
+ else if (ci->connections[i].endpoint_info)
+ {
+ if (input_pipe)
+ *input_pipe = ci->connections[i].endpoint_info >> 4;
+ if (output_pipe)
+ *output_pipe = ci->connections[i].endpoint_info & 0x0f;
+ }
+ }
+ }
+
+ return kIOReturnSuccess;
+}
+
+static IOReturn
+read_generic_connection_information (IOUSBDeviceInterface **dev, int *port_number, int *input_pipe, int *output_pipe)
+{
+ kern_return_t kr;
+ palm_ext_connection_info ci;
+
+ memset(&ci, 0, sizeof(ci));
+ kr = control_request (dev, 0xc2, PALM_GET_EXT_CONNECTION_INFORMATION, 0, 0, &ci, sizeof(ci));
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: PALM_GET_EXT_CONNECTION_INFORMATION failed (err=%08x)\n", kr));
+ return kr;
+ }
+ return decode_generic_connection_information(&ci, port_number, input_pipe, output_pipe);
+}
+
+static IOReturn
+klsi_set_portspeed(IOUSBDeviceInterface **dev, int speed)
+{
+ /* set the comms speed for a KLSI serial adapter (PalmConnect USB) */
+ kern_return_t kr;
+ klsi_port_settings settings = {5, KLSI_BAUD_9600, 8, KLSI_PARITY_NONE, KLSI_STOPBITS_0};
+ switch (speed)
+ {
+ case 230400: settings.BaudRateIndex = KLSI_BAUD_230400; break;
+ case 115200: settings.BaudRateIndex = KLSI_BAUD_115200; break;
+ case 57600: settings.BaudRateIndex = KLSI_BAUD_57600; break;
+ case 38400: settings.BaudRateIndex = KLSI_BAUD_38400; break;
+ case 28800: settings.BaudRateIndex = KLSI_BAUD_28800; break;
+ case 19200: settings.BaudRateIndex = KLSI_BAUD_19200; break;
+ case 14400: settings.BaudRateIndex = KLSI_BAUD_14400; break;
+ case 9600: settings.BaudRateIndex = KLSI_BAUD_9600; break;
+ case 7200: settings.BaudRateIndex = KLSI_BAUD_7200; break;
+ case 4800: settings.BaudRateIndex = KLSI_BAUD_4800; break;
+ case 2400: settings.BaudRateIndex = KLSI_BAUD_2400; break;
+ case 1200: settings.BaudRateIndex = KLSI_BAUD_1200; break;
+ case 600: settings.BaudRateIndex = KLSI_BAUD_600; break;
+ default: break;
+ }
+
+ kr = control_request(dev, 0x40, KLSI_SET_COMM_DESCRIPTOR, 0, 0, &settings, 5);
+ if (kr == kIOReturnSuccess)
+ {
+ kr = control_request(dev, 0x40, KLSI_SET_COMM_DESCRIPTOR, 0, 0, &settings, 5);
+ if (kr == kIOReturnSuccess)
+ kr = control_request(dev, 0x40, KLSI_SET_FLOWCONTROL, (speed > 9600) ? KLSI_FLOW_USE_RTS : 0, 0, NULL, 0);
+
+ control_request(dev, 0x40, KLSI_SET_HANDSHAKE_LINES, KLSI_SETHS_DTR | KLSI_SETHS_RTS, 0, NULL, 0);
+ }
+ return kr;
+}
+
+static void
+device_notification(usb_connection_t *c, io_service_t service, natural_t messageType, void *messageArgument)
+{
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: device_notification (c=%p messageType=0x%08lx)\n", c, messageType));
+
+ if (messageType == kIOMessageServiceIsTerminated && c != NULL)
+ {
+ c->device_present = 0;
+ c->opened = 0; /* so that stop_listening() does'nt try to send the control_request */
+ if (change_refcount(c,-1) > 0)
+ {
+ /* In case the reading thread is waiting for data,
+ * we need to raise the usb_data_available cond once.
+ * since darwin_usb_read tests usb.opened, it will
+ * gracefully exit during a data wait.
+ */
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: device_notification signaling c->read_queue_data_avail_cond for c=%p\n",c));
+ pthread_mutex_lock (&c->read_queue_mutex);
+ pthread_cond_signal (&c->read_queue_data_avail_cond);
+ pthread_mutex_unlock (&c->read_queue_mutex);
+ }
+ }
+}
+
+static void
+read_completion (usb_connection_t *c, IOReturn result, void *arg0)
+{
+ size_t bytes_read = (size_t) arg0;
+
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: read_completion(c=%p, result=0x%08lx, bytes_read=%d)\n", c, (long)result, bytes_read));
+
+ if (!c->opened)
+ {
+ change_refcount(c, -1);
+ return;
+ }
+
+ if (result != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN, "darwinusb: async read completion(%p) received error code 0x%08x\n", c, result));
+ }
+
+ if (bytes_read)
+ {
+ if (c->vendorID == VENDOR_PALMONE && c->productID == PRODUCT_PALMCONNECT_USB)
+ {
+ /* decode PalmConnect USB frame */
+ if (bytes_read < 2)
+ bytes_read = 0;
+ else
+ {
+ int data_size = (int)c->read_buffer[0] | ((int)c->read_buffer[1] << 8);
+ if ((data_size + 2) > bytes_read)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: invalid PalmConnect packet (%d bytes, says %d content bytes)\n",
+ bytes_read, data_size));
+ bytes_read = 0;
+ } else {
+ memmove(&c->read_buffer[0], &c->read_buffer[2], data_size);
+ bytes_read = data_size;
+ }
+ }
+ }
+ if (bytes_read > 0)
+ {
+ pthread_mutex_lock(&c->read_queue_mutex);
+ if (c->read_queue == NULL)
+ {
+ c->read_queue_size = ((bytes_read + 0xfffe) & ~0xffff) - 1; /* 64k chunks */
+ c->read_queue = (char *) malloc (c->read_queue_size);
+ c->read_queue_used = 0;
+ }
+ else if ((c->read_queue_used + bytes_read) > c->read_queue_size)
+ {
+ c->read_queue_size += ((bytes_read + 0xfffe) & ~0xffff) - 1;
+ c->read_queue = (char *) realloc (c->read_queue, c->read_queue_size);
+ }
+ if (c->read_queue)
+ {
+ memcpy(c->read_queue + c->read_queue_used, c->read_buffer, bytes_read);
+ c->read_queue_used += bytes_read;
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: signaling c->read_queue_data_avail_cond for c=%p\n",c));
+ pthread_cond_signal(&c->read_queue_data_avail_cond);
+ }
+ else
+ {
+ c->read_queue_used = 0;
+ c->read_queue_size = 0;
+ }
+ pthread_mutex_unlock(&c->read_queue_mutex);
+
+ if (c->total_bytes_read == 0)
+ {
+ /* the connection is now considered live */
+ pthread_mutex_lock(&usb_connections_mutex);
+ pthread_cond_signal(&usb_connection_added_cond);
+ pthread_mutex_unlock(&usb_connections_mutex);
+ }
+ c->total_bytes_read += (unsigned long)bytes_read;
+ }
+ }
+
+ if (result != kIOReturnAborted && c->opened && usb_run_loop)
+ {
+ if (result != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: clearing input pipe stall\n"));
+ (*c->interface)->ClearPipeStallBothEnds (c->interface, c->in_pipe_ref);
+ }
+ prime_read(c);
+ }
+
+ change_refcount(c, -1);
+}
+
+static int
+prime_read(usb_connection_t *c)
+{
+ /* increment refcount */
+ if (pthread_mutex_lock(&c->ref_count_mutex) != 0)
+ {
+ /* c became invalid? */
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: prime_read(%p): can't lock c->ref_count_mutex (structure freed?)\n", c));
+ return 0;
+ }
+ c->ref_count++;
+ pthread_mutex_unlock(&c->ref_count_mutex);
+
+ if (c->opened)
+ {
+ /* select a correct read size (always use a multiple of the USB packet size) */
+ if (c->vendorID == VENDOR_PALMONE && c->productID == PRODUCT_PALMCONNECT_USB)
+ {
+ /* with PalmConnect USB, always use 64 bytes */
+ c->last_read_ahead_size = 64;
+ }
+ else
+ {
+ c->last_read_ahead_size = c->read_ahead_size & ~(c->in_pipe_bulk_size-1);
+ if (c->last_read_ahead_size <= 0)
+ c->last_read_ahead_size = c->auto_read_size;
+ if (c->last_read_ahead_size > MAX_AUTO_READ_SIZE)
+ c->last_read_ahead_size = MAX_AUTO_READ_SIZE;
+ else if (c->last_read_ahead_size < c->in_pipe_bulk_size)
+ c->last_read_ahead_size = c->in_pipe_bulk_size; // USB packet size
+ }
+
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: prime_read(%p) for %d bytes\n", c, c->last_read_ahead_size));
+
+ IOReturn kr = (*c->interface)->ReadPipeAsyncTO (c->interface, c->in_pipe_ref,
+ c->read_buffer, c->last_read_ahead_size, 5000, 5000, (IOAsyncCallback1)&read_completion, (void *)c);
+
+ if (kr == kIOUSBPipeStalled || kr == kIOUSBTransactionTimeout || kr == kIOUSBDataToggleErr)
+ {
+ // this code may be removed later as we are now using ReadPipeAsyncTO which is not
+ // supposed to return them (it calls the completion callback instead)
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: stalled -- clearing stall and re-priming\n"));
+ (*c->interface)->ClearPipeStall (c->interface, c->in_pipe_ref);
+ kr = (*c->interface)->ReadPipeAsyncTO (c->interface, c->in_pipe_ref,
+ c->read_buffer, c->last_read_ahead_size, 5000, 5000, (IOAsyncCallback1)&read_completion, (void *)c);
+ }
+ if (kr == kIOReturnSuccess)
+ {
+ c->read_pending = 1;
+ return 1;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: prime_read(%p): ReadPipeAsync returned error 0x%08x\n", c, kr));
+ }
+
+ change_refcount(c, -1);
+ return 0;
+}
+
+static int
+accepts_device(unsigned short vendor, unsigned short product, unsigned short *flags)
+{
+ int i;
+ for (i=0; i < (int)(sizeof(acceptedDevices) / sizeof(acceptedDevices[0])); i++)
+ {
+ if (vendor == acceptedDevices[i].vendorID)
+ {
+ if (acceptedDevices[i].flags & FLAG_REJECT)
+ return 0;
+ if (acceptedDevices[i].productID == 0xffff || product == acceptedDevices[i].productID)
+ {
+ if (flags)
+ *flags = acceptedDevices[i].flags;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/***************************************************************************/
+/* */
+/* ENTRY POINTS CALLED BY LIBPISOCK */
+/* */
+/***************************************************************************/
+static int
+u_flush(pi_socket_t *ps, int flags)
+{
+ usb_connection_t *c = ((pi_usb_data_t *)ps->device->data)->ref;
+ if (change_refcount(c, +1) <= 0)
+ return PI_ERR_SOCK_DISCONNECTED;
+ if (!c->opened)
+ {
+ change_refcount(c, -1);
+ return PI_ERR_SOCK_DISCONNECTED;
+ }
+ if (flags & PI_FLUSH_INPUT)
+ {
+ pthread_mutex_lock(&c->read_queue_mutex);
+ c->read_queue_used = 0;
+ pthread_mutex_unlock(&c->read_queue_mutex);
+ }
+ change_refcount(c, -1);
+ return 0;
+}
+
+static int
+u_open(struct pi_socket *ps, struct pi_sockaddr *addr, size_t addrlen)
+{
+ pthread_mutex_lock(&usb_thread_ready_mutex);
+ if (usb_thread == 0)
+ {
+ /* thread doesn't exist yet: create it and wait for
+ * the init phase to be either successful or failed
+ */
+ pthread_create(&usb_thread, NULL, usb_thread_run, NULL);
+ pthread_cond_wait(&usb_thread_ready_cond, &usb_thread_ready_mutex);
+ pthread_mutex_unlock(&usb_thread_ready_mutex);
+ if (usb_thread != 0)
+ return 1;
+
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ }
+ pthread_mutex_unlock(&usb_thread_ready_mutex);
+ return 1;
+}
+
+static int
+u_close(struct pi_socket *ps)
+{
+ usb_connection_t *c = ((pi_usb_data_t *)ps->device->data)->ref;
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_close(ps=%p c=%p\n",ps,c));
+ if (c && change_refcount(c, 1) > 0)
+ {
+ // @@@ TODO: for KLSI, we should set total_bytes_read to 0 so that next time we receive data,
+ // @@@ a new connection is declared `live'
+ //if (c->vendorID == VENDOR_PALMONE && c->productID == PRODUCT_PALMCONNECT_USB)
+ // control_request(c->device, 0x40, KLSI_SET_HANDSHAKE_LINES, KLSI_SETHS_RTS, 0, NULL, 0);
+
+ c->opened = 0; /* set opened to 0 so that other threads don't try to acquire this connection, as it is on the way out */
+ c->total_bytes_read = 0;
+ c->total_bytes_written = 0;
+ c->ps = NULL;
+ change_refcount(c, -2); /* decrement current refcount + disconnect */
+ }
+ return close(ps->sd);
+}
+
+static int
+u_wait_for_device(struct pi_socket *ps, int *timeout)
+{
+ usb_connection_t *c = connection_for_socket(ps);
+ struct timespec to, to_expiration;
+
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_wait_for_device(ps=%p c=%p, timeout=%d)\n",ps,c,timeout ? *timeout : 0));
+
+ if (timeout && *timeout)
+ {
+ pi_timeout_to_timespec(*timeout, &to_expiration);
+ to.tv_sec = *timeout / 1000;
+ to.tv_nsec = (*timeout % 1000) * 1000 * 1000;
+ }
+
+ if (c == NULL)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_wait_for_device -> waiting for a connection to come up\n"));
+ pthread_mutex_lock(&usb_connections_mutex);
+ if (timeout && *timeout)
+ {
+ if (pthread_cond_timedwait_relative_np(&usb_connection_added_cond, &usb_connections_mutex, &to) == ETIMEDOUT)
+// if (pthread_cond_timedwait(&usb_connection_added_cond, &usb_connections_mutex, &when) == ETIMEDOUT)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_wait_for_device -> connection wait timed out\n"));
+ pthread_mutex_unlock(&usb_connections_mutex);
+ return PI_ERR_SOCK_TIMEOUT;
+ }
+ }
+ else
+ pthread_cond_wait(&usb_connection_added_cond, &usb_connections_mutex);
+ pthread_mutex_unlock(&usb_connections_mutex);
+
+ c = connection_for_socket(ps);
+
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_wait_for_device -> end of wait, c=%p\n",c));
+ if (c && c->vendorID==VENDOR_PALMONE && c->productID==PRODUCT_PALMCONNECT_USB)
+ {
+ /* when working with a PalmConnect USB, make sure we use the right speed
+ * then let the adapter send us data
+ */
+ klsi_set_portspeed(c->device, ((pi_usb_data_t *)ps->device->data)->rate);
+ }
+
+ if (timeout && *timeout)
+ {
+ /* if there was a timeout, compute the remaining timeout time */
+ *timeout = pi_timespec_to_timeout(&to_expiration);
+ }
+ }
+ return (c != NULL);
+}
+
+static int
+u_poll(struct pi_socket *ps, int timeout)
+{
+ usb_connection_t *c = connection_for_socket(ps);
+ if (c == NULL)
+ return PI_ERR_SOCK_DISCONNECTED;
+
+ struct timespec to;
+
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_poll(ps=%p c=%p, timeout=%d)\n",ps,c,timeout));
+
+ if (timeout)
+ {
+ to.tv_sec = timeout / 1000;
+ to.tv_nsec = (timeout % 1000) * 1000 * 1000;
+ }
+
+ pthread_mutex_lock(&c->read_queue_mutex);
+ int available = c->read_queue_used;
+ if (!available)
+ {
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_poll -> waiting data to be available for c=%p\n",c));
+ if (timeout)
+ {
+ if (pthread_cond_timedwait_relative_np(&c->read_queue_data_avail_cond, &c->read_queue_mutex, &to) == ETIMEDOUT)
+ {
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_poll -> data wait timed out\n"));
+ available = PI_ERR_SOCK_TIMEOUT;
+ }
+ else
+ available = c->read_queue_used;
+ }
+ else
+ {
+ /* wait forever for some data to arrive */
+ pthread_cond_wait(&c->read_queue_data_avail_cond, &c->read_queue_mutex);
+ available = c->read_queue_used;
+ }
+ }
+ pthread_mutex_unlock(&c->read_queue_mutex);
+ change_refcount(c, -1);
+
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_poll -> end, c=%p, result=%d\n",c,available));
+
+ return available;
+}
+
+static ssize_t
+u_write(struct pi_socket *ps, const unsigned char *buf, size_t len, int flags)
+{
+ IOReturn kr;
+ size_t transferred_bytes = 0,
+ data_size;
+ usb_connection_t *c = ((pi_usb_data_t *)ps->device->data)->ref;
+ if (change_refcount(c,+1)<=0 || !c->opened)
+ {
+ /* make sure we report broken connections */
+ if (ps->state == PI_SOCK_CONN_ACCEPT || ps->state == PI_SOCK_CONN_INIT)
+ ps->state = PI_SOCK_CONN_BREAK;
+ change_refcount(c, -1);
+ return PI_ERR_SOCK_DISCONNECTED;
+ }
+
+ ULOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_write(ps=%p, c=%p, len=%d, flags=%d)\n",ps,c,(int)len,flags));
+
+ if (c->vendorID == VENDOR_PALMONE && c->productID == PRODUCT_PALMCONNECT_USB)
+ {
+ /* format packets for the PalmConnect USB adapter */
+ unsigned char *packet = malloc(c->out_pipe_bulk_size);
+ if (packet == NULL)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+
+ while (len > 0)
+ {
+ data_size = len;
+ if (data_size > (size_t)(c->out_pipe_bulk_size - 2))
+ data_size = (size_t)(c->out_pipe_bulk_size - 2);
+ packet[0] = data_size;
+ packet[1] = data_size >> 8;
+ memcpy(&packet[2], &buf[transferred_bytes], data_size);
+
+ kr = (*c->interface)->WritePipeTO(c->interface, c->out_pipe_ref, packet, c->out_pipe_bulk_size, 5000, 5000);
+ if (kr != kIOReturnSuccess) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: darwin_usb_write(): WritePipe returned kr=0x%08lx\n", kr));
+ break;
+ }
+
+ c->total_bytes_written += (unsigned long)data_size;
+ transferred_bytes += data_size;
+ len -= data_size;
+ }
+ free(packet);
+ }
+ else
+ {
+ kr = (*c->interface)->WritePipeTO(c->interface, c->out_pipe_ref, (void *)buf, len, 5000, 5000);
+ if (kr != kIOReturnSuccess)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "darwinusb: darwin_usb_write(): WritePipe returned kr=0x%08lx\n", kr));
+ }
+ else
+ {
+ c->total_bytes_written += (unsigned long)len;
+ transferred_bytes = len;
+ }
+ }
+
+ if (change_refcount(c, -1) <= 0)
+ return PI_ERR_SOCK_DISCONNECTED;
+
+ return transferred_bytes;
+}
+
+static ssize_t
+u_read(struct pi_socket *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ int timeout = ((struct pi_usb_data *)ps->device->data)->timeout;
+ int timed_out = 0;
+ usb_connection_t *c = ((pi_usb_data_t *)ps->device->data)->ref;
+
+ if (change_refcount(c,+1)<=0 || !c->opened)
+ {
+ /* make sure we report broken connections */
+ if (ps->state == PI_SOCK_CONN_ACCEPT || ps->state == PI_SOCK_CONN_INIT)
+ ps->state = PI_SOCK_CONN_BREAK;
+ if (c != NULL)
+ change_refcount(c, -1);
+ return PI_ERR_SOCK_DISCONNECTED;
+ }
+
+ if (pi_buffer_expect (buf, len) == NULL)
+ {
+ errno = ENOMEM;
+ change_refcount(c, -1);
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+#ifdef DEBUG_USB
+ struct timeval startTime, endTime;
+ gettimeofday(&startTime, NULL);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_read(ps=%p, c=%p, len=%d, timeout=%d, flags=%d)\n", ps, c, (int)len, timeout, flags));
+#endif
+
+ pthread_mutex_lock(&c->read_queue_mutex);
+
+ if (flags == PI_MSG_PEEK && len > 256)
+ len = 256;
+
+ if (c->read_queue_used < len)
+ {
+ struct timeval now;
+ struct timespec when;
+ gettimeofday(&now, NULL);
+ when.tv_sec = now.tv_sec + timeout / 1000;
+ when.tv_nsec = now.tv_usec + (timeout % 1000) * 1000 * 1000;
+ if (when.tv_nsec >= 1000000000)
+ {
+ when.tv_nsec -= 1000000000;
+ when.tv_sec++;
+ }
+ do
+ {
+ /* next prime_read() will use a bigger read request */
+ c->read_ahead_size = len - c->read_queue_used - c->last_read_ahead_size;
+ if (timeout)
+ {
+ if (pthread_cond_timedwait(&c->read_queue_data_avail_cond, &c->read_queue_mutex, &when) == ETIMEDOUT)
+ {
+ timed_out = 1;
+ break;
+ }
+ }
+ else
+ pthread_cond_wait(&c->read_queue_data_avail_cond, &c->read_queue_mutex);
+ }
+ while (c->opened && (c->read_queue_used < len || (flags == PI_MSG_PEEK && c->read_queue_used >= 256)));
+
+ c->read_ahead_size = 0;
+ }
+
+ if (!c->opened)
+ {
+ /* make sure we report broken connections */
+ if (ps->state == PI_SOCK_CONN_ACCEPT || ps->state == PI_SOCK_CONN_INIT)
+ ps->state = PI_SOCK_CONN_BREAK;
+ len = PI_ERR_SOCK_DISCONNECTED;
+ }
+ else
+ {
+ if (c->read_queue_used < len)
+ len = c->read_queue_used;
+
+ if (len)
+ {
+ pi_buffer_append (buf, c->read_queue, len);
+
+ if (flags != PI_MSG_PEEK)
+ {
+ c->read_queue_used -= len;
+ if (c->read_queue_used > 0)
+ memmove(c->read_queue, c->read_queue + len, c->read_queue_used);
+ if ((c->read_queue_size - c->read_queue_used) > (16L * 65535L))
+ {
+ /* if we have more than 1M free in the read queue, we'd better
+ * shrink the buffer
+ */
+ c->read_queue_size = ((c->read_queue_used + 0xfffe) & ~0xffff) - 1;
+ c->read_queue = (char *) realloc (c->read_queue, c->read_queue_size);
+ }
+ }
+ }
+ else if (timed_out)
+ len = PI_ERR_SOCK_TIMEOUT;
+ }
+
+#ifdef DEBUG_USB
+ double a,b;
+ gettimeofday(&endTime, NULL);
+ a = (double)startTime.tv_sec + (double)startTime.tv_usec / (double)1000000;
+ b = (double)endTime.tv_sec + (double)endTime.tv_usec / (double)1000000;
+ if (len >= 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: -> u_read complete (bytes_read=%d, remaining bytes in queue=%d) in %.06fs\n",
+ len, c->read_queue_used,b-a));
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: -> u_read end with error (err=%d) in %.06fs\n",
+ len,b-a));
+ }
+#endif
+
+ pthread_mutex_unlock(&c->read_queue_mutex);
+ if (change_refcount(c, -1) <= 0)
+ len = PI_ERR_SOCK_DISCONNECTED;
+ return len;
+}
+
+static int
+u_changebaud(pi_socket_t *ps)
+{
+ /* Change the baud rate. This is only useful for serial-to-USB adapters,
+ * as these adapters need to know which rate we use to talk to the device.
+ * We currently only support the PalmConnect USB adapter.
+ */
+ pi_usb_data_t *data = (pi_usb_data_t *)ps->device->data;
+ usb_connection_t *c = data->ref;
+ if (c == NULL)
+ return PI_ERR_SOCK_DISCONNECTED;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "darwinusb: u_changebaud(ps=%p, c=%p, rate=%d)\n", ps, c, data->rate));
+
+ if (c->vendorID == VENDOR_PALMONE && c->productID == PRODUCT_PALMCONNECT_USB)
+ return klsi_set_portspeed(c->device, data->rate);
+
+ return 0;
+}
+
+void
+pi_usb_impl_init (struct pi_usb_impl *impl)
+{
+ impl->open = u_open;
+ impl->close = u_close;
+ impl->write = u_write;
+ impl->read = u_read;
+ impl->flush = u_flush;
+ impl->poll = u_poll;
+ impl->wait_for_device = u_wait_for_device;
+ impl->changebaud = u_changebaud;
+ impl->control_request = NULL; /* that is, until we factor out common code */
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/datebook.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/datebook.c
new file mode 100644
index 00000000..47b9063d
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/datebook.c
@@ -0,0 +1,485 @@
+/*
+ * $Id: datebook.c,v 1.36 2006/11/22 22:52:25 adridg Exp $
+ *
+ * datebook.c: Translate Pilot datebook data formats
+ *
+ * Copyright (c) 1996, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-datebook.h"
+
+#define alarmFlag 64
+#define repeatFlag 32
+#define noteFlag 16
+#define exceptFlag 8
+#define descFlag 4
+
+char *DatebookAlarmTypeNames[] = { "Minutes", "Hours", "Days", NULL };
+
+char *DatebookRepeatTypeNames[] =
+ { "None", "Daily", "Weekly", "MonthlyByDay", "MonthlyByDate", "Yearly",
+ NULL
+};
+
+/* dom1stSun = REM Sun 1
+ dom1stMon = Rem Mon 1
+ dom2ndSun = REM Sun 8
+ domLastSun = REM Sun 1 -7 */
+
+/***********************************************************************
+ *
+ * Function: free_Appointment
+ *
+ * Summary: Frees members of the appointment structure
+ *
+ * Parameters: Appointment_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Appointment(Appointment_t *a)
+{
+ if (a->exception != NULL) {
+ free(a->exception);
+ a->exception = NULL;
+ }
+
+ if (a->description != NULL) {
+ free(a->description);
+ a->description = NULL;
+ }
+
+ if (a->note != NULL) {
+ free(a->note);
+ a->note = NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_Appointment
+ *
+ * Summary: Fill in the appointment structure based on the raw
+ * record data
+ *
+ * Parameters: Appointment_t*, pi_buffer_t * of buffer, datebook type
+ *
+ * Returns: -1 on fail, 0 on success
+ *
+ ***********************************************************************/
+int
+unpack_Appointment(Appointment_t *a, const pi_buffer_t *buf, datebookType type)
+{
+ int iflags,
+ j,
+ destlen;
+ unsigned char *p2;
+ unsigned long d;
+
+
+ /* Note: There are possible timezone conversion problems related to
+ the use of the begin, end, repeatEnd, and exception[] members of
+ a struct Appointment. As they are kept in local (wall) time in
+ struct tm's, the timezone of the Pilot is irrelevant, _assuming_
+ that any UNIX program keeping time in time_t's converts them to
+ the correct local time. If the Pilot is in a different timezone
+ than the UNIX box, it may not be simple to deduce that correct
+ (desired) timezone.
+
+ The easiest solution is to keep apointments in struct tm's, and
+ out of time_t's. Of course, this might not actually be a help if
+ you are constantly darting across timezones and trying to keep
+ appointments.
+ -- KJA */
+
+ destlen = 8;
+
+ if (type != datebook_v1)
+ return -1;
+
+ if (buf == NULL || buf->data == NULL || buf->used < destlen)
+ return -1;
+
+ a->begin.tm_hour = get_byte(buf->data);
+ a->begin.tm_min = get_byte(buf->data + 1);
+ a->begin.tm_sec = 0;
+ d = (unsigned short int) get_short(buf->data + 4);
+ a->begin.tm_year = (d >> 9) + 4;
+ a->begin.tm_mon = ((d >> 5) & 15) - 1;
+ a->begin.tm_mday = d & 31;
+ a->begin.tm_isdst = -1;
+ a->end = a->begin;
+
+ a->end.tm_hour = get_byte(buf->data + 2);
+ a->end.tm_min = get_byte(buf->data + 3);
+
+ if (get_short(buf->data) == 0xffff) {
+ a->event = 1;
+ a->begin.tm_hour = 0;
+ a->begin.tm_min = 0;
+ a->end.tm_hour = 0;
+ a->end.tm_min = 0;
+ } else {
+ a->event = 0;
+ }
+
+ mktime(&a->begin);
+ mktime(&a->end);
+
+ iflags = get_byte(buf->data + 6);
+
+ /* buf->data+7 is gapfill */
+
+ p2 = (unsigned char *) buf->data + 8;
+
+ if (iflags & alarmFlag) {
+ a->alarm = 1;
+ a->advance = get_byte(p2);
+ p2 += 1;
+ a->advanceUnits = get_byte(p2);
+ p2 += 1;
+
+ } else {
+ a->alarm = 0;
+ a->advance = 0;
+ a->advanceUnits = 0;
+ }
+
+ if (iflags & repeatFlag) {
+ int i,
+ on;
+
+ a->repeatType = (enum repeatTypes) get_byte(p2);
+ p2 += 2;
+ d = (unsigned short int) get_short(p2);
+ p2 += 2;
+ if (d == 0xffff)
+ a->repeatForever = 1; /* repeatEnd is invalid */
+ else {
+ a->repeatEnd.tm_year = (d >> 9) + 4;
+ a->repeatEnd.tm_mon = ((d >> 5) & 15) - 1;
+ a->repeatEnd.tm_mday = d & 31;
+ a->repeatEnd.tm_min = 0;
+ a->repeatEnd.tm_hour = 0;
+ a->repeatEnd.tm_sec = 0;
+ a->repeatEnd.tm_isdst = -1;
+ mktime(&a->repeatEnd);
+ a->repeatForever = 0;
+ }
+ a->repeatFrequency = get_byte(p2);
+ p2++;
+ on = get_byte(p2);
+ p2++;
+ a->repeatDay = (enum DayOfMonthType) 0;
+ for (i = 0; i < 7; i++)
+ a->repeatDays[i] = 0;
+
+ if (a->repeatType == repeatMonthlyByDay)
+ a->repeatDay = (enum DayOfMonthType) on;
+ else if (a->repeatType == repeatWeekly)
+ for (i = 0; i < 7; i++)
+ a->repeatDays[i] = !!(on & (1 << i));
+ a->repeatWeekstart = get_byte(p2);
+ p2++;
+ p2++;
+ } else {
+ int i;
+
+ a->repeatType = (enum repeatTypes) 0;
+ a->repeatForever = 1; /* repeatEnd is invalid */
+ a->repeatFrequency = 0;
+ a->repeatDay = (enum DayOfMonthType) 0;
+ for (i = 0; i < 7; i++)
+ a->repeatDays[i] = 0;
+ a->repeatWeekstart = 0;
+ }
+
+ if (iflags & exceptFlag) {
+ a->exceptions = get_short(p2);
+ p2 += 2;
+ a->exception = malloc(sizeof(struct tm) * a->exceptions);
+
+ for (j = 0; j < a->exceptions; j++, p2 += 2) {
+ d = (unsigned short int) get_short(p2);
+ a->exception[j].tm_year = (d >> 9) + 4;
+ a->exception[j].tm_mon = ((d >> 5) & 15) - 1;
+ a->exception[j].tm_mday = d & 31;
+ a->exception[j].tm_hour = 0;
+ a->exception[j].tm_min = 0;
+ a->exception[j].tm_sec = 0;
+ a->exception[j].tm_isdst = -1;
+ mktime(&a->exception[j]);
+ }
+
+ } else {
+ a->exceptions = 0;
+ a->exception = 0;
+ }
+
+ if (iflags & descFlag) {
+ a->description = strdup((char *)p2);
+ p2 += strlen((char *)p2) + 1;
+ } else
+ a->description = 0;
+
+ if (iflags & noteFlag) {
+ a->note = strdup((char *)p2);
+ p2 += strlen((char *)p2) + 1;
+ } else {
+ a->note = 0;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_Appointment
+ *
+ * Summary: Fill in the raw appointment record data based on the
+ * appointment structure.
+ *
+ * Parameters: Appointment_t*, pi_buffer_t*, datebook database version
+ * from the datebookType enumeration -- only v1 is supported
+ * for now.
+ *
+ * Returns: -1 on error (bad arguments, mostyle) or 0 on success.
+ * The buffer is sized to accomodate the required data.
+ *
+ ***********************************************************************/
+int
+pack_Appointment(const Appointment_t *a, pi_buffer_t *buf, datebookType type)
+{
+ int iflags,
+ destlen = 8;
+ char *pos;
+
+ if (a == NULL || buf == NULL)
+ return -1;
+
+ if (type != datebook_v1)
+ return -1;
+
+ if (a->alarm)
+ destlen += 2;
+ if (a->repeatType)
+ destlen += 8;
+ if (a->exceptions)
+ destlen += 2 + 2 * a->exceptions;
+ if (a->note)
+ destlen += strlen(a->note) + 1;
+ if (a->description)
+ destlen += strlen(a->description) + 1;
+
+ pi_buffer_expect (buf, destlen);
+ buf->used = destlen;
+
+ set_byte(buf->data, a->begin.tm_hour);
+ set_byte(buf->data + 1, a->begin.tm_min);
+ set_byte(buf->data + 2, a->end.tm_hour);
+ set_byte(buf->data + 3, a->end.tm_min);
+ set_short(buf->data + 4,
+ ((a->
+ begin.tm_year - 4) << 9) | ((a->begin.tm_mon +
+ 1) << 5) | a->begin.
+ tm_mday);
+
+ if (a->event) {
+ set_long(buf->data, 0xffffffff);
+ }
+
+ iflags = 0;
+
+ pos = (char *) buf->data + 8;
+
+ if (a->alarm) {
+ iflags |= alarmFlag;
+
+ set_byte(pos, a->advance);
+ set_byte(pos + 1, a->advanceUnits);
+ pos += 2;
+ }
+
+ if (a->repeatType) {
+ int i,
+ on;
+
+ iflags |= repeatFlag;
+
+ if (a->repeatType == repeatMonthlyByDay)
+ on = a->repeatDay;
+ else if (a->repeatType == repeatWeekly) {
+ on = 0;
+ for (i = 0; i < 7; i++)
+ if (a->repeatDays[i])
+ on |= 1 << i;
+ } else
+ on = 0;
+
+ set_byte(pos, a->repeatType);
+ set_byte(pos + 1, 0);
+ pos += 2;
+
+ if (a->repeatForever)
+ set_short(pos, 0xffff);
+ else
+ set_short(pos,
+ ((a->
+ repeatEnd.tm_year -
+ 4) << 9) | ((a->repeatEnd.tm_mon +
+ 1) << 5) | a->repeatEnd.
+ tm_mday);
+
+ pos += 2;
+
+ set_byte(pos, a->repeatFrequency);
+ pos++;
+ set_byte(pos, on);
+ pos++;
+ set_byte(pos, a->repeatWeekstart);
+ pos++;
+ set_byte(pos, 0);
+ pos++;
+ }
+
+ if (a->exceptions) {
+ int i;
+
+ iflags |= exceptFlag;
+
+ set_short(pos, a->exceptions);
+ pos += 2;
+
+ for (i = 0; i < a->exceptions; i++, pos += 2)
+ set_short(pos,
+ ((a->
+ exception[i].tm_year -
+ 4) << 9) | ((a->exception[i].tm_mon +
+ 1) << 5) | a->
+ exception[i].tm_mday);
+ }
+
+ if (a->description != NULL) {
+ iflags |= descFlag;
+
+ strcpy(pos, a->description);
+ pos += strlen(pos) + 1;
+ }
+
+ if (a->note != NULL) {
+ iflags |= noteFlag;
+
+ strcpy(pos, a->note);
+ pos += strlen(pos) + 1;
+ }
+
+ set_byte(buf->data + 6, iflags);
+ set_byte(buf->data + 7, 0); /* gapfill */
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_AppointmentAppInfo
+ *
+ * Summary: Fill in the app info structure based on the raw app
+ * info data
+ *
+ * Parameters: AppointmentAppInfo_t*, char* to record, record length
+ *
+ * Returns: The necessary length of the buffer if record is NULL,
+ * or 0 on error, the length of the data used from the
+ * buffer otherwise
+ *
+ ***********************************************************************/
+int
+unpack_AppointmentAppInfo(AppointmentAppInfo_t *ai,
+ const unsigned char *record, size_t len)
+{
+ int i;
+
+ i = unpack_CategoryAppInfo(&ai->category, record, len);
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 2)
+ return 0;
+ ai->startOfWeek = get_byte(record);
+ return i + 2;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_AppointmentAppInfo
+ *
+ * Summary: Fill in the raw app info record data based on the app
+ * info structure
+ *
+ * Parameters: AppointmentAppInfo*, char* to buffer, buffer length
+ *
+ * Returns: The length of the buffer required if record is NULL,
+ * or 0 on error, the length of the data used from the
+ * buffer otherwise
+ *
+ ***********************************************************************/
+int
+pack_AppointmentAppInfo(const AppointmentAppInfo_t *ai,
+ unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&ai->category, record, len);
+ if (!record)
+ return i + 2;
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+ if (len < 2)
+ return 0;
+ set_short(record, 0);
+ set_byte(record, ai->startOfWeek);
+ record += 2;
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/debug.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/debug.c
new file mode 100644
index 00000000..8f27c694
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/debug.c
@@ -0,0 +1,242 @@
+/*
+ * $Id: debug.c,v 1.16 2006/10/12 14:21:22 desrod Exp $
+ *
+ * debug.c: Pilot-Link debug configuration and debug logging
+ *
+ * Copyright (c) 1996, Anonymous
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "pi-debug.h"
+#include "pi-threadsafe.h"
+
+static int debug_types = PI_DBG_NONE;
+static int debug_level = PI_DBG_LVL_NONE;
+static FILE *debug_file = NULL;
+static PI_MUTEX_DEFINE(logfile_mutex);
+
+/***********************************************************************
+ *
+ * Function: pi_debug_get_types
+ *
+ * Summary: fetches the current debug types configuration
+ *
+ * Parameters: void
+ *
+ * Returns: debug_types
+ *
+ ***********************************************************************/
+int
+pi_debug_get_types (void)
+{
+ return debug_types;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_debug_set_types
+ *
+ * Summary: sets the debug_types configuration
+ *
+ * Parameters: types
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+pi_debug_set_types (int types)
+{
+ debug_types = types;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_debug_get_types
+ *
+ * Summary: fetches the current debug level configuration
+ *
+ * Parameters: void
+ *
+ * Returns: debug_level
+ *
+ ***********************************************************************/
+int
+pi_debug_get_level (void)
+{
+ return debug_level;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_debug_set_level
+ *
+ * Summary: sets the debug_level configuration
+ *
+ * Parameters: level
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+pi_debug_set_level (int level)
+{
+ pi_mutex_lock(&logfile_mutex);
+ debug_level = level;
+ pi_mutex_unlock(&logfile_mutex);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_debug_set_file
+ *
+ * Summary: sets the debug log file configuration
+ *
+ * Parameters: char* to logfile name
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+pi_debug_set_file (const char *path)
+{
+ pi_mutex_lock(&logfile_mutex);
+
+ if (debug_file != NULL && debug_file != stderr)
+ fclose (debug_file);
+
+ debug_file = fopen (path, "a");
+ if (debug_file == NULL)
+ debug_file = stderr;
+
+ pi_mutex_unlock(&logfile_mutex);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_log
+ *
+ * Summary: logs a debug message
+ *
+ * Parameters: type, level, format, ...
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+pi_log (int type, int level, const char *format, ...)
+{
+ va_list ap;
+
+ if (!(debug_types & type) && type != PI_DBG_ALL)
+ return;
+
+ if (debug_level < level)
+ return;
+
+ pi_mutex_lock(&logfile_mutex);
+
+ if (debug_file == NULL)
+ debug_file = stderr;
+
+#if HAVE_PTHREAD
+ fprintf(debug_file, "[thread 0x%08lx] ", pi_thread_id());
+#endif
+ va_start(ap, format);
+ vfprintf(debug_file, format, ap);
+ va_end(ap);
+
+ fflush(debug_file);
+
+ pi_mutex_unlock(&logfile_mutex);
+}
+
+void
+pi_dumpline(const char *buf, size_t len, unsigned int addr)
+{
+ unsigned int i;
+ int offset;
+ char line[256];
+
+ offset = sprintf(line, " %.4x ", addr);
+
+ for (i = 0; i < 16; i++) {
+ if (i < len)
+ offset += sprintf(line+offset, "%.2x ",
+ 0xff & (unsigned int) buf[i]);
+ else {
+ strcpy(line+offset, " ");
+ offset += 3;
+ }
+ }
+
+ strcpy(line+offset, " ");
+ offset += 2;
+
+ for (i = 0; i < len; i++) {
+ if (buf[i] == '%') {
+ /* since we're going through pi_log, we need to
+ * properly escape % characters
+ */
+ line[offset++] = '%';
+ line[offset++] = '%';
+ } else if (isprint(buf[i]) && buf[i] >= 32 && buf[i] <= 126)
+ line[offset++] = buf[i];
+ else
+ line[offset++] = '.';
+ }
+
+ strcpy(line+offset,"\n");
+ LOG((PI_DBG_ALL, PI_DBG_LVL_NONE, line));
+}
+
+void
+dumpline(const char *buf, size_t len, unsigned int addr)
+{
+ /* this function will be removed in 0.13. Use pi_dumpline() instead. */
+ pi_dumpline(buf, len, addr);
+}
+
+void
+pi_dumpdata(const char *buf, size_t len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i += 16)
+ pi_dumpline(buf + i, ((len - i) > 16) ? 16 : len - i, i);
+}
+
+void
+dumpdata(const char *buf, size_t len)
+{
+ /* this function will be removed in 0.13. Use pi_dumpdata() instead */
+ pi_dumpdata(buf, len);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/dlp.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/dlp.c
new file mode 100644
index 00000000..25146052
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/dlp.c
@@ -0,0 +1,4911 @@
+/*
+ * $Id: dlp.c,v 1.139 2006/11/07 20:42:36 adridg Exp $
+ *
+ * dlp.c: Palm DLP protocol
+ *
+ * Copyright (c) 1996, 1997, Kenneth Albanowski
+ * Copyright (c) 1998-2003, David Desrosiers, JP Rosevear and others
+ * Copyright (c) 2004, 2005, 2006, Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef HAVE_ERRNO_H
+ #include <errno.h>
+ #ifndef ENOMSG
+ #define ENOMSG EINVAL /* For systems that don't provide ENOMSG. Use EINVAL instead. */
+ #endif
+#endif
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-dlp.h"
+#include "pi-syspkt.h"
+
+#define DLP_REQUEST_DATA(req, arg, offset) &req->argv[arg]->data[offset]
+#define DLP_RESPONSE_DATA(res, arg, offset) &res->argv[arg]->data[offset]
+
+#define get_date(ptr) (dlp_ptohdate((ptr)))
+#define set_date(ptr,val) (dlp_htopdate((val),(ptr)))
+
+#define RequireDLPVersion(sd,major,minor) \
+ if (pi_version(sd) < (((major)<<8) | (minor))) \
+ return dlpErrNotSupp
+
+/* This constant is being used during dlp_ReadResourceByType, dlp_ReadResourceByIndex, dlp_ReadRecordById, and dlp_ReadRecordByIndex
+ * Scott Gruby discovered that on some devices, reading a record that has the maximum record size can lock up the device.
+ * We'll read large records in two steps, getting the small amount of remaining data the second time.
+ * Scott's tests showed that the value above (100 bytes) was enough of a safeguard to prevent device lockup
+ */
+#define RECORD_READ_SAFEGUARD_SIZE 100
+
+/* Define prototypes */
+#ifdef PI_DEBUG
+static void record_dump (unsigned long recID, unsigned int recIndex,
+ int flags, int catID, const char *data, int data_len);
+#endif
+
+char *dlp_errorlist[] = {
+ "No error",
+ "General System error",
+ "Illegal Function",
+ "Out of memory",
+ "Invalid parameter",
+ "Not found",
+ "None Open",
+ "Already Open",
+ "Too many Open",
+ "Already Exists",
+ "Cannot Open",
+ "Record deleted",
+ "Record busy",
+ "Operation not supported",
+ "-Unused-",
+ "Read only",
+ "Not enough space",
+ "Limit exceeded",
+ "Sync cancelled",
+ "Bad arg wrapper",
+ "Argument missing",
+ "Bad argument size"
+};
+
+/* Look at "Error codes" in VFSMgr.h in the Palm SDK for their
+ implementation */
+char * vfs_errorlist[] = {
+ "No error",
+ "Buffer Overflow",
+ "Generic file error",
+ "File reference is invalid",
+ "File still open",
+ "Permission denied",
+ "File or folder already exists",
+ "FileEOF",
+ "File not found",
+ "volumereference is invalid",
+ "Volume still mounted",
+ "No filesystem",
+ "Bad data",
+ "Non-empty directory",
+ "Invalid path or filename",
+ "Volume full - not enough space",
+ "Unimplemented",
+ "Not a directory",
+ "Is a directory",
+ "Directory not found",
+ "Name truncated"
+};
+
+/* Look at "Error codes" in ExpansionMgr.h in the Palm SDK for their
+ implementation */
+char * exp_errorlist[] = {
+ "No error",
+ "Unsupported Operation",
+ "Not enough Power",
+ "Card not present",
+ "Invalid slotreference number",
+ "Slot deallocated",
+ "Card no sector read/write",
+ "Card read only",
+ "Card bad sector",
+ "Protected sector",
+ "Not open (slot driver)",
+ "still open (slot driver)",
+ "Unimplemented",
+ "Enumeration empty",
+ "Incompatible API version"
+};
+
+#ifdef DLP_TRACE
+static int dlp_trace = 0;
+#endif
+static int dlp_version_major = PI_DLP_VERSION_MAJOR;
+static int dlp_version_minor = PI_DLP_VERSION_MINOR;
+
+#ifdef PI_DEBUG
+ #define Trace(name) \
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, "DLP sd=%d %s\n", sd, #name));
+ #ifdef __GNUC__
+ #define TraceX(name,format,...) \
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, "DLP sd=%d %s " #format "\n", sd, #name, __VA_ARGS__));
+ #else
+ #define TraceX(name,format,...) \
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, "DLP sd=%d %s\n", sd, #name));
+ #endif
+#else
+ #define Trace(name)
+ #define TraceX(name,format,...)
+#endif
+
+#ifdef PI_DEBUG
+static void record_dump (unsigned long recID, unsigned int recIndex, int flags,
+ int catID, const char *data, int data_len)
+{
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " ID: 0x%8.8lX, Index: %u, Category: %d\n"
+ " Flags:%s%s%s%s%s%s (0x%2.2X), and %d bytes:\n",
+ (unsigned long) recID,
+ recIndex,
+ catID,
+ (flags & dlpRecAttrDeleted) ? " Deleted" : "",
+ (flags & dlpRecAttrDirty) ? " Dirty" : "",
+ (flags & dlpRecAttrBusy) ? " Busy" : "",
+ (flags & dlpRecAttrSecret) ? " Secret" : "",
+ (flags & dlpRecAttrArchived) ? " Archive" : "",
+ (!flags) ? " None" : "",
+ flags, data_len));
+ pi_dumpdata(data, (size_t)data_len);
+}
+#endif
+
+void
+dlp_set_protocol_version(int major, int minor)
+{
+ dlp_version_major = major;
+ dlp_version_minor = minor;
+}
+
+/***************************************************************************
+ *
+ * Function: dlp_strerror
+ *
+ * Summary: lookup text for dlp error
+ *
+ * Parameters: error number
+ *
+ * Returns: char* to error text string
+ *
+ ***************************************************************************/
+char
+*dlp_strerror(int error)
+{
+ if (error < 0)
+ error = -error;
+
+ if ((unsigned int) error >= (sizeof(dlp_errorlist)/(sizeof(char *))))
+ return "Unknown error";
+
+ return dlp_errorlist[error];
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_arg_new
+ *
+ * Summary: create a dlpArg instance
+ *
+ * Parameters: id_, length of data
+ *
+ * Returns: dlpArg* or NULL on failure
+ *
+ ***************************************************************************/
+struct dlpArg
+*dlp_arg_new (int argID, size_t len)
+{
+ struct dlpArg *arg;
+
+ arg = (struct dlpArg *)malloc(sizeof (struct dlpArg));
+
+ if (arg != NULL) {
+ arg->id_ = argID;
+ arg->len = len;
+ arg->data = NULL;
+ if (len > 0) {
+ arg->data = (char *)malloc (len);
+ if (arg->data == NULL) {
+ free(arg);
+ arg = NULL;
+ }
+ }
+ }
+
+ return arg;
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_arg_free
+ *
+ * Summary: frees a dlpArg instance
+ *
+ * Parameters: dlpArg*
+ *
+ * Returns: void
+ *
+ ***************************************************************************/
+void
+dlp_arg_free (struct dlpArg *arg)
+{
+ if (arg != NULL) {
+ if (arg->data != NULL)
+ free (arg->data);
+ free (arg);
+ }
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_arg_len
+ *
+ * Summary: computes aggregate length of data members associated with an
+ * array of dlpArg instances
+ *
+ * Parameters: number of dlpArg instances, dlpArg**
+ *
+ * Returns: aggregate length or -1 on error
+ *
+ ***************************************************************************/
+int
+dlp_arg_len (int argc, struct dlpArg **argv)
+{
+ int i, len = 0;
+
+ for (i = 0; i < argc; i++) {
+ struct dlpArg *arg = argv[i];
+
+ /* FIXME: shapiro: should these be < or <= ??? */
+ if (arg->len < PI_DLP_ARG_TINY_LEN &&
+ (arg->id_ & (PI_DLP_ARG_FLAG_SHORT | PI_DLP_ARG_FLAG_LONG)) == 0)
+ len += 2;
+ else if (arg->len < PI_DLP_ARG_SHORT_LEN &&
+ (arg->id_ & PI_DLP_ARG_FLAG_LONG) == 0)
+ len += 4;
+ else
+ len += 6;
+
+ len += arg->len;
+ }
+
+ return len;
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_request_new
+ *
+ * Summary: creates a new dlpRequest instance
+ *
+ * Parameters: dlpFunction command, number of dlpArgs, lengths of dlpArgs
+ * data member
+ *
+ * Returns: dlpRequest* or NULL if failure
+ *
+ ***************************************************************************/
+struct dlpRequest*
+dlp_request_new (enum dlpFunctions cmd, int argc, ...)
+{
+ struct dlpRequest *req;
+ va_list ap;
+ int i,
+ j;
+
+ req = (struct dlpRequest *)malloc (sizeof (struct dlpRequest));
+
+ if (req != NULL) {
+ req->cmd = cmd;
+ req->argc = argc;
+ req->argv = NULL;
+
+ if (argc) {
+ req->argv = (struct dlpArg **) malloc (sizeof (struct dlpArg *) * argc);
+ if (req->argv == NULL) {
+ free(req);
+ return NULL;
+ }
+ }
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; i++) {
+ size_t len;
+
+ len = va_arg (ap, size_t);
+ req->argv[i] = dlp_arg_new (PI_DLP_ARG_FIRST_ID + i,
+ len);
+ if (req->argv[i] == NULL) {
+ for (j = 0; j < i; j++)
+ dlp_arg_free(req->argv[j]);
+ free(req->argv);
+ free(req);
+ req = NULL;
+ break;
+ }
+ }
+ va_end (ap);
+ }
+
+ return req;
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_request_new_with_argid
+ *
+ * Summary: creates a new dlpRequest instance with argid
+ *
+ * Parameters: dlpFunction command, number of dlpArgs, argid, lengths of
+ * dlpArgs data member
+ *
+ * Returns: dlpRequest* or NULL if failure
+ *
+ ***************************************************************************/
+struct dlpRequest*
+dlp_request_new_with_argid (enum dlpFunctions cmd, int argid, int argc, ...)
+{
+ struct dlpRequest *req;
+ va_list ap;
+ int i,
+ j;
+
+ req = (struct dlpRequest *) malloc (sizeof (struct dlpRequest));
+
+ if (req != NULL) {
+ req->cmd = cmd;
+ req->argc = argc;
+ req->argv = NULL;
+
+ if (argc) {
+ req->argv = (struct dlpArg **) malloc (sizeof (struct dlpArg *) * argc);
+ if (req->argv == NULL) {
+ free(req);
+ return NULL;
+ }
+ }
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; i++) {
+ size_t len;
+
+ len = va_arg (ap, size_t);
+ req->argv[i] = dlp_arg_new (argid + i, len);
+ if (req->argv[i] == NULL) {
+ for (j = 0; j < i; j++)
+ dlp_arg_free(req->argv[j]);
+ free(req->argv);
+ free(req);
+ req = NULL;
+ break;
+ }
+ }
+ va_end (ap);
+ }
+
+ return req;
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_response_new
+ *
+ * Summary: creates a new dlpResponse instance
+ *
+ * Parameters: dlpFunction command, number of dlpArg instances
+ *
+ * Returns: dlpResponse* or NULL if failure
+ *
+ ***************************************************************************/
+struct dlpResponse
+*dlp_response_new (enum dlpFunctions cmd, int argc)
+{
+ struct dlpResponse *res;
+
+ res = (struct dlpResponse *) malloc (sizeof (struct dlpResponse));
+
+ if (res != NULL) {
+
+ res->cmd = cmd;
+ res->err = dlpErrNoError;
+ res->argc = argc;
+ res->argv = NULL;
+
+ if (argc) {
+ res->argv = (struct dlpArg **) malloc (sizeof (struct dlpArg *) * argc);
+ if (res->argv == NULL) {
+ free(res);
+ return NULL;
+ }
+ /* zero-out argv so that in case of error during
+ response read, dlp_response_free() won't try to
+ free uninitialized ptrs */
+ memset(res->argv, 0, sizeof (struct dlpArg *) * argc);
+ }
+ }
+
+ return res;
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_response_read
+ *
+ * Summary: reads dlp response
+ *
+ * Parameters: dlpResonse**, sd
+ *
+ * Returns: first dlpArg response length or -1 on error
+ *
+ ***************************************************************************/
+ssize_t
+dlp_response_read (struct dlpResponse **res, int sd)
+{
+ struct dlpResponse *response;
+ unsigned char *buf;
+ short argid;
+ int i;
+ ssize_t bytes;
+ size_t len;
+ pi_buffer_t *dlp_buf;
+
+ dlp_buf = pi_buffer_new (DLP_BUF_SIZE);
+ if (dlp_buf == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ bytes = pi_read (sd, dlp_buf, dlp_buf->allocated); /* buffer will grow as needed */
+ if (bytes < 0) {
+ pi_buffer_free (dlp_buf);
+ return bytes;
+ }
+ if (bytes < 4) {
+ /* packet is probably incomplete */
+#ifdef DEBUG
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "dlp_response_read: response too short (%d bytes)\n",
+ bytes));
+ if (bytes)
+ pi_dumpdata(dlp_buf->data, (size_t)dlp_buf->used);
+#endif
+ return pi_set_error(sd, PI_ERR_DLP_COMMAND);
+ }
+
+ response = dlp_response_new ((enum dlpFunctions)(dlp_buf->data[0] & 0x7f), dlp_buf->data[1]);
+ *res = response;
+
+ /* note that in case an error occurs, we do not deallocate the response
+ since callers already do it under all circumstances */
+ if (response == NULL) {
+ pi_buffer_free (dlp_buf);
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ response->err = (enum dlpErrors) get_short (&dlp_buf->data[2]);
+ pi_set_palmos_error(sd, (int)response->err);
+
+ /* FIXME: add bounds checking to make sure we don't access past
+ * the end of the buffer in case the data is corrupt */
+ buf = dlp_buf->data + 4;
+ for (i = 0; i < response->argc; i++) {
+ argid = get_byte (buf) & 0x3f;
+ if (get_byte(buf) & PI_DLP_ARG_FLAG_LONG) {
+ if (pi_version(sd) < 0x0104) {
+ /* we received a response from a device indicating that
+ it would have transmitted a >64k data block but DLP
+ versions prior to 1.4 don't have this capacity. In
+ this case (as observed on a T3), there is NO length
+ stored after the argid, it goes straigt to the data
+ contents. We need to report that the data is too large
+ to be transferred.
+ */
+ pi_buffer_free (dlp_buf);
+ return pi_set_error(sd, PI_ERR_DLP_DATASIZE);
+ }
+ len = get_long (&buf[2]);
+ buf += 6;
+ } else if (get_byte(buf) & PI_DLP_ARG_FLAG_SHORT) {
+ len = get_short (&buf[2]);
+ buf += 4;
+ } else {
+ argid = get_byte(buf);
+ len = get_byte(&buf[1]);
+ buf += 2;
+ }
+
+ response->argv[i] = dlp_arg_new (argid, len);
+ if (response->argv[i] == NULL) {
+ pi_buffer_free (dlp_buf);
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+ memcpy (response->argv[i]->data, buf, len);
+ buf += len;
+ }
+
+ pi_buffer_free (dlp_buf);
+
+ return response->argc ? response->argv[0]->len : 0;
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_request_write
+ *
+ * Summary: writes dlp request
+ *
+ * Parameters: dlpRequest**, sd
+ *
+ * Returns: response length or -1 on error
+ *
+ ***************************************************************************/
+ssize_t
+dlp_request_write (struct dlpRequest *req, int sd)
+{
+ unsigned char *exec_buf, *buf;
+ int i;
+ size_t len;
+
+ len = dlp_arg_len (req->argc, req->argv) + 2;
+ exec_buf = (unsigned char *) malloc (sizeof (unsigned char) * len);
+ if (exec_buf == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte (&exec_buf[PI_DLP_OFFSET_CMD], req->cmd);
+ set_byte (&exec_buf[PI_DLP_OFFSET_ARGC], req->argc);
+
+ buf = &exec_buf[PI_DLP_OFFSET_ARGV];
+ for (i = 0; i < req->argc; i++) {
+ struct dlpArg *arg = req->argv[i];
+ short argid = arg->id_;
+
+ if (arg->len < PI_DLP_ARG_TINY_LEN &&
+ (argid & (PI_DLP_ARG_FLAG_SHORT | PI_DLP_ARG_FLAG_LONG)) == 0) {
+ set_byte(&buf[0], argid | PI_DLP_ARG_FLAG_TINY);
+ set_byte(&buf[1], arg->len);
+
+ memcpy(&buf[2], arg->data, arg->len);
+ buf += arg->len + 2;
+ } else if (arg->len < PI_DLP_ARG_SHORT_LEN &&
+ (argid & PI_DLP_ARG_FLAG_LONG) == 0) {
+ set_byte(&buf[0], argid | PI_DLP_ARG_FLAG_SHORT);
+ set_byte(&buf[1], 0);
+ set_short(&buf[2], arg->len);
+
+ memcpy (&buf[4], arg->data, arg->len);
+ buf += arg->len + 4;
+ } else {
+ set_byte (&buf[0], argid | PI_DLP_ARG_FLAG_LONG);
+ set_byte(&buf[1], 0);
+ set_long (&buf[2], arg->len);
+
+ memcpy (&buf[6], arg->data, arg->len);
+ buf += arg->len + 6;
+ }
+ }
+
+ pi_flush(sd, PI_FLUSH_INPUT);
+
+ if ((i = pi_write(sd, exec_buf, len)) < (ssize_t)len) {
+ errno = -EIO;
+ if (i >= 0 && i < (ssize_t)len)
+ i = -1;
+ }
+
+ free (exec_buf);
+
+ return i;
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_request_free
+ *
+ * Summary: frees a dlpRequest instance
+ *
+ * Parameters: dlpRequest*
+ *
+ * Returns: void
+ *
+ ***************************************************************************/
+void
+dlp_request_free (struct dlpRequest *req)
+{
+ int i;
+
+ if (req == NULL)
+ return;
+
+ if (req->argv != NULL) {
+ for (i = 0; i < req->argc; i++) {
+ if (req->argv[i] != NULL)
+ dlp_arg_free (req->argv[i]);
+ }
+ free (req->argv);
+ }
+
+ free (req);
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_response_free
+ *
+ * Summary: frees a dlpResponse instance
+ *
+ * Parameters: dlpResponse*
+ *
+ * Returns: void
+ *
+ ***************************************************************************/
+void
+dlp_response_free (struct dlpResponse *res)
+{
+ int i;
+
+ if (res == NULL)
+ return;
+
+ if (res->argv != NULL) {
+ for (i = 0; i < res->argc; i++) {
+ if (res->argv[i] != NULL)
+ dlp_arg_free (res->argv[i]);
+ }
+ free (res->argv);
+ }
+
+ free (res);
+}
+
+
+/***************************************************************************
+ *
+ * Function: dlp_exec
+ *
+ * Summary: writes a dlp request and reads the response
+ *
+ * Parameters: dlpResponse*
+ *
+ * Returns: the number of response bytes, or -1 on error
+ *
+ ***************************************************************************/
+int
+dlp_exec(int sd, struct dlpRequest *req, struct dlpResponse **res)
+{
+ int bytes, result;
+ *res = NULL;
+
+ if ((result = dlp_request_write (req, sd)) < req->argc) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP sd:%i dlp_request_write returned %i\n",
+ sd, result));
+ errno = -EIO;
+ return result;
+ }
+
+ if ((bytes = dlp_response_read (res, sd)) < 0) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP sd:%i dlp_response_read returned %i\n",
+ sd, bytes));
+ errno = -EIO;
+ return bytes;
+ }
+
+ /* Check to make sure the response is for this command */
+ if ((*res)->cmd != req->cmd) {
+ /* The Palm m130 and Tungsten T return the wrong code for VFSVolumeInfo */
+ /* Tungsten T5 (and maybe Treo 650) return dlpFuncEndOfSync for dlpFuncWriteResource */
+ /* In some cases, the Tapwave Zodiac returns dlpFuncReadRecord instead of dlpFuncReadRecordEx */
+ if ((req->cmd != dlpFuncVFSVolumeInfo || (*res)->cmd != dlpFuncVFSVolumeSize)
+ && req->cmd != dlpFuncWriteResource /* T5 */
+ && req->cmd != dlpFuncReadRecord /* Zodiac */
+ && req->cmd != dlpFuncReadRecordEx) /* Zodiac */
+ {
+ errno = -ENOMSG;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ "dlp_exec: result CMD 0x%02x doesn't match requested cmd 0x%02x\n",
+ (unsigned)((*res)->cmd), (unsigned)req->cmd));
+
+ return pi_set_error(sd, PI_ERR_DLP_COMMAND);
+ }
+ }
+
+ /* Check to make sure there was no error */
+ if ((*res)->err != dlpErrNoError) {
+ errno = -ENOMSG;
+ pi_set_palmos_error(sd, (int)((*res)->err));
+ return pi_set_error(sd, PI_ERR_DLP_PALMOS);
+ }
+
+ return bytes;
+}
+
+/* These conversion functions are strictly for use within the DLP layer.
+ This particular date/time format does not occur anywhere else within the
+ Palm or its communications. */
+
+/* Notice:
+ The dates in the DLP protocol are expressed as absolute dates/times,
+ without any time zone information. For example if a file was created
+ on the device at 19:32:48, the time members will be 19, 32 and 48.
+ This simplifies things a lot since we don't need to to time zone
+ conversions. The functions below convert a breakdown DLP date to and
+ from a time_t expressed in the machine's local timezone.
+ -- FP */
+
+time_t
+dlp_ptohdate(const unsigned char *data)
+{
+ struct tm t;
+
+ /* Seems like year comes back as all zeros if the date is "empty"
+ (but other fields can vary). And mktime() chokes on 1900 B.C.
+ (result of 0 minus 1900), returning -1, which the higher level
+ code can't deal with (passes it straight on to utime(), which
+ simply leaves the file's timestamp "as-is").
+
+ So, since year 0 appears to mean "no date", we'll return an odd
+ number that works out to precisely one day before the start of
+ the Palm's clock (thus little chance of being run into by any
+ Palm-based time stamp). */
+
+ if (data[0] == 0 && data[1] == 0) {
+
+ /* This original calculation was wrong, and reported one day
+ earlier than it was supposed to report. You can verify
+ this with the following:
+
+ perl -e '$date=localtime(0x83D8FE00); print $date,"\n"'
+
+ return (time_t) 0x83D8FE00; // Wed Dec 30 16:00:00 1903 GMT
+
+ Here are others, depending on what your system requirements are:
+
+ return (time_t) 0x83D96E80; // Thu Dec 31 00:00:00 1903 GMT
+ return (time_t) 0x00007080; // Thu Jan 1 00:00:00 1970 GMT
+
+ Palm's own Conduit Development Kit references using 1/1/1904,
+ so that's what we'll use here until something else breaks
+ it.
+ */
+
+ return (time_t) 0x83DAC000; /* Fri Jan 1 00:00:00 1904 GMT */
+ }
+
+ memset(&t, 0, sizeof(t));
+ t.tm_sec = (int) data[6];
+ t.tm_min = (int) data[5];
+ t.tm_hour = (int) data[4];
+ t.tm_mday = (int) data[3];
+ t.tm_mon = (int) data[2] - 1;
+ t.tm_year = (((int)data[0] << 8) | (int)data[1]) - 1900;
+ t.tm_isdst = -1;
+
+ return mktime(&t);
+}
+
+void
+dlp_htopdate(time_t time_interval, unsigned char *data)
+{ /* @+ptrnegate@ */
+ int year;
+ const struct tm *t;
+
+ /* Fri Jan 1 00:00:00 1904 GMT */
+ time_t palm_epoch = 0x83DAC000;
+
+ if (time_interval == palm_epoch) {
+ memset(data, 0, 8);
+ return;
+ }
+
+ t = localtime(&time_interval);
+ ASSERT(t != NULL);
+
+ year = t->tm_year + 1900;
+
+ data[7] = (unsigned char) 0; /* packing spacer */
+ data[6] = (unsigned char) t->tm_sec;
+ data[5] = (unsigned char) t->tm_min;
+ data[4] = (unsigned char) t->tm_hour;
+ data[3] = (unsigned char) t->tm_mday;
+ data[2] = (unsigned char) (t->tm_mon + 1);
+ data[0] = (unsigned char) (year >> 8);
+ data[1] = (unsigned char) year;
+}
+
+int
+dlp_GetSysDateTime(int sd, time_t *t)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_GetSysDateTime);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncGetSysDateTime, 0);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ *t = dlp_ptohdate((const unsigned char *)DLP_RESPONSE_DATA (res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP GetSysDateTime %s", ctime(t)));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_SetSysDateTime(int sd, time_t t)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_SetSysDateTime,"time=0x%08lx",t);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncSetSysDateTime, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ dlp_htopdate(t, (unsigned char *)DLP_REQUEST_DATA(req, 0, 0));
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ReadStorageInfo(int sd, int cardno, struct CardInfo *c)
+{
+ int result;
+ size_t len1, len2;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadStorageInfo,"cardno=%d",cardno);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncReadStorageInfo, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), cardno);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ c->more = get_byte(DLP_RESPONSE_DATA(res, 0, 0))
+ || (get_byte(DLP_RESPONSE_DATA(res, 0, 3)) > 1);
+ c->card = get_byte(DLP_RESPONSE_DATA(res, 0, 5));
+ c->version = get_byte(DLP_RESPONSE_DATA(res, 0, 6));
+ c->creation = get_date((const unsigned char *)DLP_RESPONSE_DATA(res, 0, 8));
+ c->romSize = get_long(DLP_RESPONSE_DATA(res, 0, 16));
+ c->ramSize = get_long(DLP_RESPONSE_DATA(res, 0, 20));
+ c->ramFree = get_long(DLP_RESPONSE_DATA(res, 0, 24));
+
+ len1 = get_byte(DLP_RESPONSE_DATA(res, 0, 28));
+ memcpy(c->name, DLP_RESPONSE_DATA(res, 0, 30), len1);
+ c->name[len1] = '\0';
+
+ len2 = get_byte(DLP_RESPONSE_DATA(res, 0, 29));
+ memcpy(c->manufacturer, DLP_RESPONSE_DATA(res, 0, 30 + len1),
+ len2);
+ c->manufacturer[len2] = '\0';
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP Read Cardno: %d, Card Version: %d, Creation time: %s",
+ c->card, c->version, ctime(&c->creation)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Total ROM: %lu, Total RAM: %lu, Free RAM: %lu\n",
+ c->romSize, c->ramSize, c->ramFree));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Card name: '%s'\n", c->name));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Manufacturer name: '%s'\n", c->manufacturer));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " More: %s\n", c->more ? "Yes" : "No"));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_ReadSysInfo(int sd, struct SysInfo *s)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_ReadSysInfo);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncReadSysInfo, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), dlp_version_major);
+ set_short (DLP_REQUEST_DATA (req, 0, 2), dlp_version_minor);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ s->romVersion = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+ s->locale = get_long (DLP_RESPONSE_DATA (res, 0, 4));
+ /* The 8th byte is a filler byte */
+ s->prodIDLength = get_byte (DLP_RESPONSE_DATA (res, 0, 9));
+ memcpy(s->prodID, DLP_RESPONSE_DATA(res, 0, 10),
+ s->prodIDLength);
+
+ if (res->argc > 1) {
+ /* response added in DLP 1.2 */
+ pi_socket_t *ps = find_pi_socket(sd);
+
+ s->dlpMajorVersion =
+ get_short (DLP_RESPONSE_DATA (res, 1, 0));
+ s->dlpMinorVersion =
+ get_short (DLP_RESPONSE_DATA (res, 1, 2));
+ s->compatMajorVersion =
+ get_short (DLP_RESPONSE_DATA (res, 1, 4));
+ s->compatMinorVersion =
+ get_short (DLP_RESPONSE_DATA (res, 1, 6));
+ s->maxRecSize =
+ get_long (DLP_RESPONSE_DATA (res, 1, 8));
+
+ /* update socket information */
+ ps->dlpversion = (s->dlpMajorVersion << 8) | s->dlpMinorVersion;
+ ps->maxrecsize = s->maxRecSize;
+ } else {
+ s->dlpMajorVersion = 0;
+ s->dlpMinorVersion = 0;
+ s->compatMajorVersion = 0;
+ s->compatMinorVersion = 0;
+ s->maxRecSize = 0;
+ }
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadSysInfo ROM Ver=0x%8.8lX Locale=0x%8.8lX\n",
+ s->romVersion, s->locale));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Product ID=0x%8.8lX\n", s->prodID));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " DLP Major Ver=0x%4.4lX DLP Minor Ver=0x%4.4lX\n",
+ s->dlpMajorVersion, s->dlpMinorVersion));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Compat Major Ver=0x%4.4lX Compat Minor Vers=0x%4.4lX\n",
+ s->compatMajorVersion, s->compatMinorVersion));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Max Rec Size=%ld\n", s->maxRecSize));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_ReadDBList(int sd, int cardno, int flags, int start, pi_buffer_t *info)
+{
+ int result,
+ i,
+ count;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ unsigned char *p;
+ struct DBInfo db;
+
+ TraceX(dlp_ReadDBList,"cardno=%d flags=0x%04x start=%d",cardno,flags,start);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncReadDBList, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ pi_buffer_clear (info);
+
+ /* `multiple' only supported in DLP 1.2 and above */
+ if (pi_version(sd) < 0x0102)
+ flags &= ~dlpDBListMultiple;
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), (unsigned char) flags);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), (unsigned char) cardno);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), start);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ p = (unsigned char *)DLP_RESPONSE_DATA(res, 0, 0);
+ db.more = get_byte(p + 2);
+ count = get_byte(p + 3);
+
+ for (i=0; i < count; i++) {
+ /* PalmOS 2.0 has additional flag */
+ if (pi_version(sd) > 0x0100)
+ db.miscFlags = get_byte(p + 5);
+ else
+ db.miscFlags = 0;
+
+ db.flags = get_short(p + 6);
+ db.type = get_long(p + 8);
+ db.creator = get_long(p + 12);
+ db.version = get_short(p + 16);
+ db.modnum = get_long(p + 18);
+ db.createDate = get_date(p + 22);
+ db.modifyDate = get_date(p + 30);
+ db.backupDate = get_date(p + 38);
+ db.index = get_short(p + 46);
+
+ memset(db.name, 0, sizeof(db.name));
+ strncpy(db.name, (char *)(p + 48), 32);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadDBList Name: '%s', Version: %d, More: %s\n",
+ db.name, db.version, db.more ? "Yes" : "No"));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Creator: '%s'", printlong(db.creator)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Type: '%s' Flags: %s%s%s%s%s%s%s%s%s%s",
+ printlong(db.type),
+ (db.flags & dlpDBFlagResource) ? "Resource " : "",
+ (db.flags & dlpDBFlagReadOnly) ? "ReadOnly " : "",
+ (db.flags & dlpDBFlagAppInfoDirty) ?
+ "AppInfoDirty " : "",
+ (db.flags & dlpDBFlagBackup) ? "Backup " : "",
+ (db.flags & dlpDBFlagReset) ? "Reset " : "",
+ (db.flags & dlpDBFlagNewer) ? "Newer " : "",
+ (db.flags & dlpDBFlagCopyPrevention) ?
+ "CopyPrevention " : "",
+ (db.flags & dlpDBFlagStream) ? "Stream " : "",
+ (db.flags & dlpDBFlagOpen) ? "Open " : "",
+ (!db.flags) ? "None" : ""));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, " (0x%2.2X)\n", db.flags));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Modnum: %ld, Index: %d, Creation date: 0x%08lx, %s",
+ db.modnum, db.index, db.createDate, ctime(&db.createDate)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Modification date: 0x%08lx, %s", db.modifyDate, ctime(&db.modifyDate)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Backup date: 0x%08lx, %s", db.backupDate, ctime(&db.backupDate)));
+
+ if (pi_buffer_append(info, &db, sizeof(db)) == NULL) {
+ result = pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ break;
+ }
+
+ p += get_byte(p + 4);
+ }
+ } else {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Error in dlp_ReadDBList: %d\n", result));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_FindDBInfo(int sd, int cardno, int start, const char *dbname,
+ unsigned long type, unsigned long creator,
+ struct DBInfo *info)
+{
+ int i,
+ j;
+ pi_buffer_t *buf;
+
+ TraceX(dlp_FindDBInfo,"cardno=%d start=%d",cardno,start);
+ pi_reset_errors(sd);
+
+ buf = pi_buffer_new (sizeof (struct DBInfo));
+ if (buf == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ if (start < 0x1000) {
+ i = start;
+ while (dlp_ReadDBList(sd, cardno, 0x80 | dlpDBListMultiple, i, buf) >= 0) {
+ for (j=0; j < (int)(buf->used / sizeof(struct DBInfo)); j++) {
+ memcpy (info, buf->data + j * sizeof(struct DBInfo), sizeof(struct DBInfo));
+ if ((!dbname || strcmp(info->name, dbname) == 0)
+ && (!type || info->type == type)
+ && (!creator || info->creator == creator))
+ goto found;
+ i = info->index + 1;
+ }
+ }
+ start = 0x1000;
+ }
+
+ i = start & 0xFFF;
+ while (dlp_ReadDBList(sd, cardno, 0x40 | dlpDBListMultiple, i, buf) >= 0) {
+ for (j=0; j < (int)(buf->used / sizeof(struct DBInfo)); j++) {
+ memcpy (info, buf->data + j * sizeof(struct DBInfo), sizeof(struct DBInfo));
+ if ((!dbname || strcmp(info->name, dbname) == 0)
+ && (!type || info->type == type)
+ && (!creator || info->creator == creator))
+ {
+ info->index |= 0x1000;
+ goto found;
+ }
+ i = info->index + 1;
+ }
+ }
+
+ pi_buffer_free (buf);
+ return -1;
+
+found:
+ pi_buffer_free (buf);
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Function: dlp_decode_finddb_response
+ *
+ * Summary: Response decoding for the three variants of dlp_FindDB
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***************************************************************************/
+static void
+dlp_decode_finddb_response(struct dlpResponse *res, int *cardno, unsigned long *localid,
+ int *dbhandle, struct DBInfo *info, struct DBSizeInfo *size)
+{
+ int arg, argid;
+ for (arg = 0; arg < res->argc; arg++) {
+ argid = (res->argv[arg]->id_ & 0x7f) - PI_DLP_ARG_FIRST_ID;
+ if (argid == 0) {
+ if (cardno)
+ *cardno = get_byte(DLP_RESPONSE_DATA(res, arg, 0));
+ if (localid)
+ *localid = get_long(DLP_RESPONSE_DATA(res, arg, 2));
+ if (dbhandle)
+ *dbhandle = get_long(DLP_RESPONSE_DATA(res, arg, 6));
+
+ if (info) {
+ info->more = 0;
+ info->miscFlags =
+ get_byte(DLP_RESPONSE_DATA(res, arg, 11));
+ info->flags =
+ get_short(DLP_RESPONSE_DATA(res, arg, 12));
+ info->type =
+ get_long(DLP_RESPONSE_DATA(res, arg, 14));
+ info->creator =
+ get_long(DLP_RESPONSE_DATA(res, arg, 18));
+ info->version =
+ get_short(DLP_RESPONSE_DATA(res, arg, 22));
+ info->modnum =
+ get_long(DLP_RESPONSE_DATA(res, arg, 24));
+ info->createDate =
+ get_date((const unsigned char *)DLP_RESPONSE_DATA(res, arg, 28));
+ info->modifyDate =
+ get_date((const unsigned char *)DLP_RESPONSE_DATA(res, arg, 36));
+ info->backupDate =
+ get_date((const unsigned char *)DLP_RESPONSE_DATA(res, arg, 44));
+ info->index =
+ get_short(DLP_RESPONSE_DATA(res, arg, 52));
+
+ strncpy(info->name, DLP_RESPONSE_DATA(res, arg, 54), 32);
+ info->name[32] = '\0';
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP FindDB Name: '%s', "
+ "Version: %d, More: %s\n",
+ info->name, info->version,
+ info->more ? "Yes" : "No"));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Creator: '%s'", printlong(info->creator)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Type: '%s' Flags: %s%s%s%s%s%s%s%s%s%s",
+ printlong(info->type),
+ (info->flags & dlpDBFlagResource) ?
+ "Resource " : "",
+ (info->flags & dlpDBFlagReadOnly) ?
+ "ReadOnly " : "",
+ (info->flags & dlpDBFlagAppInfoDirty) ?
+ "AppInfoDirty " : "",
+ (info->flags & dlpDBFlagBackup) ?
+ "Backup " : "",
+ (info->flags & dlpDBFlagReset) ?
+ "Reset " : "",
+ (info->flags & dlpDBFlagNewer) ?
+ "Newer " : "",
+ (info->flags & dlpDBFlagCopyPrevention) ?
+ "CopyPrevention " : "",
+ (info->flags & dlpDBFlagStream) ?
+ "Stream " : "",
+ (info->flags & dlpDBFlagOpen) ?
+ "Open " : "",
+ (!info->flags) ? "None" : ""));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " (0x%2.2X)\n", info->flags));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Modnum: %ld, Index: %d, "
+ "Creation date: %s",
+ info->modnum, info->index,
+ ctime(&info->createDate)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Modification date: %s",
+ ctime(&info->modifyDate)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Backup date: %s",
+ ctime(&info->backupDate)));
+ }
+ }
+ else if (argid == 1) {
+ if (size) {
+ size->numRecords =
+ get_long(DLP_RESPONSE_DATA(res, arg, 0));
+ size->totalBytes =
+ get_long(DLP_RESPONSE_DATA(res, arg, 4));
+ size->dataBytes =
+ get_long(DLP_RESPONSE_DATA(res, arg, 8));
+ size->appBlockSize =
+ get_long(DLP_RESPONSE_DATA(res, arg, 12));
+ size->sortBlockSize =
+ get_long(DLP_RESPONSE_DATA(res, arg, 16));
+ size->maxRecSize =
+ get_long(DLP_RESPONSE_DATA(res, arg, 20));
+ }
+ }
+ }
+}
+
+int
+dlp_FindDBByName (int sd, int cardno, PI_CONST char *name, unsigned long *localid,
+ int *dbhandle, struct DBInfo *info, struct DBSizeInfo *size)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int flags = 0;
+
+ TraceX(dlp_FindDBByName,"cardno=%d name='%s'",cardno,name);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0102)
+ return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
+
+ req = dlp_request_new(dlpFuncFindDB, 1, 2 + (strlen(name) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ if (localid || dbhandle || info)
+ flags |= dlpFindDBOptFlagGetAttributes;
+ if (size)
+ flags |= dlpFindDBOptFlagGetSize;
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), flags);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), cardno);
+ strcpy(DLP_REQUEST_DATA(req, 0, 2), name);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0)
+ dlp_decode_finddb_response(res, NULL, localid, dbhandle, info, size);
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_FindDBByOpenHandle (int sd, int dbhandle, int *cardno,
+ unsigned long *localid, struct DBInfo *info, struct DBSizeInfo *size)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int flags = 0;
+
+ Trace(dlp_FindDBByOpenHandle);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0102)
+ return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
+
+ req = dlp_request_new_with_argid(dlpFuncFindDB, 0x21, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ /* Note: there is a bug in HotSync -- requesting the maxRecSize
+ * crashes the device, so we don't. This is supposed to work only
+ * for this variant of FindDB anyway.
+ */
+ if (cardno || localid || info)
+ flags |= dlpFindDBOptFlagGetAttributes;
+ if (size)
+ flags |= dlpFindDBOptFlagGetSize;
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), flags);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), dbhandle);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0)
+ dlp_decode_finddb_response(res, cardno, localid, NULL, info, size);
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_FindDBByTypeCreator (int sd, unsigned long type, unsigned long creator,
+ int start, int latest, int *cardno, unsigned long *localid,
+ int *dbhandle, struct DBInfo *info, struct DBSizeInfo *size)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int flags = 0, search_flags = 0;
+
+ TraceX(dlp_FindDBByTypeCreator,"type='%4.4s' creator='%4.4s' start=%d latest=%d",
+ (const char *)&type,(const char *)&creator,start,latest);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0102)
+ return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
+
+ req = dlp_request_new_with_argid(dlpFuncFindDB, 0x22, 1, 10);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ if (cardno || localid || dbhandle || info)
+ flags |= dlpFindDBOptFlagGetAttributes;
+ if (size)
+ flags |= (dlpFindDBOptFlagGetSize |
+ dlpFindDBOptFlagMaxRecSize);
+
+ if (start)
+ search_flags |= dlpFindDBSrchFlagNewSearch;
+ if (latest)
+ search_flags |= dlpFindDBSrchFlagOnlyLatest;
+
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), flags);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), search_flags);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), type);
+ set_long(DLP_REQUEST_DATA(req, 0, 6), creator);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0)
+ dlp_decode_finddb_response(res, cardno, localid, dbhandle, info, size);
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_OpenDB(int sd, int cardno, int mode, PI_CONST char *name, int *dbhandle)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_OpenDB,"'%s'",name);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncOpenDB, 1, 2 + strlen(name) + 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), cardno);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), mode);
+ strcpy(DLP_REQUEST_DATA(req, 0, 2), name);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ *dbhandle = get_byte(DLP_RESPONSE_DATA(res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "-> dlp_OpenDB dbhandle=%d\n", *dbhandle));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_DeleteDB(int sd, int card, const char *name)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_DeleteDB,"%s",name);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncDeleteDB, 1, 2 + (strlen(name) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), card);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ strcpy(DLP_REQUEST_DATA(req, 0, 2), name);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_CreateDB(int sd, unsigned long creator, unsigned long type, int cardno,
+ int flags, unsigned int version, const char *name, int *dbhandle)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_CreateDB,"'%s' type='%4.4s' creator='%4.4s' flags=0x%04x version=%d",
+ name,(const char *)&type,(const char *)&creator,flags,version);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncCreateDB, 1, 14 + (strlen(name) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), type);
+ set_byte(DLP_REQUEST_DATA(req, 0, 8), cardno);
+ set_byte(DLP_REQUEST_DATA(req, 0, 9), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 10), flags);
+ set_short(DLP_REQUEST_DATA(req, 0, 12), version);
+ strcpy(DLP_REQUEST_DATA(req, 0, 14), name);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0 && dbhandle) {
+ *dbhandle = get_byte(DLP_RESPONSE_DATA(res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP CreateDB Handle=%d\n", *dbhandle));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_CloseDB(int sd, int dbhandle)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_CloseDB);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncCloseDB, 1, 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), (unsigned char) dbhandle);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_CloseDB_All(int sd)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_CloseDB_All);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new_with_argid(dlpFuncCloseDB, 0x21, 0);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_CallApplication(int sd, unsigned long creator, unsigned long type,
+ int action, size_t length, const void *data,
+ unsigned long *retcode, pi_buffer_t *retbuf)
+{
+ int result,
+ version = pi_version(sd),
+ previous_honor_rx_timeout,
+ no_rx_timeout = 0;
+ size_t data_len;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_CallApplication,"type='%4.4s' creator='%4.4s' action=0x%04x dataLength=%d",
+ (const char *)&type,(const char *)&creator,action,(int)length);
+ pi_reset_errors(sd);
+ if (retbuf)
+ pi_buffer_clear(retbuf);
+
+ /* we are going to temporarily disable PI_SOCK_HONOR_RX_TIMEOUT
+ * so that lengthy tasks on the device side don't cause a
+ * connection timeout
+ */
+ data_len = sizeof(previous_honor_rx_timeout);
+ pi_getsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
+ &previous_honor_rx_timeout, &data_len);
+
+ if (version >= 0x0101) { /* PalmOS 2.0 call encoding */
+
+ if (length + 22 > DLP_BUF_SIZE) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP CallApplication: data too large (>64k)"));
+ pi_set_error(sd, PI_ERR_DLP_DATASIZE);
+ return -131;
+ }
+
+ req = dlp_request_new_with_argid(
+ dlpFuncCallApplication, 0x21, 1, 22 + length);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), type);
+ set_short(DLP_REQUEST_DATA(req, 0, 8), action);
+ set_long(DLP_REQUEST_DATA(req, 0, 10), length);
+ set_long(DLP_REQUEST_DATA(req, 0, 14), 0);
+ set_long(DLP_REQUEST_DATA(req, 0, 18), 0);
+ if (length)
+ memcpy(DLP_REQUEST_DATA(req, 0, 22), data, length);
+
+ data_len = sizeof(no_rx_timeout);
+ pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
+ &no_rx_timeout, &data_len);
+
+ result = dlp_exec(sd, req, &res);
+
+ pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
+ &previous_honor_rx_timeout, &data_len);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - 16;
+
+ if (retcode)
+ *retcode = get_long(DLP_RESPONSE_DATA(res, 0, 0));
+ if (retbuf)
+ pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 16), data_len);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP CallApplication Result: %lu (0x%08lx), "
+ "and %d bytes:\n",
+ get_long(DLP_RESPONSE_DATA(res, 0, 0)),
+ get_long(DLP_RESPONSE_DATA(res, 0, 0)),
+ data_len));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 16),
+ (size_t)data_len));
+ }
+
+ } else { /* PalmOS 1.0 call encoding */
+
+ if (length + 8 > DLP_BUF_SIZE) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP CallApplication: data too large (>64k)"));
+ pi_set_error(sd, PI_ERR_DLP_DATASIZE);
+ return -131;
+ }
+
+ req = dlp_request_new (dlpFuncCallApplication, 1, 8 + length);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), action);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), length);
+ memcpy(DLP_REQUEST_DATA(req, 0, 8), data, length);
+
+ data_len = sizeof(no_rx_timeout);
+ pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
+ &no_rx_timeout, &data_len);
+
+ result = dlp_exec(sd, req, &res);
+
+ pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
+ &previous_honor_rx_timeout, &data_len);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - 6;
+ if (retcode)
+ *retcode = get_short(DLP_RESPONSE_DATA(res, 0, 2));
+ if (retbuf)
+ pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 6), data_len);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP CallApplication Action: %d Result:"
+ " %u (0x%04x), and %d bytes:\n",
+ (int)get_short(DLP_RESPONSE_DATA(res, 0, 0)),
+ (unsigned int)get_short(DLP_RESPONSE_DATA(res, 0, 2)),
+ (unsigned int)get_short(DLP_RESPONSE_DATA(res, 0, 2)),
+ data_len));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 6),
+ (size_t)data_len));
+ }
+ }
+
+ dlp_response_free(res);
+ return result;
+}
+
+int
+dlp_ResetSystem(int sd)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_ResetSystem);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncResetSystem, 0);
+
+ result = dlp_exec(sd, req, &res);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_AddSyncLogEntry(int sd, char *entry)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_AddSyncLogEntry,"%s",entry);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncAddSyncLogEntry, 1, strlen(entry) + 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ strcpy(DLP_REQUEST_DATA(req, 0, 0), entry);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ if (result > 0) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP AddSyncLogEntry Entry: \n %s\n", entry));
+ }
+
+ return result;
+}
+
+int
+dlp_ReadOpenDBInfo(int sd, int dbhandle, int *records)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_ReadOpenDBInfo);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncReadOpenDBInfo, 1, 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ if (records)
+ *records = get_short(DLP_RESPONSE_DATA(res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadOpenDBInfo %d records\n",
+ get_short(DLP_RESPONSE_DATA(res, 0, 0))));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_SetDBInfo (int sd, int dbhandle, int flags, int clearFlags,
+ unsigned int version, time_t createDate, time_t modifyDate,
+ time_t backupDate, unsigned long type, unsigned long creator)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_SetDBInfo);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0102)
+ return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
+
+ req = dlp_request_new(dlpFuncSetDBInfo, 1, 40);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), clearFlags);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), flags);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), version);
+ set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 8), createDate);
+ set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 16), modifyDate);
+ set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 24), backupDate);
+ set_long(DLP_REQUEST_DATA(req, 0, 32), type);
+ set_long(DLP_REQUEST_DATA(req, 0, 36), creator);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_MoveCategory(int sd, int handle, int fromcat, int tocat)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_MoveCategory,"from %d to %d",fromcat,tocat);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncMoveCategory, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), handle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), fromcat);
+ set_byte(DLP_REQUEST_DATA(req, 0, 2), tocat);
+ set_byte(DLP_REQUEST_DATA(req, 0, 3), 0);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ if (result >= 0) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP MoveCategory Handle: %d, From: %d, To: %d\n",
+ handle, fromcat, tocat));
+ }
+
+ return result;
+}
+
+int
+dlp_OpenConduit(int sd)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_OpenConduit);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncOpenConduit, 0);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ /* if this was not done yet, this will read and cache the DLP version
+ that the Palm is running. We need this when reading responses during
+ record/resource transfers */
+ if (result >= 0)
+ pi_version(sd);
+
+ return result;
+}
+
+int
+dlp_EndOfSync(int sd, int status)
+{
+ int result;
+ pi_socket_t *ps;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_EndOfSync);
+ pi_reset_errors(sd);
+
+ ps = find_pi_socket(sd);
+ if (ps == NULL) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ req = dlp_request_new(dlpFuncEndOfSync, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short(DLP_REQUEST_DATA(req, 0, 0), status);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ /* Messy code to set end-of-sync flag on socket
+ so pi_close won't do it for us */
+ if (result == 0)
+ ps->state = PI_SOCK_CONN_END;
+
+ return result;
+}
+
+int
+dlp_AbortSync(int sd)
+{
+ pi_socket_t *ps;
+
+ Trace(dlp_AbortSync);
+ pi_reset_errors(sd);
+
+ /* Pretend we sent the sync end */
+ if ((ps = find_pi_socket(sd)) == NULL) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ ps->state = PI_SOCK_CONN_END;
+
+ return 0;
+}
+
+int
+dlp_WriteUserInfo(int sd, const struct PilotUser *User)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int len;
+
+ Trace(dlp_WriteUserInfo);
+ pi_reset_errors(sd);
+
+ len = strlen (User->username) + 1;
+
+ req = dlp_request_new (dlpFuncWriteUserInfo, 1, 22 + len);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), User->userID);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), User->viewerID);
+ set_long(DLP_REQUEST_DATA(req, 0, 8), User->lastSyncPC);
+ set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 12), User->lastSyncDate);
+ set_byte(DLP_REQUEST_DATA(req, 0, 20), 0xff);
+ set_byte(DLP_REQUEST_DATA(req, 0, 21), len);
+ strcpy(DLP_REQUEST_DATA(req, 0, 22), User->username);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_ReadUserInfo(int sd, struct PilotUser *User)
+{
+ int result;
+ size_t userlen;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_ReadUserInfo);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncReadUserInfo, 0);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ User->userID =
+ get_long(DLP_RESPONSE_DATA (res, 0, 0));
+ User->viewerID =
+ get_long(DLP_RESPONSE_DATA (res, 0, 4));
+ User->lastSyncPC =
+ get_long(DLP_RESPONSE_DATA (res, 0, 8));
+ User->successfulSyncDate =
+ get_date((const unsigned char *)DLP_RESPONSE_DATA (res, 0, 12));
+ User->lastSyncDate =
+ get_date((const unsigned char *)DLP_RESPONSE_DATA (res, 0, 20));
+ userlen =
+ get_byte(DLP_RESPONSE_DATA (res, 0, 28));
+ User->passwordLength =
+ get_byte(DLP_RESPONSE_DATA (res, 0, 29));
+
+ memcpy(User->username,
+ DLP_RESPONSE_DATA (res, 0, 30), userlen);
+ memcpy(User->password,
+ DLP_RESPONSE_DATA (res, 0, 30 + userlen),
+ User->passwordLength);
+
+ if (userlen < sizeof(User->username))
+ User->username[userlen] = '\0';
+ if (User->passwordLength < sizeof(User->password))
+ User->password[User->passwordLength] = '\0';
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadUserInfo UID=0x%8.8lX VID=0x%8.8lX "
+ "PCID=0x%8.8lX\n",
+ User->userID, User->viewerID, User->lastSyncPC));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Last Sync=%s Last Successful Sync=%s",
+ ctime (&User->lastSyncDate),
+ ctime (&User->successfulSyncDate)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " Username=%s\n", User->username));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_ReadNetSyncInfo(int sd, struct NetSyncInfo *i)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_ReadNetSyncInfo);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101)
+ return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
+
+ req = dlp_request_new(dlpFuncReadNetSyncInfo, 0);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result >= 0) {
+ size_t str_offset = 24;
+
+ i->lanSync = get_byte(DLP_RESPONSE_DATA(res, 0, 0));
+
+ i->hostName[0] = '\0';
+ memcpy(i->hostName, DLP_RESPONSE_DATA(res, 0, str_offset),
+ get_short(DLP_RESPONSE_DATA(res, 0, 18)));
+ str_offset += get_short(DLP_RESPONSE_DATA(res, 0, 18));
+
+ i->hostAddress[0] = '\0';
+ memcpy(i->hostAddress, DLP_RESPONSE_DATA(res, 0, str_offset),
+ get_short(DLP_RESPONSE_DATA(res, 0, 20)));
+ str_offset += get_short(DLP_RESPONSE_DATA(res, 0, 20));
+
+ i->hostSubnetMask[0] = '\0';
+ memcpy(i->hostSubnetMask, DLP_RESPONSE_DATA(res, 0, str_offset),
+ get_short(DLP_RESPONSE_DATA(res, 0, 22)));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadNetSyncInfo Active: %d\n", i->lanSync ? 1 : 0));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " PC hostname: '%s', address '%s', mask '%s'\n",
+ i->hostName, i->hostAddress, i->hostSubnetMask));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_WriteNetSyncInfo(int sd, const struct NetSyncInfo *i)
+{
+ int result,
+ str_offset = 24;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_WriteNetSyncInfo);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101)
+ return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadNetSyncInfo Active: %d\n", i->lanSync ? 1 : 0));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " PC hostname: '%s', address '%s', mask '%s'\n",
+ i->hostName, i->hostAddress, i->hostSubnetMask));
+
+ req = dlp_request_new(dlpFuncWriteNetSyncInfo, 1,
+ 24 + strlen(i->hostName) +
+ strlen(i->hostAddress) + strlen(i->hostSubnetMask) + 3);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ /* Change all settings */
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), 0x80 | 0x40 | 0x20 | 0x10);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), i->lanSync);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), 0); /* Reserved1 */
+ set_long(DLP_REQUEST_DATA(req, 0, 6), 0); /* Reserved2 */
+ set_long(DLP_REQUEST_DATA(req, 0, 10), 0); /* Reserved3 */
+ set_long(DLP_REQUEST_DATA(req, 0, 14), 0); /* Reserved4 */
+ set_short(DLP_REQUEST_DATA(req, 0, 18), strlen(i->hostName) + 1);
+ set_short(DLP_REQUEST_DATA(req, 0, 20), strlen(i->hostAddress) + 1);
+ set_short(DLP_REQUEST_DATA(req, 0, 22), strlen(i->hostSubnetMask) + 1);
+
+ strcpy(DLP_REQUEST_DATA(req, 0, str_offset), i->hostName);
+ str_offset += strlen(i->hostName) + 1;
+ strcpy(DLP_REQUEST_DATA(req, 0, str_offset), i->hostAddress);
+ str_offset += strlen(i->hostAddress) + 1;
+ strcpy(DLP_REQUEST_DATA(req, 0, str_offset), i->hostSubnetMask);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+#ifdef _PILOT_SYSPKT_H
+int
+dlp_RPC(int sd, struct RPC_params *p, unsigned long *result)
+{
+ int i,
+ err = 0;
+ long D0 = 0,
+ A0 = 0;
+ unsigned char *c;
+ pi_buffer_t *dlp_buf;
+
+ Trace(dlp_RPC);
+ pi_reset_errors(sd);
+
+ /* RPC through DLP breaks all the rules and isn't well documented to
+ boot */
+ dlp_buf = pi_buffer_new (DLP_BUF_SIZE);
+ if (dlp_buf == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ dlp_buf->data[0] = 0x2D;
+ dlp_buf->data[1] = 1;
+ dlp_buf->data[2] = 0; /* Unknown filler */
+ dlp_buf->data[3] = 0;
+
+ InvertRPC(p);
+
+ set_short(dlp_buf->data + 4, p->trap);
+ set_long(dlp_buf->data + 6, D0);
+ set_long(dlp_buf->data + 10, A0);
+ set_short(dlp_buf->data + 14, p->args);
+
+ c = dlp_buf->data + 16;
+ for (i = p->args - 1; i >= 0; i--) {
+ set_byte(c, p->param[i].byRef);
+ c++;
+ set_byte(c, p->param[i].size);
+ c++;
+ if (p->param[i].data)
+ memcpy(c, p->param[i].data, p->param[i].size);
+ c += p->param[i].size;
+ if (p->param[i].size & 1)
+ *c++ = 0;
+ }
+
+ if (pi_write(sd, dlp_buf->data, (size_t)(c - dlp_buf->data)) > 0) {
+ err = 0;
+ if (p->reply) {
+ int l = pi_read(sd, dlp_buf, (size_t)(c - dlp_buf->data + 2));
+
+ if (l < 0)
+ err = l;
+ else if (l < 6)
+ err = -1;
+ else if (dlp_buf->data[0] != 0xAD)
+ err = -2;
+ else if (get_short(dlp_buf->data + 2)) {
+ err = -get_short(dlp_buf->data + 2);
+ pi_set_palmos_error(sd, -err);
+ } else {
+ D0 = get_long(dlp_buf->data + 8);
+ A0 = get_long(dlp_buf->data + 12);
+ c = dlp_buf->data + 18;
+ for (i = p->args - 1; i >= 0; i--) {
+ if (p->param[i].byRef && p->param[i].data)
+ memcpy(p->param[i].data, c + 2,
+ p->param[i].size);
+ c += 2 + ((p->param[i].size + 1) &
+ (unsigned)~1);
+ }
+ }
+ }
+ }
+
+ pi_buffer_free (dlp_buf);
+
+ UninvertRPC(p);
+
+ if (result) {
+ if (p->reply == RPC_PtrReply) {
+ *result = A0;
+ } else if (p->reply == RPC_IntReply) {
+ *result = D0;
+ }
+ }
+
+ return err;
+}
+
+
+int
+dlp_ReadFeature(int sd, unsigned long creator, int num,
+ unsigned long *feature)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadFeature,"creator='%4.4s' num=%d",(const char *)&creator,num);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101) {
+ struct RPC_params p;
+ int val;
+ unsigned long errCode;
+
+ if (feature == NULL)
+ return 0;
+
+ *feature = 0x12345678;
+
+ PackRPC(&p, 0xA27B, RPC_IntReply, RPC_Long(creator), RPC_Short(num), RPC_LongPtr(feature), RPC_End);
+
+ val = dlp_RPC(sd, &p, &errCode);
+
+ if (val < 0) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadFeature Error: %s (%d)\n",
+ dlp_errorlist[-val], val));
+
+ return val;
+ }
+
+ if (errCode) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadFeature FtrGet error 0x%8.8lX\n",
+ res));
+ pi_set_palmos_error(sd, (int)errCode);
+ return pi_set_error(sd, PI_ERR_DLP_PALMOS);
+ }
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " DLP ReadFeature Feature: 0x%8.8lX\n",
+ (unsigned long) *feature));
+
+ return 0;
+ }
+
+ Trace(dlp_ReadFeatureV2);
+
+ req = dlp_request_new(dlpFuncReadFeature, 1, 6);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), num);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ if (feature)
+ *feature = (unsigned long)
+ get_long(DLP_RESPONSE_DATA(res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadFeature Feature: 0x%8.8lX\n",
+ (unsigned long)
+ get_long(DLP_RESPONSE_DATA(res, 0, 0))));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+#endif /* IFDEF _PILOT_SYSPKT_H */
+
+int
+dlp_GetROMToken(int sd, unsigned long token, void *buffer, size_t *size)
+{
+ unsigned long result;
+
+ struct RPC_params p;
+
+ int val;
+ unsigned long buffer_ptr;
+
+ Trace(dlp_GetROMToken);
+ pi_reset_errors(sd);
+
+#ifdef DLP_TRACE
+ if (dlp_trace) {
+ fprintf(stderr,
+ " Wrote: Token: '%s'\n",
+ printlong(token));
+ }
+#endif
+
+ PackRPC(&p, 0xa340, RPC_IntReply, /* sysTrapHwrGetROMToken */
+ RPC_Short(0),
+ RPC_Long(token),
+ RPC_LongPtr(&buffer_ptr),
+ RPC_ShortPtr(size), RPC_End);
+
+ val = dlp_RPC(sd, &p, &result);
+
+#ifdef DLP_TRACE
+ if (dlp_trace) {
+ if (val < 0)
+ fprintf(stderr,
+ "Result: Error: %s (%d)\n",
+ dlp_errorlist[-val], val);
+ else if (result)
+ fprintf(stderr,
+ "FtrGet error 0x%8.8lX\n",
+ (unsigned long) result);
+ else
+ fprintf(stderr,
+ " Read: Buffer Ptr: 0x%8.8lX Size: %d\n",
+ (unsigned long) buffer_ptr, *size);
+ }
+#endif
+
+ if (buffer) {
+ ((unsigned char *)buffer)[*size] = 0;
+
+ PackRPC(&p, 0xa026, RPC_IntReply, /* sysTrapMemMove */
+ RPC_Ptr(buffer, *size),
+ RPC_Long(buffer_ptr),
+ RPC_Long((unsigned long) *size),
+ RPC_End);
+
+ val = dlp_RPC(sd, &p, &result);
+ }
+
+#ifdef DLP_TRACE
+ if (dlp_trace) {
+ if (val < 0)
+ fprintf(stderr,
+ "Result: Error: %s (%d)\n",
+ dlp_errorlist[-val], val);
+ else if (result)
+ fprintf(stderr,
+ "FtrGet error 0x%8.8lX\n",
+ (unsigned long) result);
+ else
+ fprintf(stderr,
+ " Read: Buffer: %s\n", buffer);
+ }
+#endif
+
+ if (val < 0)
+ return val;
+
+ if (result)
+ return -((int)result);
+
+ return result;
+}
+
+int
+dlp_ResetLastSyncPC(int sd)
+{
+ int err;
+ struct PilotUser User;
+
+ Trace(dlp_ResetLastSyncPC);
+
+ if ((err = dlp_ReadUserInfo(sd, &User)) < 0)
+ return err;
+
+ User.lastSyncPC = 0;
+
+ return dlp_WriteUserInfo(sd, &User);
+}
+
+int
+dlp_ResetDBIndex(int sd, int dbhandle)
+{
+ int result;
+ pi_socket_t *ps;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_ResetDBIndex);
+ pi_reset_errors(sd);
+
+ if ((ps = find_pi_socket(sd)) == NULL) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ ps->dlprecord = 0;
+
+ req = dlp_request_new(dlpFuncResetRecordIndex, 1, 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ReadRecordIDList(int sd, int dbhandle, int sort, int start, int max,
+ recordid_t * IDs, int *count)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadRecordIDList,"sort=%d start=%d max=%d",
+ sort,start,max);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncReadRecordIDList, 1, 6);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), sort ? 0x80 : 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), start);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), max);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ int ret, i;
+
+ ret = get_short(DLP_RESPONSE_DATA(res, 0, 0));
+ for (i = 0; i < ret; i++)
+ IDs[i] =
+ get_long(DLP_RESPONSE_DATA(res, 0, 2 + (i * 4)));
+
+ if (count)
+ *count = ret;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadRecordIDList %d IDs:\n", ret));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 2),
+ (size_t)(ret * 4)));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_WriteRecord(int sd, int dbhandle, int flags, recordid_t recID,
+ int catID, const void *data, size_t length, recordid_t *pNewRecID)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_WriteRecord);
+ pi_reset_errors(sd);
+
+ if (length == (size_t)-1)
+ length = strlen((char *) data) + 1;
+
+ if (pi_version(sd) >= 0x0104) {
+ req = dlp_request_new(dlpFuncWriteRecordEx, 1, 12 + length);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x80); /* "data included" */
+ set_long(DLP_REQUEST_DATA(req, 0, 2), recID);
+ set_byte(DLP_REQUEST_DATA(req, 0, 6), flags);
+ set_byte(DLP_REQUEST_DATA(req, 0, 7), catID);
+ set_long(DLP_REQUEST_DATA(req, 0, 8), 0);
+
+ memcpy(DLP_REQUEST_DATA(req, 0, 12), data, length);
+ } else {
+ if ((length + 8) > DLP_BUF_SIZE) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP WriteRecord: data too large (>64k)"));
+ return PI_ERR_DLP_DATASIZE;
+ }
+
+ req = dlp_request_new(dlpFuncWriteRecord, 1, 8 + length);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x80); /* "data included" */
+ set_long(DLP_REQUEST_DATA(req, 0, 2), recID);
+ set_byte(DLP_REQUEST_DATA(req, 0, 6), flags);
+ set_byte(DLP_REQUEST_DATA(req, 0, 7), catID);
+
+ memcpy(DLP_REQUEST_DATA(req, 0, 8), data, length);
+ }
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ if (pNewRecID)
+ *pNewRecID = get_long(DLP_RESPONSE_DATA(res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP WriteRecord Record ID: 0x%8.8lX\n",
+ get_long(DLP_RESPONSE_DATA(res, 0, 0))));
+
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ record_dump(
+ get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
+ 0xffff, /* index */
+ flags,
+ catID,
+ (const char *)data, (int)length));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_DeleteRecord(int sd, int dbhandle, int all, recordid_t recID)
+{
+ int result,
+ flags = all ? 0x80 : 0;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_DeleteRecord);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncDeleteRecord, 1, 6);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), flags);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), recID);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_DeleteCategory(int sd, int dbhandle, int category)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_DeleteCategory,"category=%d",category);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101) {
+ /* Emulate if not connected to PalmOS 2.0 */
+ int i, cat, attr;
+ recordid_t id_;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP DeleteCategory Emulating with: Handle: %d, "
+ "Category: %d\n",
+ dbhandle, category & 0xff));
+
+ for (i = 0;
+ (result = dlp_ReadRecordByIndex(sd, dbhandle, i, NULL, &id_,
+ &attr, &cat)) >= 0; i++) {
+ if (cat != category
+ || (attr & dlpRecAttrDeleted)
+ || (attr & dlpRecAttrArchived))
+ continue;
+ result = dlp_DeleteRecord(sd, dbhandle, 0, id_);
+ if (result < 0)
+ break;
+ i--; /* Sigh, deleting record moves it to the end. */
+ }
+
+ return result;
+ } else {
+ int flags = 0x40;
+
+ req = dlp_request_new(dlpFuncDeleteRecord, 1, 6);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), flags);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), category & 0xff);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+ }
+}
+
+int
+dlp_ReadResourceByType(int sd, int dbhandle, unsigned long type, int resID,
+ pi_buffer_t *buffer, int *resindex)
+{
+ int result,
+ data_len;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
+
+ TraceX(dlp_ReadResourceByType,"type='%4.4s' resID=%d",(const char *)&type,resID);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new_with_argid(dlpFuncReadResource, 0x21, 1, 12);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), type);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
+ set_short(DLP_REQUEST_DATA(req, 0, 8), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 10), buffer ? maxBufferSize : 0);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - 10;
+ if (resindex)
+ *resindex = get_short(DLP_RESPONSE_DATA(res, 0, 6));
+ if (buffer) {
+ pi_buffer_clear (buffer);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
+ (size_t)data_len);
+
+ /* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
+ ** record is almost at the maximum record size. The following mitigates this and allows the record
+ ** to be read in two chunks.
+ */
+ if (data_len == maxBufferSize) {
+ dlp_response_free(res);
+ req = dlp_request_new_with_argid(dlpFuncReadResource, 0x21, 1, 12);
+ if (req != NULL) {
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), type);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
+ set_short(DLP_REQUEST_DATA(req, 0, 8), maxBufferSize); /* Offset in record */
+ set_short(DLP_REQUEST_DATA(req, 0, 10), RECORD_READ_SAFEGUARD_SIZE);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - 10; /* number of bytes returned by the second read... */
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10), (size_t)data_len);
+ data_len += maxBufferSize; /* ...that add up to the bytes received in the first read */
+ }
+ }
+ }
+ }
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadResourceByType Type: '%s', ID: %d, "
+ "Index: %d, and %d bytes:\n",
+ printlong(type), resID,
+ get_short(DLP_RESPONSE_DATA(res, 0, 6)),(size_t)data_len));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 10),(size_t)data_len));
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_ReadResourceByIndex(int sd, int dbhandle, unsigned int resindex, pi_buffer_t *buffer,
+ unsigned long *type, int *resID)
+{
+ int result,
+ data_len,
+ large = 0;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
+
+ TraceX(dlp_ReadResourceByIndex,"resindex=%d",resindex);
+ pi_reset_errors(sd);
+
+ /* TapWave (DLP 1.4) implements a `large' version of dlpFuncReadResource,
+ * which can return resources >64k
+ */
+ if (pi_version(sd) >= 0x0104) {
+ req = dlp_request_new (dlpFuncReadResourceEx, 1, 12);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), resindex);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), 0);
+ set_long(DLP_REQUEST_DATA(req, 0, 8), pi_maxrecsize(sd));
+ large = 1;
+ } else {
+ req = dlp_request_new (dlpFuncReadResource, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), resindex);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), maxBufferSize);
+ }
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - (large ? 12 : 10);
+ if (type)
+ *type = get_long(DLP_RESPONSE_DATA(res, 0, 0));
+ if (resID)
+ *resID = get_short(DLP_RESPONSE_DATA(res, 0, 4));
+ if (buffer) {
+ pi_buffer_clear (buffer);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 12 : 10),
+ (size_t)data_len);
+
+ /* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
+ ** record is almost at the maximum record size. The following mitigates this and allows the record
+ ** to be read in two chunks.
+ */
+ if (data_len == maxBufferSize && !large) {
+ dlp_response_free(res);
+ req = dlp_request_new (dlpFuncReadResource, 1, 8);
+ if (req != NULL) {
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), resindex);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), maxBufferSize); /* Offset in record */
+ set_short(DLP_REQUEST_DATA(req, 0, 6), RECORD_READ_SAFEGUARD_SIZE);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - (large ? 12 : 10); /* number of bytes returned by the second read... */
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 12 : 10),
+ (size_t)data_len);
+ data_len += maxBufferSize; /* ...that add up to the bytes received in the first read */
+ }
+ }
+ }
+ }
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadResourceByIndex Type: '%s', ID: %d, "
+ "Index: %d, and %d bytes:\n",
+ printlong(get_long(DLP_RESPONSE_DATA(res, 0, 0))),
+ get_short(DLP_RESPONSE_DATA(res, 0, 4)),
+ resindex, data_len));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, (large ? 12 : 10)),
+ (size_t)data_len));
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_WriteResource(int sd, int dbhandle, unsigned long type, int resID,
+ const void *data, size_t length)
+{
+ int result,
+ large = 0;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_WriteResource,"'%4.4s' #%d",(const char *)&type,resID);
+ pi_reset_errors(sd);
+
+ /* TapWave (DLP 1.4) implements a `large' version of dlpFuncWriteResource,
+ * which can store records >64k
+ */
+ if (pi_version(sd) >= 0x0104) {
+ req = dlp_request_new_with_argid(dlpFuncWriteResourceEx,
+ PI_DLP_ARG_FIRST_ID | PI_DLP_ARG_FLAG_LONG, 1, 12 + length);
+ large = 1;
+ } else {
+ if (length > 0xffff)
+ length = 0xffff;
+ req = dlp_request_new(dlpFuncWriteResource, 1, 10 + length);
+ }
+ if (req == NULL) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP sd:%i large:%i dlp_request_new failed\n",
+ sd, large));
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), type);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
+ if (large)
+ set_long (DLP_REQUEST_DATA(req, 0, 8), 0); /* device doesn't want length here (it computes it) */
+ else
+ set_short(DLP_REQUEST_DATA(req, 0, 8), length);
+
+ memcpy(DLP_REQUEST_DATA(req, 0, large ? 12 : 10), data, length);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+
+int
+dlp_DeleteResource(int sd, int dbhandle, int all, unsigned long restype,
+ int resID)
+{
+ int result,
+ flags = all ? 0x80 : 0;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_DeleteResource,"restype='%4.4s' resID=%d all=%d",
+ (const char *)&restype,resID,all);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncDeleteResource, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), flags);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), restype);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ReadAppBlock(int sd, int dbhandle, int offset, int reqbytes, pi_buffer_t *retbuf)
+{
+ int result,
+ data_len;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadAppBlock,"offset=%d reqbytes=%ld",offset,reqbytes);
+ pi_reset_errors(sd);
+
+ if (retbuf)
+ pi_buffer_clear(retbuf);
+
+ req = dlp_request_new(dlpFuncReadAppBlock, 1, 6);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), offset);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), reqbytes);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result >= 0) {
+ if (result < 2)
+ data_len = PI_ERR_DLP_COMMAND;
+ else {
+ data_len = res->argv[0]->len - 2;
+ if (retbuf && data_len)
+ pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 2),
+ (size_t)data_len);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadAppBlock %d bytes\n", data_len));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 2),
+ (size_t)data_len));
+ }
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_WriteAppBlock(int sd, int dbhandle, const /* @unique@ */ void *data,
+ size_t length)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_WriteAppBlock,"length=%ld",length);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncWriteAppBlock, 1, 4 + length);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), length);
+
+ if (length + 10 > DLP_BUF_SIZE) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP WriteAppBlock: data too large (>64k)"));
+ pi_set_error(sd, PI_ERR_DLP_DATASIZE);
+ return -131;
+ }
+ if (length)
+ memcpy(DLP_REQUEST_DATA(req, 0, 4), data, length);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ReadSortBlock(int sd, int dbhandle, int offset, int reqbytes, pi_buffer_t *retbuf)
+{
+ int result,
+ data_len;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadSortBlock,"offset=%d reqbytes=%d",offset,reqbytes);
+ pi_reset_errors(sd);
+
+ if (retbuf)
+ pi_buffer_clear(retbuf);
+
+ req = dlp_request_new(dlpFuncReadSortBlock, 1, 6);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), offset);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), reqbytes);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result >= 0) {
+ if (result < 2)
+ data_len = PI_ERR_DLP_COMMAND;
+ else {
+ data_len = res->argv[0]->len - 2;
+ if (retbuf)
+ pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 2),
+ (size_t)data_len);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadSortBlock %d bytes\n", data_len));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 2),
+ (size_t)data_len));
+ }
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_WriteSortBlock(int sd, int dbhandle, const /* @unique@ */ void *data,
+ size_t length)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_WriteSortBlock,"length=%ld",length);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncWriteSortBlock, 1, 4 + length);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), length);
+
+ if (length + 10 > DLP_BUF_SIZE) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP WriteSortBlock: data too large (>64k)"));
+ pi_set_error(sd, PI_ERR_DLP_DATASIZE);
+ return -131;
+ }
+ memcpy(DLP_REQUEST_DATA(req, 0, 4), data, length);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_CleanUpDatabase(int sd, int dbhandle)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_CleanUpDatabase);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncCleanUpDatabase, 1, 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ResetSyncFlags(int sd, int dbhandle)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dpl_ResetSyncFlags);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncResetSyncFlags, 1, 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ReadNextRecInCategory(int sd, int dbhandle, int category,
+ pi_buffer_t *buffer, recordid_t *recuid, int *recindex,
+ int *attr)
+{
+ int result,
+ data_len,
+ flags;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadNextRecInCategory,"category=%d",category);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101) {
+ /* Emulate for PalmOS 1.0 */
+ int cat,
+ rec;
+ pi_socket_t *ps;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadNextRecInCategory Emulating with: Handle: %d, "
+ "Category: %d\n",
+ dbhandle, category));
+
+ if ((ps = find_pi_socket(sd)) == 0) {
+ errno = ESRCH;
+ return -130;
+ }
+
+ for (;;) {
+ /* Fetch next modified record (in any category) */
+ rec = dlp_ReadRecordByIndex(sd, dbhandle,
+ ps->dlprecord, 0, 0,
+ 0, &cat);
+
+ if (rec < 0)
+ break;
+
+ if (cat != category) {
+ ps->dlprecord++;
+ continue;
+ }
+
+ rec = dlp_ReadRecordByIndex(sd, dbhandle,
+ ps->dlprecord, buffer,
+ recuid, attr, &cat);
+
+ if (rec >= 0) {
+ if (recindex)
+ *recindex = ps->dlprecord;
+ ps->dlprecord++;
+ } else {
+ /* If none found, reset modified pointer so
+ that another search on a different (or
+ the same!) category will work */
+
+ /* Freeow! Do _not_ reset, as the Palm
+ itself does not!
+
+ ps->dlprecord = 0; */
+ }
+
+ break;
+ }
+
+ return rec;
+ }
+
+ req = dlp_request_new(dlpFuncReadNextRecInCategory, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), category);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - 10;
+ if (recuid)
+ *recuid = get_long(DLP_RESPONSE_DATA(res, 0, 0));
+ if (recindex)
+ *recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
+ if (attr)
+ *attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
+ if (buffer) {
+ pi_buffer_clear (buffer);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
+ (size_t)data_len);
+ }
+
+ flags = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadNextRecInCategory ID: 0x%8.8lX, "
+ "Index: %d, Category: %d\n"
+ " Flags: %s%s%s%s%s%s (0x%2.2X) and %d bytes:\n",
+ (unsigned long) get_long(DLP_RESPONSE_DATA(res,
+ 0, 0)),
+ get_short(DLP_RESPONSE_DATA(res, 0, 4)),
+ (int) get_byte(DLP_RESPONSE_DATA(res, 0, 9)),
+ (flags & dlpRecAttrDeleted) ? " Deleted" : "",
+ (flags & dlpRecAttrDirty) ? " Dirty" : "",
+ (flags & dlpRecAttrBusy) ? " Busy" : "",
+ (flags & dlpRecAttrSecret) ? " Secret" : "",
+ (flags & dlpRecAttrArchived) ? " Archive" : "",
+ (!flags) ? " None" : "",
+ flags, data_len));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 10),
+ (size_t)data_len));
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_ReadAppPreference(int sd, unsigned long creator, int prefID, int backup,
+ int maxsize, void *buffer, size_t *size, int *version)
+{
+ int result,
+ data_len;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadAppPreference,"creator='%4.4s' prefID=%d backup=%d maxsize=%d",
+ (const char *)creator,prefID,backup,maxsize);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101) {
+ /* Emulate on PalmOS 1.0 */
+ int db;
+ pi_buffer_t *buf;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadAppPreference Emulating with: Creator: '%s', "
+ "Id: %d, Size: %d, Backup: %d\n",
+ printlong(creator), prefID,
+ buffer ? maxsize : 0, backup ? 0x80 : 0));
+
+ result = dlp_OpenDB(sd, 0, dlpOpenRead, "System Preferences", &db);
+ if (result < 0)
+ return result;
+
+ buf = pi_buffer_new (1024);
+
+ result = dlp_ReadResourceByType(sd, db, creator, prefID, buf,NULL);
+
+ if (result < 0) {
+ /* have to keep the previous error codes to properly return it */
+ int err1 = pi_error(sd);
+ int err2 = pi_palmos_error(sd);
+
+ pi_buffer_free (buf);
+ if (err1 != PI_ERR_SOCK_DISCONNECTED)
+ dlp_CloseDB(sd, db);
+
+ pi_set_error(sd, err1);
+ pi_set_palmos_error(sd, err2);
+ return result;
+ }
+
+ if (size)
+ *size = buf->used - 2;
+
+ if (version)
+ *version = get_short(buf->data);
+
+ if (result > 2) {
+ result -= 2;
+ memcpy(buffer, buf->data + 2, (size_t)result);
+ } else {
+ result = 0;
+ }
+
+ pi_buffer_free (buf);
+ dlp_CloseDB(sd, db);
+ return result;
+ }
+
+ req = dlp_request_new(dlpFuncReadAppPreference, 1, 10);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), prefID);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), buffer ? maxsize : 0);
+ set_byte(DLP_REQUEST_DATA(req, 0, 8), backup ? 0x80 : 0);
+ set_byte(DLP_REQUEST_DATA(req, 0, 9), 0); /* Reserved */
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = get_short(DLP_RESPONSE_DATA(res, 0, 4));
+ if (version)
+ *version = get_short(DLP_RESPONSE_DATA(res, 0, 0));
+ if (size && !buffer) *size =
+ get_short(DLP_RESPONSE_DATA(res, 0, 2)); /* Total sz */
+ if (size && buffer)
+ *size = data_len; /* Size returned */
+ if (buffer)
+ memcpy(buffer, DLP_RESPONSE_DATA(res, 0, 6),
+ (size_t)data_len);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadAppPref Version: %d, "
+ "Total size: %d, Read %d bytes:\n",
+ get_short(DLP_RESPONSE_DATA(res, 0, 0)),
+ get_short(DLP_RESPONSE_DATA(res, 0, 2)),
+ get_short(DLP_RESPONSE_DATA(res, 0, 4))));
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 6),
+ (size_t)data_len));
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_WriteAppPreference(int sd, unsigned long creator, int prefID, int backup,
+ int version, const void *buffer, size_t size)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_WriteAppPreference,"creator='%4.4s' prefID=%d backup=%d version=%d size=%ld",
+ (const char *)&creator,prefID,backup,version,size);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101) {
+ /* Emulate on PalmOS 1.0 */
+ int db,
+ err1,
+ err2;
+
+ if ((result = dlp_OpenDB(sd, 0, dlpOpenWrite, "System Preferences",
+ &db)) < 0)
+ return result;
+
+ if (buffer && size) {
+ unsigned char dlp_buf[DLP_BUF_SIZE];
+ memcpy(dlp_buf + 2, buffer, size);
+ set_short(dlp_buf, version);
+ result = dlp_WriteResource(sd, db, creator, prefID, dlp_buf,
+ size);
+ } else {
+ result = dlp_WriteResource(sd, db, creator, prefID, NULL,
+ 0);
+ }
+ err1 = pi_error(sd);
+ err2 = pi_palmos_error(sd);
+
+ if (err1 != PI_ERR_SOCK_DISCONNECTED)
+ dlp_CloseDB(sd, db);
+
+ if (result < 0) {
+ /* restore previous error after DB close */
+ pi_set_error(sd, err1);
+ pi_set_palmos_error(sd, err2);
+ }
+ return result;
+ }
+
+ req = dlp_request_new(dlpFuncWriteAppPreference, 1, 12 + size);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), prefID);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), version);
+ set_short(DLP_REQUEST_DATA(req, 0, 8), size);
+ set_byte(DLP_REQUEST_DATA(req, 0, 10), backup ? 0x80 : 0);
+ set_byte(DLP_REQUEST_DATA(req, 0, 11), 0); /* Reserved */
+
+ if ((size + 12) > DLP_BUF_SIZE) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
+ "DLP WriteAppPreferenceV2: data too large (>64k)"));
+ return PI_ERR_DLP_DATASIZE;
+ }
+ memcpy(DLP_REQUEST_DATA(req, 0, 12), buffer, size);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ReadNextModifiedRecInCategory(int sd, int dbhandle, int category,
+ pi_buffer_t *buffer, recordid_t *recID,
+ int *recindex, int *attr)
+{
+ int result,
+ data_len;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ TraceX(dlp_ReadNextModifiedRecInCategory,"category=%d",category);
+ pi_reset_errors(sd);
+
+ if (pi_version(sd) < 0x0101) {
+ /* Emulate for PalmOS 1.0 */
+ int cat;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ReadNextModifiedRecInCategory"
+ " Emulating with: Handle: %d, Category: %d\n",
+ dbhandle, category));
+
+ do {
+ /* Fetch next modified record (in any category) */
+ result = dlp_ReadNextModifiedRec(sd, dbhandle, buffer,
+ recID, recindex, attr, &cat);
+
+ /* If none found, reset modified pointer so that
+ another search on a different (or the same!) category
+ will start from the beginning */
+
+ /* Working on same assumption as ReadNextRecInCat,
+ elide this:
+ if (r < 0)
+ dlp_ResetDBIndex(sd, fHandle);
+ */
+
+ /* Loop until we fail to get a record or a record
+ is found in the proper category */
+ }
+ while (result >= 0 && cat != category);
+
+ return result;
+ }
+
+ req = dlp_request_new(dlpFuncReadNextModifiedRecInCategory, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), category);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ data_len = res->argv[0]->len - 10;
+
+ if (recID)
+ *recID = get_long(DLP_RESPONSE_DATA(res, 0, 0));
+ if (recindex)
+ *recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
+ if (attr)
+ *attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
+
+ if (buffer) {
+ pi_buffer_clear (buffer);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
+ (size_t)data_len);
+ }
+
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ record_dump(
+ get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
+ get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
+ get_byte(DLP_RESPONSE_DATA(res, 0, 8)), /* flags */
+ get_byte(DLP_RESPONSE_DATA(res, 0, 9)), /* catID */
+ DLP_RESPONSE_DATA(res, 0, 10), data_len));
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_ReadNextModifiedRec(int sd, int dbhandle, pi_buffer_t *buffer, recordid_t * recID,
+ int *recindex, int *attr, int *category)
+{
+ int result,
+ data_len;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ Trace(dlp_ReadNextModifiedRec);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncReadNextModifiedRec, 1, 1);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result >= 0) {
+ data_len = res->argv[0]->len -10;
+ if (recID)
+ *recID = get_long(DLP_RESPONSE_DATA(res, 0, 0));
+ if (recindex)
+ *recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
+ if (attr)
+ *attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
+ if (category)
+ *category = get_byte(DLP_RESPONSE_DATA(res, 0, 9));
+
+ if (buffer) {
+ pi_buffer_clear (buffer);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
+ (size_t)data_len);
+ }
+
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ record_dump(
+ get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
+ get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
+ get_byte(DLP_RESPONSE_DATA(res, 0, 8)), /* flags */
+ get_byte(DLP_RESPONSE_DATA(res, 0, 9)), /* catID */
+ DLP_RESPONSE_DATA(res, 0, 10), data_len));
+ } else {
+ data_len = result;
+ }
+
+ dlp_response_free(res);
+
+ return data_len;
+}
+
+int
+dlp_ReadRecordById(int sd, int dbhandle, recordid_t recuid, pi_buffer_t *buffer,
+ int *recindex, int *attr, int *category)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
+
+ TraceX(dlp_ReadRecordById,"recuid=0x%08lx",recuid);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncReadRecord, 1, 10);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), recuid);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), 0); /* Offset into record */
+ set_short(DLP_REQUEST_DATA(req, 0, 8), buffer ? maxBufferSize : 0); /* length to return */
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ result = res->argv[0]->len - 10;
+ if (recindex)
+ *recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
+ if (attr)
+ *attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
+ if (category)
+ *category = get_byte(DLP_RESPONSE_DATA(res, 0, 9));
+ if (buffer) {
+ pi_buffer_clear (buffer);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
+ (size_t)result);
+
+ /* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
+ ** record is almost at the maximum record size. The following mitigates this and allows the record
+ ** to be read in two chunks.
+ */
+ if (result == maxBufferSize) {
+ dlp_response_free(res);
+ req = dlp_request_new(dlpFuncReadRecord, 1, 10);
+ if (req != NULL) {
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
+ set_long(DLP_REQUEST_DATA(req, 0, 2), recuid);
+ set_short(DLP_REQUEST_DATA(req, 0, 6), maxBufferSize); /* Offset into record */
+ set_short(DLP_REQUEST_DATA(req, 0, 8), buffer ? RECORD_READ_SAFEGUARD_SIZE : 0); /* length to return */
+
+ result = dlp_exec(sd, req, &res);
+ dlp_request_free(req);
+
+ if (result > 0) {
+ result = res->argv[0]->len - 10;
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
+ (size_t)result);
+ result += maxBufferSize;
+ }
+ }
+ }
+ }
+
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ record_dump(
+ get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
+ get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
+ get_byte(DLP_RESPONSE_DATA(res, 0, 8)), /* flags */
+ get_byte(DLP_RESPONSE_DATA(res, 0, 9)), /* catID */
+ DLP_RESPONSE_DATA(res, 0, 10), result));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ReadRecordByIndex(int sd, int dbhandle, int recindex, pi_buffer_t *buffer,
+ recordid_t * recuid, int *attr, int *category)
+{
+ int result,
+ large = 0;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
+
+ TraceX(dlp_ReadRecordByIndex,"recindex=%d",recindex);
+ pi_reset_errors(sd);
+
+ /* TapWave (DLP 1.4) implements a `large' version of dlpFuncReadRecord,
+ * which can return records >64k
+ */
+ if (pi_version(sd) >= 0x0104) {
+ req = dlp_request_new_with_argid(dlpFuncReadRecordEx, 0x21, 1, 12);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x00);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), recindex);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), 0); /* Offset into record */
+ set_long(DLP_REQUEST_DATA(req, 0, 8), pi_maxrecsize(sd)); /* length to return */
+ large = 1;
+ } else {
+ req = dlp_request_new_with_argid(dlpFuncReadRecord, 0x21, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x00);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), recindex);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), 0); /* Offset into record */
+ set_short(DLP_REQUEST_DATA(req, 0, 6), buffer ? maxBufferSize : 0); /* length to return */
+ }
+ result = dlp_exec(sd, req, &res);
+ dlp_request_free(req);
+
+ if (result > 0) {
+ result = res->argv[0]->len - (large ? 14 : 10);
+ if (recuid)
+ *recuid = get_long(DLP_RESPONSE_DATA(res, 0, 0));
+ if (attr)
+ *attr = get_byte(DLP_RESPONSE_DATA(res, 0, large ? 12 : 8));
+ if (category)
+ *category = get_byte(DLP_RESPONSE_DATA(res, 0, large ? 13 : 9));
+ if (buffer) {
+ pi_buffer_clear (buffer);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 14 : 10),
+ (size_t)result);
+
+ /* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
+ ** record is almost at the maximum record size. The following mitigates this and allows the record
+ ** to be read in two chunks.
+ */
+ if (result == maxBufferSize && !large) {
+ dlp_response_free(res);
+ req = dlp_request_new_with_argid(dlpFuncReadRecord, 0x21, 1, 8);
+ if (req != NULL) {
+ set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
+ set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x00);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), recindex);
+ set_short(DLP_REQUEST_DATA(req, 0, 4), maxBufferSize); /* Offset into record */
+ set_short(DLP_REQUEST_DATA(req, 0, 6), buffer ? RECORD_READ_SAFEGUARD_SIZE : 0); /* length to return */
+
+ result = dlp_exec(sd, req, &res);
+ dlp_request_free(req);
+
+ if (result > 0) {
+ result = res->argv[0]->len - (large ? 14 : 10);
+ pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 14 : 10),
+ (size_t)result);
+
+ result += maxBufferSize;
+ }
+ }
+ }
+ }
+
+ CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
+ record_dump(
+ get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recUID */
+ get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
+ get_byte(DLP_RESPONSE_DATA(res, 0, large ? 12 : 8)), /* flags */
+ get_byte(DLP_RESPONSE_DATA(res, 0, large ? 13 : 9)), /* catID */
+ DLP_RESPONSE_DATA(res, 0, large ? 14 : 10), result));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ExpSlotEnumerate(int sd, int *numSlots, int *slotRefs)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ Trace(dlp_ExpSlotEnumerate);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncExpSlotEnumerate, 0);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ int slots, i;
+
+ slots = get_short(DLP_RESPONSE_DATA (res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ExpSlotEnumerate %d\n", slots));
+
+ if (slots) {
+ for (i = 0; i < slots && i < *numSlots; i++) {
+ slotRefs[i] =
+ get_short(DLP_RESPONSE_DATA (res, 0,
+ 2 + (2 * i)));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " %d Slot-Refnum %d\n", i, slotRefs[i]));
+ }
+ }
+
+ *numSlots = slots;
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ExpCardPresent(int sd, int slotRef)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_ExpCardPresent,"slotRef=%d",slotRef);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncExpCardPresent, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short(DLP_REQUEST_DATA(req, 0, 0), slotRef);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_ExpCardInfo(int sd, int slotRef, unsigned long *flags, int *numStrings,
+ char **strings)
+{
+ int result;
+ struct dlpRequest* req;
+ struct dlpResponse* res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_ExpCardInfo,"slotRef=%d",slotRef);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncExpCardInfo, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short(DLP_REQUEST_DATA(req, 0, 0), slotRef);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ *flags = get_long(DLP_RESPONSE_DATA (res, 0, 0));
+ *numStrings = get_byte(DLP_RESPONSE_DATA (res, 0, 4));
+
+ if (strings && *numStrings) {
+ int i, len, sz = 0;
+ char *p = DLP_RESPONSE_DATA (res, 0, 8);
+
+ for (i=0; i < *numStrings; i++, sz+=len, p+=len)
+ len = strlen (p) + 1;
+
+ *strings = (char *) malloc ((size_t)sz);
+ if (*strings)
+ memcpy (*strings, DLP_RESPONSE_DATA (res, 0, 8), (size_t)sz);
+ else
+ result = pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP ExpCardInfo flags: 0x%08lx numStrings: %d\n",
+ *flags, *numStrings));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSGetDefaultDir(int sd, int volRefNum, const char *type, char *dir,
+ int *len)
+{
+ int result, buflen;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSGetDefaultDir,"volRefNum=%d",volRefNum);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncVFSGetDefaultDir,
+ 1, 2 + (strlen(type) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short(DLP_REQUEST_DATA(req, 0, 0), volRefNum);
+ strcpy(DLP_REQUEST_DATA(req, 0, 2), type);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ buflen = get_short(DLP_RESPONSE_DATA (res, 0, 0));
+
+ if (*len < buflen + 1)
+ result = pi_set_error(sd, PI_ERR_DLP_BUFSIZE);
+ else {
+ if (buflen)
+ strncpy(dir, DLP_RESPONSE_DATA (res, 0, 2),
+ (size_t)buflen);
+ else
+ dir[0] = '\0';
+
+ *len = buflen;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Default dir is %s\n", dir));
+ }
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSImportDatabaseFromFile(int sd, int volRefNum, const char *path,
+ int *cardno, unsigned long *localid)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSImportDatabaseFromFile,"volRefNum=%d path='%s'",volRefNum,path);
+ pi_reset_errors(sd);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Import file <%s>%d\n", path));
+
+ req = dlp_request_new(dlpFuncVFSImportDatabaseFromFile,
+ 1, 2 + (strlen(path) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short(DLP_REQUEST_DATA(req, 0, 0), volRefNum);
+ strcpy(DLP_REQUEST_DATA(req, 0, 2), path);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+
+ if (result > 0) {
+ if (cardno)
+ *cardno = get_short(DLP_RESPONSE_DATA (res, 0, 0));
+ if (localid)
+ *localid = get_short(DLP_RESPONSE_DATA (res, 0, 2));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Database imported as: cardNo:%d dbID:%d\n",
+ get_short(DLP_RESPONSE_DATA (res, 0, 0)),
+ get_short(DLP_RESPONSE_DATA (res, 0, 2))));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSExportDatabaseToFile(int sd, int volRefNum, const char *path,
+ int cardno, unsigned int localid)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSExportDatabaseToFile,"cardno=%d localid=0x%08lx volRefNum=%d path='%s'",
+ cardno,(long)localid,volRefNum,path);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncVFSExportDatabaseToFile,
+ 1, 8 + (strlen(path) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short(DLP_REQUEST_DATA(req, 0, 0), volRefNum);
+ set_short(DLP_REQUEST_DATA(req, 0, 2), cardno);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), localid);
+ strcpy(DLP_REQUEST_DATA(req, 0, 8), path);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSFileCreate(int sd, int volRefNum, const char *name)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileCreate,"volRefNum=%d name='%s'",volRefNum,name);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileCreate, 1, 2 + (strlen(name) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+ strcpy (DLP_REQUEST_DATA (req, 0, 2), name);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileOpen(int sd, int volRefNum, const char *path, int openMode,
+ FileRef *fileRef)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileOpen,"volRefNum=%d mode=0x%04x path='%s'",
+ volRefNum,openMode,path);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileOpen, 1, 4 + (strlen (path) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+ set_short (DLP_REQUEST_DATA (req, 0, 2), openMode);
+ strcpy (DLP_REQUEST_DATA (req, 0, 4), path);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ *fileRef = get_long(DLP_RESPONSE_DATA (res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "OpenFileRef: 0x%x\n", *fileRef));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSFileClose(int sd, FileRef fileRef)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileClose,"fileRef=%ld",fileRef);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileClose, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Closed FileRef: %x\n", fileRef));
+
+ return result;
+}
+
+int
+dlp_VFSFileWrite(int sd, FileRef fileRef, const void *data, size_t len)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res = NULL;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileWrite,"fileRef=%ld len=%ld",(long)fileRef,(long)len);
+ pi_reset_errors(sd);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Write to FileRef: %x bytes %d\n", fileRef, len));
+
+ req = dlp_request_new (dlpFuncVFSFileWrite, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+ set_long (DLP_REQUEST_DATA (req, 0, 4), len);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result >= 0) {
+ int bytes = pi_write (sd, data, len);
+ result = bytes;
+ if (result < (int)len) {
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "send failed %d\n", result));
+ } else {
+ dlp_response_free (res);
+ res = NULL;
+
+ result = dlp_response_read (&res, sd);
+
+ if (result > 0) {
+ pi_set_palmos_error(sd, get_short(DLP_RESPONSE_DATA (res, 0, 2)));
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "send success (%d) res 0x%04x!\n", len, pi_palmos_error(sd)));
+ result = bytes;
+ }
+ }
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileRead(int sd, FileRef fileRef, pi_buffer_t *data, size_t len)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+ size_t bytes = 0;
+ int freeze_txid = 1;
+ size_t opt_size = sizeof(int);
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileRead,"fileRef=%ld len=%ld",(long)fileRef,(long)len);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileRead, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+ set_long (DLP_REQUEST_DATA (req, 0, 4), len);
+
+ /* if we're using PADP, this socket option is required so that
+ * the transfer can complete without error
+ */
+ pi_setsockopt(sd, PI_LEVEL_PADP, PI_PADP_FREEZE_TXID, &freeze_txid, &opt_size);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ pi_buffer_clear (data);
+
+ if (result >= 0) {
+
+ do {
+ result = pi_read(sd, data, len);
+ if (result > 0) {
+ len -= result;
+ bytes += result;
+ }
+ } while (result > 0 && len > 0);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "dlp_VFSFileRead: read %u bytes (last pi_read was %d)\n",
+ (unsigned)bytes, result));
+
+ if (result >= 0)
+ result = bytes;
+ }
+
+ dlp_response_free(res);
+
+ freeze_txid = 0;
+ pi_setsockopt(sd, PI_LEVEL_PADP, PI_PADP_FREEZE_TXID, &freeze_txid, &opt_size);
+
+ return result;
+}
+
+int
+dlp_VFSFileDelete(int sd, int volRefNum, const char *path)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileDelete,"volRefNum=%d path='%s'",volRefNum,path);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileDelete, 1, 2 + (strlen (path) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+ strcpy (DLP_REQUEST_DATA (req, 0, 2), path);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileRename(int sd, int volRefNum, const char *path,
+ const char *newname)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileRename,"volRefNum=%d file '%s' renamed '%s'",
+ volRefNum,path,rename);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileRename,
+ 1, 4 + (strlen (path) + 1) + (strlen (newname) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+ set_short (DLP_REQUEST_DATA (req, 0, 2), 2);
+ strcpy (DLP_REQUEST_DATA (req, 0, 4), path);
+ strcpy (DLP_REQUEST_DATA (req, 0, 4 + (strlen(path) + 1)), newname);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileEOF(int sd, FileRef fileRef)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileEOF,"fileRef=%ld",fileRef);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileEOF, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileTell(int sd, FileRef fileRef,int *position)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileTell,"fileRef=%ld",fileRef);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncVFSFileTell, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ *position = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileGetAttributes (int sd, FileRef fileRef, unsigned long *attributes)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileGetAttributes,"fileRef=%ld",fileRef);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileGetAttributes, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ *attributes = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSFileSetAttributes(int sd, FileRef fileRef, unsigned long attributes)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileSetAttributes,"fileRef=%ld attributes=0x%08lx",
+ fileRef,attributes);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileSetAttributes, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+ set_long (DLP_REQUEST_DATA (req, 0, 4), attributes);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileGetDate(int sd, FileRef fileRef, int which, time_t *date)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileGetDate,"fileRef=%ld which=%d",fileRef,which);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileGetDate, 1, 6);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+ set_short (DLP_REQUEST_DATA (req, 0, 4), which);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ *date = get_long (DLP_RESPONSE_DATA (res, 0, 0)) - 2082852000;
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Requested date(%d): %d / %x calc %d / %x\n",which,
+ get_long(DLP_RESPONSE_DATA (res, 0, 0)),
+ get_long(DLP_RESPONSE_DATA (res, 0, 0)),
+ *date,*date));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileSetDate(int sd, FileRef fileRef, int which, time_t date)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileSetDate,"fileRef=%ld which=%d date=0x%08lx",
+ (long)fileRef,which,(long)date);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncVFSFileSetDate, 1, 10);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA(req, 0, 0), fileRef);
+ set_short (DLP_REQUEST_DATA(req, 0, 4), which);
+ set_long (DLP_REQUEST_DATA(req, 0, 6), date + 2082852000);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSDirCreate(int sd, int volRefNum, const char *path)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSDirCreate,"volRefNum=%d path='%s'",volRefNum,path);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSDirCreate, 1, 2 + (strlen(path) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+ strcpy (DLP_REQUEST_DATA (req, 0, 2), path);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSDirEntryEnumerate(int sd, FileRef dirRefNum,
+ unsigned long *dirIterator, int *maxDirItems, struct VFSDirInfo *data)
+{
+ unsigned int result,
+ entries,
+ from,
+ at,
+ slen,
+ count;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSDirEntryEnumerate,"dirRef=%ld",dirRefNum);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSDirEntryEnumerate, 1, 12);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), dirRefNum);
+ set_long (DLP_REQUEST_DATA (req, 0, 4), *dirIterator);
+ set_long (DLP_REQUEST_DATA (req, 0, 8), 8 + *maxDirItems * (4 + vfsMAXFILENAME));
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ if (result) {
+ *dirIterator = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+ entries = get_long (DLP_RESPONSE_DATA (res, 0, 4));
+ } else {
+ *dirIterator = vfsIteratorStop;
+ entries = 0;
+ }
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "%d results returnd (ilterator: %d)\n", entries,
+ *dirIterator));
+
+ from = 8;
+ count = 0;
+
+ for (at = 0; at < entries; at++) {
+ if (*maxDirItems > at) {
+ data[at].attr =
+ get_long(DLP_RESPONSE_DATA (res, 0, from));
+
+ /* fix for Sony sims (and probably devices too): they return
+ the attributes in the high word of attr instead of the low
+ word. We can safely shift it since the high 16 bits are not
+ used for VFS flags */
+ if ((data[at].attr & 0x0000FFFF) == 0 &&
+ (data[at].attr & 0xFFFF0000) != 0)
+ data[at].attr >>= 16;
+
+ strncpy (data[at].name,
+ DLP_RESPONSE_DATA(res, 0, from + 4),
+ vfsMAXFILENAME);
+ data[at].name[vfsMAXFILENAME-1] = 0;
+ count++;
+ }
+
+ /* Zero terminated string. Strings that have an
+ even length will be null terminated and have a
+ pad byte. */
+ slen = strlen (DLP_RESPONSE_DATA(res, 0, from + 4)) + 1;
+ if (slen & 1)
+ slen++; /* make even stringlen + NULL */
+
+ /* 6 = 4 (attr) + 1 (NULL) -+ 1 (PADDING) */
+ from += slen + 4;
+ }
+ *maxDirItems = count;
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSVolumeFormat(int sd, unsigned char flags,
+ int fsLibRef, struct VFSSlotMountParam *param)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ Trace(dlp_VFSVolumeFormat);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncVFSVolumeFormat, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+/* FIXME check sizes, list the mount params properly */
+ set_short(DLP_REQUEST_DATA(req, 0, 0), fsLibRef);
+ set_short(DLP_REQUEST_DATA(req, 0, 2),
+ sizeof(struct VFSSlotMountParam));
+ set_byte(DLP_REQUEST_DATA(req, 0, 4), flags);
+ set_byte(DLP_REQUEST_DATA(req, 0, 4), 0); /* unused */
+
+ set_short(DLP_REQUEST_DATA(req, 0, 6), param->vfsMountParam.volRefNum);
+ set_short(DLP_REQUEST_DATA(req, 0, 8), param->vfsMountParam.reserved);
+ set_long(DLP_REQUEST_DATA(req, 0, 10), param->vfsMountParam.mountClass);
+ set_short(DLP_REQUEST_DATA(req, 0, 14), param->slotLibRefNum);
+ set_short(DLP_REQUEST_DATA(req, 0, 16), param->slotRefNum);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free(req);
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSVolumeEnumerate(int sd, int *numVols, int *volRefs)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ Trace(dlp_VFSVolumeEnumerate);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSVolumeEnumerate, 0);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ int vols, i;
+
+ vols = get_short (DLP_RESPONSE_DATA (res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP VFSVolumeEnumerate %d\n", vols));
+
+ if (vols) {
+ for (i = 0; i < vols && i < *numVols; i++) {
+ volRefs[i] =
+ get_short (DLP_RESPONSE_DATA (res,
+ 0, 2 + (2 * i)));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ " %d Volume-Refnum %d\n", i, volRefs[i]));
+ }
+ }
+ *numVols = vols;
+ }
+ else
+ *numVols = 0;
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSVolumeInfo(int sd, int volRefNum, struct VFSInfo *volInfo)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSVolumeInfo,"volRefNum=%d",volRefNum);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSVolumeInfo, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA(req, 0, 0), volRefNum);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ volInfo->attributes = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+ volInfo->fsType = get_long (DLP_RESPONSE_DATA (res, 0, 4));
+ volInfo->fsCreator = get_long (DLP_RESPONSE_DATA (res, 0, 8));
+ volInfo->mountClass = get_long (DLP_RESPONSE_DATA (res, 0, 12));
+ volInfo->slotLibRefNum = get_short (DLP_RESPONSE_DATA (res, 0, 16));
+ volInfo->slotRefNum = get_short (DLP_RESPONSE_DATA (res, 0, 18));
+ volInfo->mediaType = get_long (DLP_RESPONSE_DATA (res, 0, 20));
+ volInfo->reserved = get_long (DLP_RESPONSE_DATA (res, 0, 24));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "VFSVolumeInfo: fstype '%s' ", printlong(volInfo->fsType)));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "fscreator: '%s'\nSlotlibref %d Slotref %d\n",
+ printlong(volInfo->fsCreator),
+ volInfo->slotLibRefNum,
+ volInfo->slotRefNum));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "Media: '%s'\n", printlong(volInfo->mediaType)));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSVolumeGetLabel(int sd, int volRefNum, int *len, char *name)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSVolumeGetLabel,"volRefNum=%d",volRefNum);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSVolumeGetLabel, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ strncpy(name, DLP_RESPONSE_DATA(res, 0, 0),
+ (size_t)(*len - 1));
+ *len = strlen(name);
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP VFSVolumeGetLabel %s\n", name));
+ }
+
+ dlp_response_free(res);
+
+ return result;
+}
+
+int
+dlp_VFSVolumeSetLabel(int sd, int volRefNum, const char *name)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSVolumeSetLabel,"volRefNum=%d name='%s'",volRefNum,name);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSVolumeSetLabel, 1,
+ 2 + (strlen(name) + 1));
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+ strcpy (DLP_REQUEST_DATA (req, 0, 2), name);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_response_free (res);
+ dlp_request_free (req);
+
+ return result;
+}
+
+int
+dlp_VFSVolumeSize(int sd, int volRefNum, long *volSizeUsed,
+ long *volSizeTotal)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSVolumeSize,"volRefNum=%d",volRefNum);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSVolumeSize, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ *volSizeUsed = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+ *volSizeTotal = get_long (DLP_RESPONSE_DATA (res, 0, 4));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP VFS Volume Size total: %d used: %d\n",
+ *volSizeTotal, *volSizeUsed));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileSeek(int sd, FileRef fileRef, int origin, int offset)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileSeek,"fileRef=%ld origin=%d offset=%d",
+ fileRef,origin,offset);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileSeek, 1, 10);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+ set_short (DLP_REQUEST_DATA (req, 0, 4), origin);
+ set_long (DLP_REQUEST_DATA (req, 0, 6), offset);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileResize(int sd, FileRef fileRef, int newSize)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileResize,"fileRef=%ld newSize=%d",fileRef,newSize);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new(dlpFuncVFSFileResize, 1, 8);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long(DLP_REQUEST_DATA(req, 0, 0), fileRef);
+ set_long(DLP_REQUEST_DATA(req, 0, 4), newSize);
+
+ result = dlp_exec(sd, req, &res);
+
+ dlp_request_free (req);
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_VFSFileSize(int sd, FileRef fileRef, int *size)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1,2);
+ TraceX(dlp_VFSFileSize,"fileRef=%ld",fileRef);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncVFSFileSize, 1, 4);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ *size = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP VFS File Size: %d\n", *size));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+int
+dlp_ExpSlotMediaType(int sd, int slotNum, unsigned long *mediaType)
+{
+ int result;
+ struct dlpRequest *req;
+ struct dlpResponse *res;
+
+ RequireDLPVersion(sd,1, 4);
+ TraceX(dlp_ExpSlotMediaType,"slotNum=%d",slotNum);
+ pi_reset_errors(sd);
+
+ req = dlp_request_new (dlpFuncExpSlotMediaType, 1, 2);
+ if (req == NULL)
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+
+ set_short (DLP_REQUEST_DATA (req, 0, 0), slotNum);
+
+ result = dlp_exec (sd, req, &res);
+
+ dlp_request_free (req);
+
+ if (result > 0) {
+ *mediaType = get_long (DLP_RESPONSE_DATA (res, 0, 0));
+
+ LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
+ "DLP Media Type for slot %d: %4.4s\n",
+ slotNum, mediaType));
+ }
+
+ dlp_response_free (res);
+
+ return result;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/expense.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/expense.c
new file mode 100644
index 00000000..bbd06a6d
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/expense.c
@@ -0,0 +1,481 @@
+/*
+ * $Id: expense.c,v 1.29 2006/11/07 21:13:24 adridg Exp $
+ *
+ * expense.c: Translate Pilot expense tracker data formats
+ *
+ * Copyright (c) 1997, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-expense.h"
+
+char *ExpenseSortNames[] = { "Date", "Type", NULL };
+char *ExpenseDistanceNames[] = { "Miles", "Kilometers", NULL };
+char *ExpensePaymentNames[] =
+ { "AmEx", "Cash", "Check", "CreditCard", "MasterCard", "Prepaid",
+ "VISA", "Unfiled"
+};
+
+char *ExpenseTypeNames[] =
+ { "Airfare", "Breakfast", "Bus", "Business Meals", "Car Rental",
+ "Dinner", "Entertainment", "Fax", "Gas", "Gifts", "Hotel",
+ "Incidentals", "Laundry", "Limo", "Lodging", "Lunch", "Mileage",
+ "Other", "Parking", "Postage", "Snack", "Subway", "Supplies",
+ "Taxi", "Telephone", "Tips", "Tolls", "Train"
+};
+
+
+/***********************************************************************
+ *
+ * Function: free_Expense
+ *
+ * Summary: frees members of the Expense structure
+ *
+ * Parameters: Expense_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Expense(Expense_t *expense)
+{
+ if (expense->note != NULL) {
+ free(expense->note);
+ expense->note = NULL;
+ }
+
+ if (expense->amount != NULL) {
+ free(expense->amount);
+ expense->amount = NULL;
+ }
+
+ if (expense->city != NULL) {
+ free(expense->city);
+ expense->city = NULL;
+ }
+
+ if (expense->vendor != NULL) {
+ free(expense->vendor);
+ expense->vendor = NULL;
+ }
+
+ if (expense->attendees != NULL) {
+ free(expense->attendees);
+ expense->attendees = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_Expense
+ *
+ * Summary: unpack Expense records
+ *
+ * Parameters: Expense_t*, char* to buffer, length of buffer
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_Expense(Expense_t *expense, unsigned char *buffer, int len)
+{
+ unsigned long d;
+ unsigned char *start = buffer;
+
+ if (len < 6)
+ return 0;
+
+ d = (unsigned short int) get_short(buffer);
+ expense->date.tm_year = (d >> 9) + 4;
+ expense->date.tm_mon = ((d >> 5) & 15) - 1;
+ expense->date.tm_mday = d & 31;
+ expense->date.tm_hour = 0;
+ expense->date.tm_min = 0;
+ expense->date.tm_sec = 0;
+ expense->date.tm_isdst = -1;
+ mktime(&expense->date);
+
+ expense->type = (enum ExpenseType) get_byte(buffer + 2);
+ expense->payment = (enum ExpensePayment) get_byte(buffer + 3);
+ expense->currency = get_byte(buffer + 4);
+
+ buffer += 6;
+ len -= 6;
+
+ if (len < 1)
+ return 0;
+
+ if (*buffer) {
+ expense->amount = strdup((char *)buffer);
+ buffer += strlen(expense->amount);
+ len -= strlen(expense->amount);
+ } else {
+ expense->amount = 0;
+ }
+ buffer++;
+ len--;
+
+ if (len < 1)
+ return 0;
+
+ if (*buffer) {
+ expense->vendor = strdup((char *)buffer);
+ buffer += strlen(expense->vendor);
+ len -= strlen(expense->vendor);
+ } else {
+ expense->vendor = 0;
+ }
+ buffer++;
+ len--;
+
+ if (len < 1)
+ return 0;
+
+ if (*buffer) {
+ expense->city = strdup((char *)buffer);
+ buffer += strlen(expense->city);
+ len -= strlen(expense->city);
+ } else {
+ expense->city = 0;
+ }
+ buffer++;
+ len--;
+
+ if (len < 1)
+ return 0;
+
+ if (*buffer) {
+ expense->attendees = strdup((char *)buffer);
+ buffer += strlen(expense->attendees);
+ len -= strlen(expense->attendees);
+ } else {
+ expense->attendees = 0;
+ }
+ buffer++;
+ len--;
+
+ if (len < 1)
+ return 0;
+
+ if (*buffer) {
+ expense->note = strdup((char *)buffer);
+ buffer += strlen(expense->note);
+ len -= strlen(expense->note);
+ } else {
+ expense->note = 0;
+ }
+
+ buffer++;
+ len--;
+
+ return (buffer - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_Expense
+ *
+ * Summary: pack Expense records
+ *
+ * Parameters: Expense_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+pack_Expense(Expense_t *expense, unsigned char *record, int len)
+{
+ int destlen = 6 + 1 + 1 + 1 + 1 + 1;
+ unsigned char *buf = record;
+
+ if (expense->amount)
+ destlen += strlen(expense->amount);
+ if (expense->vendor)
+ destlen += strlen(expense->vendor);
+ if (expense->city)
+ destlen += strlen(expense->city);
+ if (expense->attendees)
+ destlen += strlen(expense->attendees);
+ if (expense->note)
+ destlen += strlen(expense->note);
+
+ if (!record)
+ return destlen;
+ if (len < destlen)
+ return 0;
+
+ set_short(buf,
+ ((expense->date.tm_year - 4) << 9) | ((expense->date.tm_mon +
+ 1) << 5) | expense->date.
+ tm_mday);
+ buf += 2;
+ set_byte(buf, expense->type);
+ set_byte(buf + 1, expense->payment);
+ set_byte(buf + 2, expense->currency);
+ set_byte(buf + 3, 0); /* gapfill */
+ buf += 4;
+
+ if (expense->amount) {
+ strcpy((char *)buf, expense->amount);
+ buf += strlen((char *)buf);
+ } else {
+ set_byte(buf, 0);
+ }
+ buf++;
+
+ if (expense->vendor) {
+ strcpy((char *)buf, expense->vendor);
+ buf += strlen((char *)buf);
+ } else {
+ set_byte(buf, 0);
+ }
+ buf++;
+
+ if (expense->city) {
+ strcpy((char *)buf, expense->city);
+ buf += strlen((char *)buf);
+ } else {
+ set_byte(buf, 0);
+ }
+ buf++;
+
+ if (expense->attendees) {
+ strcpy((char *)buf, expense->attendees);
+ buf += strlen((char *)buf);
+ } else {
+ set_byte(buf, 0);
+ }
+ buf++;
+
+ if (expense->note) {
+ strcpy((char *)buf, expense->note);
+ buf += strlen((char *)buf);
+ } else {
+ set_byte(buf, 0);
+ }
+ buf++;
+
+ return (buf - record);
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_ExpenseAppInfo
+ *
+ * Summary: unpacks ExpenseAppInfo record
+ *
+ * Parameters: ExpenseAppInfo_t*, char* to record, record length
+ *
+ * Returns: effective record length
+ *
+ ***********************************************************************/
+int
+unpack_ExpenseAppInfo(ExpenseAppInfo_t *appinfo, unsigned char *record,
+ size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = unpack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+
+ appinfo->sortOrder = (enum ExpenseSort) get_byte(record);
+ record += 2;
+ for (i = 0; i < 4; i++) {
+ memcpy(appinfo->currencies[i].name, record, 16);
+ record += 16;
+ memcpy(appinfo->currencies[i].symbol, record, 4);
+ record += 4;
+ memcpy(appinfo->currencies[i].rate, record, 8);
+ record += 8;
+ }
+ return (record - start);
+}
+
+/***********************************************************************
+ *
+ * Function: pack_ExpenseAppInfo
+ *
+ * Summary: packs ExpenseAppInfo record
+ *
+ * Parameters: ExpenseAppInfo_t*, char* to record, record length
+ *
+ * Returns: effective record length
+ *
+ ***********************************************************************/
+int
+pack_ExpenseAppInfo(ExpenseAppInfo_t *appinfo, unsigned char *record,
+ size_t len)
+{
+ int i,
+ destlen = 2 + (16 + 4 + 8) * 4;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!record)
+ return i + destlen;
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+ if (len < destlen)
+ return 0;
+ set_byte(record, appinfo->sortOrder);
+ set_byte(record + 1, 0); /* gapfill */
+ record += 2;
+ for (i = 0; i < 4; i++) {
+ memcpy(record, appinfo->currencies[i].name, 16);
+ record += 16;
+ memcpy(record, appinfo->currencies[i].symbol, 4);
+ record += 4;
+ memcpy(record, appinfo->currencies[i].rate, 8);
+ record += 8;
+ }
+
+ return (record - start);
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_ExpensePref
+ *
+ * Summary: unpacks ExpensePref record
+ *
+ * Parameters: ExpensePref_t*, char* to record, record length
+ *
+ * Returns: effective record length
+ *
+ ***********************************************************************/
+int
+unpack_ExpensePref(ExpensePref_t *pref, unsigned char *record, int len)
+{
+ int i;
+ unsigned char *start = record;
+
+ (void) len;
+
+ pref->currentCategory = get_short(record);
+ record += 2;
+ pref->defaultCurrency = get_short(record);
+ record += 2;
+ pref->attendeeFont = get_byte(record);
+ record++;
+ pref->showAllCategories = get_byte(record);
+ record++;
+ pref->showCurrency = get_byte(record);
+ record++;
+ pref->saveBackup = get_byte(record);
+ record++;
+ pref->allowQuickFill = get_byte(record);
+ record++;
+ pref->unitOfDistance = (enum ExpenseDistance) get_byte(record);
+ record++;
+
+ for (i = 0; i < 5; i++) {
+ pref->currencies[i] = get_byte(record);
+ record++;
+ }
+
+ for (i = 0; i < 2; i++) {
+ pref->unknown[i] = get_byte(record);
+ record++;
+ }
+
+ pref->noteFont = get_byte(record);
+ record++;
+
+ return (record - start);
+}
+
+/***********************************************************************
+ *
+ * Function: pack_ExpensePref
+ *
+ * Summary: packs ExpensePref record
+ *
+ * Parameters: ExpensePref_t*, char* to record, record length
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int pack_ExpensePref(ExpensePref_t *p, unsigned char *record, int len)
+{
+ int i;
+ unsigned char *start = record;
+
+ (void) len;
+
+ set_short(record, p->currentCategory);
+ record += 2;
+ set_short(record, p->defaultCurrency);
+ record += 2;
+ set_byte(record, p->attendeeFont);
+ record++;
+ set_byte(record, p->showAllCategories);
+ record++;
+ set_byte(record, p->showCurrency);
+ record++;
+ set_byte(record, p->saveBackup);
+ record++;
+ set_byte(record, p->allowQuickFill);
+ record++;
+ set_byte(record, p->unitOfDistance);
+ record++;
+ for (i = 0; i < 5; i++) {
+ set_byte(record, p->currencies[i]);
+ record++;
+ }
+ /* Unknown values */
+ set_byte(record, 0xff);
+ record++;
+ set_byte(record, 0xff);
+ record++;
+
+ set_byte(record, p->noteFont);
+ record++;
+
+ return record - start;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/freebsdusb.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/freebsdusb.c
new file mode 100644
index 00000000..5ec1682e
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/freebsdusb.c
@@ -0,0 +1,460 @@
+/*
+ * $Id: freebsdusb.c,v 1.28 2006/10/12 14:21:22 desrod Exp $
+ *
+ * freebsdusb.c: device IO for FreeBSD usb devices
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski.
+ * 2002, Anish Mistry
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-usb.h"
+
+#ifdef HAVE_SYS_IOCTL_COMPAT_H
+#include <sys/ioctl_compat.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+
+#if defined(__FreeBSD__)
+/* freebsd usb header */
+#include <dev/usb/usb.h>
+#define MAX_BUF 256
+#endif
+
+/* Declare prototypes */
+static int u_open(pi_socket_t *ps, struct pi_sockaddr *addr, size_t addrlen);
+static int u_close(pi_socket_t *ps);
+static ssize_t u_write(pi_socket_t *ps, const unsigned char *buf, size_t len, int flags);
+static ssize_t u_read(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags);
+static int u_poll(pi_socket_t *ps, int timeout);
+static int u_flush(pi_socket_t *ps, int flags);
+
+void pi_usb_impl_init (struct pi_usb_impl *impl)
+{
+ impl->open = u_open;
+ impl->close = u_close;
+ impl->write = u_write;
+ impl->read = u_read;
+ impl->flush = u_flush;
+ impl->poll = u_poll;
+}
+
+
+/***********************************************************************
+ *
+ * Function: u_open
+ *
+ * Summary: Open the usb port and establish a connection for
+ * communicating over the usb port.
+ *
+ * Parameters: ps is of type pi_socket_t which will given a copy of the
+ * valid file descriptor that is returned by the function.
+ *
+ * addr of type pi_socketaddr contains the member pi_device
+ * which is a character string of the usb device.
+ *
+ * XXX addrlen is of type int contain the size of addr? I'm
+ * not using this, should I? Possible buffer overflow because
+ * I'm not checking something?
+ *
+ * Returns: The file descriptor
+ *
+ ***********************************************************************/
+static int
+u_open(pi_socket_t *ps, struct pi_sockaddr *addr, size_t addrlen)
+{
+ int fd,
+ i,
+ endpoint_fd;
+
+ struct usb_device_info udi;
+ /* struct usb_ctl_request ur; */
+ /* unsigned char usbresponse[50]; */
+
+ char *tty = addr->pi_device;
+ char *pEndPoint = NULL;
+
+ /* open the usb device */
+ if ((fd = open(tty, O_RDWR, 0)) < 0) {
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+ /* check for a valid file descriptor */
+ if (fd < 0) {
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+ /* fill the udi structure with information about the handheld, after
+ this is where you will probably want to do device specific stuff
+ */
+
+ if (ioctl(fd, USB_GET_DEVICEINFO, &udi)) {
+ close(fd);
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV USB_GET_DEVICE_INFO USB FreeBSD fd: %d\n", fd));
+
+ /* set the configuration */
+ i = 1;
+ if (ioctl(fd, USB_SET_CONFIG, &i) < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "DEV USB_SET_CONFIG USB FreeBSD fd: %d failed\n", fd));
+
+ close(fd);
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+ /* close the main communication pipe since we have initilized
+ everything we needed to
+ NOTE: we HAVE to do all this stuff to the main pipe or we will
+ cause a kernel panic when data is sent over the endpoint */
+ close(fd);
+
+ /* open endpoint */
+ /* allocate data for the usb endpoint string */
+ pEndPoint = malloc(strlen(tty)+20);
+ if(!pEndPoint)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+
+ /* create device endpoint name string */
+ sprintf(pEndPoint, "%s.%d", tty, 2);
+
+ /* open the endpoint with read write access */
+ endpoint_fd = open(pEndPoint, O_RDWR, 0);
+ if(endpoint_fd < 0) {
+ /* we failed to open the endpoint */
+ free(pEndPoint);
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ }
+
+ if ((i = fcntl(endpoint_fd, F_GETFL, 0)) != -1) {
+ i &= ~O_NONBLOCK;
+ fcntl(endpoint_fd, F_SETFL, i);
+ }
+
+ /* set short transfer so that we can allow "short" reads since we
+ will don't know exactly
+ what is coming so we can't specify exact byte amounts */
+ i = 1;
+ if (ioctl(endpoint_fd, USB_SET_SHORT_XFER, &i) < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV USB_SET_SHORT_XFER USB FreeBSD fd: %d failed\n",
+ endpoint_fd));
+ }
+
+ /* 0 timeout value will cause us the wait until the device has data
+ available or is disconnected */
+ i = 0;
+ if (ioctl(endpoint_fd, USB_SET_TIMEOUT, &i) < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV USB_SET_TIMEOUT USB FreeBSD fd: %d failed\n",
+ endpoint_fd));
+ }
+
+ /* save our file descriptor in the pi_socket structure */
+ if ((i = pi_socket_setsd(ps, endpoint_fd)) < 0) {
+ free(pEndPoint);
+ return i;
+ }
+
+ /* free endpoint string memory */
+ free(pEndPoint);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV OPEN USB FreeBSD fd: %d\n", endpoint_fd));
+
+ /* return our endpoint file descriptor since this is where the
+ reading and writing will be done */
+ return endpoint_fd;
+
+}
+
+/***********************************************************************
+ *
+ * Function: u_close
+ *
+ * Summary: Close the open socket/file descriptor
+ *
+ * Parameters: ps is of type pi_socket that contains the member sd which is
+ * the file descriptor that is to be closed.
+ *
+ * Returns: 0 if sucessful or -1 if it failed and errno set to the error
+ *
+ ***********************************************************************/
+static int
+u_close(pi_socket_t *ps)
+{
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV CLOSE USB FreeBSD fd: %d\n", ps->sd));
+
+ return close(ps->sd);
+}
+
+/***********************************************************************
+ *
+ * Function: u_poll
+ *
+ * Summary: Poll the open socket/file descriptor
+ *
+ * Parameters: None
+ *
+ * Returns: 1 always since we buffer our own data and you can't poll()
+ * FreeBSD USB devices?
+ *
+ ***********************************************************************/
+static int
+u_poll(pi_socket_t *ps, int timeout)
+{
+ /* stub this function and log an error that this should never needed
+ to be called */
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV POLL USB FreeBSD Timeout: %d\npoll()"
+ " should not be called for FreeBSD USB\n", timeout));
+
+ return 1;
+}
+
+/***********************************************************************
+ *
+ * Function: u_write
+ *
+ * Parameters: ps is of type pi_socket that contains the sd member which is
+ * the file descriptor that the data in buf will be written to.
+ *
+ * buf is a unsigned char pointer that points to the data that
+ * is to be written to ps->sd.
+ *
+ * len is of type int and indicated the number of bytes to
+ * write to ps->sd.
+ *
+ * flags is of type int and contains various write flags. What
+ * flags and should I respect them, since I am currently not
+ * checking this variable?
+ *
+ * Parameters: None
+ *
+ * Returns: The number of bytes written from buf or negative to indicate an
+ * error
+ *
+ ***********************************************************************/
+static ssize_t
+u_write(pi_socket_t *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int nwrote,
+ total,
+ write_len;
+ fd_set ready;
+
+ total = len;
+ write_len = len;
+
+ /* FIXME: there is no timeout handling in the original freebsdusb code! */
+
+ while (total > 0) {
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ if (!FD_ISSET(ps->sd, &ready)) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+
+ nwrote = write(ps->sd, buf, write_len);
+ if (nwrote < 0) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+
+ write_len -= nwrote;
+ buf += nwrote;
+ total -= nwrote;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV TX USB FreeBSD Bytes: %d\n", len));
+
+ return len;
+}
+
+/***********************************************************************
+ *
+ * Function: u_read
+ *
+ * Summary: Read incoming data from the socket/file descriptor and
+ * buffer any extra data that is read in the process of
+ * receiving data from the device.
+ *
+ * Parameters: ps is of type pi_socket that contains the sd member which is
+ * the file descriptor that the data in buf will be read. It
+ * also contains the read buffer.
+ *
+ * buf is a pointer to an unsigned character string that will
+ * receive the data the is read from the device.
+ *
+ * len is of type int that is the the number of bytes to read
+ * from the device/buffer into buf.
+ *
+ * flags is of type in that currently only indicated if you
+ * want to peek data from the device/buffer .
+ *
+ * Returns: The number of bytes that was read from the device or from
+ * the buffer and copied to buf.
+ *
+ ***********************************************************************/
+static ssize_t
+u_read(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ struct pi_usb_data *data = (struct pi_usb_data *) ps->device->data;
+ ssize_t rlen;
+ int bytes_read = 0;
+ fd_set ready;
+ struct timeval t;
+
+ if (flags == PI_MSG_PEEK && len > 256)
+ len = 256;
+
+ if (pi_buffer_expect (buf, len) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ /* first extract anything we had in the "peek" buffer */
+ if (data->buf_size > 0) {
+ bytes_read = len > data->buf_size ? data->buf_size : len;
+ len -= bytes_read;
+ pi_buffer_append(buf, data->buf, bytes_read);
+ if (flags != PI_MSG_PEEK) {
+ data->buf_size -= bytes_read;
+ if (data->buf_size > 0)
+ memmove(data->buf, data->buf + bytes_read, data->buf_size);
+ }
+ if (!len)
+ return bytes_read;
+ }
+
+ /* check to see if device is ready for read */
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ if (data->timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ if (select(ps->sd + 1, &ready, 0, 0, &t) == 0)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ /* If data is available in time, read it */
+ if (!FD_ISSET(ps->sd, &ready)) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV RX USB FreeBSD timeout\n"));
+ errno = ETIMEDOUT;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ /* read data to pre-sized buffer */
+ rlen = read(ps->sd, &buf->data[buf->used], len);
+ if (rlen > 0) {
+ if (flags == PI_MSG_PEEK) {
+ memcpy(data->buf, buf->data + buf->used, rlen);
+ data->buf_size = rlen;
+ }
+ buf->used += rlen;
+ bytes_read += rlen;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV RX USB FreeBSD Bytes: %d:%d\n", bytes_read,
+ bytes_read + data->buf_size));
+
+ }
+ else
+ bytes_read = PI_ERR_SOCK_IO;
+
+ return bytes_read;
+}
+
+/***********************************************************************
+ *
+ * Function: u_flush
+ *
+ * Summary: Flush incoming and/or outgoing data from the socket/file
+ * descriptor
+ *
+ * Parameters: ps is of type pi_socket that contains the sd member which is
+ * the file descriptor that the data in buf will be read. It
+ * also contains the read buffer.
+ *
+ * flags is of type int and can be a combination of
+ * PI_FLUSH_INPUT and PI_FLUSH_OUTPUT
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+static int
+u_flush(pi_socket_t *ps, int flags)
+{
+ char buf[256];
+ int fl;
+ struct pi_usb_data *data = (struct pi_usb_data *) ps->device->data;
+
+ if (flags & PI_FLUSH_INPUT) {
+ /* clear internal buffer */
+ data->buf_size = 0;
+
+ /* flush pending data */
+ if ((fl = fcntl(ps->sd, F_GETFL, 0)) != -1) {
+ fcntl(ps->sd, F_SETFL, fl | O_NONBLOCK);
+ while (read(ps->sd, buf, sizeof(buf)) > 0)
+ ;
+ fcntl(ps->sd, F_SETFL, fl);
+ }
+ }
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/hinote.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/hinote.c
new file mode 100644
index 00000000..e315e3cf
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/hinote.c
@@ -0,0 +1,180 @@
+/*
+ * $Id: hinote.c,v 1.22 2006/10/12 14:21:22 desrod Exp $
+ *
+ * hinote.c: Translate Hi-Note data formats
+ *
+ * Copyright 1997 Bill Goodman
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-hinote.h"
+
+/***********************************************************************
+ *
+ * Function: free_HiNoteNote
+ *
+ * Summary: frees HiNoteNote_t members
+ *
+ * Parameters: HiNoteNote_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_HiNoteNote(HiNoteNote_t *hinote)
+{
+ if (hinote->text != NULL) {
+ free(hinote->text);
+ hinote->text = NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_HiNoteNote
+ *
+ * Summary: Unpack a HiNote record
+ *
+ * Parameters: HiNoteNote_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_HiNoteNote(HiNoteNote_t *hinote, unsigned char *buffer, int len)
+{
+ if (len < 3)
+ return 0;
+
+ hinote->flags = buffer[0];
+ hinote->level = buffer[1];
+ hinote->text = strdup((char *) &buffer[2]);
+
+ return strlen((char *) &buffer[2]) + 3;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_HiNoteNote
+ *
+ * Summary: Pack a HiNote record
+ *
+ * Parameters: HiNoteNote_t*
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+pack_HiNoteNote(HiNoteNote_t *hinote, unsigned char *buffer, int len)
+{
+ int destlen;
+
+ destlen = 3;
+ if (hinote->text)
+ destlen += strlen(hinote->text);
+
+ if (!buffer)
+ return destlen;
+ if (len < destlen)
+ return 0;
+
+ buffer[0] = hinote->flags;
+ buffer[1] = hinote->level;
+
+ if (hinote->text)
+ strcpy((char *) &buffer[2], hinote->text);
+ else {
+ buffer[2] = 0;
+ }
+ return destlen;
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_HiNoteAppInfo
+ *
+ * Summary: Unpack the HiNote AppInfo block
+ *
+ * Parameters: HiNoteAppInfo_t*, char* to record, record length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_HiNoteAppInfo(HiNoteAppInfo_t *appinfo, unsigned char *record, size_t len)
+{
+ int i,
+ idx;
+ unsigned char *start;
+
+ start = record;
+ i = unpack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+ if (len < 48)
+ return 0;
+ for (idx = 0; i < 48; i++)
+ appinfo->reserved[i] = *record++;
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_HiNoteAppInfo
+ *
+ * Summary: Pack the HiNote AppInfo block
+ *
+ * Parameters: HiNoteAppInfo_t*, char* record, length of record
+ *
+ * Returns: effective record length
+ *
+ ***********************************************************************/
+int
+pack_HiNoteAppInfo(HiNoteAppInfo_t *appinfo, unsigned char *record, size_t len)
+{
+ int i,
+ idx;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&appinfo->category, record, len);
+ if (i == 0) /* category pack failed */
+ return 0;
+ if (!record)
+ return i + 48;
+ record += i;
+ len -= i;
+ if (len < 48)
+ return (record - start);
+ for (idx = 0; i < 48; i++)
+ *record++ = appinfo->reserved[i];
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/inet.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/inet.c
new file mode 100644
index 00000000..9906bdde
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/inet.c
@@ -0,0 +1,595 @@
+/*
+ * $Id: inet.c,v 1.61 2006/10/12 14:21:22 desrod Exp $
+ *
+ * inet.c: Interface layer to TCP/IP NetSync connections
+ *
+ * Copyright (c) 1997, Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 1999, John Franks
+ * Copyright (c) 2004, 2005 Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-inet.h"
+#include "pi-cmp.h"
+#include "pi-net.h"
+
+/* Declare prototypes */
+static void pi_inet_device_free (pi_device_t *dev);
+static pi_protocol_t* pi_inet_protocol (pi_device_t *dev);
+static pi_protocol_t* pi_inet_protocol_dup (pi_protocol_t *prot);
+static void pi_inet_protocol_free (pi_protocol_t *prot);
+static int pi_inet_close(pi_socket_t *ps);
+static int pi_inet_connect(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen);
+static int pi_inet_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen);
+static int pi_inet_listen(pi_socket_t *ps, int backlog);
+static int pi_inet_accept(pi_socket_t *ps, struct sockaddr *addr, size_t *addrlen);
+static ssize_t pi_inet_read(pi_socket_t *ps, pi_buffer_t *msg, size_t len, int flags);
+static ssize_t pi_inet_write(pi_socket_t *ps, const unsigned char *msg, size_t len, int flags);
+static int pi_inet_getsockopt(pi_socket_t *ps, int level, int option_name, void *option_value, size_t *option_len);
+static int pi_inet_setsockopt(pi_socket_t *ps, int level, int option_name, const void *option_value, size_t *option_len);
+static int pi_inet_flush(pi_socket_t *ps, int flags);
+
+extern int pi_socket_init(pi_socket_t *ps);
+
+pi_device_t*
+pi_inet_device (int type)
+{
+ pi_device_t *dev = NULL;
+ pi_inet_data_t *data = NULL;
+
+ dev = (pi_device_t *)malloc (sizeof (pi_device_t));
+ if (dev != NULL) {
+ data = (pi_inet_data_t *)malloc (sizeof (pi_inet_data_t));
+ if (data == NULL) {
+ free(dev);
+ dev = NULL;
+ }
+ }
+
+ if (dev != NULL && data != NULL) {
+ dev->free = pi_inet_device_free;
+ dev->protocol = pi_inet_protocol;
+ dev->bind = pi_inet_bind;
+ dev->listen = pi_inet_listen;
+ dev->accept = pi_inet_accept;
+ dev->connect = pi_inet_connect;
+ dev->close = pi_inet_close;
+
+ data->timeout = 0;
+ data->rx_bytes = 0;
+ data->rx_errors = 0;
+ data->tx_bytes = 0;
+ data->tx_errors = 0;
+ dev->data = data;
+ }
+
+ return dev;
+}
+
+static void
+pi_inet_device_free (pi_device_t *dev)
+{
+ ASSERT (dev != NULL);
+ if (dev != NULL) {
+ if (dev->data != NULL)
+ free(dev->data);
+ free(dev);
+ }
+}
+
+static pi_protocol_t*
+pi_inet_protocol (pi_device_t *dev)
+{
+ pi_protocol_t *prot;
+ pi_inet_data_t *data;
+
+ ASSERT (dev != NULL);
+
+ data = dev->data;
+
+ prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+
+ if (prot != NULL) {
+ prot->level = PI_LEVEL_DEV;
+ prot->dup = pi_inet_protocol_dup;
+ prot->free = pi_inet_protocol_free;
+ prot->read = pi_inet_read;
+ prot->write = pi_inet_write;
+ prot->flush = pi_inet_flush;
+ prot->getsockopt = pi_inet_getsockopt;
+ prot->setsockopt = pi_inet_setsockopt;
+ prot->data = NULL;
+ }
+
+ return prot;
+}
+
+static pi_protocol_t*
+pi_inet_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ ASSERT (prot != NULL);
+
+ new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+
+ if (new_prot != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+ new_prot->data = NULL;
+ }
+
+ return new_prot;
+}
+
+static void
+pi_inet_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT (prot != NULL);
+ if (prot != NULL)
+ free(prot);
+}
+
+static int
+pi_inet_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ int opt,
+ sd,
+ err;
+ size_t optlen;
+ struct pi_sockaddr *paddr = (struct pi_sockaddr *) addr;
+ struct sockaddr_in serv_addr;
+ char *device = paddr->pi_device,
+ *port = NULL;
+
+ /* Figure out the addresses to allow */
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ if (strlen(device) > 1 && strncmp(device, "any", 3)) {
+ serv_addr.sin_addr.s_addr = inet_addr(device);
+ if (serv_addr.sin_addr.s_addr == (in_addr_t)-1) {
+ struct hostent *hostent = gethostbyname(device);
+
+ if (!hostent)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+
+ memcpy((char *) &serv_addr.sin_addr.s_addr,
+ hostent->h_addr, (size_t)hostent->h_length);
+ }
+ } else {
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ if ((port = strchr(device, ':')) != NULL) {
+ serv_addr.sin_port = htons(atoi(++port));
+ } else {
+ serv_addr.sin_port = htons(14238);
+ }
+
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sd < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "DEV BIND Inet: Unable to create socket\n"));
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ }
+ if ((err = pi_socket_setsd (ps, sd)) < 0)
+ return err;
+
+ opt = 1;
+ optlen = sizeof(opt);
+
+ if (setsockopt(ps->sd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt,
+ (int)optlen) < 0) {
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ }
+
+ if (bind(ps->sd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV BIND Inet Bound to %s\n", device));
+
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ return 0;
+}
+
+static int
+pi_inet_connect(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ int sd,
+ err;
+
+ struct pi_sockaddr *paddr = (struct pi_sockaddr *) addr;
+ struct sockaddr_in serv_addr;
+ char *device = paddr->pi_device;
+
+ /* Figure out the addresses to allow */
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ if (strlen(device) > 1) {
+ serv_addr.sin_addr.s_addr = inet_addr(device);
+ if (serv_addr.sin_addr.s_addr == (in_addr_t)-1) {
+ struct hostent *hostent = gethostbyname(device);
+
+ if (!hostent) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "DEV CONNECT Inet: Unable"
+ " to determine host\n"));
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ }
+
+ memcpy((char *) &serv_addr.sin_addr.s_addr,
+ hostent->h_addr, (size_t)hostent->h_length);
+ }
+ } else {
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ serv_addr.sin_port = htons(14238);
+
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (sd < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "DEV CONNECT Inet: Unable to create socket\n"));
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ }
+
+ if ((err = pi_socket_setsd (ps, sd)) < 0)
+ return err;
+
+ if (connect (ps->sd, (struct sockaddr *) &serv_addr,
+ sizeof(serv_addr)) < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "DEV CONNECT Inet: Unable to connect\n"));
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ }
+
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if ((err = cmp_tx_handshake(ps)) < 0)
+ goto fail;
+ break;
+ case PI_CMD_NET:
+ if ((err = net_tx_handshake(ps)) < 0)
+ goto fail;
+ break;
+ }
+ ps->state = PI_SOCK_CONN_INIT;
+ ps->command = 0;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV CONNECT Inet: Connected\n"));
+ return 0;
+
+fail:
+ return err;
+}
+
+static int
+pi_inet_listen(pi_socket_t *ps, int backlog)
+{
+ int result;
+
+ result = listen(ps->sd, backlog);
+ if (result == 0)
+ ps->state = PI_SOCK_LISTEN;
+
+ return result;
+}
+
+static int
+pi_inet_accept(pi_socket_t *ps, struct sockaddr *addr, size_t *addrlen)
+{
+ int sd,
+ err,
+ split = 0,
+ chunksize = 0;
+ size_t len,
+ size;
+ pl_socklen_t l = 0;
+ unsigned char cmp_flags;
+
+ if (addrlen)
+ l = *addrlen;
+ sd = accept(ps->sd, addr, &l);
+ if (addrlen)
+ *addrlen = l;
+ if (sd < 0) {
+ pi_set_error(ps->sd, sd);
+ err = PI_ERR_GENERIC_SYSTEM;
+ goto fail;
+ }
+
+ pi_socket_setsd(ps, sd);
+ pi_socket_init(ps);
+
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if ((err = cmp_rx_handshake(ps, 57600, 0)) < 0)
+ goto fail;
+
+ /* propagate the long packet format flag to both command and non-command stacks */
+ size = sizeof(cmp_flags);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_FLAGS, &cmp_flags, &size);
+ if (cmp_flags & CMP_FL_LONG_PACKET_SUPPORT) {
+ int use_long_format = 1;
+ size = sizeof(int);
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
+ &use_long_format, &size);
+ ps->command ^= 1;
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
+ &use_long_format, &size);
+ ps->command ^= 1;
+ }
+
+ break;
+ case PI_CMD_NET:
+ /* network: make sure we don't split writes. set socket option
+ * on both the command and non-command instances of the protocol
+ */
+ len = sizeof (split);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_SPLIT_WRITES,
+ &split, &len);
+ len = sizeof (chunksize);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_WRITE_CHUNKSIZE,
+ &chunksize, &len);
+
+ ps->command ^= 1;
+ len = sizeof (split);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_SPLIT_WRITES,
+ &split, &len);
+ len = sizeof (chunksize);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_WRITE_CHUNKSIZE,
+ &chunksize, &len);
+ ps->command ^= 1;
+
+ if ((err = net_rx_handshake(ps)) < 0)
+ goto fail;
+ break;
+ }
+
+ ps->state = PI_SOCK_CONN_ACCEPT;
+ ps->command = 0;
+ ps->dlprecord = 0;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV INET ACCEPT accepted\n"));
+
+ return ps->sd;
+
+ fail:
+ return err;
+}
+
+static int
+pi_inet_close(pi_socket_t *ps)
+{
+ if (ps->sd) {
+ close(ps->sd);
+ ps->sd = 0;
+ }
+ if (ps->laddr) {
+ free(ps->laddr);
+ ps->laddr = NULL;
+ }
+ if (ps->raddr) {
+ free(ps->raddr);
+ ps->raddr = NULL;
+ }
+ return 0;
+}
+
+static int
+pi_inet_flush(pi_socket_t *ps, int flags)
+{
+ char buf[256];
+ int fl;
+
+ if (flags & PI_FLUSH_INPUT) {
+ if ((fl = fcntl(ps->sd, F_GETFL, 0)) != -1) {
+ fcntl(ps->sd, F_SETFL, fl | O_NONBLOCK);
+ while (recv(ps->sd, buf, sizeof(buf), 0) > 0)
+ ;
+ fcntl(ps->sd, F_SETFL, fl);
+ }
+ }
+ return 0;
+}
+
+static ssize_t
+pi_inet_write(pi_socket_t *ps, const unsigned char *msg, size_t len, int flags)
+{
+ int total,
+ nwrote;
+ pi_inet_data_t *data = (pi_inet_data_t *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ total = len;
+ while (total > 0) {
+ if (data->timeout == 0) {
+ if (select(ps->sd + 1, 0, &ready, 0, 0) < 0
+ && errno == EINTR)
+ continue;
+ } else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ if (select(ps->sd + 1, 0, &ready, 0, &t) == 0)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+ if (!FD_ISSET(ps->sd, &ready)) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+
+ nwrote = write(ps->sd, msg, len);
+ if (nwrote < 0) {
+ /* test errno to properly set the socket error */
+ if (errno == EPIPE || errno == EBADF) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+ return pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ }
+
+ total -= nwrote;
+ }
+ data->tx_bytes += len;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV TX Inet Bytes: %d\n", len));
+
+ return len;
+}
+
+static ssize_t
+pi_inet_read(pi_socket_t *ps, pi_buffer_t *msg, size_t len, int flags)
+{
+ int r,
+ fl = 0;
+ pi_inet_data_t *data = (pi_inet_data_t *)ps->device->data;
+ fd_set ready;
+ struct timeval t;
+
+ if (pi_buffer_expect (msg, len) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ if (flags == PI_MSG_PEEK)
+ fl = MSG_PEEK;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ if (data->timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ if (select(ps->sd + 1, &ready, 0, 0, &t) == 0)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ /* If data is available in time, read it */
+ if (FD_ISSET(ps->sd, &ready)) {
+ r = recv(ps->sd, msg->data + msg->used, len, fl);
+ if (r < 0) {
+ if (errno == EPIPE || errno == EBADF) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+ return pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ }
+
+ data->rx_bytes += r;
+ msg->used += r;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV RX Inet Bytes: %d\n", r));
+ return r;
+ }
+
+ /* otherwise throw out any current packet and return */
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN, "DEV RX Inet timeout\n"));
+ data->rx_errors++;
+ return 0;
+}
+
+static int
+pi_inet_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ pi_inet_data_t *data = (pi_inet_data_t *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout)) {
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ }
+ memcpy (option_value, &data->timeout,
+ sizeof (data->timeout));
+ *option_len = sizeof (data->timeout);
+ break;
+ }
+
+ return 0;
+}
+
+static int
+pi_inet_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ pi_inet_data_t *data = (pi_inet_data_t *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout)) {
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ }
+ memcpy (&data->timeout, option_value,
+ sizeof (data->timeout));
+ break;
+ }
+
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/libusb.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/libusb.c
new file mode 100644
index 00000000..e571aeaf
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/libusb.c
@@ -0,0 +1,605 @@
+/*
+ * $Id: libusb.c,v 1.33 2007/02/09 16:06:22 desrod Exp $
+ *
+ * libusb.c: device i/o for libusb
+ *
+ * Copyright (c) 2004 Zephaniah E. Hull & Florent Pillet.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-usb.h"
+#include "pi-util.h"
+
+#ifdef HAVE_SYS_IOCTL_COMPAT_H
+#include <sys/ioctl_compat.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <usb.h>
+
+#if defined(sun) && defined(__SVR4)
+#define __FUNCTION__ __func__
+#endif
+
+static int u_open(struct pi_socket *ps, struct pi_sockaddr *addr, size_t addrlen);
+static int u_close(struct pi_socket *ps);
+static ssize_t u_write(struct pi_socket *ps, const unsigned char *buf, size_t len,
+ int flags);
+static ssize_t u_read(struct pi_socket *ps, pi_buffer_t *buf, size_t len,
+ int flags);
+static int u_read_i(struct pi_socket *ps, pi_buffer_t *buf, size_t len, int flags,
+ int timeout);
+static int u_poll(struct pi_socket *ps, int timeout);
+static int u_wait_for_device(struct pi_socket *ps, int *timeout);
+static int u_flush(pi_socket_t *ps, int flags);
+static int u_control_request (pi_usb_data_t *usb_data, int request_type,
+ int request, int value, int control_index, void *data, int size, int timeout);
+
+void pi_usb_impl_init (struct pi_usb_impl *impl)
+{
+ impl->open = u_open;
+ impl->close = u_close;
+ impl->write = u_write;
+ impl->read = u_read;
+ impl->flush = u_flush;
+ impl->poll = u_poll;
+ impl->wait_for_device = u_wait_for_device;
+ impl->changebaud = NULL; /* we don't need this one for libusb (yet) */
+ impl->control_request = u_control_request;
+}
+
+
+/***********************************************************************
+ *
+ * Start of the device identification code.
+ *
+ ***********************************************************************/
+
+static usb_dev_handle *USB_handle;
+static int USB_interface;
+static int USB_in_endpoint;
+static int USB_out_endpoint;
+
+static int
+USB_open (pi_usb_data_t *data)
+{
+ usb_init ();
+
+ return 1;
+}
+
+static int
+USB_poll (pi_usb_data_t *data)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ int ret;
+ u_int8_t input_endpoint = 0xFF, output_endpoint = 0xFF;
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ int first;
+#endif
+
+ usb_find_busses ();
+ usb_find_devices ();
+ CHECK (PI_DBG_DEV, PI_DBG_LVL_DEBUG, usb_set_debug (2));
+
+ for (bus = usb_busses; bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+ int i;
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: checking device %p\n",
+ __FILE__, dev));
+
+ if (dev->descriptor.bNumConfigurations < 1)
+ continue;
+ if (!dev->config)
+ continue;
+ if (dev->config[0].bNumInterfaces < 1)
+ continue;
+ if (dev->config[0].interface[0].num_altsetting < 1)
+ continue;
+ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints < 2)
+ continue;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d, 0x%04x 0x%04x.\n",
+ __FILE__, __LINE__, dev->descriptor.idVendor, dev->descriptor.idProduct));
+
+ if (USB_check_device (data, dev->descriptor.idVendor, dev->descriptor.idProduct))
+ continue;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: trying to open device %p\n",
+ __FILE__, dev));
+
+ USB_handle = usb_open(dev);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: USB_handle=%p\n",
+ __FILE__, USB_handle));
+
+ data->ref = USB_handle;
+
+ input_endpoint = output_endpoint = 0xFF;
+ USB_in_endpoint = USB_out_endpoint = 0xFF;
+
+ ret = USB_configure_device (data, &input_endpoint, &output_endpoint);
+ if (ret < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "%s: USB configure failed for familar device: 0x%04x 0x%04x. (LifeDrive issue?)\n",
+ __FILE__, dev->descriptor.idVendor, dev->descriptor.idProduct));
+
+ usb_close(USB_handle);
+ continue;
+ }
+
+ for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++) {
+ struct usb_endpoint_descriptor *endpoint;
+ u_int8_t address;
+
+ endpoint = &dev->config[0].interface[0].altsetting[0].endpoint[i];
+
+ if (endpoint->wMaxPacketSize != 0x40)
+ continue;
+ if ((endpoint->bmAttributes & USB_ENDPOINT_TYPE_MASK) != USB_ENDPOINT_TYPE_BULK)
+ continue;
+ address = endpoint->bEndpointAddress;
+ if ((address & USB_ENDPOINT_DIR_MASK)) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "In: 0x%x 0x%x.\n", address, input_endpoint));
+ if (input_endpoint == 0xFF)
+ USB_in_endpoint = address;
+ else if ((address & USB_ENDPOINT_ADDRESS_MASK) == input_endpoint)
+ USB_in_endpoint = address;
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "Out: 0x%x 0x%x.\n", address, output_endpoint));
+ if (output_endpoint == 0xFF)
+ USB_out_endpoint = address;
+ else if ((address & USB_ENDPOINT_ADDRESS_MASK) == output_endpoint)
+ USB_out_endpoint = address;
+ }
+ }
+
+ if (USB_in_endpoint == 0xFF || USB_out_endpoint == 0xFF) {
+ usb_close (USB_handle);
+ continue;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "Config: %d, 0x%x 0x%x | 0x%x 0x%x.\n",
+ ret, input_endpoint, output_endpoint, USB_in_endpoint, USB_out_endpoint));
+
+ USB_interface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ first = 1;
+claim:
+#endif
+ i = usb_claim_interface (USB_handle, USB_interface);
+ if (i < 0) {
+ if (i == -EBUSY) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "Unable to claim device: Busy.\n"));
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ if (first) {
+ usb_detach_kernel_driver_np (USB_handle, USB_interface);
+ first = 0;
+ goto claim;
+ }
+#endif
+ } else if (i == -ENOMEM)
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "Unable to claim device: No memory.\n"));
+ else
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "Unable to claim device: %d.\n", i));
+ usb_close (USB_handle);
+
+ errno = -i;
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d.\n",
+ __FILE__, __LINE__));
+
+ return 0;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d.\n",
+ __FILE__, __LINE__));
+ return 1;
+ }
+ }
+
+ errno = ENODEV;
+ CHECK (PI_DBG_DEV, PI_DBG_LVL_DEBUG, usb_set_debug (0));
+ return 0;
+}
+
+static int
+USB_close (void)
+{
+ if (!USB_handle)
+ return 0;
+
+ usb_release_interface (USB_handle, USB_interface);
+ usb_close (USB_handle);
+ USB_handle = NULL;
+ return 1;
+}
+
+
+/***********************************************************************
+ *
+ * Start of the read thread code, please note that all of this runs
+ * in a separate thread.
+ *
+ ***********************************************************************/
+
+#define MAX_READ_SIZE 16384
+#define AUTO_READ_SIZE 64
+static char *RD_buffer = NULL;
+static size_t RD_buffer_size;
+static size_t RD_buffer_used;
+static pthread_mutex_t RD_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t RD_buffer_available_cond = PTHREAD_COND_INITIALIZER;
+static int RD_wanted;
+static int RD_running = 0;
+static char RD_usb_buffer[MAX_READ_SIZE];
+static pthread_t RD_thread = 0;
+
+static void
+RD_do_read (int timeout)
+{
+ int bytes_read, read_size;
+
+ read_size = RD_wanted - RD_buffer_used;
+ if (read_size < AUTO_READ_SIZE)
+ read_size = AUTO_READ_SIZE;
+ else if (read_size > MAX_READ_SIZE)
+ read_size = MAX_READ_SIZE;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "Reading: len: %d, timeout: %d.\n", read_size, timeout));
+ bytes_read = usb_bulk_read (USB_handle, USB_in_endpoint, RD_usb_buffer, read_size, timeout);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d\n",
+ __FILE__, __LINE__, __FUNCTION__, bytes_read));
+ if (bytes_read < 0) {
+ if (bytes_read == -ENODEV) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_NONE, "Device went byebye!\n"));
+ RD_running = 0;
+ return;
+#ifdef ELAST
+ } else if (bytes_read == -(ELAST + 1)) {
+ usb_clear_halt (USB_handle, USB_in_endpoint);
+ return;
+#endif
+ } else if (bytes_read == -ETIMEDOUT)
+ return;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "libusb: USB bulk read returned error code %d\n", bytes_read));
+ return;
+ }
+ if (!bytes_read)
+ return;
+
+
+ pthread_mutex_lock (&RD_buffer_mutex);
+ if ((RD_buffer_used + bytes_read) > RD_buffer_size) {
+ RD_buffer_size = ((RD_buffer_used + bytes_read + 0xfffe) & ~0xffff) - 1; /* 64k chunks. */
+ RD_buffer = realloc (RD_buffer, RD_buffer_size);
+ }
+
+ memcpy (RD_buffer + RD_buffer_used, RD_usb_buffer, bytes_read);
+ RD_buffer_used += bytes_read;
+ pthread_cond_broadcast (&RD_buffer_available_cond);
+ pthread_mutex_unlock (&RD_buffer_mutex);
+}
+
+static void *
+RD_main (void *foo)
+{
+ RD_buffer_used = 0;
+ RD_buffer = NULL;
+ RD_buffer_size = 0;
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+ while (RD_running == 1) {
+ RD_do_read (0);
+ }
+
+ RD_running = 0;
+
+ return NULL;
+}
+
+
+static int
+RD_start (void)
+{
+ if (RD_thread || RD_running)
+ return 0;
+
+ RD_running = 1;
+ pthread_create (&RD_thread, NULL, RD_main, NULL);
+
+ return 1;
+}
+
+static int
+RD_stop (void)
+{
+ if (!RD_thread && !RD_running)
+ return 0;
+
+ if (RD_running)
+ RD_running = 0;
+
+ if (RD_thread) {
+ pthread_cancel(RD_thread);
+ RD_thread = 0;
+ }
+
+ if (RD_thread || RD_running)
+ return 0;
+
+ return 1;
+}
+
+
+/***********************************************************************
+ *
+ * Start of the glue code which makes this whole mess WORK.
+ *
+ ***********************************************************************/
+
+
+static int
+u_open(struct pi_socket *ps, struct pi_sockaddr *addr, size_t addrlen)
+{
+ pi_usb_data_t *data = (pi_usb_data_t *)ps->device->data;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s).\n",
+ __FILE__, __LINE__, __FUNCTION__));
+
+ if (RD_running)
+ return -1;
+ if (!USB_open (data))
+ return -1;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s).\n",
+ __FILE__, __LINE__, __FUNCTION__));
+
+ return 1;
+}
+
+static int
+u_close(struct pi_socket *ps)
+{
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s).\n",
+ __FILE__, __LINE__, __FUNCTION__));
+
+ RD_stop ();
+ USB_close ();
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s).\n",
+ __FILE__, __LINE__, __FUNCTION__));
+
+ return close (ps->sd);
+}
+
+static int
+u_wait_for_device(struct pi_socket *ps, int *timeout)
+{
+ pi_usb_data_t *data = (pi_usb_data_t *)ps->device->data;
+ struct timespec when;
+ int ret = 0;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s).\n",
+ __FILE__, __LINE__, __FUNCTION__));
+
+ if (*timeout)
+ pi_timeout_to_timespec (*timeout, &when);
+
+ while (1) {
+ ret = USB_poll (data);
+ if (ret > 0) {
+ /* Evil, calculate how much longer the timeout is. */
+ if (*timeout) {
+ *timeout = pi_timespec_to_timeout (&when);
+ if (*timeout <= 0)
+ *timeout = 1;
+ }
+ if (!RD_start ()) {
+ USB_close ();
+ return -1;
+ }
+ return ret;
+
+ }
+
+ if (*timeout) {
+ if (pi_timeout_expired(&when)) {
+ *timeout = 1;
+ return 0;
+ }
+ }
+ usleep (500000);
+ }
+
+ return 0;
+}
+
+static int
+u_poll(struct pi_socket *ps, int timeout)
+{
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s).\n",
+ __FILE__, __LINE__, __FUNCTION__));
+
+ return u_read_i (ps, NULL, 1, PI_MSG_PEEK, timeout);
+}
+
+static ssize_t
+u_write(struct pi_socket *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int timeout = ((struct pi_usb_data *)ps->device->data)->timeout;
+ int ret;
+
+ if (!RD_running)
+ return -1;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "Writing: len: %d, flags: %d, timeout: %d.\n", len, flags, timeout));
+ if (len <= 0)
+ return 0;
+
+ ret = usb_bulk_write (USB_handle, USB_out_endpoint, buf, len, timeout);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "Wrote: %d.\n", ret));
+ if (ret > 0)
+ CHECK (PI_DBG_DEV, PI_DBG_LVL_DEBUG, pi_dumpdata (buf, ret));
+
+ return (ssize_t)ret;
+}
+
+static ssize_t
+u_read(struct pi_socket *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ int ret;
+
+ ret = u_read_i (ps, buf, len, flags, ((struct pi_usb_data *)ps->device->data)->timeout);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "Read: %d (%d).\n", ret, len));
+ if (ret > 0)
+ CHECK (PI_DBG_DEV, PI_DBG_LVL_DEBUG, pi_dumpdata (buf->data, ret));
+
+ return (ssize_t)ret;
+}
+
+static int
+u_read_i(struct pi_socket *ps, pi_buffer_t *buf, size_t len, int flags, int timeout)
+{
+ if (!RD_running)
+ return PI_ERR_SOCK_DISCONNECTED;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d %d %d\n",
+ __FILE__, __LINE__, __FUNCTION__, len, flags, timeout));
+
+ pthread_mutex_lock (&RD_buffer_mutex);
+ if (flags & PI_MSG_PEEK && len > 256)
+ len = 256;
+
+ if (RD_buffer_used < len) {
+ struct timeval now;
+ struct timespec when, nownow;
+ int last_used;
+ gettimeofday(&now, NULL);
+ when.tv_sec = now.tv_sec + timeout / 1000;
+ when.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000;
+ if (when.tv_nsec >= 1000000000) {
+ when.tv_nsec -= 1000000000;
+ when.tv_sec++;
+ }
+
+ RD_wanted = len;
+ do {
+ last_used = RD_buffer_used;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d %d.\n",
+ __FILE__, __LINE__, __FUNCTION__, len, RD_buffer_used));
+
+ if (timeout) {
+ gettimeofday(&now, NULL);
+ nownow.tv_sec = now.tv_sec;
+ nownow.tv_nsec = now.tv_usec * 1000;
+ if ((nownow.tv_sec == when.tv_sec ? (nownow.tv_nsec > when.tv_nsec) : (nownow.tv_sec > when.tv_sec))) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d %d.\n",
+ __FILE__, __LINE__, __FUNCTION__, len, RD_buffer_used));
+ break;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d %d.\n",
+ __FILE__, __LINE__, __FUNCTION__, len, RD_buffer_used));
+ if (pthread_cond_timedwait (&RD_buffer_available_cond, &RD_buffer_mutex, &when) == ETIMEDOUT) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d %d.\n",
+ __FILE__, __LINE__, __FUNCTION__, len, RD_buffer_used));
+ break;
+ }
+ } else
+ pthread_cond_wait (&RD_buffer_available_cond, &RD_buffer_mutex);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d %d.\n",
+ __FILE__, __LINE__, __FUNCTION__, len, RD_buffer_used));
+ } while (RD_buffer_used < len);
+
+ RD_wanted = 0;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s): %d %d.\n",
+ __FILE__, __LINE__, __FUNCTION__, len, RD_buffer_used));
+
+ if (!RD_running) {
+ pthread_mutex_unlock (&RD_buffer_mutex);
+ return PI_ERR_SOCK_DISCONNECTED;
+ }
+
+ if (RD_buffer_used < len)
+ len = RD_buffer_used;
+
+ if (len && buf) {
+ pi_buffer_append (buf, RD_buffer, len);
+ if (!(flags & PI_MSG_PEEK)) {
+ RD_buffer_used -= len;
+ if (RD_buffer_used)
+ memmove (RD_buffer, RD_buffer + len, RD_buffer_used);
+
+ if ((RD_buffer_size - RD_buffer_used) > (1024 * 1024)) {
+ /* If we have more then 1M free in the buffer, shrink it. */
+ RD_buffer_size = ((RD_buffer_used + 0xfffe) & ~0xffff) - 1;
+ RD_buffer = realloc (RD_buffer, RD_buffer_size);
+ }
+ }
+ }
+
+ pthread_mutex_unlock (&RD_buffer_mutex);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s %d (%s).\n",
+ __FILE__, __LINE__, __FUNCTION__));
+ return len;
+}
+
+static int
+u_flush(pi_socket_t *ps, int flags)
+{
+ if (flags & PI_FLUSH_INPUT) {
+ /* clear internal buffer */
+ pthread_mutex_lock (&RD_buffer_mutex);
+ RD_buffer_used = 0;
+ pthread_mutex_unlock (&RD_buffer_mutex);
+ }
+ return 0;
+}
+
+static int
+u_control_request (pi_usb_data_t *usb_data, int request_type, int request,
+ int value, int control_index, void *data, int size, int timeout)
+{
+ return usb_control_msg (usb_data->ref, request_type, request, value, control_index, data, size, timeout);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/linuxusb.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/linuxusb.c
new file mode 100644
index 00000000..a662a01f
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/linuxusb.c
@@ -0,0 +1,400 @@
+/*
+ * $Id: linuxusb.c,v 1.24 2006/10/12 14:21:22 desrod Exp $
+ *
+ * linuxusb.c: device i/o for linux usb
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-usb.h"
+#include "pi-error.h"
+
+#ifdef HAVE_SYS_IOCTL_COMPAT_H
+#include <sys/ioctl_compat.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+
+
+static int u_open(pi_socket_t *ps, struct pi_sockaddr *addr, size_t addrlen);
+static int u_close(pi_socket_t *ps);
+static int u_write(pi_socket_t *ps, unsigned char *buf, size_t len, int flags);
+static int u_read(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags);
+static int u_poll(pi_socket_t *ps, int timeout);
+static int u_flush(pi_socket_t *ps, int flags);
+
+void pi_usb_impl_init (struct pi_usb_impl *impl)
+{
+ impl->open = u_open;
+ impl->close = u_close;
+ impl->write = u_write;
+ impl->read = u_read;
+ impl->flush = u_flush;
+ impl->poll = u_poll;
+ impl->wait_for_device = NULL; /* not implemented in linuxusb yet */
+ impl->changebaud = NULL; /* we don't need this one on linuxusb
+ * as USB serial adapters redirect to serial ports
+ */
+ impl->control_request = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * Function: u_open
+ *
+ * Summary: Open the usb port and establish a connection for
+ *
+ * Parameters: None
+ *
+ * Returns: The file descriptor
+ *
+ ***********************************************************************/
+static int
+u_open(pi_socket_t *ps, struct pi_sockaddr *addr, size_t addrlen)
+{
+ int fd,
+ i;
+ char *tty = addr->pi_device;
+
+ if ((fd = open(tty, O_RDWR | O_NONBLOCK)) < 0) {
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM; /* errno already set */
+ }
+
+ if (!isatty(fd)) {
+ close(fd);
+ errno = EINVAL;
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+ if ((i = fcntl(fd, F_GETFL, 0)) != -1) {
+ i &= ~O_NONBLOCK;
+ fcntl(fd, F_SETFL, i);
+ }
+
+ if ((i = pi_socket_setsd(ps, fd)) < 0)
+ return i;
+
+ return fd;
+}
+
+
+/***********************************************************************
+ *
+ * Function: u_close
+ *
+ * Summary: Close the open socket/file descriptor
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+u_close(pi_socket_t *ps)
+{
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV CLOSE linuxusb fd: %d\n", ps->sd));
+
+ return close(ps->sd);
+}
+
+
+/***********************************************************************
+ *
+ * Function: u_poll
+ *
+ * Summary: Poll the open socket/file descriptor
+ *
+ * Parameters: None
+ *
+ * Returns: 1 on success, PI_ERR_SOCK_TIMEOUT on timeout
+ *
+ ***********************************************************************/
+static int
+u_poll(pi_socket_t *ps, int timeout)
+{
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ if (timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+ select(ps->sd + 1, &ready, 0, 0, &t);
+ }
+
+ if (!FD_ISSET(ps->sd, &ready)) {
+ /* otherwise throw out any current packet and return */
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV POLL linuxusb timeout\n"));
+ errno = ETIMEDOUT;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV POLL linuxusb found data on fd: %d\n", ps->sd));
+
+ return 1;
+}
+
+
+/***********************************************************************
+ *
+ * Function: u_write
+ *
+ * Summary: Write to the open socket/file descriptor
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+u_write(pi_socket_t *ps, unsigned char *buf, size_t len, int flags)
+{
+ int total,
+ nwrote;
+ struct pi_usb_data *data = (struct pi_usb_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ total = len;
+ while (total > 0) {
+ if (data->timeout == 0)
+ select(ps->sd + 1, 0, &ready, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ if (select(ps->sd + 1, 0, &ready, 0, &t))
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ if (!FD_ISSET(ps->sd, &ready)) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+
+ nwrote = write(ps->sd, buf, len);
+ if (nwrote < 0) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+
+ total -= nwrote;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV TX linuxusb wrote %d bytes\n", len));
+
+ return len;
+}
+
+
+/***********************************************************************
+ *
+ * Function: u_read_buf
+ *
+ * Summary: read buffer
+ *
+ * Parameters: pi_socket_t*, char* to buffer, length of buffer
+ *
+ * Returns: number of bytes read
+ *
+ ***********************************************************************/
+static int
+u_read_buf (pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ struct pi_usb_data *data = (struct pi_usb_data *)ps->device->data;
+ size_t rbuf = data->buf_size;
+
+ if (rbuf > len)
+ rbuf = len;
+
+ if (pi_buffer_append (buf, data->buf, rbuf) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ if (flags != PI_MSG_PEEK) {
+ data->buf_size -= rbuf;
+ if (data->buf_size > 0)
+ memmove(data->buf, &data->buf[rbuf], data->buf_size);
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV RX linuxusb read %d bytes from read-ahead buffer\n", rbuf));
+
+ return rbuf;
+}
+
+
+/***********************************************************************
+ *
+ * Function: u_read
+ *
+ * Summary: Read incoming data from the socket/file descriptor
+ *
+ * Parameters: pi_socket_t*, char* to buffer, buffer length, flags
+ *
+ * Returns: number of bytes read or negative otherwise
+ *
+ ***********************************************************************/
+static int
+u_read(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ ssize_t rbuf = 0,
+ bytes;
+ struct pi_usb_data *data = (struct pi_usb_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ /* check whether we have at least partial data in store */
+ if (data->buf_size) {
+ rbuf = u_read_buf(ps, buf, len, flags);
+ if (rbuf < 0)
+ return rbuf;
+ len -= rbuf;
+ if (len == 0)
+ return rbuf;
+ }
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+ if (data->timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ if (select(ps->sd + 1, &ready, 0, 0, &t) == 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV RX linuxusb timeout\n"));
+ errno = ETIMEDOUT;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+ }
+
+ /* If data is available in time, read it */
+ if (FD_ISSET(ps->sd, &ready)) {
+ if (flags == PI_MSG_PEEK && len > 256)
+ len = 256;
+
+ if (pi_buffer_expect (buf, len) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ bytes = read(ps->sd, buf->data + buf->used, len);
+
+ if (bytes > 0) {
+ if (flags == PI_MSG_PEEK) {
+ memcpy(data->buf + data->buf_size, buf->data + buf->used, bytes);
+ data->buf_size += bytes;
+ }
+ buf->used += bytes;
+ rbuf += bytes;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV RX linuxusb read %d bytes\n", bytes));
+ }
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV RX linuxusb timeout\n"));
+ errno = ETIMEDOUT;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ return rbuf;
+}
+
+/***********************************************************************
+ *
+ * Function: u_flush
+ *
+ * Summary: Flush incoming and/or outgoing data from the socket/file
+ * descriptor
+ *
+ * Parameters: ps is of type pi_socket that contains the sd member which is
+ * the file descriptor that the data in buf will be read. It
+ * also contains the read buffer.
+ *
+ * flags is of type int and can be a combination of
+ * PI_FLUSH_INPUT and PI_FLUSH_OUTPUT
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+static int
+u_flush(pi_socket_t *ps, int flags)
+{
+ char buf[256];
+ int fl;
+ struct pi_usb_data *data = (struct pi_usb_data *) ps->device->data;
+
+ if (flags & PI_FLUSH_INPUT) {
+ /* clear internal buffer */
+ data->buf_size = 0;
+
+ /* flush pending data */
+ if ((fl = fcntl(ps->sd, F_GETFL, 0)) != -1) {
+ fcntl(ps->sd, F_SETFL, fl | O_NONBLOCK);
+ while (recv(ps->sd, buf, sizeof(buf), 0) > 0)
+ ;
+ fcntl(ps->sd, F_SETFL, 0);
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV FLUSH linuxusb flushed input buffer\n"));
+ }
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/location.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/location.c
new file mode 100644
index 00000000..537c7f2e
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/location.c
@@ -0,0 +1,805 @@
+/*
+ * $Id: location.c,v 1.1 2009/02/22 08:09:01 nicholas Exp $
+ *
+ * location.c: Translate Pilot location data formats
+ * (c) 2008, Jon Schewe
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pi-macros.h"
+#include "pi-location.h"
+
+/***********************************************************************
+ *
+ * Function: new_Timezone
+ *
+ * Summary: Create empty timzone
+ *
+ * Parameters: Timezone_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+new_Timezone(Timezone_t *a)
+{
+ a->offset = 0;
+ a->t2 = 0;
+ a->dstStart.dayOfWeek = 0;
+ a->dstStart.weekOfMonth = 0;
+ a->dstStart.month = 0;
+ a->dstStart.unknown = 0;
+ a->dstEnd.dayOfWeek = 0;
+ a->dstEnd.weekOfMonth = 0;
+ a->dstEnd.month = 0;
+ a->dstEnd.unknown = 0;
+ a->dstObserved = 0;
+ a->t4 = 0;
+ a->unknown = 0;
+ a->name = NULL;
+}
+
+/***********************************************************************
+ *
+ * Function: new_Locatio
+ *
+ * Summary: Create empty location
+ *
+ * Parameters: Location_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+new_Location(Location_t *a)
+{
+ new_Timezone(&(a->tz));
+ a->unknownExists = 0;
+ a->unknown = 0;
+ a->latitude.degrees = 0;
+ a->latitude.minutes = 0;
+ a->latitude.direction = 0;
+ a->longitude.degrees = 0;
+ a->longitude.minutes = 0;
+ a->longitude.direction = 0;
+ a->note = NULL;
+}
+
+/***********************************************************************
+ *
+ * Function: copy_Timezone
+ *
+ * Summary: Copy the data from one timezone to another. The destination
+ * timezone event must already be cleared, either by creating new or by
+ * calling free_Timezone on it first.
+ *
+ * Parameters: Timezone_t*, Timezone_t*
+ *
+ * Returns: int -1 on failure (errno will be set), 0 on success
+ *
+ ***********************************************************************/
+int
+copy_Timezone(const Timezone_t *source, Timezone_t *dest)
+{
+
+ dest->offset = source->offset;
+ dest->t2 = source->t2;
+ dest->dstStart.dayOfWeek = source->dstStart.dayOfWeek;
+ dest->dstStart.weekOfMonth = source->dstStart.weekOfMonth;
+ dest->dstStart.month = source->dstStart.month;
+ dest->dstStart.unknown = source->dstStart.unknown;
+ dest->dstEnd.dayOfWeek = source->dstEnd.dayOfWeek;
+ dest->dstEnd.weekOfMonth = source->dstEnd.weekOfMonth;
+ dest->dstEnd.month = source->dstEnd.month;
+ dest->dstEnd.unknown = source->dstEnd.unknown;
+ dest->dstObserved = source->dstObserved;
+ dest->t4 = source->t4;
+ dest->unknown = source->unknown;
+ if(NULL != source->name) {
+ dest->name = strdup(source->name);
+ } else {
+ dest->name = NULL;
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: copy_Location
+ *
+ * Summary: Copy the data from one location to another. The destination
+ * location event must already be cleared, either by creating new or by
+ * calling free_Location on it first.
+ *
+ * Parameters: Location_t*, Location_t*
+ *
+ * Returns: int -1 on failure (errno will be set), 0 on success
+ *
+ ***********************************************************************/
+int
+copy_Location(const Location_t *source, Location_t *dest)
+{
+ int retval;
+ retval = copy_Timezone(&(source->tz), &(dest->tz));
+ if(0 != retval) {
+ return retval;
+ }
+ dest->unknownExists = source->unknownExists;
+ dest->unknown = source->unknown;
+ dest->latitude.degrees = source->latitude.degrees;
+ dest->latitude.minutes = source->latitude.minutes;
+ dest->latitude.direction = source->latitude.direction;
+ dest->longitude.degrees = source->longitude.degrees;
+ dest->longitude.minutes = source->longitude.minutes;
+ dest->longitude.direction = source->longitude.direction;
+ if(NULL != source->note) {
+ dest->note = strdup(source->note);
+ } else {
+ dest->note = NULL;
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: free_Location
+ *
+ * Summary: Free the members of a location structure
+ *
+ * Parameters: Location_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Location(Location_t *loc)
+{
+ free_Timezone(&(loc->tz));
+
+ if(loc->note != NULL) {
+ free(loc->note);
+ loc->note = NULL;
+ }
+
+}
+
+/***********************************************************************
+ *
+ * Function: dup_Timezone
+ *
+ * Summary: Allocate memory for a new timezone that is a duplicate of this one and copy the data into it
+ *
+ * Parameters: Timezone_t*
+ *
+ * Returns: Timezone_t* or NULL if there isn't enough memory and errno is set to ENOMEM
+ *
+ ***********************************************************************/
+Timezone_t*
+dup_Timezone(const Timezone_t *tz)
+{
+ Timezone_t *retval = (Timezone_t*)malloc(sizeof(Timezone_t));
+ if(NULL == retval) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ retval->offset = tz->offset;
+ retval->t2 = tz->t2;
+ memcpy(&(retval->dstStart), &(tz->dstStart), sizeof(DST_t));
+ memcpy(&(retval->dstEnd), &(tz->dstEnd), sizeof(DST_t));
+ retval->dstObserved = tz->dstObserved;
+ retval->t4 = tz->t4;
+ retval->unknown = tz->unknown;
+ if(NULL != tz->name) {
+ retval->name = strdup(tz->name);
+ } else {
+ retval->name = NULL;
+ }
+
+ return retval;
+}
+
+/***********************************************************************
+ *
+ * Function: free_Timezone
+ *
+ * Summary: Free the members of a timezone structure
+ *
+ * Parameters: Timezone_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Timezone(Timezone_t *tz) {
+ if(tz->name != NULL) {
+ free(tz->name);
+ tz->name = NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_DST
+ *
+ * Summary: Fill in the daylight savings time structure based on the raw record
+ * data
+ *
+ * Parameters: DST_t*, pi_buffer_t *buf
+ *
+ * Returns: -1 on error, 0 on success
+ *
+ ***********************************************************************/
+int
+unpack_DST(DST_t *dst, const pi_buffer_t *buf) {
+ return unpack_DST_p(dst, buf->data, 0);
+}
+/**
+ Does the work for unpack_DST given a position in buf
+*/
+int
+unpack_DST_p(DST_t *dst, const unsigned char *data, const size_t position) {
+ uint8_t byte;
+
+ byte = get_byte(data+position);
+ switch(byte) {
+ case 0x00:
+ dst->dayOfWeek = sunday;
+ break;
+ case 0x01:
+ dst->dayOfWeek = monday;
+ break;
+ case 0x02:
+ dst->dayOfWeek = tuesday;
+ break;
+ case 0x03:
+ dst->dayOfWeek = wednesday;
+ break;
+ case 0x04:
+ dst->dayOfWeek = thursday;
+ break;
+ case 0x05:
+ dst->dayOfWeek = friday;
+ break;
+ case 0x06:
+ dst->dayOfWeek = saturday;
+ break;
+ default:
+ printf("Illegal value found in day of week: 0x%02X\n", byte);
+ return -1;
+ }
+
+ byte = get_byte(data+position+1);
+ switch(byte) {
+ case 0x00:
+ dst->weekOfMonth = first;
+ break;
+ case 0x01:
+ dst->weekOfMonth = second;
+ break;
+ case 0x02:
+ dst->weekOfMonth = third;
+ break;
+ case 0x03:
+ dst->weekOfMonth = fourth;
+ break;
+ case 0x04:
+ dst->weekOfMonth = last;
+ break;
+ default:
+ printf("Illegal value found in week: 0x%02Xd\n", byte);
+ return -1;
+ }
+
+ byte = get_byte(data+position+2);
+ switch(byte) {
+ case 0x00:
+ dst->month = none;
+ break;
+ case 0x01:
+ dst->month = january;
+ break;
+ case 0x02:
+ dst->month = february;
+ break;
+ case 0x03:
+ dst->month = march;
+ break;
+ case 0x04:
+ dst->month = april;
+ break;
+ case 0x05:
+ dst->month = may;
+ break;
+ case 0x06:
+ dst->month = june;
+ break;
+ case 0x07:
+ dst->month = july;
+ break;
+ case 0x08:
+ dst->month = august;
+ break;
+ case 0x09:
+ dst->month = september;
+ break;
+ case 0x0a:
+ dst->month = october;
+ break;
+ case 0x0b:
+ dst->month = november;
+ break;
+ case 0x0c:
+ dst->month = december;
+ break;
+ default:
+ printf("Illegal value found in month: 0x%02Xd\n", byte);
+ return -1;
+ }
+
+ dst->unknown = get_byte(data+position+3);
+ switch(dst->unknown) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ /*case 0x04:*/
+ break;
+ default:
+ printf("Bad value for DST.unknown: 0x%02x\n", dst->unknown);
+ return -1;
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_timezone
+ *
+ * Summary: Fill in the timezone structure based on the raw record
+ * data
+ *
+ * Parameters: Timezone_t*, pi_buffer_t *buf, optional position in buf
+ *
+ * Returns: -1 on error, number of bytes read on success
+ *
+ ***********************************************************************/
+int
+unpack_Timezone(Timezone_t *tz, const pi_buffer_t *buf) {
+ return unpack_Timezone_p(tz, buf->data, 0);
+}
+/**
+ * Does the work of unpack_Timezone given a position in buf.
+ *
+ * Returns: -1 on error, number of bytes read on success
+ */
+int
+unpack_Timezone_p(Timezone_t *tz, const unsigned char *data, const size_t position) {
+ uint8_t byte;
+ size_t localPosition = position;
+
+ tz->offset = get_short(data+localPosition);
+ localPosition += 2;
+ /*printf("Offset is %d\n", tz->offset);*/
+
+ tz->t2 = get_byte(data + localPosition);
+ ++localPosition;
+ switch(tz->t2) {
+ case 0x00:
+ break;
+ case 0x01:
+ break;
+ case 0x02:
+ break;
+ case 0x03:
+ break;
+ default:
+ /*printf("Bad value for t2 0x%02X\n", tz->t2);*/
+ return -1;
+ }
+
+ if(unpack_DST_p(&(tz->dstStart), data, localPosition) != 0) {
+ return -1;
+ }
+ localPosition += 4;
+
+ if(unpack_DST_p(&(tz->dstEnd), data, localPosition) != 0) {
+ return -1;
+ }
+ localPosition += 4;
+
+ byte = get_byte(data+localPosition);
+ ++localPosition;
+ switch(byte) {
+ case 0x3c:
+ /* dst observed */
+ tz->dstObserved = 1;
+ break;
+ case 0x00:
+ /* dst not observed */
+ tz->dstObserved = 0;
+ break;
+ default:
+ printf("Illegal value in dst_observed 0x%02X\n", byte);
+ return -1;
+ }
+
+ tz->t4 = get_byte(data+localPosition);
+ ++localPosition;
+
+ tz->unknown = get_byte(data+localPosition);
+ ++localPosition;
+ switch(tz->unknown) {
+ case 0x80:
+ case 0x00:
+ break;
+ default:
+ printf("Bad value for unknown 0x%02X\n", tz->unknown);
+ return -1;
+ }
+
+ if(0x00 == data+localPosition) {
+ tz->name = NULL;
+ ++localPosition;
+ } else {
+ tz->name = strdup((char *)(data+localPosition));
+ localPosition += strlen(tz->name) + 1;
+ }
+
+ return localPosition;
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_Location
+ *
+ * Summary: Fill in the location structure based on the raw record
+ * data
+ *
+ * Parameters: Location_t*, pi_buffer_t *buf
+ *
+ * Returns: -1 on error, 0 on success
+ *
+ ***********************************************************************/
+int
+unpack_Location(Location_t *loc, const pi_buffer_t *buf)
+{
+ size_t localPosition = 0;
+
+ localPosition = unpack_Timezone_p(&(loc->tz), buf->data, localPosition);
+ if(localPosition < 0) {
+ return -1;
+ }
+
+ loc->unknownExists = 0;
+
+ /* unpack latitude */
+ loc->latitude.degrees = get_short(buf->data+localPosition);
+ loc->latitude.minutes = get_short(buf->data+localPosition+2);
+ if(loc->latitude.degrees > 90 || loc->latitude.degrees < -90
+ || loc->latitude.minutes > 60 || loc->latitude.minutes < -60) {
+ /*
+ printf("latitude degrees out of range: %d or\n", loc->latitude.degrees);
+ printf("latitude minutes out of range: %d\n", loc->latitude.minutes);
+ */
+
+ loc->unknownExists = 1;
+ loc->unknown = get_byte(buf->data+localPosition);
+ ++localPosition;
+
+ /*printf("Found unknown: 0x%02X\n", loc->unknown); */
+
+ loc->latitude.degrees = get_short(buf->data+localPosition);
+ localPosition += 2;
+ loc->latitude.minutes = get_short(buf->data+localPosition);
+ localPosition += 2;
+ } else {
+ localPosition += 4;
+ }
+
+ loc->longitude.degrees = get_short(buf->data+localPosition);
+ localPosition += 2;
+ loc->longitude.minutes = get_short(buf->data+localPosition);
+ localPosition += 2;
+
+ /* now make latitude and longitude easy to read */
+ loc->latitude.direction = south;
+ loc->longitude.direction = west;
+ if(loc->latitude.minutes < 0) {
+ loc->latitude.direction = north;
+ loc->latitude.minutes = -1 * loc->latitude.minutes;
+ }
+ if(loc->latitude.degrees < 0) {
+ loc->latitude.direction = north;
+ loc->latitude.degrees = -1 * loc->latitude.degrees;
+ }
+ if(loc->longitude.minutes < 0) {
+ loc->longitude.direction = east;
+ loc->longitude.minutes = -1 * loc->longitude.minutes;
+ }
+ if(loc->longitude.degrees < 0) {
+ loc->longitude.direction = east;
+ loc->longitude.degrees = -1 * loc->longitude.degrees;
+ }
+
+
+ if(0x00 == buf->data[localPosition]) {
+ loc->note = NULL;
+ ++localPosition;
+ } else {
+ loc->note = strdup((char *)(buf->data+localPosition));
+ localPosition += strlen(loc->note) + 1;
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_DST
+ *
+ * Summary: append raw DST record data to buf based on the
+ * DST structure
+ *
+ * Parameters: DST_t*, pi_buffer_t *buf of record, record type
+ *
+ * Returns: -1 on error, 0 on success.
+ *
+ ***********************************************************************/
+int
+pack_DST(const DST_t *dst, pi_buffer_t *buf)
+{
+ size_t offset;
+
+ if (dst == NULL || buf == NULL)
+ return -1;
+
+ offset = buf->used;
+
+ pi_buffer_expect(buf, buf->used + 4);
+ buf->used = buf->used + 4;
+
+ switch(dst->dayOfWeek) {
+ case sunday:
+ set_byte(buf->data+offset, 0x00);
+ break;
+ case monday:
+ set_byte(buf->data+offset, 0x01);
+ break;
+ case tuesday:
+ set_byte(buf->data+offset, 0x02);
+ break;
+ case wednesday:
+ set_byte(buf->data+offset, 0x03);
+ break;
+ case thursday:
+ set_byte(buf->data+offset, 0x04);
+ break;
+ case friday:
+ set_byte(buf->data+offset, 0x05);
+ break;
+ case saturday:
+ set_byte(buf->data+offset, 0x06);
+ break;
+ default:
+ return -1;
+
+ }
+
+ switch(dst->weekOfMonth) {
+ case first:
+ set_byte(buf->data+offset+1, 0x00);
+ break;
+ case second:
+ set_byte(buf->data+offset+1, 0x01);
+ break;
+ case third:
+ set_byte(buf->data+offset+1, 0x02);
+ break;
+ case fourth:
+ set_byte(buf->data+offset+1, 0x03);
+ break;
+ case last:
+ set_byte(buf->data+offset+1, 0x04);
+ break;
+ default:
+ return -1;
+
+ }
+
+ switch(dst->month) {
+ case none:
+ set_byte(buf->data+offset+2, 0x00);
+ break;
+ case january:
+ set_byte(buf->data+offset+2, 0x01);
+ break;
+ case february:
+ set_byte(buf->data+offset+2, 0x02);
+ break;
+ case march:
+ set_byte(buf->data+offset+2, 0x03);
+ break;
+ case april:
+ set_byte(buf->data+offset+2, 0x04);
+ break;
+ case may:
+ set_byte(buf->data+offset+2, 0x05);
+ break;
+ case june:
+ set_byte(buf->data+offset+2, 0x06);
+ break;
+ case july:
+ set_byte(buf->data+offset+2, 0x07);
+ break;
+ case august:
+ set_byte(buf->data+offset+2, 0x08);
+ break;
+ case september:
+ set_byte(buf->data+offset+2, 0x09);
+ break;
+ case october:
+ set_byte(buf->data+offset+2, 0x0a);
+ break;
+ case november:
+ set_byte(buf->data+offset+2, 0x0b);
+ break;
+ case december:
+ set_byte(buf->data+offset+2, 0x0c);
+ break;
+ default:
+ return -1;
+ }
+
+ set_byte(buf->data+offset+3, dst->unknown);
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_Timezone
+ *
+ * Summary: Append the raw Timezone record to buf based on the
+ * Timezone structure
+ *
+ * Parameters: Timezone_t*, pi_buffer_t *buf of record, record type
+ *
+ * Returns: -1 on error, 0 on success.
+ *
+ ***********************************************************************/
+int
+pack_Timezone(const Timezone_t *tz, pi_buffer_t *buf)
+{
+
+ size_t offset;
+
+ if (tz == NULL || buf == NULL)
+ return -1;
+
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used + 3);
+ buf->used = buf->used + 3;
+
+ set_short(buf->data+offset, tz->offset);
+ set_byte(buf->data+offset+2, tz->t2);
+
+ pack_DST(&(tz->dstStart), buf);
+ pack_DST(&(tz->dstEnd), buf);
+
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used + 3);
+ buf->used = buf->used + 3;
+
+ if(tz->dstObserved) {
+ set_byte(buf->data+offset, 0x3c);
+ } else {
+ set_byte(buf->data+offset, 0x00);
+ }
+ set_byte(buf->data+offset, tz->t4);
+
+ if(NULL != tz->name) {
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used + strlen(tz->name)+1);
+ buf->used = buf->used + strlen(tz->name)+1;
+
+ strcpy((char *)(buf->data+offset), tz->name);
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pack_Location
+ *
+ * Summary: Append the raw Location record to buf based on the
+ * Location structure
+ *
+ * Parameters: Location_t*, pi_buffer_t *buf of record, record type
+ *
+ * Returns: -1 on error, 0 on success.
+ *
+ ***********************************************************************/
+int
+pack_Location(const Location_t *loc, pi_buffer_t *buf)
+{
+ size_t offset;
+
+ if (loc == NULL || buf == NULL)
+ return -1;
+
+ pack_Timezone(&(loc->tz), buf);
+
+ if(loc->unknownExists) {
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used + 1);
+ buf->used = buf->used+1;
+ set_byte(buf->data+offset, loc->unknown);
+ }
+
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used+8);
+ buf->used = buf->used+8;
+
+ if(loc->latitude.direction == north) {
+ set_short(buf->data+offset, -1 * loc->latitude.degrees);
+ set_short(buf->data+offset+2, -1 * loc->latitude.minutes);
+ } else {
+ set_short(buf->data+offset, loc->latitude.degrees);
+ set_short(buf->data+offset+2, loc->latitude.minutes);
+ }
+ if(loc->longitude.direction == east) {
+ set_short(buf->data+offset+4, -1 * loc->longitude.degrees);
+ set_short(buf->data+offset+6, -1 * loc->longitude.minutes);
+ } else {
+ set_short(buf->data+offset+4, loc->longitude.degrees);
+ set_short(buf->data+offset+6, loc->longitude.minutes);
+ }
+
+ if(NULL != loc->note) {
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used + strlen(loc->note)+1);
+ buf->used = buf->used + strlen(loc->note)+1;
+
+ strcpy((char *)(buf->data+offset), loc->note);
+ } else {
+ offset = buf->used;
+ pi_buffer_expect(buf, buf->used + 1);
+ set_byte(buf->data+offset, 0);
+ buf->used = buf->used + 1;
+ }
+
+
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/mail.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/mail.c
new file mode 100644
index 00000000..f4c97bc9
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/mail.c
@@ -0,0 +1,683 @@
+/*
+ * $Id: mail.c,v 1.25 2006/10/12 14:21:22 desrod Exp $
+ *
+ * mail.c: Translate Pilot mail data formats
+ *
+ * Copyright (c) 1997, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-mail.h"
+
+char *MailSortTypeNames[] = { "Date", "Type", NULL };
+char *MailSyncTypeNames[] = { "All", "Send", "Filter", NULL };
+
+/***********************************************************************
+ *
+ * Function: free_Mail
+ *
+ * Summary: frees all the Mail_t structure members
+ *
+ * Parameters: Mail_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Mail(Mail_t *mail)
+{
+ if (mail->from != NULL) {
+ free(mail->from);
+ mail->from = NULL;
+ }
+
+ if (mail->to != NULL) {
+ free(mail->to);
+ mail->to = NULL;
+ }
+
+ if (mail->subject != NULL) {
+ free(mail->subject);
+ mail->to = NULL;
+ }
+
+ if (mail->cc != NULL) {
+ free(mail->cc);
+ mail->cc = NULL;
+ }
+
+ if (mail->bcc != NULL) {
+ free(mail->bcc);
+ mail->bcc = NULL;
+ }
+
+ if (mail->replyTo) {
+ free(mail->replyTo);
+ mail->replyTo = NULL;
+ }
+
+ if (mail->sentTo) {
+ free(mail->sentTo);
+ mail->sentTo = NULL;
+ }
+
+ if (mail->body != NULL) {
+ free(mail->body);
+ mail->body = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: free_MailAppInfo
+ *
+ * Summary: frees all MailAppInfo_t structure members
+ *
+ * Parameters: MailAppInfo_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_MailAppInfo(MailAppInfo_t *appinfo)
+{
+ /* if (appinfo->signature)
+ free(appinfo->signature); */
+}
+
+
+/***********************************************************************
+ *
+ * Function: free_MailSyncPref
+ *
+ * Summary: frees all MailSyncPref_t structure members
+ *
+ * Parameters: MailSyncPref_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_MailSyncPref(MailSyncPref_t *pref)
+{
+ if (pref->filterTo != NULL) {
+ free(pref->filterTo);
+ pref->filterTo = NULL;
+ }
+
+ if (pref->filterFrom != NULL) {
+ free(pref->filterFrom);
+ pref->filterFrom = NULL;
+ }
+
+ if (pref->filterSubject != NULL) {
+ free(pref->filterSubject);
+ pref->filterSubject = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: free_MailSignaturePref
+ *
+ * Summary: frees all MailSignaturePref_t structure members
+ *
+ * Parameters: MailSignaturePref_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_MailSignaturePref(MailSignaturePref_t *pref)
+{
+ if (pref->signature != NULL) {
+ free(pref->signature);
+ pref->signature = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_Mail
+ *
+ * Summary: unpacks Mail
+ *
+ * Parameters: Mail_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_Mail(Mail_t *mail, unsigned char *buffer, size_t len)
+{
+ int flags;
+ unsigned long d;
+ unsigned char *start = buffer;
+
+ if (len < 6)
+ return 0;
+
+ d = (unsigned short int) get_short(buffer);
+ mail->date.tm_year = (d >> 9) + 4;
+ mail->date.tm_mon = ((d >> 5) & 15) - 1;
+ mail->date.tm_mday = d & 31;
+ mail->date.tm_hour = get_byte(buffer + 2);
+ mail->date.tm_min = get_byte(buffer + 3);
+ mail->date.tm_sec = 0;
+ mail->date.tm_isdst = -1;
+ mktime(&mail->date);
+
+ if (d)
+ mail->dated = 1;
+ else
+ mail->dated = 0;
+
+ flags = get_byte(buffer + 4);
+
+ mail->read = (flags & (1 << 7)) ? 1 : 0;
+ mail->signature = (flags & (1 << 6)) ? 1 : 0;
+ mail->confirmRead = (flags & (1 << 5)) ? 1 : 0;
+ mail->confirmDelivery = (flags & (1 << 4)) ? 1 : 0;
+ mail->priority = (flags & (3 << 2)) >> 2;
+ mail->addressing = (flags & 3);
+
+ buffer += 6;
+ len -= 6;
+
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->subject = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->subject = 0;
+ buffer++;
+ len--;
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->from = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->from = 0;
+ buffer++;
+ len--;
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->to = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->to = 0;
+ buffer++;
+ len--;
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->cc = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->cc = 0;
+ buffer++;
+ len--;
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->bcc = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->bcc = 0;
+ buffer++;
+ len--;
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->replyTo = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->replyTo = 0;
+ buffer++;
+ len--;
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->sentTo = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->sentTo = 0;
+ buffer++;
+ len--;
+ if (len < 1)
+ return 0;
+ if (get_byte(buffer)) {
+ mail->body = strdup((char *)buffer);
+ buffer += strlen((char *)buffer);
+ len -= strlen((char *)buffer);
+ } else
+ mail->body = 0;
+ buffer++;
+ len--;
+
+ return (buffer - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_Mail
+ *
+ * Summary: packs Mail
+ *
+ * Parameters: Mail_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+pack_Mail(struct Mail *mail, unsigned char *buffer, size_t len)
+{
+ size_t destlen = 6 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1;
+ unsigned char *start = buffer;
+
+ if (mail->subject)
+ destlen += strlen(mail->subject);
+ if (mail->from)
+ destlen += strlen(mail->from);
+ if (mail->to)
+ destlen += strlen(mail->to);
+ if (mail->cc)
+ destlen += strlen(mail->cc);
+ if (mail->bcc)
+ destlen += strlen(mail->bcc);
+ if (mail->replyTo)
+ destlen += strlen(mail->replyTo);
+ if (mail->sentTo)
+ destlen += strlen(mail->sentTo);
+ if (mail->body)
+ destlen += strlen(mail->body);
+
+ if (!buffer)
+ return destlen;
+ if (len < destlen)
+ return 0;
+
+ set_short(buffer,
+ ((mail->date.tm_year - 4) << 9) | ((mail->date.tm_mon +
+ 1) << 5) | mail->date.
+ tm_mday);
+ set_byte(buffer + 2, mail->date.tm_hour);
+ set_byte(buffer + 3, mail->date.tm_min);
+
+ if (!mail->dated)
+ set_long(buffer, 0);
+
+ set_byte(buffer + 4, (mail->read ? (1 << 7) : 0) |
+ (mail->signature ? (1 << 6) : 0) | (mail->
+ confirmRead ? (1 << 5) :
+ 0) | (mail->
+ confirmDelivery
+ ? (1 << 4) : 0) |
+ ((mail->priority & 3) << 2) | (mail->addressing & 3));
+ set_byte(buffer + 5, 0);
+
+ buffer += 6;
+
+ if (mail->subject) {
+ strcpy((char *)buffer, mail->subject);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+ if (mail->from) {
+ strcpy((char *)buffer, mail->from);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+ if (mail->to) {
+ strcpy((char *)buffer, mail->to);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+ if (mail->cc) {
+ strcpy((char *)buffer, mail->cc);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+ if (mail->bcc) {
+ strcpy((char *)buffer, mail->bcc);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+ if (mail->replyTo) {
+ strcpy((char *)buffer, mail->replyTo);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+ if (mail->sentTo) {
+ strcpy((char *)buffer, mail->sentTo);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+ if (mail->body) {
+ strcpy((char *)buffer, mail->body);
+ buffer += strlen((char *)buffer);
+ } else
+ set_byte(buffer, 0);
+ buffer++;
+
+ return (buffer - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_MailAppInfo
+ *
+ * Summary: unpacks MailAppInfo
+ *
+ * Parameters: MailAppInfo_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_MailAppInfo(MailAppInfo_t *appinfo, unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = unpack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+ if (len < 11)
+ return 0;
+ appinfo->dirty = get_short(record);
+ record += 2;
+ appinfo->sortOrder = get_byte(record);
+ record += 2;
+ appinfo->unsentMessage = get_long(record);
+ record += 4;
+
+/* ai->signature = 0; */
+/* strdup(start + get_short(record)); */
+ record += 3;
+
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_MailAppInfo
+ *
+ * Summary: packs MailAppInfo
+ *
+ * Parameters: MailAppInfo_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+pack_MailAppInfo(struct MailAppInfo *appinfo, unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!record)
+ return i + 11;
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+ if (len < 8)
+ return 0;
+ set_short(record, appinfo->dirty);
+ record += 2;
+ set_short(record, 0); /* gapfill */
+ set_byte(record, appinfo->sortOrder);
+ record += 2;
+ set_long(record, appinfo->unsentMessage);
+ record += 4;
+
+ set_short(record, (record - start + 2));
+ record += 2;
+
+ /* if (appinfo->signature)
+ strcpy(record, appinfo->signature);
+ else
+ set_byte(record, 0);
+ record += strlen(record); */
+ set_byte(record, 0);
+ record++;
+
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_MailSyncPref
+ *
+ * Summary: unpacks Mail
+ *
+ * Parameters: MailSyncPref_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_MailSyncPref(MailSyncPref_t *pref, unsigned char *record, size_t len)
+{
+ unsigned char *start = record;
+
+ pref->syncType = get_byte(record);
+ record += 1;
+ pref->getHigh = get_byte(record);
+ record += 1;
+ pref->getContaining = get_byte(record);
+ record += 2;
+ pref->truncate = get_short(record);
+ record += 2;
+
+ if (get_byte(record)) {
+ pref->filterTo = strdup((char *)record);
+ record += strlen((char *)record);
+ } else
+ pref->filterTo = 0;
+ record++;
+ if (get_byte(record)) {
+ pref->filterFrom = strdup((char *)record);
+ record += strlen((char *)record);
+ } else
+ pref->filterFrom = 0;
+ record++;
+ if (get_byte(record)) {
+ pref->filterSubject = strdup((char *)record);
+ record += strlen((char *)record);
+ } else
+ pref->filterSubject = 0;
+ record++;
+
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_MailSyncPref
+ *
+ * Summary: packs Mail
+ *
+ * Parameters: MailSyncPref_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+pack_MailSyncPref(MailSyncPref_t *pref, unsigned char *record, size_t len)
+{
+ size_t destlen = 6 + 1 + 1 + 1;
+ unsigned char *start = record;
+
+ if (pref->filterTo)
+ destlen += strlen(pref->filterTo);
+ if (pref->filterSubject)
+ destlen += strlen(pref->filterSubject);
+ if (pref->filterFrom)
+ destlen += strlen(pref->filterFrom);
+
+ if (!record)
+ return destlen;
+ if (len < destlen)
+ return 0;
+
+ set_byte(record, pref->syncType);
+ record++;
+ set_byte(record, pref->getHigh);
+ record++;
+ set_byte(record, pref->getContaining);
+ record++;
+ set_byte(record, 0);
+ record++; /* gapfill */
+ set_short(record, pref->truncate);
+ record += 2;
+
+ if (pref->filterTo) {
+ strcpy((char *)record, pref->filterTo);
+ record += strlen(pref->filterTo);
+ }
+ *record++ = 0;
+
+ if (pref->filterFrom) {
+ strcpy((char *)record, pref->filterFrom);
+ record += strlen(pref->filterFrom);
+ }
+ *record++ = 0;
+
+ if (pref->filterSubject) {
+ strcpy((char *)record, pref->filterSubject);
+ record += strlen(pref->filterSubject);
+ }
+ *record++ = 0;
+
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_MailSignaturePref
+ *
+ * Summary: unpacks MailSignaturePref
+ *
+ * Parameters: MailSignaturePref_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_MailSignaturePref(MailSignaturePref_t *pref,
+ unsigned char *record, size_t len)
+{
+ unsigned char *start = record;
+
+ if (len < 1)
+ return 0;
+
+ pref->signature = strdup((char *)record);
+
+ record += strlen(pref->signature) + 1;
+
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_MailSignaturePref
+ *
+ * Summary: packs MailSignaturePref
+ *
+ * Parameters: MailSignaturePref_t*, char* to buffer, buffer length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+pack_MailSignaturePref(struct MailSignaturePref *pref, unsigned char *record,
+ size_t len)
+{
+ size_t destlen = 1;
+ unsigned char *start = record;
+
+ if (pref->signature)
+ destlen += strlen(pref->signature);
+
+ if (!record)
+ return destlen;
+ if (len < destlen)
+ return 0;
+ if (pref->signature) {
+ strcpy((char *)record, pref->signature);
+ record += strlen(pref->signature);
+ }
+ *record = 0;
+ record++;
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/md5.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/md5.c
new file mode 100644
index 00000000..cc8213b0
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/md5.c
@@ -0,0 +1,240 @@
+/*
+ * $Id: md5.c,v 1.9 2006/10/12 14:21:22 desrod Exp $
+ *
+ * LICENSE: Public Domain
+ *
+ * This code implements the MD5 message-digest algorithm. The algorithm is
+ * due to Ron Rivest. This code was written by Colin Plumb in 1993, no
+ * copyright is claimed. This code is in the public domain; do with it what
+ * you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc. This code has
+ * been tested against that, and is equivalent, except that you don't need
+ * to include two pages of legalese with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an MD5Context
+ * structure, pass it to MD5Init, call MD5Update as needed on buffers full
+ * of bytes, and then call MD5Final, which will fill a supplied 16-byte
+ * array with the digest.
+ *
+ * Modified by Ian Jackson in 1995 so as not to use Colin Plumb's
+ * 'usuals.h'. Arranged for byteSwap to be compiled and called even on
+ * little-endian machines, as performance isn't critical here.
+ *
+ */
+
+#include <string.h> /* for memcpy() */
+#include "pi-md5.h"
+
+/*
+ * Note: this code is harmless but does nothing on little-endian machines.
+ */
+void byteSwap(UINT32 * buf, unsigned words)
+{
+ UINT8 *p = (UINT8 *) buf;
+
+ do {
+ *buf++ = (UINT32) ((unsigned) p[3] << 8 | p[2]) << 16 |
+ ((unsigned) p[1] << 8 | p[0]);
+ p += 4;
+ } while (--words);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+ ctx->bytes[0] = 0;
+ ctx->bytes[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, UINT8 const *buf, unsigned len)
+{
+ UINT32 t;
+
+ /* Update byte count */
+
+ t = ctx->bytes[0];
+ if ((ctx->bytes[0] = t + len) < t)
+ ctx->bytes[1]++; /* Carry from low to high */
+
+ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
+ if (t > len) {
+ memcpy((UINT8 *) ctx->in + 64 - t, buf, len);
+ return;
+ }
+ /* First chunk is an odd size */
+ memcpy((UINT8 *) ctx->in + 64 - t, buf, t);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+
+ /* Process data in 64-byte chunks */
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(UINT8 digest[16], struct MD5Context *ctx)
+{
+ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+ UINT8 *p = (UINT8 *) ctx->in + count;
+
+ /* Set the first char of padding to 0x80. There is always room. */
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 56 bytes (-8..55) */
+ count = 56 - 1 - count;
+
+ if (count < 0) { /* Padding forces an extra block */
+ memset(p, 0, (size_t)(count + 8));
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ p = (UINT8 *) ctx->in;
+ count = 56;
+ }
+ memset(p, 0, (size_t)count);
+ byteSwap(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ctx->in[14] = ctx->bytes[0] << 3;
+ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+ MD5Transform(ctx->buf, ctx->in);
+
+ byteSwap(ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void MD5Transform(UINT32 buf[4], UINT32 const in[16])
+{
+ register UINT32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+#endif
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/memo.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/memo.c
new file mode 100644
index 00000000..aab418f8
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/memo.c
@@ -0,0 +1,186 @@
+/*
+ * $Id: memo.c,v 1.27 2006/11/22 22:52:25 adridg Exp $
+ *
+ * memo.c: Translate Pilot memopad data formats
+ *
+ * Copyright (c) 1996, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-macros.h"
+#include "pi-memo.h"
+
+/***********************************************************************
+ *
+ * Function: free_Memo
+ *
+ * Summary: Frees all record data associated with the Memo database
+ *
+ * Parameters: Memo_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_Memo(Memo_t *memo)
+{
+ if (memo->text != NULL) {
+ free(memo->text);
+ memo->text = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_Memo
+ *
+ * Summary: Unpack the memo structure from the buffer
+ *
+ * Parameters: Memo_t*, char* to buffer, length
+ *
+ * Returns: Length in bytes of the buffer allocated
+ *
+ ***********************************************************************/
+int
+unpack_Memo(Memo_t *memo, const pi_buffer_t *record, memoType type)
+{
+ if (type != memo_v1)
+ /* Don't support anything else yet */
+ return -1;
+ if (record == NULL || record->data == NULL || record->used < 1)
+ return -1;
+ memo->text = strdup((char *) record->data);
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_Memo
+ *
+ * Summary: Pack the memo structure into the buffer allocated
+ *
+ * Parameters: Memo_t*, char* to buffer, length of buffer
+ *
+ * Returns: buffer length
+ *
+ ***********************************************************************/
+int
+pack_Memo(const Memo_t *memo, pi_buffer_t *record, memoType type)
+{
+ size_t destlen = (memo->text ? strlen(memo->text) : 0) + 1;
+
+ if (type != memo_v1)
+ /* Don't support anything else yet */
+ return -1;
+ if (record == NULL)
+ return -1;
+
+ pi_buffer_expect(record, destlen);
+ record->used = destlen;
+
+ if (memo->text)
+ strcpy((char *) record->data, memo->text);
+ else
+ record->data[0] = 0;
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_MemoAppInfo
+ *
+ * Summary: Unpack the memo AppInfo block structure
+ *
+ * Parameters: MemoAppInfo_t*, char* to record, record length
+ *
+ * Returns: effective record length
+ *
+ ***********************************************************************/
+int
+unpack_MemoAppInfo(struct MemoAppInfo *appinfo, const unsigned char *record,
+ size_t len)
+{
+ int i = unpack_CategoryAppInfo(&appinfo->category, record, len);
+ unsigned char *start = record;
+
+ appinfo->type = memo_v1;
+
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+ if (len >= 4) {
+ record += 2;
+ appinfo->sortByAlpha = get_byte(record);
+ record += 2;
+ } else {
+ appinfo->sortByAlpha = 0;
+ }
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_MemoAppInfo
+ *
+ * Summary: Pack the memo AppInfo block structure
+ *
+ * Parameters: MemoAppInfo_t*, char* to record, record length
+ *
+ * Returns: effective record length
+ *
+ ***********************************************************************/
+int
+pack_MemoAppInfo(const MemoAppInfo_t *appinfo, unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!record)
+ return i + 4;
+ if (i == 0) /* category pack failed */
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 4)
+ return (record - start);
+ set_short(record, 0); /* gapfill new for 2.0 */
+ record += 2;
+ set_byte(record, appinfo->sortByAlpha); /* new for 2.0 */
+ record++;
+ set_byte(record, 0); /* gapfill new for 2.0 */
+ record++;
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/money.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/money.c
new file mode 100644
index 00000000..3173cae9
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/money.c
@@ -0,0 +1,268 @@
+/*
+ * $Id: money.c,v 1.16 2006/10/12 14:21:22 desrod Exp $
+ *
+ * money.c: Translate Pilot MoneyManager data formats
+ *
+ * Copyright (c) 1998, Rui Oliveira
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-macros.h"
+#include "pi-money.h"
+
+/***********************************************************************
+ *
+ * Function: unpack_Transaction
+ *
+ * Summary: unpacks Transaction_t data
+ *
+ * Parameters: Transaction_t*, char* to buffer, length of buffer
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_Transaction(Transaction_t *trans, unsigned char *buffer, size_t len)
+{
+
+ unsigned char *p;
+
+ if (len < 46)
+ return 0;
+
+ p = buffer;
+ trans->flags = get_byte(p);
+ p += 2; /* gap */
+ trans->checknum = get_short(p);
+ p += 2;
+ trans->amount = get_slong(p);
+ p += 4;
+ trans->total = get_slong(p);
+ p += 4;
+ trans->amountc = get_sshort(p);
+ p += 2;
+ trans->totalc = get_sshort(p);
+ p += 2;
+
+ trans->second = get_sshort(p);
+ p += 2;
+ trans->minute = get_sshort(p);
+ p += 2;
+ trans->hour = get_sshort(p);
+ p += 2;
+ trans->day = get_sshort(p);
+ p += 2;
+ trans->month = get_sshort(p);
+ p += 2;
+ trans->year = get_sshort(p);
+ p += 2;
+ trans->wday = get_sshort(p);
+ p += 2;
+
+ trans->repeat = get_byte(p);
+ p += 1;
+ trans->flags2 = get_byte(p);
+ p += 1;
+ trans->type = get_byte(p);
+ p += 1;
+
+ memcpy(trans->reserved, p, 2);
+ p += 2;
+
+ trans->xfer = get_byte(p);
+ p += 1;
+
+ strcpy(trans->description, (char *)p);
+ p += 19;
+ strcpy(trans->note, (char *)p);
+ p += strlen((char *)p) + 1;
+
+ return (p - buffer);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_Transaction
+ *
+ * Summary: unpacks Transaction_t data
+ *
+ * Parameters: Transaction_t*, char* to buffer, length of buffer
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int pack_Transaction(struct Transaction *trans, unsigned char *buffer,
+ size_t len)
+{
+ size_t destlen = 46 + strlen(trans->note) + 1;
+ unsigned char *p;
+
+ if (!buffer)
+ return destlen;
+ if (len < destlen)
+ return 0;
+
+ p = buffer;
+ set_byte(p, trans->flags);
+ p += 1;
+ set_byte(p, 0);
+ p += 1; /* gap fill */
+ set_short(p, trans->checknum);
+ p += 2;
+ set_slong(p, trans->amount);
+ p += 4;
+ set_slong(p, trans->total);
+ p += 4;
+ set_sshort(p, trans->amountc);
+ p += 2;
+ set_sshort(p, trans->totalc);
+ p += 2;
+
+ set_sshort(p, trans->second);
+ p += 2;
+ set_sshort(p, trans->minute);
+ p += 2;
+ set_sshort(p, trans->hour);
+ p += 2;
+ set_sshort(p, trans->day);
+ p += 2;
+ set_sshort(p, trans->month);
+ p += 2;
+ set_sshort(p, trans->year);
+ p += 2;
+ set_sshort(p, trans->wday);
+ p += 2;
+
+ set_byte(p, trans->repeat);
+ p += 1;
+ set_byte(p, trans->flags2);
+ p += 1;
+ set_byte(p, trans->type);
+ p += 1;
+
+ /* gap fill */
+ set_short(p, 0);
+ p += 2;
+
+ set_byte(p, trans->xfer);
+ p += 1;
+
+ strcpy((char *)p, trans->description);
+ p += 19;
+ strcpy((char *)p, trans->note);
+ p += strlen((char *)p) + 1;
+
+ return (p - buffer);
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_MoneyAppInfo
+ *
+ * Summary: unpacks MoneyAppInfo_t data
+ *
+ * Parameters: MoneyAppInfo_t*, char* to buffer, length of buffer
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+unpack_MoneyAppInfo(MoneyAppInfo_t *appinfo, unsigned char *buffer, size_t len)
+{
+ int i,
+ j;
+
+ unsigned char *p;
+
+ i = unpack_CategoryAppInfo(&appinfo->category, buffer, len);
+ if (!i)
+ return 0;
+
+ p = (unsigned char *) (buffer + i);
+
+ len -= i;
+ if (len < 603)
+ return 0;
+
+ for (j = 0; j < 20; j++) {
+ memcpy(appinfo->typeLabels[j], p, 10);
+ p += 10;
+ }
+
+ for (j = 0; j < 20; j++) {
+ memcpy(appinfo->tranLabels[j], p, 20);
+ p += 20;
+ }
+
+ return i + 603;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_MoneyAppInfo
+ *
+ * Summary: packs MoneyAppInfo_t data
+ *
+ * Parameters: MoneyAppInfo_t*, char* to buffer, length of buffer
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+pack_MoneyAppInfo(MoneyAppInfo_t *appinfo, unsigned char *buffer, size_t len)
+{
+ int i,
+ j;
+ unsigned char *p;
+
+ i = pack_CategoryAppInfo(&appinfo->category, buffer, len);
+
+ if (!buffer)
+ return i + 603;
+ if (!i)
+ return i;
+
+ p = (unsigned char *) (buffer + i);
+ len -= i;
+ if (i < 603)
+ return 0;
+
+ for (j = 0; j < 20; j++) {
+ memcpy(p, appinfo->typeLabels[j], 10);
+ p += 10;
+ }
+
+ for (j = 0; j < 20; j++) {
+ memcpy(p, appinfo->tranLabels[j], 20);
+ p += 20;
+ }
+
+ return (i + 603);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/net.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/net.c
new file mode 100644
index 00000000..27946982
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/net.c
@@ -0,0 +1,715 @@
+/*
+ * $Id: net.c,v 1.45 2006/10/12 14:21:22 desrod Exp $
+ *
+ * net.c: Protocol for NetSync connections
+ *
+ * Copyright (c) 1997, Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 1999, John Franks
+ * Copyright (c) 2004, 2005 Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-net.h"
+#include "pi-error.h"
+
+#define PI_NET_TIMEOUT 30*1000
+
+static int net_flush(pi_socket_t *ps, int flags);
+static int net_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len);
+static int net_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len);
+
+/***********************************************************************
+ *
+ * Function: net_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t
+*net_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot = NULL;
+ pi_net_data_t *data = NULL,
+ *new_data = NULL;
+
+ ASSERT(prot != NULL);
+
+ new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ if (new_prot != NULL) {
+ new_data = (pi_net_data_t *)malloc (sizeof (pi_net_data_t));
+ if (new_data == NULL) {
+ free(new_prot);
+ new_prot = NULL;
+ }
+ }
+
+ if (new_prot != NULL && new_data != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+
+ data = (pi_net_data_t *)prot->data;
+ new_data->type = data->type;
+ new_data->split_writes = data->split_writes;
+ new_data->write_chunksize = data->write_chunksize;
+ new_data->txid = data->txid;
+ new_prot->data = new_data;
+ }
+
+ return new_prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: net_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static
+void net_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT (prot != NULL);
+
+ if (prot != NULL) {
+ if (prot->data != NULL)
+ free(prot->data);
+ free(prot);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: net_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: void
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_protocol_t
+*net_protocol (void)
+{
+ pi_protocol_t *prot = NULL;
+ pi_net_data_t *data = NULL;
+
+ prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ if (prot != NULL) {
+ data = (pi_net_data_t *)malloc (sizeof (pi_net_data_t));
+ if (data == NULL) {
+ free(prot);
+ prot = NULL;
+ }
+ }
+
+ if (prot != NULL && data != NULL) {
+ prot->level = PI_LEVEL_NET;
+ prot->dup = net_protocol_dup;
+ prot->free = net_protocol_free;
+ prot->read = net_rx;
+ prot->write = net_tx;
+ prot->flush = net_flush;
+ prot->getsockopt = net_getsockopt;
+ prot->setsockopt = net_setsockopt;
+
+ data->type = PI_NET_TYPE_DATA;
+ data->split_writes = 1; /* write packet header and data separately */
+ data->write_chunksize = 4096; /* and push data in 4k chunks. Required for some USB devices */
+ data->txid = 0x00;
+ prot->data = data;
+ }
+
+ return prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: net_rx_handshake
+ *
+ * Summary: RX handshake
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+int
+net_rx_handshake(pi_socket_t *ps)
+{
+ static const unsigned char msg1[] = /* 50 bytes */
+ "\x12\x01\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00"
+ "\x24\xff\xff\xff\xff\x3c\x00\x3c\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\xc0\xa8\xa5\x1f\x04\x27\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+ static const unsigned char msg2[] = /* 46 bytes */
+ "\x13\x01\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00"
+ "\x20\xff\xff\xff\xff\x00\x3c\x00\x3c\x00\x00\x00\x00"
+ "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00";
+ pi_buffer_t *buffer;
+ int err;
+
+ buffer = pi_buffer_new (256);
+ if (buffer == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ if ((err = net_rx(ps, buffer, 256, 0)) >= 0 &&
+ (err = net_tx(ps, msg1, 50, 0)) >= 0 &&
+ (err = net_rx(ps, buffer, 50, 0)) >= 0 &&
+ (err = net_tx(ps, msg2, 46, 0)) >= 0 &&
+ (err = net_rx(ps, buffer, 8, 0)) >= 0)
+ {
+ pi_buffer_free (buffer);
+ return 0;
+ }
+
+ pi_buffer_free (buffer);
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * Function: net_tx_handshake
+ *
+ * Summary: TX handshake
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+int
+net_tx_handshake(pi_socket_t *ps)
+{
+ static const unsigned char msg1[] = /* 22 bytes */
+ "\x90\x01\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00"
+ "\x08\x01\x00\x00\x00\x00\x00\x00\x00";
+ static const unsigned char msg2[] = /* 50 bytes */
+ "\x92\x01\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00"
+ "\x24\xff\xff\xff\xff\x00\x3c\x00\x3c\x40\x00\x00\x00"
+ "\x01\x00\x00\x00\xc0\xa8\xa5\x1e\x04\x01\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+ static const unsigned char msg3[] = /* 8 bytes */
+ "\x93\x00\x00\x00\x00\x00\x00\x00";
+ pi_buffer_t *buffer;
+ int err;
+
+ buffer = pi_buffer_new (256);
+ if (buffer == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ if ((err = net_tx(ps, msg1, 22, 0)) >= 0 &&
+ (err = net_rx(ps, buffer, 256, 0)) >= 0 &&
+ (err = net_tx(ps, msg2, 50, 0)) >= 0 &&
+ (err = net_rx(ps, buffer, 256, 0)) >= 0 &&
+ (err = net_tx(ps, msg3, 8, 0)) >= 0)
+ {
+ pi_buffer_free (buffer);
+ return 0;
+ }
+
+ pi_buffer_free (buffer);
+ return err;
+}
+
+/***********************************************************************
+ *
+ * Function: net_flush
+ *
+ * Summary: Flush input and output buffers
+ *
+ * Parameters: pi_socket_t*, flags
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+int
+net_flush(pi_socket_t *ps, int flags)
+{
+ pi_protocol_t *prot,
+ *next;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_NET);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_NET);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ return next->flush(ps, flags);
+}
+
+/***********************************************************************
+ *
+ * Function: net_tx
+ *
+ * Summary: Transmit NET Packets
+ *
+ * Parameters: pi_socket_t*, char* to buf, buf length, flags
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+ssize_t
+net_tx(pi_socket_t *ps, const unsigned char *msg, size_t len, int flags)
+{
+ int bytes,
+ offset,
+ remain,
+ tosend;
+ pi_protocol_t *prot,
+ *next;
+ pi_net_data_t *data;
+ unsigned char *buf;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_NET);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+ data = (pi_net_data_t *)prot->data;
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_NET);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ /* Create the header */
+ buf = (unsigned char *) malloc(PI_NET_HEADER_LEN + len);
+ if (buf == NULL)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ buf[PI_NET_OFFSET_TYPE] = data->type;
+ if (data->type == PI_NET_TYPE_TCKL)
+ buf[PI_NET_OFFSET_TXID] = 0xff;
+ else
+ buf[PI_NET_OFFSET_TXID] = data->txid;
+ set_long(&buf[PI_NET_OFFSET_SIZE], len);
+ memcpy(&buf[PI_NET_HEADER_LEN], msg, len);
+
+ /* Write the header and body, possibly in one write, or in two,
+ * or in more, depending on the current options. Crucial options
+ * here are `split_writes' and `write_chunksize' in this protocol's
+ * data (use net_setsockopt() to set them).
+ */
+ if (data->split_writes)
+ {
+ /* Bugfix for USB send problems. If connected over
+ * USB, do the following:
+ * - send the 6 bytes of header first
+ * - split the rest of data into chunks if the write_chunksize opt is set
+ * This is what Palm Desktop does on Windows for the Zire 72
+ * (uses split writes and 4k chunks)
+ * -- FP
+ */
+ bytes = next->write(ps, buf, PI_NET_HEADER_LEN, flags);
+ if (bytes < PI_NET_HEADER_LEN)
+ {
+ free(buf);
+ return bytes;
+ }
+ offset = PI_NET_HEADER_LEN;
+ remain = len;
+ }
+ else
+ {
+ offset = 0;
+ remain = PI_NET_HEADER_LEN + len;
+ }
+
+ while (remain > 0)
+ {
+ if (data->write_chunksize)
+ tosend = (remain > data->write_chunksize) ? data->write_chunksize : remain;
+ else
+ tosend = remain;
+
+ bytes = next->write(ps, &buf[offset], tosend, flags);
+ if (bytes < tosend)
+ {
+ free(buf);
+ return bytes;
+ }
+ remain -= bytes;
+ offset += bytes;
+ }
+
+ CHECK(PI_DBG_NET, PI_DBG_LVL_INFO, net_dump_header(buf, 1, ps->sd));
+ CHECK(PI_DBG_NET, PI_DBG_LVL_DEBUG, pi_dumpdata((char *)msg, len));
+
+ free(buf);
+ return len;
+}
+
+/***********************************************************************
+ *
+ * Function: net_rx
+ *
+ * Summary: Receive NET Packets
+ *
+ * Parameters: ps --> socket to read from
+ * msg <-- malloc()ed buffer containing the data
+ * len --> unused
+ * flags --> unused
+ *
+ * Returns: A negative number on error, 0 on timeout, otherwise the
+ * length of the received packet.
+ *
+ ***********************************************************************/
+ssize_t
+net_rx(pi_socket_t *ps, pi_buffer_t *msg, size_t len, int flags)
+{
+ int bytes,
+ total_bytes,
+ packet_len,
+ timeout,
+ honor_rx_timeout;
+ size_t size;
+ pi_protocol_t *prot,
+ *next;
+ pi_buffer_t *header;
+ pi_net_data_t *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_NET);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (pi_net_data_t *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_NET);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ size = sizeof(honor_rx_timeout);
+ pi_getsockopt(ps->sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
+ &honor_rx_timeout, &size);
+
+ timeout = honor_rx_timeout ? PI_NET_TIMEOUT : 0;
+ size = sizeof(timeout);
+ pi_setsockopt(ps->sd, PI_LEVEL_DEV, PI_DEV_TIMEOUT,
+ &timeout, &size);
+
+ header = pi_buffer_new (PI_NET_HEADER_LEN);
+ if (header == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ /* loop until we find a non-tickle packet (if the other end
+ sends us a tickle, we would receive it prior to getting
+ the expected reply to one of our commands, so we need
+ to make sure tickle packets don't get in the way) */
+ total_bytes = 0;
+ while (!total_bytes) {
+ if (data->txid == 0) {
+ /* Peek to see if it is a headerless packet */
+ bytes = next->read(ps, header, 1, flags);
+ if (bytes <= 0) {
+ pi_buffer_free (header);
+ return bytes;
+ }
+
+ LOG ((PI_DBG_NET, PI_DBG_LVL_INFO,
+ "NET RX (%i): Checking for headerless packet %d\n",
+ ps->sd, header->data[0]));
+
+ if (header->data[0] == 0x90) {
+ /* Cause the header bytes to be skipped */
+ LOG ((PI_DBG_NET, PI_DBG_LVL_INFO,
+ "NET RX (%i): Headerless packet\n",
+ ps->sd));
+ total_bytes = PI_NET_HEADER_LEN;
+ header->data[PI_NET_OFFSET_TYPE] = PI_NET_TYPE_DATA;
+ header->data[PI_NET_OFFSET_TXID] = 0x01;
+ set_long (&header->data[PI_NET_OFFSET_SIZE], 21);
+ break;
+ } else {
+ total_bytes += bytes;
+ }
+ }
+
+ /* bytes in what's left of the header */
+ while (total_bytes < PI_NET_HEADER_LEN) {
+ bytes = next->read(ps, header,
+ (size_t)(PI_NET_HEADER_LEN - total_bytes), flags);
+ if (bytes <= 0) {
+ pi_buffer_free (header);
+ return bytes;
+ }
+ total_bytes += bytes;
+ }
+
+ packet_len = get_long(&header->data[PI_NET_OFFSET_SIZE]);
+ data->type = header->data[PI_NET_OFFSET_TYPE];
+
+ switch (data->type) {
+ case PI_NET_TYPE_TCKL:
+ if (packet_len != 0) {
+ LOG ((PI_DBG_NET, PI_DBG_LVL_ERR,
+ "NET RX (%i): tickle packet with non-zero length\n",
+ ps->sd));
+ pi_buffer_free(header);
+ return pi_set_error(ps->sd, PI_ERR_PROT_BADPACKET);
+ }
+ /* valid tickle packet; continue reading. */
+ LOG((PI_DBG_NET, PI_DBG_LVL_DEBUG,
+ "NET RX (%i): received tickle packet\n",
+ ps->sd));
+ total_bytes = 0;
+ header->used = 0;
+ break;
+
+ case PI_NET_TYPE_DATA:
+ /* move on to reading the rest of the packet */
+ break;
+
+ default:
+ LOG ((PI_DBG_NET, PI_DBG_LVL_ERR,
+ "NET RX (%i): Unknown packet type\n",
+ ps->sd));
+ CHECK(PI_DBG_NET, PI_DBG_LVL_INFO, pi_dumpdata((char *)header->data, PI_NET_HEADER_LEN));
+ pi_buffer_free(header);
+ return pi_set_error(ps->sd, PI_ERR_PROT_BADPACKET);
+ }
+ }
+
+ total_bytes = 0;
+ packet_len = get_long(&header->data[PI_NET_OFFSET_SIZE]);
+
+ /* shield against absurd packet lengths */
+ if (packet_len < 0 || packet_len > 0x100000L) {
+ /* we see an invalid packet */
+ next->flush(ps, PI_FLUSH_INPUT);
+ LOG ((PI_DBG_NET, PI_DBG_LVL_ERR, "NET RX (%i): Invalid packet length (%ld)\n", ps->sd, packet_len));
+ pi_buffer_free(header);
+ return pi_set_error(ps->sd, PI_ERR_PROT_BADPACKET);
+ }
+
+ /* read the actual packet data */
+ while (total_bytes < packet_len) {
+ bytes = next->read(ps, msg,
+ (size_t)(packet_len - total_bytes), flags);
+ if (bytes < 0) {
+ pi_buffer_free (header);
+ return bytes;
+ }
+ total_bytes += bytes;
+ }
+
+ CHECK(PI_DBG_NET, PI_DBG_LVL_INFO, net_dump_header(header->data, 0, ps->sd));
+ CHECK(PI_DBG_NET, PI_DBG_LVL_DEBUG, net_dump(header->data, msg->data));
+
+ /* Update the transaction id */
+ if (ps->state == PI_SOCK_CONN_INIT || ps->command == 1)
+ data->txid = header->data[PI_NET_OFFSET_TXID];
+ else {
+ data->txid++;
+ if (data->txid == 0xff)
+ data->txid = 1;
+ }
+
+ pi_buffer_free (header);
+ return packet_len;
+}
+
+/***********************************************************************
+ *
+ * Function: net_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+net_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ pi_net_data_t *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_NET);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (pi_net_data_t *)prot->data;
+
+ switch (option_name) {
+ case PI_NET_TYPE:
+ if (*option_len != sizeof (data->type)) {
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ }
+ memcpy (option_value, &data->type,
+ sizeof (data->type));
+ *option_len = sizeof (data->type);
+ break;
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: net_setsockopt
+ *
+ * Summary: set options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+net_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ pi_net_data_t *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_NET);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (pi_net_data_t *)prot->data;
+
+ switch (option_name) {
+ case PI_NET_TYPE:
+ if (*option_len != sizeof (data->type)) {
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ }
+ memcpy (&data->type, option_value,
+ sizeof (data->type));
+ break;
+
+ /* this option, when set to != 0, instructs NET to separately
+ * write the NET header and the data block. Data can be further
+ * sent in chunks by also setting PI_NET_WRITE_CHUNKSIZE below.
+ */
+ case PI_NET_SPLIT_WRITES:
+ if (*option_len != sizeof (data->split_writes)) {
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ }
+ memcpy (&data->split_writes, option_value,
+ sizeof(data->split_writes));
+ break;
+
+ /* this option, when set to != 0, instructs NET to write the
+ * packet data in chunks of the given maximum size. If
+ * PI_NET_SPLIT_WRITES is not set, and this option is set, we
+ * chunk the whole write (including the NET header)
+ */
+ case PI_NET_WRITE_CHUNKSIZE:
+ if (*option_len != sizeof (data->write_chunksize)) {
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ }
+ memcpy (&data->write_chunksize, option_value,
+ sizeof(data->write_chunksize));
+ break;
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: net_dump_header
+ *
+ * Summary: Dump the NET packet header
+ *
+ * Parameters: char* to net packet, TX boolean
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+net_dump_header(unsigned char *data, int rxtx, int sd)
+{
+ LOG((PI_DBG_NET, PI_DBG_LVL_NONE,
+ "NET %s sd=%i type=%d txid=0x%.2x len=0x%.4x\n",
+ rxtx ? "TX" : "RX",
+ sd,
+ get_byte(&data[PI_NET_OFFSET_TYPE]),
+ get_byte(&data[PI_NET_OFFSET_TXID]),
+ get_long(&data[PI_NET_OFFSET_SIZE])));
+}
+
+
+/***********************************************************************
+ *
+ * Function: net_dump
+ *
+ * Summary: Dump the NET packet
+ *
+ * Parameters: char* to net packet
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+net_dump(unsigned char *header, unsigned char *data)
+{
+ size_t size;
+
+ size = get_long(&header[PI_NET_OFFSET_SIZE]);
+ pi_dumpdata((char *)data, size);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/notepad.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/notepad.c
new file mode 100644
index 00000000..aca64ed9
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/notepad.c
@@ -0,0 +1,265 @@
+/*
+ * $Id: notepad.c,v 1.14 2006/10/12 14:21:22 desrod Exp $
+ *
+ * notepad.c: Translate Palm NotePad application data formats
+ *
+ * Copyright (c) 2002, Angus Ainslie
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-notepad.h"
+
+
+/***********************************************************************
+ *
+ * Function: free_NotePad
+ *
+ * Summary: Free the memory and filehandle from the record alloc.
+ *
+ ***********************************************************************/
+void free_NotePad( NotePad_t *a )
+{
+ if( a->flags & NOTEPAD_FLAG_NAME )
+ {
+/* fprintf( stderr, "Freeing name: %s\n", a->name ); */
+ free(a->name);
+ }
+
+ if( a->flags & NOTEPAD_FLAG_BODY )
+ {
+/* fprintf( stderr, "Freeing data\n" ); */
+ free(a->data);
+ }
+
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_NotePad
+ *
+ * Summary: Unpack the NotePad structure into records we can chew on
+ *
+ ***********************************************************************/
+int unpack_NotePad(NotePad_t *notepad, unsigned char *buffer, size_t len)
+{
+ unsigned char *start = buffer;
+
+ notepad->createDate.sec = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->createDate.min = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->createDate.hour = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->createDate.day = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->createDate.month = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->createDate.year = (unsigned short int) get_short(buffer);
+ buffer += 2;
+
+ notepad->createDate.s = (unsigned short int) get_short(buffer);
+ buffer += 2;
+
+ notepad->changeDate.sec = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->changeDate.min = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->changeDate.hour = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->changeDate.day = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->changeDate.month = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->changeDate.year = (unsigned short int) get_short(buffer);
+ buffer += 2;
+
+ notepad->changeDate.s = (unsigned short int) get_short(buffer);
+ buffer += 2;
+
+ notepad->flags = (unsigned short int) get_short(buffer);
+ buffer += 2;
+
+/* fprintf( stderr, "flags: 0x%x\n", notepad->flags ); */
+
+ if( notepad->flags & NOTEPAD_FLAG_ALARM )
+ {
+/* fprintf( stderr, "Getting Alarm\n" ); */
+ notepad->alarmDate.sec = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->alarmDate.min = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->alarmDate.hour = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->alarmDate.day = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->alarmDate.month = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ notepad->alarmDate.year = (unsigned short int) get_short(buffer);
+ buffer += 2;
+
+ notepad->alarmDate.s = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ }
+
+ if( notepad->flags & NOTEPAD_FLAG_NAME )
+ {
+/* fprintf( stderr, "Getting Name\n" ); */
+ notepad->name = strdup((char *) buffer);
+
+ buffer += strlen( notepad->name ) + 1;
+
+ if( (strlen( notepad->name ) + 1)%2 == 1)
+ buffer++;
+
+ }
+ else
+ {
+ notepad->name = NULL;
+ }
+
+
+ if( notepad->flags & NOTEPAD_FLAG_BODY )
+ {
+/* fprintf( stderr, "Getting Body\n" ); */
+ notepad->body.bodyLen = get_long( buffer );
+ buffer += 4;
+
+ notepad->body.width = get_long( buffer );
+ buffer += 4;
+
+ notepad->body.height = get_long( buffer );
+ buffer += 4;
+
+ notepad->body.l1 = get_long( buffer );
+ buffer += 4;
+
+ notepad->body.dataType = get_long( buffer );
+ buffer += 4;
+
+ notepad->body.dataLen = get_long( buffer );
+ buffer += 4;
+
+ notepad->data = malloc( notepad->body.dataLen );
+
+ if( notepad->data == NULL )
+ {
+ fprintf( stderr, "Body data alloc failed\n" );
+ return( 0 );
+ }
+
+ memcpy( notepad->data, buffer, notepad->body.dataLen );
+
+ }
+
+ return ( buffer - start ); /* FIXME: return real length */
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_NotePad
+ *
+ * Summary: Pack the NotePad records into a structure
+ *
+ ***********************************************************************/
+int pack_NotePad(NotePad_t *notepad, unsigned char *buf, size_t len)
+{
+ return( 0 );
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_NotePadAppInfo
+ *
+ * Summary: Unpack the NotePad AppInfo block from the structure
+ *
+ ***********************************************************************/
+int unpack_NotePadAppInfo(NotePadAppInfo_t *appinfo, unsigned char *record,
+ size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = unpack_CategoryAppInfo( &appinfo->category, record, len );
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 4)
+ return 0;
+ appinfo->dirty = get_short(record);
+ record += 2;
+ appinfo->sortByPriority = get_byte(record);
+ record += 2;
+ return (record - start);
+}
+
+/***********************************************************************
+ *
+ * Function: pack_NotePadAppInfo
+ *
+ * Summary: Pack the AppInfo block/record back into the structure
+ *
+ ***********************************************************************/
+int
+pack_NotePadAppInfo(NotePadAppInfo_t *appinfo, unsigned char *record,
+ size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!record)
+ return i + 4;
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 4)
+ return 0;
+ set_short(record, appinfo->dirty);
+ set_byte(record + 2, appinfo->sortByPriority);
+ set_byte(record + 3, 0); /* gapfill */
+ record += 4;
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/padp.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/padp.c
new file mode 100644
index 00000000..ec364398
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/padp.c
@@ -0,0 +1,971 @@
+/*
+ * $Id: padp.c,v 1.59 2006/10/13 09:52:13 fpillet Exp $
+ *
+ * padp.c: Pilot PADP protocol
+ *
+ * (c) 1996, D. Jeff Dionne.
+ * Much of this code adapted from Brian J. Swetland <swetland@uiuc.edu>
+ * Mostly rewritten by Kenneth Albanowski. Adjusted timeout values and
+ * better error handling by Tilo Christ.
+ * (c) 2005, Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-padp.h"
+#include "pi-slp.h"
+#include "pi-error.h"
+
+#define PI_PADP_TX_TIMEOUT 2*1000
+#define PI_PADP_TX_RETRIES 10
+#define PI_PADP_RX_BLOCK_TO 30*1000
+#define PI_PADP_RX_SEGMENT_TO 30*1000
+
+/* Declare function prototypes */
+static int padp_flush(pi_socket_t *ps, int flags);
+static int padp_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len);
+static int padp_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len);
+static int padp_sendack(struct pi_socket *ps, struct pi_padp_data *data,
+ unsigned char txid, struct padp *padp, int flags);
+
+
+/***********************************************************************
+ *
+ * Function: padp_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+padp_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot = NULL;
+ pi_padp_data_t *data = NULL,
+ *new_data = NULL;
+
+ new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ if (new_prot != NULL) {
+ new_data = (pi_padp_data_t *)malloc (sizeof (pi_padp_data_t));
+ if (new_data == NULL) {
+ free(new_prot);
+ new_prot = NULL;
+ } else {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+
+ data = (pi_padp_data_t *)prot->data;
+ memcpy(new_data, data, sizeof(pi_padp_data_t));
+ new_prot->data = new_data;
+ }
+ }
+
+ return new_prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: padp_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static
+void padp_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT (prot != NULL);
+
+ if (prot != NULL) {
+ if (prot->data != NULL)
+ free(prot->data);
+ free(prot);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: padp_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: void
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_protocol_t
+*padp_protocol (void)
+{
+ pi_protocol_t *prot = NULL;
+ pi_padp_data_t *data = NULL;
+
+ prot = (pi_protocol_t *) malloc (sizeof (pi_protocol_t));
+ if (prot != NULL) {
+ data = (pi_padp_data_t *) malloc (sizeof (pi_padp_data_t));
+ if (data == NULL) {
+ free(prot);
+ prot = NULL;
+ } else {
+ prot->level = PI_LEVEL_PADP;
+ prot->dup = padp_protocol_dup;
+ prot->free = padp_protocol_free;
+ prot->read = padp_rx;
+ prot->write = padp_tx;
+ prot->flush = padp_flush;
+ prot->getsockopt = padp_getsockopt;
+ prot->setsockopt = padp_setsockopt;
+
+ data->type = padData;
+ data->last_type = -1;
+ data->txid = 0xff;
+ data->next_txid = 0xff;
+ data->freeze_txid = 0;
+ data->use_long_format = 0;
+ prot->data = data;
+ }
+ }
+
+ return prot;
+}
+
+/***********************************************************************
+ *
+ * Function: padp_tx
+ *
+ * Summary: Transmit PADP packets
+ *
+ * Parameters: pi_socket_t*, char* to buffer, buffer length, flags
+ *
+ * Returns: Number of packets transmitted
+ *
+ ***********************************************************************/
+ssize_t
+padp_tx(pi_socket_t *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int fl = PADP_FL_FIRST,
+ count = 0,
+ retries,
+ result,
+ type,
+ socket,
+ timeout,
+ header_size;
+ size_t size,
+ tlen;
+ unsigned char txid;
+ pi_protocol_t *prot, *next;
+ pi_padp_data_t *data;
+ pi_buffer_t *padp_buf;
+ struct padp padp;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_PADP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (pi_padp_data_t *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_PADP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ if (data->type == padWake)
+ data->txid = 0xff;
+
+ if (!data->freeze_txid) {
+ if (data->txid == 0)
+ data->txid = 0x10; /* some random # */
+ else if (data->txid >= 0xfe)
+ data->next_txid = 1; /* wrap */
+ else
+ data->next_txid = data->txid + 1;
+ }
+
+ if (data->type != padAck && ps->state == PI_SOCK_CONN_ACCEPT)
+ data->txid = data->next_txid;
+
+ padp_buf = pi_buffer_new (PI_PADP_HEADER_LEN + 2 + PI_PADP_MTU);
+ if (padp_buf == NULL)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+
+ pi_flush(ps->sd, PI_FLUSH_INPUT);
+
+ do {
+ retries = PI_PADP_TX_RETRIES;
+ do {
+ padp_buf->used = 0;
+
+ type = PI_SLP_TYPE_PADP;
+ socket = PI_SLP_SOCK_DLP;
+ timeout = PI_PADP_TX_TIMEOUT;
+
+ size = sizeof(type);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TYPE, &type, &size);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_DEST, &socket, &size);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_SRC, &socket, &size);
+ size = sizeof(timeout);
+ pi_setsockopt(ps->sd, PI_LEVEL_DEV, PI_DEV_TIMEOUT, &timeout, &size);
+ size = sizeof(data->txid);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TXID, &data->txid, &size);
+
+ tlen = (len > PI_PADP_MTU) ? PI_PADP_MTU : len;
+ header_size = data->use_long_format ? PI_PADP_HEADER_LEN+2 : PI_PADP_HEADER_LEN;
+
+ /* build the packet */
+ set_byte(&padp_buf->data[PI_PADP_OFFSET_TYPE], data->type);
+ set_byte(&padp_buf->data[PI_PADP_OFFSET_FLGS], fl |
+ (len == tlen ? PADP_FL_LAST : 0) |
+ (data->use_long_format ? PADP_FL_LONG : 0));
+ if (data->use_long_format)
+ set_long(&padp_buf->data[PI_PADP_OFFSET_SIZE], (fl ? len : (size_t)count));
+ else
+ set_short(&padp_buf->data[PI_PADP_OFFSET_SIZE], (fl ? len : (size_t)count));
+ memcpy(padp_buf->data + header_size, buf, tlen);
+
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_INFO, padp_dump_header(padp_buf->data, 1));
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_DEBUG, padp_dump(padp_buf->data));
+
+ /* send the packet, check for disconnection (i.e. when running over USB) */
+ result = next->write(ps, padp_buf->data, header_size + tlen, flags);
+ if (result < 0) {
+ if (result == PI_ERR_SOCK_DISCONNECTED)
+ goto disconnected;
+ }
+
+ /* Tickles don't get acks */
+ if (data->type == padTickle)
+ break;
+
+keepwaiting:
+ LOG((PI_DBG_PADP, PI_DBG_LVL_DEBUG, "PADP TX waiting for ACK\n"));
+ result = next->read(ps, padp_buf, PI_PADP_HEADER_LEN + 2 + PI_PADP_MTU, flags);
+ if (result > 0) {
+ padp.type = get_byte(&padp_buf->data[PI_PADP_OFFSET_TYPE]);
+ padp.flags = get_byte(&padp_buf->data[PI_PADP_OFFSET_FLGS]);
+ if (padp.flags & PADP_FL_LONG) {
+ header_size = PI_PADP_HEADER_LEN + 2;
+ padp.size = get_long(&padp_buf->data[PI_PADP_OFFSET_SIZE]);
+ } else {
+ header_size = PI_PADP_HEADER_LEN;
+ padp.size = get_short(&padp_buf->data[PI_PADP_OFFSET_SIZE]);
+ }
+
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_INFO, padp_dump_header(padp_buf->data, 0));
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_DEBUG, padp_dump(padp_buf->data));
+
+ size = sizeof(type);
+ pi_getsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_LASTTYPE, &type, &size);
+ size = sizeof(txid);
+ pi_getsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_LASTTXID, &txid, &size);
+
+ if (type == PI_SLP_TYPE_PADP
+ && padp.type == (unsigned char)padData
+ && txid == data->txid
+ && len == tlen) {
+ /* We didn't receive the ack for the
+ last packet, but the incomding data
+ is the response to this transmission.
+ The ack was lost.
+ */
+ LOG((PI_DBG_PADP, PI_DBG_LVL_WARN,
+ "PADP TX Missing Ack\n"));
+ count += tlen;
+ goto done;
+ } else if (padp.type == (unsigned char)padTickle) {
+ /* Tickle to avoid timeout */
+ goto keepwaiting;
+ } else if (type == PI_SLP_TYPE_PADP &&
+ padp.type == (unsigned char)padAck &&
+ txid == data->txid) {
+ if (padp.flags & PADP_FL_MEMERROR) {
+ /* OS 2.x enjoys sending erroneous memory errors */
+ LOG((PI_DBG_PADP, PI_DBG_LVL_WARN,
+ "PADP TX Memory Error\n"));
+
+ /* Mimimum failure: transmission failed due to
+ * lack of memory in reciever link layer, but
+ * connection is still active. This transmission
+ * was lost, but other transmissions will be
+ * received.
+ */
+ errno = EMSGSIZE;
+ count = -1;
+ goto done;
+ }
+
+ /* Successful Ack */
+ buf = buf + tlen;
+ len -= tlen;
+ count += tlen;
+ fl = 0;
+ LOG((PI_DBG_PADP, PI_DBG_LVL_DEBUG, "PADP TX got ACK\n"));
+ break;
+ } else if (type == PI_SLP_TYPE_PADP &&
+ padp.type == data->last_ack_padp.type &&
+ padp.flags == data->last_ack_padp.flags &&
+ padp.size == data->last_ack_padp.size &&
+ txid == data->last_ack_txid) {
+ /* A repeat of a packet we already received. The
+ ack got lost, so resend it. */
+ LOG((PI_DBG_PADP, PI_DBG_LVL_WARN,
+ "PADP TX resending lost ACK\n"));
+ padp_sendack(ps, data, txid, &padp, flags);
+ continue;
+ } else {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR,
+ "PADP TX Unexpected packet "
+ "(possible port speed problem? "
+ "out of sync packet?)\n"));
+ padp_dump_header (buf, 1);
+ /* Got unknown packet */
+ errno = EIO;
+ count = -1;
+ goto done;
+ }
+
+ } else if (result == PI_ERR_SOCK_DISCONNECTED)
+ goto disconnected;
+
+ } while (--retries > 0);
+
+ if (retries == 0) {
+ /* Maximum failure: transmission
+ failed, and the connection must be presumed dead */
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR, "PADP TX too many retries"));
+ errno = ETIMEDOUT;
+ pi_buffer_free (padp_buf);
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+ } while (len);
+
+done:
+ if (data->type != padAck && ps->state == PI_SOCK_CONN_INIT)
+ data->txid = data->next_txid;
+ pi_buffer_free (padp_buf);
+ return count;
+
+disconnected:
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR, "PADP TX disconnected"));
+ pi_buffer_free(padp_buf);
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+}
+
+
+/***********************************************************************
+ *
+ * Function: padp_rx
+ *
+ * Summary: Receive PADP packets
+ *
+ * Parameters: pi_socket_t*, char* to buffer, expected length, flags
+ *
+ * Returns: number of bytes received or negative on error
+ *
+ ***********************************************************************/
+ssize_t
+padp_rx(pi_socket_t *ps, pi_buffer_t *buf, size_t expect, int flags)
+{
+ int bytes,
+ offset = 0,
+ ouroffset = 0,
+ honor_rx_timeout,
+ type,
+ timeout,
+ header_size;
+ unsigned char txid;
+ size_t total_bytes,
+ size;
+ pi_protocol_t *next, *prot;
+ pi_padp_data_t *data;
+ struct padp padp;
+ pi_buffer_t *padp_buf;
+ time_t endtime;
+
+ LOG((PI_DBG_PADP, PI_DBG_LVL_DEBUG, "PADP RX expect=%d flags=0x%04x\n",
+ expect, flags));
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_PADP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (pi_padp_data_t *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_PADP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ size = sizeof(honor_rx_timeout);
+ pi_getsockopt(ps->sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
+ &honor_rx_timeout, &size);
+
+ padp_buf = pi_buffer_new (PI_PADP_HEADER_LEN + PI_PADP_MTU);
+ if (padp_buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ /* the txid may be "frozen" if we're in the process of doing a large read
+ * over VFS. In this case, all packets have the same txid
+ */
+ if (!data->freeze_txid) {
+ if (ps->state == PI_SOCK_CONN_ACCEPT) {
+ if (data->txid >= 0xfe)
+ data->next_txid = 1; /* wrap */
+ else
+ data->next_txid = data->txid + 1;
+ } else
+ data->next_txid = data->txid;
+ }
+
+ endtime = time(NULL) + PI_PADP_RX_BLOCK_TO / 1000;
+
+ for (;;) {
+ if (honor_rx_timeout && time(NULL) > endtime) {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR,
+ "PADP RX Timed out"));
+ /* Bad timeout breaks connection */
+ errno = ETIMEDOUT;
+ ps->state = PI_SOCK_CONN_BREAK;
+ pi_buffer_free (padp_buf);
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+
+ timeout = honor_rx_timeout ? PI_PADP_RX_BLOCK_TO + 2000 : 0;
+ size = sizeof(timeout);
+ pi_setsockopt(ps->sd, PI_LEVEL_DEV, PI_DEV_TIMEOUT,
+ &timeout, &size);
+
+ total_bytes = 0;
+ padp_buf->used = 0;
+ header_size = PI_PADP_HEADER_LEN;
+ while (total_bytes < header_size) {
+ bytes = next->read(ps, padp_buf,
+ (size_t)header_size + PI_PADP_MTU - total_bytes, flags);
+ if (bytes < 0) {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR, "PADP RX Read Error\n"));
+ pi_buffer_free (padp_buf);
+ return bytes;
+ }
+ total_bytes += bytes;
+
+ /* check for the long packet format flag and adjust header size */
+ if (header_size==PI_PADP_HEADER_LEN &&
+ total_bytes >= PI_PADP_HEADER_LEN &&
+ (padp_buf->data[PI_PADP_OFFSET_FLGS] & PADP_FL_LONG)) {
+ header_size += 2;
+ }
+ }
+
+ padp.type = padp_buf->data[PI_PADP_OFFSET_TYPE];
+ padp.flags = padp_buf->data[PI_PADP_OFFSET_FLGS];
+ if (padp.flags & PADP_FL_LONG)
+ padp.size = get_long(&padp_buf->data[PI_PADP_OFFSET_SIZE]);
+ else
+ padp.size = get_short(&padp_buf->data[PI_PADP_OFFSET_SIZE]);
+
+ size = sizeof(type);
+ pi_getsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_LASTTYPE, &type, &size);
+ size = sizeof(txid);
+ pi_getsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_LASTTXID, &txid, &size);
+
+ if (padp.flags & PADP_FL_MEMERROR) {
+ if (txid == data->txid) {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_WARN,
+ "PADP RX Memory Error\n"));
+ errno = EMSGSIZE;
+ ouroffset = -1;
+ goto done; /* Mimimum failure:
+ transmission failed due to
+ lack of memory in reciever
+ link layer, but connection is
+ still active. This
+ transmission was lost, but
+ other transmissions will be
+ received. */
+ }
+ continue;
+ } else if (padp.type == padTickle) {
+ /* Tickle to avoid timeout */
+ LOG((PI_DBG_PADP, PI_DBG_LVL_WARN,
+ "PADP RX Got Tickled\n"));
+ endtime = time(NULL) + PI_PADP_RX_BLOCK_TO / 1000;
+ continue;
+ } else if (type != PI_SLP_TYPE_PADP ||
+ padp.type != padData ||
+ txid != data->txid ||
+ !(padp.flags & PADP_FL_FIRST)) {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR,
+ "PADP RX Wrong packet type on queue"
+ "(possible port speed problem? (loc1))\n"));
+ continue;
+ }
+ break;
+ }
+
+ /* OK, we got the expected begin-of-data packet */
+ endtime = time(NULL) + PI_PADP_RX_SEGMENT_TO / 1000;
+
+ for (;;) {
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_INFO, padp_dump_header(padp_buf->data, 0));
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_DEBUG, padp_dump(padp_buf->data));
+
+ /* Ack the packet */
+ padp_sendack(ps, data, data->txid, &padp, flags);
+
+ /* calculate length and offset - remove */
+ offset = ((padp.flags & PADP_FL_FIRST) ? 0 : padp.size);
+ total_bytes -= PI_PADP_HEADER_LEN;
+
+ /* If packet was out of order, ignore it */
+ if (offset == ouroffset) {
+ if (pi_buffer_append (buf, &padp_buf->data[header_size], total_bytes) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+ ouroffset += total_bytes;
+ }
+
+ if (padp.flags & PADP_FL_LAST)
+ break;
+
+ endtime = time(NULL) + PI_PADP_RX_SEGMENT_TO / 1000;
+
+ for (;;) {
+ if (honor_rx_timeout && time(NULL) > endtime) {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR,
+ "PADP RX Segment Timeout"));
+
+ /* Segment timeout, return error */
+ errno = ETIMEDOUT;
+ ouroffset = -1;
+ /* Bad timeout breaks connection */
+ ps->state = PI_SOCK_CONN_BREAK;
+ pi_buffer_free (padp_buf);
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+
+ timeout = honor_rx_timeout ? (PI_PADP_RX_SEGMENT_TO + 2000) : 0;
+ size = sizeof(timeout);
+ pi_setsockopt(ps->sd, PI_LEVEL_DEV, PI_DEV_TIMEOUT, &timeout, &size);
+
+ total_bytes = 0;
+ padp_buf->used = 0;
+ header_size = PI_PADP_HEADER_LEN;
+
+ while (total_bytes < header_size) {
+ bytes = next->read(ps, padp_buf,
+ header_size + PI_PADP_MTU - total_bytes, flags);
+ if (bytes < 0) {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR, "PADP RX Read Error"));
+ pi_buffer_free (padp_buf);
+ return pi_set_error(ps->sd, bytes);
+ }
+ total_bytes += bytes;
+
+ /* check for the long packet format flag and adjust header size */
+ if (header_size==PI_PADP_HEADER_LEN &&
+ total_bytes >= PI_PADP_HEADER_LEN &&
+ (padp_buf->data[PI_PADP_OFFSET_FLGS] & PADP_FL_LONG)) {
+ header_size += 2;
+ }
+ }
+
+ padp.type = padp_buf->data[PI_PADP_OFFSET_TYPE];
+ padp.flags = padp_buf->data[PI_PADP_OFFSET_FLGS];
+ if (padp.flags & PADP_FL_LONG)
+ padp.size = get_long(&padp_buf->data[PI_PADP_OFFSET_SIZE]);
+ else
+ padp.size = get_short(&padp_buf->data[PI_PADP_OFFSET_SIZE]);
+
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_INFO, padp_dump_header(padp_buf->data, 0));
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_DEBUG, padp_dump(padp_buf->data));
+
+ size = sizeof(type);
+ pi_getsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_LASTTYPE, &type, &size);
+ size = sizeof(txid);
+ pi_getsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_LASTTXID, &txid, &size);
+
+ if (padp.flags & PADP_FL_MEMERROR) {
+ if (txid == data->txid) {
+ /* Mimimum failure: transmission failed due
+ to lack of memory in receiver link layer,
+ but connection is still active. This
+ transmission was lost, but other transmissions
+ will be received. */
+ LOG((PI_DBG_PADP, PI_DBG_LVL_WARN,
+ "PADP RX Memory Error"));
+ errno = EMSGSIZE;
+ ouroffset = -1;
+ goto done;
+ }
+ continue;
+ }
+
+ if (padp.type == (unsigned char) 4) {
+ /* Tickle to avoid timeout */
+ endtime = time(NULL) +
+ PI_PADP_RX_BLOCK_TO / 1000;
+ LOG((PI_DBG_PADP, PI_DBG_LVL_WARN,
+ "PADP RX Got Tickled"));
+ continue;
+ }
+
+ if (type != PI_SLP_TYPE_PADP ||
+ padp.type != padData ||
+ txid != data->txid ||
+ (padp.flags & PADP_FL_FIRST)) {
+ LOG((PI_DBG_PADP, PI_DBG_LVL_ERR,
+ "PADP RX Wrong packet type on queue"
+ "(possible port speed problem? (loc2))\n"));
+ continue;
+ }
+ break;
+ }
+ }
+
+done:
+ data->txid = data->next_txid;
+
+ pi_buffer_free (padp_buf);
+
+ return ouroffset;
+}
+
+/***********************************************************************
+ *
+ * Function: padp_flush
+ *
+ * Summary: Flush input and output buffers
+ *
+ * Parameters: pi_socket_t*, flags
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+padp_flush(pi_socket_t *ps, int flags)
+{
+ pi_protocol_t *prot,
+ *next;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_PADP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_PADP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ return next->flush(ps, flags);
+}
+
+/***********************************************************************
+ *
+ * Function: padp_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+padp_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ pi_padp_data_t *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_PADP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+ data = (pi_padp_data_t *)prot->data;
+
+ switch (option_name) {
+ case PI_PADP_TYPE:
+ if (*option_len != sizeof (data->type))
+ goto error;
+ memcpy (option_value, &data->type, sizeof (data->type));
+ break;
+
+ case PI_PADP_LASTTYPE:
+ if (*option_len != sizeof (data->last_type))
+ goto error;
+ memcpy (option_value, &data->last_type, sizeof (data->last_type));
+ break;
+
+ case PI_PADP_FREEZE_TXID:
+ if (*option_len != sizeof (data->freeze_txid))
+ goto error;
+ memcpy (option_value, &data->freeze_txid, sizeof(data->freeze_txid));
+ break;
+
+ case PI_PADP_USE_LONG_FORMAT:
+ if (*option_len != sizeof (data->use_long_format))
+ goto error;
+ memcpy (option_value, &data->use_long_format, sizeof(data->use_long_format));
+ break;
+ }
+
+ return 0;
+
+ error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: padp_setsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+padp_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ pi_padp_data_t *data;
+ int was_frozen;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_PADP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+ data = (pi_padp_data_t *)prot->data;
+
+ switch (option_name) {
+ case PI_PADP_TYPE:
+ if (*option_len != sizeof (data->type))
+ goto error;
+ memcpy (&data->type, option_value, sizeof (data->type));
+ break;
+
+ case PI_PADP_FREEZE_TXID:
+ if (*option_len != sizeof (data->freeze_txid))
+ goto error;
+ was_frozen = data->freeze_txid;
+ memcpy (&data->freeze_txid, option_value, sizeof (data->freeze_txid));
+ if (was_frozen && !data->freeze_txid) {
+ data->next_txid++;
+ if (data->next_txid >= 0xfe)
+ data->next_txid = 1;
+ }
+ break;
+
+ case PI_PADP_USE_LONG_FORMAT:
+ if (*option_len != sizeof (data->use_long_format))
+ goto error;
+ memcpy (&data->use_long_format, option_value, sizeof(data->use_long_format));
+ break;
+ }
+
+ return 0;
+
+ error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+/***********************************************************************
+*
+* Function: padp_sendack
+*
+* Summary: Acknowledge receipt of a packet
+*
+* Parameters:
+*
+* Returns:
+*
+***********************************************************************/
+static int
+padp_sendack(struct pi_socket *ps,
+ struct pi_padp_data *data, /* padp state, will be modified */
+ unsigned char txid, /* txid of the packet being acked */
+ struct padp *padp, /* padp header of the packet being acked */
+ int flags)
+{
+ int type,
+ socket,
+ result,
+ header_size;
+ size_t size;
+ unsigned char
+ npadp_buf[PI_PADP_HEADER_LEN+2];
+ struct pi_protocol
+ *next;
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_PADP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ type = 2;
+ socket = PI_SLP_SOCK_DLP;
+ size = sizeof(type);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TYPE, &type, &size);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_DEST, &socket, &size);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_SRC, &socket, &size);
+ size = sizeof(txid);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TXID, &txid, &size);
+
+ header_size = PI_PADP_HEADER_LEN;
+ set_byte(&npadp_buf[PI_PADP_OFFSET_TYPE], padAck);
+ set_byte(&npadp_buf[PI_PADP_OFFSET_FLGS], padp->flags);
+ if (padp->flags & PADP_FL_LONG) {
+ header_size += 2;
+ set_long(&npadp_buf[PI_PADP_OFFSET_SIZE], padp->size);
+ } else {
+ set_short(&npadp_buf[PI_PADP_OFFSET_SIZE], padp->size);
+ }
+
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_INFO, padp_dump_header(npadp_buf, 1));
+ CHECK(PI_DBG_PADP, PI_DBG_LVL_DEBUG, padp_dump(npadp_buf));
+
+ result = next->write(ps, npadp_buf, header_size, flags);
+
+ if (result >= 0) {
+ data->last_ack_txid = txid;
+ data->last_ack_padp.type = padp->type;
+ data->last_ack_padp.flags = padp->flags;
+ data->last_ack_padp.size = padp->size;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * Function: padp_dump_header
+ *
+ * Summary: Dump PADP packet header
+ *
+ * Parameters: char* to data, RXTX boolean
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+padp_dump_header(const unsigned char *data, int rxtx)
+{
+ long s;
+ char *stype;
+ unsigned char type, flags;
+
+ type = get_byte (&data[PI_PADP_OFFSET_TYPE]);
+ switch (type) {
+ case padData:
+ stype = "DATA";
+ break;
+ case padAck:
+ stype = "ACK";
+ break;
+ case padTickle:
+ stype = "TICKLE";
+ break;
+ case padAbort:
+ stype = "ABORT";
+ break;
+ default:
+ stype = "UNK";
+ break;
+ }
+
+ flags = get_byte(&data[PI_PADP_OFFSET_FLGS]);
+ if (flags & PADP_FL_LONG)
+ s = get_long(&data[PI_PADP_OFFSET_SIZE]);
+ else
+ s = get_short(&data[PI_PADP_OFFSET_SIZE]);
+
+ LOG((PI_DBG_PADP, PI_DBG_LVL_NONE,
+ "PADP %s %c%c%c type=%s len=%ld\n",
+ rxtx ? "TX" : "RX",
+ (flags & PADP_FL_FIRST) ? 'F' : ' ',
+ (flags & PADP_FL_LAST) ? 'L' : ' ',
+ (flags & PADP_FL_MEMERROR) ? 'M' : ' ',
+ stype, s));
+}
+
+
+/***********************************************************************
+ *
+ * Function: padp_dump
+ *
+ * Summary: Dump PADP packets
+ *
+ * Parameters: char* to data
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+padp_dump(const unsigned char *data)
+{
+ size_t size;
+ unsigned char
+ type,
+ flags;
+ int header_size = PI_PADP_HEADER_LEN;
+
+ type = get_byte (&data[PI_PADP_OFFSET_TYPE]);
+ flags = get_byte (&data[PI_PADP_OFFSET_FLGS]);
+ if (flags & PADP_FL_LONG) {
+ header_size += 2;
+ size = get_long(&data[PI_PADP_OFFSET_SIZE]);
+ } else
+ size = get_short(&data[PI_PADP_OFFSET_SIZE]);
+
+ if (size > PI_PADP_MTU)
+ size = PI_PADP_MTU;
+ if (type != padAck)
+ pi_dumpdata((char *)&data[header_size], size);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/palmpix.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/palmpix.c
new file mode 100644
index 00000000..5a4c3cc4
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/palmpix.c
@@ -0,0 +1,1815 @@
+/*
+ * $Id: palmpix.c,v 1.17 2006/10/12 14:21:22 desrod Exp $
+ *
+ * palmpix.c: Translate PalmPix image format
+ *
+ * Copyright 2001 Angus Ainslie <angusa@deltatee.com>
+ * Copyright 2001 John Marshall <jmarshall@acm.org>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if HAVE_STDINT_H
+# include <stdint.h>
+#else
+# if HAVE_INTTYPES_H
+# include <inttypes.h>
+# else
+
+# ifndef uint8_t
+# define uint8_t unsigned char
+# endif
+
+# ifndef uint16_t
+# define uint16_t unsigned short
+# endif
+
+# ifndef uint32_t
+# define uint32_t unsigned long
+# endif
+
+# ifndef int8_t
+# define int8_t char
+# endif
+
+# ifndef int16_t
+# define int16_t short
+# endif
+
+# ifndef int32_t
+# define int32_t long
+# endif
+
+# endif /* HAVE_INTTYPES_H */
+#endif /* HAVE_STDINT_H */
+
+#include "pi-macros.h"
+#include "pi-palmpix.h"
+
+#define max(a,b) (( a > b ) ? a : b )
+#define min(a,b) (( a < b ) ? a : b )
+
+int ColourCorrect (const struct PalmPixHeader *picHdr, uint8_t *r, uint8_t *gr, uint8_t *gb,
+ uint8_t *b);
+
+int Histogram(const struct PalmPixHeader *picHdr, uint8_t *r, uint8_t *gr, uint8_t *gb,
+ uint8_t *b);
+
+void DecodeRow(uint8_t *compData, uint8_t *lastRow, uint8_t *unCompData,
+ uint32_t *offset, int32_t *firstWord, uint16_t *PPLutsW,
+ uint8_t *PPLuts, uint16_t halfWidth);
+
+uint8_t huffWidth[] = {
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x0c,0x0c,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,
+ 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
+ 0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c
+};
+
+uint16_t huffTable[] =
+{
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,0xfff7,
+ 0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,
+ 0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,
+ 0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,
+ 0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,0xffe8,
+ 0xff60,0xff7b,0xffa5,0xffa5,0xffbd,0xffbd,0xffbd,0xffbd,
+ 0xffd0,0xffd0,0xffd0,0xffd0,0xffd0,0xffd0,0xffd0,0xffd0,
+ 0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,
+ 0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,0xffdc,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,0xffef,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,0xfff3,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,0xfffa,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
+ 0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,
+ 0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,
+ 0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,
+ 0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,
+ 0x0024,0x0024,0x0024,0x0024,0x0024,0x0024,0x0024,0x0024,
+ 0x0024,0x0024,0x0024,0x0024,0x0024,0x0024,0x0024,0x0024,
+ 0x0030,0x0030,0x0030,0x0030,0x0030,0x0030,0x0030,0x0030,
+ 0x0043,0x0043,0x0043,0x0043,0x005b,0x005b,0x0085,0x00a0
+};
+
+/****************************************************************
+ * Bias
+ *
+ * Bias is based on the Fast Alternative to Perlin's Bias algorithm
+ * in Graphics Gems IV by
+ * Christophe Schlick schlick@labri.u-bordeuax.fr
+ *****************************************************************/
+
+static void Bias( double bias, int width, int height, uint8_t *data )
+{
+ int i;
+ double num, denom, t;
+
+ fprintf( stderr, "Bias factor : %lf\n", bias );
+
+ for( i=0; i<width*height; i++ )
+ {
+ t = (double)data[i]/256.0;
+ num = t;
+ denom = (1.0/bias - 2) * (1.0 - t) + 1;
+ data[i] = num/denom * 256.0;
+ }
+}
+
+/***********************************************************************
+ * Odd green rows and even green rows have a different histogram
+ ***********************************************************************/
+int ColourCorrect (const struct PalmPixHeader *picHdr, uint8_t *r, uint8_t *gr, uint8_t *gb, uint8_t *b)
+{
+ /* uint8_t *tmpRow; */
+ uint8_t gbMin, gbMax, grMin, grMax, rMin, rMax, bMin, bMax;
+ float grInc, gbInc, rInc, bInc, grCur, gbCur, rCur, bCur;
+ float rMean = 0, grMean = 0, gbMean = 0, bMean = 0, maxMean;
+ uint16_t width = picHdr->w/2;
+ uint16_t height = picHdr->h/2;
+ int i;
+ uint8_t red[256], greenB[256], greenR[256], blue[256];
+
+ memset( red, 0, 256 * sizeof( uint8_t ));
+ memset( greenR, 0, 256 * sizeof( uint8_t ));
+ memset( greenB, 0, 256 * sizeof( uint8_t ));
+ memset( blue, 0, 256 * sizeof( uint8_t ));
+
+ gbMin = grMin = rMin = bMin = 255;
+ gbMax = grMax = rMax = bMax = 0;
+
+ for( i=0; i<width*height; i ++ )
+ {
+ gbMin = min( gbMin, gb[i] );
+ grMin = min( grMin, gr[i] );
+ rMin = min( rMin, r[i] );
+ bMin = min( bMin, b[i] );
+
+ gbMax = max( gbMax, gb[i] );
+ grMax = max( grMax, gr[i] );
+ rMax = max( rMax, r[i] );
+ bMax = max( bMax, b[i] );
+
+ rMean += r[i];
+ gbMean += gb[i];
+ grMean += gr[i];
+ bMean += b[i];
+ }
+
+ rMean = rMean / ( width * height );
+ gbMean = gbMean / ( width * height );
+ grMean = grMean / ( width * height );
+ bMean = bMean / ( width * height );
+
+ maxMean = max( max( gbMean-gbMin, grMean-grMin ), max( bMean-bMin, rMean-rMin ));
+
+ rInc = maxMean / (rMean-rMin);
+ grInc = maxMean / (grMean-grMin);
+ gbInc = maxMean / (gbMean-gbMin);
+ bInc = maxMean / (bMean-bMin);
+
+ rCur = 0;
+ grCur = 0;
+ gbCur = 0;
+ bCur = 0;
+
+ for (i = 0; i<256; i++)
+ {
+ if( i < rMin )
+ red[i] = 0;
+ else
+ {
+ if( rCur < 255 )
+ red[i] = rCur;
+ else
+ red[i] = 255;
+
+ rCur += rInc;
+ }
+
+ if( i < grMin )
+ greenR[i] = 0;
+ else
+ {
+ if( grCur < 255 )
+ greenR[i] = grCur;
+ else
+ greenR[i] = 255;
+
+ grCur += grInc;
+ }
+
+ if( i < gbMin )
+ greenB[i] = 0;
+ else
+ {
+ if( gbCur < 255 )
+ greenB[i] = gbCur;
+ else
+ greenB[i] = 255;
+
+ gbCur += gbInc;
+ }
+
+ if( i < bMin )
+ blue[i] = 0;
+ else
+ {
+ if( bCur < 255 )
+ blue[i] = bCur;
+ else
+ blue[i] = 255;
+
+ bCur += bInc;
+ }
+ }
+
+ for( i=0; i<width*height; i ++ )
+ {
+ gb[i] = greenB[gb[i]];
+ gr[i] = greenR[gr[i]];
+ b[i] = blue[b[i]];
+ r[i] = red[r[i]];
+ }
+
+ return( 1 );
+}
+
+int Histogram( const struct PalmPixHeader *picHdr, uint8_t *r, uint8_t *gr, uint8_t *gb, uint8_t *b )
+{
+ /* uint8_t *tmpRow; */
+ uint8_t gbMin, gbMax, grMin, grMax, rMin, rMax, bMin, bMax;
+ uint32_t rCum, grCum, gbCum, bCum;
+ uint32_t grC[256], gbC[256], rC[256], bC[256];
+ float grInc, gbInc, rInc, bInc, grCur, gbCur, rCur, bCur;
+ uint16_t width = picHdr->w/2;
+ uint16_t height = picHdr->h/2;
+ int i;
+ float clip;
+ uint8_t red[256], greenB[256], greenR[256], blue[256];
+ float redCeiling = 254;
+ float greenCeiling = 252;
+ float blueCeiling = 255;
+
+ memset( red, 0, 256 * sizeof( uint8_t ));
+ memset( greenR, 0, 256 * sizeof( uint8_t ));
+ memset( greenB, 0, 256 * sizeof( uint8_t ));
+ memset( blue, 0, 256 * sizeof( uint8_t ));
+
+ memset( rC, 0, 256 * sizeof( uint32_t ));
+ memset( grC, 0, 256 * sizeof( uint32_t ));
+ memset( gbC, 0, 256 * sizeof( uint32_t ));
+ memset( bC, 0, 256 * sizeof( uint32_t ));
+
+ gbMin = grMin = rMin = bMin = 255;
+ gbMax = grMax = rMax = bMax = 0;
+
+ for( i=0; i<width*height; i ++ )
+ {
+ rC[r[i]]++;
+ grC[gr[i]]++;
+ gbC[gb[i]]++;
+ bC[b[i]]++;
+ }
+
+ rCum = grCum = gbCum = bCum = 0;
+
+ clip = 0.05 * width * height;
+
+ for( i=0; i<256; i++ )
+ {
+ rCum += rC[i];
+
+ if( rMin == 255 && rCum > clip )
+ rMin = i;
+
+ grCum += grC[i];
+
+ if( grMin == 255 && grCum > clip )
+ grMin = i;
+
+ gbCum += gbC[i];
+
+ if( gbMin == 255 && gbCum > clip )
+ gbMin = i;
+
+ bCum += bC[i];
+
+ if( bMin == 255 && bCum > clip )
+ bMin = i;
+
+ if( rMin != 255 && grMin != 255 && gbMin != 255 && bMin != 255 )
+ break;
+ }
+
+ rCum = grCum = gbCum = bCum = 0;
+
+ for( i=255; i > 0; i-- )
+ {
+ rCum += rC[i];
+
+ if( rMax == 0 && rCum > clip )
+ rMax = i;
+
+ grCum += grC[i];
+
+ if( grMax == 0 && grCum > clip )
+ grMax = i;
+
+ gbCum += gbC[i];
+
+ if( gbMax == 0 && gbCum > clip )
+ gbMax = i;
+
+ bCum += bC[i];
+
+ if( bMax == 0 && bCum > clip )
+ bMax = i;
+
+ if( rMax != 0 && grMax != 0 && gbMax != 0 && bMax != 0 )
+ break;
+ }
+
+ rInc = redCeiling / (rMax-rMin);
+ grInc = greenCeiling / (grMax-grMin);
+ gbInc = greenCeiling / (gbMax-gbMin);
+ bInc = blueCeiling / (bMax-bMin);
+
+ rCur = 0;
+ grCur = 0;
+ gbCur = 0;
+ bCur = 0;
+
+ for (i = 0; i<256; i++)
+ {
+ if( i < rMin )
+ red[i] = 0;
+ else
+ {
+ if( rCur < redCeiling )
+ red[i] = rCur;
+ else
+ red[i] = greenCeiling;
+
+ rCur += rInc;
+ }
+
+ if( i < grMin )
+ greenR[i] = 0;
+ else
+ {
+ if( grCur < greenCeiling )
+ greenR[i] = grCur;
+ else
+ greenR[i] = greenCeiling;
+
+ grCur += grInc;
+ }
+
+ if( i < gbMin )
+ greenB[i] = 0;
+ else
+ {
+ if( gbCur < greenCeiling )
+ greenB[i] = gbCur;
+ else
+ greenB[i] = blueCeiling;
+
+ gbCur += gbInc;
+ }
+
+ if( i < bMin )
+ blue[i] = 0;
+ else
+ {
+ if( bCur < blueCeiling )
+ blue[i] = bCur;
+ else
+ blue[i] = blueCeiling;
+
+ bCur += bInc;
+ }
+ }
+
+ for( i=0; i<width*height; i ++ )
+ {
+ gb[i] = greenB[gb[i]];
+ gr[i] = greenR[gr[i]];
+ b[i] = blue[b[i]];
+ r[i] = red[r[i]];
+ }
+
+ return( 1 );
+}
+
+/*****************************************************************************
+ * The interpolation function looks a litte strange in that it uses 4 * the
+ * green component when the green component is centered. This is to compensate
+ * for a different intensity on odd and even green rows. All green
+ * interpolations have an equal number of pixels from a red row and blue row.
+ *****************************************************************************/
+static void Interpolate( const struct PalmPixHeader *pixHdr, uint8_t *red, uint8_t *greenR, uint8_t *greenB, uint8_t *blue, uint8_t *pp, int offset_r, int offset_g, int offset_b )
+{
+ int idx, offset, ppOff;
+ int x, y, rowOff;
+ uint8_t r, g, b;
+ int rawWidth = pixHdr->w/2;
+
+ for( y=1; y<pixHdr->h-1; y++ )
+ {
+
+ idx = y/2;
+ offset = idx * rawWidth;
+ ppOff = y * pixHdr->w;
+
+ if( y%2 == 1 )
+ {
+ for( x=1; x<rawWidth-1; x++ )
+ {
+
+ rowOff = x*2;
+
+ r = (red[offset+x-1] + red[offset + x] + red[offset + rawWidth + x -1] + red[offset + rawWidth + x])>>2;
+ g = (greenR[offset+x] + greenR[offset+x+rawWidth] + greenB[offset + x - 1] + greenB[offset + x])>>2;
+ b = blue[offset + x];
+ pp[3 * (ppOff + rowOff) + offset_r] = r;
+ pp[3 * (ppOff + rowOff) + offset_g] = g;
+ pp[3 * (ppOff + rowOff) + offset_b] = b;
+
+ r = (red[offset + x] + red[offset + rawWidth + x])>>1;
+ g = (( greenB[offset + x] << 2 ) + greenR[offset+x] + greenR[offset+x+1] + greenR[offset+x+rawWidth] + greenR[offset+x+rawWidth+1] )>>3;
+ b = (blue[offset + x] + blue[offset + x + 1])>>1;
+ pp[3 * (ppOff + rowOff + 1) + offset_r] = r;
+ pp[3 * (ppOff + rowOff + 1) + offset_g] = g;
+ pp[3 * (ppOff + rowOff + 1) + offset_b] = b;
+
+ }
+ }
+ else
+ {
+ for( x=1; x<rawWidth-1; x++ )
+ {
+ rowOff = x*2;
+
+ r = (red[offset + x - 1] + red[offset + x])>>1;
+ g = (( greenR[offset + x] << 2 ) + greenB[offset-rawWidth+x-1] + greenB[offset-rawWidth+x] + greenB[offset+x-1] + greenB[offset+x] )>>3;
+ b = (blue[offset-rawWidth+x] + blue[offset+x])>>1;
+ pp[3 * (ppOff + rowOff) + offset_r] = r;
+ pp[3 * (ppOff + rowOff) + offset_g] = g;
+ pp[3 * (ppOff + rowOff) + offset_b] = b;
+
+ r = red[offset+x];
+ g = (greenR[offset+x] + greenR[offset+x+1] + greenB[offset-rawWidth+x] + greenB[offset + x])>>2;
+ b = (blue[offset+x-rawWidth] + blue[offset+x-rawWidth-1] + blue[offset+x] + blue[offset+x+1])>>2;
+ pp[3 * (ppOff + rowOff + 1) + offset_r] = r;
+ pp[3 * (ppOff + rowOff + 1) + offset_g] = g;
+ pp[3 * (ppOff + rowOff + 1) + offset_b] = b;
+
+ }
+ }
+ }
+
+}
+
+void DecodeRow( uint8_t *compData, uint8_t *lastRow, uint8_t *unCompData, uint32_t *offset, int32_t *firstWord, uint16_t *PPLutsW, uint8_t *PPLuts, uint16_t halfWidth )
+{
+ uint8_t *saveStartP, shiftOut;
+ int16_t tmpW3, tmpResult, tmpW0, idx, resultW;
+ uint32_t lutIdx, tmpL0, tmpL2, tmpL5;
+
+ saveStartP = compData;
+
+ tmpW3 = 32 - *firstWord;
+
+ tmpResult = 32 - tmpW3;
+
+ tmpL5 = compData[0]<<24 | compData[1]<<16 | compData[2]<<8 | compData[3] ;
+ tmpL5 = tmpL5<<tmpResult;
+ tmpL0 = tmpL5;
+
+ compData += 4;
+
+ tmpL0 = tmpL0 >> 24;
+
+ unCompData[0] = (uint8_t)tmpL0;
+
+ tmpL5 = tmpL5 << 8;
+ tmpW3 = tmpW3 - 8;
+ idx = 1;
+
+ while( idx < halfWidth )
+ {
+ if( tmpW3 < 12 )
+ {
+ tmpW0 = 16 - tmpW3;
+ tmpL2 = ( compData[0]<<8 | compData[1] ) << tmpW0;
+ tmpL5 = tmpL5 | tmpL2;
+ tmpW3 += 16;
+ compData += 2;
+ }
+
+ lutIdx = tmpL5 >> 20;
+
+ shiftOut = PPLuts[lutIdx];
+
+ tmpL5 = tmpL5 << shiftOut;
+
+ tmpW3 = tmpW3 - shiftOut;
+
+ resultW = ( unCompData[idx-1] + lastRow[idx] ) >> 1;
+
+ resultW = resultW + PPLutsW[lutIdx];
+
+ if( resultW > 255 )
+ resultW = 255;
+
+ if( resultW < 0 )
+ resultW = 0;
+
+ unCompData[idx++] = (uint8_t)resultW;
+
+ }
+
+ while( tmpW3 > 0 )
+ {
+ compData--;
+ tmpW3 -= 8;
+ }
+
+ *offset = compData - saveStartP;
+ *firstWord = -tmpW3;
+
+}
+
+/* A binary PalmPixHeader is a record of length 196 in the following format.
+ Note that multibyte integers are in little endian byte order -- they are
+ NOT in m68k byte order.
+
+ 0UInt8 numRec;
+ 1UInt8 s0; // Always zero
+ 2UInt8 month;
+ 3UInt8 day;
+ 4UInt8 cent;
+ 5UInt8 year;
+ 6UInt8 hour;
+ 7UInt8 min;
+ 8UInt8 sec;
+ 9UInt8 resolution; // 640x480 = 1, 320x240 = 2, 400x300 = 3, 800x600 = 4
+ 10UInt16 w;
+ 12UInt16 h;
+ 14UInt16 thumbLen; // Size of the thumbnail following the name
+ 16UInt16 GRsize;
+ 18UInt8 sep0;
+ 19UInt16 Rsize;
+ 21UInt8 sep1;
+ 22UInt16 Bsize;
+ 24UInt8 sep2;
+ 25UInt16 GBsize;
+ 27UInt16 pad1;
+ 29UInt16 num; // hires 1200, lowres 300
+ 31UInt8 resA[14];
+ 45UInt8 zoom;
+ 46UInt8 softMajor; // Always 0x0102 [see below]
+ 47UInt8 softMinor; // Always 0x0102 [see below]
+ 48UInt8 resB[34];
+ 82UInt16 dir[57];
+
+ */
+
+
+ /* The remainder is due to John Marshall. It is pretty trivial compared to
+ the analysis above. */
+
+static int
+ get_le_short (const unsigned char *p)
+{
+
+ return p[0] | (p[1] << 8);
+
+}
+
+int
+ unpack_PalmPixHeader (struct PalmPixHeader *h, const unsigned char *p, int len)
+{
+ int magic1, magic2;
+
+ if (len != 196)
+ return 0;
+
+ magic1 = p[1];
+ magic2 = get_le_short (&p[46]);
+
+ /* FIXME For now, don't check the magic. I've seen 0x0002 and 0x0201.
+ I'm not sure that the endianness is right on this one. Possibly it
+ should be interpreted as two bytes instead (major and minor?). */
+ #if 0
+ if (magic1 != 0 || (magic2 != 0x0102 && magic2 != 0x0002))
+ return 0;
+ #endif
+
+ h->numRec= p[0];
+ h->month= p[2];
+ h->day= p[3];
+ h->year= p[4] * 100 + p[5];
+ h->hour= p[6];
+ h->min= p[7];
+ h->sec= p[8];
+ h->resolution= p[9];
+ h->w= get_le_short (&p[10]);
+ h->h= get_le_short (&p[12]);
+ h->thumbLen= get_le_short (&p[14]);
+ h->chansize[pixChannelGR] = get_le_short (&p[16]);
+ h->chansize[pixChannelR] = get_le_short (&p[19]);
+ h->chansize[pixChannelB] = get_le_short (&p[22]);
+ h->chansize[pixChannelGB] = get_le_short (&p[25]);
+ h->num= get_le_short (&p[29]);
+ h->zoom= p[45];
+
+ return 196;
+
+}
+
+int unpack_PalmPix (struct PalmPixState *s,
+ const struct PalmPixHeader *h, int header_recno, int wanted)
+{
+ int retcode = 1;
+
+ if (wanted & pixName)
+ {
+
+ void *buffer;
+ size_t bufsize;
+ if (s->getrecord (s, header_recno + 1, &buffer, &bufsize) == 0
+ && bufsize == 32)
+ {
+
+ memcpy (s->pixname, buffer, 32);
+ s->pixname[32] = '\0';
+
+ }
+ else
+ retcode = 0;
+
+ }
+
+ if (wanted & pixThumbnail)
+ {
+
+ /* FIXME */
+ retcode = 0;
+ fprintf (stderr,
+ "palmpix.c: thumbnail reader not implemented\n");
+
+ }
+
+ if (wanted & pixPixmap)
+ {
+
+ int rawWidth = h->w / 2;
+ int rawHeight = h->h / 2;
+ unsigned char *raw;
+ unsigned char *chan[4]; /* red/greenR/greenB/blue channels */
+ int chansize_max = 0;
+ int recno = header_recno;
+ int failed = 1;
+ int k;
+
+ for (k = 0; k < 4; k++)
+ chan[k] = NULL;
+ raw = NULL;
+ s->pixmap = NULL;
+
+ for (k = 0; k < 4; k++)
+ {
+
+ chan[k] = malloc ((size_t)(rawWidth * rawHeight));
+ if (chan[k] == NULL)
+ goto failed;
+ memset (chan[k], 0, (size_t)(rawWidth * rawHeight));
+ if (chansize_max < h->chansize[k])
+ chansize_max = h->chansize[k];
+
+ }
+
+
+ raw = malloc ((size_t)chansize_max);
+ if (raw == NULL)
+ goto failed;
+
+ s->pixmap = malloc ((size_t)(h->w * h->h * 3));
+ if (s->pixmap == NULL)
+ goto failed;
+
+ recno += 4; /* Skip to the first channel record. */
+
+ for (k = 0; k < 4; k++)
+ {
+ long num_bytes, offset;
+ int32_t lastWord = 0;
+ int j;
+
+ for (num_bytes = 0; num_bytes < h->chansize[k]; recno++)
+ {
+ void *buffer;
+ size_t bufsize;
+ if (s->getrecord (s, recno, &buffer, &bufsize) == 0) {
+ if (bufsize > h->chansize[k] - num_bytes)
+ bufsize = h->chansize[k] - num_bytes;
+ memcpy (&raw[num_bytes], buffer, (size_t)bufsize);
+ num_bytes += bufsize;
+
+ }
+ else
+ goto failed;
+
+ }
+
+ offset = 0;
+ memcpy (chan[k], &raw[offset], (size_t)rawWidth);
+ offset += rawWidth;
+
+ for (j = 1; j < rawHeight; j++)
+ {
+ uint32_t eaten;
+ DecodeRow (&raw[offset],
+ &chan[k][rawWidth * (j - 1)],
+ &chan[k][rawWidth * j],
+ &eaten, &lastWord,
+ huffTable, huffWidth, rawWidth);
+ offset += eaten;
+
+ }
+
+ }
+
+ if( s->flags & PALMPIX_COLOUR_CORRECTION )
+ ColourCorrect ( h, chan[pixChannelR], chan[pixChannelGR],
+ chan[pixChannelGB], chan[pixChannelB] );
+
+ if( s->bias != 50 )
+ {
+ Bias ( (double)s->bias / 100.0, rawWidth, rawHeight, chan[pixChannelR]);
+ Bias ( (double)s->bias / 100.0, rawWidth, rawHeight, chan[pixChannelGR]);
+ Bias ( (double)s->bias / 100.0, rawWidth, rawHeight, chan[pixChannelGB]);
+ Bias ( (double)s->bias / 100.0, rawWidth, rawHeight, chan[pixChannelB]);
+ }
+
+ if( s->flags & PALMPIX_HISTOGRAM_STRETCH )
+ Histogram ( h, chan[pixChannelR], chan[pixChannelGR],
+ chan[pixChannelGB], chan[pixChannelB] );
+
+ Interpolate (h,
+ chan[pixChannelR], chan[pixChannelGR],
+ chan[pixChannelGB], chan[pixChannelB],
+ s->pixmap, s->offset_r, s->offset_g, s->offset_b);
+
+ failed = 0;
+
+failed:
+ for (k = 0; k < 4; k++)
+ free (chan[k]);
+ free (raw);
+ if (failed)
+ {
+ free (s->pixmap);
+ retcode = 0;
+ }
+ }
+
+ s->highest_recno = header_recno + 3 + h->numRec;
+
+ return retcode;
+}
+
+int
+ free_PalmPix_data (struct PalmPixState *s)
+{
+ free (s->pixmap);
+
+ return 1;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-buffer.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-buffer.c
new file mode 100644
index 00000000..8064f316
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-buffer.c
@@ -0,0 +1,117 @@
+/*
+ * $Id: pi-buffer.c,v 1.10 2006/10/12 14:21:22 desrod Exp $
+ *
+ * pi-buffer.c: simple data block management for variable data storage
+ *
+ * Copyright (c) 2004-2005, Florent Pillet.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-buffer.h"
+
+pi_buffer_t*
+pi_buffer_new (size_t capacity)
+{
+ pi_buffer_t* buf;
+ buf = (struct pi_buffer_t *) malloc (sizeof (struct pi_buffer_t));
+ if (buf == NULL)
+ return NULL;
+
+ if (capacity <= 0)
+ capacity = 16; /* allocating 0 byte is illegal - use a small value instead */
+
+ buf->data = (unsigned char *) malloc (capacity);
+ if (buf->data == NULL) {
+ free (buf);
+ return NULL;
+ }
+
+ buf->allocated = capacity;
+ buf->used = 0;
+ return buf;
+}
+
+pi_buffer_t*
+pi_buffer_expect (pi_buffer_t *buf, size_t expect)
+{
+ if ((buf->allocated - buf->used) >= expect)
+ return buf;
+
+ if (buf->data)
+ buf->data = (unsigned char *) realloc (buf->data, buf->used + expect);
+ else
+ buf->data = (unsigned char *) malloc (expect);
+
+ if (buf->data == NULL) {
+ buf->allocated = 0;
+ buf->used = 0;
+ return NULL;
+ }
+
+ buf->allocated = buf->used + expect;
+ return buf;
+}
+
+pi_buffer_t*
+pi_buffer_append (pi_buffer_t *buf, const void *data, size_t len)
+{
+ if (pi_buffer_expect (buf, len) == NULL)
+ return NULL;
+
+ memcpy (buf->data + buf->used, data, len);
+ buf->used += len;
+
+ return buf;
+}
+
+pi_buffer_t *
+pi_buffer_append_buffer (pi_buffer_t *dest, const pi_buffer_t *src)
+{
+ return pi_buffer_append (dest, src->data, src->used);
+}
+
+void
+pi_buffer_clear (pi_buffer_t *buf)
+{
+ buf->used = 0;
+ if (buf->allocated > (size_t)65535)
+ {
+ buf->data = (unsigned char *) realloc (buf->data, 65535);
+ buf->allocated = (buf->data == NULL) ? 0 : 65535;
+ }
+}
+
+void
+pi_buffer_free (pi_buffer_t* buf)
+{
+ if (buf) {
+ if (buf->data)
+ free (buf->data);
+ free (buf);
+ }
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-file.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-file.c
new file mode 100644
index 00000000..e507bb32
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-file.c
@@ -0,0 +1,1531 @@
+/*
+ * $Id: pi-file.c,v 1.72 2006/10/12 14:21:22 desrod Exp $
+ *
+ * Pilot File Interface Library
+ * Pace Willisson <pace@blitz.com> December 1996
+ * Additions by Kenneth Albanowski
+ * Additions by Florent Pillet
+ *
+ * This is free software, licensed under the GNU Library Public License V2.
+ * See the file COPYING.LIB for details.
+ *
+ * the following is extracted from the combined wisdom of
+ * PDB by Kevin L. Flynn
+ * install-prc by Brian J. Swetland, D. Jeff Dionne and Kenneth Albanowski
+ * makedoc7 by Pat Beirne, <patb@corel.com>
+ * and the include files from the pilot SDK
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-file.h"
+#include "pi-error.h"
+
+#undef FILEDEBUG
+#define pi_mktag(c1,c2,c3,c4) (((c1)<<24)|((c2)<<16)|((c3)<<8)|(c4))
+
+/*
+ header:
+ 32 name
+ 2 flags
+ 2 version
+ 4 creation time
+ 4 modification time
+ 4 backup time
+ 4 modification number
+ 4 app info offset
+ 4 sort info offset
+ 4 type
+ 4 creator
+ 4 uniq id seed (I think it is just garbage)
+ 4 next record list id (normally 0, or ptr to extended hdr)
+ 2 num records for this header
+
+ Hypothetically plus 2 more bytes if an extended or perhaps secondary
+ header (not supported) (In practice, this value is never set, instead it
+ usually indicates a damaged file.)
+
+ if the low bit of attr is on, then next thing is a list of resource entry
+ descriptors:
+
+ resource entry header
+ 4 type
+ 2 id
+ 4 offset
+
+ otherwise, if the low bit of attr is off, the next thing is a list of
+ record entry decriptors:
+
+ record entry header
+ 4 offset
+ 1 record attributes
+ 3 unique id
+
+ then two bytes of unknown purpose, \0\0 seems safe
+
+ next, the app_info, if any, then the sort_info, if any
+
+ then the space used the data. Every offset is an offset from the
+ beginning of the file, and will point until this area. Each block starts
+ at the given offset and ends at the beginning of the next block. The last
+ block ends at the end of the file.
+ */
+
+#define PI_HDR_SIZE 78
+#define PI_RESOURCE_ENT_SIZE 10
+#define PI_RECORD_ENT_SIZE 8
+
+/* Local prototypes */
+static int pi_file_close_for_write(pi_file_t *pf);
+static void pi_file_free(pi_file_t *pf);
+static int pi_file_find_resource_by_type_id(const pi_file_t *pf, unsigned long restype, int resid, int *resindex);
+static pi_file_entry_t *pi_file_append_entry(pi_file_t *pf);
+static int pi_file_set_rbuf_size(pi_file_t *pf, size_t size);
+
+/* this seems to work, but what about leap years? */
+/*#define PILOT_TIME_DELTA (((unsigned)(1970 - 1904) * 365 * 24 * 60 * 60) + 1450800)*/
+
+/* Exact value of "Jan 1, 1970 0:00:00 GMT" - "Jan 1, 1904 0:00:00 GMT" */
+#define PILOT_TIME_DELTA (unsigned)(2082844800)
+
+
+/* FIXME: These conversion functions apply no timezone correction. UNIX uses
+ UTC for time_t's, while the Pilot uses local time for database backup
+ time and appointments, etc. It is not particularly simple to convert
+ between these in UNIX, especially since the Pilot's local time is
+ unknown, and if syncing over political boundries, could easily be
+ different then the local time on the UNIX box. Since the Pilot does not
+ know what timezone it is in, there is no unambiguous way to correct for
+ this.
+
+ Worse, the creation date for a program is stored in the local time _of
+ the computer which did the final linking of that program_. Again, the
+ Pilot does not store the timezone information needed to reconstruct
+ where/when this was.
+
+ A better immediate tack would be to dissect these into struct tm's, and
+ return those.
+ --KJA
+ */
+time_t
+pilot_time_to_unix_time(unsigned long raw_time)
+{
+ return (time_t) (raw_time - PILOT_TIME_DELTA);
+}
+
+unsigned long
+unix_time_to_pilot_time(time_t t)
+{
+ return (unsigned long) ((unsigned long) t + PILOT_TIME_DELTA);
+}
+
+pi_file_t
+*pi_file_open(const char *name)
+{
+ int i,
+ file_size;
+
+ pi_file_t *pf;
+ struct DBInfo *ip;
+ pi_file_entry_t *entp;
+
+ unsigned char buf[PI_HDR_SIZE];
+ unsigned char *p;
+ off_t offset, app_info_offset = 0, sort_info_offset = 0;
+
+ if ((pf = calloc(1, sizeof (pi_file_t))) == NULL)
+ return NULL;
+
+ if ((pf->f = fopen(name, "rb")) == NULL)
+ goto bad;
+
+ fseek(pf->f, 0, SEEK_END);
+ file_size = ftell(pf->f);
+ fseek(pf->f, 0, SEEK_SET);
+
+ if (fread(buf, PI_HDR_SIZE, 1, pf->f) != (size_t) 1) {
+ LOG ((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE OPEN %s: can't read header\n", name));
+ goto bad;
+ }
+
+ p = buf;
+ ip = &pf->info;
+
+ memcpy(ip->name, p, 32);
+ ip->flags = get_short(p + 32);
+ ip->miscFlags = dlpDBMiscFlagRamBased;
+ ip->version = get_short(p + 34);
+ ip->createDate = pilot_time_to_unix_time(get_long(p + 36));
+ ip->modifyDate = pilot_time_to_unix_time(get_long(p + 40));
+ ip->backupDate = pilot_time_to_unix_time(get_long(p + 44));
+ ip->modnum = get_long(p + 48);
+ app_info_offset = get_long(p + 52);
+ sort_info_offset = get_long(p + 56);
+ ip->type = get_long(p + 60);
+ ip->creator = get_long(p + 64);
+ pf->unique_id_seed = get_long(p + 68);
+
+ /* record list header */
+ pf->next_record_list_id = get_long(p + 72);
+ pf->num_entries = get_short(p + 76);
+
+ LOG ((PI_DBG_API, PI_DBG_LVL_INFO,
+ "FILE OPEN Name: '%s' Flags: 0x%4.4X Version: %d\n",
+ ip->name, ip->flags, ip->version));
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ " Creation date: %s", ctime(&ip->createDate)));
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ " Modification date: %s", ctime(&ip->modifyDate)));
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ " Backup date: %s", ctime(&ip->backupDate)));
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ " Appinfo Size: %d Sortinfo Size: %d\n",
+ pf->app_info_size, pf->sort_info_size));
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ " Type: '%s'", printlong(ip->type)));
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ " Creator: '%s' Seed: 0x%8.8lX\n", printlong(ip->creator),
+ pf->unique_id_seed));
+
+ if (pf->next_record_list_id != 0) {
+ LOG ((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE OPEN %s: this file is probably damaged\n", name));
+ goto bad;
+ }
+
+ if (ip->flags & dlpDBFlagResource) {
+ pf->resource_flag = 1;
+ pf->ent_hdr_size = PI_RESOURCE_ENT_SIZE;
+ } else {
+ pf->resource_flag = 0;
+ pf->ent_hdr_size = PI_RECORD_ENT_SIZE;
+ }
+
+ if (pf->num_entries < 0) {
+ LOG ((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE OPEN %s: bad header\n", name));
+ goto bad;
+ }
+
+ offset = file_size;
+
+ if (pf->num_entries) {
+ if ((pf->entries =
+ calloc((size_t)pf->num_entries,
+ sizeof *pf->entries)) == NULL)
+ goto bad;
+
+ for (i = 0, entp = pf->entries; i < pf->num_entries;
+ i++, entp++) {
+ if (fread(buf, (size_t) pf->ent_hdr_size, 1, pf->f)
+ != (size_t) 1)
+ goto bad;
+
+ p = buf;
+ if (pf->resource_flag) {
+ entp->type = get_long(p);
+ entp->resource_id = get_short(p + 4);
+ entp->offset = get_long(p + 6);
+
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ "FILE OPEN Entry %d '%s' #%d @%X\n", i,
+ printlong(entp->type), entp->resource_id,
+ entp->offset));
+ } else {
+ entp->offset = get_long(p);
+ entp->attrs = get_byte(p + 4);
+ entp->uid = get_treble(p + 5);
+
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ "FILE OPEN Entry %d UID: "
+ "0x%8.8X Attrs: %2.2X Offset: @%X\n", i,
+ (int) entp->uid, entp->attrs,
+ entp->offset));
+ }
+ }
+
+ for (i = 0, entp = pf->entries + pf->num_entries - 1;
+ i < pf->num_entries; i++, entp--) {
+ entp->size = offset - entp->offset;
+ offset = entp->offset;
+
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ "FILE OPEN Entry: %d Size: %d\n",
+ pf->num_entries - i - 1, entp->size));
+
+ if (entp->size < 0 ||
+ (entp->offset + entp->size) > file_size) {
+ LOG ((PI_DBG_API, PI_DBG_LVL_DEBUG,
+ "FILE OPEN %s: Entry %d corrupt,"
+ " giving up\n",
+ name, pf->num_entries - i - 1));
+ goto bad;
+ }
+ }
+ }
+
+ if (sort_info_offset) {
+ pf->sort_info_size = offset - sort_info_offset;
+ offset = sort_info_offset;
+ }
+
+ if (app_info_offset) {
+ pf->app_info_size = offset - app_info_offset;
+ offset = app_info_offset;
+ }
+
+ if (pf->app_info_size < 0 ||
+ (sort_info_offset + pf->sort_info_size) > file_size ||
+ pf->sort_info_size < 0 ||
+ (app_info_offset + pf->app_info_size) > file_size) {
+ LOG ((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE OPEN %s: bad header "
+ "(app_info @ %d size %d, "
+ "sort_info @ %d size %d)\n", name,
+ app_info_offset, pf->app_info_size,
+ sort_info_offset, pf->sort_info_size));
+ goto bad;
+ }
+
+ if (pf->app_info_size == 0)
+ pf->app_info = NULL;
+ else {
+ if ((pf->app_info =
+ malloc((size_t) pf->app_info_size)) == NULL)
+ goto bad;
+ fseek(pf->f, (long)app_info_offset, SEEK_SET);
+ if (fread(pf->app_info, 1, (size_t) pf->app_info_size, pf->f)
+ != (size_t) pf->app_info_size)
+ goto bad;
+ }
+
+ if (pf->sort_info_size == 0)
+ pf->sort_info = NULL;
+ else {
+ if ((pf->sort_info = malloc((size_t)pf->sort_info_size))
+ == NULL)
+ goto bad;
+ fseek(pf->f, (long)sort_info_offset, SEEK_SET);
+ if (fread(pf->sort_info, 1, (size_t) pf->sort_info_size,
+ pf->f) != (size_t) pf->sort_info_size)
+ goto bad;
+ }
+
+ return pf;
+
+bad:
+ pi_file_close(pf);
+ return NULL;
+}
+
+int
+pi_file_close(pi_file_t *pf)
+{
+ int err;
+
+ if (!pf)
+ return PI_ERR_FILE_INVALID;
+
+ if (pf->for_writing)
+ pf->err = pi_file_close_for_write(pf);
+
+ err = pf->err;
+
+ pi_file_free(pf);
+
+ return err;
+}
+
+void
+pi_file_get_info(const pi_file_t *pf, struct DBInfo *infop)
+{
+ *infop = pf->info;
+}
+
+void
+pi_file_get_app_info(pi_file_t *pf, void **datap, size_t *sizep)
+{
+ *datap = pf->app_info;
+ *sizep = pf->app_info_size;
+}
+
+void
+pi_file_get_sort_info(pi_file_t *pf, void **datap, size_t *sizep)
+{
+ *datap = pf->sort_info;
+ *sizep = pf->sort_info_size;
+}
+
+int
+pi_file_read_resource_by_type_id(pi_file_t *pf, unsigned long restype,
+ int resid, void **bufp, size_t *sizep,
+ int *resindex)
+{
+ int i,
+ result;
+
+ result = pi_file_find_resource_by_type_id(pf, restype, resid, &i);
+ if (!result)
+ return PI_ERR_FILE_NOT_FOUND;
+ if (resindex)
+ *resindex = i;
+ return pi_file_read_resource(pf, i, bufp, sizep, NULL, NULL);
+}
+
+int
+pi_file_type_id_used(const pi_file_t *pf, unsigned long restype, int resid)
+{
+ return pi_file_find_resource_by_type_id(pf, restype, resid, NULL);
+}
+
+int
+pi_file_read_resource(pi_file_t *pf, int i,
+ void **bufp, size_t *sizep, unsigned long *type,
+ int *idp)
+{
+ pi_file_entry_t *entp;
+ int result;
+
+ if (pf->for_writing || !pf->resource_flag)
+ return PI_ERR_FILE_INVALID;
+
+ if (i < 0 || i >= pf->num_entries)
+ return PI_ERR_GENERIC_ARGUMENT;
+
+ entp = &pf->entries[i];
+
+ if (bufp) {
+ if ((result = pi_file_set_rbuf_size(pf, (size_t) entp->size)) < 0)
+ return result;
+ fseek(pf->f, pf->entries[i].offset, SEEK_SET);
+ if (fread(pf->rbuf, 1, (size_t) entp->size, pf->f) !=
+ (size_t) entp->size)
+ return PI_ERR_FILE_ERROR;
+ *bufp = pf->rbuf;
+ }
+
+ if (sizep)
+ *sizep = entp->size;
+ if (type)
+ *type = entp->type;
+ if (idp)
+ *idp = entp->resource_id;
+
+ return 0;
+}
+
+int
+pi_file_read_record(pi_file_t *pf, int recindex,
+ void **bufp, size_t *sizep, int *recattrs, int *category,
+ recordid_t * recuid)
+{
+ int result;
+ pi_file_entry_t *entp;
+
+ if (pf->for_writing || pf->resource_flag)
+ return PI_ERR_FILE_INVALID;
+
+ if (recindex < 0 || recindex >= pf->num_entries)
+ return PI_ERR_GENERIC_ARGUMENT;
+
+ entp = &pf->entries[recindex];
+
+ if (bufp) {
+ if ((result = pi_file_set_rbuf_size(pf, (size_t) entp->size)) < 0) {
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE READ_RECORD Unable to set buffer size!\n"));
+ return result;
+ }
+
+ fseek(pf->f, pf->entries[recindex].offset, SEEK_SET);
+
+ if (fread(pf->rbuf, 1, (size_t) entp->size, pf->f) !=
+ (size_t) entp->size) {
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE READ_RECORD Unable to read record!\n"));
+ return PI_ERR_FILE_ERROR;
+ }
+
+ *bufp = pf->rbuf;
+ }
+
+ LOG ((PI_DBG_API, PI_DBG_LVL_INFO,
+ "FILE READ_RECORD Record: %d Bytes: %d\n", recindex, entp->size));
+
+ if (sizep)
+ *sizep = entp->size;
+ if (recattrs)
+ *recattrs = entp->attrs & 0xf0;
+ if (category)
+ *category = entp->attrs & 0xf;
+ if (recuid)
+ *recuid = entp->uid;
+
+ return 0;
+}
+
+int
+pi_file_read_record_by_id(pi_file_t *pf, recordid_t uid,
+ void **bufp, size_t *sizep, int *idxp, int *attrp,
+ int *catp)
+{
+ int i;
+ struct pi_file_entry *entp;
+
+ for (i = 0, entp = pf->entries; i < pf->num_entries;
+ i++, entp++) {
+ if (entp->uid == uid) {
+ if (idxp)
+ *idxp = i;
+ return (pi_file_read_record
+ (pf, i, bufp, sizep, attrp, catp, &uid));
+ }
+ }
+
+ return PI_ERR_FILE_NOT_FOUND;
+}
+
+int
+pi_file_id_used(const pi_file_t *pf, recordid_t uid)
+{
+ int i;
+ struct pi_file_entry *entp;
+
+ for (i = 0, entp = pf->entries; i < pf->num_entries; i++, entp++) {
+ if (entp->uid == uid)
+ return 1;
+ }
+ return 0;
+}
+
+pi_file_t *
+pi_file_create(const char *name, const struct DBInfo *info)
+{
+ pi_file_t *pf = calloc(1, sizeof(pi_file_t));
+
+ if (pf == NULL)
+ return NULL;
+
+ if ((pf->file_name = strdup(name)) == NULL)
+ goto bad;
+
+ pf->for_writing = 1;
+ pf->info = *info;
+
+ if (info->flags & dlpDBFlagResource) {
+ pf->resource_flag = 1;
+ pf->ent_hdr_size = PI_RESOURCE_ENT_SIZE;
+ } else {
+ pf->resource_flag = 0;
+ pf->ent_hdr_size = PI_RECORD_ENT_SIZE;
+ }
+
+ pf->tmpbuf = pi_buffer_new(2048);
+ if (pf->tmpbuf == NULL)
+ goto bad;
+
+ return (pf);
+
+bad:
+ pi_file_free(pf);
+ return NULL;
+}
+
+int
+pi_file_set_info(pi_file_t *pf, const struct DBInfo *ip)
+{
+ if (!pf->for_writing)
+ return PI_ERR_FILE_INVALID;
+
+ if ((ip->flags & dlpDBFlagResource) !=
+ (pf->info.flags & dlpDBFlagResource))
+ return PI_ERR_FILE_INVALID;
+
+ pf->info = *ip;
+
+ return 0;
+}
+
+int
+pi_file_set_app_info(pi_file_t *pf, void *data, size_t size)
+{
+ void *p;
+
+ if (!size) {
+ if (pf->app_info)
+ free(pf->app_info);
+ pf->app_info_size = 0;
+ return 0;
+ }
+
+ if ((p = malloc(size)) == NULL)
+ return PI_ERR_GENERIC_MEMORY;
+
+ memcpy(p, data, size);
+
+ if (pf->app_info)
+ free(pf->app_info);
+
+ pf->app_info = p;
+ pf->app_info_size = size;
+
+ return 0;
+}
+
+int
+pi_file_set_sort_info(pi_file_t *pf, void *data, size_t size)
+{
+ void *p;
+
+ if (!size) {
+ if (pf->sort_info)
+ free(pf->sort_info);
+ pf->sort_info_size = 0;
+ return 0;
+ }
+
+ if ((p = malloc(size)) == NULL)
+ return PI_ERR_GENERIC_MEMORY;
+
+ memcpy(p, data, size);
+
+ if (pf->sort_info)
+ free(pf->sort_info);
+
+ pf->sort_info = p;
+ pf->sort_info_size = size;
+
+ return 0;
+}
+
+int
+pi_file_append_resource(pi_file_t *pf, void *data, size_t size,
+ unsigned long restype, int resid)
+{
+ pi_file_entry_t *entp;
+
+ if (!pf->for_writing || !pf->resource_flag)
+ return PI_ERR_FILE_INVALID;
+ if (pi_file_type_id_used(pf, restype, resid))
+ return PI_ERR_FILE_ALREADY_EXISTS;
+
+ entp = pi_file_append_entry(pf);
+ if (entp == NULL)
+ return PI_ERR_GENERIC_MEMORY;
+
+ if (size && pi_buffer_append(pf->tmpbuf, data, size) == NULL) {
+ pf->err = 1;
+ return PI_ERR_GENERIC_MEMORY;
+ }
+
+ entp->size = size;
+ entp->type = restype;
+ entp->resource_id = resid;
+
+ return size;
+}
+
+int
+pi_file_append_record(pi_file_t *pf, void *data, size_t size,
+ int recattrs, int category, recordid_t recuid)
+{
+ pi_file_entry_t *entp;
+
+ if (!pf->for_writing || pf->resource_flag)
+ return PI_ERR_FILE_INVALID;
+ if (recuid && pi_file_id_used(pf, recuid))
+ return PI_ERR_FILE_ALREADY_EXISTS;
+
+ entp = pi_file_append_entry(pf);
+ if (entp == NULL)
+ return PI_ERR_GENERIC_MEMORY;
+
+ if (size && pi_buffer_append(pf->tmpbuf, data, size) == NULL) {
+ pf->err = 1;
+ return PI_ERR_GENERIC_MEMORY;
+ }
+
+ entp->size = size;
+ entp->attrs = (recattrs & 0xf0) | (category & 0xf);
+ entp->uid = recuid;
+
+ return size;
+}
+
+void
+pi_file_get_entries(pi_file_t *pf, int *entries)
+{
+ *entries = pf->num_entries;
+}
+
+int
+pi_file_retrieve(pi_file_t *pf, int socket, int cardno,
+ progress_func report_progress)
+{
+ int db = -1,
+ result,
+ old_device = 0;
+
+ unsigned int j;
+
+ struct DBInfo dbi;
+ struct DBSizeInfo size_info;
+
+ pi_buffer_t *buffer = NULL;
+ pi_progress_t progress;
+
+ pi_reset_errors(socket);
+ memset(&size_info, 0, sizeof(size_info));
+ memset(&dbi, 0, sizeof(dbi));
+
+ /* Try to get more info on the database to retrieve. Note that
+ * with some devices like the Tungsten T3 and shadowed databases
+ * like AddressDB, the size_info is -wrong-. It doesn't reflect
+ * the actual contents of the database except for the number of
+ * records. Also, this call doesn't work pre-OS 3.
+ */
+ if ((result = dlp_FindDBByName(socket, cardno, pf->info.name,
+ NULL, NULL, &dbi, &size_info)) < 0)
+ {
+ if (result != PI_ERR_DLP_UNSUPPORTED)
+ goto fail;
+ old_device = 1;
+ }
+
+ if ((result = dlp_OpenDB (socket, cardno, dlpOpenRead | dlpOpenSecret,
+ pf->info.name, &db)) < 0)
+ goto fail;
+
+ buffer = pi_buffer_new (DLP_BUF_SIZE);
+ if (buffer == NULL) {
+ result = pi_set_error(socket, PI_ERR_GENERIC_MEMORY);
+ goto fail;
+ }
+
+ if (old_device) {
+ int num_records;
+ if ((result = dlp_ReadOpenDBInfo(socket, db, &num_records)) < 0)
+ goto fail;
+ size_info.numRecords = num_records;
+ }
+
+ memset(&progress, 0, sizeof(progress));
+ progress.type = PI_PROGRESS_RECEIVE_DB;
+ progress.data.db.pf = pf;
+ progress.data.db.size = size_info;
+
+ if (size_info.appBlockSize
+ || (dbi.miscFlags & dlpDBMiscFlagRamBased)
+ || old_device) {
+ /* what we're trying to do here is avoid trying to read an appBlock
+ * from a ROM file, because this crashes on several devices.
+ * Also, on several palmOne devices, the size info returned by the OS
+ * is absolutely incorrect. This happens with some system shadow files
+ * like AddressDB on T3, which actually do contain data and an appInfo
+ * block but the system tells us there's no appInfo and nearly no data,
+ * but still gives the accurate number of records. Seems to be bad
+ * structure shadows in PACE.
+ * In any case, the ultimate result is that:
+ * 1. On devices pre-OS 3, we do always try to read the appInfo block
+ * because dlp_FindDBByName() is unsupported so we can't find out if
+ * there's an appInfo block
+ * 2. On OS5+ devices, we're not sure that the appInfo size we have is
+ * accurate. But if we try reading an appInfo block in ROM it may
+ * crash the device
+ * 3. Therefore, we only try to read the appInfo block if we are
+ * working on a RAM file or we are sure that a ROM file has appInfo.
+ */
+ result = dlp_ReadAppBlock(socket, db, 0, DLP_BUF_SIZE, buffer);
+ if (result > 0) {
+ pi_file_set_app_info(pf, buffer->data, (size_t)result);
+ progress.transferred_bytes += result;
+ if (report_progress && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = PI_ERR_FILE_ABORTED;
+ goto fail;
+ }
+ }
+ }
+
+ if (pf->info.flags & dlpDBFlagResource) {
+ for (j = 0; j < size_info.numRecords; j++) {
+ int resource_id;
+ unsigned long type;
+
+ if ((result = dlp_ReadResourceByIndex(socket, db, j, buffer,
+ &type, &resource_id)) < 0)
+ goto fail;
+
+ if ((result = pi_file_append_resource (pf, buffer->data, buffer->used,
+ type, resource_id)) < 0) {
+ pi_set_error(socket, result);
+ goto fail;
+ }
+
+ progress.transferred_bytes += buffer->used;
+ progress.data.db.transferred_records++;
+
+ if (report_progress && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = pi_set_error(socket, PI_ERR_FILE_ABORTED);
+ goto fail;
+ }
+ }
+ } else for (j = 0; j < size_info.numRecords; j++) {
+ int attr,
+ category;
+ unsigned long resource_id;
+
+ if ((result = dlp_ReadRecordByIndex(socket, db, j, buffer, &resource_id, &attr,
+ &category)) < 0)
+ goto fail;
+
+ progress.transferred_bytes += buffer->used;
+ progress.data.db.transferred_records++;
+
+ if (report_progress
+ && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = pi_set_error(socket, PI_ERR_FILE_ABORTED);
+ goto fail;
+ }
+
+ /* There is no way to restore records with these
+ attributes, so there is no use in backing them up
+ */
+ if (attr &
+ (dlpRecAttrArchived | dlpRecAttrDeleted))
+ continue;
+ if ((result = pi_file_append_record(pf, buffer->data, buffer->used,
+ attr, category, resource_id)) < 0) {
+ pi_set_error(socket, result);
+ goto fail;
+ }
+ }
+
+ pi_buffer_free(buffer);
+
+ return dlp_CloseDB(socket, db);
+
+fail:
+ if (db != -1 && pi_socket_connected(socket)) {
+ int err = pi_error(socket); /* make sure we keep last error code */
+ int palmoserr = pi_palmos_error(socket);
+
+ dlp_CloseDB(socket, db);
+
+ pi_set_error(socket, err); /* then restore it afterwards */
+ pi_set_palmos_error(socket, palmoserr);
+ }
+
+ if (buffer != NULL)
+ pi_buffer_free (buffer);
+
+ if (result >= 0) {
+ /* one of our pi_file* calls failed */
+ result = pi_set_error(socket, PI_ERR_FILE_ERROR);
+ }
+ return result;
+}
+
+int
+pi_file_install(pi_file_t *pf, int socket, int cardno,
+ progress_func report_progress)
+{
+ int db = -1,
+ j,
+ reset = 0,
+ flags,
+ version,
+ freeai = 0,
+ result,
+ err1,
+ err2;
+ size_t l,
+ size = 0;
+ void *buffer;
+ pi_progress_t progress;
+
+ version = pi_version(socket);
+
+ memset(&progress, 0, sizeof(progress));
+ progress.type = PI_PROGRESS_SEND_DB;
+ progress.data.db.pf = pf;
+ progress.data.db.size.numRecords = pf->num_entries;
+ progress.data.db.size.dataBytes = pf->app_info_size;
+ progress.data.db.size.appBlockSize = pf->app_info_size;
+ progress.data.db.size.maxRecSize = pi_maxrecsize(socket);
+
+ /* compute total size for progress reporting, and check that
+ either records are 64k or less, or the handheld can accept
+ large records. we do this prior to starting the install,
+ to avoid messing the device up if we have to fail. */
+ for (j = 0; j < pf->num_entries; j++) {
+ result = (pf->info.flags & dlpDBFlagResource) ?
+ pi_file_read_resource(pf, j, 0, &size, 0, 0) :
+ pi_file_read_record(pf, j, 0, &size, 0, 0, 0);
+ if (result < 0) {
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE INSTALL can't read all records/resources\n"));
+ goto fail;
+ }
+ if (size > 65536 && version < 0x0104) {
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE INSTALL Database contains"
+ " record/resource over 64K!\n"));
+ goto fail;
+ }
+ progress.data.db.size.dataBytes += size;
+ }
+
+ progress.data.db.size.totalBytes =
+ progress.data.db.size.dataBytes +
+ pf->ent_hdr_size * pf->num_entries +
+ PI_HDR_SIZE + 2;
+
+ /* Delete DB if it already exists */
+ dlp_DeleteDB(socket, cardno, pf->info.name);
+
+ /* Set up DB flags */
+ flags = pf->info.flags;
+
+ /* Judd - 25Nov99 - Graffiti hack We want to make sure that these 2
+ flags get set for this one */
+ if (pf->info.creator == pi_mktag('g', 'r', 'a', 'f')) {
+ flags |= dlpDBFlagNewer;
+ flags |= dlpDBFlagReset;
+ }
+
+ if (strcmp(pf->info.name, "Graffiti ShortCuts ") == 0) {
+ flags |= 0x8000; /* Rewrite an open DB */
+ reset = 1; /* To be on the safe side */
+ }
+ LOG((PI_DBG_API, PI_DBG_LVL_INFO,
+ "FILE INSTALL Name: %s Flags: %8.8X\n", pf->info.name, flags));
+
+ /* Create DB */
+ if ((result = dlp_CreateDB
+ (socket, pf->info.creator, pf->info.type, cardno, flags,
+ pf->info.version, pf->info.name, &db)) < 0) {
+ int retry = 0;
+
+ /* Judd - 25Nov99 - Graffiti hack
+
+ The dlpDBFlagNewer specifies that if a DB is open and
+ cannot be deleted then it can be overwritten by a DB with
+ a different name. The creator ID of "graf" is what
+ really identifies a DB, not the name. We could call it
+ JimBob and the palm would still find it and use it. */
+
+ if (strcmp(pf->info.name, "Graffiti ShortCuts ") == 0) {
+ strcpy(pf->info.name, "Graffiti ShortCuts");
+ retry = 1;
+ } else if (strcmp(pf->info.name, "Graffiti ShortCuts") ==
+ 0) {
+ strcpy(pf->info.name, "Graffiti ShortCuts ");
+ retry = 1;
+ } else if (pf->info.creator ==
+ pi_mktag('g', 'r', 'a', 'f')) {
+ /* Yep, someone has named it JimBob */
+ strcpy(pf->info.name, "Graffiti ShortCuts");
+ retry = 1;
+ }
+
+ if (retry) {
+ /* Judd - 25Nov99 - Graffiti hack
+ We changed the name, now we can try to write it
+ again */
+ if ((result = dlp_CreateDB
+ (socket, pf->info.creator, pf->info.type,
+ cardno, flags, pf->info.version,
+ pf->info.name, &db)) < 0) {
+ return result;
+ }
+ } else {
+ return result;
+ }
+ }
+
+ pi_file_get_app_info(pf, &buffer, &l);
+
+ /* Compensate for bug in OS 2.x Memo */
+ if (version > 0x0100
+ && strcmp(pf->info.name, "MemoDB") == 0
+ && l > 0
+ && l < 282) {
+ /* Justification: The appInfo structure was accidentally
+ lengthend in OS 2.0, but the Memo application does not
+ check that it is long enough, hence the shorter block
+ from OS 1.x will cause the 2.0 Memo application to lock
+ up if the sort preferences are modified. This code
+ detects the installation of a short app info block on a
+ 2.0 machine, and lengthens it. This transformation will
+ never lose information. */
+ void *b2 = calloc(1, 282);
+ memcpy(b2, buffer, (size_t)l);
+ buffer = b2;
+ progress.data.db.size.appBlockSize = 282;
+ l = 282;
+ freeai = 1;
+ }
+
+ /* All system updates seen to have the 'ptch' type, so trigger a
+ reboot on those */
+ if (pf->info.creator == pi_mktag('p', 't', 'c', 'h'))
+ reset = 1;
+
+ if (pf->info.flags & dlpDBFlagReset)
+ reset = 1;
+
+ /* Upload appInfo block */
+ if (l > 0) {
+ if ((result = dlp_WriteAppBlock(socket, db, buffer, l)) < 0) {
+ if (freeai)
+ free(buffer);
+ goto fail;
+ }
+ if (freeai)
+ free(buffer);
+ progress.transferred_bytes = l;
+ if (report_progress && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = pi_set_error(socket, PI_ERR_FILE_ABORTED);
+ goto fail;
+ }
+ }
+
+ /* Upload resources / records */
+ if (pf->info.flags & dlpDBFlagResource) {
+ for (j = 0; j < pf->num_entries; j++) {
+ int resource_id;
+ unsigned long type;
+
+ if ((result = pi_file_read_resource(pf, j, &buffer, &size,
+ &type, &resource_id)) < 0)
+ goto fail;
+
+ /* Skip empty resource, it cannot be installed */
+ if (size == 0)
+ continue;
+
+ if ((result = dlp_WriteResource(socket, db, type, resource_id, buffer,
+ size)) < 0)
+ goto fail;
+
+ progress.transferred_bytes += size;
+ progress.data.db.transferred_records++;
+
+ if (report_progress && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = pi_set_error(socket, PI_ERR_FILE_ABORTED);
+ goto fail;
+ }
+
+ /* If we see a 'boot' section, regardless of file
+ type, require reset */
+ if (type == pi_mktag('b', 'o', 'o', 't'))
+ reset = 1;
+ }
+ } else {
+ for (j = 0; j < pf->num_entries; j++) {
+ int attr,
+ category;
+ unsigned long resource_id;
+
+ if ((result = pi_file_read_record(pf, j, &buffer, &size, &attr,
+ &category, &resource_id)) < 0)
+ goto fail;
+
+ /* Old OS version cannot install deleted records, so
+ don't even try */
+ if ((attr & (dlpRecAttrArchived | dlpRecAttrDeleted))
+ && version < 0x0101)
+ continue;
+
+ if ((result = dlp_WriteRecord(socket, db, attr, resource_id, category,
+ buffer, size, 0)) < 0)
+ goto fail;
+
+ progress.transferred_bytes += size;
+ progress.data.db.transferred_records++;
+
+ if (report_progress
+ && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = pi_set_error(socket, PI_ERR_FILE_ABORTED);
+ goto fail;
+ }
+ }
+ }
+
+ if (reset)
+ dlp_ResetSystem(socket);
+
+ return dlp_CloseDB(socket, db);
+
+fail:
+ /* save error codes then restore them after
+ closing/deleting the DB */
+ err1 = pi_error(socket);
+ err2 = pi_palmos_error(socket);
+
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR, "FILE INSTALL error: pilot-link "
+ "0x%04x, PalmOS 0x%04x\n", err1, err2));
+ if (db != -1 && pi_socket_connected(socket))
+ dlp_CloseDB(socket, db);
+ if (pi_socket_connected(socket))
+ dlp_DeleteDB(socket, cardno, pf->info.name);
+
+ pi_set_error(socket, err1);
+ pi_set_palmos_error(socket, err2);
+
+ if (result >= 0)
+ result = pi_set_error(socket, PI_ERR_FILE_ERROR);
+ return result;
+}
+
+int
+pi_file_merge(pi_file_t *pf, int socket, int cardno,
+ progress_func report_progress)
+{
+ int db = -1,
+ j,
+ reset = 0,
+ version,
+ result;
+ void *buffer;
+ size_t size;
+ pi_progress_t progress;
+
+ version = pi_version(socket);
+
+ memset(&progress, 0, sizeof(progress));
+ progress.type = PI_PROGRESS_SEND_DB;
+ progress.data.db.pf = pf;
+ progress.data.db.size.numRecords = pf->num_entries;
+ progress.data.db.size.dataBytes = pf->app_info_size;
+ progress.data.db.size.appBlockSize = pf->app_info_size;
+ progress.data.db.size.maxRecSize = pi_maxrecsize(socket);
+
+ if (dlp_OpenDB(socket, cardno, dlpOpenReadWrite | dlpOpenSecret,
+ pf->info.name, &db) < 0)
+ return pi_file_install(pf, socket, cardno, report_progress);
+
+ /* compute total size for progress reporting, and check that
+ either records are 64k or less, or the handheld can accept
+ large records. we do this prior to starting the install,
+ to avoid messing the device up if we have to fail. */
+ for (j = 0; j < pf->num_entries; j++) {
+ result = (pf->info.flags & dlpDBFlagResource) ?
+ pi_file_read_resource(pf, j, 0, &size, 0, 0) :
+ pi_file_read_record(pf, j, 0, &size, 0, 0, 0);
+ if (result < 0) {
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE INSTALL can't read all records/resources\n"));
+ goto fail;
+ }
+ if (size > 65536 && version < 0x0104) {
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR,
+ "FILE INSTALL Database contains"
+ " record/resource over 64K!\n"));
+ result = pi_set_error(socket, PI_ERR_DLP_DATASIZE);
+ goto fail;
+ }
+ progress.data.db.size.dataBytes += size;
+ }
+
+ progress.data.db.size.totalBytes =
+ progress.data.db.size.dataBytes +
+ pf->ent_hdr_size * pf->num_entries +
+ PI_HDR_SIZE + 2;
+
+ /* All system updates seen to have the 'ptch' type, so trigger a
+ reboot on those */
+ if (pf->info.creator == pi_mktag('p', 't', 'c', 'h'))
+ reset = 1;
+
+ if (pf->info.flags & dlpDBFlagReset)
+ reset = 1;
+
+ /* Upload resources / records */
+ if (pf->info.flags & dlpDBFlagResource) {
+ for (j = 0; j < pf->num_entries; j++) {
+ int resource_id;
+ unsigned long type;
+
+ if ((result = pi_file_read_resource
+ (pf, j, &buffer, &size, &type, &resource_id)) < 0)
+ goto fail;
+
+ if (size == 0)
+ continue;
+
+ if ((result = dlp_WriteResource
+ (socket, db, type, resource_id, buffer, size)) < 0)
+ goto fail;
+
+ progress.transferred_bytes += size;
+ progress.data.db.transferred_records++;
+
+ if (report_progress && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = pi_set_error(socket, PI_ERR_FILE_ABORTED);
+ goto fail;
+ }
+
+ /* If we see a 'boot' section, regardless of file
+ type, require reset */
+ if (type == pi_mktag('b', 'o', 'o', 't'))
+ reset = 1;
+ }
+ } else {
+ for (j = 0; j < pf->num_entries; j++) {
+ int attr,
+ category;
+ unsigned long resource_id;
+
+ if ((result = pi_file_read_record(pf, j, &buffer, &size,
+ &attr, &category, &resource_id)) < 0)
+ goto fail;
+
+ /* Old OS version cannot install deleted records, so
+ don't even try */
+ if ((attr & (dlpRecAttrArchived | dlpRecAttrDeleted))
+ && version < 0x0101)
+ continue;
+
+ if ((result = dlp_WriteRecord(socket, db, attr, 0, category,
+ buffer, size, 0)) < 0)
+ goto fail;
+
+ progress.transferred_bytes += size;
+ progress.data.db.transferred_records++;
+
+ if (report_progress && report_progress(socket,
+ &progress) == PI_TRANSFER_STOP) {
+ result = PI_ERR_FILE_ABORTED;
+ goto fail;
+ }
+ }
+ }
+
+ if (reset)
+ dlp_ResetSystem(socket);
+
+ return dlp_CloseDB(socket, db);
+
+fail:
+ if (db != -1 && pi_socket_connected(socket)) {
+ int err1 = pi_error(socket);
+ int err2 = pi_palmos_error(socket);
+
+ dlp_CloseDB(socket, db);
+
+ pi_set_error(socket, err1);
+ pi_set_palmos_error(socket, err2);
+ }
+ if (result >= 0)
+ result = pi_set_error(socket, PI_ERR_FILE_ERROR);
+ return result;
+}
+
+/*********************************************************************************/
+/* */
+/* INTERNAL FUNCTIONS */
+/* */
+/*********************************************************************************/
+
+/***********************************************************************
+ *
+ * Function: pi_file_close_for_write
+ *
+ * Summary: Writes a file to disk
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_file_close_for_write(pi_file_t *pf)
+{
+ int i,
+ offset;
+ FILE *f;
+
+ struct DBInfo *ip;
+ struct pi_file_entry *entp;
+ struct stat sbuf;
+
+ unsigned char buf[512];
+ unsigned char *p;
+
+ ip = &pf->info;
+ if (pf->num_entries >= 64 * 1024) {
+ LOG((PI_DBG_API, PI_DBG_LVL_ERR,
+ "pi_file_close_for_write: too many entries "
+ "for this implentation of pi-file: %d\n",
+ pf->num_entries));
+ return PI_ERR_FILE_INVALID;
+ }
+
+ /*
+ * Unlink instead of overwriting.
+ * For the case of something along the lines of:
+ * cp -lav backup_2005_05_27 backup_2005_05_28
+ * Then updating the new copy.
+ * -- Warp.
+ */
+
+ if (!stat (pf->file_name, &sbuf))
+ if (S_ISREG(sbuf.st_mode))
+ unlink (pf->file_name);
+
+ if ((f = fopen(pf->file_name, "wb")) == NULL)
+ return PI_ERR_FILE_ERROR;
+
+ ip = &pf->info;
+
+ offset = PI_HDR_SIZE + pf->num_entries * pf->ent_hdr_size + 2;
+
+ p = buf;
+ memcpy(p, ip->name, 32);
+ set_short(p + 32, ip->flags);
+ set_short(p + 34, ip->version);
+ set_long(p + 36, unix_time_to_pilot_time(ip->createDate));
+ set_long(p + 40, unix_time_to_pilot_time(ip->modifyDate));
+ set_long(p + 44, unix_time_to_pilot_time(ip->backupDate));
+ set_long(p + 48, ip->modnum);
+ set_long(p + 52, pf->app_info_size ? offset : 0);
+ offset += pf->app_info_size;
+ set_long(p + 56, pf->sort_info_size ? offset : 0);
+ offset += pf->sort_info_size;
+ set_long(p + 60, ip->type);
+ set_long(p + 64, ip->creator);
+ set_long(p + 68, pf->unique_id_seed);
+ set_long(p + 72, pf->next_record_list_id);
+ set_short(p + 76, pf->num_entries);
+
+ if (fwrite(buf, PI_HDR_SIZE, 1, f) != 1)
+ goto bad;
+
+ for (i = 0, entp = pf->entries; i < pf->num_entries; i++, entp++) {
+ entp->offset = offset;
+
+ p = buf;
+ if (pf->resource_flag) {
+ set_long(p, entp->type);
+ set_short(p + 4, entp->resource_id);
+ set_long(p + 6, entp->offset);
+ } else {
+ set_long(p, entp->offset);
+ set_byte(p + 4, entp->attrs);
+ set_treble(p + 5, entp->uid);
+ }
+
+ if (fwrite(buf, (size_t) pf->ent_hdr_size, 1, f) != 1)
+ goto bad;
+
+ offset += entp->size;
+ }
+
+ /* This may just be packing */
+ fwrite("\0\0", 1, 2, f);
+
+ if (pf->app_info
+ && (fwrite(pf->app_info, 1,(size_t) pf->app_info_size, f) !=
+ (size_t) pf->app_info_size))
+ goto bad;
+
+ if (pf->sort_info
+ && (fwrite(pf->sort_info, 1, (size_t) pf->sort_info_size, f) !=
+ (size_t) pf->sort_info_size))
+ goto bad;
+
+
+ fwrite(pf->tmpbuf->data, pf->tmpbuf->used, 1, f);
+ fflush(f);
+
+ if (ferror(f) || feof(f))
+ goto bad;
+
+ fclose(f);
+ return 0;
+
+bad:
+ fclose(f);
+ return PI_ERR_FILE_ERROR;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_file_free
+ *
+ * Summary: Flush and clean the file handles used
+ *
+ * Parameters: file handle pi_file_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static
+void pi_file_free(pi_file_t *pf)
+{
+ ASSERT (pf != NULL);
+
+ if (pf->f != 0)
+ fclose(pf->f);
+
+ if (pf->app_info != NULL)
+ free(pf->app_info);
+
+ if (pf->sort_info != NULL)
+ free(pf->sort_info);
+
+ if (pf->entries != NULL)
+ free(pf->entries);
+
+ if (pf->file_name != NULL)
+ free(pf->file_name);
+
+ if (pf->rbuf != NULL)
+ free(pf->rbuf);
+
+ if (pf->tmpbuf != NULL)
+ pi_buffer_free(pf->tmpbuf);
+
+ /* in case caller forgets the struct has been freed... */
+ memset(pf, 0, sizeof(pi_file_t));
+
+ free(pf);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_file_set_rbuf_size
+ *
+ * Summary: set pi_file rbuf size
+ *
+ * Parameters: file handle pi_file_t*, rbuf size
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_file_set_rbuf_size(pi_file_t *pf, size_t size)
+{
+ size_t new_size;
+ void *rbuf;
+
+ if (size > (size_t)pf->rbuf_size) {
+ if (pf->rbuf_size == 0) {
+ new_size = size + 2048;
+ rbuf = malloc(new_size);
+ } else {
+ new_size = size + 2048;
+ rbuf = realloc(pf->rbuf, new_size);
+ }
+
+ if (rbuf == NULL)
+ return PI_ERR_GENERIC_MEMORY;
+
+ pf->rbuf_size = new_size;
+ pf->rbuf = rbuf;
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_file_append_entry
+ *
+ * Summary: Internal function to extend entry list if necessary,
+ * and return a pointer to the next available slot
+ *
+ * Parameters: None
+ *
+ * Returns: NULL on allocation error
+ *
+ ***********************************************************************/
+static pi_file_entry_t
+*pi_file_append_entry(pi_file_t *pf)
+{
+ int new_count;
+ size_t new_size;
+ struct pi_file_entry *new_entries;
+ struct pi_file_entry *entp;
+
+ if (pf->num_entries >= pf->num_entries_allocated) {
+ if (pf->num_entries_allocated == 0)
+ new_count = 100;
+ else
+ new_count = pf->num_entries_allocated * 3 / 2;
+ new_size = new_count * sizeof *pf->entries;
+
+ if (pf->entries == NULL)
+ new_entries = malloc(new_size);
+ else
+ new_entries = realloc(pf->entries, new_size);
+
+ if (new_entries == NULL)
+ return NULL;
+
+ pf->num_entries_allocated = new_count;
+ pf->entries = new_entries;
+ }
+
+ entp = &pf->entries[pf->num_entries++];
+ memset(entp, 0, sizeof *entp);
+ return entp;
+}
+
+static int
+pi_file_find_resource_by_type_id(const pi_file_t *pf,
+ unsigned long restype, int resid, int *resindex)
+{
+ int i;
+ struct pi_file_entry *entp;
+
+ if (!pf->resource_flag)
+ return PI_ERR_FILE_INVALID;
+
+ for (i = 0, entp = pf->entries; i < pf->num_entries; i++, entp++) {
+ if (entp->type == restype && entp->resource_id == resid) {
+ if (resindex)
+ *resindex = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-header.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-header.c
new file mode 100644
index 00000000..a4d19404
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/pi-header.c
@@ -0,0 +1,63 @@
+/*
+ * $Id: pi-header.c,v 1.25 2006/10/12 14:21:22 desrod Exp $
+ *
+ * pi-header.c: Splash for the version/etc.
+ *
+ * Copyright (c) 2000, David A. Desrosiers
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include "pi-version.h"
+#include "pi-header.h"
+
+void print_splash(const char *progname)
+{
+ char *patchlevel = "";
+
+ fprintf(stderr," DEPRECATED: The application is calling print_splash()\n");
+#ifdef PILOT_LINK_PATCH
+ patchlevel = PILOT_LINK_PATCH;
+#endif
+ printf(" .--------------------------------------------.\n"
+ " | (c) Copyright 1996-2006, pilot-link team |\n"
+ " | Join the pilot-link lists to help out. |\n"
+ " `--------------------------------------------'\n"
+ " This is %s, from pilot-link version %d.%d.%d%s\n\n"
+ " Build target..: %s\n"
+ " Build date....: %s %s\n\n", progname,
+ PILOT_LINK_VERSION, PILOT_LINK_MAJOR, PILOT_LINK_MINOR,
+ patchlevel, HOST_OS, __DATE__, __TIME__);
+
+ printf(" pilot-link %d.%d.%d%s is covered under the GPL/LGPL\n",
+ PILOT_LINK_VERSION, PILOT_LINK_MAJOR, PILOT_LINK_MINOR,
+ patchlevel);
+
+ printf(" See the file COPYING under docs for more info.\n\n"
+ " Please use --help for more detailed options.\n");
+
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/serial.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/serial.c
new file mode 100644
index 00000000..37d292a2
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/serial.c
@@ -0,0 +1,717 @@
+/*
+ * $Id: serial.c,v 1.72 2006/10/12 14:21:22 desrod Exp $
+ *
+ * serial.c: Interface layer to serial HotSync connections
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 2005, Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h> /* Needed for Redhat 6.x machines */
+#include <unistd.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-socket.h"
+#include "pi-serial.h"
+#include "pi-net.h"
+#include "pi-cmp.h"
+#include "pi-error.h"
+#include "pi-util.h"
+
+#ifdef OS2
+#include <sys/select.h>
+#endif
+
+/* Declare prototypes */
+static int pi_serial_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_serial_bind(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_serial_listen(pi_socket_t *ps, int backlog);
+static int pi_serial_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen);
+static int pi_serial_getsockopt(pi_socket_t *ps, int level,
+ int option_name, void *option_value,
+ size_t *option_len);
+static int pi_serial_setsockopt(pi_socket_t *ps, int level,
+ int option_name, const void *option_value,
+ size_t *option_len);
+static int pi_serial_close(pi_socket_t *ps);
+
+extern int pi_socket_init(pi_socket_t *ps);
+
+
+/* Protocol Functions */
+/***********************************************************************
+ *
+ * Function: pi_serial_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_serial_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ ASSERT (prot != NULL);
+
+ new_prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ if (new_prot != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+ new_prot->data = NULL;
+ }
+
+ return new_prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_serial_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT (prot != NULL);
+
+ if (prot != NULL)
+ free(prot);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_serial_protocol (pi_device_t *dev)
+{
+ pi_protocol_t *prot;
+ struct pi_serial_data *data;
+
+ ASSERT (dev != NULL);
+
+ prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ data = (struct pi_serial_data *)(dev->data);
+
+ if (prot != NULL) {
+ prot->level = PI_LEVEL_DEV;
+ prot->dup = pi_serial_protocol_dup;
+ prot->free = pi_serial_protocol_free;
+ prot->read = data->impl.read;
+ prot->write = data->impl.write;
+ prot->flush = data->impl.flush;
+ prot->getsockopt = pi_serial_getsockopt;
+ prot->setsockopt = pi_serial_setsockopt;
+ prot->data = NULL;
+ }
+
+ return prot;
+}
+
+
+/* Device Functions */
+/***********************************************************************
+ *
+ * Function: pi_serial_device_free
+ *
+ * Summary: frees an existing pi_device struct
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_serial_device_free (pi_device_t *dev)
+{
+ ASSERT (dev != NULL);
+
+ free(dev->data);
+ free(dev);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_device
+ *
+ * Summary: creates and inits pi_device struct instance
+ *
+ * Parameters: device type
+ *
+ * Returns: pi_device_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_device_t*
+pi_serial_device (int type)
+{
+ pi_device_t *dev;
+ struct pi_serial_data *data;
+
+ dev = (pi_device_t *) malloc(sizeof (pi_device_t));
+ if (dev == NULL)
+ return NULL;
+
+ data = (struct pi_serial_data *) malloc(sizeof (struct pi_serial_data));
+ if (data == NULL) {
+ free(dev);
+ return NULL;
+ }
+
+ dev->free = pi_serial_device_free;
+ dev->protocol = pi_serial_protocol;
+ dev->bind = pi_serial_bind;
+ dev->listen = pi_serial_listen;
+ dev->accept = pi_serial_accept;
+ dev->connect = pi_serial_connect;
+ dev->close = pi_serial_close;
+
+ switch (type) {
+ case PI_SERIAL_DEV:
+ pi_serial_impl_init (&data->impl);
+ break;
+ default:
+ pi_serial_impl_init (&data->impl);
+ break;
+ }
+
+ data->buf_size = 0;
+ data->rate = -1;
+ data->establishrate = -1;
+ data->establishhighrate = -1;
+ data->timeout = 0;
+ data->rx_bytes = 0;
+ data->rx_errors = 0;
+ data->tx_bytes = 0;
+ data->tx_errors = 0;
+
+ dev->data = data;
+
+ return dev;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_connect
+ *
+ * Summary: Connect socket to a given address
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_serial_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+ struct pi_sockaddr *pa = (struct pi_sockaddr *) addr;
+ int err;
+
+ if (ps->type == PI_SOCK_STREAM) {
+ if (ps->protocol == PI_PF_SYS) {
+ data->establishrate = data->rate = 57600;
+ } else {
+ if (data->establishrate == -1)
+ get_pilot_rate(&data->establishrate, &data->establishhighrate);
+
+ /* Mandatory CMP connection rate */
+ data->rate = 9600;
+ }
+ } else if (ps->type == PI_SOCK_RAW) {
+ /* Mandatory SysPkt connection rate */
+ data->establishrate = data->rate = 57600;
+ }
+
+ if ((err = data->impl.open(ps, pa, addrlen)) < 0)
+ return err; /* errno already set */
+
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ if (ps->type == PI_SOCK_STREAM) {
+ size_t size;
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if (cmp_tx_handshake(ps) < 0)
+ goto fail;
+
+ size = sizeof(data->rate);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_BAUD,
+ &data->rate, &size);
+
+ if ((err = data->impl.changebaud(ps)) < 0)
+ goto fail;
+ break;
+
+ case PI_CMD_NET:
+ if ((err = data->impl.changebaud(ps)) < 0)
+ goto fail;
+ break;
+
+ case PI_CMD_SYS:
+ if ((err = data->impl.changebaud(ps)) < 0)
+ goto fail;
+ break;
+ }
+ }
+ ps->state = PI_SOCK_CONN_INIT;
+ ps->command = 0;
+ return 0;
+
+fail:
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_bind
+ *
+ * Summary: Bind address to a local socket
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_serial_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+ struct pi_sockaddr *pa = (struct pi_sockaddr *) addr;
+ int err, count = 0;
+
+ if (ps->type == PI_SOCK_STREAM) {
+ if (data->establishrate == -1)
+ get_pilot_rate(&data->establishrate, &data->establishhighrate);
+
+ /* Mandatory CMP connection rate */
+ data->rate = 9600;
+ } else if (ps->type == PI_SOCK_RAW) {
+ /* Mandatory SysPkt connection rate */
+ data->establishrate = data->rate = 57600;
+ }
+
+begin:
+ if ((err = data->impl.open(ps, pa, addrlen)) < 0) {
+ int save_errno = errno;
+#ifdef MAXPATHLEN
+ char realport[MAXPATHLEN];
+#else
+ # ifdef PATH_MAX
+ char realport[PATH_MAX];
+ # else
+ char realport[4096];
+ # endif /* PATH_MAX */
+#endif /* MAXPATHLEN */
+
+ realpath(pa->pi_device, realport);
+ errno = save_errno;
+
+ if (errno == ENOENT) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ " The device %s does not exist..\n",
+ pa->pi_device));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ " Possible solution:\n\n\tmknod %s c "
+ "<major> <minor>\n\n", pa->pi_device));
+ } else if (errno == EACCES) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ " Please check the "
+ "permissions on %s..\n", realport));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ " Possible solution:\n\n\tchmod 0666 "
+ "%s\n\n", realport));
+ } else if (errno == ENODEV) {
+ while (count <= 5) {
+ if (isatty(fileno(stdout))) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "\r Port not connected,"
+ " sleeping for 2 seconds, "));
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "%d retries..",
+ 5-count));
+ }
+ sleep(2);
+ count++;
+ goto begin;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "\n\n Device not found on %s, \
+ Did you hit HotSync?\n\n", realport));
+ } else if (errno == EISDIR) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ " The port specified must"
+ " contain a device name, and %s was"
+ " a directory.\n"
+ " Please change that to reference a"
+ " real device, and try"
+ " again\n\n", pa->pi_device));
+ }
+ return err;
+ }
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_serial_listen
+ *
+ * Summary: Prepare for incoming connections
+ *
+ * Parameters: pi_socket*, backlog
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int pi_serial_listen(pi_socket_t *ps, int backlog)
+{
+ int result;
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+
+ /* ps->rate has been set by bind */
+ result = data->impl.changebaud(ps);
+ if (result == 0)
+ ps->state = PI_SOCK_LISTEN;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_serial_accept
+ *
+ * Summary: Accept an incoming connection
+ *
+ * Parameters: pi_socket*, sockaddr*
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_serial_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+ size_t size;
+ int err;
+
+ /* Wait for data */
+#ifdef linux
+ if (ps->accept_to) {
+ /* shield against losing the first packet */
+ int result = data->impl.poll(ps, 1000);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d, poll result: %d.\n", __FILE__, __LINE__, result));
+
+ if (result < 0) {
+ char buf[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ data->impl.write(ps, buf, sizeof (buf), 1000);
+ }
+ }
+#endif
+ if ((err = data->impl.poll(ps, ps->accept_to * 1000)) < 0)
+ goto fail;
+
+ data->timeout = ps->accept_to * 1000;
+
+ pi_socket_init(ps);
+ if (ps->type == PI_SOCK_STREAM) {
+ struct timeval tv;
+ unsigned char cmp_flags;
+
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if ((err = cmp_rx_handshake(ps, data->establishrate, data->establishhighrate)) < 0)
+ goto fail;
+
+ /* propagate the long packet format flag to both command and non-command stacks */
+ size = sizeof(cmp_flags);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_FLAGS, &cmp_flags, &size);
+ if (cmp_flags & CMP_FL_LONG_PACKET_SUPPORT) {
+ int use_long_format = 1;
+ size = sizeof(int);
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
+ &use_long_format, &size);
+ ps->command ^= 1;
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
+ &use_long_format, &size);
+ ps->command ^= 1;
+ }
+
+ /* We always reconfigure our port, no matter what */
+ size = sizeof(data->rate);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_BAUD, &data->rate, &size);
+ if ((err = data->impl.changebaud(ps)) < 0)
+ goto fail;
+
+ /* Palm device needs some time to reconfigure its port */
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+ select(0, 0, 0, 0, &tv);
+ break;
+
+ case PI_CMD_NET:
+ /* serial/network: make sure we don't split writes. set socket option
+ * on both the command and non-command instances of the protocol
+ */
+#ifdef MACOSX
+ /* We need to turn fragmentation OFF to improve Bluetooth performance
+ * but this code is also used by USB on Linux and Freebsd
+ * therefore, only compile it when running OS X
+ */
+ {
+ int split = 0;
+ size_t chunksize = 0;
+
+ size = sizeof (split);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_SPLIT_WRITES,
+ &split, &size);
+ size = sizeof (chunksize);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_WRITE_CHUNKSIZE,
+ &chunksize, &size);
+
+ ps->command ^= 1;
+ size = sizeof (split);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_SPLIT_WRITES,
+ &split, &size);
+ size = sizeof (chunksize);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_WRITE_CHUNKSIZE,
+ &chunksize, &size);
+ ps->command ^= 1;
+ }
+#endif
+ if ((err = net_rx_handshake(ps)) < 0)
+ goto fail;
+ break;
+ }
+ ps->dlprecord = 0;
+ }
+
+ data->timeout = 0;
+ ps->command = 0;
+ ps->state = PI_SOCK_CONN_ACCEPT;
+
+ return ps->sd;
+
+fail:
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_serial_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_RATE:
+ if (*option_len != sizeof (data->rate))
+ goto error;
+ memcpy (option_value, &data->rate, sizeof (data->rate));
+ break;
+
+ case PI_DEV_ESTRATE:
+ if (*option_len != sizeof (data->establishrate))
+ goto error;
+ memcpy (option_value, &data->establishrate, sizeof (data->establishrate));
+ break;
+
+ case PI_DEV_HIGHRATE:
+ if (*option_len != sizeof (data->establishhighrate))
+ goto error;
+ memcpy (option_value, &data->establishhighrate, sizeof (data->establishhighrate));
+ break;
+
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout))
+ goto error;
+ memcpy (option_value, &data->timeout, sizeof (data->timeout));
+ break;
+ }
+
+ return 0;
+
+error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_setsockopt
+ *
+ * Summary: set options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_serial_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+
+ /* FIXME: can't change stuff if already connected */
+ switch (option_name) {
+ case PI_DEV_ESTRATE:
+ if (*option_len != sizeof (data->establishrate))
+ goto error;
+ memcpy (&data->establishrate, option_value, sizeof (data->establishrate));
+ break;
+
+ case PI_DEV_HIGHRATE:
+ if (*option_len != sizeof (data->establishhighrate))
+ goto error;
+ memcpy (&data->establishhighrate, option_value, sizeof (data->establishhighrate));
+ break;
+
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout))
+ goto error;
+ memcpy (&data->timeout, option_value, sizeof (data->timeout));
+ break;
+ }
+
+ return 0;
+
+ error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_close
+ *
+ * Summary: Close a connection, destroy the socket
+ *
+ * Parameters: pi_socket*
+ *
+ * Returns: always 0 for success
+ *
+ ***********************************************************************/
+static int pi_serial_close(pi_socket_t *ps)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+
+ if (ps->sd) {
+ data->impl.close (ps);
+ ps->sd = 0;
+ }
+
+ if (ps->laddr) {
+ free(ps->laddr);
+ ps->laddr = NULL;
+ }
+
+ if (ps->raddr) {
+ free(ps->raddr);
+ ps->raddr = NULL;
+ }
+
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/slp.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/slp.c
new file mode 100644
index 00000000..c3063a3c
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/slp.c
@@ -0,0 +1,657 @@
+/*
+ * $Id: slp.c,v 1.56 2006/10/13 09:52:13 fpillet Exp $
+ *
+ * slp.c: Pilot SLP protocol
+ *
+ * (c) 1996, D. Jeff Dionne.
+ * Much of this code adapted from Brian J. Swetland <swetland@uiuc.edu>
+ * Additional work Copyright (c) 2005, Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-serial.h"
+#include "pi-slp.h"
+#include "pi-error.h"
+
+/* Declare function prototypes */
+static int slp_flush(pi_socket_t *ps, int flags);
+static int slp_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len);
+static int slp_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len);
+
+
+/***********************************************************************
+ *
+ * Function: slp_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+slp_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ struct pi_slp_data *data,
+ *new_data;
+
+ new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ new_data = (struct pi_slp_data *)malloc (sizeof (struct pi_slp_data));
+
+ if (new_prot != NULL && new_data != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+
+ data = (struct pi_slp_data *)prot->data;
+
+ new_data->dest = data->dest;
+ new_data->last_dest = data->last_dest;
+ new_data->src = data->src;
+ new_data->last_src = data->last_src;
+ new_data->type = data->type;
+ new_data->last_type = data->last_type;
+ new_data->txid = data->txid;
+ new_data->last_txid = data->last_txid;
+
+ new_prot->data = new_data;
+
+ } else if (new_prot != NULL) {
+ free(new_prot);
+ new_prot = NULL;
+ } else if (new_data != NULL) {
+ free(new_data);
+ new_data = NULL;
+ }
+
+ return new_prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: slp_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+slp_protocol_free (pi_protocol_t *prot)
+{
+ if (prot != NULL) {
+ if (prot->data != NULL)
+ free(prot->data);
+ free(prot);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: slp_protocol
+ *
+ * Summary: creates a pi_protocol struct instance
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_protocol_t*
+slp_protocol (void)
+{
+ pi_protocol_t *prot;
+ struct pi_slp_data *data;
+
+ prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ data = (struct pi_slp_data *)malloc (sizeof (struct pi_slp_data));
+
+ if (prot != NULL && data != NULL) {
+ prot->level = PI_LEVEL_SLP;
+ prot->dup = slp_protocol_dup;
+ prot->free = slp_protocol_free;
+ prot->read = slp_rx;
+ prot->write = slp_tx;
+ prot->flush = slp_flush;
+ prot->getsockopt = slp_getsockopt;
+ prot->setsockopt = slp_setsockopt;
+
+ data->dest = PI_SLP_SOCK_DLP;
+ data->last_dest = -1;
+ data->src = PI_SLP_SOCK_DLP;
+ data->last_src = -1;
+ data->type = PI_SLP_TYPE_PADP;
+ data->last_type = -1;
+ data->txid = 0xfe;
+ data->last_txid = 0xff;
+ prot->data = data;
+
+ } else if (prot != NULL) {
+ free(prot);
+ prot = NULL;
+ } else if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+
+ return prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: slp_tx
+ *
+ * Summary: Build and queue up an SLP packet to be transmitted
+ *
+ * Parameters: None
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+ssize_t
+slp_tx(pi_socket_t *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int bytes;
+ pi_protocol_t *prot,
+ *next;
+ struct pi_slp_data *data;
+ struct slp *slp;
+ unsigned char *slp_buf;
+ unsigned int i,
+ n;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SLP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_slp_data *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_SLP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ slp_buf = (unsigned char *) malloc (PI_SLP_HEADER_LEN +
+ PI_SLP_MTU + PI_SLP_FOOTER_LEN);
+ if (slp_buf == NULL)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+
+ slp = (struct slp *) slp_buf;
+
+ /* Header values */
+ slp->_be = 0xbe;
+ slp->_ef = 0xef;
+ slp->_ed = 0xed;
+ slp->dest = data->dest;
+ slp->src = data->src;
+ slp->type = data->type;
+ set_short(&slp->dlen, len);
+ slp->id_ = data->txid;
+
+ for (n = i = 0; i < 9; i++)
+ n += slp_buf[i];
+ slp->csum = 0xff & n;
+
+ /* Copy in the packet data */
+ memcpy (slp_buf + PI_SLP_HEADER_LEN, buf, len);
+
+ /* CRC value */
+ set_short(&slp_buf[PI_SLP_HEADER_LEN + len],
+ crc16(slp_buf, (int)(PI_SLP_HEADER_LEN + len)));
+
+ /* Write out the data */
+ bytes = next->write(ps, slp_buf,
+ PI_SLP_HEADER_LEN + len + PI_SLP_FOOTER_LEN, flags);
+
+ if (bytes >= 0) {
+ CHECK(PI_DBG_SLP, PI_DBG_LVL_INFO, slp_dump_header(slp_buf, 1));
+ CHECK(PI_DBG_SLP, PI_DBG_LVL_DEBUG, slp_dump(slp_buf));
+ }
+
+ free (slp_buf);
+
+ return bytes;
+}
+
+/* Sigh. SLP is a really broken protocol. It has no proper framing, so it
+ makes a proper "device driver" layer impossible. There ought to be a
+ layer below SLP that reads frames off the wire and passes them up.
+ Instead, all we can do is have the device driver give us bytes and SLP has
+ to keep a pile of status info while it builds frames for itself. So
+ here's the code that does that. */
+
+/***********************************************************************
+ *
+ * Function: slp_rx
+ *
+ * Summary: Accept SLP packets on the wire
+ *
+ * Parameters: None
+ *
+ * Returns: packet length or negative on error
+ *
+ ***********************************************************************/
+ssize_t
+slp_rx(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ int i,
+ computed_crc,
+ received_crc,
+ b1,
+ b2,
+ b3,
+ state,
+ expect = 0,
+ packet_len,
+ bytes;
+ unsigned char
+ header_checksum;
+ pi_protocol_t *prot,
+ *next;
+ pi_buffer_t *slp_buf;
+ struct pi_slp_data *data;
+
+ LOG((PI_DBG_SLP, PI_DBG_LVL_DEBUG, "SLP RX len=%d flags=0x%04x\n",
+ len, flags));
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SLP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_slp_data *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_SLP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ slp_buf = pi_buffer_new (PI_SLP_HEADER_LEN + PI_SLP_MTU + PI_SLP_FOOTER_LEN);
+ if (slp_buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ state = 0;
+ packet_len = 0;
+
+ for (;;) {
+ switch (state) {
+ case 0:
+ expect = 3;
+ state++;
+ break;
+
+ case 1:
+ b1 = slp_buf->data[PI_SLP_OFFSET_SIG1];
+ b2 = slp_buf->data[PI_SLP_OFFSET_SIG2];
+ b3 = slp_buf->data[PI_SLP_OFFSET_SIG3];
+ if (b1 == PI_SLP_SIG_BYTE1 &&
+ b2 == PI_SLP_SIG_BYTE2 &&
+ b3 == PI_SLP_SIG_BYTE3) {
+ state++;
+ expect = PI_SLP_HEADER_LEN - 3;
+ } else {
+ slp_buf->data[PI_SLP_OFFSET_SIG1] = slp_buf->data[PI_SLP_OFFSET_SIG2];
+ slp_buf->data[PI_SLP_OFFSET_SIG2] = slp_buf->data[PI_SLP_OFFSET_SIG3];
+ expect = 1;
+ slp_buf->used = 2;
+ LOG((PI_DBG_SLP, PI_DBG_LVL_WARN,
+ "SLP RX Unexpected signature"
+ " 0x%.2x 0x%.2x 0x%.2x\n",
+ b1, b2, b3));
+ }
+ break;
+
+ case 2:
+ /* Addition check sum for header */
+ for (header_checksum = i = 0; i < 9; i++)
+ header_checksum += slp_buf->data[i];
+
+ /* read in the whole SLP header. */
+ if (header_checksum == slp_buf->data[PI_SLP_OFFSET_SUM]) {
+ state++;
+ packet_len = get_short(&slp_buf->data[PI_SLP_OFFSET_SIZE]);
+ if (packet_len > (int)len) {
+ LOG((PI_DBG_SLP, PI_DBG_LVL_ERR,
+ "SLP RX Packet size exceed buffer\n"));
+ pi_buffer_free (slp_buf);
+ return pi_set_error(ps->sd, PI_ERR_PROT_BADPACKET);
+ }
+ expect = packet_len;
+ } else {
+ LOG((PI_DBG_SLP, PI_DBG_LVL_WARN,
+ "SLP RX Header checksum failed for header:\n"));
+ pi_dumpdata((const char *)slp_buf->data, PI_SLP_HEADER_LEN);
+ pi_buffer_free (slp_buf);
+ return 0;
+ }
+ break;
+
+ case 3:
+ state++;
+ expect = PI_SLP_FOOTER_LEN;
+ break;
+
+ case 4:
+ /* that should be the whole packet. */
+ computed_crc = crc16(slp_buf->data, PI_SLP_HEADER_LEN + packet_len);
+ received_crc = get_short(&slp_buf->data[PI_SLP_HEADER_LEN + packet_len]);
+ if (get_byte(&slp_buf->data[PI_SLP_OFFSET_TYPE]) == PI_SLP_TYPE_LOOP) {
+ /* Adjust because every tenth loopback
+ * packet has a bogus check sum */
+ if (computed_crc != received_crc)
+ computed_crc |= 0x00e0;
+ }
+ if (computed_crc != received_crc) {
+ LOG((PI_DBG_SLP, PI_DBG_LVL_ERR,
+ "SLP RX packet crc failed: "
+ "computed=0x%.4x received=0x%.4x\n",
+ computed_crc, received_crc));
+ pi_buffer_free (slp_buf);
+ return 0;
+ }
+
+ /* Track the info so getsockopt will work */
+ data->last_dest = get_byte(&slp_buf->data[PI_SLP_OFFSET_DEST]);
+ data->last_src = get_byte(&slp_buf->data[PI_SLP_OFFSET_SRC]);
+ data->last_type = get_byte(&slp_buf->data[PI_SLP_OFFSET_TYPE]);
+ data->last_txid = get_byte(&slp_buf->data[PI_SLP_OFFSET_TXID]);
+
+ CHECK(PI_DBG_SLP, PI_DBG_LVL_INFO, slp_dump_header(slp_buf->data, 0));
+ CHECK(PI_DBG_SLP, PI_DBG_LVL_DEBUG, slp_dump(slp_buf->data));
+
+ if (pi_buffer_append (buf, &slp_buf->data[PI_SLP_HEADER_LEN], packet_len) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+ pi_buffer_free (slp_buf);
+ return packet_len;
+
+ default:
+ break;
+ }
+
+ do {
+ bytes = next->read(ps, slp_buf, (size_t)expect, flags);
+ if (bytes < 0) {
+ LOG((PI_DBG_SLP, PI_DBG_LVL_ERR,
+ "SLP RX Read Error %d\n",
+ bytes));
+ pi_buffer_free (slp_buf);
+ return bytes;
+ }
+ expect -= bytes;
+ } while (expect > 0);
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: slp_flush
+ *
+ * Summary: Flush input and output buffers
+ *
+ * Parameters: pi_socket_t*, flags
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+slp_flush(pi_socket_t *ps, int flags)
+{
+ pi_protocol_t *prot,
+ *next;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SLP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_SLP);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ return next->flush(ps, flags);
+}
+
+/***********************************************************************
+ *
+ * Function: slp_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+slp_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ struct pi_slp_data *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SLP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (struct pi_slp_data *)prot->data;
+
+ switch (option_name) {
+ case PI_SLP_DEST:
+ if (*option_len < sizeof (data->dest))
+ goto error;
+ memcpy (option_value, &data->dest, sizeof (data->dest));
+ *option_len = sizeof (data->dest);
+ break;
+ case PI_SLP_LASTDEST:
+ if (*option_len < sizeof (data->dest))
+ goto error;
+ memcpy (option_value, &data->last_dest,
+ sizeof (data->last_dest));
+ *option_len = sizeof (data->last_dest);
+ break;
+ case PI_SLP_SRC:
+ if (*option_len < sizeof (data->src))
+ goto error;
+ memcpy (option_value, &data->src,
+ sizeof (data->src));
+ *option_len = sizeof (data->src);
+ break;
+ case PI_SLP_LASTSRC:
+ if (*option_len < sizeof (data->last_src))
+ goto error;
+ memcpy (option_value, &data->last_src,
+ sizeof (data->last_src));
+ *option_len = sizeof (data->last_src);
+ break;
+ case PI_SLP_TYPE:
+ if (*option_len < sizeof (data->type))
+ goto error;
+ memcpy (option_value, &data->type,
+ sizeof (data->type));
+ *option_len = sizeof (data->type);
+ break;
+ case PI_SLP_LASTTYPE:
+ if (*option_len < sizeof (data->last_type))
+ goto error;
+ memcpy (option_value, &data->last_type,
+ sizeof (data->last_type));
+ *option_len = sizeof (data->last_type);
+ break;
+ case PI_SLP_TXID:
+ if (*option_len < sizeof (data->txid))
+ goto error;
+ memcpy (option_value, &data->txid,
+ sizeof (data->txid));
+ *option_len = sizeof (data->txid);
+ break;
+ case PI_SLP_LASTTXID:
+ if (*option_len < sizeof (data->last_txid))
+ goto error;
+ memcpy (option_value, &data->last_txid,
+ sizeof (data->last_txid));
+ *option_len = sizeof (data->last_txid);
+ break;
+ }
+
+ return 0;
+
+ error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: slp_setsockopt
+ *
+ * Summary: set options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+slp_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ pi_protocol_t *prot;
+ struct pi_slp_data *data;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SLP);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+ data = (struct pi_slp_data *)prot->data;
+
+ switch (option_name) {
+ case PI_SLP_DEST:
+ if (*option_len != sizeof (data->dest))
+ goto error;
+ memcpy (&data->dest, option_value,
+ sizeof (data->dest));
+ *option_len = sizeof (data->dest);
+ break;
+ case PI_SLP_SRC:
+ if (*option_len != sizeof (data->src))
+ goto error;
+ memcpy (&data->src, option_value,
+ sizeof (data->src));
+ *option_len = sizeof (data->src);
+ break;
+ case PI_SLP_TYPE:
+ if (*option_len != sizeof (data->type))
+ goto error;
+ memcpy (&data->type, option_value,
+ sizeof (data->type));
+ *option_len = sizeof (data->type);
+ break;
+ case PI_SLP_TXID:
+ if (*option_len != sizeof (data->txid))
+ goto error;
+ memcpy (&data->txid, option_value,
+ sizeof (data->txid));
+ *option_len = sizeof (data->txid);
+ break;
+ }
+
+ return 0;
+
+ error:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: slp_dump_header
+ *
+ * Summary: Dump the contents of the SPL frame header
+ *
+ * Parameters: char* to data buffer, RXTX flag
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+slp_dump_header(const unsigned char *data, int rxtx)
+{
+ LOG((PI_DBG_SLP, PI_DBG_LVL_NONE,
+ "SLP %s %d->%d type=%d txid=0x%.2x len=0x%.4x checksum=0x%.2x\n",
+ rxtx ? "TX" : "RX",
+ get_byte(&data[PI_SLP_OFFSET_DEST]),
+ get_byte(&data[PI_SLP_OFFSET_SRC]),
+ get_byte(&data[PI_SLP_OFFSET_TYPE]),
+ get_byte(&data[PI_SLP_OFFSET_TXID]),
+ get_short(&data[PI_SLP_OFFSET_SIZE]),
+ get_byte(&data[PI_SLP_OFFSET_SUM])));
+}
+
+
+/***********************************************************************
+ *
+ * Function: slp_dump
+ *
+ * Summary: Dump the contents of the SPL frame
+ *
+ * Parameters: char* to data buffer
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+slp_dump(const unsigned char *data)
+{
+ pi_dumpdata((char *)&data[PI_SLP_HEADER_LEN], get_short(&data[PI_SLP_OFFSET_SIZE]));
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/socket.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/socket.c
new file mode 100644
index 00000000..2f877448
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/socket.c
@@ -0,0 +1,1694 @@
+/*
+ * $Id: socket.c,v 1.118 2006/11/07 21:13:24 adridg Exp $
+ *
+ * socket.c: Berkeley sockets style interface to Pilot
+ *
+ * Copyright (c) 1996, D. Jeff Dionne.
+ * Copyright (c) 1997-1999, Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 2000-2001, JP Rosevear
+ * Copyright (c) 2004-2005, Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "pi-source.h"
+#include "pi-serial.h"
+#ifdef HAVE_USB
+#include "pi-usb.h"
+#endif
+#include "pi-bluetooth.h"
+#include "pi-inet.h"
+#include "pi-slp.h"
+#include "pi-sys.h"
+#include "pi-padp.h"
+#include "pi-cmp.h"
+#include "pi-net.h"
+#include "pi-dlp.h"
+#include "pi-syspkt.h"
+#include "pi-debug.h"
+#include "pi-error.h"
+#include "pi-threadsafe.h"
+
+/* Declare function prototypes */
+static pi_socket_list_t *ps_list_append (pi_socket_list_t *list,
+ pi_socket_t *ps);
+static pi_socket_t *ps_list_find (pi_socket_list_t *list,
+ int pi_sd);
+static pi_socket_list_t *ps_list_remove (pi_socket_list_t *list,
+ int pi_sd);
+static pi_socket_list_t *ps_list_copy (pi_socket_list_t *list);
+static void ps_list_free (pi_socket_list_t *list);
+
+static void protocol_queue_add (pi_socket_t *ps, pi_protocol_t *prot);
+static void protocol_cmd_queue_add (pi_socket_t *ps, pi_protocol_t *prot);
+static pi_protocol_t *protocol_queue_find (pi_socket_t *ps, int level);
+static pi_protocol_t *protocol_queue_find_next (pi_socket_t *ps, int level);
+
+int pi_socket_init(pi_socket_t *ps);
+
+static int is_connected (pi_socket_t *ps);
+static int is_listener (pi_socket_t *ps);
+
+/* GLOBALS */
+static PI_MUTEX_DEFINE(psl_mutex);
+static pi_socket_list_t *psl = NULL;
+
+static PI_MUTEX_DEFINE(watch_list_mutex);
+static pi_socket_list_t *watch_list = NULL;
+
+/* Automated tickling interval */
+static unsigned int interval = 0;
+
+/* Indicates that the exit function has already been installed. Made non-static
+ * so that library users can choose to not have an exit function installed */
+int pi_sock_installedexit = 0;
+
+/* Linked List Code */
+/***********************************************************************
+ *
+ * Function: ps_list_dump
+ *
+ * Summary: internal debugging function
+ *
+ * Parameters: pi_socket_list_t *
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+#if 0
+static void
+ps_list_dump (pi_socket_list_t *list)
+{
+ fprintf(stderr, "* Dumping pi_socket_list @ %p:\n",(void*)list);
+ while (list != NULL) {
+ fprintf(stderr," %p: ps=%p, pi_sd=%d\n", (void*)list, (void*)list->ps, list->ps->sd);
+ list = list->next;
+ }
+}
+#endif
+
+/***********************************************************************
+ *
+ * Function: ps_list_append
+ *
+ * Summary: creates and appends a new pi_socket_list element to
+ * the (possibly empty) pi_socket_list and fills in the
+ * pi_socket_t* member to point to the given pi_socket.
+ *
+ * Parameters: pi_socket_list_t*, pi_socket_t*
+ *
+ * Returns: pi_socket_list_t*, or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_socket_list_t *
+ps_list_append (pi_socket_list_t *list, pi_socket_t *ps)
+{
+ pi_socket_list_t *elem, *new_elem;
+
+ ASSERT (ps != NULL);
+
+ new_elem = (pi_socket_list_t *) malloc (sizeof(pi_socket_list_t));
+ if (new_elem == NULL)
+ return list;
+
+ new_elem->ps = ps;
+ new_elem->next = NULL;
+
+ if (list == NULL)
+ return new_elem;
+
+ elem = list;
+ while (elem->next != NULL)
+ elem = elem->next;
+ elem->next = new_elem;
+
+ return list;
+}
+
+
+/***********************************************************************
+ *
+ * Function: ps_list_find
+ *
+ * Summary: traverse a (possibly empty) pi_socket_list and find
+ * the first list element whose pi_socket_t* member points
+ * to a pi_socket matching the given socket descriptor
+ *
+ * Parameters: pi_socket_list_t *, socket descriptor
+ *
+ * Returns: pi_socket_t *, or NULL if no match
+ *
+ * NOTE: ps_list_find returns a pointer which points directly to
+ * the socket (pi_socket_t *) whereas ps_find_elem returns a
+ * pointer to the list element (pi_socket_list_t *) which
+ * _contains_ a pointer to the socket
+ *
+ ***********************************************************************/
+static pi_socket_t *
+ps_list_find (pi_socket_list_t *list, int pi_sd)
+{
+ pi_socket_list_t *elem;
+
+ for (elem = list; elem != NULL; elem = elem->next)
+ if (elem->ps != NULL && elem->ps->sd == pi_sd)
+ return elem->ps;
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * Function: ps_list_remove
+ *
+ * Summary: remove first pi_socket_list element pointing to a pi_socket
+ * member matching socket descriptor
+ *
+ * Parameters: pi_socket_list_t *, socket descriptor
+ *
+ * Returns: the (possibly NULL) head pi_socket_list_t *
+ *
+ * NOTE: only the pi_socket_list element is freed,
+ * _not_ the pi_socket. Consequently, this function
+ * makes the (risky) assumption that the pi_socket will
+ * be freed elsewhere.
+ *
+ ***********************************************************************/
+static pi_socket_list_t *
+ps_list_remove (pi_socket_list_t *list, int pi_sd)
+{
+ pi_socket_list_t *elem,
+ *new_list = list,
+ *prev_elem = NULL;
+
+ for (elem = list; elem != NULL; elem = elem->next) {
+ if (elem->ps == NULL)
+ continue;
+ else if (elem->ps->sd == pi_sd) {
+ if (prev_elem == NULL)
+ new_list = elem->next;
+ else
+ prev_elem->next = elem->next;
+ free(elem);
+ break;
+ }
+ prev_elem = elem;
+ }
+
+ return new_list;
+}
+
+
+/***********************************************************************
+ *
+ * Function: ps_list_copy
+ *
+ * Summary: copy pi_socket_list
+ *
+ * Parameters: pi_socket_list_t *
+ *
+ * Returns: pi_socket_list_t* (new list head)
+ *
+ * NOTE: pi_list_copy does _not_ copy the pi_socket member, it
+ * copies only the list elements
+ *
+ ***********************************************************************/
+static pi_socket_list_t *
+ps_list_copy (pi_socket_list_t *list)
+{
+ pi_socket_list_t *l, *new_list = NULL;
+
+ for (l = list; l != NULL; l = l->next)
+ new_list = ps_list_append (new_list, l->ps);
+
+ return new_list;
+}
+
+
+/***********************************************************************
+ *
+ * Function: ps_list_free
+ *
+ * Summary: free pi_socket_list elements
+ *
+ * Parameters: pi_socket_list_t *
+ *
+ * Returns: void
+ *
+ * NOTE: only the pi_socket_list elements are freed,
+ * _not_ the pi_sockets. Consequently, this function
+ * makes the (risky) assumption that the pi_sockets will
+ * be freed elsewhere.
+ *
+ ***********************************************************************/
+static void
+ps_list_free (pi_socket_list_t *list)
+{
+ pi_socket_list_t *l, *next;
+
+ if (list == NULL)
+ return;
+
+ l = list;
+ do {
+ next = l->next;
+ free(l);
+ l = next;
+ } while (l != NULL);
+}
+
+/* Protocol Queue */
+/***********************************************************************
+ *
+ * Function: protocol_queue_add
+ *
+ * Summary: adds protocol queue to pi_socket
+ *
+ * Parameters: pi_socket_t*, pi_protocol_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+protocol_queue_add (pi_socket_t *ps, pi_protocol_t *prot)
+{
+ ps->protocol_queue = realloc(ps->protocol_queue,
+ (sizeof(pi_protocol_t *)) * (ps->queue_len + 1));
+ if (ps->protocol_queue != NULL) {
+ ps->protocol_queue[ps->queue_len] = prot;
+ ps->queue_len++;
+ } else {
+ errno = ENOMEM;
+ ps->queue_len = 0;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: cmd_queue_add
+ *
+ * Summary: adds command queue to pi_socket
+ *
+ * Parameters: pi_socket_t*, pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+protocol_cmd_queue_add (pi_socket_t *ps, pi_protocol_t *prot)
+{
+ ps->cmd_queue = realloc(ps->cmd_queue,
+ (sizeof(pi_protocol_t *)) * (ps->cmd_len + 1));
+ if (ps->cmd_queue != NULL) {
+ ps->cmd_queue[ps->cmd_len] = prot;
+ ps->cmd_len++;
+ } else {
+ errno = ENOMEM;
+ ps->cmd_len = 0;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: protocol_queue_find
+ *
+ * Summary: find queue entry
+ *
+ * Parameters: pi_socket_t*, level
+ *
+ * Returns: pi_protocol*, or NULL if queue entry not found
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+protocol_queue_find (pi_socket_t *ps, int level)
+{
+ int i;
+
+ if (ps->command) {
+ for (i = 0; i < ps->cmd_len; i++) {
+ if (ps->cmd_queue[i]->level == level)
+ return ps->cmd_queue[i];
+ }
+ } else {
+ for (i = 0; i < ps->queue_len; i++) {
+ if (ps->protocol_queue[i]->level == level)
+ return ps->protocol_queue[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * Function: protocol_queue_find_next
+ *
+ * Summary: find next queue entry
+ *
+ * Parameters: pi_socket*, level
+ *
+ * Returns: pi_protocol_t* or NULL if next queue entry not found
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+protocol_queue_find_next (pi_socket_t *ps, int level)
+{
+ int i;
+
+ if (ps->command && ps->cmd_len == 0)
+ return NULL;
+
+ if (!ps->command && ps->queue_len == 0)
+ return NULL;
+
+ if (ps->command && level == 0)
+ return ps->cmd_queue[0];
+
+ if (!ps->command && level == 0)
+ return ps->protocol_queue[0];
+
+ if (ps->command) {
+ for (i = 0; i < ps->cmd_len - 1; i++) {
+ if (ps->cmd_queue[i]->level == level)
+ return ps->cmd_queue[i + 1];
+ }
+ } else {
+ for (i = 0; i < ps->queue_len - 1; i++) {
+ if (ps->protocol_queue[i]->level == level)
+ return ps->protocol_queue[i + 1];
+ }
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * Function: protocol_queue_build
+ *
+ * Summary: build protocol queue
+ *
+ * Parameters: pi_socket_t*, autodetect
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+protocol_queue_build (pi_socket_t *ps, int autodetect)
+{
+ int protocol,
+ result;
+ pi_protocol_t
+ *dev_prot,
+ *dev_cmd_prot;
+
+ LOG((PI_DBG_SOCK,PI_DBG_LVL_DEBUG, "SOCK fd=%d auto=%d\n",ps->sd,autodetect));
+
+ /* The device protocol */
+ dev_prot = ps->device->protocol (ps->device);
+ dev_cmd_prot = ps->device->protocol (ps->device);
+
+ /* When opening the device in RAW mode, we stay low-level */
+ if (ps->type == PI_SOCK_RAW) {
+ LOG((PI_DBG_SOCK,PI_DBG_LVL_DEBUG, "RAW mode, no protocol\n",ps->sd,autodetect));
+ protocol_queue_add (ps, dev_prot);
+ protocol_cmd_queue_add (ps, dev_cmd_prot);
+ return;
+ }
+
+ protocol = ps->protocol;
+
+ LOG((PI_DBG_SOCK,PI_DBG_LVL_DEBUG, "SOCK proto=%s (%d)\n",
+ protocol == PI_PF_DEV ? "DEV" :
+ protocol == PI_PF_SLP ? "SLP" :
+ protocol == PI_PF_SYS ? "SYS" :
+ protocol == PI_PF_PADP? "PADP" :
+ protocol == PI_PF_NET ? "NET" :
+ protocol == PI_PF_DLP ? "DLP" :
+ "unknown", protocol));
+
+ if (protocol == PI_PF_DLP && autodetect) {
+ int skipped_bytes = 0,
+ bytes_to_skip;
+ pi_buffer_t
+ *detect_buf = pi_buffer_new(64);
+
+ for (;;) {
+ /* try to peek a header start from the input sent by the device */
+ result = dev_prot->read (ps, detect_buf, 10, PI_MSG_PEEK);
+ if (result < 0)
+ break;
+ if (result != 10) {
+ pi_buffer_clear(detect_buf);
+ continue;
+ }
+
+ bytes_to_skip = 1;
+
+ /* detect a valid PADP header packet */
+ if (detect_buf->data[0] == PI_SLP_SIG_BYTE1 &&
+ detect_buf->data[1] == PI_SLP_SIG_BYTE2 &&
+ detect_buf->data[2] == PI_SLP_SIG_BYTE3)
+ {
+ /* compute the checksum */
+ int i;
+ unsigned char header_checksum;
+ for (header_checksum = i = 0; i < 9; i++)
+ header_checksum += detect_buf->data[i];
+
+ if (header_checksum == detect_buf->data[9]) { /* sum */
+ if (detect_buf->data[3] == PI_SLP_SOCK_DLP && /* src */
+ detect_buf->data[4] == PI_SLP_SOCK_DLP && /* dest */
+ detect_buf->data[5] == PI_SLP_TYPE_PADP && /* type */
+ detect_buf->data[8] == 0xff) /* txid */
+ {
+ protocol = PI_PF_PADP;
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_INFO,
+ "\nusing PADP/SLP protocol (skipped %d bytes)\n",
+ skipped_bytes));
+ break;
+ }
+ else {
+ /* valid but not what we're looking for, skip it altogether */
+ bytes_to_skip = 10;
+ }
+ } else {
+ /* skip the SLP SIG bytes */
+ bytes_to_skip = 3;
+ }
+ }
+
+ /* detect NET header packets */
+ else if (detect_buf->data[0] == 0x01 && /* NET packet */
+ detect_buf->data[2] == 0x00 && /* length byte 0 */
+ detect_buf->data[3] == 0x00 && /* length byte 1 */
+ detect_buf->data[4] == 0x00 && /* length byte 2 */
+ detect_buf->data[5] > 0 && /* length byte 3 */
+ detect_buf->data[6] == 0x90) /* PI_NET_SIG_BYTE1 */
+ {
+ protocol = PI_PF_NET;
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_INFO,
+ "\nusing NET protocol (skipped %d bytes)\n",
+ skipped_bytes));
+ break;
+ }
+
+ /* detect NET packet for cases where we lost the first 6 bytes
+ * (this unfortunately happens on Linux with unixserial, and the
+ * correct way to cope with this is to recognize the second
+ * part of the NET handshake packet)
+ */
+ else if (detect_buf->data[0] == 0x90 && /* PI_NET_SIG_BYTE1 */
+ detect_buf->data[1] == 0x01 &&
+ detect_buf->data[2] == 0x00 &&
+ detect_buf->data[3] == 0x00 &&
+ detect_buf->data[4] == 0x00 &&
+ detect_buf->data[5] == 0x00 &&
+ detect_buf->data[6] == 0x00 &&
+ detect_buf->data[7] == 0x00 &&
+ detect_buf->data[8] == 0x00 &&
+ detect_buf->data[9] == 0x20)
+ {
+ protocol = PI_PF_NET;
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_INFO,
+ "\nusing NET protocol (skipped %d bytes)\n",
+ skipped_bytes));
+ break;
+ }
+
+ /* eliminate one byte from the input, trying to frame a proper header */
+ result = dev_prot->read (ps, detect_buf, bytes_to_skip, 0);
+ if (result < 0)
+ break;
+ skipped_bytes += bytes_to_skip;
+ pi_buffer_clear(detect_buf);
+ }
+
+ pi_buffer_free(detect_buf);
+
+ if (result < 0) {
+ /* if there was an error (i.e. disconnect), temporarily fallback
+ * on PADP protocol. In further releases, we should really make
+ * this function return an error if there was a problem. -- fpillet
+ */
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_DEBUG,
+ "Error: last read returned %d; switching to PADP by default\n",
+ result));
+ protocol = PI_PF_PADP;
+ }
+
+ } else if (protocol == PI_PF_DLP) {
+ protocol = PI_PF_PADP;
+ }
+
+ /* The connected protocol queue */
+ switch (protocol) {
+ case PI_PF_PADP:
+ protocol_queue_add (ps, padp_protocol ());
+ case PI_PF_SLP:
+ protocol_queue_add (ps, slp_protocol ());
+ break;
+ case PI_PF_NET:
+ protocol_queue_add (ps, net_protocol ());
+ break;
+ case PI_PF_SYS:
+ protocol_queue_add (ps, sys_protocol ());
+ protocol_queue_add (ps, slp_protocol ());
+ break;
+ }
+
+ /* The command protocol queue */
+ switch (protocol) {
+ case PI_PF_PADP:
+ case PI_PF_SLP:
+ protocol_cmd_queue_add (ps, cmp_protocol ());
+ protocol_cmd_queue_add (ps, padp_protocol ());
+ protocol_cmd_queue_add (ps, slp_protocol ());
+ ps->cmd = PI_CMD_CMP;
+ break;
+ case PI_PF_NET:
+ protocol_cmd_queue_add (ps, net_protocol ());
+ ps->cmd = PI_CMD_NET;
+ break;
+ case PI_PF_SYS:
+ ps->cmd = PI_CMD_SYS;
+ break;
+ default:
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_ERR, "invalid protocol (%d)", protocol));
+ break;
+ }
+
+ protocol_queue_add (ps, dev_prot);
+ protocol_cmd_queue_add (ps, dev_cmd_prot);
+}
+
+
+/***********************************************************************
+ *
+ * Function: protocol_queue_destroy
+ *
+ * Summary: destroy protocol queue
+ *
+ * Parameters: pi_socket_t *
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+protocol_queue_destroy (pi_socket_t *ps)
+{
+ int i;
+ for (i = 0; i < ps->queue_len; i++)
+ ps->protocol_queue[i]->free(ps->protocol_queue[i]);
+ for (i = 0; i < ps->cmd_len; i++)
+ ps->cmd_queue[i]->free(ps->cmd_queue[i]);
+
+ if (ps->queue_len > 0)
+ free(ps->protocol_queue);
+ if (ps->cmd_len > 0)
+ free(ps->cmd_queue);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_protocol
+ *
+ * Summary: destroy protocol queue
+ *
+ * Parameters: socket descriptor, level
+ *
+ * Returns: pi_protocol_t*
+ *
+ ***********************************************************************/
+pi_protocol_t *
+pi_protocol (int pi_sd, int level)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return NULL;
+ }
+
+ return protocol_queue_find(ps, level);
+}
+
+pi_protocol_t *
+pi_protocol_next (int pi_sd, int level)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return NULL;
+ }
+
+ return protocol_queue_find_next(ps, level);
+}
+
+
+/* Environment Code */
+/***********************************************************************
+ *
+ * Function: env_check
+ *
+ * Summary: configures Pilot-Link debug environment
+ *
+ * Parameters: void
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+env_dbgcheck (void)
+{
+ if (getenv("PILOT_DEBUG")) {
+ int types = 0,
+ done;
+ char *debug,
+ *b,
+ *e;
+
+ debug = strdup(getenv("PILOT_DEBUG"));
+
+ b = debug;
+ done = 0;
+ while (!done) {
+ e = strchr(b, ' ');
+ if (e)
+ *e = '\0';
+ else
+ done = 1;
+
+ if (!strcmp(b, "SYS"))
+ types |= PI_DBG_SYS;
+ else if (!strcmp(b, "DEV"))
+ types |= PI_DBG_DEV;
+ else if (!strcmp(b, "SLP"))
+ types |= PI_DBG_SLP;
+ else if (!strcmp(b, "PADP"))
+ types |= PI_DBG_PADP;
+ else if (!strcmp(b, "DLP"))
+ types |= PI_DBG_DLP;
+ else if (!strcmp(b, "NET"))
+ types |= PI_DBG_NET;
+ else if (!strcmp(b, "CMP"))
+ types |= PI_DBG_CMP;
+ else if (!strcmp(b, "SOCK"))
+ types |= PI_DBG_SOCK;
+ else if (!strcmp(b, "API"))
+ types |= PI_DBG_API;
+ else if (!strcmp(b, "USER"))
+ types |= PI_DBG_USER;
+ else if (!strcmp(b, "ALL"))
+ types |= PI_DBG_ALL;
+ e++;
+ b = e;
+ }
+ pi_debug_set_types(types);
+
+ free(debug);
+ }
+
+ /* PILOT Debug Level */
+ if (getenv("PILOT_DEBUG_LEVEL")) {
+ int level = 0;
+ const char *debug;
+
+
+ debug = getenv("PILOT_DEBUG_LEVEL");
+ if (!strcmp(debug, "NONE"))
+ level |= PI_DBG_LVL_NONE;
+ else if (!strcmp(debug, "ERR"))
+ level |= PI_DBG_LVL_ERR;
+ else if (!strcmp(debug, "WARN"))
+ level |= PI_DBG_LVL_WARN;
+ else if (!strcmp(debug, "INFO"))
+ level |= PI_DBG_LVL_INFO;
+ else if (!strcmp(debug, "DEBUG"))
+ level |= PI_DBG_LVL_DEBUG;
+
+ pi_debug_set_level (level);
+ }
+
+ /* log file name */
+ if (getenv("PILOT_LOG") && atoi(getenv("PILOT_LOG"))) {
+ const char *logfile;
+
+ logfile = getenv("PILOT_LOGFILE");
+ if (logfile == NULL)
+ pi_debug_set_file("pilot-link.debug");
+ else
+ pi_debug_set_file(logfile);
+ }
+}
+
+/* Util functions */
+/***********************************************************************
+ *
+ * Function: is_connected
+ *
+ * Summary: interrogate socket connection state
+ *
+ * Parameters: pi_socket*
+ *
+ * Returns: 1 if socket is connected, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+is_connected (pi_socket_t *ps)
+{
+ return (ps->state == PI_SOCK_CONN_INIT || ps->state == PI_SOCK_CONN_ACCEPT) ? 1 : 0;
+}
+
+/***********************************************************************
+ *
+ * Function: is_listener
+ *
+ * Summary: interrogate socket listener state
+ *
+ * Parameters: pi_socket*
+ *
+ * Returns: 1 if socket is listener, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+is_listener (pi_socket_t *ps)
+{
+ return (ps->state == PI_SOCK_LISTEN) ? 1 : 0;
+}
+
+/* Alarm Handling Code */
+static RETSIGTYPE
+onalarm(int signo)
+{
+ pi_socket_list_t *l;
+
+ signal(signo, onalarm);
+
+ pi_mutex_lock(&watch_list_mutex);
+
+ for (l = watch_list; l != NULL; l = l->next) {
+ pi_socket_t *ps = l->ps;
+
+ if (!is_connected(ps))
+ continue;
+
+ if (pi_tickle(ps->sd) < 0) {
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_INFO,
+ "SOCKET Socket %d is busy during tickle\n",
+ ps->sd));
+ alarm(1);
+ } else {
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_INFO,
+ "SOCKET Tickling socket %d\n", ps->sd));
+ alarm(interval);
+ }
+ }
+
+ pi_mutex_unlock(&watch_list_mutex);
+}
+
+/* Exit Handling Code */
+/***********************************************************************
+ *
+ * Function: onexit
+ *
+ * Summary: this function closes and destroys all pi_sockets and
+ * frees the global pi_socket_list
+ *
+ * Parameters: void
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+onexit(void)
+{
+ pi_socket_list_t *l,
+ *list;
+
+ pi_mutex_lock(&psl_mutex);
+ list = ps_list_copy (psl);
+ pi_mutex_unlock(&psl_mutex);
+
+ for (l = list; l != NULL; l = l->next)
+ pi_close(l->ps->sd);
+
+ ps_list_free (list);
+}
+
+
+/***********************************************************************
+ *
+ * Function: installexit
+ *
+ * Summary: install exit function using atexit()
+ *
+ * Parameters: void
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+installexit(void)
+{
+ if (!pi_sock_installedexit) {
+ atexit(onexit);
+ pi_sock_installedexit = 1;
+ }
+}
+
+int
+pi_socket(int domain, int type, int protocol)
+{
+ pi_socket_t *ps;
+ pi_socket_list_t *list;
+
+ env_dbgcheck ();
+
+ if (protocol == 0) {
+ if (type == PI_SOCK_STREAM)
+ protocol = PI_PF_DLP;
+ else if (type == PI_SOCK_RAW)
+ protocol = PI_PF_DEV;
+ }
+
+ ps = calloc(1, sizeof(pi_socket_t));
+ if (ps == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Create unique socket descriptor */
+ if ((ps->sd = open(NULL_DEVICE, O_RDWR)) == -1) {
+ int err = errno; /* Save errno of open */
+
+ free(ps);
+ errno = err;
+ return -1;
+ }
+
+ /* Initialize the rest of the fields (calloc zeroes out
+ all the fields we don't touch) */
+ ps->type = type;
+ ps->protocol = protocol;
+ ps->state = PI_SOCK_CLOSE;
+ ps->honor_rx_to = 1;
+ ps->command = 1;
+
+ /* post the new socket to the list */
+ list = pi_socket_recognize(ps);
+ if (list == NULL) {
+ close (ps->sd);
+ free(ps);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ installexit();
+ return ps->sd;
+}
+
+int
+pi_socket_setsd(pi_socket_t *ps, int pi_sd)
+{
+#ifdef HAVE_DUP2
+ ps->sd = dup2(pi_sd, ps->sd);
+#else
+ close(ps->sd);
+ #ifdef F_DUPFD
+ ps->sd = fcntl(pi_sd, F_DUPFD, ps->sd);
+ #else
+ ps->sd = dup(pi_sd);
+ #endif
+#endif
+ if (ps->sd == -1)
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ if (ps->sd != pi_sd)
+ close(pi_sd);
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_socket_init
+ *
+ * Summary: inits the pi_socket
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+int
+pi_socket_init(pi_socket_t *ps)
+{
+ protocol_queue_build (ps, 1);
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_socket_recognize
+ *
+ * Summary: appends the pi_socket to global list
+ *
+ * Parameters: pi_socket*
+ *
+ * Returns: pi_socket_list_t *
+ *
+ ***********************************************************************/
+pi_socket_list_t *
+pi_socket_recognize(pi_socket_t *ps)
+{
+ pi_mutex_lock(&psl_mutex);
+ psl = ps_list_append(psl, ps);
+ pi_mutex_unlock(&psl_mutex);
+ return psl;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_devsocket (static)
+ *
+ * Summary: Looks up a socket and creates a new device
+ * FIXME: Decide whether or not to create the socket here
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static pi_socket_t *
+pi_devsocket(int pi_sd, const char *port, struct pi_sockaddr *addr)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return NULL;
+ }
+
+ if (port == NULL && (port = getenv("PILOTPORT")) == NULL) {
+ errno = ENXIO;
+ return NULL;
+ }
+
+ /* Create the device and sockaddr */
+ addr->pi_family = PI_AF_PILOT;
+ if (!strncmp (port, "serial:", 7)) {
+ strncpy(addr->pi_device, port + 7, sizeof(addr->pi_device));
+ ps->device = pi_serial_device (PI_SERIAL_DEV);
+#ifdef HAVE_USB
+ } else if (!strncmp (port, "usb:", 4)) {
+ strncpy(addr->pi_device, port + 4, sizeof(addr->pi_device));
+ ps->device = pi_usb_device (PI_USB_DEV);
+#endif
+ } else if (!strncmp (port, "net:", 4)) {
+ strncpy(addr->pi_device, port + 4, sizeof(addr->pi_device));
+ ps->device = pi_inet_device (PI_NET_DEV);
+#ifdef HAVE_BLUEZ
+ } else if (!strncmp (port, "bluetooth:", 10) || !strncmp (port, "bt:", 3)) {
+ strncpy(addr->pi_device, strchr(port, ':') + 1, sizeof(addr->pi_device));
+ ps->device = pi_bluetooth_device (PI_BLUETOOTH_DEV);
+#endif
+ } else {
+ /* No prefix assumed to be serial: (for compatibility) */
+ strncpy(addr->pi_device, port, sizeof(addr->pi_device));
+ ps->device = pi_serial_device (PI_SERIAL_DEV);
+ }
+
+ return ps;
+}
+
+int
+pi_connect(int pi_sd, const char *port)
+{
+ pi_socket_t *ps;
+ struct pi_sockaddr addr;
+ int result;
+
+ ps = pi_devsocket(pi_sd, port, &addr);
+ if (!ps)
+ return PI_ERR_SOCK_INVALID;
+
+ /* Build the protocol queue */
+ protocol_queue_build (ps, 0);
+
+ result = ps->device->connect (ps, (struct sockaddr *)&addr, sizeof(addr));
+ if (result < 0)
+ pi_close(pi_sd);
+
+ return result;
+}
+
+int
+pi_bind(int pi_sd, const char *port)
+{
+ int bind_return;
+ pi_socket_t *ps;
+ struct pi_sockaddr addr;
+
+ ps = pi_devsocket(pi_sd, port, &addr);
+ if (!ps)
+ return PI_ERR_SOCK_INVALID;
+
+ bind_return =
+ ps->device->bind (ps, (struct sockaddr *)&addr, sizeof(addr));
+ if (bind_return < 0) {
+ ps->device->free (ps->device);
+ ps->device = NULL;
+
+ }
+ return bind_return;
+}
+
+int
+pi_listen(int pi_sd, int backlog)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ return ps->device->listen (ps, backlog);
+}
+
+int
+pi_accept(int pi_sd, struct sockaddr *addr, size_t *addrlen)
+{
+ return pi_accept_to(pi_sd, addr, addrlen, 0);
+}
+
+int
+pi_accept_to(int pi_sd, struct sockaddr *addr, size_t *addrlen, int timeout)
+{
+ pi_socket_t *ps;
+ int result;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (!is_listener (ps))
+ return PI_ERR_SOCK_LISTENER;
+
+ ps->accept_to = timeout;
+
+ result = ps->device->accept(ps, addr, addrlen);
+ if (result < 0) {
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_DEBUG,
+ "pi_accept_to: ps->device->accept returned %d, calling pi_close()\n",
+ result));
+ pi_close(pi_sd);
+ }
+
+ return result;
+}
+
+int
+pi_getsockopt(int pi_sd, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ pi_socket_t *ps;
+ pi_protocol_t *prot;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ /* handle getsockopt at socket level */
+ if (level == PI_LEVEL_SOCK) {
+ switch (option_name) {
+ case PI_SOCK_STATE:
+ if (*option_len != sizeof (ps->state))
+ goto argerr;
+ memcpy (option_value, &ps->state, sizeof (ps->state));
+ break;
+
+ case PI_SOCK_HONOR_RX_TIMEOUT:
+ if (*option_len != sizeof (ps->honor_rx_to))
+ goto argerr;
+ memcpy (option_value, &ps->honor_rx_to, sizeof (ps->honor_rx_to));
+ break;
+
+ default:
+ goto argerr;
+ }
+ return 0;
+ }
+
+ /* find the protocol at the requested level and forward it the getsockopt request */
+ prot = protocol_queue_find (ps, level);
+
+ if (prot == NULL || prot->level != level) {
+ errno = EINVAL;
+ return pi_set_error(pi_sd, PI_ERR_SOCK_INVALID);
+ }
+
+ return prot->getsockopt (ps, level, option_name, option_value, option_len);
+
+argerr:
+ errno = EINVAL;
+ return pi_set_error(pi_sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+int
+pi_setsockopt(int pi_sd, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ pi_socket_t *ps;
+ pi_protocol_t *prot;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ /* handle setsockopt at socket level */
+ if (level == PI_LEVEL_SOCK) {
+ switch (option_name) {
+ case PI_SOCK_STATE:
+ if (*option_len != sizeof (ps->state))
+ goto argerr;
+ memcpy (&ps->state, option_value, sizeof (ps->state));
+ break;
+
+ case PI_SOCK_HONOR_RX_TIMEOUT:
+ if (*option_len != sizeof (ps->honor_rx_to))
+ goto argerr;
+ memcpy (&ps->honor_rx_to, option_value, sizeof (ps->honor_rx_to));
+ break;
+
+ default:
+ goto argerr;
+ }
+ return 0;
+ }
+
+ /* find the protocol at the requested level and forward it the setsockopt request */
+ prot = protocol_queue_find (ps, level);
+
+ if (prot == NULL || prot->level != level) {
+ errno = EINVAL;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ return prot->setsockopt (ps, level, option_name, option_value, option_len);
+
+argerr:
+ errno = EINVAL;
+ return pi_set_error(pi_sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_send
+ *
+ * Summary: Send message on a connected socket
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+pi_send(int pi_sd, const void *msg, size_t len, int flags)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (!is_connected (ps))
+ return PI_ERR_SOCK_DISCONNECTED;
+
+ if (interval)
+ alarm(interval);
+
+ return ps->protocol_queue[0]->write (ps, (void *)msg, len, flags);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_recv
+ *
+ * Summary: Receive msg on a connected socket
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+ssize_t
+pi_recv(int pi_sd, pi_buffer_t *msg, size_t len, int flags)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (!is_connected (ps))
+ return PI_ERR_SOCK_DISCONNECTED;
+
+ return ps->protocol_queue[0]->read (ps, msg, len, flags);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_read
+ *
+ * Summary: Wrapper for receive
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+ssize_t
+pi_read(int pi_sd, pi_buffer_t *msg, size_t len)
+{
+ return pi_recv(pi_sd, msg, len, 0);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_write
+ *
+ * Summary: Wrapper for send
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+ssize_t
+pi_write(int pi_sd, const void *msg, size_t len)
+{
+ return pi_send(pi_sd, msg, len, 0);
+}
+
+void
+pi_flush(int pi_sd, int flags)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return;
+ }
+
+ if (!is_connected (ps))
+ return;
+
+ ps->protocol_queue[0]->flush (ps, flags);
+}
+
+int
+pi_tickle(int pi_sd)
+{
+ int result=0,
+ type,
+ oldtype;
+ size_t len = 0,
+ size;
+ unsigned char msg[1];
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (!is_connected (ps))
+ return PI_ERR_SOCK_DISCONNECTED;
+
+ LOG((PI_DBG_SOCK, PI_DBG_LVL_INFO,
+ "SOCKET Tickling socket %d\n", pi_sd));
+
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ /* save previous packet type */
+ size = sizeof(type);
+ pi_getsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_TYPE, &oldtype, &size);
+
+ /* set packet type to "tickle" */
+ type = padTickle;
+ size = sizeof(type);
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_TYPE, &type, &size);
+
+ /* send packet */
+ result = ps->protocol_queue[0]->write (ps, msg, len, 0);
+
+ /* restore previous packet type */
+ size = sizeof(type);
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_TYPE, &oldtype, &size);
+ break;
+
+ case PI_CMD_NET:
+ /* Enter command state */
+ ps->command = 1;
+
+ /* Set the type to "tickle" */
+ type = PI_NET_TYPE_TCKL;
+ size = sizeof(type);
+ pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_TYPE, &type, &size);
+
+ /* send packet */
+ result = ps->cmd_queue[0]->write (ps, msg, len, 0);
+
+ /* Exit command state */
+ ps->command = 0;
+ break;
+ }
+
+ return result;
+}
+
+int
+pi_close(int pi_sd)
+{
+ int result = 0;
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (ps->type == PI_SOCK_STREAM && ps->cmd != PI_CMD_SYS) {
+ if (is_connected (ps)) {
+ ps->command = 1;
+
+ /* then end sync, with clean status */
+ result = dlp_EndOfSync(ps->sd, 0);
+
+ ps->command = 0;
+ }
+ }
+
+ if (result == 0) {
+ /* we need to remove the entry from the list prior to
+ * closing it, because closing it will reset the pi_sd */
+ pi_mutex_lock(&psl_mutex);
+ psl = ps_list_remove (psl, pi_sd);
+ pi_mutex_unlock(&psl_mutex);
+
+ pi_mutex_lock(&watch_list_mutex);
+ watch_list = ps_list_remove (watch_list, pi_sd);
+ pi_mutex_unlock(&watch_list_mutex);
+
+ if (ps->device != NULL)
+ result = ps->device->close (ps);
+
+ protocol_queue_destroy(ps);
+
+ if (ps->device != NULL)
+ ps->device->free(ps->device);
+
+ if (ps->sd > 0)
+ close(ps->sd);
+ free(ps);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_getsockname
+ *
+ * Summary: Get the local address for a socket
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+pi_getsockname(int pi_sd, struct sockaddr *addr, size_t *namelen)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (*namelen > ps->laddrlen)
+ *namelen = ps->laddrlen;
+ memcpy(addr, &ps->laddr, *namelen);
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_getsockpeer
+ *
+ * Summary: Get the remote address for a socket
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+pi_getsockpeer(int pi_sd, struct sockaddr *addr, size_t *namelen)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (*namelen > ps->raddrlen)
+ *namelen = ps->raddrlen;
+ memcpy(addr, &ps->raddr, *namelen);
+
+ return 0;
+}
+
+int
+pi_version(int pi_sd)
+{
+ size_t size;
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ if (ps->dlpversion)
+ return ps->dlpversion;
+
+ if (ps->cmd == PI_CMD_CMP) {
+ /* Enter command state */
+ ps->command = 1;
+
+ /* Get the version */
+ size = sizeof(ps->dlpversion);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_VERS, &ps->dlpversion, &size);
+ ps->maxrecsize = DLP_BUF_SIZE;
+
+ /* Exit command state */
+ ps->command = 0;
+ }
+
+ return ps->dlpversion;
+}
+
+unsigned long
+pi_maxrecsize(int pi_sd)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return 0;
+ }
+
+ /* pi_version will read necessary info from device */
+ if (pi_version(pi_sd) == 0)
+ return DLP_BUF_SIZE;
+
+ return ps->maxrecsize;
+}
+
+/***********************************************************************
+ *
+ * Function: find_pi_socket
+ *
+ * Summary: Thread-safe wrapper for ps_list_find
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+pi_socket_t *
+find_pi_socket(int pi_sd)
+{
+ pi_socket_t *result;
+
+ pi_mutex_lock(&psl_mutex);
+ result = ps_list_find (psl, pi_sd);
+ pi_mutex_unlock(&psl_mutex);
+
+ return result;
+}
+
+int
+pi_watchdog(int pi_sd, int newinterval)
+{
+ pi_socket_t *ps;
+
+ if (!(ps = find_pi_socket(pi_sd))) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+
+ pi_mutex_lock(&watch_list_mutex);
+ watch_list = ps_list_append (watch_list, ps);
+ pi_mutex_unlock(&watch_list_mutex);
+
+ signal(SIGALRM, onalarm);
+ interval = newinterval;
+ alarm(interval);
+
+ return 0;
+}
+
+int
+pi_error(int pi_sd)
+{
+ pi_socket_t *ps;
+
+ if ((ps = find_pi_socket(pi_sd)) == NULL) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+ return ps->last_error;
+}
+
+int
+pi_set_error(int pi_sd, int error_code)
+{
+ pi_socket_t *ps;
+
+ if ((ps = find_pi_socket(pi_sd)))
+ ps->last_error = error_code;
+ else
+ errno = ESRCH;
+
+ /* also update errno if makes sense */
+ if (error_code == PI_ERR_GENERIC_MEMORY)
+ errno = ENOMEM;
+
+ return error_code;
+}
+
+int
+pi_palmos_error(int pi_sd)
+{
+ pi_socket_t *ps;
+
+ if ((ps = find_pi_socket(pi_sd)) == NULL) {
+ errno = ESRCH;
+ return PI_ERR_SOCK_INVALID;
+ }
+ return ps->palmos_error;
+}
+
+int
+pi_set_palmos_error(int pi_sd, int error_code)
+{
+ pi_socket_t *ps;
+
+ if ((ps = find_pi_socket(pi_sd)))
+ ps->palmos_error = error_code;
+ else
+ errno = ESRCH;
+ return error_code;
+}
+
+void
+pi_reset_errors(int pi_sd)
+{
+ pi_socket_t *ps;
+
+ if ((ps = find_pi_socket(pi_sd))) {
+ ps->last_error = 0;
+ ps->palmos_error = 0;
+ } else
+ errno = ESRCH;
+}
+
+int
+pi_socket_connected(int pi_sd)
+{
+ pi_socket_t *ps;
+
+ if ((ps = find_pi_socket(pi_sd)))
+ return is_connected(ps);
+ errno = ESRCH;
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/sys.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/sys.c
new file mode 100644
index 00000000..8555cdd7
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/sys.c
@@ -0,0 +1,372 @@
+/*
+ * $Id: sys.c,v 1.17 2006/10/12 14:21:22 desrod Exp $
+ *
+ * sys.c: Pilot System Protocol
+ *
+ * (c) 1996, Kenneth Albanowski.
+ * Derived from padp.c.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-slp.h"
+#include "pi-sys.h"
+#include "pi-error.h"
+
+/* Declare function prototypes */
+static int sys_flush(pi_socket_t *ps, int flags);
+static int sys_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len);
+static int sys_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len);
+
+
+/***********************************************************************
+ *
+ * Function: sys_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t *
+sys_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot = NULL;
+ pi_sys_data_t *data = NULL,
+ *new_data = NULL;
+
+ new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ if (new_prot != NULL) {
+ new_data = (pi_sys_data_t *)malloc (sizeof (pi_sys_data_t));
+ if (new_data == NULL) {
+ free(new_prot);
+ new_prot = NULL;
+ }
+ }
+
+ if (new_prot != NULL && new_data != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+
+ data = (pi_sys_data_t *)prot->data;
+ new_data->txid = data->txid;
+ new_prot->data = new_data;
+ }
+
+ return new_prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+sys_protocol_free (pi_protocol_t *prot)
+{
+
+ ASSERT (prot != NULL);
+ if (prot != NULL) {
+ if (prot->data != NULL)
+ free(prot->data);
+ free(prot);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: void
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_protocol_t *
+sys_protocol (void)
+{
+ pi_protocol_t *prot = NULL;
+ pi_sys_data_t *data = NULL;
+
+ prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+ if (prot != NULL) {
+ data = (pi_sys_data_t *)malloc (sizeof (pi_sys_data_t));
+ if (data == NULL) {
+ free(prot);
+ prot = NULL;
+ }
+ }
+
+ if (prot != NULL && data != NULL) {
+ prot->level = PI_LEVEL_SYS;
+ prot->dup = sys_protocol_dup;
+ prot->free = sys_protocol_free;
+ prot->read = sys_rx;
+ prot->write = sys_tx;
+ prot->flush = sys_flush;
+ prot->getsockopt = sys_getsockopt;
+ prot->setsockopt = sys_setsockopt;
+
+ data->txid = 0x00;
+ prot->data = data;
+ }
+
+ return prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_tx
+ *
+ * Summary: Send a system message
+ *
+ * Parameters: pi_socket_t*, char* to buffer, buffer length, flags
+ *
+ * Returns: 0 if success, nonzero otherwise
+ *
+ ***********************************************************************/
+ssize_t
+sys_tx(pi_socket_t *ps, const unsigned char *buf, size_t len, int flags)
+{
+ pi_protocol_t *prot,
+ *next;
+
+ pi_sys_data_t *data;
+
+ int type,
+ socket;
+
+ size_t size;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SYS);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (pi_sys_data_t *)prot->data;
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_SYS);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ if (!data->txid || data->txid == 0xff)
+ data->txid = 0x11; /* some random # */
+ data->txid++;
+ if (!data->txid || data->txid == 0xff)
+ data->txid = 0x11; /* some random # */
+
+ type = PI_SLP_TYPE_RDCP;
+
+ /* Fix me, allow socket type */
+ socket = PI_SLP_SOCK_CON;
+ size = sizeof(type);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TYPE,
+ &type, &size);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_DEST,
+ &socket, &size);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_SRC,
+ &socket, &size);
+ size = sizeof(data->txid);
+ pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TXID,
+ &data->txid, &size);
+
+ len = next->write(ps, buf, len, flags);
+ if (len >= 0) {
+ CHECK(PI_DBG_SYS, PI_DBG_LVL_INFO, sys_dump_header(buf, 1));
+ CHECK(PI_DBG_SYS, PI_DBG_LVL_DEBUG, sys_dump(buf, len));
+ }
+
+ return len;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_rx
+ *
+ * Summary: Receive system message
+ *
+ * Parameters: pi_socket_t*, char* to buffer, buffer length, flags
+ *
+ * Returns: Length of read or negative on error
+ *
+ ***********************************************************************/
+ssize_t
+sys_rx(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ pi_protocol_t *next,
+ *prot;
+
+ pi_sys_data_t *data;
+ size_t data_len;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SYS);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data = (pi_sys_data_t *)prot->data;
+ next = pi_protocol_next(ps->sd, PI_LEVEL_SYS);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ data_len = next->read(ps, buf, len, flags);
+
+ CHECK(PI_DBG_SYS, PI_DBG_LVL_INFO, sys_dump_header(buf->data, 0));
+ CHECK(PI_DBG_SYS, PI_DBG_LVL_DEBUG, sys_dump(buf->data, data_len));
+
+ return data_len;
+}
+
+/***********************************************************************
+ *
+ * Function: sys_flush
+ *
+ * Summary: Flush input and output buffers
+ *
+ * Parameters: pi_socket_t*, flags
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+sys_flush(pi_socket_t *ps, int flags)
+{
+ pi_protocol_t *prot,
+ *next;
+
+ prot = pi_protocol(ps->sd, PI_LEVEL_SYS);
+ if (prot == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ next = pi_protocol_next(ps->sd, PI_LEVEL_SYS);
+ if (next == NULL)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
+
+ return next->flush(ps, flags);
+}
+
+/***********************************************************************
+ *
+ * Function: sys_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success
+ *
+ ***********************************************************************/
+static int
+sys_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_setsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success
+ *
+ ***********************************************************************/
+static int
+sys_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_dump_header
+ *
+ * Summary: Dump SYS packet header
+ *
+ * Parameters: char* to data, RXTX boolean
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+sys_dump_header(const unsigned char *data, int rxtx)
+{
+ LOG((PI_DBG_SYS, PI_DBG_LVL_NONE,
+ "SYS %s\n", rxtx ? "TX" : "RX"));
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_dump
+ *
+ * Summary: Dump SYS packet
+ *
+ * Parameters: char* to data, length
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+sys_dump(const unsigned char *data, size_t len)
+{
+ pi_dumpdata((char *)&data[PI_SYS_HEADER_LEN], len);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/syspkt.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/syspkt.c
new file mode 100644
index 00000000..8cafb839
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/syspkt.c
@@ -0,0 +1,1031 @@
+/*
+ * $Id: syspkt.c,v 1.41 2006/10/12 14:21:23 desrod Exp $
+ *
+ * syspkt.c: Pilot SysPkt manager
+ *
+ * (c) 1996, Kenneth Albanowski.
+ * Derived from padp.c.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "pi-source.h"
+#include "pi-syspkt.h"
+#include "pi-slp.h"
+#include "pi-serial.h"
+#include "pi-error.h"
+
+/* Declare prototypes */
+static int sys_PackRegisters(void *data, struct Pilot_registers *r);
+
+
+/***********************************************************************
+ *
+ * Function: sys_UnpackState
+ *
+ * Summary: Get the state command
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_UnpackState(void *buffer, struct Pilot_state *s)
+{
+ int idx;
+ unsigned char *data = buffer;
+
+ s->reset = get_short(data);
+ s->exception = get_short(data + 2);
+ memcpy(s->func_name, data + 152, 32);
+ memcpy(s->instructions, data + 78, 30);
+ s->func_name[32 - 1] = 0;
+ s->func_start = get_long(data + 144);
+ s->func_end = get_long(data + 148);
+ sys_UnpackRegisters(data + 4, &s->regs);
+
+ for (idx = 0; idx < 6; idx++) {
+ s->breakpoint[idx].address = get_long(data + 108 + idx * 6);
+ s->breakpoint[idx].enabled = get_byte(data + 112 + idx * 6);
+ }
+
+ s->trap_rev = get_short(data + 184);
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_UnpackRegisters
+ *
+ * Summary: Read the register commands
+ *
+ * Parameters: None
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+int
+sys_UnpackRegisters(void *data, struct Pilot_registers *r)
+{
+ unsigned char *buffer = data;
+
+ r->D[0] = get_long(buffer + 0);
+ r->D[1] = get_long(buffer + 4);
+ r->D[2] = get_long(buffer + 8);
+ r->D[3] = get_long(buffer + 12);
+ r->D[4] = get_long(buffer + 16);
+ r->D[5] = get_long(buffer + 20);
+ r->D[6] = get_long(buffer + 24);
+ r->D[7] = get_long(buffer + 28);
+ r->A[0] = get_long(buffer + 32);
+ r->A[1] = get_long(buffer + 36);
+ r->A[2] = get_long(buffer + 40);
+ r->A[3] = get_long(buffer + 44);
+ r->A[4] = get_long(buffer + 48);
+ r->A[5] = get_long(buffer + 52);
+ r->A[6] = get_long(buffer + 56);
+ r->USP = get_long(buffer + 60);
+ r->SSP = get_long(buffer + 64);
+ r->PC = get_long(buffer + 68);
+
+ r->SR = get_short(buffer + 72);
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_PackRegisters
+ *
+ * Summary: Pack the register commands
+ *
+ * Parameters: None
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+static int
+sys_PackRegisters(void *data, struct Pilot_registers *r)
+{
+ int idx;
+ unsigned char *buffer = data;
+
+ for (idx = 0; idx < 8; idx++)
+ set_long(buffer + idx * 4, r->D[idx]);
+ for (idx = 0; idx < 7; idx++)
+ set_long(buffer + 32 + idx * 4, r->A[idx]);
+ set_long(buffer + 60, r->USP);
+ set_long(buffer + 64, r->SSP);
+ set_long(buffer + 68, r->PC);
+
+ set_short(buffer + 72, r->SR);
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: sys_Continue
+ *
+ * Summary: Define the Continue command
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_Continue(int sd, struct Pilot_registers *r, struct Pilot_watch *w)
+{
+ char buf[94];
+
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ buf[4] = 0x07;
+ buf[5] = 0; /* gapfill */
+
+ if (!r)
+ return pi_write(sd, buf, 6);
+
+ sys_PackRegisters(buf + 6, r);
+ set_byte(buf + 80, (w != 0) ? 1 : 0);
+ set_byte(buf + 81, 0);
+ set_long(buf + 82, w ? w->address : 0);
+ set_long(buf + 86, w ? w->length : 0);
+ set_long(buf + 90, w ? w->checksum : 0);
+
+ return pi_write(sd, buf, 94);
+}
+
+/***********************************************************************
+ *
+ * Function: sys_Step
+ *
+ * Summary: Single-step command
+ *
+ * Parameters: None
+ *
+ * Returns: Socket, command, 6 bytes
+ *
+ ***********************************************************************/
+int
+sys_Step(int sd)
+{
+ char buf[94];
+
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ buf[4] = 0x03;
+ buf[5] = 0; /* gapfill */
+
+ return pi_write(sd, buf, 6);
+}
+
+/***********************************************************************
+ *
+ * Function: sys_SetBreakpoints
+ *
+ * Summary: Set the breakpoints (0x0C, 0x8C)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_SetBreakpoints(int sd, struct Pilot_breakpoint *b)
+{
+ int idx;
+ pi_buffer_t *buf;
+
+ buf = pi_buffer_new (94);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ buf->data[0] = 0;
+ buf->data[1] = 0;
+ buf->data[2] = 0;
+ buf->data[3] = 0;
+ buf->data[4] = 0x0c;
+ buf->data[5] = 0; /* gapfill */
+
+ for (idx = 0; idx < 6; idx++) {
+ set_long(buf->data + 6 + idx * 6, b[idx].address);
+ set_byte(buf->data + 10 + idx * 6, b[idx].enabled);
+ set_byte(buf->data + 11 + idx * 6, 0);
+ }
+
+ pi_write(sd, buf->data, 42);
+
+ idx = pi_read(sd, buf, 6);
+
+ if (idx <= 0 || buf->data[4] != (unsigned char) 0x8c) {
+ pi_buffer_free (buf);
+ return 0;
+ }
+
+ pi_buffer_free (buf);
+ return 1;
+}
+
+/***********************************************************************
+ *
+ * Function: sys_SetTrapBreaks
+ *
+ * Summary: Set the Trap Breaks (0x11, 0x91)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_SetTrapBreaks(int sd, int *traps)
+{
+ int idx;
+ pi_buffer_t *buf;
+
+ buf = pi_buffer_new (32);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ buf->data[0] = 0;
+ buf->data[1] = 0;
+ buf->data[2] = 0;
+ buf->data[3] = 0;
+ buf->data[4] = 0x11;
+ buf->data[5] = 0; /* gapfill */
+
+ for (idx = 0; idx < 5; idx++) {
+ set_short(buf->data + 6 + idx * 2, traps[idx]);
+ }
+
+ pi_write(sd, buf->data, 16);
+
+ idx = pi_read(sd, buf, 6);
+
+ if ((idx <= 0) || (buf->data[4] != (unsigned char) 0x91)) {
+ pi_buffer_free (buf);
+ return 0;
+ }
+
+ pi_buffer_free (buf);
+ return 1;
+}
+
+/***********************************************************************
+ *
+ * Function: sys_GetTrapBreaks
+ *
+ * Summary: Get the Trap Breaks (0x10, 0x90)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_GetTrapBreaks(int sd, int *traps)
+{
+ int idx;
+ pi_buffer_t *buf;
+
+ buf = pi_buffer_new (32);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ buf->data[0] = 0;
+ buf->data[1] = 0;
+ buf->data[2] = 0;
+ buf->data[3] = 0;
+ buf->data[4] = 0x10;
+ buf->data[5] = 0; /* gapfill */
+
+ pi_write(sd, buf->data, 6);
+
+ idx = pi_read(sd, buf, 16);
+
+ if ((idx < 16) || (buf->data[4] != (unsigned char) 0x90)) {
+ pi_buffer_free (buf);
+ return 0;
+ }
+
+ for (idx = 0; idx < 5; idx++) {
+ traps[idx] = get_short(buf->data + 6 + idx * 2);
+ }
+
+ pi_buffer_free (buf);
+ return 1;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_ToggleDbgBreaks
+ *
+ * Summary: Enable the DbgBreaks command (0x0D, 0x8D)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_ToggleDbgBreaks(int sd)
+{
+ int idx;
+ pi_buffer_t *buf;
+ unsigned char byte;
+
+ buf = pi_buffer_new (32);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ buf->data[0] = 0;
+ buf->data[1] = 0;
+ buf->data[2] = 0;
+ buf->data[3] = 0;
+ buf->data[4] = 0x0d;
+ buf->data[5] = 0; /* gapfill */
+
+ pi_write(sd, buf->data, 6);
+
+ idx = pi_read(sd, buf, 7);
+
+ if ((idx < 7) || (buf->data[4] != (unsigned char) 0x8d)) {
+ pi_buffer_free (buf);
+ return 0;
+ }
+
+ byte = get_byte(buf->data + 6);
+
+ pi_buffer_free (buf);
+
+ return byte;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_QueryState
+ *
+ * Summary: Query the state (uh)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_QueryState(int sd)
+{
+ char buf[6];
+
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 0; /* gapfill */
+
+ return pi_write(sd, buf, 2);
+}
+
+/***********************************************************************
+ *
+ * Function: sys_ReadMemory
+ *
+ * Summary: Read memory (0x01, 0x81)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_ReadMemory(int sd, unsigned long addr, unsigned long len, void *dest)
+{
+ int result;
+ unsigned long todo, done;
+ pi_buffer_t *buf;
+
+ buf = pi_buffer_new (0xFFFF);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ done = 0;
+ do {
+ todo = len;
+ if (todo > 256)
+ todo = 256;
+
+ buf->data[0] = 0;
+ buf->data[1] = 0;
+ buf->data[2] = 0;
+ buf->data[3] = 0;
+ buf->data[4] = 0x01;
+ buf->data[5] = 0; /* gapfill */
+
+ set_long(buf->data + 6, addr + done);
+ set_short(buf->data + 10, todo);
+
+ pi_write(sd, buf->data, 12);
+
+ result = pi_read(sd, buf, todo + 6);
+
+ if (result < 0) {
+ pi_buffer_free (buf);
+ return done;
+ }
+
+ if ((buf->data[4] == 0x81)
+ && ((unsigned int) result == todo + 6)) {
+ memcpy(((char *) dest) + done, buf->data + 6, todo);
+ done += todo;
+ } else {
+ pi_buffer_free (buf);
+ return done;
+ }
+ } while (done < len);
+
+ pi_buffer_free (buf);
+ return done;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_WriteMemory
+ *
+ * Summary: Write memory (0x02, 0x82)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_WriteMemory(int sd, unsigned long addr, unsigned long len, void *src)
+{
+ int result;
+ unsigned long todo, done;
+ pi_buffer_t *buf;
+
+ buf = pi_buffer_new (0xFFFF);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ done = 0;
+ do {
+ todo = len;
+ if (todo > 256)
+ todo = 256;
+
+ buf->data[0] = 0;
+ buf->data[1] = 0;
+ buf->data[2] = 0;
+ buf->data[3] = 0;
+ buf->data[4] = 0x02;
+ buf->data[5] = 0; /* gapfill */
+
+ set_long(buf->data + 6, addr);
+ set_short(buf->data + 10, len);
+ memcpy(buf->data + 12, (char *)src + done, todo);
+
+ pi_write(sd, buf->data, len + 12);
+
+ result = pi_read(sd, buf, 6);
+
+ if (result < 0) {
+ pi_buffer_free (buf);
+ return done;
+ }
+
+ if ((buf->data[4] == (unsigned char)0x82)
+ && ((unsigned long) result == todo + 6)) {
+ ;
+ } else {
+ pi_buffer_free (buf);
+ return done;
+ }
+ } while (done < len);
+
+ pi_buffer_free (buf);
+ return done;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_Find
+ *
+ * Summary: Searches a range of addresses for data (0x13, 0x80)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_Find(int sd, unsigned long startaddr, unsigned long stopaddr, size_t len,
+ int caseinsensitive, void *data, unsigned long *found)
+{
+ int result;
+ unsigned char byte;
+ pi_buffer_t *buf;
+
+ buf = pi_buffer_new (len + 17);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ buf->data[0] = 0;
+ buf->data[1] = 0;
+ buf->data[2] = 0;
+ buf->data[3] = 0;
+ buf->data[4] = 0x11;
+ buf->data[5] = 0; /* gapfill */
+
+ set_long(buf->data + 6, startaddr);
+ set_long(buf->data + 10, stopaddr);
+ set_short(buf->data + 14, len);
+ set_byte(buf->data + 16, caseinsensitive);
+ memcpy(buf->data + 17, data, len);
+
+ pi_write(sd, buf->data, len + 17);
+
+ result = pi_read(sd, buf, 12);
+
+ if (result < 0) {
+ pi_buffer_free (buf);
+ return result;
+ }
+
+ if (found)
+ *found = get_long(buf->data + 6);
+
+ byte = get_byte(buf->data + 10);
+
+ pi_buffer_free (buf);
+
+ return byte;
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_RemoteEvent
+ *
+ * Summary: Parameters sent from host to target to feed pen and
+ * keyboard events. They do not require a response.
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_RemoteEvent(int sd, int penDown, int x, int y, int keypressed,
+ int keymod, int keyasc, int keycode)
+{
+ char buf[16];
+
+ /* Offset 1, 3 and 9 are padding */
+ set_byte(&buf[0], 0x0D); /* RemoteEvtCommand */
+ set_byte(&buf[1], 0);
+ set_byte(&buf[2], penDown);
+ set_byte(&buf[3], 0);
+ set_short(&buf[4], x);
+ set_short(&buf[6], y);
+ set_byte(&buf[8], keypressed);
+ set_byte(&buf[9], 0);
+ set_short(&buf[10], keymod);
+ set_short(&buf[12], keyasc);
+ set_short(&buf[14], keycode);
+
+ return pi_write(sd, buf, 16);
+}
+
+
+/***********************************************************************
+ *
+ * Function: sys_RPC
+ *
+ * Summary: Remote Procedure calls (0x0A, 0x8A)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+sys_RPC(int sd, int sockaddr, int trap, long *D0, long *A0, int params,
+ struct RPC_param *param, int reply)
+{
+ int idx;
+ unsigned char *c;
+ pi_buffer_t *buf;
+
+ buf = pi_buffer_new (4096);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ buf->data[0] = sockaddr; /* 0 for debug, 1 for console */
+ buf->data[1] = sockaddr;
+ buf->data[2] = 0;
+ buf->data[4] = 0x0a;
+ buf->data[5] = 0;
+
+ set_short(buf->data + 6, trap);
+ set_long(buf->data + 8, *D0);
+ set_long(buf->data + 12, *A0);
+ set_short(buf->data + 16, params);
+
+ c = buf->data + 18;
+ for (idx = params - 1; idx >= 0; idx--) {
+ set_byte(c, param[idx].byRef);
+ c++;
+ set_byte(c, param[idx].size);
+ c++;
+ if (param[idx].data)
+ memcpy(c, param[idx].data, param[idx].size);
+ c += param[idx].size;
+ if (param[idx].size & 1)
+ *c++ = 0;
+ }
+
+ if (sockaddr == 3)
+ set_short(buf->data + 4, c - buf->data - 6);
+
+ pi_write(sd, buf->data + 4,(size_t)(c - buf->data - 4));
+
+ if (reply) {
+ int l = pi_read(sd, buf, 4096);
+
+ if (l < 0) {
+ pi_buffer_free (buf);
+ return l;
+ }
+
+ if (buf->data[0] != (unsigned char)0x8a) {
+ pi_buffer_free (buf);
+ return pi_set_error(sd, -2);
+ }
+
+ *D0 = get_long(buf->data + 4);
+ *A0 = get_long(buf->data + 8);
+ c = buf->data + 14;
+ for (idx = params - 1; idx >= 0; idx--) {
+ if (param[idx].byRef && param[idx].data)
+ memcpy(param[idx].data, c + 2,
+ param[idx].size);
+ c += 2 + ((get_byte(c + 1) + 1) & ~1);
+ }
+ }
+
+ pi_buffer_free (buf);
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: RPC
+ *
+ * Summary: Deprecated
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+RPC(int sd, int sockaddr, int trap, int reply, ...)
+{
+ int idx = 0,
+ j,
+ RPC_arg[20];
+ va_list ap;
+ struct RPC_param p[20];
+ long D0 = 0,
+ A0 = 0;
+
+ va_start(ap, reply);
+ for (;;) {
+ int type = va_arg(ap, int);
+
+ if (type == 0)
+ break;
+ if (type < 0) {
+ p[idx].byRef = 0;
+ p[idx].size = -type;
+ RPC_arg[idx] = va_arg(ap, int);
+
+ p[idx].data = &RPC_arg[idx];
+ p[idx].invert = 0;
+ } else {
+ void *c = va_arg(ap, void *);
+
+ p[idx].byRef = 1;
+ p[idx].size = type;
+ p[idx].data = c;
+ p[idx].invert = va_arg(ap, int);
+
+ if (p[idx].invert) {
+ if (p[idx].size == 2) {
+ int *s = c;
+
+ *s = htons(*s);
+ } else {
+ int *l = c;
+
+ *l = htonl(*l);
+ }
+ }
+ }
+ idx++;
+ }
+ va_end(ap);
+
+ if (sys_RPC(sd, sockaddr, trap, &D0, &A0, idx, p, reply != 2) < 0)
+ return pi_error(sd);
+
+ for (j = 0; j < idx; j++) {
+ if (p[j].invert) {
+ void *c = p[j].data;
+
+ if (p[j].size == 2) {
+ int *s = c;
+
+ *s = htons(*s);
+ } else {
+ int *l = c;
+
+ *l = htonl(*l);
+ }
+ }
+ }
+
+ if (reply)
+ return A0;
+ return D0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: PackRPC
+ *
+ * Summary: Pack the RPC structure for transmission
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+PackRPC(struct RPC_params *p, int trap, int reply, ...)
+{
+ int idx = 0;
+ va_list ap;
+
+ p->trap = trap;
+ p->reply = reply;
+
+ va_start(ap, reply);
+ for (;;) {
+ int type = (int) va_arg(ap, int);
+
+ if (type == 0)
+ break;
+ if (type < 0) {
+ p->param[idx].byRef = 0;
+ p->param[idx].size = -type;
+ p->param[idx].arg = (int) va_arg(ap, int);
+
+ p->param[idx].data = &p->param[idx].arg;
+ p->param[idx].invert = 0;
+ } else {
+ void *c = (void *) va_arg(ap, void *);
+
+ p->param[idx].byRef = 1;
+ p->param[idx].size = type;
+ p->param[idx].data = c;
+ p->param[idx].invert = (int) va_arg(ap, int);
+ }
+ idx++;
+ }
+ p->args = idx;
+ va_end(ap);
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: UninvertRPC
+ *
+ * Summary:
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+void
+UninvertRPC(struct RPC_params *p)
+{
+ int j;
+
+ for (j = 0; j < p->args; j++) {
+ if (p->param[j].invert) {
+ void *c = p->param[j].data;
+
+ if ((p->param[j].invert == 2)
+ && (p->param[j].size == 2)) {
+ int *s = c;
+
+ *s = htons(*s) >> 8;
+ } else if (p->param[j].size == 2) {
+ int *s = c;
+
+ *s = htons(*s);
+ } else {
+ long *l = c;
+
+ *l = htonl(*l);
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: InvertRPC
+ *
+ * Summary:
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+void
+InvertRPC(struct RPC_params *p)
+{
+ int j;
+
+ for (j = 0; j < p->args; j++) {
+ if (p->param[j].invert) {
+ void *c = p->param[j].data;
+
+ if ((p->param[j].invert == 2)
+ && (p->param[j].size == 2)) {
+ int *s = c;
+
+ *s = ntohs(*s) >> 8;
+ } else if (p->param[j].size == 2) {
+ int *s = c;
+
+ *s = ntohs(*s);
+ } else {
+ long *l = c;
+
+ *l = ntohl((unsigned) *l);
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: DoRPC
+ *
+ * Summary: Actually execute the RPC query/response
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+unsigned long
+DoRPC(int sd, int sockaddr, struct RPC_params *p, int *error)
+{
+ int err;
+ long D0 = 0,
+ A0 = 0;
+
+ InvertRPC(p);
+
+ err =
+ sys_RPC(sd, sockaddr, p->trap, &D0, &A0, p->args, &p->param[0],
+ p->reply);
+
+ UninvertRPC(p);
+
+ if (error)
+ *error = err;
+
+ if (p->reply == RPC_PtrReply)
+ return A0;
+ else if (p->reply == RPC_IntReply)
+ return D0;
+ else
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * Function: RPC_Int_Void
+ *
+ * Summary:
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+RPC_Int_Void(int sd, int trap)
+{
+ return RPC(sd, 1, trap, 0, RPC_End);
+}
+
+
+/***********************************************************************
+ *
+ * Function: RPC_Ptr_Void
+ *
+ * Summary:
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int
+RPC_Ptr_Void(int sd, int trap)
+{
+ return RPC(sd, 1, trap, 1, RPC_End);
+}
+
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/threadsafe.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/threadsafe.c
new file mode 100644
index 00000000..4b4b69dc
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/threadsafe.c
@@ -0,0 +1,70 @@
+/*
+ * $Id: threadsafe.c,v 1.5 2006/10/12 14:21:23 desrod Exp $
+ *
+ * threadsafe.c: utilities for thread-safe behavior
+ *
+ * Copyright (c) 2005, Florent Pillet.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#include "pi-threadsafe.h"
+
+int pi_mutex_lock(pi_mutex_t *mutex)
+{
+#if HAVE_PTHREAD
+ return pthread_mutex_lock(mutex);
+#else
+ return 0;
+#endif
+}
+
+int pi_mutex_trylock(pi_mutex_t *mutex)
+{
+#if HAVE_PTHREAD
+ return pthread_mutex_trylock(mutex);
+#else
+ return 0;
+#endif
+}
+
+int pi_mutex_unlock(pi_mutex_t *mutex)
+{
+#if HAVE_PTHREAD
+ return pthread_mutex_unlock(mutex);
+#else
+ return 0;
+#endif
+}
+
+unsigned long pi_thread_id()
+{
+#if HAVE_PTHREAD
+ return (unsigned long)pthread_self();
+#else
+ return 0;
+#endif
+}
+
+#include "pi-threadsafe.h"
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/todo.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/todo.c
new file mode 100644
index 00000000..c74c3738
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/todo.c
@@ -0,0 +1,293 @@
+/*
+ * $Id: todo.c,v 1.28 2006/11/22 22:52:25 adridg Exp $
+ *
+ * todo.c: Translate Palm ToDo application data formats
+ *
+ * Copyright (c) 1996, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-todo.h"
+
+/* Maximum length of Description and Note fields */
+#define DescMaxLength 256
+#define NoteMaxLength 4096
+
+
+/***********************************************************************
+ *
+ * Function: free_ToDo
+ *
+ * Summary: Free the memory and filehandle from the record alloc.
+ *
+ * Parameters: ToDo_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+free_ToDo(ToDo_t *todo)
+{
+
+ if (todo->description != NULL) {
+ free(todo->description);
+ todo->description = NULL;
+ }
+
+ if (todo->note != NULL) {
+ free(todo->note);
+ todo->note = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_ToDo
+ *
+ * Summary: Unpack the ToDo structure from buffer into records
+ * we can chew on.
+ *
+ * Parameters: ToDo_t*, pi_buffer_t * of buffer, todo type
+ *
+ * Returns: -1 on fail, 0 on success
+ *
+ ***********************************************************************/
+int
+unpack_ToDo(ToDo_t *todo, const pi_buffer_t *buf, todoType type)
+{
+ unsigned long d;
+ int ofs;
+
+ /* Note: There are possible timezone conversion problems related to
+ the use of the due member of a struct ToDo. As it is kept in
+ local (wall) time in struct tm's, the timezone of the Palm is
+ irrelevant, _assuming_ that any UNIX program keeping time in
+ time_t's converts them to the correct local time. If the Palm is
+ in a different timezone than the UNIX box, it may not be simple
+ to deduce that correct (desired) timezone.
+
+ The easiest solution is to keep apointments in struct tm's, and
+ out of time_t's. Of course, this might not actually be a help if
+ you are constantly darting across timezones and trying to keep
+ appointments.
+ -- KJA */
+
+ if (type != todo_v1)
+ return -1;
+
+ if (buf == NULL || buf->data == NULL || buf->used < 3)
+ return -1;
+
+ d = (unsigned short int) get_short(buf->data);
+ if (d != 0xffff) {
+ todo->due.tm_year = (d >> 9) + 4;
+ todo->due.tm_mon = ((d >> 5) & 15) - 1;
+ todo->due.tm_mday = d & 31;
+ todo->due.tm_hour = 0;
+ todo->due.tm_min = 0;
+ todo->due.tm_sec = 0;
+ todo->due.tm_isdst = -1;
+ mktime(&todo->due);
+ todo->indefinite = 0;
+ } else {
+ todo->indefinite = 1; /* todo->due is invalid */
+ }
+
+ todo->priority = get_byte(buf->data + 2);
+ if (todo->priority & 0x80) {
+ todo->complete = 1;
+ todo->priority &= 0x7f;
+ } else {
+ todo->complete = 0;
+ }
+
+ ofs = 3;
+
+ if (buf->used - ofs < 1)
+ return -1;
+
+ todo->description = strdup((char *) buf->data + ofs);
+
+ ofs += strlen(todo->description) + 1;
+
+ if (buf->used - ofs < 1) {
+ free(todo->description);
+ todo->description = 0;
+ return -1;
+ }
+ todo->note = strdup((char *) buf->data + ofs);
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_ToDo
+ *
+ * Summary: Pack the ToDo records into a structure
+ *
+ * Parameters: ToDo_t*, pi_buffer_t *buf of record, record type
+ *
+ * Returns: -1 on error, 0 on success.
+ *
+ ***********************************************************************/
+int
+pack_ToDo(const ToDo_t *todo, pi_buffer_t *buf, todoType type)
+{
+ int pos;
+ size_t destlen = 3;
+
+ if (todo == NULL || buf == NULL)
+ return -1;
+
+ if (type != todo_v1)
+ return -1;
+
+ if (todo->description)
+ destlen += strlen(todo->description);
+ destlen++;
+ if (todo->note)
+ destlen += strlen(todo->note);
+ destlen++;
+
+ pi_buffer_expect (buf, destlen);
+ buf->used = destlen;
+
+ if (todo->indefinite) {
+ buf->data[0] = 0xff;
+ buf->data[1] = 0xff;
+ } else {
+ set_short(buf->data,
+ ((todo->due.tm_year - 4) << 9) | ((todo->due.tm_mon +
+ 1) << 5) | todo->
+ due.tm_mday);
+ }
+ buf->data[2] = todo->priority;
+ if (todo->complete) {
+ buf->data[2] |= 0x80;
+ }
+
+ pos = 3;
+ if (todo->description) {
+ strcpy((char *) buf->data + pos, todo->description);
+ pos += strlen(todo->description) + 1;
+ } else {
+ buf->data[pos++] = 0;
+ }
+
+ if (todo->note) {
+ strcpy((char *) buf->data + pos, todo->note);
+ pos += strlen(todo->note) + 1;
+ } else {
+ buf->data[pos++] = 0;
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_ToDoAppInfo
+ *
+ * Summary: Unpack the ToDo AppInfo block from the structure
+ *
+ * Parameters: ToDoAppInfo_t*, char* to record, record length
+ *
+ * Returns: effective record length
+ *
+ ***********************************************************************/
+int
+unpack_ToDoAppInfo(ToDoAppInfo_t *appinfo, const unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ appinfo->type = todo_v1;
+
+ i = unpack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 4)
+ return 0;
+ appinfo->dirty = get_short(record);
+ record += 2;
+ appinfo->sortByPriority = get_byte(record);
+ record += 2;
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_ToDoAppInfo
+ *
+ * Summary: Pack the AppInfo block/record back into the structure
+ *
+ * Parameters: ToDoAppInfo_t*, char* to record, record length
+ *
+ * Returns: effective buffer length
+ *
+ ***********************************************************************/
+int
+pack_ToDoAppInfo(const ToDoAppInfo_t *appinfo, unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!record)
+ return i + 4;
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 4)
+ return 0;
+ set_short(record, appinfo->dirty);
+ set_byte(record + 2, appinfo->sortByPriority);
+ set_byte(record + 3, 0); /* gapfill */
+ record += 4;
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/unixserial.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/unixserial.c
new file mode 100644
index 00000000..4cf48db9
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/unixserial.c
@@ -0,0 +1,745 @@
+/*
+ * $Id: unixserial.c,v 1.53 2006/10/12 14:21:23 desrod Exp $
+ *
+ * unixserial.c: tty line interface code for Pilot serial comms under UNIX
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h> /* Needed for Redhat 6.x machines */
+#include <fcntl.h>
+#include <string.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-serial.h"
+#include "pi-error.h"
+
+/* if this is running on a NeXT system... */
+#ifdef NeXT
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_COMPAT_H
+#include <sys/ioctl_compat.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef SGTTY
+
+#ifndef HAVE_CFMAKERAW
+#define cfmakeraw(ptr) (ptr)->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR\
+ |IGNCR|ICRNL|IXON);\
+ (ptr)->c_oflag &= ~OPOST;\
+ (ptr)->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);\
+ (ptr)->c_cflag &= ~(CSIZE|PARENB);\
+ (ptr)->c_cflag |= CS8
+#endif
+
+#ifndef HAVE_CFSETSPEED
+#if defined(HAVE_CFSETISPEED) && defined(HAVE_CFSETOSPEED)
+#define cfsetspeed(t,speed) \
+ (cfsetispeed(t,speed) || cfsetospeed(t,speed))
+#else
+static int cfsetspeed(struct termios *t, int speed)
+{
+#ifdef HAVE_TERMIOS_CSPEED
+ t->c_ispeed = speed;
+ t->c_ospeed = speed;
+#else
+ t->c_cflag |= speed;
+#endif
+ return 0;
+}
+#endif
+#endif
+
+#endif /* SGTTY */
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+
+/* Linux versions "before 2.1.8 or so" fail to flush hardware FIFO on port
+ close */
+#ifdef linux
+# ifndef LINUX_VERSION_CODE
+# include <linux/version.h>
+# endif
+# ifndef LINUX_VERSION_CODE
+# define sleeping_beauty
+# else
+# if (LINUX_VERSION_CODE < 0x020108)
+# define sleeping_beauty
+# endif
+# endif
+#endif
+
+/* Unspecified NetBSD versions fail to flush hardware FIFO on port close */
+#if defined(__NetBSD__) || defined (__OpenBSD__)
+# define sleeping_beauty
+#endif
+
+/* Unspecified BSD/OS versions fail to flush hardware FIFO on port close */
+#ifdef __bsdi__
+# define sleeping_beauty
+#endif
+
+/* SGI IRIX fails to flush hardware FIFO on port close */
+#ifdef __sgi
+# define sleeping_beauty
+#endif
+
+/* Declare prototypes */
+static int s_open(pi_socket_t *ps, struct pi_sockaddr *addr,
+ size_t addrlen);
+static int s_close(pi_socket_t *ps);
+static int s_changebaud(pi_socket_t *ps);
+static ssize_t s_write(pi_socket_t *ps, const unsigned char *buf,
+ size_t len, int flags);
+static ssize_t s_read(pi_socket_t *ps, pi_buffer_t *buf, size_t len,
+ int flags);
+static int s_poll(pi_socket_t *ps, int timeout);
+
+static speed_t calcrate(int baudrate);
+void pi_serial_impl_init (struct pi_serial_impl *impl);
+static int s_flush(pi_socket_t *ps, int flags);
+
+#ifdef sleeping_beauty
+static void s_delay(time_t sec, suseconds_t usec);
+#endif
+
+
+/***********************************************************************
+ *
+ * Function: s_open
+ *
+ * Summary: Open the serial port and establish a connection for
+ * unix
+ *
+ * Parameters: pi_socket_t*, pi_socket_taddr*, size_t
+ *
+ * Returns: The file descriptor or negative on error
+ *
+ ***********************************************************************/
+int
+s_open(pi_socket_t *ps, struct pi_sockaddr *addr, size_t addrlen)
+{
+ int fd,
+ i;
+ char *tty = addr->pi_device;
+
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+
+#ifndef SGTTY
+ struct termios tcn;
+#else
+ struct sgttyb tcn;
+#endif
+ if ((fd = open(tty, O_RDWR | O_NONBLOCK)) < 0) {
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM; /* errno already set */
+ }
+
+ if (!isatty(fd)) {
+ close(fd);
+ errno = EINVAL;
+ ps->last_error = PI_ERR_GENERIC_SYSTEM;
+ return PI_ERR_GENERIC_SYSTEM;
+ }
+
+#ifndef SGTTY
+ /* Set the tty to raw and to the correct speed */
+ tcgetattr(fd, &tcn);
+
+ data->tco = tcn;
+ tcn.c_oflag = 0;
+ tcn.c_iflag = IGNBRK | IGNPAR;
+ tcn.c_cflag = CREAD | CLOCAL | CS8;
+
+ cfsetspeed(&tcn, calcrate(data->rate));
+
+ tcn.c_lflag = NOFLSH;
+
+ cfmakeraw(&tcn);
+
+ for (i = 0; i < 16; i++)
+ tcn.c_cc[i] = 0;
+
+ tcn.c_cc[VMIN] = 1;
+ tcn.c_cc[VTIME] = 0;
+
+ tcsetattr(fd, TCSANOW, &tcn);
+#else
+ /* Set the tty to raw and to the correct speed */
+ ioctl(fd, TIOCGETP, &tcn);
+
+ data->tco = tcn;
+
+ tcn.sg_flags = RAW;
+ tcn.sg_ispeed = calcrate(data->rate);
+ tcn.sg_ospeed = calcrate(data->rate);
+
+ ioctl(fd, TIOCSETN, &tcn);
+#endif
+
+ if ((i = fcntl(fd, F_GETFL, 0)) != -1) {
+ i &= ~O_NONBLOCK;
+ fcntl(fd, F_SETFL, i);
+ }
+
+ if ((i = pi_socket_setsd(ps, fd)) < 0)
+ return i;
+
+ return fd;
+}
+
+
+/***********************************************************************
+ *
+ * Function: s_close
+ *
+ * Summary: Close the open socket/file descriptor
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+s_close(pi_socket_t *ps)
+{
+#ifdef sleeping_beauty
+ s_delay(2, 0);
+#endif
+
+#if 0 /* previous test would never allow this code to execute */
+ #ifndef SGTTY
+ tcsetattr(ps->sd, TCSADRAIN, &data->tco);
+ #else
+ ioctl(ps->sd, TIOCSETP, &data->tco);
+ #endif
+#endif
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO,
+ "DEV CLOSE unixserial fd: %d\n", ps->sd));
+
+ return close(ps->sd);
+}
+
+
+/***********************************************************************
+ *
+ * Function: s_poll
+ *
+ * Summary: poll the open socket/file descriptor
+ *
+ * Parameters: pi_socket_t*, timeout in milliseconds
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+s_poll(pi_socket_t *ps, int timeout)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ if (timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+ if (select(ps->sd + 1, &ready, 0, 0, &t) == 0)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ if (!FD_ISSET(ps->sd, &ready)) {
+ /* otherwise throw out any current packet and return */
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV POLL unixserial timeout\n"));
+ data->rx_errors++;
+ errno = ETIMEDOUT;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV POLL unixserial found data on fd: %d\n", ps->sd));
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: s_write
+ *
+ * Summary: Write to the open socket/file descriptor
+ *
+ * Parameters: pi_socket_t*, unsigned char* to buf, buf length
+ *
+ * Returns: number of bytes written or negative on error
+ *
+ ***********************************************************************/
+static ssize_t
+s_write(pi_socket_t *ps, const unsigned char *buf, size_t len,
+ int flags)
+{
+ ssize_t total,
+ nwrote;
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ total = len;
+ while (total > 0) {
+ if (data->timeout == 0)
+ select(ps->sd + 1, 0, &ready, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ if (select(ps->sd + 1, 0, &ready, 0, &t) == 0)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ if (!FD_ISSET(ps->sd, &ready))
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+
+ nwrote = write(ps->sd, buf, len);
+ if (nwrote < 0) {
+ if (errno == EPIPE || errno == EBADF) {
+ ps->state = PI_SOCK_CONN_BREAK;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_DISCONNECTED);
+ }
+ return pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ }
+ total -= nwrote;
+ }
+ data->tx_bytes += len;
+
+ /* hack to slow things down so that the Visor will work */
+ usleep(10 + len);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV TX unixserial wrote %d bytes\n", len));
+
+ return len;
+}
+
+
+/***********************************************************************
+ *
+ * Function: s_read_buf
+ *
+ * Summary: read from data buffer
+ *
+ * Parameters: pi_socket_t*, pi_buffer_t* to buf, length to get
+ *
+ * Returns: number of bytes read
+ *
+ ***********************************************************************/
+static size_t
+s_read_buf (pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+ size_t rbuf = data->buf_size;
+
+ if (rbuf > len)
+ rbuf = len;
+
+ if (pi_buffer_append (buf, data->buf, rbuf) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ if (flags != PI_MSG_PEEK) {
+ data->buf_size -= rbuf;
+ if (data->buf_size > 0)
+ memmove(data->buf, &data->buf[rbuf], data->buf_size);
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV RX unixserial read %d bytes from read-ahead buffer\n", rbuf));
+
+ return rbuf;
+}
+
+/***********************************************************************
+ *
+ * Function: s_read
+ *
+ * Summary: Read incoming data from the socket/file descriptor
+ *
+ * Parameters: pi_socket_t*, pi_buffer_t* to buf, expect length, flags
+ *
+ * Returns: number of bytes read or negative on error
+ *
+ ***********************************************************************/
+static ssize_t
+s_read(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ ssize_t rbuf = 0,
+ bytes;
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ /* check whether we have at least partial data in store */
+ if (data->buf_size) {
+ rbuf = s_read_buf(ps, buf, len, flags);
+ if (rbuf < 0)
+ return rbuf;
+ len -= rbuf;
+ if (len == 0)
+ return rbuf;
+ }
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+ if (data->timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ if (select(ps->sd + 1, &ready, 0, 0, &t) == 0)
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ /* If data is available in time, read it */
+ if (FD_ISSET(ps->sd, &ready)) {
+ if (flags == PI_MSG_PEEK && len > 256)
+ len = 256;
+
+ if (pi_buffer_expect (buf, len) == NULL) {
+ errno = ENOMEM;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ bytes = read(ps->sd, &buf->data[buf->used], len);
+
+ if (bytes > 0) {
+ if (flags == PI_MSG_PEEK) {
+ memcpy(data->buf + data->buf_size, buf->data + buf->used, bytes);
+ data->buf_size += bytes;
+ }
+ buf->used += bytes;
+ data->rx_bytes += bytes;
+ rbuf += bytes;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV RX unixserial read %d bytes\n", bytes));
+ } else if (bytes < 0) {
+ rbuf = bytes;
+ }
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN,
+ "DEV RX unixserial timeout\n"));
+ data->rx_errors++;
+ errno = ETIMEDOUT;
+ return pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ }
+
+ return rbuf;
+}
+
+/***********************************************************************
+ *
+ * Function: s_flush
+ *
+ * Summary: Flush incoming and/or outgoing data from the socket/file
+ * descriptor
+ *
+ * Parameters: ps is of type pi_socket that contains the sd member which is
+ * the file descriptor that the data in buf will be read. It
+ * also contains the read buffer.
+ *
+ * flags is of type int and can be a combination of
+ * PI_FLUSH_INPUT and PI_FLUSH_OUTPUT
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+static int
+s_flush(pi_socket_t *ps, int flags)
+{
+ int fl;
+ char buf[256];
+ struct pi_serial_data *data = (struct pi_serial_data *) ps->device->data;
+
+ if (flags & PI_FLUSH_INPUT) {
+ /* clear internal buffer */
+ data->buf_size = 0;
+
+ /* flush pending data (we assume the socket is in blocking mode) */
+ if ((fl = fcntl(ps->sd, F_GETFL, 0)) != -1)
+ {
+ fcntl(ps->sd, F_SETFL, fl | O_NONBLOCK);
+ while (recv(ps->sd, buf, sizeof(buf), 0) > 0)
+ ;
+ fcntl(ps->sd, F_SETFL, fl);
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV FLUSH unixserial flushed input buffer\n"));
+ }
+ return 0;
+}
+
+#ifdef sleeping_beauty
+/***********************************************************************
+ *
+ * Function: s_delay
+ *
+ * Summary: Delay for a given period of time
+ *
+ * Parameters: seconds, microseconds
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static void
+s_delay(time_t sec, suseconds_t usec)
+{
+ struct timeval tv;
+
+ tv.tv_sec = sec;
+ tv.tv_usec = usec;
+
+ select(0, 0, 0, 0, &tv);
+}
+#endif
+
+
+/***********************************************************************
+ *
+ * Function: s_changebaud
+ *
+ * Summary: Change the speed of the socket
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: 0 on success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+s_changebaud(pi_socket_t *ps)
+{
+ struct pi_serial_data *data =
+ (struct pi_serial_data *)ps->device->data;
+#ifndef SGTTY
+ struct termios tcn;
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG,
+ "DEV SPEED unixserial switch to %d bps\n", (int)data->rate));
+
+#ifdef sleeping_beauty
+ s_delay(0, 200000);
+#endif
+ /* Set the tty to the new speed */
+ if (tcgetattr(ps->sd, &tcn))
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+
+ tcn.c_cflag = CREAD | CLOCAL | CS8;
+ cfsetspeed(&tcn, calcrate(data->rate));
+
+ if (tcsetattr(ps->sd, TCSADRAIN, &tcn))
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+
+#else
+ struct sgttyb tcn;
+
+ if (ioctl(ps->sd, TIOCGETP, &tcn))
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+
+ tcn.sg_ispeed = calcrate(data->rate);
+ tcn.sg_ospeed = calcrate(data->rate);
+
+ if (ioctl(ps->sd, TIOCSETN, &tcn))
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+#endif
+
+#ifdef sleeping_beauty
+ s_delay(0, 200000);
+#endif
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_serial_impl_init
+ *
+ * Summary: initialize function pointers for serial I/O operations
+ *
+ * Parameters: struct pi_serial_impl*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+void
+pi_serial_impl_init (struct pi_serial_impl *impl)
+{
+ impl->open = s_open;
+ impl->close = s_close;
+ impl->changebaud = s_changebaud;
+ impl->write = s_write;
+ impl->read = s_read;
+ impl->flush = s_flush;
+ impl->poll = s_poll;
+}
+
+
+/***********************************************************************
+ *
+ * Function: calcrate
+ *
+ * Summary: validates the selected baudrate
+ *
+ * Paramters: buadrate
+ *
+ * Returns: POSIX defined baudrate constant or terminates the process
+ * if the requested baudrate is not supported.
+ *
+ ***********************************************************************/
+static speed_t
+calcrate(int baudrate)
+{
+#ifdef B50
+ if (baudrate == 50)
+ return B50;
+#endif
+#ifdef B75
+ if (baudrate == 75)
+ return B75;
+#endif
+#ifdef B110
+ if (baudrate == 110)
+ return B110;
+#endif
+#ifdef B134
+ if (baudrate == 134)
+ return B134;
+#endif
+#ifdef B150
+ if (baudrate == 150)
+ return B150;
+#endif
+#ifdef B200
+ if (baudrate == 200)
+ return B200;
+#endif
+#ifdef B300
+ if (baudrate == 300)
+ return B300;
+#endif
+#ifdef B600
+ if (baudrate == 600)
+ return B600;
+#endif
+#ifdef B1200
+ if (baudrate == 1200)
+ return B1200;
+#endif
+#ifdef B1800
+ if (baudrate == 1800)
+ return B1800;
+#endif
+#ifdef B2400
+ if (baudrate == 2400)
+ return B2400;
+#endif
+#ifdef B4800
+ if (baudrate == 4800)
+ return B4800;
+#endif
+#ifdef B9600
+ if (baudrate == 9600)
+ return B9600;
+#endif
+#ifdef B19200
+ else if (baudrate == 19200)
+ return B19200;
+#endif
+#ifdef B38400
+ else if (baudrate == 38400)
+ return B38400;
+#endif
+#ifdef B57600
+ else if (baudrate == 57600)
+ return B57600;
+#endif
+#ifdef B76800
+ else if (baudrate == 76800)
+ return B76800;
+#endif
+#ifdef B115200
+ else if (baudrate == 115200)
+ return B115200;
+#endif
+#ifdef B230400
+ else if (baudrate == 230400)
+ return B230400;
+#endif
+#ifdef B460800
+ else if (baudrate == 460800)
+ return B460800;
+#endif
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
+ "DEV Serial CHANGEBAUD Unable to set baud rate %d\n",
+ baudrate));
+ abort(); /* invalid baud rate */
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/usb.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/usb.c
new file mode 100644
index 00000000..050e52f5
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/usb.c
@@ -0,0 +1,1099 @@
+/*
+ * $Id: usb.c,v 1.57 2009/05/25 04:19:46 desrod Exp $
+ *
+ * usb.c: Interface layer to serial HotSync connections
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 2005, Florent Pillet
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-usb.h"
+#include "pi-net.h"
+#include "pi-cmp.h"
+#include "pi-error.h"
+#include "pi-util.h"
+
+pi_protocol_t *pi_usb_protocol_dup (pi_protocol_t *prot);
+
+static int pi_usb_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_usb_bind(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_usb_listen(pi_socket_t *ps, int backlog);
+static int pi_usb_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen);
+static int pi_usb_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len);
+static int pi_usb_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len);
+static int pi_usb_close(pi_socket_t *ps);
+
+static int USB_configure_visor (pi_usb_data_t *dev, u_int8_t *input_pipe, u_int8_t *output_pipe);
+static int USB_configure_generic (pi_usb_data_t *dev, u_int8_t *input_pipe, u_int8_t *output_pipe);
+
+int pi_socket_init(pi_socket_t *ps);
+
+/* Protocol Functions */
+/***********************************************************************
+ *
+ * Function: pi_usb_protocol_dup
+ *
+ * Summary: creates a new copy of a USB pi_protocol instance
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: new pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_protocol_t *
+pi_usb_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ ASSERT(prot != NULL);
+
+ new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+
+ if (new_prot != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+ new_prot->data = NULL;
+ }
+
+ return new_prot;
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_usb_protocol_free
+ *
+ * Summary: frees USB pi_protocol instance
+ *
+ * Parameters: pi_protocol_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_usb_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT(prot != NULL);
+
+ if (prot != NULL)
+ free(prot);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_usb_protocol
+ *
+ * Summary: creates a new USB pi_protocol instance
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: new pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t *
+pi_usb_protocol (pi_device_t *dev)
+{
+ pi_protocol_t *prot;
+ pi_usb_data_t *data;
+
+ ASSERT(dev != NULL);
+
+ data = dev->data;
+
+ prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
+
+ if (prot != NULL) {
+ prot->level = PI_LEVEL_DEV;
+ prot->dup = pi_usb_protocol_dup;
+ prot->free = pi_usb_protocol_free;
+ prot->read = data->impl.read;
+ prot->write = data->impl.write;
+ prot->flush = data->impl.flush;
+ prot->getsockopt = pi_usb_getsockopt;
+ prot->setsockopt = pi_usb_setsockopt;
+ prot->data = NULL;
+ }
+
+ return prot;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_usb_device_free
+ *
+ * Summary: frees USB pi_device instance
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_usb_device_free (pi_device_t *dev)
+{
+ pi_usb_data_t *data = (pi_usb_data_t *)dev->data;
+
+ ASSERT(dev != NULL);
+
+ if (data != NULL)
+ free(data);
+ if (dev != NULL)
+ free(dev);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_usb_device
+ *
+ * Summary: creates a new USB pi_device instance
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: new pi_device_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_device_t *
+pi_usb_device (int type)
+{
+ pi_device_t *dev;
+ pi_usb_data_t *data;
+
+ dev = (pi_device_t *)malloc (sizeof (pi_device_t));
+ if (dev != NULL) {
+ data = (pi_usb_data_t *)malloc (sizeof (struct pi_usb_data));
+ if (data == NULL) {
+ free(dev);
+ dev = NULL;
+ } else {
+ dev->free = pi_usb_device_free;
+ dev->protocol = pi_usb_protocol;
+ dev->bind = pi_usb_bind;
+ dev->listen = pi_usb_listen;
+ dev->accept = pi_usb_accept;
+ dev->connect = pi_usb_connect;
+ dev->close = pi_usb_close;
+
+ memset(data, 0, sizeof(struct pi_usb_data));
+ data->rate = -1;
+ data->establishrate = -1;
+ data->establishhighrate = 0;
+ pi_usb_impl_init (&data->impl);
+
+ dev->data = data;
+ }
+ }
+
+ return dev;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_usb_connect
+ *
+ * Summary: Connect socket to a given address
+ *
+ * Parameters: pi_socket_t*, sockaddr*, socket length
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_usb_connect(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ struct pi_usb_data *data = (pi_usb_data_t *)ps->device->data;
+ struct pi_sockaddr *pa = (struct pi_sockaddr *) addr;
+ int result, timeout;
+ size_t size;
+
+ if (ps->type == PI_SOCK_STREAM) {
+ if (ps->protocol == PI_PF_SYS) {
+ data->establishrate = data->rate = 57600;
+ } else {
+ if (data->establishrate == -1)
+ get_pilot_rate(&data->establishrate, &data->establishhighrate);
+
+ /* Mandatory CMP connection rate */
+ data->rate = 9600;
+ }
+ } else if (ps->type == PI_SOCK_RAW) {
+ /* Mandatory SysPkt connection rate */
+ data->establishrate = data->rate = 57600;
+ }
+
+ result = data->impl.open(ps, pa, addrlen);
+ if (result < 0)
+ goto fail;
+
+ data->timeout = timeout = ps->accept_to * 1000;
+
+ if (data->impl.wait_for_device) {
+ result = data->impl.wait_for_device (ps, &timeout);
+ if (result <= 0)
+ goto fail;
+ }
+
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ if (ps->type == PI_SOCK_STREAM) {
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if ((result = cmp_tx_handshake(ps)) < 0)
+ goto fail;
+ size = sizeof(data->rate);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_BAUD,
+ &data->rate, &size);
+ if ((result = data->impl.changebaud(ps)) < 0)
+ goto fail;
+ break;
+
+ case PI_CMD_NET:
+ if ((result = net_tx_handshake(ps)) < 0)
+ goto fail;
+ break;
+ }
+ }
+ ps->state = PI_SOCK_CONN_INIT;
+ ps->command = 0;
+
+fail:
+ return (result < 0) ? result : 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_usb_bind
+ *
+ * Summary: Bind address to a local socket
+ *
+ * Parameters: pi_socket_t*, sockaddr*, socket length
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_usb_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ struct pi_usb_data *data = (pi_usb_data_t *)ps->device->data;
+ struct pi_sockaddr *pa = (struct pi_sockaddr *) addr;
+ int result;
+
+ /* this rate stuff is only useful on platforms where USB-serial adapters
+ * connect through the USB layer, not through a serial tty
+ */
+ if (ps->type == PI_SOCK_STREAM) {
+ if (data->establishrate == -1)
+ get_pilot_rate(&data->establishrate, &data->establishhighrate);
+
+ /* Mandatory CMP connection rate */
+ data->rate = 9600;
+ } else if (ps->type == PI_SOCK_RAW) {
+ /* Mandatory SysPkt connection rate */
+ data->establishrate = data->rate = 57600;
+ }
+
+ result = data->impl.open(ps, pa, addrlen);
+ if (result < 0)
+ return result;
+
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_usb_listen
+ *
+ * Summary: Prepare for incoming connections
+ *
+ * Parameters: pi_socket_t*, backlog
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+static int
+pi_usb_listen(pi_socket_t *ps, int backlog)
+{
+ ps->state = PI_SOCK_LISTEN;
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_usb_accept
+ *
+ * Summary: Accept an incoming connection
+ *
+ * Parameters: pi_socket_t*, sockaddr*, socket length
+ *
+ * Returns: pi_socket descriptor or negative on error
+ *
+ ***********************************************************************/
+static int
+pi_usb_accept(pi_socket_t *ps, struct sockaddr *addr, size_t *addrlen)
+{
+ struct pi_usb_data *data = (pi_usb_data_t *)ps->device->data;
+ int result,
+ timeout;
+ size_t size;
+
+ data->timeout = timeout = ps->accept_to * 1000;
+
+ if (data->impl.wait_for_device) {
+ result = data->impl.wait_for_device (ps, &timeout);
+ if (result <= 0)
+ return result;
+ }
+
+ /* Wait for data */
+#ifdef LINUX
+ /*
+ * Evilish kluge, some palm devices won't send the initial
+ * packets if we don't try and get them fairly quickly.
+ *
+ * Sending a 0 byte NET packet can get them talking again
+ * in some cases though.
+ */
+ result = data->impl.poll(ps, 1000);
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d, poll result: %d.\n", __FILE__, __LINE__, result));
+
+ if (result <= 0) {
+ char buf[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ data->impl.write(ps, buf, sizeof (buf), 1000);
+ }
+#endif
+
+ result = data->impl.poll(ps, timeout);
+ if (result <= 0) {
+ if (result == 0) {
+ return(PI_ERR_SOCK_LISTENER);
+ } else {
+ return result;
+ }
+ }
+
+ pi_socket_init(ps);
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d, prot: 0x%x, type: 0x%x, cmd: 0x%x.\n", __FILE__, __LINE__, ps->protocol, ps->type, ps->cmd));
+ if (ps->type == PI_SOCK_STREAM) {
+ struct timeval tv;
+ unsigned char cmp_flags;
+
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d, cmp rx.\n", __FILE__, __LINE__));
+ if ((result = cmp_rx_handshake(ps, data->establishrate, data->establishhighrate)) < 0)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "usb.c: cmp_rx_handshake returned %d\n", result));
+ return result;
+ }
+
+ /* propagate the long packet format flag to both command and non-command stacks */
+ size = sizeof(cmp_flags);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_FLAGS, &cmp_flags, &size);
+ if (cmp_flags & CMP_FL_LONG_PACKET_SUPPORT) {
+ int use_long_format = 1;
+ size = sizeof(int);
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
+ &use_long_format, &size);
+ ps->command ^= 1;
+ pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
+ &use_long_format, &size);
+ ps->command ^= 1;
+ }
+
+ /* reconfigure the port to match the negotiated speed */
+ size = sizeof(data->rate);
+ pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_BAUD, &data->rate, &size);
+ if (data->impl.changebaud != NULL) {
+ if ((result = data->impl.changebaud(ps)) < 0)
+ return result;
+
+ /* handheld needs some time to reconfigure its port */
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+ select(0, 0, 0, 0, &tv);
+ }
+ break;
+
+ case PI_CMD_NET:
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d, net rx.\n", __FILE__, __LINE__));
+ if ((result = net_rx_handshake(ps)) < 0)
+ {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "usb.c: cmp_rx_handshake returned %d\n", result));
+ return result;
+ }
+ break;
+
+ default:
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "%s: %d, unknown rx %x.\n", __FILE__, __LINE__,ps->cmd));
+ break;
+ }
+ ps->dlprecord = 0;
+ }
+
+ data->timeout = 0;
+ ps->command = 0;
+ ps->state = PI_SOCK_CONN_ACCEPT;
+ return ps->sd;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_usb_getsockopt
+ *
+ * Summary: get options on USB socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_usb_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ pi_usb_data_t *data = (pi_usb_data_t *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_RATE:
+ if (*option_len != sizeof (data->rate))
+ goto fail;
+ memcpy (option_value, &data->rate, sizeof (data->rate));
+ break;
+
+ case PI_DEV_ESTRATE:
+ if (*option_len != sizeof (data->establishrate))
+ goto fail;
+ memcpy (option_value, &data->establishrate,
+ sizeof (data->establishrate));
+ break;
+
+ case PI_DEV_HIGHRATE:
+ if (*option_len != sizeof (data->establishhighrate))
+ goto fail;
+ memcpy (option_value, &data->establishhighrate,
+ sizeof (data->establishhighrate));
+ break;
+
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout))
+ goto fail;
+ memcpy (option_value, &data->timeout,
+ sizeof (data->timeout));
+ break;
+ }
+
+ return 0;
+
+fail:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_usb_setsockopt
+ *
+ * Summary: set options on USB socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_usb_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ pi_usb_data_t *data = (pi_usb_data_t *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_ESTRATE:
+ if (*option_len != sizeof (data->establishrate))
+ goto fail;
+ memcpy (&data->establishrate, option_value,
+ sizeof (data->establishrate));
+ break;
+
+ case PI_DEV_HIGHRATE:
+ if (*option_len != sizeof (data->establishhighrate))
+ goto fail;
+ memcpy (&data->establishhighrate, option_value,
+ sizeof (data->establishhighrate));
+ break;
+
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout))
+ goto fail;
+ memcpy (&data->timeout, option_value,
+ sizeof (data->timeout));
+ break;
+ }
+
+ return 0;
+
+fail:
+ errno = EINVAL;
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pi_usb_close
+ *
+ * Summary: Close a connection, destroy the socket
+ *
+ * Parameters: pi_socket_t*
+ *
+ * Returns: 0
+ *
+ ***********************************************************************/
+static int
+pi_usb_close(pi_socket_t *ps)
+{
+ pi_usb_data_t *data = (pi_usb_data_t *)ps->device->data;
+
+ if (ps->sd != 0) {
+ data->impl.close (ps);
+ ps->sd = 0;
+ }
+
+ if (ps->laddr != NULL) {
+ free(ps->laddr);
+ ps->laddr = NULL;
+ }
+ if (ps->raddr != NULL) {
+ free(ps->raddr);
+ ps->raddr = NULL;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Start of the identification and init code.
+ */
+
+/*
+ * This is the table of USB devices that we know about, what they are, and
+ * some flags.
+ *
+ * This table helps us determine whether a connecting USB device is one we'd
+ * like to talk to.
+ *
+ */
+pi_usb_dev_t known_devices[] = {
+ /* Sony */
+ {
+ .vendor = 0x054c,
+ .product = 0x0038,
+ .idstr = "Sony S S320 and other Palm OS 3.5 devices",
+ .flags = USB_INIT_SONY_CLIE,
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x0066,
+ .idstr = "Sony T, SJ series, and other Palm OS 4.0 devices",
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x0095,
+ .idstr = "Sony S360",
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x000a,
+ .idstr = "Sony NR and other Palm OS 4.1 devices",
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x009a,
+ .idstr = "Sony NR70V/U",
+ .flags = USB_INIT_SONY_CLIE,
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x00da,
+ .idstr = "Sony NX",
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x00e9,
+ .idstr = "Sony NZ",
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x0144,
+ .idstr = "Sony UX",
+ },
+
+ {
+ .vendor = 0x054c,
+ .product = 0x0169,
+ .idstr = "Sony TJ",
+ .flags = USB_INIT_SONY_CLIE,
+ },
+
+ /* AlphaSmart */
+ {
+ .vendor = 0x081e,
+ .product = 0xdf00,
+ .idstr = "Alphasmart Dana",
+ },
+
+ /* HANDSPRING (vendor 0x082d) */
+ {
+ .vendor = 0x082d,
+ .product = 0x0100,
+ .idstr = "Visor, Treo 300",
+ .flags = USB_INIT_VISOR,
+ },
+
+ {
+ .vendor = 0x082d,
+ .product = 0x0200,
+ .idstr = "Treo",
+ },
+
+ {
+ .vendor = 0x082d,
+ .product = 0x0300,
+ .idstr = "Treo 600",
+ },
+
+ /* PalmOne, Palm Inc */
+ {
+ .vendor = 0x0830,
+ .product = 0x0001,
+ .idstr = "m500",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0002,
+ .idstr = "m505",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0003,
+ .idstr = "m515",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0010,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0011,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0020,
+ .idstr = "i705",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0030,
+ .idstr = "Tungsten|Z",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0031,
+ .idstr = "Tungsten|W",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0040,
+ .idstr = "m125",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0050,
+ .idstr = "m130",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0051,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0052,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0053,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0060,
+ .idstr = "Tungsten series, Zire 71",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0061,
+ .idstr = "Zire 31, 72, Z22",
+ .flags = USB_INIT_TAPWAVE,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0062,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0063,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0070,
+ .idstr = "Zire",
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0071,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0080,
+ .idstr = "m100",
+ .flags = USB_INIT_NONE,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0099,
+ },
+
+ {
+ .vendor = 0x0830,
+ .product = 0x0100,
+ },
+
+ /* GARMIN */
+ {
+ .vendor = 0x091e,
+ .product = 0x0004,
+ .idstr = "IQUE 3600",
+ },
+
+ /* Kyocera */
+ {
+ .vendor = 0x0c88,
+ .product = 0x0021,
+ .idstr = "7135 Smartphone",
+ },
+
+ {
+ .vendor = 0x0c88,
+ .product = 0xa226,
+ .idstr = "6035 Smartphone",
+ },
+
+ /* Tapwave */
+ {
+ .vendor = 0x12ef,
+ .product = 0x0100,
+ .idstr = "Zodiac, Zodiac2",
+ .flags = USB_INIT_TAPWAVE,
+ },
+
+ /* ACEECA */
+ {
+ .vendor = 0x4766,
+ .product = 0x0001,
+ .idstr = "MEZ1000",
+ },
+
+ /* Samsung */
+ {
+ .vendor = 0x04e8,
+ .product = 0x8001,
+ .idstr = "i330",
+ },
+};
+
+int
+USB_check_device (pi_usb_data_t *dev, u_int16_t vendor, u_int16_t product)
+{
+ unsigned int i;
+
+ for (i = 0; i < (sizeof (known_devices) / sizeof (known_devices[0])); i++) {
+ if (known_devices[i].vendor == vendor) {
+ if (!known_devices[i].product ||
+ known_devices[i].product == product) {
+ dev->dev.flags |= known_devices[i].flags;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+
+/*
+ * Device configuration, ugh.
+ */
+
+int
+USB_configure_device (pi_usb_data_t *dev, u_int8_t *input_pipe, u_int8_t *output_pipe)
+{
+ int ret;
+ u_int32_t flags = dev->dev.flags;
+
+ *input_pipe = 0xff;
+ *output_pipe = 0xff;
+
+ /*
+ * Device specific magic incantations
+ *
+ * Many devices agree on talking only if you say the "magic" incantation first.
+ * Usually, it's a control request or a sequence of control requests
+ *
+ */
+
+ if (flags & USB_INIT_NONE)
+ return 0;
+ if (flags & USB_INIT_VISOR)
+ ret = USB_configure_visor (dev, input_pipe, output_pipe);
+ else if (flags & USB_INIT_SONY_CLIE) {
+ /* according to linux code, PEG S-300 awaits these two requests */
+ /* USB_REQ_GET_CONFIGURATION */
+ ret = dev->impl.control_request (dev, 0x80, 0x08, 0, 0, NULL, 1, 0);
+ if (ret < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "usb: Sony USB_REQ_GET_CONFIGURATION failed (err=%08x)\n", ret));
+ }
+ /* USB_REQ_GET_INTERFACE */
+ ret = dev->impl.control_request (dev, 0x80, 0x0A, 0, 0, NULL, 1, 0);
+ if (ret < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "usb: Sony USB_REQ_GET_INTERFACE failed (err=%08x)\n", ret));
+ }
+ } else {
+ /* other devices will either accept or deny this generic call */
+ ret = USB_configure_generic (dev, input_pipe, output_pipe);
+ if (ret < 0) {
+ return -1;
+ }
+ }
+
+ /* query bytes available. Not that we really care,
+ but most devices expect to receive this before
+ they agree on talking to us. */
+ if (!(flags & USB_INIT_TAPWAVE)) {
+ unsigned char ba[2] = { 0 };
+
+ ret = dev->impl.control_request (dev, 0xc2, GENERIC_REQUEST_BYTES_AVAILABLE, 0, 0, &ba[0], 2, 0);
+ if (ret < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "usb: GENERIC_REQUEST_BYTES_AVAILABLE failed (err=%08x)\n", ret));
+ /* configuration have to fail to skip this device - or LifeDrive(?) devices will hang */
+ return -1;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "GENERIC_REQUEST_BYTES_AVAILABLE returns 0x%02x%02x\n", ba[0], ba[1]));
+ }
+
+ return 0;
+}
+
+static int
+USB_configure_visor (pi_usb_data_t *dev, u_int8_t *input_pipe, u_int8_t *output_pipe)
+{
+ int i, ret;
+ visor_connection_info_t ci;
+
+ ret = dev->impl.control_request (dev, 0xc2, VISOR_GET_CONNECTION_INFORMATION, 0, 0, &ci, sizeof (ci), 0);
+ if (ret < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "usb: VISOR_GET_CONNECTION_INFORMATION failed (err=%08x)\n", ret));
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "usb: VISOR_GET_CONNECTION_INFORMATION, num_ports=%d\n", ci.num_ports));
+ if (ci.num_ports > 2)
+ ci.num_ports = 2;
+ for (i=0; i < ci.num_ports; i++)
+ {
+ char *function_str;
+ switch (ci.connections[i].port_function_id)
+ {
+ case VISOR_FUNCTION_GENERIC:
+ function_str="GENERIC";
+ break;
+ case VISOR_FUNCTION_DEBUGGER:
+ function_str="DEBUGGER";
+ break;
+ case VISOR_FUNCTION_HOTSYNC:
+ function_str="HOTSYNC";
+ break;
+ case VISOR_FUNCTION_CONSOLE:
+ function_str="CONSOLE";
+ break;
+ case VISOR_FUNCTION_REMOTE_FILE_SYS:
+ function_str="REMOTE_FILE_SYSTEM";
+ break;
+ default:
+ function_str="UNKNOWN";
+ break;
+ }
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port_function_id=0x%02x (%s)\n", i,
+ ci.connections[i].port_function_id,
+ function_str));
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port=%d\n", i,
+ ci.connections[i].port));
+ }
+ }
+ return ret;
+}
+
+static int
+USB_configure_generic (pi_usb_data_t *dev, u_int8_t *input_pipe, u_int8_t *output_pipe)
+{
+ int i, ret;
+ int hotsync = 0;
+ palm_ext_connection_info_t ci;
+ u_int32_t flags = dev->dev.flags;
+
+ ret = dev->impl.control_request (dev, 0xc2, PALM_GET_EXT_CONNECTION_INFORMATION, 0, 0, &ci, sizeof (ci), 0);
+ if (ret < 0) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "usb: PALM_GET_EXT_CONNECTION_INFORMATION failed (err=%08x)\n", ret));
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "usb: PALM_GET_EXT_CONNECTION_INFORMATION, num_ports=%d, endpoint_numbers_different=%d\n",
+ ci.num_ports,
+ ci.endpoint_numbers_different));
+ for (i=0; i < ci.num_ports; i++) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port_function_id='%c%c%c%c'\n", i,
+ ci.connections[i].port_function_id[0],
+ ci.connections[i].port_function_id[1],
+ ci.connections[i].port_function_id[2],
+ ci.connections[i].port_function_id[3]));
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] port=%d\n", i,
+ ci.connections[i].port));
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "\t[%d] endpoint_info=%d\n", i,
+ ci.connections[i].endpoint_info));
+ if (!memcmp(ci.connections[i].port_function_id, "cnys", 4)) {
+
+ /* found hotsync port */
+ hotsync = 1;
+
+ /* 'sync': we found the pipes to use for synchronization force
+ find_interfaces to select this one rather than another one */
+ if (ci.endpoint_numbers_different) {
+ if (input_pipe)
+ *input_pipe = ci.connections[i].endpoint_info >> 4;
+ if (output_pipe)
+ *output_pipe = ci.connections[i].endpoint_info & 0x0f;
+ } else {
+ if (input_pipe)
+ *input_pipe = ci.connections[i].port;
+ if (output_pipe)
+ *output_pipe = ci.connections[i].port;
+ }
+ }
+ }
+
+ if (!hotsync) {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_ERR, "usb: PALM_GET_EXT_CONNECTION_INFORMATION - no hotsync port found.\n", ret));
+ return -1;
+ }
+ }
+
+ if (flags & USB_INIT_TAPWAVE) {
+ /*
+ * Tapwave: for Zodiac, the TwUSBD.sys driver on Windows sends
+ * the ext-connection-info packet two additional times.
+ */
+ ret = dev->impl.control_request (dev, 0xc2, PALM_GET_EXT_CONNECTION_INFORMATION, 0, 0, &ci, sizeof (ci), 0);
+ ret = dev->impl.control_request (dev, 0xc2, PALM_GET_EXT_CONNECTION_INFORMATION, 0, 0, &ci, sizeof (ci), 0);
+ }
+ return ret;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/utils.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/utils.c
new file mode 100644
index 00000000..eb2cc1c9
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/utils.c
@@ -0,0 +1,413 @@
+/*
+ * $Id: utils.c,v 1.47 2006/10/12 14:21:23 desrod Exp $
+ *
+ * utils.c: misc. stuff for dealing with packets.
+ *
+ * Portions Copyright (c) 1996, D. Jeff Dionne.
+ * Portions Copyright (c) 1996, Kenneth Albanowski
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+
+void pi_timeout_to_timespec(int timeout, struct timespec *ts);
+void get_pilot_rate(int *establishrate, int *establishhighrate);
+int pi_timespec_to_timeout(const struct timespec *ts);
+int pi_timeout_expired(const struct timespec *ts);
+size_t palm_strftime(char *s, size_t max, const char *fmt,
+ const struct tm *tm);
+
+/* this routine ruthlessly stolen verbatim from Brian J. Swetland */
+
+/***********************************************************************
+ *
+ * Function: crc16
+ *
+ * Summary: Implementation of the CRC16 Cyclic Redundancy Check
+ *
+ * Parameters: None
+ *
+ * Returns: CRC + NULL
+ *
+ ***********************************************************************/
+int crc16(unsigned char *ptr, int count)
+{
+ int crc,
+ i;
+
+ crc = 0;
+ while (--count >= 0) {
+ crc = crc ^ (int) *ptr++ << 8;
+ for (i = 0; i < 8; ++i)
+ if (crc & 0x8000)
+ crc = crc << 1 ^ 0x1021;
+ else
+ crc = crc << 1;
+ }
+ return (crc & 0xFFFF);
+}
+
+void get_pilot_rate(int *establishrate, int *establishhighrate)
+{
+ /* Default PADP connection rate */
+ char *rate_env = getenv("PILOTRATE");
+ if (rate_env) {
+ /* Establish high rate */
+ if (rate_env[0] == 'H') {
+ *establishrate = atoi(rate_env + 1);
+ *establishhighrate = 1;
+ } else {
+ *establishrate = atoi(rate_env);
+ *establishhighrate = 0;
+ }
+ }
+ else {
+ *establishrate = -1;
+ }
+}
+
+#ifndef HAVE_STRDUP
+char *strdup(const char *s)
+{
+ char *result;
+ size_t size = strlen(s) + 1;
+
+ if (!(result = malloc(size))) {
+ return NULL;
+ }
+
+ memcpy(result, s, size);
+
+ return result;
+}
+#endif
+
+/* Borrowed from GNU sh-utils, and then probably from GNU libc */
+#ifndef HAVE_PUTENV
+#if HAVE_GNU_LD
+ # define environ __environ
+#else
+ extern char **environ;
+#endif
+
+/* Put STRING, which is of the form "NAME=VALUE", in the environment */
+int putenv(const char *string)
+{
+ const char *const name_end = strchr(string, '=');
+ register size_t size;
+ register char **ep;
+
+ if (name_end == NULL) {
+ /* Remove the variable from the environment. */
+ size = strlen(string);
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp(*ep, string, size)
+ && (*ep)[size] == '=') {
+ while (ep[1] != NULL) {
+ ep[0] = ep[1];
+ ++ep;
+ }
+ *ep = NULL;
+ return 0;
+ }
+ }
+
+ size = 0;
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp(*ep, string, name_end - string)
+ && (*ep)[name_end - string] == '=')
+ break;
+ else
+ ++size;
+
+ if (*ep == NULL) {
+ static char **last_environ = NULL;
+ char **new_environ =
+ (char **) malloc((size + 2) * sizeof(char *));
+
+ if (new_environ == NULL)
+ return -1;
+ (void) memcpy((void *) new_environ, (void *) environ,
+ size * sizeof(char *));
+
+ new_environ[size] = (char *) string;
+ new_environ[size + 1] = NULL;
+ if (last_environ != NULL)
+ free((void *) last_environ);
+ last_environ = new_environ;
+ environ = new_environ;
+ } else
+ *ep = (char *) string;
+
+ return 0;
+}
+#endif
+
+#ifdef OS2
+/* Replacement version of getenv(), because the one in the EMX 0.9c, fix03
+ dist appears to be busted when called from inside a DLL. (MJJ) */
+char *getenv(const char *envar)
+{
+ APIRET rc;
+ unsigned char *envstring;
+
+ /* just call the OS/2 function directly */
+ rc = DosScanEnv(envar, &envstring);
+ if (rc)
+ return NULL;
+ else
+ return envstring;
+}
+#endif
+
+
+
+#ifndef HAVE_INET_ATON
+/***********************************************************************
+ *
+ * Function: inet_aton
+ *
+ * Summary: Manipulate our network address information
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+int inet_aton(const char *cp, struct in_addr *addr)
+{
+ register u_long val;
+ register int base;
+ register int n;
+ register char c;
+ u_int parts[4];
+ register u_int *pp = parts;
+
+ for (;;) {
+ /* Collect number up to ``.''. Values are specified as for
+ C: 0x=hex, 0=octal, other=decimal. */
+ val = 0;
+ base = 10;
+ if (*cp == '0') {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp) != '\0') {
+ if (isascii(c) && isdigit(c)) {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isascii(c) && isxdigit(c)) {
+ val =
+ (val << 4) + (c + 10 -
+ (islower(c) ? 'a' :
+ 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.') {
+ /* Internet format:
+ a.b.c.d
+ a.b.c (with c treated as 16-bits)
+ a.b (with b treated as 24 bits) */
+
+ if (pp >= parts + 3 || val > 0xff)
+ return (0);
+ *pp++ = val, cp++;
+ } else
+ break;
+ }
+ /* Check for trailing characters. */
+ if (*cp && (!isascii(*cp) || !isspace(*cp)))
+ return (0);
+
+ /* Concoct the address according to the number of parts specified. */
+ n = pp - parts + 1;
+ switch (n) {
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return (0);
+ val |=
+ (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = htonl(val);
+ return (1);
+}
+#endif
+
+char *printlong(unsigned long val)
+{
+ static char buf[5];
+
+ set_long(buf, val);
+ buf[4] = 0;
+ return buf;
+}
+
+unsigned long makelong(char *c)
+{
+ int l = strlen(c);
+ char c2[4];
+
+ if (l >= 4)
+ return get_long(c);
+ memset(c2, ' ', 4);
+ memcpy(c2, c, (size_t)l);
+ return get_long(c2);
+}
+
+double get_float(void *buffer)
+{
+ unsigned char *buf = buffer;
+ unsigned long frac = get_long(buf);
+
+ int expr = get_sshort(buf + 4),
+ sign = get_byte(buf + 6);
+
+ /* if (sign) f = frac; else f = -frac; return ldexp(f, exp); */
+ return ldexp(sign ? (double) frac : -(double) frac, expr);
+}
+
+void set_float(void *buffer, double value)
+{
+ int expr,
+ sign;
+ unsigned char *buf = buffer;
+ unsigned long frac;
+ double r;
+
+ /* Take absolute */
+ if (value < 0) {
+ sign = 0;
+ value = -value;
+ } else
+ sign = 0xFF;
+
+ /* Convert mantissa to 32-bit integer, and take exponent */
+ r = ldexp(frexp(value, &expr), 32);
+ frac = (unsigned long)r;
+ expr -= 32;
+
+ /* Store values in buffer */
+ set_long(buf, frac);
+ set_sshort(buf + 4, expr);
+ set_byte(buf + 6, sign);
+ set_byte(buf + 7, 0);
+}
+
+int compareTm(struct tm *a, struct tm *b)
+{
+ int date;
+
+ date = a->tm_year - b->tm_year;
+ if (date)
+ return date;
+ date = a->tm_mon - b->tm_mon;
+ if (date)
+ return date;
+ date = a->tm_mday - b->tm_mday;
+ if (date)
+ return date;
+ date = a->tm_hour - b->tm_hour;
+ if (date)
+ return date;
+ date = a->tm_min - b->tm_min;
+ if (date)
+ return date;
+ date = a->tm_sec - b->tm_sec;
+ return date;
+}
+
+void pi_timeout_to_timespec(int timeout, struct timespec *ts)
+{
+ /* convert a timeout value (in milliseconds) to an absolute timespec */
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ ts->tv_sec = now.tv_sec + (long)(timeout / 1000);
+ ts->tv_nsec = (now.tv_usec + ((long)timeout % 1000) * 1000) * 1000;
+ if (ts->tv_nsec >= 1000000000) {
+ ts->tv_nsec -= 1000000000;
+ ts->tv_sec++;
+ }
+}
+
+int pi_timespec_to_timeout(const struct timespec *ts)
+{
+ /* convert an absolute timespec to a timeout value (in milliseconds) from now
+ * returns a negative if the timeout expired already
+ */
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return (int)(((double)ts->tv_sec * 1000.0 + (double)ts->tv_nsec / 1000000.0) -
+ ((double)now.tv_sec * 1000.0 + (double)now.tv_usec / 1000.0));
+}
+
+int pi_timeout_expired(const struct timespec *ts)
+{
+ return pi_timespec_to_timeout(ts) <= 0;
+}
+
+/* Fix some issues with some locales reporting 2 or 4 digit years */
+size_t palm_strftime(char *s, size_t max, const char *fmt,
+ const struct tm *tm) {
+
+ return strftime(s, max, fmt, tm);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/veo.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/veo.c
new file mode 100644
index 00000000..3a8489df
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/veo.c
@@ -0,0 +1,165 @@
+/*
+ * $Id: veo.c,v 1.7 2006/10/12 14:21:23 desrod Exp $
+ *
+ * veo.c: Translate veo traveler data formats
+ *
+ * Copyright (c) 2002, Angus Ainslie
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pi-macros.h"
+#include "pi-veo.h"
+
+/***********************************************************************
+ *
+ * Function: free_Veo
+ *
+ * Summary: Free the memory and filehandle from the record alloc.
+ *
+ ***********************************************************************/
+void
+free_Veo( Veo_t *veo )
+{
+}
+
+/***********************************************************************
+ *
+ * Function: unpack_Veo
+ *
+ * Summary: Unpack the Veo structure into records we can chew on
+ *
+ ***********************************************************************/
+int
+unpack_Veo(Veo_t *veo, unsigned char *buffer, size_t len)
+{
+ unsigned char *start = buffer;
+
+ /* consume unknown */
+ buffer += 1;
+ veo->quality = (unsigned char) get_byte(buffer);
+ buffer += 1;
+ veo->resolution = (unsigned char) get_byte(buffer);
+ buffer += 1;
+ /* consume 12 more unknowns */
+ buffer += 12;
+ veo->picnum = (unsigned long int) get_long(buffer);
+ buffer += 4;
+ veo->day = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ veo->month = (unsigned short int) get_short(buffer);
+ buffer += 2;
+ veo->year = (unsigned short int) get_short(buffer);
+ buffer += 2;
+
+ if( veo->resolution == 0 )
+ {
+ veo->width = 640;
+ veo->height = 480;
+ }
+ else if( veo->resolution == 1 )
+ {
+ veo->width = 320;
+ veo->height = 240;
+ }
+ else
+ fprintf( stderr, "unknown resolution\n" );
+
+ return ( buffer - start ); /* FIXME: return real length */
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_Veo
+ *
+ * Summary: Pack the Veo records into a structure
+ *
+ ***********************************************************************/
+int pack_Veo(Veo_t *veo, unsigned char *buf, size_t len)
+{
+ return( 0 );
+}
+
+
+/***********************************************************************
+ *
+ * Function: unpack_VeoAppInfo
+ *
+ * Summary: Unpack the Veo AppInfo block from the structure
+ *
+ ***********************************************************************/
+int unpack_VeoAppInfo(struct VeoAppInfo *appinfo, unsigned char *record,
+ size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = unpack_CategoryAppInfo( &appinfo->category, record, len );
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 4)
+ return 0;
+ appinfo->dirty = get_short(record);
+ record += 2;
+ appinfo->sortByPriority = get_byte(record);
+ record += 2;
+ return (record - start);
+}
+
+
+/***********************************************************************
+ *
+ * Function: pack_VeoAppInfo
+ *
+ * Summary: Pack the AppInfo block/record back into the structure
+ *
+ ***********************************************************************/
+int
+pack_VeoAppInfo(struct VeoAppInfo *appinfo, unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = pack_CategoryAppInfo(&appinfo->category, record, len);
+ if (!record)
+ return i + 4;
+ if (!i)
+ return 0;
+ record += i;
+ len -= i;
+ if (len < 4)
+ return 0;
+ set_short(record, appinfo->dirty);
+ set_byte(record + 2, appinfo->sortByPriority);
+ set_byte(record + 3, 0); /* gapfill */
+ record += 4;
+
+ return (record - start);
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
+
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/versamail.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/versamail.c
new file mode 100644
index 00000000..3ceb6686
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/libpisock/versamail.c
@@ -0,0 +1,394 @@
+/*
+ * $Id: versamail.c,v 1.11 2006/10/12 14:21:23 desrod Exp $
+ *
+ * versamail.c: Translate VersaMail data formats
+ *
+ * Copyright (c) 2004, Nick Piper
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "pi-macros.h"
+#include "pi-versamail.h"
+
+
+/*
+
+Todo: What is unknown1 and 2?
+ What is reserved 1 and 2?
+ What is download ? (It's non zero, when there is more to d/l,
+ and appears to be an ID, allocated
+ by VersaMail. Maybe an index into another db?)
+ How do we do attachments ? They are not kept in-line, but in another db.
+ Attachments are related to unknown3.
+ Why is mark = 2, when there is no mark set, and 3 when it is?
+
+*/
+
+void free_VersaMail(struct VersaMail *a)
+{
+ if (a->messageUID)
+ free(a->messageUID);
+ if (a->to)
+ free(a->to);
+ if (a->from)
+ free(a->from);
+ if (a->cc)
+ free(a->cc);
+ if (a->bcc)
+ free(a->bcc);
+ if (a->subject)
+ free(a->subject);
+ if (a->dateString)
+ free(a->dateString);
+ if (a->body)
+ free(a->body);
+ if (a->replyTo)
+ free(a->replyTo);
+ if (a->unknown3)
+ free(a->unknown3);
+}
+
+
+
+#define SHUFFLE_BUFFER(shuffle_distance) { \
+ len -= shuffle_distance; \
+ buffer += shuffle_distance; \
+ }
+
+#define GET_BYTE_INTO(attrib) { \
+ attrib = get_byte(buffer); \
+ SHUFFLE_BUFFER(1); \
+ }
+
+#define GET_SHORT_INTO(attrib) { \
+ attrib = (unsigned int) get_short(buffer); \
+ SHUFFLE_BUFFER(2); \
+ }
+
+#define GET_STR_INTO(attrib) { \
+ if (get_byte(buffer)) { \
+ attrib = strdup(buffer); \
+ SHUFFLE_BUFFER(strlen(buffer)); \
+ } else { \
+ attrib = NULL; \
+ }; \
+ buffer++; \
+ len--; \
+ }
+
+#define PUT_STR_FROM(attrib) { \
+ if (attrib) { \
+ strcpy(buffer, attrib); \
+ SHUFFLE_BUFFER(strlen(buffer)); \
+ } else \
+ set_byte(buffer, 0); \
+ buffer++; \
+ len--; \
+ }
+
+
+#define ADD_LENGTH(str, destlen) { \
+ if (str) { \
+ destlen += 1+strlen(str); \
+ } else { \
+ destlen++; \
+ }; \
+ } \
+
+#define CONVERT_TIME_T_PALM_TO_UNIX(t) (t=t-2082844800)
+#define CONVERT_TIME_T_UNIX_TO_PALM(t) (t=t+2082844800)
+
+int unpack_VersaMail(struct VersaMail *a, char *buffer, size_t len)
+{
+ time_t date_t;
+ struct tm *date_tm;
+ char *start = buffer;
+
+ /* 000000 - 000003 */
+ a->imapuid = (unsigned long) get_long(buffer);
+ SHUFFLE_BUFFER(4);
+
+
+ /* This is different to the other databases, because Palm didn't
+ write VersaMail :-) */
+ /* 000004 - 000007 */
+ date_t = (time_t) get_long(buffer);
+ CONVERT_TIME_T_PALM_TO_UNIX(date_t);
+ date_tm = localtime(&date_t);
+ memcpy(&(a->date), date_tm, sizeof(struct tm));
+ SHUFFLE_BUFFER(4);
+
+ /* 000008 - 000009 */
+ GET_SHORT_INTO(a->category);
+
+ /* 00000A - 00000B */
+ GET_SHORT_INTO(a->accountNo);
+
+ /* 00000C - 00000D */
+ GET_SHORT_INTO(a->unknown1);
+ /* 00000E - 00000E */
+ GET_BYTE_INTO(a->download);
+ /* 00000F - 00000F */
+ GET_BYTE_INTO(a->mark);
+ /* of the above, bit 0 is mark, apparently bit 4 is header-only flag,
+ and it looks like bit 1 is always set, which gives a normal
+ value of 2 */
+
+ /* 000010 - 000011 */
+ GET_SHORT_INTO(a->unknown2);
+
+ /* 000012 - 000013 */
+ a->reserved1 = (get_byte(buffer));
+ a->reserved2 = (get_byte(buffer + 1) >> 1);
+ a->read = (get_byte(buffer + 1) && 1);
+ SHUFFLE_BUFFER(2);
+
+ /* This is the size, as provided by the imap server:
+ * 1 FETCH (UID 12779 BODY[] {3377} .... )
+ Size==3377
+ I guess VersaMail uses it to determine how much
+ more there might be to download. I don't think it uses it
+ to know there IS more to download though, because
+ the palm doesn't track most of the headers, so it'll never
+ be able to calculate if there is more or not, exactly.
+ */
+
+ /* 000014 - 000017 */
+ a->msgSize = get_long(buffer);
+ SHUFFLE_BUFFER(4);
+
+ GET_STR_INTO(a->messageUID);
+ GET_STR_INTO(a->to);
+ GET_STR_INTO(a->from);
+ GET_STR_INTO(a->cc);
+ GET_STR_INTO(a->bcc);
+ GET_STR_INTO(a->subject);
+ GET_STR_INTO(a->dateString);
+ GET_STR_INTO(a->body);
+ GET_STR_INTO(a->replyTo);
+
+ a->unknown3length = 0;
+ a->unknown3 = NULL;
+ a->attachmentCount = 0;
+ if (len > 0) {
+ a->unknown3 = (void *) malloc(len);
+
+ /*
+ printf("Msg has extra %d bytes. That's 4*%d + %d\n",
+ len, len / 4, len % 4);
+ */
+
+
+ /*
+ Example:
+
+ Byte 0: 0x 43 | C | 67 / Variable amount of 'rubbish'
+ Byte 1: 0x 50 | P | 80 \ NOT neccessary !NULL
+ Byte 2: 0x 0 | . | 0 /
+ Byte 3: 0x 68 | h | 104 | Each attachment adds four bytes,
+ Byte 4: 0x ffffffc0 | . | -64 | NULL, an int, then two signed ints
+ Byte 5: 0x ffffff90 | . | -112 \
+ Byte 6: 0x 0 | . | 0 /
+ Byte 7: 0x 68 | h | 104 |
+ Byte 8: 0x ffffffc0 | . | -64 |
+ Byte 9: 0x ffffff92 | . | -110 \
+ Byte 10: 0x 0 | . | 0 /
+ Byte 11: 0x 68 | h | 104 |
+ Byte 12: 0x ffffffc0 | . | -64 |
+ Byte 13: 0x ffffff94 | . | -108 \
+ Byte 14: 0x 0 | . | 0 /
+ Byte 15: 0x 0 | . | 0 | Then we end with a block of
+ Byte 16: 0x 0 | . | 0 | four NULLs
+ Byte 17: 0x 0 | . | 0 \
+
+ The 'rubbish' doesn't seem to be for alignment within the pdb, AFAIKS.
+ */
+
+ a->attachmentCount = (len / 4) - 1;
+ if (a->unknown3) {
+ a->unknown3length = len;
+ memcpy(a->unknown3, buffer, len);
+ SHUFFLE_BUFFER(len);
+ }
+ }
+
+ return (buffer - start);
+}
+
+int pack_VersaMail(struct VersaMail *a, char *buffer, size_t len)
+{
+ time_t date_t;
+ unsigned int destlen;
+ char *start = buffer;
+
+ destlen = 4 + 4 + 2 + 2 + 2 + 2 + 2 + 2 + 4 + a->unknown3length;
+
+ ADD_LENGTH(a->messageUID, destlen);
+ ADD_LENGTH(a->to, destlen);
+ ADD_LENGTH(a->from, destlen);
+ ADD_LENGTH(a->cc, destlen);
+ ADD_LENGTH(a->bcc, destlen);
+ ADD_LENGTH(a->subject, destlen);
+ ADD_LENGTH(a->dateString, destlen);
+ ADD_LENGTH(a->body, destlen);
+ ADD_LENGTH(a->replyTo, destlen);
+
+ if (!buffer)
+ return destlen;
+
+ if (len < destlen)
+ return 0;
+
+ set_long(buffer, a->imapuid);
+ SHUFFLE_BUFFER(4);
+
+ date_t = mktime(&(a->date));
+ CONVERT_TIME_T_UNIX_TO_PALM(date_t);
+ set_long(buffer, (unsigned long) date_t);
+ SHUFFLE_BUFFER(4);
+
+ set_short(buffer, a->category);
+ SHUFFLE_BUFFER(2);
+ set_short(buffer, a->accountNo);
+ SHUFFLE_BUFFER(2);
+ set_short(buffer, a->unknown1);
+ SHUFFLE_BUFFER(2);
+ set_byte(buffer, a->download);
+ SHUFFLE_BUFFER(1);
+ set_byte(buffer, a->mark);
+ SHUFFLE_BUFFER(1);
+ set_short(buffer, a->unknown2);
+ SHUFFLE_BUFFER(2);
+
+ set_byte(buffer, a->reserved1);
+ set_byte(buffer + 1, ((a->reserved2 << 1) || a->read));
+ SHUFFLE_BUFFER(2);
+
+ set_long(buffer, a->msgSize);
+ SHUFFLE_BUFFER(4);
+
+ PUT_STR_FROM(a->messageUID);
+ PUT_STR_FROM(a->to);
+ PUT_STR_FROM(a->from);
+ PUT_STR_FROM(a->cc);
+ PUT_STR_FROM(a->bcc);
+ PUT_STR_FROM(a->subject);
+ PUT_STR_FROM(a->dateString);
+ PUT_STR_FROM(a->body);
+ PUT_STR_FROM(a->replyTo);
+
+ if (a->unknown3length > 0) {
+ memcpy(buffer, a->unknown3, a->unknown3length);
+ }
+
+ return (buffer - start);
+}
+
+int unpack_VersaMailAppInfo(struct VersaMailAppInfo *ai,
+ unsigned char *record, size_t len)
+{
+ int i;
+ unsigned char *start = record;
+
+ i = unpack_CategoryAppInfo(&ai->category, record, len);
+ if (!i)
+ return i;
+ record += i;
+ len -= i;
+
+ return (record - start);
+}
+
+/*
+
+Message provided to the maintainer of pilot-mailsync:
+(the above implementation does not fully agree, BTW)
+
+-------- Original Message --------
+Subject: Re: QueueSync2.0
+Date: Sat, 31 Jan 2004 03:19:28 +0900
+From: Masaru matsumoto <matumoto@queuesoft.jp>
+To: Jochen Garcke <jochen@garcke.de>
+References: <401A7AE7.5090109@garcke.de>
+
+Hi,
+
+The definition of the database is to refer to the following.
+But, because I analyzed it, it has the possibility to be wrong.
+Write only information on VersaMail. Because there are many problems in
+ClieMail.
+
+
+typedef struct
+{
+ UInt16 mu_reserved1 : 8;
+ UInt16 mu_reserved2 : 7;
+ UInt16 mu_read : 1;
+} mu_MailFlagsType;
+
+typedef struct {
+ UInt32 mu_version;
+ UInt32 mu_datetime;
+ UInt16 mu_category;
+ UInt16 mu_account_no;
+ UInt16 mu_rfu1;
+ UInt16 mu_mark;
+ UInt16 mu_rfu2;
+ mu_MailFlagsType mu_flags;
+ UInt32 mu_msgSize;
+ char mu_firstField;
+} mu_MailPackedDBRecordType;
+
+typedef mu_MailPackedDBRecordType * mu_MailPackedDBRecordPtr;
+
+
+mu_msgSize =
+strlen(subject)+strlen(contents)+strlen(dateString)+strlen(replyto)+4;
+
+Field sequence :
+messageUID
+to
+from
+cc
+bcc
+subject
+dateString
+body
+replayTo
+
+*/
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */