Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
X
xcap-capability-linux
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
xcap
xcap-capability-linux
Commits
7d8c2206
Commit
7d8c2206
authored
15 years ago
by
Len Brown
Browse files
Options
Downloads
Plain Diff
Merge branch 'msi-wmi' into release
parents
f02f465b
de078e57
Loading
Loading
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
drivers/platform/x86/Kconfig
+12
-0
12 additions, 0 deletions
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
+1
-0
1 addition, 0 deletions
drivers/platform/x86/Makefile
drivers/platform/x86/msi-wmi.c
+293
-0
293 additions, 0 deletions
drivers/platform/x86/msi-wmi.c
with
306 additions
and
0 deletions
drivers/platform/x86/Kconfig
+
12
−
0
View file @
7d8c2206
...
...
@@ -367,6 +367,18 @@ config ACPI_WMI
It is safe to enable this driver even if your DSDT doesn't define
any ACPI-WMI devices.
config MSI_WMI
tristate "MSI WMI extras"
depends on ACPI_WMI
depends on INPUT
depends on BACKLIGHT_CLASS_DEVICE
select INPUT_SPARSEKMAP
help
Say Y here if you want to support WMI-based hotkeys on MSI laptops.
To compile this driver as a module, choose M here: the module will
be called msi-wmi.
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras (DEPRECATED)"
depends on ACPI
...
...
This diff is collapsed.
Click to expand it.
drivers/platform/x86/Makefile
+
1
−
0
View file @
7d8c2206
...
...
@@ -18,6 +18,7 @@ obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
obj-$(CONFIG_PANASONIC_LAPTOP)
+=
panasonic-laptop.o
obj-$(CONFIG_INTEL_MENLOW)
+=
intel_menlow.o
obj-$(CONFIG_ACPI_WMI)
+=
wmi.o
obj-$(CONFIG_MSI_WMI)
+=
msi-wmi.o
obj-$(CONFIG_ACPI_ASUS)
+=
asus_acpi.o
obj-$(CONFIG_TOPSTAR_LAPTOP)
+=
topstar-laptop.o
obj-$(CONFIG_ACPI_TOSHIBA)
+=
toshiba_acpi.o
This diff is collapsed.
Click to expand it.
drivers/platform/x86/msi-wmi.c
0 → 100644
+
293
−
0
View file @
7d8c2206
/*
* MSI WMI hotkeys
*
* Copyright (C) 2009 Novell <trenn@suse.de>
*
* Most stuff taken over from hp-wmi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include
<linux/kernel.h>
#include
<linux/input.h>
#include
<linux/input/sparse-keymap.h>
#include
<linux/acpi.h>
#include
<linux/backlight.h>
MODULE_AUTHOR
(
"Thomas Renninger <trenn@suse.de>"
);
MODULE_DESCRIPTION
(
"MSI laptop WMI hotkeys driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
);
MODULE_ALIAS
(
"wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
);
/* Temporary workaround until the WMI sysfs interface goes in
{ "svn", DMI_SYS_VENDOR },
{ "pn", DMI_PRODUCT_NAME },
{ "pvr", DMI_PRODUCT_VERSION },
{ "rvn", DMI_BOARD_VENDOR },
{ "rn", DMI_BOARD_NAME },
*/
MODULE_ALIAS
(
"dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*"
);
#define DRV_NAME "msi-wmi"
#define DRV_PFX DRV_NAME ": "
#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
#define dprintk(msg...) pr_debug(DRV_PFX msg)
#define KEYCODE_BASE 0xD0
#define MSI_WMI_BRIGHTNESSUP KEYCODE_BASE
#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1)
#define MSI_WMI_VOLUMEUP (KEYCODE_BASE + 2)
#define MSI_WMI_VOLUMEDOWN (KEYCODE_BASE + 3)
static
struct
key_entry
msi_wmi_keymap
[]
=
{
{
KE_KEY
,
MSI_WMI_BRIGHTNESSUP
,
{
KEY_BRIGHTNESSUP
}
},
{
KE_KEY
,
MSI_WMI_BRIGHTNESSDOWN
,
{
KEY_BRIGHTNESSDOWN
}
},
{
KE_KEY
,
MSI_WMI_VOLUMEUP
,
{
KEY_VOLUMEUP
}
},
{
KE_KEY
,
MSI_WMI_VOLUMEDOWN
,
{
KEY_VOLUMEDOWN
}
},
{
KE_END
,
0
}
};
static
ktime_t
last_pressed
[
ARRAY_SIZE
(
msi_wmi_keymap
)
-
1
];
struct
backlight_device
*
backlight
;
static
int
backlight_map
[]
=
{
0x00
,
0x33
,
0x66
,
0x99
,
0xCC
,
0xFF
};
static
struct
input_dev
*
msi_wmi_input_dev
;
static
int
msi_wmi_query_block
(
int
instance
,
int
*
ret
)
{
acpi_status
status
;
union
acpi_object
*
obj
;
struct
acpi_buffer
output
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
status
=
wmi_query_block
(
MSIWMI_BIOS_GUID
,
instance
,
&
output
);
obj
=
output
.
pointer
;
if
(
!
obj
||
obj
->
type
!=
ACPI_TYPE_INTEGER
)
{
if
(
obj
)
{
printk
(
KERN_ERR
DRV_PFX
"query block returned object "
"type: %d - buffer length:%d
\n
"
,
obj
->
type
,
obj
->
type
==
ACPI_TYPE_BUFFER
?
obj
->
buffer
.
length
:
0
);
}
kfree
(
obj
);
return
-
EINVAL
;
}
*
ret
=
obj
->
integer
.
value
;
kfree
(
obj
);
return
0
;
}
static
int
msi_wmi_set_block
(
int
instance
,
int
value
)
{
acpi_status
status
;
struct
acpi_buffer
input
=
{
sizeof
(
int
),
&
value
};
dprintk
(
"Going to set block of instance: %d - value: %d
\n
"
,
instance
,
value
);
status
=
wmi_set_block
(
MSIWMI_BIOS_GUID
,
instance
,
&
input
);
return
ACPI_SUCCESS
(
status
)
?
0
:
1
;
}
static
int
bl_get
(
struct
backlight_device
*
bd
)
{
int
level
,
err
,
ret
;
/* Instance 1 is "get backlight", cmp with DSDT */
err
=
msi_wmi_query_block
(
1
,
&
ret
);
if
(
err
)
{
printk
(
KERN_ERR
DRV_PFX
"Could not query backlight: %d
\n
"
,
err
);
return
-
EINVAL
;
}
dprintk
(
"Get: Query block returned: %d
\n
"
,
ret
);
for
(
level
=
0
;
level
<
ARRAY_SIZE
(
backlight_map
);
level
++
)
{
if
(
backlight_map
[
level
]
==
ret
)
{
dprintk
(
"Current backlight level: 0x%X - index: %d
\n
"
,
backlight_map
[
level
],
level
);
break
;
}
}
if
(
level
==
ARRAY_SIZE
(
backlight_map
))
{
printk
(
KERN_ERR
DRV_PFX
"get: Invalid brightness value: 0x%X
\n
"
,
ret
);
return
-
EINVAL
;
}
return
level
;
}
static
int
bl_set_status
(
struct
backlight_device
*
bd
)
{
int
bright
=
bd
->
props
.
brightness
;
if
(
bright
>=
ARRAY_SIZE
(
backlight_map
)
||
bright
<
0
)
return
-
EINVAL
;
/* Instance 0 is "set backlight" */
return
msi_wmi_set_block
(
0
,
backlight_map
[
bright
]);
}
static
struct
backlight_ops
msi_backlight_ops
=
{
.
get_brightness
=
bl_get
,
.
update_status
=
bl_set_status
,
};
static
void
msi_wmi_notify
(
u32
value
,
void
*
context
)
{
struct
acpi_buffer
response
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
static
struct
key_entry
*
key
;
union
acpi_object
*
obj
;
ktime_t
cur
;
wmi_get_event_data
(
value
,
&
response
);
obj
=
(
union
acpi_object
*
)
response
.
pointer
;
if
(
obj
&&
obj
->
type
==
ACPI_TYPE_INTEGER
)
{
int
eventcode
=
obj
->
integer
.
value
;
dprintk
(
"Eventcode: 0x%x
\n
"
,
eventcode
);
key
=
sparse_keymap_entry_from_scancode
(
msi_wmi_input_dev
,
eventcode
);
if
(
key
)
{
ktime_t
diff
;
cur
=
ktime_get_real
();
diff
=
ktime_sub
(
cur
,
last_pressed
[
key
->
code
-
KEYCODE_BASE
]);
/* Ignore event if the same event happened in a 50 ms
timeframe -> Key press may result in 10-20 GPEs */
if
(
ktime_to_us
(
diff
)
<
1000
*
50
)
{
dprintk
(
"Suppressed key event 0x%X - "
"Last press was %lld us ago
\n
"
,
key
->
code
,
ktime_to_us
(
diff
));
return
;
}
last_pressed
[
key
->
code
-
KEYCODE_BASE
]
=
cur
;
if
(
key
->
type
==
KE_KEY
&&
/* Brightness is served via acpi video driver */
(
!
acpi_video_backlight_support
()
||
(
key
->
code
!=
MSI_WMI_BRIGHTNESSUP
&&
key
->
code
!=
MSI_WMI_BRIGHTNESSDOWN
)))
{
dprintk
(
"Send key: 0x%X - "
"Input layer keycode: %d
\n
"
,
key
->
code
,
key
->
keycode
);
sparse_keymap_report_entry
(
msi_wmi_input_dev
,
key
,
1
,
true
);
}
}
else
printk
(
KERN_INFO
"Unknown key pressed - %x
\n
"
,
eventcode
);
}
else
printk
(
KERN_INFO
DRV_PFX
"Unknown event received
\n
"
);
kfree
(
response
.
pointer
);
}
static
int
__init
msi_wmi_input_setup
(
void
)
{
int
err
;
msi_wmi_input_dev
=
input_allocate_device
();
if
(
!
msi_wmi_input_dev
)
return
-
ENOMEM
;
msi_wmi_input_dev
->
name
=
"MSI WMI hotkeys"
;
msi_wmi_input_dev
->
phys
=
"wmi/input0"
;
msi_wmi_input_dev
->
id
.
bustype
=
BUS_HOST
;
err
=
sparse_keymap_setup
(
msi_wmi_input_dev
,
msi_wmi_keymap
,
NULL
);
if
(
err
)
goto
err_free_dev
;
err
=
input_register_device
(
msi_wmi_input_dev
);
if
(
err
)
goto
err_free_keymap
;
memset
(
last_pressed
,
0
,
sizeof
(
last_pressed
));
return
0
;
err_free_keymap:
sparse_keymap_free
(
msi_wmi_input_dev
);
err_free_dev:
input_free_device
(
msi_wmi_input_dev
);
return
err
;
}
static
int
__init
msi_wmi_init
(
void
)
{
int
err
;
if
(
!
wmi_has_guid
(
MSIWMI_EVENT_GUID
))
{
printk
(
KERN_ERR
"This machine doesn't have MSI-hotkeys through WMI
\n
"
);
return
-
ENODEV
;
}
err
=
wmi_install_notify_handler
(
MSIWMI_EVENT_GUID
,
msi_wmi_notify
,
NULL
);
if
(
err
)
return
-
EINVAL
;
err
=
msi_wmi_input_setup
();
if
(
err
)
goto
err_uninstall_notifier
;
if
(
!
acpi_video_backlight_support
())
{
backlight
=
backlight_device_register
(
DRV_NAME
,
NULL
,
NULL
,
&
msi_backlight_ops
);
if
(
IS_ERR
(
backlight
))
goto
err_free_input
;
backlight
->
props
.
max_brightness
=
ARRAY_SIZE
(
backlight_map
)
-
1
;
err
=
bl_get
(
NULL
);
if
(
err
<
0
)
goto
err_free_backlight
;
backlight
->
props
.
brightness
=
err
;
}
dprintk
(
"Event handler installed
\n
"
);
return
0
;
err_free_backlight:
backlight_device_unregister
(
backlight
);
err_free_input:
input_unregister_device
(
msi_wmi_input_dev
);
err_uninstall_notifier:
wmi_remove_notify_handler
(
MSIWMI_EVENT_GUID
);
return
err
;
}
static
void
__exit
msi_wmi_exit
(
void
)
{
if
(
wmi_has_guid
(
MSIWMI_EVENT_GUID
))
{
wmi_remove_notify_handler
(
MSIWMI_EVENT_GUID
);
sparse_keymap_free
(
msi_wmi_input_dev
);
input_unregister_device
(
msi_wmi_input_dev
);
backlight_device_unregister
(
backlight
);
}
}
module_init
(
msi_wmi_init
);
module_exit
(
msi_wmi_exit
);
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment