~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to drivers/tty/n_tracesink.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  n_tracesink.c - Trace data router and sink path through tty space.
 
3
 *
 
4
 *  Copyright (C) Intel 2011
 
5
 *
 
6
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License version 2
 
10
 *  as published by the Free Software Foundation.
 
11
 *
 
12
 *  This program is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
18
 *
 
19
 * The trace sink uses the Linux line discipline framework to receive
 
20
 * trace data coming from the PTI source line discipline driver
 
21
 * to a user-desired tty port, like USB.
 
22
 * This is to provide a way to extract modem trace data on
 
23
 * devices that do not have a PTI HW module, or just need modem
 
24
 * trace data to come out of a different HW output port.
 
25
 * This is part of a solution for the P1149.7, compact JTAG, standard.
 
26
 */
 
27
 
 
28
#include <linux/init.h>
 
29
#include <linux/kernel.h>
 
30
#include <linux/module.h>
 
31
#include <linux/types.h>
 
32
#include <linux/ioctl.h>
 
33
#include <linux/tty.h>
 
34
#include <linux/tty_ldisc.h>
 
35
#include <linux/errno.h>
 
36
#include <linux/string.h>
 
37
#include <asm-generic/bug.h>
 
38
#include "n_tracesink.h"
 
39
 
 
40
/*
 
41
 * Other ldisc drivers use 65536 which basically means,
 
42
 * 'I can always accept 64k' and flow control is off.
 
43
 * This number is deemed appropriate for this driver.
 
44
 */
 
45
#define RECEIVE_ROOM    65536
 
46
#define DRIVERNAME      "n_tracesink"
 
47
 
 
48
/*
 
49
 * there is a quirk with this ldisc is he can write data
 
50
 * to a tty from anyone calling his kernel API, which
 
51
 * meets customer requirements in the drivers/misc/pti.c
 
52
 * project.  So he needs to know when he can and cannot write when
 
53
 * the API is called. In theory, the API can be called
 
54
 * after an init() but before a successful open() which
 
55
 * would crash the system if tty is not checked.
 
56
 */
 
57
static struct tty_struct *this_tty;
 
58
static DEFINE_MUTEX(writelock);
 
59
 
 
60
/**
 
61
 * n_tracesink_open() - Called when a tty is opened by a SW entity.
 
62
 * @tty: terminal device to the ldisc.
 
63
 *
 
64
 * Return:
 
65
 *      0 for success,
 
66
 *      -EFAULT = couldn't get a tty kref n_tracesink will sit
 
67
 *       on top of
 
68
 *      -EEXIST = open() called successfully once and it cannot
 
69
 *      be called again.
 
70
 *
 
71
 * Caveats: open() should only be successful the first time a
 
72
 * SW entity calls it.
 
73
 */
 
74
static int n_tracesink_open(struct tty_struct *tty)
 
75
{
 
76
        int retval = -EEXIST;
 
77
 
 
78
        mutex_lock(&writelock);
 
79
        if (this_tty == NULL) {
 
80
                this_tty = tty_kref_get(tty);
 
81
                if (this_tty == NULL) {
 
82
                        retval = -EFAULT;
 
83
                } else {
 
84
                        tty->disc_data = this_tty;
 
85
                        tty_driver_flush_buffer(tty);
 
86
                        retval = 0;
 
87
                }
 
88
        }
 
89
        mutex_unlock(&writelock);
 
90
 
 
91
        return retval;
 
92
}
 
93
 
 
94
/**
 
95
 * n_tracesink_close() - close connection
 
96
 * @tty: terminal device to the ldisc.
 
97
 *
 
98
 * Called when a software entity wants to close a connection.
 
99
 */
 
100
static void n_tracesink_close(struct tty_struct *tty)
 
101
{
 
102
        mutex_lock(&writelock);
 
103
        tty_driver_flush_buffer(tty);
 
104
        tty_kref_put(this_tty);
 
105
        this_tty = NULL;
 
106
        tty->disc_data = NULL;
 
107
        mutex_unlock(&writelock);
 
108
}
 
109
 
 
110
/**
 
111
 * n_tracesink_read() - read request from user space
 
112
 * @tty:  terminal device passed into the ldisc.
 
113
 * @file: pointer to open file object.
 
114
 * @buf:  pointer to the data buffer that gets eventually returned.
 
115
 * @nr:   number of bytes of the data buffer that is returned.
 
116
 *
 
117
 * function that allows read() functionality in userspace. By default if this
 
118
 * is not implemented it returns -EIO. This module is functioning like a
 
119
 * router via n_tracesink_receivebuf(), and there is no real requirement
 
120
 * to implement this function. However, an error return value other than
 
121
 * -EIO should be used just to show that there was an intent not to have
 
122
 * this function implemented.  Return value based on read() man pages.
 
123
 *
 
124
 * Return:
 
125
 *       -EINVAL
 
126
 */
 
127
static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file,
 
128
                                unsigned char __user *buf, size_t nr) {
 
129
        return -EINVAL;
 
130
}
 
131
 
 
132
/**
 
133
 * n_tracesink_write() - Function that allows write() in userspace.
 
134
 * @tty:  terminal device passed into the ldisc.
 
135
 * @file: pointer to open file object.
 
136
 * @buf:  pointer to the data buffer that gets eventually returned.
 
137
 * @nr:   number of bytes of the data buffer that is returned.
 
138
 *
 
139
 * By default if this is not implemented, it returns -EIO.
 
140
 * This should not be implemented, ever, because
 
141
 * 1. this driver is functioning like a router via
 
142
 *    n_tracesink_receivebuf()
 
143
 * 2. No writes to HW will ever go through this line discpline driver.
 
144
 * However, an error return value other than -EIO should be used
 
145
 * just to show that there was an intent not to have this function
 
146
 * implemented.  Return value based on write() man pages.
 
147
 *
 
148
 * Return:
 
149
 *      -EINVAL
 
150
 */
 
151
static ssize_t n_tracesink_write(struct tty_struct *tty, struct file *file,
 
152
                                 const unsigned char *buf, size_t nr) {
 
153
        return -EINVAL;
 
154
}
 
155
 
 
156
/**
 
157
 * n_tracesink_datadrain() - Kernel API function used to route
 
158
 *                           trace debugging data to user-defined
 
159
 *                           port like USB.
 
160
 *
 
161
 * @buf:   Trace debuging data buffer to write to tty target
 
162
 *         port. Null value will return with no write occurring.
 
163
 * @count: Size of buf. Value of 0 or a negative number will
 
164
 *         return with no write occuring.
 
165
 *
 
166
 * Caveat: If this line discipline does not set the tty it sits
 
167
 * on top of via an open() call, this API function will not
 
168
 * call the tty's write() call because it will have no pointer
 
169
 * to call the write().
 
170
 */
 
171
void n_tracesink_datadrain(u8 *buf, int count)
 
172
{
 
173
        mutex_lock(&writelock);
 
174
 
 
175
        if ((buf != NULL) && (count > 0) && (this_tty != NULL))
 
176
                this_tty->ops->write(this_tty, buf, count);
 
177
 
 
178
        mutex_unlock(&writelock);
 
179
}
 
180
EXPORT_SYMBOL_GPL(n_tracesink_datadrain);
 
181
 
 
182
/*
 
183
 * Flush buffer is not impelemented as the ldisc has no internal buffering
 
184
 * so the tty_driver_flush_buffer() is sufficient for this driver's needs.
 
185
 */
 
186
 
 
187
/*
 
188
 * tty_ldisc function operations for this driver.
 
189
 */
 
190
static struct tty_ldisc_ops tty_n_tracesink = {
 
191
        .owner          = THIS_MODULE,
 
192
        .magic          = TTY_LDISC_MAGIC,
 
193
        .name           = DRIVERNAME,
 
194
        .open           = n_tracesink_open,
 
195
        .close          = n_tracesink_close,
 
196
        .read           = n_tracesink_read,
 
197
        .write          = n_tracesink_write
 
198
};
 
199
 
 
200
/**
 
201
 * n_tracesink_init-    module initialisation
 
202
 *
 
203
 * Registers this module as a line discipline driver.
 
204
 *
 
205
 * Return:
 
206
 *      0 for success, any other value error.
 
207
 */
 
208
static int __init n_tracesink_init(void)
 
209
{
 
210
        /* Note N_TRACESINK is defined in linux/tty.h */
 
211
        int retval = tty_register_ldisc(N_TRACESINK, &tty_n_tracesink);
 
212
 
 
213
        if (retval < 0)
 
214
                pr_err("%s: Registration failed: %d\n", __func__, retval);
 
215
 
 
216
        return retval;
 
217
}
 
218
 
 
219
/**
 
220
 * n_tracesink_exit -   module unload
 
221
 *
 
222
 * Removes this module as a line discipline driver.
 
223
 */
 
224
static void __exit n_tracesink_exit(void)
 
225
{
 
226
        int retval = tty_unregister_ldisc(N_TRACESINK);
 
227
 
 
228
        if (retval < 0)
 
229
                pr_err("%s: Unregistration failed: %d\n", __func__,  retval);
 
230
}
 
231
 
 
232
module_init(n_tracesink_init);
 
233
module_exit(n_tracesink_exit);
 
234
 
 
235
MODULE_LICENSE("GPL");
 
236
MODULE_AUTHOR("Jay Freyensee");
 
237
MODULE_ALIAS_LDISC(N_TRACESINK);
 
238
MODULE_DESCRIPTION("Trace sink ldisc driver");