summaryrefslogtreecommitdiffstats
path: root/x11/gnome-applets/files/patch-battstat_acpi-freebsd.c
blob: 48746fa03bbdf8e6d60ce296926fb61a9588a184 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
--- battstat/acpi-freebsd.c.orig	Sun Jul  3 16:41:26 2005
+++ battstat/acpi-freebsd.c	Sun Jul  3 16:49:55 2005
@@ -31,9 +31,13 @@
 
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/socket.h>
 #include <sys/sysctl.h>
+#include <sys/un.h>
 #include <sys/ioctl.h>
+#if defined(__i386__)
 #include <machine/apm_bios.h>
+#endif
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
@@ -92,16 +96,36 @@ gboolean
 acpi_freebsd_init(struct acpi_info * acpiinfo)
 {
   int acpi_fd;
+  int event_fd;
 
   g_assert(acpiinfo);
 
-  acpi_fd = open(ACPIDEV, O_RDONLY);
-  if (acpi_fd >= 0) {
-    acpiinfo->acpifd = acpi_fd;
+  if (acpiinfo->acpifd == -1) {
+    acpi_fd = open(ACPIDEV, O_RDONLY);
+    if (acpi_fd >= 0) {
+      acpiinfo->acpifd = acpi_fd;
+    }
+    else {
+      acpiinfo->acpifd = -1;
+      return FALSE;
+    }
   }
-  else {
-    acpiinfo->acpifd = -1;
-    return FALSE;
+
+  event_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+  if (event_fd >= 0) {
+    struct sockaddr_un addr;
+    addr.sun_family = AF_UNIX;
+    strcpy(addr.sun_path, "/var/run/devd.pipe");
+    if (connect(event_fd, (struct sockaddr *) &addr, sizeof(addr)) == 0) {
+      acpiinfo->event_fd = event_fd;
+      acpiinfo->event_inited = TRUE;
+      acpiinfo->channel = g_io_channel_unix_new(event_fd);
+    }
+    else {
+      close(event_fd);
+      acpiinfo->event_fd = -1;
+      acpiinfo->event_inited = FALSE;
+    }
   }
 
   update_battery_info(acpiinfo);
@@ -110,6 +134,65 @@ acpi_freebsd_init(struct acpi_info * acp
   return TRUE;
 }
 
+#define ACPI_EVENT_IGNORE	0
+#define ACPI_EVENT_AC		1
+#define ACPI_EVENT_BATTERY_INFO	2
+
+static int parse_acpi_event(GString *buffer)
+{
+  if (strstr(buffer->str, "system=ACPI")) {
+    if (strstr(buffer->str, "subsystem=ACAD"))
+      return ACPI_EVENT_AC;
+    if (strstr(buffer->str, "subsystem=CMBAT"))
+      return ACPI_EVENT_BATTERY_INFO;
+  }
+
+  return ACPI_EVENT_IGNORE;
+}
+
+void acpi_freebsd_update(struct acpi_info *acpiinfo)
+{
+  /* XXX This is needed for systems where devd does not have permissions
+   * to allow for event-driven updates.
+   */
+  update_ac_info(acpiinfo);
+  update_battery_info(acpiinfo);
+}
+
+gboolean acpi_process_event(struct acpi_info *acpiinfo, gboolean *read_error)
+{
+  gsize i;
+  int evt;
+  gboolean result = FALSE;
+  GString *buffer;
+  GIOStatus stat;
+  buffer = g_string_new(NULL);
+
+  *read_error = FALSE;
+  stat = g_io_channel_read_line_string(acpiinfo->channel, buffer, &i, NULL);
+
+  if (stat == G_IO_STATUS_ERROR || stat == G_IO_STATUS_EOF) {
+    *read_error = TRUE;
+    g_string_free(buffer, TRUE);
+    return FALSE;
+  }
+
+  evt = parse_acpi_event(buffer);
+  switch (evt) {
+    case ACPI_EVENT_AC:
+      update_ac_info(acpiinfo);
+      result = TRUE;
+      break;
+    case ACPI_EVENT_BATTERY_INFO:
+      update_battery_info(acpiinfo);
+      result = TRUE;
+      break;
+  }
+
+  g_string_free(buffer, TRUE);
+  return result;
+}
+
 void
 acpi_freebsd_cleanup(struct acpi_info * acpiinfo)
 {
@@ -119,21 +202,12 @@ acpi_freebsd_cleanup(struct acpi_info * 
     close(acpiinfo->acpifd);
     acpiinfo->acpifd = -1;
   }
-}
 
-/* XXX This is a hack since user-land applications can't get ACPI events yet.
- * Devd provides this (or supposedly provides this), but you need to be
- * root to access devd.
- */
-gboolean
-acpi_process_event(struct acpi_info * acpiinfo)
-{
-  g_assert(acpiinfo);
-
-  update_ac_info(acpiinfo);
-  update_battery_info(acpiinfo);
-
-  return TRUE;
+  if (acpiinfo->event_fd >= 0) {
+    g_io_channel_unref(acpiinfo->channel);
+    close(acpiinfo->event_fd);
+    acpiinfo->event_fd = -1;
+  }
 }
 
 gboolean
OpenPOWER on IntegriCloud