Based on kernel version 3.15.4. Page generated on 2014-07-07 09:03 EST.
1 /* Disk protection for HP machines. 2 * 3 * Copyright 2008 Eric Piel 4 * Copyright 2009 Pavel Machek <pavel@ucw.cz> 5 * 6 * GPLv2. 7 */ 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <unistd.h> 12 #include <fcntl.h> 13 #include <sys/stat.h> 14 #include <sys/types.h> 15 #include <string.h> 16 #include <stdint.h> 17 #include <errno.h> 18 #include <signal.h> 19 #include <sys/mman.h> 20 #include <sched.h> 21 22 char unload_heads_path[64]; 23 24 int set_unload_heads_path(char *device) 25 { 26 char devname[64]; 27 28 if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0) 29 return -EINVAL; 30 strncpy(devname, device + 5, sizeof(devname)); 31 32 snprintf(unload_heads_path, sizeof(unload_heads_path) - 1, 33 "/sys/block/%s/device/unload_heads", devname); 34 return 0; 35 } 36 int valid_disk(void) 37 { 38 int fd = open(unload_heads_path, O_RDONLY); 39 if (fd < 0) { 40 perror(unload_heads_path); 41 return 0; 42 } 43 44 close(fd); 45 return 1; 46 } 47 48 void write_int(char *path, int i) 49 { 50 char buf[1024]; 51 int fd = open(path, O_RDWR); 52 if (fd < 0) { 53 perror("open"); 54 exit(1); 55 } 56 sprintf(buf, "%d", i); 57 if (write(fd, buf, strlen(buf)) != strlen(buf)) { 58 perror("write"); 59 exit(1); 60 } 61 close(fd); 62 } 63 64 void set_led(int on) 65 { 66 write_int("/sys/class/leds/hp::hddprotect/brightness", on); 67 } 68 69 void protect(int seconds) 70 { 71 write_int(unload_heads_path, seconds*1000); 72 } 73 74 int on_ac(void) 75 { 76 // /sys/class/power_supply/AC0/online 77 } 78 79 int lid_open(void) 80 { 81 // /proc/acpi/button/lid/LID/state 82 } 83 84 void ignore_me(void) 85 { 86 protect(0); 87 set_led(0); 88 } 89 90 int main(int argc, char **argv) 91 { 92 int fd, ret; 93 struct sched_param param; 94 95 if (argc == 1) 96 ret = set_unload_heads_path("/dev/sda"); 97 else if (argc == 2) 98 ret = set_unload_heads_path(argv[1]); 99 else 100 ret = -EINVAL; 101 102 if (ret || !valid_disk()) { 103 fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n", 104 argv[0]); 105 exit(1); 106 } 107 108 fd = open("/dev/freefall", O_RDONLY); 109 if (fd < 0) { 110 perror("/dev/freefall"); 111 return EXIT_FAILURE; 112 } 113 114 daemon(0, 0); 115 param.sched_priority = sched_get_priority_max(SCHED_FIFO); 116 sched_setscheduler(0, SCHED_FIFO, ¶m); 117 mlockall(MCL_CURRENT|MCL_FUTURE); 118 119 signal(SIGALRM, ignore_me); 120 121 for (;;) { 122 unsigned char count; 123 124 ret = read(fd, &count, sizeof(count)); 125 alarm(0); 126 if ((ret == -1) && (errno == EINTR)) { 127 /* Alarm expired, time to unpark the heads */ 128 continue; 129 } 130 131 if (ret != sizeof(count)) { 132 perror("read"); 133 break; 134 } 135 136 protect(21); 137 set_led(1); 138 if (1 || on_ac() || lid_open()) 139 alarm(2); 140 else 141 alarm(20); 142 } 143 144 close(fd); 145 return EXIT_SUCCESS; 146 }