acpi_battery: support for _BIX method.

change int types to uint32, as it's more correct.

Change-Id: Iae7043abe4c8b8a121548fe6d6a809f1bd879c8a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2334
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Jérôme Duval
2020-03-10 13:14:09 +00:00
committed by waddlesplash
parent 4f732f12a1
commit 1b16a232eb
2 changed files with 171 additions and 107 deletions
+37 -17
View File
@@ -31,29 +31,49 @@ const uint32 kMagicACPIBatteryID = 17822;
#define BATTERY_CHARGING 0x02
#define BATTERY_CRITICAL_STATE 0x04
#define BATTERY_MAX_STRING_LENGTH 32
typedef struct {
int state;
int current_rate;
int capacity;
int voltage;
uint32 state;
uint32 current_rate;
uint32 capacity;
uint32 voltage;
} acpi_battery_info;
typedef struct {
int power_unit;
int design_capacity;
int last_full_charge;
int technology;
int design_voltage;
int design_capacity_warning;
int design_capacity_low;
int capacity_granularity_1;
int capacity_granularity_2;
char model_number[32];
char serial_number[32];
char type[32];
char oem_info[32];
uint32 power_unit;
#define ACPI_BATTERY_UNIT_MW 0
#define ACPI_BATTERY_UNIT_MA 1
uint32 design_capacity;
uint32 last_full_charge;
uint32 technology;
uint32 design_voltage;
uint32 design_capacity_warning;
uint32 design_capacity_low;
uint32 capacity_granularity_1;
uint32 capacity_granularity_2;
char model_number[BATTERY_MAX_STRING_LENGTH];
char serial_number[BATTERY_MAX_STRING_LENGTH];
char type[BATTERY_MAX_STRING_LENGTH];
char oem_info[BATTERY_MAX_STRING_LENGTH];
// ACPI 4.0 and later
uint16 revision;
#define ACPI_BATTERY_REVISION_0 0
#define ACPI_BATTERY_REVISION_1 1
#define ACPI_BATTERY_REVISION_BIF 0xffff
uint32 cycles;
uint32 accuracy;
uint32 max_sampling_time;
uint32 min_sampling_time;
uint32 max_average_interval;
uint32 min_average_interval;
// ACPI 6.0 and later
uint32 swapping_capability;
#define ACPI_BATTERY_SWAPPING_NO 0
#define ACPI_BATTERY_SWAPPING_COLD 1
#define ACPI_BATTERY_SWAPPING_HOT 2
} acpi_extended_battery_info;
@@ -48,20 +48,38 @@ struct battery_device_cookie {
//#define TRACE_BATTERY
#ifdef TRACE_BATTERY
# define TRACE(x...) dprintf("acpi_battery: "x)
# define TRACE(x...) dprintf("acpi_battery: " x)
#else
# define TRACE(x...)
#endif
#define ERROR(x...) dprintf("acpi_battery: " x)
static device_manager_info *sDeviceManager;
static ConditionVariable sBatteryCondition;
inline uint32
GetUint32(acpi_object_type* pointer)
{
return (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : UINT32_MAX;
}
inline void
GetString(char* buffer, size_t length, acpi_object_type* pointer)
{
strlcpy(buffer, (pointer->object_type == ACPI_TYPE_STRING)
? pointer->string.string : "", length);
}
status_t
ReadBatteryStatus(battery_driver_cookie* cookie,
acpi_battery_info* batteryStatus)
{
TRACE("ReadBatteryStatus\n");
status_t status = B_ERROR;
acpi_data buffer;
@@ -84,27 +102,19 @@ ReadBatteryStatus(battery_driver_cookie* cookie,
}
pointer = object->package.objects;
batteryStatus->state = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : BATTERY_CRITICAL_STATE;
pointer++;
batteryStatus->current_rate = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
pointer++;
batteryStatus->capacity = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
pointer++;
batteryStatus->voltage = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
batteryStatus->state = GetUint32(pointer++);
if (batteryStatus->state == UINT32_MAX)
batteryStatus->state = BATTERY_CRITICAL_STATE;
batteryStatus->current_rate = GetUint32(pointer++);
batteryStatus->capacity = GetUint32(pointer++);
batteryStatus->voltage = GetUint32(pointer++);
/* If key values are all < 0, it is likely that the battery slot is empty
* or the battery is damaged. Set BATTERY_CRITICAL_STATE
*/
if (batteryStatus->voltage < 0
&& batteryStatus->current_rate < 0
&& batteryStatus->capacity < 0) {
if (batteryStatus->voltage == UINT32_MAX
&& batteryStatus->current_rate == UINT32_MAX
&& batteryStatus->capacity == UINT32_MAX) {
batteryStatus->state = BATTERY_CRITICAL_STATE;
}
@@ -119,6 +129,7 @@ status_t
ReadBatteryInfo(battery_driver_cookie* cookie,
acpi_extended_battery_info* batteryInfo)
{
TRACE("ReadBatteryInfo\n");
acpi_data buffer;
buffer.pointer = NULL;
buffer.length = ACPI_ALLOCATE_BUFFER;
@@ -126,76 +137,77 @@ ReadBatteryInfo(battery_driver_cookie* cookie,
acpi_object_type* object;
acpi_object_type* pointer;
bool isBIF = false;
status_t status = cookie->acpi->evaluate_method(cookie->acpi_cookie,
"_BIF", NULL, &buffer);
if (status != B_OK)
goto exit;
"_BIX", NULL, &buffer);
if (status != B_OK) {
isBIF = true;
free(buffer.pointer);
buffer.pointer = NULL;
buffer.length = ACPI_ALLOCATE_BUFFER;
status = cookie->acpi->evaluate_method(cookie->acpi_cookie,
"_BIF", NULL, &buffer);
if (status != B_OK)
goto exit;
}
object = (acpi_object_type*)buffer.pointer;
TRACE("ReadBatteryInfo %d %u\n", object->object_type,
object->package.count);
if (object->object_type != ACPI_TYPE_PACKAGE
|| object->package.count < 13) {
|| (isBIF && object->package.count < 13)) {
status = B_ERROR;
goto exit;
}
pointer = object->package.objects;
batteryInfo->power_unit = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
if (isBIF) {
batteryInfo->revision = ACPI_BATTERY_REVISION_BIF;
} else {
batteryInfo->revision = GetUint32(pointer++);
TRACE("ReadBatteryInfo revision %u\n", batteryInfo->revision);
pointer++;
batteryInfo->design_capacity = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
if (batteryInfo->revision == ACPI_BATTERY_REVISION_0) {
if (object->package.count < 20) {
status = B_ERROR;
goto exit;
}
} else if (object->package.count < 21) {
status = B_ERROR;
goto exit;
}
pointer++;
batteryInfo->last_full_charge = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
}
batteryInfo->power_unit = GetUint32(pointer++);
batteryInfo->design_capacity = GetUint32(pointer++);
batteryInfo->last_full_charge = GetUint32(pointer++);
batteryInfo->technology = GetUint32(pointer++);
batteryInfo->design_voltage = GetUint32(pointer++);
batteryInfo->design_capacity_warning = GetUint32(pointer++);
batteryInfo->design_capacity_low = GetUint32(pointer++);
pointer++;
batteryInfo->technology = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
if (batteryInfo->revision != ACPI_BATTERY_REVISION_BIF) {
batteryInfo->cycles = GetUint32(pointer++);
batteryInfo->accuracy = GetUint32(pointer++);
batteryInfo->max_sampling_time = GetUint32(pointer++);
batteryInfo->min_sampling_time = GetUint32(pointer++);
batteryInfo->max_average_interval = GetUint32(pointer++);
batteryInfo->min_average_interval = GetUint32(pointer++);
}
pointer++;
batteryInfo->design_voltage = (pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
pointer++;
batteryInfo->design_capacity_warning =
(pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
pointer++;
batteryInfo->design_capacity_low =
(pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
pointer++;
batteryInfo->capacity_granularity_1 =
(pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
pointer++;
batteryInfo->capacity_granularity_2 =
(pointer->object_type == ACPI_TYPE_INTEGER)
? pointer->integer.integer : -1;
pointer++;
strlcpy(batteryInfo->model_number,
(pointer->object_type == ACPI_TYPE_STRING)
? pointer->string.string : "", sizeof(batteryInfo->model_number));
pointer++;
strlcpy(batteryInfo->serial_number,
(pointer->object_type == ACPI_TYPE_STRING)
? pointer->string.string : "", sizeof(batteryInfo->serial_number));
pointer++;
strlcpy(batteryInfo->type, (pointer->object_type == ACPI_TYPE_STRING)
? pointer->string.string : "", sizeof(batteryInfo->type));
pointer++;
strlcpy(batteryInfo->oem_info, (pointer->object_type == ACPI_TYPE_STRING)
? pointer->string.string : "", sizeof(batteryInfo->oem_info));
batteryInfo->capacity_granularity_1 = GetUint32(pointer++);
batteryInfo->capacity_granularity_2 = GetUint32(pointer++);
GetString(batteryInfo->model_number, sizeof(batteryInfo->model_number),
pointer++);
GetString(batteryInfo->serial_number, sizeof(batteryInfo->serial_number),
pointer++);
GetString(batteryInfo->type, sizeof(batteryInfo->type), pointer++);
GetString(batteryInfo->oem_info, sizeof(batteryInfo->oem_info), pointer++);
if (batteryInfo->revision != ACPI_BATTERY_REVISION_BIF
&& batteryInfo->revision >= ACPI_BATTERY_REVISION_1) {
batteryInfo->swapping_capability = GetUint32(pointer++);
}
exit:
free(buffer.pointer);
return status;
@@ -255,14 +267,32 @@ TraceBatteryInfo(acpi_extended_battery_info* batteryInfo)
TRACE("BIF last full charge %i\n", batteryInfo->last_full_charge);
TRACE("BIF technology %i\n", batteryInfo->technology);
TRACE("BIF design voltage %i\n", batteryInfo->design_voltage);
TRACE("BIF design capacity warning %i\n", batteryInfo->design_capacity_warning);
TRACE("BIF design capacity warning %i\n",
batteryInfo->design_capacity_warning);
TRACE("BIF design capacity low %i\n", batteryInfo->design_capacity_low);
TRACE("BIF capacity granularity 1 %i\n", batteryInfo->capacity_granularity_1);
TRACE("BIF capacity granularity 2 %i\n", batteryInfo->capacity_granularity_2);
TRACE("BIF capacity granularity 1 %i\n",
batteryInfo->capacity_granularity_1);
TRACE("BIF capacity granularity 2 %i\n",
batteryInfo->capacity_granularity_2);
if (batteryInfo->revision != ACPI_BATTERY_REVISION_BIF) {
TRACE("BIX cycles %i\n", batteryInfo->cycles);
TRACE("BIX accuracy %i\n", batteryInfo->accuracy);
TRACE("BIX max_sampling_time %i\n", batteryInfo->max_sampling_time);
TRACE("BIX min_sampling_time %i\n", batteryInfo->min_sampling_time);
TRACE("BIX max_average_interval %i\n",
batteryInfo->max_average_interval);
TRACE("BIX min_average_interval %i\n",
batteryInfo->min_average_interval);
}
TRACE("BIF model number %s\n", batteryInfo->model_number);
TRACE("BIF serial number %s\n", batteryInfo->serial_number);
TRACE("BIF type %s\n", batteryInfo->type);
TRACE("BIF oem info %s\n", batteryInfo->oem_info);
if (batteryInfo->revision != ACPI_BATTERY_REVISION_BIF
&& batteryInfo->revision >= ACPI_BATTERY_REVISION_1) {
TRACE("BIX swapping_capability %i\n",
batteryInfo->swapping_capability);
}
}
@@ -330,8 +360,9 @@ acpi_battery_read(void* _cookie, off_t position, void *buffer, size_t* numBytes)
max_len -= strlen(str);
str += strlen(str);
snprintf(str, max_len, " State %i, Current Rate %i, Capacity %i, "
"Voltage %i\n", batteryStatus.state, batteryStatus.current_rate,
snprintf(str, max_len, " State %" B_PRIu32 ", Current Rate %" B_PRIu32
", Capacity %" B_PRIu32 ", Voltage %" B_PRIu32 "\n",
batteryStatus.state, batteryStatus.current_rate,
batteryStatus.capacity, batteryStatus.voltage);
max_len -= strlen(str);
str += strlen(str);
@@ -340,17 +371,20 @@ acpi_battery_read(void* _cookie, off_t position, void *buffer, size_t* numBytes)
max_len -= strlen(str);
str += strlen(str);
snprintf(str, max_len, " Power Unit %i, Design Capacity %i, "
"Last Full Charge %i, Technology %i\n", batteryInfo.power_unit,
batteryInfo.design_capacity, batteryInfo.last_full_charge,
batteryInfo.technology);
snprintf(str, max_len, " Power Unit %" B_PRIu32 ", Design Capacity %"
B_PRIu32 ", Last Full Charge %" B_PRIu32 ", Technology %" B_PRIu32
"\n", batteryInfo.power_unit, batteryInfo.design_capacity,
batteryInfo.last_full_charge, batteryInfo.technology);
max_len -= strlen(str);
str += strlen(str);
snprintf(str, max_len, " Design Voltage %i, Design Capacity Warning %i, "
"Design Capacity Low %i, Capacity Granularity1 %i, "
"Capacity Granularity1 %i\n", batteryInfo.design_voltage,
batteryInfo.design_capacity_warning, batteryInfo.design_capacity_low,
batteryInfo.capacity_granularity_1, batteryInfo.capacity_granularity_1);
snprintf(str, max_len, " Design Voltage %" B_PRIu32 ", Design Capacity"
" Warning %" B_PRIu32 ", Design Capacity Low %" B_PRIu32 ", "
"Capacity Granularity1 %" B_PRIu32 ", Capacity Granularity2 %"
B_PRIu32 "\n", batteryInfo.design_voltage,
batteryInfo.design_capacity_warning,
batteryInfo.design_capacity_low,
batteryInfo.capacity_granularity_1,
batteryInfo.capacity_granularity_2);
max_len -= strlen(str);
str += strlen(str);
snprintf(str, max_len, " Model Number %s, Serial Number %s, "
@@ -371,7 +405,8 @@ acpi_battery_read(void* _cookie, off_t position, void *buffer, size_t* numBytes)
static status_t
acpi_battery_write(void* cookie, off_t position, const void* buffer, size_t* numBytes)
acpi_battery_write(void* cookie, off_t position, const void* buffer,
size_t* numBytes)
{
return B_ERROR;
}
@@ -517,6 +552,15 @@ acpi_battery_init_driver(device_node *node, void **driverCookie)
parent = sDeviceManager->get_parent_node(node);
sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
(void **)&device->acpi_cookie);
#ifdef TRACE_BATTERY
const char* device_path;
if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_PATH_ITEM,
&device_path, false) == B_OK) {
TRACE("acpi_battery_init_driver %s\n", device_path);
}
#endif
sDeviceManager->put_node(parent);
// install notify handler
@@ -547,7 +591,7 @@ acpi_battery_register_child_devices(void *cookie)
int pathID = sDeviceManager->create_id(ACPI_BATTERY_PATHID_GENERATOR);
if (pathID < 0) {
TRACE("register_child_devices: couldn't create a path_id\n");
ERROR("register_child_devices: couldn't create a path_id\n");
return B_ERROR;
}