Add _BIX (Battery Information Extended) object support.
ACPI Control Method Batteries have a _BIF and/or _BIX object which provide static properties of the battery. FreeBSD acpi_cmbat module supported _BIF object only, which was deprecated as of ACPI 4.0. _BIX is an extended version of _BIF defined in ACPI 4.0 or later. As of writing, _BIX has two revisions. One is in ACPI 4.0 (rev.0) and another is in ACPI 6.0 (rev.1). It seems that hardware vendors still stick to _BIF only or _BIX rev.0 + _BIF for the maximum compatibility. Microsoft requires _BIX rev.0 for Windows machines, so there are some laptop machines with _BIX rev.0 only. In this case, FreeBSD does not recognize the battery information. After this change, the acpi_cmbat module gets battery information from _BIX or _BIF object and internally uses _BIX rev.1 data structure as the primary information store in the kernel. ACPIIO_BATT_GET_BI[FX] returns an acpi_bi[fx] structure built by using information obtained from a _BIF or a _BIX object found on the system. The revision number field can be used to check which field is available. The acpiconf(8) utility will show additional information if _BIX is available. Although ABIs of ACPIIO_BATT_* were changed, the existing APIs for userland utilities are not changed and the backward-compatible ABIs are provided. This means that older versions of acpiconf(8) can also work with the new kernel. The (union acpi_battery_ioctl_arg) was padded to 256 byte long to avoid another ABI change in the future. A _BIX object with its revision number >1 will be treated as compatible with the rev.1 _BIX format. Reviewed by: takawata MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D23728
This commit is contained in:
parent
9fab908a79
commit
294de6bbd6
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 26, 2019
|
||||
.Dd February 16, 2020
|
||||
.Dt ACPI_BATTERY 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -37,6 +37,7 @@
|
||||
The
|
||||
.Nm
|
||||
is a driver for battery management features of the ACPI module.
|
||||
.Pp
|
||||
An ACPI-compatible battery device supports either a Control
|
||||
Method Battery interface or a Smart Battery subsystem interface.
|
||||
The former is accessed by the AML
|
||||
@ -45,7 +46,8 @@ code control methods,
|
||||
and the latter is controlled directly through the ACPI EC
|
||||
.Pq Embedded Controller
|
||||
typically via an SMBus interface.
|
||||
This driver supports the
|
||||
.Pp
|
||||
This driver supports the
|
||||
.Xr sysctl 8
|
||||
and
|
||||
.Xr ioctl 2
|
||||
@ -59,60 +61,86 @@ driver takes a single integer value for the battery unit
|
||||
number as an argument,
|
||||
and returns a specific structure for each request.
|
||||
A special unit number
|
||||
.Li ACPI_BATTERY_ALL_UNITS
|
||||
.Dv ACPI_BATTERY_ALL_UNITS
|
||||
specifies all of the attached units
|
||||
and reports accumulated information.
|
||||
.Bl -tag -width indent
|
||||
.It ACPIIO_BATT_GET_UNITS Vt int
|
||||
.It Dv ACPIIO_BATT_GET_UNITS Vt int
|
||||
Returns the number of battery units in the system.
|
||||
The unit number argument will be ignored.
|
||||
.It ACPIIO_BATT_GET_BATTINFO Vt struct acpi_battinfo
|
||||
.It Dv ACPIIO_BATT_GET_BATTINFO Vt struct acpi_battinfo
|
||||
Returns the following:
|
||||
.Bl -tag -width indent
|
||||
.It cap
|
||||
.It Va cap
|
||||
Battery capacity in percent,
|
||||
.It min
|
||||
.It Va min
|
||||
Remaining battery life in minutes,
|
||||
.It state
|
||||
.It Va state
|
||||
Current status of the battery encoded in the following:
|
||||
.Bl -tag -width indent
|
||||
.It ACPI_BATT_STAT_DISCHARG Pq 0x0001
|
||||
.It Dv ACPI_BATT_STAT_DISCHARG Pq 0x0001
|
||||
Battery is discharging,
|
||||
.It ACPI_BATT_STAT_CHARGING Pq 0x0002
|
||||
.It Dv ACPI_BATT_STAT_CHARGING Pq 0x0002
|
||||
Battery is being charged, or
|
||||
.It ACPI_BATT_STAT_CRITICAL Pq 0x0004
|
||||
.It Dv ACPI_BATT_STAT_CRITICAL Pq 0x0004
|
||||
Remaining battery life is critically low.
|
||||
.El
|
||||
.Pp
|
||||
Note that the status bits of each battery will be
|
||||
consolidated when
|
||||
.Li ACPI_BATTERY_ALL_UNITS
|
||||
.Dv ACPI_BATTERY_ALL_UNITS
|
||||
is specified.
|
||||
.It rate
|
||||
.It Va rate
|
||||
Current battery discharging rate in mW.
|
||||
.Li -1
|
||||
means not discharging right now.
|
||||
.El
|
||||
.It ACPIIO_BATT_GET_BIF Vt struct acpi_bif
|
||||
.It Dv ACPIIO_BATT_GET_BIX Vt struct acpi_bix
|
||||
Returns battery information given by the ACPI
|
||||
.Li _BIF Pq Battery Information
|
||||
.Li _BIX Pq Battery Information
|
||||
object,
|
||||
which is the static portion of the Control Method
|
||||
Battery information.
|
||||
In the case of a Smart Battery attached to SMBus,
|
||||
In the case of a Smart Battery attached to
|
||||
SMBus or a Control Method Battery with a
|
||||
.Li _BIF
|
||||
object,
|
||||
this ioctl will build a
|
||||
.Vt struct acpi_bif
|
||||
.Vt struct acpi_bix
|
||||
structure based on the obtained information
|
||||
and return it.
|
||||
.Bl -tag -width indent
|
||||
.It units
|
||||
.It Va rev
|
||||
Revision number of the object.
|
||||
There are the following well-known values:
|
||||
.Bl -tag -width indent
|
||||
.It Dv ACPI_BIX_REV_0 Pq 0x0000
|
||||
A
|
||||
.Li _BIX
|
||||
object in ACPI 4.0.
|
||||
.It Dv ACPI_BIX_REV_1 Pq 0x0001
|
||||
A
|
||||
.Li _BIX
|
||||
object in ACPI 6.0.
|
||||
.It Dv ACPI_BIX_REV_BIF Pq 0xffff
|
||||
A
|
||||
.Li _BIX
|
||||
object built from the
|
||||
.Li _BIF
|
||||
object found on the system.
|
||||
.El
|
||||
.Pp
|
||||
Note that this field should be checked by using
|
||||
.Fn ACPI_BIX_REV_MIN_CHECK var rev
|
||||
macro when checking the minimum revision number.
|
||||
.It Va units
|
||||
Indicates the units used by the battery to report its
|
||||
capacity and charge rate encoded in the following:
|
||||
.Bl -tag -width indent
|
||||
.It ACPI_BIF_UNITS_MW Pq 0x00000000
|
||||
.It ACPI_BIX_UNITS_MW Pq 0x00000000
|
||||
in mW
|
||||
.Pq power
|
||||
.It ACPI_BIF_UNITS_MA Pq 0x00000001
|
||||
.It ACPI_BIX_UNITS_MA Pq 0x00000001
|
||||
in mA
|
||||
.Pq current
|
||||
.El
|
||||
@ -120,31 +148,69 @@ in mA
|
||||
Note that capacity is expressed in mWh or mAh,
|
||||
and rate is expressed in mW or mA,
|
||||
respectively.
|
||||
.It dcap
|
||||
.It Va dcap
|
||||
The Battery's design capacity,
|
||||
which is the nominal capacity of a new battery.
|
||||
This is expressed as power or current depending on
|
||||
the value of
|
||||
.Va units .
|
||||
.It lfcap
|
||||
.It Va lfcap
|
||||
Predicted battery capacity when fully charged.
|
||||
Typically this will decrease every charging cycle.
|
||||
.It btech
|
||||
Battery technology:
|
||||
.Bl -tag -width indent
|
||||
.It 0x00000000 Primary cell Pq non-rechargable
|
||||
.It 0x00000001 Secondery cell Pq rechargable
|
||||
.It 0x00000001 Secondary cell Pq rechargable
|
||||
.El
|
||||
.It dvol
|
||||
.It Va dvol
|
||||
Design voltage in mV,
|
||||
which is the nominal voltage of a new battery.
|
||||
.It wcap
|
||||
.It Va wcap
|
||||
Design capacity of warning.
|
||||
When a discharging battery device reaches this capacity,
|
||||
notification is sent to the system.
|
||||
.It lcap
|
||||
.It Va lcap
|
||||
Design capacity of low.
|
||||
.It gra1
|
||||
.It Va cycles
|
||||
.Pq rev 0 or newer
|
||||
The number of cycles the battery has experienced.
|
||||
A cycle means an amount of discharge occurred which was
|
||||
approximately equal to the value of Design Capacity.
|
||||
.It Va accuracy
|
||||
.Pq rev 0 or newer
|
||||
The accuracy of the battery capacity measurement,
|
||||
in thousandth of a percent.
|
||||
.It Va stmax
|
||||
.Pq rev 0 or newer
|
||||
The Maximum Sampling Time of the battery in
|
||||
milliseconds.
|
||||
This is the maximum duration between two consecutive
|
||||
measurements of the battery's capacities specified in
|
||||
.Li _BST .
|
||||
If two succeeding readings of
|
||||
.Li _BST
|
||||
beyond this duration occur,
|
||||
two different results can be returned.
|
||||
.It Va stmin
|
||||
.Pq rev 0 or newer
|
||||
The Minimum Sampling Time of the battery in
|
||||
milliseconds.
|
||||
.It Va aimax
|
||||
.Pq rev 0 or newer
|
||||
The Maximum Average Interval of the battery in
|
||||
milliseconds.
|
||||
This is the length of time within which the battery
|
||||
averages the capacity measurements specified in
|
||||
.Li _BST .
|
||||
The Sampling Time specifies the frequency of measurements,
|
||||
and the Average Interval specifies the width of the time
|
||||
window of every measurement.
|
||||
.It Va aimin
|
||||
.Pq rev 0 or newer
|
||||
The Minimum Average Interval of the battery in
|
||||
milliseconds.
|
||||
.It Va gra1
|
||||
Battery capacity granularity between
|
||||
.Va low
|
||||
and
|
||||
@ -152,7 +218,7 @@ and
|
||||
This is expressed as power or current depending on
|
||||
the value of
|
||||
.Va units .
|
||||
.It gra2
|
||||
.It Va gra2
|
||||
Battery capacity granularity between
|
||||
.Va warning
|
||||
and
|
||||
@ -160,15 +226,41 @@ and
|
||||
This is expressed as power or current depending on
|
||||
the value of
|
||||
.Va units .
|
||||
.It model
|
||||
.It Va model
|
||||
Model number of the battery as a string.
|
||||
.It serial
|
||||
.It Va serial
|
||||
Serial number of the battery as a string.
|
||||
.It type
|
||||
.It Va type
|
||||
Type identifier of the battery as a string.
|
||||
.It oeminfo
|
||||
.It Va oeminfo
|
||||
OEM-specific information of the battery as a string.
|
||||
.It Va scap
|
||||
.Pq rev 1 or newer
|
||||
Battery swapping capability encoded in the following:
|
||||
.Bl -tag -width indent
|
||||
.It ACPI_BIX_SCAP_NO Pq 0x00000000
|
||||
Non-swappable
|
||||
.It ACPI_BIX_SCAP_COLD Pq 0x00000001
|
||||
Cold-swappable
|
||||
.It ACPI_BIX_SCAP_HOT Pq 0x00000010
|
||||
Hot-swappable
|
||||
.El
|
||||
.El
|
||||
.It Dv ACPIIO_BATT_GET_BIF Vt struct acpi_bif
|
||||
.Pq deprecated
|
||||
Returns battery information given by the ACPI
|
||||
.Li _BIF Pq Battery Information
|
||||
object,
|
||||
which was deprecated in ACPI 4.0 specification.
|
||||
The data structure is a subset of
|
||||
.Vt struct acpi_bix .
|
||||
.Pp
|
||||
Note that this ioctl will built a
|
||||
.Vt struct acpi_bif
|
||||
structure based on the obtained information
|
||||
even if this object is not available and a
|
||||
.Li _BIX
|
||||
object is found.
|
||||
.It ACPIIO_BATT_GET_BST Vt struct acpi_bst
|
||||
Returns battery information given by the ACPI
|
||||
.Li _BST Pq Battery Status
|
||||
@ -180,25 +272,25 @@ this ioctl will build a
|
||||
structure based on the obtained information
|
||||
and return it.
|
||||
.Bl -tag -width indent
|
||||
.It state
|
||||
.It Va state
|
||||
Battery state.
|
||||
The value is encoded in the same way as
|
||||
.Va state
|
||||
of
|
||||
.Vt struct acpi_battinfo .
|
||||
.It rate
|
||||
.It Va rate
|
||||
Battery present rate of charging or discharging.
|
||||
The unit of the value depends on
|
||||
.Va unit
|
||||
of
|
||||
.Vt struct acpi_bif .
|
||||
.It cap
|
||||
.It Va cap
|
||||
Battery remaining capacity.
|
||||
The unit of this value depends on
|
||||
.Va unit
|
||||
of
|
||||
.Vt struct acpi_bif .
|
||||
.It volt
|
||||
.It Va volt
|
||||
Battery present voltage.
|
||||
.El
|
||||
.El
|
||||
@ -212,6 +304,8 @@ connected batteries:
|
||||
.It Va hw.acpi.battery.info_expire
|
||||
Information cache expiration time in seconds.
|
||||
The battery information obtained by
|
||||
.Li _BIX
|
||||
or
|
||||
.Li _BIF
|
||||
object will be stored and reused for successive
|
||||
read access to this MIB within the specified period.
|
||||
@ -276,8 +370,11 @@ Battery information was changed.
|
||||
.An Munehiro Matsuda ,
|
||||
.An Takanori Watanabe Aq Mt takawata@FreeBSD.org ,
|
||||
.An Mitsuru IWASAKI Aq Mt iwasaki@FreeBSD.org ,
|
||||
.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org ,
|
||||
and
|
||||
.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org .
|
||||
.An Hiroki Sato Aq Mt hrs@FreeBSD.org .
|
||||
.Pp
|
||||
This manual page was written by
|
||||
.An Takanori Watanabe Aq Mt takawata@FreeBSD.org .
|
||||
.An Takanori Watanabe Aq Mt takawata@FreeBSD.org
|
||||
and
|
||||
.An Hiroki Sato Aq Mt hrs@FreeBSD.org .
|
||||
|
@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
/* Default seconds before re-sampling the battery state. */
|
||||
#define ACPI_BATTERY_INFO_EXPIRE 5
|
||||
|
||||
static int acpi_batteries_initted;
|
||||
static int acpi_batteries_initialized;
|
||||
static int acpi_battery_info_expire = ACPI_BATTERY_INFO_EXPIRE;
|
||||
static struct acpi_battinfo acpi_battery_battinfo;
|
||||
static struct sysctl_ctx_list acpi_battery_sysctl_ctx;
|
||||
@ -65,11 +65,10 @@ acpi_battery_register(device_t dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
ACPI_SERIAL_BEGIN(battery);
|
||||
if (!acpi_batteries_initted)
|
||||
error = acpi_battery_init();
|
||||
error = acpi_battery_init();
|
||||
ACPI_SERIAL_END(battery);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -107,11 +106,12 @@ acpi_battery_bst_valid(struct acpi_bst *bst)
|
||||
bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN);
|
||||
}
|
||||
|
||||
/* Check _BIF results for validity. */
|
||||
/* Check _BI[FX] results for validity. */
|
||||
int
|
||||
acpi_battery_bif_valid(struct acpi_bif *bif)
|
||||
acpi_battery_bix_valid(struct acpi_bix *bix)
|
||||
{
|
||||
return (bif->lfcap != 0);
|
||||
|
||||
return (bix->lfcap != 0);
|
||||
}
|
||||
|
||||
/* Get info about one or all batteries. */
|
||||
@ -123,7 +123,7 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
|
||||
devclass_t batt_dc;
|
||||
device_t batt_dev;
|
||||
struct acpi_bst *bst;
|
||||
struct acpi_bif *bif;
|
||||
struct acpi_bix *bix;
|
||||
struct acpi_battinfo *bi;
|
||||
|
||||
/*
|
||||
@ -139,11 +139,11 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
|
||||
|
||||
/*
|
||||
* Allocate storage for all _BST data, their derived battinfo data,
|
||||
* and the current battery's _BIF data.
|
||||
* and the current battery's _BIX (or _BIF) data.
|
||||
*/
|
||||
bst = malloc(devcount * sizeof(*bst), M_TEMP, M_WAITOK | M_ZERO);
|
||||
bi = malloc(devcount * sizeof(*bi), M_TEMP, M_WAITOK | M_ZERO);
|
||||
bif = malloc(sizeof(*bif), M_TEMP, M_WAITOK | M_ZERO);
|
||||
bix = malloc(sizeof(*bix), M_TEMP, M_WAITOK | M_ZERO);
|
||||
|
||||
/*
|
||||
* Pass 1: for each battery that is present and valid, get its status,
|
||||
@ -173,12 +173,12 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
|
||||
* Be sure we can get various info from the battery.
|
||||
*/
|
||||
if (ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 ||
|
||||
ACPI_BATT_GET_INFO(batt_dev, bif) != 0)
|
||||
ACPI_BATT_GET_INFO(batt_dev, bix, sizeof(*bix)) != 0)
|
||||
continue;
|
||||
|
||||
/* If a battery is not installed, we sometimes get strange values. */
|
||||
if (!acpi_battery_bst_valid(&bst[i]) ||
|
||||
!acpi_battery_bif_valid(bif))
|
||||
!acpi_battery_bix_valid(bix))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@ -197,18 +197,18 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
|
||||
* is 0 (due to some error reading the battery), skip this
|
||||
* conversion.
|
||||
*/
|
||||
if (bif->units == ACPI_BIF_UNITS_MA && bif->dvol != 0 && dev == NULL) {
|
||||
bst[i].rate = (bst[i].rate * bif->dvol) / 1000;
|
||||
bst[i].cap = (bst[i].cap * bif->dvol) / 1000;
|
||||
bif->lfcap = (bif->lfcap * bif->dvol) / 1000;
|
||||
if (bix->units == ACPI_BIX_UNITS_MA && bix->dvol != 0 && dev == NULL) {
|
||||
bst[i].rate = (bst[i].rate * bix->dvol) / 1000;
|
||||
bst[i].cap = (bst[i].cap * bix->dvol) / 1000;
|
||||
bix->lfcap = (bix->lfcap * bix->dvol) / 1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* The calculation above may set bif->lfcap to zero. This was
|
||||
* The calculation above may set bix->lfcap to zero. This was
|
||||
* seen on a laptop with a broken battery. The result of the
|
||||
* division was rounded to zero.
|
||||
*/
|
||||
if (!acpi_battery_bif_valid(bif))
|
||||
if (!acpi_battery_bix_valid(bix))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@ -216,16 +216,16 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
|
||||
* "real-capacity" when the battery is fully charged. That breaks
|
||||
* the above arithmetic as it needs to be 100% maximum.
|
||||
*/
|
||||
if (bst[i].cap > bif->lfcap)
|
||||
bst[i].cap = bif->lfcap;
|
||||
if (bst[i].cap > bix->lfcap)
|
||||
bst[i].cap = bix->lfcap;
|
||||
|
||||
/* Calculate percent capacity remaining. */
|
||||
bi[i].cap = (100 * bst[i].cap) / bif->lfcap;
|
||||
bi[i].cap = (100 * bst[i].cap) / bix->lfcap;
|
||||
|
||||
/* If this battery is not present, don't use its capacity. */
|
||||
if (bi[i].cap != -1) {
|
||||
total_cap += bst[i].cap;
|
||||
total_lfcap += bif->lfcap;
|
||||
total_lfcap += bix->lfcap;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -291,12 +291,9 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
if (bi)
|
||||
free(bi, M_TEMP);
|
||||
if (bif)
|
||||
free(bif, M_TEMP);
|
||||
if (bst)
|
||||
free(bst, M_TEMP);
|
||||
free(bi, M_TEMP);
|
||||
free(bix, M_TEMP);
|
||||
free(bst, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -365,7 +362,8 @@ acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
|
||||
unit = 0;
|
||||
dev = NULL;
|
||||
ioctl_arg = NULL;
|
||||
if (IOCPARM_LEN(cmd) == sizeof(*ioctl_arg)) {
|
||||
if (IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg) ||
|
||||
IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg_v1)) {
|
||||
ioctl_arg = (union acpi_battery_ioctl_arg *)addr;
|
||||
unit = ioctl_arg->unit;
|
||||
if (unit != ACPI_BATTERY_ALL_UNITS)
|
||||
@ -376,12 +374,14 @@ acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
|
||||
* No security check required: information retrieval only. If
|
||||
* new functions are added here, a check might be required.
|
||||
*/
|
||||
/* Unit check */
|
||||
switch (cmd) {
|
||||
case ACPIIO_BATT_GET_UNITS:
|
||||
*(int *)addr = acpi_battery_get_units();
|
||||
error = 0;
|
||||
break;
|
||||
case ACPIIO_BATT_GET_BATTINFO:
|
||||
case ACPIIO_BATT_GET_BATTINFO_V1:
|
||||
if (dev != NULL || unit == ACPI_BATTERY_ALL_UNITS) {
|
||||
bzero(&ioctl_arg->battinfo, sizeof(ioctl_arg->battinfo));
|
||||
error = acpi_battery_get_battinfo(dev, &ioctl_arg->battinfo);
|
||||
@ -390,24 +390,19 @@ acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
|
||||
case ACPIIO_BATT_GET_BIF:
|
||||
if (dev != NULL) {
|
||||
bzero(&ioctl_arg->bif, sizeof(ioctl_arg->bif));
|
||||
error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif);
|
||||
|
||||
/*
|
||||
* Remove invalid characters. Perhaps this should be done
|
||||
* within a convenience function so all callers get the
|
||||
* benefit.
|
||||
*/
|
||||
acpi_battery_clean_str(ioctl_arg->bif.model,
|
||||
sizeof(ioctl_arg->bif.model));
|
||||
acpi_battery_clean_str(ioctl_arg->bif.serial,
|
||||
sizeof(ioctl_arg->bif.serial));
|
||||
acpi_battery_clean_str(ioctl_arg->bif.type,
|
||||
sizeof(ioctl_arg->bif.type));
|
||||
acpi_battery_clean_str(ioctl_arg->bif.oeminfo,
|
||||
sizeof(ioctl_arg->bif.oeminfo));
|
||||
error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif,
|
||||
sizeof(ioctl_arg->bif));
|
||||
}
|
||||
break;
|
||||
case ACPIIO_BATT_GET_BIX:
|
||||
if (dev != NULL) {
|
||||
bzero(&ioctl_arg->bix, sizeof(ioctl_arg->bix));
|
||||
error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bix,
|
||||
sizeof(ioctl_arg->bix));
|
||||
}
|
||||
break;
|
||||
case ACPIIO_BATT_GET_BST:
|
||||
case ACPIIO_BATT_GET_BST_V1:
|
||||
if (dev != NULL) {
|
||||
bzero(&ioctl_arg->bst, sizeof(ioctl_arg->bst));
|
||||
error = ACPI_BATT_GET_STATUS(dev, &ioctl_arg->bst);
|
||||
@ -417,6 +412,25 @@ acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
|
||||
error = EINVAL;
|
||||
}
|
||||
|
||||
/* Sanitize the string members. */
|
||||
switch (cmd) {
|
||||
case ACPIIO_BATT_GET_BIX:
|
||||
case ACPIIO_BATT_GET_BIF:
|
||||
/*
|
||||
* Remove invalid characters. Perhaps this should be done
|
||||
* within a convenience function so all callers get the
|
||||
* benefit.
|
||||
*/
|
||||
acpi_battery_clean_str(ioctl_arg->bix.model,
|
||||
sizeof(ioctl_arg->bix.model));
|
||||
acpi_battery_clean_str(ioctl_arg->bix.serial,
|
||||
sizeof(ioctl_arg->bix.serial));
|
||||
acpi_battery_clean_str(ioctl_arg->bix.type,
|
||||
sizeof(ioctl_arg->bix.type));
|
||||
acpi_battery_clean_str(ioctl_arg->bix.oeminfo,
|
||||
sizeof(ioctl_arg->bix.oeminfo));
|
||||
};
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -450,26 +464,29 @@ acpi_battery_init(void)
|
||||
|
||||
ACPI_SERIAL_ASSERT(battery);
|
||||
|
||||
if (acpi_batteries_initialized)
|
||||
return(0);
|
||||
|
||||
error = ENXIO;
|
||||
dev = devclass_get_device(devclass_find("acpi"), 0);
|
||||
if (dev == NULL)
|
||||
goto out;
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl,
|
||||
NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl,
|
||||
NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
error = acpi_register_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
error = acpi_register_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
#define ACPI_REGISTER_IOCTL(a, b, c) do { \
|
||||
error = acpi_register_ioctl(a, b, c); \
|
||||
if (error) \
|
||||
goto out; \
|
||||
} while (0)
|
||||
|
||||
ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, NULL);
|
||||
ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, NULL);
|
||||
ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl, NULL);
|
||||
ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL);
|
||||
ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl, NULL);
|
||||
ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL);
|
||||
ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl, NULL);
|
||||
#undef ACPI_REGISTER_IOCTL
|
||||
|
||||
sysctl_ctx_init(&acpi_battery_sysctl_ctx);
|
||||
acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&acpi_battery_sysctl_ctx,
|
||||
@ -505,14 +522,17 @@ acpi_battery_init(void)
|
||||
&acpi_battery_info_expire, 0,
|
||||
"time in seconds until info is refreshed");
|
||||
|
||||
acpi_batteries_initted = TRUE;
|
||||
acpi_batteries_initialized = TRUE;
|
||||
|
||||
out:
|
||||
if (error != 0) {
|
||||
if (error) {
|
||||
acpi_deregister_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl);
|
||||
acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl);
|
||||
acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl);
|
||||
acpi_deregister_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl);
|
||||
acpi_deregister_ioctl(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl);
|
||||
acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl);
|
||||
acpi_deregister_ioctl(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
@ -61,12 +61,13 @@ ACPI_MODULE_NAME("BATTERY")
|
||||
|
||||
#define ACPI_BATTERY_BST_CHANGE 0x80
|
||||
#define ACPI_BATTERY_BIF_CHANGE 0x81
|
||||
#define ACPI_BATTERY_BIX_CHANGE ACPI_BATTERY_BIF_CHANGE
|
||||
|
||||
struct acpi_cmbat_softc {
|
||||
device_t dev;
|
||||
int flags;
|
||||
|
||||
struct acpi_bif bif;
|
||||
struct acpi_bix bix;
|
||||
struct acpi_bst bst;
|
||||
struct timespec bst_lastupdated;
|
||||
};
|
||||
@ -82,10 +83,10 @@ static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify,
|
||||
static int acpi_cmbat_info_expired(struct timespec *lastupdated);
|
||||
static void acpi_cmbat_info_updated(struct timespec *lastupdated);
|
||||
static void acpi_cmbat_get_bst(void *arg);
|
||||
static void acpi_cmbat_get_bif_task(void *arg);
|
||||
static void acpi_cmbat_get_bif(void *arg);
|
||||
static int acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp);
|
||||
static int acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp);
|
||||
static void acpi_cmbat_get_bix_task(void *arg);
|
||||
static void acpi_cmbat_get_bix(void *arg);
|
||||
static int acpi_cmbat_bst(device_t, struct acpi_bst *);
|
||||
static int acpi_cmbat_bix(device_t, void *, size_t);
|
||||
static void acpi_cmbat_init_battery(void *arg);
|
||||
|
||||
static device_method_t acpi_cmbat_methods[] = {
|
||||
@ -96,7 +97,7 @@ static device_method_t acpi_cmbat_methods[] = {
|
||||
DEVMETHOD(device_resume, acpi_cmbat_resume),
|
||||
|
||||
/* ACPI battery interface */
|
||||
DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif),
|
||||
DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bix),
|
||||
DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst),
|
||||
|
||||
DEVMETHOD_END
|
||||
@ -205,12 +206,12 @@ acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
|
||||
timespecclear(&sc->bst_lastupdated);
|
||||
break;
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
case ACPI_BATTERY_BIF_CHANGE:
|
||||
case ACPI_BATTERY_BIX_CHANGE:
|
||||
/*
|
||||
* Queue a callback to get the current battery info from thread
|
||||
* context. It's not safe to block in a notify handler.
|
||||
*/
|
||||
AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev);
|
||||
AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bix_task, dev);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -269,15 +270,15 @@ acpi_cmbat_get_bst(void *arg)
|
||||
as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer);
|
||||
if (ACPI_FAILURE(as)) {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"error fetching current battery status -- %s\n",
|
||||
AcpiFormatException(as));
|
||||
"error fetching current battery status -- %s\n",
|
||||
AcpiFormatException(as));
|
||||
goto end;
|
||||
}
|
||||
|
||||
res = (ACPI_OBJECT *)bst_buffer.Pointer;
|
||||
if (!ACPI_PKG_VALID(res, 4)) {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"battery status corrupted\n");
|
||||
"battery status corrupted\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -307,119 +308,194 @@ acpi_cmbat_get_bst(void *arg)
|
||||
sc->flags &= ~ACPI_BATT_STAT_CRITICAL;
|
||||
|
||||
end:
|
||||
if (bst_buffer.Pointer != NULL)
|
||||
AcpiOsFree(bst_buffer.Pointer);
|
||||
AcpiOsFree(bst_buffer.Pointer);
|
||||
}
|
||||
|
||||
/* XXX There should be a cleaner way to do this locking. */
|
||||
static void
|
||||
acpi_cmbat_get_bif_task(void *arg)
|
||||
acpi_cmbat_get_bix_task(void *arg)
|
||||
{
|
||||
|
||||
ACPI_SERIAL_BEGIN(cmbat);
|
||||
acpi_cmbat_get_bif(arg);
|
||||
acpi_cmbat_get_bix(arg);
|
||||
ACPI_SERIAL_END(cmbat);
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_cmbat_get_bif(void *arg)
|
||||
acpi_cmbat_get_bix(void *arg)
|
||||
{
|
||||
struct acpi_cmbat_softc *sc;
|
||||
ACPI_STATUS as;
|
||||
ACPI_OBJECT *res;
|
||||
ACPI_HANDLE h;
|
||||
ACPI_BUFFER bif_buffer;
|
||||
ACPI_BUFFER bix_buffer;
|
||||
device_t dev;
|
||||
int i, n;
|
||||
const struct {
|
||||
enum { _BIX, _BIF } type;
|
||||
char *name;
|
||||
} bobjs[] = {
|
||||
{ _BIX, "_BIX"},
|
||||
{ _BIF, "_BIF"},
|
||||
};
|
||||
|
||||
ACPI_SERIAL_ASSERT(cmbat);
|
||||
|
||||
dev = arg;
|
||||
sc = device_get_softc(dev);
|
||||
h = acpi_get_handle(dev);
|
||||
bif_buffer.Pointer = NULL;
|
||||
bif_buffer.Length = ACPI_ALLOCATE_BUFFER;
|
||||
bix_buffer.Pointer = NULL;
|
||||
bix_buffer.Length = ACPI_ALLOCATE_BUFFER;
|
||||
|
||||
as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer);
|
||||
if (ACPI_FAILURE(as)) {
|
||||
for (n = 0; n < sizeof(bobjs); n++) {
|
||||
as = AcpiEvaluateObject(h, bobjs[n].name, NULL, &bix_buffer);
|
||||
if (!ACPI_FAILURE(as)) {
|
||||
res = (ACPI_OBJECT *)bix_buffer.Pointer;
|
||||
break;
|
||||
}
|
||||
AcpiOsFree(bix_buffer.Pointer);
|
||||
bix_buffer.Pointer = NULL;
|
||||
bix_buffer.Length = ACPI_ALLOCATE_BUFFER;
|
||||
}
|
||||
/* Both _BIF and _BIX were not found. */
|
||||
if (n == sizeof(bobjs)) {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"error fetching current battery info -- %s\n",
|
||||
AcpiFormatException(as));
|
||||
"error fetching current battery info -- %s\n",
|
||||
AcpiFormatException(as));
|
||||
goto end;
|
||||
}
|
||||
|
||||
res = (ACPI_OBJECT *)bif_buffer.Pointer;
|
||||
if (!ACPI_PKG_VALID(res, 13)) {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"battery info corrupted\n");
|
||||
goto end;
|
||||
/*
|
||||
* ACPI _BIX and _BIF revision mismatch check:
|
||||
*
|
||||
* 1. _BIF has no revision field. The number of fields must be 13.
|
||||
*
|
||||
* 2. _BIX has a revision field. As of ACPI 6.3 it must be "0" or
|
||||
* "1". The number of fields will be checked---20 and 21,
|
||||
* respectively.
|
||||
*
|
||||
* If the revision number is grater than "1" and the number of
|
||||
* fields is grater than 21, it will be treated as compatible with
|
||||
* ACPI 6.0 _BIX. If not, it will be ignored.
|
||||
*/
|
||||
i = 0;
|
||||
switch (bobjs[n].type) {
|
||||
case _BIX:
|
||||
if (acpi_PkgInt16(res, i++, &sc->bix.rev) != 0) {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"_BIX revision error\n");
|
||||
goto end;
|
||||
}
|
||||
#define ACPI_BIX_REV_MISMATCH_ERR(x, r) do { \
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \
|
||||
"_BIX revision mismatch (%u != %u)\n", x, r); \
|
||||
goto end; \
|
||||
} while (0)
|
||||
|
||||
if (ACPI_PKG_VALID_EQ(res, 21)) { /* ACPI 6.0 _BIX */
|
||||
if (sc->bix.rev != ACPI_BIX_REV_1)
|
||||
ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_1);
|
||||
} else if (ACPI_PKG_VALID_EQ(res, 20)) {/* ACPI 4.0 _BIX */
|
||||
if (sc->bix.rev != ACPI_BIX_REV_0)
|
||||
ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_0);
|
||||
} else if (ACPI_PKG_VALID(res, 22) &&
|
||||
ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1 + 1)) {
|
||||
/*
|
||||
* Unknown _BIX with 22 or more members.
|
||||
* Assume 21 members are compatible with 6.0 _BIX.
|
||||
*/
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"Unknown _BIX revision(%u). "
|
||||
"Assuming compatible with revision %u.\n",
|
||||
sc->bix.rev, ACPI_BIX_REV_1);
|
||||
} else {
|
||||
/* Invalid _BIX. Ignore it. */
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"Invalid _BIX found (rev=%u, count=%u). Ignored.\n",
|
||||
sc->bix.rev, res->Package.Count);
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
#undef ACPI_BIX_REV_MISMATCH_ERR
|
||||
case _BIF:
|
||||
if (ACPI_PKG_VALID_EQ(res, 13)) /* _BIF */
|
||||
sc->bix.rev = ACPI_BIX_REV_BIF;
|
||||
else {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"Invalid _BIF found (count=%u). Ignored.\n",
|
||||
res->Package.Count);
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgStr(res, 9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"rev = %04x\n", sc->bix.rev);
|
||||
#define BIX_GETU32(NAME) do { \
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \
|
||||
#NAME " = %u\n", sc->bix.NAME); \
|
||||
if (acpi_PkgInt32(res, i++, &sc->bix.NAME) != 0) \
|
||||
goto end; \
|
||||
} while (0)
|
||||
|
||||
BIX_GETU32(units);
|
||||
BIX_GETU32(dcap);
|
||||
BIX_GETU32(lfcap);
|
||||
BIX_GETU32(btech);
|
||||
BIX_GETU32(dvol);
|
||||
BIX_GETU32(wcap);
|
||||
BIX_GETU32(lcap);
|
||||
if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_0)) {
|
||||
BIX_GETU32(cycles);
|
||||
BIX_GETU32(accuracy);
|
||||
BIX_GETU32(stmax);
|
||||
BIX_GETU32(stmin);
|
||||
BIX_GETU32(aimax);
|
||||
BIX_GETU32(aimin);
|
||||
}
|
||||
BIX_GETU32(gra1);
|
||||
BIX_GETU32(gra2);
|
||||
if (acpi_PkgStr(res, i++, sc->bix.model, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgStr(res, i++, sc->bix.serial, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgStr(res, i++, sc->bix.type, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
if (acpi_PkgStr(res, i++, sc->bix.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0)
|
||||
goto end;
|
||||
if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1))
|
||||
BIX_GETU32(scap);
|
||||
#undef BIX_GETU32
|
||||
end:
|
||||
if (bif_buffer.Pointer != NULL)
|
||||
AcpiOsFree(bif_buffer.Pointer);
|
||||
AcpiOsFree(bix_buffer.Pointer);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp)
|
||||
acpi_cmbat_bix(device_t dev, void *bix, size_t len)
|
||||
{
|
||||
struct acpi_cmbat_softc *sc;
|
||||
|
||||
if (len != sizeof(struct acpi_bix) &&
|
||||
len != sizeof(struct acpi_bif))
|
||||
return (-1);
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/*
|
||||
* Just copy the data. The only value that should change is the
|
||||
* last-full capacity, so we only update when we get a notify that says
|
||||
* the info has changed. Many systems apparently take a long time to
|
||||
* process a _BIF call so we avoid it if possible.
|
||||
* process a _BI[FX] call so we avoid it if possible.
|
||||
*/
|
||||
ACPI_SERIAL_BEGIN(cmbat);
|
||||
bifp->units = sc->bif.units;
|
||||
bifp->dcap = sc->bif.dcap;
|
||||
bifp->lfcap = sc->bif.lfcap;
|
||||
bifp->btech = sc->bif.btech;
|
||||
bifp->dvol = sc->bif.dvol;
|
||||
bifp->wcap = sc->bif.wcap;
|
||||
bifp->lcap = sc->bif.lcap;
|
||||
bifp->gra1 = sc->bif.gra1;
|
||||
bifp->gra2 = sc->bif.gra2;
|
||||
strncpy(bifp->model, sc->bif.model, sizeof(sc->bif.model));
|
||||
strncpy(bifp->serial, sc->bif.serial, sizeof(sc->bif.serial));
|
||||
strncpy(bifp->type, sc->bif.type, sizeof(sc->bif.type));
|
||||
strncpy(bifp->oeminfo, sc->bif.oeminfo, sizeof(sc->bif.oeminfo));
|
||||
memcpy(bix, &sc->bix, len);
|
||||
ACPI_SERIAL_END(cmbat);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp)
|
||||
acpi_cmbat_bst(device_t dev, struct acpi_bst *bst)
|
||||
{
|
||||
struct acpi_cmbat_softc *sc;
|
||||
|
||||
@ -428,12 +504,9 @@ acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp)
|
||||
ACPI_SERIAL_BEGIN(cmbat);
|
||||
if (acpi_BatteryIsPresent(dev)) {
|
||||
acpi_cmbat_get_bst(dev);
|
||||
bstp->state = sc->bst.state;
|
||||
bstp->rate = sc->bst.rate;
|
||||
bstp->cap = sc->bst.cap;
|
||||
bstp->volt = sc->bst.volt;
|
||||
memcpy(bst, &sc->bst, sizeof(*bst));
|
||||
} else
|
||||
bstp->state = ACPI_BATT_STAT_NOT_PRESENT;
|
||||
bst->state = ACPI_BATT_STAT_NOT_PRESENT;
|
||||
ACPI_SERIAL_END(cmbat);
|
||||
|
||||
return (0);
|
||||
@ -448,7 +521,7 @@ acpi_cmbat_init_battery(void *arg)
|
||||
|
||||
dev = (device_t)arg;
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"battery initialization start\n");
|
||||
"battery enitialization start\n");
|
||||
|
||||
/*
|
||||
* Try repeatedly to get valid data from the battery. Since the
|
||||
@ -487,11 +560,11 @@ acpi_cmbat_init_battery(void *arg)
|
||||
timespecclear(&sc->bst_lastupdated);
|
||||
acpi_cmbat_get_bst(dev);
|
||||
}
|
||||
if (retry == 0 || !acpi_battery_bif_valid(&sc->bif))
|
||||
acpi_cmbat_get_bif(dev);
|
||||
if (retry == 0 || !acpi_battery_bix_valid(&sc->bix))
|
||||
acpi_cmbat_get_bix(dev);
|
||||
|
||||
valid = acpi_battery_bst_valid(&sc->bst) &&
|
||||
acpi_battery_bif_valid(&sc->bif);
|
||||
acpi_battery_bix_valid(&sc->bix);
|
||||
ACPI_SERIAL_END(cmbat);
|
||||
|
||||
if (valid)
|
||||
@ -500,9 +573,9 @@ acpi_cmbat_init_battery(void *arg)
|
||||
|
||||
if (retry == ACPI_CMBAT_RETRY_MAX) {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"battery initialization failed, giving up\n");
|
||||
"battery initialization failed, giving up\n");
|
||||
} else {
|
||||
ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
|
||||
"battery initialization done, tried %d times\n", retry + 1);
|
||||
"battery initialization done, tried %d times\n", retry + 1);
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ HEADER {
|
||||
typedef ACPI_STATUS (*acpi_scan_cb_t)(ACPI_HANDLE h, device_t *dev,
|
||||
int level, void *arg);
|
||||
|
||||
struct acpi_bix;
|
||||
struct acpi_bif;
|
||||
struct acpi_bst;
|
||||
};
|
||||
@ -210,14 +211,16 @@ METHOD int ec_write {
|
||||
};
|
||||
|
||||
#
|
||||
# Get battery information (_BIF format)
|
||||
# Get battery information (_BIF or _BIX format)
|
||||
#
|
||||
# device_t dev: Battery device
|
||||
# struct acpi_bif *bif: Pointer to storage for _BIF results
|
||||
# void *bix: Pointer to storage for _BIF or _BIX results
|
||||
# size_t len: length of acpi_bif or acpi_bix.
|
||||
#
|
||||
METHOD int batt_get_info {
|
||||
device_t dev;
|
||||
struct acpi_bif *bif;
|
||||
void *bix;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
#
|
||||
|
@ -70,6 +70,19 @@ acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst)
|
||||
{
|
||||
UINT64 tmp;
|
||||
int error;
|
||||
|
||||
error = acpi_PkgInt(res, idx, &tmp);
|
||||
if (error == 0)
|
||||
*dst = (uint16_t)tmp;
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size)
|
||||
{
|
||||
|
@ -46,9 +46,9 @@ struct acpi_smbat_softc {
|
||||
uint8_t sb_base_addr;
|
||||
device_t ec_dev;
|
||||
|
||||
struct acpi_bif bif;
|
||||
struct acpi_bix bix;
|
||||
struct acpi_bst bst;
|
||||
struct timespec bif_lastupdated;
|
||||
struct timespec bix_lastupdated;
|
||||
struct timespec bst_lastupdated;
|
||||
};
|
||||
|
||||
@ -57,7 +57,7 @@ static int acpi_smbat_attach(device_t dev);
|
||||
static int acpi_smbat_shutdown(device_t dev);
|
||||
static int acpi_smbat_info_expired(struct timespec *lastupdated);
|
||||
static void acpi_smbat_info_updated(struct timespec *lastupdated);
|
||||
static int acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif);
|
||||
static int acpi_smbat_get_bix(device_t dev, void *, size_t);
|
||||
static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst);
|
||||
|
||||
ACPI_SERIAL_DECL(smbat, "ACPI Smart Battery");
|
||||
@ -87,7 +87,7 @@ static device_method_t acpi_smbat_methods[] = {
|
||||
|
||||
/* ACPI battery interface */
|
||||
DEVMETHOD(acpi_batt_get_status, acpi_smbat_get_bst),
|
||||
DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bif),
|
||||
DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bix),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
@ -141,7 +141,7 @@ acpi_smbat_attach(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
timespecclear(&sc->bif_lastupdated);
|
||||
timespecclear(&sc->bix_lastupdated);
|
||||
timespecclear(&sc->bst_lastupdated);
|
||||
|
||||
if (acpi_battery_register(dev) != 0) {
|
||||
@ -415,7 +415,7 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif)
|
||||
acpi_smbat_get_bix(device_t dev, void *bix, size_t len)
|
||||
{
|
||||
struct acpi_smbat_softc *sc;
|
||||
int error;
|
||||
@ -423,70 +423,76 @@ acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif)
|
||||
uint16_t val;
|
||||
uint8_t addr;
|
||||
|
||||
if (len != sizeof(struct acpi_bix) &&
|
||||
len != sizeof(struct acpi_bif))
|
||||
return (-1);
|
||||
|
||||
ACPI_SERIAL_BEGIN(smbat);
|
||||
|
||||
addr = SMBATT_ADDRESS;
|
||||
error = ENXIO;
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (!acpi_smbat_info_expired(&sc->bif_lastupdated)) {
|
||||
if (!acpi_smbat_info_expired(&sc->bix_lastupdated)) {
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sc->bix.rev = ACPI_BIX_REV_BIF;
|
||||
|
||||
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val))
|
||||
goto out;
|
||||
if (val & SMBATT_BM_CAPACITY_MODE) {
|
||||
factor = 10;
|
||||
sc->bif.units = ACPI_BIF_UNITS_MW;
|
||||
sc->bix.units = ACPI_BIX_UNITS_MW;
|
||||
} else {
|
||||
factor = 1;
|
||||
sc->bif.units = ACPI_BIF_UNITS_MA;
|
||||
sc->bix.units = ACPI_BIX_UNITS_MA;
|
||||
}
|
||||
|
||||
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_CAPACITY, &val))
|
||||
goto out;
|
||||
sc->bif.dcap = val * factor;
|
||||
sc->bix.dcap = val * factor;
|
||||
|
||||
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_FULL_CHARGE_CAPACITY, &val))
|
||||
goto out;
|
||||
sc->bif.lfcap = val * factor;
|
||||
sc->bif.btech = 1; /* secondary (rechargeable) */
|
||||
sc->bix.lfcap = val * factor;
|
||||
sc->bix.btech = 1; /* secondary (rechargeable) */
|
||||
|
||||
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_VOLTAGE, &val))
|
||||
goto out;
|
||||
sc->bif.dvol = val;
|
||||
sc->bix.dvol = val;
|
||||
|
||||
sc->bif.wcap = sc->bif.dcap / 10;
|
||||
sc->bif.lcap = sc->bif.dcap / 10;
|
||||
sc->bix.wcap = sc->bix.dcap / 10;
|
||||
sc->bix.lcap = sc->bix.dcap / 10;
|
||||
|
||||
sc->bif.gra1 = factor; /* not supported */
|
||||
sc->bif.gra2 = factor; /* not supported */
|
||||
sc->bix.gra1 = factor; /* not supported */
|
||||
sc->bix.gra2 = factor; /* not supported */
|
||||
|
||||
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_NAME,
|
||||
sc->bif.model, sizeof(sc->bif.model)))
|
||||
sc->bix.model, sizeof(sc->bix.model)))
|
||||
goto out;
|
||||
|
||||
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_SERIAL_NUMBER, &val))
|
||||
goto out;
|
||||
snprintf(sc->bif.serial, sizeof(sc->bif.serial), "0x%04x", val);
|
||||
snprintf(sc->bix.serial, sizeof(sc->bix.serial), "0x%04x", val);
|
||||
|
||||
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_CHEMISTRY,
|
||||
sc->bif.type, sizeof(sc->bif.type)))
|
||||
sc->bix.type, sizeof(sc->bix.type)))
|
||||
goto out;
|
||||
|
||||
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_MANUFACTURER_DATA,
|
||||
sc->bif.oeminfo, sizeof(sc->bif.oeminfo)))
|
||||
sc->bix.oeminfo, sizeof(sc->bix.oeminfo)))
|
||||
goto out;
|
||||
|
||||
/* XXX check if device was replugged during read? */
|
||||
|
||||
acpi_smbat_info_updated(&sc->bif_lastupdated);
|
||||
acpi_smbat_info_updated(&sc->bix_lastupdated);
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
if (error == 0)
|
||||
memcpy(bif, &sc->bif, sizeof(sc->bif));
|
||||
memcpy(bix, &sc->bix, len);
|
||||
ACPI_SERIAL_END(smbat);
|
||||
return (error);
|
||||
}
|
||||
|
@ -48,9 +48,13 @@ struct acpi_battinfo {
|
||||
int rate; /* emptying rate */
|
||||
};
|
||||
|
||||
/*
|
||||
* Battery Information object. Note that this object is deprecated in
|
||||
* ACPI 4.0
|
||||
*/
|
||||
#define ACPI_CMBAT_MAXSTRLEN 32
|
||||
struct acpi_bif {
|
||||
uint32_t units; /* Units (mW or mA). */
|
||||
uint32_t units; /* Power Unit (mW or mA). */
|
||||
#define ACPI_BIF_UNITS_MW 0 /* Capacity in mWh, rate in mW. */
|
||||
#define ACPI_BIF_UNITS_MA 1 /* Capacity in mAh, rate in mA. */
|
||||
uint32_t dcap; /* Design Capacity */
|
||||
@ -67,6 +71,76 @@ struct acpi_bif {
|
||||
char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */
|
||||
};
|
||||
|
||||
/*
|
||||
* Members in acpi_bix are reordered so that the first part is compatible
|
||||
* with acpi_bif.
|
||||
*/
|
||||
struct acpi_bix {
|
||||
/* _BIF-compatible */
|
||||
uint32_t units; /* Power Unit (mW or mA). */
|
||||
#define ACPI_BIX_UNITS_MW 0 /* Capacity in mWh, rate in mW. */
|
||||
#define ACPI_BIX_UNITS_MA 1 /* Capacity in mAh, rate in mA. */
|
||||
uint32_t dcap; /* Design Capacity */
|
||||
uint32_t lfcap; /* Last Full capacity */
|
||||
uint32_t btech; /* Battery Technology */
|
||||
uint32_t dvol; /* Design voltage (mV) */
|
||||
uint32_t wcap; /* WARN capacity */
|
||||
uint32_t lcap; /* Low capacity */
|
||||
uint32_t gra1; /* Granularity 1 (Warn to Low) */
|
||||
uint32_t gra2; /* Granularity 2 (Full to Warn) */
|
||||
char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */
|
||||
char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */
|
||||
char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */
|
||||
char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */
|
||||
/* ACPI 4.0 or later */
|
||||
uint16_t rev; /* Revision */
|
||||
#define ACPI_BIX_REV_0 0 /* ACPI 4.0 _BIX */
|
||||
#define ACPI_BIX_REV_1 1 /* ACPI 6.0 _BIX */
|
||||
#define ACPI_BIX_REV_BIF 0xffff /* _BIF */
|
||||
#define ACPI_BIX_REV_MIN_CHECK(x, min) \
|
||||
(((min) == ACPI_BIX_REV_BIF) ? ((x) == ACPI_BIX_REV_BIF) : \
|
||||
(((x) == ACPI_BIX_REV_BIF) ? 0 : ((x) >= (min))))
|
||||
uint32_t cycles; /* Cycle Count */
|
||||
uint32_t accuracy; /* Measurement Accuracy */
|
||||
uint32_t stmax; /* Max Sampling Time */
|
||||
uint32_t stmin; /* Min Sampling Time */
|
||||
uint32_t aimax; /* Max Average Interval */
|
||||
uint32_t aimin; /* Min Average Interval */
|
||||
/* ACPI 6.0 or later */
|
||||
uint32_t scap; /* Battery Swapping Capability */
|
||||
#define ACPI_BIX_SCAP_NO 0x00000000
|
||||
#define ACPI_BIX_SCAP_COLD 0x00000001
|
||||
#define ACPI_BIX_SCAP_HOT 0x00000010
|
||||
uint8_t bix_reserved[58]; /* padding */
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* acpi_bix in the original order just for reference */
|
||||
struct acpi_bix {
|
||||
uint16_t rev; /* Revision */
|
||||
uint32_t units; /* Power Unit (mW or mA). */
|
||||
uint32_t dcap; /* Design Capacity */
|
||||
uint32_t lfcap; /* Last Full capacity */
|
||||
uint32_t btech; /* Battery Technology */
|
||||
uint32_t dvol; /* Design voltage (mV) */
|
||||
uint32_t wcap; /* Design Capacity of Warning */
|
||||
uint32_t lcap; /* Design Capacity of Low */
|
||||
uint32_t cycles; /* Cycle Count */
|
||||
uint32_t accuracy; /* Measurement Accuracy */
|
||||
uint32_t stmax; /* Max Sampling Time */
|
||||
uint32_t stmin; /* Min Sampling Time */
|
||||
uint32_t aimax; /* Max Average Interval */
|
||||
uint32_t aimin; /* Min Average Interval */
|
||||
uint32_t gra1; /* Granularity 1 (Warn to Low) */
|
||||
uint32_t gra2; /* Granularity 2 (Full to Warn) */
|
||||
char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */
|
||||
char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */
|
||||
char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */
|
||||
char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */
|
||||
uint32_t scap; /* Battery Swapping Capability */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct acpi_bst {
|
||||
uint32_t state; /* Battery State */
|
||||
uint32_t rate; /* Present Rate */
|
||||
@ -91,7 +165,8 @@ struct acpi_bst {
|
||||
(ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL)
|
||||
#define ACPI_BATT_STAT_NOT_PRESENT ACPI_BATT_STAT_BST_MASK
|
||||
|
||||
union acpi_battery_ioctl_arg {
|
||||
/* For backward compatibility */
|
||||
union acpi_battery_ioctl_arg_v1 {
|
||||
int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */
|
||||
|
||||
struct acpi_battinfo battinfo;
|
||||
@ -99,15 +174,27 @@ union acpi_battery_ioctl_arg {
|
||||
struct acpi_bif bif;
|
||||
struct acpi_bst bst;
|
||||
};
|
||||
union acpi_battery_ioctl_arg {
|
||||
int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */
|
||||
|
||||
struct acpi_battinfo battinfo;
|
||||
|
||||
struct acpi_bix bix;
|
||||
struct acpi_bif bif;
|
||||
struct acpi_bst bst;
|
||||
};
|
||||
|
||||
#define ACPI_BATTERY_ALL_UNITS (-1)
|
||||
#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BIF value unknown. */
|
||||
#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BI[FX] value unknown. */
|
||||
|
||||
/* Common battery ioctls */
|
||||
#define ACPIIO_BATT_GET_UNITS _IOR('B', 0x01, int)
|
||||
#define ACPIIO_BATT_GET_BATTINFO _IOWR('B', 0x03, union acpi_battery_ioctl_arg)
|
||||
#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg)
|
||||
#define ACPIIO_BATT_GET_BATTINFO_V1 _IOWR('B', 0x03, union acpi_battery_ioctl_arg_v1)
|
||||
#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg_v1)
|
||||
#define ACPIIO_BATT_GET_BIX _IOWR('B', 0x10, union acpi_battery_ioctl_arg)
|
||||
#define ACPIIO_BATT_GET_BST _IOWR('B', 0x11, union acpi_battery_ioctl_arg)
|
||||
#define ACPIIO_BATT_GET_BST_V1 _IOWR('B', 0x11, union acpi_battery_ioctl_arg_v1)
|
||||
|
||||
/* Control Method battery ioctls (deprecated) */
|
||||
#define ACPIIO_CMBAT_GET_BIF ACPIIO_BATT_GET_BIF
|
||||
|
@ -479,7 +479,7 @@ int acpi_battery_remove(device_t dev);
|
||||
int acpi_battery_get_units(void);
|
||||
int acpi_battery_get_info_expire(void);
|
||||
int acpi_battery_bst_valid(struct acpi_bst *bst);
|
||||
int acpi_battery_bif_valid(struct acpi_bif *bif);
|
||||
int acpi_battery_bix_valid(struct acpi_bix *bix);
|
||||
int acpi_battery_get_battinfo(device_t dev,
|
||||
struct acpi_battinfo *info);
|
||||
|
||||
@ -493,8 +493,12 @@ int acpi_acad_get_acline(int *);
|
||||
#define ACPI_PKG_VALID(pkg, size) \
|
||||
((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \
|
||||
(pkg)->Package.Count >= (size))
|
||||
#define ACPI_PKG_VALID_EQ(pkg, size) \
|
||||
((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \
|
||||
(pkg)->Package.Count == (size))
|
||||
int acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst);
|
||||
int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst);
|
||||
int acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst);
|
||||
int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size);
|
||||
int acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type,
|
||||
int *rid, struct resource **dst, u_int flags);
|
||||
|
@ -96,34 +96,61 @@ acpi_battinfo(int num)
|
||||
|
||||
/* Print battery design information. */
|
||||
battio.unit = num;
|
||||
if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1)
|
||||
if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) == -1)
|
||||
err(EX_IOERR, "get battery info (%d) failed", num);
|
||||
amp = battio.bif.units;
|
||||
amp = battio.bix.units;
|
||||
pwr_units = amp ? "mA" : "mW";
|
||||
if (battio.bif.dcap == UNKNOWN_CAP)
|
||||
if (battio.bix.dcap == UNKNOWN_CAP)
|
||||
printf("Design capacity:\tunknown\n");
|
||||
else
|
||||
printf("Design capacity:\t%d %sh\n", battio.bif.dcap,
|
||||
printf("Design capacity:\t%d %sh\n", battio.bix.dcap,
|
||||
pwr_units);
|
||||
if (battio.bif.lfcap == UNKNOWN_CAP)
|
||||
if (battio.bix.lfcap == UNKNOWN_CAP)
|
||||
printf("Last full capacity:\tunknown\n");
|
||||
else
|
||||
printf("Last full capacity:\t%d %sh\n", battio.bif.lfcap,
|
||||
printf("Last full capacity:\t%d %sh\n", battio.bix.lfcap,
|
||||
pwr_units);
|
||||
printf("Technology:\t\t%s\n", battio.bif.btech == 0 ?
|
||||
printf("Technology:\t\t%s\n", battio.bix.btech == 0 ?
|
||||
"primary (non-rechargeable)" : "secondary (rechargeable)");
|
||||
if (battio.bif.dvol == UNKNOWN_CAP)
|
||||
if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_1)) {
|
||||
printf("Battery Swappable Capability:\t");
|
||||
if (battio.bix.scap == ACPI_BIX_SCAP_NO)
|
||||
printf("Non-swappable\n");
|
||||
else if (battio.bix.scap == ACPI_BIX_SCAP_COLD)
|
||||
printf("cold swap\n");
|
||||
else if (battio.bix.scap == ACPI_BIX_SCAP_HOT)
|
||||
printf("hot swap\n");
|
||||
else
|
||||
printf("unknown\n");
|
||||
}
|
||||
if (battio.bix.dvol == UNKNOWN_CAP)
|
||||
printf("Design voltage:\t\tunknown\n");
|
||||
else
|
||||
printf("Design voltage:\t\t%d mV\n", battio.bif.dvol);
|
||||
printf("Capacity (warn):\t%d %sh\n", battio.bif.wcap, pwr_units);
|
||||
printf("Capacity (low):\t\t%d %sh\n", battio.bif.lcap, pwr_units);
|
||||
printf("Low/warn granularity:\t%d %sh\n", battio.bif.gra1, pwr_units);
|
||||
printf("Warn/full granularity:\t%d %sh\n", battio.bif.gra2, pwr_units);
|
||||
printf("Model number:\t\t%s\n", battio.bif.model);
|
||||
printf("Serial number:\t\t%s\n", battio.bif.serial);
|
||||
printf("Type:\t\t\t%s\n", battio.bif.type);
|
||||
printf("OEM info:\t\t%s\n", battio.bif.oeminfo);
|
||||
printf("Design voltage:\t\t%d mV\n", battio.bix.dvol);
|
||||
printf("Capacity (warn):\t%d %sh\n", battio.bix.wcap, pwr_units);
|
||||
printf("Capacity (low):\t\t%d %sh\n", battio.bix.lcap, pwr_units);
|
||||
if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_0)) {
|
||||
if (battio.bix.cycles != ACPI_BATT_UNKNOWN)
|
||||
printf("Cycle Count:\t\t%d\n", battio.bix.cycles);
|
||||
printf("Mesurement Accuracy:\t%d %%\n",
|
||||
battio.bix.accuracy / 1000);
|
||||
if (battio.bix.stmax != ACPI_BATT_UNKNOWN)
|
||||
printf("Max Sampling Time:\t%d ms\n",
|
||||
battio.bix.stmax);
|
||||
if (battio.bix.stmin != ACPI_BATT_UNKNOWN)
|
||||
printf("Min Sampling Time:\t%d ms\n",
|
||||
battio.bix.stmin);
|
||||
printf("Max Average Interval:\t%d ms\n",
|
||||
battio.bix.aimax);
|
||||
printf("Min Average Interval:\t%d ms\n",
|
||||
battio.bix.aimin);
|
||||
}
|
||||
printf("Low/warn granularity:\t%d %sh\n", battio.bix.gra1, pwr_units);
|
||||
printf("Warn/full granularity:\t%d %sh\n", battio.bix.gra2, pwr_units);
|
||||
printf("Model number:\t\t%s\n", battio.bix.model);
|
||||
printf("Serial number:\t\t%s\n", battio.bix.serial);
|
||||
printf("Type:\t\t\t%s\n", battio.bix.type);
|
||||
printf("OEM info:\t\t%s\n", battio.bix.oeminfo);
|
||||
|
||||
/* Fetch battery voltage information. */
|
||||
volt = UNKNOWN_VOLTAGE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user