• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Telephony Development<a name="EN-US_TOPIC_0000001167051994"></a>
2
3## Initializing a Modem Vendor Library<a name="section211mcpsimp"></a>
4
5### When to Use<a name="section213mcpsimp"></a>
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<a name="section811343241215"></a>
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<a name="table223mcpsimp"></a>
20<table><thead align="left"><tr id="row229mcpsimp"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p231mcpsimp"><a name="p231mcpsimp"></a><a name="p231mcpsimp"></a>API</p>
21</th>
22<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p233mcpsimp"><a name="p233mcpsimp"></a><a name="p233mcpsimp"></a>Description</p>
23</th>
24</tr>
25</thead>
26<tbody><tr id="row235mcpsimp"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p237mcpsimp"><a name="p237mcpsimp"></a><a name="p237mcpsimp"></a>const HRilOps *RilInitOps(const struct HRilReport * reportOps)</p>
27</td>
28<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p239mcpsimp"><a name="p239mcpsimp"></a><a name="p239mcpsimp"></a>Function: Provides an entry for running a modem vendor library.</p>
29<p id="p56281836194610"><a name="p56281836194610"></a><a name="p56281836194610"></a>Input parameter:</p>
30<p id="p240mcpsimp"><a name="p240mcpsimp"></a><a name="p240mcpsimp"></a><strong id="b164737479278"><a name="b164737479278"></a><a name="b164737479278"></a>reportOps</strong>: Specifies the pointer to the event callback function, which is passed by RIL Adapter.</p>
31<p id="p241mcpsimp"><a name="p241mcpsimp"></a><a name="p241mcpsimp"></a>Return result: function pointer of the service request API.</p>
32</td>
33</tr>
34</tbody>
35</table>
36
37### How to Develop<a name="section51031144122"></a>
38
391.  Set the event callback function pointers passed by RIL Adapter through  **RilInitOps**.
40
41    ```
42    // Define the callback function pointers of the modem vendor library.
43    static struct HRilReport g_reportOps = {
44        OnCallReport, // Callback function for call services
45        OnDataReport, // Callback function for cellular data services
46        OnModemReport, // Callback function for modem services
47        OnNetworkReport, // Callback function for network search services
48        OnSimReport, // Callback function for SIM card services
49        OnSmsReport // Callback function for SMS services
50    };
51    ```
52
53
541.  Create the  **g\_reader**  main thread to enable message looping.
55
56    ```
57    pthread_attr_t t;
58    pthread_attr_init(&t);
59    pthread_attr_setdetachstate(&t, PTHREAD_CREATE_DETACHED);
60    ret = pthread_create(&g_reader, &t, ReaderLoop, &t); // Create the g_reader thread.
61    ```
62
63
641.  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.
65
66    ```
67    g_fd = open(g_devicePath, O_RDWR); // Open the device node specified by g_devicePath.
68    pthread_attr_init(&attr);
69    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
70    ret = pthread_create(&g_eventListeners, &attr, EventListeners, NULL);
71    ```
72
73
741.  Return the function pointer of the service request API.
75
76    ```
77    // Structure for the service request API of the call module
78    typedef struct {
79        // Obtain the call list.
80        void (*GetCallList)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
81        // Make a call.
82        void (*Dial)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
83        // Disconnect a call.
84        void (*Hangup)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
85        // Reject a call.
86        void (*Reject)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
87        // Answer a call.
88        void (*Answer)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
89    } HRilCallReq;
90
91    // Callback function pointers of the call module
92    static const HRilCallReq g_callReqOps = {
93        .GetCallList = ReqGetCallList, // Obtain the call list.
94        .Dial = ReqDial,               // Make a call.
95        .Hangup = ReqHangup,           // Disconnect a call.
96        .Reject = ReqReject,           // Reject a call.
97        .Answer = ReqAnswer,           // Answer a call.
98    };
99
100    // Service request structure
101    typedef struct {
102        const HRilCallReq *callOps;       // Pointer to the structure of call service requests
103        const HRilSimReq *simOps;         // Pointer to the structure of SIM card service requests
104        const HRilSmsReq *smsOps;         // Pointer to the structure of SMS and MMS service requests
105        const HRilDataReq *dataOps;       // Pointer to the structure of cellular data service requests
106        const HRilNetworkReq *networkOps; // Pointer to the structure of network search service requests
107        const HRilModemReq *modemOps;     // Pointer to the structure of modem service requests
108    } HRilOps;
109
110    // Service request APIs
111    HRilOps g_hrilOps = {
112        .callOps = &g_callReqOps,       // API for call service requests
113        .simOps = &g_simReqOps,         // API for SIM card service requests
114        .smsOps = &g_smsReqOps,         // API for SMS and MMS service requests
115        .networkOps = &g_networkReqOps, // API for cellular data service requests
116        .dataOps = &g_dataReqOps,       // API for network search service requests
117        .modemOps = &g_modemReqOps,     // API for modem service requests
118    };
119    ```
120
121
122### Debugging and Verification<a name="section5351151517132"></a>
123
1241.  Use the  [hdc\_std](subsys-toolchain-hdc-guide.md#section05992022154916)  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](#section590mcpsimp).
125
126    ```
127    hdc_std file send libril_vendor.z.so /system/lib/
128    ```
129
1302.  Reboot the debugging device.
131
132    ```
133    hdc_std shell sync
134    hdc_std shell reboot
135    ```
136
1373.  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:
138
139    ```
140    01-01 05:13:23.071   136  2319 D 00000/RilAdapterInit: [RilAdapterDispatch-(hril_hdf.c:55)] sbuf IPC obtain test success!
141    01-01 05:13:23.071   136  2319 D 00000/RilAdapterInit: [LoadVendor-(hril_hdf.c:33)] RilInit rilInit start
142    01-01 05:13:23.071   136  2319 D 00000/RilAdapterInit: [LoadVendor -(hril_hdf.c:45)] RilInit rilInit completed
143    ```
144
145
146## Responding to Modem Service Requests<a name="section295mcpsimp"></a>
147
148### When to Use<a name="section297mcpsimp"></a>
149
150After 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.
151
152### Available APIs<a name="section9503155219134"></a>
153
154The following table describes the APIs for responding to modem service requests, with the dial module as an example.
155
156**Table  2**  APIs for responding to modem service requests
157
158<a name="table303mcpsimp"></a>
159<table><thead align="left"><tr id="row309mcpsimp"><th class="cellrowborder" valign="top" width="49.84%" id="mcps1.2.3.1.1"><p id="p311mcpsimp"><a name="p311mcpsimp"></a><a name="p311mcpsimp"></a>API</p>
160</th>
161<th class="cellrowborder" valign="top" width="50.160000000000004%" id="mcps1.2.3.1.2"><p id="p313mcpsimp"><a name="p313mcpsimp"></a><a name="p313mcpsimp"></a>Description</p>
162</th>
163</tr>
164</thead>
165<tbody><tr id="row315mcpsimp"><td class="cellrowborder" valign="top" width="49.84%" headers="mcps1.2.3.1.1 "><p id="p317mcpsimp"><a name="p317mcpsimp"></a><a name="p317mcpsimp"></a>void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen);</p>
166</td>
167<td class="cellrowborder" valign="top" width="50.160000000000004%" headers="mcps1.2.3.1.2 "><p id="p319mcpsimp"><a name="p319mcpsimp"></a><a name="p319mcpsimp"></a>Function: Processes number dial requests.</p>
168<p id="p12610151394115"><a name="p12610151394115"></a><a name="p12610151394115"></a>Input parameters:</p>
169<a name="ul105511416204116"></a><a name="ul105511416204116"></a><ul id="ul105511416204116"><li><strong id="b85517162414"><a name="b85517162414"></a><a name="b85517162414"></a>requestInfo</strong>: request type</li></ul>
170<a name="ul1676502416411"></a><a name="ul1676502416411"></a><ul id="ul1676502416411"><li><strong id="b1576510240416"><a name="b1576510240416"></a><a name="b1576510240416"></a>data</strong>: called number</li></ul>
171<a name="ul842034134114"></a><a name="ul842034134114"></a><ul id="ul842034134114"><li><strong id="b1542193411415"><a name="b1542193411415"></a><a name="b1542193411415"></a>dataLen</strong>: data length</li></ul>
172<p id="p323mcpsimp"><a name="p323mcpsimp"></a><a name="p323mcpsimp"></a>Return value: none</p>
173</td>
174</tr>
175<tr id="row324mcpsimp"><td class="cellrowborder" valign="top" width="49.84%" headers="mcps1.2.3.1.1 "><p id="p326mcpsimp"><a name="p326mcpsimp"></a><a name="p326mcpsimp"></a>void (*OnCallReport)(struct ReportInfo reportInfo, const void *data, size_t dataLen);</p>
176</td>
177<td class="cellrowborder" valign="top" width="50.160000000000004%" headers="mcps1.2.3.1.2 "><p id="p328mcpsimp"><a name="p328mcpsimp"></a><a name="p328mcpsimp"></a>Function: Reports the execution result of a service request to RIL Adapter.</p>
178<p id="p489264432"><a name="p489264432"></a><a name="p489264432"></a>Input parameters:</p>
179<a name="ul44156301444"></a><a name="ul44156301444"></a><ul id="ul44156301444"><li><strong id="b15415930154418"><a name="b15415930154418"></a><a name="b15415930154418"></a>reportInfo</strong>: request type</li></ul>
180<a name="ul18380115494513"></a><a name="ul18380115494513"></a><ul id="ul18380115494513"><li><strong id="b83808549457"><a name="b83808549457"></a><a name="b83808549457"></a>data</strong>: called number</li></ul>
181<a name="ul118421156184517"></a><a name="ul118421156184517"></a><ul id="ul118421156184517"><li><strong id="b48421056144519"><a name="b48421056144519"></a><a name="b48421056144519"></a>dataLen</strong>: data length</li></ul>
182<p id="p332mcpsimp"><a name="p332mcpsimp"></a><a name="p332mcpsimp"></a>Return value: none</p>
183</td>
184</tr>
185</tbody>
186</table>
187
188### How to Develop<a name="section17190412101414"></a>
189
1901.  Implement processing of dial requests in the  **ReqDial\(\)**  API.
191
192    ```
193    // Implement the API for processing dial requests.
194    void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen)
195    {
196        HRilDial *pDial = NULL;
197        char cmd[MAX_BUFF_SIZE] = {0};
198        const char *clir = NULL;
199        int ret;
200        int err = HRIL_ERR_SUCCESS;
201        struct ReportInfo reportInfo = {};
202        ResponseInfo *pResponse = NULL;
203        if (data == NULL) {
204            TELEPHONY_LOGE("data is null!!!");
205            err = HRIL_ERR_INVALID_PARAMETER;
206            reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
207            OnCallReport(reportInfo, NULL, 0);
208            return;
209        }
210        pDial = (HRilDial *)data;
211        switch (pDial->clir) {
212            case CALL_CLIR_INVOCATION:
213                clir = "I";
214                break; /* invocation */
215            case CALL_CLIR_SUPPRESSION:
216                clir = "i";
217                break; /* suppression */
218            case CALL_CLIR_SUBSCRIPTION_DEFUALT:
219            default:
220                clir = "";
221                break; /* subscription default */
222        }
223        (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir);
224        ret = SendCommandLock(cmd, NULL, 0, &pResponse); // Send the AT command.
225        ......
226    }
227    ```
228
2292.  After the modem executes the dial command, report the execution result to RIL Adapter via  **OnCallReport\(\)**.
230
231    ```
232    ret = SendCommandLock(cmd, NULL, 0, &pResponse);
233    if (ret != 0 || (pResponse != NULL && pResponse->success == 0)) {
234        TELEPHONY_LOGE("ATD send failed");
235        err = HRIL_ERR_GENERIC_FAILURE;
236    }
237    reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
238    OnCallReport(reportInfo, NULL, 0); // Invoke the callback function of the call service.
239    ```
240
241
242### Debugging and Verification<a name="section10207938171413"></a>
243
2441.  Use the  [hdc\_std](subsys-toolchain-hdc-guide.md#section05992022154916)  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.
245
246    ```
247    hdc_std file send libril_vendor.z.so /system/lib/
248    ```
249
2502.  Reboot the debugging device.
251
252    ```
253    hdc_std shell sync
254    hdc_std shell reboot
255    ```
256
2573.  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.
258
259    ```
260    hdc_std shell
261    # ./system/bin/ril_adapter_test
262    ----> Test Enter  --------->Call---------------------
263
264    1----> RilUnitTest::OnRequestCallDialTest
265    2----> RilUnitTest:: OnRequestCallHangupTest
266    3----> RilUnitTest:: OnRequestCallAnswerTest
267    4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest
268    5----> RilUnitTest::OnRequestRefusedCallTest
269
270    1
271    ```
272
2734.  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:
274
275    ```
276    01-01 05:27:27.419   136   408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:210)] SendCommandLock enter, cmd: ATD17620373527
277    01-01 05:27:27.419   136   408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:231)] SendCommandLock() command ATD17620373527
278    01-01 05:27:27.419   136   408 D 02b01/Rilvendor: [WriteATCommand-(channel.c:115)] WriteATCommand enter, cmd:ATD17620373527
279    01-01 05:27:27.421   136   187 D 02b01/Rilvendor: [ReadResponse-(channel.c:94)] g_bufferCur :
280    01-01 05:27:27.421   136   187 D 02b01/Rilvendor: OK
281    01-01 05:27:27.422   136   187 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:144)] processLine line = OK
282    01-01 05:27:27.422   136   187 D 02b01/Rilvendor: [ReadResponse-(channel.c:81)] ReadResponse enter
283    01-01 05:27:27.422   136   187 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine  g_bufferCur:
284    01-01 05:27:27.422   136   187 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null
285    01-01 05:27:27.422   136   187 E 02b01/Rilvendor:^ORIG:1,0
286    01-01 05:27:27.422   136   408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:234)] processLine line = ^ORIG:1,0
287    01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(vendor_report.c:234)] enter to [^ORIG:1,0]: (null)
288    01-01 05:27:27.422   136   408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:264)] err = 0, cmd:ADT17620373527
289    ```
290
291
292## Reporting Modem Events<a name="section390mcpsimp"></a>
293
294### When to Use<a name="section401mcpsimp"></a>
295
296A 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.
297
298### Available APIs<a name="section191193791518"></a>
299
300The following table describes the API for reporting modem events.
301
302**Table  3**  API for reporting modem events
303
304<a name="table407mcpsimp"></a>
305<table><thead align="left"><tr id="row413mcpsimp"><th class="cellrowborder" valign="top" width="52%" id="mcps1.2.3.1.1"><p id="p415mcpsimp"><a name="p415mcpsimp"></a><a name="p415mcpsimp"></a>API</p>
306</th>
307<th class="cellrowborder" valign="top" width="48%" id="mcps1.2.3.1.2"><p id="p417mcpsimp"><a name="p417mcpsimp"></a><a name="p417mcpsimp"></a>Description</p>
308</th>
309</tr>
310</thead>
311<tbody><tr id="row419mcpsimp"><td class="cellrowborder" valign="top" width="52%" headers="mcps1.2.3.1.1 "><p id="p421mcpsimp"><a name="p421mcpsimp"></a><a name="p421mcpsimp"></a>void OnNotifyOps(const char *s, const char *smsPdu)</p>
312</td>
313<td class="cellrowborder" valign="top" width="48%" headers="mcps1.2.3.1.2 "><p id="p423mcpsimp"><a name="p423mcpsimp"></a><a name="p423mcpsimp"></a>Function: Distributes the events reported by the modem.</p>
314<p id="p17924530141912"><a name="p17924530141912"></a><a name="p17924530141912"></a>Input parameters:</p>
315<a name="ul678053915191"></a><a name="ul678053915191"></a><ul id="ul678053915191"><li><strong id="b14780173912196"><a name="b14780173912196"></a><a name="b14780173912196"></a>s</strong>: AT command prefix</li></ul>
316<a name="ul206343434192"></a><a name="ul206343434192"></a><ul id="ul206343434192"><li><strong id="b65891958173518"><a name="b65891958173518"></a><a name="b65891958173518"></a>smsPdu</strong>: PDU of the SMS message</li></ul>
317<p id="p426mcpsimp"><a name="p426mcpsimp"></a><a name="p426mcpsimp"></a>Return value: none</p>
318</td>
319</tr>
320</tbody>
321</table>
322
323### How to Develop<a name="section16394112401512"></a>
324
3251.  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.
326
327    ```
328    // Parse the data reported by the modem as events proactively reported by the corresponding module.
329    void OnNotifyOps(const char *s, const char *smsPdu)
330    {
331        int ret = 0;
332        struct ReportInfo reportInfo = {0};
333        reportInfo.error = HRIL_ERR_SUCCESS;
334        reportInfo.type = HRIL_NOTIFICATION;
335        if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
336            return;
337        }
338        TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu);
339        // Determine the type of the proactively reported events based on the AT command.
340        if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") ||
341            ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") ||
342            ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) {
343            reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED;
344            OnCallReport(reportInfo, NULL, 0);
345        } else if (ReportStrWith(s, "+CMT:")) {
346            reportInfo.notifyId = HNOTI_SMS_NEW_SMS;
347            OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu));
348        }
349        // Report the events of each module to the hril layer.
350        ...
351    }
352    ```
353
354
3551.  Distribute the reported events from the  **hril**  layer to the Telephony Service layer.
356
357    ```
358    // Report the call status proactively.
359    int32_t HRilCall::CallStateUpdated(
360        int32_t slotId, int32_t notifyType, const HRilErrno e, const void *response, size_t responseLen)
361    {
362        struct HdfSBuf *dataSbuf = HdfSBufTypedObtain(SBUF_IPC);
363        if (serviceCallbackNotify_ == nullptr) {
364            TELEPHONY_LOGE("RilAdapter serviceCallbackNotify_ is null");
365            HdfSBufRecycle(dataSbuf);
366            return HDF_FAILURE;
367        }
368        // Distribute events.
369        int32_t ret = serviceCallbackNotify_->dispatcher->Dispatch(
370            serviceCallbackNotify_, HNOTI_CALL_STATE_UPDATED, dataSbuf, nullptr);
371        if (ret != HDF_SUCCESS) {
372            HdfSBufRecycle(dataSbuf);
373            return HDF_FAILURE;
374        }
375        HdfSBufRecycle(dataSbuf);
376        return HDF_SUCCESS;
377    }
378    ```
379
380
381### Debugging and Verification<a name="section16999174401516"></a>
382
3831.  Use the  [hdc\_std](subsys-toolchain-hdc-guide.md#section05992022154916)  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.
384
385    ```
386    hdc_std file send libril_vendor.z.so /system/lib/
387    ```
388
3892.  Reboot the debugging device.
390
391    ```
392    hdc_std shell sync
393    hdc_std shell reboot
394    ```
395
3963.  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.
397
398    ```
399    hdc_std shell
400    # ./system/bin/ril_adapter_test
401    ----> Test Enter  --------->Call---------------------
402
403    1----> RilUnitTest::OnRequestCallDialTest
404    2----> RilUnitTest:: OnRequestCallHangupTest
405    3----> RilUnitTest:: OnRequestCallAnswerTest
406    4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest
407    5----> RilUnitTest::OnRequestRefusedCallTest
408
409    1
410    ```
411
4124.  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:
413
414    ```
415    01-01 00:08:01.334   546   551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0
416    01-01 00:08:01.334   546   557 D 02b01/TelRilTest: [ProcessEvent-(tel_ril_test.cpp:1262)] TelRilTest::DemoHandler::ProcessEvent --> eventId:101
417    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur :
418    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: ^ORIG:1,0
419    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^ORIG:1,0
420    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^ORIG:1,0
421    01-01 00:08:01.334   143   512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^ORIG:1,0]:(null)
422    01-01 00:08:01.335   143   512 W 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:167)] enter to  is unrecognized command: ^ORIG:1,0
423    01-01 00:08:01.335   143   512 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine  g_bufferCur:
424    01-01 00:08:01.335   143   512 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null
425    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur :
426    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: ^CCALLSTATE: 1,0,1
427    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^CCALLSTATE: 1,0,1
428    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^CCALLSTATE: 1,0,1
429    01-01 00:08:01.336   143   512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^CCALLSTATE: 1,0,1]:(null)
430    01-01 00:08:01.336   546   551 D 02b01/CoreService: [OnRemoteRequest-(tel_ril_manager.cpp:80)] RilManager OnRemoteRequest code:1001
431    01-01 00:08:01.336   546   551 D 02b01/CoreService: [NotifyObserver-(observer_handler.cpp:76)] handler->SendEvent:8
432    ```
433
434
435### Development Examples<a name="section33444350167"></a>
436
437-   **Outgoing Call**
438
439    The following figure shows the API calling for an outgoing call.
440
441    **Figure  1**  Time sequence of API calling for an outgoing call<a name="fig494mcpsimp"></a>
442
443
444    ![](figure/en-us_image_0000001171507146.png)
445
446    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\(\)**.
447
448    ```
449    // Callback function pointer of the call module
450    static const HRilCallReq g_callReqOps = {
451        .GetCallList = ReqGetCallList, // Obtain the call list.
452        .Dial = ReqDial,               // Make a call.
453        .Hangup = ReqHangup,           // Disconnect a call.
454        .Reject = ReqReject,           // Reject a call.
455        .Answer = ReqAnswer,           // Answer a call.
456    };
457
458    // Service request APIs
459    HRilOps g_hrilOps = {
460        .callOps = &g_callReqOps,       // API for call service requests
461        .simOps = &g_simReqOps,         // API for SIM card service requests
462        .smsOps = &g_smsReqOps,         // API for SMS and MMS service requests
463        .networkOps = &g_networkReqOps, // API for cellular data service requests
464        .dataOps = &g_dataReqOps,       // API for network search service requests
465        .modemOps = &g_modemReqOps,     // API for modem service requests
466    };
467
468    // Implement the API for processing dial requests.
469    void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen)
470    {
471        HRilDial *pDial = NULL;
472        char cmd[MAX_BUFF_SIZE] = {0};
473        const char *clir = NULL;
474        int ret;
475        int err = HRIL_ERR_SUCCESS;
476        struct ReportInfo reportInfo = {};
477        ResponseInfo *pResponse = NULL;
478        if (data == NULL) {
479            TELEPHONY_LOGE("data is null!!!");
480            err = HRIL_ERR_INVALID_PARAMETER;
481            reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
482            OnCallReport(reportInfo, NULL, 0);
483            return;
484        }
485        pDial = (HRilDial *)data;
486        switch (pDial->clir) {
487            case CALL_CLIR_INVOCATION:
488                clir = "I";
489                break; /* invocation */
490            case CALL_CLIR_SUPPRESSION:
491                clir = "i";
492                break; /* suppression */
493            case CALL_CLIR_SUBSCRIPTION_DEFUALT:
494            default:
495                clir = "";
496                break; /* subscription default */
497        }
498        (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir);
499        ret = SendCommandLock(cmd, NULL, 0, &pResponse); // Send the AT command.
500        if (ret != 0) {
501            err = HRIL_ERR_CMD_SEND_FAILURE;
502            TELEPHONY_LOGE("ATD send failed");
503        } else {
504            if (pResponse != NULL && pResponse->success == 0) {
505                TELEPHONY_LOGE("ReqDial return ERROR");
506                err = HRIL_ERR_CMD_NO_CARRIER;
507            }
508        }
509        reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
510        OnCallReport(reportInfo, NULL, 0); // Invoke the callback function of the call service.
511        FreeResponseInfo(pResponse);
512    }
513    ```
514
515
516-   **Incoming Call**
517
518    The following figure shows the API calling of an incoming call.
519
520    **Figure  2**  Time sequence of API calling for an incoming call<a name="fig556mcpsimp"></a>
521
522
523    ![](figure/en-us_image_0000001214727595.png)
524
525    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.
526
527    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\)**.
528
529    ```
530    // Parse the data reported by the modem as events proactively reported by the corresponding module.
531    void OnNotifyOps(const char *s, const char *smsPdu)
532    {
533        int ret = 0;
534        struct ReportInfo reportInfo = {0};
535        reportInfo.error = HRIL_ERR_SUCCESS;
536        reportInfo.type = HRIL_NOTIFICATION;
537        if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
538            return;
539        }
540        TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu);
541        // Determine the type of the proactively reported events based on the AT command.
542        if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") ||
543            ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") ||
544            ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) {
545            reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED;
546            OnCallReport(reportInfo, NULL, 0);  // Invoke the callback function of the call service.
547        } else if (ReportStrWith(s, "+CMT:")) {
548            reportInfo.notifyId = HNOTI_SMS_NEW_SMS;
549            OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu));
550        }
551        // add your codes
552        ......
553    }
554    ```
555
556
557## Integrating Modem Vendor Libraries<a name="section590mcpsimp"></a>
558
559### Configuring Compilation Information<a name="section592mcpsimp"></a>
560
561Compile 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](#section211mcpsimp). The following is an example of  **BUILD.gn**:
562
563```
564import("//build/ohos.gni")
565RIL_ADAPTER = "//base/telephony"
566ohos_shared_library("ril_vendor") { // Modem vendor library
567    sources = [ // Source files to compile
568        "at_call.c",
569        "at_data.c",
570        "xxx.c",
571    ]
572    include_dirs = [ // Header files
573        "$RIL_ADAPTER/ril_adapter/vendor/include",
574        "$RIL_ADAPTER/ril_adapter/interfaces/innerkits",
575        "include",
576    ]
577    deps = [ // Internal dependencies
578        "//drivers/adapter/uhdf2/osal:libhdf_utils",
579        "//base/telephony/core_service/utils:libtelephony_common",
580    ]
581    external_deps = [ "hilog:libhilog" ] // External dependencies
582
583    part_name = "ril_adapter"  // Part name
584    subsystem_name = "telephony" // Subsystem name
585}
586```
587
588### Debugging and Verification<a name="section620mcpsimp"></a>
589
5901.  Compile the code.
5912.  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.
592
593