1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * TCP Console Driver File: dev_tcpconsole.c
6 * Evil hack: A console driver that uses a TCP socket.
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
48 #include "lib_types.h"
49 #include "lib_malloc.h"
50 #include "lib_printf.h"
52 #include "cfe_device.h"
53 #include "cfe_ioctl.h"
54 #include "addrspace.h"
56 #include "cfe_timer.h"
58 #include "bsp_config.h"
65 * Friendly warning: Don't put printfs in here or enable any
66 * debugging messages in the TCP stack if you're really
67 * going to use this for your console device. You'll end up
68 * with a recursion loop!
71 /* *********************************************************************
73 ********************************************************************* */
75 #define TCPCONSOLE_DEFAULT_PORT 23 /* telnet */
77 /* *********************************************************************
79 ********************************************************************* */
81 static void tcpconsole_probe(cfe_driver_t
*drv
,
82 unsigned long probe_a
, unsigned long probe_b
,
85 static int tcpconsole_open(cfe_devctx_t
*ctx
);
86 static int tcpconsole_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
87 static int tcpconsole_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
);
88 static int tcpconsole_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
89 static int tcpconsole_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
90 static int tcpconsole_close(cfe_devctx_t
*ctx
);
92 const static cfe_devdisp_t tcpconsole_dispatch
= {
103 const cfe_driver_t tcpconsole
= {
107 &tcpconsole_dispatch
,
112 /* *********************************************************************
113 * tcpconsole structure
114 ********************************************************************* */
117 * States our connection can be in
120 #define TCPCONSTAT_IDLE 0
121 #define TCPCONSTAT_LISTEN 1
122 #define TCPCONSTAT_CONNECTED 2
123 #define TCPCONSTAT_DISCONNECTED 3
124 #define TCPCONSTAT_BROKEN 4
130 typedef struct tcpconsole_s
{
137 static void tcpconsole_probe(cfe_driver_t
*drv
,
138 unsigned long probe_a
, unsigned long probe_b
,
144 softc
= (tcpconsole_t
*) KMALLOC(sizeof(tcpconsole_t
),0);
146 softc
->tcp_socket
= -1;
147 softc
->tcp_status
= TCPCONSTAT_IDLE
;
148 xsprintf(descr
, "%s", drv
->drv_description
);
150 if (probe_a
== 0) probe_a
= TCPCONSOLE_DEFAULT_PORT
;
152 softc
->tcp_port
= (int)probe_a
;
154 cfe_attach(drv
, softc
, NULL
, descr
);
159 static int tcpconsole_isready(tcpconsole_t
*softc
,int *rxbytes
)
164 res
= tcp_status(softc
->tcp_socket
,&connstat
,rxbytes
,&rxeof
);
168 * -1 if we could not get status
169 * 0 if we are not connected or are connected and at EOF
170 * 1 if we are connected.
173 if (res
< 0) return res
;
174 if (connstat
!= TCPSTATUS_CONNECTED
) return 0;
175 if (!rxeof
) return 1;
181 static int tcpconsole_process(tcpconsole_t
*softc
)
185 switch (softc
->tcp_status
) {
186 case TCPCONSTAT_IDLE
:
187 /* Idle, set up listening socket */
190 softc
->tcp_status
= TCPCONSTAT_BROKEN
;
193 softc
->tcp_socket
= res
;
195 res
= tcp_listen(softc
->tcp_socket
,softc
->tcp_port
);
198 tcp_close(softc
->tcp_socket
);
199 softc
->tcp_status
= TCPCONSTAT_BROKEN
;
200 softc
->tcp_socket
= -1;
203 softc
->tcp_status
= TCPCONSTAT_LISTEN
;
206 case TCPCONSTAT_LISTEN
:
207 /* Still waiting for a connection */
209 if (tcpconsole_isready(softc
,NULL
) > 0) {
210 softc
->tcp_status
= TCPCONSTAT_CONNECTED
;
214 case TCPCONSTAT_CONNECTED
:
215 res
= 0; /* do nothing, we're okay */
218 case TCPCONSTAT_DISCONNECTED
:
219 /* Currently connected, kill off this connection */
220 tcp_close(softc
->tcp_socket
);
221 softc
->tcp_socket
= -1;
222 softc
->tcp_status
= TCPCONSTAT_IDLE
;
225 case TCPCONSTAT_BROKEN
:
226 /* Broken. Stay broken. */
235 static int tcpconsole_open(cfe_devctx_t
*ctx
)
240 static int tcpconsole_read(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
242 tcpconsole_t
*softc
= ctx
->dev_softc
;
248 tcpconsole_process(softc
);
250 buffer
->buf_retlen
= 0;
252 if (softc
->tcp_status
== TCPCONSTAT_CONNECTED
) {
253 bptr
= buffer
->buf_ptr
;
254 blen
= buffer
->buf_length
;
256 if (tcpconsole_isready(softc
,NULL
) <= 0) {
257 softc
->tcp_status
= TCPCONSTAT_DISCONNECTED
;
261 res
= tcp_recv(softc
->tcp_socket
,bptr
,blen
);
264 buffer
->buf_retlen
= res
;
271 static int tcpconsole_inpstat(cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
)
273 tcpconsole_t
*softc
= ctx
->dev_softc
;
274 unsigned int rxbytes
;
277 tcpconsole_process(softc
);
279 inpstat
->inp_status
= 0;
281 if (softc
->tcp_status
== TCPCONSTAT_CONNECTED
) {
282 if (tcpconsole_isready(softc
,&rxbytes
) <= 0) {
283 softc
->tcp_status
= TCPCONSTAT_DISCONNECTED
;
286 inpstat
->inp_status
= (rxbytes
> 0);
293 static int tcpconsole_write(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
295 tcpconsole_t
*softc
= ctx
->dev_softc
;
301 tcpconsole_process(softc
);
303 buffer
->buf_retlen
= 0;
305 if (softc
->tcp_status
== TCPCONSTAT_CONNECTED
) {
306 bptr
= buffer
->buf_ptr
;
307 blen
= buffer
->buf_length
;
309 if (tcpconsole_isready(softc
,NULL
) <= 0) {
310 softc
->tcp_status
= TCPCONSTAT_DISCONNECTED
;
314 res
= tcp_send(softc
->tcp_socket
,bptr
,blen
);
317 buffer
->buf_retlen
= res
;
324 static int tcpconsole_ioctl(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
329 static int tcpconsole_close(cfe_devctx_t
*ctx
)
331 tcpconsole_t
*softc
= ctx
->dev_softc
;
333 if (softc
->tcp_status
== TCPCONSTAT_CONNECTED
) {
334 softc
->tcp_status
= TCPCONSTAT_DISCONNECTED
;