Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Roccat common functions for device specific drivers
0004  *
0005  * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net>
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");