static int acpi_capm_get_info(apm_info_t aip) { int acline; struct acpi_battinfo batt; aip->ai_infoversion = 1; aip->ai_major = 1; aip->ai_minor = 2; aip->ai_status = apm_softc.active; aip->ai_capabilities= 0xff00; /* XXX unknown */ if (acpi_acad_get_acline(&acline)) aip->ai_acline = 0xff; /* unknown */ else aip->ai_acline = acline; /* on/off */ if (acpi_battery_get_battinfo(NULL, &batt)) { aip->ai_batt_stat = 0xff; /* unknown */ aip->ai_batt_life = 0xff; /* unknown */ aip->ai_batt_time = -1; /* unknown */ aip->ai_batteries = 0; } else { aip->ai_batt_stat = acpi_capm_convert_battstate(&batt); aip->ai_batt_life = batt.cap; aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60; aip->ai_batteries = acpi_battery_get_units(); } return (0); }
static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS) { int count, error; count = acpi_battery_get_units(); error = sysctl_handle_int(oidp, &count, 0, req); return (error); }
static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg) { union acpi_battery_ioctl_arg *ioctl_arg; int error, unit; device_t dev; /* For commands that use the ioctl_arg struct, validate it first. */ error = ENXIO; unit = 0; dev = NULL; ioctl_arg = NULL; if (IOCPARM_LEN(cmd) == sizeof(*ioctl_arg)) { ioctl_arg = (union acpi_battery_ioctl_arg *)addr; unit = ioctl_arg->unit; if (unit != ACPI_BATTERY_ALL_UNITS) dev = acpi_battery_find_dev(unit); } /* * No security check required: information retrieval only. If * new functions are added here, a check might be required. */ switch (cmd) { case ACPIIO_BATT_GET_UNITS: *(int *)addr = acpi_battery_get_units(); error = 0; break; case ACPIIO_BATT_GET_BATTINFO: 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); } break; 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)); } break; case ACPIIO_BATT_GET_BST: if (dev != NULL) { bzero(&ioctl_arg->bst, sizeof(ioctl_arg->bst)); error = ACPI_BATT_GET_STATUS(dev, &ioctl_arg->bst); } break; default: error = EINVAL; } return (error); }
static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg) { union acpi_battery_ioctl_arg *ioctl_arg; int error, unit; device_t dev; /* * Giant is acquired to work around a reference counting bug in ACPICA * versions prior to 20130328. If not for that bug this function could * be executed concurrently without any problems. * The bug is in acpi_BatteryIsPresent -> AcpiGetObjectInfo call tree, * where AcpiUtExecute_HID, AcpiUtExecute_UID, etc are executed without * protection of any ACPICA lock and may concurrently call * AcpiUtRemoveReference on a battery object. */ mtx_lock(&Giant); /* For commands that use the ioctl_arg struct, validate it first. */ error = ENXIO; unit = 0; dev = NULL; ioctl_arg = NULL; if (IOCPARM_LEN(cmd) == sizeof(*ioctl_arg)) { ioctl_arg = (union acpi_battery_ioctl_arg *)addr; unit = ioctl_arg->unit; if (unit != ACPI_BATTERY_ALL_UNITS) dev = acpi_battery_find_dev(unit); } /* * No security check required: information retrieval only. If * new functions are added here, a check might be required. */ switch (cmd) { case ACPIIO_BATT_GET_UNITS: *(int *)addr = acpi_battery_get_units(); error = 0; break; case ACPIIO_BATT_GET_BATTINFO: 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); } break; 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)); } break; case ACPIIO_BATT_GET_BST: if (dev != NULL) { bzero(&ioctl_arg->bst, sizeof(ioctl_arg->bst)); error = ACPI_BATT_GET_STATUS(dev, &ioctl_arg->bst); } break; default: error = EINVAL; } mtx_unlock(&Giant); return (error); }