hid-roccat-common.c 4.7 KB

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