Diag » History » Version 13
laforge, 12/23/2016 03:29 PM
logs mask updating in linux programs
1 | 4 | laforge | {{>toc}} |
---|---|---|---|
2 | |||
3 | 1 | laforge | h1. Diag |
4 | |||
5 | 12 | laforge | Qualcomm _Diag_ is the qualcomm diagnostics interface built into many Qualcomm based chipsets (or rather their software) for a long time (more than a decade). It is not publicly documented, but there are tools from Qualcomm (QPST, QXDM) as well as proprietary third-party tools and some Free Softare projects that implement parts of it. |
6 | |||
7 | The general idea is that there is some physical transport medium between the chipset/modem and an external PC, and the PC can request certain diagnostic information to be sent via that physical transport. Initially, this transport was a dedicated serial port/UART. Later, this became a virtual serial port over USB. |
||
8 | |||
9 | In a single-processor Modem (with only a baseband processor) it is rather simple: Some software on the baseband processor implements the DIAG protocol, and responds to any related requests received on the DIAG port. |
||
10 | |||
11 | In a multi-processor situation (like the MDM9215/MDM9x07 with their Linux-running Cortex-A5), the situation becomes slightly more complex. First of all, not only the external host/PC might want to consume DIAG information, but also code on the Linux processor inside the chip. Furthermore, code in the Linux processor might also want to offer some DIAG information towards the external host/PC. |
||
12 | |||
13 | The Qualcomm Android Linux kernel (usd even on the non-Android devices) implements several related kernel drivers, see [[Qualcomm_Kernel#diag]] |
||
14 | |||
15 | In userspace on the Linux inside the modem, there is a (unfortunately again non-free) library called @libdiag@ which offers some convenience API for programs to either consume DIAG or to generate/respond to DIAG received from the host/PC. Luckily the library is not performing much required functionality, so third-party programs like "SnoopSnitch":https://opensource.srlabs.de/projects/snoopsnitch have managed to talk directly to the @/dev/diag@ kernel device without needing to use that non-free library. |
||
16 | |||
17 | 6 | laforge | |
18 | 1 | laforge | h2. Acronyms |
19 | |||
20 | |DCI|Diag Consumer Interface| |
||
21 | |||
22 | 4 | laforge | h2. Child Pages |
23 | |||
24 | {{child_pages()}} |
||
25 | 6 | laforge | |
26 | h2. Subsystems |
||
27 | |||
28 | h3. Logging |
||
29 | |||
30 | Logging works by so-called log-codes. The Log code identifies the source/category of the logged information. Log codes are 16bit unsigned integers. |
||
31 | |||
32 | |_.Base Code|_.Purpose| |
||
33 | |0x1000|CDMA 1x| |
||
34 | |0x4000|WCDMA| |
||
35 | |0x5000|GSM| |
||
36 | |0x6000|Location Based Services| |
||
37 | |0x7000|UMTS| |
||
38 | |0x8000|TDMA| |
||
39 | |0xA000|DTV| |
||
40 | |0xB000|APPS| |
||
41 | |0xB010|LTE (until 0xB1FF)| |
||
42 | |0xB400|WIMAX| |
||
43 | |0xC000|DSP| |
||
44 | |0xD000|TD-SCDMA (until 0xD1FF)| |
||
45 | |0xF000|LOG TOOLS| |
||
46 | 4 | laforge | |
47 | 3 | laforge | h2. Kernel support |
48 | |||
49 | 1 | laforge | See [[Qualcomm_Kernel#diag]] |
50 | |||
51 | 4 | laforge | h2. Library |
52 | 1 | laforge | |
53 | 4 | laforge | There is @/usr/lib/libdiag.so.1@ which is linked by virtually any Qualcomm or Quectel proprietary program running on the Linux in the Modem. |
54 | |||
55 | it offers the follwing symbols: |
||
56 | <pre> |
||
57 | 9 | laforge | log_submit |
58 | pools |
||
59 | diag_vote_md_real_time |
||
60 | DiagSvc_Free |
||
61 | diag_dci_get_real_time_status_proc |
||
62 | diagpkt_subsys_get_delayed_rsp_id |
||
63 | diagpkt_subsys_alloc_v2 |
||
64 | diag_read_mask_file_list |
||
65 | diagpkt_subsys_get_cmd_code |
||
66 | Diag_LSM_Event_DeInit |
||
67 | diag_wakelock_init |
||
68 | mask_file2 |
||
69 | cleanup_mask |
||
70 | diag_register_dci_client |
||
71 | mask_file |
||
72 | msg_send_var |
||
73 | diagpkt_subsys_alloc_v2_delay |
||
74 | log_to_memory |
||
75 | diagpkt_alloc |
||
76 | db_thread_initialized |
||
77 | _init |
||
78 | stop_cond |
||
79 | diag_hdlc_toggle |
||
80 | diag_wakelock_acquire |
||
81 | parser_state |
||
82 | num_bytes_read |
||
83 | log_update_dci_mask |
||
84 | send_mask_modem |
||
85 | qsr4_db_file_fd |
||
86 | qsr4_db_write_buf_pool |
||
87 | event_update_mask |
||
88 | mask_sync_initialize |
||
89 | file_name_curr |
||
90 | msg_sprintf |
||
91 | mask_file_mdm2 |
||
92 | event_report_payload |
||
93 | DiagSvc_Malloc_Init |
||
94 | diag_release_dci_client |
||
95 | update_sync_mask |
||
96 | diag_send_socket_data |
||
97 | diag_register_dci_stream_proc |
||
98 | DiagSvc_Malloc |
||
99 | buffer_init |
||
100 | msg_mask_tbl_size |
||
101 | curr_write_idx |
||
102 | diag_logger_flush |
||
103 | pool0_buffers |
||
104 | log_set_length |
||
105 | hdlc_disabled |
||
106 | fd_qsr4_xml |
||
107 | qsr4_xml_file_name |
||
108 | diagpkt_LSM_process_request |
||
109 | diag_get_real_time_status |
||
110 | Diag_LSM_Pkt_DeInit |
||
111 | flush_buffer |
||
112 | diag_callback_send_data |
||
113 | dci_cumulative_event_mask |
||
114 | dci_transaction_id |
||
115 | diag_get_health_stats_proc |
||
116 | stop_mutex |
||
117 | diag_get_health_stats |
||
118 | log_free |
||
119 | mask_file_mdm |
||
120 | diagpkt_subsys_reset_delayed_rsp_id |
||
121 | diag_logger_init |
||
122 | dummy_handler |
||
123 | diag_send_data |
||
124 | diag_kill_qshrink4_threads |
||
125 | ts_get_lohi |
||
126 | diagpkt_subsys_set_rsp_cnt |
||
127 | diag_notify_parser_thread |
||
128 | diag_disable_all_logs |
||
129 | diagpkt_commit |
||
130 | proc_type |
||
131 | diag_log_stream_config |
||
132 | log_status |
||
133 | msg_send |
||
134 | WriteToDisk |
||
135 | Diag_LSM_Log_DeInit |
||
136 | fd_dev |
||
137 | diag_dci_get_real_time_status |
||
138 | qsr4_db_cmd_req_buf |
||
139 | diagpkt_subsys_alloc |
||
140 | get_sync_mask |
||
141 | diag_get_dci_support_list_proc |
||
142 | diag_get_real_time_status_proc |
||
143 | qsr4_read_db_mutex |
||
144 | dir_name |
||
145 | diag_set_socket_fd |
||
146 | diag_switch_logging_proc |
||
147 | diagpkt_get_cmd_code |
||
148 | diagpkt_subsys_get_status |
||
149 | in_read |
||
150 | Diag_LSM_Event_Init |
||
151 | diag_dci_error_type |
||
152 | diag_disable_all_events |
||
153 | pid_file |
||
154 | qsr4_db_parser_thread_hdl |
||
155 | num_dci_proc |
||
156 | in_wait_for_peripheral_status |
||
157 | write_in_progress |
||
158 | Diag_LSM_Pkt_Init |
||
159 | max_file_size |
||
160 | ts_get |
||
161 | diag_get_event_status |
||
162 | log_set_timestamp |
||
163 | curr_read |
||
164 | diag_register_dci_signal_data |
||
165 | diagpkt_shorten |
||
166 | curr_read_idx |
||
167 | pool1_buffers |
||
168 | lookup_pkt_rsp_transaction |
||
169 | diag_disable_console |
||
170 | max_file_num |
||
171 | diag_send_dci_async_req |
||
172 | log_get_length |
||
173 | diagpkt_set_cmd_code |
||
174 | diagpkt_subsys_set_status |
||
175 | diag_peripheral_buffering_drain_immediate |
||
176 | event_mask |
||
177 | log_commit |
||
178 | min_file_size |
||
179 | gdwClientID |
||
180 | msg_send_ts |
||
181 | read_thread_hdl |
||
182 | valid_token |
||
183 | add_guid_to_qshrink4_header |
||
184 | msg_mask |
||
185 | file_list_size |
||
186 | log_shorten |
||
187 | diagpkt_free |
||
188 | fd_socket |
||
189 | flush_log |
||
190 | create_diag_qshrink4_db_parser_thread |
||
191 | diag_read_mask_file |
||
192 | diag_deregister_dci_signal_data |
||
193 | num_dci_clients_event |
||
194 | proc_name |
||
195 | diag_lsm_dci_deinit |
||
196 | diag_wakelock_release |
||
197 | read_buffer |
||
198 | diagpkt_subsys_get_id |
||
199 | peripheral_name |
||
200 | Diag_LSM_Init |
||
201 | diag_configure_peripheral_buffering_tx_mode |
||
202 | curr_write |
||
203 | diag_callback_send_data_hdlc |
||
204 | qsr_msg_send_1 |
||
205 | qsr_msg_send_2 |
||
206 | db_write_thread_hdl |
||
207 | Diag_LSM_Msg_Init |
||
208 | qsr_msg_send_3 |
||
209 | token_list |
||
210 | diag_has_remote_device |
||
211 | diag_register_remote_callback |
||
212 | in_write |
||
213 | file_list |
||
214 | process_incoming_data |
||
215 | delete_log |
||
216 | log_to_device |
||
217 | logging_mode |
||
218 | log_set_code |
||
219 | diagpkt_delay_commit |
||
220 | flush_in_progress |
||
221 | diag_send_to_output |
||
222 | diag_get_max_channels |
||
223 | Diag_LSM_Log_Init |
||
224 | file_name_del |
||
225 | uart_logging_proc |
||
226 | DiagSvc_Malloc_Exit |
||
227 | output_dir |
||
228 | diag_event_stream_config |
||
229 | Diag_LSM_DeInit |
||
230 | diagpkt_tbl_reg |
||
231 | diag_dci_vote_real_time |
||
232 | kill_thread |
||
233 | count_written_bytes_1 |
||
234 | qsr_msg_send |
||
235 | event_report |
||
236 | diag_fd |
||
237 | event_update_dci_mask |
||
238 | diag_get_dci_support_list |
||
239 | log_update_mask |
||
240 | parse_data_for_qsr4_db_file_op_rsp |
||
241 | file_list_index |
||
242 | rename_file_names |
||
243 | diag_register_callback |
||
244 | diag_lsm_dci_init |
||
245 | diag_vote_md_real_time_proc |
||
246 | msg_send_1 |
||
247 | msg_send_2 |
||
248 | msg_send_3 |
||
249 | diag_is_wakelock_init |
||
250 | disk_write_hdl |
||
251 | diag_register_socket_cb |
||
252 | msg_update_mask |
||
253 | diag_set_peripheral_mask |
||
254 | log_alloc |
||
255 | dci_client_tbl |
||
256 | do_mask_sync |
||
257 | write_qshrink_header |
||
258 | fd_uart |
||
259 | qsr_msg_send_var |
||
260 | periph_info |
||
261 | diag_logger_exit |
||
262 | send_empty_mask |
||
263 | gnDiag_LSM_Event_Initialized |
||
264 | diagpkt_err_rsp |
||
265 | diag_logger_write |
||
266 | diag_get_log_status |
||
267 | qsr4_read_db_cond |
||
268 | rename_dir_name |
||
269 | diag_wakelock_destroy |
||
270 | diag_register_dci_stream |
||
271 | log_get_code |
||
272 | msg_mask_tbl |
||
273 | Diag_LSM_Msg_DeInit |
||
274 | to_integer |
||
275 | _fini |
||
276 | diag_get_peripheral_name_from_mask |
||
277 | count_written_bytes |
||
278 | diag_switch_logging |
||
279 | fd_md |
||
280 | 4 | laforge | </pre> |
281 | 5 | laforge | |
282 | 10 | laforge | h3. Initialization |
283 | |||
284 | |_.Function|_.Purpose| |
||
285 | |Diag_LSM_Init()|Registering with Diag which gives the client a handle to the Diag. Called once per process| |
||
286 | |||
287 | 5 | laforge | h3. Logging Service API |
288 | |||
289 | This is about sending log messages via the Diag interface. |
||
290 | |||
291 | |_.Function|_.Purpose| |
||
292 | |log_alloc(u16 code, len)|Allocate a buffer + fill header| |
||
293 | |log_shorten(ptr, len)|Shorten the length of a previously allocated buffer| |
||
294 | |log_commit(ptr)|Send the log to diag| |
||
295 | |log_free(ptr)|Free a buffer previously allocated with log_alloc()| |
||
296 | |log_submit(ptr)|Convenience wrapper around log_alloc()/memcpy()/log_commit()| |
||
297 | |||
298 | 7 | laforge | On the [[EC25]], it seems only the following Linux programs use the avove API to generate logs via Diag: |
299 | * @/usr/bin/cnss_diag@ |
||
300 | * @/usr/bin/ftmdaemon@ |
||
301 | * @/usr/bin/mbimd@ |
||
302 | * @/usr/bin/test_diag@ |
||
303 | |||
304 | 5 | laforge | h3. Diag Consumer Interface |
305 | |||
306 | 1 | laforge | This seems to be about implementing a program that consumes Diag events. You can register to certain events/masks and then receive the related information in call-backs. |
307 | 8 | laforge | |
308 | |_.Function|_.Description| |
||
309 | |diag_lsm_dci_init()|Initialize DCI subsystem of libdiag| |
||
310 | 11 | laforge | |diag_register_dci_client()|Register a DCI client, issues DIAG_IOCTL_DCI_REG to /dev/diag| |
311 | |diag_get_dci_support_list()|Get list of peripherals supported, issues DIAG_IOCTL_DCI_SUPPORT to /dev/diag| |
||
312 | |diag_register_dci_stream()|Register call-backs for events and logs, writes to /dev/diag| |
||
313 | |diag_event_stream_config()|Set up event streaming to the client, writes to /dev/diag| |
||
314 | |diag_log_stream_config()|Specify array of requested log codes, writes to /dev/diag| |
||
315 | |diag_get_health_stats()|Get statistics about missed/succeeded logs and events, issues DIAG_IOCTL_DCI_HEALTH_STATS to /dev/diag| |
||
316 | 8 | laforge | |diag_register_dci_signal_data()|Request OS signal when DCI data is received| |
317 | 13 | laforge | |
318 | h3. How to configure/enable logging |
||
319 | |||
320 | An external DIAG receiver (e.g. on the host PC) can configure which particular log messages he wants to receive and which not. |
||
321 | |||
322 | For the Linux programs using the libdiag.so logging service API, this means that every time an external DIAG log receiver updates the DIAG mask, that mask is passed into every program using libdiag, so they can update their log masks. This is done by reading on the @/dev/diag@ device and calling into @process_diag_payload()@ which in turn calls @log_update_mask()@ pr @msg_update_mask()@ which updates the @log_mask@ array. |
||
323 | |||
324 | When a given log line is created, exactly that @log_mask@ or @read_mask@ array is consulted to check if the given subsystem is enabled or not. |