Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
0d69a3c7
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
0d69a3c7
编写于
2月 21, 2013
作者:
J
Jiri Kosina
浏览文件
操作
浏览文件
下载
差异文件
Merge branches 'for-3.9/sony' and 'for-3.9/steelseries' into for-linus
Conflicts: drivers/hid/hid-core.c
上级
73759518
99d24902
7e415762
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
469 addition
and
3 deletion
+469
-3
Documentation/ABI/testing/sysfs-driver-hid-srws1
Documentation/ABI/testing/sysfs-driver-hid-srws1
+21
-0
drivers/hid/Kconfig
drivers/hid/Kconfig
+6
-0
drivers/hid/Makefile
drivers/hid/Makefile
+1
-0
drivers/hid/hid-core.c
drivers/hid/hid-core.c
+1
-0
drivers/hid/hid-ids.h
drivers/hid/hid-ids.h
+4
-0
drivers/hid/hid-sony.c
drivers/hid/hid-sony.c
+43
-3
drivers/hid/hid-steelseries.c
drivers/hid/hid-steelseries.c
+393
-0
未找到文件。
Documentation/ABI/testing/sysfs-driver-hid-srws1
0 → 100644
浏览文件 @
0d69a3c7
What: /sys/class/leds/SRWS1::<serial>::RPM1
What: /sys/class/leds/SRWS1::<serial>::RPM2
What: /sys/class/leds/SRWS1::<serial>::RPM3
What: /sys/class/leds/SRWS1::<serial>::RPM4
What: /sys/class/leds/SRWS1::<serial>::RPM5
What: /sys/class/leds/SRWS1::<serial>::RPM6
What: /sys/class/leds/SRWS1::<serial>::RPM7
What: /sys/class/leds/SRWS1::<serial>::RPM8
What: /sys/class/leds/SRWS1::<serial>::RPM9
What: /sys/class/leds/SRWS1::<serial>::RPM10
What: /sys/class/leds/SRWS1::<serial>::RPM11
What: /sys/class/leds/SRWS1::<serial>::RPM12
What: /sys/class/leds/SRWS1::<serial>::RPM13
What: /sys/class/leds/SRWS1::<serial>::RPM14
What: /sys/class/leds/SRWS1::<serial>::RPM15
What: /sys/class/leds/SRWS1::<serial>::RPMALL
Date: Jan 2013
KernelVersion: 3.9
Contact: Simon Wood <simon@mungewell.org>
Description: Provides a control for turning on/off the LEDs which form
an RPM meter on the front of the controller
drivers/hid/Kconfig
浏览文件 @
0d69a3c7
...
...
@@ -596,6 +596,12 @@ config HID_SPEEDLINK
---help---
Support for Speedlink Vicious and Divine Cezanne mouse.
config HID_STEELSERIES
tristate "Steelseries SRW-S1 steering wheel support"
depends on USB_HID
---help---
Support for Steelseries SRW-S1 steering wheel
config HID_SUNPLUS
tristate "Sunplus wireless desktop"
depends on USB_HID
...
...
drivers/hid/Makefile
浏览文件 @
0d69a3c7
...
...
@@ -101,6 +101,7 @@ obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SMARTJOYPLUS)
+=
hid-sjoy.o
obj-$(CONFIG_HID_SONY)
+=
hid-sony.o
obj-$(CONFIG_HID_SPEEDLINK)
+=
hid-speedlink.o
obj-$(CONFIG_HID_STEELSERIES)
+=
hid-steelseries.o
obj-$(CONFIG_HID_SUNPLUS)
+=
hid-sunplus.o
obj-$(CONFIG_HID_GREENASIA)
+=
hid-gaff.o
obj-$(CONFIG_HID_THINGM)
+=
hid-thingm.o
...
...
drivers/hid/hid-core.c
浏览文件 @
0d69a3c7
...
...
@@ -1702,6 +1702,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{
HID_USB_DEVICE
(
USB_VENDOR_ID_SONY
,
USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER
)
},
{
HID_BLUETOOTH_DEVICE
(
USB_VENDOR_ID_SONY
,
USB_DEVICE_ID_SONY_PS3_CONTROLLER
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_SONY
,
USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_STEELSERIES
,
USB_DEVICE_ID_STEELSERIES_SRWS1
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_SUNPLUS
,
USB_DEVICE_ID_SUNPLUS_WDESKTOP
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_THINGM
,
USB_DEVICE_ID_BLINK1
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_THRUSTMASTER
,
0xb300
)
},
...
...
drivers/hid/hid-ids.h
浏览文件 @
0d69a3c7
...
...
@@ -715,6 +715,7 @@
#define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
#define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374
#define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
...
...
@@ -732,6 +733,9 @@
#define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403
#define USB_DEVICE_ID_MTP_SITRONIX 0x5001
#define USB_VENDOR_ID_STEELSERIES 0x1038
#define USB_DEVICE_ID_STEELSERIES_SRWS1 0x1410
#define USB_VENDOR_ID_SUN 0x0430
#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
...
...
drivers/hid/hid-sony.c
浏览文件 @
0d69a3c7
...
...
@@ -33,6 +33,28 @@ static const u8 sixaxis_rdesc_fixup[] = {
0x03
,
0x46
,
0xFF
,
0x03
,
0x09
,
0x01
,
0x81
,
0x02
};
static
const
u8
sixaxis_rdesc_fixup2
[]
=
{
0x05
,
0x01
,
0x09
,
0x04
,
0xa1
,
0x01
,
0xa1
,
0x02
,
0x85
,
0x01
,
0x75
,
0x08
,
0x95
,
0x01
,
0x15
,
0x00
,
0x26
,
0xff
,
0x00
,
0x81
,
0x03
,
0x75
,
0x01
,
0x95
,
0x13
,
0x15
,
0x00
,
0x25
,
0x01
,
0x35
,
0x00
,
0x45
,
0x01
,
0x05
,
0x09
,
0x19
,
0x01
,
0x29
,
0x13
,
0x81
,
0x02
,
0x75
,
0x01
,
0x95
,
0x0d
,
0x06
,
0x00
,
0xff
,
0x81
,
0x03
,
0x15
,
0x00
,
0x26
,
0xff
,
0x00
,
0x05
,
0x01
,
0x09
,
0x01
,
0xa1
,
0x00
,
0x75
,
0x08
,
0x95
,
0x04
,
0x35
,
0x00
,
0x46
,
0xff
,
0x00
,
0x09
,
0x30
,
0x09
,
0x31
,
0x09
,
0x32
,
0x09
,
0x35
,
0x81
,
0x02
,
0xc0
,
0x05
,
0x01
,
0x95
,
0x13
,
0x09
,
0x01
,
0x81
,
0x02
,
0x95
,
0x0c
,
0x81
,
0x01
,
0x75
,
0x10
,
0x95
,
0x04
,
0x26
,
0xff
,
0x03
,
0x46
,
0xff
,
0x03
,
0x09
,
0x01
,
0x81
,
0x02
,
0xc0
,
0xa1
,
0x02
,
0x85
,
0x02
,
0x75
,
0x08
,
0x95
,
0x30
,
0x09
,
0x01
,
0xb1
,
0x02
,
0xc0
,
0xa1
,
0x02
,
0x85
,
0xee
,
0x75
,
0x08
,
0x95
,
0x30
,
0x09
,
0x01
,
0xb1
,
0x02
,
0xc0
,
0xa1
,
0x02
,
0x85
,
0xef
,
0x75
,
0x08
,
0x95
,
0x30
,
0x09
,
0x01
,
0xb1
,
0x02
,
0xc0
,
0xc0
,
};
struct
sony_sc
{
unsigned
long
quirks
;
};
...
...
@@ -43,9 +65,19 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
{
struct
sony_sc
*
sc
=
hid_get_drvdata
(
hdev
);
if
((
sc
->
quirks
&
VAIO_RDESC_CONSTANT
)
&&
*
rsize
>=
56
&&
rdesc
[
54
]
==
0x81
&&
rdesc
[
55
]
==
0x07
)
{
hid_info
(
hdev
,
"Fixing up Sony Vaio VGX report descriptor
\n
"
);
/*
* Some Sony RF receivers wrongly declare the mouse pointer as a
* a constant non-data variable.
*/
if
((
sc
->
quirks
&
VAIO_RDESC_CONSTANT
)
&&
*
rsize
>=
56
&&
/* usage page: generic desktop controls */
/* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
/* usage: mouse */
rdesc
[
2
]
==
0x09
&&
rdesc
[
3
]
==
0x02
&&
/* input (usage page for x,y axes): constant, variable, relative */
rdesc
[
54
]
==
0x81
&&
rdesc
[
55
]
==
0x07
)
{
hid_info
(
hdev
,
"Fixing up Sony RF Receiver report descriptor
\n
"
);
/* input: data, variable, relative */
rdesc
[
55
]
=
0x06
;
}
...
...
@@ -56,6 +88,12 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info
(
hdev
,
"Fixing up Sony Sixaxis report descriptor
\n
"
);
memcpy
((
void
*
)
&
rdesc
[
83
],
(
void
*
)
&
sixaxis_rdesc_fixup
,
sizeof
(
sixaxis_rdesc_fixup
));
}
else
if
(
sc
->
quirks
&
SIXAXIS_CONTROLLER_USB
&&
*
rsize
>
sizeof
(
sixaxis_rdesc_fixup2
))
{
hid_info
(
hdev
,
"Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)
\n
"
,
*
rsize
,
(
int
)
sizeof
(
sixaxis_rdesc_fixup2
));
*
rsize
=
sizeof
(
sixaxis_rdesc_fixup2
);
memcpy
(
rdesc
,
&
sixaxis_rdesc_fixup2
,
*
rsize
);
}
return
rdesc
;
}
...
...
@@ -217,6 +255,8 @@ static const struct hid_device_id sony_devices[] = {
.
driver_data
=
SIXAXIS_CONTROLLER_BT
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_SONY
,
USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE
),
.
driver_data
=
VAIO_RDESC_CONSTANT
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_SONY
,
USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE
),
.
driver_data
=
VAIO_RDESC_CONSTANT
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
sony_devices
);
...
...
drivers/hid/hid-steelseries.c
0 → 100644
浏览文件 @
0d69a3c7
/*
* HID driver for Steelseries SRW-S1
*
* Copyright (c) 2013 Simon Wood
*/
/*
* 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.
*/
#include <linux/device.h>
#include <linux/usb.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h"
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
#define SRWS1_NUMBER_LEDS 15
struct
steelseries_srws1_data
{
__u16
led_state
;
/* the last element is used for setting all leds simultaneously */
struct
led_classdev
*
led
[
SRWS1_NUMBER_LEDS
+
1
];
};
#endif
/* Fixed report descriptor for Steelseries SRW-S1 wheel controller
*
* The original descriptor hides the sensitivity and assists dials
* a custom vendor usage page. This inserts a patch to make them
* appear in the 'Generic Desktop' usage.
*/
static
__u8
steelseries_srws1_rdesc_fixed
[]
=
{
0x05
,
0x01
,
/* Usage Page (Desktop) */
0x09
,
0x08
,
/* Usage (MultiAxis), Changed */
0xA1
,
0x01
,
/* Collection (Application), */
0xA1
,
0x02
,
/* Collection (Logical), */
0x95
,
0x01
,
/* Report Count (1), */
0x05
,
0x01
,
/* Changed Usage Page (Desktop), */
0x09
,
0x30
,
/* Changed Usage (X), */
0x16
,
0xF8
,
0xF8
,
/* Logical Minimum (-1800), */
0x26
,
0x08
,
0x07
,
/* Logical Maximum (1800), */
0x65
,
0x14
,
/* Unit (Degrees), */
0x55
,
0x0F
,
/* Unit Exponent (15), */
0x75
,
0x10
,
/* Report Size (16), */
0x81
,
0x02
,
/* Input (Variable), */
0x09
,
0x31
,
/* Changed Usage (Y), */
0x15
,
0x00
,
/* Logical Minimum (0), */
0x26
,
0xFF
,
0x03
,
/* Logical Maximum (1023), */
0x75
,
0x0C
,
/* Report Size (12), */
0x81
,
0x02
,
/* Input (Variable), */
0x09
,
0x32
,
/* Changed Usage (Z), */
0x15
,
0x00
,
/* Logical Minimum (0), */
0x26
,
0xFF
,
0x03
,
/* Logical Maximum (1023), */
0x75
,
0x0C
,
/* Report Size (12), */
0x81
,
0x02
,
/* Input (Variable), */
0x05
,
0x01
,
/* Usage Page (Desktop), */
0x09
,
0x39
,
/* Usage (Hat Switch), */
0x25
,
0x07
,
/* Logical Maximum (7), */
0x35
,
0x00
,
/* Physical Minimum (0), */
0x46
,
0x3B
,
0x01
,
/* Physical Maximum (315), */
0x65
,
0x14
,
/* Unit (Degrees), */
0x75
,
0x04
,
/* Report Size (4), */
0x95
,
0x01
,
/* Report Count (1), */
0x81
,
0x02
,
/* Input (Variable), */
0x25
,
0x01
,
/* Logical Maximum (1), */
0x45
,
0x01
,
/* Physical Maximum (1), */
0x65
,
0x00
,
/* Unit, */
0x75
,
0x01
,
/* Report Size (1), */
0x95
,
0x03
,
/* Report Count (3), */
0x81
,
0x01
,
/* Input (Constant), */
0x05
,
0x09
,
/* Usage Page (Button), */
0x19
,
0x01
,
/* Usage Minimum (01h), */
0x29
,
0x11
,
/* Usage Maximum (11h), */
0x95
,
0x11
,
/* Report Count (17), */
0x81
,
0x02
,
/* Input (Variable), */
/* ---- Dial patch starts here ---- */
0x05
,
0x01
,
/* Usage Page (Desktop), */
0x09
,
0x33
,
/* Usage (RX), */
0x75
,
0x04
,
/* Report Size (4), */
0x95
,
0x02
,
/* Report Count (2), */
0x15
,
0x00
,
/* Logical Minimum (0), */
0x25
,
0x0b
,
/* Logical Maximum (b), */
0x81
,
0x02
,
/* Input (Variable), */
0x09
,
0x35
,
/* Usage (RZ), */
0x75
,
0x04
,
/* Report Size (4), */
0x95
,
0x01
,
/* Report Count (1), */
0x25
,
0x03
,
/* Logical Maximum (3), */
0x81
,
0x02
,
/* Input (Variable), */
/* ---- Dial patch ends here ---- */
0x06
,
0x00
,
0xFF
,
/* Usage Page (FF00h), */
0x09
,
0x01
,
/* Usage (01h), */
0x75
,
0x04
,
/* Changed Report Size (4), */
0x95
,
0x0D
,
/* Changed Report Count (13), */
0x81
,
0x02
,
/* Input (Variable), */
0xC0
,
/* End Collection, */
0xA1
,
0x02
,
/* Collection (Logical), */
0x09
,
0x02
,
/* Usage (02h), */
0x75
,
0x08
,
/* Report Size (8), */
0x95
,
0x10
,
/* Report Count (16), */
0x91
,
0x02
,
/* Output (Variable), */
0xC0
,
/* End Collection, */
0xC0
/* End Collection */
};
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
static
void
steelseries_srws1_set_leds
(
struct
hid_device
*
hdev
,
__u16
leds
)
{
struct
list_head
*
report_list
=
&
hdev
->
report_enum
[
HID_OUTPUT_REPORT
].
report_list
;
struct
hid_report
*
report
=
list_entry
(
report_list
->
next
,
struct
hid_report
,
list
);
__s32
*
value
=
report
->
field
[
0
]
->
value
;
value
[
0
]
=
0x40
;
value
[
1
]
=
leds
&
0xFF
;
value
[
2
]
=
leds
>>
8
;
value
[
3
]
=
0x00
;
value
[
4
]
=
0x00
;
value
[
5
]
=
0x00
;
value
[
6
]
=
0x00
;
value
[
7
]
=
0x00
;
value
[
8
]
=
0x00
;
value
[
9
]
=
0x00
;
value
[
10
]
=
0x00
;
value
[
11
]
=
0x00
;
value
[
12
]
=
0x00
;
value
[
13
]
=
0x00
;
value
[
14
]
=
0x00
;
value
[
15
]
=
0x00
;
usbhid_submit_report
(
hdev
,
report
,
USB_DIR_OUT
);
/* Note: LED change does not show on device until the device is read/polled */
}
static
void
steelseries_srws1_led_all_set_brightness
(
struct
led_classdev
*
led_cdev
,
enum
led_brightness
value
)
{
struct
device
*
dev
=
led_cdev
->
dev
->
parent
;
struct
hid_device
*
hid
=
container_of
(
dev
,
struct
hid_device
,
dev
);
struct
steelseries_srws1_data
*
drv_data
=
hid_get_drvdata
(
hid
);
if
(
!
drv_data
)
{
hid_err
(
hid
,
"Device data not found."
);
return
;
}
if
(
value
==
LED_OFF
)
drv_data
->
led_state
=
0
;
else
drv_data
->
led_state
=
(
1
<<
(
SRWS1_NUMBER_LEDS
+
1
))
-
1
;
steelseries_srws1_set_leds
(
hid
,
drv_data
->
led_state
);
}
static
enum
led_brightness
steelseries_srws1_led_all_get_brightness
(
struct
led_classdev
*
led_cdev
)
{
struct
device
*
dev
=
led_cdev
->
dev
->
parent
;
struct
hid_device
*
hid
=
container_of
(
dev
,
struct
hid_device
,
dev
);
struct
steelseries_srws1_data
*
drv_data
;
drv_data
=
hid_get_drvdata
(
hid
);
if
(
!
drv_data
)
{
hid_err
(
hid
,
"Device data not found."
);
return
LED_OFF
;
}
return
(
drv_data
->
led_state
>>
SRWS1_NUMBER_LEDS
)
?
LED_FULL
:
LED_OFF
;
}
static
void
steelseries_srws1_led_set_brightness
(
struct
led_classdev
*
led_cdev
,
enum
led_brightness
value
)
{
struct
device
*
dev
=
led_cdev
->
dev
->
parent
;
struct
hid_device
*
hid
=
container_of
(
dev
,
struct
hid_device
,
dev
);
struct
steelseries_srws1_data
*
drv_data
=
hid_get_drvdata
(
hid
);
int
i
,
state
=
0
;
if
(
!
drv_data
)
{
hid_err
(
hid
,
"Device data not found."
);
return
;
}
for
(
i
=
0
;
i
<
SRWS1_NUMBER_LEDS
;
i
++
)
{
if
(
led_cdev
!=
drv_data
->
led
[
i
])
continue
;
state
=
(
drv_data
->
led_state
>>
i
)
&
1
;
if
(
value
==
LED_OFF
&&
state
)
{
drv_data
->
led_state
&=
~
(
1
<<
i
);
steelseries_srws1_set_leds
(
hid
,
drv_data
->
led_state
);
}
else
if
(
value
!=
LED_OFF
&&
!
state
)
{
drv_data
->
led_state
|=
1
<<
i
;
steelseries_srws1_set_leds
(
hid
,
drv_data
->
led_state
);
}
break
;
}
}
static
enum
led_brightness
steelseries_srws1_led_get_brightness
(
struct
led_classdev
*
led_cdev
)
{
struct
device
*
dev
=
led_cdev
->
dev
->
parent
;
struct
hid_device
*
hid
=
container_of
(
dev
,
struct
hid_device
,
dev
);
struct
steelseries_srws1_data
*
drv_data
;
int
i
,
value
=
0
;
drv_data
=
hid_get_drvdata
(
hid
);
if
(
!
drv_data
)
{
hid_err
(
hid
,
"Device data not found."
);
return
LED_OFF
;
}
for
(
i
=
0
;
i
<
SRWS1_NUMBER_LEDS
;
i
++
)
if
(
led_cdev
==
drv_data
->
led
[
i
])
{
value
=
(
drv_data
->
led_state
>>
i
)
&
1
;
break
;
}
return
value
?
LED_FULL
:
LED_OFF
;
}
static
int
steelseries_srws1_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
{
int
ret
,
i
;
struct
led_classdev
*
led
;
size_t
name_sz
;
char
*
name
;
struct
steelseries_srws1_data
*
drv_data
=
kzalloc
(
sizeof
(
*
drv_data
),
GFP_KERNEL
);
if
(
drv_data
==
NULL
)
{
hid_err
(
hdev
,
"can't alloc SRW-S1 memory
\n
"
);
return
-
ENOMEM
;
}
hid_set_drvdata
(
hdev
,
drv_data
);
ret
=
hid_parse
(
hdev
);
if
(
ret
)
{
hid_err
(
hdev
,
"parse failed
\n
"
);
goto
err_free
;
}
ret
=
hid_hw_start
(
hdev
,
HID_CONNECT_DEFAULT
);
if
(
ret
)
{
hid_err
(
hdev
,
"hw start failed
\n
"
);
goto
err_free
;
}
/* register led subsystem */
drv_data
->
led_state
=
0
;
for
(
i
=
0
;
i
<
SRWS1_NUMBER_LEDS
+
1
;
i
++
)
drv_data
->
led
[
i
]
=
NULL
;
steelseries_srws1_set_leds
(
hdev
,
0
);
name_sz
=
strlen
(
hdev
->
uniq
)
+
16
;
/* 'ALL', for setting all LEDs simultaneously */
led
=
kzalloc
(
sizeof
(
struct
led_classdev
)
+
name_sz
,
GFP_KERNEL
);
if
(
!
led
)
{
hid_err
(
hdev
,
"can't allocate memory for LED ALL
\n
"
);
goto
err_led
;
}
name
=
(
void
*
)(
&
led
[
1
]);
snprintf
(
name
,
name_sz
,
"SRWS1::%s::RPMALL"
,
hdev
->
uniq
);
led
->
name
=
name
;
led
->
brightness
=
0
;
led
->
max_brightness
=
1
;
led
->
brightness_get
=
steelseries_srws1_led_all_get_brightness
;
led
->
brightness_set
=
steelseries_srws1_led_all_set_brightness
;
drv_data
->
led
[
SRWS1_NUMBER_LEDS
]
=
led
;
ret
=
led_classdev_register
(
&
hdev
->
dev
,
led
);
if
(
ret
)
goto
err_led
;
/* Each individual LED */
for
(
i
=
0
;
i
<
SRWS1_NUMBER_LEDS
;
i
++
)
{
led
=
kzalloc
(
sizeof
(
struct
led_classdev
)
+
name_sz
,
GFP_KERNEL
);
if
(
!
led
)
{
hid_err
(
hdev
,
"can't allocate memory for LED %d
\n
"
,
i
);
goto
err_led
;
}
name
=
(
void
*
)(
&
led
[
1
]);
snprintf
(
name
,
name_sz
,
"SRWS1::%s::RPM%d"
,
hdev
->
uniq
,
i
+
1
);
led
->
name
=
name
;
led
->
brightness
=
0
;
led
->
max_brightness
=
1
;
led
->
brightness_get
=
steelseries_srws1_led_get_brightness
;
led
->
brightness_set
=
steelseries_srws1_led_set_brightness
;
drv_data
->
led
[
i
]
=
led
;
ret
=
led_classdev_register
(
&
hdev
->
dev
,
led
);
if
(
ret
)
{
hid_err
(
hdev
,
"failed to register LED %d. Aborting.
\n
"
,
i
);
err_led:
/* Deregister all LEDs (if any) */
for
(
i
=
0
;
i
<
SRWS1_NUMBER_LEDS
+
1
;
i
++
)
{
led
=
drv_data
->
led
[
i
];
drv_data
->
led
[
i
]
=
NULL
;
if
(
!
led
)
continue
;
led_classdev_unregister
(
led
);
kfree
(
led
);
}
goto
out
;
/* but let the driver continue without LEDs */
}
}
out:
return
0
;
err_free:
kfree
(
drv_data
);
return
ret
;
}
static
void
steelseries_srws1_remove
(
struct
hid_device
*
hdev
)
{
int
i
;
struct
led_classdev
*
led
;
struct
steelseries_srws1_data
*
drv_data
=
hid_get_drvdata
(
hdev
);
if
(
drv_data
)
{
/* Deregister LEDs (if any) */
for
(
i
=
0
;
i
<
SRWS1_NUMBER_LEDS
+
1
;
i
++
)
{
led
=
drv_data
->
led
[
i
];
drv_data
->
led
[
i
]
=
NULL
;
if
(
!
led
)
continue
;
led_classdev_unregister
(
led
);
kfree
(
led
);
}
}
hid_hw_stop
(
hdev
);
kfree
(
drv_data
);
return
;
}
#endif
static
__u8
*
steelseries_srws1_report_fixup
(
struct
hid_device
*
hdev
,
__u8
*
rdesc
,
unsigned
int
*
rsize
)
{
if
(
*
rsize
>=
115
&&
rdesc
[
11
]
==
0x02
&&
rdesc
[
13
]
==
0xc8
&&
rdesc
[
29
]
==
0xbb
&&
rdesc
[
40
]
==
0xc5
)
{
hid_info
(
hdev
,
"Fixing up Steelseries SRW-S1 report descriptor
\n
"
);
rdesc
=
steelseries_srws1_rdesc_fixed
;
*
rsize
=
sizeof
(
steelseries_srws1_rdesc_fixed
);
}
return
rdesc
;
}
static
const
struct
hid_device_id
steelseries_srws1_devices
[]
=
{
{
HID_USB_DEVICE
(
USB_VENDOR_ID_STEELSERIES
,
USB_DEVICE_ID_STEELSERIES_SRWS1
)
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
steelseries_srws1_devices
);
static
struct
hid_driver
steelseries_srws1_driver
=
{
.
name
=
"steelseries_srws1"
,
.
id_table
=
steelseries_srws1_devices
,
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
.
probe
=
steelseries_srws1_probe
,
.
remove
=
steelseries_srws1_remove
,
#endif
.
report_fixup
=
steelseries_srws1_report_fixup
};
static
int
__init
steelseries_srws1_init
(
void
)
{
return
hid_register_driver
(
&
steelseries_srws1_driver
);
}
static
void
__exit
steelseries_srws1_exit
(
void
)
{
hid_unregister_driver
(
&
steelseries_srws1_driver
);
}
module_init
(
steelseries_srws1_init
);
module_exit
(
steelseries_srws1_exit
);
MODULE_LICENSE
(
"GPL"
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录