/** 
 * \file detect.c
 * Example program to detect a device and list capabilities.
 *
 * Copyright (C) 2005-2008 Linus Walleij <triad@df.lth.se>
 * Copyright (C) 2007 Ted Bullock <tbullock@canada.com>
 *
 * This library 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 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "common.h"
#include "util.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#define XML_BUFSIZE 0x10000

static void dump_xml_fragment(uint8_t *buf, uint32_t len)
{
  static int endianness = 0; // 0 = LE, 1 = BE
  uint32_t bp = 0;
  
  while (bp < len) {
    if (buf[bp+0] == 0xFF && buf[bp+1] == 0xFE) {
      endianness = 0;
    } else if (buf[bp+0] == 0xFE && buf[bp+1] == 0xff) {
      endianness = 1;
    } else {
      uint16_t tmp;
      
      if (endianness == 0) {
	tmp = buf[bp+1] << 8 | buf[bp+0];
      } else {
	tmp = buf[bp+0] << 8 | buf[bp+1];
      }
      // Fix this some day, we only print ISO 8859-1 correctly here,
      // should atleast support UTF-8.
      printf("%c", (uint8_t) tmp);
    }
    bp += 2;
  }
  printf("\n");
}

int main (int argc, char **argv)
{
  LIBMTP_raw_device_t * rawdevices;
  int numrawdevices;
  LIBMTP_error_number_t err;
  int i;

  LIBMTP_Init();

  fprintf(stdout, "libmtp version: " LIBMTP_VERSION_STRING "\n\n");

  fprintf(stdout, "Listing raw device(s)\n");
  err = LIBMTP_Detect_Raw_Devices(&rawdevices, &numrawdevices);
  switch(err) {
  case LIBMTP_ERROR_NO_DEVICE_ATTACHED:
    fprintf(stdout, "   No raw devices found.\n");
    return 0;
  case LIBMTP_ERROR_CONNECTING:
    fprintf(stderr, "Detect: There has been an error connecting. Exiting\n");
    return 1;
  case LIBMTP_ERROR_MEMORY_ALLOCATION:
    fprintf(stderr, "Detect: Encountered a Memory Allocation Error. Exiting\n");
    return 1;
  case LIBMTP_ERROR_NONE:
    {
      int i;
      
      fprintf(stdout, "   Found %d device(s):\n", numrawdevices);
      for (i = 0; i < numrawdevices; i++) {
	if (rawdevices[i].device_entry.vendor != NULL ||
	    rawdevices[i].device_entry.product != NULL) {
	  fprintf(stdout, "   %s: %s (%04x:%04x) @ bus %d, dev %d\n", 
		  rawdevices[i].device_entry.vendor,
		  rawdevices[i].device_entry.product,
		  rawdevices[i].device_entry.vendor_id,
		  rawdevices[i].device_entry.product_id,
		  rawdevices[i].bus_location,
		  rawdevices[i].devnum);
	} else {
	  fprintf(stdout, "   %04x:%04x @ bus %d, dev %d\n", 
		  rawdevices[i].device_entry.vendor_id,
		  rawdevices[i].device_entry.product_id,
		  rawdevices[i].bus_location,
		  rawdevices[i].devnum);
	}
      }
    }
    break;
  case LIBMTP_ERROR_GENERAL:
  default:
    fprintf(stderr, "Unknown connection error.\n");
    return 1;
  }

  /* Iterate over connected MTP devices */
  fprintf(stdout, "Attempting to connect device(s)\n");
  for (i = 0; i < numrawdevices; i++) {
    LIBMTP_mtpdevice_t *device;
    LIBMTP_file_t *files;
    char *friendlyname;
    char *syncpartner;
    char *sectime;
    char *devcert;
    uint16_t *filetypes;
    uint16_t filetypes_len;
    uint8_t maxbattlevel;
    uint8_t currbattlevel;
    int ret;

    device = LIBMTP_Open_Raw_Device(&rawdevices[i]);
    if (device == NULL) {
      fprintf(stderr, "Unable to open raw device %d\n", i);
      continue;
    }

    LIBMTP_Dump_Errorstack(device);
    LIBMTP_Clear_Errorstack(device);
    LIBMTP_Dump_Device_Info(device);
    
    printf("MTP-specific device properties:\n");
    // The friendly name
    friendlyname = LIBMTP_Get_Friendlyname(device);
    if (friendlyname == NULL) {
      fprintf(stdout, "   Friendly name: (NULL)\n");
    } else {
      fprintf(stdout, "   Friendly name: %s\n", friendlyname);
      free(friendlyname);
    }
    syncpartner = LIBMTP_Get_Syncpartner(device);
    if (syncpartner == NULL) {
      fprintf(stdout, "   Synchronization partner: (NULL)\n");
    } else {
      fprintf(stdout, "   Synchronization partner: %s\n", syncpartner);
      free(syncpartner);
    }
    
    // Some battery info
    ret = LIBMTP_Get_Batterylevel(device, &maxbattlevel, &currbattlevel);
    if (ret == 0) {
      fprintf(stdout, "   Battery level %d of %d (%d%%)\n",currbattlevel, maxbattlevel, 
	      (int) ((float) currbattlevel/ (float) maxbattlevel * 100.0));
    } else {
      // Silently ignore. Some devices does not support getting the 
      // battery level.
      LIBMTP_Clear_Errorstack(device);
    }
    
    ret = LIBMTP_Get_Supported_Filetypes(device, &filetypes, &filetypes_len);
    if (ret == 0) {
      uint16_t i;
      
      printf("libmtp supported (playable) filetypes:\n");
      for (i = 0; i < filetypes_len; i++) {
	fprintf(stdout, "   %s\n", LIBMTP_Get_Filetype_Description(filetypes[i]));
      }
    } else {
      LIBMTP_Dump_Errorstack(device);
      LIBMTP_Clear_Errorstack(device);
    }
    
    // Secure time XML fragment
    ret = LIBMTP_Get_Secure_Time(device, &sectime);
    if (ret == 0 && sectime != NULL) {
      fprintf(stdout, "\nSecure Time:\n%s\n", sectime);
      free(sectime);
    } else {
      // Silently ignore - there may be devices not supporting secure time.
      LIBMTP_Clear_Errorstack(device);
    }
    
    // Device certificate XML fragment
    ret = LIBMTP_Get_Device_Certificate(device, &devcert);
    if (ret == 0 && devcert != NULL) {
      fprintf(stdout, "\nDevice Certificate:\n%s\n", devcert);
      free(devcert);
    } else {
      fprintf(stdout, "Unable to acquire device certificate, perhaps this device "
	      "does not support this\n");
      LIBMTP_Dump_Errorstack(device);
      LIBMTP_Clear_Errorstack(device);
    }

    // Try to get Media player device info XML file...
    files = LIBMTP_Get_Filelisting_With_Callback(device, NULL, NULL);
    if (files != NULL) {
      LIBMTP_file_t *file, *tmp;
      file = files;
      while (file != NULL) {
	if (!strcmp(file->filename, "WMPInfo.xml") ||
	    !strcmp(file->filename, "WMPinfo.xml") ||
	    !strcmp(file->filename, "default-capabilities.xml")) {
	    if (file->item_id != 0) {
	      /* Dump this file */
	      FILE *xmltmp = tmpfile();
	      int tmpfiledescriptor = fileno(xmltmp);
	      
	      if (tmpfiledescriptor != -1) {
		int ret = LIBMTP_Get_Track_To_File_Descriptor(device,
							      file->item_id,
							      tmpfiledescriptor,
							      NULL,
							      NULL);
		if (ret == 0) {
		  uint8_t *buf = NULL;
		  uint32_t readbytes;
		  
		  buf = malloc(XML_BUFSIZE);
		  if (buf == NULL) {
		    printf("Could not allocate %08x bytes...\n", XML_BUFSIZE);
		    LIBMTP_Dump_Errorstack(device);
		    LIBMTP_Clear_Errorstack(device);
		    free(rawdevices);
		    return 1;
		  }
		  
		  lseek(tmpfiledescriptor, 0, SEEK_SET);
		  readbytes = read(tmpfiledescriptor, (void*) buf, XML_BUFSIZE);
		  
		  if (readbytes >= 2 && readbytes < XML_BUFSIZE) {
		    fprintf(stdout, "\n%s file contents:\n", file->filename);
		    dump_xml_fragment(buf, readbytes);
		  } else {
		    perror("Unable to read file");
		    LIBMTP_Dump_Errorstack(device);
		    LIBMTP_Clear_Errorstack(device);
		  }
		  free(buf);
		} else {
		  LIBMTP_Dump_Errorstack(device);
		  LIBMTP_Clear_Errorstack(device);
		}
		fclose(xmltmp);
	      }
	    }
	}
	tmp = file;
	file = file->next;
	LIBMTP_destroy_file_t(tmp);
      }
    }
    LIBMTP_Release_Device(device);
  } /* End For Loop */

  free(rawdevices);

  printf("OK.\n");
  
  return 0; 
}
