OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [joystick/] [serport.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * $Id: serport.c,v 1.1.1.1 2004-04-15 02:03:25 phoenix Exp $
3
 *
4
 *  Copyright (c) 1999-2001 Vojtech Pavlik
5
 *
6
 *  Sponsored by SuSE
7
 */
8
 
9
/*
10
 * This is a module that converts a tty line into a much simpler
11
 * 'serial io port' abstraction that the input device drivers use.
12
 */
13
 
14
/*
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
 *
29
 *  Should you need to contact me, the author, you can do so either by
30
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31
 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
32
 */
33
 
34
#include <asm/uaccess.h>
35
#include <linux/kernel.h>
36
#include <linux/slab.h>
37
#include <linux/module.h>
38
#include <linux/init.h>
39
#include <linux/serio.h>
40
#include <linux/tty.h>
41
 
42
struct serport {
43
        struct tty_struct *tty;
44
        wait_queue_head_t wait;
45
        struct serio serio;
46
};
47
 
48
/*
49
 * Callback functions from the serio code.
50
 */
51
 
52
static int serport_serio_write(struct serio *serio, unsigned char data)
53
{
54
        struct serport *serport = serio->driver;
55
        return -(serport->tty->driver.write(serport->tty, 0, &data, 1) != 1);
56
}
57
 
58
static int serport_serio_open(struct serio *serio)
59
{
60
        return 0;
61
}
62
 
63
static void serport_serio_close(struct serio *serio)
64
{
65
        struct serport *serport = serio->driver;
66
        wake_up_interruptible(&serport->wait);
67
}
68
 
69
/*
70
 * serport_ldisc_open() is the routine that is called upon setting our line
71
 * discipline on a tty. It looks for the Mag, and if found, registers
72
 * it as a joystick device.
73
 */
74
 
75
static int serport_ldisc_open(struct tty_struct *tty)
76
{
77
        struct serport *serport;
78
 
79
        MOD_INC_USE_COUNT;
80
 
81
        if (!(serport = kmalloc(sizeof(struct serport), GFP_KERNEL))) {
82
                MOD_DEC_USE_COUNT;
83
                return -ENOMEM;
84
        }
85
 
86
        memset(serport, 0, sizeof(struct serport));
87
 
88
        serport->tty = tty;
89
        tty->disc_data = serport;
90
 
91
        serport->serio.type = SERIO_RS232;
92
        serport->serio.write = serport_serio_write;
93
        serport->serio.open = serport_serio_open;
94
        serport->serio.close = serport_serio_close;
95
        serport->serio.driver = serport;
96
 
97
        init_waitqueue_head(&serport->wait);
98
 
99
        return 0;
100
}
101
 
102
/*
103
 * serport_ldisc_close() is the opposite of serport_ldisc_open()
104
 */
105
 
106
static void serport_ldisc_close(struct tty_struct *tty)
107
{
108
        struct serport *serport = (struct serport*) tty->disc_data;
109
        kfree(serport);
110
        MOD_DEC_USE_COUNT;
111
}
112
 
113
/*
114
 * serport_ldisc_receive() is called by the low level tty driver when characters
115
 * are ready for us. We forward the characters, one by one to the 'interrupt'
116
 * routine.
117
 */
118
 
119
static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
120
{
121
        struct serport *serport = (struct serport*) tty->disc_data;
122
        int i;
123
        for (i = 0; i < count; i++)
124
                if (serport->serio.dev)
125
                        serport->serio.dev->interrupt(&serport->serio, cp[i], 0);
126
}
127
 
128
/*
129
 * serport_ldisc_room() reports how much room we do have for receiving data.
130
 * Although we in fact have infinite room, we need to specify some value
131
 * here, and 256 seems to be reasonable.
132
 */
133
 
134
static int serport_ldisc_room(struct tty_struct *tty)
135
{
136
        return 256;
137
}
138
 
139
/*
140
 * serport_ldisc_read() just waits indefinitely if everything goes well.
141
 * However, when the serio driver closes the serio port, it finishes,
142
 * returning 0 characters.
143
 */
144
 
145
static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char * buf, size_t nr)
146
{
147
        struct serport *serport = (struct serport*) tty->disc_data;
148
        DECLARE_WAITQUEUE(wait, current);
149
        char name[32];
150
 
151
#ifdef CONFIG_DEVFS_FS
152
        sprintf(name, tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
153
#else
154
        sprintf(name, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
155
#endif
156
 
157
        serio_register_port(&serport->serio);
158
 
159
        printk(KERN_INFO "serio%d: Serial port %s\n", serport->serio.number, name);
160
 
161
        add_wait_queue(&serport->wait, &wait);
162
        current->state = TASK_INTERRUPTIBLE;
163
 
164
        while(serport->serio.type && !signal_pending(current)) schedule();
165
 
166
        current->state = TASK_RUNNING;
167
        remove_wait_queue(&serport->wait, &wait);
168
 
169
        serio_unregister_port(&serport->serio);
170
 
171
        return 0;
172
}
173
 
174
/*
175
 * serport_ldisc_ioctl() allows to set the port protocol, and device ID
176
 */
177
 
178
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
179
{
180
        struct serport *serport = (struct serport*) tty->disc_data;
181
 
182
        switch (cmd) {
183
                case SPIOCSTYPE:
184
                        return get_user(serport->serio.type, (unsigned long *) arg);
185
        }
186
 
187
        return -EINVAL;
188
}
189
 
190
/*
191
 * The line discipline structure.
192
 */
193
 
194
static struct tty_ldisc serport_ldisc = {
195
        name:           "input",
196
        open:           serport_ldisc_open,
197
        close:          serport_ldisc_close,
198
        read:           serport_ldisc_read,
199
        ioctl:          serport_ldisc_ioctl,
200
        receive_buf:    serport_ldisc_receive,
201
        receive_room:   serport_ldisc_room,
202
};
203
 
204
/*
205
 * The functions for insering/removing us as a module.
206
 */
207
 
208
int __init serport_init(void)
209
{
210
        if (tty_register_ldisc(N_MOUSE, &serport_ldisc)) {
211
                printk(KERN_ERR "serport.c: Error registering line discipline.\n");
212
                return -ENODEV;
213
        }
214
 
215
        return  0;
216
}
217
 
218
void __exit serport_exit(void)
219
{
220
        tty_register_ldisc(N_MOUSE, NULL);
221
}
222
 
223
module_init(serport_init);
224
module_exit(serport_exit);
225
 
226
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.