ma600.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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. /* define this macro for release version */
  34. //#define NDEBUG
  35. #include <linux/module.h>
  36. #include <linux/delay.h>
  37. #include <linux/tty.h>
  38. #include <linux/sched.h>
  39. #include <linux/init.h>
  40. #include <net/irda/irda.h>
  41. #include <net/irda/irda_device.h>
  42. #include <net/irda/irtty.h>
  43. #ifndef NDEBUG
  44. #undef IRDA_DEBUG
  45. #define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args))
  46. #undef ASSERT(expr, func)
  47. #define ASSERT(expr, func) 
  48. if(!(expr)) { 
  49.         printk( "Assertion failed! %s,%s,%s,line=%dn",
  50.          #expr,__FILE__,__FUNCTION__,__LINE__); 
  51.         ##func}
  52. #endif
  53. /* convert hex value to ascii hex */
  54. static const char hexTbl[] = "0123456789ABCDEF";
  55. static void ma600_open(dongle_t *self, struct qos_info *qos);
  56. static void ma600_close(dongle_t *self);
  57. static int  ma600_change_speed(struct irda_task *task);
  58. static int  ma600_reset(struct irda_task *task);
  59. /* control byte for MA600 */
  60. #define MA600_9600 0x00
  61. #define MA600_19200 0x01
  62. #define MA600_38400 0x02
  63. #define MA600_57600 0x03
  64. #define MA600_115200 0x04
  65. #define MA600_DEV_ID1 0x05
  66. #define MA600_DEV_ID2 0x06
  67. #define MA600_2400 0x08
  68. static struct dongle_reg dongle = {
  69. Q_NULL,
  70. IRDA_MA600_DONGLE,
  71. ma600_open,
  72. ma600_close,
  73. ma600_reset,
  74. ma600_change_speed,
  75. };
  76. int __init ma600_init(void)
  77. {
  78. IRDA_DEBUG(2, __FUNCTION__ "()n");
  79. return irda_device_register_dongle(&dongle);
  80. }
  81. void __exit ma600_cleanup(void)
  82. {
  83. IRDA_DEBUG(2, __FUNCTION__ "()n");
  84. irda_device_unregister_dongle(&dongle);
  85. }
  86. /*
  87. Power on:
  88. (0) Clear RTS and DTR for 1 second
  89. (1) Set RTS and DTR for 1 second
  90. (2) 9600 bps now
  91. Note: assume RTS, DTR are clear before
  92. */
  93. static void ma600_open(dongle_t *self, struct qos_info *qos)
  94. {
  95. IRDA_DEBUG(2, __FUNCTION__ "()n");
  96. qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
  97. |IR_57600|IR_115200;
  98. qos->min_turn_time.bits = 0x01; /* Needs at least 1 ms */
  99. irda_qos_bits_to_value(qos);
  100. //self->set_dtr_rts(self->dev, FALSE, FALSE);
  101. // should wait 1 second
  102. self->set_dtr_rts(self->dev, TRUE, TRUE);
  103. // should wait 1 second
  104. MOD_INC_USE_COUNT;
  105. }
  106. static void ma600_close(dongle_t *self)
  107. {
  108. IRDA_DEBUG(2, __FUNCTION__ "()n");
  109. /* Power off dongle */
  110. self->set_dtr_rts(self->dev, FALSE, FALSE);
  111. MOD_DEC_USE_COUNT;
  112. }
  113. static __u8 get_control_byte(__u32 speed)
  114. {
  115. __u8 byte;
  116. switch (speed) {
  117. default:
  118. case 115200:
  119. byte = MA600_115200;
  120. break;
  121. case 57600:
  122. byte = MA600_57600;
  123. break;
  124. case 38400:
  125. byte = MA600_38400;
  126. break;
  127. case 19200:
  128. byte = MA600_19200;
  129. break;
  130. case 9600:
  131. byte = MA600_9600;
  132. break;
  133. case 2400:
  134. byte = MA600_2400;
  135. break;
  136. }
  137. return byte;
  138. }
  139. /*
  140.  * Function ma600_change_speed (dev, state, speed)
  141.  *
  142.  *    Set the speed for the MA600 type dongle. Warning, this 
  143.  *    function must be called with a process context!
  144.  *
  145.  *    Algorithm
  146.  *    1. Reset
  147.  *    2. clear RTS, set DTR and wait for 1ms
  148.  *    3. send Control Byte to the MA600 through TXD to set new baud rate
  149.  *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
  150.  *       it takes about 10 msec)
  151.  *    4. set RTS, set DTR (return to NORMAL Operation)
  152.  *    5. wait at least 10 ms, new setting (baud rate, etc) takes effect here 
  153.  *       after
  154.  */
  155. static int ma600_change_speed(struct irda_task *task)
  156. {
  157. dongle_t *self = (dongle_t *) task->instance;
  158. __u32 speed = (__u32) task->param;
  159. static __u8 byte;
  160. __u8 byte_echo;
  161. int ret = 0;
  162. IRDA_DEBUG(2, __FUNCTION__ "()n");
  163. ASSERT(task != NULL, return -1;);
  164. if (self->speed_task && self->speed_task != task) {
  165. IRDA_DEBUG(0, __FUNCTION__ "(), busy!n");
  166. return MSECS_TO_JIFFIES(10);
  167. } else {
  168. self->speed_task = task;
  169. }
  170. switch (task->state) {
  171. case IRDA_TASK_INIT:
  172. case IRDA_TASK_CHILD_INIT:
  173. /* 
  174.  * Need to reset the dongle and go to 9600 bps before
  175.                  * programming 
  176.  */
  177. if (irda_task_execute(self, ma600_reset, NULL, task, 
  178.       (void *) speed)) {
  179. /* Dongle need more time to reset */
  180. irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
  181. /* give 1 second to finish */
  182. ret = MSECS_TO_JIFFIES(1000);
  183. } else {
  184. irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
  185. }
  186. break;
  187. case IRDA_TASK_CHILD_WAIT:
  188. WARNING(__FUNCTION__ "(), resetting dongle timed out!n");
  189. ret = -1;
  190. break;
  191. case IRDA_TASK_CHILD_DONE:
  192. /* Set DTR, Clear RTS */
  193. self->set_dtr_rts(self->dev, TRUE, FALSE);
  194. ret = MSECS_TO_JIFFIES(1); /* Sleep 1 ms */
  195. irda_task_next_state(task, IRDA_TASK_WAIT);
  196. break;
  197. case IRDA_TASK_WAIT:
  198. speed = (__u32) task->param;
  199. byte = get_control_byte(speed);
  200. /* Write control byte */
  201. self->write(self->dev, &byte, sizeof(byte));
  202. irda_task_next_state(task, IRDA_TASK_WAIT1);
  203. /* Wait at least 10 ms */
  204. ret = MSECS_TO_JIFFIES(15);
  205. break;
  206. case IRDA_TASK_WAIT1:
  207. /* Read control byte echo */
  208. self->read(self->dev, &byte_echo, sizeof(byte_echo));
  209. if(byte != byte_echo) {
  210. /* if control byte != echo, I don't know what to do */
  211. printk(KERN_WARNING __FUNCTION__ "() control byte written != read!n");
  212. printk(KERN_WARNING "control byte = 0x%c%cn", 
  213.        hexTbl[(byte>>4)&0x0f], hexTbl[byte&0x0f]);
  214. printk(KERN_WARNING "byte echo = 0x%c%cn", 
  215.        hexTbl[(byte_echo>>4) & 0x0f], 
  216.        hexTbl[byte_echo & 0x0f]);
  217. #ifndef NDEBUG
  218. } else {
  219. IRDA_DEBUG(2, __FUNCTION__ "() control byte write read OKn");
  220. #endif
  221. }
  222. /* Set DTR, Set RTS */
  223. self->set_dtr_rts(self->dev, TRUE, TRUE);
  224. irda_task_next_state(task, IRDA_TASK_WAIT2);
  225. /* Wait at least 10 ms */
  226. ret = MSECS_TO_JIFFIES(10);
  227. break;
  228. case IRDA_TASK_WAIT2:
  229. irda_task_next_state(task, IRDA_TASK_DONE);
  230. self->speed_task = NULL;
  231. break;
  232. default:
  233. ERROR(__FUNCTION__ "(), unknown state %dn", task->state);
  234. irda_task_next_state(task, IRDA_TASK_DONE);
  235. self->speed_task = NULL;
  236. ret = -1;
  237. break;
  238. }
  239. return ret;
  240. }
  241. /*
  242.  * Function ma600_reset (driver)
  243.  *
  244.  *      This function resets the ma600 dongle. Warning, this function 
  245.  *      must be called with a process context!! 
  246.  *
  247.  *      Algorithm:
  248.  *       0. DTR=0, RTS=1 and wait 10 ms
  249.  *       1. DTR=1, RTS=1 and wait 10 ms
  250.  *        2. 9600 bps now
  251.  */
  252. int ma600_reset(struct irda_task *task)
  253. {
  254. dongle_t *self = (dongle_t *) task->instance;
  255. int ret = 0;
  256. IRDA_DEBUG(2, __FUNCTION__ "()n");
  257. ASSERT(task != NULL, return -1;);
  258. if (self->reset_task && self->reset_task != task) {
  259. IRDA_DEBUG(0, __FUNCTION__ "(), busy!n");
  260. return MSECS_TO_JIFFIES(10);
  261. } else
  262. self->reset_task = task;
  263. switch (task->state) {
  264. case IRDA_TASK_INIT:
  265. /* Clear DTR and Set RTS */
  266. self->set_dtr_rts(self->dev, FALSE, TRUE);
  267. irda_task_next_state(task, IRDA_TASK_WAIT1);
  268. ret = MSECS_TO_JIFFIES(10); /* Sleep 10 ms */
  269. break;
  270. case IRDA_TASK_WAIT1:
  271. /* Set DTR and RTS */
  272. self->set_dtr_rts(self->dev, TRUE, TRUE);
  273. irda_task_next_state(task, IRDA_TASK_WAIT2);
  274. ret = MSECS_TO_JIFFIES(10); /* Sleep 10 ms */
  275. break;
  276. case IRDA_TASK_WAIT2:
  277. irda_task_next_state(task, IRDA_TASK_DONE);
  278. self->reset_task = NULL;
  279. break;
  280. default:
  281. ERROR(__FUNCTION__ "(), unknown state %dn", task->state);
  282. irda_task_next_state(task, IRDA_TASK_DONE);
  283. self->reset_task = NULL;
  284. ret = -1;
  285. }
  286. return ret;
  287. }
  288. MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95");
  289. MODULE_DESCRIPTION("MA600 dongle driver version 0.1");
  290. MODULE_LICENSE("GPL");
  291. /*
  292.  * Function init_module (void)
  293.  *
  294.  *    Initialize MA600 module
  295.  *
  296.  */
  297. module_init(ma600_init);
  298. /*
  299.  * Function cleanup_module (void)
  300.  *
  301.  *    Cleanup MA600 module
  302.  *
  303.  */
  304. module_exit(ma600_cleanup);