root/drivers/hid/hid-sjoy.c

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

DEFINITIONS

This source file includes following definitions.
  1. hid_sjoyff_play
  2. sjoyff_init
  3. sjoyff_init
  4. sjoy_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Force feedback support for SmartJoy PLUS PS2->USB adapter
   4  *
   5  *  Copyright (c) 2009 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
   6  *
   7  *  Based of hid-pl.c and hid-gaff.c
   8  *   Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com>
   9  *   Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
  10  */
  11 
  12 /*
  13  */
  14 
  15 /* #define DEBUG */
  16 
  17 #include <linux/input.h>
  18 #include <linux/slab.h>
  19 #include <linux/hid.h>
  20 #include <linux/module.h>
  21 #include "hid-ids.h"
  22 
  23 #ifdef CONFIG_SMARTJOYPLUS_FF
  24 
  25 struct sjoyff_device {
  26         struct hid_report *report;
  27 };
  28 
  29 static int hid_sjoyff_play(struct input_dev *dev, void *data,
  30                          struct ff_effect *effect)
  31 {
  32         struct hid_device *hid = input_get_drvdata(dev);
  33         struct sjoyff_device *sjoyff = data;
  34         u32 left, right;
  35 
  36         left = effect->u.rumble.strong_magnitude;
  37         right = effect->u.rumble.weak_magnitude;
  38         dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right);
  39 
  40         left = left * 0xff / 0xffff;
  41         right = (right != 0); /* on/off only */
  42 
  43         sjoyff->report->field[0]->value[1] = right;
  44         sjoyff->report->field[0]->value[2] = left;
  45         dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
  46         hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
  47 
  48         return 0;
  49 }
  50 
  51 static int sjoyff_init(struct hid_device *hid)
  52 {
  53         struct sjoyff_device *sjoyff;
  54         struct hid_report *report;
  55         struct hid_input *hidinput;
  56         struct list_head *report_list =
  57                         &hid->report_enum[HID_OUTPUT_REPORT].report_list;
  58         struct list_head *report_ptr = report_list;
  59         struct input_dev *dev;
  60         int error;
  61 
  62         if (list_empty(report_list)) {
  63                 hid_err(hid, "no output reports found\n");
  64                 return -ENODEV;
  65         }
  66 
  67         list_for_each_entry(hidinput, &hid->inputs, list) {
  68                 report_ptr = report_ptr->next;
  69 
  70                 if (report_ptr == report_list) {
  71                         hid_err(hid, "required output report is missing\n");
  72                         return -ENODEV;
  73                 }
  74 
  75                 report = list_entry(report_ptr, struct hid_report, list);
  76                 if (report->maxfield < 1) {
  77                         hid_err(hid, "no fields in the report\n");
  78                         return -ENODEV;
  79                 }
  80 
  81                 if (report->field[0]->report_count < 3) {
  82                         hid_err(hid, "not enough values in the field\n");
  83                         return -ENODEV;
  84                 }
  85 
  86                 sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
  87                 if (!sjoyff)
  88                         return -ENOMEM;
  89 
  90                 dev = hidinput->input;
  91 
  92                 set_bit(FF_RUMBLE, dev->ffbit);
  93 
  94                 error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
  95                 if (error) {
  96                         kfree(sjoyff);
  97                         return error;
  98                 }
  99 
 100                 sjoyff->report = report;
 101                 sjoyff->report->field[0]->value[0] = 0x01;
 102                 sjoyff->report->field[0]->value[1] = 0x00;
 103                 sjoyff->report->field[0]->value[2] = 0x00;
 104                 hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
 105         }
 106 
 107         hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
 108 
 109         return 0;
 110 }
 111 #else
 112 static inline int sjoyff_init(struct hid_device *hid)
 113 {
 114         return 0;
 115 }
 116 #endif
 117 
 118 static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id)
 119 {
 120         int ret;
 121 
 122         hdev->quirks |= id->driver_data;
 123 
 124         ret = hid_parse(hdev);
 125         if (ret) {
 126                 hid_err(hdev, "parse failed\n");
 127                 goto err;
 128         }
 129 
 130         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 131         if (ret) {
 132                 hid_err(hdev, "hw start failed\n");
 133                 goto err;
 134         }
 135 
 136         sjoyff_init(hdev);
 137 
 138         return 0;
 139 err:
 140         return ret;
 141 }
 142 
 143 static const struct hid_device_id sjoy_devices[] = {
 144         { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO),
 145                 .driver_data = HID_QUIRK_NOGET },
 146         { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO),
 147                 .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
 148                                HID_QUIRK_SKIP_OUTPUT_REPORTS },
 149         { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO),
 150                 .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
 151                                HID_QUIRK_SKIP_OUTPUT_REPORTS },
 152         { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
 153         { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
 154         { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD),
 155                 .driver_data = HID_QUIRK_MULTI_INPUT |
 156                                HID_QUIRK_SKIP_OUTPUT_REPORTS },
 157         { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII),
 158                 .driver_data = HID_QUIRK_MULTI_INPUT |
 159                                HID_QUIRK_SKIP_OUTPUT_REPORTS },
 160         { }
 161 };
 162 MODULE_DEVICE_TABLE(hid, sjoy_devices);
 163 
 164 static struct hid_driver sjoy_driver = {
 165         .name = "smartjoyplus",
 166         .id_table = sjoy_devices,
 167         .probe = sjoy_probe,
 168 };
 169 module_hid_driver(sjoy_driver);
 170 
 171 MODULE_LICENSE("GPL");
 172 MODULE_AUTHOR("Jussi Kivilinna");
 173 

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