Linux Audio

Check our new training course

Loading...
v3.1
  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
 21#include <linux/module.h>
 22#include <linux/delay.h>
 23#include <linux/init.h>
 24
 25#include <net/irda/irda.h>
 26
 27#include "sir-dev.h"
 28
 29static int mcp2120_reset(struct sir_dev *dev);
 30static int mcp2120_open(struct sir_dev *dev);
 31static int mcp2120_close(struct sir_dev *dev);
 32static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed);
 33
 34#define MCP2120_9600    0x87
 35#define MCP2120_19200   0x8B
 36#define MCP2120_38400   0x85
 37#define MCP2120_57600   0x83
 38#define MCP2120_115200  0x81
 39
 40#define MCP2120_COMMIT  0x11
 41
 42static struct dongle_driver mcp2120 = {
 43	.owner		= THIS_MODULE,
 44	.driver_name	= "Microchip MCP2120",
 45	.type		= IRDA_MCP2120_DONGLE,
 46	.open		= mcp2120_open,
 47	.close		= mcp2120_close,
 48	.reset		= mcp2120_reset,
 49	.set_speed	= mcp2120_change_speed,
 50};
 51
 52static int __init mcp2120_sir_init(void)
 53{
 54	return irda_register_dongle(&mcp2120);
 55}
 56
 57static void __exit mcp2120_sir_cleanup(void)
 58{
 59	irda_unregister_dongle(&mcp2120);
 60}
 61
 62static int mcp2120_open(struct sir_dev *dev)
 63{
 64	struct qos_info *qos = &dev->qos;
 65
 66	IRDA_DEBUG(2, "%s()\n", __func__);
 67
 68	/* seems no explicit power-on required here and reset switching it on anyway */
 69
 70	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 71	qos->min_turn_time.bits = 0x01;
 72	irda_qos_bits_to_value(qos);
 73
 74	return 0;
 75}
 76
 77static int mcp2120_close(struct sir_dev *dev)
 78{
 79	IRDA_DEBUG(2, "%s()\n", __func__);
 80
 81	/* Power off dongle */
 82        /* reset and inhibit mcp2120 */
 83	sirdev_set_dtr_rts(dev, TRUE, TRUE);
 84	// sirdev_set_dtr_rts(dev, FALSE, FALSE);
 85
 86	return 0;
 87}
 88
 89/*
 90 * Function mcp2120_change_speed (dev, speed)
 91 *
 92 *    Set the speed for the MCP2120.
 93 *
 94 */
 95
 96#define MCP2120_STATE_WAIT_SPEED	(SIRDEV_STATE_DONGLE_SPEED+1)
 97
 98static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed)
 99{
100	unsigned state = dev->fsm.substate;
101	unsigned delay = 0;
102	u8 control[2];
103	static int ret = 0;
104
105	IRDA_DEBUG(2, "%s()\n", __func__);
106
107	switch (state) {
108	case SIRDEV_STATE_DONGLE_SPEED:
109		/* Set DTR to enter command mode */
110		sirdev_set_dtr_rts(dev, TRUE, FALSE);
111                udelay(500);
112
113		ret = 0;
114		switch (speed) {
115		default:
116			speed = 9600;
117			ret = -EINVAL;
118			/* fall through */
119		case 9600:
120			control[0] = MCP2120_9600;
121                        //printk("mcp2120 9600\n");
122			break;
123		case 19200:
124			control[0] = MCP2120_19200;
125                        //printk("mcp2120 19200\n");
126			break;
127		case 34800:
128			control[0] = MCP2120_38400;
129                        //printk("mcp2120 38400\n");
130			break;
131		case 57600:
132			control[0] = MCP2120_57600;
133                        //printk("mcp2120 57600\n");
134			break;
135		case 115200:
136                        control[0] = MCP2120_115200;
137                        //printk("mcp2120 115200\n");
138			break;
139		}
140		control[1] = MCP2120_COMMIT;
141	
142		/* Write control bytes */
143		sirdev_raw_write(dev, control, 2);
144		dev->speed = speed;
145
146		state = MCP2120_STATE_WAIT_SPEED;
147		delay = 100;
148                //printk("mcp2120_change_speed: dongle_speed\n");
149		break;
150
151	case MCP2120_STATE_WAIT_SPEED:
152		/* Go back to normal mode */
153		sirdev_set_dtr_rts(dev, FALSE, FALSE);
154                //printk("mcp2120_change_speed: mcp_wait\n");
155		break;
156
157	default:
158		IRDA_ERROR("%s(), undefine state %d\n", __func__, state);
 
159		ret = -EINVAL;
160		break;
161	}
162	dev->fsm.substate = state;
163	return (delay > 0) ? delay : ret;
164}
165
166/*
167 * Function mcp2120_reset (driver)
168 *
169 *      This function resets the mcp2120 dongle.
170 *      
171 *      Info: -set RTS to reset mcp2120
172 *            -set DTR to set mcp2120 software command mode
173 *            -mcp2120 defaults to 9600 baud after reset
174 *
175 *      Algorithm:
176 *      0. Set RTS to reset mcp2120.
177 *      1. Clear RTS and wait for device reset timer of 30 ms (max).
178 *      
179 */
180
181#define MCP2120_STATE_WAIT1_RESET	(SIRDEV_STATE_DONGLE_RESET+1)
182#define MCP2120_STATE_WAIT2_RESET	(SIRDEV_STATE_DONGLE_RESET+2)
183
184static int mcp2120_reset(struct sir_dev *dev)
185{
186	unsigned state = dev->fsm.substate;
187	unsigned delay = 0;
188	int ret = 0;
189
190	IRDA_DEBUG(2, "%s()\n", __func__);
191
192	switch (state) {
193	case SIRDEV_STATE_DONGLE_RESET:
194                //printk("mcp2120_reset: dongle_reset\n");
195		/* Reset dongle by setting RTS*/
196		sirdev_set_dtr_rts(dev, TRUE, TRUE);
197		state = MCP2120_STATE_WAIT1_RESET;
198		delay = 50;
199		break;
200
201	case MCP2120_STATE_WAIT1_RESET:
202                //printk("mcp2120_reset: mcp2120_wait1\n");
203                /* clear RTS and wait for at least 30 ms. */
204		sirdev_set_dtr_rts(dev, FALSE, FALSE);
205		state = MCP2120_STATE_WAIT2_RESET;
206		delay = 50;
207		break;
208
209	case MCP2120_STATE_WAIT2_RESET:
210                //printk("mcp2120_reset mcp2120_wait2\n");
211		/* Go back to normal mode */
212		sirdev_set_dtr_rts(dev, FALSE, FALSE);
213		break;
214
215	default:
216		IRDA_ERROR("%s(), undefined state %d\n", __func__, state);
 
217		ret = -EINVAL;
218		break;
219	}
220	dev->fsm.substate = state;
221	return (delay > 0) ? delay : ret;
222}
223
224MODULE_AUTHOR("Felix Tang <tangf@eyetap.org>");
225MODULE_DESCRIPTION("Microchip MCP2120");
226MODULE_LICENSE("GPL");
227MODULE_ALIAS("irda-dongle-9"); /* IRDA_MCP2120_DONGLE */
228
229module_init(mcp2120_sir_init);
230module_exit(mcp2120_sir_cleanup);
v4.6
  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
 21#include <linux/module.h>
 22#include <linux/delay.h>
 23#include <linux/init.h>
 24
 25#include <net/irda/irda.h>
 26
 27#include "sir-dev.h"
 28
 29static int mcp2120_reset(struct sir_dev *dev);
 30static int mcp2120_open(struct sir_dev *dev);
 31static int mcp2120_close(struct sir_dev *dev);
 32static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed);
 33
 34#define MCP2120_9600    0x87
 35#define MCP2120_19200   0x8B
 36#define MCP2120_38400   0x85
 37#define MCP2120_57600   0x83
 38#define MCP2120_115200  0x81
 39
 40#define MCP2120_COMMIT  0x11
 41
 42static struct dongle_driver mcp2120 = {
 43	.owner		= THIS_MODULE,
 44	.driver_name	= "Microchip MCP2120",
 45	.type		= IRDA_MCP2120_DONGLE,
 46	.open		= mcp2120_open,
 47	.close		= mcp2120_close,
 48	.reset		= mcp2120_reset,
 49	.set_speed	= mcp2120_change_speed,
 50};
 51
 52static int __init mcp2120_sir_init(void)
 53{
 54	return irda_register_dongle(&mcp2120);
 55}
 56
 57static void __exit mcp2120_sir_cleanup(void)
 58{
 59	irda_unregister_dongle(&mcp2120);
 60}
 61
 62static int mcp2120_open(struct sir_dev *dev)
 63{
 64	struct qos_info *qos = &dev->qos;
 65
 
 
 66	/* seems no explicit power-on required here and reset switching it on anyway */
 67
 68	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 69	qos->min_turn_time.bits = 0x01;
 70	irda_qos_bits_to_value(qos);
 71
 72	return 0;
 73}
 74
 75static int mcp2120_close(struct sir_dev *dev)
 76{
 
 
 77	/* Power off dongle */
 78        /* reset and inhibit mcp2120 */
 79	sirdev_set_dtr_rts(dev, TRUE, TRUE);
 80	// sirdev_set_dtr_rts(dev, FALSE, FALSE);
 81
 82	return 0;
 83}
 84
 85/*
 86 * Function mcp2120_change_speed (dev, speed)
 87 *
 88 *    Set the speed for the MCP2120.
 89 *
 90 */
 91
 92#define MCP2120_STATE_WAIT_SPEED	(SIRDEV_STATE_DONGLE_SPEED+1)
 93
 94static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed)
 95{
 96	unsigned state = dev->fsm.substate;
 97	unsigned delay = 0;
 98	u8 control[2];
 99	static int ret = 0;
100
 
 
101	switch (state) {
102	case SIRDEV_STATE_DONGLE_SPEED:
103		/* Set DTR to enter command mode */
104		sirdev_set_dtr_rts(dev, TRUE, FALSE);
105                udelay(500);
106
107		ret = 0;
108		switch (speed) {
109		default:
110			speed = 9600;
111			ret = -EINVAL;
112			/* fall through */
113		case 9600:
114			control[0] = MCP2120_9600;
115                        //printk("mcp2120 9600\n");
116			break;
117		case 19200:
118			control[0] = MCP2120_19200;
119                        //printk("mcp2120 19200\n");
120			break;
121		case 34800:
122			control[0] = MCP2120_38400;
123                        //printk("mcp2120 38400\n");
124			break;
125		case 57600:
126			control[0] = MCP2120_57600;
127                        //printk("mcp2120 57600\n");
128			break;
129		case 115200:
130                        control[0] = MCP2120_115200;
131                        //printk("mcp2120 115200\n");
132			break;
133		}
134		control[1] = MCP2120_COMMIT;
135	
136		/* Write control bytes */
137		sirdev_raw_write(dev, control, 2);
138		dev->speed = speed;
139
140		state = MCP2120_STATE_WAIT_SPEED;
141		delay = 100;
142                //printk("mcp2120_change_speed: dongle_speed\n");
143		break;
144
145	case MCP2120_STATE_WAIT_SPEED:
146		/* Go back to normal mode */
147		sirdev_set_dtr_rts(dev, FALSE, FALSE);
148                //printk("mcp2120_change_speed: mcp_wait\n");
149		break;
150
151	default:
152		net_err_ratelimited("%s(), undefine state %d\n",
153				    __func__, state);
154		ret = -EINVAL;
155		break;
156	}
157	dev->fsm.substate = state;
158	return (delay > 0) ? delay : ret;
159}
160
161/*
162 * Function mcp2120_reset (driver)
163 *
164 *      This function resets the mcp2120 dongle.
165 *      
166 *      Info: -set RTS to reset mcp2120
167 *            -set DTR to set mcp2120 software command mode
168 *            -mcp2120 defaults to 9600 baud after reset
169 *
170 *      Algorithm:
171 *      0. Set RTS to reset mcp2120.
172 *      1. Clear RTS and wait for device reset timer of 30 ms (max).
173 *      
174 */
175
176#define MCP2120_STATE_WAIT1_RESET	(SIRDEV_STATE_DONGLE_RESET+1)
177#define MCP2120_STATE_WAIT2_RESET	(SIRDEV_STATE_DONGLE_RESET+2)
178
179static int mcp2120_reset(struct sir_dev *dev)
180{
181	unsigned state = dev->fsm.substate;
182	unsigned delay = 0;
183	int ret = 0;
184
 
 
185	switch (state) {
186	case SIRDEV_STATE_DONGLE_RESET:
187                //printk("mcp2120_reset: dongle_reset\n");
188		/* Reset dongle by setting RTS*/
189		sirdev_set_dtr_rts(dev, TRUE, TRUE);
190		state = MCP2120_STATE_WAIT1_RESET;
191		delay = 50;
192		break;
193
194	case MCP2120_STATE_WAIT1_RESET:
195                //printk("mcp2120_reset: mcp2120_wait1\n");
196                /* clear RTS and wait for at least 30 ms. */
197		sirdev_set_dtr_rts(dev, FALSE, FALSE);
198		state = MCP2120_STATE_WAIT2_RESET;
199		delay = 50;
200		break;
201
202	case MCP2120_STATE_WAIT2_RESET:
203                //printk("mcp2120_reset mcp2120_wait2\n");
204		/* Go back to normal mode */
205		sirdev_set_dtr_rts(dev, FALSE, FALSE);
206		break;
207
208	default:
209		net_err_ratelimited("%s(), undefined state %d\n",
210				    __func__, state);
211		ret = -EINVAL;
212		break;
213	}
214	dev->fsm.substate = state;
215	return (delay > 0) ? delay : ret;
216}
217
218MODULE_AUTHOR("Felix Tang <tangf@eyetap.org>");
219MODULE_DESCRIPTION("Microchip MCP2120");
220MODULE_LICENSE("GPL");
221MODULE_ALIAS("irda-dongle-9"); /* IRDA_MCP2120_DONGLE */
222
223module_init(mcp2120_sir_init);
224module_exit(mcp2120_sir_cleanup);