In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces you the example analysis of the Android GSM driver module, the content is very detailed, interested friends can refer to, hope to be helpful to you.
The RIL driver module of Android is divided into three parts: rild,libril.so and librefrence_ril.so under the hardware/ril directory, and another radiooptions can be used for automatic or manual debugging. All depend on the rilh header file in the include directory. At present, the cupcake branch is supported by gsm, and there is another cdma branch, which is analyzed here as the gsm driver.
GSM module, due to the history of Modem, AP has been interacting with BB through serial port-based AT commands. Some current edge or 3G modules, or ap,bp integrated chips like omap, have used USB or other high-speed bus communication, but most of them still use analog serial port mechanism to use AT commands. The RIL (Radio Interface Layer) layer here is mainly based on AT command operations, such as issuing commands, response parsing and so on. (the MUX protocol used by gprs and other transmissions is not included here and will not be introduced for the time being. )
The following is a detailed analysis, mainly involving the basic architecture and initialization:
First, let's introduce the relationship between rild and libril.so as well as librefrence_ril.so:
1. Rild:
Only one main function is implemented as the entry point of the entire ril layer and is responsible for completing the initialization.
2. Libril.so:
It is closely integrated with rild and is its shared library, and this relationship has been established at compile time. The component is ril.cpp,ril_event.cpp. Libril.so resides in the rild daemon, which mainly communicates with the upper layer, accepts the ril request and passes it to the librefrence_ril.so, and sends the feedback from the librefrence_ril.so back to the calling process.
3. Librefrence_ril.so:
Rild is loaded manually by dlopen, and the binding is slightly loose, which is also because librefrence.so is mainly responsible for communicating with Modem hardware. This makes it easier to replace or modify to fit more Modem types. It converts requests from libril.so to AT commands, monitors feedback from Modem, and passes it back to libril.so. During initialization, rild takes a set of function pointers through the symbol RIL_Init and establishes a relationship with it.
4. Radiooptions:
Radiooptiongs uses socket to communicate with rild by obtaining startup parameters, which can be used to configure Modem parameters during debugging.
Next, the initialization process is analyzed. The main entry is the main function in rild.c, which mainly completes three tasks:
1. Turn on the event mechanism in libril.so. In RIL_startEventLoop, it is the core message loop driven by multi-channel Imax O.
two。 Initializing the librefrence_ril.so, that is, the part that communicates with the hardware or analog hardware modem (hereinafter referred to as hardware), is done through the RIL_Init function.
3. Get a set of function pointers RIL_RadioFunctions through RIL_Init, complete the registration through RIL_register, and open the socket channel that accepts upper-level commands.
First of all, let's take a look at the * tasks, that is, the RIL_startEventLoop function. RIL_startEventLoop is implemented in ril.cpp. Its main purpose is to set up a thread through pthread_create (& s_tid_dispatch, & attr, eventLoop, NULL), and the entry point is in eventLoop. In eventLoop, the ril_event_loop () function in ril_event.cpp is called to establish a message (event) queue mechanism.
Let's take a closer look at the mechanism of this message queue, which is all in ril_event.cpp.
Void ril_event_init ()
Void ril_event_set (struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
Void ril_event_add (struct ril_event * ev)
Void ril_timer_add (struct ril_event * ev, struct timeval * tv)
Void ril_event_del (struct ril_event * ev)
Void ril_event_loop ()
Struct ril_event {
Struct ril_event * next
Struct ril_event * prev
Int fd
Int index
Bool persist
Struct timeval timeout
Ril_event_cb func
Void * param
}
Each ril_event structure is bound to a fd handle (which can be a file, socket, pipe, etc.) and takes a func pointer to perform the specified operation.
The specific process is as follows: after the ril_event_init is completed, configure a new ril_event through ril_event_set, and join the queue through ril_event_add (usually added by rilEventAddWakeup). Add will put the fd of all ril_event in the queue into a fd collection readFds. In this way, ril_event_loop can wait for these fd through a multiplexing mechanism (select). If any fd has data written, it goes into the analysis process processTimeouts (), processReadReadies (& rfds, n), firePending (). These processes will be analyzed in detail later.
In addition, we can see that an s _ wakeupfd_event has been linked before entering ril_event_loop, which is realized through the mechanism of pipe. The purpose of this event is to wake up the multiplexing blocking of ril_event_loop internally in some cases, such as when some commands with timeout timeout expire.
At this point, the * task analysis is completed, so a message loop based on event queue is established, and the request sent by the upper layer can be accepted later (the event object of the upper layer request is established in the third task).
Next, let's look at the second task. The entry of this task is RIL_Init. RIL_Init first gets the device file of the hardware interface or the socket of the analog hardware interface through parameters. Then a new thread is opened to continue initialization, that is, mainLoop.
The main task of mainLoop is to establish communication with the hardware, and then block and wait for the active report or response of the hardware through the read method. After registering some basic callbacks (timeout,readerclose), mainLoop first opens the hardware device file to establish communication with the hardware. S_device_path and s_port are the device path parameters obtained earlier and open them (both can be opened and have their own reader at the same time, and it is easy to add dual-card dual-standby support here).
Next, the reader wait loop on the device file is established through the at_open function, which is also done by creating a new thread, ret = pthread_create (& s_tid_reader, & attr, readerLoop, & attr), entry point readerLoop.
AT commands are delimited by line breaks of\ r\ n or\ n\ r, so readerLoop is driven by line. Unless there is an error, timeout, etc., a complete line of responses or active reports will be read before returning. With this loop running, our basic AT response mechanism has been established. Its specific analysis, including the ATUnsolHandler attached to at_open, is included in the serial articles that analyze response later.
With the response mechanism (of course, the ability to communicate with the hardware can also make requests), through RIL_requestTimedCallback (initializeCallback, NULL, & TIMEVAL_0), run to initializeCallback and execute some Modem initialization commands, mainly in the way of AT commands. The process of issuing AT commands will be included in a serial article that analyzes request later. As you can see here, it is mainly some parameter configuration, as well as the network status check and so on. At this point, the analysis of the second task is complete, and the hardware is accessible.
* is the third task. The third task starts with the return value of RIL_Init, which is a pointer to the RIL_RadioFunctions structure.
Typedef struct {
Int version; / * set to RIL_VERSION * /
RIL_RequestFunc onRequest
RIL_RadioStateRequest onStateRequest
RIL_Supports supports
RIL_Cancel onCancel
RIL_GetVersion getVersion
} RIL_RadioFunctions
The most important of these is the onrequest field, where requests from the upper layer are mapped by this function and converted into corresponding AT commands to be sent to the hardware. Rild registers this pointer through RIL_register.
Another task to be accomplished in RIL_register is to open the previously mentioned socket interface that communicates with the upper layer (s_fdListen is the primary interface and s_fdDebug is used for debugging).
Then register the two socket interfaces using the mechanism implemented in Task 1 (only s_fdListen is listed)
Ril_event_set (& s_listen_event, s_fdListen, false
ListenCallback, NULL)
RilEventAddWakeup & s_listen_event)
In this way, two socket are added to the set of check handles that set up the multiplexed I socket O in Task 1, and once there is a request from the upper layer, the event mechanism can respond to the processing. At this point, the startup process has been analyzed.
This is the end of the sample analysis of the Android GSM driver module. I hope the above content can be helpful to you and learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.