OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [ac.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $)
3
 *
4
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6
 *
7
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or (at
12
 *  your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful, but
15
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 *  General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License along
20
 *  with this program; if not, write to the Free Software Foundation, Inc.,
21
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22
 *
23
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
 */
25
 
26
#include <linux/kernel.h>
27
#include <linux/module.h>
28
#include <linux/init.h>
29
#include <linux/types.h>
30
#ifdef CONFIG_ACPI_PROCFS_POWER
31
#include <linux/proc_fs.h>
32
#include <linux/seq_file.h>
33
#endif
34
#ifdef CONFIG_ACPI_SYSFS_POWER
35
#include <linux/power_supply.h>
36
#endif
37
#include <acpi/acpi_bus.h>
38
#include <acpi/acpi_drivers.h>
39
 
40
#define ACPI_AC_COMPONENT               0x00020000
41
#define ACPI_AC_CLASS                   "ac_adapter"
42
#define ACPI_AC_DEVICE_NAME             "AC Adapter"
43
#define ACPI_AC_FILE_STATE              "state"
44
#define ACPI_AC_NOTIFY_STATUS           0x80
45
#define ACPI_AC_STATUS_OFFLINE          0x00
46
#define ACPI_AC_STATUS_ONLINE           0x01
47
#define ACPI_AC_STATUS_UNKNOWN          0xFF
48
 
49
#define _COMPONENT              ACPI_AC_COMPONENT
50
ACPI_MODULE_NAME("ac");
51
 
52
MODULE_AUTHOR("Paul Diefenbaugh");
53
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
54
MODULE_LICENSE("GPL");
55
 
56
#ifdef CONFIG_ACPI_PROCFS_POWER
57
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
58
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
59
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
60
#endif
61
 
62
static int acpi_ac_add(struct acpi_device *device);
63
static int acpi_ac_remove(struct acpi_device *device, int type);
64
static int acpi_ac_resume(struct acpi_device *device);
65
 
66
const static struct acpi_device_id ac_device_ids[] = {
67
        {"ACPI0003", 0},
68
        {"", 0},
69
};
70
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
71
 
72
static struct acpi_driver acpi_ac_driver = {
73
        .name = "ac",
74
        .class = ACPI_AC_CLASS,
75
        .ids = ac_device_ids,
76
        .ops = {
77
                .add = acpi_ac_add,
78
                .remove = acpi_ac_remove,
79
                .resume = acpi_ac_resume,
80
                },
81
};
82
 
83
struct acpi_ac {
84
#ifdef CONFIG_ACPI_SYSFS_POWER
85
        struct power_supply charger;
86
#endif
87
        struct acpi_device * device;
88
        unsigned long state;
89
};
90
 
91
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
92
 
93
#ifdef CONFIG_ACPI_PROCFS_POWER
94
static const struct file_operations acpi_ac_fops = {
95
        .open = acpi_ac_open_fs,
96
        .read = seq_read,
97
        .llseek = seq_lseek,
98
        .release = single_release,
99
};
100
#endif
101
#ifdef CONFIG_ACPI_SYSFS_POWER
102
static int get_ac_property(struct power_supply *psy,
103
                           enum power_supply_property psp,
104
                           union power_supply_propval *val)
105
{
106
        struct acpi_ac *ac = to_acpi_ac(psy);
107
        switch (psp) {
108
        case POWER_SUPPLY_PROP_ONLINE:
109
                val->intval = ac->state;
110
                break;
111
        default:
112
                return -EINVAL;
113
        }
114
        return 0;
115
}
116
 
117
static enum power_supply_property ac_props[] = {
118
        POWER_SUPPLY_PROP_ONLINE,
119
};
120
#endif
121
/* --------------------------------------------------------------------------
122
                               AC Adapter Management
123
   -------------------------------------------------------------------------- */
124
 
125
static int acpi_ac_get_state(struct acpi_ac *ac)
126
{
127
        acpi_status status = AE_OK;
128
 
129
 
130
        if (!ac)
131
                return -EINVAL;
132
 
133
        status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state);
134
        if (ACPI_FAILURE(status)) {
135
                ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state"));
136
                ac->state = ACPI_AC_STATUS_UNKNOWN;
137
                return -ENODEV;
138
        }
139
 
140
        return 0;
141
}
142
 
