linux/drivers/net/irda/ma600-sir.c
<<
>>
Prefs
   1/*********************************************************************
   2 *                
   3 * Filename:      ma600.c
   4 * Version:       0.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
   9 * Modified at:   Sat Aug 16 09:34:13 2003
  10 * Modified by:   Martin Diehl <mad@mdiehl.de> (modified for new sir_dev)
  11 *
  12 * Note: very thanks to Mr. Maru Wang <maru@mobileaction.com.tw> for providing 
  13 *       information on the MA600 dongle
  14 * 
  15 *     Copyright (c) 2000 Leung, All Rights Reserved.
  16 *      
  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.
  21 *  
  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.
  26 * 
  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, 
  30 *     MA 02111-1307 USA
  31 *     
  32 ********************************************************************/
  33
  34#include <linux/module.h>
  35#include <linux/delay.h>
  36#include <linux/init.h>
  37
  38#include <net/irda/irda.h>
  39
  40#include "sir-dev.h"
  41
  42static int ma600_open(struct sir_dev *);
  43static int ma600_close(struct sir_dev *);
  44static int ma600_change_speed(struct sir_dev *, unsigned);
  45static int ma600_reset(struct sir_dev *);
  46
  47/* control byte for MA600 */
  48#define MA600_9600      0x00
  49#define MA600_19200     0x01
  50#define MA600_38400     0x02
  51#define MA600_57600     0x03
  52#define MA600_115200    0x04
  53#define MA600_DEV_ID1   0x05
  54#define MA600_DEV_ID2   0x06
  55#define MA600_2400      0x08
  56
  57static struct dongle_driver ma600 = {
  58        .owner          = THIS_MODULE,
  59        .driver_name    = "MA600",
  60        .type           = IRDA_MA600_DONGLE,
  61        .open           = ma600_open,
  62        .close          = ma600_close,
  63        .reset          = ma600_reset,
  64        .set_speed      = ma600_change_speed,
  65};
  66
  67
  68static int __init ma600_sir_init(void)
  69{
  70        IRDA_DEBUG(2, "%s()\n", __func__);
  71        return irda_register_dongle(&ma600);
  72}
  73
  74static void __exit ma600_sir_cleanup(void)
  75{
  76        IRDA_DEBUG(2, "%s()\n", __func__);
  77        irda_unregister_dongle(&ma600);
  78}
  79
  80/*
  81        Power on:
  82                (0) Clear RTS and DTR for 1 second
  83                (1) Set RTS and DTR for 1 second
  84                (2) 9600 bps now
  85        Note: assume RTS, DTR are clear before
  86*/
  87static int ma600_open(struct sir_dev *dev)
  88{
  89        struct qos_info *qos = &dev->qos;
  90
  91        IRDA_DEBUG(2, "%s()\n", __func__);
  92
  93        sirdev_set_dtr_rts(dev, TRUE, TRUE);
  94
  95        /* Explicitly set the speeds we can accept */
  96        qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
  97                                |IR_57600|IR_115200;
  98        /* Hm, 0x01 means 10ms - for >= 1ms we would need 0x07 */
  99        qos->min_turn_time.bits = 0x01;         /* Needs at least 1 ms */       
 100        irda_qos_bits_to_value(qos);
 101
 102        /* irda thread waits 50 msec for power settling */
 103
 104        return 0;
 105}
 106
 107static int ma600_close(struct sir_dev *dev)
 108{
 109        IRDA_DEBUG(2, "%s()\n", __func__);
 110
 111        /* Power off dongle */
 112        sirdev_set_dtr_rts(dev, FALSE, FALSE);
 113
 114        return 0;
 115}
 116
 117static __u8 get_control_byte(__u32 speed)
 118{
 119        __u8 byte;
 120
 121        switch (speed) {
 122        default:
 123        case 115200:
 124                byte = MA600_115200;
 125                break;
 126        case 57600:
 127                byte = MA600_57600;
 128                break;
 129        case 38400:
 130                byte = MA600_38400;
 131                break;
 132        case 19200:
 133                byte = MA600_19200;
 134                break;
 135        case 9600:
 136                byte = MA600_9600;
 137                break;
 138        case 2400:
 139                byte = MA600_2400;
 140                break;
 141        }
 142
 143        return byte;
 144}
 145
 146/*
 147 * Function ma600_change_speed (dev, speed)
 148 *
 149 *    Set the speed for the MA600 type dongle.
 150 *
 151 *    The dongle has already been reset to a known state (dongle default)
 152 *    We cycle through speeds by pulsing RTS low and then high.
 153 */
 154
 155/*
 156 * Function ma600_change_speed (dev, speed)
 157 *
 158 *    Set the speed for the MA600 type dongle.
 159 *
 160 *    Algorithm
 161 *    1. Reset (already done by irda thread state machine)
 162 *    2. clear RTS, set DTR and wait for 1ms
 163 *    3. send Control Byte to the MA600 through TXD to set new baud rate
 164 *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
 165 *       it takes about 10 msec)
 166 *    4. set RTS, set DTR (return to NORMAL Operation)
 167 *    5. wait at least 10 ms, new setting (baud rate, etc) takes effect here 
 168 *       after
 169 */
 170
 171/* total delays are only about 20ms - let's just sleep for now to
 172 * avoid the state machine complexity before we get things working
 173 */
 174
 175static int ma600_change_speed(struct sir_dev *dev, unsigned speed)
 176{
 177        u8      byte;
 178        
 179        IRDA_DEBUG(2, "%s(), speed=%d (was %d)\n", __func__,
 180                speed, dev->speed);
 181
 182        /* dongle already reset, dongle and port at default speed (9600) */
 183
 184        /* Set RTS low for 1 ms */
 185        sirdev_set_dtr_rts(dev, TRUE, FALSE);
 186        mdelay(1);
 187
 188        /* Write control byte */
 189        byte = get_control_byte(speed);
 190        sirdev_raw_write(dev, &byte, sizeof(byte));
 191
 192        /* Wait at least 10ms: fake wait_until_sent - 10 bits at 9600 baud*/
 193        msleep(15);                                     /* old ma600 uses 15ms */
 194
 195#if 1
 196        /* read-back of the control byte. ma600 is the first dongle driver
 197         * which uses this so there might be some unidentified issues.
 198         * Disable this in case of problems with readback.
 199         */
 200
 201        sirdev_raw_read(dev, &byte, sizeof(byte));
 202        if (byte != get_control_byte(speed))  {
 203                IRDA_WARNING("%s(): bad control byte read-back %02x != %02x\n",
 204                             __func__, (unsigned) byte,
 205                             (unsigned) get_control_byte(speed));
 206                return -1;
 207        }
 208        else
 209                IRDA_DEBUG(2, "%s() control byte write read OK\n", __func__);
 210#endif
 211
 212        /* Set DTR, Set RTS */
 213        sirdev_set_dtr_rts(dev, TRUE, TRUE);
 214
 215        /* Wait at least 10ms */
 216        msleep(10);
 217
 218        /* dongle is now switched to the new speed */
 219        dev->speed = speed;
 220
 221        return 0;
 222}
 223
 224/*
 225 * Function ma600_reset (dev)
 226 *
 227 *      This function resets the ma600 dongle.
 228 *
 229 *      Algorithm:
 230 *        0. DTR=0, RTS=1 and wait 10 ms
 231 *        1. DTR=1, RTS=1 and wait 10 ms
 232 *        2. 9600 bps now
 233 */
 234
 235/* total delays are only about 20ms - let's just sleep for now to
 236 * avoid the state machine complexity before we get things working
 237 */
 238
 239static int ma600_reset(struct sir_dev *dev)
 240{
 241        IRDA_DEBUG(2, "%s()\n", __func__);
 242
 243        /* Reset the dongle : set DTR low for 10 ms */
 244        sirdev_set_dtr_rts(dev, FALSE, TRUE);
 245        msleep(10);
 246
 247        /* Go back to normal mode */
 248        sirdev_set_dtr_rts(dev, TRUE, TRUE);
 249        msleep(10);
 250
 251        dev->speed = 9600;      /* That's the dongle-default */
 252
 253        return 0;
 254}
 255
 256MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95");
 257MODULE_DESCRIPTION("MA600 dongle driver version 0.1");
 258MODULE_LICENSE("GPL");
 259MODULE_ALIAS("irda-dongle-11"); /* IRDA_MA600_DONGLE */
 260                
 261module_init(ma600_sir_init);
 262module_exit(ma600_sir_cleanup);
 263
 264
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.