Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16 354 lines 9.0 kB view raw
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: 10 * Modified by: 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/* define this macro for release version */ 35//#define NDEBUG 36 37#include <linux/module.h> 38#include <linux/delay.h> 39#include <linux/tty.h> 40#include <linux/init.h> 41 42#include <net/irda/irda.h> 43#include <net/irda/irda_device.h> 44 45#ifndef NDEBUG 46 #undef IRDA_DEBUG 47 #define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args)) 48 49 #undef ASSERT 50 #define ASSERT(expr, func) \ 51 if(!(expr)) { \ 52 printk( "Assertion failed! %s,%s,%s,line=%d\n",\ 53 #expr,__FILE__,__FUNCTION__,__LINE__); \ 54 func} 55#endif 56 57/* convert hex value to ascii hex */ 58static const char hexTbl[] = "0123456789ABCDEF"; 59 60 61static void ma600_open(dongle_t *self, struct qos_info *qos); 62static void ma600_close(dongle_t *self); 63static int ma600_change_speed(struct irda_task *task); 64static int ma600_reset(struct irda_task *task); 65 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 75 76static struct dongle_reg dongle = { 77 .type = IRDA_MA600_DONGLE, 78 .open = ma600_open, 79 .close = ma600_close, 80 .reset = ma600_reset, 81 .change_speed = ma600_change_speed, 82 .owner = THIS_MODULE, 83}; 84 85static int __init ma600_init(void) 86{ 87 IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 88 return irda_device_register_dongle(&dongle); 89} 90 91static void __exit ma600_cleanup(void) 92{ 93 IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 94 irda_device_unregister_dongle(&dongle); 95} 96 97/* 98 Power on: 99 (0) Clear RTS and DTR for 1 second 100 (1) Set RTS and DTR for 1 second 101 (2) 9600 bps now 102 Note: assume RTS, DTR are clear before 103*/ 104static void ma600_open(dongle_t *self, struct qos_info *qos) 105{ 106 IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 107 108 qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400 109 |IR_57600|IR_115200; 110 qos->min_turn_time.bits = 0x01; /* Needs at least 1 ms */ 111 irda_qos_bits_to_value(qos); 112 113 //self->set_dtr_rts(self->dev, FALSE, FALSE); 114 // should wait 1 second 115 116 self->set_dtr_rts(self->dev, TRUE, TRUE); 117 // should wait 1 second 118} 119 120static void ma600_close(dongle_t *self) 121{ 122 IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 123 124 /* Power off dongle */ 125 self->set_dtr_rts(self->dev, FALSE, FALSE); 126} 127 128static __u8 get_control_byte(__u32 speed) 129{ 130 __u8 byte; 131 132 switch (speed) { 133 default: 134 case 115200: 135 byte = MA600_115200; 136 break; 137 case 57600: 138 byte = MA600_57600; 139 break; 140 case 38400: 141 byte = MA600_38400; 142 break; 143 case 19200: 144 byte = MA600_19200; 145 break; 146 case 9600: 147 byte = MA600_9600; 148 break; 149 case 2400: 150 byte = MA600_2400; 151 break; 152 } 153 154 return byte; 155} 156 157/* 158 * Function ma600_change_speed (dev, state, speed) 159 * 160 * Set the speed for the MA600 type dongle. Warning, this 161 * function must be called with a process context! 162 * 163 * Algorithm 164 * 1. Reset 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 171 * after 172 */ 173static int ma600_change_speed(struct irda_task *task) 174{ 175 dongle_t *self = (dongle_t *) task->instance; 176 __u32 speed = (__u32) task->param; 177 static __u8 byte; 178 __u8 byte_echo; 179 int ret = 0; 180 181 IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 182 183 ASSERT(task != NULL, return -1;); 184 185 if (self->speed_task && self->speed_task != task) { 186 IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__); 187 return msecs_to_jiffies(10); 188 } else { 189 self->speed_task = task; 190 } 191 192 switch (task->state) { 193 case IRDA_TASK_INIT: 194 case IRDA_TASK_CHILD_INIT: 195 /* 196 * Need to reset the dongle and go to 9600 bps before 197 * programming 198 */ 199 if (irda_task_execute(self, ma600_reset, NULL, task, 200 (void *) speed)) { 201 /* Dongle need more time to reset */ 202 irda_task_next_state(task, IRDA_TASK_CHILD_WAIT); 203 204 /* give 1 second to finish */ 205 ret = msecs_to_jiffies(1000); 206 } else { 207 irda_task_next_state(task, IRDA_TASK_CHILD_DONE); 208 } 209 break; 210 211 case IRDA_TASK_CHILD_WAIT: 212 IRDA_WARNING("%s(), resetting dongle timed out!\n", 213 __FUNCTION__); 214 ret = -1; 215 break; 216 217 case IRDA_TASK_CHILD_DONE: 218 /* Set DTR, Clear RTS */ 219 self->set_dtr_rts(self->dev, TRUE, FALSE); 220 221 ret = msecs_to_jiffies(1); /* Sleep 1 ms */ 222 irda_task_next_state(task, IRDA_TASK_WAIT); 223 break; 224 225 case IRDA_TASK_WAIT: 226 speed = (__u32) task->param; 227 byte = get_control_byte(speed); 228 229 /* Write control byte */ 230 self->write(self->dev, &byte, sizeof(byte)); 231 232 irda_task_next_state(task, IRDA_TASK_WAIT1); 233 234 /* Wait at least 10 ms */ 235 ret = msecs_to_jiffies(15); 236 break; 237 238 case IRDA_TASK_WAIT1: 239 /* Read control byte echo */ 240 self->read(self->dev, &byte_echo, sizeof(byte_echo)); 241 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]); 250 #ifndef NDEBUG 251 } else { 252 IRDA_DEBUG(2, "%s() control byte write read OK\n", __FUNCTION__); 253 #endif 254 } 255 256 /* Set DTR, Set RTS */ 257 self->set_dtr_rts(self->dev, TRUE, TRUE); 258 259 irda_task_next_state(task, IRDA_TASK_WAIT2); 260 261 /* Wait at least 10 ms */ 262 ret = msecs_to_jiffies(10); 263 break; 264 265 case IRDA_TASK_WAIT2: 266 irda_task_next_state(task, IRDA_TASK_DONE); 267 self->speed_task = NULL; 268 break; 269 270 default: 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; 275 ret = -1; 276 break; 277 } 278 return ret; 279} 280 281/* 282 * Function ma600_reset (driver) 283 * 284 * This function resets the ma600 dongle. Warning, this function 285 * must be called with a process context!! 286 * 287 * Algorithm: 288 * 0. DTR=0, RTS=1 and wait 10 ms 289 * 1. DTR=1, RTS=1 and wait 10 ms 290 * 2. 9600 bps now 291 */ 292int ma600_reset(struct irda_task *task) 293{ 294 dongle_t *self = (dongle_t *) task->instance; 295 int ret = 0; 296 297 IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 298 299 ASSERT(task != NULL, return -1;); 300 301 if (self->reset_task && self->reset_task != task) { 302 IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__); 303 return msecs_to_jiffies(10); 304 } else 305 self->reset_task = task; 306 307 switch (task->state) { 308 case IRDA_TASK_INIT: 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 */ 313 break; 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 */ 319 break; 320 case IRDA_TASK_WAIT2: 321 irda_task_next_state(task, IRDA_TASK_DONE); 322 self->reset_task = NULL; 323 break; 324 default: 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; 329 ret = -1; 330 } 331 return ret; 332} 333 334MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95"); 335MODULE_DESCRIPTION("MA600 dongle driver version 0.1"); 336MODULE_LICENSE("GPL"); 337MODULE_ALIAS("irda-dongle-11"); /* IRDA_MA600_DONGLE */ 338 339/* 340 * Function init_module (void) 341 * 342 * Initialize MA600 module 343 * 344 */ 345module_init(ma600_init); 346 347/* 348 * Function cleanup_module (void) 349 * 350 * Cleanup MA600 module 351 * 352 */ 353module_exit(ma600_cleanup); 354