xref: /OK3568_Linux_fs/kernel/drivers/power/supply/test_power.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Power supply driver for testing.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2010  Anton Vorontsov <cbouatmailru@gmail.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Dynamic module parameter code from the Virtual Battery Driver
8*4882a593Smuzhiyun  * Copyright (C) 2008 Pylone, Inc.
9*4882a593Smuzhiyun  * By: Masashi YOKOTA <yokota@pylone.jp>
10*4882a593Smuzhiyun  * Originally found here:
11*4882a593Smuzhiyun  * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/power_supply.h>
17*4882a593Smuzhiyun #include <linux/errno.h>
18*4882a593Smuzhiyun #include <linux/delay.h>
19*4882a593Smuzhiyun #include <generated/utsrelease.h>
20*4882a593Smuzhiyun #include <linux/of.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun enum test_power_id {
23*4882a593Smuzhiyun 	TEST_AC,
24*4882a593Smuzhiyun 	TEST_BATTERY,
25*4882a593Smuzhiyun 	TEST_USB,
26*4882a593Smuzhiyun 	TEST_POWER_NUM,
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun static int ac_online			= 1;
30*4882a593Smuzhiyun static int usb_online			= 1;
31*4882a593Smuzhiyun static int battery_status		= POWER_SUPPLY_STATUS_DISCHARGING;
32*4882a593Smuzhiyun static int battery_health		= POWER_SUPPLY_HEALTH_GOOD;
33*4882a593Smuzhiyun static int battery_present		= 1; /* true */
34*4882a593Smuzhiyun static int battery_technology		= POWER_SUPPLY_TECHNOLOGY_LION;
35*4882a593Smuzhiyun static int battery_capacity		= 50;
36*4882a593Smuzhiyun static int battery_voltage		= 3300;
37*4882a593Smuzhiyun static int battery_charge_counter	= -1000;
38*4882a593Smuzhiyun static int battery_current		= -1600;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static bool module_initialized;
41*4882a593Smuzhiyun 
test_power_get_ac_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)42*4882a593Smuzhiyun static int test_power_get_ac_property(struct power_supply *psy,
43*4882a593Smuzhiyun 				      enum power_supply_property psp,
44*4882a593Smuzhiyun 				      union power_supply_propval *val)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	switch (psp) {
47*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_ONLINE:
48*4882a593Smuzhiyun 		val->intval = ac_online;
49*4882a593Smuzhiyun 		break;
50*4882a593Smuzhiyun 	default:
51*4882a593Smuzhiyun 		return -EINVAL;
52*4882a593Smuzhiyun 	}
53*4882a593Smuzhiyun 	return 0;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
test_power_get_usb_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)56*4882a593Smuzhiyun static int test_power_get_usb_property(struct power_supply *psy,
57*4882a593Smuzhiyun 				      enum power_supply_property psp,
58*4882a593Smuzhiyun 				      union power_supply_propval *val)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	switch (psp) {
61*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_ONLINE:
62*4882a593Smuzhiyun 		val->intval = usb_online;
63*4882a593Smuzhiyun 		break;
64*4882a593Smuzhiyun 	default:
65*4882a593Smuzhiyun 		return -EINVAL;
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 	return 0;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
test_power_get_battery_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)70*4882a593Smuzhiyun static int test_power_get_battery_property(struct power_supply *psy,
71*4882a593Smuzhiyun 					   enum power_supply_property psp,
72*4882a593Smuzhiyun 					   union power_supply_propval *val)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	switch (psp) {
75*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_MODEL_NAME:
76*4882a593Smuzhiyun 		val->strval = "Test battery";
77*4882a593Smuzhiyun 		break;
78*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_MANUFACTURER:
79*4882a593Smuzhiyun 		val->strval = "Linux";
80*4882a593Smuzhiyun 		break;
81*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
82*4882a593Smuzhiyun 		val->strval = UTS_RELEASE;
83*4882a593Smuzhiyun 		break;
84*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_STATUS:
85*4882a593Smuzhiyun 		val->intval = battery_status;
86*4882a593Smuzhiyun 		break;
87*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CHARGE_TYPE:
88*4882a593Smuzhiyun 		val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
89*4882a593Smuzhiyun 		break;
90*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_HEALTH:
91*4882a593Smuzhiyun 		val->intval = battery_health;
92*4882a593Smuzhiyun 		break;
93*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_PRESENT:
94*4882a593Smuzhiyun 		val->intval = battery_present;
95*4882a593Smuzhiyun 		break;
96*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_TECHNOLOGY:
97*4882a593Smuzhiyun 		val->intval = battery_technology;
98*4882a593Smuzhiyun 		break;
99*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
100*4882a593Smuzhiyun 		val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
101*4882a593Smuzhiyun 		break;
102*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CAPACITY:
103*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CHARGE_NOW:
104*4882a593Smuzhiyun 		val->intval = battery_capacity;
105*4882a593Smuzhiyun 		break;
106*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
107*4882a593Smuzhiyun 		val->intval = battery_charge_counter;
108*4882a593Smuzhiyun 		break;
109*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
110*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CHARGE_FULL:
111*4882a593Smuzhiyun 		val->intval = 100;
112*4882a593Smuzhiyun 		break;
113*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
114*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
115*4882a593Smuzhiyun 		val->intval = 3600;
116*4882a593Smuzhiyun 		break;
117*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_TEMP:
118*4882a593Smuzhiyun 		val->intval = 26;
119*4882a593Smuzhiyun 		break;
120*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
121*4882a593Smuzhiyun 		val->intval = battery_voltage;
122*4882a593Smuzhiyun 		break;
123*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CURRENT_AVG:
124*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CURRENT_NOW:
125*4882a593Smuzhiyun 		val->intval = battery_current;
126*4882a593Smuzhiyun 		break;
127*4882a593Smuzhiyun 	default:
128*4882a593Smuzhiyun 		pr_info("%s: some properties deliberately report errors.\n",
129*4882a593Smuzhiyun 			__func__);
130*4882a593Smuzhiyun 		return -EINVAL;
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 	return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static enum power_supply_property test_power_ac_props[] = {
136*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_ONLINE,
137*4882a593Smuzhiyun };
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static enum power_supply_property test_power_battery_props[] = {
140*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_STATUS,
141*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CHARGE_TYPE,
142*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_HEALTH,
143*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_PRESENT,
144*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_TECHNOLOGY,
145*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
146*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CHARGE_FULL,
147*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CHARGE_NOW,
148*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
149*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CAPACITY,
150*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
151*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
152*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
153*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_MODEL_NAME,
154*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_MANUFACTURER,
155*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
156*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_TEMP,
157*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
158*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CURRENT_AVG,
159*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CURRENT_NOW,
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun static char *test_power_ac_supplied_to[] = {
163*4882a593Smuzhiyun 	"test_battery",
164*4882a593Smuzhiyun };
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun static struct power_supply *test_power_supplies[TEST_POWER_NUM];
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static const struct power_supply_desc test_power_desc[] = {
169*4882a593Smuzhiyun 	[TEST_AC] = {
170*4882a593Smuzhiyun 		.name = "test_ac",
171*4882a593Smuzhiyun 		.type = POWER_SUPPLY_TYPE_MAINS,
172*4882a593Smuzhiyun 		.properties = test_power_ac_props,
173*4882a593Smuzhiyun 		.num_properties = ARRAY_SIZE(test_power_ac_props),
174*4882a593Smuzhiyun 		.get_property = test_power_get_ac_property,
175*4882a593Smuzhiyun 	},
176*4882a593Smuzhiyun 	[TEST_BATTERY] = {
177*4882a593Smuzhiyun 		.name = "test_battery",
178*4882a593Smuzhiyun 		.type = POWER_SUPPLY_TYPE_BATTERY,
179*4882a593Smuzhiyun 		.properties = test_power_battery_props,
180*4882a593Smuzhiyun 		.num_properties = ARRAY_SIZE(test_power_battery_props),
181*4882a593Smuzhiyun 		.get_property = test_power_get_battery_property,
182*4882a593Smuzhiyun 	},
183*4882a593Smuzhiyun 	[TEST_USB] = {
184*4882a593Smuzhiyun 		.name = "test_usb",
185*4882a593Smuzhiyun 		.type = POWER_SUPPLY_TYPE_USB,
186*4882a593Smuzhiyun 		.properties = test_power_ac_props,
187*4882a593Smuzhiyun 		.num_properties = ARRAY_SIZE(test_power_ac_props),
188*4882a593Smuzhiyun 		.get_property = test_power_get_usb_property,
189*4882a593Smuzhiyun 	},
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static const struct power_supply_config test_power_configs[] = {
193*4882a593Smuzhiyun 	{
194*4882a593Smuzhiyun 		/* test_ac */
195*4882a593Smuzhiyun 		.supplied_to = test_power_ac_supplied_to,
196*4882a593Smuzhiyun 		.num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
197*4882a593Smuzhiyun 	}, {
198*4882a593Smuzhiyun 		/* test_battery */
199*4882a593Smuzhiyun 	}, {
200*4882a593Smuzhiyun 		/* test_usb */
201*4882a593Smuzhiyun 		.supplied_to = test_power_ac_supplied_to,
202*4882a593Smuzhiyun 		.num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
203*4882a593Smuzhiyun 	},
204*4882a593Smuzhiyun };
205*4882a593Smuzhiyun 
test_power_init(void)206*4882a593Smuzhiyun static int __init test_power_init(void)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	int i;
209*4882a593Smuzhiyun 	int ret;
210*4882a593Smuzhiyun 	struct device_node *dev_node;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	dev_node = of_find_node_by_name(NULL, "test-power");
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	if (!dev_node) {
215*4882a593Smuzhiyun 		pr_info("%s: could not find dev node\n", __func__);
216*4882a593Smuzhiyun 		return 0;
217*4882a593Smuzhiyun 	}
218*4882a593Smuzhiyun 	if (!of_device_is_available(dev_node)) {
219*4882a593Smuzhiyun 		pr_info("%s: test power disabled\n", __func__);
220*4882a593Smuzhiyun 		return 0;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 	of_node_put(dev_node);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_supplies));
225*4882a593Smuzhiyun 	BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_configs));
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) {
228*4882a593Smuzhiyun 		test_power_supplies[i] = power_supply_register(NULL,
229*4882a593Smuzhiyun 						&test_power_desc[i],
230*4882a593Smuzhiyun 						&test_power_configs[i]);
231*4882a593Smuzhiyun 		if (IS_ERR(test_power_supplies[i])) {
232*4882a593Smuzhiyun 			pr_err("%s: failed to register %s\n", __func__,
233*4882a593Smuzhiyun 				test_power_desc[i].name);
234*4882a593Smuzhiyun 			ret = PTR_ERR(test_power_supplies[i]);
235*4882a593Smuzhiyun 			goto failed;
236*4882a593Smuzhiyun 		}
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	module_initialized = true;
240*4882a593Smuzhiyun 	return 0;
241*4882a593Smuzhiyun failed:
242*4882a593Smuzhiyun 	while (--i >= 0)
243*4882a593Smuzhiyun 		power_supply_unregister(test_power_supplies[i]);
244*4882a593Smuzhiyun 	return ret;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun module_init(test_power_init);
247*4882a593Smuzhiyun 
test_power_exit(void)248*4882a593Smuzhiyun static void __exit test_power_exit(void)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun 	int i;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	/* Let's see how we handle changes... */
253*4882a593Smuzhiyun 	ac_online = 0;
254*4882a593Smuzhiyun 	usb_online = 0;
255*4882a593Smuzhiyun 	battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
256*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
257*4882a593Smuzhiyun 		power_supply_changed(test_power_supplies[i]);
258*4882a593Smuzhiyun 	pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n",
259*4882a593Smuzhiyun 		__func__);
260*4882a593Smuzhiyun 	ssleep(10);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
263*4882a593Smuzhiyun 		power_supply_unregister(test_power_supplies[i]);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	module_initialized = false;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun module_exit(test_power_exit);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun #define MAX_KEYLENGTH 256
272*4882a593Smuzhiyun struct battery_property_map {
273*4882a593Smuzhiyun 	int value;
274*4882a593Smuzhiyun 	char const *key;
275*4882a593Smuzhiyun };
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun static struct battery_property_map map_ac_online[] = {
278*4882a593Smuzhiyun 	{ 0,  "off"  },
279*4882a593Smuzhiyun 	{ 1,  "on" },
280*4882a593Smuzhiyun 	{ -1, NULL  },
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun static struct battery_property_map map_status[] = {
284*4882a593Smuzhiyun 	{ POWER_SUPPLY_STATUS_CHARGING,     "charging"     },
285*4882a593Smuzhiyun 	{ POWER_SUPPLY_STATUS_DISCHARGING,  "discharging"  },
286*4882a593Smuzhiyun 	{ POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" },
287*4882a593Smuzhiyun 	{ POWER_SUPPLY_STATUS_FULL,         "full"         },
288*4882a593Smuzhiyun 	{ -1,                               NULL           },
289*4882a593Smuzhiyun };
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun static struct battery_property_map map_health[] = {
292*4882a593Smuzhiyun 	{ POWER_SUPPLY_HEALTH_GOOD,           "good"        },
293*4882a593Smuzhiyun 	{ POWER_SUPPLY_HEALTH_OVERHEAT,       "overheat"    },
294*4882a593Smuzhiyun 	{ POWER_SUPPLY_HEALTH_DEAD,           "dead"        },
295*4882a593Smuzhiyun 	{ POWER_SUPPLY_HEALTH_OVERVOLTAGE,    "overvoltage" },
296*4882a593Smuzhiyun 	{ POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure"     },
297*4882a593Smuzhiyun 	{ -1,                                 NULL          },
298*4882a593Smuzhiyun };
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun static struct battery_property_map map_present[] = {
301*4882a593Smuzhiyun 	{ 0,  "false" },
302*4882a593Smuzhiyun 	{ 1,  "true"  },
303*4882a593Smuzhiyun 	{ -1, NULL    },
304*4882a593Smuzhiyun };
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun static struct battery_property_map map_technology[] = {
307*4882a593Smuzhiyun 	{ POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" },
308*4882a593Smuzhiyun 	{ POWER_SUPPLY_TECHNOLOGY_LION, "LION" },
309*4882a593Smuzhiyun 	{ POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" },
310*4882a593Smuzhiyun 	{ POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" },
311*4882a593Smuzhiyun 	{ POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" },
312*4882a593Smuzhiyun 	{ POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" },
313*4882a593Smuzhiyun 	{ -1,				NULL   },
314*4882a593Smuzhiyun };
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 
map_get_value(struct battery_property_map * map,const char * key,int def_val)317*4882a593Smuzhiyun static int map_get_value(struct battery_property_map *map, const char *key,
318*4882a593Smuzhiyun 				int def_val)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	char buf[MAX_KEYLENGTH];
321*4882a593Smuzhiyun 	int cr;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	strncpy(buf, key, MAX_KEYLENGTH);
324*4882a593Smuzhiyun 	buf[MAX_KEYLENGTH-1] = '\0';
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	cr = strnlen(buf, MAX_KEYLENGTH) - 1;
327*4882a593Smuzhiyun 	if (cr < 0)
328*4882a593Smuzhiyun 		return def_val;
329*4882a593Smuzhiyun 	if (buf[cr] == '\n')
330*4882a593Smuzhiyun 		buf[cr] = '\0';
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	while (map->key) {
333*4882a593Smuzhiyun 		if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0)
334*4882a593Smuzhiyun 			return map->value;
335*4882a593Smuzhiyun 		map++;
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	return def_val;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 
map_get_key(struct battery_property_map * map,int value,const char * def_key)342*4882a593Smuzhiyun static const char *map_get_key(struct battery_property_map *map, int value,
343*4882a593Smuzhiyun 				const char *def_key)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	while (map->key) {
346*4882a593Smuzhiyun 		if (map->value == value)
347*4882a593Smuzhiyun 			return map->key;
348*4882a593Smuzhiyun 		map++;
349*4882a593Smuzhiyun 	}
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	return def_key;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
signal_power_supply_changed(struct power_supply * psy)354*4882a593Smuzhiyun static inline void signal_power_supply_changed(struct power_supply *psy)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	if (module_initialized)
357*4882a593Smuzhiyun 		power_supply_changed(psy);
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
param_set_ac_online(const char * key,const struct kernel_param * kp)360*4882a593Smuzhiyun static int param_set_ac_online(const char *key, const struct kernel_param *kp)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	ac_online = map_get_value(map_ac_online, key, ac_online);
363*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_AC]);
364*4882a593Smuzhiyun 	return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
param_get_ac_online(char * buffer,const struct kernel_param * kp)367*4882a593Smuzhiyun static int param_get_ac_online(char *buffer, const struct kernel_param *kp)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	return sprintf(buffer, "%s\n",
370*4882a593Smuzhiyun 			map_get_key(map_ac_online, ac_online, "unknown"));
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
param_set_usb_online(const char * key,const struct kernel_param * kp)373*4882a593Smuzhiyun static int param_set_usb_online(const char *key, const struct kernel_param *kp)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	usb_online = map_get_value(map_ac_online, key, usb_online);
376*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_USB]);
377*4882a593Smuzhiyun 	return 0;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
param_get_usb_online(char * buffer,const struct kernel_param * kp)380*4882a593Smuzhiyun static int param_get_usb_online(char *buffer, const struct kernel_param *kp)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	return sprintf(buffer, "%s\n",
383*4882a593Smuzhiyun 			map_get_key(map_ac_online, usb_online, "unknown"));
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
param_set_battery_status(const char * key,const struct kernel_param * kp)386*4882a593Smuzhiyun static int param_set_battery_status(const char *key,
387*4882a593Smuzhiyun 					const struct kernel_param *kp)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	battery_status = map_get_value(map_status, key, battery_status);
390*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
391*4882a593Smuzhiyun 	return 0;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
param_get_battery_status(char * buffer,const struct kernel_param * kp)394*4882a593Smuzhiyun static int param_get_battery_status(char *buffer, const struct kernel_param *kp)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	return sprintf(buffer, "%s\n",
397*4882a593Smuzhiyun 			map_get_key(map_ac_online, battery_status, "unknown"));
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun 
param_set_battery_health(const char * key,const struct kernel_param * kp)400*4882a593Smuzhiyun static int param_set_battery_health(const char *key,
401*4882a593Smuzhiyun 					const struct kernel_param *kp)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	battery_health = map_get_value(map_health, key, battery_health);
404*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
405*4882a593Smuzhiyun 	return 0;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
param_get_battery_health(char * buffer,const struct kernel_param * kp)408*4882a593Smuzhiyun static int param_get_battery_health(char *buffer, const struct kernel_param *kp)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun 	return sprintf(buffer, "%s\n",
411*4882a593Smuzhiyun 			map_get_key(map_ac_online, battery_health, "unknown"));
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
param_set_battery_present(const char * key,const struct kernel_param * kp)414*4882a593Smuzhiyun static int param_set_battery_present(const char *key,
415*4882a593Smuzhiyun 					const struct kernel_param *kp)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun 	battery_present = map_get_value(map_present, key, battery_present);
418*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_AC]);
419*4882a593Smuzhiyun 	return 0;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun 
param_get_battery_present(char * buffer,const struct kernel_param * kp)422*4882a593Smuzhiyun static int param_get_battery_present(char *buffer,
423*4882a593Smuzhiyun 					const struct kernel_param *kp)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun 	return sprintf(buffer, "%s\n",
426*4882a593Smuzhiyun 			map_get_key(map_ac_online, battery_present, "unknown"));
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
param_set_battery_technology(const char * key,const struct kernel_param * kp)429*4882a593Smuzhiyun static int param_set_battery_technology(const char *key,
430*4882a593Smuzhiyun 					const struct kernel_param *kp)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun 	battery_technology = map_get_value(map_technology, key,
433*4882a593Smuzhiyun 						battery_technology);
434*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
435*4882a593Smuzhiyun 	return 0;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
param_get_battery_technology(char * buffer,const struct kernel_param * kp)438*4882a593Smuzhiyun static int param_get_battery_technology(char *buffer,
439*4882a593Smuzhiyun 					const struct kernel_param *kp)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun 	return sprintf(buffer, "%s\n",
442*4882a593Smuzhiyun 			map_get_key(map_ac_online, battery_technology,
443*4882a593Smuzhiyun 					"unknown"));
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
param_set_battery_capacity(const char * key,const struct kernel_param * kp)446*4882a593Smuzhiyun static int param_set_battery_capacity(const char *key,
447*4882a593Smuzhiyun 					const struct kernel_param *kp)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	int tmp;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	if (1 != sscanf(key, "%d", &tmp))
452*4882a593Smuzhiyun 		return -EINVAL;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	battery_capacity = tmp;
455*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
456*4882a593Smuzhiyun 	return 0;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun #define param_get_battery_capacity param_get_int
460*4882a593Smuzhiyun 
param_set_battery_voltage(const char * key,const struct kernel_param * kp)461*4882a593Smuzhiyun static int param_set_battery_voltage(const char *key,
462*4882a593Smuzhiyun 					const struct kernel_param *kp)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun 	int tmp;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	if (1 != sscanf(key, "%d", &tmp))
467*4882a593Smuzhiyun 		return -EINVAL;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	battery_voltage = tmp;
470*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
471*4882a593Smuzhiyun 	return 0;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun #define param_get_battery_voltage param_get_int
475*4882a593Smuzhiyun 
param_set_battery_charge_counter(const char * key,const struct kernel_param * kp)476*4882a593Smuzhiyun static int param_set_battery_charge_counter(const char *key,
477*4882a593Smuzhiyun 					const struct kernel_param *kp)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	int tmp;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	if (1 != sscanf(key, "%d", &tmp))
482*4882a593Smuzhiyun 		return -EINVAL;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	battery_charge_counter = tmp;
485*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
486*4882a593Smuzhiyun 	return 0;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun #define param_get_battery_charge_counter param_get_int
490*4882a593Smuzhiyun 
param_set_battery_current(const char * key,const struct kernel_param * kp)491*4882a593Smuzhiyun static int param_set_battery_current(const char *key,
492*4882a593Smuzhiyun 					const struct kernel_param *kp)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun 	int tmp;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	if (1 != sscanf(key, "%d", &tmp))
497*4882a593Smuzhiyun 		return -EINVAL;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	battery_current = tmp;
500*4882a593Smuzhiyun 	signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
501*4882a593Smuzhiyun 	return 0;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun #define param_get_battery_current param_get_int
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_ac_online = {
507*4882a593Smuzhiyun 	.set = param_set_ac_online,
508*4882a593Smuzhiyun 	.get = param_get_ac_online,
509*4882a593Smuzhiyun };
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_usb_online = {
512*4882a593Smuzhiyun 	.set = param_set_usb_online,
513*4882a593Smuzhiyun 	.get = param_get_usb_online,
514*4882a593Smuzhiyun };
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_status = {
517*4882a593Smuzhiyun 	.set = param_set_battery_status,
518*4882a593Smuzhiyun 	.get = param_get_battery_status,
519*4882a593Smuzhiyun };
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_present = {
522*4882a593Smuzhiyun 	.set = param_set_battery_present,
523*4882a593Smuzhiyun 	.get = param_get_battery_present,
524*4882a593Smuzhiyun };
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_technology = {
527*4882a593Smuzhiyun 	.set = param_set_battery_technology,
528*4882a593Smuzhiyun 	.get = param_get_battery_technology,
529*4882a593Smuzhiyun };
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_health = {
532*4882a593Smuzhiyun 	.set = param_set_battery_health,
533*4882a593Smuzhiyun 	.get = param_get_battery_health,
534*4882a593Smuzhiyun };
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_capacity = {
537*4882a593Smuzhiyun 	.set = param_set_battery_capacity,
538*4882a593Smuzhiyun 	.get = param_get_battery_capacity,
539*4882a593Smuzhiyun };
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_voltage = {
542*4882a593Smuzhiyun 	.set = param_set_battery_voltage,
543*4882a593Smuzhiyun 	.get = param_get_battery_voltage,
544*4882a593Smuzhiyun };
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_charge_counter = {
547*4882a593Smuzhiyun 	.set = param_set_battery_charge_counter,
548*4882a593Smuzhiyun 	.get = param_get_battery_charge_counter,
549*4882a593Smuzhiyun };
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_battery_current = {
552*4882a593Smuzhiyun 	.set = param_set_battery_current,
553*4882a593Smuzhiyun 	.get = param_get_battery_current,
554*4882a593Smuzhiyun };
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun #define param_check_ac_online(name, p) __param_check(name, p, void);
557*4882a593Smuzhiyun #define param_check_usb_online(name, p) __param_check(name, p, void);
558*4882a593Smuzhiyun #define param_check_battery_status(name, p) __param_check(name, p, void);
559*4882a593Smuzhiyun #define param_check_battery_present(name, p) __param_check(name, p, void);
560*4882a593Smuzhiyun #define param_check_battery_technology(name, p) __param_check(name, p, void);
561*4882a593Smuzhiyun #define param_check_battery_health(name, p) __param_check(name, p, void);
562*4882a593Smuzhiyun #define param_check_battery_capacity(name, p) __param_check(name, p, void);
563*4882a593Smuzhiyun #define param_check_battery_voltage(name, p) __param_check(name, p, void);
564*4882a593Smuzhiyun #define param_check_battery_charge_counter(name, p) __param_check(name, p, void);
565*4882a593Smuzhiyun #define param_check_battery_current(name, p) __param_check(name, p, void);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun module_param(ac_online, ac_online, 0644);
569*4882a593Smuzhiyun MODULE_PARM_DESC(ac_online, "AC charging state <on|off>");
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun module_param(usb_online, usb_online, 0644);
572*4882a593Smuzhiyun MODULE_PARM_DESC(usb_online, "USB charging state <on|off>");
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun module_param(battery_status, battery_status, 0644);
575*4882a593Smuzhiyun MODULE_PARM_DESC(battery_status,
576*4882a593Smuzhiyun 	"battery status <charging|discharging|not-charging|full>");
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun module_param(battery_present, battery_present, 0644);
579*4882a593Smuzhiyun MODULE_PARM_DESC(battery_present,
580*4882a593Smuzhiyun 	"battery presence state <good|overheat|dead|overvoltage|failure>");
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun module_param(battery_technology, battery_technology, 0644);
583*4882a593Smuzhiyun MODULE_PARM_DESC(battery_technology,
584*4882a593Smuzhiyun 	"battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun module_param(battery_health, battery_health, 0644);
587*4882a593Smuzhiyun MODULE_PARM_DESC(battery_health,
588*4882a593Smuzhiyun 	"battery health state <good|overheat|dead|overvoltage|failure>");
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun module_param(battery_capacity, battery_capacity, 0644);
591*4882a593Smuzhiyun MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)");
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun module_param(battery_voltage, battery_voltage, 0644);
594*4882a593Smuzhiyun MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)");
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun module_param(battery_charge_counter, battery_charge_counter, 0644);
597*4882a593Smuzhiyun MODULE_PARM_DESC(battery_charge_counter,
598*4882a593Smuzhiyun 	"battery charge counter (microampere-hours)");
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun module_param(battery_current, battery_current, 0644);
601*4882a593Smuzhiyun MODULE_PARM_DESC(battery_current, "battery current (milliampere)");
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun MODULE_DESCRIPTION("Power supply driver for testing");
604*4882a593Smuzhiyun MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
605*4882a593Smuzhiyun MODULE_LICENSE("GPL");
606