1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/***************************************************************************
* Copyright (C) 2006 by Valentine Sinitsyn *
* [email protected] *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "cpufreqdconnection.h"
#include <qdir.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
/* Excerpt from cpufreqd_remote.h (cpufreqd-2.0.0)
*
* Copyright (C) 2005 Mattia Dongili <[email protected]>
* Hrvoje Zeba <[email protected]>
*
* Format:
* it is an uint32_t used as bitmask
*
* 31-16 15-0
* <command> <arguments>
*
* The response may be longer than a single line and is
* terminated by the RESPONSE_END (see defines).
*/
#define CMD_SHIFT 16
#define ARG_MASK 0x0000ffff
#define REMOTE_CMD(c) (c >> CMD_SHIFT)
#define REMOTE_ARG(c) (c & ARG_MASK)
#define MAKE_COMMAND(cmd, arg) ((cmd << CMD_SHIFT) | arg)
#define INVALID_CMD 0xffffffff
/**
* This class encapsulates cpufreqd connection performed via Unix sockets
*@author: Valentine Sinitsyn ([email protected])
*/
CPUFreqdConnection::CPUFreqdConnection(): m_fd(-1) {
lookup();
}
CPUFreqdConnection::~CPUFreqdConnection() {
}
bool CPUFreqdConnection::open() {
struct sockaddr_un sck;
// socket name is too long - it can't be copied to to sun_path
if (m_socket.isEmpty() || m_socket.length() >= 108)
return false;
if (m_fd > 0)
close();
if ((m_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
return false;
sck.sun_family = AF_UNIX;
//It is guaranted that socket.ascii() is shorter than 108 bytes, but we want to be sure
strncpy(sck.sun_path, m_socket.ascii(), 108);
if (::connect(m_fd, (struct sockaddr *)&sck, sizeof(sck)) == -1)
return false;
return true;
}
ssize_t CPUFreqdConnection::read(void *buf, size_t size) {
return ::read(m_fd, buf, size);
}
bool CPUFreqdConnection::write(uint32_t cmd, uint32_t arg) {
uint32_t command;
command = MAKE_COMMAND(cmd, arg);
return (::write(m_fd, &command, sizeof(command)) == (int)sizeof(command));
}
void CPUFreqdConnection::close() {
::close(m_fd);
m_fd = -1;
}
bool CPUFreqdConnection::available() const {
return !m_socket.isEmpty();
}
bool CPUFreqdConnection::lookup() {
QString candidate;
QDir tmp("/tmp", "cpufreqd-*", QDir::Time, QDir::Dirs);
if (tmp.count())
candidate = "/tmp/" + tmp[0] + "/cpufreqd";
if (candidate != m_socket) {
m_socket = candidate;
return true;
}
return false;
}
|