linux/drivers/hid/hid-roccat-lua.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Roccat Lua driver for Linux
   4 *
   5 * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
   6 */
   7
   8/*
   9 */
  10
  11/*
  12 * Roccat Lua is a gamer mouse which cpi, button and light settings can be
  13 * configured.
  14 */
  15
  16#include <linux/device.h>
  17#include <linux/input.h>
  18#include <linux/hid.h>
  19#include <linux/module.h>
  20#include <linux/slab.h>
  21#include <linux/hid-roccat.h>
  22#include "hid-ids.h"
  23#include "hid-roccat-common.h"
  24#include "hid-roccat-lua.h"
  25
  26static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
  27                char *buf, loff_t off, size_t count,
  28                size_t real_size, uint command)
  29{
  30        struct device *dev = kobj_to_dev(kobj);
  31        struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
  32        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
  33        int retval;
  34
  35        if (off >= real_size)
  36                return 0;
  37
  38        if (off != 0 || count != real_size)
  39                return -EINVAL;
  40
  41        mutex_lock(&lua->lua_lock);
  42        retval = roccat_common2_receive(usb_dev, command, buf, real_size);
  43        mutex_unlock(&lua->lua_lock);
  44
  45        return retval ? retval : real_size;
  46}
  47
  48static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
  49                void const *buf, loff_t off, size_t count,
  50                size_t real_size, uint command)
  51{
  52        struct device *dev = kobj_to_dev(kobj);
  53        struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
  54        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
  55        int retval;
  56
  57        if (off != 0 || count != real_size)
  58                return -EINVAL;
  59
  60        mutex_lock(&lua->lua_lock);
  61        retval = roccat_common2_send(usb_dev, command, buf, real_size);
  62        mutex_unlock(&lua->lua_lock);
  63
  64        return retval ? retval : real_size;
  65}
  66
  67#define LUA_SYSFS_W(thingy, THINGY) \
  68static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \
  69                struct kobject *kobj, struct bin_attribute *attr, \
  70                char *buf, loff_t off, size_t count) \
  71{ \
  72        return lua_sysfs_write(fp, kobj, buf, off, count, \
  73                        LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
  74}
  75
  76#define LUA_SYSFS_R(thingy, THINGY) \
  77static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \
  78                struct kobject *kobj, struct bin_attribute *attr, \
  79                char *buf, loff_t off, size_t count) \
  80{ \
  81        return lua_sysfs_read(fp, kobj, buf, off, count, \
  82                        LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
  83}
  84
  85#define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
  86LUA_SYSFS_W(thingy, THINGY) \
  87LUA_SYSFS_R(thingy, THINGY) \
  88static struct bin_attribute lua_ ## thingy ## _attr = { \
  89        .attr = { .name = #thingy, .mode = 0660 }, \
  90        .size = LUA_SIZE_ ## THINGY, \
  91        .read = lua_sysfs_read_ ## thingy, \
  92        .write = lua_sysfs_write_ ## thingy \
  93};
  94
  95LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
  96
  97static int lua_create_sysfs_attributes(struct usb_interface *intf)
  98{
  99        return sysfs_create_bin_file(&intf->dev.kobj, &lua_control_attr);
 100}
 101
 102static void lua_remove_sysfs_attributes(struct usb_interface *intf)
 103{
 104        sysfs_remove_bin_file(&intf->dev.kobj, &lua_control_attr);
 105}
 106
 107static int lua_init_lua_device_struct(struct usb_device *usb_dev,
 108                struct lua_device *lua)
 109{
 110        mutex_init(&lua->lua_lock);
 111
 112        return 0;
 113}
 114
 115static int lua_init_specials(struct hid_device *hdev)
 116{
 117        struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 118        struct usb_device *usb_dev = interface_to_usbdev(intf);
 119        struct lua_device *lua;
 120        int retval;
 121
 122        lua = kzalloc(sizeof(*lua), GFP_KERNEL);
 123        if (!lua) {
 124                hid_err(hdev, "can't alloc device descriptor\n");
 125                return -ENOMEM;
 126        }
 127        hid_set_drvdata(hdev, lua);
 128
 129        retval = lua_init_lua_device_struct(usb_dev, lua);
 130        if (retval) {
 131                hid_err(hdev, "couldn't init struct lua_device\n");
 132                goto exit;
 133        }
 134
 135        retval = lua_create_sysfs_attributes(intf);
 136        if (retval) {
 137                hid_err(hdev, "cannot create sysfs files\n");
 138                goto exit;
 139        }
 140
 141        return 0;
 142exit:
 143        kfree(lua);
 144        return retval;
 145}
 146
 147static void lua_remove_specials(struct hid_device *hdev)
 148{
 149        struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 150        struct lua_device *lua;
 151
 152        lua_remove_sysfs_attributes(intf);
 153
 154        lua = hid_get_drvdata(hdev);
 155        kfree(lua);
 156}
 157
 158static int lua_probe(struct hid_device *hdev,
 159                const struct hid_device_id *id)
 160{
 161        int retval;
 162
 163        retval = hid_parse(hdev);
 164        if (retval) {
 165                hid_err(hdev, "parse failed\n");
 166                goto exit;
 167        }
 168
 169        retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 170        if (retval) {
 171                hid_err(hdev, "hw start failed\n");
 172                goto exit;
 173        }
 174
 175        retval = lua_init_specials(hdev);
 176        if (retval) {
 177                hid_err(hdev, "couldn't install mouse\n");
 178                goto exit_stop;
 179        }
 180
 181        return 0;
 182
 183exit_stop:
 184        hid_hw_stop(hdev);
 185exit:
 186        return retval;
 187}
 188
 189static void lua_remove(struct hid_device *hdev)
 190{
 191        lua_remove_specials(hdev);
 192        hid_hw_stop(hdev);
 193}
 194
 195static const struct hid_device_id lua_devices[] = {
 196        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
 197        { }
 198};
 199
 200MODULE_DEVICE_TABLE(hid, lua_devices);
 201
 202static struct hid_driver lua_driver = {
 203                .name = "lua",
 204                .id_table = lua_devices,
 205                .probe = lua_probe,
 206                .remove = lua_remove
 207};
 208module_hid_driver(lua_driver);
 209
 210MODULE_AUTHOR("Stefan Achatz");
 211MODULE_DESCRIPTION("USB Roccat Lua driver");
 212MODULE_LICENSE("GPL v2");
 213