/** * Allocate and initialize a struct for a Modbus device instance. * * @param resource The resource description string. * @param serialcomm Additionnal parameters for serial port resources. * * @return The allocated sr_modbus_dev_inst structure or NULL on failure. */ SR_PRIV struct sr_modbus_dev_inst *modbus_dev_inst_new(const char *resource, const char *serialcomm, int modbusaddr) { struct sr_modbus_dev_inst *modbus = NULL; const struct sr_modbus_dev_inst *modbus_dev; gchar **params; unsigned int i; for (i = 0; i < modbus_devs_size; i++) { modbus_dev = modbus_devs[i]; if (!strncmp(resource, modbus_dev->prefix, strlen(modbus_dev->prefix))) { sr_dbg("Opening %s device %s.", modbus_dev->name, resource); modbus = g_malloc(sizeof(*modbus)); *modbus = *modbus_dev; modbus->priv = g_malloc0(modbus->priv_size); modbus->read_timeout_ms = 1000; params = g_strsplit(resource, "/", 0); if (modbus->dev_inst_new(modbus->priv, resource, params, serialcomm, modbusaddr) != SR_OK) { sr_modbus_free(modbus); modbus = NULL; } g_strfreev(params); break; } } return modbus; }
/** * Standard driver dev_clear() helper. * * Clear driver, this means, close all instances. * * This function can be used to implement the dev_clear() driver API * callback. dev_close() is called before every sr_dev_inst is cleared. * * The only limitation is driver-specific device contexts (sdi->priv). * These are freed, but any dynamic allocation within structs stored * there cannot be freed. * * @param driver The driver which will have its instances released. * @param clear_private If not NULL, this points to a function called * with sdi->priv as argument. The function can then clear any device * instance-specific resources kept there. It must also clear the struct * pointed to by sdi->priv. * * @return SR_OK on success. */ SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver, std_dev_clear_callback clear_private) { struct drv_context *drvc; struct sr_dev_inst *sdi; GSList *l; int ret; if (!(drvc = driver->context)) /* Driver was never initialized, nothing to do. */ return SR_OK; ret = SR_OK; for (l = drvc->instances; l; l = l->next) { if (!(sdi = l->data)) { ret = SR_ERR_BUG; continue; } if (driver->dev_close) driver->dev_close(sdi); if (sdi->conn) { #ifdef HAVE_LIBSERIALPORT if (sdi->inst_type == SR_INST_SERIAL) sr_serial_dev_inst_free(sdi->conn); #endif #ifdef HAVE_LIBUSB_1_0 if (sdi->inst_type == SR_INST_USB) sr_usb_dev_inst_free(sdi->conn); #endif if (sdi->inst_type == SR_INST_SCPI) sr_scpi_free(sdi->conn); if (sdi->inst_type == SR_INST_MODBUS) sr_modbus_free(sdi->conn); } if (clear_private) /* The helper function is responsible for freeing * its own sdi->priv! */ clear_private(sdi->priv); else g_free(sdi->priv); sr_dev_inst_free(sdi); } g_slist_free(drvc->instances); drvc->instances = NULL; return ret; }
static struct sr_dev_inst *sr_modbus_scan_resource(const char *resource, const char *serialcomm, int modbusaddr, struct sr_dev_inst *(*probe_device)(struct sr_modbus_dev_inst *modbus)) { struct sr_modbus_dev_inst *modbus; struct sr_dev_inst *sdi; if (!(modbus = modbus_dev_inst_new(resource, serialcomm, modbusaddr))) return NULL; if (sr_modbus_open(modbus) != SR_OK) { sr_info("Couldn't open Modbus device."); sr_modbus_free(modbus); return NULL; }; if ((sdi = probe_device(modbus))) return sdi; sr_modbus_close(modbus); sr_modbus_free(modbus); return NULL; }