Advertisement
Guest User

fancontrol loop for UX32VD

a guest
Mar 9th, 2013
1,150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.25 KB | None | 0 0
  1. // Tested on ASUS UX32VD
  2. // DO NOT TRY ON ANY OTHER COMPUTER UNLESS YOU KNOW WHAT YOU ARE DOING!
  3. //
  4. // code taken from http://www.aneas.org/knowledge/asus_f3jp_fan_control.php
  5. // and modified for UX32VD
  6.  
  7. // File: fancntrl.c
  8. // Compile: gcc fancntrl.c -o fanctrl
  9. // Usage: sudo ./fanctrl <fan speed at 40°C> <fan speed at 50°C> <fan speed at 60°C> <fan speed at 70°C> <fan speed at 80°C>
  10. //      where <fan speed at T°C> is the fan speed expected at T°C from 0x00 (off) to 0xFF (MAX)
  11.  
  12. // WARNING!!! This file is proof of concept and is an UGLY hack!
  13.  
  14.  
  15. #include <stdio.h> // printf
  16. #include <stdlib.h> // atoi
  17. #include <stdint.h> // uint8_t, uint16_t
  18. #include <string.h> // strcmp
  19. #include <unistd.h> // usleep
  20. #include <sys/io.h> // inb, outb
  21.  
  22. //#define DEBUG
  23.  
  24. // IO ports
  25. const uint16_t EC4D = 0x0257; // data register
  26. const uint16_t EC4C = 0x0258; // command register
  27.  
  28. #define ERROR16 (0xFFFF)
  29.  
  30. // waits for the status bit to clear, max ERROR16 tries
  31. uint8_t WEIE() {
  32. #ifdef DEBUG
  33.         printf("Called : WEIE\n");
  34. #endif
  35.         uint16_t Local0 = 0xFFFF;
  36.         uint8_t Local1 = inb(EC4C) & 0x02;
  37.         while(Local0 != 0 && Local1 == 0x02) {
  38.                 Local1 = inb(EC4C) & 0x02;
  39.                 Local0--;
  40.                 usleep(5*1000); //sleep 5 msec
  41.         }
  42. #ifdef DEBUG
  43.         printf("Left : WEIE\n");
  44. #endif
  45.  
  46.         return (Local0 == 0);
  47. }
  48.  
  49. // waits for the status bit to clear, max ERROR16 tries
  50. uint8_t WEOE () {
  51. #ifdef DEBUG
  52.         printf("Called : WEOE\n");
  53. #endif
  54.         uint16_t Local0 = 0xFFFF;
  55.         uint8_t Local1 = inb(EC4C) & 0x01;
  56.         while(Local0 != 0 && Local1 == 0x01) {
  57.                 Local1 = inb(EC4C) & 0x01;
  58.                 Local0--;
  59.                 usleep(5*1000); //sleep 5 msec
  60.                 inb(EC4D); // maybe not needed?
  61.         }
  62. #ifdef DEBUG
  63.         printf("Left : WEOE\n");
  64. #endif
  65.  
  66.         return (Local0 == 0);
  67. }
  68.  
  69. uint8_t WEOF() {
  70. #ifdef DEBUG
  71.         printf("Called : WEOF\n");
  72. #endif
  73.         uint16_t Local0 = 0xFFFF;
  74.         uint8_t Local1 = inb(EC4C) & 0x01;
  75.         while(Local0 != 0 && Local1 == 0x01) {
  76.                 Local1 = inb(EC4C) & 0x01;
  77.                 Local0--;
  78.                 usleep(5*1000); //sleep 5 msec
  79.         }
  80. #ifdef DEBUG
  81.         printf("Left : WEOF\n");
  82. #endif
  83.  
  84.         return (Local0 == 0);
  85. }
  86. /* read from RAM */
  87. uint16_t RRAM (uint16_t Arg0) {
  88.         uint16_t Local0, Local1;
  89.         Local0 = Arg0;
  90.         Local1 = Local0 & 0xFF;
  91.         Local0 = (Local0 >> 0x08);
  92.         Local0 = Local0 & 0xFF;
  93.  
  94.         if (WEOE() != 0){ return ERROR16; }
  95.         if (WEIE() != 0){ return ERROR16; }
  96.         outb(0xFF, EC4C);
  97.         if (WEIE() != 0){ return ERROR16; }
  98.         outb(0x80, EC4C);
  99.         if (WEIE() != 0){ return ERROR16; }
  100.         outb(Local0, EC4D);
  101.         if (WEIE() != 0){ return ERROR16; }
  102.         outb(Local1, EC4D);
  103.         if (WEIE() != 0){ return ERROR16; }
  104.         if (WEOF() != 0){ return ERROR16; }
  105.        
  106.         return inb(EC4D);
  107. }
  108.  
  109. /* write to RAM */
  110. uint16_t WRAM (uint16_t Arg0, uint8_t Arg1) {
  111.         uint16_t Local0, Local1;
  112.         Local0 = Arg0;
  113.         Local1 = Local0 & 0xFF;
  114.         Local0 = (Local0 >> 0x08);
  115.         Local0 = Local0 & 0xFF;
  116.  
  117.         if (WEOE() != 0){ return ERROR16; }
  118.         if (WEIE() != 0){ return ERROR16; }
  119.         outb(0xFF, EC4C);
  120.         if (WEIE() != 0){ return ERROR16; }
  121.         outb(0x81, EC4C);
  122.         if (WEIE() != 0){ return ERROR16; }
  123.         outb(Local0, EC4D);
  124.         if (WEIE() != 0){ return ERROR16; }
  125.         outb(Local1, EC4D);
  126.         if (WEIE() != 0){ return ERROR16; }
  127.         outb(Arg1, EC4D);
  128.         if (WEIE() != 0){ return ERROR16; }
  129.  
  130.         return 0;
  131. }
  132.  
  133. // sets the QUIET fan speed
  134. uint16_t WMFN (uint8_t Arg0) { //ST98
  135. #ifdef DEBUG
  136.         printf("Called : WMFN 0x%X\n", Arg0);
  137. #endif
  138.         if (WEOE() != 0){ return ERROR16; }
  139.         if (WEIE() != 0){ return ERROR16; }
  140.         outb(0xFF, EC4C);
  141.         if (WEIE() != 0){ return ERROR16; }
  142.         outb(0x98, EC4C);
  143.         if (WEIE() != 0){ return ERROR16; }
  144.         outb(Arg0, EC4D);
  145.         if (WEIE() != 0){ return ERROR16; }
  146.         if (WEIE() != 0){ return ERROR16; } //not needed?
  147. #ifdef DEBUG
  148.         printf("Left : WMFN\n");
  149. #endif
  150.        
  151.         return 0;
  152. }
  153.  
  154. /*
  155. ST83 Arg0 Arg1
  156.         Read speed of the fan(s). DOES NOT WORK IN MANUAL MODE
  157.   Args:
  158.         Arg0    - 0 = fan1
  159.                 - 1 = fan2
  160.   Returns:
  161.                 - fan speed 0x0(OFF) - 0xFF(MAX)
  162. */
  163. uint16_t RFOV (uint8_t Arg0) { //ST83
  164. #ifdef DEBUG
  165.         printf("Called : RFOV 0x%X\n", Arg0);
  166. #endif
  167.         if (Arg0 > 0x01) {
  168.                 return ERROR16;
  169.         }
  170.         if (WEOE() != 0){ return ERROR16; }
  171.         if (WEIE() != 0){ return ERROR16; }
  172.         outb(0xFF, EC4C);
  173.         if (WEIE() != 0){ return ERROR16; }
  174.         outb(0x83, EC4C);
  175.         if (WEIE() != 0){ return ERROR16; }
  176.         outb(Arg0, EC4D);
  177.         if (WEIE() != 0){ return ERROR16; }
  178.         if (WEOF() != 0){ return ERROR16; }
  179. #ifdef DEBUG
  180.         printf("Left : RFOV\n");
  181. #endif
  182.  
  183.         return inb(EC4D);
  184. }
  185.  
  186. /*
  187. ST84 Arg0 Arg1
  188.         Sets speed of the fan(s)
  189.   Args:
  190.         Arg0    - 0 = fan1
  191.                 - 1 = fan2
  192.         Arg1    - fan speed 0x0(OFF) - 0xFF(MAX)
  193. */
  194.  
  195. uint16_t WFOV (uint8_t Arg0, uint8_t Arg1) { //ST84
  196.         if (Arg0 > 0x01) {
  197.                 return ERROR16;
  198.         }
  199.         if (WEOE() != 0){ return ERROR16; }
  200.         if (WEIE() != 0){ return ERROR16; }
  201.         outb(0xFF, EC4C);
  202.         if (WEIE() != 0){ return ERROR16; }
  203.         outb(0x84, EC4C);
  204.         if (WEIE() != 0){ return ERROR16; }
  205.         outb(Arg0, EC4D);
  206.         if (WEIE() != 0){ return ERROR16; }
  207.         outb(Arg1, EC4D);
  208.         if (WEIE() != 0){ return ERROR16; }
  209.        
  210.         return 0;
  211. }
  212.  
  213. /*
  214. SFNV Arg0 Arg1
  215.         Sets speed of the fan(s)
  216.   Args:
  217.         Arg0    - 0 to reset fans to AUTO
  218.                 - 1 = fan1
  219.                 - 2 = fan2
  220.         Arg1    - if Arg0 == 0, then 0x1 bit reset fan1 0x2 bit reset fan2
  221.                 - fan speed 0x0(OFF) - 0xFF(MAX)
  222. */
  223. #define SFNV_SET_FAN1 (0x01)
  224. #define SFNV_SET_FAN2 (0x02)
  225. #define SFNV_AUTO_FAN1 (0x01)
  226. #define SFNV_AUTO_FAN2 (0x02)
  227. #define SFNV_AUTO_ALL (SFNV_AUTO_FAN1 | SFNV_AUTO_FAN2)
  228.  
  229. uint16_t SFNV (uint8_t Arg0, uint8_t Arg1) {
  230.         uint16_t Local0;
  231.         // Set the fans to automatic
  232.         if (Arg0 == 0) {
  233.                 // set fan1 to AUTO
  234.                 if (Arg1 & SFNV_AUTO_FAN1) {
  235.                         if ((Local0 = RRAM(0x0521)) == ERROR16) {return ERROR16; };
  236.                         Local0 |= 0x80;
  237.                         WRAM (0x0521, (uint8_t) (0xFF & Local0)); //ignore error?
  238.                 }
  239.                 // set fan2 to AUTO
  240.                 if (Arg1 & SFNV_AUTO_FAN2) {
  241.                         if ((Local0 = RRAM(0x0522)) == ERROR16) {return ERROR16; };
  242.                         Local0 |= 0x80;
  243.                         WRAM (0x0522, (uint8_t) (0xFF & Local0)); //ignore error?
  244.                 }
  245.                 return 0;
  246.         }
  247.         // Set the speed of fan1
  248.         else if (Arg0 == SFNV_SET_FAN1) {
  249.                 if ((Local0 = RRAM(0x0521)) == ERROR16) {return ERROR16; };
  250.                 Local0 &= 0x7F;
  251.                 WRAM (0x0521, (uint8_t) (0xFF & Local0)); //ignore error?
  252.                 // DECF |= 0x1
  253.                 return WFOV (0x00, Arg1);
  254.         }
  255.         // Set the speed of fan2
  256.         else if (Arg0 == SFNV_SET_FAN2) {
  257.                 if ((Local0 = RRAM(0x0522) == ERROR16)) {return ERROR16; };
  258.                 Local0 &= 0x7F;
  259.                 WRAM (0x0522, (uint8_t) (0xFF & Local0)); //ignore error?
  260.                 // DECF |= 0x2
  261.                 return WFOV (0x01, Arg1);
  262.         }
  263.         return ERROR16;
  264. }
  265.  
  266. int set(int speed) {
  267.         if(ioperm(EC4D, 1, 1)) {
  268.                 printf("Error: could not gain access to IO port EC4D (0x%X). Are you root?\n", EC4D);
  269.                 return 1;
  270.         }
  271.  
  272.         if(ioperm(EC4C, 1, 1)) {
  273.       printf("Error: could not gain access to IO port EC4C (0x%X). Are you root?\n", EC4C);
  274.       return 1;
  275.         }
  276.  
  277. #if 0
  278.         printf("Fan speeds: \tFan1: %d, Fan2: %d\n", RFOV(0x00), RFOV(0x01));
  279. #endif
  280.         if (WMFN(speed)) {
  281.       printf("error\n");
  282.         }
  283.         else {
  284.       printf("speed has been set to %d\n",speed);
  285.     }
  286.  
  287.         // Set FAN1 speed to 0xFF (MAX)
  288. //      SFNV(0x1, 0xFF);
  289.         // Set FAN2 speed to 0x00 (OFF)
  290. //      SFNV(0x2, 0x00);
  291.         // reset both fans back to AUTO control
  292. //      SFNV(0x0, 0x01|0x02);
  293.  
  294.         return 0;
  295. }
  296.  
  297. int main(int argc, char ** argv) {
  298.        if(argc != 6) {
  299.                 printf("usage:\n %s speed[40] speed[50] speed[60] speed[70] speed[80]\n", argv[0]);
  300.         printf("speed[T] is the speed you expect at temperature T (°C)\n");       
  301.         return 1;
  302.         }
  303.  
  304.         uint8_t speed = 0xFF;
  305.     int speed40 = atoi(argv[1]);
  306.     int speed50 = atoi(argv[2]);
  307.     int speed60 = atoi(argv[3]);
  308.     int speed70 = atoi(argv[4]);
  309.     int speed80 = atoi(argv[5]);
  310.    
  311.     if(speed40 < 1 || speed40 > 255) {
  312.       printf("Error: the speed %d is not possible\n", speed40);
  313.       return 1;
  314.     }
  315.     if(speed50 < 1 || speed50 > 255) {
  316.       printf("Error: the speed %d is not possible\n", speed50);
  317.       return 1;
  318.     }
  319.     if(speed60 < 1 || speed60 > 255) {
  320.       printf("Error: the speed %d is not possible\n", speed60);
  321.       return 1;
  322.     }
  323.     if(speed70 < 1 || speed70 > 255) {
  324.       printf("Error: the speed %d is not possible\n", speed70);
  325.       return 1;
  326.     }
  327.     if(speed80 < 1 || speed80 > 255) {
  328.       printf("Error: the speed %d is not possible\n", speed80);
  329.       return 1;
  330.     }
  331.     FILE *fp;
  332.     int temperature;
  333.     while(1){
  334.       fp = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
  335.       fscanf(fp, "%d", &temperature);
  336.       fclose(fp);
  337.       printf("temperature: %d\n",temperature);
  338.       if (temperature < 40000)
  339.         speed = speed40;
  340.       else if (temperature < 50000)
  341.         speed = speed40 + (temperature-40000)*(speed50-speed40)/10000;
  342.       else if (temperature < 60000)
  343.         speed = speed50 + (temperature-50000)*(speed60-speed50)/10000;
  344.       else if (temperature < 70000)
  345.         speed = speed60 + (temperature-60000)*(speed70-speed60)/10000;
  346.       else
  347.         {speed = speed70 + (temperature-35000)*(speed80-speed70)/10000;
  348.           if (speed > 255) speed = 255;}
  349.       set(speed);
  350.       sleep(5);}
  351. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement