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