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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*********************************************************************
  2.  *            
  3.  *    
  4.  * Filename:      mcp2120.c
  5.  * Version:       1.0
  6.  * Description:   Implementation for the MCP2120 (Microchip)
  7.  * Status:        Experimental.
  8.  * Author:        Felix Tang (tangf@eyetap.org)
  9.  * Created at:    Sun Mar 31 19:32:12 EST 2002
  10.  * Based on code by:   Dag Brattli <dagb@cs.uit.no>
  11.  * 
  12.  *     Copyright (c) 2002 Felix Tang, All Rights Reserved.
  13.  *      
  14.  *     This program is free software; you can redistribute it and/or 
  15.  *     modify it under the terms of the GNU General Public License as 
  16.  *     published by the Free Software Foundation; either version 2 of 
  17.  *     the License, or (at your option) any later version.
  18.  *  
  19.  ********************************************************************/
  20. #include <linux/module.h>
  21. #include <linux/delay.h>
  22. #include <linux/tty.h>
  23. #include <linux/sched.h>
  24. #include <linux/init.h>
  25. #include <net/irda/irda.h>
  26. #include <net/irda/irmod.h>
  27. #include <net/irda/irda_device.h>
  28. #include <net/irda/irtty.h>
  29. static int  mcp2120_reset(struct irda_task *task);
  30. static void mcp2120_open(dongle_t *self, struct qos_info *qos);
  31. static void mcp2120_close(dongle_t *self);
  32. static int  mcp2120_change_speed(struct irda_task *task);
  33. #define MCP2120_9600    0x87
  34. #define MCP2120_19200   0x8B
  35. #define MCP2120_38400   0x85
  36. #define MCP2120_57600   0x83
  37. #define MCP2120_115200  0x81
  38. #define MCP2120_COMMIT  0x11
  39. static struct dongle_reg dongle = {
  40. Q_NULL,
  41. IRDA_MCP2120_DONGLE,
  42. mcp2120_open,
  43. mcp2120_close,
  44. mcp2120_reset,
  45. mcp2120_change_speed,
  46. };
  47. int __init mcp2120_init(void)
  48. {
  49. return irda_device_register_dongle(&dongle);
  50. }
  51. void mcp2120_cleanup(void)
  52. {
  53. irda_device_unregister_dongle(&dongle);
  54. }
  55. static void mcp2120_open(dongle_t *self, struct qos_info *qos)
  56. {
  57. qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
  58. qos->min_turn_time.bits = 0x01;
  59. MOD_INC_USE_COUNT;
  60. }
  61. static void mcp2120_close(dongle_t *self)
  62. {
  63. /* Power off dongle */
  64.         /* reset and inhibit mcp2120 */
  65. self->set_dtr_rts(self->dev, TRUE, TRUE);
  66. //self->set_dtr_rts(self->dev, FALSE, FALSE);
  67. MOD_DEC_USE_COUNT;
  68. }
  69. /*
  70.  * Function mcp2120_change_speed (dev, speed)
  71.  *
  72.  *    Set the speed for the MCP2120.
  73.  *
  74.  */
  75. static int mcp2120_change_speed(struct irda_task *task)
  76. {
  77. dongle_t *self = (dongle_t *) task->instance;
  78. __u32 speed = (__u32) task->param;
  79. __u8 control[2];
  80. int ret = 0;
  81. self->speed_task = task;
  82. switch (task->state) {
  83. case IRDA_TASK_INIT:
  84. /* Need to reset the dongle and go to 9600 bps before
  85.                    programming */
  86.                 //printk("Dmcp2120_change_speed irda_task_initn");
  87. if (irda_task_execute(self, mcp2120_reset, NULL, task, 
  88.       (void *) speed))
  89. {
  90. /* Dongle need more time to reset */
  91. irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
  92. /* Give reset 1 sec to finish */
  93. ret = MSECS_TO_JIFFIES(1000);
  94. }
  95. break;
  96. case IRDA_TASK_CHILD_WAIT:
  97. WARNING(__FUNCTION__ "(), resetting dongle timed out!n");
  98. ret = -1;
  99. break;
  100. case IRDA_TASK_CHILD_DONE:
  101. /* Set DTR to enter command mode */
  102. self->set_dtr_rts(self->dev, TRUE, FALSE);
  103.                 udelay(500);
  104. switch (speed) {
  105. case 9600:
  106. default:
  107. control[0] = MCP2120_9600;
  108.                         //printk("mcp2120 9600n");
  109. break;
  110. case 19200:
  111. control[0] = MCP2120_19200;
  112.                         //printk("mcp2120 19200n");
  113. break;
  114. case 34800:
  115. control[0] = MCP2120_38400;
  116.                         //printk("mcp2120 38400n");
  117. break;
  118. case 57600:
  119. control[0] = MCP2120_57600;
  120.                         //printk("mcp2120 57600n");
  121. break;
  122. case 115200:
  123.                         control[0] = MCP2120_115200;
  124.                         //printk("mcp2120 115200n");
  125. break;
  126. }
  127.         control[1] = MCP2120_COMMIT;
  128. /* Write control bytes */
  129.                 self->write(self->dev, control, 2);
  130.  
  131.                 irda_task_next_state(task, IRDA_TASK_WAIT);
  132. ret = MSECS_TO_JIFFIES(100);
  133.                 //printk("mcp2120_change_speed irda_child_donen");
  134. break;
  135. case IRDA_TASK_WAIT:
  136. /* Go back to normal mode */
  137. self->set_dtr_rts(self->dev, FALSE, FALSE);
  138. irda_task_next_state(task, IRDA_TASK_DONE);
  139. self->speed_task = NULL;
  140.                 //printk("mcp2120_change_speed irda_task_waitn");
  141. break;
  142. default:
  143. ERROR(__FUNCTION__ "(), unknown state %dn", task->state);
  144. irda_task_next_state(task, IRDA_TASK_DONE);
  145. self->speed_task = NULL;
  146. ret = -1;
  147. break;
  148. }
  149. return ret;
  150. }
  151. /*
  152.  * Function mcp2120_reset (driver)
  153.  *
  154.  *      This function resets the mcp2120 dongle.
  155.  *      
  156.  *      Info: -set RTS to reset mcp2120
  157.  *            -set DTR to set mcp2120 software command mode
  158.  *            -mcp2120 defaults to 9600 baud after reset
  159.  *
  160.  *      Algorithm:
  161.  *      0. Set RTS to reset mcp2120.
  162.  *      1. Clear RTS and wait for device reset timer of 30 ms (max).
  163.  *      
  164.  */
  165. static int mcp2120_reset(struct irda_task *task)
  166. {
  167. dongle_t *self = (dongle_t *) task->instance;
  168. int ret = 0;
  169. self->reset_task = task;
  170. switch (task->state) {
  171. case IRDA_TASK_INIT:
  172.                 //printk("mcp2120_reset irda_task_initn");
  173. /* Reset dongle by setting RTS*/
  174. self->set_dtr_rts(self->dev, TRUE, TRUE);
  175. irda_task_next_state(task, IRDA_TASK_WAIT1);
  176. ret = MSECS_TO_JIFFIES(50);
  177. break;
  178. case IRDA_TASK_WAIT1:
  179.                 //printk("mcp2120_reset irda_task_wait1n");
  180.                 /* clear RTS and wait for at least 30 ms. */
  181. self->set_dtr_rts(self->dev, FALSE, FALSE);
  182. irda_task_next_state(task, IRDA_TASK_WAIT2);
  183. ret = MSECS_TO_JIFFIES(50);
  184. break;
  185. case IRDA_TASK_WAIT2:
  186.                 //printk("mcp2120_reset irda_task_wait2n");
  187. /* Go back to normal mode */
  188. self->set_dtr_rts(self->dev, FALSE, FALSE);
  189. irda_task_next_state(task, IRDA_TASK_DONE);
  190. self->reset_task = NULL;
  191. break;
  192. default:
  193. ERROR(__FUNCTION__ "(), unknown state %dn", task->state);
  194. irda_task_next_state(task, IRDA_TASK_DONE);
  195. self->reset_task = NULL;
  196. ret = -1;
  197. break;
  198. }
  199. return ret;
  200. }
  201. #ifdef MODULE
  202. MODULE_AUTHOR("Felix Tang <tangf@eyetap.org>");
  203. MODULE_DESCRIPTION("Microchip MCP2120");
  204. MODULE_LICENSE("GPL");
  205. /*
  206.  * Function init_module (void)
  207.  *
  208.  *    Initialize MCP2120 module
  209.  *
  210.  */
  211. int init_module(void)
  212. {
  213. return mcp2120_init();
  214. }
  215. /*
  216.  * Function cleanup_module (void)
  217.  *
  218.  *    Cleanup MCP2120 module
  219.  *
  220.  */
  221. void cleanup_module(void)
  222. {
  223.         mcp2120_cleanup();
  224. }
  225. #endif /* MODULE */