Chan vgsm
From VoiSmart Open Source Wiki
The chan_vgsm.so Asterisk's module is a quite complex plug-in that provides:
- The VGSM channel type
- Several management, monitoring and debugging CLI commands
- Inbound SMS (SMS-DELIVER) spooling
- Outbound SMS (SMS-SUBMIT) submission through AMI
Internally, several thread get spawned by chan_vgsm module, a description of each thread role follows:
Contents |
monitor thread
Within chan_vgsm each module is managed by a monitor thread whose purpose is to handle power-on, power-off and reset sequences, initialize the GSM module, monitor the registration status, handle failures and recovery. The monitor thread is based on a state machine with the following states:
- CLOSED
- OFF
- POWERING_ON
- POWERING_OFF
- RESETTING
- WAITING_INITIALIZATION
- INITIALIZING
- READY
- WAITING_SIM
- WAITING_PIN
- FAILED
Transitions from one state to another is caused by external events or timers.
comm thread
Although the AT commands style interface may look very straightforward, the need to support bidirectional messages (unsolicited response codes) requires a quite complex state machine to handle duplex communication with proper locking and synchronization. Since the module may want to send an URC at any time, we must not mistake that the characters we are receiving between a response to a command and an unsolicited response. This is accomplished by sending the command and waiting for the echo to the command itself. The module has a locking mechanism which prevents URCs to be sent after the first character of the echo and the last character of the response.
Thus, the timeline of a request will not look like this:
WRONG! TX => ATE1<cr> RX <= ATE1<cr> RING<cr><lf> OK<cr><lf>
Instead, the RING URC will be postponed after the command has been executed and the response transmitted completely:
OK TX => ATE1<cr> RX <= ATE1<cr> OK<cr><lf> RING<cr><lf>
Other parts of chan_vgsm post requests into a queue and either wait for them to be completed or registers a callback that is called on completion.
The comm thread picks the requests from the queue and executes them sequentially taking care of the locking and synchronization issues. The thread is based on a state machine (in figure) with the following states:
- CLOSED
- FAILED
- RECOVERING
- IDLE
- READING_URC
- AWAITING_SMS_ECHO
- AWAITING_SMS_ECHO_1A
- AWAITING_ECHO
- AWAITING_ECHO_READING_URC
- READING_RESPONSE
The thread is normally in IDLE state either awaiting for request to be queued in the requests queue or URC being received on the serial line. When a request is picked from the queue the state is set to AWAITING_ECHO and the request is transmitted to the module. If a full echo of the request is received the state changes to READING_RESPONSE and the response is read until completion (OK or an error code). If the received string differs from the expected echo, it means that an URC is being received and the state changes to AWAITING_ECHO_READING_URC, the URC is read and the state changes back to AWAITING_ECHO until all URCs have been received.
If an URC is received while IDLE, the state changes to READING_URC and the URC is read, then the state returns to IDLE:
In case of a timeout, the comm's state changes to RECOVERING and actions are performed to regain synchronization with the module. If unable to recover, the state changes permanently to FAILED.
AWAITING_SMS_ECHO and AWAITING_SMS_ECHO_1A cope with the different interactive sequences needed to send the SMS text.
Comm thread is fully asynchronous and no part of its code may sleep, otherwise events belonging to other modules cannot be handled.
comm_urc thread
After receiving an URC a handler function has to be called to perform the appropriate actions, however, those actions may include waiting for events and thus sleeping for long times or performing direct requests. Being asynchronous, the comm thread may not thus call the handler directly. The comm thread queues the URCs in a specific queue instead and wakes up the comm_urc thread which sequentially dequeues the URCs from the queue and calls the appropriate handler function.
Being just one thread, the URC handlers will be called sequentially, so, if a handler takes long time the other URCs will be delayed considerably. If this turns out to be an issue, more than one thread can be spawned to handler concurrent URCs.
comm_completion thread
For the same reason explained above, completion callbacks cannot be called directly by the comm thread, so, this thread scans for completed requests and calls the completion handler appropriately.

