![]() |
![]() |
![]() |
Run a script on a device
#include <sys/modem.h> int modem_script( int fd, struct modem_script* table, speed_t* baud, void (*io)( char* progress, char* in, char* out ), int (*cancel)(void) );
libc
The modem_script() function runs the script table on the device associated with the file descriptor fd. The script implements a simple state machine which emits strings and waits for responses.
Each string emitted and received is passed to the function io() as follows:
Call | Description |
---|---|
(*io)(str, 0, 0) | Emitted progress string |
(*io)(0, str, 0) | Received string |
(*io)(0, 0, str) | Emitted response string |
This allows an application to setup a callback which can display the scripts interaction in a status window.
If a cancel function is provided, it's called once each newquiet 1/10 of a second while waiting for input. If this function returns a nonzero value, the read returns immediately with -1 and errno is set to ETIMEDOUT. The cancel function can be used as a callback in a graphical dialer which needs to support a cancel button to stop a script.
The table is passed as an array of structures containing the following members:
Member | Description |
---|---|
char curstate | The current state. Execution always begins at state 1 which must be the first array element of table. Multiple elements may have the same current state in which case any received input is matched against each pattern member for that state. |
int curflags | The flags to use on a pattern match of a response. MODEM_NOECHO -- Don't echo response through the io() callback. MODEM_BAUD -- Extract any number in the response and assign it to baud. |
char newstate | When a pattern match occurs with pattern this is the next state. A state transition causes response to be output and newflags, newtimeout and newquiet to be saved and associated with the new state. Changing to a new state of 0 causes modem_script() to return with the value in retvalue. |
int newflags | Saved on a state transition and passed to modem_read() when waiting for a response in the new state. These flags are described in modem_read(). |
int newtimeout | Saved on a state transition and passed to modem_read() when waiting for a response in the new state. This timeout is described in modem_read(). |
int newquiet | Saved on a state transition and passed to modem_read() when waiting for a response in the new state. This quiet timeout is described in modem_read(). |
short retvalue | Return value when script terminates with a pattern match and the new state is 0. |
char* pattern | A pattern to match against received characters. The pattern is matched using the fnmatch() function. Only patterns in the current state or the wildcard state of 0 are matched. On a match the current state is transitioned to newstate. |
char* response | On a pattern match this response is output to the device. If the curflags don't have MODEM_NOECHO set, then the response is given to the callback function passed as the io parameter. |
char* progress | On a pattern match, this progress string is passed to the callback function passed as the io parameter. |
The following example clarifies the operation of the script:
/* curstate curflags newstate newflags newtimeout newquiet retvalue pattern response */ struct modem_script table[] ={ {1, 0, 1, 0, 2, 5, 0, NULL, "ATZ\\r\\P0a"}, {1, 0, 2, 0, 30, 5, 0, "*ok*", "ATDT5910934"}, {2, MODEM_BAUD, 3, MODEM_LASTLINE, 10, 5, 0, "*connect*", NULL}, {3, 0, 4, 0, 8, 5, 0, "*login:*", "guest"}, {4, MODEM_NOECHO, 5, 0, 15, 5, 0, "*password:*", "xxxx"}, {5, 0, 0, 0, 0, 0, 0, "*$ *", NULL}, {0, 0, 0, 0, 0, 0, 1, "*no carrier*", NULL}, {0, 0, 0, 0, 0, 0, 2, "*no answer*", NULL}, {0, 0, 0, 0, 0, 0, 3, "*no dialtone*", NULL}, {0, 0, 0, 0, 0, 0, 4, "*busy*", NULL}, { NULL } };
When this script is passed to modem_script(), the current state is set to 1 and the output will be ATZ (the response in the first array element).
While in any state, modem_script() waits for input matching it against the current state or the wildcard state of 0.
Input | Action |
---|---|
*ok* | Go to state 2 and emit ATDT1-591-0934. The flags to be used in the new state are set to 0, the quiet time in the new state is set to 5/10 of a second, and the timeout time in the new state is set to 30 seconds. |
*no carrier* | Go to state 0 (the termination newstate), return with the contents of retvalue (1). |
*no answer* | Go to state 0 (the termination newstate), return with the contents of retvalue (2). |
*no dialtone* | Go to state 0 (the termination newstate), return with the contents of retvalue (3). |
*busy* | Go to state 0 (the termination newstate), return with the contents of retvalue (4). |
Input | Action |
---|---|
*connect* | Go to state 3 and don't emit anything to the device. The flags to be used in the new state are set to MODEM_LASTLINE, the quiet time in the new state is set to 5/10 of a second, and the timeout time in the new state is set to 10 seconds. Since the current flags are MODEM_BAUD the baud rate is extracted from the connect message. |
*no carrier* | Same as previous table |
*no answer* | Same as previous table |
*no dialtone* | Same as previous table |
*busy* | Same as previous table |
Input | Action |
---|---|
*login* | Go to state 4 and emit guest. The flags to be used in the new state are set to 0, the quiet time in the new state is set to 5/10 of a second, and the timeout time in the new state is set to 8 seconds. |
*no carrier* | Same as previous table |
*no answer* | Same as previous table |
*no dialtone* | Same as previous table |
*busy* | Same as previous table |
Input | Action |
---|---|
*password* | Go to state 5 and emit xxx. The flags to be used in the new state are set to 0, the quiet time in the new state is set to 5/10 of a second, and the timeout time in the new state is set to 15 seconds. Since the current flags are MODEM_NOECHO the password response xxx isn't sent to the io() callback. |
*no carrier* | Same as previous table |
*no answer* | Same as previous table |
*no dialtone* | Same as previous table |
*busy* | Same as previous table |
Input | Action |
---|---|
*$ * | Go to state 0 (the termination newstate), return with the contents of retvalue (0). |
*no carrier* | Same as previous table |
*no answer* | Same as previous table |
*no dialtone* | Same as previous table |
*busy* | Same as previous table |
If the flag MODEM_BAUD is set for a state then any number embedded in a matching response is extracted and assigned as a number to the baud parameter.
If the flag MODEM_NOECHO isn't set for a state then all emitted strings are also set to the passed io function as (*io)(0, 0, response).
The retvalue member of a script entry which terminates the script. This will always be a positive number. If modem_script fails, -1 is returned (errno is set).
Safety: | |
---|---|
Cancellation point | Yes |
Interrupt handler | No |
Signal handler | Read the Caveats |
Thread | Read the Caveats |
Depending on what you do in your cancel function, modem_read() may or not be signal handler or thread-safe.
modem_open(), modem_read(), modem_write()
![]() |
![]() |
![]() |