diff options
Diffstat (limited to 'drivers/usb/input/hiddev.c')
-rw-r--r-- | drivers/usb/input/hiddev.c | 72 |
1 files changed, 38 insertions, 34 deletions
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 70477f02cc29..f6b839c257a7 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c | |||
@@ -49,7 +49,7 @@ struct hiddev { | |||
49 | int open; | 49 | int open; |
50 | wait_queue_head_t wait; | 50 | wait_queue_head_t wait; |
51 | struct hid_device *hid; | 51 | struct hid_device *hid; |
52 | struct hiddev_list *list; | 52 | struct list_head list; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | struct hiddev_list { | 55 | struct hiddev_list { |
@@ -59,7 +59,7 @@ struct hiddev_list { | |||
59 | unsigned flags; | 59 | unsigned flags; |
60 | struct fasync_struct *fasync; | 60 | struct fasync_struct *fasync; |
61 | struct hiddev *hiddev; | 61 | struct hiddev *hiddev; |
62 | struct hiddev_list *next; | 62 | struct list_head node; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | 65 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; |
@@ -73,12 +73,15 @@ static struct hiddev *hiddev_table[HIDDEV_MINORS]; | |||
73 | static struct hid_report * | 73 | static struct hid_report * |
74 | hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | 74 | hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) |
75 | { | 75 | { |
76 | unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK; | 76 | unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; |
77 | unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; | ||
77 | struct hid_report_enum *report_enum; | 78 | struct hid_report_enum *report_enum; |
79 | struct hid_report *report; | ||
78 | struct list_head *list; | 80 | struct list_head *list; |
79 | 81 | ||
80 | if (rinfo->report_type < HID_REPORT_TYPE_MIN || | 82 | if (rinfo->report_type < HID_REPORT_TYPE_MIN || |
81 | rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL; | 83 | rinfo->report_type > HID_REPORT_TYPE_MAX) |
84 | return NULL; | ||
82 | 85 | ||
83 | report_enum = hid->report_enum + | 86 | report_enum = hid->report_enum + |
84 | (rinfo->report_type - HID_REPORT_TYPE_MIN); | 87 | (rinfo->report_type - HID_REPORT_TYPE_MIN); |
@@ -88,21 +91,25 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | |||
88 | break; | 91 | break; |
89 | 92 | ||
90 | case HID_REPORT_ID_FIRST: | 93 | case HID_REPORT_ID_FIRST: |
91 | list = report_enum->report_list.next; | 94 | if (list_empty(&report_enum->report_list)) |
92 | if (list == &report_enum->report_list) | ||
93 | return NULL; | 95 | return NULL; |
94 | rinfo->report_id = ((struct hid_report *) list)->id; | 96 | |
97 | list = report_enum->report_list.next; | ||
98 | report = list_entry(list, struct hid_report, list); | ||
99 | rinfo->report_id = report->id; | ||
95 | break; | 100 | break; |
96 | 101 | ||
97 | case HID_REPORT_ID_NEXT: | 102 | case HID_REPORT_ID_NEXT: |
98 | list = (struct list_head *) | 103 | report = report_enum->report_id_hash[rid]; |
99 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; | 104 | if (!report) |
100 | if (list == NULL) | ||
101 | return NULL; | 105 | return NULL; |
102 | list = list->next; | 106 | |
107 | list = report->list.next; | ||
103 | if (list == &report_enum->report_list) | 108 | if (list == &report_enum->report_list) |
104 | return NULL; | 109 | return NULL; |
105 | rinfo->report_id = ((struct hid_report *) list)->id; | 110 | |
111 | report = list_entry(list, struct hid_report, list); | ||
112 | rinfo->report_id = report->id; | ||
106 | break; | 113 | break; |
107 | 114 | ||
108 | default: | 115 | default: |
@@ -125,12 +132,13 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) | |||
125 | struct hid_field *field; | 132 | struct hid_field *field; |
126 | 133 | ||
127 | if (uref->report_type < HID_REPORT_TYPE_MIN || | 134 | if (uref->report_type < HID_REPORT_TYPE_MIN || |
128 | uref->report_type > HID_REPORT_TYPE_MAX) return NULL; | 135 | uref->report_type > HID_REPORT_TYPE_MAX) |
136 | return NULL; | ||
129 | 137 | ||
130 | report_enum = hid->report_enum + | 138 | report_enum = hid->report_enum + |
131 | (uref->report_type - HID_REPORT_TYPE_MIN); | 139 | (uref->report_type - HID_REPORT_TYPE_MIN); |
132 | 140 | ||
133 | list_for_each_entry(report, &report_enum->report_list, list) | 141 | list_for_each_entry(report, &report_enum->report_list, list) { |
134 | for (i = 0; i < report->maxfield; i++) { | 142 | for (i = 0; i < report->maxfield; i++) { |
135 | field = report->field[i]; | 143 | field = report->field[i]; |
136 | for (j = 0; j < field->maxusage; j++) { | 144 | for (j = 0; j < field->maxusage; j++) { |
@@ -142,6 +150,7 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) | |||
142 | } | 150 | } |
143 | } | 151 | } |
144 | } | 152 | } |
153 | } | ||
145 | 154 | ||
146 | return NULL; | 155 | return NULL; |
147 | } | 156 | } |
@@ -150,9 +159,9 @@ static void hiddev_send_event(struct hid_device *hid, | |||
150 | struct hiddev_usage_ref *uref) | 159 | struct hiddev_usage_ref *uref) |
151 | { | 160 | { |
152 | struct hiddev *hiddev = hid->hiddev; | 161 | struct hiddev *hiddev = hid->hiddev; |
153 | struct hiddev_list *list = hiddev->list; | 162 | struct hiddev_list *list; |
154 | 163 | ||
155 | while (list) { | 164 | list_for_each_entry(list, &hiddev->list, node) { |
156 | if (uref->field_index != HID_FIELD_INDEX_NONE || | 165 | if (uref->field_index != HID_FIELD_INDEX_NONE || |
157 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | 166 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { |
158 | list->buffer[list->head] = *uref; | 167 | list->buffer[list->head] = *uref; |
@@ -160,8 +169,6 @@ static void hiddev_send_event(struct hid_device *hid, | |||
160 | (HIDDEV_BUFFER_SIZE - 1); | 169 | (HIDDEV_BUFFER_SIZE - 1); |
161 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 170 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
162 | } | 171 | } |
163 | |||
164 | list = list->next; | ||
165 | } | 172 | } |
166 | 173 | ||
167 | wake_up_interruptible(&hiddev->wait); | 174 | wake_up_interruptible(&hiddev->wait); |
@@ -180,7 +187,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | |||
180 | uref.report_type = | 187 | uref.report_type = |
181 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 188 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
182 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 189 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
183 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 190 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); |
184 | uref.report_id = field->report->id; | 191 | uref.report_id = field->report->id; |
185 | uref.field_index = field->index; | 192 | uref.field_index = field->index; |
186 | uref.usage_index = (usage - field->usage); | 193 | uref.usage_index = (usage - field->usage); |
@@ -200,7 +207,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | |||
200 | uref.report_type = | 207 | uref.report_type = |
201 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 208 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
202 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 209 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
203 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 210 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); |
204 | uref.report_id = report->id; | 211 | uref.report_id = report->id; |
205 | uref.field_index = HID_FIELD_INDEX_NONE; | 212 | uref.field_index = HID_FIELD_INDEX_NONE; |
206 | 213 | ||
@@ -213,7 +220,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) | |||
213 | { | 220 | { |
214 | int retval; | 221 | int retval; |
215 | struct hiddev_list *list = file->private_data; | 222 | struct hiddev_list *list = file->private_data; |
223 | |||
216 | retval = fasync_helper(fd, file, on, &list->fasync); | 224 | retval = fasync_helper(fd, file, on, &list->fasync); |
225 | |||
217 | return retval < 0 ? retval : 0; | 226 | return retval < 0 ? retval : 0; |
218 | } | 227 | } |
219 | 228 | ||
@@ -224,14 +233,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) | |||
224 | static int hiddev_release(struct inode * inode, struct file * file) | 233 | static int hiddev_release(struct inode * inode, struct file * file) |
225 | { | 234 | { |
226 | struct hiddev_list *list = file->private_data; | 235 | struct hiddev_list *list = file->private_data; |
227 | struct hiddev_list **listptr; | ||
228 | 236 | ||
229 | listptr = &list->hiddev->list; | ||
230 | hiddev_fasync(-1, file, 0); | 237 | hiddev_fasync(-1, file, 0); |
231 | 238 | list_del(&list->node); | |
232 | while (*listptr && (*listptr != list)) | ||
233 | listptr = &((*listptr)->next); | ||
234 | *listptr = (*listptr)->next; | ||
235 | 239 | ||
236 | if (!--list->hiddev->open) { | 240 | if (!--list->hiddev->open) { |
237 | if (list->hiddev->exist) | 241 | if (list->hiddev->exist) |
@@ -248,7 +252,8 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
248 | /* | 252 | /* |
249 | * open file op | 253 | * open file op |
250 | */ | 254 | */ |
251 | static int hiddev_open(struct inode * inode, struct file * file) { | 255 | static int hiddev_open(struct inode *inode, struct file *file) |
256 | { | ||
252 | struct hiddev_list *list; | 257 | struct hiddev_list *list; |
253 | 258 | ||
254 | int i = iminor(inode) - HIDDEV_MINOR_BASE; | 259 | int i = iminor(inode) - HIDDEV_MINOR_BASE; |
@@ -260,9 +265,7 @@ static int hiddev_open(struct inode * inode, struct file * file) { | |||
260 | return -ENOMEM; | 265 | return -ENOMEM; |
261 | 266 | ||
262 | list->hiddev = hiddev_table[i]; | 267 | list->hiddev = hiddev_table[i]; |
263 | list->next = hiddev_table[i]->list; | 268 | list_add_tail(&list->node, &hiddev_table[i]->list); |
264 | hiddev_table[i]->list = list; | ||
265 | |||
266 | file->private_data = list; | 269 | file->private_data = list; |
267 | 270 | ||
268 | if (!list->hiddev->open++) | 271 | if (!list->hiddev->open++) |
@@ -362,6 +365,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
362 | static unsigned int hiddev_poll(struct file *file, poll_table *wait) | 365 | static unsigned int hiddev_poll(struct file *file, poll_table *wait) |
363 | { | 366 | { |
364 | struct hiddev_list *list = file->private_data; | 367 | struct hiddev_list *list = file->private_data; |
368 | |||
365 | poll_wait(file, &list->hiddev->wait, wait); | 369 | poll_wait(file, &list->hiddev->wait, wait); |
366 | if (list->head != list->tail) | 370 | if (list->head != list->tail) |
367 | return POLLIN | POLLRDNORM; | 371 | return POLLIN | POLLRDNORM; |
@@ -382,7 +386,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
382 | struct hiddev_collection_info cinfo; | 386 | struct hiddev_collection_info cinfo; |
383 | struct hiddev_report_info rinfo; | 387 | struct hiddev_report_info rinfo; |
384 | struct hiddev_field_info finfo; | 388 | struct hiddev_field_info finfo; |
385 | struct hiddev_usage_ref_multi *uref_multi=NULL; | 389 | struct hiddev_usage_ref_multi *uref_multi = NULL; |
386 | struct hiddev_usage_ref *uref; | 390 | struct hiddev_usage_ref *uref; |
387 | struct hiddev_devinfo dinfo; | 391 | struct hiddev_devinfo dinfo; |
388 | struct hid_report *report; | 392 | struct hid_report *report; |
@@ -764,15 +768,15 @@ int hiddev_connect(struct hid_device *hid) | |||
764 | } | 768 | } |
765 | 769 | ||
766 | init_waitqueue_head(&hiddev->wait); | 770 | init_waitqueue_head(&hiddev->wait); |
767 | 771 | INIT_LIST_HEAD(&hiddev->list); | |
768 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
769 | |||
770 | hiddev->hid = hid; | 772 | hiddev->hid = hid; |
771 | hiddev->exist = 1; | 773 | hiddev->exist = 1; |
772 | 774 | ||
773 | hid->minor = hid->intf->minor; | 775 | hid->minor = hid->intf->minor; |
774 | hid->hiddev = hiddev; | 776 | hid->hiddev = hiddev; |
775 | 777 | ||
778 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
779 | |||
776 | return 0; | 780 | return 0; |
777 | } | 781 | } |
778 | 782 | ||