1 /* $NetBSD: sysmon_power.c,v 1.41 2009/06/08 00:55:35 pgoyette Exp $ */
4 * Copyright (c) 2007 Juan Romero Pardines.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Copyright (c) 2003 Wasabi Systems, Inc.
30 * All rights reserved.
32 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed for the NetBSD Project by
45 * Wasabi Systems, Inc.
46 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
47 * or promote products derived from this software without specific prior
50 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
64 * Power management framework for sysmon.
66 * We defer to a power management daemon running in userspace, since
67 * power management is largely a policy issue. This merely provides
68 * for power management event notification to that daemon.
71 #include <sys/cdefs.h>
72 __KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.41 2009/06/08 00:55:35 pgoyette Exp $");
74 #include "opt_compat_netbsd.h"
75 #include <sys/param.h>
76 #include <sys/reboot.h>
77 #include <sys/systm.h>
79 #include <sys/select.h>
80 #include <sys/vnode.h>
81 #include <sys/condvar.h>
82 #include <sys/mutex.h>
85 #include <sys/device.h>
87 #include <dev/sysmon/sysmonvar.h>
88 #include <prop/proplib.h>
91 * Singly linked list for dictionaries to be stored/sent.
93 struct power_event_dictionary
{
94 SLIST_ENTRY(power_event_dictionary
) pev_dict_head
;
95 prop_dictionary_t dict
;
99 struct power_event_description
{
105 * Available events for power switches.
107 static const struct power_event_description pswitch_event_desc
[] = {
108 { PSWITCH_EVENT_PRESSED
, "pressed" },
109 { PSWITCH_EVENT_RELEASED
, "released" },
114 * Available script names for power switches.
116 static const struct power_event_description pswitch_type_desc
[] = {
117 { PSWITCH_TYPE_POWER
, "power_button" },
118 { PSWITCH_TYPE_SLEEP
, "sleep_button" },
119 { PSWITCH_TYPE_LID
, "lid_switch" },
120 { PSWITCH_TYPE_RESET
, "reset_button" },
121 { PSWITCH_TYPE_ACADAPTER
, "acadapter" },
122 { PSWITCH_TYPE_HOTKEY
, "hotkey_button" },
127 * Available events for envsys(4).
129 static const struct power_event_description penvsys_event_desc
[] = {
130 { PENVSYS_EVENT_NORMAL
, "normal" },
131 { PENVSYS_EVENT_CRITICAL
, "critical" },
132 { PENVSYS_EVENT_CRITOVER
, "critical-over" },
133 { PENVSYS_EVENT_CRITUNDER
, "critical-under" },
134 { PENVSYS_EVENT_WARNOVER
, "warning-over" },
135 { PENVSYS_EVENT_WARNUNDER
, "warning-under" },
136 { PENVSYS_EVENT_BATT_CRIT
, "critical-capacity" },
137 { PENVSYS_EVENT_BATT_WARN
, "warning-capacity" },
138 { PENVSYS_EVENT_STATE_CHANGED
, "state-changed" },
139 { PENVSYS_EVENT_LOW_POWER
, "low-power" },
144 * Available script names for envsys(4).
146 static const struct power_event_description penvsys_type_desc
[] = {
147 { PENVSYS_TYPE_BATTERY
, "sensor_battery" },
148 { PENVSYS_TYPE_DRIVE
, "sensor_drive" },
149 { PENVSYS_TYPE_FAN
, "sensor_fan" },
150 { PENVSYS_TYPE_INDICATOR
, "sensor_indicator" },
151 { PENVSYS_TYPE_POWER
, "sensor_power" },
152 { PENVSYS_TYPE_RESISTANCE
, "sensor_resistance" },
153 { PENVSYS_TYPE_TEMP
, "sensor_temperature" },
154 { PENVSYS_TYPE_VOLTAGE
, "sensor_voltage" },
158 #define SYSMON_MAX_POWER_EVENTS 32
159 #define SYSMON_POWER_DICTIONARY_BUSY 0x01
160 #define SYSMON_POWER_DICTIONARY_READY 0x02
162 static power_event_t sysmon_power_event_queue
[SYSMON_MAX_POWER_EVENTS
];
163 static int sysmon_power_event_queue_head
;
164 static int sysmon_power_event_queue_tail
;
165 static int sysmon_power_event_queue_count
;
167 static SLIST_HEAD(, power_event_dictionary
) pev_dict_list
=
168 SLIST_HEAD_INITIALIZER(&pev_dict_list
);
170 static struct selinfo sysmon_power_event_queue_selinfo
;
171 static struct lwp
*sysmon_power_daemon
;
173 static kmutex_t sysmon_power_event_queue_mtx
;
174 static kcondvar_t sysmon_power_event_queue_cv
;
176 static char sysmon_power_type
[32];
178 static int sysmon_power_make_dictionary(prop_dictionary_t
, void *, int, int);
179 static int sysmon_power_daemon_task(struct power_event_dictionary
*,
181 static void sysmon_power_destroy_dictionary(struct power_event_dictionary
*);
183 #define SYSMON_NEXT_EVENT(x) (((x) + 1) % SYSMON_MAX_POWER_EVENTS)
188 * Initializes the mutexes and condition variables in the
189 * boot process via init_main.c.
192 sysmon_power_init(void)
194 mutex_init(&sysmon_power_event_queue_mtx
, MUTEX_DEFAULT
, IPL_NONE
);
195 cv_init(&sysmon_power_event_queue_cv
, "smpower");
196 selinit(&sysmon_power_event_queue_selinfo
);
200 * sysmon_queue_power_event:
202 * Enqueue a power event for the power mangement daemon. Returns
203 * non-zero if we were able to enqueue a power event.
206 sysmon_queue_power_event(power_event_t
*pev
)
208 KASSERT(mutex_owned(&sysmon_power_event_queue_mtx
));
210 if (sysmon_power_event_queue_count
== SYSMON_MAX_POWER_EVENTS
)
213 sysmon_power_event_queue
[sysmon_power_event_queue_head
] = *pev
;
214 sysmon_power_event_queue_head
=
215 SYSMON_NEXT_EVENT(sysmon_power_event_queue_head
);
216 sysmon_power_event_queue_count
++;
222 * sysmon_get_power_event:
224 * Get a power event from the queue. Returns non-zero if there
225 * is an event available.
228 sysmon_get_power_event(power_event_t
*pev
)
230 KASSERT(mutex_owned(&sysmon_power_event_queue_mtx
));
232 if (sysmon_power_event_queue_count
== 0)
235 *pev
= sysmon_power_event_queue
[sysmon_power_event_queue_tail
];
236 sysmon_power_event_queue_tail
=
237 SYSMON_NEXT_EVENT(sysmon_power_event_queue_tail
);
238 sysmon_power_event_queue_count
--;
244 * sysmon_power_event_queue_flush:
246 * Flush the event queue, and reset all state.
249 sysmon_power_event_queue_flush(void)
251 KASSERT(mutex_owned(&sysmon_power_event_queue_mtx
));
253 sysmon_power_event_queue_head
= 0;
254 sysmon_power_event_queue_tail
= 0;
255 sysmon_power_event_queue_count
= 0;
259 * sysmon_power_daemon_task:
261 * Assign required power event members and sends a signal
262 * to the process to notify that an event was enqueued succesfully.
265 sysmon_power_daemon_task(struct power_event_dictionary
*ped
,
266 void *pev_data
, int event
)
271 if (!ped
|| !ped
->dict
|| !pev_data
)
274 mutex_enter(&sysmon_power_event_queue_mtx
);
278 * Power switch events.
280 case PSWITCH_EVENT_PRESSED
:
281 case PSWITCH_EVENT_RELEASED
:
284 struct sysmon_pswitch
*pswitch
=
285 (struct sysmon_pswitch
*)pev_data
;
287 pev
.pev_type
= POWER_EVENT_SWITCH_STATE_CHANGE
;
289 pev
.pev_switch
.psws_state
= event
;
290 pev
.pev_switch
.psws_type
= pswitch
->smpsw_type
;
292 if (pswitch
->smpsw_name
) {
293 (void)strlcpy(pev
.pev_switch
.psws_name
,
295 sizeof(pev
.pev_switch
.psws_name
));
298 error
= sysmon_power_make_dictionary(ped
->dict
,
303 mutex_exit(&sysmon_power_event_queue_mtx
);
313 case PENVSYS_EVENT_NORMAL
:
314 case PENVSYS_EVENT_CRITICAL
:
315 case PENVSYS_EVENT_CRITUNDER
:
316 case PENVSYS_EVENT_CRITOVER
:
317 case PENVSYS_EVENT_WARNUNDER
:
318 case PENVSYS_EVENT_WARNOVER
:
319 case PENVSYS_EVENT_BATT_CRIT
:
320 case PENVSYS_EVENT_BATT_WARN
:
321 case PENVSYS_EVENT_STATE_CHANGED
:
322 case PENVSYS_EVENT_LOW_POWER
:
324 struct penvsys_state
*penvsys
=
325 (struct penvsys_state
*)pev_data
;
327 pev
.pev_type
= POWER_EVENT_ENVSYS_STATE_CHANGE
;
329 error
= sysmon_power_make_dictionary(ped
->dict
,
334 mutex_exit(&sysmon_power_event_queue_mtx
);
342 mutex_exit(&sysmon_power_event_queue_mtx
);
349 rv
= sysmon_queue_power_event(&pev
);
351 printf("%s: WARNING: state change event %d lost; "
352 "queue full\n", __func__
, pev
.pev_type
);
353 mutex_exit(&sysmon_power_event_queue_mtx
);
358 * Notify the daemon that an event is ready and its
359 * dictionary is ready to be fetched.
361 ped
->flags
|= SYSMON_POWER_DICTIONARY_READY
;
362 SLIST_INSERT_HEAD(&pev_dict_list
, ped
, pev_dict_head
);
363 cv_broadcast(&sysmon_power_event_queue_cv
);
364 mutex_exit(&sysmon_power_event_queue_mtx
);
365 selnotify(&sysmon_power_event_queue_selinfo
, 0, 0);
375 * Open the system monitor device.
378 sysmonopen_power(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
382 mutex_enter(&sysmon_power_event_queue_mtx
);
383 if (sysmon_power_daemon
!= NULL
)
386 sysmon_power_daemon
= l
;
387 sysmon_power_event_queue_flush();
389 mutex_exit(&sysmon_power_event_queue_mtx
);
397 * Close the system monitor device.
400 sysmonclose_power(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
404 mutex_enter(&sysmon_power_event_queue_mtx
);
405 count
= sysmon_power_event_queue_count
;
406 sysmon_power_daemon
= NULL
;
407 sysmon_power_event_queue_flush();
408 mutex_exit(&sysmon_power_event_queue_mtx
);
411 printf("WARNING: %d power event%s lost by exiting daemon\n",
412 count
, count
> 1 ? "s" : "");
420 * Read the system monitor device.
423 sysmonread_power(dev_t dev
, struct uio
*uio
, int flags
)
428 /* We only allow one event to be read at a time. */
429 if (uio
->uio_resid
!= POWER_EVENT_MSG_SIZE
)
432 mutex_enter(&sysmon_power_event_queue_mtx
);
434 if (sysmon_get_power_event(&pev
)) {
435 rv
= uiomove(&pev
, POWER_EVENT_MSG_SIZE
, uio
);
439 if (flags
& IO_NDELAY
) {
444 cv_wait(&sysmon_power_event_queue_cv
,
445 &sysmon_power_event_queue_mtx
);
447 mutex_exit(&sysmon_power_event_queue_mtx
);
455 * Poll the system monitor device.
458 sysmonpoll_power(dev_t dev
, int events
, struct lwp
*l
)
462 revents
= events
& (POLLOUT
| POLLWRNORM
);
464 /* Attempt to save some work. */
465 if ((events
& (POLLIN
| POLLRDNORM
)) == 0)
468 mutex_enter(&sysmon_power_event_queue_mtx
);
469 if (sysmon_power_event_queue_count
)
470 revents
|= events
& (POLLIN
| POLLRDNORM
);
472 selrecord(l
, &sysmon_power_event_queue_selinfo
);
473 mutex_exit(&sysmon_power_event_queue_mtx
);
479 filt_sysmon_power_rdetach(struct knote
*kn
)
482 mutex_enter(&sysmon_power_event_queue_mtx
);
483 SLIST_REMOVE(&sysmon_power_event_queue_selinfo
.sel_klist
,
484 kn
, knote
, kn_selnext
);
485 mutex_exit(&sysmon_power_event_queue_mtx
);
489 filt_sysmon_power_read(struct knote
*kn
, long hint
)
492 mutex_enter(&sysmon_power_event_queue_mtx
);
493 kn
->kn_data
= sysmon_power_event_queue_count
;
494 mutex_exit(&sysmon_power_event_queue_mtx
);
496 return kn
->kn_data
> 0;
499 static const struct filterops sysmon_power_read_filtops
=
500 { 1, NULL
, filt_sysmon_power_rdetach
, filt_sysmon_power_read
};
502 static const struct filterops sysmon_power_write_filtops
=
503 { 1, NULL
, filt_sysmon_power_rdetach
, filt_seltrue
};
506 * sysmonkqfilter_power:
508 * Kqueue filter for the system monitor device.
511 sysmonkqfilter_power(dev_t dev
, struct knote
*kn
)
515 switch (kn
->kn_filter
) {
517 klist
= &sysmon_power_event_queue_selinfo
.sel_klist
;
518 kn
->kn_fop
= &sysmon_power_read_filtops
;
522 klist
= &sysmon_power_event_queue_selinfo
.sel_klist
;
523 kn
->kn_fop
= &sysmon_power_write_filtops
;
530 mutex_enter(&sysmon_power_event_queue_mtx
);
531 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
532 mutex_exit(&sysmon_power_event_queue_mtx
);
540 * Perform a power managmenet control request.
543 sysmonioctl_power(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
548 case POWER_IOC_GET_TYPE
:
549 case POWER_IOC_GET_TYPE_WITH_LOSSAGE
:
551 struct power_type
*power_type
= (void *) data
;
553 (void)strlcpy(power_type
->power_type
,
555 sizeof(power_type
->power_type
));
558 case POWER_EVENT_RECVDICT
:
560 struct plistref
*plist
= (struct plistref
*)data
;
561 struct power_event_dictionary
*ped
;
564 * Get the first dictionary enqueued and mark it
567 mutex_enter(&sysmon_power_event_queue_mtx
);
568 ped
= SLIST_FIRST(&pev_dict_list
);
569 if (!ped
|| !ped
->dict
) {
570 mutex_exit(&sysmon_power_event_queue_mtx
);
575 if ((ped
->flags
& SYSMON_POWER_DICTIONARY_READY
) == 0) {
576 mutex_exit(&sysmon_power_event_queue_mtx
);
581 if (ped
->flags
& SYSMON_POWER_DICTIONARY_BUSY
) {
582 mutex_exit(&sysmon_power_event_queue_mtx
);
587 ped
->flags
|= SYSMON_POWER_DICTIONARY_BUSY
;
588 mutex_exit(&sysmon_power_event_queue_mtx
);
593 error
= prop_dictionary_copyout_ioctl(plist
,
598 * Remove the dictionary now that we don't need it.
600 mutex_enter(&sysmon_power_event_queue_mtx
);
601 ped
->flags
&= ~SYSMON_POWER_DICTIONARY_BUSY
;
602 ped
->flags
&= ~SYSMON_POWER_DICTIONARY_READY
;
603 SLIST_REMOVE_HEAD(&pev_dict_list
, pev_dict_head
);
604 mutex_exit(&sysmon_power_event_queue_mtx
);
605 sysmon_power_destroy_dictionary(ped
);
617 * sysmon_power_make_dictionary:
619 * Adds the properties for an event in a dictionary.
622 sysmon_power_make_dictionary(prop_dictionary_t dict
, void *power_data
,
627 KASSERT(mutex_owned(&sysmon_power_event_queue_mtx
));
631 * create the dictionary for a power switch event.
633 case POWER_EVENT_SWITCH_STATE_CHANGE
:
635 const struct power_event_description
*peevent
=
637 const struct power_event_description
*petype
=
639 struct sysmon_pswitch
*smpsw
=
640 (struct sysmon_pswitch
*)power_data
;
641 const char *pwrtype
= "pswitch";
643 #define SETPROP(key, str) \
645 if ((str) && !prop_dictionary_set_cstring(dict, \
648 printf("%s: failed to set %s\n", __func__, (str)); \
651 } while (/* CONSTCOND */ 0)
654 SETPROP("driver-name", smpsw
->smpsw_name
);
656 for (i
= 0; peevent
[i
].type
!= -1; i
++)
657 if (peevent
[i
].type
== event
)
660 SETPROP("powerd-event-name", peevent
[i
].desc
);
662 for (i
= 0; petype
[i
].type
!= -1; i
++)
663 if (petype
[i
].type
== smpsw
->smpsw_type
)
666 SETPROP("powerd-script-name", petype
[i
].desc
);
667 SETPROP("power-type", pwrtype
);
671 * create a dictionary for power envsys event.
673 case POWER_EVENT_ENVSYS_STATE_CHANGE
:
675 const struct power_event_description
*peevent
=
677 const struct power_event_description
*petype
=
679 struct penvsys_state
*pes
=
680 (struct penvsys_state
*)power_data
;
681 const char *pwrtype
= "envsys";
683 SETPROP("driver-name", pes
->pes_dvname
);
684 SETPROP("sensor-name", pes
->pes_sensname
);
685 SETPROP("state-description", pes
->pes_statedesc
);
687 for (i
= 0; peevent
[i
].type
!= -1; i
++)
688 if (peevent
[i
].type
== event
)
691 SETPROP("powerd-event-name", peevent
[i
].desc
);
693 for (i
= 0; petype
[i
].type
!= -1; i
++)
694 if (petype
[i
].type
== pes
->pes_type
)
697 SETPROP("powerd-script-name", petype
[i
].desc
);
698 SETPROP("power-type", pwrtype
);
709 * sysmon_power_destroy_dictionary:
711 * Destroys a power_event_dictionary object and all its
712 * properties in the dictionary.
715 sysmon_power_destroy_dictionary(struct power_event_dictionary
*ped
)
717 prop_object_iterator_t iter
;
720 KASSERT(ped
!= NULL
);
721 KASSERT((ped
->flags
& SYSMON_POWER_DICTIONARY_BUSY
) == 0);
723 iter
= prop_dictionary_iterator(ped
->dict
);
727 while ((obj
= prop_object_iterator_next(iter
)) != NULL
) {
728 prop_dictionary_remove(ped
->dict
,
729 prop_dictionary_keysym_cstring_nocopy(obj
));
730 prop_object_iterator_reset(iter
);
733 prop_object_iterator_release(iter
);
734 prop_object_release(ped
->dict
);
736 kmem_free(ped
, sizeof(*ped
));
740 * sysmon_power_settype:
742 * Sets the back-end power management type. This information can
743 * be used by the power management daemon.
746 sysmon_power_settype(const char *type
)
750 * Don't bother locking this; it's going to be set
751 * during autoconfiguration, and then only read from
754 (void)strlcpy(sysmon_power_type
, type
, sizeof(sysmon_power_type
));
757 #define PENVSYS_SHOWSTATE(str) \
759 printf("%s: %s limit on '%s'\n", \
760 pes->pes_dvname, (str), pes->pes_sensname); \
761 } while (/* CONSTCOND */ 0)
764 * sysmon_penvsys_event:
766 * Puts an event onto the sysmon power queue and sends the
767 * appropiate event if the daemon is running, otherwise a
771 sysmon_penvsys_event(struct penvsys_state
*pes
, int event
)
773 struct power_event_dictionary
*ped
;
774 const char *mystr
= NULL
;
776 KASSERT(pes
!= NULL
);
778 if (sysmon_power_daemon
!= NULL
) {
780 * Create a dictionary for the new event.
782 ped
= kmem_zalloc(sizeof(*ped
), KM_NOSLEEP
);
785 ped
->dict
= prop_dictionary_create();
787 if (sysmon_power_daemon_task(ped
, pes
, event
) == 0)
791 switch (pes
->pes_type
) {
792 case PENVSYS_TYPE_BATTERY
:
794 case PENVSYS_EVENT_LOW_POWER
:
795 printf("sysmon: LOW POWER! SHUTTING DOWN.\n");
796 cpu_reboot(RB_POWERDOWN
, NULL
);
798 case PENVSYS_EVENT_STATE_CHANGED
:
799 printf("%s: state changed on '%s' to '%s'\n",
800 pes
->pes_dvname
, pes
->pes_sensname
,
803 case PENVSYS_EVENT_BATT_CRIT
:
804 mystr
= "critical capacity";
805 PENVSYS_SHOWSTATE(mystr
);
807 case PENVSYS_EVENT_BATT_WARN
:
808 mystr
= "warning capacity";
809 PENVSYS_SHOWSTATE(mystr
);
811 case PENVSYS_EVENT_NORMAL
:
812 printf("%s: normal capacity on '%s'\n",
813 pes
->pes_dvname
, pes
->pes_sensname
);
817 case PENVSYS_TYPE_FAN
:
818 case PENVSYS_TYPE_INDICATOR
:
819 case PENVSYS_TYPE_TEMP
:
820 case PENVSYS_TYPE_POWER
:
821 case PENVSYS_TYPE_RESISTANCE
:
822 case PENVSYS_TYPE_VOLTAGE
:
824 case PENVSYS_EVENT_CRITICAL
:
826 PENVSYS_SHOWSTATE(mystr
);
828 case PENVSYS_EVENT_CRITOVER
:
829 mystr
= "critical over";
830 PENVSYS_SHOWSTATE(mystr
);
832 case PENVSYS_EVENT_CRITUNDER
:
833 mystr
= "critical under";
834 PENVSYS_SHOWSTATE(mystr
);
836 case PENVSYS_EVENT_WARNOVER
:
837 mystr
= "warning over";
838 PENVSYS_SHOWSTATE(mystr
);
840 case PENVSYS_EVENT_WARNUNDER
:
841 mystr
= "warning under";
842 PENVSYS_SHOWSTATE(mystr
);
844 case PENVSYS_EVENT_NORMAL
:
845 printf("%s: normal state on '%s'\n",
846 pes
->pes_dvname
, pes
->pes_sensname
);
849 printf("%s: unknown event\n", __func__
);
852 case PENVSYS_TYPE_DRIVE
:
854 case PENVSYS_EVENT_STATE_CHANGED
:
855 printf("%s: state changed on '%s' to '%s'\n",
856 pes
->pes_dvname
, pes
->pes_sensname
,
859 case PENVSYS_EVENT_NORMAL
:
860 printf("%s: normal state on '%s' (%s)\n",
861 pes
->pes_dvname
, pes
->pes_sensname
,
867 printf("%s: unknown power type\n", __func__
);
873 * sysmon_pswitch_register:
875 * Register a power switch device.
878 sysmon_pswitch_register(struct sysmon_pswitch
*smpsw
)
885 * sysmon_pswitch_unregister:
887 * Unregister a power switch device.
890 sysmon_pswitch_unregister(struct sysmon_pswitch
*smpsw
)
896 * sysmon_pswitch_event:
898 * Register an event on a power switch device.
901 sysmon_pswitch_event(struct sysmon_pswitch
*smpsw
, int event
)
903 struct power_event_dictionary
*ped
= NULL
;
905 KASSERT(smpsw
!= NULL
);
908 * For pnp specific events, we don't care if the power daemon
911 if (smpsw
->smpsw_type
== PSWITCH_TYPE_LID
) {
913 case PSWITCH_EVENT_PRESSED
:
914 pmf_event_inject(NULL
, PMFE_CHASSIS_LID_CLOSE
);
916 case PSWITCH_EVENT_RELEASED
:
917 pmf_event_inject(NULL
, PMFE_CHASSIS_LID_OPEN
);
924 if (sysmon_power_daemon
!= NULL
) {
926 * Create a new dictionary for the event.
928 ped
= kmem_zalloc(sizeof(*ped
), KM_NOSLEEP
);
931 ped
->dict
= prop_dictionary_create();
933 if (sysmon_power_daemon_task(ped
, smpsw
, event
) == 0)
937 switch (smpsw
->smpsw_type
) {
938 case PSWITCH_TYPE_POWER
:
939 if (event
!= PSWITCH_EVENT_PRESSED
) {
945 * Attempt a somewhat graceful shutdown of the system,
946 * as if the user has issued a reboot(2) call with
949 printf("%s: power button pressed, shutting down!\n",
951 cpu_reboot(RB_POWERDOWN
, NULL
);
954 case PSWITCH_TYPE_RESET
:
955 if (event
!= PSWITCH_EVENT_PRESSED
) {
961 * Attempt a somewhat graceful reboot of the system,
962 * as if the user had issued a reboot(2) call.
964 printf("%s: reset button pressed, rebooting!\n",
969 case PSWITCH_TYPE_SLEEP
:
970 if (event
!= PSWITCH_EVENT_PRESSED
) {
976 * Try to enter a "sleep" state.
979 printf("%s: sleep button pressed.\n", smpsw
->smpsw_name
);
982 case PSWITCH_TYPE_HOTKEY
:
984 * Eat up the event, there's nothing we can do
988 case PSWITCH_TYPE_LID
:
990 case PSWITCH_EVENT_PRESSED
:
992 * Try to enter a "standby" state.
995 printf("%s: lid closed.\n", smpsw
->smpsw_name
);
998 case PSWITCH_EVENT_RELEASED
:
1000 * Come out of "standby" state.
1003 printf("%s: lid opened.\n", smpsw
->smpsw_name
);
1007 printf("%s: unknown lid switch event: %d\n",
1008 smpsw
->smpsw_name
, event
);
1012 case PSWITCH_TYPE_ACADAPTER
:
1014 case PSWITCH_EVENT_PRESSED
:
1016 * Come out of power-save state.
1018 aprint_normal("%s: AC adapter online.\n",
1022 case PSWITCH_EVENT_RELEASED
:
1024 * Try to enter a power-save state.
1026 aprint_normal("%s: AC adapter offline.\n",