diff options
Diffstat (limited to 'src/mm-serial.c')
-rw-r--r-- | src/mm-serial.c | 1024 |
1 files changed, 49 insertions, 975 deletions
diff --git a/src/mm-serial.c b/src/mm-serial.c index 0301a592..48492ce4 100644 --- a/src/mm-serial.c +++ b/src/mm-serial.c @@ -1,864 +1,100 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -#define _GNU_SOURCE /* for strcasestr() */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2009 Red Hat, Inc. + */ #include <stdio.h> #include <stdlib.h> -#include <termio.h> #include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/ioctl.h> #include <string.h> #include "mm-serial.h" #include "mm-errors.h" #include "mm-options.h" -static gboolean mm_serial_queue_process (gpointer data); +#define TYPE_TAG "type" G_DEFINE_TYPE (MMSerial, mm_serial, G_TYPE_OBJECT) enum { PROP_0, - PROP_DEVICE, - PROP_BAUD, - PROP_BITS, - PROP_PARITY, - PROP_STOPBITS, - PROP_SEND_DELAY, - PROP_CARRIER_DETECT, LAST_PROP }; -#define SERIAL_BUF_SIZE 2048 - #define MM_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_SERIAL, MMSerialPrivate)) typedef struct { - int fd; - GHashTable *reply_cache; - GIOChannel *channel; - GQueue *queue; - GString *command; - GString *response; - - /* Response parser data */ - MMSerialResponseParserFn response_parser_fn; - gpointer response_parser_user_data; - GDestroyNotify response_parser_notify; - GSList *unsolicited_msg_handlers; - - struct termios old_t; - - char *device; - guint baud; - guint bits; - char parity; - guint stopbits; - guint64 send_delay; - gboolean carrier_detect; - - guint queue_schedule; - guint watch_id; - guint timeout_id; + GHashTable *ports; } MMSerialPrivate; -typedef struct { - GRegex *regex; - MMSerialUnsolicitedMsgFn callback; - gpointer user_data; - GDestroyNotify notify; -} MMUnsolicitedMsgHandler; - -const char * -mm_serial_get_device (MMSerial *serial) -{ - g_return_val_if_fail (MM_IS_SERIAL (serial), NULL); - - return MM_SERIAL_GET_PRIVATE (serial)->device; -} - -static void -mm_serial_set_cached_reply (MMSerial *self, - const char *command, - const char *reply) -{ - if (reply) - g_hash_table_insert (MM_SERIAL_GET_PRIVATE (self)->reply_cache, - g_strdup (command), - g_strdup (reply)); - else - g_hash_table_remove (MM_SERIAL_GET_PRIVATE (self)->reply_cache, command); -} - -static const char * -mm_serial_get_cached_reply (MMSerial *self, - const char *command) -{ - return (char *) g_hash_table_lookup (MM_SERIAL_GET_PRIVATE (self)->reply_cache, command); -} - -static int -parse_baudrate (guint i) -{ - int speed; - - switch (i) { - case 0: - speed = B0; - break; - case 50: - speed = B50; - break; - case 75: - speed = B75; - break; - case 110: - speed = B110; - break; - case 150: - speed = B150; - break; - case 300: - speed = B300; - break; - case 600: - speed = B600; - break; - case 1200: - speed = B1200; - break; - case 2400: - speed = B2400; - break; - case 4800: - speed = B4800; - break; - case 9600: - speed = B9600; - break; - case 19200: - speed = B19200; - break; - case 38400: - speed = B38400; - break; - case 57600: - speed = B57600; - break; - case 115200: - speed = B115200; - break; - case 460800: - speed = B460800; - break; - default: - g_warning ("Invalid baudrate '%d'", i); - speed = B9600; - } - - return speed; -} - -static int -parse_bits (guint i) -{ - int bits; - - switch (i) { - case 5: - bits = CS5; - break; - case 6: - bits = CS6; - break; - case 7: - bits = CS7; - break; - case 8: - bits = CS8; - break; - default: - g_warning ("Invalid bits (%d). Valid values are 5, 6, 7, 8.", i); - bits = CS8; - } - - return bits; -} - -static int -parse_parity (char c) -{ - int parity; - - switch (c) { - case 'n': - case 'N': - parity = 0; - break; - case 'e': - case 'E': - parity = PARENB; - break; - case 'o': - case 'O': - parity = PARENB | PARODD; - break; - default: - g_warning ("Invalid parity (%c). Valid values are n, e, o", c); - parity = 0; - } - - return parity; -} - -static int -parse_stopbits (guint i) -{ - int stopbits; - - switch (i) { - case 1: - stopbits = 0; - break; - case 2: - stopbits = CSTOPB; - break; - default: - g_warning ("Invalid stop bits (%d). Valid values are 1 and 2)", i); - stopbits = 0; - } - - return stopbits; -} - -static gboolean -config_fd (MMSerial *self) -{ - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - struct termio stbuf; - int speed; - int bits; - int parity; - int stopbits; - - speed = parse_baudrate (priv->baud); - bits = parse_bits (priv->bits); - parity = parse_parity (priv->parity); - stopbits = parse_stopbits (priv->stopbits); - - ioctl (priv->fd, TCGETA, &stbuf); - - stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR ); - stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET); - stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL); - stbuf.c_lflag &= ~(ECHO | ECHOE); - stbuf.c_cc[VMIN] = 1; - stbuf.c_cc[VTIME] = 0; - stbuf.c_cc[VEOF] = 1; - - stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB); - stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits); - - if (ioctl (priv->fd, TCSETA, &stbuf) < 0) { - g_warning ("(%s) cannot control device (errno %d)", priv->device, errno); - return FALSE; - } - - return TRUE; -} - -static void -serial_debug (const char *prefix, const char *buf, int len) -{ - static GString *debug = NULL; - const char *s; - - if (!mm_options_debug ()) - return; - - if (len < 0) - len = strlen (buf); - - if (!debug) - debug = g_string_sized_new (256); - - g_string_append (debug, prefix); - g_string_append (debug, " '"); - - s = buf; - while (len--) { - if (g_ascii_isprint (*s)) - g_string_append_c (debug, *s); - else if (*s == '\r') - g_string_append (debug, "<CR>"); - else if (*s == '\n') - g_string_append (debug, "<LF>"); - else - g_string_append_printf (debug, "\\%d", *s); - - s++; - } - - g_string_append_c (debug, '\''); - g_debug ("%s", debug->str); - g_string_truncate (debug, 0); -} - -static gboolean -mm_serial_send_command (MMSerial *self, - const char *command, - GError **error) +MMSerialPort * +mm_serial_get_port (MMSerial *self, const char *name) { - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - const char *s; - int status; - int eagain_count = 1000; - - if (priv->fd == 0) { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED, - "%s", "Sending command failed: device is not enabled"); - return FALSE; - } - - if (mm_serial_is_connected (self)) { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED, - "%s", "Sending command failed: device is connected"); - return FALSE; - } - - g_string_truncate (priv->command, g_str_has_prefix (command, "AT") ? 0 : 2); - g_string_append (priv->command, command); - - if (command[strlen (command)] != '\r') - g_string_append_c (priv->command, '\r'); - - serial_debug ("-->", priv->command->str, -1); - - s = priv->command->str; - while (*s) { - status = write (priv->fd, s, 1); - if (status < 0) { - if (errno == EAGAIN) { - eagain_count--; - if (eagain_count <= 0) { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED, - "Sending command failed: '%s'", strerror (errno)); - break; - } - } else { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED, - "Sending command failed: '%s'", strerror (errno)); - break; - } - } else - s++; - - if (priv->send_delay) - usleep (priv->send_delay); - } - - return *s == '\0'; + return g_hash_table_lookup (MM_SERIAL_GET_PRIVATE (self)->ports, name); } -typedef struct { - char *command; - MMSerialResponseFn callback; - gpointer user_data; - guint32 timeout; - gboolean cached; -} MMQueueData; - static void -mm_serial_schedule_queue_process (MMSerial *self) +find_primary (gpointer key, gpointer data, gpointer user_data) { - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - GSource *source; + MMSerialPort **found = user_data; + MMSerialPort *port = MM_SERIAL_PORT (data); + MMSerialPortType ptype; - if (priv->queue_schedule) - /* Already scheduled */ + if (*found) return; - source = g_idle_source_new (); - g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_queue_process), G_OBJECT (self))); - g_source_attach (source, NULL); - priv->queue_schedule = g_source_get_id (source); - g_source_unref (source); -} - -static void -mm_serial_got_response (MMSerial *self, GError *error) -{ - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - MMQueueData *info; - - if (priv->timeout_id) - g_source_remove (priv->timeout_id); - - info = (MMQueueData *) g_queue_pop_head (priv->queue); - if (info) { - if (info->cached && !error) - mm_serial_set_cached_reply (self, info->command, priv->response->str); - - if (info->callback) - info->callback (self, priv->response, error, info->user_data); - - g_free (info->command); - g_slice_free (MMQueueData, info); - } - - if (error) - g_error_free (error); - - g_string_truncate (priv->response, 0); - if (!g_queue_is_empty (priv->queue)) - mm_serial_schedule_queue_process (self); -} - -static gboolean -mm_serial_timed_out (gpointer data) -{ - MMSerial *self = MM_SERIAL (data); - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - GError *error; - - priv->timeout_id = 0; - - error = g_error_new_literal (MM_SERIAL_ERROR, - MM_SERIAL_RESPONSE_TIMEOUT, - "Serial command timed out"); - /* FIXME: This is not completely correct - if the response finally arrives and there's - some other command waiting for response right now, the other command will - get the output of the timed out command. Not sure what to do here. */ - mm_serial_got_response (self, error); - - return FALSE; -} - -static gboolean -mm_serial_queue_process (gpointer data) -{ - MMSerial *self = MM_SERIAL (data); - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - MMQueueData *info; - GError *error = NULL; - - priv->queue_schedule = 0; - - info = (MMQueueData *) g_queue_peek_head (priv->queue); - if (!info) - return FALSE; - - if (info->cached) { - const char *cached = mm_serial_get_cached_reply (self, info->command); - - if (cached) { - g_string_append (priv->response, cached); - mm_serial_got_response (self, NULL); - return FALSE; - } - } - - if (mm_serial_send_command (self, info->command, &error)) { - GSource *source; - - source = g_timeout_source_new (info->timeout); - g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_timed_out), G_OBJECT (self))); - g_source_attach (source, NULL); - priv->timeout_id = g_source_get_id (source); - g_source_unref (source); - } else { - mm_serial_got_response (self, error); - } - - return FALSE; -} - -void -mm_serial_add_unsolicited_msg_handler (MMSerial *self, - GRegex *regex, - MMSerialUnsolicitedMsgFn callback, - gpointer user_data, - GDestroyNotify notify) -{ - MMUnsolicitedMsgHandler *handler; - MMSerialPrivate *priv; - - g_return_if_fail (MM_IS_SERIAL (self)); - g_return_if_fail (regex != NULL); - - handler = g_slice_new (MMUnsolicitedMsgHandler); - handler->regex = g_regex_ref (regex); - handler->callback = callback; - handler->user_data = user_data; - handler->notify = notify; - - priv = MM_SERIAL_GET_PRIVATE (self); - priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler); -} - -void -mm_serial_set_response_parser (MMSerial *self, - MMSerialResponseParserFn fn, - gpointer user_data, - GDestroyNotify notify) -{ - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - - g_return_if_fail (MM_IS_SERIAL (self)); - - if (priv->response_parser_notify) - priv->response_parser_notify (priv->response_parser_user_data); - - priv->response_parser_fn = fn; - priv->response_parser_user_data = user_data; - priv->response_parser_notify = notify; -} - -static gboolean -remove_eval_cb (const GMatchInfo *match_info, - GString *result, - gpointer user_data) -{ - int *result_len = (int *) user_data; - int start; - int end; - - if (g_match_info_fetch_pos (match_info, 0, &start, &end)) - *result_len -= (end - start); - - return FALSE; -} - -static void -parse_unsolicited_messages (MMSerial *self, - GString *response) -{ - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - GSList *iter; - - for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) { - MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) iter->data; - GMatchInfo *match_info; - gboolean matches; - - matches = g_regex_match_full (handler->regex, response->str, response->len, 0, 0, &match_info, NULL); - if (handler->callback) { - while (g_match_info_matches (match_info)) { - handler->callback (self, match_info, handler->user_data); - g_match_info_next (match_info, NULL); - } - } - - g_match_info_free (match_info); - - if (matches) { - /* Remove matches */ - char *str; - int result_len = response->len; - - str = g_regex_replace_eval (handler->regex, response->str, response->len, 0, 0, - remove_eval_cb, &result_len, NULL); - - g_string_truncate (response, 0); - g_string_append_len (response, str, result_len); - g_free (str); - } - } -} - -static gboolean -parse_response (MMSerial *self, - GString *response, - GError **error) -{ - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - - g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE); - - parse_unsolicited_messages (self, response); - - return priv->response_parser_fn (priv->response_parser_user_data, response, error); + ptype = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (port), TYPE_TAG)); + if (ptype == MM_SERIAL_PORT_TYPE_PRIMARY) + *found = port; } -static gboolean -data_available (GIOChannel *source, - GIOCondition condition, - gpointer data) +MMSerialPort * +mm_serial_add_port (MMSerial *self, + const char *name, + MMSerialPortType ptype) { - MMSerial *self = MM_SERIAL (data); MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - char buf[SERIAL_BUF_SIZE + 1]; - gsize bytes_read; - GIOStatus status; - - if (condition & G_IO_HUP) { - g_string_truncate (priv->response, 0); - mm_serial_close (self); - return FALSE; - } - - if (condition & G_IO_ERR) { - g_string_truncate (priv->response, 0); - return TRUE; - } - - do { - GError *err = NULL; - - status = g_io_channel_read_chars (source, buf, SERIAL_BUF_SIZE, &bytes_read, &err); - if (status == G_IO_STATUS_ERROR) { - g_warning ("%s", err->message); - g_error_free (err); - err = NULL; - } - - if (bytes_read > 0) { - serial_debug ("<--", buf, bytes_read); - g_string_append_len (priv->response, buf, bytes_read); - } - - /* Make sure the string doesn't grow too long */ - if (priv->response->len > SERIAL_BUF_SIZE) { - g_warning ("%s (%s): response buffer filled before repsonse received", - G_STRFUNC, mm_serial_get_device (self)); - g_string_erase (priv->response, 0, (SERIAL_BUF_SIZE / 2)); - } - - if (parse_response (self, priv->response, &err)) - mm_serial_got_response (self, err); - } while (bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN); - - return TRUE; -} - -gboolean -mm_serial_open (MMSerial *self, GError **error) -{ - MMSerialPrivate *priv; + MMSerialPort *port = NULL; g_return_val_if_fail (MM_IS_SERIAL (self), FALSE); + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (ptype != MM_SERIAL_PORT_TYPE_UNKNOWN, FALSE); - priv = MM_SERIAL_GET_PRIVATE (self); - - if (priv->fd) - /* Already open */ - return TRUE; - - g_debug ("(%s) opening serial device...", priv->device); - priv->fd = open (priv->device, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); - - if (priv->fd < 0) { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED, - "Could not open serial device %s: %s", priv->device, strerror (errno)); - return FALSE; - } - - if (ioctl (priv->fd, TCGETA, &priv->old_t) < 0) { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED, - "Could not open serial device %s: %s", priv->device, strerror (errno)); - close (priv->fd); - return FALSE; - } - - if (!config_fd (self)) { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED, - "Could not open serial device %s: %s", priv->device, strerror (errno)); - close (priv->fd); - priv->fd = 0; - return FALSE; - } - - priv->channel = g_io_channel_unix_new (priv->fd); - priv->watch_id = g_io_add_watch (priv->channel, - G_IO_IN | G_IO_ERR | G_IO_HUP, - data_available, self); - - return TRUE; -} - -void -mm_serial_close (MMSerial *self) -{ - MMSerialPrivate *priv; - - g_return_if_fail (MM_IS_SERIAL (self)); - - priv = MM_SERIAL_GET_PRIVATE (self); - - if (priv->fd) { - g_message ("Closing device '%s'", priv->device); + g_return_val_if_fail (g_hash_table_lookup (priv->ports, name) == NULL, FALSE); - if (priv->channel) { - g_source_remove (priv->watch_id); - g_io_channel_shutdown (priv->channel, TRUE, NULL); - g_io_channel_unref (priv->channel); - priv->channel = NULL; - } - - ioctl (priv->fd, TCSETA, &priv->old_t); - close (priv->fd); - priv->fd = 0; + if (ptype == MM_SERIAL_PORT_TYPE_PRIMARY) { + g_hash_table_foreach (priv->ports, find_primary, &port); + g_return_val_if_fail (port == NULL, FALSE); } -} - -static void -internal_queue_command (MMSerial *self, - const char *command, - gboolean cached, - guint32 timeout_seconds, - MMSerialResponseFn callback, - gpointer user_data) -{ - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - MMQueueData *info; - - g_return_if_fail (MM_IS_SERIAL (self)); - g_return_if_fail (command != NULL); - - info = g_slice_new0 (MMQueueData); - info->command = g_strdup (command); - info->cached = cached; - info->timeout = timeout_seconds * 1000; - info->callback = callback; - info->user_data = user_data; - - /* Clear the cached value for this command if not asking for cached value */ - if (!cached) - mm_serial_set_cached_reply (self, command, NULL); - - g_queue_push_tail (priv->queue, info); - - if (g_queue_get_length (priv->queue) == 1) - mm_serial_schedule_queue_process (self); -} - -void -mm_serial_queue_command (MMSerial *self, - const char *command, - guint32 timeout_seconds, - MMSerialResponseFn callback, - gpointer user_data) -{ - internal_queue_command (self, command, FALSE, timeout_seconds, callback, user_data); -} - -void -mm_serial_queue_command_cached (MMSerial *self, - const char *command, - guint32 timeout_seconds, - MMSerialResponseFn callback, - gpointer user_data) -{ - internal_queue_command (self, command, TRUE, timeout_seconds, callback, user_data); -} - -typedef struct { - MMSerial *serial; - speed_t current_speed; - MMSerialFlashFn callback; - gpointer user_data; -} FlashInfo; - -static speed_t -get_speed (MMSerial *self) -{ - struct termios options; - - tcgetattr (MM_SERIAL_GET_PRIVATE (self)->fd, &options); - - return cfgetospeed (&options); -} - -static void -set_speed (MMSerial *self, speed_t speed) -{ - struct termios options; - int fd; - - fd = MM_SERIAL_GET_PRIVATE (self)->fd; - tcgetattr (fd, &options); - - cfsetispeed (&options, speed); - cfsetospeed (&options, speed); - - options.c_cflag |= (CLOCAL | CREAD); - tcsetattr (fd, TCSANOW, &options); -} - -static void -flash_done (gpointer data) -{ - FlashInfo *info = (FlashInfo *) data; - - info->callback (info->serial, info->user_data); - - g_slice_free (FlashInfo, info); -} -static gboolean -flash_do (gpointer data) -{ - FlashInfo *info = (FlashInfo *) data; - - set_speed (info->serial, info->current_speed); - - return FALSE; -} - -guint -mm_serial_flash (MMSerial *self, - guint32 flash_time, - MMSerialFlashFn callback, - gpointer user_data) -{ - FlashInfo *info; - guint id; - - g_return_val_if_fail (MM_IS_SERIAL (self), 0); - g_return_val_if_fail (callback != NULL, 0); - - info = g_slice_new0 (FlashInfo); - info->serial = self; - info->current_speed = get_speed (self); - info->callback = callback; - info->user_data = user_data; - - set_speed (self, B0); - - id = g_timeout_add_full (G_PRIORITY_DEFAULT, - flash_time, - flash_do, - info, - flash_done); + port = mm_serial_port_new (name); + if (!port) + return NULL; - return id; + g_object_set_data (G_OBJECT (port), TYPE_TAG, GUINT_TO_POINTER (ptype)); + g_hash_table_insert (priv->ports, g_strdup (name), port); + return port; } gboolean -mm_serial_is_connected (MMSerial *self) +mm_serial_remove_port (MMSerial *self, MMSerialPort *port) { - MMSerialPrivate *priv; - int mcs = 0; - g_return_val_if_fail (MM_IS_SERIAL (self), FALSE); + g_return_val_if_fail (port != NULL, FALSE); - priv = MM_SERIAL_GET_PRIVATE (self); - - if (!priv->carrier_detect) - return FALSE; - - if (priv->fd == 0) - return FALSE; - - if (ioctl (priv->fd, TIOCMGET, &mcs) < 0) - return FALSE; - - return mcs & TIOCM_CAR ? TRUE : FALSE; + return g_hash_table_remove (MM_SERIAL_GET_PRIVATE (self)->ports, port); } /*****************************************************************************/ @@ -868,74 +104,14 @@ mm_serial_init (MMSerial *self) { MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - priv->reply_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - priv->baud = 57600; - priv->bits = 8; - priv->parity = 'n'; - priv->stopbits = 1; - priv->send_delay = 1000; - priv->carrier_detect = TRUE; - - priv->queue = g_queue_new (); - priv->command = g_string_new_len ("AT", SERIAL_BUF_SIZE); - priv->response = g_string_sized_new (SERIAL_BUF_SIZE); -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - MMSerialPrivate *priv; - - object = G_OBJECT_CLASS (mm_serial_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - priv = MM_SERIAL_GET_PRIVATE (object); - - if (!priv->device) { - g_warning ("No device provided"); - g_object_unref (object); - return NULL; - } - - return object; + priv->ports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); } static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (object); - switch (prop_id) { - case PROP_DEVICE: - /* Construct only */ - priv->device = g_value_dup_string (value); - break; - case PROP_BAUD: - priv->baud = g_value_get_uint (value); - break; - case PROP_BITS: - priv->bits = g_value_get_uint (value); - break; - case PROP_PARITY: - priv->parity = g_value_get_char (value); - break; - case PROP_STOPBITS: - priv->stopbits = g_value_get_uint (value); - break; - case PROP_SEND_DELAY: - priv->send_delay = g_value_get_uint64 (value); - break; - case PROP_CARRIER_DETECT: - priv->carrier_detect = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -946,30 +122,7 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (object); - switch (prop_id) { - case PROP_DEVICE: - g_value_set_string (value, priv->device); - break; - case PROP_BAUD: - g_value_set_uint (value, priv->baud); - break; - case PROP_BITS: - g_value_set_uint (value, priv->bits); - break; - case PROP_PARITY: - g_value_set_char (value, priv->parity); - break; - case PROP_STOPBITS: - g_value_set_uint (value, priv->stopbits); - break; - case PROP_SEND_DELAY: - g_value_set_uint64 (value, priv->send_delay); - break; - case PROP_CARRIER_DETECT: - g_value_set_boolean (value, priv->carrier_detect); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -982,28 +135,7 @@ finalize (GObject *object) MMSerial *self = MM_SERIAL (object); MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self); - mm_serial_close (self); - - g_hash_table_destroy (priv->reply_cache); - g_queue_free (priv->queue); - g_string_free (priv->command, TRUE); - g_string_free (priv->response, TRUE); - g_free (priv->device); - - while (priv->unsolicited_msg_handlers) { - MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) priv->unsolicited_msg_handlers->data; - - if (handler->notify) - handler->notify (handler->user_data); - - g_regex_unref (handler->regex); - g_slice_free (MMUnsolicitedMsgHandler, handler); - priv->unsolicited_msg_handlers = g_slist_delete_link (priv->unsolicited_msg_handlers, - priv->unsolicited_msg_handlers); - } - - if (priv->response_parser_notify) - priv->response_parser_notify (priv->response_parser_user_data); + g_hash_table_destroy (priv->ports); G_OBJECT_CLASS (mm_serial_parent_class)->finalize (object); } @@ -1016,65 +148,7 @@ mm_serial_class_init (MMSerialClass *klass) g_type_class_add_private (object_class, sizeof (MMSerialPrivate)); /* Virtual methods */ - object_class->constructor = constructor; object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_DEVICE, - g_param_spec_string (MM_SERIAL_DEVICE, - "Device", - "Serial device", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_BAUD, - g_param_spec_uint (MM_SERIAL_BAUD, - "Baud", - "Baud rate", - 0, G_MAXUINT, 57600, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_BITS, - g_param_spec_uint (MM_SERIAL_BITS, - "Bits", - "Bits", - 5, 8, 8, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_PARITY, - g_param_spec_char (MM_SERIAL_PARITY, - "Parity", - "Parity", - 'E', 'o', 'n', - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_STOPBITS, - g_param_spec_uint (MM_SERIAL_STOPBITS, - "Stopbits", - "Stopbits", - 1, 2, 1, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_SEND_DELAY, - g_param_spec_uint64 (MM_SERIAL_SEND_DELAY, - "SendDelay", - "Send delay", - 0, G_MAXUINT64, 0, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_CARRIER_DETECT, - g_param_spec_boolean (MM_SERIAL_CARRIER_DETECT, - "CarrierDetect", - "Has carrier detect", - TRUE, - G_PARAM_READWRITE)); } |