diff options
Diffstat (limited to 'serial/manager.c')
-rw-r--r-- | serial/manager.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/serial/manager.c b/serial/manager.c index 6b60423d..bd0362df 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -57,6 +57,10 @@ #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" +/* Waiting for udev to create the device node */ +#define MAX_OPEN_TRIES 5 +#define OPEN_WAIT 300 /* ms */ + struct pending_connect { DBusConnection *conn; DBusMessage *msg; @@ -89,6 +93,16 @@ static struct { { NULL } }; +typedef void (*open_notify_t) (int fd, int err, void *data); +typedef void (*udata_free_t) (void *data); +struct open_context { + char *dev; + open_notify_t notify; + udata_free_t ufree; + void *udata; + int ntries; +}; + static DBusConnection *connection = NULL; static GSList *pending_connects = NULL; static int rfcomm_ctl = -1; @@ -130,6 +144,58 @@ static struct pending_connect *find_pending_connect_by_pattern(const char *bda, return NULL; } +static gboolean open_continue(struct open_context *oc) +{ + int fd; + + fd = open(oc->dev, O_RDONLY | O_NOCTTY); + if (fd < 0) { + int err = errno; + error("Could not open %s: %s (%d)", + oc->dev, strerror(err), err); + if (++oc->ntries >= MAX_OPEN_TRIES) { + /* Reporting error */ + oc->notify(fd, err, oc->udata); + return FALSE; + } + return TRUE; + } + /* Connection succeeded */ + oc->notify(fd, 0, oc->udata); + return FALSE; +} + +static void open_context_free(void *data) +{ + struct open_context *oc = data; + + if (oc->ufree) + oc->ufree(oc->udata); + g_free(oc->dev); + g_free(oc); +} + +int port_open(const char *dev, open_notify_t notify, + void *udata, udata_free_t ufree) +{ + int fd; + + fd = open(dev, O_RDONLY | O_NOCTTY); + if (fd < 0) { + struct open_context *oc; + oc = g_new0(struct open_context, 1); + oc->dev = g_strdup(dev); + oc->notify = notify; + oc->ufree = ufree; + oc->udata = udata; + g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, OPEN_WAIT, + (GSourceFunc) open_continue, oc, open_context_free); + return -EINPROGRESS; + } + + return fd; +} + static uint16_t str2class(const char *pattern) { int i; |