Line data Source code
1 1 : /** @file
2 : * @brief HL7800 modem public API header file.
3 : *
4 : * Allows an application to control the HL7800 modem.
5 : *
6 : * Copyright (c) 2020 Laird Connectivity
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : */
10 :
11 : #ifndef ZEPHYR_INCLUDE_DRIVERS_MODEM_HL7800_H_
12 : #define ZEPHYR_INCLUDE_DRIVERS_MODEM_HL7800_H_
13 :
14 : #ifdef __cplusplus
15 : extern "C" {
16 : #endif
17 :
18 : #include <zephyr/types.h>
19 :
20 : #include <time.h>
21 :
22 : /* The size includes the NUL character, the strlen doesn't */
23 0 : #define MDM_HL7800_REVISION_MAX_SIZE 29
24 0 : #define MDM_HL7800_REVISION_MAX_STRLEN (MDM_HL7800_REVISION_MAX_SIZE - 1)
25 :
26 0 : #define MDM_HL7800_IMEI_SIZE 16
27 0 : #define MDM_HL7800_IMEI_STRLEN (MDM_HL7800_IMEI_SIZE - 1)
28 :
29 0 : #define MDM_HL7800_ICCID_MAX_SIZE 21
30 0 : #define MDM_HL7800_ICCID_MAX_STRLEN (MDM_HL7800_ICCID_MAX_SIZE - 1)
31 :
32 0 : #define MDM_HL7800_SERIAL_NUMBER_SIZE 15
33 0 : #define MDM_HL7800_SERIAL_NUMBER_STRLEN (MDM_HL7800_SERIAL_NUMBER_SIZE - 1)
34 :
35 0 : #define MDM_HL7800_APN_MAX_SIZE 64
36 0 : #define MDM_HL7800_APN_USERNAME_MAX_SIZE 65
37 0 : #define MDM_HL7800_APN_PASSWORD_MAX_SIZE 65
38 :
39 0 : #define MDM_HL7800_APN_MAX_STRLEN (MDM_HL7800_APN_MAX_SIZE - 1)
40 0 : #define MDM_HL7800_APN_USERNAME_MAX_STRLEN \
41 : (MDM_HL7800_APN_USERNAME_MAX_SIZE - 1)
42 0 : #define MDM_HL7800_APN_PASSWORD_MAX_STRLEN \
43 : (MDM_HL7800_APN_PASSWORD_MAX_SIZE - 1)
44 :
45 0 : #define MDM_HL7800_APN_CMD_MAX_SIZE \
46 : (32 + MDM_HL7800_APN_USERNAME_MAX_STRLEN + \
47 : MDM_HL7800_APN_PASSWORD_MAX_STRLEN)
48 :
49 0 : #define MDM_HL7800_APN_CMD_MAX_STRLEN (MDM_HL7800_APN_CMD_MAX_SIZE - 1)
50 :
51 0 : struct mdm_hl7800_apn {
52 0 : char value[MDM_HL7800_APN_MAX_SIZE];
53 0 : char username[MDM_HL7800_APN_USERNAME_MAX_SIZE];
54 0 : char password[MDM_HL7800_APN_PASSWORD_MAX_SIZE];
55 : };
56 :
57 0 : #define MDM_HL7800_LTE_BAND_STR_SIZE 21
58 0 : #define MDM_HL7800_LTE_BAND_STRLEN (MDM_HL7800_LTE_BAND_STR_SIZE - 1)
59 :
60 0 : #define MDM_HL7800_OPERATOR_INDEX_SIZE 3
61 0 : #define MDM_HL7800_OPERATOR_INDEX_STRLEN (MDM_HL7800_OPERATOR_INDEX_SIZE - 1)
62 :
63 0 : #define MDM_HL7800_IMSI_MIN_STR_SIZE 15
64 0 : #define MDM_HL7800_IMSI_MAX_STR_SIZE 16
65 0 : #define MDM_HL7800_IMSI_MAX_STRLEN (MDM_HL7800_IMSI_MAX_STR_SIZE - 1)
66 :
67 0 : #define MDM_HL7800_MODEM_FUNCTIONALITY_SIZE 2
68 0 : #define MDM_HL7800_MODEM_FUNCTIONALITY_STRLEN \
69 : (MDM_HL7800_MODEM_FUNCTIONALITY_SIZE - 1)
70 :
71 0 : #define MDM_HL7800_MAX_GPS_STR_SIZE 33
72 :
73 0 : #define MDM_HL7800_MAX_POLTE_USER_ID_SIZE 16
74 0 : #define MDM_HL7800_MAX_POLTE_PASSWORD_SIZE 16
75 0 : #define MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE 33
76 :
77 : /* Assign the server error code (location response) to a value
78 : * that isn't used by locate response so that a single status
79 : * callback can be used.
80 : */
81 0 : #define MDM_HL7800_POLTE_SERVER_ERROR 10
82 :
83 0 : #define MDM_HL7800_SET_POLTE_USER_AND_PASSWORD_FMT_STR "AT%%POLTECMD=\"SERVERAUTH\",\"%s\",\"%s\""
84 :
85 0 : struct mdm_hl7800_site_survey {
86 0 : uint32_t earfcn; /* EUTRA Absolute Radio Frequency Channel Number */
87 0 : uint32_t cell_id;
88 0 : int rsrp;
89 0 : int rsrq;
90 : };
91 :
92 0 : enum mdm_hl7800_radio_mode { MDM_RAT_CAT_M1 = 0, MDM_RAT_CAT_NB1 };
93 :
94 0 : enum mdm_hl7800_event {
95 : HL7800_EVENT_RESERVED = 0,
96 : HL7800_EVENT_NETWORK_STATE_CHANGE,
97 : HL7800_EVENT_APN_UPDATE,
98 : HL7800_EVENT_RSSI,
99 : HL7800_EVENT_SINR,
100 : HL7800_EVENT_STARTUP_STATE_CHANGE,
101 : HL7800_EVENT_SLEEP_STATE_CHANGE,
102 : HL7800_EVENT_RAT,
103 : HL7800_EVENT_BANDS,
104 : HL7800_EVENT_ACTIVE_BANDS,
105 : HL7800_EVENT_FOTA_STATE,
106 : HL7800_EVENT_FOTA_COUNT,
107 : HL7800_EVENT_REVISION,
108 : HL7800_EVENT_GPS,
109 : HL7800_EVENT_GPS_POSITION_STATUS,
110 : HL7800_EVENT_POLTE_REGISTRATION,
111 : HL7800_EVENT_POLTE_LOCATE_STATUS,
112 : HL7800_EVENT_POLTE,
113 : HL7800_EVENT_SITE_SURVEY,
114 : HL7800_EVENT_STATE,
115 : };
116 :
117 0 : enum mdm_hl7800_state {
118 : HL7800_STATE_NOT_READY = 0,
119 : HL7800_STATE_INITIALIZED,
120 : };
121 :
122 0 : enum mdm_hl7800_startup_state {
123 : HL7800_STARTUP_STATE_READY = 0,
124 : HL7800_STARTUP_STATE_WAITING_FOR_ACCESS_CODE,
125 : HL7800_STARTUP_STATE_SIM_NOT_PRESENT,
126 : HL7800_STARTUP_STATE_SIMLOCK,
127 : HL7800_STARTUP_STATE_UNRECOVERABLE_ERROR,
128 : HL7800_STARTUP_STATE_UNKNOWN,
129 : HL7800_STARTUP_STATE_INACTIVE_SIM
130 : };
131 :
132 0 : enum mdm_hl7800_network_state {
133 : HL7800_NOT_REGISTERED = 0,
134 : HL7800_HOME_NETWORK,
135 : HL7800_SEARCHING,
136 : HL7800_REGISTRATION_DENIED,
137 : HL7800_OUT_OF_COVERAGE,
138 : HL7800_ROAMING,
139 : HL7800_EMERGENCY = 8,
140 : /* Laird defined states */
141 : HL7800_UNABLE_TO_CONFIGURE = 0xf0
142 : };
143 :
144 0 : enum mdm_hl7800_sleep {
145 : HL7800_SLEEP_UNINITIALIZED = 0,
146 : HL7800_SLEEP_HIBERNATE,
147 : HL7800_SLEEP_AWAKE,
148 : HL7800_SLEEP_LITE_HIBERNATE,
149 : HL7800_SLEEP_SLEEP,
150 : };
151 :
152 0 : enum mdm_hl7800_fota_state {
153 : HL7800_FOTA_IDLE,
154 : HL7800_FOTA_START,
155 : HL7800_FOTA_WIP,
156 : HL7800_FOTA_PAD,
157 : HL7800_FOTA_SEND_EOT,
158 : HL7800_FOTA_FILE_ERROR,
159 : HL7800_FOTA_INSTALL,
160 : HL7800_FOTA_REBOOT_AND_RECONFIGURE,
161 : HL7800_FOTA_COMPLETE,
162 : };
163 :
164 0 : enum mdm_hl7800_functionality {
165 : HL7800_FUNCTIONALITY_MINIMUM = 0,
166 : HL7800_FUNCTIONALITY_FULL = 1,
167 : HL7800_FUNCTIONALITY_AIRPLANE = 4
168 : };
169 :
170 : /* The modem reports state values as an enumeration and a string.
171 : * GPS values are reported with a type of value and string.
172 : */
173 0 : struct mdm_hl7800_compound_event {
174 0 : uint8_t code;
175 0 : char *string;
176 : };
177 :
178 0 : enum mdm_hl7800_gnss_event {
179 : HL7800_GNSS_EVENT_INVALID = -1,
180 : HL7800_GNSS_EVENT_INIT,
181 : HL7800_GNSS_EVENT_START,
182 : HL7800_GNSS_EVENT_STOP,
183 : HL7800_GNSS_EVENT_POSITION,
184 : };
185 :
186 0 : enum mdm_hl7800_gnss_status {
187 : HL7800_GNSS_STATUS_INVALID = -1,
188 : HL7800_GNSS_STATUS_FAILURE,
189 : HL7800_GNSS_STATUS_SUCCESS,
190 : };
191 :
192 0 : enum mdm_hl7800_gnss_position_event {
193 : HL7800_GNSS_POSITION_EVENT_INVALID = -1,
194 : HL7800_GNSS_POSITION_EVENT_LOST_OR_NOT_AVAILABLE_YET,
195 : HL7800_GNSS_POSITION_EVENT_PREDICTION_AVAILABLE,
196 : HL7800_GNSS_POSITION_EVENT_2D_AVAILABLE,
197 : HL7800_GNSS_POSITION_EVENT_3D_AVAILABLE,
198 : HL7800_GNSS_POSITION_EVENT_FIXED_TO_INVALID,
199 : };
200 :
201 0 : enum mdm_hl7800_gps_string_types {
202 : HL7800_GPS_STR_LATITUDE,
203 : HL7800_GPS_STR_LONGITUDE,
204 : HL7800_GPS_STR_GPS_TIME,
205 : HL7800_GPS_STR_FIX_TYPE,
206 : HL7800_GPS_STR_HEPE,
207 : HL7800_GPS_STR_ALTITUDE,
208 : HL7800_GPS_STR_ALT_UNC,
209 : HL7800_GPS_STR_DIRECTION,
210 : HL7800_GPS_STR_HOR_SPEED,
211 : HL7800_GPS_STR_VER_SPEED
212 : };
213 :
214 : /* status: negative errno, 0 on success
215 : * user and password aren't valid if status is non-zero.
216 : */
217 0 : struct mdm_hl7800_polte_registration_event_data {
218 0 : int status;
219 0 : char *user;
220 0 : char *password;
221 : };
222 :
223 : /* status: negative errno, 0 on success, non-zero error code
224 : * Data is not valid if status is non-zero.
225 : */
226 0 : struct mdm_hl7800_polte_location_data {
227 0 : uint32_t timestamp;
228 0 : int status;
229 0 : char latitude[MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE];
230 0 : char longitude[MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE];
231 0 : char confidence_in_meters[MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE];
232 : };
233 :
234 : /**
235 : * event - The type of event
236 : * event_data - Pointer to event specific data structure:
237 : * HL7800_EVENT_NETWORK_STATE_CHANGE - mdm_hl7800_compound_event
238 : * HL7800_EVENT_APN_UPDATE - struct mdm_hl7800_apn
239 : * HL7800_EVENT_RSSI - int
240 : * HL7800_EVENT_SINR - int
241 : * HL7800_EVENT_STARTUP_STATE_CHANGE - mdm_hl7800_compound_event
242 : * HL7800_EVENT_SLEEP_STATE_CHANGE - mdm_hl7800_compound_event
243 : * HL7800_EVENT_RAT - int
244 : * HL7800_EVENT_BANDS - string
245 : * HL7800_EVENT_ACTIVE_BANDS - string
246 : * HL7800_EVENT_FOTA_STATE - mdm_hl7800_compound_event
247 : * HL7800_EVENT_FOTA_COUNT - uint32_t
248 : * HL7800_EVENT_REVISION - string
249 : * HL7800_EVENT_GPS - mdm_hl7800_compound_event
250 : * HL7800_EVENT_GPS_POSITION_STATUS int
251 : * HL7800_EVENT_POLTE_REGISTRATION mdm_hl7800_polte_registration_event_data
252 : * HL7800_EVENT_POLTE mdm_hl7800_polte_location_data
253 : * HL7800_EVENT_POLTE_LOCATE_STATUS int
254 : * HL7800_EVENT_SITE_SURVEY mdm_hl7800_site_survey
255 : * HL7800_EVENT_STATE mdm_hl7800_compound_event
256 : */
257 1 : typedef void (*mdm_hl7800_event_callback_t)(enum mdm_hl7800_event event,
258 : void *event_data);
259 :
260 0 : struct mdm_hl7800_callback_agent {
261 0 : sys_snode_t node;
262 0 : mdm_hl7800_event_callback_t event_callback;
263 : };
264 :
265 : /**
266 : * @brief Power off the HL7800
267 : *
268 : * @return int32_t 0 for success
269 : */
270 1 : int32_t mdm_hl7800_power_off(void);
271 :
272 : /**
273 : * @brief Reset the HL7800 (and allow it to reconfigure).
274 : *
275 : * @return int32_t >= 0 for success, < 0 for failure
276 : */
277 1 : int32_t mdm_hl7800_reset(void);
278 :
279 : /**
280 : * @brief Control the wake signals to the HL7800.
281 : * @note this API should only be used for debug purposes.
282 : *
283 : * @param awake True to keep the HL7800 awake, False to allow sleep
284 : */
285 1 : void mdm_hl7800_wakeup(bool awake);
286 :
287 : /**
288 : * @brief Send an AT command to the HL7800.
289 : * @note This API should only be used for debug purposes.
290 : * It is possible to break the driver using this API.
291 : *
292 : * @param data AT command string
293 : * @param resp_timeout Timeout in seconds to wait for the response
294 : * @param resp Pointer to the response buffer. This can be NULL to ignore the response.
295 : * @param resp_len Input: length of the response buffer, Output: length of the response.
296 : * This can be NULL.
297 : * @return int32_t 0 for success
298 : */
299 1 : int32_t mdm_hl7800_send_at_cmd(const uint8_t *data, uint8_t resp_timeout, char *resp,
300 : uint16_t *resp_len);
301 :
302 : /**
303 : * @brief Get the signal quality of the HL7800.
304 : * If CONFIG_MODEM_HL7800_RSSI_RATE_SECONDS is non-zero, then
305 : * this function returns the value from the last periodic read.
306 : * If CONFIG_MODEM_HL7800_RSSI_RATE_SECONDS is 0, then this
307 : * may cause the modem to be woken so that the values can be queried.
308 : *
309 : * @param rsrp Reference Signals Received Power (dBm)
310 : * Range = -140 dBm to -44 dBm
311 : * @param sinr Signal to Interference plus Noise Ratio (dB)
312 : * Range = -128 dB to 40 dB
313 : */
314 1 : void mdm_hl7800_get_signal_quality(int *rsrp, int *sinr);
315 :
316 : /**
317 : * @brief Get the SIM card ICCID
318 : *
319 : */
320 1 : char *mdm_hl7800_get_iccid(void);
321 :
322 : /**
323 : * @brief Get the HL7800 serial number
324 : *
325 : */
326 1 : char *mdm_hl7800_get_sn(void);
327 :
328 : /**
329 : * @brief Get the HL7800 IMEI
330 : *
331 : */
332 1 : char *mdm_hl7800_get_imei(void);
333 :
334 : /**
335 : * @brief Get the HL7800 firmware version
336 : *
337 : */
338 1 : char *mdm_hl7800_get_fw_version(void);
339 :
340 : /**
341 : * @brief Get the IMSI
342 : *
343 : */
344 1 : char *mdm_hl7800_get_imsi(void);
345 :
346 : /**
347 : * @brief Update the Access Point Name in the modem.
348 : *
349 : * @retval 0 on success, negative on failure.
350 : */
351 1 : int32_t mdm_hl7800_update_apn(char *access_point_name);
352 :
353 : /**
354 : * @brief Update the Radio Access Technology (mode).
355 : *
356 : * @retval 0 on success, negative on failure.
357 : */
358 1 : int32_t mdm_hl7800_update_rat(enum mdm_hl7800_radio_mode value);
359 :
360 : /**
361 : * @retval true if RAT value is valid
362 : */
363 1 : bool mdm_hl7800_valid_rat(uint8_t value);
364 :
365 : /**
366 : * @brief Register a function that is called when a modem event occurs.
367 : * Multiple users registering for callbacks is supported.
368 : *
369 : * @param agent event callback agent
370 : *
371 : * @retval 0 on success, negative on failure
372 : */
373 1 : int mdm_hl7800_register_event_callback(struct mdm_hl7800_callback_agent *agent);
374 :
375 : /**
376 : * @brief Unregister a callback event function
377 : *
378 : * @param agent event callback agent
379 : *
380 : * @retval 0 on success, negative on failure
381 : */
382 1 : int mdm_hl7800_unregister_event_callback(struct mdm_hl7800_callback_agent *agent);
383 :
384 : /**
385 : * @brief Force modem module to generate status events.
386 : *
387 : * @note This can be used to get the current state when a module initializes
388 : * later than the modem.
389 : */
390 1 : void mdm_hl7800_generate_status_events(void);
391 :
392 : /**
393 : * @brief Get the local time from the modem's real time clock.
394 : *
395 : * @param tm time structure
396 : * @param offset The amount the local time is offset from GMT/UTC in seconds.
397 : * @return int32_t 0 if successful
398 : */
399 1 : int32_t mdm_hl7800_get_local_time(struct tm *tm, int32_t *offset);
400 :
401 : #ifdef CONFIG_MODEM_HL7800_FW_UPDATE
402 : /**
403 : * @brief Update the HL7800 via XMODEM protocol. During the firmware update
404 : * no other modem functions will be available.
405 : *
406 : * @param file_path Absolute path of the update file
407 : *
408 : * @param 0 if successful
409 : */
410 : int32_t mdm_hl7800_update_fw(char *file_path);
411 : #endif
412 :
413 : /**
414 : * @brief Read the operator index from the modem.
415 : *
416 : * @retval negative error code, 0 on success
417 : */
418 1 : int32_t mdm_hl7800_get_operator_index(void);
419 :
420 : /**
421 : * @brief Get modem functionality
422 : *
423 : * @return int32_t negative errno on failure, else mdm_hl7800_functionality
424 : */
425 1 : int32_t mdm_hl7800_get_functionality(void);
426 :
427 : /**
428 : * @brief Set airplane, normal, or reduced functionality mode.
429 : * Airplane mode persists when reset.
430 : *
431 : * @note Boot functionality is also controlled by Kconfig
432 : * MODEM_HL7800_BOOT_IN_AIRPLANE_MODE.
433 : *
434 : * @param mode
435 : * @return int32_t negative errno, 0 on success
436 : */
437 1 : int32_t mdm_hl7800_set_functionality(enum mdm_hl7800_functionality mode);
438 :
439 : /**
440 : * @brief When rate is non-zero: Put modem into Airplane mode. Enable GPS and
441 : * generate HL7800_EVENT_GPS events.
442 : * When zero: Disable GPS and put modem into normal mode.
443 : *
444 : * @note Airplane mode isn't cleared when the modem is reset.
445 : *
446 : * @param rate in seconds to query location
447 : * @return int32_t negative errno, 0 on success
448 : */
449 1 : int32_t mdm_hl7800_set_gps_rate(uint32_t rate);
450 :
451 : /**
452 : * @brief Register modem/SIM with polte.io
453 : *
454 : * @note It takes around 30 seconds for HL7800_EVENT_POLTE_REGISTRATION to
455 : * be generated. If the applications saves the user and password
456 : * information into non-volatile memory, then this command
457 : * only needs to be run once.
458 : *
459 : * @return int32_t negative errno, 0 on success
460 : */
461 1 : int32_t mdm_hl7800_polte_register(void);
462 :
463 : /**
464 : * @brief Enable PoLTE.
465 : *
466 : * @param user from polte.io or register command callback
467 : * @param password from polte.io register command callback
468 : * @return int32_t negative errno, 0 on success
469 : */
470 1 : int32_t mdm_hl7800_polte_enable(char *user, char *password);
471 :
472 : /**
473 : * @brief Locate device using PoLTE.
474 : *
475 : * @note The first HL7800_EVENT_POLTE_LOCATE_STATUS event indicates
476 : * the status of issuing the locate command. The second event
477 : * requires 20-120 seconds to be generated and it contains the
478 : * location information (or indicates server failure).
479 : *
480 : * @return int32_t negative errno, 0 on success
481 : */
482 1 : int32_t mdm_hl7800_polte_locate(void);
483 :
484 : /**
485 : * @brief Perform a site survey. This command may return different values
486 : * each time it is run (depending on what is in range).
487 : *
488 : * HL7800_EVENT_SITE_SURVEY is generated for each response received from modem.
489 : *
490 : * @retval negative error code, 0 on success
491 : */
492 1 : int32_t mdm_hl7800_perform_site_survey(void);
493 :
494 : /**
495 : * @brief Set desired sleep level. Requires MODEM_HL7800_LOW_POWER_MODE
496 : *
497 : * @param level (sleep, lite hibernate, or hibernate)
498 : * @return int negative errno, 0 on success
499 : */
500 1 : int mdm_hl7800_set_desired_sleep_level(enum mdm_hl7800_sleep level);
501 :
502 : /**
503 : * @brief Allows mapping of WAKE_UP signal
504 : * to a user accessible test point on the development board.
505 : *
506 : * @param func to be called when application requests modem wake/sleep.
507 : * The state parameter of the callback is 1 when modem should stay awake,
508 : * 0 when modem can sleep
509 : */
510 1 : void mdm_hl7800_register_wake_test_point_callback(void (*func)(int state));
511 :
512 : /**
513 : * @brief Allows mapping of P1.12_GPIO6 signal
514 : * to a user accessible test point on the development board.
515 : *
516 : * @param func to be called when modem wakes/sleeps is sleep level is
517 : * hibernate or lite hibernate.
518 : * The state parameter of the callback follows gpio_pin_get definitions,
519 : * but will default high if there is an error reading pin
520 : */
521 1 : void mdm_hl7800_register_gpio6_callback(void (*func)(int state));
522 :
523 : /**
524 : * @brief Allows mapping of UART1_CTS signal
525 : * to a user accessible test point on the development board.
526 : *
527 : * @param func to be called when CTS state changes if sleep level is sleep.
528 : * The state parameter of the callback follows gpio_pin_get definitions,
529 : * but will default low if there is an error reading pin
530 : */
531 1 : void mdm_hl7800_register_cts_callback(void (*func)(int state));
532 :
533 : /**
534 : * @brief Set the bands available for the LTE connection.
535 : * NOTE: This will cause the modem to reboot. This call returns before the reboot.
536 : *
537 : * @param bands Band bitmap in hexadecimal format without the 0x prefix.
538 : * Leading 0's for the value can be omitted.
539 : *
540 : * @return int32_t negative errno, 0 on success
541 : */
542 1 : int32_t mdm_hl7800_set_bands(const char *bands);
543 :
544 : /**
545 : * @brief Set the log level for the modem.
546 : *
547 : * @note It cannot be set higher than CONFIG_MODEM_LOG_LEVEL.
548 : * If debug level is desired, then it must be compiled with that level.
549 : *
550 : * @param level 0 (None) - 4 (Debug)
551 : *
552 : * @retval new log level
553 : */
554 1 : uint32_t mdm_hl7800_log_filter_set(uint32_t level);
555 :
556 : #ifdef __cplusplus
557 : }
558 : #endif
559 :
560 : #endif /* ZEPHYR_INCLUDE_DRIVERS_MODEM_HL7800_H_ */
|