4 mechanizmus Android QMI --- prenos správ QCRIL

4 Android Qmi Mechanism Qcril Message Transmission



originál: https://blog.csdn.net/u012439416/article/details/74276765

4 Prenos správ QCRIL
Keď má ril požiadavku, zavolá metódu onRequest () knižnice ril. V tomto okamihu to bude založené na zozname funkcií registrovaných s aktuálnym Qcril.



Zadajte metódu onRequest_rid pre qcril_request_api, takže metóda onRequest_rid je záznam v QCRIL.



metóda. Proces volania je nasledovný,



Qcril_execute_event najskôr zavolá metódu qcril_hash_table_lookup, aby vyhľadala aktuálnu udalosť z tabuľky, ak nie

Nájdite aktuálnu požiadavku, považuje sa to za nezákonnú, po jej nájdení zadajte príkaz qcril_dispatch_event () na odoslanie udalosti,

(entry_ptr-> obslužný program) (params_ptr, & ret)



Ret je výsledkom návratu, aktuálny obslužný program udalosti sa volá obslužný program entry_ptr->. Tu zodpovedajúci psovod

Položka v tabuľke qcril_hash_table. V prvej kapitole sa údaje v tabuľke qcril_event_table skopírujú do tabuľky qcril_hash_table.

Handler tu teda možno chápať ako položku v qcril_event_table.

Potom, čo proces vstúpi do funkcie spracovania konkrétnej požiadavky, ako je napríklad hovor, príslušná požiadavka je RIL_REQUEST_DIAL,

Jeho funkcia spracovania je: qcril_qmi_voice_request_dial požiadavka na zavesenie telefónu je RIL_REQUEST_HANGUP,

Jeho funkciou spracovania je qcril_qmi_voice_request_hangup

Metóda qcril_qmi_voice_request_hangup ďalej volá qcril_qmi_client_send_msg_async, aby ich poslala do vrstvy QMI.

S qcril_qmi_client_send_msg_async sa samozrejme pracuje asynchrónne a qcril_qmi_client_send_msg_sync sa spracováva synchrónne.

Nakoniec obidve metódy zavolajú qmi_client_send_msg_sync na dokončenie odoslania.

Niektoré ďalšie metódy spracovania môžu volať tieto dve metódy na odoslanie do vrstvy QMI alebo priamo zavolať qmi_client_send_msg_sync na odoslanie.
2.1 Spracovanie správy vrstvy QMI

Vývojový diagram hovorov je nasledovný,

ril_err = qcril_qmi_client_send_msg_async (QCRIL_QMI_CLIENT_VOICE,
QMI_VOICE_ANSWER_CALL_REQ_V02,
& ans_call_req_msg,
sizeof (ans_call_req_msg),
ans_call_resp_msg_ptr,
sizeof (* ans_call_resp_msg_ptr),
(void *) (uintptr_t) user_data)

Tu vybraná služba qmi_service je hlas. Dôvod, prečo je hlas vybraný ako prenosový kanál, je ten, že druhým parametrom je QMI_VOICE_GET_CONFIG_REQ_V02.

Hlavná logika metódy qcril_qmi_client_send_msg_async je nasledovná.

