1 /* 2 * Copyright 2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Clemens Zeidler, haiku@clemens-zeidler.de 7 */ 8 9 10 #include "APMDriverInterface.h" 11 12 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 13 # include <arch/x86/apm_defs.h> 14 # include <generic_syscall_defs.h> 15 # include <syscalls.h> 16 // temporary, as long as there is no real power state API 17 #endif 18 19 20 const bigtime_t kUpdateInterval = 2000000; 21 // every two seconds 22 23 24 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 25 // definitions for the APM driver available for BeOS 26 enum { 27 APM_CONTROL = B_DEVICE_OP_CODES_END + 1, 28 APM_DUMP_POWER_STATUS, 29 APM_BIOS_CALL, 30 APM_SET_SAFETY 31 }; 32 33 #define BIOS_APM_GET_POWER_STATUS 0x530a 34 #endif 35 36 37 APMDriverInterface::~APMDriverInterface() 38 { 39 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 40 close(fDevice); 41 #endif 42 } 43 44 45 status_t 46 APMDriverInterface::Connect() 47 { 48 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 49 uint32 version = 0; 50 status_t status = _kern_generic_syscall(APM_SYSCALLS, B_SYSCALL_INFO, 51 &version, sizeof(version)); 52 if (status == B_OK) { 53 battery_info info; 54 status = _kern_generic_syscall(APM_SYSCALLS, APM_GET_BATTERY_INFO, 55 &info, sizeof(battery_info)); 56 } 57 58 return status; 59 60 #else 61 fDevice = open("/dev/misc/apm", O_RDONLY); 62 if (fDevice < 0) { 63 return B_ERROR; 64 } 65 66 return B_OK; 67 #endif 68 } 69 70 71 status_t 72 APMDriverInterface::GetBatteryInfo(battery_info* info, int32 index) 73 { 74 if (index != 0) 75 return B_BAD_VALUE; 76 77 info->current_rate = -1; 78 79 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 80 // TODO: retrieve data from APM kernel interface 81 apm_battery_info apmInfo; 82 status_t status = _kern_generic_syscall(APM_SYSCALLS, APM_GET_BATTERY_INFO, 83 &apmInfo, sizeof(apm_battery_info)); 84 if (status == B_OK) { 85 info->state = apmInfo.online ? BATTERY_CHARGING : BATTERY_DISCHARGING; 86 info->capacity = apmInfo.percent; 87 info->full_capacity = 100; 88 info->time_left = apmInfo.time_left; 89 } 90 91 return status; 92 #else 93 if (fDevice < 0) 94 return B_ERROR; 95 96 uint16 regs[6] = {0, 0, 0, 0, 0, 0}; 97 regs[0] = BIOS_APM_GET_POWER_STATUS; 98 regs[1] = 0x1; 99 if (ioctl(fDevice, APM_BIOS_CALL, regs) == 0) { 100 bool online = (regs[1] >> 8) != 0 && (regs[1] >> 8) != 2; 101 info->state = online ? BATTERY_CHARGING : BATTERY_DISCHARGING; 102 info->capacity = regs[2] & 255; 103 if (info->capacity > 100) 104 info->capacity = -1; 105 info->full_capacity = 100; 106 info->time_left = info->capacity >= 0 ? regs[3] : -1; 107 if (info->time_left > 0xffff) 108 info->time_left = -1; 109 else if (info->time_left & 0x8000) 110 info->time_left = (info->time_left & 0x7fff) * 60; 111 } 112 113 return B_OK; 114 #endif 115 } 116 117 118 status_t 119 APMDriverInterface::GetExtendedBatteryInfo(acpi_extended_battery_info* info, 120 int32 index) 121 { 122 return B_ERROR; 123 } 124 125 126 int32 127 APMDriverInterface::GetBatteryCount() 128 { 129 return 1; 130 } 131 132 133 void 134 APMDriverInterface::_WatchPowerStatus() 135 { 136 while (atomic_get(&fIsWatching) > 0) { 137 Broadcast(kMsgUpdate); 138 acquire_sem_etc(fWaitSem, 1, B_RELATIVE_TIMEOUT, kUpdateInterval); 139 } 140 } 141 142