pwmfan.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * <one line to give the library's name and an idea of what it does.>
  3. * Copyright 2015 Malte Veerman maldela@halloarsch.de
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License or (at your option) version 3 or any later version
  9. * accepted by the membership of KDE e.V. (or its successor approved
  10. * by the membership of KDE e.V.), which shall act as a proxy
  11. * defined in Section 14 of version 3 of the license.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "pwmfan.h"
  23. #include "hwmon.h"
  24. #include <QtCore/QTextStream>
  25. #include <QtCore/QTimer>
  26. #include <QtCore/QDir>
  27. #include <QtCore/QFile>
  28. #include <QtCore/QDebug>
  29. #include <KConfigCore/KConfigGroup>
  30. #include <KConfigCore/KSharedConfig>
  31. #include <KAuth/KAuthExecuteJob>
  32. #define MAX_ERRORS_FOR_RPM_ZERO 10
  33. PwmFan::PwmFan(Hwmon *parent, uint index) : Fan(parent, index),
  34. m_pwmStream(new QTextStream),
  35. m_modeStream(new QTextStream),
  36. m_temp(Q_NULLPTR),
  37. m_hasTemp(false),
  38. m_minTemp(0),
  39. m_maxTemp(100),
  40. m_minPwm(255),
  41. m_maxPwm(255),
  42. m_minStart(255),
  43. m_minStop(255),
  44. m_zeroRpm(0),
  45. m_testStatus(NotStarted)
  46. {
  47. connect(this, SIGNAL(tempChanged()), parent, SLOT(updateConfig()));
  48. connect(this, SIGNAL(hasTempChanged()), parent, SLOT(updateConfig()));
  49. connect(this, SIGNAL(minTempChanged()), parent, SLOT(updateConfig()));
  50. connect(this, SIGNAL(maxTempChanged()), parent, SLOT(updateConfig()));
  51. connect(this, SIGNAL(minPwmChanged()), parent, SLOT(updateConfig()));
  52. connect(this, SIGNAL(maxPwmChanged()), parent, SLOT(updateConfig()));
  53. connect(this, SIGNAL(minStartChanged()), parent, SLOT(updateConfig()));
  54. connect(this, SIGNAL(minStopChanged()), parent, SLOT(updateConfig()));
  55. if (QDir(parent->path()).isReadable())
  56. {
  57. QFile *pwmFile = new QFile(parent->path() + "/pwm" + QString::number(index), this);
  58. if (pwmFile->open(QFile::ReadWrite))
  59. {
  60. m_pwmStream->setDevice(pwmFile);
  61. *m_pwmStream >> m_pwm;
  62. }
  63. else if (pwmFile->open(QFile::ReadOnly))
  64. {
  65. m_pwmStream->setDevice(pwmFile);
  66. *m_pwmStream >> m_pwm;
  67. }
  68. else
  69. qDebug() << "Can't open pwmFile " << pwmFile->fileName();
  70. QFile *pwmModeFile = new QFile(parent->path() + "/pwm" + QString::number(index) + "_mode", this);
  71. if (pwmModeFile->open(QFile::ReadWrite))
  72. {
  73. m_modeStream->setDevice(pwmModeFile);
  74. *m_modeStream >> m_pwmMode;
  75. }
  76. else if (pwmModeFile->open(QFile::ReadOnly))
  77. {
  78. m_modeStream->setDevice(pwmModeFile);
  79. *m_modeStream >> m_pwmMode;
  80. }
  81. else
  82. qDebug() << "Can't open pwmModeFile " << pwmModeFile->fileName();
  83. }
  84. }
  85. PwmFan::~PwmFan()
  86. {
  87. delete m_pwmStream;
  88. delete m_modeStream;
  89. }
  90. void PwmFan::update()
  91. {
  92. Fan::update();
  93. m_pwmStream->seek(0);
  94. setPwm(m_pwmStream->readAll().toInt(), false);
  95. m_modeStream->seek(0);
  96. setPwmMode(m_modeStream->readAll().toInt(), false);
  97. }
  98. void PwmFan::reset()
  99. {
  100. Fan::reset();
  101. QIODevice *oldFile = m_pwmStream->device();
  102. delete m_pwmStream;
  103. delete oldFile;
  104. oldFile = m_modeStream->device();
  105. delete m_modeStream;
  106. delete oldFile;
  107. QFile *pwmFile = new QFile(m_parent->path() + "/pwm" + QString::number(m_index), this);
  108. if (pwmFile->open(QFile::ReadWrite))
  109. {
  110. m_pwmStream = new QTextStream(pwmFile);
  111. *m_pwmStream >> m_pwm;
  112. }
  113. else if (pwmFile->open(QFile::ReadOnly))
  114. {
  115. m_pwmStream = new QTextStream(pwmFile);
  116. *m_pwmStream >> m_pwm;
  117. }
  118. else
  119. qDebug() << "Can't open pwmFile " << pwmFile->fileName();
  120. QFile *pwmModeFile = new QFile(m_parent->path() + "/pwm" + QString::number(m_index) + "_mode", this);
  121. if (pwmModeFile->open(QFile::ReadWrite))
  122. {
  123. m_modeStream = new QTextStream(pwmModeFile);
  124. *m_modeStream >> m_pwmMode;
  125. }
  126. else if (pwmModeFile->open(QFile::ReadOnly))
  127. {
  128. m_modeStream = new QTextStream(pwmModeFile);
  129. *m_modeStream >> m_pwmMode;
  130. }
  131. else
  132. qDebug() << "Can't open pwmModeFile " << pwmModeFile->fileName();
  133. }
  134. bool PwmFan::setPwm(int pwm, bool write)
  135. {
  136. if (m_pwm != pwm)
  137. {
  138. m_pwm = pwm;
  139. emit pwmChanged();
  140. if (write)
  141. {
  142. if (m_pwmStream->device()->isWritable())
  143. *m_pwmStream << pwm;
  144. else
  145. {
  146. KAuth::Action action("fancontrol.gui.helper.action");
  147. action.setHelperId("fancontrol.gui.helper");
  148. if (!action.isValid())
  149. {
  150. qDebug() << "setPwm action is invalid";
  151. return false;
  152. }
  153. QVariantMap map;
  154. map["action"] = "write";
  155. map["filename"] = qobject_cast<QFile *>(m_pwmStream->device())->fileName();
  156. map["content"] = QString::number(pwm);
  157. action.setArguments(map);
  158. KAuth::ExecuteJob *reply = action.execute();
  159. if (!reply->exec())
  160. {
  161. qDebug() << "setPwm error:" << reply->errorString() << reply->errorText();
  162. return false;
  163. }
  164. }
  165. }
  166. }
  167. return true;
  168. }
  169. bool PwmFan::setPwmMode(int pwmMode, bool write)
  170. {
  171. if (m_pwmMode != pwmMode)
  172. {
  173. m_pwmMode = pwmMode;
  174. emit pwmModeChanged();
  175. if (write)
  176. {
  177. if (m_modeStream->device()->isWritable())
  178. *m_modeStream << pwmMode;
  179. else
  180. {
  181. KAuth::Action action("fancontrol.gui.helper.action");
  182. action.setHelperId("fancontrol.gui.helper");
  183. if (!action.isValid())
  184. {
  185. qDebug() << "setPwmMode action is invalid";
  186. return false;
  187. }
  188. QVariantMap map;
  189. map["action"] = "write";
  190. map["filename"] = qobject_cast<QFile *>(m_modeStream->device())->fileName();
  191. map["content"] = QString::number(pwmMode);
  192. action.setArguments(map);
  193. KAuth::ExecuteJob *reply = action.execute();
  194. if (!reply->exec())
  195. {
  196. qDebug() << "setPwmMode error:" << reply->errorString() << reply->errorText();
  197. return false;
  198. }
  199. }
  200. }
  201. }
  202. return true;
  203. }
  204. bool PwmFan::test()
  205. {
  206. if (setPwmMode(1) && setPwm(255))
  207. {
  208. m_testStatus = FindingStop1;
  209. emit testingChanged();
  210. QTimer::singleShot(500, this, SLOT(continueTest()));
  211. qDebug() << "Start testing...";
  212. }
  213. else
  214. {
  215. qDebug() << "Testing failed";
  216. return false;
  217. }
  218. return true;
  219. }
  220. void PwmFan::abortTest()
  221. {
  222. setPwm(255);
  223. disconnect(0, 0, this, SLOT(continueTest()));
  224. m_testStatus = Cancelled;
  225. emit testingChanged();
  226. setPwm(255);
  227. }
  228. void PwmFan::continueTest()
  229. {
  230. update();
  231. switch (m_testStatus)
  232. {
  233. case FindingStop1:
  234. if (m_rpm > 0)
  235. {
  236. setPwm(qMin(m_pwm * 0.95, m_pwm - 5.0));
  237. m_zeroRpm = 0;
  238. }
  239. else
  240. {
  241. if (m_zeroRpm < MAX_ERRORS_FOR_RPM_ZERO)
  242. {
  243. m_zeroRpm++;
  244. }
  245. else
  246. {
  247. m_testStatus = FindingStart;
  248. m_zeroRpm = 0;
  249. qDebug() << "Start finding start value...";
  250. }
  251. }
  252. QTimer::singleShot(500, this, SLOT(continueTest()));
  253. break;
  254. case FindingStart:
  255. if (m_rpm == 0)
  256. setPwm(m_pwm + 2);
  257. else
  258. {
  259. m_testStatus = FindingStop2;
  260. setMinStart(m_pwm);
  261. qDebug() << "Start finding stop value...";
  262. }
  263. QTimer::singleShot(1000, this, SLOT(continueTest()));
  264. break;
  265. case FindingStop2:
  266. if (m_rpm > 0)
  267. {
  268. setPwm(m_pwm - 1);
  269. m_zeroRpm = 0;
  270. QTimer::singleShot(1000, this, SLOT(continueTest()));
  271. }
  272. else
  273. {
  274. if (m_zeroRpm < MAX_ERRORS_FOR_RPM_ZERO)
  275. {
  276. m_zeroRpm++;
  277. QTimer::singleShot(500, this, SLOT(continueTest()));
  278. }
  279. else
  280. {
  281. m_testStatus = Finished;
  282. emit testingChanged();
  283. m_zeroRpm = 0;
  284. setMinStop(m_pwm + 5);
  285. qDebug() << "Finished testing!";
  286. }
  287. }
  288. break;
  289. default:
  290. break;
  291. }
  292. }
  293. bool PwmFan::testing() const
  294. {
  295. return m_testStatus == FindingStop1 || m_testStatus == FindingStop2 || m_testStatus == FindingStart;
  296. }
  297. bool PwmFan::active() const
  298. {
  299. KConfigGroup active = KSharedConfig::openConfig("fancontrol-gui")->group("active");
  300. KConfigGroup localActive = active.group(m_parent->name());
  301. return localActive.readEntry("pwmfan" + QString::number(m_index), true);
  302. }
  303. void PwmFan::setActive(bool a)
  304. {
  305. KConfigGroup active = KSharedConfig::openConfig("fancontrol-gui")->group("active");
  306. KConfigGroup localActive = active.group(m_parent->name());
  307. if (a != localActive.readEntry("pwmfan" + QString::number(m_index), true))
  308. {
  309. localActive.writeEntry("pwmfan" + QString::number(m_index), a);
  310. emit activeChanged();
  311. }
  312. }