/****************************************************************************

Author:      Todor T. Zviskov (a.k.a. Warder) - http://warder.ath.cx:81/
Name:        sensors.c
Version:     0.3
Description: Prints the hardware sensors readings from
             /sys/devices/legacy/i2c-# in linux kernel 2.6 (and recent 2.5.x)
             Tested with via686 chipset only, other chipsets may return
             strange values.
License:     GPL-2 - http://www.gnu.org/licenses/gpl.txt

Changes:     0.3
             - check for more devices before saying modules not loaded

             0.2
             - fans have no max value, it's div
	     - the temp values returned 10x values with one of the kernel
	       patches I applied (it's 5digits, not 4)

****************************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main()
{
	//names that in /sys/devices/legacy/i2c-# for via686
	char names[31][80] = {"name", "in_input0", "in_min0", "in_max0",
				"in_input1", "in_min1", "in_max1",
				"in_input2", "in_min2", "in_max2",
				"in_input3", "in_min3", "in_max3",
				"in_input4", "in_min4", "in_max4",
				"fan_input1", "fan_min1", "fan_div1",
				"fan_input2", "fan_min2", "fan_div2",
				"temp_input1", "temp_min1", "temp_max1",
				"temp_input2", "temp_min2", "temp_max2",
				"temp_input3", "temp_min3", "temp_max3"};
	//user-friendly translations of the above
	char via686[31][80] = {"", "VCore:", "min =", "max =",
				"+2.5V:", "min =", "max =",
				"+3.3V:", "min =", "max =",
				"+5V:", "min =", "max =",
				"+12V:", "min =", "max =",
				"CPU fan:", "min =", "div =",
				"case fan:", "min =", "div =",
				"sys temp:", "limit =", "hysteresis =",
				"CPU temp:", "limit =", "hysteresis =",
				"sBr temp:", "limit =", "hysteresis ="};
	float values[31];
	char i2c_dir[80] = "/sys/devices/legacy";
	char i2c_dir_num[80];
	char data_file[80];
	char name[80];
	char temp[80];
	FILE *inFile;
	int i, j, flag = 0;
	DIR *dirp;
	struct dirent *dp;

	//see if we /sys (kernel 2.5/2.6)
	if ((inFile = fopen (i2c_dir, "r")) == NULL)
	{
		printf ("You are NOT running a 2.5/2.6 kernel OR you don't have /sys created.\nFor 2.0.x-2.4.x kernels, please use the lm_sensors package.\n\n");
		return 1;
	}
	fclose (inFile);
	
	//loop for /sys/devices/legacy/i2c-#
	for (i=0; i<20; i++)
	{
		sprintf (i2c_dir_num, "%s/i2c-%d/", i2c_dir, i);
		dirp = opendir(i2c_dir_num);
		//see if we got the i2c-# dir
		if (dirp == NULL && flag == 0)
			flag = 1; //we found nothing in all loops
		else if (dirp == NULL)
			continue;
		else
		{
			flag = 2; //we found something
			//find the #-xxxx dir in /sys/devices/legacy/i2c-#
			while (dirp)
			{
				if ((dp = readdir(dirp)) != NULL)
				{
					if (strstr(dp->d_name, "-"))
						sprintf(i2c_dir_num, "%s%s/", i2c_dir_num, dp->d_name);
				}
				else
				break;
			}
			closedir(dirp);

			//retreive the name of the sensor/chipset
			sprintf (data_file, "%s%s", i2c_dir_num, names[0]);
			if ((inFile = fopen (data_file, "r")) != NULL);
			{
				fgets (name, 80, inFile);
				printf ("Device:	%s\n", name);
			}
			fclose (inFile);
			if (strstr (name, "via686"))
				printf ("NOTE: This program has only been tested with via686 chip and might return strange values with other chipsets!\n\n");

			//read and print all files containing the info
			for (j=1; j<31; j++)
			{
				sprintf (data_file, "%s%s", i2c_dir_num, names[j]);
				if ((inFile = fopen (data_file, "r")) != NULL)
				{
					fscanf (inFile, "%f", &values[j]);

					//adjust the values
					if (j <= 15)
						values[j]=values[j]/1000;
					if (j >= 22)
					{
						//check for the length
						sprintf(temp, "%.0f", values[j]);
						if (strlen (temp) == 5)
							values[j]=values[j]/1000;
						else
							values[j]=values[j]/100;
					}

					//format and print the output
					if (strstr (names[j], "in_input"))
						printf ("%s		%.2f V	(", via686[j],values[j]);
					if (strstr (names[j], "in_min"))
						printf ("%s %.2f V, ", via686[j],values[j]);
					if (strstr (names[j], "in_max"))
						printf ("%s %.2f V)\n", via686[j],values[j]);
					if (strstr (names[j], "fan_input"))
						printf ("%s	%.0fRPM	(", via686[j],values[j]);
					if (strstr (names[j], "fan_min"))
						printf ("%s %.0f RPM, ", via686[j],values[j]);
					if (strstr (names[j], "fan_div"))
						printf ("%s %.0f)\n", via686[j],values[j]);
					if (strstr (names[j], "temp_input"))
						printf ("%s	%.1fC	(", via686[j],values[j]);
					if (strstr (names[j], "temp_min"))
						printf ("%s %.1fC, ", via686[j],values[j]);
					if (strstr (names[j], "temp_max"))
						printf ("%s %.1fC)\n", via686[j],values[j]);

					//printf ("%s:	%.2f\n", via686[j], values[j]);
					fclose (inFile);
				}
			}
		}
	}
	//we got no info
	if (flag == 1)
	{
		printf ("I2C and Sensors are not enabled in your kernel or you don't have the modules loaded.\n\n");
		return 1;
	}
	return 0;
}
