GSMD is an event-driven daemon. Each event shall have a response and will pass through the function '''gsmd_select_main()''' in which finding and then executing their correspond callback functions.

−

Every event will pass through the '''gsmd_select_main()''' in which finding and executing their correspond call back functions.

+

+

The last part of gsmd '''main''' function enters a infinite loop, trying to call '''gsmd_select_main'''.

+

+

while(1) {

+

int ret = gsmd_select_main();

+

...

+

}

+

+

=== Design Policy ===

+

* All commands will wait synchronously for a response until timeout.

+

* All callback functions of commands with multiple-line responses are re-entrant.

+

* Commands of specific modem will be put in vendor plug-in.

+

* Commands or some special scheme for specific platform will be put in machine plug-in.

=== gsmd_select_main() ===

=== gsmd_select_main() ===

−

gsmd_select_main this is core of the call back function scheme. All devices, gsmd monitors, are described as a struct '''gsmd_fd''', and gsmd_select_main will select them.

+

gsmd_select_main this is core of the callback function scheme. All devices, gsmd monitors and linked in a [http://wiki.kldp.org/wiki.php/LinkedList list], are described as a struct '''gsmd_fd''', and gsmd_select_main will [http://swoolley.org/man.cgi/select select] them.

−

Once an event comes out from one of the devices, gsmd_select_main will try to call it's call back function that devices registered.

+

Once an event comes out from one of the devices, gsmd_select_main will try to call it's '''callback function''' that devices registered.

+

+

int gsmd_select_main()

+

{

+

struct gsmd_fd *ufd, *ufd2;

+

fd_set readset, writeset, exceptset;

+

int i;

+

+

FD_ZERO(&readset);

+

FD_ZERO(&writeset);

+

FD_ZERO(&exceptset);

+

+

/* prepare read and write fdsets */

+

llist_for_each_entry(ufd, &gsmd_fds, list) {

+

if (ufd->when & GSMD_FD_READ)

+

FD_SET(ufd->fd, &readset);

+

+

if (ufd->when & GSMD_FD_WRITE)

+

FD_SET(ufd->fd, &writeset);

+

+

if (ufd->when & GSMD_FD_EXCEPT)

+

FD_SET(ufd->fd, &exceptset);

+

}

+

+

'''i = select(maxfd+1, &readset, &writeset, &exceptset, NULL);'''

+

if (i > 0) {

+

/* call registered callback functions */

+

llist_for_each_entry_safe(ufd, ufd2, &gsmd_fds, list) {

+

int flags = 0;

+

+

if (FD_ISSET(ufd->fd, &readset))

+

flags |= GSMD_FD_READ;

+

+

if (FD_ISSET(ufd->fd, &writeset))

+

flags |= GSMD_FD_WRITE;

+

+

if (FD_ISSET(ufd->fd, &exceptset))

+

flags |= GSMD_FD_EXCEPT;

+

+

if (flags)

+

''' ufd->cb(ufd->fd, flags, ufd->data);'''

+

}

+

}

+

return i;

+

}

+

−

==== gsmd_fd ====

+

==== gsmd_fd ====

struct gsmd_fd {

struct gsmd_fd {

struct llist_head list;

struct llist_head list;

int fd; /* file descriptor */

int fd; /* file descriptor */

unsigned int when;

unsigned int when;

−

int (*cb)(int fd, unsigned int what, void *data);

+

'''int (*cb)(int fd, unsigned int what, void *data);'''

void *data; /* void * to pass to callback */

void *data; /* void * to pass to callback */

};

};

−

=== call back functions ===

+

When there are anything change in fd, the gsmd_select_main will detect them and try to call it's callback function cb.

−

Gsmd will open two devices. One is uart to modem and the other is the Unix socket, communicating with libgsmd.

+

−

The default call back function of uart (to modem) is ml_parse, in which dealing with writing AT command, and reading response or notifications from modem.

+

That means if you redirect the callback function cb to another implementation, the gsmd will behave very differently.

+

+

==== gsmd_atcmd ====

+

struct gsmd_atcmd {

+

'''struct llist_head list;'''

+

void *ctx;

+

'''int (*cb)(struct gsmd_atcmd *cmd, void *ctx, char *resp);'''

+

char *resp;

+

int32_t ret;

+

u_int32_t buflen;

+

u_int16_t id;

+

u_int8_t flags;

+

char *cur;

+

char buf[];

+

};

+

+

=== callback functions ===

+

Gsmd opens at least one devices. One is uart to modem and others are the Unix socket, communicating with libgsmd.

+

'''atcmd_select_cb''' is the default callback function that dealing the UART to the modem. It will handle sending AT commands to GSM modem or receive whatever return from modem and send them into parser.

+

+

The default parser callback function of UART (to modem) is '''ml_parse''', in which dealing with reading the response from modem and dispatching the correct callback function to handle the response.

+

+

==== atcmd_select_cb ====

+

There are two queues that handles the atcmds. One is pending_atcmds, and the other is busy_atcmds.

+

pending_atcmds links all the atcmds user send to gsmd in sequence and those commands are not send to modem yet.

+

busy_atcmds links all the atcmds sent to gsm modem but not get the response yet.

+

Both pending_atcmds and busy_atcmds are FIFO queue.

+

+

There are two mode of atcmd_select_cb "GSMD_FD_READ" and "GSMD_FD_WRITE". If there are data come out from uart, atcmd_select_cb will be called in READ mode. It will try to read the data from uart and put them llparser_string. llparser_string will try to use the actual parser implementation set by gsmd. (default is ml_parser)

+

+

If there are atcmds in pending_atcmds queue, the atcmd_select_cb will be called in WRITE mode. It will try to write the atcmd at the head of queue to modem, and move this atcmd handler into busy_atcmds queue.

Gsmd is a daemon that handles the communications between applications and GSM modem.
Applications manipulate gsmd through the APIs defined in libgsmd.
libgsmd communicates with gsmd through unix socket, and modem goes through UART.
The diagram is as following.

gsmd_select_main this is core of the callback function scheme. All devices, gsmd monitors and linked in a list, are described as a struct gsmd_fd, and gsmd_select_main will select them.
Once an event comes out from one of the devices, gsmd_select_main will try to call it's callback function that devices registered.

There are two queues that handles the atcmds. One is pending_atcmds, and the other is busy_atcmds.
pending_atcmds links all the atcmds user send to gsmd in sequence and those commands are not send to modem yet.
busy_atcmds links all the atcmds sent to gsm modem but not get the response yet.
Both pending_atcmds and busy_atcmds are FIFO queue.

There are two mode of atcmd_select_cb "GSMD_FD_READ" and "GSMD_FD_WRITE". If there are data come out from uart, atcmd_select_cb will be called in READ mode. It will try to read the data from uart and put them llparser_string. llparser_string will try to use the actual parser implementation set by gsmd. (default is ml_parser)

If there are atcmds in pending_atcmds queue, the atcmd_select_cb will be called in WRITE mode. It will try to write the atcmd at the head of queue to modem, and move this atcmd handler into busy_atcmds queue.

Gsmd

GSMD is a event driven daemon. Each event shall has a response.
Every event will pass through the gsmd_select_main() in which finding and executing their correspond call back functions.

gsmd_select_main()

gsmd_select_main this is core of the call back function scheme. All devices, gsmd monitors, are described as a struct gsmd_fd, and gsmd_select_main will select them.
Once an event comes out from one of the devices, gsmd_select_main will try to call it's call back function that devices registered.