root/drivers/hid/hid-roccat-common.c

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

DEFINITIONS

This source file includes following definitions.
  1. roccat_common2_feature_report
  2. roccat_common2_receive
  3. roccat_common2_send
  4. roccat_common2_receive_control_status
  5. roccat_common2_send_with_status
  6. roccat_common2_device_init_struct
  7. roccat_common2_sysfs_read
  8. roccat_common2_sysfs_write

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Roccat common functions for device specific drivers
   4  *
   5  * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net>
   6  */
   7 
   8 /*
   9  */
  10 
  11 #include <linux/hid.h>
  12 #include <linux/slab.h>
  13 #include <linux/module.h>
  14 #include "hid-roccat-common.h"
  15 
  16 static inline uint16_t roccat_common2_feature_report(uint8_t report_id)
  17 {
  18         return 0x300 | report_id;
  19 }
  20 
  21 int roccat_common2_receive(struct usb_device *usb_dev, uint report_id,
  22                 void *data, uint size)
  23 {
  24         char *buf;
  25         int len;
  26 
  27         buf = kmalloc(size, GFP_KERNEL);
  28         if (buf == NULL)
  29                 return -ENOMEM;
  30 
  31         len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
  32                         HID_REQ_GET_REPORT,
  33                         USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
  34                         roccat_common2_feature_report(report_id),
  35                         0, buf, size, USB_CTRL_SET_TIMEOUT);
  36 
  37         memcpy(data, buf, size);
  38         kfree(buf);
  39         return ((len < 0) ? len : ((len != size) ? -EIO : 0));
  40 }
  41 EXPORT_SYMBOL_GPL(roccat_common2_receive);
  42 
  43 int roccat_common2_send(struct usb_device *usb_dev, uint report_id,
  44                 void const *data, uint size)
  45 {
  46         char *buf;
  47         int len;
  48 
  49         buf = kmemdup(data, size, GFP_KERNEL);
  50         if (buf == NULL)
  51                 return -ENOMEM;
  52 
  53         len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
  54                         HID_REQ_SET_REPORT,
  55                         USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
  56                         roccat_common2_feature_report(report_id),
  57                         0, buf, size, USB_CTRL_SET_TIMEOUT);
  58 
  59         kfree(buf);
  60         return ((len < 0) ? len : ((len != size) ? -EIO : 0));
  61 }
  62 EXPORT_SYMBOL_GPL(roccat_common2_send);
  63 
  64 enum roccat_common2_control_states {
  65         ROCCAT_COMMON_CONTROL_STATUS_CRITICAL = 0,
  66         ROCCAT_COMMON_CONTROL_STATUS_OK = 1,
  67         ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2,
  68         ROCCAT_COMMON_CONTROL_STATUS_BUSY = 3,
  69         ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW = 4,
  70 };
  71 
  72 static int roccat_common2_receive_control_status(struct usb_device *usb_dev)
  73 {
  74         int retval;
  75         struct roccat_common2_control control;
  76 
  77         do {
  78                 msleep(50);
  79                 retval = roccat_common2_receive(usb_dev,
  80                                 ROCCAT_COMMON_COMMAND_CONTROL,
  81                                 &control, sizeof(struct roccat_common2_control));
  82 
  83                 if (retval)
  84                         return retval;
  85 
  86                 switch (control.value) {
  87                 case ROCCAT_COMMON_CONTROL_STATUS_OK:
  88                         return 0;
  89                 case ROCCAT_COMMON_CONTROL_STATUS_BUSY:
  90                         msleep(500);
  91                         continue;
  92                 case ROCCAT_COMMON_CONTROL_STATUS_INVALID:
  93                 case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL:
  94                 case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW:
  95                         return -EINVAL;
  96                 default:
  97                         dev_err(&usb_dev->dev,
  98                                         "roccat_common2_receive_control_status: "
  99                                         "unknown response value 0x%x\n",
 100                                         control.value);
 101                         return -EINVAL;
 102                 }
 103 
 104         } while (1);
 105 }
 106 
 107 int roccat_common2_send_with_status(struct usb_device *usb_dev,
 108                 uint command, void const *buf, uint size)
 109 {
 110         int retval;
 111 
 112         retval = roccat_common2_send(usb_dev, command, buf, size);
 113         if (retval)
 114                 return retval;
 115 
 116         msleep(100);
 117 
 118         return roccat_common2_receive_control_status(usb_dev);
 119 }
 120 EXPORT_SYMBOL_GPL(roccat_common2_send_with_status);
 121 
 122 int roccat_common2_device_init_struct(struct usb_device *usb_dev,
 123                 struct roccat_common2_device *dev)
 124 {
 125         mutex_init(&dev->lock);
 126         return 0;
 127 }
 128 EXPORT_SYMBOL_GPL(roccat_common2_device_init_struct);
 129 
 130 ssize_t roccat_common2_sysfs_read(struct file *fp, struct kobject *kobj,
 131                 char *buf, loff_t off, size_t count,
 132                 size_t real_size, uint command)
 133 {
 134         struct device *dev = kobj_to_dev(kobj)->parent->parent;
 135         struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
 136         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 137         int retval;
 138 
 139         if (off >= real_size)
 140                 return 0;
 141 
 142         if (off != 0 || count != real_size)
 143                 return -EINVAL;
 144 
 145         mutex_lock(&roccat_dev->lock);
 146         retval = roccat_common2_receive(usb_dev, command, buf, real_size);
 147         mutex_unlock(&roccat_dev->lock);
 148 
 149         return retval ? retval : real_size;
 150 }
 151 EXPORT_SYMBOL_GPL(roccat_common2_sysfs_read);
 152 
 153 ssize_t roccat_common2_sysfs_write(struct file *fp, struct kobject *kobj,
 154                 void const *buf, loff_t off, size_t count,
 155                 size_t real_size, uint command)
 156 {
 157         struct device *dev = kobj_to_dev(kobj)->parent->parent;
 158         struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
 159         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 160         int retval;
 161 
 162         if (off != 0 || count != real_size)
 163                 return -EINVAL;
 164 
 165         mutex_lock(&roccat_dev->lock);
 166         retval = roccat_common2_send_with_status(usb_dev, command, buf, real_size);
 167         mutex_unlock(&roccat_dev->lock);
 168 
 169         return retval ? retval : real_size;
 170 }
 171 EXPORT_SYMBOL_GPL(roccat_common2_sysfs_write);
 172 
 173 MODULE_AUTHOR("Stefan Achatz");
 174 MODULE_DESCRIPTION("USB Roccat common driver");
 175 MODULE_LICENSE("GPL v2");

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