[1] - subdevice number you wish to emulate commands for
TODO:
- Improve error handling
Support for digital io commands could be added, except I can't see why
anyone would want to use them
Fix it so more that one comedi_rt_timer can be configured at once
#include <rtai_sched.h>
#endif
-/* Change this if you need more channels */
-#define N_CHANLIST 16
-
static int timer_attach(comedi_device *dev,comedi_devconfig *it);
static int timer_detach(comedi_device *dev);
static comedi_driver driver_timer={
comedi_subdevice *s;
RT_TASK rt_task;
int soft_irq;
- int chanlist[N_CHANLIST];
}timer_private;
#define devpriv ((timer_private *)dev->private)
-static comedi_device *broken_rt_dev;
+static comedi_device *broken_rt_dev = NULL;
#ifdef CONFIG_COMEDI_RTL
static void timer_interrupt(int irq,void *d,struct pt_regs * regs)
CR_AREF(cmd->chanlist[i]),
&data);
if(ret<0){
- /* eek! */
- rt_printk("eek!\n");
+ comedi_error(dev, "read error");
+ comedi_error_done(dev, s);
+ goto cleanup;
}
if(cmd->convert_src == TRIG_TIMER)
rt_task_wait_period();
s->async->events = 0;
}
comedi_done(dev,s);
- rt_pend_linux_srq(devpriv->soft_irq);
- rt_task_delete(&devpriv->rt_task);
+cleanup:
- /* eek! */
+ rt_pend_linux_srq(devpriv->soft_irq);
+ // we are deleting ourself here, no lines afterwards will be executed!
+ rt_task_delete(&devpriv->rt_task);
}
static void timer_ao_task_func(int d)
for(i=0;i<cmd->scan_end_arg;i++){
data = buf_remove(dev,s);
if(data < 0) {
- /* eek! */
- rt_printk("eek!\n");
+ comedi_error(dev, "buffer underrun");
+ comedi_error_done(dev, s);
+ goto cleanup;
}
ret = comedi_data_write(devpriv->device,devpriv->subd,
CR_CHAN(cmd->chanlist[i]),
CR_AREF(cmd->chanlist[i]),
data);
if(ret<0){
- /* eek! */
- rt_printk("eek!\n");
+ comedi_error(dev, "write error");
+ comedi_error_done(dev, s);
+ goto cleanup;
}
if(cmd->convert_src == TRIG_TIMER)
rt_task_wait_period();
rt_task_wait_period();
}
comedi_done(dev,s);
- rt_pend_linux_srq(devpriv->soft_irq);
- rt_task_delete(&devpriv->rt_task);
+cleanup:
- /* eek! */
+ rt_pend_linux_srq(devpriv->soft_irq);
+ // we are deleting ourself here, no lines afterwards will be executed!
+ rt_task_delete(&devpriv->rt_task);
}
static int timer_insn(comedi_device *dev,comedi_subdevice *s,
static int timer_cancel(comedi_device *dev,comedi_subdevice *s)
{
rt_task_delete(&devpriv->rt_task);
-
- comedi_unlock(devpriv->device,devpriv->subd);
+ rt_pend_linux_srq(devpriv->soft_irq);
return 0;
}
printk("comedi%d: timer: ",dev->minor);
+ if(broken_rt_dev)
+ {
+ printk("Only a single comedi_rt_timer can be configured at once.\n"
+ " Hopefully this will be fixed in the future.\n");
+ return -EBUSY;
+ }
+
dev->board_name="timer";
dev->n_subdevices=2;
}
}
+ broken_rt_dev = NULL;
+
return 0;
}