Mauro Carvalho Chehab | baa293e | 2019-06-27 15:39:22 -0300 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0 |
Mauro Carvalho Chehab | 93d2c15 | 2019-04-14 08:50:59 -0300 | [diff] [blame] | 2 | |
| 3 | ============= |
| 4 | Intel MID PTI |
| 5 | ============= |
| 6 | |
| 7 | The Intel MID PTI project is HW implemented in Intel Atom |
| 8 | system-on-a-chip designs based on the Parallel Trace |
| 9 | Interface for MIPI P1149.7 cJTAG standard. The kernel solution |
| 10 | for this platform involves the following files:: |
| 11 | |
| 12 | ./include/linux/pti.h |
| 13 | ./drivers/.../n_tracesink.h |
| 14 | ./drivers/.../n_tracerouter.c |
| 15 | ./drivers/.../n_tracesink.c |
| 16 | ./drivers/.../pti.c |
| 17 | |
| 18 | pti.c is the driver that enables various debugging features |
| 19 | popular on platforms from certain mobile manufacturers. |
| 20 | n_tracerouter.c and n_tracesink.c allow extra system information to |
| 21 | be collected and routed to the pti driver, such as trace |
| 22 | debugging data from a modem. Although n_tracerouter |
| 23 | and n_tracesink are a part of the complete PTI solution, |
| 24 | these two line disciplines can work separately from |
| 25 | pti.c and route any data stream from one /dev/tty node |
| 26 | to another /dev/tty node via kernel-space. This provides |
| 27 | a stable, reliable connection that will not break unless |
| 28 | the user-space application shuts down (plus avoids |
| 29 | kernel->user->kernel context switch overheads of routing |
| 30 | data). |
| 31 | |
| 32 | An example debugging usage for this driver system: |
| 33 | |
| 34 | * Hook /dev/ttyPTI0 to syslogd. Opening this port will also start |
| 35 | a console device to further capture debugging messages to PTI. |
| 36 | * Hook /dev/ttyPTI1 to modem debugging data to write to PTI HW. |
| 37 | This is where n_tracerouter and n_tracesink are used. |
| 38 | * Hook /dev/pti to a user-level debugging application for writing |
| 39 | to PTI HW. |
| 40 | * `Use mipi_` Kernel Driver API in other device drivers for |
| 41 | debugging to PTI by first requesting a PTI write address via |
| 42 | mipi_request_masterchannel(1). |
| 43 | |
| 44 | Below is example pseudo-code on how a 'privileged' application |
| 45 | can hook up n_tracerouter and n_tracesink to any tty on |
| 46 | a system. 'Privileged' means the application has enough |
| 47 | privileges to successfully manipulate the ldisc drivers |
| 48 | but is not just blindly executing as 'root'. Keep in mind |
| 49 | the use of ioctl(,TIOCSETD,) is not specific to the n_tracerouter |
| 50 | and n_tracesink line discpline drivers but is a generic |
| 51 | operation for a program to use a line discpline driver |
Jonathan Neuschäfer | 7867dbb | 2019-10-04 19:01:19 +0200 | [diff] [blame] | 52 | on a tty port other than the default n_tty: |
| 53 | |
| 54 | .. code-block:: c |
Mauro Carvalho Chehab | 93d2c15 | 2019-04-14 08:50:59 -0300 | [diff] [blame] | 55 | |
| 56 | /////////// To hook up n_tracerouter and n_tracesink ///////// |
| 57 | |
| 58 | // Note that n_tracerouter depends on n_tracesink. |
| 59 | #include <errno.h> |
| 60 | #define ONE_TTY "/dev/ttyOne" |
| 61 | #define TWO_TTY "/dev/ttyTwo" |
| 62 | |
| 63 | // needed global to hand onto ldisc connection |
| 64 | static int g_fd_source = -1; |
| 65 | static int g_fd_sink = -1; |
| 66 | |
| 67 | // these two vars used to grab LDISC values from loaded ldisc drivers |
| 68 | // in OS. Look at /proc/tty/ldiscs to get the right numbers from |
| 69 | // the ldiscs loaded in the system. |
| 70 | int source_ldisc_num, sink_ldisc_num = -1; |
| 71 | int retval; |
| 72 | |
| 73 | g_fd_source = open(ONE_TTY, O_RDWR); // must be R/W |
| 74 | g_fd_sink = open(TWO_TTY, O_RDWR); // must be R/W |
| 75 | |
| 76 | if (g_fd_source <= 0) || (g_fd_sink <= 0) { |
| 77 | // doubt you'll want to use these exact error lines of code |
| 78 | printf("Error on open(). errno: %d\n",errno); |
| 79 | return errno; |
| 80 | } |
| 81 | |
| 82 | retval = ioctl(g_fd_sink, TIOCSETD, &sink_ldisc_num); |
| 83 | if (retval < 0) { |
| 84 | printf("Error on ioctl(). errno: %d\n", errno); |
| 85 | return errno; |
| 86 | } |
| 87 | |
| 88 | retval = ioctl(g_fd_source, TIOCSETD, &source_ldisc_num); |
| 89 | if (retval < 0) { |
| 90 | printf("Error on ioctl(). errno: %d\n", errno); |
| 91 | return errno; |
| 92 | } |
| 93 | |
| 94 | /////////// To disconnect n_tracerouter and n_tracesink //////// |
| 95 | |
| 96 | // First make sure data through the ldiscs has stopped. |
| 97 | |
| 98 | // Second, disconnect ldiscs. This provides a |
| 99 | // little cleaner shutdown on tty stack. |
| 100 | sink_ldisc_num = 0; |
| 101 | source_ldisc_num = 0; |
| 102 | ioctl(g_fd_uart, TIOCSETD, &sink_ldisc_num); |
| 103 | ioctl(g_fd_gadget, TIOCSETD, &source_ldisc_num); |
| 104 | |
| 105 | // Three, program closes connection, and cleanup: |
| 106 | close(g_fd_uart); |
| 107 | close(g_fd_gadget); |
| 108 | g_fd_uart = g_fd_gadget = NULL; |