0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/hid.h>
0012 #include <linux/slab.h>
0013 #include <linux/module.h>
0014 #include "hid-roccat-common.h"
0015
0016 static inline uint16_t roccat_common2_feature_report(uint8_t report_id)
0017 {
0018 return 0x300 | report_id;
0019 }
0020
0021 int roccat_common2_receive(struct usb_device *usb_dev, uint report_id,
0022 void *data, uint size)
0023 {
0024 char *buf;
0025 int len;
0026
0027 buf = kmalloc(size, GFP_KERNEL);
0028 if (buf == NULL)
0029 return -ENOMEM;
0030
0031 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
0032 HID_REQ_GET_REPORT,
0033 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
0034 roccat_common2_feature_report(report_id),
0035 0, buf, size, USB_CTRL_SET_TIMEOUT);
0036
0037 memcpy(data, buf, size);
0038 kfree(buf);
0039 return ((len < 0) ? len : ((len != size) ? -EIO : 0));
0040 }
0041 EXPORT_SYMBOL_GPL(roccat_common2_receive);
0042
0043 int roccat_common2_send(struct usb_device *usb_dev, uint report_id,
0044 void const *data, uint size)
0045 {
0046 char *buf;
0047 int len;
0048
0049 buf = kmemdup(data, size, GFP_KERNEL);
0050 if (buf == NULL)
0051 return -ENOMEM;
0052
0053 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
0054 HID_REQ_SET_REPORT,
0055 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
0056 roccat_common2_feature_report(report_id),
0057 0, buf, size, USB_CTRL_SET_TIMEOUT);
0058
0059 kfree(buf);
0060 return ((len < 0) ? len : ((len != size) ? -EIO : 0));
0061 }
0062 EXPORT_SYMBOL_GPL(roccat_common2_send);
0063
0064 enum roccat_common2_control_states {
0065 ROCCAT_COMMON_CONTROL_STATUS_CRITICAL = 0,
0066 ROCCAT_COMMON_CONTROL_STATUS_OK = 1,
0067 ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2,
0068 ROCCAT_COMMON_CONTROL_STATUS_BUSY = 3,
0069 ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW = 4,
0070 };
0071
0072 static int roccat_common2_receive_control_status(struct usb_device *usb_dev)
0073 {
0074 int retval;
0075 struct roccat_common2_control control;
0076
0077 do {
0078 msleep(50);
0079 retval = roccat_common2_receive(usb_dev,
0080 ROCCAT_COMMON_COMMAND_CONTROL,
0081 &control, sizeof(struct roccat_common2_control));
0082
0083 if (retval)
0084 return retval;
0085
0086 switch (control.value) {
0087 case ROCCAT_COMMON_CONTROL_STATUS_OK:
0088 return 0;
0089 case ROCCAT_COMMON_CONTROL_STATUS_BUSY:
0090 msleep(500);
0091 continue;
0092 case ROCCAT_COMMON_CONTROL_STATUS_INVALID:
0093 case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL:
0094 case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW:
0095 return -EINVAL;
0096 default:
0097 dev_err(&usb_dev->dev,
0098 "roccat_common2_receive_control_status: "
0099 "unknown response value 0x%x\n",
0100 control.value);
0101 return -EINVAL;
0102 }
0103
0104 } while (1);
0105 }
0106
0107 int roccat_common2_send_with_status(struct usb_device *usb_dev,
0108 uint command, void const *buf, uint size)
0109 {
0110 int retval;
0111
0112 retval = roccat_common2_send(usb_dev, command, buf, size);
0113 if (retval)
0114 return retval;
0115
0116 msleep(100);
0117
0118 return roccat_common2_receive_control_status(usb_dev);
0119 }
0120 EXPORT_SYMBOL_GPL(roccat_common2_send_with_status);
0121
0122 int roccat_common2_device_init_struct(struct usb_device *usb_dev,
0123 struct roccat_common2_device *dev)
0124 {
0125 mutex_init(&dev->lock);
0126 return 0;
0127 }
0128 EXPORT_SYMBOL_GPL(roccat_common2_device_init_struct);
0129
0130 ssize_t roccat_common2_sysfs_read(struct file *fp, struct kobject *kobj,
0131 char *buf, loff_t off, size_t count,
0132 size_t real_size, uint command)
0133 {
0134 struct device *dev = kobj_to_dev(kobj)->parent->parent;
0135 struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
0136 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
0137 int retval;
0138
0139 if (off >= real_size)
0140 return 0;
0141
0142 if (off != 0 || count != real_size)
0143 return -EINVAL;
0144
0145 mutex_lock(&roccat_dev->lock);
0146 retval = roccat_common2_receive(usb_dev, command, buf, real_size);
0147 mutex_unlock(&roccat_dev->lock);
0148
0149 return retval ? retval : real_size;
0150 }
0151 EXPORT_SYMBOL_GPL(roccat_common2_sysfs_read);
0152
0153 ssize_t roccat_common2_sysfs_write(struct file *fp, struct kobject *kobj,
0154 void const *buf, loff_t off, size_t count,
0155 size_t real_size, uint command)
0156 {
0157 struct device *dev = kobj_to_dev(kobj)->parent->parent;
0158 struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
0159 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
0160 int retval;
0161
0162 if (off != 0 || count != real_size)
0163 return -EINVAL;
0164
0165 mutex_lock(&roccat_dev->lock);
0166 retval = roccat_common2_send_with_status(usb_dev, command, buf, real_size);
0167 mutex_unlock(&roccat_dev->lock);
0168
0169 return retval ? retval : real_size;
0170 }
0171 EXPORT_SYMBOL_GPL(roccat_common2_sysfs_write);
0172
0173 MODULE_AUTHOR("Stefan Achatz");
0174 MODULE_DESCRIPTION("USB Roccat common driver");
0175 MODULE_LICENSE("GPL v2");