1/********************************************************************* 2 * 3 * Filename: tekram.c 4 * Version: 1.3 5 * Description: Implementation of the Tekram IrMate IR-210B dongle 6 * Status: Experimental. 7 * Author: Dag Brattli <dagb@cs.uit.no> 8 * Created at: Wed Oct 21 20:02:35 1998 9 * Modified at: Sun Oct 27 22:02:38 2002 10 * Modified by: Martin Diehl <mad@mdiehl.de> 11 * 12 * Copyright (c) 1998-1999 Dag Brattli, 13 * Copyright (c) 2002 Martin Diehl, 14 * All Rights Reserved. 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License as 18 * published by the Free Software Foundation; either version 2 of 19 * the License, or (at your option) any later version. 20 * 21 * Neither Dag Brattli nor University of Tromsø admit liability nor 22 * provide warranty for any of this software. This material is 23 * provided "AS-IS" and at no charge. 24 * 25 ********************************************************************/ 26 27#include <linux/module.h> 28#include <linux/delay.h> 29#include <linux/init.h> 30 31#include <net/irda/irda.h> 32 33#include "sir-dev.h" 34 35static int tekram_delay = 150; /* default is 150 ms */ 36module_param(tekram_delay, int, 0); 37MODULE_PARM_DESC(tekram_delay, "tekram dongle write complete delay"); 38 39static int tekram_open(struct sir_dev *); 40static int tekram_close(struct sir_dev *); 41static int tekram_change_speed(struct sir_dev *, unsigned); 42static int tekram_reset(struct sir_dev *); 43 44#define TEKRAM_115200 0x00 45#define TEKRAM_57600 0x01 46#define TEKRAM_38400 0x02 47#define TEKRAM_19200 0x03 48#define TEKRAM_9600 0x04 49 50#define TEKRAM_PW 0x10 /* Pulse select bit */ 51 52static struct dongle_driver tekram = { 53 .owner = THIS_MODULE, 54 .driver_name = "Tekram IR-210B", 55 .type = IRDA_TEKRAM_DONGLE, 56 .open = tekram_open, 57 .close = tekram_close, 58 .reset = tekram_reset, 59 .set_speed = tekram_change_speed, 60}; 61 62static int __init tekram_sir_init(void) 63{ 64 if (tekram_delay < 1 || tekram_delay > 500) 65 tekram_delay = 200; 66 pr_debug("%s - using %d ms delay\n", 67 tekram.driver_name, tekram_delay); 68 return irda_register_dongle(&tekram); 69} 70 71static void __exit tekram_sir_cleanup(void) 72{ 73 irda_unregister_dongle(&tekram); 74} 75 76static int tekram_open(struct sir_dev *dev) 77{ 78 struct qos_info *qos = &dev->qos; 79 80 sirdev_set_dtr_rts(dev, TRUE, TRUE); 81 82 qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; 83 qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ 84 irda_qos_bits_to_value(qos); 85 86 /* irda thread waits 50 msec for power settling */ 87 88 return 0; 89} 90 91static int tekram_close(struct sir_dev *dev) 92{ 93 /* Power off dongle */ 94 sirdev_set_dtr_rts(dev, FALSE, FALSE); 95 96 return 0; 97} 98 99/* 100 * Function tekram_change_speed (dev, state, speed) 101 * 102 * Set the speed for the Tekram IRMate 210 type dongle. Warning, this 103 * function must be called with a process context! 104 * 105 * Algorithm 106 * 1. clear DTR 107 * 2. set RTS, and wait at least 7 us 108 * 3. send Control Byte to the IR-210 through TXD to set new baud rate 109 * wait until the stop bit of Control Byte is sent (for 9600 baud rate, 110 * it takes about 100 msec) 111 * 112 * [oops, why 100 msec? sending 1 byte (10 bits) takes 1.05 msec 113 * - is this probably to compensate for delays in tty layer?] 114 * 115 * 5. clear RTS (return to NORMAL Operation) 116 * 6. wait at least 50 us, new setting (baud rate, etc) takes effect here 117 * after 118 */ 119 120#define TEKRAM_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1) 121 122static int tekram_change_speed(struct sir_dev *dev, unsigned speed) 123{ 124 unsigned state = dev->fsm.substate; 125 unsigned delay = 0; 126 u8 byte; 127 static int ret = 0; 128 129 switch(state) { 130 case SIRDEV_STATE_DONGLE_SPEED: 131 132 switch (speed) { 133 default: 134 speed = 9600; 135 ret = -EINVAL; 136 /* fall thru */ 137 case 9600: 138 byte = TEKRAM_PW|TEKRAM_9600; 139 break; 140 case 19200: 141 byte = TEKRAM_PW|TEKRAM_19200; 142 break; 143 case 38400: 144 byte = TEKRAM_PW|TEKRAM_38400; 145 break; 146 case 57600: 147 byte = TEKRAM_PW|TEKRAM_57600; 148 break; 149 case 115200: 150 byte = TEKRAM_115200; 151 break; 152 } 153 154 /* Set DTR, Clear RTS */ 155 sirdev_set_dtr_rts(dev, TRUE, FALSE); 156 157 /* Wait at least 7us */ 158 udelay(14); 159 160 /* Write control byte */ 161 sirdev_raw_write(dev, &byte, 1); 162 163 dev->speed = speed; 164 165 state = TEKRAM_STATE_WAIT_SPEED; 166 delay = tekram_delay; 167 break; 168 169 case TEKRAM_STATE_WAIT_SPEED: 170 /* Set DTR, Set RTS */ 171 sirdev_set_dtr_rts(dev, TRUE, TRUE); 172 udelay(50); 173 break; 174 175 default: 176 net_err_ratelimited("%s - undefined state %d\n", 177 __func__, state); 178 ret = -EINVAL; 179 break; 180 } 181 182 dev->fsm.substate = state; 183 return (delay > 0) ? delay : ret; 184} 185 186/* 187 * Function tekram_reset (driver) 188 * 189 * This function resets the tekram dongle. Warning, this function 190 * must be called with a process context!! 191 * 192 * Algorithm: 193 * 0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 ) 194 * 1. clear RTS 195 * 2. set DTR, and wait at least 1 ms 196 * 3. clear DTR to SPACE state, wait at least 50 us for further 197 * operation 198 */ 199 200static int tekram_reset(struct sir_dev *dev) 201{ 202 /* Clear DTR, Set RTS */ 203 sirdev_set_dtr_rts(dev, FALSE, TRUE); 204 205 /* Should sleep 1 ms */ 206 msleep(1); 207 208 /* Set DTR, Set RTS */ 209 sirdev_set_dtr_rts(dev, TRUE, TRUE); 210 211 /* Wait at least 50 us */ 212 udelay(75); 213 214 dev->speed = 9600; 215 216 return 0; 217} 218 219MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); 220MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver"); 221MODULE_LICENSE("GPL"); 222MODULE_ALIAS("irda-dongle-0"); /* IRDA_TEKRAM_DONGLE */ 223 224module_init(tekram_sir_init); 225module_exit(tekram_sir_cleanup); 226