Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / lisp / battery.el
index 1b13f46..a3be2fe 100644 (file)
@@ -1,7 +1,6 @@
 ;;; battery.el --- display battery status information  -*- coding: iso-8859-1 -*-
 
-;; Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2012 Free Software Foundation, Inc.
 
 ;; Author: Ralph Schleicher <rs@nunatak.allgaeu.org>
 ;; Keywords: hardware
              (file-directory-p "/sys/class/power_supply/")
              (directory-files "/sys/class/power_supply/" nil "BAT[0-9]$"))
         'battery-linux-sysfs)
+       ((and (eq system-type 'gnu/linux)
+             (file-directory-p "/sys/class/power_supply/yeeloong-bat/")
+             (directory-files "/sys/class/power_supply/yeeloong-bat/" nil "charge_"))
+        'battery-yeeloong-sysfs)
        ((and (eq system-type 'darwin)
              (condition-case nil
                  (with-temp-buffer
@@ -78,6 +81,8 @@ introduced by a `%' character in a control string."
         "Power %L, battery %B (%p%% load)")
        ((eq battery-status-function 'battery-pmset)
         "%L power, battery %B (%p%% load, remaining time %t)")
+       ((eq battery-status-function 'battery-yeeloong-sysfs)
+        "%L power, battery %B (%p%% load, remaining time %t)")
        (battery-status-function
         "Power %L, battery %B (%p%% load, remaining time %t)"))
   "Control string formatting the string to display in the echo area.
@@ -103,6 +108,11 @@ string are substituted as defined by the current value of the variable
   "String to display in the mode line.")
 ;;;###autoload (put 'battery-mode-line-string 'risky-local-variable t)
 
+(defcustom battery-mode-line-limit 100
+  "Percentage of full battery load below which display battery status"
+  :type 'integer
+  :group 'battery)
+
 (defcustom battery-mode-line-format
   (cond ((eq battery-status-function 'battery-linux-proc-acpi)
         "[%b%p%%,%d°C]")
@@ -160,22 +170,29 @@ The text being displayed in the echo area is controlled by the variables
 
 ;;;###autoload
 (define-minor-mode display-battery-mode
-  "Display battery status information in the mode line.
-The text being displayed in the mode line is controlled by the variables
+  "Toggle battery status display in mode line (Display Battery mode).
+With a prefix argument ARG, enable Display Battery mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+The text displayed in the mode line is controlled by
 `battery-mode-line-format' and `battery-status-function'.
-The mode line will be updated automatically every `battery-update-interval'
+The mode line is be updated every `battery-update-interval'
 seconds."
   :global t :group 'battery
   (setq battery-mode-line-string "")
   (or global-mode-string (setq global-mode-string '("")))
   (and battery-update-timer (cancel-timer battery-update-timer))
-  (if (not display-battery-mode)
-      (setq global-mode-string
-           (delq 'battery-mode-line-string global-mode-string))
-    (add-to-list 'global-mode-string 'battery-mode-line-string t)
-    (setq battery-update-timer (run-at-time nil battery-update-interval
-                                           'battery-update-handler))
-    (battery-update)))
+  (if (and battery-status-function battery-mode-line-format)
+      (if (not display-battery-mode)
+         (setq global-mode-string
+               (delq 'battery-mode-line-string global-mode-string))
+       (add-to-list 'global-mode-string 'battery-mode-line-string t)
+       (setq battery-update-timer (run-at-time nil battery-update-interval
+                                               'battery-update-handler))
+       (battery-update))
+    (message "Battery status not available")
+    (setq display-battery-mode nil)))
 
 (defun battery-update-handler ()
   (battery-update)
@@ -183,16 +200,21 @@ seconds."
 
 (defun battery-update ()
   "Update battery status information in the mode line."
-  (setq battery-mode-line-string
-       (propertize (if (and battery-mode-line-format
-                            battery-status-function)
-                       (battery-format
-                        battery-mode-line-format
-                        (funcall battery-status-function))
-                     "")
-                   'help-echo "Battery status information"))
+  (let ((data (and battery-status-function (funcall battery-status-function))))
+    (setq battery-mode-line-string
+         (propertize (if (and battery-mode-line-format
+                              (<= (car (read-from-string (cdr (assq ?p data))))
+                                  battery-mode-line-limit))
+                         (battery-format
+                          battery-mode-line-format
+                          data)
+                       "")
+                     'face
+                     (and (<= (car (read-from-string (cdr (assq ?p data))))
+                                  battery-load-critical)
+                          'error)
+                     'help-echo "Battery status information")))
   (force-mode-line-update))
-
 \f
 ;;; `/proc/apm' interface for Linux.
 
@@ -210,7 +232,7 @@ seconds."
   "Regular expression matching contents of `/proc/apm'.")
 
 (defun battery-linux-proc-apm ()
-  "Get APM status information from Linux kernel.
+  "Get APM status information from Linux (the kernel).
 This function works only with the new `/proc/apm' format introduced
 in Linux version 1.3.58.
 
@@ -281,7 +303,7 @@ The following %-sequences are provided:
 ;;; `/proc/acpi/' interface for Linux.
 
 (defun battery-linux-proc-acpi ()
-  "Get ACPI status information from Linux kernel.
+  "Get ACPI status information from Linux (the kernel).
 This function works only with the `/proc/acpi/' format introduced
 in Linux version 2.4.20 and 2.6.0.
 
@@ -405,10 +427,15 @@ format introduced in Linux version 2.4.25.
 
 The following %-sequences are provided:
 %c Current capacity (mAh or mWh)
+%r Current rate
 %B Battery status (verbose)
+%d Temperature (in degrees Celsius)
 %p Battery load percentage
-%L AC line status (verbose)"
-  (let (charging-state
+%L AC line status (verbose)
+%m Remaining time (to charge or discharge) in minutes
+%h Remaining time (to charge or discharge) in hours
+%t Remaining time (to charge or discharge) in the form `h:min'"
+  (let (charging-state rate temperature hours
        (charge-full 0.0)
        (charge-now 0.0)
        (energy-full 0.0)
@@ -428,6 +455,12 @@ The following %-sequences are provided:
          (and (re-search-forward "POWER_SUPPLY_STATUS=\\(.*\\)$" nil t)
               (member charging-state '("Unknown" "Full" nil))
               (setq charging-state (match-string 1)))
+         (when (re-search-forward
+                 "POWER_SUPPLY_\\(CURRENT\\|POWER\\)_NOW=\\([0-9]*\\)$"
+                 nil t)
+           (setq rate (float (string-to-number (match-string 2)))))
+         (when (re-search-forward "POWER_SUPPLY_TEMP=\\([0-9]*\\)$" nil t)
+           (setq temperature (match-string 1)))
          (let (full-string now-string)
            ;; Sysfs may list either charge (mAh) or energy (mWh).
            ;; Keep track of both, and choose which to report later.
@@ -450,12 +483,30 @@ The following %-sequences are provided:
                   (setq energy-full (+ energy-full
                                        (string-to-number full-string))
                         energy-now  (+ energy-now
-                                       (string-to-number now-string)))))))))
+                                       (string-to-number now-string))))))
+         (goto-char (point-min))
+         (when (and energy-now rate (not (zerop rate))
+                    (re-search-forward
+                      "POWER_SUPPLY_VOLTAGE_NOW=\\([0-9]*\\)$" nil t))
+           (let ((remaining (if (string= charging-state "Discharging")
+                                energy-now
+                              (- energy-full energy-now))))
+             (setq hours (/ (/ (* remaining (string-to-number
+                                              (match-string 1)))
+                                rate)
+                            10000000.0)))))))
     (list (cons ?c (cond ((or (> charge-full 0) (> charge-now 0))
                          (number-to-string charge-now))
                         ((or (> energy-full 0) (> energy-now 0))
                          (number-to-string energy-now))
                         (t "N/A")))
+         (cons ?r (if rate (format "%.1f" (/ rate 1000000.0)) "N/A"))
+         (cons ?m (if hours (format "%d" (* hours 60)) "N/A"))
+         (cons ?h (if hours (format "%d" hours) "N/A"))
+         (cons ?t (if hours
+                      (format "%d:%02d" hours (* (- hours (floor hours)) 60))
+                    "N/A"))
+         (cons ?d (or temperature "N/A"))
          (cons ?B (or charging-state "N/A"))
          (cons ?p (cond ((> charge-full 0)
                          (format "%.1f"
@@ -473,7 +524,90 @@ The following %-sequences are provided:
                         "BAT")
                     "N/A")))))
 
+(defun battery-yeeloong-sysfs ()
+  "Get ACPI status information from Linux (the kernel).
+This function works only on the Lemote Yeeloong.
 
+The following %-sequences are provided:
+%c Current capacity (mAh)
+%r Current rate
+%B Battery status (verbose)
+%b Battery status, empty means high, `-' means low,
+   `!' means critical, and `+' means charging
+%L AC line status (verbose)
+%p Battery load percentage
+%m Remaining time (to charge or discharge) in minutes
+%h Remaining time (to charge or discharge) in hours
+%t Remaining time (to charge or discharge) in the form `h:min'"
+
+  (let (capacity
+       capacity-level
+       status
+       ac-online
+       hours
+       current-now
+       charge-full
+       charge-now)
+
+    (with-temp-buffer
+      (ignore-errors
+       (insert-file-contents "/sys/class/power_supply/yeeloong-bat/uevent")
+       (goto-char 1)
+       (search-forward "POWER_SUPPLY_CHARGE_NOW=")
+       (setq charge-now (read (current-buffer)))
+       (goto-char 1)
+       (search-forward "POWER_SUPPLY_CHARGE_FULL=")
+       (setq charge-full (read (current-buffer)))
+       (goto-char 1)
+       (search-forward "POWER_SUPPLY_CURRENT_NOW=")
+       (setq current-now (read (current-buffer)))
+       (goto-char 1)
+       (search-forward "POWER_SUPPLY_CAPACITY_LEVEL=")
+       (setq capacity-level (buffer-substring (point) (line-end-position)))
+       (goto-char 1)
+       (search-forward "POWER_SUPPLY_STATUS=")
+       (setq status (buffer-substring (point) (line-end-position))))
+       
+      (erase-buffer)
+      (ignore-errors
+       (insert-file-contents
+        "/sys/class/power_supply/yeeloong-ac/online")
+       (goto-char 1)
+       (setq ac-online (read (current-buffer)))
+       (erase-buffer)))
+
+
+    (setq capacity (round (/ (* charge-now 100.0) charge-full)))
+    (when (and current-now (not (= current-now 0)))
+      (if (< current-now 0)
+         ;; Charging
+         (setq hours (/ (- charge-now charge-full) (+ 0.0 current-now)))
+       ;; Discharging
+       (setq hours (/ charge-now (+ 0.0 current-now)))))
+
+    (list (cons ?c (if charge-now
+                      (number-to-string charge-now)
+                    "N/A"))
+         (cons ?r current-now)
+         (cons ?B (cond ((equal capacity-level "Full") "full")
+                        ((equal status "Charging") "charging")
+                        ((equal capacity-level "Low") "low")
+                        ((equal capacity-level "Critical") "critical")
+                        (t "high")))
+         (cons ?b (cond ((equal capacity-level "Full") " ")
+                        ((equal status "Charging") "+")
+                        ((equal capacity-level "Low") "-")
+                        ((equal capacity-level "Critical") "!")
+                        (t " ")))
+         (cons ?h (if hours (number-to-string hours) "N/A"))
+         (cons ?m (if hours (number-to-string (* 60 hours)) "N/A"))
+         (cons ?t (if hours
+                      (format "%d:%d"
+                              (/ (round (* 60 hours)) 60)
+                              (% (round (* 60 hours)) 60))
+                    "N/A"))
+         (cons ?p (if capacity (number-to-string capacity) "N/A"))
+         (cons ?L (if (eq ac-online 1) "AC" "BAT")))))
 \f
 ;;; `pmset' interface for Darwin (OS X).