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