Jean Tourrilhes <[EMAIL PROTECTED]> writes:

>       Hi everybody...
> 
>       A few weeks ago, I was complaining that the timming in the
> Actisys dongle driver in Linux IrDA were absurd. Today I received my
> batch of Actisys dongle, and guess what, I could not make it work with
> Linux IrDA.
>       So, I wiped out the initialisation code and the code to change
> speed in the old driver and replaced it with something simpler, faster
> and more robust. I have to thanks Lichen Wang from Actisys who sent me

Well, I'm not so sure it's more robust ;-)

> a nice e-mail detailing the secret of their dongle.
>       Anyway, the result is a new dongle driver that work for me.
>       Enjoy...
> 

> static int actisys_change_speed(struct irda_task *task)
> {
>       dongle_t *self = (dongle_t *) task->instance;
>       __u32 speed = (__u32) task->param;      /* Target speed */
>         int index = 0;
>       int ret = 0;
>       
>         IRDA_DEBUG(4, __FUNCTION__ "(), speed=%d (was %d)\n",
>                  speed, self->speed);
> 
>       /* Go to a known state by reseting the dongle */
> 
>       /* Reset the dongle : set DTR low for 10 us */
>       self->set_dtr_rts(self->dev, FALSE, TRUE);
>       udelay(MIN_DELAY);
> 
>       /* Go back to normal mode (we are now at 9600 b/s) */
>       self->set_dtr_rts(self->dev, TRUE, TRUE);
>  
>       /* Now, we can set the speed requested */
> 
>       /* Send RTS pulses until we reach the target speed */
>       while((index < 5) && (speed != baud_rates[index++]))

I think it's very dangerous to increase the index here! Anyway, the index
will be one higher than the current baudrate when this loop is finished. 

>       {
>               /* Make sure previous pulse is finished */
>               udelay(MIN_DELAY);
> 
>               /* Set RTS low for 10 us */
>               self->set_dtr_rts(self->dev, TRUE, FALSE);
>               udelay(MIN_DELAY);
> 
>               /* Set RTS high for 10 us */
>               self->set_dtr_rts(self->dev, TRUE, TRUE);
>       }
> 
>       /* Check if life is sweet... */
>       if(speed != baud_rates[index])

... and that is very dangerous here, if index becomes 5 (which it can be if
something goes wrong), you will index outside the array. Well, I cannot
find any reason why this should match at all, so I'm confused that you
actually got this code to work!? You find a match, but increase the index
at the same time, which means that the index is pointing to the next
entry (which should not match).

>               ret = -1;       /* This should not happen */
>       self->speed = baud_rates[index];        /* Do we care ? */
> 
>       /* Basta lavoro, on se casse d'ici... */
>       irda_task_next_state(task, IRDA_TASK_DONE);
> 
>       return ret;
> }

I think it would be better (and safer) to do it like this:

        /* Send RTS pulses until we reach the target speed */
        for (i=0; i<5; i++) {
                if (speed == baud_rates[i]) {
                        self->speed = baud_rates[i];
                        break;
                }
                /* Make sure previous pulse is finished */
                udelay(MIN_DELAY);

                /* Set RTS low for 10 us */
                self->set_dtr_rts(self->dev, TRUE, FALSE);
                udelay(MIN_DELAY);

                /* Set RTS high for 10 us */
                self->set_dtr_rts(self->dev, TRUE, TRUE);
        }

        /* Check if life is sweet... */
        if (i == 5)
                ret = -1;  /* This should not happen */

I have fixed this in my code, and I'll be releasing a new patch later ...

-- Dag

-- 
   / Dag Brattli                   | The Linux-IrDA Project               /
  // University of Tromsoe, Norway | Infrared communication for Linux    //
 /// http://www.cs.uit.no/~dagb    | http://www.cs.uit.no/linux-irda/   ///

_______________________________________________
Linux-IrDA mailing list  -  [EMAIL PROTECTED]
http://www4.pasta.cs.UiT.No/mailman/listinfo/linux-irda

Reply via email to