Files
haiku-beta6/src/preferences/cpufrequency/DriverInterface.cpp
T
Axel Dörfler 40890e97b3 * Committed Clemens Zeidler's Intel speedstep driver. Thanks a lot, Clemens!
This is a very welcome addition.
* There are a few issues, and maybe questionable decisions (like the dependence
  on ACPI), but I see no reason why it shouldn't be added in its current form
  already.
* Unfortunately, I could not test it yet, though, as the CPU of my laptop is
  not supported; will see if I can find a supported hardware, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28903 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-01-14 21:08:37 +00:00

218 lines
3.9 KiB
C++

/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, [email protected]
*/
#include "DriverInterface.h"
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <Path.h>
#define DRIVER_DIR "/dev/power"
CPUFreqDriverInterface::CPUFreqDriverInterface()
: fInitOK(false),
fDriverHandler(-1),
fIsWatching(false),
fWatchingMessenger(NULL)
{
fFrequencyStates = new StateList(20, true);
if (_FindSpeedStepDriver(DRIVER_DIR) == B_OK)
fInitOK = true;
status_t ret;
freq_info states[MAX_CPU_FREQUENCY_STATES];
ret = ioctl(fDriverHandler, GET_CPU_FREQ_STATES, &states,
sizeof(freq_info) * MAX_CPU_FREQUENCY_STATES);
if (ret != B_OK)
return;
for (int i = 0; i < MAX_CPU_FREQUENCY_STATES && states[i].frequency != 0;
i++) {
fFrequencyStates->AddItem(new freq_info(states[i]));
}
}
CPUFreqDriverInterface::~CPUFreqDriverInterface()
{
delete fFrequencyStates;
if (InitCheck() == B_OK)
close(fDriverHandler);
}
status_t
CPUFreqDriverInterface::InitCheck()
{
if (fInitOK)
return B_OK;
return B_ERROR;
}
StateList*
CPUFreqDriverInterface::GetCpuFrequencyStates()
{
return fFrequencyStates;
}
freq_info*
CPUFreqDriverInterface::GetCurrentFrequencyState()
{
uint16 stateId = 0;
status_t ret;
ret = ioctl(fDriverHandler, GET_CURENT_CPU_FREQ_STATE, &stateId,
sizeof(uint16));
if (ret != B_OK)
return NULL;
int32 i = 0;
while (true) {
freq_info* state = fFrequencyStates->ItemAt(i);
if (!state)
break;
i++;
if (state->id == stateId)
return state;
}
return NULL;
}
int32
CPUFreqDriverInterface::GetNumberOfFrequencyStates()
{
return fFrequencyStates->CountItems();
}
status_t
CPUFreqDriverInterface::SetFrequencyState(const freq_info* state)
{
status_t ret;
ret = ioctl(fDriverHandler, SET_CPU_FREQ_STATE, &(state->id),
sizeof(uint16));
return ret;
}
status_t
CPUFreqDriverInterface::StartWatching(BHandler* target)
{
if (fIsWatching)
return B_ERROR;
if (fWatchingMessenger)
delete fWatchingMessenger;
fWatchingMessenger = new BMessenger(target);
status_t status = B_ERROR;
fThreadId = spawn_thread(&_ThreadWatchFreqFunction, "FreqThread",
B_LOW_PRIORITY, this);
if (fThreadId >= 0)
status = resume_thread(fThreadId);
else
return fThreadId;
if (status == B_OK) {
fIsWatching = true;
return B_OK;
}
return status;
}
status_t
CPUFreqDriverInterface::StopWatching()
{
if (fIsWatching &&
ioctl(fDriverHandler, STOP_WATCHING_CPU_FREQ) == B_OK)
{
delete fWatchingMessenger;
fWatchingMessenger = NULL;
fIsWatching = false;
status_t status;
return wait_for_thread(fThreadId, &status);
}
return B_ERROR;
}
int32
CPUFreqDriverInterface::_ThreadWatchFreqFunction(void* data)
{
CPUFreqDriverInterface* that = (CPUFreqDriverInterface*)data;
that->_WatchFrequency();
return 0;
}
void
CPUFreqDriverInterface::_WatchFrequency()
{
uint16 newId = 0;
while (ioctl(fDriverHandler, WATCH_CPU_FREQ, &newId,
sizeof(uint16)) == B_OK)
{
int i = 0;
while (true) {
freq_info* state = fFrequencyStates->ItemAt(i);
if (!state)
break;
i++;
if (state->id == newId) {
BMessage msg(kMSGFrequencyChanged);
msg.AddPointer("freq_info", state);
fWatchingMessenger->SendMessage(&msg);
break;
}
}
}
}
status_t
CPUFreqDriverInterface::_FindSpeedStepDriver(const char* path)
{
BDirectory dir(path);
BEntry entry;
while (dir.GetNextEntry(&entry) == B_OK) {
BPath path;
entry.GetPath(&path);
if (entry.IsDirectory()) {
if (_FindSpeedStepDriver(path.Path()) == B_OK)
return B_OK;
}
else {
printf("path %s\n", path.Path());
fDriverHandler = open(path.Path(), O_RDWR);
if (fDriverHandler >= 0) {
uint32 magicId = 0;
status_t ret;
ret = ioctl(fDriverHandler, IDENTIFY_DEVICE, &magicId,
sizeof(uint32));
if (ret == B_OK && magicId == kMagicFreqID)
return B_OK;
}
}
}
return B_ERROR;
}