Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
8269cc4e
Commit
8269cc4e
authored
Jul 22, 2007
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull battery into release branch
parents
939ab201
78490d82
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
438 additions
and
235 deletions
+438
-235
drivers/acpi/battery.c
drivers/acpi/battery.c
+438
-235
No files found.
drivers/acpi/battery.c
View file @
8269cc4e
...
...
@@ -43,21 +43,30 @@
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_HID "PNP0C0A"
#define ACPI_BATTERY_DEVICE_NAME "Battery"
#define ACPI_BATTERY_FILE_INFO "info"
#define ACPI_BATTERY_FILE_STATUS "state"
#define ACPI_BATTERY_FILE_ALARM "alarm"
#define ACPI_BATTERY_NOTIFY_STATUS 0x80
#define ACPI_BATTERY_NOTIFY_INFO 0x81
#define ACPI_BATTERY_UNITS_WATTS "mW"
#define ACPI_BATTERY_UNITS_AMPS "mA"
#define _COMPONENT ACPI_BATTERY_COMPONENT
#define ACPI_BATTERY_UPDATE_TIME 0
#define ACPI_BATTERY_NONE_UPDATE 0
#define ACPI_BATTERY_EASY_UPDATE 1
#define ACPI_BATTERY_INIT_UPDATE 2
ACPI_MODULE_NAME
(
"battery"
);
MODULE_AUTHOR
(
"Paul Diefenbaugh"
);
MODULE_DESCRIPTION
(
"ACPI Battery Driver"
);
MODULE_LICENSE
(
"GPL"
);
static
unsigned
int
update_time
=
ACPI_BATTERY_UPDATE_TIME
;
/* 0 - every time, > 0 - by update_time */
module_param
(
update_time
,
uint
,
0644
);
extern
struct
proc_dir_entry
*
acpi_lock_battery_dir
(
void
);
extern
void
*
acpi_unlock_battery_dir
(
struct
proc_dir_entry
*
acpi_battery_dir
);
...
...
@@ -76,7 +85,7 @@ static struct acpi_driver acpi_battery_driver = {
},
};
struct
acpi_battery_stat
us
{
struct
acpi_battery_stat
e
{
acpi_integer
state
;
acpi_integer
present_rate
;
acpi_integer
remaining_capacity
;
...
...
@@ -99,33 +108,111 @@ struct acpi_battery_info {
acpi_string
oem_info
;
};
struct
acpi_battery_flags
{
u8
present
:
1
;
/* Bay occupied? */
u8
power_unit
:
1
;
/* 0=watts, 1=apms */
u8
alarm
:
1
;
/* _BTP present? */
u8
reserved
:
5
;
enum
acpi_battery_files
{
ACPI_BATTERY_INFO
=
0
,
ACPI_BATTERY_STATE
,
ACPI_BATTERY_ALARM
,
ACPI_BATTERY_NUMFILES
,
};
struct
acpi_battery_trips
{
unsigned
long
warning
;
unsigned
long
low
;
struct
acpi_battery_flags
{
u8
battery_present_prev
;
u8
alarm_present
;
u8
init_update
;
u8
update
[
ACPI_BATTERY_NUMFILES
];
u8
power_unit
;
};
struct
acpi_battery
{
struct
acpi_device
*
device
;
struct
mutex
mutex
;
struct
acpi_device
*
device
;
struct
acpi_battery_flags
flags
;
struct
acpi_battery_trips
trips
;
struct
acpi_buffer
bif_data
;
struct
acpi_buffer
bst_data
;
unsigned
long
alarm
;
struct
acpi_battery_info
*
info
;
unsigned
long
update_time
[
ACPI_BATTERY_NUMFILES
]
;
};
inline
int
acpi_battery_present
(
struct
acpi_battery
*
battery
)
{
return
battery
->
device
->
status
.
battery_present
;
}
inline
char
*
acpi_battery_power_units
(
struct
acpi_battery
*
battery
)
{
if
(
battery
->
flags
.
power_unit
)
return
ACPI_BATTERY_UNITS_AMPS
;
else
return
ACPI_BATTERY_UNITS_WATTS
;
}
inline
acpi_handle
acpi_battery_handle
(
struct
acpi_battery
*
battery
)
{
return
battery
->
device
->
handle
;
}
/* --------------------------------------------------------------------------
Battery Management
-------------------------------------------------------------------------- */
static
int
acpi_battery_get_info
(
struct
acpi_battery
*
battery
,
struct
acpi_battery_info
**
bif
)
static
void
acpi_battery_check_result
(
struct
acpi_battery
*
battery
,
int
result
)
{
if
(
!
battery
)
return
;
if
(
result
)
{
battery
->
flags
.
init_update
=
1
;
}
}
static
int
acpi_battery_extract_package
(
struct
acpi_battery
*
battery
,
union
acpi_object
*
package
,
struct
acpi_buffer
*
format
,
struct
acpi_buffer
*
data
,
char
*
package_name
)
{
acpi_status
status
=
AE_OK
;
struct
acpi_buffer
data_null
=
{
0
,
NULL
};
status
=
acpi_extract_package
(
package
,
format
,
&
data_null
);
if
(
status
!=
AE_BUFFER_OVERFLOW
)
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting size %s"
,
package_name
));
return
-
ENODEV
;
}
if
(
data_null
.
length
!=
data
->
length
)
{
kfree
(
data
->
pointer
);
data
->
pointer
=
kzalloc
(
data_null
.
length
,
GFP_KERNEL
);
if
(
!
data
->
pointer
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_NO_MEMORY
,
"kzalloc()"
));
return
-
ENOMEM
;
}
data
->
length
=
data_null
.
length
;
}
status
=
acpi_extract_package
(
package
,
format
,
data
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting %s"
,
package_name
));
return
-
ENODEV
;
}
return
0
;
}
static
int
acpi_battery_get_status
(
struct
acpi_battery
*
battery
)
{
int
result
=
0
;
result
=
acpi_bus_get_status
(
battery
->
device
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"Evaluating _STA"
));
return
-
ENODEV
;
}
return
result
;
}
static
int
acpi_battery_get_info
(
struct
acpi_battery
*
battery
)
{
int
result
=
0
;
acpi_status
status
=
0
;
...
...
@@ -133,16 +220,20 @@ acpi_battery_get_info(struct acpi_battery *battery,
struct
acpi_buffer
format
=
{
sizeof
(
ACPI_BATTERY_FORMAT_BIF
),
ACPI_BATTERY_FORMAT_BIF
};
struct
acpi_buffer
data
=
{
0
,
NULL
};
union
acpi_object
*
package
=
NULL
;
struct
acpi_buffer
*
data
=
NULL
;
struct
acpi_battery_info
*
bif
=
NULL
;
battery
->
update_time
[
ACPI_BATTERY_INFO
]
=
get_seconds
();
if
(
!
battery
||
!
bif
)
return
-
EINVAL
;
if
(
!
acpi_battery_present
(
battery
)
)
return
0
;
/* Evalute _BIF */
/* Evalu
a
te _BIF */
status
=
acpi_evaluate_object
(
battery
->
device
->
handle
,
"_BIF"
,
NULL
,
&
buffer
);
status
=
acpi_evaluate_object
(
acpi_battery_handle
(
battery
),
"_BIF"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Evaluating _BIF"
));
return
-
ENODEV
;
...
...
@@ -150,41 +241,29 @@ acpi_battery_get_info(struct acpi_battery *battery,
package
=
buffer
.
pointer
;
/* Extract Package Data */
status
=
acpi_extract_package
(
package
,
&
format
,
&
data
);
if
(
status
!=
AE_BUFFER_OVERFLOW
)
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting _BIF"
));
result
=
-
ENODEV
;
goto
end
;
}
data
=
&
battery
->
bif_data
;
data
.
pointer
=
kzalloc
(
data
.
length
,
GFP_KERNEL
);
if
(
!
data
.
pointer
)
{
result
=
-
ENOMEM
;
goto
end
;
}
/* Extract Package Data */
status
=
acpi_extract_package
(
package
,
&
format
,
&
data
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting _BIF"
));
kfree
(
data
.
pointer
);
result
=
-
ENODEV
;
result
=
acpi_battery_extract_package
(
battery
,
package
,
&
format
,
data
,
"_BIF"
);
if
(
result
)
goto
end
;
}
end:
kfree
(
buffer
.
pointer
);
if
(
!
result
)
(
*
bif
)
=
data
.
pointer
;
if
(
!
result
)
{
bif
=
data
->
pointer
;
battery
->
flags
.
power_unit
=
bif
->
power_unit
;
}
return
result
;
}
static
int
acpi_battery_get_status
(
struct
acpi_battery
*
battery
,
struct
acpi_battery_status
**
bst
)
static
int
acpi_battery_get_state
(
struct
acpi_battery
*
battery
)
{
int
result
=
0
;
acpi_status
status
=
0
;
...
...
@@ -192,16 +271,19 @@ acpi_battery_get_status(struct acpi_battery *battery,
struct
acpi_buffer
format
=
{
sizeof
(
ACPI_BATTERY_FORMAT_BST
),
ACPI_BATTERY_FORMAT_BST
};
struct
acpi_buffer
data
=
{
0
,
NULL
};
union
acpi_object
*
package
=
NULL
;
struct
acpi_buffer
*
data
=
NULL
;
battery
->
update_time
[
ACPI_BATTERY_STATE
]
=
get_seconds
();
if
(
!
battery
||
!
bst
)
return
-
EINVAL
;
if
(
!
acpi_battery_present
(
battery
)
)
return
0
;
/* Evalute _BST */
/* Evalu
a
te _BST */
status
=
acpi_evaluate_object
(
battery
->
device
->
handle
,
"_BST"
,
NULL
,
&
buffer
);
status
=
acpi_evaluate_object
(
acpi_battery_handle
(
battery
),
"_BST"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Evaluating _BST"
));
return
-
ENODEV
;
...
...
@@ -209,55 +291,49 @@ acpi_battery_get_status(struct acpi_battery *battery,
package
=
buffer
.
pointer
;
/* Extract Package Data */
status
=
acpi_extract_package
(
package
,
&
format
,
&
data
);
if
(
status
!=
AE_BUFFER_OVERFLOW
)
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting _BST"
));
result
=
-
ENODEV
;
goto
end
;
}
data
=
&
battery
->
bst_data
;
data
.
pointer
=
kzalloc
(
data
.
length
,
GFP_KERNEL
);
if
(
!
data
.
pointer
)
{
result
=
-
ENOMEM
;
goto
end
;
}
/* Extract Package Data */
status
=
acpi_extract_package
(
package
,
&
format
,
&
data
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting _BST"
));
kfree
(
data
.
pointer
);
result
=
-
ENODEV
;
result
=
acpi_battery_extract_package
(
battery
,
package
,
&
format
,
data
,
"_BST"
);
if
(
result
)
goto
end
;
}
end:
kfree
(
buffer
.
pointer
);
if
(
!
result
)
(
*
bst
)
=
data
.
pointer
;
return
result
;
}
static
int
acpi_battery_set_alarm
(
struct
acpi_battery
*
battery
,
unsigned
long
alarm
)
static
int
acpi_battery_get_alarm
(
struct
acpi_battery
*
battery
)
{
battery
->
update_time
[
ACPI_BATTERY_ALARM
]
=
get_seconds
();
return
0
;
}
static
int
acpi_battery_set_alarm
(
struct
acpi_battery
*
battery
,
unsigned
long
alarm
)
{
acpi_status
status
=
0
;
union
acpi_object
arg0
=
{
ACPI_TYPE_INTEGER
};
struct
acpi_object_list
arg_list
=
{
1
,
&
arg0
};
battery
->
update_time
[
ACPI_BATTERY_ALARM
]
=
get_seconds
();
if
(
!
battery
)
return
-
E
INVAL
;
if
(
!
acpi_battery_present
(
battery
)
)
return
-
E
NODEV
;
if
(
!
battery
->
flags
.
alarm
)
if
(
!
battery
->
flags
.
alarm
_present
)
return
-
ENODEV
;
arg0
.
integer
.
value
=
alarm
;
status
=
acpi_evaluate_object
(
battery
->
device
->
handle
,
"_BTP"
,
&
arg_list
,
NULL
);
status
=
acpi_evaluate_object
(
acpi_battery_handle
(
battery
),
"_BTP"
,
&
arg_list
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
...
...
@@ -268,65 +344,114 @@ acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
return
0
;
}
static
int
acpi_battery_
check
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_
init_alarm
(
struct
acpi_battery
*
battery
)
{
int
result
=
0
;
acpi_status
status
=
AE_OK
;
acpi_handle
handle
=
NULL
;
struct
acpi_
device
*
device
=
NULL
;
struct
acpi_battery_info
*
bif
=
NULL
;
struct
acpi_
battery_info
*
bif
=
battery
->
bif_data
.
pointer
;
unsigned
long
alarm
=
battery
->
alarm
;
/* See if alarms are supported, and if so, set default */
if
(
!
battery
)
return
-
EINVAL
;
status
=
acpi_get_handle
(
acpi_battery_handle
(
battery
),
"_BTP"
,
&
handle
);
if
(
ACPI_SUCCESS
(
status
))
{
battery
->
flags
.
alarm_present
=
1
;
if
(
!
alarm
&&
bif
)
{
alarm
=
bif
->
design_capacity_warning
;
}
result
=
acpi_battery_set_alarm
(
battery
,
alarm
);
if
(
result
)
goto
end
;
}
else
{
battery
->
flags
.
alarm_present
=
0
;
}
device
=
battery
->
device
;
end:
result
=
acpi_bus_get_status
(
device
);
if
(
result
)
return
result
;
}
/* Insertion? */
i
f
(
!
battery
->
flags
.
present
&&
device
->
status
.
battery_present
)
{
static
int
acpi_battery_init_update
(
struct
acpi_battery
*
battery
)
{
i
nt
result
=
0
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Battery inserted
\n
"
));
result
=
acpi_battery_get_status
(
battery
);
if
(
result
)
return
result
;
/* Evalute _BIF to get certain static information */
battery
->
flags
.
battery_present_prev
=
acpi_battery_present
(
battery
);
result
=
acpi_battery_get_info
(
battery
,
&
bif
);
if
(
acpi_battery_present
(
battery
))
{
result
=
acpi_battery_get_info
(
battery
);
if
(
result
)
return
result
;
result
=
acpi_battery_get_state
(
battery
);
if
(
result
)
return
result
;
battery
->
flags
.
power_unit
=
bif
->
power_unit
;
battery
->
trips
.
warning
=
bif
->
design_capacity_warning
;
battery
->
trips
.
low
=
bif
->
design_capacity_low
;
kfree
(
bif
);
acpi_battery_init_alarm
(
battery
);
}
/* See if alarms are supported, and if so, set default */
return
result
;
}
status
=
acpi_get_handle
(
battery
->
device
->
handle
,
"_BTP"
,
&
handle
);
if
(
ACPI_SUCCESS
(
status
))
{
battery
->
flags
.
alarm
=
1
;
acpi_battery_set_alarm
(
battery
,
battery
->
trips
.
warning
);
static
int
acpi_battery_update
(
struct
acpi_battery
*
battery
,
int
update
,
int
*
update_result_ptr
)
{
int
result
=
0
;
int
update_result
=
ACPI_BATTERY_NONE_UPDATE
;
if
(
!
acpi_battery_present
(
battery
))
{
update
=
1
;
}
if
(
battery
->
flags
.
init_update
)
{
result
=
acpi_battery_init_update
(
battery
);
if
(
result
)
goto
end
;
update_result
=
ACPI_BATTERY_INIT_UPDATE
;
}
else
if
(
update
)
{
result
=
acpi_battery_get_status
(
battery
);
if
(
result
)
goto
end
;
if
((
!
battery
->
flags
.
battery_present_prev
&
acpi_battery_present
(
battery
))
||
(
battery
->
flags
.
battery_present_prev
&
!
acpi_battery_present
(
battery
)))
{
result
=
acpi_battery_init_update
(
battery
);
if
(
result
)
goto
end
;
update_result
=
ACPI_BATTERY_INIT_UPDATE
;
}
else
{
update_result
=
ACPI_BATTERY_EASY_UPDATE
;
}
}
/* Removal? */
end:
else
if
(
battery
->
flags
.
present
&&
!
device
->
status
.
battery_present
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Battery removed
\n
"
));
}
battery
->
flags
.
init_update
=
(
result
!=
0
);
battery
->
flags
.
present
=
device
->
status
.
battery_presen
t
;
*
update_result_ptr
=
update_resul
t
;
return
result
;
}
static
void
acpi_battery_
check_present
(
struct
acpi_battery
*
battery
)
static
void
acpi_battery_
notify_update
(
struct
acpi_battery
*
battery
)
{
if
(
!
battery
->
flags
.
present
)
{
acpi_battery_check
(
battery
);
acpi_battery_get_status
(
battery
);
if
(
battery
->
flags
.
init_update
)
{
return
;
}
if
((
!
battery
->
flags
.
battery_present_prev
&
acpi_battery_present
(
battery
))
||
(
battery
->
flags
.
battery_present_prev
&
!
acpi_battery_present
(
battery
)))
{
battery
->
flags
.
init_update
=
1
;
}
else
{
battery
->
flags
.
update
[
ACPI_BATTERY_INFO
]
=
1
;
battery
->
flags
.
update
[
ACPI_BATTERY_STATE
]
=
1
;
battery
->
flags
.
update
[
ACPI_BATTERY_ALARM
]
=
1
;
}
}
...
...
@@ -335,37 +460,33 @@ static void acpi_battery_check_present(struct acpi_battery *battery)
-------------------------------------------------------------------------- */
static
struct
proc_dir_entry
*
acpi_battery_dir
;
static
int
acpi_battery_read_info
(
struct
seq_file
*
seq
,
void
*
offset
)
static
int
acpi_battery_print_info
(
struct
seq_file
*
seq
,
int
result
)
{
int
result
=
0
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery_info
*
bif
=
NULL
;
char
*
units
=
"?"
;
if
(
!
battery
)
if
(
result
)
goto
end
;
acpi_battery_check_present
(
battery
);
if
(
battery
->
flags
.
present
)
if
(
acpi_battery_present
(
battery
))
seq_printf
(
seq
,
"present: yes
\n
"
);
else
{
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
}
/* Battery Info (_BIF) */
result
=
acpi_battery_get_info
(
battery
,
&
bif
);
if
(
result
||
!
bif
)
{
seq_printf
(
seq
,
"ERROR: Unable to read battery information
\n
"
);
bif
=
battery
->
bif_data
.
pointer
;
if
(
!
bif
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"BIF buffer is NULL"
));
result
=
-
ENODEV
;
goto
end
;
}
units
=
bif
->
power_unit
?
ACPI_BATTERY_UNITS_AMPS
:
ACPI_BATTERY_UNITS_WATTS
;
/* Battery Units */
units
=
acpi_battery_power_units
(
battery
)
;
if
(
bif
->
design_capacity
==
ACPI_BATTERY_VALUE_UNKNOWN
)
seq_printf
(
seq
,
"design capacity: unknown
\n
"
);
...
...
@@ -396,7 +517,6 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
else
seq_printf
(
seq
,
"design voltage: %d mV
\n
"
,
(
u32
)
bif
->
design_voltage
);
seq_printf
(
seq
,
"design capacity warning: %d %sh
\n
"
,
(
u32
)
bif
->
design_capacity_warning
,
units
);
seq_printf
(
seq
,
"design capacity low: %d %sh
\n
"
,
...
...
@@ -411,50 +531,40 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
seq_printf
(
seq
,
"OEM info: %s
\n
"
,
bif
->
oem_info
);
end:
kfree
(
bif
);
return
0
;
}
if
(
result
)
seq_printf
(
seq
,
"ERROR: Unable to read battery info
\n
"
);
static
int
acpi_battery_info_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
acpi_battery_read_info
,
PDE
(
inode
)
->
data
);
return
result
;
}
static
int
acpi_battery_
read_state
(
struct
seq_file
*
seq
,
void
*
offse
t
)
static
int
acpi_battery_
print_state
(
struct
seq_file
*
seq
,
int
resul
t
)
{
int
result
=
0
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery_stat
us
*
bst
=
NULL
;
struct
acpi_battery_stat
e
*
bst
=
NULL
;
char
*
units
=
"?"
;
if
(
!
battery
)
if
(
result
)
goto
end
;
acpi_battery_check_present
(
battery
);
if
(
battery
->
flags
.
present
)
if
(
acpi_battery_present
(
battery
))
seq_printf
(
seq
,
"present: yes
\n
"
);
else
{
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
}
/* Battery Units */
units
=
battery
->
flags
.
power_unit
?
ACPI_BATTERY_UNITS_AMPS
:
ACPI_BATTERY_UNITS_WATTS
;
/* Battery Status (_BST) */
result
=
acpi_battery_get_status
(
battery
,
&
bst
);
if
(
result
||
!
bst
)
{
seq_printf
(
seq
,
"ERROR: Unable to read battery status
\n
"
);
bst
=
battery
->
bst_data
.
pointer
;
if
(
!
bst
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"BST buffer is NULL"
));
result
=
-
ENODEV
;
goto
end
;
}
/* Battery Units */
units
=
acpi_battery_power_units
(
battery
);
if
(
!
(
bst
->
state
&
0x04
))
seq_printf
(
seq
,
"capacity state: ok
\n
"
);
else
...
...
@@ -490,48 +600,43 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
(
u32
)
bst
->
present_voltage
);
end:
kfree
(
bst
);
return
0
;
}
if
(
result
)
{
seq_printf
(
seq
,
"ERROR: Unable to read battery state
\n
"
);
}
static
int
acpi_battery_state_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
acpi_battery_read_state
,
PDE
(
inode
)
->
data
);
return
result
;
}
static
int
acpi_battery_
read_alarm
(
struct
seq_file
*
seq
,
void
*
offse
t
)
static
int
acpi_battery_
print_alarm
(
struct
seq_file
*
seq
,
int
resul
t
)
{
struct
acpi_battery
*
battery
=
seq
->
private
;
char
*
units
=
"?"
;
if
(
!
battery
)
if
(
result
)
goto
end
;
acpi_battery_check_present
(
battery
);
if
(
!
battery
->
flags
.
present
)
{
if
(
!
acpi_battery_present
(
battery
))
{
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
}
/* Battery Units */
units
=
battery
->
flags
.
power_unit
?
ACPI_BATTERY_UNITS_AMPS
:
ACPI_BATTERY_UNITS_WATTS
;
/* Battery Alarm */
units
=
acpi_battery_power_units
(
battery
);
seq_printf
(
seq
,
"alarm: "
);
if
(
!
battery
->
alarm
)
seq_printf
(
seq
,
"unsupported
\n
"
);
else
seq_printf
(
seq
,
"%
d %sh
\n
"
,
(
u32
)
battery
->
alarm
,
units
);
seq_printf
(
seq
,
"%
lu %sh
\n
"
,
battery
->
alarm
,
units
);
end:
return
0
;
if
(
result
)
seq_printf
(
seq
,
"ERROR: Unable to read battery alarm
\n
"
);
return
result
;
}
static
ssize_t
...
...
@@ -543,27 +648,113 @@ acpi_battery_write_alarm(struct file *file,
char
alarm_string
[
12
]
=
{
'\0'
};
struct
seq_file
*
m
=
file
->
private_data
;
struct
acpi_battery
*
battery
=
m
->
private
;
int
update_result
=
ACPI_BATTERY_NONE_UPDATE
;
if
(
!
battery
||
(
count
>
sizeof
(
alarm_string
)
-
1
))
return
-
EINVAL
;
acpi_battery_check_present
(
battery
);
mutex_lock
(
&
battery
->
mutex
);
if
(
!
battery
->
flags
.
present
)
return
-
ENODEV
;
result
=
acpi_battery_update
(
battery
,
1
,
&
update_result
);
if
(
result
)
{
result
=
-
ENODEV
;
goto
end
;
}
if
(
copy_from_user
(
alarm_string
,
buffer
,
count
))
return
-
EFAULT
;
if
(
!
acpi_battery_present
(
battery
))
{
result
=
-
ENODEV
;
goto
end
;
}
if
(
copy_from_user
(
alarm_string
,
buffer
,
count
))
{
result
=
-
EFAULT
;
goto
end
;
}
alarm_string
[
count
]
=
'\0'
;
result
=
acpi_battery_set_alarm
(
battery
,
simple_strtoul
(
alarm_string
,
NULL
,
0
));
if
(
result
)
goto
end
;
end:
acpi_battery_check_result
(
battery
,
result
);
if
(
!
result
)
result
=
count
;
mutex_unlock
(
&
battery
->
mutex
);
return
result
;
}
typedef
int
(
*
print_func
)(
struct
seq_file
*
seq
,
int
result
);
typedef
int
(
*
get_func
)(
struct
acpi_battery
*
battery
);
static
struct
acpi_read_mux
{
print_func
print
;
get_func
get
;
}
acpi_read_funcs
[
ACPI_BATTERY_NUMFILES
]
=
{
{.
get
=
acpi_battery_get_info
,
.
print
=
acpi_battery_print_info
},
{.
get
=
acpi_battery_get_state
,
.
print
=
acpi_battery_print_state
},
{.
get
=
acpi_battery_get_alarm
,
.
print
=
acpi_battery_print_alarm
},
};
static
int
acpi_battery_read
(
int
fid
,
struct
seq_file
*
seq
)
{
struct
acpi_battery
*
battery
=
seq
->
private
;
int
result
=
0
;
int
update_result
=
ACPI_BATTERY_NONE_UPDATE
;
int
update
=
0
;
mutex_lock
(
&
battery
->
mutex
);
update
=
(
get_seconds
()
-
battery
->
update_time
[
fid
]
>=
update_time
);
update
=
(
update
|
battery
->
flags
.
update
[
fid
]);
result
=
acpi_battery_update
(
battery
,
update
,
&
update_result
);
if
(
result
)
goto
end
;
if
(
update_result
==
ACPI_BATTERY_EASY_UPDATE
)
{
result
=
acpi_read_funcs
[
fid
].
get
(
battery
);
if
(
result
)
goto
end
;
}
end:
result
=
acpi_read_funcs
[
fid
].
print
(
seq
,
result
);
acpi_battery_check_result
(
battery
,
result
);
battery
->
flags
.
update
[
fid
]
=
result
;
mutex_unlock
(
&
battery
->
mutex
);
return
result
;
}
static
int
acpi_battery_read_info
(
struct
seq_file
*
seq
,
void
*
offset
)
{
return
acpi_battery_read
(
ACPI_BATTERY_INFO
,
seq
);
}
static
int
acpi_battery_read_state
(
struct
seq_file
*
seq
,
void
*
offset
)
{
return
acpi_battery_read
(
ACPI_BATTERY_STATE
,
seq
);
}
static
int
acpi_battery_read_alarm
(
struct
seq_file
*
seq
,
void
*
offset
)
{
return
acpi_battery_read
(
ACPI_BATTERY_ALARM
,
seq
);
}
static
int
acpi_battery_info_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
acpi_battery_read_info
,
PDE
(
inode
)
->
data
);
}
return
count
;
static
int
acpi_battery_state_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
acpi_battery_read_state
,
PDE
(
inode
)
->
data
);
}
static
int
acpi_battery_alarm_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
...
...
@@ -571,35 +762,51 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
return
single_open
(
file
,
acpi_battery_read_alarm
,
PDE
(
inode
)
->
data
);
}
static
const
struct
file_operations
acpi_battery_info_ops
=
{
static
struct
battery_file
{
struct
file_operations
ops
;
mode_t
mode
;
char
*
name
;
}
acpi_battery_file
[]
=
{
{
.
name
=
"info"
,
.
mode
=
S_IRUGO
,
.
ops
=
{
.
open
=
acpi_battery_info_open_fs
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
static
const
struct
file_operations
acpi_battery_state_ops
=
{
},
},
{
.
name
=
"state"
,
.
mode
=
S_IRUGO
,
.
ops
=
{
.
open
=
acpi_battery_state_open_fs
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
static
const
struct
file_operations
acpi_battery_alarm_ops
=
{
},
},
{
.
name
=
"alarm"
,
.
mode
=
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
.
ops
=
{
.
open
=
acpi_battery_alarm_open_fs
,
.
read
=
seq_read
,
.
write
=
acpi_battery_write_alarm
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
},
},
};
static
int
acpi_battery_add_fs
(
struct
acpi_device
*
device
)
{
struct
proc_dir_entry
*
entry
=
NULL
;
int
i
;
if
(
!
acpi_device_dir
(
device
))
{
acpi_device_dir
(
device
)
=
proc_mkdir
(
acpi_device_bid
(
device
),
...
...
@@ -609,38 +816,16 @@ static int acpi_battery_add_fs(struct acpi_device *device)
acpi_device_dir
(
device
)
->
owner
=
THIS_MODULE
;
}
/* 'info' [R] */
entry
=
create_proc_entry
(
ACPI_BATTERY_FILE_INFO
,
S_IRUGO
,
acpi_device_dir
(
device
));
for
(
i
=
0
;
i
<
ACPI_BATTERY_NUMFILES
;
++
i
)
{
entry
=
create_proc_entry
(
acpi_battery_file
[
i
].
name
,
acpi_battery_file
[
i
].
mode
,
acpi_device_dir
(
device
));
if
(
!
entry
)
return
-
ENODEV
;
else
{
entry
->
proc_fops
=
&
acpi_battery_info_
ops
;
entry
->
proc_fops
=
&
acpi_battery_file
[
i
].
ops
;
entry
->
data
=
acpi_driver_data
(
device
);
entry
->
owner
=
THIS_MODULE
;
}
/* 'status' [R] */
entry
=
create_proc_entry
(
ACPI_BATTERY_FILE_STATUS
,
S_IRUGO
,
acpi_device_dir
(
device
));
if
(
!
entry
)
return
-
ENODEV
;
else
{
entry
->
proc_fops
=
&
acpi_battery_state_ops
;
entry
->
data
=
acpi_driver_data
(
device
);
entry
->
owner
=
THIS_MODULE
;
}
/* 'alarm' [R/W] */
entry
=
create_proc_entry
(
ACPI_BATTERY_FILE_ALARM
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
acpi_device_dir
(
device
));
if
(
!
entry
)
return
-
ENODEV
;
else
{
entry
->
proc_fops
=
&
acpi_battery_alarm_ops
;
entry
->
data
=
acpi_driver_data
(
device
);
entry
->
owner
=
THIS_MODULE
;
}
return
0
;
...
...
@@ -648,15 +833,12 @@ static int acpi_battery_add_fs(struct acpi_device *device)
static
int
acpi_battery_remove_fs
(
struct
acpi_device
*
device
)
{
int
i
;
if
(
acpi_device_dir
(
device
))
{
remove_proc_entry
(
ACPI_BATTERY_FILE_ALARM
,
acpi_device_dir
(
device
));
remove_proc_entry
(
ACPI_BATTERY_FILE_STATUS
,
for
(
i
=
0
;
i
<
ACPI_BATTERY_NUMFILES
;
++
i
)
{
remove_proc_entry
(
acpi_battery_file
[
i
].
name
,
acpi_device_dir
(
device
));
remove_proc_entry
(
ACPI_BATTERY_FILE_INFO
,
acpi_device_dir
(
device
));
}
remove_proc_entry
(
acpi_device_bid
(
device
),
acpi_battery_dir
);
acpi_device_dir
(
device
)
=
NULL
;
}
...
...
@@ -673,7 +855,6 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
struct
acpi_battery
*
battery
=
data
;
struct
acpi_device
*
device
=
NULL
;
if
(
!
battery
)
return
;
...
...
@@ -684,8 +865,10 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
case
ACPI_BATTERY_NOTIFY_INFO
:
case
ACPI_NOTIFY_BUS_CHECK
:
case
ACPI_NOTIFY_DEVICE_CHECK
:
acpi_battery_check
(
battery
);
acpi_bus_generate_event
(
device
,
event
,
battery
->
flags
.
present
);
device
=
battery
->
device
;
acpi_battery_notify_update
(
battery
);
acpi_bus_generate_event
(
device
,
event
,
acpi_battery_present
(
battery
));
break
;
default:
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
...
...
@@ -702,7 +885,6 @@ static int acpi_battery_add(struct acpi_device *device)
acpi_status
status
=
0
;
struct
acpi_battery
*
battery
=
NULL
;
if
(
!
device
)
return
-
EINVAL
;
...
...
@@ -710,15 +892,21 @@ static int acpi_battery_add(struct acpi_device *device)
if
(
!
battery
)
return
-
ENOMEM
;
mutex_init
(
&
battery
->
mutex
);
mutex_lock
(
&
battery
->
mutex
);
battery
->
device
=
device
;
strcpy
(
acpi_device_name
(
device
),
ACPI_BATTERY_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_BATTERY_CLASS
);
acpi_driver_data
(
device
)
=
battery
;
result
=
acpi_battery_
check
(
battery
);
result
=
acpi_battery_
get_status
(
battery
);
if
(
result
)
goto
end
;
battery
->
flags
.
init_update
=
1
;
result
=
acpi_battery_add_fs
(
device
);
if
(
result
)
goto
end
;
...
...
@@ -727,6 +915,7 @@ static int acpi_battery_add(struct acpi_device *device)
ACPI_ALL_NOTIFY
,
acpi_battery_notify
,
battery
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Installing notify handler"
));
result
=
-
ENODEV
;
goto
end
;
}
...
...
@@ -736,11 +925,14 @@ static int acpi_battery_add(struct acpi_device *device)
device
->
status
.
battery_present
?
"present"
:
"absent"
);
end:
if
(
result
)
{
acpi_battery_remove_fs
(
device
);
kfree
(
battery
);
}
mutex_unlock
(
&
battery
->
mutex
);
return
result
;
}
...
...
@@ -749,18 +941,27 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
acpi_status
status
=
0
;
struct
acpi_battery
*
battery
=
NULL
;
if
(
!
device
||
!
acpi_driver_data
(
device
))
return
-
EINVAL
;
battery
=
acpi_driver_data
(
device
);
mutex_lock
(
&
battery
->
mutex
);
status
=
acpi_remove_notify_handler
(
device
->
handle
,
ACPI_ALL_NOTIFY
,
acpi_battery_notify
);
acpi_battery_remove_fs
(
device
);
kfree
(
battery
->
bif_data
.
pointer
);
kfree
(
battery
->
bst_data
.
pointer
);
mutex_unlock
(
&
battery
->
mutex
);
mutex_destroy
(
&
battery
->
mutex
);
kfree
(
battery
);
return
0
;
...
...
@@ -775,7 +976,10 @@ static int acpi_battery_resume(struct acpi_device *device)
return
-
EINVAL
;
battery
=
device
->
driver_data
;
return
acpi_battery_check
(
battery
);
battery
->
flags
.
init_update
=
1
;
return
0
;
}
static
int
__init
acpi_battery_init
(
void
)
...
...
@@ -800,7 +1004,6 @@ static int __init acpi_battery_init(void)
static
void
__exit
acpi_battery_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
acpi_battery_driver
);
acpi_unlock_battery_dir
(
acpi_battery_dir
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment