vserver 2.0 rc7
[linux-2.6.git] / drivers / usb / input / pid.c
index d1ea1f0..2569638 100644 (file)
 /* Called when a transfer is completed */
 static void hid_pid_ctrl_out(struct urb *u, struct pt_regs *regs)
 {
-    dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n");
+       dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n");
 }
 
-static void hid_pid_exit(struct hid_devicehid)
+static void hid_pid_exit(struct hid_device *hid)
 {
-    struct hid_ff_pid *private = hid->ff_private;
-    
-    if (private->urbffout) {
-       usb_kill_urb(private->urbffout);
-       usb_free_urb(private->urbffout);
-    }
+       struct hid_ff_pid *private = hid->ff_private;
+
+       if (private->urbffout) {
+               usb_kill_urb(private->urbffout);
+               usb_free_urb(private->urbffout);
+       }
 }
 
-static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "requested periodic force upload\n");
-    return 0;
+static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+       dev_info(&pid->hid->dev->dev, "requested periodic force upload\n");
+       return 0;
 }
 
-static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "requested constant force upload\n");
-    return 0;
+static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+       dev_info(&pid->hid->dev->dev, "requested constant force upload\n");
+       return 0;
 }
 
-static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "requested Condition force upload\n");
-    return 0;
+static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+       dev_info(&pid->hid->dev->dev, "requested Condition force upload\n");
+       return 0;
 }
 
-static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "request ramp force upload\n");
-    return 0;
+static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+       dev_info(&pid->hid->dev->dev, "request ramp force upload\n");
+       return 0;
 }
 
 static int hid_pid_event(struct hid_device *hid, struct input_dev *input,
-                         unsigned int type, unsigned int code, int value)
+                        unsigned int type, unsigned int code, int value)
 {
-    dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value);
+       dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value);
 
-    if (type != EV_FF)
-       return -1;
+       if (type != EV_FF)
+               return -1;
 
-    
-
-    return 0;
+       return 0;
 }
 
 /* Lock must be held by caller */
-static void hid_pid_ctrl_playback(struct hid_device *hid,
-                                  struct hid_pid_effect *effect, int play)
+static void hid_pid_ctrl_playback(struct hid_device *hid, struct hid_pid_effect *effect, int play)
 {
-       if (play) {
+       if (play)
                set_bit(FF_PID_FLAGS_PLAYING, &effect->flags);
-
-       } else {
+       else
                clear_bit(FF_PID_FLAGS_PLAYING, &effect->flags);
-       }
 }
 
-
 static int hid_pid_erase(struct input_dev *dev, int id)
 {
        struct hid_device *hid = dev->private;
-       struct hid_field* field;
-       struct hid_report* report;
        struct hid_ff_pid *pid = hid->ff_private;
+       struct hid_field *field;
        unsigned long flags;
-       unsigned wanted_report = HID_UP_PID | FF_PID_USAGE_BLOCK_FREE;  /*  PID Block Free Report */
        int ret;
 
        if (!CHECK_OWNERSHIP(id, pid))
                return -EACCES;
 
        /* Find report */
-       ret =  hid_find_report_by_usage(hid, wanted_report, &report, HID_OUTPUT_REPORT);
-       if(!ret) {
+       field = hid_find_field_by_usage(hid, HID_UP_PID | FF_PID_USAGE_BLOCK_FREE,
+                                       HID_OUTPUT_REPORT);
+       if (!field) {
                dev_err(&hid->dev->dev, "couldn't find report\n");
-               return ret;
-       }
-
-       /* Find field */
-       field = (struct hid_field *) kmalloc(sizeof(struct hid_field), GFP_KERNEL);
-       if(!field) {
-               dev_err(&hid->dev->dev, "couldn't allocate field\n");
-               return -ENOMEM;
+               return -EIO;
        }
 
-       ret = hid_set_field(field, ret, pid->effects[id].device_id);
-       if(!ret) {
+       ret = hid_set_field(field, 0, pid->effects[id].device_id);
+       if (ret) {
                dev_err(&hid->dev->dev, "couldn't set field\n");
                return ret;
        }
 
-       hid_submit_report(hid, report, USB_DIR_OUT);
+       hid_submit_report(hid, field->report, USB_DIR_OUT);
 
        spin_lock_irqsave(&pid->lock, flags);
        hid_pid_ctrl_playback(hid, pid->effects + id, 0);
        pid->effects[id].flags = 0;
        spin_unlock_irqrestore(&pid->lock, flags);
 
-       return ret;
+       return 0;
 }
 
 /* Erase all effects this process owns */
@@ -158,31 +148,32 @@ static int hid_pid_flush(struct input_dev *dev, struct file *file)
        int i;
 
        /*NOTE: no need to lock here. The only times EFFECT_USED is
-         modified is when effects are uploaded or when an effect is
-         erased. But a process cannot close its dev/input/eventX fd
-         and perform ioctls on the same fd all at the same time */
-       for (i=0; i<dev->ff_effects_max; ++i)
-               if ( current->pid == pid->effects[i].owner
-                    && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags))
+          modified is when effects are uploaded or when an effect is
+          erased. But a process cannot close its dev/input/eventX fd
+          and perform ioctls on the same fd all at the same time */
+       /*FIXME: multiple threads, anyone? */
+       for (i = 0; i < dev->ff_effects_max; ++i)
+               if (current->pid == pid->effects[i].owner
+                   && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags))
                        if (hid_pid_erase(dev, i))
                                dev_warn(&hid->dev->dev, "erase effect %d failed", i);
 
        return 0;
 }
 
