|
From: johann d. <jd...@us...> - 2002-04-13 08:03:07
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv29652/drivers/usb
Added Files:
pid.c pid.h
Log Message:
Added code by Rodrigo Damazio.
--- NEW FILE: pid.c ---
/*
* PID Force feedback support for hid devices.
*
* Copyright (c) 2002 Rodrigo Damazio.
* Portions by Johann Deneux and Bjorn Augustson
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so by
* e-mail - mail your message to <rda...@ls...>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/input.h>
#include <linux/usb.h>
#include "hid.h"
#include "pid.h"
#define DEBUG
/*
MODULE_AUTHOR("Rodrigo Damazio <rda...@ls...>");
MODULE_DESCRIPTION("USB PID(Physical Interface Device) Driver");
MODULE_LICENSE("GPL");
*/
#define CHECK_OWNERSHIP(i, hid_pid) \
((i) < FF_EFFECTS_MAX && i >= 0 && \
test_bit(FF_PID_FLAGS_USED, &hid_pid->effects[(i)].flags) && \
(current->pid == 0 || \
(hid_pid)->effects[(i)].owner == current->pid))
/* Called when a transfer is completed */
static void hid_pid_ctrl_out(struct urb *u)
{
}
static void hid_pid_exit(struct hid_device* hid)
{
}
static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
return -ENOMEM;
}
static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
return -ENOMEM;
}
static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
return -ENOMEM;
}
static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
return -ENOMEM;
}
static int hid_pid_event(struct hid_device *hid, struct input_dev *input,
unsigned int type, unsigned int code, int value)
{
#ifdef DEBUG
printk ("PID event received: type=%d,code=%d,value=%d.\n",type,code,value);
#endif
if (type != EV_FF)
return -1;
return 0;
}
static int hid_pid_flush(struct input_dev *input, struct file *file)
{
return 0;
}
static int hid_pid_upload_effect(struct input_dev *dev,
struct ff_effect *effect)
{
struct hid_ff_pid* pid_private = (struct hid_ff_pid*)(dev->private);
int id;
int ret;
int is_update;
#ifdef DEBUG
printk("Upload effect called: effect_type=%x\n",effect->type);
#endif
/* Check this effect type is supported by this device */
if (!test_bit(effect->type, dev->ffbit))
return -EINVAL;
/*
* If we want to create a new effect, get a free id
*/
if (effect->id == -1) {
for (id=0; id < FF_EFFECTS_MAX; ++id)
if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id].flags)) break;
if ( id == FF_EFFECTS_MAX || id >= dev->ff_effects_max)
return -ENOMEM;
effect->id = id;
#ifdef DEBUG
printk("Effect ID is %d\n.",id);
#endif
pid_private->effects[id].owner = current->pid;
pid_private->effects[id].flags = (1<<FF_PID_FLAGS_USED);
is_update = FF_PID_FALSE;
}
else {
/* We want to update an effect */
if (!CHECK_OWNERSHIP(effect->id, pid_private)) return -EACCES;
/* Parameter type cannot be updated */
if (effect->type != pid_private->effects[effect->id].effect.type)
return -EINVAL;
/* Check the effect is not already being updated */
if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags)) {
return -EAGAIN;
}
is_update = FF_PID_TRUE;
}
/*
* Upload the effect
*/
switch (effect->type) {
case FF_PERIODIC:
ret = pid_upload_periodic(pid_private, effect, is_update);
break;
case FF_CONSTANT:
ret = pid_upload_constant(pid_private, effect, is_update);
break;
case FF_SPRING:
case FF_FRICTION:
case FF_DAMPER:
case FF_INERTIA:
ret = pid_upload_condition(pid_private, effect, is_update);
break;
case FF_RAMP:
ret = pid_upload_ramp(pid_private, effect, is_update);
break;
default:
return -EINVAL;
}
if (ret == 0) {
/* A packet was sent, forbid new updates until we are notified
* that the packet was updated
*/
set_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags);
}
pid_private->effects[effect->id].effect = *effect;
return ret;
}
int hid_pid_init(struct hid_device *hid)
{
struct hid_ff_pid *private;
private = hid->input.private = hid->ff_private = kmalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
if (!private) return -1;
memset(private,0,sizeof(struct hid_ff_pid));
private->hid = hid;
hid->ff_exit = hid_pid_exit;
hid->ff_event = hid_pid_event;
/* Open output URB */
if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) {
kfree(private);
return -1;
}
usb_fill_control_urb(private->urbffout, hid->dev,0,(void *) &private->ffcr,private->ctrl_buffer,8,hid_pid_ctrl_out,hid);
hid->input.upload_effect = hid_pid_upload_effect;
hid->input.flush = hid_pid_flush;
set_bit(EV_FF, hid->input.evbit);
set_bit(EV_FF_STATUS, hid->input.evbit);
/* Retrieve specific device capabilities(types of effects it can play, etc.) */
// set_bit(FF_CONSTANT, hid->input.ffbit);
printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rda...@ls...>.\n");
return 0;
}
static int __init hid_pid_modinit(void)
{
return 0;
}
static void __exit hid_pid_modexit(void)
{
}
//module_init(hid_pid_modinit);
//module_exit(hid_pid_modexit);
--- NEW FILE: pid.h ---
/*
* PID Force feedback support for hid devices.
*
* Copyright (c) 2002 Rodrigo Damazio.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so by
* e-mail - mail your message to <rda...@ls...>
*/
#define FF_EFFECTS_MAX 64
#define FF_PID_FLAGS_USED 1
#define FF_PID_FLAGS_UPDATING 2
#define FF_PID_FALSE 0
#define FF_PID_TRUE 1
struct hid_pid_effect {
unsigned int flags;
pid_t owner;
struct ff_effect effect;
};
struct hid_ff_pid {
struct hid_device *hid;
struct urb *urbffout;
struct usb_ctrlrequest ffcr;
char ctrl_buffer[8];
unsigned long int gain;
unsigned int max_effects;
struct hid_pid_effect effects[FF_EFFECTS_MAX];
};
|