143
#ifdef CONFIG_ACPI_PROCFS_POWER
144
/* --------------------------------------------------------------------------
145
                              FS Interface (/proc)
146
   -------------------------------------------------------------------------- */
147
 
148
static struct proc_dir_entry *acpi_ac_dir;
149
 
150
static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
151
{
152
        struct acpi_ac *ac = seq->private;
153
 
154
 
155
        if (!ac)
156
                return 0;
157
 
158
        if (acpi_ac_get_state(ac)) {
159
                seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
160
                return 0;
161
        }
162
 
163
        seq_puts(seq, "state:                   ");
164
        switch (ac->state) {
165
        case ACPI_AC_STATUS_OFFLINE:
166
                seq_puts(seq, "off-line\n");
167
                break;
168
        case ACPI_AC_STATUS_ONLINE:
169
                seq_puts(seq, "on-line\n");
170
                break;
171
        default:
172
                seq_puts(seq, "unknown\n");
173
                break;
174
        }
175
 
176
        return 0;
177
}
178
 
179
static int acpi_ac_open_fs(struct inode *inode, struct file *file)
180
{
181
        return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
182
}
183
 
184
static int acpi_ac_add_fs(struct acpi_device *device)
185
{
186
        struct proc_dir_entry *entry = NULL;
187
 
188
 
189
        if (!acpi_device_dir(device)) {
190
                acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
191
                                                     acpi_ac_dir);
192
                if (!acpi_device_dir(device))
193
                        return -ENODEV;
194
                acpi_device_dir(device)->owner = THIS_MODULE;
195
        }
196
 
197
        /* 'state' [R] */
198
        entry = create_proc_entry(ACPI_AC_FILE_STATE,
199
                                  S_IRUGO, acpi_device_dir(device));
200
        if (!entry)
201
                return -ENODEV;
202
        else {
203
                entry->proc_fops = &acpi_ac_fops;
204
                entry->data = acpi_driver_data(device);
205
                entry->owner = THIS_MODULE;
206
        }
207
 
208
        return 0;
209
}
210
 
211
static int acpi_ac_remove_fs(struct acpi_device *device)
212
{
213
 
214
        if (acpi_device_dir(device)) {
215
                remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device));
216
 
217
                remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
218
                acpi_device_dir(device) = NULL;
219
        }
220
 
221
        return 0;
222
}
223
#endif
224
 
225
/* --------------------------------------------------------------------------
226
                                   Driver Model
227
   -------------------------------------------------------------------------- */
228
 
229
static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
230
{
231
        struct acpi_ac *ac = data;
232
        struct acpi_device *device = NULL;
233
 
234
 
235
        if (!ac)
236
                return;
237
 
238
        device = ac->device;
239
        switch (event) {
240
        case ACPI_AC_NOTIFY_STATUS:
241
        case ACPI_NOTIFY_BUS_CHECK:
242
        case ACPI_NOTIFY_DEVICE_CHECK:
243
                acpi_ac_get_state(ac);
244
                acpi_bus_generate_proc_event(device, event, (u32) ac->state);
245
                acpi_bus_generate_netlink_event(device->pnp.device_class,
246
                                                  device->dev.bus_id, event,
247
                                                  (u32) ac->state);
248
#ifdef CONFIG_ACPI_SYSFS_POWER
249
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
250
#endif
251
                break;
252
        default:
253
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
254
                                  "Unsupported event [0x%x]\n", event));
255
                break;
256
        }
257
 
258
        return;
259
}
260
 
