root/drivers/hid/hid-axff.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. axff_play
  2. axff_init
  3. axff_init
  4. ax_probe
  5. ax_remove

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

/* [<][>][^][v][top][bottom][index][help] */