@@ -42,6 +42,7 @@ static struct cdev hidraw_cdev;
42
42
static struct class * hidraw_class ;
43
43
static struct hidraw * hidraw_table [HIDRAW_MAX_DEVICES ];
44
44
static DEFINE_MUTEX (minors_lock );
45
+ static void drop_ref (struct hidraw * hid , int exists_bit );
45
46
46
47
static ssize_t hidraw_read (struct file * file , char __user * buffer , size_t count , loff_t * ppos )
47
48
{
@@ -113,7 +114,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
113
114
__u8 * buf ;
114
115
int ret = 0 ;
115
116
116
- if (!hidraw_table [minor ]) {
117
+ if (!hidraw_table [minor ] || ! hidraw_table [ minor ] -> exist ) {
117
118
ret = - ENODEV ;
118
119
goto out ;
119
120
}
@@ -261,7 +262,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
261
262
}
262
263
263
264
mutex_lock (& minors_lock );
264
- if (!hidraw_table [minor ]) {
265
+ if (!hidraw_table [minor ] || ! hidraw_table [ minor ] -> exist ) {
265
266
err = - ENODEV ;
266
267
goto out_unlock ;
267
268
}
@@ -298,36 +299,12 @@ static int hidraw_open(struct inode *inode, struct file *file)
298
299
static int hidraw_release (struct inode * inode , struct file * file )
299
300
{
300
301
unsigned int minor = iminor (inode );
301
- struct hidraw * dev ;
302
302
struct hidraw_list * list = file -> private_data ;
303
- int ret ;
304
- int i ;
305
-
306
- mutex_lock (& minors_lock );
307
- if (!hidraw_table [minor ]) {
308
- ret = - ENODEV ;
309
- goto unlock ;
310
- }
311
303
304
+ drop_ref (hidraw_table [minor ], 0 );
312
305
list_del (& list -> node );
313
- dev = hidraw_table [minor ];
314
- if (!-- dev -> open ) {
315
- if (list -> hidraw -> exist ) {
316
- hid_hw_power (dev -> hid , PM_HINT_NORMAL );
317
- hid_hw_close (dev -> hid );
318
- } else {
319
- kfree (list -> hidraw );
320
- }
321
- }
322
-
323
- for (i = 0 ; i < HIDRAW_BUFFER_SIZE ; ++ i )
324
- kfree (list -> buffer [i ].value );
325
306
kfree (list );
326
- ret = 0 ;
327
- unlock :
328
- mutex_unlock (& minors_lock );
329
-
330
- return ret ;
307
+ return 0 ;
331
308
}
332
309
333
310
static long hidraw_ioctl (struct file * file , unsigned int cmd ,
@@ -529,21 +506,7 @@ EXPORT_SYMBOL_GPL(hidraw_connect);
529
506
void hidraw_disconnect (struct hid_device * hid )
530
507
{
531
508
struct hidraw * hidraw = hid -> hidraw ;
532
-
533
- mutex_lock (& minors_lock );
534
- hidraw -> exist = 0 ;
535
-
536
- device_destroy (hidraw_class , MKDEV (hidraw_major , hidraw -> minor ));
537
-
538
- hidraw_table [hidraw -> minor ] = NULL ;
539
-
540
- if (hidraw -> open ) {
541
- hid_hw_close (hid );
542
- wake_up_interruptible (& hidraw -> wait );
543
- } else {
544
- kfree (hidraw );
545
- }
546
- mutex_unlock (& minors_lock );
509
+ drop_ref (hidraw , 1 );
547
510
}
548
511
EXPORT_SYMBOL_GPL (hidraw_disconnect );
549
512
@@ -585,3 +548,23 @@ void hidraw_exit(void)
585
548
unregister_chrdev_region (dev_id , HIDRAW_MAX_DEVICES );
586
549
587
550
}
551
+
552
+ static void drop_ref (struct hidraw * hidraw , int exists_bit )
553
+ {
554
+ mutex_lock (& minors_lock );
555
+ if (exists_bit ) {
556
+ hid_hw_close (hidraw -> hid );
557
+ hidraw -> exist = 0 ;
558
+ if (hidraw -> open )
559
+ wake_up_interruptible (& hidraw -> wait );
560
+ } else {
561
+ -- hidraw -> open ;
562
+ }
563
+
564
+ if (!hidraw -> open && !hidraw -> exist ) {
565
+ device_destroy (hidraw_class , MKDEV (hidraw_major , hidraw -> minor ));
566
+ hidraw_table [hidraw -> minor ] = NULL ;
567
+ kfree (hidraw );
568
+ }
569
+ mutex_unlock (& minors_lock );
570
+ }
0 commit comments