1 /*
2  * Copyright 2016 Google Inc. All Rights Reserved.
3  * Author: gkalsi@google.com (Gurjant Kalsi)
4  *
5  * Use of this source code is governed by a MIT-style
6  * license that can be found in the LICENSE file or at
7  * https://opensource.org/licenses/MIT
8  *
9  *******************************************************************************
10  *
11  * This app serves as an example of how to use the high level bidirectional
12  * debugging pipe.
13  *
14  * The high level debugging protocol supports three operations:
15  *
16  *  + ndebugusr_await_host(timeout);
17  *  + ndebug_read_usr(buffer, timeout);
18  *  + ndebug_write_usr(buffer, bytes, timeout);
19  *
20  * The client must call ndebugusr_await_host prior to using the read/write api.
21  * When a transport is connected and a remote debugger becomes available, this
22  * method will return NO_ERROR. At this point, the client is welcome to use the
23  * read/write API.
24  *
25  * Any subsequent read/write operation may return ERR_CHANNEL_CLOSED. This is
26  * because we must be able to accommodate the possibility of the device becoming
27  * disconnected.
28  * If ERR_CHANNEL_CLOSED is received, the client MUST assume that the connection
29  * has closed and will not be recovered.
30  * The client MUST NOT issue any more read or write calls.
31  * The client MUST call ndebugusr_await_host and wait for the host to become
32  * active again at which point the client will be given a new connection to a
33  * new host.
34  *
35  * The following example app implements a simple echo server that demonstrates
36  * data being read then echoed back to the host.
37  */
38 
39 #include <lib/ndebug/ndebug.h>
40 #include <lib/ndebug/user.h>
41 
42 #include <app.h>
43 #include <lk/debug.h>
44 #include <lk/err.h>
45 #include <string.h>
46 
ndebugtest_entry(const struct app_descriptor * app,void * args)47 static void ndebugtest_entry(const struct app_descriptor *app, void *args) {
48     // Pad the buffer with one extra byte to acommodate a NULL character for
49     // printing using printf(...)
50     static uint8_t buf[NDEBUG_USR_MAX_PACKET_SIZE + 1];
51 
52     while (true) {
53         // Wait for USB to connect and somebody to answer the phone on the other
54         // end of the line.
55         status_t result = ndebug_await_connection_usr(INFINITE_TIME);
56         if (result != NO_ERROR) {
57             printf("Error %d while awaiting host. Retrying...\n", result);
58             continue;
59         }
60 
61         // Read bytes from the USB stack and echo them back to the host until
62         // the channel is closed. When the channel is closed, go back to waiting
63         // for the host to reopen the channel.
64         // Continue this process indefinitely.
65         while (true) {
66 
67             // Read some bytes from the USB stack
68             ssize_t bytes_read =
69                 ndebug_read_usr(buf, INFINITE_TIME);
70             if (bytes_read == ERR_CHANNEL_CLOSED) {
71                 printf("Channel reset during read.\n");
72                 break;
73             } else if (bytes_read < 0) {
74                 printf("Error while reading. Retcode = %ld\n", bytes_read);
75                 break;
76             }
77 
78             // Tack a NULL to the end of the bytes and print them to the
79             // console.
80             buf[bytes_read] = '\0';
81             printf("%s", buf);
82 
83             // Echo the bytes back the device.
84             ssize_t bytes_written =
85                 ndebug_write_usr(buf, bytes_read, INFINITE_TIME);
86             if (bytes_written == ERR_CHANNEL_CLOSED) {
87                 printf("Channel reset during write.\n");
88                 break;
89             } else if (bytes_written < 0) {
90                 printf("Error while writing. Retcode = %ld\n", bytes_written);
91                 break;
92             }
93 
94         }
95     }
96 }
97 
98 APP_START(ndebugtest)
99 .entry = ndebugtest_entry,
100 APP_END