-
 static int hid_pid_upload_effect(struct input_dev *dev,
-                                 struct ff_effect *effect)
+                                struct ff_effect *effect)
 {
-       struct hid_ff_pid* pid_private  = (struct hid_ff_pid*)(dev->private);
+       struct hid_ff_pid *pid_private = (struct hid_ff_pid *)(dev->private);
        int ret;
        int is_update;
-       unsigned long flags = 0;
+       unsigned long flags;
 
-        dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n",effect->type);
+       dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n", effect->type);
        /* Check this effect type is supported by this device */
        if (!test_bit(effect->type, dev->ffbit)) {
-               dev_dbg(&pid_private->hid->dev->dev, "invalid kind of effect requested.\n");
+               dev_dbg(&pid_private->hid->dev->dev,
+                       "invalid kind of effect requested.\n");
                return -EINVAL;
        }
 
@@ -190,31 +181,30 @@ static int hid_pid_upload_effect(struct input_dev *dev,
         * If we want to create a new effect, get a free id
         */
        if (effect->id == -1) {
-               int id=0;
+               int id = 0;
 
                // Spinlock so we don`t get a race condition when choosing IDs
                spin_lock_irqsave(&pid_private->lock, flags);
 
-               while(id < FF_EFFECTS_MAX)
-                       if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags)) 
-                           break;
+               while (id < FF_EFFECTS_MAX)
+                       if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags))
+                               break;
 
-               if ( id == FF_EFFECTS_MAX) {
-                       spin_unlock_irqrestore(&pid_private->lock,flags);
+               if (id == FF_EFFECTS_MAX) {
+                       spin_unlock_irqrestore(&pid_private->lock, flags);
 // TEMP - We need to get ff_effects_max correctly first:  || id >= dev->ff_effects_max) {
                        dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n");
                        return -ENOMEM;
                }
 
                effect->id = id;
-               dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.",id);
+               dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id);
                pid_private->effects[id].owner = current->pid;
-               pid_private->effects[id].flags = (1<<FF_PID_FLAGS_USED);
-               spin_unlock_irqrestore(&pid_private->lock,flags);
+               pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED);
+               spin_unlock_irqrestore(&pid_private->lock, flags);
 
                is_update = FF_PID_FALSE;
-       }
-       else {
+       } else {
                /* We want to update an effect */
                if (!CHECK_OWNERSHIP(effect->id, pid_private))
                        return -EACCES;
@@ -224,9 +214,8 @@ static int hid_pid_upload_effect(struct input_dev *dev,
                        return -EINVAL;
 
                /* Check the effect is not already being updated */
-               if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags)) {
+               if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags))
                        return -EAGAIN;
-               }
 
                is_update = FF_PID_TRUE;
        }
@@ -235,28 +224,30 @@ static int hid_pid_upload_effect(struct input_dev *dev,
         * 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:
-                       dev_dbg(&pid_private->hid->dev->dev, "invalid type of effect requested - %x.\n", effect->type);
-                       return -EINVAL;
+       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:
+               dev_dbg(&pid_private->hid->dev->dev,
+                       "invalid type of effect requested - %x.\n",
+                       effect->type);
+               return -EINVAL;
        }
        /* If a packet was sent, forbid new updates until we are notified
         * that the packet was updated
@@ -269,37 +260,36 @@ static int hid_pid_upload_effect(struct input_dev *dev,
 
 int hid_pid_init(struct hid_device *hid)
 {
-    struct hid_ff_pid *private;
-    struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
-
-    private = hid->ff_private = kmalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
-    if (!private) return -1;
-    
-    memset(private,0,sizeof(struct hid_ff_pid));
-
-    hid->ff_private = private; /* 'cause memset can move the block away */
-
-    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);
-    hidinput->input.upload_effect = hid_pid_upload_effect;
-    hidinput->input.flush = hid_pid_flush;
-    hidinput->input.ff_effects_max = 8;  // A random default
-    set_bit(EV_FF, hidinput->input.evbit);
-    set_bit(EV_FF_STATUS, hidinput->input.evbit);
-
-    spin_lock_init(&private->lock);
-
-    printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n");
-    
-    return 0;    
+       struct hid_ff_pid *private;
+       struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
+
+       private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL);
+       if (!private)
+               return -ENOMEM;
+
+       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);
+       hidinput->input.upload_effect = hid_pid_upload_effect;
+       hidinput->input.flush = hid_pid_flush;
+       hidinput->input.ff_effects_max = 8;     // A random default
+       set_bit(EV_FF, hidinput->input.evbit);
+       set_bit(EV_FF_STATUS, hidinput->input.evbit);
+
+       spin_lock_init(&private->lock);
+
+       printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n");
+
+       return 0;
 }