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