Imported Upstream version 2.5
[platform/upstream/powertop.git] / src / devices / usb.cpp
1 /*
2  * Copyright 2010, Intel Corporation
3  *
4  * This file is part of PowerTOP
5  *
6  * This program file is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program in a file named COPYING; if not, write to the
17  * Free Software Foundation, Inc,
18  * 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301 USA
20  * or just google for it.
21  *
22  * Authors:
23  *      Arjan van de Ven <arjan@linux.intel.com>
24  */
25 #include "usb.h"
26
27 #include <string.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31
32 #include "../lib.h"
33 #include "../parameters/parameters.h"
34
35 #include <iostream>
36 #include <fstream>
37
38 usbdevice::usbdevice(const char *_name, const char *path, const char *devid): device()
39 {
40         ifstream file;
41         char filename[4096];
42         char vendor[4096];
43         char product[4096];
44
45         strcpy(sysfs_path, path);
46         register_sysfs_path(sysfs_path);
47         strcpy(name, _name);
48         strcpy(devname, devid);
49         sprintf(humanname, _("USB device: %s"), pretty_print(devid, vendor, 4096));
50         active_before = 0;
51         active_after = 0;
52         connected_before = 0;
53         connected_after = 0;
54
55         index = get_param_index(devname);
56         r_index = get_result_index(name);
57         rootport = 0;
58         cached_valid = 0;
59
60
61         /* root ports and hubs should count as 0 power ... their activity is derived */
62         sprintf(filename, "%s/bDeviceClass", path);
63         file.open(filename, ios::in);
64         if (file) {
65                 int dclass = 0;
66
67                 file >> dclass;
68                 file.close();
69                 if (dclass == 9)
70                         rootport = 1;
71         };
72
73         vendor[0] = 0;
74         product[0] = 0;
75         sprintf(filename, "%s/manufacturer", path);
76         file.open(filename, ios::in);
77         if (file) {
78                 file.getline(vendor, 2047);
79                 if (strstr(vendor, "Linux "))
80                         vendor[0] = 0;
81                 file.close();
82         };
83         sprintf(filename, "%s/product", path);
84         file.open(filename, ios::in);
85         if (file) {
86                 file.getline(product, 2040);
87                 file.close();
88         };
89         if (strlen(vendor) && strlen(product))
90                 sprintf(humanname, _("USB device: %s (%s)"), product, vendor);
91         else if (strlen(product))
92                 sprintf(humanname, _("USB device: %s"), product);
93         else if (strlen(vendor))
94                 sprintf(humanname, _("USB device: %s"), vendor);
95 }
96
97
98
99 void usbdevice::start_measurement(void)
100 {
101         ifstream file;
102         char fullpath[4096];
103
104         active_before = 0;
105         active_after = 0;
106         connected_before = 0;
107         connected_after = 0;
108
109         sprintf(fullpath, "%s/power/active_duration", sysfs_path);
110         file.open(fullpath, ios::in);
111         if (file) {
112                 file >> active_before;
113         }
114         file.close();
115
116         sprintf(fullpath, "%s/power/connected_duration", sysfs_path);
117         file.open(fullpath, ios::in);
118         if (file) {
119                 file >> connected_before;
120         }
121         file.close();
122 }
123
124 void usbdevice::end_measurement(void)
125 {
126         ifstream file;
127         char fullpath[4096];
128
129         sprintf(fullpath, "%s/power/active_duration", sysfs_path);
130         file.open(fullpath, ios::in);
131         if (file) {
132                 file >> active_after;
133         }
134         file.close();
135
136         sprintf(fullpath, "%s/power/connected_duration", sysfs_path);
137         file.open(fullpath, ios::in);
138         if (file) {
139                 file >> connected_after;
140         }
141         file.close();
142         report_utilization(name, utilization());
143
144 }
145
146 double usbdevice::utilization(void) /* percentage */
147 {
148         double d;
149         d = 100.0 * (active_after - active_before) / (0.01 + connected_after - connected_before);
150         if (d < 0.0)
151                 d = 0.0;
152         if (d > 99.8)
153                 d = 100.0;
154         return d;
155 }
156
157 const char * usbdevice::device_name(void)
158 {
159         return name;
160 }
161
162 const char * usbdevice::human_name(void)
163 {
164         return humanname;
165 }
166
167
168 double usbdevice::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
169 {
170         double power;
171         double factor;
172         double util;
173
174         if (rootport || !cached_valid)
175                 return 0.0;
176
177
178         power = 0;
179         factor = get_parameter_value(index, bundle);
180         util = get_result_value(r_index, result);
181
182         power += util * factor / 100.0;
183
184         return power;
185 }
186
187 static void create_all_usb_devices_callback(const char *d_name)
188 {
189         char filename[4096];
190         ifstream file;
191         class usbdevice *usb;
192         char device_name[4096];
193         char vendorid[64], devid[64];
194         char devid_name[4096];
195
196         sprintf(filename, "/sys/bus/usb/devices/%s", d_name);
197         sprintf(device_name, "%s/power/active_duration", filename);
198         if (access(device_name, R_OK) != 0)
199                 return;
200
201         sprintf(device_name, "%s/idVendor", filename);
202         file.open(device_name, ios::in);
203         if (file)
204                 file.getline(vendorid, 64);
205         file.close();
206         sprintf(device_name, "%s/idProduct", filename);
207         file.open(device_name, ios::in);
208         if (file)
209                 file.getline(devid, 64);
210         file.close();
211
212         sprintf(devid_name, "usb-device-%s-%s", vendorid, devid);
213         sprintf(device_name, "usb-device-%s-%s-%s", d_name, vendorid, devid);
214         if (result_device_exists(device_name))
215                 return;
216
217         usb = new class usbdevice(device_name, filename, devid_name);
218         all_devices.push_back(usb);
219         register_parameter(devid_name, 0.1);
220 }
221
222 void create_all_usb_devices(void)
223 {
224         process_directory("/sys/bus/usb/devices/", create_all_usb_devices_callback);
225 }