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)