1 /*********************************************************************
 
   5  * Description:   Implementation of the MA600 dongle
 
   6  * Status:        Experimental.
 
   7  * Author:        Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95
 
   8  * Created at:    Sat Jun 10 20:02:35 2000
 
  12  * Note: very thanks to Mr. Maru Wang <maru@mobileaction.com.tw> for providing 
 
  13  *       information on the MA600 dongle
 
  15  *     Copyright (c) 2000 Leung, All Rights Reserved.
 
  17  *     This program is free software; you can redistribute it and/or 
 
  18  *     modify it under the terms of the GNU General Public License as 
 
  19  *     published by the Free Software Foundation; either version 2 of 
 
  20  *     the License, or (at your option) any later version.
 
  22  *     This program is distributed in the hope that it will be useful,
 
  23  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  24  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
  25  *     GNU General Public License for more details.
 
  27  *     You should have received a copy of the GNU General Public License 
 
  28  *     along with this program; if not, write to the Free Software 
 
  29  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 
  32  ********************************************************************/
 
  34 /* define this macro for release version */
 
  37 #include <linux/module.h>
 
  38 #include <linux/delay.h>
 
  39 #include <linux/tty.h>
 
  40 #include <linux/init.h>
 
  42 #include <net/irda/irda.h>
 
  43 #include <net/irda/irda_device.h>
 
  47         #define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args))
 
  50         #define ASSERT(expr, func) \
 
  52                 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
 
  53                 #expr,__FILE__,__FUNCTION__,__LINE__); \
 
  57 /* convert hex value to ascii hex */
 
  58 static const char hexTbl[] = "0123456789ABCDEF";
 
  61 static void ma600_open(dongle_t *self, struct qos_info *qos);
 
  62 static void ma600_close(dongle_t *self);
 
  63 static int  ma600_change_speed(struct irda_task *task);
 
  64 static int  ma600_reset(struct irda_task *task);
 
  66 /* control byte for MA600 */
 
  67 #define MA600_9600      0x00
 
  68 #define MA600_19200     0x01
 
  69 #define MA600_38400     0x02
 
  70 #define MA600_57600     0x03
 
  71 #define MA600_115200    0x04
 
  72 #define MA600_DEV_ID1   0x05
 
  73 #define MA600_DEV_ID2   0x06
 
  74 #define MA600_2400      0x08
 
  76 static struct dongle_reg dongle = {
 
  77         .type = IRDA_MA600_DONGLE,
 
  81         .change_speed = ma600_change_speed,
 
  85 static int __init ma600_init(void)
 
  87         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
  88         return irda_device_register_dongle(&dongle);
 
  91 static void __exit ma600_cleanup(void)
 
  93         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
  94         irda_device_unregister_dongle(&dongle);
 
  99                 (0) Clear RTS and DTR for 1 second
 
 100                 (1) Set RTS and DTR for 1 second
 
 102         Note: assume RTS, DTR are clear before
 
 104 static void ma600_open(dongle_t *self, struct qos_info *qos)
 
 106         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 108         qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
 
 110         qos->min_turn_time.bits = 0x01;         /* Needs at least 1 ms */       
 
 111         irda_qos_bits_to_value(qos);
 
 113         //self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 114         // should wait 1 second
 
 116         self->set_dtr_rts(self->dev, TRUE, TRUE);
 
 117         // should wait 1 second
 
 120 static void ma600_close(dongle_t *self)
 
 122         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 124         /* Power off dongle */
 
 125         self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 128 static __u8 get_control_byte(__u32 speed)
 
 158  * Function ma600_change_speed (dev, state, speed)
 
 160  *    Set the speed for the MA600 type dongle. Warning, this 
 
 161  *    function must be called with a process context!
 
 165  *    2. clear RTS, set DTR and wait for 1ms
 
 166  *    3. send Control Byte to the MA600 through TXD to set new baud rate
 
 167  *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
 
 168  *       it takes about 10 msec)
 
 169  *    4. set RTS, set DTR (return to NORMAL Operation)
 
 170  *    5. wait at least 10 ms, new setting (baud rate, etc) takes effect here 
 
 173 static int ma600_change_speed(struct irda_task *task)
 
 175         dongle_t *self = (dongle_t *) task->instance;
 
 176         __u32 speed = (__u32) task->param;
 
 181         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 183         ASSERT(task != NULL, return -1;);
 
 185         if (self->speed_task && self->speed_task != task) {
 
 186                 IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
 
 187                 return msecs_to_jiffies(10);
 
 189                 self->speed_task = task;
 
 192         switch (task->state) {
 
 194         case IRDA_TASK_CHILD_INIT:
 
 196                  * Need to reset the dongle and go to 9600 bps before
 
 199                 if (irda_task_execute(self, ma600_reset, NULL, task, 
 
 201                         /* Dongle need more time to reset */
 
 202                         irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
 
 204                         /* give 1 second to finish */
 
 205                         ret = msecs_to_jiffies(1000);
 
 207                         irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
 
 211         case IRDA_TASK_CHILD_WAIT:
 
 212                 IRDA_WARNING("%s(), resetting dongle timed out!\n",
 
 217         case IRDA_TASK_CHILD_DONE:
 
 218                 /* Set DTR, Clear RTS */
 
 219                 self->set_dtr_rts(self->dev, TRUE, FALSE);
 
 221                 ret = msecs_to_jiffies(1);              /* Sleep 1 ms */
 
 222                 irda_task_next_state(task, IRDA_TASK_WAIT);
 
 226                 speed = (__u32) task->param;
 
 227                 byte = get_control_byte(speed);
 
 229                 /* Write control byte */
 
 230                 self->write(self->dev, &byte, sizeof(byte));
 
 232                 irda_task_next_state(task, IRDA_TASK_WAIT1);
 
 234                 /* Wait at least 10 ms */
 
 235                 ret = msecs_to_jiffies(15);
 
 238         case IRDA_TASK_WAIT1:
 
 239                 /* Read control byte echo */
 
 240                 self->read(self->dev, &byte_echo, sizeof(byte_echo));
 
 242                 if(byte != byte_echo) {
 
 243                         /* if control byte != echo, I don't know what to do */
 
 244                         printk(KERN_WARNING "%s() control byte written != read!\n", __FUNCTION__);
 
 245                         printk(KERN_WARNING "control byte = 0x%c%c\n", 
 
 246                                hexTbl[(byte>>4)&0x0f], hexTbl[byte&0x0f]);
 
 247                         printk(KERN_WARNING "byte echo = 0x%c%c\n", 
 
 248                                hexTbl[(byte_echo>>4) & 0x0f], 
 
 249                                hexTbl[byte_echo & 0x0f]);
 
 252                         IRDA_DEBUG(2, "%s() control byte write read OK\n", __FUNCTION__);
 
 256                 /* Set DTR, Set RTS */
 
 257                 self->set_dtr_rts(self->dev, TRUE, TRUE);
 
 259                 irda_task_next_state(task, IRDA_TASK_WAIT2);
 
 261                 /* Wait at least 10 ms */
 
 262                 ret = msecs_to_jiffies(10);
 
 265         case IRDA_TASK_WAIT2:
 
 266                 irda_task_next_state(task, IRDA_TASK_DONE);
 
 267                 self->speed_task = NULL;
 
 271                 IRDA_ERROR("%s(), unknown state %d\n",
 
 272                            __FUNCTION__, task->state);
 
 273                 irda_task_next_state(task, IRDA_TASK_DONE);
 
 274                 self->speed_task = NULL;
 
 282  * Function ma600_reset (driver)
 
 284  *      This function resets the ma600 dongle. Warning, this function 
 
 285  *      must be called with a process context!! 
 
 288  *        0. DTR=0, RTS=1 and wait 10 ms
 
 289  *        1. DTR=1, RTS=1 and wait 10 ms
 
 292 int ma600_reset(struct irda_task *task)
 
 294         dongle_t *self = (dongle_t *) task->instance;
 
 297         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 299         ASSERT(task != NULL, return -1;);
 
 301         if (self->reset_task && self->reset_task != task) {
 
 302                 IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
 
 303                 return msecs_to_jiffies(10);
 
 305                 self->reset_task = task;
 
 307         switch (task->state) {
 
 309                 /* Clear DTR and Set RTS */
 
 310                 self->set_dtr_rts(self->dev, FALSE, TRUE);
 
 311                 irda_task_next_state(task, IRDA_TASK_WAIT1);
 
 312                 ret = msecs_to_jiffies(10);             /* Sleep 10 ms */
 
 314         case IRDA_TASK_WAIT1:
 
 315                 /* Set DTR and RTS */
 
 316                 self->set_dtr_rts(self->dev, TRUE, TRUE);
 
 317                 irda_task_next_state(task, IRDA_TASK_WAIT2);
 
 318                 ret = msecs_to_jiffies(10);             /* Sleep 10 ms */
 
 320         case IRDA_TASK_WAIT2:
 
 321                 irda_task_next_state(task, IRDA_TASK_DONE);
 
 322                 self->reset_task = NULL;
 
 325                 IRDA_ERROR("%s(), unknown state %d\n",
 
 326                            __FUNCTION__, task->state);
 
 327                 irda_task_next_state(task, IRDA_TASK_DONE);             
 
 328                 self->reset_task = NULL;
 
 334 MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95");
 
 335 MODULE_DESCRIPTION("MA600 dongle driver version 0.1");
 
 336 MODULE_LICENSE("GPL");
 
 337 MODULE_ALIAS("irda-dongle-11"); /* IRDA_MA600_DONGLE */
 
 340  * Function init_module (void)
 
 342  *    Initialize MA600 module
 
 345 module_init(ma600_init);
 
 348  * Function cleanup_module (void)
 
 350  *    Cleanup MA600 module
 
 353 module_exit(ma600_cleanup);