261
static int acpi_ac_add(struct acpi_device *device)
262
{
263
        int result = 0;
264
        acpi_status status = AE_OK;
265
        struct acpi_ac *ac = NULL;
266
 
267
 
268
        if (!device)
269
                return -EINVAL;
270
 
271
        ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
272
        if (!ac)
273
                return -ENOMEM;
274
 
275
        ac->device = device;
276
        strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
277
        strcpy(acpi_device_class(device), ACPI_AC_CLASS);
278
        acpi_driver_data(device) = ac;
279
 
280
        result = acpi_ac_get_state(ac);
281
        if (result)
282
                goto end;
283
 
284
#ifdef CONFIG_ACPI_PROCFS_POWER
285
        result = acpi_ac_add_fs(device);
286
#endif
287
        if (result)
288
                goto end;
289
#ifdef CONFIG_ACPI_SYSFS_POWER
290
        ac->charger.name = acpi_device_bid(device);
291
        ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
292
        ac->charger.properties = ac_props;
293
        ac->charger.num_properties = ARRAY_SIZE(ac_props);
294
        ac->charger.get_property = get_ac_property;
295
        power_supply_register(&ac->device->dev, &ac->charger);
296
#endif
297
        status = acpi_install_notify_handler(device->handle,
298
                                             ACPI_ALL_NOTIFY, acpi_ac_notify,
299
                                             ac);
300
        if (ACPI_FAILURE(status)) {
301
                result = -ENODEV;
302
                goto end;
303
        }
304
 
305
        printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
306
               acpi_device_name(device), acpi_device_bid(device),
307
               ac->state ? "on-line" : "off-line");
308
 
309
      end:
310
        if (result) {
311
#ifdef CONFIG_ACPI_PROCFS_POWER
312
                acpi_ac_remove_fs(device);
313
#endif
314
                kfree(ac);
315
        }
316
 
317
        return result;
318
}
319
 
320
static int acpi_ac_resume(struct acpi_device *device)
321
{
322
        struct acpi_ac *ac;
323
        unsigned old_state;
324
        if (!device || !acpi_driver_data(device))
325
                return -EINVAL;
326
        ac = acpi_driver_data(device);
327
        old_state = ac->state;
328
        if (acpi_ac_get_state(ac))
329
                return 0;
330
#ifdef CONFIG_ACPI_SYSFS_POWER
331
        if (old_state != ac->state)
332
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
333
#endif
334
        return 0;
335
}
336
 
337
static int acpi_ac_remove(struct acpi_device *device, int type)
338
{
339
        acpi_status status = AE_OK;
340
        struct acpi_ac *ac = NULL;
341
 
342
 
343
        if (!device || !acpi_driver_data(device))
344
                return -EINVAL;
345
 
346
        ac = acpi_driver_data(device);
347
 
348
        status = acpi_remove_notify_handler(device->handle,
349
                                            ACPI_ALL_NOTIFY, acpi_ac_notify);
350
#ifdef CONFIG_ACPI_SYSFS_POWER
351
        if (ac->charger.dev)
352
                power_supply_unregister(&ac->charger);
353
#endif
354
#ifdef CONFIG_ACPI_PROCFS_POWER
355
        acpi_ac_remove_fs(device);
356
#endif
357
 
358
        kfree(ac);
359
 
360
        return 0;
361
}
362
 
363
static int __init acpi_ac_init(void)
364
{
365
        int result;
366
 
367
        if (acpi_disabled)
368
                return -ENODEV;
369
 
370
#ifdef CONFIG_ACPI_PROCFS_POWER
371
        acpi_ac_dir = acpi_lock_ac_dir();
372
        if (!acpi_ac_dir)
373
                return -ENODEV;
374
#endif
375
 
376
        result = acpi_bus_register_driver(&acpi_ac_driver);
377
        if (result < 0) {
378
#ifdef CONFIG_ACPI_PROCFS_POWER
379
                acpi_unlock_ac_dir(acpi_ac_dir);
380
#endif
381
                return -ENODEV;
382
        }
383
 
384
        return 0;
385
}
386
 
387
static void __exit acpi_ac_exit(void)
388
{
389
 
390
        acpi_bus_unregister_driver(&acpi_ac_driver);
391
 
392
#ifdef CONFIG_ACPI_PROCFS_POWER
393
        acpi_unlock_ac_dir(acpi_ac_dir);
394
#endif
395
 
396
        return;
397
}
398
 
399
module_init(acpi_ac_init);
400
module_exit(acpi_ac_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.