mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 05:04:09 +08:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: "Some more updates for the input subsystem. You will get a fix for race in mousedev that has been causing quite a few oopses lately and a small fixup for force feedback support in evdev" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: mousedev - fix race when creating mixed device Input: don't modify the id of ioctl-provided ff effect on upload failure
This commit is contained in:
commit
915ac4e26e
@ -954,11 +954,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
error = input_ff_upload(dev, &effect, file);
|
error = input_ff_upload(dev, &effect, file);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
|
if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Multi-number variable-length handlers */
|
/* Multi-number variable-length handlers */
|
||||||
|
@ -67,7 +67,6 @@ struct mousedev {
|
|||||||
struct device dev;
|
struct device dev;
|
||||||
struct cdev cdev;
|
struct cdev cdev;
|
||||||
bool exist;
|
bool exist;
|
||||||
bool is_mixdev;
|
|
||||||
|
|
||||||
struct list_head mixdev_node;
|
struct list_head mixdev_node;
|
||||||
bool opened_by_mixdev;
|
bool opened_by_mixdev;
|
||||||
@ -77,6 +76,9 @@ struct mousedev {
|
|||||||
int old_x[4], old_y[4];
|
int old_x[4], old_y[4];
|
||||||
int frac_dx, frac_dy;
|
int frac_dx, frac_dy;
|
||||||
unsigned long touch;
|
unsigned long touch;
|
||||||
|
|
||||||
|
int (*open_device)(struct mousedev *mousedev);
|
||||||
|
void (*close_device)(struct mousedev *mousedev);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mousedev_emul {
|
enum mousedev_emul {
|
||||||
@ -116,9 +118,6 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
|
|||||||
static struct mousedev *mousedev_mix;
|
static struct mousedev *mousedev_mix;
|
||||||
static LIST_HEAD(mousedev_mix_list);
|
static LIST_HEAD(mousedev_mix_list);
|
||||||
|
|
||||||
static void mixdev_open_devices(void);
|
|
||||||
static void mixdev_close_devices(void);
|
|
||||||
|
|
||||||
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
|
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
|
||||||
#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
|
#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
|
||||||
|
|
||||||
@ -428,9 +427,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
|
|||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (mousedev->is_mixdev)
|
if (!mousedev->exist)
|
||||||
mixdev_open_devices();
|
|
||||||
else if (!mousedev->exist)
|
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
else if (!mousedev->open++) {
|
else if (!mousedev->open++) {
|
||||||
retval = input_open_device(&mousedev->handle);
|
retval = input_open_device(&mousedev->handle);
|
||||||
@ -446,9 +443,7 @@ static void mousedev_close_device(struct mousedev *mousedev)
|
|||||||
{
|
{
|
||||||
mutex_lock(&mousedev->mutex);
|
mutex_lock(&mousedev->mutex);
|
||||||
|
|
||||||
if (mousedev->is_mixdev)
|
if (mousedev->exist && !--mousedev->open)
|
||||||
mixdev_close_devices();
|
|
||||||
else if (mousedev->exist && !--mousedev->open)
|
|
||||||
input_close_device(&mousedev->handle);
|
input_close_device(&mousedev->handle);
|
||||||
|
|
||||||
mutex_unlock(&mousedev->mutex);
|
mutex_unlock(&mousedev->mutex);
|
||||||
@ -459,21 +454,29 @@ static void mousedev_close_device(struct mousedev *mousedev)
|
|||||||
* stream. Note that this function is called with mousedev_mix->mutex
|
* stream. Note that this function is called with mousedev_mix->mutex
|
||||||
* held.
|
* held.
|
||||||
*/
|
*/
|
||||||
static void mixdev_open_devices(void)
|
static int mixdev_open_devices(struct mousedev *mixdev)
|
||||||
{
|
{
|
||||||
struct mousedev *mousedev;
|
int error;
|
||||||
|
|
||||||
if (mousedev_mix->open++)
|
error = mutex_lock_interruptible(&mixdev->mutex);
|
||||||
return;
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
|
if (!mixdev->open++) {
|
||||||
if (!mousedev->opened_by_mixdev) {
|
struct mousedev *mousedev;
|
||||||
if (mousedev_open_device(mousedev))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mousedev->opened_by_mixdev = true;
|
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
|
||||||
|
if (!mousedev->opened_by_mixdev) {
|
||||||
|
if (mousedev_open_device(mousedev))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mousedev->opened_by_mixdev = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&mixdev->mutex);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -481,19 +484,22 @@ static void mixdev_open_devices(void)
|
|||||||
* device. Note that this function is called with mousedev_mix->mutex
|
* device. Note that this function is called with mousedev_mix->mutex
|
||||||
* held.
|
* held.
|
||||||
*/
|
*/
|
||||||
static void mixdev_close_devices(void)
|
static void mixdev_close_devices(struct mousedev *mixdev)
|
||||||
{
|
{
|
||||||
struct mousedev *mousedev;
|
mutex_lock(&mixdev->mutex);
|
||||||
|
|
||||||
if (--mousedev_mix->open)
|
if (!--mixdev->open) {
|
||||||
return;
|
struct mousedev *mousedev;
|
||||||
|
|
||||||
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
|
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
|
||||||
if (mousedev->opened_by_mixdev) {
|
if (mousedev->opened_by_mixdev) {
|
||||||
mousedev->opened_by_mixdev = false;
|
mousedev->opened_by_mixdev = false;
|
||||||
mousedev_close_device(mousedev);
|
mousedev_close_device(mousedev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&mixdev->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -522,7 +528,7 @@ static int mousedev_release(struct inode *inode, struct file *file)
|
|||||||
mousedev_detach_client(mousedev, client);
|
mousedev_detach_client(mousedev, client);
|
||||||
kfree(client);
|
kfree(client);
|
||||||
|
|
||||||
mousedev_close_device(mousedev);
|
mousedev->close_device(mousedev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -550,7 +556,7 @@ static int mousedev_open(struct inode *inode, struct file *file)
|
|||||||
client->mousedev = mousedev;
|
client->mousedev = mousedev;
|
||||||
mousedev_attach_client(mousedev, client);
|
mousedev_attach_client(mousedev, client);
|
||||||
|
|
||||||
error = mousedev_open_device(mousedev);
|
error = mousedev->open_device(mousedev);
|
||||||
if (error)
|
if (error)
|
||||||
goto err_free_client;
|
goto err_free_client;
|
||||||
|
|
||||||
@ -861,16 +867,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
|
|||||||
|
|
||||||
if (mixdev) {
|
if (mixdev) {
|
||||||
dev_set_name(&mousedev->dev, "mice");
|
dev_set_name(&mousedev->dev, "mice");
|
||||||
|
|
||||||
|
mousedev->open_device = mixdev_open_devices;
|
||||||
|
mousedev->close_device = mixdev_close_devices;
|
||||||
} else {
|
} else {
|
||||||
int dev_no = minor;
|
int dev_no = minor;
|
||||||
/* Normalize device number if it falls into legacy range */
|
/* Normalize device number if it falls into legacy range */
|
||||||
if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
|
if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
|
||||||
dev_no -= MOUSEDEV_MINOR_BASE;
|
dev_no -= MOUSEDEV_MINOR_BASE;
|
||||||
dev_set_name(&mousedev->dev, "mouse%d", dev_no);
|
dev_set_name(&mousedev->dev, "mouse%d", dev_no);
|
||||||
|
|
||||||
|
mousedev->open_device = mousedev_open_device;
|
||||||
|
mousedev->close_device = mousedev_close_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
mousedev->exist = true;
|
mousedev->exist = true;
|
||||||
mousedev->is_mixdev = mixdev;
|
|
||||||
mousedev->handle.dev = input_get_device(dev);
|
mousedev->handle.dev = input_get_device(dev);
|
||||||
mousedev->handle.name = dev_name(&mousedev->dev);
|
mousedev->handle.name = dev_name(&mousedev->dev);
|
||||||
mousedev->handle.handler = handler;
|
mousedev->handle.handler = handler;
|
||||||
@ -919,7 +930,7 @@ static void mousedev_destroy(struct mousedev *mousedev)
|
|||||||
device_del(&mousedev->dev);
|
device_del(&mousedev->dev);
|
||||||
mousedev_cleanup(mousedev);
|
mousedev_cleanup(mousedev);
|
||||||
input_free_minor(MINOR(mousedev->dev.devt));
|
input_free_minor(MINOR(mousedev->dev.devt));
|
||||||
if (!mousedev->is_mixdev)
|
if (mousedev != mousedev_mix)
|
||||||
input_unregister_handle(&mousedev->handle);
|
input_unregister_handle(&mousedev->handle);
|
||||||
put_device(&mousedev->dev);
|
put_device(&mousedev->dev);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user