/* Copyright (c) 2007, 2010 Christophe Fergeau <teuf@gnome.org>
* Part of the libgpod project.
*
* URL: http://www.gtkpod.org/
* URL: http://gtkpod.sourceforge.net/
*
* The code contained in this file is free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either version
* 2.1 of the License, or (at your option) any later version.
*
* This file 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* iTunes and iPod are trademarks of Apple
*
* This product is not supported/written/published by Apple!
*
*/
#include "config.h"
#include "backends.h"
#include <errno.h>
#include <glib.h>
#include <glib/gstdio.h>
#ifndef __USE_BSD
#define __USE_BSD /* for mkdtemp */
#endif
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/mount.h>
#include <itdb.h>
#include <itdb_device.h>
#include "itdb-syslog.h"
#ifdef HAVE_SGUTILS
extern char *read_sysinfo_extended (const char *device);
#endif
#ifdef HAVE_LIBUSB
extern char *read_sysinfo_extended_from_usb (guint bus_number, guint device_address);
#endif
struct _ProductionInfo {
gchar *factory_id;
guint production_year;
guint production_week;
guint production_index;
char *model_id;
};
typedef struct _ProductionInfo ProductionInfo;
static void
production_info_free (ProductionInfo *info)
{
g_return_if_fail (info != NULL);
g_free (info->factory_id);
g_free (info->model_id);
g_free (info);
}
static ProductionInfo *
parse_serial_number (const char *serial_number)
{
ProductionInfo *info;
char int_str[4];
if (serial_number == NULL) {
return NULL;
}
if (strlen (serial_number) < 11) {
return NULL;
}
info = g_new0 (ProductionInfo, 1);
info->factory_id = g_strndup (serial_number, 2);
serial_number += 2;
strncpy (int_str, serial_number, 1);
serial_number += 1;
info->production_year = 2000 + g_ascii_strtoull (int_str, NULL, 10);
strncpy (int_str, serial_number, 2);
serial_number += 2;
info->production_week = g_ascii_strtoull (int_str, NULL, 10);
strncpy (int_str, serial_number, 3);
serial_number += 3;
info->production_index = g_ascii_strtoull (int_str, NULL, 36);
info->model_id = g_strdup (serial_number);
return info;
}
static char *
get_model_name (const Itdb_IpodInfo *info)
{
if (info == NULL) {
return NULL;
}
switch (info->ipod_generation) {
case ITDB_IPOD_GENERATION_UNKNOWN:
return g_strdup ("unknown");
case ITDB_IPOD_GENERATION_FIRST:
case ITDB_IPOD_GENERATION_SECOND:
case ITDB_IPOD_GENERATION_THIRD:
case ITDB_IPOD_GENERATION_FOURTH:
return g_strdup ("grayscale");
case ITDB_IPOD_GENERATION_PHOTO:
return g_strdup ("color");
case ITDB_IPOD_GENERATION_MINI_1:
case ITDB_IPOD_GENERATION_MINI_2:
return g_strdup ("mini");
case ITDB_IPOD_GENERATION_SHUFFLE_1:
case ITDB_IPOD_GENERATION_SHUFFLE_2:
case ITDB_IPOD_GENERATION_SHUFFLE_3:
case ITDB_IPOD_GENERATION_SHUFFLE_4:
return g_strdup ("shuffle");
case ITDB_IPOD_GENERATION_NANO_1:
case ITDB_IPOD_GENERATION_NANO_2:
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
case ITDB_IPOD_GENERATION_NANO_6:
return g_strdup ("nano");
case ITDB_IPOD_GENERATION_VIDEO_1:
case ITDB_IPOD_GENERATION_VIDEO_2:
return g_strdup ("video");
case ITDB_IPOD_GENERATION_CLASSIC_1:
case ITDB_IPOD_GENERATION_CLASSIC_2:
case ITDB_IPOD_GENERATION_CLASSIC_3:
return g_strdup ("classic");
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
case ITDB_IPOD_GENERATION_TOUCH_4:
return g_strdup ("touch");
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
case ITDB_IPOD_GENERATION_IPHONE_4:
return g_strdup ("phone");
case ITDB_IPOD_GENERATION_IPAD_1:
return g_strdup ("ipad");
case ITDB_IPOD_GENERATION_MOBILE:
return g_strdup ("rokr");
}
g_assert_not_reached ();
}
static double
get_generation (const Itdb_IpodInfo *info)
{
if (info == NULL) {
return 0.0;
}
switch (info->ipod_generation) {
case ITDB_IPOD_GENERATION_UNKNOWN:
return 0.0;
case ITDB_IPOD_GENERATION_FIRST:
return 1.0;
case ITDB_IPOD_GENERATION_SECOND:
return 2.0;
case ITDB_IPOD_GENERATION_THIRD:
return 3.0;
case ITDB_IPOD_GENERATION_FOURTH:
return 4.0;
case ITDB_IPOD_GENERATION_PHOTO:
return 4.0;
case ITDB_IPOD_GENERATION_MINI_1:
return 1.0;
case ITDB_IPOD_GENERATION_MINI_2:
return 2.0;
case ITDB_IPOD_GENERATION_SHUFFLE_1:
return 1.0;
case ITDB_IPOD_GENERATION_SHUFFLE_2:
return 2.0;
case ITDB_IPOD_GENERATION_SHUFFLE_3:
return 3.0;
case ITDB_IPOD_GENERATION_SHUFFLE_4:
return 4.0;
case ITDB_IPOD_GENERATION_NANO_1:
return 1.0;
case ITDB_IPOD_GENERATION_NANO_2:
return 2.0;
case ITDB_IPOD_GENERATION_NANO_3:
return 3.0;
case ITDB_IPOD_GENERATION_NANO_4:
return 4.0;
case ITDB_IPOD_GENERATION_NANO_5:
return 5.0;
case ITDB_IPOD_GENERATION_NANO_6:
return 6.0;
case ITDB_IPOD_GENERATION_VIDEO_1:
return 5.0;
case ITDB_IPOD_GENERATION_VIDEO_2:
return 5.5;
case ITDB_IPOD_GENERATION_CLASSIC_1:
return 6.0;
case ITDB_IPOD_GENERATION_CLASSIC_2:
case ITDB_IPOD_GENERATION_CLASSIC_3:
return 6.5;
case ITDB_IPOD_GENERATION_TOUCH_1:
return 1.0;
case ITDB_IPOD_GENERATION_TOUCH_2:
return 2.0;
case ITDB_IPOD_GENERATION_TOUCH_3:
return 3.0;
case ITDB_IPOD_GENERATION_TOUCH_4:
return 4.0;
case ITDB_IPOD_GENERATION_IPHONE_1:
return 1.0;
case ITDB_IPOD_GENERATION_IPHONE_2:
return 2.0;
case ITDB_IPOD_GENERATION_IPHONE_3:
return 3.0;
case ITDB_IPOD_GENERATION_IPHONE_4:
return 4.0;
case ITDB_IPOD_GENERATION_IPAD_1:
return 1.0;
case ITDB_IPOD_GENERATION_MOBILE:
return 1.0;
}
g_assert_not_reached ();
}
static char *
get_color_name (const Itdb_IpodInfo *info)
{
if (info == NULL) {
return NULL;
}
switch (info->ipod_model) {
case ITDB_IPOD_MODEL_INVALID:
case ITDB_IPOD_MODEL_UNKNOWN:
return NULL;
case ITDB_IPOD_MODEL_COLOR:
case ITDB_IPOD_MODEL_COLOR_U2:
case ITDB_IPOD_MODEL_REGULAR:
case ITDB_IPOD_MODEL_REGULAR_U2:
case ITDB_IPOD_MODEL_NANO_WHITE:
case ITDB_IPOD_MODEL_VIDEO_WHITE:
case ITDB_IPOD_MODEL_SHUFFLE:
case ITDB_IPOD_MODEL_MOBILE_1:
case ITDB_IPOD_MODEL_IPHONE_WHITE:
return g_strdup ("white");
case ITDB_IPOD_MODEL_MINI:
case ITDB_IPOD_MODEL_NANO_SILVER:
case ITDB_IPOD_MODEL_SHUFFLE_SILVER:
case ITDB_IPOD_MODEL_CLASSIC_SILVER:
case ITDB_IPOD_MODEL_TOUCH_SILVER:
case ITDB_IPOD_MODEL_IPHONE_1:
case ITDB_IPOD_MODEL_IPAD:
return g_strdup ("silver");
case ITDB_IPOD_MODEL_VIDEO_U2:
case ITDB_IPOD_MODEL_NANO_BLACK:
case ITDB_IPOD_MODEL_VIDEO_BLACK:
case ITDB_IPOD_MODEL_CLASSIC_BLACK:
case ITDB_IPOD_MODEL_SHUFFLE_BLACK:
case ITDB_IPOD_MODEL_IPHONE_BLACK:
return g_strdup ("black");
case ITDB_IPOD_MODEL_MINI_PINK:
case ITDB_IPOD_MODEL_NANO_PINK:
case ITDB_IPOD_MODEL_SHUFFLE_PINK:
return g_strdup ("pink");
case ITDB_IPOD_MODEL_MINI_GREEN:
case ITDB_IPOD_MODEL_NANO_GREEN:
case ITDB_IPOD_MODEL_SHUFFLE_GREEN:
return g_strdup ("green");
case ITDB_IPOD_MODEL_MINI_GOLD:
case ITDB_IPOD_MODEL_SHUFFLE_GOLD:
return g_strdup ("gold");
case ITDB_IPOD_MODEL_NANO_BLUE:
case ITDB_IPOD_MODEL_MINI_BLUE:
case ITDB_IPOD_MODEL_SHUFFLE_BLUE:
return g_strdup ("blue");
case ITDB_IPOD_MODEL_SHUFFLE_RED:
case ITDB_IPOD_MODEL_NANO_RED:
return g_strdup ("red");
case ITDB_IPOD_MODEL_SHUFFLE_ORANGE:
case ITDB_IPOD_MODEL_NANO_ORANGE:
return g_strdup ("orange");
case ITDB_IPOD_MODEL_SHUFFLE_PURPLE:
case ITDB_IPOD_MODEL_NANO_PURPLE:
return g_strdup ("purple");
case ITDB_IPOD_MODEL_NANO_YELLOW:
return g_strdup ("yellow");
case ITDB_IPOD_MODEL_SHUFFLE_STAINLESS:
return g_strdup ("stainless");
}
g_assert_not_reached ();
}
static char *
get_icon_name (const Itdb_IpodInfo *info)
{
const char prefix[] = "multimedia-player-apple-";
if (info == NULL) {
return g_strconcat (prefix, "ipod", NULL);
}
switch (info->ipod_generation) {
case ITDB_IPOD_GENERATION_UNKNOWN:
case ITDB_IPOD_GENERATION_FIRST:
case ITDB_IPOD_GENERATION_SECOND:
case ITDB_IPOD_GENERATION_THIRD:
case ITDB_IPOD_GENERATION_FOURTH:
return g_strconcat (prefix, "ipod", NULL);
case ITDB_IPOD_GENERATION_PHOTO:
return g_strconcat (prefix, "ipod-color", NULL);
case ITDB_IPOD_GENERATION_MINI_1:
case ITDB_IPOD_GENERATION_MINI_2:
switch (info->ipod_model) {
case ITDB_IPOD_MODEL_MINI_BLUE:
return g_strconcat (prefix, "ipod-mini-blue", NULL);
case ITDB_IPOD_MODEL_MINI_PINK:
return g_strconcat (prefix, "ipod-mini-pink", NULL);
case ITDB_IPOD_MODEL_MINI_GOLD:
return g_strconcat (prefix, "ipod-mini-gold", NULL);
case ITDB_IPOD_MODEL_MINI_GREEN:
return g_strconcat (prefix, "ipod-mini-green", NULL);
case ITDB_IPOD_MODEL_MINI:
return g_strconcat (prefix, "ipod-mini-silver", NULL);
default:
g_assert_not_reached ();
}
case ITDB_IPOD_GENERATION_SHUFFLE_1:
case ITDB_IPOD_GENERATION_SHUFFLE_3:
return g_strconcat (prefix, "ipod-shuffle", NULL);
case ITDB_IPOD_GENERATION_SHUFFLE_2:
case ITDB_IPOD_GENERATION_SHUFFLE_4:
switch (info->ipod_model) {
case ITDB_IPOD_MODEL_SHUFFLE_SILVER:
return g_strconcat (prefix, "ipod-shuffle-clip-silver", NULL);
case ITDB_IPOD_MODEL_SHUFFLE_GREEN:
return g_strconcat (prefix, "ipod-shuffle-clip-green", NULL);
case ITDB_IPOD_MODEL_SHUFFLE_GOLD:
return g_strconcat (prefix, "ipod-shuffle-clip-gold", NULL);
case ITDB_IPOD_MODEL_SHUFFLE_ORANGE:
return g_strconcat (prefix, "ipod-shuffle-clip-orange", NULL);
case ITDB_IPOD_MODEL_SHUFFLE_PURPLE:
return g_strconcat (prefix, "ipod-shuffle-clip-purple", NULL);
case ITDB_IPOD_MODEL_SHUFFLE_PINK:
return g_strconcat (prefix, "ipod-shuffle-clip-pink", NULL);
case ITDB_IPOD_MODEL_SHUFFLE_BLUE:
return g_strconcat (prefix, "ipod-shuffle-clip-blue", NULL);
default:
g_assert_not_reached ();
}
case ITDB_IPOD_GENERATION_NANO_1:
if (info->ipod_model == ITDB_IPOD_MODEL_NANO_BLACK) {
return g_strconcat (prefix, "ipod-nano-black", NULL);
} else {
return g_strconcat (prefix, "ipod-nano-white", NULL);
}
case ITDB_IPOD_GENERATION_NANO_2:
return g_strconcat (prefix, "ipod-nano-white", NULL);
case ITDB_IPOD_GENERATION_NANO_3:
switch (info->ipod_model) {
case ITDB_IPOD_MODEL_NANO_SILVER:
return g_strconcat (prefix, "ipod-nano-video", NULL);
case ITDB_IPOD_MODEL_NANO_BLACK:
return g_strconcat (prefix, "ipod-nano-video-black", NULL);
case ITDB_IPOD_MODEL_NANO_BLUE:
return g_strconcat (prefix, "ipod-nano-video-turquoise", NULL);
case ITDB_IPOD_MODEL_NANO_GREEN:
return g_strconcat (prefix, "ipod-nano-video-green", NULL);
case ITDB_IPOD_MODEL_NANO_RED:
return g_strconcat (prefix, "ipod-nano-video-red", NULL);
default:
g_assert_not_reached ();
}
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
case ITDB_IPOD_GENERATION_NANO_6:
/* FIXME: set the correct icon name once it's added to
* gnome-icon-theme-extras
*/
return g_strconcat (prefix, "ipod-nano-white", NULL);
case ITDB_IPOD_GENERATION_VIDEO_1:
case ITDB_IPOD_GENERATION_VIDEO_2:
if (info->ipod_model == ITDB_IPOD_MODEL_VIDEO_BLACK) {
return g_strconcat (prefix, "ipod-video-black", NULL);
} else {
return g_strconcat (prefix, "ipod-video-white", NULL);
}
case ITDB_IPOD_GENERATION_CLASSIC_1:
case ITDB_IPOD_GENERATION_CLASSIC_2:
case ITDB_IPOD_GENERATION_CLASSIC_3:
if (info->ipod_model == ITDB_IPOD_MODEL_CLASSIC_BLACK) {
return g_strconcat (prefix, "ipod-classic-black", NULL);
} else {
return g_strconcat (prefix, "ipod-classic-white", NULL);
}
case ITDB_IPOD_GENERATION_TOUCH_1:
return g_strconcat (prefix, "ipod-touch", NULL);
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
case ITDB_IPOD_GENERATION_TOUCH_4:
return g_strconcat (prefix, "ipod-touch-2g", NULL);
case ITDB_IPOD_GENERATION_IPHONE_1:
return g_strdup ("phone-apple-iphone");
case ITDB_IPOD_GENERATION_IPHONE_2:
return g_strdup ("phone-apple-iphone-3g");
case ITDB_IPOD_GENERATION_IPHONE_3:
return g_strdup ("phone-apple-iphone-3gs");
case ITDB_IPOD_GENERATION_IPHONE_4:
return g_strdup ("phone-apple-iphone-4g");
case ITDB_IPOD_GENERATION_IPAD_1:
return g_strdup ("computer-apple-ipad");
case ITDB_IPOD_GENERATION_MOBILE:
return g_strconcat (prefix, "ipod", NULL);
}
g_assert_not_reached ();
}
static void set_artwork_information (const SysInfoIpodProperties *props,
ItdbBackend *backend)
{
const GList *formats;
/* Cover art */
formats = itdb_sysinfo_properties_get_cover_art_formats (props);
backend->set_artwork_formats (backend, ALBUM, formats);
/* Photos */
formats = itdb_sysinfo_properties_get_photo_formats (props);
backend->set_artwork_formats (backend, PHOTO, formats);
/* Chapter images */
formats = itdb_sysinfo_properties_get_chapter_image_formats (props);
backend->set_artwork_formats (backend, CHAPTER, formats);
}
static gboolean ipod_set_properties (ItdbBackend *backend,
const SysInfoIpodProperties *props)
{
const char *serial_number;
const char *firmware_version;
char *icon_name;
const Itdb_IpodInfo *info;
char *model_name;
char *color_name;
double generation;
ProductionInfo *prod_info;
backend->set_version (backend, 1);
serial_number = itdb_sysinfo_properties_get_serial_number (props);
info = itdb_ipod_info_from_serial (serial_number);
if ((info == NULL) || (info->ipod_generation == ITDB_IPOD_GENERATION_UNKNOWN)) {
backend->set_is_unknown (backend, TRUE);
g_debug("unknown ipod generation");
return TRUE;
} else {
backend->set_is_unknown (backend, FALSE);
}
icon_name = get_icon_name (info);
backend->set_icon_name (backend, icon_name);
g_free (icon_name);
if (itdb_sysinfo_properties_get_firewire_id (props) != NULL) {
const char *fwid;
fwid = itdb_sysinfo_properties_get_firewire_id (props);
backend->set_firewire_id (backend, fwid);
}
if (serial_number != NULL) {
backend->set_serial_number (backend, serial_number);
}
firmware_version = itdb_sysinfo_properties_get_firmware_version (props);
if (firmware_version != NULL) {
backend->set_firmware_version (backend, firmware_version);
}
set_artwork_information (props, backend);
model_name = get_model_name (info);
if (model_name != NULL) {
backend->set_model_name (backend, model_name);
g_free (model_name);
}
generation = get_generation (info);
if (generation != 0.0) {
backend->set_generation (backend, generation);
}
color_name = get_color_name (info);
if (color_name != NULL) {
backend->set_color (backend, color_name);
g_free (color_name);
}
if (serial_number != NULL) {
prod_info = parse_serial_number (serial_number);
if (prod_info != NULL) {
if (prod_info->factory_id != NULL) {
backend->set_factory_id (backend,
prod_info->factory_id);
}
if (prod_info->production_year != 0) {
backend->set_production_year (backend,
prod_info->production_year);
}
if (prod_info->production_week != 0) {
backend->set_production_week (backend,
prod_info->production_week);
}
if (prod_info->production_index != 0) {
backend->set_production_index (backend,
prod_info->production_index);
}
}
production_info_free (prod_info);
}
return TRUE;
}
static gboolean mounted_ipod_set_properties (ItdbBackend *backend,
const char *ipod_mountpoint)
{
Itdb_iTunesDB *itdb;
Itdb_Playlist *mpl;
char *control_path;
itdb = itdb_parse (ipod_mountpoint, NULL);
if (itdb == NULL) {
g_debug("failed to parse iTunesDB at %s", ipod_mountpoint);
return FALSE;
}
control_path = itdb_get_control_dir (ipod_mountpoint);
if (control_path != NULL) {
if (strlen (control_path) >= strlen (ipod_mountpoint)) {
backend->set_control_path (backend,
control_path + strlen (ipod_mountpoint));
g_free (control_path);
}
}
mpl = itdb_playlist_mpl (itdb);
if (mpl == NULL) {
g_debug("corrupted iTunesDB (no master playlist) at %s",
ipod_mountpoint);
return FALSE;
}
if (mpl->name != NULL) {
backend->set_name (backend, mpl->name);
}
return FALSE;
}
static char *mount_ipod (const char *dev_path, const char *fstype)
{
char *filename;
char *tmpname;
int result;
filename = g_build_filename (TMPMOUNTDIR, "ipodXXXXXX", NULL);
if (filename == NULL) {
g_debug("failed to build temporary template at "TMPMOUNTDIR);
return NULL;
}
tmpname = mkdtemp (filename);
if (tmpname == NULL) {
g_debug("failed to build temporary filename using template %s",
filename);
g_free (filename);
return NULL;
}
g_assert (tmpname == filename);
result = mount (dev_path, tmpname, fstype, 0, NULL);
if (result != 0) {
g_debug("failed to mount device %s at %s: %s",
dev_path, tmpname, strerror(errno));
g_rmdir (filename);
g_free (filename);
return NULL;
}
g_debug("device successfully mounted at %s", tmpname);
return tmpname;
}
static gboolean write_sysinfo_extended (const char *mountpoint,
const char *data)
{
char *filename;
char *devdirpath;
gboolean success;
GError *error = { 0, };
devdirpath = itdb_get_device_dir (mountpoint);
/* Make sure the device dir exists (not necessarily true on
* Shuffles */
if (devdirpath == NULL) {
gchar *controldirpath;
controldirpath = itdb_get_control_dir (mountpoint);
if (controldirpath == NULL) {
itdb_syslog("failed to build path for control dir at %s",
mountpoint);
return FALSE;
}
devdirpath = g_build_filename (controldirpath, "Device", NULL);
g_free (controldirpath);
g_mkdir (devdirpath, 0777);
g_debug("creating %s", devdirpath);
}
filename = g_build_filename (devdirpath, "SysInfoExtended", NULL);
g_free (devdirpath);
if (filename == NULL) {
itdb_syslog("failed to build path for SysInfoExtended at %s",
mountpoint);
return FALSE;
}
success = g_file_set_contents (filename, data, -1, &error);
if (!success) {
itdb_syslog("failed to write %s: %s", filename, error->message);
g_clear_error(&error);
} else {
g_debug("successfully written SysInfoExtended at %s", filename);
}
g_free (filename);
return success;
}
static char *get_info_from_usb (usb_bus_number, usb_device_number)
{
#ifdef HAVE_LIBUSB
return read_sysinfo_extended_from_usb (usb_bus_number,
usb_device_number);
#else
g_debug("libgpod was compiled without USB support, "
"not trying to read SysInfoExtended from USB");
return NULL;
#endif
}
static char *get_info_from_sg (const char *dev)
{
#ifdef HAVE_SGUTILS
return read_sysinfo_extended (dev);
#else
g_debug("libgpod was compiled without sgutils support, "
"not trying to read SysInfoExtended from SCSI");
return NULL;
#endif
}
int itdb_callout_set_ipod_properties (ItdbBackend *backend, const char *dev,
gint usb_bus_number,
gint usb_device_number,
const char *fstype)
{
char *ipod_mountpoint = NULL;
char *xml = NULL;
SysInfoIpodProperties *props;
GError *error = { 0, };
if (usb_bus_number != 0) {
g_debug("trying to read info from USB device %d:%d",
usb_bus_number, usb_device_number);
xml = get_info_from_usb (usb_bus_number, usb_device_number);
}
if (xml == NULL) {
g_debug("tring to read info from SCSI device %s", dev);
xml = get_info_from_sg (dev);
} else {
g_debug("iPod properties successfully read from USB");
}
if (xml == NULL) {
itdb_syslog("couldn't read SysInfoExtended from device");
return -1;
} else {
g_debug("iPod properties successfully read from SCSI");
}
props = itdb_sysinfo_extended_parse_from_xml (xml, &error);
if (props == NULL) {
itdb_syslog("failed to parse SysInfoExtended: %s",
error->message);
g_clear_error(&error);
g_debug("%s", xml);
return -1;
}
ipod_set_properties (backend, props);
itdb_sysinfo_properties_free (props);
ipod_mountpoint = mount_ipod (dev, fstype);
if (ipod_mountpoint == NULL) {
itdb_syslog("failed to mount device");
g_free (xml);
return -1;
}
write_sysinfo_extended (ipod_mountpoint, xml);
g_free (xml);
/* mounted_ipod_set_properties will call itdb_parse on the ipod
* which we just mounted, which will create an ItdbDevice
* containing most of what 'dev' had above. For now, I'm leaving
* this kind of duplication since I want the hal information to be
* added even if for some reason we don't manage to mount the ipod
*/
mounted_ipod_set_properties (backend, ipod_mountpoint);
umount (ipod_mountpoint);
g_rmdir (ipod_mountpoint);
g_free (ipod_mountpoint);
return 0;
}