Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932261AbWE3LCR (ORCPT ); Tue, 30 May 2006 07:02:17 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932255AbWE3LCA (ORCPT ); Tue, 30 May 2006 07:02:00 -0400 Received: from pne-smtpout4-sn1.fre.skanova.net ([81.228.11.168]:5552 "EHLO pne-smtpout4-sn1.fre.skanova.net") by vger.kernel.org with ESMTP id S932235AbWE3LBs (ORCPT ); Tue, 30 May 2006 07:01:48 -0400 Message-Id: <20060530110132.977816000@gmail.com> References: <20060530105705.157014000@gmail.com> User-Agent: quilt/0.44-1 Date: Tue, 30 May 2006 13:57:10 +0300 From: Anssi Hannula To: Dmitry Torokhov Cc: linux-joystick@atrey.karlin.mff.cuni.cz, linux-kernel@vger.kernel.org Subject: [patch 05/12] input: adapt uinput for the new force feedback interface Content-Disposition: inline; filename=ff-refactoring-uinput-to-new-interface.diff Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9095 Lines: 274 Modify the uinput driver for the new force feedback interface. The userspace interface of the force feedback part is changed and documentation in uinput.h is updated accordingly. MODULE_VERSION is also added to reflect the revision. Signed-off-by: Anssi Hannula --- drivers/input/misc/uinput.c | 79 ++++++++++++++++++++++++++++++++++++-------- include/linux/uinput.h | 21 ++++++++--- 2 files changed, 80 insertions(+), 20 deletions(-) Index: linux-2.6.17-rc4-git12/drivers/input/misc/uinput.c =================================================================== --- linux-2.6.17-rc4-git12.orig/drivers/input/misc/uinput.c 2006-05-30 13:38:57.000000000 +0300 +++ linux-2.6.17-rc4-git12/drivers/input/misc/uinput.c 2006-05-30 13:42:16.000000000 +0300 @@ -20,6 +20,9 @@ * Author: Aristeu Sergio Rozanski Filho * * Changes/Revisions: + * 0.3 09/04/2006 (Anssi Hannula ) + * - updated ff support for the changes in kernel interface + * - added MODULE_VERSION * 0.2 16/10/2004 (Micah Dowty ) * - added force feedback support * - added UI_SET_PHYS @@ -40,6 +43,9 @@ static int uinput_dev_event(struct input { struct uinput_device *udev; + if (type == EV_FF) + return input_ff_event(dev, type, code, value); + udev = dev->private; udev->buff[udev->head].type = type; @@ -107,18 +113,31 @@ static int uinput_request_submit(struct return request->retval; } -static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect) +static void uinput_dev_set_gain(struct input_dev *dev, u16 gain) +{ + uinput_dev_event(dev, EV_FF, FF_GAIN, gain); +} + +static void uinput_dev_set_autocenter(struct input_dev *dev, u16 magnitude) +{ + uinput_dev_event(dev, EV_FF, FF_AUTOCENTER, magnitude); +} + +static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value) +{ + return uinput_dev_event(dev, EV_FF, effect_id, value); +} + +static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) { struct uinput_request request; int retval; - if (!test_bit(EV_FF, dev->evbit)) - return -ENOSYS; - request.id = -1; init_completion(&request.done); request.code = UI_FF_UPLOAD; - request.u.effect = effect; + request.u.upload.effect = effect; + request.u.upload.old = old; retval = uinput_request_reserve_slot(dev->private, &request); if (!retval) @@ -166,6 +185,14 @@ static void uinput_destroy_device(struct udev->state = UIST_NEW_DEVICE; } +static struct ff_driver uinput_ff_driver = { + .upload = uinput_dev_upload_effect, + .erase = uinput_dev_erase_effect, + .playback = uinput_dev_playback, + .set_gain = uinput_dev_set_gain, + .set_autocenter = uinput_dev_set_autocenter +}; + static int uinput_create_device(struct uinput_device *udev) { int error; @@ -181,6 +208,14 @@ static int uinput_create_device(struct u return error; } + if (udev->dev->ff) { + error = input_ff_register(udev->dev, &uinput_ff_driver); + if (error) { + uinput_destroy_device(udev); + return error; + } + } + udev->state = UIST_CREATED; return 0; @@ -243,8 +278,6 @@ static int uinput_allocate_device(struct return -ENOMEM; udev->dev->event = uinput_dev_event; - udev->dev->upload_effect = uinput_dev_upload_effect; - udev->dev->erase_effect = uinput_dev_erase_effect; udev->dev->private = udev; return 0; @@ -296,7 +329,12 @@ static int uinput_setup_device(struct ui dev->id.vendor = user_dev->id.vendor; dev->id.product = user_dev->id.product; dev->id.version = user_dev->id.version; - dev->ff_effects_max = user_dev->ff_effects_max; + if (user_dev->ff_effects_max) { + retval = input_ff_allocate(dev); + if (retval) + goto exit; + dev->ff_effects_max = user_dev->ff_effects_max; + } size = sizeof(int) * (ABS_MAX + 1); memcpy(dev->absmax, user_dev->absmax, size); @@ -459,7 +497,12 @@ static long uinput_ioctl(struct file *fi break; case UI_SET_EVBIT: - retval = uinput_set_bit(arg, evbit, EV_MAX); + if (arg == EV_FF) + /* EV_FF shall not be touched by the driver + it is set by force feedback subsystem */ + retval = -EINVAL; + else + retval = uinput_set_bit(arg, evbit, EV_MAX); break; case UI_SET_KEYBIT: @@ -487,7 +530,10 @@ static long uinput_ioctl(struct file *fi break; case UI_SET_FFBIT: - retval = uinput_set_bit(arg, ffbit, FF_MAX); + if (!udev->dev->ff) + retval = -EINVAL; + else + retval = uinput_set_bit(arg, ff->flags, FF_MAX); break; case UI_SET_SWBIT: @@ -525,12 +571,17 @@ static long uinput_ioctl(struct file *fi break; } req = uinput_request_find(udev, ff_up.request_id); - if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) { + if (!(req && req->code == UI_FF_UPLOAD && req->u.upload.effect)) { retval = -EINVAL; break; } ff_up.retval = 0; - memcpy(&ff_up.effect, req->u.effect, sizeof(struct ff_effect)); + memcpy(&ff_up.effect, req->u.upload.effect, sizeof(struct ff_effect)); + if (req->u.upload.old) + memcpy(&ff_up.old, req->u.upload.old, sizeof(struct ff_effect)); + else + memset(&ff_up.old, 0, sizeof(struct ff_effect)); + if (copy_to_user(p, &ff_up, sizeof(ff_up))) { retval = -EFAULT; break; @@ -561,12 +612,11 @@ static long uinput_ioctl(struct file *fi break; } req = uinput_request_find(udev, ff_up.request_id); - if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) { + if (!(req && req->code == UI_FF_UPLOAD && req->u.upload.effect)) { retval = -EINVAL; break; } req->retval = ff_up.retval; - memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect)); uinput_request_done(udev, req); break; @@ -622,6 +672,7 @@ static void __exit uinput_exit(void) MODULE_AUTHOR("Aristeu Sergio Rozanski Filho"); MODULE_DESCRIPTION("User level driver support for input subsystem"); MODULE_LICENSE("GPL"); +MODULE_VERSION("0.3"); module_init(uinput_init); module_exit(uinput_exit); Index: linux-2.6.17-rc4-git12/include/linux/uinput.h =================================================================== --- linux-2.6.17-rc4-git12.orig/include/linux/uinput.h 2006-05-30 13:38:57.000000000 +0300 +++ linux-2.6.17-rc4-git12/include/linux/uinput.h 2006-05-30 13:40:55.000000000 +0300 @@ -22,12 +22,18 @@ * Author: Aristeu Sergio Rozanski Filho * * Changes/Revisions: + * 0.3 24/05/2006 (Anssi Hannula ) + * - update ff support for the changes in kernel interface + * - add UINPUT_VERSION * 0.2 16/10/2004 (Micah Dowty ) * - added force feedback support * - added UI_SET_PHYS * 0.1 20/06/2002 * - first public version */ + +#define UINPUT_VERSION 3 + #ifdef __KERNEL__ #define UINPUT_MINOR 223 #define UINPUT_NAME "uinput" @@ -45,7 +51,10 @@ struct uinput_request { union { int effect_id; - struct ff_effect* effect; + struct { + struct ff_effect* effect; + struct ff_effect* old; + } upload; } u; }; @@ -69,6 +78,7 @@ struct uinput_ff_upload { int request_id; int retval; struct ff_effect effect; + struct ff_effect old; }; struct uinput_ff_erase { @@ -105,7 +115,7 @@ struct uinput_ff_erase { * ioctls to retrieve additional parameters and send the return code. * The callback blocks until this return code is sent. * - * The described callback mechanism is only used if EV_FF is set. + * The described callback mechanism is only used if ff_effects_max is set. * Otherwise, default implementations of upload_effect and erase_effect * are used. * @@ -116,9 +126,9 @@ struct uinput_ff_erase { * the 'value' from the EV_UINPUT event. * 3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the * uinput_ff_upload struct. It will be filled in with the - * ff_effect passed to upload_effect(). - * 4. Perform the effect upload, and place the modified ff_effect - * and a return code back into the uinput_ff_upload struct. + * ff_effects passed to upload_effect(). + * 4. Perform the effect upload, and place a return code back into + the uinput_ff_upload struct. * 5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the * uinput_ff_upload_effect struct. This will complete execution * of our upload_effect() handler. @@ -133,7 +143,6 @@ struct uinput_ff_erase { * effect ID passed to erase_effect(). * 4. Perform the effect erasure, and place a return code back * into the uinput_ff_erase struct. - * and a return code back into the uinput_ff_erase struct. * 5. Issue a UI_END_FF_ERASE ioctl, also giving it the * uinput_ff_erase_effect struct. This will complete execution * of our erase_effect() handler. -- Anssi Hannula - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/