Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

Linux/drivers/hid/hid-axff.c

  1 /*
  2  * Force feedback support for ACRUX game controllers
  3  *
  4  * From what I have gathered, these devices are mass produced in China
  5  * by several vendors. They often share the same design as the original
  6  * Xbox 360 controller.
  7  *
  8  * 1a34:0802 "ACRUX USB GAMEPAD 8116"
  9  *  - tested with an EXEQ EQ-PCU-02090 game controller.
 10  *
 11  * Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru>
 12  */
 13 
 14 /*
 15  * This program is free software; you can redistribute it and/or modify
 16  * it under the terms of the GNU General Public License as published by
 17  * the Free Software Foundation; either version 2 of the License, or
 18  * (at your option) any later version.
 19  *
 20  * This program is distributed in the hope that it will be useful,
 21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 23  * GNU General Public License for more details.
 24  *
 25  * You should have received a copy of the GNU General Public License
 26  * along with this program; if not, write to the Free Software
 27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 28  */
 29 
 30 #include <linux/input.h>
 31 #include <linux/slab.h>
 32 #include <linux/hid.h>
 33 #include <linux/module.h>
 34 
 35 #include "hid-ids.h"
 36 
 37 #ifdef CONFIG_HID_ACRUX_FF
 38 
 39 struct axff_device {
 40         struct hid_report *report;
 41 };
 42 
 43 static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 44 {
 45         struct hid_device *hid = input_get_drvdata(dev);
 46         struct axff_device *axff = data;
 47         struct hid_report *report = axff->report;
 48         int field_count = 0;
 49         int left, right;
 50         int i, j;
 51 
 52         left = effect->u.rumble.strong_magnitude;
 53         right = effect->u.rumble.weak_magnitude;
 54 
 55         dbg_hid("called with 0x%04x 0x%04x", left, right);
 56 
 57         left = left * 0xff / 0xffff;
 58         right = right * 0xff / 0xffff;
 59 
 60         for (i = 0; i < report->maxfield; i++) {
 61                 for (j = 0; j < report->field[i]->report_count; j++) {
 62                         report->field[i]->value[j] =
 63                                 field_count % 2 ? right : left;
 64                         field_count++;
 65                 }
 66         }
 67 
 68         dbg_hid("running with 0x%02x 0x%02x", left, right);
 69         hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
 70 
 71         return 0;
 72 }
 73 
 74 static int axff_init(struct hid_device *hid)
 75 {
 76         struct axff_device *axff;
 77         struct hid_report *report;
 78         struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
 79         struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
 80         struct input_dev *dev = hidinput->input;
 81         int field_count = 0;
 82         int i, j;
 83         int error;
 84 
 85         if (list_empty(report_list)) {
 86                 hid_err(hid, "no output reports found\n");
 87                 return -ENODEV;
 88         }
 89 
 90         report = list_first_entry(report_list, struct hid_report, list);
 91         for (i = 0; i < report->maxfield; i++) {
 92                 for (j = 0; j < report->field[i]->report_count; j++) {
 93                         report->field[i]->value[j] = 0x00;
 94                         field_count++;
 95                 }
 96         }
 97 
 98         if (field_count < 4 && hid->product != 0xf705) {
 99                 hid_err(hid, "not enough fields in the report: %d\n",
100                         field_count);
101                 return -ENODEV;
102         }
103 
104         axff = kzalloc(sizeof(struct axff_device), GFP_KERNEL);
105         if (!axff)
106                 return -ENOMEM;
107 
108         set_bit(FF_RUMBLE, dev->ffbit);
109 
110         error = input_ff_create_memless(dev, axff, axff_play);
111         if (error)
112                 goto err_free_mem;
113 
114         axff->report = report;
115         hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
116 
117         hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n");
118 
119         return 0;
120 
121 err_free_mem:
122         kfree(axff);
123         return error;
124 }
125 #else
126 static inline int axff_init(struct hid_device *hid)
127 {
128         return 0;
129 }
130 #endif
131 
132 static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
133 {
134         int error;
135 
136         dev_dbg(&hdev->dev, "ACRUX HID hardware probe...\n");
137 
138         error = hid_parse(hdev);
139         if (error) {
140                 hid_err(hdev, "parse failed\n");
141                 return error;
142         }
143 
144         error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
145         if (error) {
146                 hid_err(hdev, "hw start failed\n");
147                 return error;
148         }
149 
150         error = axff_init(hdev);
151         if (error) {
152                 /*
153                  * Do not fail device initialization completely as device
154                  * may still be partially operable, just warn.
155                  */
156                 hid_warn(hdev,
157                          "Failed to enable force feedback support, error: %d\n",
158                          error);
159         }
160 
161         /*
162          * We need to start polling device right away, otherwise
163          * it will go into a coma.
164          */
165         error = hid_hw_open(hdev);
166         if (error) {
167                 dev_err(&hdev->dev, "hw open failed\n");
168                 hid_hw_stop(hdev);
169                 return error;
170         }
171 
172         return 0;
173 }
174 
175 static void ax_remove(struct hid_device *hdev)
176 {
177         hid_hw_close(hdev);
178         hid_hw_stop(hdev);
179 }
180 
181 static const struct hid_device_id ax_devices[] = {
182         { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), },
183         { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705), },
184         { }
185 };
186 MODULE_DEVICE_TABLE(hid, ax_devices);
187 
188 static struct hid_driver ax_driver = {
189         .name           = "acrux",
190         .id_table       = ax_devices,
191         .probe          = ax_probe,
192         .remove         = ax_remove,
193 };
194 module_hid_driver(ax_driver);
195 
196 MODULE_AUTHOR("Sergei Kolzun");
197 MODULE_DESCRIPTION("Force feedback support for ACRUX game controllers");
198 MODULE_LICENSE("GPL");
199 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us