if (NULL! = client_info.qmi_svc_clients [svc_type])
{
qmi_error = qmi_client_send_msg_async_with_shm (client_info.qmi_svc_clients [svc_type],
•••

Táto funkcia najskôr určí, či typ služby hlasu, ktorý voláme, existuje v zozname služieb definovanom QMI. Ak neexistuje,

Tiež je potrebné pridať službu sami. Ak existuje, vykonajte funkciu rozhrania qmi_client_send_msg_async_with_shm, ktorá odošle správu klientovi QMI.

Táto metóda priamo volá metódu qmi_client_send_msg_sync.
rc = qmi_client_send_msg_sync (user_handle,
msg_id,
req_c_struct,
req_c_struct_len,
resp_c_struct,
resp_c_struct_len,
timeout_msecs)

Po odoslaní synchronizačnej správy na stranu BP vo vrstve QMUX bude čakať na odpoveď BP, takže posledným parametrom funkcie je časový limit.

Asynchrónne správy sa nevyžadujú.

Metóda qmi_client_send_msg_sync najskôr vypočíta dĺžku správy s požiadavkou a nastaví maximálnu dĺžku vrátenej správy, potom požiadavku

Správa je kódovaná vo formáte QMUX a odosielaná pomocou funkcie qmi_service_send_msg_sync_millisec (). Nakoniec

Počkajte na odpoveď vrátenú stranou BP a dekódujte vrátenú odpoveď.

2.2 Spracovanie správy vrstvy QMUX

Vývojový diagram spracovania správ QMUX je nasledovný.

Metóda qmi_service_send_msg_sync_millisec najskôr získa niektoré správy vyžadované vrstvou QMUX a odošle conn_id kanála.

Client_id použitý vo formáte správy QMUX

conn_id = QMI_SRVC_CLIENT_HANDLE_TO_CONN_ID (manipulácia s používateľom)

client_id = QMI_SRVC_CLIENT_HANDLE_TO_CLIENT_ID (užívateľská rukoväť)

Potom sa zabalí do štruktúry, ktorá prenáša správu qmi_service_txn_info_type * txn, ktorú nájdeme neskôr v nasledujúcom kóde.

Je tranciationID v správe QMUX.

/ * Inicializácia identifikačných polí * /
txn-> conn_id = conn_id
txn-> service_id = service_id
txn-> client_id = client_id
txn-> msg_id = msg_id
txn-> api_flag = api_flag
/ * Inicializovať polia * /
txn-> srvc_txn_info.txn_type = QMI_TXN_SYNC
txn-> srvc_txn_info.sync_async.sync.user_reply_buf = NULL
txn-> srvc_txn_info.sync_async.sync.user_reply_buf_size = 0
txn-> srvc_txn_info.sync_async.sync.rsp_rc = QMI_NO_ERR
txn-> srvc_txn_info.sync_async.sync.qmi_err_code = QMI_SERVICE_ERR_NONE


Po ich dokončení je volaná metóda qmi_service_send_msg na odoslanie. Táto metóda určuje, či sú ID služby a conn_id kanála platné.

if ((int) conn_id> = (int) QMI_MAX_CONN_IDS)
{
vrátiť QMI_INTERNAL_ERR
}
if (qmi_qcci_internal_public_service_id_to_bookkeeping_service_id (service_id)> =
QMI_MAX_SERVICES)
{
vrátiť QMI_INTERNAL_ERR
}

Najskôr zavolajte qmi_service_write_std_srvc_msg_hdr, metóda k odoslanej správe pridá ID a dĺžku správy.

if (qmi_service_write_std_srvc_msg_hdr (& msg_buf,
& msg_buf_size,
msg_id,
msg_buf_size)<0)

Nie je teda ťažké uhádnuť, že princíp kodeku vo funkcii rozhrania qmi_client_send_msg_sync () odosielateľa QMI je podľa QMUX.

Formát TLV v správe je kódovaný. Potom choďte na tento krok plus ID správy a dĺžka, správa služby QMI v celej QMUX SDU

dokončené. Metóda qmi_service_write_std_srvc_msg_hdr je nasledovná.

statický
int qmi_service_write_std_srvc_msg_hdr (nepodpísaný znak ** msg_buf,
int * msg_buf_size, nepodpísaný dlhý msg_id, int dĺžka)
{
nepodpísaný znak * tmp_msg_buf
/ * Zadný ukazovateľ nahor o 4 bajty * /
* msg_buf - = QMI_SRVC_STD_MSG_HDR_SIZE
* msg_buf_size + = QMI_SRVC_STD_MSG_HDR_SIZE
tmp_msg_buf = * msg_buf
/ * Napíš do políčka ID správy (16 bitov) * /
WRITE_16_BIT_VAL (tmp_msg_buf, msg_id)
/ * Napíšte pole dĺžky * /
WRITE_16_BIT_VAL (tmp_msg_buf, dĺžka)
návrat 0
}

Spôsob pridania ID a dĺžky správy: posun ukazovateľa správy. Ukazovateľ sa posunie dopredu a dĺžka správy sa zvýši. Potom použite podobnú metódu,

Kontrolné príznaky a tranciačné ID sú pridané funkciou qmi_service_write_std_txn_hdr_and_inc_txn_id ().

Vyplňte celý QMUX SDU. Nakoniec sa odošle do vrstvy QMUX prostredníctvom funkcie qmi_qmux_if_send_qmi_msg (), tu,

Po dokončení celého procesu rozhrania QMI je hlavnou funkciou získanie žiadosti odoslanej hornou vrstvou a výber zodpovedajúceho serviceid, conn_id, id klienta,

Správa dokončí zapuzdrenie celého QMUX SDU a odošle sa do QMUX.

Funkciou funkcie qmi_qmux_if_send_qmi_msg () je pridať zabalenú QMUX SDU do hornej vrstvy.

QMUX HEADER funguje. Metóda pridania hlavičky QMUX je tiež posunutím ukazovateľa.

Metóda qmi_qmux_if_send_qmi_msg priamo volá metódu qmi_qmux_if_send_to_qmux na spracovanie.

Najskôr sú riadiace bity, ID služby QMI a ID klienta QMI v hlavičke QMUX zabalené do štruktúry hdr a potom doplnené Memcpy.
/ * Nastaviť správu na odoslanie * /
memset (& hdr, 0, sizeof (qmi_qmux_if_msg_hdr_type))
hdr.msg_id = msg_id
hdr.qmux_client_id = qmux_client_id
hdr.qmux_txn_id = qmux_txn_id
hdr.qmi_conn_id = qmi_conn_id
hdr.qmi_service_id = qmi_service_id
hdr.qmi_client_id = qmi_client_id
hdr.control_flags = 0 // Nepoužíva sa pre TX na QMUX, platí iba pre RX
/ * Zmenšiť ukazovateľ msg a prírastok msg_len * /
správa - = QMI_QMUX_IF_HDR_SIZE
msg_len + = (int) QMI_QMUX_IF_HDR_SIZE
/ * Skopírujte hlavičku do medzipamäte správy * /
memcpy ((void *) msg, (void *) & hdr, QMI_QMUX_IF_HDR_SIZE)

Je tu zabalená celá správa QMUXMessage. Potom bude volanie makra odoslaná zabalená správa QMUXmage do nižšej vrstvy.

QMI_QMUX_IF_PLATFORM_TX_MSG (). Toto makro definuje funkciu linux_qmi_qmux_if_client_tx_msg ().

Makro QMI_QMUX_IF_PLATFORM_TX_MSG v qmi_platform_qmux_if.h je definované nasledovne.

#define QMI_QMUX_IF_PLATFORM_TX_MSG (klient, správa, správa_len)

linux_qmi_qmux_if_client_tx_msg (klient, msg, msg_len)

Preto volanie makra QMI_QMUX_IF_PLATFORM_TX_MSG znamená volanie metódy linux_qmi_qmux_if_client_tx_msg.

Táto metóda posiela správu na rozhranie linux_qmi_qmux_if_server cez soket.

if ((rc = send (client_fd,
(neplatné *) správa,
(size_t) msg_len,
MSG_DONTWAIT | MSG_NOSIGNAL))<0)