/* 
 * treo-grab-calls.c: 
 *
 *   Grab call logs off a Treo 600 phone and dump csv to stdout.
 *
 * (c) 2004, Matthew Allum <mallum@o-hand.com>
 *
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

/* 
   Compile with something like;

       gcc -Wall -g treo-grab-calls.c -o treo-grab-calls -lpisock

   ( you need the pilot-link librarys installed )

 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>

#include <pi-dlp.h>
#include <pi-file.h>
#include <pi-socket.h>
#include <pi-header.h>

#define PHONECALL_PDB_NAME "PhoneCallDB.pdb"
#define PORT               "/dev/ttyUSB1"

typedef struct PhoneCallLogEntry /* 10 Bytes */
{
  unsigned short unknown_1;
  unsigned short call_date;		
  unsigned char  call_hour;
  unsigned char  call_mins;
  unsigned char  unknown_2[2];
  unsigned short call_duration;

} PhoneCallLogEntry;

/* FIXME: need to ifdef around these for LE systems */
/* FIXME: Does pilot-link already provide these kind of funcs ?*/

unsigned short 
ntohs(unsigned short x)
{
  unsigned short y;
  char *a, *b;

  a = (char *) &x; b = (char *) &y;
  b[0] = a[1]; b[1] = a[0];
  return y;
}

int
fetch_remote_file(int sd, char *fullname)
{
  struct DBInfo   info;
  char           *basename = NULL;
  struct pi_file *pi_fp;

  basename = strdup(fullname);

  basename[strlen(fullname)-4] = '\0';

  if (dlp_FindDBInfo(sd, 0, 0, basename, 0, 0, &info) < 0) 
    {
      free(basename);
      return 0;
    }

  /* info.flags &= 0x2fd; needed ? */

  pi_fp = pi_file_create(fullname, &info);

  if (pi_file_retrieve(pi_fp, sd, 0) < 0)
    {
      free(basename);
      return 0;
    }

  pi_file_close(pi_fp);

  free(basename);
  return 1;
}


int 
main(int argc, char **argv)
{
  char           *call_type_lookup[10] = { "Incoming", "Missed", "Outgoing" };
  struct pi_file *pi_fp;
  int             i, size, attr, cat, nentries;
  pi_uid_t        uid;
  int             sd = -1;
  void           *buf;

  PhoneCallLogEntry *log_entry; 
  char              *log_entry_name   = NULL;
  char              *log_entry_number = NULL;
  struct tm          log_entry_tm;
  unsigned short     d;
  char               date_str[64];
  int                dur_h, dur_m, dur_s;

  if ((sd = pilot_connect(PORT)) < 0)
    {
      fprintf(stderr, "FAILED: unable to connect via '%s'\n", PORT);
      exit(1);
    }

  if (!fetch_remote_file(sd, PHONECALL_PDB_NAME))
    {
      fprintf(stderr, "FAILED: unable to fetch '%s'\n", PHONECALL_PDB_NAME);
      exit(1);
    }

  if ((pi_fp = pi_file_open(PHONECALL_PDB_NAME)) == NULL)
    {
      printf("FAILED: could not open local '%s'\n", PHONECALL_PDB_NAME);
      exit(1);
    }

  pi_file_get_entries(pi_fp, &nentries);

  for (i=0; i < nentries; i++)
    {
      if (pi_file_read_record(pi_fp, i, &buf, &size, 
			      &attr, &cat, &uid) < 0) 
	{
	  printf("Error reading record: %d\n\n", i);
	  continue;
	}

      log_entry      = (PhoneCallLogEntry*)buf;

      log_entry_name = log_entry_number = buf + 10;
      
      while ( *log_entry_number != '\0' ) 
	log_entry_number++;

      log_entry_number++;

      /* Covert palm style date to unix one - thanks pilot-link/todo.c */

      d = ntohs(log_entry->call_date);

      log_entry_tm.tm_year 	= (d >> 9) + 4;
      log_entry_tm.tm_mon 	= ((d >> 5) & 15) - 1;
      log_entry_tm.tm_mday 	= d & 31;
      log_entry_tm.tm_hour 	= 0;
      log_entry_tm.tm_min 	= 0;
      log_entry_tm.tm_sec 	= 0;
      log_entry_tm.tm_isdst     = -1;
      mktime(&log_entry_tm);

      snprintf(date_str, 64, "%04d-%02d-%02d",
	       log_entry_tm.tm_year + 1900, 
	       log_entry_tm.tm_mon + 1, 
	       log_entry_tm.tm_mday );


      /* Break the call duration up into hours/mins/secs */
	
      d = ntohs(log_entry->call_duration);

      dur_s  = d % 60;
      d = d - dur_s;
      dur_m  = (d % (60*60)) / 60;
      d = d - (dur_m * 60);
      dur_h = d / (60*60);
	
      printf("%s %02d:%02d:00,%02d:%02d:%02d,%s,%s,%s\n", 
	     date_str,
	     log_entry->call_hour,
	     log_entry->call_mins,
	     dur_h, dur_m, dur_s,
	     *log_entry_name   != '\0' ? log_entry_name   : "Unknown",
	     *log_entry_number != '\0' ? log_entry_number : "Unknown",
	     call_type_lookup[cat-1]
	     );

    }

  pi_file_close(pi_fp);

  unlink(PHONECALL_PDB_NAME);

  return 0;
}
