/*
 * Hardware Information, version 0.3
 * Copyright (C) 2003-2004 Leandro Pereira <leandro@linuxmag.com.br>
 * USB support rewritten by Christophe Grosjean <christopheg@wanadoo.fr>
 *
 * May be modified and/or distributed under the terms of GNU GPL version 2.
 */

#include "hardinfo.h"
#include "usb.h"

gboolean usb_update(gpointer data)
{
	MainWindow *mainwindow = (MainWindow*)data;
	GtkCTreeNode *node;
	USBDevice *usb;	
	
	if(!mainwindow) return FALSE;

	gtk_clist_freeze(GTK_CLIST(mainwindow->ctree));

	usb = hi_scan_usb();

        if (usb != NULL) {
                node = tree_group_new(mainwindow, _("USB Devices"), USB);
                for (; usb != NULL; usb = usb->next) {
                        hi_insert_generic(usb, USB);
                        if (!usb->product) 
                                usb->product = g_strdup_printf
                                        (_("Unknown device (%s)"), usb->class);
                        
                        tree_insert_item(mainwindow, node, usb->product,
                                         generic_devices);
                }
        }

	gtk_clist_thaw(GTK_CLIST(mainwindow->ctree));
	
	return TRUE;	
}



 USBDevice *hi_scan_usb(void)
 {
 	FILE *proc_usb;
 	gint n=0;
 	USBDevice *usb_dev = NULL, *usb = NULL;
 	struct stat st;
 	gchar buffer[128];
 	
 	if (stat("/proc/bus/usb/devices", &st)) return NULL;

 	proc_usb = fopen("/proc/bus/usb/devices", "r");
 	while(fgets(buffer, 128, proc_usb)){
 	  int lg = strlen(buffer);
 	  if (lg>0 && buffer[lg-1] == '\n'){
 	    buffer[lg-1]=0;
 	  }
 	  if (strstr(buffer, "Manufacturer=")) {
 	    gchar *buf = buffer;

 	    for (;*buf; buf++) {
 	      if (*buf == '=') {
 		if (usb){
 		  usb->vendor = g_strdup(buf+1);
 		}
 		break;
 	      }
 	    }
 	  } else if (strstr(buffer, "Product=")) {
 	    gchar *buf = buffer;
 	    for (; *buf; buf++) {
 	      if (*buf == '=') {
 		if (usb_dev){
 		  usb_dev->product = g_strdup(buf+1);
 		}
 	      }
 	    }
 	  } else if (!strncmp(buffer, "D:  Ve", 6)) {
 	    gchar *buf = buffer;
 	    gfloat version;
 	    gint class_id;

 	    usb_dev = g_new0(USBDevice, 1);
 	    usb_dev->next = usb;
 	    usb = usb_dev;
 	    
 	    buf+=4;
 	    
 	    sscanf(buf, "Ver= %f Cls= %d", &version, &class_id);
 	    
 	    usb_dev->version = version;
 	    usb_dev->class_id= class_id;
 	    
 	    walk_until('(');
 	    buf[6]=0;
 	    usb_dev->class = g_strdup(buf+1);
 	    
 	    n++;		
 	  } else if (!strncmp(buffer, "P:  Ve", 6)) {
 	    gchar *buf = buffer;
 	    gint vendor_id, prod_id;
 	    gfloat rev;
 	    
 	    buf+=4;
 	    
 	    sscanf(buf, "Vendor= %x ProdID= %x Rev= %f",
 		   &vendor_id, &prod_id, &rev);
 	    if (usb_dev){
 	      usb_dev->vendor_id = vendor_id;
 	      usb_dev->prod_id = prod_id;
 	      usb_dev->revision = rev;
 	    }
 	  }
 	}
 	fclose(proc_usb);
 	return usb;
 }

