• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Telephony Development
2
3## Initializing a Modem Vendor Library
4
5### When to Use
6
7Initializing a modem vendor library means to implement **const HRilOps \*RilInitOps\(const struct HRilReport \*reportOps\)** function in the vendor library. This function is mainly used to:
8
9-   Receive function pointers to event callbacks of RIL Adapter. When a service event needs to be reported, the target pointer will be called to report the event to RIL Adapter.
10-   Create a thread for reading modem nodes. In this thread, the data reported by the modem is read cyclically and parsed as a specific service event for reporting.
11-   Return the function pointer of the service request API to RIL Adapter.
12
13### Available APIs
14
15The following table describes the API for initializing a modem vendor library.
16
17**Table  1** API for initializing a modem vendor library
18
19| API | Description |
20| -------- | -------- |
21| const&nbsp;HRilOps&nbsp;\*RilInitOps(const&nbsp;struct&nbsp;HRilReport&nbsp;\*&nbsp;reportOps) | Provides an entry for running a modem vendor library.<br>Input parameter:<br>**reportOps**: Specifies the pointer to the event callback function, which is passed by RIL Adapter.<br/>Return result: function pointer of the service request API. |
22
23### How to Develop
24
251.  Set the event callback function pointers passed by RIL Adapter through **RilInitOps**.
26
27    ```
28    // Define the callback function pointers of the modem vendor library.
29    static struct HRilReport g_reportOps = {
30        OnCallReport, // Callback function for call services
31        OnDataReport, // Callback function for cellular data services
32        OnModemReport, // Callback function for modem services
33        OnNetworkReport, // Callback function for network search services
34        OnSimReport, // Callback function for SIM card services
35        OnSmsReport // Callback function for SMS services
36    };
37    ```
38
39
402.  Create the **g\_reader** main thread to enable message looping.
41
42    ```
43    pthread_attr_t t;
44    pthread_attr_init(&t);
45    pthread_attr_setdetachstate(&t, PTHREAD_CREATE_DETACHED);
46    ret = pthread_create(&g_reader, &t, ReaderLoop, &t); // Create the g_reader thread.
47    ```
48
49
503.  In the **g\_eventListeners** thread, use **open\(\)** to open a modem node and then create the **g\_reader** thread to read and process messages reported by the modem.
51
52    ```
53    g_fd = open(g_devicePath, O_RDWR); // Open the device node specified by g_devicePath.
54    pthread_attr_init(&attr);
55    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
56    ret = pthread_create(&g_eventListeners, &attr, EventListeners, NULL);
57    ```
58
59
604.  Return the function pointer of the service request API.
61
62    ```
63    // Structure for the service request API of the call module
64    typedef struct {
65        // Obtain the call list.
66        void (*GetCallList)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
67        // Make a call.
68        void (*Dial)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
69        // Disconnect a call.
70        void (*Hangup)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
71        // Reject a call.
72        void (*Reject)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
73        // Answer a call.
74        void (*Answer)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
75    } HRilCallReq;
76
77    // Callback function pointers of the call module
78    static const HRilCallReq g_callReqOps = {
79        .GetCallList = ReqGetCallList, // Obtain the call list.
80        .Dial = ReqDial,               // Make a call.
81        .Hangup = ReqHangup,           // Disconnect a call.
82        .Reject = ReqReject,           // Reject a call.
83        .Answer = ReqAnswer,           // Answer a call.
84    };
85
86    // Service request structure
87    typedef struct {
88        const HRilCallReq *callOps;       // Pointer to the structure of call service requests
89        const HRilSimReq *simOps;         // Pointer to the structure of SIM card service requests
90        const HRilSmsReq *smsOps;         // Pointer to the structure of SMS and MMS service requests
91        const HRilDataReq *dataOps;       // Pointer to the structure of cellular data service requests
92        const HRilNetworkReq *networkOps; // Pointer to the structure of network search service requests
93        const HRilModemReq *modemOps;     // Pointer to the structure of modem service requests
94    } HRilOps;
95
96    // Service request APIs
97    HRilOps g_hrilOps = {
98        .callOps = &g_callReqOps,       // API for call service requests
99        .simOps = &g_simReqOps,         // API for SIM card service requests
100        .smsOps = &g_smsReqOps,         // API for SMS and MMS service requests
101        .networkOps = &g_networkReqOps, // API for cellular data service requests
102        .dataOps = &g_dataReqOps,       // API for network search service requests
103        .modemOps = &g_modemReqOps,     // API for modem service requests
104    };
105    ```
106
107
108### Debugging and Verification
109
1101.  Use the [hdc\_std](../subsystems/subsys-toolchain-hdc-guide.md#how-to-obtain) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device. For details about how to integrate a library file, see  [Integrating Modem Vendor Libraries](#integrating-modem-vendor-libraries).
111
112    ```
113    hdc_std file send libril_vendor.z.so /system/lib/
114    ```
115
1162.  Reboot the debugging device.
117
118    ```
119    hdc_std shell sync
120    hdc_std shell reboot
121    ```
122
1233.  Run the **hdc\_std shell hilog** command to view the debug log, and check whether the **RilInitOps\(\)** function is successfully executed. The following debug log is for reference:
124
125    ```
126    09-02 07:40:47.807   455   455 I 01f08/HrilHdf: [LoadVendor-(hril_hdf.c:148)] RilInit LoadVendor start with rilLibPath:libril_vendor.z.so
127    09-02 07:40:47.830   455   455 I 01f08/HrilHdf: [LoadVendor-(hril_hdf.c:163)] HRilRegOps completed
128    ```
129
130
131## Responding to Modem Service Requests
132
133### When to Use
134
135After receiving a specific telephony service request, RIL Adapter calls the target function pointer obtained in modem vendor library initialization to send a specific service request to the vendor library. Then, the vendor library processes the request based on the request ID.
136
137### Available APIs
138
139The following table describes the APIs for responding to modem service requests, with the dial module as an example.
140
141**Table  2** APIs for responding to modem service requests
142
143| API | Description |
144| -------- | -------- |
145| void&nbsp;ReqDial(ReqDataInfo&nbsp;\*requestInfo,&nbsp;const&nbsp;void&nbsp;\*data,&nbsp;size_t&nbsp;dataLen); | Processes number dial requests.<br>Input parameters:<br>**requestInfo**: request type<br/>**data**: called number<br/>**dataLen**: data length<br/>Return value: none |
146| void&nbsp;(\*OnCallReport)(struct&nbsp;ReportInfo&nbsp;reportInfo,&nbsp;const&nbsp;void&nbsp;\*data,&nbsp;size_t&nbsp;dataLen); | Reports the execution result of a service request to RIL Adapter.<br>Input parameters:<br>**reportInfo**: request type<br/>**data**: called number<br/>**dataLen**: data length<br/>Return value: none |
147
148### How to Develop
149
1501.  Implement processing of dial requests in the **ReqDial\(\)** API.
151
152    ```
153    // Implement the API for processing dial requests.
154    void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen)
155    {
156        HRilDial *pDial = NULL;
157        char cmd[MAX_BUFF_SIZE] = {0};
158        const char *clir = NULL;
159        int ret;
160        int err = HRIL_ERR_SUCCESS;
161        struct ReportInfo reportInfo = {};
162        ResponseInfo *pResponse = NULL;
163        if (data == NULL) {
164            TELEPHONY_LOGE("data is null!!!");
165            err = HRIL_ERR_INVALID_PARAMETER;
166            reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
167            OnCallReport(reportInfo, NULL, 0);
168            return;
169        }
170        pDial = (HRilDial *)data;
171        switch (pDial->clir) {
172            case CALL_CLIR_INVOCATION:
173                clir = "I";
174                break; /* invocation */
175            case CALL_CLIR_SUPPRESSION:
176                clir = "i";
177                break; /* suppression */
178            case CALL_CLIR_SUBSCRIPTION_DEFUALT:
179            default:
180                clir = "";
181                break; /* subscription default */
182        }
183        (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir);
184        ret = SendCommandLock(cmd, NULL, 0, &pResponse); // Send the AT command.
185        ......
186    }
187    ```
188
1892.  After the modem executes the dial command, report the execution result to RIL Adapter via **OnCallReport\(\)**.
190
191    ```
192    ret = SendCommandLock(cmd, NULL, 0, &pResponse);
193    if (ret != 0 || (pResponse != NULL && pResponse->success == 0)) {
194        TELEPHONY_LOGE("ATD send failed");
195        err = HRIL_ERR_GENERIC_FAILURE;
196    }
197    reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
198    OnCallReport(reportInfo, NULL, 0); // Invoke the callback function of the call service.
199    ```
200
201
202### Debugging and Verification
203
2041.  Use the [hdc\_std](../subsystems/subsys-toolchain-hdc-guide.md#how-to-obtain) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
205
206    ```
207    hdc_std file send libril_vendor.z.so /system/lib/
208    ```
209
2102.  Reboot the debugging device.
211
212    ```
213    hdc_std shell sync
214    hdc_std shell reboot
215    ```
216
2173.  Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function.
218
219    ```
220    hdc_std shell
221    # ./system/bin/ril_adapter_test
222    ----> Test Enter  --------->Call---------------------
223
224    1----> RilUnitTest::OnRequestCallDialTest
225    2----> RilUnitTest:: OnRequestCallHangupTest
226    3----> RilUnitTest:: OnRequestCallAnswerTest
227    4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest
228    5----> RilUnitTest::OnRequestRefusedCallTest
229
230    1
231    ```
232
2334.  Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **ReqDial\(\)** is successfully executed. The following debug log is for reference:
234
235    ```
236    09-02 07:55:09.073   455  2059 I 01f08/RilVendor: [SendCommandLock-(at_support.c:226)] command ATD18675231804;, NeedATPause:0, atCmd:AT
237    09-02 07:55:09.099   455  2053 I 01f08/Rilvendor: [ProcessResponse-(at_support.c:159)] processLine line = OK
238    09-02 07:55:09.100   455  2053 E 01f08/RilVendor: [ReportStrWith-(vendor_util.c:63)] str or prefix parameter is null.
239    09-02 07:55:09.100   455  2053 E 01f08/RilVendor: [ProcessLastResponse-(vendor_channel.c:77)] g_bufferCur endLine is null
240    09-02 07:55:09.100   455  2059 I 01f08/RilVendor: [SendCommandLock-(at_support.c:243)] err = 0
241    09-02 07:55:09.100   455  2053 I 01f08/RilVendor: [ProcessResponse-(at_support.c:159)] processLine line = ^ORIG:1,0
242    ```
243
244
245## Reporting Modem Events
246
247### When to Use
248
249A modem node thread reads the messages reported by the modem cyclically, parses the messages into specific events, and then reports the events to RIL Adapter.
250
251### Available APIs
252
253The following table describes the API for reporting modem events.
254
255**Table  3** API for reporting modem events
256
257| API | Description |
258| -------- | -------- |
259| void&nbsp;OnNotifyOps(const&nbsp;char&nbsp;\*s,&nbsp;const&nbsp;char&nbsp;\*smsPdu) | Distributes the events reported by the modem.<br>Input parameters:<br/>**s**: AT command prefix<br/>**smsPdu**: PDU of the SMS message<br/>Return value: none |
260
261### How to Develop
262
2631.  Call **OnNotifyOps\(\)** in the g\_reader thread of the modem device node to parse reported modem events. On determining the command type, call **OnXxxReport\(\)** to report the parsed module events to the hril layer.
264
265    ```
266    // Parse the data reported by the modem as events proactively reported by the corresponding module.
267    void OnNotifyOps(const char *s, const char *smsPdu)
268    {
269        int ret = 0;
270        struct ReportInfo reportInfo = {0};
271        reportInfo.error = HRIL_ERR_SUCCESS;
272        reportInfo.type = HRIL_NOTIFICATION;
273        if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
274            return;
275        }
276        TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu);
277        // Determine the type of the proactively reported events based on the AT command.
278        if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") ||
279            ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") ||
280            ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) {
281            reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED;
282            OnCallReport(reportInfo, NULL, 0);
283        } else if (ReportStrWith(s, "+CMT:")) {
284            reportInfo.notifyId = HNOTI_SMS_NEW_SMS;
285            OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu));
286        }
287        // Report the events of each module to the hril layer.
288        ...
289    }
290    ```
291
292
2932.  Distribute the reported events from the **hril** layer to the Telephony Service layer.
294
295    ```
296    // Report the call status proactively.
297    int32_t HRilCall::CallStateUpdated(
298        int32_t slotId, int32_t notifyType, const HRilErrno e, const void *response, size_t responseLen)
299    {
300        struct HdfSBuf *dataSbuf = HdfSBufTypedObtain(SBUF_IPC);
301        if (serviceCallbackNotify_ == nullptr) {
302            TELEPHONY_LOGE("RilAdapter serviceCallbackNotify_ is null");
303            HdfSBufRecycle(dataSbuf);
304            return HDF_FAILURE;
305        }
306        // Distribute events.
307        int32_t ret = serviceCallbackNotify_->dispatcher->Dispatch(
308            serviceCallbackNotify_, HNOTI_CALL_STATE_UPDATED, dataSbuf, nullptr);
309        if (ret != HDF_SUCCESS) {
310            HdfSBufRecycle(dataSbuf);
311            return HDF_FAILURE;
312        }
313        HdfSBufRecycle(dataSbuf);
314        return HDF_SUCCESS;
315    }
316    ```
317
318
319### Debugging and Verification
320
3211.  Use the [hdc\_std](../subsystems/subsys-toolchain-hdc-guide.md#how-to-obtain) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
322
323    ```
324    hdc_std file send libril_vendor.z.so /system/lib/
325    ```
326
3272.  Reboot the debugging device.
328
329    ```
330    hdc_std shell sync
331    hdc_std shell reboot
332    ```
333
3343.  Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function.
335
336    ```
337    hdc_std shell
338    # ./system/bin/ril_adapter_test
339    ----> Test Enter  --------->Call---------------------
340
341    1----> RilUnitTest::OnRequestCallDialTest
342    2----> RilUnitTest:: OnRequestCallHangupTest
343    3----> RilUnitTest:: OnRequestCallAnswerTest
344    4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest
345    5----> RilUnitTest::OnRequestRefusedCallTest
346
347    1
348    ```
349
3504.  Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **OnNotifyOps\(\)** is successfully executed. The following debug log is for reference:
351
352    ```
353    01-01 00:08:01.334   546   551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0
354    01-01 00:08:01.334   546   557 D 02b01/TelRilTest: [ProcessEvent-(tel_ril_test.cpp:1262)] TelRilTest::DemoHandler::ProcessEvent --> eventId:101
355    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur :
356    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: ^ORIG:1,0
357    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^ORIG:1,0
358    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^ORIG:1,0
359    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^ORIG:1,0]:(null)
360    01-01 00:08:01.335   143   512 W 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:167)] enter to  is unrecognized command: ^ORIG:1,0
361    01-01 00:08:01.335   143   512 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine  g_bufferCur:
362    01-01 00:08:01.335   143   512 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null
363    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur :
364    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: ^CCALLSTATE: 1,0,1
365    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^CCALLSTATE: 1,0,1
366    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^CCALLSTATE: 1,0,1
367    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^CCALLSTATE: 1,0,1]:(null)
368    01-01 00:08:01.336   546   551 D 02b01/CoreService: [OnRemoteRequest-(tel_ril_manager.cpp:80)] RilManager OnRemoteRequest code:1001
369    01-01 00:08:01.336   546   551 D 02b01/CoreService: [NotifyObserver-(observer_handler.cpp:76)] handler->SendEvent:8
370    ```
371
372
373### Development Examples
374
375-  **Outgoing Call**
376
377    The following figure shows the API calling for an outgoing call.
378
379   **Figure  1** Time sequence of API calling for an outgoing call<a name="fig494mcpsimp"></a>
380
381
382    ![](figures/en-us_image_0000001171507146.png)
383
384   When an application initiates an outgoing call, RIL Adapter receives a call request, and the **hril** layer invokes the **ReqDial\(\)** function. In **ReqDial\(\)**, the data passed by the Telephony Service is encapsulated as an AT command and sent to the modem. After executing the dial command, the modem reports the execution result to RIL Adapter through **OnCallReport\(\)**.
385
386    ```
387    // Callback function pointer of the call module
388    static const HRilCallReq g_callReqOps = {
389        .GetCallList = ReqGetCallList, // Obtain the call list.
390        .Dial = ReqDial,               // Make a call.
391        .Hangup = ReqHangup,           // Disconnect a call.
392        .Reject = ReqReject,           // Reject a call.
393        .Answer = ReqAnswer,           // Answer a call.
394    };
395
396    // Service request APIs
397    HRilOps g_hrilOps = {
398        .callOps = &g_callReqOps,       // API for call service requests
399        .simOps = &g_simReqOps,         // API for SIM card service requests
400        .smsOps = &g_smsReqOps,         // API for SMS and MMS service requests
401        .networkOps = &g_networkReqOps, // API for cellular data service requests
402        .dataOps = &g_dataReqOps,       // API for network search service requests
403        .modemOps = &g_modemReqOps,     // API for modem service requests
404    };
405
406    // Implement the API for processing dial requests.
407    void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen)
408    {
409        HRilDial *pDial = NULL;
410        char cmd[MAX_BUFF_SIZE] = {0};
411        const char *clir = NULL;
412        int ret;
413        int err = HRIL_ERR_SUCCESS;
414        struct ReportInfo reportInfo = {};
415        ResponseInfo *pResponse = NULL;
416        if (data == NULL) {
417            TELEPHONY_LOGE("data is null!!!");
418            err = HRIL_ERR_INVALID_PARAMETER;
419            reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
420            OnCallReport(reportInfo, NULL, 0);
421            return;
422        }
423        pDial = (HRilDial *)data;
424        switch (pDial->clir) {
425            case CALL_CLIR_INVOCATION:
426                clir = "I";
427                break; /* invocation */
428            case CALL_CLIR_SUPPRESSION:
429                clir = "i";
430                break; /* suppression */
431            case CALL_CLIR_SUBSCRIPTION_DEFUALT1:
432            default:
433                clir = "";
434                break; /* subscription default */
435        }
436        (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir);
437        ret = SendCommandLock(cmd, NULL, 0, &pResponse); // Send the AT command.
438        if (ret != 0) {
439            err = HRIL_ERR_CMD_SEND_FAILURE;
440            TELEPHONY_LOGE("ATD send failed");
441        } else {
442            if (pResponse != NULL && pResponse->success == 0) {
443                TELEPHONY_LOGE("ReqDial return ERROR");
444                err = HRIL_ERR_CMD_NO_CARRIER;
445            }
446        }
447        reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
448        OnCallReport(reportInfo, NULL, 0); // Invoke the callback function of the call service.
449        FreeResponseInfo(pResponse);
450    }
451    ```
452
453
454-  **Incoming Call**
455
456    The following figure shows the API calling of an incoming call.
457
458   **Figure  2** Time sequence of API calling for an incoming call<a name="fig556mcpsimp"></a>
459
460
461    ![](figures/en-us_image_0000001214727595.png)
462
463   The **g\_reader** thread cyclically reads the messages reported by the modem. When the modem receives an incoming call event, it actively reports the information about the incoming call.
464
465   The **g\_reader** thread calls **OnNotifyOps\(\)** to parse the reported information. If the parsed data reported by the modem starts with characters such as **+CRING** or **RING**, it indicates that an incoming call event exists. In this case, the event is reported to RIL Adapter through **OnCallReport\(reportInfo, NULL, 0\)**.
466
467    ```
468    // Parse the data reported by the modem as events proactively reported by the corresponding module.
469    void OnNotifyOps(const char *s, const char *smsPdu)
470    {
471        int ret = 0;
472        struct ReportInfo reportInfo = {0};
473        reportInfo.error = HRIL_ERR_SUCCESS;
474        reportInfo.type = HRIL_NOTIFICATION;
475        if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
476            return;
477        }
478        TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu);
479        // Determine the type of the proactively reported events based on the AT command.
480        if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") ||
481            ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") ||
482            ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) {
483            reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED;
484            OnCallReport(reportInfo, NULL, 0);  // Invoke the callback function of the call service.
485        } else if (ReportStrWith(s, "+CMT:")) {
486            reportInfo.notifyId = HNOTI_SMS_NEW_SMS;
487            OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu));
488        }
489        // add your codes
490        ......
491    }
492    ```
493
494
495## Integrating Modem Vendor Libraries
496
497### Configuring Compilation Information
498
499Compile the modem vendor library into a dynamic library by using **BUILD.gn**. Upon startup, RIL Adapter loads the dynamic library to the system in dlopen mode and then initializes the library. For details about how to implement vendor library initialization, see  [Initializing a Modem Vendor Library](#initializing-a-modem-vendor-library). The following is an example of **BUILD.gn**:
500
501```
502import("//build/ohos.gni")
503RIL_ADAPTER = "//base/telephony"
504ohos_shared_library("ril_vendor") { // Modem vendor library
505    sources = [ // Source files to compile
506        "at_call.c",
507        "at_data.c",
508        "xxx.c",
509    ]
510    include_dirs = [ // Header files
511        "$RIL_ADAPTER/ril_adapter/vendor/include",
512        "$RIL_ADAPTER/ril_adapter/interfaces/innerkits",
513        "include",
514    ]
515    deps = [ // Internal dependencies
516        "//drivers/adapter/uhdf2/osal:libhdf_utils",
517        "//base/telephony/core_service/utils:libtelephony_common",
518    ]
519    external_deps = [ "hilog:libhilog" ] // External dependencies
520
521    part_name = "ril_adapter"  // Part name
522    subsystem_name = "telephony" // Subsystem name
523}
524```
525
526### Debugging and Verification
527
5281.  Compile the code.
5292.  Check whether **libril\_vendor.z.so** exists in the **/out/{device_name}/telephony/ril\_adapter** directory. If yes, the integration is successful. Otherwise, correct the error and perform debugging and verification again.
530
531