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
8c2f421c
Commit
8c2f421c
authored
Jul 28, 2016
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-4.8/hid-led' into for-linus
Conflicts: drivers/hid/hid-thingm.c
parents
e82a82c1
f4c109b6
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
554 additions
and
555 deletions
+554
-555
MAINTAINERS
MAINTAINERS
+0
-5
drivers/hid/Kconfig
drivers/hid/Kconfig
+19
-4
drivers/hid/Makefile
drivers/hid/Makefile
+1
-1
drivers/hid/hid-core.c
drivers/hid/hid-core.c
+5
-3
drivers/hid/hid-ids.h
drivers/hid/hid-ids.h
+6
-0
drivers/hid/hid-led.c
drivers/hid/hid-led.c
+523
-0
drivers/hid/hid-thingm.c
drivers/hid/hid-thingm.c
+0
-259
drivers/usb/misc/Kconfig
drivers/usb/misc/Kconfig
+0
-9
drivers/usb/misc/Makefile
drivers/usb/misc/Makefile
+0
-1
drivers/usb/misc/usbled.c
drivers/usb/misc/usbled.c
+0
-273
No files found.
MAINTAINERS
View file @
8c2f421c
...
...
@@ -11314,11 +11314,6 @@ F: Documentation/thermal/cpu-cooling-api.txt
F: drivers/thermal/cpu_cooling.c
F: include/linux/cpu_cooling.h
THINGM BLINK(1) USB RGB LED DRIVER
M: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
S: Maintained
F: drivers/hid/hid-thingm.c
THINKPAD ACPI EXTRAS DRIVER
M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
L: ibm-acpi-devel@lists.sourceforge.net
...
...
drivers/hid/Kconfig
View file @
8c2f421c
...
...
@@ -388,6 +388,21 @@ config HID_LCPOWER
---help---
Support for LC-Power RC1000MCE RF remote control.
config HID_LED
tristate "Simple RGB LED support"
depends on HID
depends on LEDS_CLASS
---help---
Support for simple RGB LED devices. Currently supported are:
- Riso Kagaku Webmail Notifier
- Dream Cheeky Webmail Notifier and Friends Alert
- ThingM blink(1)
- Delcom Visual Signal Indicator Generation 2
- Greynut Luxafor
To compile this driver as a module, choose M here: the
module will be called hid-led.
config HID_LENOVO
tristate "Lenovo / Thinkpad devices"
depends on HID
...
...
@@ -819,11 +834,11 @@ config HID_THINGM
tristate "ThingM blink(1) USB RGB LED"
depends on HID
depends on LEDS_CLASS
select HID_LED
---help---
Support for the ThingM blink(1) USB RGB LED. This driver registers a
Linux LED class instance, plus additional sysfs attributes to control
RGB colors, fade time and playing. The device is exposed through hidraw
to access other functions.
Support for the ThingM blink(1) USB RGB LED. This driver has been
merged into the generic hid led driver. Config symbol HID_THINGM
just selects HID_LED and will be removed soon.
config HID_THRUSTMASTER
tristate "ThrustMaster devices support"
...
...
drivers/hid/Makefile
View file @
8c2f421c
...
...
@@ -91,12 +91,12 @@ 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
obj-$(CONFIG_HID_THRUSTMASTER)
+=
hid-tmff.o
obj-$(CONFIG_HID_TIVO)
+=
hid-tivo.o
obj-$(CONFIG_HID_TOPSEED)
+=
hid-topseed.o
obj-$(CONFIG_HID_TWINHAN)
+=
hid-twinhan.o
obj-$(CONFIG_HID_UCLOGIC)
+=
hid-uclogic.o
obj-$(CONFIG_HID_LED)
+=
hid-led.o
obj-$(CONFIG_HID_XINMO)
+=
hid-xinmo.o
obj-$(CONFIG_HID_ZEROPLUS)
+=
hid-zpff.o
obj-$(CONFIG_HID_ZYDACRON)
+=
hid-zydacron.o
...
...
drivers/hid/hid-core.c
View file @
8c2f421c
...
...
@@ -1879,8 +1879,11 @@ static const struct hid_device_id hid_have_special_driver[] = {
{
HID_USB_DEVICE
(
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_BARCODE_3
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_BARCODE_4
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_MOUSE
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DELCOM
,
USB_DEVICE_ID_DELCOM_VISUAL_IND
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DRAGONRISE
,
0x0006
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DRAGONRISE
,
0x0011
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DREAM_CHEEKY
,
USB_DEVICE_ID_DREAM_CHEEKY_WN
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DREAM_CHEEKY
,
USB_DEVICE_ID_DREAM_CHEEKY_FA
)
},
{
HID_BLUETOOTH_DEVICE
(
USB_VENDOR_ID_ELECOM
,
USB_DEVICE_ID_ELECOM_BM084
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_ELO
,
0x0009
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_ELO
,
0x0030
)
},
...
...
@@ -1964,6 +1967,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{
HID_USB_DEVICE
(
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_SPACENAVIGATOR
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROCHIP
,
USB_DEVICE_ID_PICOLCD
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROCHIP
,
USB_DEVICE_ID_PICOLCD_BOOTLOADER
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROCHIP
,
USB_DEVICE_ID_LUXAFOR
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROSOFT
,
USB_DEVICE_ID_MS_COMFORT_MOUSE_4500
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROSOFT
,
USB_DEVICE_ID_MS_COMFORT_KEYBOARD
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROSOFT
,
USB_DEVICE_ID_SIDEWINDER_GV
)
},
...
...
@@ -2010,6 +2014,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{
HID_USB_DEVICE
(
USB_VENDOR_ID_PETALYNX
,
USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_PLANTRONICS
,
HID_ANY_ID
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_PRIMAX
,
USB_DEVICE_ID_PRIMAX_KEYBOARD
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_RISO_KAGAKU
,
USB_DEVICE_ID_RI_KA_WEBMAIL
)
},
#if IS_ENABLED(CONFIG_HID_ROCCAT)
{
HID_USB_DEVICE
(
USB_VENDOR_ID_ROCCAT
,
USB_DEVICE_ID_ROCCAT_ARVO
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_ROCCAT
,
USB_DEVICE_ID_ROCCAT_ISKU
)
},
...
...
@@ -2350,8 +2355,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DEALEXTREAME
,
USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DELORME
,
USB_DEVICE_ID_DELORME_EARTHMATE
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DELORME
,
USB_DEVICE_ID_DELORME_EM_LT20
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DREAM_CHEEKY
,
0x0004
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DREAM_CHEEKY
,
0x000a
)
},
{
HID_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
0x0400
)
},
{
HID_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
0x0401
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_ESSENTIAL_REALITY
,
USB_DEVICE_ID_ESSENTIAL_REALITY_P5
)
},
...
...
@@ -2488,7 +2491,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{
HID_USB_DEVICE
(
USB_VENDOR_ID_SYNAPTICS
,
USB_DEVICE_ID_SYNAPTICS_DPAD
)
},
#endif
{
HID_USB_DEVICE
(
USB_VENDOR_ID_YEALINK
,
USB_DEVICE_ID_YEALINK_P1K_P4K_B2K
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_RISO_KAGAKU
,
USB_DEVICE_ID_RI_KA_WEBMAIL
)
},
{
}
};
...
...
drivers/hid/hid-ids.h
View file @
8c2f421c
...
...
@@ -300,6 +300,9 @@
#define USB_VENDOR_ID_DEALEXTREAME 0x10c5
#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a
#define USB_VENDOR_ID_DELCOM 0x0fc5
#define USB_DEVICE_ID_DELCOM_VISUAL_IND 0xb080
#define USB_VENDOR_ID_DELORME 0x1163
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
...
...
@@ -338,6 +341,8 @@
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34
#define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004
#define USB_DEVICE_ID_DREAM_CHEEKY_FA 0x000a
#define USB_VENDOR_ID_ELITEGROUP 0x03fc
#define USB_DEVICE_ID_ELITEGROUP_05D8 0x05d8
...
...
@@ -684,6 +689,7 @@
#define USB_DEVICE_ID_PICOLCD_BOOTLOADER 0xf002
#define USB_DEVICE_ID_PICK16F1454 0x0042
#define USB_DEVICE_ID_PICK16F1454_V2 0xf2f7
#define USB_DEVICE_ID_LUXAFOR 0xf372
#define USB_VENDOR_ID_MICROSOFT 0x045e
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
...
...
drivers/hid/hid-led.c
0 → 100644
View file @
8c2f421c
/*
* Simple USB RGB LED driver
*
* Copyright 2016 Heiner Kallweit <hkallweit1@gmail.com>
* Based on drivers/hid/hid-thingm.c and
* drivers/usb/misc/usbled.c
*
* 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, version 2.
*/
#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include "hid-ids.h"
enum
hidled_report_type
{
RAW_REQUEST
,
OUTPUT_REPORT
};
enum
hidled_type
{
RISO_KAGAKU
,
DREAM_CHEEKY
,
THINGM
,
DELCOM
,
LUXAFOR
,
};
static
unsigned
const
char
riso_kagaku_tbl
[]
=
{
/* R+2G+4B -> riso kagaku color index */
[
0
]
=
0
,
/* black */
[
1
]
=
2
,
/* red */
[
2
]
=
1
,
/* green */
[
3
]
=
5
,
/* yellow */
[
4
]
=
3
,
/* blue */
[
5
]
=
6
,
/* magenta */
[
6
]
=
4
,
/* cyan */
[
7
]
=
7
/* white */
};
#define RISO_KAGAKU_IX(r, g, b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)]
union
delcom_packet
{
__u8
data
[
8
];
struct
{
__u8
major_cmd
;
__u8
minor_cmd
;
__u8
data_lsb
;
__u8
data_msb
;
}
tx
;
struct
{
__u8
cmd
;
}
rx
;
struct
{
__le16
family_code
;
__le16
security_code
;
__u8
fw_version
;
}
fw
;
};
#define DELCOM_GREEN_LED 0
#define DELCOM_RED_LED 1
#define DELCOM_BLUE_LED 2
struct
hidled_device
;
struct
hidled_rgb
;
struct
hidled_config
{
enum
hidled_type
type
;
const
char
*
name
;
const
char
*
short_name
;
enum
led_brightness
max_brightness
;
int
num_leds
;
size_t
report_size
;
enum
hidled_report_type
report_type
;
int
(
*
init
)(
struct
hidled_device
*
ldev
);
int
(
*
write
)(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
);
};
struct
hidled_led
{
struct
led_classdev
cdev
;
struct
hidled_rgb
*
rgb
;
char
name
[
32
];
};
struct
hidled_rgb
{
struct
hidled_device
*
ldev
;
struct
hidled_led
red
;
struct
hidled_led
green
;
struct
hidled_led
blue
;
u8
num
;
};
struct
hidled_device
{
const
struct
hidled_config
*
config
;
struct
hid_device
*
hdev
;
struct
hidled_rgb
*
rgb
;
struct
mutex
lock
;
};
#define MAX_REPORT_SIZE 16
#define to_hidled_led(arg) container_of(arg, struct hidled_led, cdev)
static
bool
riso_kagaku_switch_green_blue
;
module_param
(
riso_kagaku_switch_green_blue
,
bool
,
S_IRUGO
|
S_IWUSR
);
MODULE_PARM_DESC
(
riso_kagaku_switch_green_blue
,
"switch green and blue RGB component for Riso Kagaku devices"
);
static
int
hidled_send
(
struct
hidled_device
*
ldev
,
__u8
*
buf
)
{
int
ret
;
mutex_lock
(
&
ldev
->
lock
);
if
(
ldev
->
config
->
report_type
==
RAW_REQUEST
)
ret
=
hid_hw_raw_request
(
ldev
->
hdev
,
buf
[
0
],
buf
,
ldev
->
config
->
report_size
,
HID_FEATURE_REPORT
,
HID_REQ_SET_REPORT
);
else
if
(
ldev
->
config
->
report_type
==
OUTPUT_REPORT
)
ret
=
hid_hw_output_report
(
ldev
->
hdev
,
buf
,
ldev
->
config
->
report_size
);
else
ret
=
-
EINVAL
;
mutex_unlock
(
&
ldev
->
lock
);
if
(
ret
<
0
)
return
ret
;
return
ret
==
ldev
->
config
->
report_size
?
0
:
-
EMSGSIZE
;
}
/* reading data is supported for report type RAW_REQUEST only */
static
int
hidled_recv
(
struct
hidled_device
*
ldev
,
__u8
*
buf
)
{
int
ret
;
if
(
ldev
->
config
->
report_type
!=
RAW_REQUEST
)
return
-
EINVAL
;
mutex_lock
(
&
ldev
->
lock
);
ret
=
hid_hw_raw_request
(
ldev
->
hdev
,
buf
[
0
],
buf
,
ldev
->
config
->
report_size
,
HID_FEATURE_REPORT
,
HID_REQ_SET_REPORT
);
if
(
ret
<
0
)
goto
err
;
ret
=
hid_hw_raw_request
(
ldev
->
hdev
,
buf
[
0
],
buf
,
ldev
->
config
->
report_size
,
HID_FEATURE_REPORT
,
HID_REQ_GET_REPORT
);
err:
mutex_unlock
(
&
ldev
->
lock
);
return
ret
<
0
?
ret
:
0
;
}
static
u8
riso_kagaku_index
(
struct
hidled_rgb
*
rgb
)
{
enum
led_brightness
r
,
g
,
b
;
r
=
rgb
->
red
.
cdev
.
brightness
;
g
=
rgb
->
green
.
cdev
.
brightness
;
b
=
rgb
->
blue
.
cdev
.
brightness
;
if
(
riso_kagaku_switch_green_blue
)
return
RISO_KAGAKU_IX
(
r
,
b
,
g
);
else
return
RISO_KAGAKU_IX
(
r
,
g
,
b
);
}
static
int
riso_kagaku_write
(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
)
{
struct
hidled_led
*
led
=
to_hidled_led
(
cdev
);
struct
hidled_rgb
*
rgb
=
led
->
rgb
;
__u8
buf
[
MAX_REPORT_SIZE
]
=
{};
buf
[
1
]
=
riso_kagaku_index
(
rgb
);
return
hidled_send
(
rgb
->
ldev
,
buf
);
}
static
int
dream_cheeky_write
(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
)
{
struct
hidled_led
*
led
=
to_hidled_led
(
cdev
);
struct
hidled_rgb
*
rgb
=
led
->
rgb
;
__u8
buf
[
MAX_REPORT_SIZE
]
=
{};
buf
[
1
]
=
rgb
->
red
.
cdev
.
brightness
;
buf
[
2
]
=
rgb
->
green
.
cdev
.
brightness
;
buf
[
3
]
=
rgb
->
blue
.
cdev
.
brightness
;
buf
[
7
]
=
0x1a
;
buf
[
8
]
=
0x05
;
return
hidled_send
(
rgb
->
ldev
,
buf
);
}
static
int
dream_cheeky_init
(
struct
hidled_device
*
ldev
)
{
__u8
buf
[
MAX_REPORT_SIZE
]
=
{};
/* Dream Cheeky magic */
buf
[
1
]
=
0x1f
;
buf
[
2
]
=
0x02
;
buf
[
4
]
=
0x5f
;
buf
[
7
]
=
0x1a
;
buf
[
8
]
=
0x03
;
return
hidled_send
(
ldev
,
buf
);
}
static
int
_thingm_write
(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
,
u8
offset
)
{
struct
hidled_led
*
led
=
to_hidled_led
(
cdev
);
__u8
buf
[
MAX_REPORT_SIZE
]
=
{
1
,
'c'
};
buf
[
2
]
=
led
->
rgb
->
red
.
cdev
.
brightness
;
buf
[
3
]
=
led
->
rgb
->
green
.
cdev
.
brightness
;
buf
[
4
]
=
led
->
rgb
->
blue
.
cdev
.
brightness
;
buf
[
7
]
=
led
->
rgb
->
num
+
offset
;
return
hidled_send
(
led
->
rgb
->
ldev
,
buf
);
}
static
int
thingm_write_v1
(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
)
{
return
_thingm_write
(
cdev
,
br
,
0
);
}
static
int
thingm_write
(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
)
{
return
_thingm_write
(
cdev
,
br
,
1
);
}
static
const
struct
hidled_config
hidled_config_thingm_v1
=
{
.
name
=
"ThingM blink(1) v1"
,
.
short_name
=
"thingm"
,
.
max_brightness
=
255
,
.
num_leds
=
1
,
.
report_size
=
9
,
.
report_type
=
RAW_REQUEST
,
.
write
=
thingm_write_v1
,
};
static
int
thingm_init
(
struct
hidled_device
*
ldev
)
{
__u8
buf
[
MAX_REPORT_SIZE
]
=
{
1
,
'v'
};
int
ret
;
ret
=
hidled_recv
(
ldev
,
buf
);
if
(
ret
)
return
ret
;
/* Check for firmware major version 1 */
if
(
buf
[
3
]
==
'1'
)
ldev
->
config
=
&
hidled_config_thingm_v1
;
return
0
;
}
static
inline
int
delcom_get_lednum
(
const
struct
hidled_led
*
led
)
{
if
(
led
==
&
led
->
rgb
->
red
)
return
DELCOM_RED_LED
;
else
if
(
led
==
&
led
->
rgb
->
green
)
return
DELCOM_GREEN_LED
;
else
return
DELCOM_BLUE_LED
;
}
static
int
delcom_enable_led
(
struct
hidled_led
*
led
)
{
union
delcom_packet
dp
=
{
.
tx
.
major_cmd
=
101
,
.
tx
.
minor_cmd
=
12
};
dp
.
tx
.
data_lsb
=
1
<<
delcom_get_lednum
(
led
);
dp
.
tx
.
data_msb
=
0
;
return
hidled_send
(
led
->
rgb
->
ldev
,
dp
.
data
);
}
static
int
delcom_set_pwm
(
struct
hidled_led
*
led
)
{
union
delcom_packet
dp
=
{
.
tx
.
major_cmd
=
101
,
.
tx
.
minor_cmd
=
34
};
dp
.
tx
.
data_lsb
=
delcom_get_lednum
(
led
);
dp
.
tx
.
data_msb
=
led
->
cdev
.
brightness
;
return
hidled_send
(
led
->
rgb
->
ldev
,
dp
.
data
);
}
static
int
delcom_write
(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
)
{
struct
hidled_led
*
led
=
to_hidled_led
(
cdev
);
int
ret
;
/*
* enable LED
* We can't do this in the init function already because the device
* is internally reset later.
*/
ret
=
delcom_enable_led
(
led
);
if
(
ret
)
return
ret
;
return
delcom_set_pwm
(
led
);
}
static
int
delcom_init
(
struct
hidled_device
*
ldev
)
{
union
delcom_packet
dp
=
{
.
rx
.
cmd
=
104
};
int
ret
;
ret
=
hidled_recv
(
ldev
,
dp
.
data
);
if
(
ret
)
return
ret
;
/*
* Several Delcom devices share the same USB VID/PID
* Check for family id 2 for Visual Signal Indicator
*/
return
le16_to_cpu
(
dp
.
fw
.
family_code
)
==
2
?
0
:
-
ENODEV
;
}
static
int
luxafor_write
(
struct
led_classdev
*
cdev
,
enum
led_brightness
br
)
{
struct
hidled_led
*
led
=
to_hidled_led
(
cdev
);
__u8
buf
[
MAX_REPORT_SIZE
]
=
{
[
1
]
=
1
};
buf
[
2
]
=
led
->
rgb
->
num
+
1
;
buf
[
3
]
=
led
->
rgb
->
red
.
cdev
.
brightness
;
buf
[
4
]
=
led
->
rgb
->
green
.
cdev
.
brightness
;
buf
[
5
]
=
led
->
rgb
->
blue
.
cdev
.
brightness
;
return
hidled_send
(
led
->
rgb
->
ldev
,
buf
);
}
static
const
struct
hidled_config
hidled_configs
[]
=
{
{
.
type
=
RISO_KAGAKU
,
.
name
=
"Riso Kagaku Webmail Notifier"
,
.
short_name
=
"riso_kagaku"
,
.
max_brightness
=
1
,
.
num_leds
=
1
,
.
report_size
=
6
,
.
report_type
=
OUTPUT_REPORT
,
.
write
=
riso_kagaku_write
,
},
{
.
type
=
DREAM_CHEEKY
,
.
name
=
"Dream Cheeky Webmail Notifier"
,
.
short_name
=
"dream_cheeky"
,
.
max_brightness
=
31
,
.
num_leds
=
1
,
.
report_size
=
9
,
.
report_type
=
RAW_REQUEST
,
.
init
=
dream_cheeky_init
,
.
write
=
dream_cheeky_write
,
},
{
.
type
=
THINGM
,
.
name
=
"ThingM blink(1)"
,
.
short_name
=
"thingm"
,
.
max_brightness
=
255
,
.
num_leds
=
2
,
.
report_size
=
9
,
.
report_type
=
RAW_REQUEST
,
.
init
=
thingm_init
,
.
write
=
thingm_write
,
},
{
.
type
=
DELCOM
,
.
name
=
"Delcom Visual Signal Indicator G2"
,
.
short_name
=
"delcom"
,
.
max_brightness
=
100
,
.
num_leds
=
1
,
.
report_size
=
8
,
.
report_type
=
RAW_REQUEST
,
.
init
=
delcom_init
,
.
write
=
delcom_write
,
},
{
.
type
=
LUXAFOR
,
.
name
=
"Greynut Luxafor"
,
.
short_name
=
"luxafor"
,
.
max_brightness
=
255
,
.
num_leds
=
6
,
.
report_size
=
9
,
.
report_type
=
OUTPUT_REPORT
,
.
write
=
luxafor_write
,
},
};
static
int
hidled_init_led
(
struct
hidled_led
*
led
,
const
char
*
color_name
,
struct
hidled_rgb
*
rgb
,
unsigned
int
minor
)
{
const
struct
hidled_config
*
config
=
rgb
->
ldev
->
config
;
if
(
config
->
num_leds
>
1
)
snprintf
(
led
->
name
,
sizeof
(
led
->
name
),
"%s%u:%s:led%u"
,
config
->
short_name
,
minor
,
color_name
,
rgb
->
num
);
else
snprintf
(
led
->
name
,
sizeof
(
led
->
name
),
"%s%u:%s"
,
config
->
short_name
,
minor
,
color_name
);
led
->
cdev
.
name
=
led
->
name
;
led
->
cdev
.
max_brightness
=
config
->
max_brightness
;
led
->
cdev
.
brightness_set_blocking
=
config
->
write
;
led
->
cdev
.
flags
=
LED_HW_PLUGGABLE
;
led
->
rgb
=
rgb
;
return
devm_led_classdev_register
(
&
rgb
->
ldev
->
hdev
->
dev
,
&
led
->
cdev
);
}
static
int
hidled_init_rgb
(
struct
hidled_rgb
*
rgb
,
unsigned
int
minor
)
{
int
ret
;
/* Register the red diode */
ret
=
hidled_init_led
(
&
rgb
->
red
,
"red"
,
rgb
,
minor
);
if
(
ret
)
return
ret
;
/* Register the green diode */
ret
=
hidled_init_led
(
&
rgb
->
green
,
"green"
,
rgb
,
minor
);
if
(
ret
)
return
ret
;
/* Register the blue diode */
return
hidled_init_led
(
&
rgb
->
blue
,
"blue"
,
rgb
,
minor
);
}
static
int
hidled_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
{
struct
hidled_device
*
ldev
;
unsigned
int
minor
;
int
ret
,
i
;
ldev
=
devm_kzalloc
(
&
hdev
->
dev
,
sizeof
(
*
ldev
),
GFP_KERNEL
);
if
(
!
ldev
)
return
-
ENOMEM
;
ret
=
hid_parse
(
hdev
);
if
(
ret
)
return
ret
;
ldev
->
hdev
=
hdev
;
mutex_init
(
&
ldev
->
lock
);
for
(
i
=
0
;
!
ldev
->
config
&&
i
<
ARRAY_SIZE
(
hidled_configs
);
i
++
)
if
(
hidled_configs
[
i
].
type
==
id
->
driver_data
)
ldev
->
config
=
&
hidled_configs
[
i
];
if
(
!
ldev
->
config
)
return
-
EINVAL
;
if
(
ldev
->
config
->
init
)
{
ret
=
ldev
->
config
->
init
(
ldev
);
if
(
ret
)
return
ret
;
}
ldev
->
rgb
=
devm_kcalloc
(
&
hdev
->
dev
,
ldev
->
config
->
num_leds
,
sizeof
(
struct
hidled_rgb
),
GFP_KERNEL
);
if
(
!
ldev
->
rgb
)
return
-
ENOMEM
;
ret
=
hid_hw_start
(
hdev
,
HID_CONNECT_HIDRAW
);
if
(
ret
)
return
ret
;
minor
=
((
struct
hidraw
*
)
hdev
->
hidraw
)
->
minor
;
for
(
i
=
0
;
i
<
ldev
->
config
->
num_leds
;
i
++
)
{
ldev
->
rgb
[
i
].
ldev
=
ldev
;
ldev
->
rgb
[
i
].
num
=
i
;
ret
=
hidled_init_rgb
(
&
ldev
->
rgb
[
i
],
minor
);
if
(
ret
)
{
hid_hw_stop
(
hdev
);
return
ret
;
}
}
hid_info
(
hdev
,
"%s initialized
\n
"
,
ldev
->
config
->
name
);
return
0
;
}
static
const
struct
hid_device_id
hidled_table
[]
=
{
{
HID_USB_DEVICE
(
USB_VENDOR_ID_RISO_KAGAKU
,
USB_DEVICE_ID_RI_KA_WEBMAIL
),
.
driver_data
=
RISO_KAGAKU
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DREAM_CHEEKY
,
USB_DEVICE_ID_DREAM_CHEEKY_WN
),
.
driver_data
=
DREAM_CHEEKY
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DREAM_CHEEKY
,
USB_DEVICE_ID_DREAM_CHEEKY_FA
),
.
driver_data
=
DREAM_CHEEKY
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_THINGM
,
USB_DEVICE_ID_BLINK1
),
.
driver_data
=
THINGM
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_DELCOM
,
USB_DEVICE_ID_DELCOM_VISUAL_IND
),
.
driver_data
=
DELCOM
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROCHIP
,
USB_DEVICE_ID_LUXAFOR
),
.
driver_data
=
LUXAFOR
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
hidled_table
);
static
struct
hid_driver
hidled_driver
=
{
.
name
=
"hid-led"
,
.
probe
=
hidled_probe
,
.
id_table
=
hidled_table
,
};
module_hid_driver
(
hidled_driver
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Heiner Kallweit <hkallweit1@gmail.com>"
);
MODULE_DESCRIPTION
(
"Simple USB RGB LED driver"
);
drivers/hid/hid-thingm.c
deleted
100644 → 0
View file @
e82a82c1
/*
* ThingM blink(1) USB RGB LED driver
*
* Copyright 2013-2014 Savoir-faire Linux Inc.
* Vivien Didelot <vivien.didelot@savoirfairelinux.com>
*
* 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, version 2.
*/
#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include "hid-ids.h"
#define REPORT_ID 1
#define REPORT_SIZE 9
/* Firmware major number of supported devices */
#define THINGM_MAJOR_MK1 '1'
#define THINGM_MAJOR_MK2 '2'
struct
thingm_fwinfo
{
char
major
;
unsigned
numrgb
;
unsigned
first
;
};
static
const
struct
thingm_fwinfo
thingm_fwinfo
[]
=
{
{
.
major
=
THINGM_MAJOR_MK1
,
.
numrgb
=
1
,
.
first
=
0
,
},
{
.
major
=
THINGM_MAJOR_MK2
,
.
numrgb
=
2
,
.
first
=
1
,
}
};
/* A red, green or blue channel, part of an RGB chip */
struct
thingm_led
{
struct
thingm_rgb
*
rgb
;
struct
led_classdev
ldev
;
char
name
[
32
];
};
/* Basically a WS2812 5050 RGB LED chip */
struct
thingm_rgb
{
struct
thingm_device
*
tdev
;
struct
thingm_led
red
;
struct
thingm_led
green
;
struct
thingm_led
blue
;
u8
num
;
};
struct
thingm_device
{
struct
hid_device
*
hdev
;
struct
{
char
major
;
char
minor
;
}
version
;
const
struct
thingm_fwinfo
*
fwinfo
;
struct
mutex
lock
;
struct
thingm_rgb
*
rgb
;
};
static
int
thingm_send
(
struct
thingm_device
*
tdev
,
u8
buf
[
REPORT_SIZE
])
{
int
ret
;
hid_dbg
(
tdev
->
hdev
,
"-> %d %c %7ph
\n
"
,
buf
[
0
],
buf
[
1
],
&
buf
[
2
]);
mutex_lock
(
&
tdev
->
lock
);
ret
=
hid_hw_raw_request
(
tdev
->
hdev
,
buf
[
0
],
buf
,
REPORT_SIZE
,
HID_FEATURE_REPORT
,
HID_REQ_SET_REPORT
);
mutex_unlock
(
&
tdev
->
lock
);
return
ret
<
0
?
ret
:
0
;
}
static
int
thingm_recv
(
struct
thingm_device
*
tdev
,
u8
buf
[
REPORT_SIZE
])
{
int
ret
;
/*
* A read consists of two operations: sending the read command
* and the actual read from the device. Use the mutex to protect
* the full sequence of both operations.
*/
mutex_lock
(
&
tdev
->
lock
);
ret
=
hid_hw_raw_request
(
tdev
->
hdev
,
buf
[
0
],
buf
,
REPORT_SIZE
,
HID_FEATURE_REPORT
,
HID_REQ_SET_REPORT
);
if
(
ret
<
0
)
goto
err
;
ret
=
hid_hw_raw_request
(
tdev
->
hdev
,
buf
[
0
],
buf
,
REPORT_SIZE
,
HID_FEATURE_REPORT
,
HID_REQ_GET_REPORT
);
if
(
ret
<
0
)
goto
err
;
ret
=
0
;
hid_dbg
(
tdev
->
hdev
,
"<- %d %c %7ph
\n
"
,
buf
[
0
],
buf
[
1
],
&
buf
[
2
]);
err:
mutex_unlock
(
&
tdev
->
lock
);
return
ret
;
}
static
int
thingm_version
(
struct
thingm_device
*
tdev
)
{
u8
buf
[
REPORT_SIZE
]
=
{
REPORT_ID
,
'v'
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
int
err
;
err
=
thingm_recv
(
tdev
,
buf
);
if
(
err
)
return
err
;
tdev
->
version
.
major
=
buf
[
3
];
tdev
->
version
.
minor
=
buf
[
4
];
return
0
;
}
static
int
thingm_write_color
(
struct
thingm_rgb
*
rgb
)
{
u8
buf
[
REPORT_SIZE
]
=
{
REPORT_ID
,
'c'
,
0
,
0
,
0
,
0
,
0
,
rgb
->
num
,
0
};
buf
[
2
]
=
rgb
->
red
.
ldev
.
brightness
;
buf
[
3
]
=
rgb
->
green
.
ldev
.
brightness
;
buf
[
4
]
=
rgb
->
blue
.
ldev
.
brightness
;
return
thingm_send
(
rgb
->
tdev
,
buf
);
}
static
int
thingm_led_set
(
struct
led_classdev
*
ldev
,
enum
led_brightness
brightness
)
{
struct
thingm_led
*
led
=
container_of
(
ldev
,
struct
thingm_led
,
ldev
);
return
thingm_write_color
(
led
->
rgb
);
}
static
int
thingm_init_led
(
struct
thingm_led
*
led
,
const
char
*
color_name
,
struct
thingm_rgb
*
rgb
,
int
minor
)
{
snprintf
(
led
->
name
,
sizeof
(
led
->
name
),
"thingm%d:%s:led%d"
,
minor
,
color_name
,
rgb
->
num
);
led
->
ldev
.
name
=
led
->
name
;
led
->
ldev
.
max_brightness
=
255
;
led
->
ldev
.
brightness_set_blocking
=
thingm_led_set
;
led
->
ldev
.
flags
=
LED_HW_PLUGGABLE
;
led
->
rgb
=
rgb
;
return
devm_led_classdev_register
(
&
rgb
->
tdev
->
hdev
->
dev
,
&
led
->
ldev
);
}
static
int
thingm_init_rgb
(
struct
thingm_rgb
*
rgb
)
{
const
int
minor
=
((
struct
hidraw
*
)
rgb
->
tdev
->
hdev
->
hidraw
)
->
minor
;
int
err
;
/* Register the red diode */
err
=
thingm_init_led
(
&
rgb
->
red
,
"red"
,
rgb
,
minor
);
if
(
err
)
return
err
;
/* Register the green diode */
err
=
thingm_init_led
(
&
rgb
->
green
,
"green"
,
rgb
,
minor
);
if
(
err
)
return
err
;
/* Register the blue diode */
return
thingm_init_led
(
&
rgb
->
blue
,
"blue"
,
rgb
,
minor
);
}
static
int
thingm_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
{
struct
thingm_device
*
tdev
;
int
i
,
err
;
tdev
=
devm_kzalloc
(
&
hdev
->
dev
,
sizeof
(
struct
thingm_device
),
GFP_KERNEL
);
if
(
!
tdev
)
return
-
ENOMEM
;
tdev
->
hdev
=
hdev
;
hid_set_drvdata
(
hdev
,
tdev
);
err
=
hid_parse
(
hdev
);
if
(
err
)
return
err
;
mutex_init
(
&
tdev
->
lock
);
err
=
thingm_version
(
tdev
);
if
(
err
)
return
err
;
hid_dbg
(
hdev
,
"firmware version: %c.%c
\n
"
,
tdev
->
version
.
major
,
tdev
->
version
.
minor
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
thingm_fwinfo
)
&&
!
tdev
->
fwinfo
;
++
i
)
if
(
thingm_fwinfo
[
i
].
major
==
tdev
->
version
.
major
)
tdev
->
fwinfo
=
&
thingm_fwinfo
[
i
];
if
(
!
tdev
->
fwinfo
)
{
hid_err
(
hdev
,
"unsupported firmware %c
\n
"
,
tdev
->
version
.
major
);
return
-
ENODEV
;
}
tdev
->
rgb
=
devm_kzalloc
(
&
hdev
->
dev
,
sizeof
(
struct
thingm_rgb
)
*
tdev
->
fwinfo
->
numrgb
,
GFP_KERNEL
);
if
(
!
tdev
->
rgb
)
return
-
ENOMEM
;
err
=
hid_hw_start
(
hdev
,
HID_CONNECT_HIDRAW
);
if
(
err
)
return
err
;
for
(
i
=
0
;
i
<
tdev
->
fwinfo
->
numrgb
;
++
i
)
{
struct
thingm_rgb
*
rgb
=
tdev
->
rgb
+
i
;
rgb
->
tdev
=
tdev
;
rgb
->
num
=
tdev
->
fwinfo
->
first
+
i
;
err
=
thingm_init_rgb
(
rgb
);
if
(
err
)
{
hid_hw_stop
(
hdev
);
return
err
;
}
}
return
0
;
}
static
const
struct
hid_device_id
thingm_table
[]
=
{
{
HID_USB_DEVICE
(
USB_VENDOR_ID_THINGM
,
USB_DEVICE_ID_BLINK1
)
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
thingm_table
);
static
struct
hid_driver
thingm_driver
=
{
.
name
=
"thingm"
,
.
probe
=
thingm_probe
,
.
id_table
=
thingm_table
,
};
module_hid_driver
(
thingm_driver
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Vivien Didelot <vivien.didelot@savoirfairelinux.com>"
);
MODULE_DESCRIPTION
(
"ThingM blink(1) USB RGB LED driver"
);
drivers/usb/misc/Kconfig
View file @
8c2f421c
...
...
@@ -79,15 +79,6 @@ config USB_LCD
To compile this driver as a module, choose M here: the
module will be called usblcd.
config USB_LED
tristate "USB LED driver support"
help
Say Y here if you want to connect an USBLED device to your
computer's USB port.
To compile this driver as a module, choose M here: the
module will be called usbled.
config USB_CYPRESS_CY7C63
tristate "Cypress CY7C63xxx USB driver support"
help
...
...
drivers/usb/misc/Makefile
View file @
8c2f421c
...
...
@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o
obj-$(CONFIG_USB_ISIGHTFW)
+=
isight_firmware.o
obj-$(CONFIG_USB_LCD)
+=
usblcd.o
obj-$(CONFIG_USB_LD)
+=
ldusb.o
obj-$(CONFIG_USB_LED)
+=
usbled.o
obj-$(CONFIG_USB_LEGOTOWER)
+=
legousbtower.o
obj-$(CONFIG_USB_RIO500)
+=
rio500.o
obj-$(CONFIG_USB_TEST)
+=
usbtest.o
...
...
drivers/usb/misc/usbled.c
deleted
100644 → 0
View file @
e82a82c1
/*
* USB LED driver
*
* Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
*
* 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, version 2.
*
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
#define DRIVER_DESC "USB LED Driver"
enum
led_type
{
DELCOM_VISUAL_SIGNAL_INDICATOR
,
DREAM_CHEEKY_WEBMAIL_NOTIFIER
,
RISO_KAGAKU_LED
};
/* the Webmail LED made by RISO KAGAKU CORP. decodes a color index
internally, we want to keep the red+green+blue sysfs api, so we decode
from 1-bit RGB to the riso kagaku color index according to this table... */
static
unsigned
const
char
riso_kagaku_tbl
[]
=
{
/* R+2G+4B -> riso kagaku color index */
[
0
]
=
0
,
/* black */
[
1
]
=
2
,
/* red */
[
2
]
=
1
,
/* green */
[
3
]
=
5
,
/* yellow */
[
4
]
=
3
,
/* blue */
[
5
]
=
6
,
/* magenta */
[
6
]
=
4
,
/* cyan */
[
7
]
=
7
/* white */
};
#define RISO_KAGAKU_IX(r,g,b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)]
/* table of devices that work with this driver */
static
const
struct
usb_device_id
id_table
[]
=
{
{
USB_DEVICE
(
0x0fc5
,
0x1223
),
.
driver_info
=
DELCOM_VISUAL_SIGNAL_INDICATOR
},
{
USB_DEVICE
(
0x1d34
,
0x0004
),
.
driver_info
=
DREAM_CHEEKY_WEBMAIL_NOTIFIER
},
{
USB_DEVICE
(
0x1d34
,
0x000a
),
.
driver_info
=
DREAM_CHEEKY_WEBMAIL_NOTIFIER
},
{
USB_DEVICE
(
0x1294
,
0x1320
),
.
driver_info
=
RISO_KAGAKU_LED
},
{
},
};
MODULE_DEVICE_TABLE
(
usb
,
id_table
);
struct
usb_led
{
struct
usb_device
*
udev
;
unsigned
char
blue
;
unsigned
char
red
;
unsigned
char
green
;
enum
led_type
type
;
};
static
void
change_color
(
struct
usb_led
*
led
)
{
int
retval
=
0
;
unsigned
char
*
buffer
;
int
actlength
;
buffer
=
kmalloc
(
8
,
GFP_KERNEL
);
if
(
!
buffer
)
{
dev_err
(
&
led
->
udev
->
dev
,
"out of memory
\n
"
);
return
;
}
switch
(
led
->
type
)
{
case
DELCOM_VISUAL_SIGNAL_INDICATOR
:
{
unsigned
char
color
=
0x07
;
if
(
led
->
blue
)
color
&=
~
0x04
;
if
(
led
->
red
)
color
&=
~
0x02
;
if
(
led
->
green
)
color
&=
~
0x01
;
dev_dbg
(
&
led
->
udev
->
dev
,
"blue = %d, red = %d, green = %d, color = %.2x
\n
"
,
led
->
blue
,
led
->
red
,
led
->
green
,
color
);
retval
=
usb_control_msg
(
led
->
udev
,
usb_sndctrlpipe
(
led
->
udev
,
0
),
0x12
,
0xc8
,
(
0x02
*
0x100
)
+
0x0a
,
(
0x00
*
0x100
)
+
color
,
buffer
,
8
,
2000
);
break
;
}
case
DREAM_CHEEKY_WEBMAIL_NOTIFIER
:
dev_dbg
(
&
led
->
udev
->
dev
,
"red = %d, green = %d, blue = %d
\n
"
,
led
->
red
,
led
->
green
,
led
->
blue
);
buffer
[
0
]
=
led
->
red
;
buffer
[
1
]
=
led
->
green
;
buffer
[
2
]
=
led
->
blue
;
buffer
[
3
]
=
buffer
[
4
]
=
buffer
[
5
]
=
0
;
buffer
[
6
]
=
0x1a
;
buffer
[
7
]
=
0x05
;
retval
=
usb_control_msg
(
led
->
udev
,
usb_sndctrlpipe
(
led
->
udev
,
0
),
0x09
,
0x21
,
0x200
,
0
,
buffer
,
8
,
2000
);
break
;
case
RISO_KAGAKU_LED
:
buffer
[
0
]
=
RISO_KAGAKU_IX
(
led
->
red
,
led
->
green
,
led
->
blue
);
buffer
[
1
]
=
0
;
buffer
[
2
]
=
0
;
buffer
[
3
]
=
0
;
buffer
[
4
]
=
0
;
retval
=
usb_interrupt_msg
(
led
->
udev
,
usb_sndctrlpipe
(
led
->
udev
,
2
),
buffer
,
5
,
&
actlength
,
1000
/*ms timeout*/
);
break
;
default:
dev_err
(
&
led
->
udev
->
dev
,
"unknown device type %d
\n
"
,
led
->
type
);
}
if
(
retval
)
dev_dbg
(
&
led
->
udev
->
dev
,
"retval = %d
\n
"
,
retval
);
kfree
(
buffer
);
}
#define show_set(value) \
static ssize_t show_##value(struct device *dev, struct device_attribute *attr,\
char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", led->value); \
} \
static ssize_t set_##value(struct device *dev, struct device_attribute *attr,\
const char *buf, size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
int temp = simple_strtoul(buf, NULL, 10); \
\
led->value = temp; \
change_color(led); \
return count; \
} \
static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, show_##value, set_##value);
show_set
(
blue
);
show_set
(
red
);
show_set
(
green
);
static
int
led_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
udev
=
interface_to_usbdev
(
interface
);
struct
usb_led
*
dev
=
NULL
;
int
retval
=
-
ENOMEM
;
dev
=
kzalloc
(
sizeof
(
struct
usb_led
),
GFP_KERNEL
);
if
(
dev
==
NULL
)
{
dev_err
(
&
interface
->
dev
,
"out of memory
\n
"
);
goto
error_mem
;
}
dev
->
udev
=
usb_get_dev
(
udev
);
dev
->
type
=
id
->
driver_info
;
usb_set_intfdata
(
interface
,
dev
);
retval
=
device_create_file
(
&
interface
->
dev
,
&
dev_attr_blue
);
if
(
retval
)
goto
error
;
retval
=
device_create_file
(
&
interface
->
dev
,
&
dev_attr_red
);
if
(
retval
)
goto
error
;
retval
=
device_create_file
(
&
interface
->
dev
,
&
dev_attr_green
);
if
(
retval
)
goto
error
;
if
(
dev
->
type
==
DREAM_CHEEKY_WEBMAIL_NOTIFIER
)
{
unsigned
char
*
enable
;
enable
=
kmemdup
(
"
\x1f\x02\0\x5f\0\0\x1a\x03
"
,
8
,
GFP_KERNEL
);
if
(
!
enable
)
{
dev_err
(
&
interface
->
dev
,
"out of memory
\n
"
);
retval
=
-
ENOMEM
;
goto
error
;
}
retval
=
usb_control_msg
(
udev
,
usb_sndctrlpipe
(
udev
,
0
),
0x09
,
0x21
,
0x200
,
0
,
enable
,
8
,
2000
);
kfree
(
enable
);
if
(
retval
!=
8
)
goto
error
;
}
dev_info
(
&
interface
->
dev
,
"USB LED device now attached
\n
"
);
return
0
;
error:
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_blue
);
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_red
);
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_green
);
usb_set_intfdata
(
interface
,
NULL
);
usb_put_dev
(
dev
->
udev
);
kfree
(
dev
);
error_mem:
return
retval
;
}
static
void
led_disconnect
(
struct
usb_interface
*
interface
)
{
struct
usb_led
*
dev
;
dev
=
usb_get_intfdata
(
interface
);
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_blue
);
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_red
);
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_green
);
/* first remove the files, then set the pointer to NULL */
usb_set_intfdata
(
interface
,
NULL
);
usb_put_dev
(
dev
->
udev
);
kfree
(
dev
);
dev_info
(
&
interface
->
dev
,
"USB LED now disconnected
\n
"
);
}
static
struct
usb_driver
led_driver
=
{
.
name
=
"usbled"
,
.
probe
=
led_probe
,
.
disconnect
=
led_disconnect
,
.
id_table
=
id_table
,
};
module_usb_driver
(
led_driver
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
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