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
126
127
128
129
130
131
132
133
134
135
136
137
|
/*
* kernel/power/tuxonice_sysfs.h
*
* Copyright (C) 2004-2015 Nigel Cunningham (nigel at nigelcunningham com au)
*
* This file is released under the GPLv2.
*/
#include <linux/sysfs.h>
struct toi_sysfs_data {
struct attribute attr;
int type;
int flags;
union {
struct {
unsigned long *bit_vector;
int bit;
} bit;
struct {
int *variable;
int minimum;
int maximum;
} integer;
struct {
long *variable;
long minimum;
long maximum;
} a_long;
struct {
unsigned long *variable;
unsigned long minimum;
unsigned long maximum;
} ul;
struct {
char *variable;
int max_length;
} string;
struct {
int (*read_sysfs) (const char *buffer, int count);
int (*write_sysfs) (const char *buffer, int count);
void *data;
} special;
} data;
/* Side effects routine. Used, eg, for reparsing the
* resume= entry when it changes */
void (*write_side_effect) (void);
struct list_head sysfs_data_list;
};
enum {
TOI_SYSFS_DATA_NONE = 1,
TOI_SYSFS_DATA_CUSTOM,
TOI_SYSFS_DATA_BIT,
TOI_SYSFS_DATA_INTEGER,
TOI_SYSFS_DATA_UL,
TOI_SYSFS_DATA_LONG,
TOI_SYSFS_DATA_STRING
};
#define SYSFS_WRITEONLY 0200
#define SYSFS_READONLY 0444
#define SYSFS_RW 0644
#define SYSFS_BIT(_name, _mode, _ul, _bit, _flags) { \
.attr = {.name = _name , .mode = _mode }, \
.type = TOI_SYSFS_DATA_BIT, \
.flags = _flags, \
.data = { .bit = { .bit_vector = _ul, .bit = _bit } } }
#define SYSFS_INT(_name, _mode, _int, _min, _max, _flags, _wse) { \
.attr = {.name = _name , .mode = _mode }, \
.type = TOI_SYSFS_DATA_INTEGER, \
.flags = _flags, \
.data = { .integer = { .variable = _int, .minimum = _min, \
.maximum = _max } }, \
.write_side_effect = _wse }
#define SYSFS_UL(_name, _mode, _ul, _min, _max, _flags) { \
.attr = {.name = _name , .mode = _mode }, \
.type = TOI_SYSFS_DATA_UL, \
.flags = _flags, \
.data = { .ul = { .variable = _ul, .minimum = _min, \
.maximum = _max } } }
#define SYSFS_LONG(_name, _mode, _long, _min, _max, _flags) { \
.attr = {.name = _name , .mode = _mode }, \
.type = TOI_SYSFS_DATA_LONG, \
.flags = _flags, \
.data = { .a_long = { .variable = _long, .minimum = _min, \
.maximum = _max } } }
#define SYSFS_STRING(_name, _mode, _string, _max_len, _flags, _wse) { \
.attr = {.name = _name , .mode = _mode }, \
.type = TOI_SYSFS_DATA_STRING, \
.flags = _flags, \
.data = { .string = { .variable = _string, .max_length = _max_len } }, \
.write_side_effect = _wse }
#define SYSFS_CUSTOM(_name, _mode, _read, _write, _flags, _wse) { \
.attr = {.name = _name , .mode = _mode }, \
.type = TOI_SYSFS_DATA_CUSTOM, \
.flags = _flags, \
.data = { .special = { .read_sysfs = _read, .write_sysfs = _write } }, \
.write_side_effect = _wse }
#define SYSFS_NONE(_name, _wse) { \
.attr = {.name = _name , .mode = SYSFS_WRITEONLY }, \
.type = TOI_SYSFS_DATA_NONE, \
.write_side_effect = _wse, \
}
/* Flags */
#define SYSFS_NEEDS_SM_FOR_READ 1
#define SYSFS_NEEDS_SM_FOR_WRITE 2
#define SYSFS_HIBERNATE 4
#define SYSFS_RESUME 8
#define SYSFS_HIBERNATE_OR_RESUME (SYSFS_HIBERNATE | SYSFS_RESUME)
#define SYSFS_HIBERNATING (SYSFS_HIBERNATE | SYSFS_NEEDS_SM_FOR_WRITE)
#define SYSFS_RESUMING (SYSFS_RESUME | SYSFS_NEEDS_SM_FOR_WRITE)
#define SYSFS_NEEDS_SM_FOR_BOTH \
(SYSFS_NEEDS_SM_FOR_READ | SYSFS_NEEDS_SM_FOR_WRITE)
int toi_register_sysfs_file(struct kobject *kobj,
struct toi_sysfs_data *toi_sysfs_data);
void toi_unregister_sysfs_file(struct kobject *kobj,
struct toi_sysfs_data *toi_sysfs_data);
extern struct kobject *tuxonice_kobj;
struct kobject *make_toi_sysdir(char *name);
void remove_toi_sysdir(struct kobject *obj);
extern void toi_cleanup_sysfs(void);
extern int toi_sysfs_init(void);
extern void toi_sysfs_exit(void);
|