Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.18 295 lines 8.4 kB view raw
1/* 2 * PID Force feedback support for hid devices. 3 * 4 * Copyright (c) 2002 Rodrigo Damazio. 5 * Portions by Johann Deneux and Bjorn Augustson 6 */ 7 8/* 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 * Should you need to contact me, the author, you can do so by 24 * e-mail - mail your message to <rdamazio@lsi.usp.br> 25 */ 26 27#include <linux/config.h> 28#include <linux/module.h> 29#include <linux/slab.h> 30#include <linux/kernel.h> 31#include <linux/init.h> 32#include <linux/mm.h> 33#include <linux/smp_lock.h> 34#include <linux/spinlock.h> 35#include <linux/input.h> 36#include <linux/usb.h> 37#include "hid.h" 38#include "pid.h" 39 40#define CHECK_OWNERSHIP(i, hid_pid) \ 41 ((i) < FF_EFFECTS_MAX && i >= 0 && \ 42 test_bit(FF_PID_FLAGS_USED, &hid_pid->effects[(i)].flags) && \ 43 (current->pid == 0 || \ 44 (hid_pid)->effects[(i)].owner == current->pid)) 45 46/* Called when a transfer is completed */ 47static void hid_pid_ctrl_out(struct urb *u, struct pt_regs *regs) 48{ 49 dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n"); 50} 51 52static void hid_pid_exit(struct hid_device *hid) 53{ 54 struct hid_ff_pid *private = hid->ff_private; 55 56 if (private->urbffout) { 57 usb_kill_urb(private->urbffout); 58 usb_free_urb(private->urbffout); 59 } 60} 61 62static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) 63{ 64 dev_info(&pid->hid->dev->dev, "requested periodic force upload\n"); 65 return 0; 66} 67 68static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) 69{ 70 dev_info(&pid->hid->dev->dev, "requested constant force upload\n"); 71 return 0; 72} 73 74static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) 75{ 76 dev_info(&pid->hid->dev->dev, "requested Condition force upload\n"); 77 return 0; 78} 79 80static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) 81{ 82 dev_info(&pid->hid->dev->dev, "request ramp force upload\n"); 83 return 0; 84} 85 86static int hid_pid_event(struct hid_device *hid, struct input_dev *input, 87 unsigned int type, unsigned int code, int value) 88{ 89 dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value); 90 91 if (type != EV_FF) 92 return -1; 93 94 return 0; 95} 96 97/* Lock must be held by caller */ 98static void hid_pid_ctrl_playback(struct hid_device *hid, struct hid_pid_effect *effect, int play) 99{ 100 if (play) 101 set_bit(FF_PID_FLAGS_PLAYING, &effect->flags); 102 else 103 clear_bit(FF_PID_FLAGS_PLAYING, &effect->flags); 104} 105 106static int hid_pid_erase(struct input_dev *dev, int id) 107{ 108 struct hid_device *hid = dev->private; 109 struct hid_ff_pid *pid = hid->ff_private; 110 struct hid_field *field; 111 unsigned long flags; 112 int ret; 113 114 if (!CHECK_OWNERSHIP(id, pid)) 115 return -EACCES; 116 117 /* Find report */ 118 field = hid_find_field_by_usage(hid, HID_UP_PID | FF_PID_USAGE_BLOCK_FREE, 119 HID_OUTPUT_REPORT); 120 if (!field) { 121 dev_err(&hid->dev->dev, "couldn't find report\n"); 122 return -EIO; 123 } 124 125 ret = hid_set_field(field, 0, pid->effects[id].device_id); 126 if (ret) { 127 dev_err(&hid->dev->dev, "couldn't set field\n"); 128 return ret; 129 } 130 131 hid_submit_report(hid, field->report, USB_DIR_OUT); 132 133 spin_lock_irqsave(&pid->lock, flags); 134 hid_pid_ctrl_playback(hid, pid->effects + id, 0); 135 pid->effects[id].flags = 0; 136 spin_unlock_irqrestore(&pid->lock, flags); 137 138 return 0; 139} 140 141/* Erase all effects this process owns */ 142static int hid_pid_flush(struct input_dev *dev, struct file *file) 143{ 144 struct hid_device *hid = dev->private; 145 struct hid_ff_pid *pid = hid->ff_private; 146 int i; 147 148 /*NOTE: no need to lock here. The only times EFFECT_USED is 149 modified is when effects are uploaded or when an effect is 150 erased. But a process cannot close its dev/input/eventX fd 151 and perform ioctls on the same fd all at the same time */ 152 /*FIXME: multiple threads, anyone? */ 153 for (i = 0; i < dev->ff_effects_max; ++i) 154 if (current->pid == pid->effects[i].owner 155 && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags)) 156 if (hid_pid_erase(dev, i)) 157 dev_warn(&hid->dev->dev, "erase effect %d failed", i); 158 159 return 0; 160} 161 162static int hid_pid_upload_effect(struct input_dev *dev, 163 struct ff_effect *effect) 164{ 165 struct hid_ff_pid *pid_private = (struct hid_ff_pid *)(dev->private); 166 int ret; 167 int is_update; 168 unsigned long flags; 169 170 dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n", effect->type); 171 /* Check this effect type is supported by this device */ 172 if (!test_bit(effect->type, dev->ffbit)) { 173 dev_dbg(&pid_private->hid->dev->dev, 174 "invalid kind of effect requested.\n"); 175 return -EINVAL; 176 } 177 178 /* 179 * If we want to create a new effect, get a free id 180 */ 181 if (effect->id == -1) { 182 int id = 0; 183 184 // Spinlock so we don`t get a race condition when choosing IDs 185 spin_lock_irqsave(&pid_private->lock, flags); 186 187 while (id < FF_EFFECTS_MAX) 188 if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags)) 189 break; 190 191 if (id == FF_EFFECTS_MAX) { 192 spin_unlock_irqrestore(&pid_private->lock, flags); 193// TEMP - We need to get ff_effects_max correctly first: || id >= dev->ff_effects_max) { 194 dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n"); 195 return -ENOMEM; 196 } 197 198 effect->id = id; 199 dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d.\n", id); 200 pid_private->effects[id].owner = current->pid; 201 pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED); 202 spin_unlock_irqrestore(&pid_private->lock, flags); 203 204 is_update = FF_PID_FALSE; 205 } else { 206 /* We want to update an effect */ 207 if (!CHECK_OWNERSHIP(effect->id, pid_private)) 208 return -EACCES; 209 210 /* Parameter type cannot be updated */ 211 if (effect->type != pid_private->effects[effect->id].effect.type) 212 return -EINVAL; 213 214 /* Check the effect is not already being updated */ 215 if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags)) 216 return -EAGAIN; 217 218 is_update = FF_PID_TRUE; 219 } 220 221 /* 222 * Upload the effect 223 */ 224 switch (effect->type) { 225 case FF_PERIODIC: 226 ret = pid_upload_periodic(pid_private, effect, is_update); 227 break; 228 229 case FF_CONSTANT: 230 ret = pid_upload_constant(pid_private, effect, is_update); 231 break; 232 233 case FF_SPRING: 234 case FF_FRICTION: 235 case FF_DAMPER: 236 case FF_INERTIA: 237 ret = pid_upload_condition(pid_private, effect, is_update); 238 break; 239 240 case FF_RAMP: 241 ret = pid_upload_ramp(pid_private, effect, is_update); 242 break; 243 244 default: 245 dev_dbg(&pid_private->hid->dev->dev, 246 "invalid type of effect requested - %x.\n", 247 effect->type); 248 return -EINVAL; 249 } 250 /* If a packet was sent, forbid new updates until we are notified 251 * that the packet was updated 252 */ 253 if (ret == 0) 254 set_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags); 255 pid_private->effects[effect->id].effect = *effect; 256 return ret; 257} 258 259int hid_pid_init(struct hid_device *hid) 260{ 261 struct hid_ff_pid *private; 262 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 263 struct input_dev *input_dev = hidinput->input; 264 265 private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); 266 if (!private) 267 return -ENOMEM; 268 269 private->hid = hid; 270 271 hid->ff_exit = hid_pid_exit; 272 hid->ff_event = hid_pid_event; 273 274 /* Open output URB */ 275 if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) { 276 kfree(private); 277 return -1; 278 } 279 280 usb_fill_control_urb(private->urbffout, hid->dev, 0, 281 (void *)&private->ffcr, private->ctrl_buffer, 8, 282 hid_pid_ctrl_out, hid); 283 284 input_dev->upload_effect = hid_pid_upload_effect; 285 input_dev->flush = hid_pid_flush; 286 input_dev->ff_effects_max = 8; // A random default 287 set_bit(EV_FF, input_dev->evbit); 288 set_bit(EV_FF_STATUS, input_dev->evbit); 289 290 spin_lock_init(&private->lock); 291 292 printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n"); 293 294 return 0; 295}