ma600.c 8.8 KB

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