premier commit (version 105)
authorThomas Noel <thomas@thomas-sandbox.(none)>
Tue, 4 Mar 2008 11:48:27 +0000 (11:48 +0000)
committerThomas Noel <thomas@thomas-sandbox.(none)>
Tue, 4 Mar 2008 11:48:27 +0000 (11:48 +0000)
18 files changed:
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/dirs [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/install [new file with mode: 0644]
debian/rules [new file with mode: 0755]
ipphone5-auto-upgrade [new file with mode: 0644]
ipphone5-debug.c [new file with mode: 0644]
ipphone5-download.c [new file with mode: 0644]
ipphone5-message.c [new file with mode: 0644]
ipphone5-phonebook.c [new file with mode: 0644]
ipphone5-report.c [new file with mode: 0644]
ipphone5-upgrade [new file with mode: 0755]
ipphone5-upload.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..91b0fe9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+CPPFLAGS += -Wall
+LDFLAGS += -s
+
+PROGS = ipphone5-report ipphone5-message ipphone5-upload ipphone5-debug ipphone5-download ipphone5-phonebook
+ALLPROGS = $(PROGS) ipphone5-upgrade ipphone5-auto-upgrade
+
+all: $(PROGS)
+
+install: install-bin
+
+clean:
+       rm -f *.o *~
+       rm -f $(PROGS)
+
+dist:
+       tar czf ../ipphone-tools.tar.gz Makefile *.c debian
+
+install-bin: $(PROGS)
+       install -o root -g root -m 0755 -d $(DESTDIR)/usr/bin/
+       install -o root -g root -m 0755 $(ALLPROGS) $(DESTDIR)/usr/bin/
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..9f005e6
--- /dev/null
+++ b/README
@@ -0,0 +1,4 @@
+
+La doc actuelle est ici :
+https://wiki.auf.org/wikiteki/VoIP/ClientMatériel/Outils
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..4d020cd
--- /dev/null
@@ -0,0 +1,60 @@
+ipphone-tools (105) unstable; urgency=low
+
+  * ipphone-report peut interroger une seule machine :
+    Syntax: ipphone-report [vertical] [<IPv4-address>]
+
+ -- Thomas NOEL <thomas.noel@auf.org>  Fri,  9 Feb 2007 18:00:26 +0000
+
+ipphone-tools (104) unstable; urgency=low
+
+  * ajout auto-upgrade et download
+
+ -- Thomas NOEL <thomas.noel@auf.org>  Fri,  9 Feb 2007 09:11:57 +0000
+
+ipphone-tools (103) unstable; urgency=low
+
+  * isolation ipphone-tools : les paquets -rings et -firmware n'ont plus les
+    mêmes sources
+
+ -- Thomas NOEL <thomas.noel@auf.org>  Wed,  7 Feb 2007 09:31:37 +0000
+
+ipphone-tools (102) unstable; urgency=low
+
+  * ipphone5-upload.c qui fait presque plus de segfault ;) et qui donne un
+    mini doc
+
+ -- Thomas NOEL <thomas.noel@auf.org>  Tue,  6 Feb 2007 10:16:42 +0000
+
+ipphone-tools (101) unstable; urgency=low
+
+  * Makefile sans @ (j'aime bien tout voir), utilisation de cp -a au lieu
+    de install pour copier les firmware afin de copier les liens symboliques
+
+ -- Thomas NOEL <thomas.noel@auf.org>  Tue,  6 Feb 2007 09:50:00 +0000
+
+ipphone-tools (100) unstable; urgency=low
+
+  * multi-paquetisation : les binaires, les sonneries et le micrologiciel
+  * plus de lien symbolique : ipphone5-upgrade avertit qu'il est obsolète
+
+ -- Progfou <jean-christophe.andre@auf.org>  Mon,  5 Feb 2007 20:30:11 +0700
+
+ipphone-tools (93) unstable; urgency=low
+
+  * generalisation : ipphone-upload et ipphone-download
+  * et on met tout dans /usr/bin
+
+ -- Thomas NOEL <thomas.noel@auf.org>  Mon,  5 Feb 2007 10:44:22 +0000
+
+ipphone-tools (82-2) unstable; urgency=low
+
+  * ajout d'un petit README indiquant juste la page Wiki
+
+ -- Thomas NOEL <thomas.noel@auf.org>  Thu,  1 Feb 2007 16:33:08 +0000
+
+ipphone-tools (82-1) unstable; urgency=low
+
+  * Initial Release.
+
+ -- Progfou <jean-christophe.andre@auf.org>  Mon, 29 Jan 2007 23:35:11 +0700
+
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..b8626c4
--- /dev/null
@@ -0,0 +1 @@
+4
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..7f92c16
--- /dev/null
@@ -0,0 +1,15 @@
+Source: ipphone-tools
+Section: utils
+Priority: optional
+Maintainer: Progfou <jean-christophe.andre@auf.org>
+Build-Depends: debhelper (>= 4.0.0)
+Standards-Version: 3.6.1
+
+Package: ipphone-tools
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Suggests: ipphone-tools-rings, ipphone-tools-firmware
+Description: tools for managing YWH500 IP phones
+ See: http://www.yntx.com/en/productywh500.htm
+ and https://wiki.auf.org/wikiteki/VoIP/ClientMatériel/Outils
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..975bfe4
--- /dev/null
@@ -0,0 +1,27 @@
+This package was debianized by Progfou <jean-christophe.andre@auf.org> on
+Mon, 29 Jan 2007 23:35:11 +0700.
+
+It was downloaded from http://trac.sn.auf.org/ipphone/browser/ipphone-tools/
+
+Copyright Holder: Agence universitaire de la Francophonie
+
+License:
+
+   This package is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This package 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 package; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..e772481
--- /dev/null
@@ -0,0 +1 @@
+usr/bin
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..e845566
--- /dev/null
@@ -0,0 +1 @@
+README
diff --git a/debian/install b/debian/install
new file mode 100644 (file)
index 0000000..1df36c6
--- /dev/null
@@ -0,0 +1 @@
+usr/bin/*
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..4ebaca4
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+DH_ALWAYS_EXCLUDE=CVS:.svn
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+else
+       CFLAGS += -O2
+endif
+
+configure: configure-stamp
+configure-stamp:
+       dh_testdir
+       # Add here commands to configure the package.
+
+       touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+       dh_testdir
+
+       # Add here commands to compile the package.
+       $(MAKE)
+       #docbook-to-man debian/ipphone-tools.sgml > ipphone-tools.1
+
+       touch build-stamp
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp configure-stamp
+
+       # Add here commands to clean up after the build process.
+       -$(MAKE) clean
+
+       dh_clean 
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       dh_installdirs
+
+       # Add here commands to install the package into debian/ipphone-tools.
+       $(MAKE) install-bin DESTDIR=$(CURDIR)/debian/ipphone-tools
+       #$(MAKE) install-rings DESTDIR=$(CURDIR)/debian/ipphone-tools-rings
+       #$(MAKE) install-firmware DESTDIR=$(CURDIR)/debian/ipphone-tools-firmware
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installchangelogs 
+       dh_installdocs
+#      dh_installexamples
+#      dh_install
+#      dh_installmenu
+#      dh_installdebconf       
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+#      dh_installinit
+#      dh_installcron
+#      dh_installinfo
+#      dh_installman
+       dh_link
+       dh_strip
+       dh_compress
+       dh_fixperms
+#      dh_perl
+#      dh_python
+#      dh_makeshlibs
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/ipphone5-auto-upgrade b/ipphone5-auto-upgrade
new file mode 100644 (file)
index 0000000..ef2b00c
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh
+DIR="/usr/share/ipphone-tools/firmware"
+FIRMWARE="ipphone5-stable.bin"
+
+if ! cd "$DIR" 2>/dev/null
+then
+  echo "Error: unable to enter into the firmware directory!"
+  echo "Try this first: aptitude install ipphone5-tools-firmware"
+  exit 1
+fi
+
+OPTIONS="$(readlink "$FIRMWARE" | sed 's/^.*-\([0-9]*\)-auf\([0-9]*\).*$/-v V1=\1 -v V2=\2/p;d')"
+
+ipphone5-report |
+awk -F: $OPTIONS '
+!/^#/ {
+  ip = $1;
+  telnum = $4;
+  match($3,"[0-9]+-[0-9]+");
+  v = substr($3,RSTART,RLENGTH);
+  i = index(v,"-");
+  v1 = substr(v,1,i-1);
+  v2 = substr(v,i+1);
+  if ((v1 < V1) || (v2 < V2)) print ip,telnum,v1"-"v2,V1"-"V2;
+}
+' |
+while read IP TELNUM CURRENT STABLE
+do
+  echo -n "Upgrading $IP ($TELNUM) from $CURRENT to $STABLE... "
+  if ipphone5-upload "$FIRMWARE" $IP >&/dev/null
+  then
+    echo 'Done.'
+  else
+    echo 'Failed!'
+  fi
+done
+exit 0
diff --git a/ipphone5-debug.c b/ipphone5-debug.c
new file mode 100644 (file)
index 0000000..8924e2e
--- /dev/null
@@ -0,0 +1,79 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> /* inet_aton,inet_ntoa */
+#include <signal.h>    /* signal,SIG* */
+#include <errno.h>     /* errno,E* */
+#include <unistd.h>    /* read,write,close */
+#include <string.h>    /* memset */
+#include <stdio.h>     /* FILE,fprintf */
+
+#define UDP_DEBUG_DST_PORT 0x2021
+#define UDP_DEBUG_SRC_PORT 1025
+
+#define DEBUG_BUFFER_SIZE 1024 // FIXME: check the real size
+
+// FIXME: see Palm1DebugConvert.cpp
+
+void human_debug(const char *buffer, int size) {
+       const unsigned char *p;
+       for (p = (unsigned char *)buffer; *p; p++) {
+               if (32 <= *p && *p <= 127) {
+                       fprintf(stdout, "%c", *p);
+               } else if (*p == '\r' && *(p+1) == '\n') {
+                       fprintf(stdout, "\\n");
+                       p++;
+               } else {
+                       fprintf(stdout, "\\%03o", *p);
+               }
+       }
+}
+
+int main(int argc, const char *argv[]) {
+       const char *progname;
+       int sd;
+       struct sockaddr_in sin;
+
+       // check arguments count
+       progname = argv[0];
+       if (argc != 1) {
+               fprintf(stderr, "Syntax: %s\n", progname);
+               return 1;
+       }
+
+       // prepare receiving answers (bind debug port)
+       sd = socket(PF_INET, SOCK_DGRAM, 0);
+       if (sd < 0) {
+               fprintf(stderr, "Unable to create a socket!\n");
+               return 3;
+       }
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(UDP_DEBUG_DST_PORT);
+       sin.sin_addr.s_addr = htonl(INADDR_ANY);
+       if (bind(sd, (struct sockaddr *)&sin, sizeof(sin))) {
+               fprintf(stderr, "Unable to bind!\n");
+               return 4;
+       }
+
+       // wait for answers
+       signal(SIGPIPE, SIG_IGN);
+       while (1) {
+               char buffer[DEBUG_BUFFER_SIZE];
+               struct sockaddr_in sinrecv;
+               socklen_t sinrecv_len = sizeof(sinrecv);
+               int size = recvfrom(sd, buffer, sizeof(buffer), 0, (struct sockaddr *)&sinrecv, &sinrecv_len);
+               if (size < DEBUG_BUFFER_SIZE) {
+                       fprintf(stdout, "%s:", inet_ntoa(sinrecv.sin_addr));
+                       buffer[size] = '\0'; // FIXME: should be managed below
+                       human_debug(buffer, size);
+                       fprintf(stdout, "\n");
+                       fflush(stdout);
+               } else {
+                       fprintf(stderr, "Warning: received an invalid packet size of %d bytes!\n", size);
+               }
+       }
+
+       // cleaning
+       close(sd);
+       return 0;
+}
diff --git a/ipphone5-download.c b/ipphone5-download.c
new file mode 100644 (file)
index 0000000..06defcb
--- /dev/null
@@ -0,0 +1,139 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> /* inet_aton,inet_ntoa */
+#include <unistd.h>    /* read,write,close */
+#include <string.h>    /* memset */
+#include <stdlib.h>    /* malloc */
+#include <stdio.h>     /* FILE,fprintf */
+
+#define FILE_READ_MAX_SIZE 655000
+#define FILE_ONE_PAGE_SIZE 64000
+
+#define SDRAM_MAX_LENGTH 640000
+#define TOTAL_SETTINGS_SIZE 4096
+
+#define TCP_DOWNLOAD_SIZE 128
+#define TCP_DOWNLOAD_PORT 0x2223 // 8739
+
+#define DATA_HINT "dh"
+#define SETTINGS_HINT "sh"
+
+/*
+ * Download protocol (from PalmToolDlg.cpp):
+ * Step1. PC make a TCP connection to Palm1's page0 program
+ * Step2. PC sends 2 bytes to Palm1 for data "dh" or settings "sh" hints
+ *                Palm1 sends back 128 byte of data
+ *        Repeat step2 until the whole data has been received
+ * Step3. PC close the TCP connection indicate the download is over
+ */
+int download(int sd, char *buffer, size_t length, const char *hint) {
+       fprintf(stdout, "Downloading... ");
+       // receiving data
+       while (length > 0) {
+               write(sd, hint, strlen(hint));
+               read(sd, buffer, TCP_DOWNLOAD_SIZE);
+               // FIXME: should check for errors!
+               fprintf(stdout, "%10d\b\b\b\b\b\b\b\b\b\b", length);
+               buffer += TCP_DOWNLOAD_SIZE;
+               length -= TCP_DOWNLOAD_SIZE;
+       }
+       fprintf(stdout, "Done.     \n");
+       return 0;
+}
+
+int main(int argc, const char *argv[]) {
+       const char *progname, *filename, *extension, *hint, *ipaddr;
+       FILE *filehandle;
+       size_t length, length_padded;
+       char *buffer;
+       struct in_addr sin_addr;
+       int sd;
+       struct sockaddr_in sin;
+
+       // check arguments count
+       progname = argv[0];
+       if (argc != 3) {
+               fprintf(stderr, "Syntax: %s <filename> <IPv4-address>\n", progname);
+               return 1;
+       }
+       filename = argv[1];
+       ipaddr = argv[2];
+
+       // check first argument (filename)
+       filehandle = fopen(filename, "wb");
+       if (filehandle == NULL) {
+               fprintf(stderr, "Unable to open '%s' !\n", filename);
+               return 2;
+       }
+       fprintf(stdout, "File name: %s\n", filename);
+
+       // check file type (by extension, for now...)
+       extension = strrchr(filename, '.');
+       if (extension && !strcasecmp(extension, ".dh")) {
+               hint = DATA_HINT;
+               length = SDRAM_MAX_LENGTH; // < FILE_READ_MAX_SIZE
+       } else if (extension && !strcasecmp(extension, ".sh")) {
+               hint = SETTINGS_HINT;
+               length = TOTAL_SETTINGS_SIZE; // < FILE_ONE_PAGE_SIZE
+       } else {
+               fprintf(stderr, "Unknown file type!\n");
+               return 2;
+       }
+
+       // normalize file size
+       length_padded = length + TCP_DOWNLOAD_SIZE*2 - 1;
+       length_padded /= TCP_DOWNLOAD_SIZE*2;
+       length_padded *= TCP_DOWNLOAD_SIZE*2;
+
+       // prepare to load data into memory
+       fprintf(stdout, "File length: %d bytes", length);
+       if (length_padded > length) {
+               fprintf(stdout, " (padding to %d bytes)", length_padded);
+       }
+       fprintf(stdout, "\n");
+       buffer = malloc(length_padded);
+       if (buffer == NULL) {
+               fprintf(stderr, "Unable to allocate enough (%d bytes) memory!\n", length_padded);
+               return 4;
+       }
+
+       // check second argument (IPv4 address)
+       if (!inet_aton(ipaddr, &sin_addr)) {
+               fprintf(stderr, "'%s' is an invalid IPv4 address!\n", ipaddr);
+               return 6;
+       }
+       fprintf(stdout, "IPv4 address: %s\n", inet_ntoa(sin_addr));
+
+       // connect to the host
+       sd = socket(PF_INET, SOCK_STREAM, 0);
+       if (sd < 0) {
+               fprintf(stderr, "Unable to create a socket!\n");
+               return 7;
+       }
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(TCP_DOWNLOAD_PORT);
+       memcpy(&sin.sin_addr, &sin_addr, sizeof(sin.sin_addr));
+       if (connect(sd, (struct sockaddr *)&sin, sizeof(sin))) {
+               fprintf(stderr, "Unable to connect to host!\n");
+               return 8;
+       }
+
+       // do the upgrade process
+       setbuf(stdout, NULL);
+       if (download(sd, buffer, length_padded, hint)) return 9;
+
+       // save to file
+       //if (length < length_padded) {
+       //      memset(buffer + length, 0, length_padded - length);
+       //}
+       if (fwrite(buffer, length, 1, filehandle) != 1) { // XXX: length_padded?
+               fprintf(stderr, "Unable to write the whole file content!\n");
+               return 5;
+       }
+       fclose(filehandle);
+
+       // cleaning
+       close(sd);
+       return 0;
+}
diff --git a/ipphone5-message.c b/ipphone5-message.c
new file mode 100644 (file)
index 0000000..af307cf
--- /dev/null
@@ -0,0 +1,58 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> /* inet_aton,inet_ntoa */
+#include <unistd.h>    /* read,write,close */
+#include <string.h>    /* memset */
+#include <stdio.h>     /* FILE,fprintf */
+
+#define UDP_DEBUG_SRC_PORT 1025
+#define REPORT_DST_IPADDR "224.1.2.5"
+
+int main(int argc, const char *argv[]) {
+       const char *progname, *message, *ipaddr;
+       struct in_addr sin_addr;
+       int sd;
+       struct sockaddr_in sin;
+
+       // check arguments count
+       progname = argv[0];
+       if (argc == 2) { // multicast
+               message = argv[1];
+               ipaddr = REPORT_DST_IPADDR;
+       } else if (argc == 3) { // specific destination
+               message = argv[1];
+               ipaddr = argv[2];
+       } else {
+               fprintf(stderr, "Syntax: %s <message> [<IPv4-address>]\n", progname);
+               return 1;
+       }
+       setbuf(stdout, NULL);
+
+       // check IPv4 address
+       if (!inet_aton(ipaddr, &sin_addr)) {
+               fprintf(stderr, "'%s' is an invalid IPv4 address!\n", ipaddr);
+               return 2;
+       }
+       fprintf(stdout, "IPv4 address: %s\n", inet_ntoa(sin_addr));
+
+       // prepare receiving answers (bind report port)
+       sd = socket(PF_INET, SOCK_DGRAM, 0);
+       if (sd < 0) {
+               fprintf(stderr, "Unable to create a socket!\n");
+               return 3;
+       }
+
+       // send message to display
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(UDP_DEBUG_SRC_PORT);
+       inet_aton(ipaddr, &sin.sin_addr);
+       if (sendto(sd, message, strlen(message)+1, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+               fprintf(stderr, "Error sending UDP request!\n");
+               return 4;
+       }
+
+       // cleaning
+       close(sd);
+       return 0;
+}
diff --git a/ipphone5-phonebook.c b/ipphone5-phonebook.c
new file mode 100644 (file)
index 0000000..6d60724
--- /dev/null
@@ -0,0 +1,110 @@
+#include <unistd.h>    /* read,write,close */
+#include <string.h>    /* str* */
+#include <stdlib.h>    /* atoi */
+#include <stdio.h>     /* FILE,fprintf */
+
+#define SETTINGS_HINT "sh"
+
+#define TOTAL_SETTINGS_SIZE 4096
+
+#define SPEED_DIAL_BEGIN 0x0200
+#define SPEED_DIAL_NUM 100
+#define SPEED_DIAL_LEN 32
+#define PHONE_NUMBER_LEN 16
+
+void display_phonebook(FILE *filehandle, int start, int end) {
+       char buffer[SPEED_DIAL_LEN*SPEED_DIAL_NUM], *pos;
+       if (start < 0) start = 0;
+       if (end > (SPEED_DIAL_NUM - 1)) end = SPEED_DIAL_NUM - 1;
+       fseek(filehandle, SPEED_DIAL_BEGIN + (SPEED_DIAL_LEN * start), SEEK_SET);
+       pos = buffer + (SPEED_DIAL_LEN * start);
+       fread(pos, SPEED_DIAL_LEN, (end - start + 1), filehandle);
+       fprintf(stdout, "#index:number:name\n");
+       while (start <= end) {
+               // FIXME: should not be ".16" but something like ".%d",PHONE_NUMBER_LEN
+               fprintf(stdout, "%d:%.16s:%.16s\n", start, pos, pos + PHONE_NUMBER_LEN);
+               pos += SPEED_DIAL_LEN;
+               start++;
+       }
+}
+
+int change_phonebook(FILE *filehandle, int index, const char *number, const char *name) {
+       char buffer[SPEED_DIAL_LEN];
+       if (index < 0 || (SPEED_DIAL_NUM - 1) < index) return -1;
+       strncpy(buffer, number, PHONE_NUMBER_LEN);
+       strncpy(buffer + PHONE_NUMBER_LEN, name, SPEED_DIAL_LEN - PHONE_NUMBER_LEN);
+       fseek(filehandle, SPEED_DIAL_BEGIN + (SPEED_DIAL_LEN * index), SEEK_SET);
+       if (fwrite(buffer, SPEED_DIAL_LEN, 1, filehandle) != 1) return -2;
+       return 0;
+}
+
+int main(int argc, const char *argv[]) {
+       const char *progname, *filename, *extension;
+       FILE *filehandle;
+       size_t length;
+
+       // check arguments count
+       progname = argv[0];
+       if (argc < 2 || 5 < argc) {
+               fprintf(stderr, "Syntax: %s <filename> [<index>[-<end>] [<new-number> [<new-name>]]]\n", progname);
+               return 1;
+       }
+       filename = argv[1];
+
+       // check first argument (filename)
+       filehandle = fopen(filename, "r+b");
+       if (filehandle == NULL) {
+               fprintf(stderr, "Unable to open '%s' !\n", filename);
+               return 2;
+       }
+       // fprintf(stdout, "# File name: %s\n", filename);
+
+       // check file type (by extension, for now...)
+       extension = strrchr(filename, '.');
+       if (extension && strcasecmp(extension, ".sh")) {
+               fprintf(stderr, "Unknown file type!\n");
+               return 2;
+       }
+
+       // check file size
+       fseek(filehandle, 0L, SEEK_END);
+       length = ftell(filehandle);
+       if (length != TOTAL_SETTINGS_SIZE) {
+               fprintf(stderr, "Invalid file size (%d != %d) !\n", length, TOTAL_SETTINGS_SIZE);
+               return 3;
+       }
+       // fprintf(stdout, "# File length: %d bytes\n", length);
+
+       // proceed as requested
+       if (argc < 4) {
+               int start, end;
+               if (argc > 2) {
+                       char *pos, tmp[8]; /* "NNN-NNN\0" */
+                       strncpy(tmp, argv[2], sizeof(tmp));
+                       tmp[sizeof(tmp)-1] = '\0';
+                       pos = strchr(tmp, '-');
+                       if (pos) {
+                               *(pos++) = 0;
+                               start = atoi(tmp);
+                               end = *pos ? atoi(pos) : (SPEED_DIAL_NUM - 1);
+                       } else {
+                               start = end = atoi(tmp);
+                       }
+               } else {
+                       start = 0;
+                       end = SPEED_DIAL_NUM - 1;
+               }
+               display_phonebook(filehandle, start, end);
+       } else {
+               int index;
+               const char *number, *name;
+               index = atoi(argv[2]);
+               number = argv[3];
+               name = (argc >= 5) ? argv[4] : "";
+               change_phonebook(filehandle, index, number, name);
+       }
+
+       // cleaning
+       fclose(filehandle);
+       return 0;
+}
diff --git a/ipphone5-report.c b/ipphone5-report.c
new file mode 100644 (file)
index 0000000..2983931
--- /dev/null
@@ -0,0 +1,165 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> /* inet_aton,inet_ntoa */
+#include <signal.h>    /* signal,SIG* */
+#include <errno.h>     /* errno,E* */
+#include <unistd.h>    /* read,write,close */
+#include <string.h>    /* strcmp,memset */
+#include <stdio.h>     /* FILE,fprintf */
+
+#define WAIT_TIME_MANY    3 // seconds
+#define WAIT_TIME_ONLYONE 1 // seconds
+
+#define UDP_DEBUG_SRC_PORT 1025
+
+#define REPORT_REQUEST_STRING "Hello, world!"
+#define REPORT_DST_IPADDR "224.1.2.5"
+#define REPORT_SRC_PORT 61030
+
+#define REPORT_IP_POS          0       // 0-3 IP
+#define REPORT_MAC_POS         4       // 4-9 MAC
+#define REPORT_VERSION_POS     10      // 10-39 Version
+#define REPORT_NUMBER_POS      40      // 40-59 Phone Number
+#define REPORT_TYPE_POS                60      // 60 ip type
+#define REPORT_LOGON_POS       61      // 61 Logon status
+#define REPORT_CALL_POS                62      // 62 Call status
+#define REPORT_PROTOCOL_POS    63      // 63 Protocol
+#define REPORT_TOTAL_LEN       64
+
+static const char *report_type[] = {
+  "static", "dhcp", "pppoe", "modem"
+};
+
+static const char *report_protocol[] = {
+  "h323", "sip", "mgcp", "n2p", "iax2", "wp", "epn", "others"
+};
+
+void human_report(const unsigned char *buffer) {
+       const unsigned char *p;
+       fprintf(stdout, "================\n");
+       p = buffer + REPORT_IP_POS;
+       fprintf(stdout, "IPv4 address...: %d.%d.%d.%d\n", p[0],p[1],p[2],p[3]);
+       p = buffer + REPORT_MAC_POS;
+       fprintf(stdout, "MAC address....: %02x-%02x-%02x-%02x-%02x-%02x\n", p[0],p[1],p[2],p[3],p[4],p[5]);
+       p = buffer + REPORT_VERSION_POS;
+       fprintf(stdout, "Version........: %-30.30s\n", p);
+       p = buffer + REPORT_NUMBER_POS;
+       fprintf(stdout, "Phone Number...: %-20.20s\n", p);
+       p = buffer + REPORT_TYPE_POS;
+       fprintf(stdout, "IP Type........: %d (%s)\n", p[0], (p[0] < sizeof(report_type)/sizeof(char*)) ? report_type[p[0]] : "unknown");
+       p = buffer + REPORT_LOGON_POS;
+       fprintf(stdout, "Logged on......: %d (%s)\n", p[0], (p[0] == 1 ? "Yes" : "No"));
+       p = buffer + REPORT_CALL_POS;
+       fprintf(stdout, "Busy...........: %d (%s)\n", p[0], (p[0] == 1 ? "Yes" : "No"));
+       p = buffer + REPORT_PROTOCOL_POS;
+       fprintf(stdout, "Protocol.......: %d (%s)\n", p[0], (p[0] < sizeof(report_protocol)/sizeof(char*)) ? report_protocol[p[0]] : "unknown");
+}
+
+void machine_report(const unsigned char *buffer) {
+       const unsigned char *p;
+       p = buffer + REPORT_IP_POS;
+       fprintf(stdout, "%d.%d.%d.%d:", p[0],p[1],p[2],p[3]);
+       p = buffer + REPORT_MAC_POS;
+       fprintf(stdout, "%02x-%02x-%02x-%02x-%02x-%02x:", p[0],p[1],p[2],p[3],p[4],p[5]);
+       p = buffer + REPORT_VERSION_POS;
+       fprintf(stdout, "%.30s:", p);
+       p = buffer + REPORT_NUMBER_POS;
+       fprintf(stdout, "%.20s:", p);
+       p = buffer + REPORT_TYPE_POS;
+       fprintf(stdout, "%s:", (p[0] < sizeof(report_type)/sizeof(char*)) ? report_type[p[0]] : "unknown");
+       p = buffer + REPORT_LOGON_POS;
+       fprintf(stdout, "%s:", (p[0] == 1 ? "Yes" : "No"));
+       p = buffer + REPORT_CALL_POS;
+       fprintf(stdout, "%s:", (p[0] == 1 ? "Yes" : "No"));
+       p = buffer + REPORT_PROTOCOL_POS;
+       fprintf(stdout, "%s\n", (p[0] < sizeof(report_protocol)/sizeof(char*)) ? report_protocol[p[0]] : "unknown");
+}
+
+char alarm_signal = 0;
+void signal_handler(int signal_number) {
+       if (signal_number == SIGALRM) alarm_signal = 1;
+}
+
+int main(int argc, const char *argv[]) {
+       const char *progname, *ipaddr;
+       struct in_addr sin_addr;
+       int only_one, answers_count;
+       int sd;
+       struct sockaddr_in sin, sinreq;
+       void (*report_function)(const unsigned char *) = machine_report;
+
+       // check arguments count
+       progname = argv[0];
+       if (argc >= 2 && !strcmp(argv[1], "vertical")) {
+               report_function = human_report;
+               argc--; argv++;
+       }
+       if (argc != 1 && argc != 2) {
+               fprintf(stderr, "Syntax: %s [vertical] [<IPv4-address>]\n", progname);
+               return 1;
+       }
+       setbuf(stdout, NULL);
+
+       // check second argument (IPv4 address)
+       if (argc == 2) {
+               ipaddr = argv[1];
+               only_one = 1;
+       } else {
+               ipaddr = REPORT_DST_IPADDR;
+               only_one = 0;
+       }
+       if (!inet_aton(ipaddr, &sin_addr)) {
+               fprintf(stderr, "'%s' is an invalid IPv4 address!\n", ipaddr);
+               return 2;
+       }
+
+       // prepare receiving answers (bind report port)
+       sd = socket(PF_INET, SOCK_DGRAM, 0);
+       if (sd < 0) {
+               fprintf(stderr, "Unable to create a socket!\n");
+               return 3;
+       }
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(REPORT_SRC_PORT);
+       sin.sin_addr.s_addr = htonl(INADDR_ANY);
+       if (bind(sd, (struct sockaddr *)&sin, sizeof(sin))) {
+               fprintf(stderr, "Unable to bind!\n");
+               return 4;
+       }
+
+       // send report request
+       memset(&sinreq, 0, sizeof(sinreq));
+       sinreq.sin_family = AF_INET;
+       sinreq.sin_port = htons(UDP_DEBUG_SRC_PORT);
+       memcpy(&sinreq.sin_addr, &sin_addr, sizeof(sinreq.sin_addr));
+       if (sendto(sd, REPORT_REQUEST_STRING, sizeof(REPORT_REQUEST_STRING), 0, (struct sockaddr *)&sinreq, sizeof(sinreq)) < 0) {
+               fprintf(stderr, "Error sending UDP request!\n");
+               return 5;
+       }
+
+       // wait for answers
+       if (!only_one) {
+               fprintf(stdout, "#ipv4-address:mac-address:version:phone-number:connexion:logged:busy:protocol\n");
+       }
+       signal(SIGPIPE, SIG_IGN);
+       signal(SIGALRM, signal_handler);
+       alarm(only_one ? WAIT_TIME_ONLYONE : WAIT_TIME_MANY);
+       answers_count = 0;
+       while (!(only_one && (answers_count == 1)) && !alarm_signal) {
+               unsigned char buffer[REPORT_TOTAL_LEN];
+               int size = recv(sd, buffer, sizeof(buffer), MSG_DONTWAIT);
+               if (size == -1 && errno == EAGAIN) {
+                       usleep(200);
+               } else if (size == REPORT_TOTAL_LEN) {
+                       (*report_function)(buffer);
+                       answers_count++;
+               } else {
+                       fprintf(stderr, "Warning: received an invalid packet size of %d bytes!\n", size);
+               }
+       }
+
+       // cleaning
+       close(sd);
+       return (only_one && (answers_count != 1)) ? -1 : 0;
+}
diff --git a/ipphone5-upgrade b/ipphone5-upgrade
new file mode 100755 (executable)
index 0000000..3baf77a
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo 'This program has been deprecated, use "ipphone5-upload" instead.' 1>&2
+exit -1
diff --git a/ipphone5-upload.c b/ipphone5-upload.c
new file mode 100644 (file)
index 0000000..9e93a27
--- /dev/null
@@ -0,0 +1,185 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> /* inet_aton,inet_ntoa */
+#include <unistd.h>    /* read,write,close */
+#include <string.h>    /* memset */
+#include <stdlib.h>    /* malloc */
+#include <stdio.h>     /* FILE,fprintf */
+
+#define FILE_FULL_PAGE_SIZE 65536
+
+#define FIRMWARE_SIZE (FILE_FULL_PAGE_SIZE*15)
+#define MAX_PCMRING_SIZE 15360
+#define SDRAM_MAX_LENGTH 640000
+#define TOTAL_SETTINGS_SIZE 4096
+
+#define TCP_UPLOAD_SIZE 128
+#define TCP_UPLOAD_PORT 0x2223 // 8739
+
+#define OPTIONS_UPLOAD_PAGE 128
+#define PROGRAM_UPLOAD_PAGE 129
+#define RING_UPLOAD_PAGE 130
+#define MAP_UPLOAD_PAGE 132
+#define ALTERNATE_SETTING_UPLOAD_PAGE 133
+
+/*
+ * Upload protocol (from PalmToolDlg.cpp):
+ * Step1. PC make a TCP connection to Palm1's page0 program
+ * Step2. PC sends 128 bytes package data to Palm1
+ *                Palm1 send back 1 byte of "0xff"
+ *        Repeat step2 until the whole data has been sent
+ * Step3. PC sends 1 byte data indicate which page to write to
+ *                Palm1 send back 1 byte of "0xff"
+ * Step4. PC close the TCP connection indicate the update progress is over
+ */
+int upload(int sd, const char *buffer, size_t length, int upload_page) {
+       unsigned char result;
+       fprintf(stdout, "Uploading... ");
+       // sending data
+       while (length > 0) {
+               write(sd, buffer, TCP_UPLOAD_SIZE);
+               read(sd, &result, 1);
+               if (result != 0xff) {
+                       fprintf(stderr, "Warning: unexpected read result (%02X) !\n", result);
+                       fprintf(stdout, "Aborting.\n");
+                       return 1;
+               }
+               fprintf(stdout, "%10d\b\b\b\b\b\b\b\b\b\b", length);
+               buffer += TCP_UPLOAD_SIZE;
+               length -= TCP_UPLOAD_SIZE;
+       }
+       // sending page number
+       result = upload_page;
+       write(sd, &result, 1);
+       read(sd, &result, 1);
+       if (result != 0xff) {
+               fprintf(stderr, "Warning: unexpected read result (%02X) !\n", result);
+               fprintf(stdout, "Aborting.\n");
+               return 1;
+       }
+       fprintf(stdout, "Done.     \n");
+       return 0;
+}
+
+int main(int argc, const char *argv[]) {
+       const char *progname, *filename, *extension, *ipaddr;
+       FILE *filehandle;
+       int upload_page;
+       size_t length, length_padded;
+       char *buffer;
+       struct in_addr sin_addr;
+       int sd;
+       struct sockaddr_in sin;
+
+       // check arguments count
+       progname = argv[0];
+       if (argc != 3) {
+               fprintf(stderr, "Syntax: %s <filename> <IPv4-address>\n", progname);
+               fprintf(stderr, "  where <filename> is one of:\n");
+               fprintf(stderr, "        <name>.bin : firmware\n");
+               fprintf(stderr, "        <name>.dat : ring\n");
+               fprintf(stderr, "        <name>.sh  : options\n");
+               fprintf(stderr, "        map.txt    : digit map\n");
+               fprintf(stderr, "        stdram.dat : \n");
+               return 1;
+       }
+       filename = argv[1];
+       ipaddr = argv[2];
+
+       // check first argument (filename)
+       filehandle = fopen(filename, "rb");
+       if (filehandle == NULL) {
+               fprintf(stderr, "Unable to open '%s' !\n", filename);
+               return 2;
+       }
+       fprintf(stdout, "File name: %s\n", filename);
+
+       // check file type (by extension, for now...)
+       extension = strrchr(filename, '.');
+       if (!strcasecmp(filename, "sdram.dat")) {
+               // FIXME: upload_page = ;
+               fprintf(stderr, "Not implemented yet!\n");
+               return 2;
+       } else if (!strcasecmp(filename, "map.txt")) {
+               upload_page = MAP_UPLOAD_PAGE;
+       } else if (extension && !strcasecmp(extension, ".sh")) {
+               upload_page = OPTIONS_UPLOAD_PAGE;
+       } else if (extension && !strcasecmp(extension, ".bin")) {
+               upload_page = PROGRAM_UPLOAD_PAGE;
+       } else if (extension && !strcasecmp(extension, ".dat")) {
+               upload_page = RING_UPLOAD_PAGE;
+       } else {
+               fprintf(stderr, "Unknown file type!\n");
+               return 2;
+       }
+
+       // get file size
+       fseek(filehandle, 0L, SEEK_END);
+       length = ftell(filehandle);
+       length_padded = length + TCP_UPLOAD_SIZE*2 - 1;
+       length_padded /= TCP_UPLOAD_SIZE*2;
+       length_padded *= TCP_UPLOAD_SIZE*2;
+
+       // check file size
+       if ((upload_page == PROGRAM_UPLOAD_PAGE) && (length_padded != FIRMWARE_SIZE)) {
+               fprintf(stderr, "Invalid file size (%d != %d) !\n", length_padded, FIRMWARE_SIZE);
+               return 3;
+       } else if ((upload_page == RING_UPLOAD_PAGE) && (length_padded > MAX_PCMRING_SIZE)) {
+               fprintf(stderr, "Invalid file size (%d > %d) !\n", length_padded, MAX_PCMRING_SIZE);
+               return 3;
+       } else if ((upload_page == OPTIONS_UPLOAD_PAGE) && (length_padded != TOTAL_SETTINGS_SIZE)) {
+               fprintf(stderr, "Invalid file size (%d > %d) !\n", length_padded, MAX_PCMRING_SIZE);
+               return 3;
+       }
+
+       // load data into memory
+       fprintf(stdout, "File length: %d bytes", length);
+       if (length_padded > length) {
+               fprintf(stdout, " (padding to %d bytes)", length_padded);
+       }
+       fprintf(stdout, "\n");
+       buffer = malloc(length_padded);
+       if (buffer == NULL) {
+               fprintf(stderr, "Unable to allocate enough (%d bytes) memory!\n", length_padded);
+               return 4;
+       }
+       fseek(filehandle, 0L, SEEK_SET);
+       if (fread(buffer, length, 1, filehandle) != 1) {
+               fprintf(stderr, "Unable to read the whole file content!\n");
+               return 5;
+       }
+       fclose(filehandle);
+       if (length < length_padded) {
+               memset(buffer + length, 0, length_padded - length);
+       }
+
+       // check second argument (IPv4 address)
+       if (!inet_aton(ipaddr, &sin_addr)) {
+               fprintf(stderr, "'%s' is an invalid IPv4 address!\n", ipaddr);
+               return 6;
+       }
+       fprintf(stdout, "IPv4 address: %s\n", inet_ntoa(sin_addr));
+
+       // connect to the host
+       sd = socket(PF_INET, SOCK_STREAM, 0);
+       if (sd < 0) {
+               fprintf(stderr, "Unable to create a socket!\n");
+               return 7;
+       }
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(TCP_UPLOAD_PORT);
+       memcpy(&sin.sin_addr, &sin_addr, sizeof(sin.sin_addr));
+       if (connect(sd, (struct sockaddr *)&sin, sizeof(sin))) {
+               fprintf(stderr, "Unable to connect to host!\n");
+               return 8;
+       }
+
+       // do the upgrade process
+       setbuf(stdout, NULL);
+       if (upload(sd, buffer, length_padded, upload_page)) return 9;
+
+       // cleaning
+       close(sd);
+       return 0;
+}