Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hid-roccat-common.c
Go to the documentation of this file.
1 /*
2  * Roccat common functions for device specific drivers
3  *
4  * Copyright (c) 2011 Stefan Achatz <[email protected]>
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 #include <linux/hid.h>
15 #include <linux/slab.h>
16 #include <linux/module.h>
17 #include "hid-roccat-common.h"
18 
19 static inline uint16_t roccat_common2_feature_report(uint8_t report_id)
20 {
21  return 0x300 | report_id;
22 }
23 
24 int roccat_common2_receive(struct usb_device *usb_dev, uint report_id,
25  void *data, uint size)
26 {
27  char *buf;
28  int len;
29 
30  buf = kmalloc(size, GFP_KERNEL);
31  if (buf == NULL)
32  return -ENOMEM;
33 
34  len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
37  roccat_common2_feature_report(report_id),
38  0, buf, size, USB_CTRL_SET_TIMEOUT);
39 
40  memcpy(data, buf, size);
41  kfree(buf);
42  return ((len < 0) ? len : ((len != size) ? -EIO : 0));
43 }
45 
46 int roccat_common2_send(struct usb_device *usb_dev, uint report_id,
47  void const *data, uint size)
48 {
49  char *buf;
50  int len;
51 
52  buf = kmemdup(data, size, GFP_KERNEL);
53  if (buf == NULL)
54  return -ENOMEM;
55 
56  len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
59  roccat_common2_feature_report(report_id),
60  0, buf, size, USB_CTRL_SET_TIMEOUT);
61 
62  kfree(buf);
63  return ((len < 0) ? len : ((len != size) ? -EIO : 0));
64 }
66 
72 };
73 
74 static int roccat_common2_receive_control_status(struct usb_device *usb_dev)
75 {
76  int retval;
77  struct roccat_common2_control control;
78 
79  do {
80  msleep(50);
81  retval = roccat_common2_receive(usb_dev,
83  &control, sizeof(struct roccat_common2_control));
84 
85  if (retval)
86  return retval;
87 
88  switch (control.value) {
90  return 0;
92  msleep(500);
93  continue;
95 
97  /* seems to be critical - replug necessary */
98  return -EINVAL;
99  default:
100  dev_err(&usb_dev->dev,
101  "roccat_common2_receive_control_status: "
102  "unknown response value 0x%x\n",
103  control.value);
104  return -EINVAL;
105  }
106 
107  } while (1);
108 }
109 
110 int roccat_common2_send_with_status(struct usb_device *usb_dev,
111  uint command, void const *buf, uint size)
112 {
113  int retval;
114 
115  retval = roccat_common2_send(usb_dev, command, buf, size);
116  if (retval)
117  return retval;
118 
119  msleep(100);
120 
121  return roccat_common2_receive_control_status(usb_dev);
122 }
124 
125 MODULE_AUTHOR("Stefan Achatz");
126 MODULE_DESCRIPTION("USB Roccat common driver");
127 MODULE_LICENSE("GPL v2");