* [PATCH v2] HID: lg4ff: Take advantage of private driver data
@ 2012-04-09 7:08 Michal Malý
2012-04-09 15:53 ` simon
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Michal Malý @ 2012-04-09 7:08 UTC (permalink / raw)
To: linux-input; +Cc: jkosina, simon
[-- Attachment #1: Type: text/plain, Size: 6440 bytes --]
Hi,
this is a revised version of HID: lg4ff: Use Private Data I asked Simon to
submit for me earlier. To recap what the patch is about, it takes advantage
of the changes introduced in my patches from 2011/04/02. lg4ff now calls
hid_get/set_drvdata() to read or store device configuration. The way I understand
it, this is how all HID drivers store their private data. The change from the version
that was submitted earlier are removed all occurences of uninitialized_var() macro.
Please note that this patch depends on
"[PATCH v4] HID: hid-lg: Allow for custom device-specific properties to be stored in private drv data"
"[PATCH v4] HID: lg4ff: Remove sysfs iface before deallocating memory"
Signed-off-by: Michal Malý <madcatxster@gmail.com>
---
drivers/hid/hid-lg4ff.c | 92 ++++++++++++++++++++++-------------------------
1 file changed, 42 insertions(+), 50 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 1145292..32c173f 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -51,10 +51,7 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
-static bool list_inited;
-
struct lg4ff_device_entry {
- char *device_id; /* Use name in respective kobject structure's address as the ID */
__u16 range;
__u16 min_range;
__u16 max_range;
@@ -63,8 +60,6 @@ struct lg4ff_device_entry {
void (*set_range)(struct hid_device *hid, u16 range);
};
-static struct lg4ff_device_entry device_list;
-
static const signed short lg4ff_wheel_effects[] = {
FF_CONSTANT,
FF_AUTOCENTER,
@@ -285,18 +280,20 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n
/* Read current range and display it in terminal */
static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct lg4ff_device_entry *uninitialized_var(entry);
- struct list_head *h;
struct hid_device *hid = to_hid_device(dev);
+ struct lg4ff_device_entry *entry;
+ struct lg_drv_data *drv_data;
size_t count;
- list_for_each(h, &device_list.list) {
- entry = list_entry(h, struct lg4ff_device_entry, list);
- if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
- break;
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Private driver data not found!\n");
+ return 0;
}
- if (h == &device_list.list) {
- dbg_hid("Device not found!");
+
+ entry = drv_data->device_props;
+ if (!entry) {
+ hid_err(hid, "Device properties not found!\n");
return 0;
}
@@ -308,19 +305,21 @@ static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *att
* according to the type of the wheel */
static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- struct lg4ff_device_entry *uninitialized_var(entry);
- struct list_head *h;
struct hid_device *hid = to_hid_device(dev);
+ struct lg4ff_device_entry *entry;
+ struct lg_drv_data *drv_data;
__u16 range = simple_strtoul(buf, NULL, 10);
- list_for_each(h, &device_list.list) {
- entry = list_entry(h, struct lg4ff_device_entry, list);
- if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
- break;
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Private driver data not found!\n");
+ return 0;
}
- if (h == &device_list.list) {
- dbg_hid("Device not found!");
- return count;
+
+ entry = drv_data->device_props;
+ if (!entry) {
+ hid_err(hid, "Device properties not found!\n");
+ return 0;
}
if (range == 0)
@@ -344,6 +343,7 @@ int lg4ff_init(struct hid_device *hid)
struct hid_report *report;
struct hid_field *field;
struct lg4ff_device_entry *entry;
+ struct lg_drv_data *drv_data;
struct usb_device_descriptor *udesc;
int error, i, j;
__u16 bcdDevice, rev_maj, rev_min;
@@ -423,28 +423,24 @@ int lg4ff_init(struct hid_device *hid)
dev->ff->set_autocenter(dev, 0);
}
- /* Initialize device_list if this is the first device to handle by lg4ff */
- if (!list_inited) {
- INIT_LIST_HEAD(&device_list.list);
- list_inited = 1;
+ /* Get private driver data */
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Cannot add device, private driver data not allocated\n");
+ return -1;
}
- /* Add the device to device_list */
+ /* Initialize device properties */
entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL);
if (!entry) {
- hid_err(hid, "Cannot add device, insufficient memory.\n");
- return -ENOMEM;
- }
- entry->device_id = kstrdup((&hid->dev)->kobj.name, GFP_KERNEL);
- if (!entry->device_id) {
- hid_err(hid, "Cannot set device_id, insufficient memory.\n");
- kfree(entry);
+ hid_err(hid, "Cannot add device, insufficient memory to allocate device properties.\n");
return -ENOMEM;
}
+ drv_data->device_props = entry;
+
entry->min_range = lg4ff_devices[i].min_range;
entry->max_range = lg4ff_devices[i].max_range;
entry->set_range = lg4ff_devices[i].set_range;
- list_add(&entry->list, &device_list.list);
/* Create sysfs interface */
error = device_create_file(&hid->dev, &dev_attr_range);
@@ -463,27 +459,23 @@ int lg4ff_init(struct hid_device *hid)
int lg4ff_deinit(struct hid_device *hid)
{
- bool found = 0;
struct lg4ff_device_entry *entry;
- struct list_head *h, *g;
-
+ struct lg_drv_data *drv_data;
+
device_remove_file(&hid->dev, &dev_attr_range);
- list_for_each_safe(h, g, &device_list.list) {
- entry = list_entry(h, struct lg4ff_device_entry, list);
- if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) {
- list_del(h);
- kfree(entry->device_id);
- kfree(entry);
- found = 1;
- break;
- }
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Error while deinitializing device, no private driver data.\n");
+ return -1;
}
-
- if (!found) {
- hid_err(hid, "Device entry not found!\n");
+ entry = drv_data->device_props;
+ if (!entry) {
+ hid_err(hid, "Error while deinitializing device, no device properties data.\n");
return -1;
}
+ /* Deallocate memory */
+ kfree(entry);
dbg_hid("Device successfully unregistered\n");
return 0;
--
1.7.9.6
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2] HID: lg4ff: Take advantage of private driver data
2012-04-09 7:08 [PATCH v2] HID: lg4ff: Take advantage of private driver data Michal Malý
@ 2012-04-09 15:53 ` simon
2012-04-09 16:08 ` [PATCH] HID: hid-lg4ff: Add support for G27 LEDs Simon Wood
2012-04-13 12:59 ` [PATCH v2] HID: lg4ff: Take advantage of private driver data Jiri Kosina
2 siblings, 0 replies; 13+ messages in thread
From: simon @ 2012-04-09 15:53 UTC (permalink / raw)
To: "Michal Malý"; +Cc: linux-input, jkosina, simon
I tested this against a G27 and WiiWheel and it appears to function
correctly.
I'll shortly send another patch on top of this which enables the LEDs on
the G27. Hopefully this will bring to a close this short series of
patches.
Simon.
> Please note that this patch depends on
> "[PATCH v4] HID: hid-lg: Allow for custom device-specific properties to be
> stored in private drv data"
> "[PATCH v4] HID: lg4ff: Remove sysfs iface before deallocating memory"
>
> Signed-off-by: Michal Malý <madcatxster@gmail.com>
tested-by: Simon Wood <simon@mungewell.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-09 7:08 [PATCH v2] HID: lg4ff: Take advantage of private driver data Michal Malý
2012-04-09 15:53 ` simon
@ 2012-04-09 16:08 ` Simon Wood
2012-04-13 12:59 ` Jiri Kosina
2012-04-13 12:59 ` [PATCH v2] HID: lg4ff: Take advantage of private driver data Jiri Kosina
2 siblings, 1 reply; 13+ messages in thread
From: Simon Wood @ 2012-04-09 16:08 UTC (permalink / raw)
To: linux-input
Cc: linux-kernel, Jiri Kosina, Michael Bauer, Michal Maly, Simon Wood
This patch adds supports for controlling the LED 'tachometer' on
the G27 wheel, via the LED subsystem.
The 5 LEDs are arranged from right (1=grn, 2=grn, 3=yel, 4=yel, 5=red)
and 'mirrored' to the left (10 LEDs in total).
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 148 insertions(+), 1 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 32c173f..8960347 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -55,7 +55,8 @@ struct lg4ff_device_entry {
__u16 range;
__u16 min_range;
__u16 max_range;
- __u8 leds;
+ __u8 led_state;
+ struct led_classdev *led[5];
struct list_head list;
void (*set_range)(struct hid_device *hid, u16 range);
};
@@ -335,6 +336,86 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
return count;
}
+static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
+{
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+
+ report->field[0]->value[0] = 0xf8;
+ report->field[0]->value[1] = 0x12;
+ report->field[0]->value[2] = leds;
+ report->field[0]->value[3] = 0x00;
+ report->field[0]->value[4] = 0x00;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+static void lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, state = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return;
+ }
+
+ for (i = 0; i < 5; i++) {
+ if (led_cdev != entry->led[i])
+ continue;
+ state = (entry->led_state >> i) & 1;
+ if (value == LED_OFF && state) {
+ entry->led_state &= ~(1 << i);
+ lg4ff_set_leds(hid, entry->led_state);
+ } else if (value != LED_OFF && !state) {
+ entry->led_state |= 1 << i;
+ lg4ff_set_leds(hid, entry->led_state);
+ }
+ break;
+ }
+}
+
+static enum led_brightness lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, value = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return LED_OFF;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return LED_OFF;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (led_cdev == entry->led[i]) {
+ value = (entry->led_state >> i) & 1;
+ break;
+ }
+
+ return value ? LED_FULL : LED_OFF;
+}
+
int lg4ff_init(struct hid_device *hid)
{
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
@@ -347,6 +428,9 @@ int lg4ff_init(struct hid_device *hid)
struct usb_device_descriptor *udesc;
int error, i, j;
__u16 bcdDevice, rev_maj, rev_min;
+ struct led_classdev *led;
+ size_t name_sz;
+ char *name;
/* Find the report to use */
if (list_empty(report_list)) {
@@ -453,14 +537,66 @@ int lg4ff_init(struct hid_device *hid)
if (entry->set_range != NULL)
entry->set_range(hid, entry->range);
+ /* register led subsystem - G27 only */
+ entry->led_state = 0;
+ for (j = 0; j < 5; j++)
+ entry->led[j] = NULL;
+
+ if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) {
+ lg4ff_set_leds(hid, 0);
+
+ name_sz = strlen(dev_name(&hid->dev)) + 8;
+
+ for (j = 0; j < 5; j++) {
+ led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
+ if (!led) {
+ hid_err(hid, "can't allocate memory for LED %d\n", j);
+ error = -ENOMEM;
+ goto err;
+ }
+
+ name = (void *)(&led[1]);
+ snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1);
+ led->name = name;
+ led->brightness = 0;
+ led->max_brightness = 1;
+ led->brightness_get = lg4ff_led_get_brightness;
+ led->brightness_set = lg4ff_led_set_brightness;
+
+ entry->led[j] = led;
+ error = led_classdev_register(&hid->dev, led);
+ if (error) {
+ hid_err(hid, "failed to register LED %d. Aborting.\n", j);
+ goto err;
+ }
+ }
+
+ dbg_hid("sysfs interface created for leds\n");
+ }
+
hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
return 0;
+
+err:
+ /* Deregister LEDs (if any) but let the driver continue */
+ for (j = 0; j < 5; j++) {
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+
+ return 0;
}
int lg4ff_deinit(struct hid_device *hid)
{
struct lg4ff_device_entry *entry;
struct lg_drv_data *drv_data;
+ int j;
+ struct led_classdev *led;
device_remove_file(&hid->dev, &dev_attr_range);
@@ -474,6 +610,17 @@ int lg4ff_deinit(struct hid_device *hid)
hid_err(hid, "Error while deinitializing device, no device properties data.\n");
return -1;
}
+
+ /* Deregister LEDs (if any) */
+ for (j = 0; j < 5; j++) {
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+
/* Deallocate memory */
kfree(entry);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-09 16:08 ` [PATCH] HID: hid-lg4ff: Add support for G27 LEDs Simon Wood
@ 2012-04-13 12:59 ` Jiri Kosina
2012-04-18 7:03 ` [PATCH 1/2] " Simon Wood
0 siblings, 1 reply; 13+ messages in thread
From: Jiri Kosina @ 2012-04-13 12:59 UTC (permalink / raw)
To: Simon Wood; +Cc: linux-input, linux-kernel, Michael Bauer, Michal Maly
On Mon, 9 Apr 2012, Simon Wood wrote:
> This patch adds supports for controlling the LED 'tachometer' on
> the G27 wheel, via the LED subsystem.
>
> The 5 LEDs are arranged from right (1=grn, 2=grn, 3=yel, 4=yel, 5=red)
> and 'mirrored' to the left (10 LEDs in total).
>
> Signed-off-by: Simon Wood <simon@mungewell.org>
> ---
> drivers/hid/hid-lg4ff.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 148 insertions(+), 1 deletions(-)
This patch introduces a clear dependency of hid-lg4ff driver on
CONFIG_LEDS_CLASS, but the code doesn't reflect it.
So either you have to put #ifdef into source to compile the leds part out
if leds subsystem is not enabled, or you have to introduce Kconfig rule to
cover this.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2] HID: lg4ff: Take advantage of private driver data
2012-04-09 7:08 [PATCH v2] HID: lg4ff: Take advantage of private driver data Michal Malý
2012-04-09 15:53 ` simon
2012-04-09 16:08 ` [PATCH] HID: hid-lg4ff: Add support for G27 LEDs Simon Wood
@ 2012-04-13 12:59 ` Jiri Kosina
2 siblings, 0 replies; 13+ messages in thread
From: Jiri Kosina @ 2012-04-13 12:59 UTC (permalink / raw)
To: Michal Malý; +Cc: linux-input, simon
On Mon, 9 Apr 2012, Michal Malý wrote:
> Hi,
>
> this is a revised version of HID: lg4ff: Use Private Data I asked Simon to
> submit for me earlier. To recap what the patch is about, it takes advantage
> of the changes introduced in my patches from 2011/04/02. lg4ff now calls
> hid_get/set_drvdata() to read or store device configuration. The way I understand
> it, this is how all HID drivers store their private data. The change from the version
> that was submitted earlier are removed all occurences of uninitialized_var() macro.
>
> Please note that this patch depends on
> "[PATCH v4] HID: hid-lg: Allow for custom device-specific properties to be stored in private drv data"
> "[PATCH v4] HID: lg4ff: Remove sysfs iface before deallocating memory"
>
> Signed-off-by: Michal Malý <madcatxster@gmail.com>
Applied, thanks.
--
Jiri Kosina
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-13 12:59 ` Jiri Kosina
@ 2012-04-18 7:03 ` Simon Wood
2012-04-18 7:03 ` [PATCH 2/2] HID: hid-lg4ff: Updated Comments Simon Wood
2012-04-18 11:24 ` [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs Jiri Kosina
0 siblings, 2 replies; 13+ messages in thread
From: Simon Wood @ 2012-04-18 7:03 UTC (permalink / raw)
To: linux-input
Cc: linux-kernel, Jiri Kosina, Michael Bauer, Michal Maly, Simon Wood
This patch adds supports for controlling the LED 'tachometer' on
the G27 wheel, via the LED subsystem.
The 5 LEDs are arranged from right (1=grn, 2=grn, 3=yel, 4=yel, 5=red)
and 'mirrored' to the left (10 LEDs in total).
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 154 insertions(+), 1 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 32c173f..ab5232e 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -55,7 +55,8 @@ struct lg4ff_device_entry {
__u16 range;
__u16 min_range;
__u16 max_range;
- __u8 leds;
+ __u8 led_state;
+ struct led_classdev *led[5];
struct list_head list;
void (*set_range)(struct hid_device *hid, u16 range);
};
@@ -335,6 +336,88 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
return count;
}
+#ifdef CONFIG_LEDS_CLASS
+static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
+{
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+
+ report->field[0]->value[0] = 0xf8;
+ report->field[0]->value[1] = 0x12;
+ report->field[0]->value[2] = leds;
+ report->field[0]->value[3] = 0x00;
+ report->field[0]->value[4] = 0x00;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+static void lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, state = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return;
+ }
+
+ for (i = 0; i < 5; i++) {
+ if (led_cdev != entry->led[i])
+ continue;
+ state = (entry->led_state >> i) & 1;
+ if (value == LED_OFF && state) {
+ entry->led_state &= ~(1 << i);
+ lg4ff_set_leds(hid, entry->led_state);
+ } else if (value != LED_OFF && !state) {
+ entry->led_state |= 1 << i;
+ lg4ff_set_leds(hid, entry->led_state);
+ }
+ break;
+ }
+}
+
+static enum led_brightness lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, value = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return LED_OFF;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return LED_OFF;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (led_cdev == entry->led[i]) {
+ value = (entry->led_state >> i) & 1;
+ break;
+ }
+
+ return value ? LED_FULL : LED_OFF;
+}
+#endif
+
int lg4ff_init(struct hid_device *hid)
{
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
@@ -453,6 +536,57 @@ int lg4ff_init(struct hid_device *hid)
if (entry->set_range != NULL)
entry->set_range(hid, entry->range);
+ /* register led subsystem - G27 only */
+ entry->led_state = 0;
+ for (j = 0; j < 5; j++)
+ entry->led[j] = NULL;
+
+#ifdef CONFIG_LEDS_CLASS
+ if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) {
+ struct led_classdev *led;
+ size_t name_sz;
+ char *name;
+
+ lg4ff_set_leds(hid, 0);
+
+ name_sz = strlen(dev_name(&hid->dev)) + 8;
+
+ for (j = 0; j < 5; j++) {
+ led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
+ if (!led) {
+ hid_err(hid, "can't allocate memory for LED %d\n", j);
+ goto err;
+ }
+
+ name = (void *)(&led[1]);
+ snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1);
+ led->name = name;
+ led->brightness = 0;
+ led->max_brightness = 1;
+ led->brightness_get = lg4ff_led_get_brightness;
+ led->brightness_set = lg4ff_led_set_brightness;
+
+ entry->led[j] = led;
+ error = led_classdev_register(&hid->dev, led);
+
+ if (error) {
+ hid_err(hid, "failed to register LED %d. Aborting.\n", j);
+err:
+ /* Deregister LEDs (if any) but let the driver continue */
+ for (j = 0; j < 5; j++) {
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+ break; /* Don't create any more LEDs */
+ }
+ }
+ }
+#endif
+
hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
return 0;
}
@@ -474,6 +608,25 @@ int lg4ff_deinit(struct hid_device *hid)
hid_err(hid, "Error while deinitializing device, no device properties data.\n");
return -1;
}
+
+#ifdef CONFIG_LEDS_CLASS
+ {
+ int j;
+ struct led_classdev *led;
+
+ /* Deregister LEDs (if any) */
+ for (j = 0; j < 5; j++) {
+
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+ }
+#endif
+
/* Deallocate memory */
kfree(entry);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/2] HID: hid-lg4ff: Updated Comments
2012-04-18 7:03 ` [PATCH 1/2] " Simon Wood
@ 2012-04-18 7:03 ` Simon Wood
2012-04-18 11:24 ` [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs Jiri Kosina
1 sibling, 0 replies; 13+ messages in thread
From: Simon Wood @ 2012-04-18 7:03 UTC (permalink / raw)
To: linux-input
Cc: linux-kernel, Jiri Kosina, Michael Bauer, Michal Maly, Simon Wood
Updated comments to say that this driver now supports all Logitech
gaming wheels, and not just the WiiWheel
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index ab5232e..cbafb46 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -1,7 +1,8 @@
/*
- * Force feedback support for Logitech Speed Force Wireless
+ * Force feedback support for Logitech Gaming Wheels
*
- * http://wiibrew.org/wiki/Logitech_USB_steering_wheel
+ * Including G27, G25, DFP, DFGT, FFEX, Momo, Momo2 &
+ * Wireless Speed Force (WiiWheel)
*
* Copyright (c) 2010 Simon Wood <simon@mungewell.org>
*/
@@ -587,7 +588,7 @@ err:
}
#endif
- hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
+ hid_info(hid, "Force feedback for Logitech Gaming Wheels\n");
return 0;
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-18 7:03 ` [PATCH 1/2] " Simon Wood
2012-04-18 7:03 ` [PATCH 2/2] HID: hid-lg4ff: Updated Comments Simon Wood
@ 2012-04-18 11:24 ` Jiri Kosina
2012-04-18 14:58 ` simon
1 sibling, 1 reply; 13+ messages in thread
From: Jiri Kosina @ 2012-04-18 11:24 UTC (permalink / raw)
To: Simon Wood; +Cc: linux-input, linux-kernel, Michael Bauer, Michal Maly
On Wed, 18 Apr 2012, Simon Wood wrote:
> This patch adds supports for controlling the LED 'tachometer' on
> the G27 wheel, via the LED subsystem.
>
> The 5 LEDs are arranged from right (1=grn, 2=grn, 3=yel, 4=yel, 5=red)
> and 'mirrored' to the left (10 LEDs in total).
>
> Signed-off-by: Simon Wood <simon@mungewell.org>
> ---
> drivers/hid/hid-lg4ff.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 154 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
> index 32c173f..ab5232e 100644
> --- a/drivers/hid/hid-lg4ff.c
> +++ b/drivers/hid/hid-lg4ff.c
> @@ -55,7 +55,8 @@ struct lg4ff_device_entry {
> __u16 range;
> __u16 min_range;
> __u16 max_range;
> - __u8 leds;
> + __u8 led_state;
> + struct led_classdev *led[5];
Why not put this under the CONFIG_LEDS_CLASS condition as well?
> struct list_head list;
> void (*set_range)(struct hid_device *hid, u16 range);
> };
> @@ -335,6 +336,88 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
> return count;
> }
>
> +#ifdef CONFIG_LEDS_CLASS
> +static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
> +{
> + struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
> + struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
> +
> + report->field[0]->value[0] = 0xf8;
> + report->field[0]->value[1] = 0x12;
> + report->field[0]->value[2] = leds;
> + report->field[0]->value[3] = 0x00;
> + report->field[0]->value[4] = 0x00;
> + report->field[0]->value[5] = 0x00;
> + report->field[0]->value[6] = 0x00;
> + usbhid_submit_report(hid, report, USB_DIR_OUT);
> +}
> +
> +static void lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
> + struct lg4ff_device_entry *entry;
> + int i, state = 0;
> +
> + if (!drv_data) {
> + hid_err(hid, "Device data not found.");
> + return;
> + }
> +
> + entry = (struct lg4ff_device_entry *)drv_data->device_props;
> +
> + if (!entry) {
> + hid_err(hid, "Device properties not found.");
> + return;
> + }
> +
> + for (i = 0; i < 5; i++) {
> + if (led_cdev != entry->led[i])
> + continue;
> + state = (entry->led_state >> i) & 1;
> + if (value == LED_OFF && state) {
> + entry->led_state &= ~(1 << i);
> + lg4ff_set_leds(hid, entry->led_state);
> + } else if (value != LED_OFF && !state) {
> + entry->led_state |= 1 << i;
> + lg4ff_set_leds(hid, entry->led_state);
> + }
> + break;
> + }
> +}
> +
> +static enum led_brightness lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
> + struct lg4ff_device_entry *entry;
> + int i, value = 0;
> +
> + if (!drv_data) {
> + hid_err(hid, "Device data not found.");
> + return LED_OFF;
> + }
> +
> + entry = (struct lg4ff_device_entry *)drv_data->device_props;
> +
> + if (!entry) {
> + hid_err(hid, "Device properties not found.");
> + return LED_OFF;
> + }
> +
> + for (i = 0; i < 5; i++)
> + if (led_cdev == entry->led[i]) {
> + value = (entry->led_state >> i) & 1;
> + break;
> + }
> +
> + return value ? LED_FULL : LED_OFF;
> +}
> +#endif
> +
> int lg4ff_init(struct hid_device *hid)
> {
> struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
> @@ -453,6 +536,57 @@ int lg4ff_init(struct hid_device *hid)
> if (entry->set_range != NULL)
> entry->set_range(hid, entry->range);
>
> + /* register led subsystem - G27 only */
> + entry->led_state = 0;
> + for (j = 0; j < 5; j++)
> + entry->led[j] = NULL;
> +
The same here.
> +#ifdef CONFIG_LEDS_CLASS
> + if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) {
> + struct led_classdev *led;
> + size_t name_sz;
> + char *name;
> +
> + lg4ff_set_leds(hid, 0);
> +
> + name_sz = strlen(dev_name(&hid->dev)) + 8;
> +
> + for (j = 0; j < 5; j++) {
> + led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
> + if (!led) {
> + hid_err(hid, "can't allocate memory for LED %d\n", j);
> + goto err;
> + }
> +
> + name = (void *)(&led[1]);
> + snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1);
> + led->name = name;
> + led->brightness = 0;
> + led->max_brightness = 1;
> + led->brightness_get = lg4ff_led_get_brightness;
> + led->brightness_set = lg4ff_led_set_brightness;
> +
> + entry->led[j] = led;
> + error = led_classdev_register(&hid->dev, led);
> +
> + if (error) {
> + hid_err(hid, "failed to register LED %d. Aborting.\n", j);
> +err:
> + /* Deregister LEDs (if any) but let the driver continue */
> + for (j = 0; j < 5; j++) {
> + led = entry->led[j];
> + entry->led[j] = NULL;
> + if (!led)
> + continue;
> + led_classdev_unregister(led);
> + kfree(led);
Indentation seems to be wrong here.
> + }
> + break; /* Don't create any more LEDs */
Putting the whole err: label outside the outer for cycle would make the
whole thing much more readable (and would save you the break). Could you
please redo this?
> + }
> + }
> + }
> +#endif
> +
> hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
> return 0;
> }
> @@ -474,6 +608,25 @@ int lg4ff_deinit(struct hid_device *hid)
> hid_err(hid, "Error while deinitializing device, no device properties data.\n");
> return -1;
> }
> +
> +#ifdef CONFIG_LEDS_CLASS
> + {
> + int j;
> + struct led_classdev *led;
> +
> + /* Deregister LEDs (if any) */
> + for (j = 0; j < 5; j++) {
> +
> + led = entry->led[j];
> + entry->led[j] = NULL;
> + if (!led)
> + continue;
> + led_classdev_unregister(led);
> + kfree(led);
> + }
> + }
> +#endif
> +
> /* Deallocate memory */
> kfree(entry);
>
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-18 11:24 ` [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs Jiri Kosina
@ 2012-04-18 14:58 ` simon
2012-04-20 10:05 ` Jiri Kosina
0 siblings, 1 reply; 13+ messages in thread
From: simon @ 2012-04-18 14:58 UTC (permalink / raw)
To: Jiri Kosina
Cc: Simon Wood, linux-input, linux-kernel, Michael Bauer, Michal Maly
>> + __u8 led_state;
>> + struct led_classdev *led[5];
>
> Why not put this under the CONFIG_LEDS_CLASS condition as well?
Can do, I don't think these are referenced anywhere else.
>> + /* register led subsystem - G27 only */
>> + entry->led_state = 0;
>> + for (j = 0; j < 5; j++)
>> + entry->led[j] = NULL;
>> +
>
> The same here.
OK.
>> + if (error) {
>> + hid_err(hid, "failed to register LED %d. Aborting.\n", j);
>> +err:
>> + /* Deregister LEDs (if any) but let the driver continue */
>> + for (j = 0; j < 5; j++) {
>> + led = entry->led[j];
>> + entry->led[j] = NULL;
>> + if (!led)
>> + continue;
>> + led_classdev_unregister(led);
>> + kfree(led);
>
> Indentation seems to be wrong here.
Bugger...
>
>> + }
>> + break; /* Don't create any more LEDs */
>
> Putting the whole err: label outside the outer for cycle would make the
> whole thing much more readable (and would save you the break). Could you
> please redo this?
The 'break' is actually not needed as 'j' has reached maximum value and
the outer for loop would be at completion. I put the 'break' there just to
highlight this fact.
Maybe just a comment would be OK, such as 'on error fall though to driver
completion'.
The reason I'd like this code here is that it seems traditional to output
the following 'hid_info' line once the driver is fully active.
>> hid_info(hid, "Force feedback for Logitech Speed Force Wireless by
>> Simon Wood <simon@mungewell.org>\n");
Moving the 'err:' code would have to:
1). Jump back to hit this hid_info line
2). Duplicate the hid_info line
3). Have err code called as a function
Any major objections to keeping it as is?
Man, it seems to be taking me ages to get this code right....
Simon
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-18 14:58 ` simon
@ 2012-04-20 10:05 ` Jiri Kosina
2012-04-21 12:41 ` Simon Wood
0 siblings, 1 reply; 13+ messages in thread
From: Jiri Kosina @ 2012-04-20 10:05 UTC (permalink / raw)
To: Simon Wood; +Cc: linux-input, linux-kernel, Michael Bauer, Michal Maly
On Wed, 18 Apr 2012, simon@mungewell.org wrote:
> > Putting the whole err: label outside the outer for cycle would make the
> > whole thing much more readable (and would save you the break). Could you
> > please redo this?
>
> The 'break' is actually not needed as 'j' has reached maximum value and
> the outer for loop would be at completion.
Ah, right, I have even missed this fact, that you are using the same index
in the inner loop as in the outter loop.
Quite unreadable indeed :)
> I put the 'break' there just to highlight this fact.
>
> Maybe just a comment would be OK, such as 'on error fall though to driver
> completion'.
>
> The reason I'd like this code here is that it seems traditional to output
> the following 'hid_info' line once the driver is fully active.
>
> >> hid_info(hid, "Force feedback for Logitech Speed Force Wireless by
> >> Simon Wood <simon@mungewell.org>\n");
>
> Moving the 'err:' code would have to:
> 1). Jump back to hit this hid_info line
> 2). Duplicate the hid_info line
> 3). Have err code called as a function
I am not getting it. Why can't you do just something like
for ( .... ) {
/* outter loop */
if (error) {
for ( ... ) {
/* inner loop */
}
goto out;
}
}
out:
hid_info(....);
return;
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-20 10:05 ` Jiri Kosina
@ 2012-04-21 12:41 ` Simon Wood
2012-04-21 12:41 ` [PATCH 2/2] HID: hid-lg4ff: Updated Comments Simon Wood
2012-04-23 18:55 ` [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs Jiri Kosina
0 siblings, 2 replies; 13+ messages in thread
From: Simon Wood @ 2012-04-21 12:41 UTC (permalink / raw)
To: linux-input
Cc: linux-kernel, Jiri Kosina, Michael Bauer, Michal Maly, Simon Wood
This patch adds supports for controlling the LED 'tachometer' on
the G27 wheel, via the LED subsystem.
The 5 LEDs are arranged from right (1=grn, 2=grn, 3=yel, 4=yel, 5=red)
and 'mirrored' to the left (10 LEDs in total).
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 157 insertions(+), 1 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 32c173f..1e942a0 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -55,7 +55,10 @@ struct lg4ff_device_entry {
__u16 range;
__u16 min_range;
__u16 max_range;
- __u8 leds;
+#ifdef CONFIG_LEDS_CLASS
+ __u8 led_state;
+ struct led_classdev *led[5];
+#endif
struct list_head list;
void (*set_range)(struct hid_device *hid, u16 range);
};
@@ -335,6 +338,88 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
return count;
}
+#ifdef CONFIG_LEDS_CLASS
+static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
+{
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+
+ report->field[0]->value[0] = 0xf8;
+ report->field[0]->value[1] = 0x12;
+ report->field[0]->value[2] = leds;
+ report->field[0]->value[3] = 0x00;
+ report->field[0]->value[4] = 0x00;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+static void lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, state = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return;
+ }
+
+ for (i = 0; i < 5; i++) {
+ if (led_cdev != entry->led[i])
+ continue;
+ state = (entry->led_state >> i) & 1;
+ if (value == LED_OFF && state) {
+ entry->led_state &= ~(1 << i);
+ lg4ff_set_leds(hid, entry->led_state);
+ } else if (value != LED_OFF && !state) {
+ entry->led_state |= 1 << i;
+ lg4ff_set_leds(hid, entry->led_state);
+ }
+ break;
+ }
+}
+
+static enum led_brightness lg4ff_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 lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+ struct lg4ff_device_entry *entry;
+ int i, value = 0;
+
+ if (!drv_data) {
+ hid_err(hid, "Device data not found.");
+ return LED_OFF;
+ }
+
+ entry = (struct lg4ff_device_entry *)drv_data->device_props;
+
+ if (!entry) {
+ hid_err(hid, "Device properties not found.");
+ return LED_OFF;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (led_cdev == entry->led[i]) {
+ value = (entry->led_state >> i) & 1;
+ break;
+ }
+
+ return value ? LED_FULL : LED_OFF;
+}
+#endif
+
int lg4ff_init(struct hid_device *hid)
{
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
@@ -453,6 +538,58 @@ int lg4ff_init(struct hid_device *hid)
if (entry->set_range != NULL)
entry->set_range(hid, entry->range);
+#ifdef CONFIG_LEDS_CLASS
+ /* register led subsystem - G27 only */
+ entry->led_state = 0;
+ for (j = 0; j < 5; j++)
+ entry->led[j] = NULL;
+
+ if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) {
+ struct led_classdev *led;
+ size_t name_sz;
+ char *name;
+
+ lg4ff_set_leds(hid, 0);
+
+ name_sz = strlen(dev_name(&hid->dev)) + 8;
+
+ for (j = 0; j < 5; j++) {
+ led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
+ if (!led) {
+ hid_err(hid, "can't allocate memory for LED %d\n", j);
+ goto err;
+ }
+
+ name = (void *)(&led[1]);
+ snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1);
+ led->name = name;
+ led->brightness = 0;
+ led->max_brightness = 1;
+ led->brightness_get = lg4ff_led_get_brightness;
+ led->brightness_set = lg4ff_led_set_brightness;
+
+ entry->led[j] = led;
+ error = led_classdev_register(&hid->dev, led);
+
+ if (error) {
+ hid_err(hid, "failed to register LED %d. Aborting.\n", j);
+err:
+ /* Deregister LEDs (if any) */
+ for (j = 0; j < 5; j++) {
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+ goto out; /* Let the driver continue without LEDs */
+ }
+ }
+ }
+#endif
+
+out:
hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
return 0;
}
@@ -474,6 +611,25 @@ int lg4ff_deinit(struct hid_device *hid)
hid_err(hid, "Error while deinitializing device, no device properties data.\n");
return -1;
}
+
+#ifdef CONFIG_LEDS_CLASS
+ {
+ int j;
+ struct led_classdev *led;
+
+ /* Deregister LEDs (if any) */
+ for (j = 0; j < 5; j++) {
+
+ led = entry->led[j];
+ entry->led[j] = NULL;
+ if (!led)
+ continue;
+ led_classdev_unregister(led);
+ kfree(led);
+ }
+ }
+#endif
+
/* Deallocate memory */
kfree(entry);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/2] HID: hid-lg4ff: Updated Comments
2012-04-21 12:41 ` Simon Wood
@ 2012-04-21 12:41 ` Simon Wood
2012-04-23 18:55 ` [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs Jiri Kosina
1 sibling, 0 replies; 13+ messages in thread
From: Simon Wood @ 2012-04-21 12:41 UTC (permalink / raw)
To: linux-input
Cc: linux-kernel, Jiri Kosina, Michael Bauer, Michal Maly, Simon Wood
Updated comments to say that this driver now supports all Logitech
gaming wheels, and not just the WiiWheel.
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 1e942a0..24cf037 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -1,7 +1,8 @@
/*
- * Force feedback support for Logitech Speed Force Wireless
+ * Force feedback support for Logitech Gaming Wheels
*
- * http://wiibrew.org/wiki/Logitech_USB_steering_wheel
+ * Including G27, G25, DFP, DFGT, FFEX, Momo, Momo2 &
+ * Speed Force Wireless (WiiWheel)
*
* Copyright (c) 2010 Simon Wood <simon@mungewell.org>
*/
@@ -590,7 +591,7 @@ err:
#endif
out:
- hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
+ hid_info(hid, "Force feedback support for Logitech Gaming Wheels\n");
return 0;
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs
2012-04-21 12:41 ` Simon Wood
2012-04-21 12:41 ` [PATCH 2/2] HID: hid-lg4ff: Updated Comments Simon Wood
@ 2012-04-23 18:55 ` Jiri Kosina
1 sibling, 0 replies; 13+ messages in thread
From: Jiri Kosina @ 2012-04-23 18:55 UTC (permalink / raw)
To: Simon Wood; +Cc: linux-input, linux-kernel, Michael Bauer, Michal Maly
On Sat, 21 Apr 2012, Simon Wood wrote:
> This patch adds supports for controlling the LED 'tachometer' on
> the G27 wheel, via the LED subsystem.
>
> The 5 LEDs are arranged from right (1=grn, 2=grn, 3=yel, 4=yel, 5=red)
> and 'mirrored' to the left (10 LEDs in total).
>
> Signed-off-by: Simon Wood <simon@mungewell.org>
Both patches applied, thanks.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-04-23 18:55 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-09 7:08 [PATCH v2] HID: lg4ff: Take advantage of private driver data Michal Malý
2012-04-09 15:53 ` simon
2012-04-09 16:08 ` [PATCH] HID: hid-lg4ff: Add support for G27 LEDs Simon Wood
2012-04-13 12:59 ` Jiri Kosina
2012-04-18 7:03 ` [PATCH 1/2] " Simon Wood
2012-04-18 7:03 ` [PATCH 2/2] HID: hid-lg4ff: Updated Comments Simon Wood
2012-04-18 11:24 ` [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs Jiri Kosina
2012-04-18 14:58 ` simon
2012-04-20 10:05 ` Jiri Kosina
2012-04-21 12:41 ` Simon Wood
2012-04-21 12:41 ` [PATCH 2/2] HID: hid-lg4ff: Updated Comments Simon Wood
2012-04-23 18:55 ` [PATCH 1/2] HID: hid-lg4ff: Add support for G27 LEDs Jiri Kosina
2012-04-13 12:59 ` [PATCH v2] HID: lg4ff: Take advantage of private driver data Jiri Kosina
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).