[media] V4L: mx3_camera: convert to the new mbus-config subdev operations
[pandora-kernel.git] / drivers / hid / hid-lg4ff.c
index 5c9eef2..103f30d 100644 (file)
@@ -157,7 +157,9 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e
        return 0;
 }
 
-static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude)
+/* Sends default autocentering command compatible with
+ * all wheels except Formula Force EX */
+static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude)
 {
        struct hid_device *hid = input_get_drvdata(dev);
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
@@ -174,6 +176,26 @@ static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude)
        usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
 
+/* Sends autocentering command compatible with Formula Force EX */
+static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       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);
+       magnitude = magnitude * 90 / 65535;
+       
+
+       report->field[0]->value[0] = 0xfe;
+       report->field[0]->value[1] = 0x03;
+       report->field[0]->value[2] = magnitude >> 14;
+       report->field[0]->value[3] = magnitude >> 14;
+       report->field[0]->value[4] = magnitude;
+       report->field[0]->value[5] = 0x00;
+       report->field[0]->value[6] = 0x00;
+
+       usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
 /* Sends command to set range compatible with G25/G27/Driving Force GT */
 static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
 {
@@ -263,7 +285,7 @@ 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 *entry = 0;
+       struct lg4ff_device_entry *uninitialized_var(entry);
        struct list_head *h;
        struct hid_device *hid = to_hid_device(dev);
        size_t count;
@@ -286,7 +308,7 @@ 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 *entry = 0;
+       struct lg4ff_device_entry *uninitialized_var(entry);
        struct list_head *h;
        struct hid_device *hid = to_hid_device(dev);
        __u16 range = simple_strtoul(buf, NULL, 10);
@@ -390,8 +412,16 @@ int lg4ff_init(struct hid_device *hid)
        if (error)
                return error;
 
-       if (test_bit(FF_AUTOCENTER, dev->ffbit))
-               dev->ff->set_autocenter = hid_lg4ff_set_autocenter;
+       /* Check if autocentering is available and
+        * set the centering force to zero by default */
+       if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+               if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN)  /* Formula Force EX expects different autocentering command */
+                       dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
+               else
+                       dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
+
+               dev->ff->set_autocenter(dev, 0);
+       }
 
                /* Initialize device_list if this is the first device to handle by lg4ff */
        if (!list_inited) {
@@ -405,12 +435,12 @@ int lg4ff_init(struct hid_device *hid)
                hid_err(hid, "Cannot add device, insufficient memory.\n");
                return -ENOMEM;
        }
-       entry->device_id = (char *)kzalloc(strlen((&hid->dev)->kobj.name) + 1, GFP_KERNEL);
+       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);
                return -ENOMEM;
        }
-       strcpy(entry->device_id, (&hid->dev)->kobj.name);
        entry->min_range = lg4ff_devices[i].min_range;
        entry->max_range = lg4ff_devices[i].max_range;
        entry->set_range = lg4ff_devices[i].set_range;