#if 0
USBDevice *hi_scan_usb(void)
{
	FILE *proc_usb;
	gchar buffer[64];
	gint n=0;
	USBDevice *usb_dev = NULL, *usb = NULL;
	struct stat st;
	
	usb = NULL;

	if (stat("/proc/bus/usb/devices", &st)) return NULL;

	proc_usb = fopen("/proc/bus/usb/devices", "r");
	while(fgets(buffer, 64, proc_usb)){
		if (strstr(buffer, "Manufacturer=")) {
			gchar *buf = buffer;
			gboolean lock = FALSE;
			gpointer start = NULL, end = NULL;
			
			for (; buf != NULL; buf++) {
				if (lock && *buf == '\n') {
					end = buf;
					break;
				} else if (!lock && *buf == '=') {
					start = buf+1;
					lock = TRUE;
				}
			}
			
			buf = end;
			*buf = 0;
			buf = start;
			
			usb->vendor = g_strdup(buf);
		} else if (strstr(buffer, "Product=")) {
			gchar *buf = buffer;
			gboolean lock = FALSE;
			gpointer start = NULL, end = NULL;
			
			for (; buf != NULL; buf++) {
				if (lock && *buf == '\n') {
					end = buf;
					break;
				} else if (!lock && *buf == '=') {
					start = buf+1;
					lock = TRUE;
				}
			}
			
			buf = end;
			*buf=0;
			buf = start;

			usb_dev->product = g_strdup(buf);
		} else if (!strncmp(buffer, "D:  Ve", 6)) {
			gchar *buf = buffer;
			gpointer start;
			gfloat version;
			gint class_id;
			
			usb_dev = g_new0(USBDevice, 1);
			usb_dev->next = usb;
			usb = usb_dev;

			buf+=4;
			
			sscanf(buf, "Ver =%f Cls=%d", &version, &class_id);
			
			usb_dev->version = version;
			usb_dev->class_id= class_id;

			walk_until('(');
			start = buf+1;
			buf+=6;
			*buf = 0;
			buf = start;
			
			usb_dev->class = g_strdup(buf);
			n++;		
		} else if (!strncmp(buffer, "P:  Ve", 6)) {
			gchar *buf = buffer;
			gint vendor_id, prod_id;
			gfloat rev;
			
			buf+=4;
			
			sscanf(buf, "Vendor=%x ProdID=%x Rev= %f",
				&vendor_id, &prod_id, &rev);
			
			usb_dev->vendor_id = vendor_id;
			usb_dev->prod_id = prod_id;
			usb_dev->revision = rev;
		}
	}
	fclose(proc_usb);
	
	return usb;
}
#endif

void hi_show_usb_info(MainWindow *mainwindow, USBDevice *device)
{
	gchar *buf;

	if(!device) return;

	detail_window_set_icon(mainwindow->det_window, IMG_PREFIX "usb.png");

	gtk_window_set_title(GTK_WINDOW(mainwindow->det_window->window), _("USB Device"));
	

	detail_window_set_dev_name(mainwindow->det_window, device->product);
	detail_window_set_dev_type(mainwindow->det_window, device->vendor ?
				   device->vendor : "");

	buf = g_strdup_printf("%s (%d)", device->class, device->class_id);
	detail_window_append_info(mainwindow->det_window, _("Class"), buf);
	g_free(buf);
	
	detail_window_append_separator(mainwindow->det_window);
	
	buf = g_strdup_printf("%.2f", device->version);
	detail_window_append_info(mainwindow->det_window, _("Version"), buf);
	g_free(buf);

	buf = g_strdup_printf("%.2f", device->revision);
	detail_window_append_info(mainwindow->det_window, _("Revision"), buf);
	g_free(buf);

	if(!device->prod_id) return;

	detail_window_append_separator(mainwindow->det_window);
	
	detail_window_append_info_int(mainwindow->det_window, _("Vendor ID"), device->vendor_id, TRUE);
	detail_window_append_info_int(mainwindow->det_window, _("Product ID"), device->prod_id, TRUE);
	
}