Syncing a Tungsten T via USB using gpilotd works
- From: Peter Dieth <peter dieth suedwest-aktiv de>
- To: gnome-pilot-list gnome org
- Subject: Syncing a Tungsten T via USB using gpilotd works
- Date: 10 Jan 2003 20:52:55 +0100
Hi all,
I am using a Palm Tungsten T (running PalmOS5.0) with
RedHat8.0 (2.4.18-18), pilot-link-0.11.7, gnome-pilot-0.1.71-1
and evolution 1.2.1. This configuration is not able
to sync the Tungsten T using the USB craddle.
I digged through the gnome-pilot sources, managed to
patch the sources and now I am a happy syncer. :-)
I have attached the file gpilotd.c which contains my
(ugly) patch for the Tungsten T.
The gory details:
I am checking the output of /proc/bus/usb/devices against the unique
USB product ID of the Tungsten T (Vendor=0830 ProdID=0060).
If this string is found, we can set the necessary parameters/flags
for syncing.
Cheers,
Peter
--
Suedwest Presse Online-Dienste GmbH
Dipl.-Inform.(FH) Peter Dieth - Geschäftsbereichsleiter
Frauenstrasse 77, D-89073 Ulm
peter dieth suedwest-aktiv de http://www.suedwest-aktiv.de
Fon: 0731-156-801 Fax: 0731-156-659
http://www.koepfe.de/me.asp?ID=PRDH207303
PGP key http://www.dieth.de/contact.phtml
PGP fingerprint 01 98 7D CB 6D 84 C1 35 59 32 CE 5C 0A 33 E8 88
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- *//*
* Copyright (C) 1998-2000 Free Software Foundation
*
* 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.
*
* Authors: Eskil Heyn Olsen
* Vadim Strizhevsky
* Manish Vachharajani
* Dave Camp
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* for crypt () */
#ifdef USE_XOPEN_SOURCE
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE
#endif /* _XOPEN_SOURCE */
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <glib.h>
#include <pwd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <libgnome/libgnome.h>
#include <pi-source.h>
#include <pi-dlp.h>
#include <pi-version.h>
#include "manager.h"
#include "gnome-pilot-structures.h"
#include "orbit_daemon_glue.h"
#include "gpilot-gui.h"
#include "gnome-pilot-conduit-backup.h"
#include <libgpilotdCM/gnome-pilot-conduit-management.h>
/* Set to true when the config should be reloaded */
gboolean reread_config;
gint device_equal_by_io (GPilotDevice *,GIOChannel *);
gboolean device_in (GIOChannel *,
GIOCondition ,
GPilotContext *);
gboolean device_err (GIOChannel *,
GIOCondition ,
GPilotContext *);
gboolean network_device_in (GIOChannel *,
GIOCondition ,
GPilotContext *);
gboolean network_device_err (GIOChannel *,
GIOCondition ,
GPilotContext *);
void monitor_channel (GPilotDevice *,GPilotContext *);
void remove_pid_file (void);
gint
device_equal_by_io (GPilotDevice *dev,GIOChannel *io)
{
return !(dev->io==io);
}
static void
remove_device (GPilotContext *context,GPilotDevice *device)
{
GList *l;
g_message ("Removing %s",device->name);
l = g_list_find (context->devices,device);
if (l != NULL) {
gpilot_device_free (l->data);
g_list_remove (context->devices,l);
} else {
g_message ("%s not found",device->name);
}
}
static void
pilot_set_baud_rate (GPilotDevice *device)
{
static gchar rate_buf[128];
g_snprintf (rate_buf,128,"PILOTRATE=%d", device->speed);
g_message ("setting %s",rate_buf);
putenv (rate_buf);
}
/*
Sets *error to 1 on fatal error on the device, 2 on other errors , 0 otherwise.
*/
static int
pilot_connect (GPilotDevice *device,int *error)
{
struct pi_sockaddr addr;
int sd, listen_sd, pf;
int ret;
if (device->type != PILOT_DEVICE_NETWORK) {
pilot_set_baud_rate (device);
}
switch (device->type) {
case PILOT_DEVICE_SERIAL:
pf = PI_PF_PADP;
break;
case PILOT_DEVICE_USB_VISOR:
pf = PI_PF_NET;
break;
case PILOT_DEVICE_IRDA:
pf = PI_PF_PADP;
break;
case PILOT_DEVICE_NETWORK:
pf = PI_PF_NET;
break;
default:
pf = PI_PF_DLP;
break;
}
if (!(listen_sd = pi_socket (PI_AF_PILOT, PI_SOCK_STREAM, pf))) {
g_warning ("pi_socket: %s",strerror (errno));
if (error) *error = 1;
return -1;
}
addr.pi_family = PI_AF_PILOT;
/*
Most important for networking
. resolves inside libpisock as network
It is done earlier in gpilotd_device_init
so don't really need to do it again here.
*/
if (device->type == PILOT_DEVICE_NETWORK) {
device->port = "net:any";
}
strcpy (addr.pi_device,device->port);
ret = pi_bind (listen_sd, (struct sockaddr*)&addr, sizeof (addr));
if (ret == -1) {
g_warning (_("Unable to bind to pilot"));
if (error)
*error = 1;
pi_close(listen_sd);
return 0;
}
ret = pi_listen (listen_sd, 1);
if (ret != 0) {
g_warning ("pi_listen: %s", strerror (errno));
if (error)
*error = 2;
pi_close(listen_sd);
return 0;
}
sd = pi_accept_to (listen_sd, NULL,0, device->timeout);
if (sd == -1) {
g_warning ("pi_accept_to: %s", strerror (errno));
g_warning ("pi_accept_to: timeout was %d secs", device->timeout);
if (error)
*error = 2;
pi_close(listen_sd);
return 0;
}
if (error)
*error = 0;
pi_close(listen_sd);
return sd;
}
static void pilot_disconnect (int sd)
{
dlp_EndOfSync (sd, 0);
pi_close (sd);
}
static void write_sync_stamp (GPilotPilot *pilot,
int pfd,
struct PilotUser *pu,
guint32 last_sync_pc,
time_t t)
{
gchar prefix[256];
pu->lastSyncPC=last_sync_pc;
pu->lastSyncDate=t;
g_snprintf (prefix,255,"/gnome-pilot.d/gpilotd/Pilot%d/",pilot->number);
gnome_config_push_prefix (prefix);
gnome_config_private_set_int ("sync_date",t);
gnome_config_pop_prefix ();
gnome_config_sync ();
dlp_WriteUserInfo (pfd,pu);
}
/** pilot lookup methods **/
static gint
match_pilot_and_majick (const GPilotPilot *pilot,
unsigned long creation,
unsigned long romversion)
{
if (pilot->creation == creation &&
pilot->romversion == romversion) {
g_message ("pilot %s %ld %ld matches %ld %ld",
pilot->name,
pilot->creation,
pilot->romversion,
creation,
romversion);
return 1;
}
g_message ("pilot %s %ld %ld doesn't match %ld %ld",
pilot->name,
pilot->creation,
pilot->romversion,
creation,
romversion);
return 0;
}
/**************************/
/*
* We get a pfd, a device and the context (called if a pilot
* with id == 0 synchronizes)
* Get whatever majick number we can get and try to id
* the pilot and offer to restore it. If it can id the
* pilot, ask the user to choose one or "make a new pilot"
*/
static gboolean
gpilot_attempt_restore (struct PilotUser pu,
int pfd,
GPilotDevice *device,
GPilotContext *context)
{
struct SysInfo sysinfo;
struct CardInfo cardinfo;
GPilotPilot *pilot = NULL;
GList *iterator;
gboolean result = FALSE;
dlp_ReadStorageInfo (pfd, 0, &cardinfo);
dlp_ReadSysInfo (pfd, &sysinfo);
if (g_list_length (context->pilots) == 1) {
pilot = GPILOT_PILOT (g_list_nth (context->pilots, 0)->data);
g_message ("D: Only one pilot (%s) profile...", pilot->name);
} else {
for (iterator = context->pilots; iterator; iterator = g_list_next (iterator)) {
pilot = GPILOT_PILOT (iterator->data);
if (match_pilot_and_majick (pilot,
cardinfo.creation,
sysinfo.romVersion)) {
break;
}
}
}
if (pilot) {
GPilotPilot *a_pilot;
a_pilot = gpilot_gui_restore (context, pilot);
if (a_pilot) {
orbed_notify_connect (pilot->name,pu);
result = gpilot_start_unknown_restore (pfd, device, a_pilot);
orbed_notify_disconnect (pilot->name);
}
} else {
/* MUST GO */
gpilot_gui_warning_dialog ("no ident\n"
"restoring pilot with ident\n"
"c/r = %lu/%lu, exciting things\n"
"will soon be here...",
cardinfo.creation,
sysinfo.romVersion);
}
return TRUE;
}
/*
* This function handles when sync_device (...) encounters an unknown pilot
*/
static void
gpilot_syncing_unknown_pilot (struct PilotUser pu,
int pfd,
GPilotDevice *device,
GPilotContext *context)
{
g_warning (_("Unknown pilot, no userID/username match %ld"),pu.userID);
/* FIXME: here, restoring one of the available pilots should be
offered to the user. Of course with password prompt if the user
has password set
bug # 8217 */
if (pu.userID == 0) {
if (gpilot_attempt_restore (pu, pfd, device, context) == FALSE) {
gpilot_gui_warning_dialog (_("Use gnomecc to configure pilot"));
}
} else {
/* FIXME: here we should offer to create a profile for the pilot,
bug # 8218 */
gpilot_gui_warning_dialog (_("Unknown pilot - no pilots matches ID %ld\n"
"Use gnomecc to set pilot's ID"),pu.userID);
}
}
/*
* If there are events for the cradle, this executes them,
* closes the connection and returns.
* Returns TRUE if connection should be closed afterwards, FALSE
* is sync should continue
*/
static gboolean
do_cradle_events (int pfd,
GPilotContext *context,
struct PilotUser *pu,
GPilotDevice *device)
{
GList *events,*it;
gboolean ret = TRUE;
/* elements in events freed by gpc_request_purge calls
in orbed_notify_completion */
events = gpc_queue_load_requests_for_cradle (device->name);
g_message (_("Cradle %s has %d events"), device->name, g_list_length (events));
/* if no events, return FALSE */
if (g_list_length (events)==0) ret = FALSE;
it = events;
while (it) {
GPilotRequest *req;
req = it->data;
switch (req->type) {
case GREQ_SET_USERINFO:
g_message (_("Setting userinfo..."));
g_snprintf (pu->username,127,"%s", req->parameters.set_userinfo.user_id);
pu->userID = req->parameters.set_userinfo.pilot_id;
dlp_WriteUserInfo (pfd,pu);
if (req->parameters.set_userinfo.continue_sync) {
g_message (_("Sync continues"));
ret = FALSE;
}
orbed_notify_completion (&req);
break;
case GREQ_GET_SYSINFO: {
struct SysInfo sysinfo;
struct CardInfo cardinfo;
dlp_ReadStorageInfo (pfd, 0, &cardinfo);
dlp_ReadSysInfo (pfd, &sysinfo);
orbed_notify_sysinfo (device->name,
sysinfo,
cardinfo,
&req);
orbed_notify_completion (&req);
}
break;
case GREQ_GET_USERINFO:
g_message (_("Getting userinfo..."));
orbed_notify_userinfo (*pu,&req);
orbed_notify_completion (&req);
break;
case GREQ_NEW_USERINFO:
/* FIXME: this is to set the new and return the old (or something)
g_message ("getting & setting userinfo");
g_snprintf (pu->username,127,"%s",req->parameters.set_userinfo.user_id);
pu->userID = req->parameters.set_userinfo.pilot_id;
dlp_WriteUserInfo (pfd,pu);
orbed_notify_completion (&req);
*/
break;
default:
g_warning ("%s:%d: *** type = %d",__FILE__,__LINE__,req->type);
g_assert_not_reached ();
break;
}
it = g_list_next (it);
}
return ret;
}
/**************************/
/*
This executes a sync for a pilot.
If first does some printing to the stdout and some logging to the
pilot, so the dudes can see what is going on. Afterwards, it does
the initial synchronization operations (which is handling file
installs, restores, specific conduits runs). This function (in
manager.c) returns a boolean, whic may abort the entire
synchronization.
If it does not, a function in manager.c will be called depending of
the default_sync_action setting for the pilot (you know, synchronize
vs copy to/from blablabla).
*/
static void
do_sync (int pfd,
GPilotContext *context,
struct PilotUser *pu,
GPilotPilot *pilot,
GPilotDevice *device)
{
GList *conduit_list, *backup_conduit_list, *file_conduit_list;
GnomePilotSyncStamp stamp;
gchar *pilot_name;
pilot_name = pilot_name_from_id (pu->userID,context);
gpilot_load_conduits (context,
pilot,
&conduit_list,
&backup_conduit_list,
&file_conduit_list);
stamp.sync_PC_Id=context->sync_PC_Id;
if (device->type == PILOT_DEVICE_NETWORK) {
g_message (_("NetSync request detected, synchronizing pilot"));
} else {
g_message (_("HotSync button pressed, synchronizing pilot"));
}
g_message (_("Pilot ID is %ld, name is %s, owner is %s"),
pu->userID,
pilot->name,
pu->username);
/* Set a log entry in the pilot */
{
gchar hostname[64];
gpilot_add_log_entry (pfd,"gnome-pilot v.%s\n",VERSION);
if (gethostname (hostname,63)==0)
gpilot_add_log_entry (pfd,_("On host %s\n"),hostname);
else
gpilot_add_log_entry (pfd,_("On host %d\n"),stamp.sync_PC_Id);
}
/* first, run the initial operations, such as single conduit runs,
restores etc. If this returns True, continue with normal conduit running,
if False, don't proceed */
if (gpilot_initial_synchronize_operations (pfd,
&stamp,
pu,
conduit_list,
backup_conduit_list,
file_conduit_list,
device,
context)) {
/* FIXME: We need to actually pass a different structure to these
functions containing the pu item and the pilot pointer so that
we can store the lastSyncPC and assorted fields in
~/.gnome_private/gnome-pilot.d/gpilotd. We will also need some
lock mechanism when we start forking for that file :)*/
switch (pilot->sync_options.default_sync_action) {
case GnomePilotConduitSyncTypeSynchronize:
g_message (_("Synchronizing..."));
gpilot_synchronize (pfd,&stamp,pu,
conduit_list,
backup_conduit_list,
file_conduit_list,
context);
break;
case GnomePilotConduitSyncTypeCopyToPilot:
g_message (_("Copying to pilot..."));
gpilot_copy_to_pilot (pfd,&stamp,pu,
conduit_list,
backup_conduit_list,
file_conduit_list,
context);
break;
case GnomePilotConduitSyncTypeCopyFromPilot:
g_message (_("Copying from pilot..."));
gpilot_copy_from_pilot (pfd,&stamp,pu,
conduit_list,
backup_conduit_list,
context);
break;
case GnomePilotConduitSyncTypeMergeToPilot:
g_message (_("Merging to pilot..."));
gpilot_merge_to_pilot (pfd,&stamp,pu,
conduit_list,
backup_conduit_list,
file_conduit_list,
context);
break;
case GnomePilotConduitSyncTypeMergeFromPilot:
g_message (_("Merging from pilot..."));
gpilot_merge_from_pilot (pfd,&stamp,pu,
conduit_list,
backup_conduit_list,
context);
break;
case GnomePilotConduitSyncTypeNotSet:
case GnomePilotConduitSyncTypeCustom:
default:
g_message (_("Using conduit settings for sync..."));
gpilot_sync_default (pfd,&stamp,pu,
conduit_list,
backup_conduit_list,
file_conduit_list,
context);
break;
}
g_message (_("Synchronization ended"));
gpilot_add_log_entry (pfd,"Synchronization completed");
} else {
g_message (_("Synchronization ended early"));
gpilot_add_log_entry (pfd,"Synchronization terminated");
}
write_sync_stamp (pilot,pfd,pu,stamp.sync_PC_Id,time (NULL));
g_free (pilot_name);
gpilot_unload_conduits (conduit_list);
gpilot_unload_conduits (backup_conduit_list);
gpilot_unload_conduits (file_conduit_list);
}
/*
* This function handles when sync_device (...) encounters a known pilot
*/
static void
gpilot_syncing_known_pilot (GPilotPilot *pilot,
struct PilotUser pu,
int pfd,
GPilotDevice *device,
GPilotContext *context)
{
struct stat buf;
int ret;
ret = stat (pilot->sync_options.basedir, &buf);
if (ret < 0 || !( S_ISDIR (buf.st_mode) && (buf.st_mode & (S_IRUSR | S_IWUSR |S_IXUSR))) ) {
g_message ("Invalid basedir: %s", pilot->sync_options.basedir);
gpilot_gui_warning_dialog (_("The base directory %s is invalid.\n"
"Please fix it or use gnomecc to choose another directory."),
pilot->sync_options.basedir);
} else {
gboolean pwd_ok = TRUE;
/* If pilot has password, check against the encrypted version
on the pilot */
if (pilot->passwd) {
char *pwd;
pwd = (char*)g_malloc (pu.passwordLength);
strncpy (pwd,pu.password,pu.passwordLength);
if (g_strcasecmp (pilot->passwd,(char*)crypt (pwd,pilot->passwd))) {
pwd_ok = FALSE;
gpilot_gui_warning_dialog (_("Unknown pilot - no pilots matches ID %ld\n"
"Use gnomecc to set pilot's ID"),pu.userID);
}
g_free (pwd);
}
if (pwd_ok) {
do_sync (pfd,context,&pu,pilot,device);
}
}
}
/*
sync_foreach is the first synchronization entry.
It first connects to the device on which the signal was detected,
then it tries to read the user info block from the pilot.
Hereafter, if there are any events queued for the synchronizing
cradle, execute them and stop the synchronization (note,
do_cradle_events returns a bool, if this is FALSE, synchronization
continues, as some cradle specific events also require a normal sync
afterwards, eg. the REVIVE call)
Anyways, if the sync continues, sync_foreach tries to match the
pilot against the known pilots. If this fails, it should handle it
intelligently, eg. if the id==0, ask if you want to restore a pilot.
If the pilot is accepted (dude, there's even a password check!), it
continues into do_sync, which does all the magic stuff.
*/
static gboolean
sync_device (GPilotDevice *device, GPilotContext *context)
{
GPilotPilot *pilot;
int pfd;
int connect_error;
struct PilotUser pu;
struct SysInfo ps;
g_assert (context != NULL);
g_return_val_if_fail (device != NULL, FALSE);
/* signal (SIGHUP,SIG_DFL); */
pfd = pilot_connect (device,&connect_error);
if (!connect_error) {
/* connect succeeded, try to read the systeminfo */
if (dlp_ReadSysInfo (pfd, &ps) < 0) {
/* no ? drop connection then */
g_warning (_("An error occured while getting the pilot's system data"));
/* connect succeeded, try to read the userinfo */
} else if (dlp_ReadUserInfo (pfd,&pu) < 0) {
/* no ? drop connection then */
g_warning (_("An error occured while getting the pilot's user data"));
} else {
/* If there are cradle specific events, handle them and stop */
if (do_cradle_events (pfd,context,&pu,device)) {
g_message (_("Completed events for cradle %s (%s)"),device->name,device->port);
} else {
/* No cradle events, validate pilot */
pilot = gpilot_find_pilot_by_id (pu.userID,context->pilots);
if (pilot == NULL) {
/* Pilot is not known */
gpilot_syncing_unknown_pilot (pu, pfd, device, context);
} else {
/* Pilot is known, make connect notifications */
orbed_notify_connect (pilot->name,pu);
gpilot_syncing_known_pilot (pilot, pu, pfd, device, context);
orbed_notify_disconnect (pilot->name);
}
}
}
pilot_disconnect (pfd);
} else {
if (connect_error==1) return FALSE; /* remove this device */
else return TRUE;
}
return TRUE;
}
gboolean
device_in (GIOChannel *io_channel,
GIOCondition condition,
GPilotContext *context) {
GPilotDevice *device;
GList *element;
gboolean result = TRUE;
g_assert (context != NULL);
element = g_list_find_custom (context->devices,
io_channel,
(GCompareFunc)device_equal_by_io);
if (element==NULL || element->data == NULL) {
g_warning ("cannot find device for active IO channel");
return FALSE;
}
device = element->data;
if (context->paused) {
return FALSE;
}
g_message (_("Woke on %s"),device->name);
result = sync_device (device,context);
#ifdef WITH_IRDA
if (device->type == PILOT_DEVICE_IRDA) {
g_message ("Restarting irda funk...");
gpilot_device_deinit (device);
gpilot_device_init (device);
monitor_channel (device, context);
result = FALSE;
}
#endif /* WITH_IRDA */
return result;
}
gboolean
device_err (GIOChannel *io_channel,
GIOCondition condition,
GPilotContext *context) {
GPilotDevice *device;
GList *element;
char *tmp;
g_assert (context != NULL);
switch (condition) {
case G_IO_IN: tmp = g_strdup_printf ("G_IO_IN"); break;
case G_IO_OUT : tmp = g_strdup_printf ("G_IO_OUT"); break;
case G_IO_PRI : tmp = g_strdup_printf ("G_IO_PRI"); break;
case G_IO_ERR : tmp = g_strdup_printf ("G_IO_ERR"); break;
case G_IO_HUP : tmp = g_strdup_printf ("G_IO_HUP"); break;
case G_IO_NVAL: tmp = g_strdup_printf ("G_IO_NVAL"); break;
default: tmp = g_strdup_printf ("unhandled port error"); break;
}
element = g_list_find_custom (context->devices,io_channel,(GCompareFunc)device_equal_by_io);
if (element==NULL) {
/* We most likely end here if the device has just been removed.
Eg. start gpilotd with a monitor on a XCopilot fake serial port,
kill xcopilot and watch things blow up as the device fails */
g_warning ("Device error on some device, caught %s",tmp);
g_free (tmp);
return FALSE;
}
device = element->data;
gpilot_gui_warning_dialog ("Device error on %s (%s)\n"
"Caught %s",device->name,device->port,tmp);
g_warning ("Device error on %s (%s), caught %s",device->name,device->port,tmp);
remove_device (context,device);
g_free (tmp);
return FALSE;
}
#ifdef WITH_NETWORK
gboolean
network_device_in (GIOChannel *io_channel,
GIOCondition condition,
GPilotContext *context) {
GPilotDevice *device;
GList *element;
gboolean result = TRUE;
g_assert (context != NULL);
element = g_list_find_custom (context->devices,
io_channel,
(GCompareFunc)device_equal_by_io);
if (element==NULL || element->data == NULL) {
g_warning ("cannot find device for active IO channel");
return FALSE;
}
device = element->data;
if (context->paused) {
return FALSE;
}
g_message (_("Woke on %s"),device->name);
result = sync_device (device,context);
return result;
}
gboolean
network_device_err (GIOChannel *io_channel,
GIOCondition condition,
GPilotContext *context) {
GPilotDevice *device;
GList *element;
char *tmp;
g_assert (context != NULL);
switch (condition) {
case G_IO_IN: tmp = g_strdup_printf ("G_IO_IN"); break;
case G_IO_OUT : tmp = g_strdup_printf ("G_IO_OUT"); break;
case G_IO_PRI : tmp = g_strdup_printf ("G_IO_PRI"); break;
case G_IO_ERR : tmp = g_strdup_printf ("G_IO_ERR"); break;
case G_IO_HUP : tmp = g_strdup_printf ("G_IO_HUP"); break;
case G_IO_NVAL: tmp = g_strdup_printf ("G_IO_NVAL"); break;
default: tmp = g_strdup_printf ("unhandled port error"); break;
}
element = g_list_find_custom (context->devices,io_channel,(GCompareFunc)device_equal_by_io);
if (element==NULL) {
/* We most likely end here if the device has just been removed.
Eg. start gpilotd with a monitor on a XCopilot fake serial port,
kill xcopilot and watch things blow up as the device fails */
g_warning ("Device error on some device, caught %s",tmp);
g_free (tmp);
return FALSE;
}
device = element->data;
gpilot_gui_warning_dialog ("Device error on %s (%s)\n"
"Caught %s",device->name,device->port,tmp);
g_warning ("Device error on %s (%s), caught %s",device->name,device->port,tmp);
remove_device (context,device);
g_free (tmp);
return FALSE;
}
#endif /* WITH_NETWORK */
#ifdef WITH_USB_VISOR
#ifdef linux
static const char *product_names[] =
{
"Handspring Visor",
"Handspring Treo",
"Palm Handheld",
NULL
};
static gboolean product_net[] =
{
FALSE,
TRUE,
TRUE,
-1
};
static gboolean
visor_devices_in (GIOChannel *io_channel,
GIOCondition condition,
GPilotContext *context) {
GPilotDevice *device;
GList *l;
int i;
gboolean visor_exists = FALSE, visor_net = TRUE;
char line[256]; /* this is more than enough to fit any line from
* /proc/bus/usb/devices */
FILE *f;
g_assert (context != NULL);
sleep (2);
if (context->paused)
return FALSE;
/* Check /proc/bus/usb/devices for a usb device */
f = fopen ("/proc/bus/usb/devices", "r");
while (fgets (line, 255, f) != NULL && !visor_exists) {
/*
* HACK_ON: identify the Tungsten based on the product id line
*
*Â (1) before pressing the hotsync button on the USBicraddle
* $ cat /proc/bus/usb/devices > /tmp/before-sync.txt
*
*Â (2) after pressing the hotsync button on the USB craddle
* $ cat /proc/bus/usb/devices > /tmp/after-sync.txt
*
*Â (3) difference is
*Â $ diff /tmp/before-sync.txt /tmp/after-sync.txt
*Â ...
* > P:Â Vendor=0830 ProdID=0060 Rev= 1.00
*Â ...
*********************** This is Tungsten T !
*/
if (line[0] == 'P') {
#define TUNGSTEN_STRING "P: Vendor=0830 ProdID=0060 Rev= 1.00"
if (!strncmp (line, TUNGSTEN_STRING, strlen(TUNGSTEN_STRING))) {
g_message("yippie - found my Tungsten T!");
visor_exists = TRUE;
visor_net = TRUE;
goto endloop;
}
}
if (line[0] != 'S')
continue;
for (i = 0; product_names[i] != NULL; i++) {
if (!strncmp (line + strlen ("S: Product="),
product_names[i],
strlen (product_names[i]))) {
visor_exists = TRUE;
visor_net = product_net[i];
}
}
}
endloop:
fclose (f);
if (visor_exists) {
l = context->devices;
while (l) {
device = l->data;
if (device->type == PILOT_DEVICE_USB_VISOR) {
if (!visor_net)
device->type = PILOT_DEVICE_SERIAL;
/* just try to synch. Until I can talk to
* the kernel guys this is the best way to
* go. */
sync_device (device, context);
if (!visor_net)
device->type = PILOT_DEVICE_USB_VISOR;
}
l = l->next;
}
}
return TRUE;
}
static gboolean
visor_devices_err (GIOChannel *io_channel,
GIOCondition condition,
GPilotContext *context)
{
g_assert (context != NULL);
gpilot_gui_warning_dialog ("Read error on /proc/bus/usb/devices");
g_warning ("Read error on /proc/bus/usb/devices");
return FALSE;
}
#endif
#endif
void monitor_channel (GPilotDevice *dev,GPilotContext *context) {
g_assert (context != NULL);
if (dev->type == PILOT_DEVICE_SERIAL
|| dev->type == PILOT_DEVICE_IRDA) {
dev->in_handle = g_io_add_watch (dev->io,
G_IO_IN,
(GIOFunc)device_in,
(gpointer)context);
dev->err_handle = g_io_add_watch (dev->io,
G_IO_ERR|G_IO_PRI|G_IO_HUP|G_IO_NVAL,
(GIOFunc)device_err,
(gpointer)context);
} else if (dev->type == PILOT_DEVICE_NETWORK) {
#ifdef WITH_NETWORK
dev->in_handle = g_io_add_watch (dev->io,
G_IO_IN,
(GIOFunc)network_device_in,
(gpointer)context);
dev->err_handle = g_io_add_watch (dev->io,
G_IO_ERR|G_IO_PRI|G_IO_HUP|G_IO_NVAL,
(GIOFunc)network_device_err,
(gpointer)context);
#else /* WITH_NETWORK */
g_assert_not_reached ();
#endif /* WITH_NETWORK */
} if (dev->type == PILOT_DEVICE_USB_VISOR) {
#ifdef WITH_USB_VISOR
#ifdef linux
/* We want to watch the /proc/bus/usb/devices file once
* per context, and then check all devices each time it is
* woken up. */
if (context->visor_fd == -1) {
context->visor_fd = open ("/proc/bus/usb/devices",
O_RDONLY);
if (context->visor_fd == -1) {
g_warning ("Could not open /proc/bus/usb/devices - make sure you have the usbdevfs properly configured and mounted.");
return;
}
context->visor_io =
g_io_channel_unix_new (context->visor_fd);
context->visor_in_handle =
g_io_add_watch (context->visor_io,
G_IO_IN,
(GIOFunc)visor_devices_in,
(gpointer)context);
context->visor_err_handle =
g_io_add_watch (context->visor_io,
G_IO_ERR|G_IO_PRI|G_IO_HUP|G_IO_NVAL,
(GIOFunc)visor_devices_err,
(gpointer)context);
}
#else /* linux*/
g_assert_not_reached ();
#endif /* linux */
#endif /* WITH_USB_VISOR */
dev->device_exists = FALSE;
}
if (dev->type == PILOT_DEVICE_NETWORK) {
g_message (_("Watching %s (%s, %s)"), dev->name, dev->ip, dev->host);
} else {
g_message (_("Watching %s (%s)"),dev->name,dev->port);
}
}
static void
sig_hup_handler (int dummy)
{
signal (SIGHUP,sig_hup_handler);
reread_config=TRUE;
}
static void
sig_term_handler (int dummy) {
g_message (_("Exiting (caught SIGTERM)..."));
remove_pid_file ();
gpilotd_corba_quit ();
exit (0);
}
static void
sig_int_handler (int dummy) {
g_message (_("Exiting (caught SIGINT)..."));
remove_pid_file ();
gpilotd_corba_quit ();
exit (0);
}
/* This deletes the ~/.gpilotd.pid file */
void
remove_pid_file () {
gchar *home_directory;
gchar *pid_file;
home_directory=g_get_home_dir ();
if (home_directory) {
pid_file=(gchar *)g_malloc (strlen (home_directory) +
strlen ("/.gpilotd.pid") + 1);
strcpy (pid_file,home_directory);
strcat (pid_file,"/.gpilotd.pid");
if (access (pid_file,R_OK|W_OK)==0) {
unlink (pid_file);
}
g_free (pid_file);
}
}
/*
The creates a ~/.gilotd.pid, containing the pid
of the gpilotd process, used by clients to send
SIGHUPS
*/
static void
write_pid_file ()
{
gchar *queue_dir;
queue_dir = g_strdup_printf ("%s/.gpilotd", g_get_home_dir ());
if (g_get_home_dir ()) {
gchar *pid_file;
int fd;
pid_file=(gchar *)g_malloc (strlen (g_get_home_dir ()) +
strlen ("/.gpilotd.pid") + 1);
strcpy (pid_file, g_get_home_dir());
strcat (pid_file,"/.gpilotd.pid");
if ((fd=open (pid_file,O_RDWR | O_TRUNC | O_CREAT, 0644)) >= 0) {
gchar pid[50]; /* If the pid is > 50 digits we have problems :) */
if (sizeof (pid_t) == sizeof (int)) {
g_snprintf (pid,50,"%d\n",getpid ());
} else { /* Assume pid_t is sizeof long */
g_snprintf (pid,50,"%ld\n",(unsigned long)getpid ());
}
write (fd,pid,strlen (pid));
close (fd);
} else {
g_warning (_("Unable to open or create "
"file %s with read/write privs"),pid_file);
}
g_free (pid_file);
} else {
g_warning (_("Unable to find home directory for uid %d"),geteuid ());
}
if (g_file_test (queue_dir, G_FILE_TEST_ISDIR)==FALSE) {
if (mkdir (queue_dir, 0700)) {
g_warning (_("Unable to create file installation queue directory"));
}
}
g_free (queue_dir);
}
/*
The main loop. Sets up monitors for the devices and calls
g_main_iteration to wait for a sync. The monitor handler handles
the sync, so look in device_in for the call to the actual sync.
If reread_config gets set to TRUE (by a SIGHUP signal, free
all devices and context and reload it
*/
static void
wait_for_sync_and_sync (GPilotContext *context) {
signal (SIGTERM,sig_term_handler);
signal (SIGINT,sig_int_handler);
signal (SIGHUP,sig_hup_handler);
g_list_foreach (context->devices, (GFunc)monitor_channel, context);
while (1) {
if (reread_config) {
g_message (_("Shutting down devices"));
gpilot_context_free (context);
g_message (_("Rereading configuration..."));
gpilot_context_init_user (context);
reread_config=FALSE;
g_list_foreach (context->devices, (GFunc)monitor_channel, context);
}
/* Enter the gtk main loop */
g_main_iteration (TRUE);
}
}
/* This function display which pilot-link version was used
and which features were enabled at compiletime */
static void
dump_build_info ()
{
GString *str = g_string_new (NULL);
g_message ("compiled for pilot-link version %s",
GP_PILOT_LINK_VERSION);
str = g_string_append (str, "compiled with ");
#ifdef WITH_VFS
str = g_string_append (str, "[VFS] ");
#endif
#ifdef WITH_USB_VISOR
str = g_string_append (str, "[USB] ");
#endif
#ifdef WITH_IRDA
str = g_string_append (str, "[IrDA] ");
#endif
#ifdef WITH_NETWORK
str = g_string_append (str, "[Network] ");
#endif
g_message (str->str);
g_string_free (str, TRUE);
}
int
main (int argc, char *argv[])
{
GPilotContext *context;
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
/*g_log_set_always_fatal (G_LOG_LEVEL_ERROR |
G_LOG_LEVEL_CRITICAL |
G_LOG_LEVEL_WARNING);*/
/* Intro */
g_message ("%s %s starting...",PACKAGE,VERSION);
dump_build_info ();
/* Setup the correct gpilotd.pid file */
remove_pid_file ();
write_pid_file ();
/* Init corba and context, this call also loads the config into context */
gtk_type_init ();
gpilotd_corba_init (&argc,argv,&context);
reread_config=FALSE;
/* Begin... */
wait_for_sync_and_sync (context);
/* It is unlikely that we will end here */
remove_pid_file ();
gpilotd_corba_quit ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]