From 5503d316c26d664117ff899c0dece6efc5ea7077 Mon Sep 17 00:00:00 2001 From: Jesse Gilles Date: Thu, 4 Sep 2014 13:38:01 -0500 Subject: add support for MTAC-MFSER --- io-module/mtac_mfser.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 io-module/mtac_mfser.c (limited to 'io-module/mtac_mfser.c') diff --git a/io-module/mtac_mfser.c b/io-module/mtac_mfser.c new file mode 100644 index 0000000..14eddd1 --- /dev/null +++ b/io-module/mtac_mfser.c @@ -0,0 +1,215 @@ +struct gpio_pin *ap_mfser_pin_by_attr_name(const char *name) { + struct gpio_pin *pin; + char *pin_attr_name; + + if (!strcmp(name, "rs4xx-term-res:0")) { + pin_attr_name = "ap1-gpio3"; + } else if (!strcmp(name, "rts-override:0")) { + pin_attr_name = "ap1-gpio4"; + } else if (!strcmp(name, "rs4xx-term-res:1")) { + pin_attr_name = "ap2-gpio3"; + } else if (!strcmp(name, "rts-override:1")) { + pin_attr_name = "ap2-gpio4"; + } else { + log_error("accessory card attribute %s not available", name); + return NULL; + } + + for (pin = gpio_pins; *pin->name; pin++) { + if (!strcmp(pin->pin.label, pin_attr_name)) { + return pin; + } + } + + log_error("pin with attr name %s not found", name); + + return NULL; +} + + +static ssize_t mts_attr_show_ap_mfser_pin(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int value; + struct gpio_pin *pin = ap_mfser_pin_by_attr_name(attr->attr.name); + + if (!pin) { + return -ENODEV; + } + + mutex_lock(&mts_io_mutex); + + value = gpio_get_value(pin->pin.gpio); + + mutex_unlock(&mts_io_mutex); + + if (value < 0) { + return value; + } + + if (pin->active_low) { + value = !value; + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t mts_attr_store_ap_mfser_pin(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int value; + struct gpio_pin *pin = ap_mfser_pin_by_attr_name(attr->attr.name); + + if (!pin) { + return -ENODEV; + } + + if (sscanf(buf, "%i", &value) != 1) { + return -EINVAL; + } + + if (pin->active_low) { + value = !value; + } + + mutex_lock(&mts_io_mutex); + + gpio_set_value(pin->pin.gpio, value); + + mutex_unlock(&mts_io_mutex); + + return count; +} + +static ssize_t mts_attr_show_mfser_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + int modesel0; + int modesel1; + + struct gpio_pin *pin_modesel0; + struct gpio_pin *pin_modesel1; + + if (strstr(attr->attr.name, ":0")) { + pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); + } + else if (strstr(attr->attr.name, ":1")) { + pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); + } + else { + log_error("unknown serial-mode attr %s", attr->attr.name); + return -ENODEV; + } + + if (!pin_modesel0 || !pin_modesel1) + return -ENODEV; + + mutex_lock(&mts_io_mutex); + + modesel0 = gpio_get_value(pin_modesel0->pin.gpio); + modesel1 = gpio_get_value(pin_modesel1->pin.gpio); + + if (modesel1 == 0 && modesel0 == 0) + ret = sprintf(buf, "loopback\n"); + else if (modesel1 == 0 && modesel0 == 1) + ret = sprintf(buf, "rs232\n"); + else if (modesel1 == 1 && modesel0 == 0) + ret = sprintf(buf, "rs485-half\n"); + else if (modesel1 == 1 && modesel0 == 1) + ret = sprintf(buf, "rs422-485-full\n"); + else + ret = sprintf(buf, "error\n"); + + mutex_unlock(&mts_io_mutex); + + return ret; +} + +static ssize_t mts_attr_store_mfser_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int modesel0; + int modesel1; + struct gpio_pin *pin_modesel0; + struct gpio_pin *pin_modesel1; + + if (strstr(attr->attr.name, ":0")) { + pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); + } + else if (strstr(attr->attr.name, ":1")) { + pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); + } + else { + log_error("unknown serial-mode attr %s", attr->attr.name); + return -ENODEV; + } + + if (!pin_modesel0 || !pin_modesel1) + return -ENODEV; + + if (!strcasecmp(buf, "loopback")) { + modesel1 = 0; + modesel0 = 0; + } + else if (!strcasecmp(buf, "rs232")) { + modesel1 = 0; + modesel0 = 1; + } + else if (!strcasecmp(buf, "rs485-half")) { + modesel1 = 1; + modesel0 = 0; + } + else if (!strcasecmp(buf, "rs422-485-full")) { + modesel1 = 1; + modesel0 = 1; + } + else { + return -EINVAL; + } + + mutex_lock(&mts_io_mutex); + + gpio_set_value(pin_modesel0->pin.gpio, modesel0); + gpio_set_value(pin_modesel1->pin.gpio, modesel1); + + mutex_unlock(&mts_io_mutex); + + return count; +} + +/* accessory port 1 serial attributes */ +static DEVICE_ATTR_MTS(dev_attr_ap1_serial_mode, "serial-mode:0", mts_attr_show_mfser_mode, mts_attr_store_mfser_mode); +static DEVICE_ATTR_MTS(dev_attr_ap1_rs4xx_term_res, "rs4xx-term-res:0", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); +static DEVICE_ATTR_MTS(dev_attr_ap1_rts_override, "rts-override:0", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); + +static int ap1_mfser_attributes_size = 3; // not including NULL at end + +static struct attribute *ap1_mfser_attributes[] = { + &dev_attr_ap1_serial_mode.attr, + &dev_attr_ap1_rs4xx_term_res.attr, // gpio3 + &dev_attr_ap1_rts_override.attr, // gpio4 + NULL, +}; + +/* accessory port 2 serial attributes */ +static DEVICE_ATTR_MTS(dev_attr_ap2_serial_mode, "serial-mode:1", mts_attr_show_mfser_mode, mts_attr_store_mfser_mode); +static DEVICE_ATTR_MTS(dev_attr_ap2_rs4xx_term_res, "rs4xx-term-res:1", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); +static DEVICE_ATTR_MTS(dev_attr_ap2_rts_override, "rts-override:1", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); + +static int ap2_mfser_attributes_size = 3; // not including NULL at end + +static struct attribute *ap2_mfser_attributes[] = { + &dev_attr_ap2_serial_mode.attr, + &dev_attr_ap2_rs4xx_term_res.attr, // gpio3 + &dev_attr_ap2_rts_override.attr, // gpio4 + NULL, +}; + + -- cgit v1.2.3 From a21c24fa2486e4d4a3b25d0dcbf873ae62fdbcec Mon Sep 17 00:00:00 2001 From: Mike Fiore Date: Tue, 23 Sep 2014 10:35:11 -0500 Subject: mts-io: clean up accessory card support use custom kernel config option MTS_NUM_ACCESSORY_PORTS to find out how many slots exist (mostly) dynamically handle any number of accessory cards streamline code to make it easier to add accessory cards in the future --- io-module/mtac_mfser.c | 106 +++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 38 deletions(-) (limited to 'io-module/mtac_mfser.c') diff --git a/io-module/mtac_mfser.c b/io-module/mtac_mfser.c index 14eddd1..5871bfe 100644 --- a/io-module/mtac_mfser.c +++ b/io-module/mtac_mfser.c @@ -2,13 +2,13 @@ struct gpio_pin *ap_mfser_pin_by_attr_name(const char *name) { struct gpio_pin *pin; char *pin_attr_name; - if (!strcmp(name, "rs4xx-term-res:0")) { + if (!strcmp(name, "rs4xx-term-res:1")) { pin_attr_name = "ap1-gpio3"; - } else if (!strcmp(name, "rts-override:0")) { + } else if (!strcmp(name, "rts-override:1")) { pin_attr_name = "ap1-gpio4"; - } else if (!strcmp(name, "rs4xx-term-res:1")) { + } else if (!strcmp(name, "rs4xx-term-res:2")) { pin_attr_name = "ap2-gpio3"; - } else if (!strcmp(name, "rts-override:1")) { + } else if (!strcmp(name, "rts-override:2")) { pin_attr_name = "ap2-gpio4"; } else { log_error("accessory card attribute %s not available", name); @@ -27,8 +27,8 @@ struct gpio_pin *ap_mfser_pin_by_attr_name(const char *name) { } -static ssize_t mts_attr_show_ap_mfser_pin(struct device *dev, - struct device_attribute *attr, +static ssize_t mts_attr_show_ap_mfser_pin(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { int value; @@ -55,8 +55,8 @@ static ssize_t mts_attr_show_ap_mfser_pin(struct device *dev, return sprintf(buf, "%d\n", value); } -static ssize_t mts_attr_store_ap_mfser_pin(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t mts_attr_store_ap_mfser_pin(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) { int value; struct gpio_pin *pin = ap_mfser_pin_by_attr_name(attr->attr.name); @@ -82,8 +82,8 @@ static ssize_t mts_attr_store_ap_mfser_pin(struct device *dev, return count; } -static ssize_t mts_attr_show_mfser_mode(struct device *dev, - struct device_attribute *attr, +static ssize_t mts_attr_show_mfser_mode(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { int ret; @@ -93,11 +93,11 @@ static ssize_t mts_attr_show_mfser_mode(struct device *dev, struct gpio_pin *pin_modesel0; struct gpio_pin *pin_modesel1; - if (strstr(attr->attr.name, ":0")) { + if (strstr(attr->attr.name, ":1")) { pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); } - else if (strstr(attr->attr.name, ":1")) { + else if (strstr(attr->attr.name, ":2")) { pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); } @@ -130,19 +130,19 @@ static ssize_t mts_attr_show_mfser_mode(struct device *dev, return ret; } -static ssize_t mts_attr_store_mfser_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t mts_attr_store_mfser_mode(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) { int modesel0; int modesel1; struct gpio_pin *pin_modesel0; struct gpio_pin *pin_modesel1; - if (strstr(attr->attr.name, ":0")) { + if (strstr(attr->attr.name, ":1")) { pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); } - else if (strstr(attr->attr.name, ":1")) { + else if (strstr(attr->attr.name, ":2")) { pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); } @@ -184,32 +184,62 @@ static ssize_t mts_attr_store_mfser_mode(struct device *dev, return count; } -/* accessory port 1 serial attributes */ -static DEVICE_ATTR_MTS(dev_attr_ap1_serial_mode, "serial-mode:0", mts_attr_show_mfser_mode, mts_attr_store_mfser_mode); -static DEVICE_ATTR_MTS(dev_attr_ap1_rs4xx_term_res, "rs4xx-term-res:0", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); -static DEVICE_ATTR_MTS(dev_attr_ap1_rts_override, "rts-override:0", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); +// 1 serial mode +// 1 rs4xx term resistor +// 1 rts override +static int ap_mfser_attrs_size = 3; -static int ap1_mfser_attributes_size = 3; // not including NULL at end +static bool mfser_setup(enum ap port) { + struct kobj_attribute *attr; + char buf[32]; -static struct attribute *ap1_mfser_attributes[] = { - &dev_attr_ap1_serial_mode.attr, - &dev_attr_ap1_rs4xx_term_res.attr, // gpio3 - &dev_attr_ap1_rts_override.attr, // gpio4 - NULL, -}; + log_info("loading MFSER accessory card in port %d", port); -/* accessory port 2 serial attributes */ -static DEVICE_ATTR_MTS(dev_attr_ap2_serial_mode, "serial-mode:1", mts_attr_show_mfser_mode, mts_attr_store_mfser_mode); -static DEVICE_ATTR_MTS(dev_attr_ap2_rs4xx_term_res, "rs4xx-term-res:1", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); -static DEVICE_ATTR_MTS(dev_attr_ap2_rts_override, "rts-override:1", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); + if (device_attrs_size + ap_mfser_attrs_size >= device_attrs_max_size) { + log_error("can't load MFSER accessory card in port %d - not enough room for attributes", port); + return false; + } -static int ap2_mfser_attributes_size = 3; // not including NULL at end + sprintf(buf, "serial-mode:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_mfser_mode; + attr->store = mts_attr_store_mfser_mode; + device_attrs[device_attrs_size++] = &attr->attr; -static struct attribute *ap2_mfser_attributes[] = { - &dev_attr_ap2_serial_mode.attr, - &dev_attr_ap2_rs4xx_term_res.attr, // gpio3 - &dev_attr_ap2_rts_override.attr, // gpio4 - NULL, -}; + sprintf(buf, "rs4xx-term-res:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_mfser_pin; + attr->store = mts_attr_store_ap_mfser_pin; + device_attrs[device_attrs_size++] = &attr->attr; + sprintf(buf, "rts-override:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_mfser_pin; + attr->store = mts_attr_store_ap_mfser_pin; + device_attrs[device_attrs_size++] = &attr->attr; + + return true; +} +static bool mfser_teardown(enum ap port) { + log_info("unloading MFSER accessory card in port %d", port); + return true; +} + +static struct ap_info mfser_info = { + .product_id = MTAC_MFSER_0_0, + .setup = &mfser_setup, + .teardown = &mfser_teardown +}; -- cgit v1.2.3 From c83b0cf41999478d31c86fb50740d1fdf0fbb003 Mon Sep 17 00:00:00 2001 From: Mike Fiore Date: Thu, 25 Sep 2014 14:03:36 -0500 Subject: mts-io: clean up memory allocated for accessory cards on module unload or setup failure --- io-module/mtac_mfser.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'io-module/mtac_mfser.c') diff --git a/io-module/mtac_mfser.c b/io-module/mtac_mfser.c index 5871bfe..207180f 100644 --- a/io-module/mtac_mfser.c +++ b/io-module/mtac_mfser.c @@ -190,6 +190,7 @@ static ssize_t mts_attr_store_mfser_mode(struct kobject *kobj, static int ap_mfser_attrs_size = 3; static bool mfser_setup(enum ap port) { + int port_index = port - 1; struct kobj_attribute *attr; char buf[32]; @@ -200,6 +201,10 @@ static bool mfser_setup(enum ap port) { return false; } + // mark the attribute indices we're using so we know what to clean up + port_info[port_index]->attrs_start = device_attrs_size; + port_info[port_index]->attrs_end = device_attrs_size + ap_mfser_attrs_size; + sprintf(buf, "serial-mode:%d", port); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { @@ -234,12 +239,33 @@ static bool mfser_setup(enum ap port) { } static bool mfser_teardown(enum ap port) { + int i; + int port_index = port - 1; + log_info("unloading MFSER accessory card in port %d", port); + + // clean up allocated memory for attributes + for (i = port_info[port_index]->attrs_start; i < port_info[port_index]->attrs_end; i++) { + if (device_attrs[i]) { + if (device_attrs[i]->name) + kfree(device_attrs[i]->name); + + kfree(device_attrs[i]); + } + } + + port_info[port_index]->attrs_start = 0; + port_info[port_index]->attrs_end = 0; + return true; } -static struct ap_info mfser_info = { - .product_id = MTAC_MFSER_0_0, - .setup = &mfser_setup, - .teardown = &mfser_teardown -}; +bool set_mfser_info(struct ap_info* info) { + info->product_id = MTAC_MFSER_0_0; + info->setup = &mfser_setup; + info->teardown = &mfser_teardown; + info->attrs_start = 0; + info->attrs_end = 0; + + return true; +} -- cgit v1.2.3 From 8f1a0efb9e68a955544bce4bbc9dec6e4cb57f61 Mon Sep 17 00:00:00 2001 From: Mike Fiore Date: Thu, 25 Sep 2014 15:52:29 -0500 Subject: mts-io: add accessory card eeprom contents as read-only sysfs attribtues --- io-module/mtac_mfser.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'io-module/mtac_mfser.c') diff --git a/io-module/mtac_mfser.c b/io-module/mtac_mfser.c index 207180f..ed97cc6 100644 --- a/io-module/mtac_mfser.c +++ b/io-module/mtac_mfser.c @@ -187,7 +187,11 @@ static ssize_t mts_attr_store_mfser_mode(struct kobject *kobj, // 1 serial mode // 1 rs4xx term resistor // 1 rts override -static int ap_mfser_attrs_size = 3; +// 1 vendor-id +// 1 product-id +// 1 device-id +// 1 hw-version +static int ap_mfser_attrs_size = 7; static bool mfser_setup(enum ap port) { int port_index = port - 1; @@ -235,6 +239,12 @@ static bool mfser_setup(enum ap port) { attr->store = mts_attr_store_ap_mfser_pin; device_attrs[device_attrs_size++] = &attr->attr; + // add attributes for eeprom contents + if (! ap_add_product_info_attributes(port, MTAC_MFSER_0_0)) { + log_error("failed to add product info attributes"); + return false; + } + return true; } -- cgit v1.2.3 From 0f27f5666932274a30ca018c7dacfd7a9e5fc8bb Mon Sep 17 00:00:00 2001 From: Mike Fiore Date: Wed, 1 Oct 2014 08:41:26 -0500 Subject: mts-io: standardize lookup of pin name by attribute name 1 set of functions for ap gpio pin store and show each type of card defines a callback that specifies the mapping of attribute names to pin names --- io-module/mtac_mfser.c | 100 ++++++++----------------------------------------- 1 file changed, 16 insertions(+), 84 deletions(-) (limited to 'io-module/mtac_mfser.c') diff --git a/io-module/mtac_mfser.c b/io-module/mtac_mfser.c index ed97cc6..7c5862c 100644 --- a/io-module/mtac_mfser.c +++ b/io-module/mtac_mfser.c @@ -1,85 +1,16 @@ -struct gpio_pin *ap_mfser_pin_by_attr_name(const char *name) { - struct gpio_pin *pin; - char *pin_attr_name; - - if (!strcmp(name, "rs4xx-term-res:1")) { - pin_attr_name = "ap1-gpio3"; - } else if (!strcmp(name, "rts-override:1")) { - pin_attr_name = "ap1-gpio4"; - } else if (!strcmp(name, "rs4xx-term-res:2")) { - pin_attr_name = "ap2-gpio3"; - } else if (!strcmp(name, "rts-override:2")) { - pin_attr_name = "ap2-gpio4"; +static char* mfser_gpio_pin_name_by_attr_name(const char* name) { + if (! strcmp(name, "rs4xx-term-res:1")) { + return "ap1-gpio3"; + } else if (! strcmp(name, "rts-override:1")) { + return "ap1-gpio4"; + } else if (! strcmp(name, "rs4xx-term-res:2")) { + return "ap2-gpio3"; + } else if (! strcmp(name, "rts-override:2")) { + return "ap2-gpio4"; } else { - log_error("accessory card attribute %s not available", name); - return NULL; + log_error("attirbute name [%s] is invalid for MFSER", name); + return ""; } - - for (pin = gpio_pins; *pin->name; pin++) { - if (!strcmp(pin->pin.label, pin_attr_name)) { - return pin; - } - } - - log_error("pin with attr name %s not found", name); - - return NULL; -} - - -static ssize_t mts_attr_show_ap_mfser_pin(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - int value; - struct gpio_pin *pin = ap_mfser_pin_by_attr_name(attr->attr.name); - - if (!pin) { - return -ENODEV; - } - - mutex_lock(&mts_io_mutex); - - value = gpio_get_value(pin->pin.gpio); - - mutex_unlock(&mts_io_mutex); - - if (value < 0) { - return value; - } - - if (pin->active_low) { - value = !value; - } - - return sprintf(buf, "%d\n", value); -} - -static ssize_t mts_attr_store_ap_mfser_pin(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) -{ - int value; - struct gpio_pin *pin = ap_mfser_pin_by_attr_name(attr->attr.name); - - if (!pin) { - return -ENODEV; - } - - if (sscanf(buf, "%i", &value) != 1) { - return -EINVAL; - } - - if (pin->active_low) { - value = !value; - } - - mutex_lock(&mts_io_mutex); - - gpio_set_value(pin->pin.gpio, value); - - mutex_unlock(&mts_io_mutex); - - return count; } static ssize_t mts_attr_show_mfser_mode(struct kobject *kobj, @@ -225,8 +156,8 @@ static bool mfser_setup(enum ap port) { log_error("failed to create attribute[%s]", buf); return false; } - attr->show = mts_attr_show_ap_mfser_pin; - attr->store = mts_attr_store_ap_mfser_pin; + attr->show = mts_attr_show_ap_gpio_pin; + attr->store = mts_attr_store_ap_gpio_pin; device_attrs[device_attrs_size++] = &attr->attr; sprintf(buf, "rts-override:%d", port); @@ -235,8 +166,8 @@ static bool mfser_setup(enum ap port) { log_error("failed to create attribute[%s]", buf); return false; } - attr->show = mts_attr_show_ap_mfser_pin; - attr->store = mts_attr_store_ap_mfser_pin; + attr->show = mts_attr_show_ap_gpio_pin; + attr->store = mts_attr_store_ap_gpio_pin; device_attrs[device_attrs_size++] = &attr->attr; // add attributes for eeprom contents @@ -276,6 +207,7 @@ bool set_mfser_info(struct ap_info* info) { info->teardown = &mfser_teardown; info->attrs_start = 0; info->attrs_end = 0; + info->gpio_pin_name_by_attr_name = &mfser_gpio_pin_name_by_attr_name; return true; } -- cgit v1.2.3 From f9010f0863063e6836394469edf43e86c98d49fe Mon Sep 17 00:00:00 2001 From: Mike Fiore Date: Fri, 3 Oct 2014 15:09:42 -0500 Subject: mts-io: reorganize accessory card attributes, move them into subdirs under mts-io subdirs named ap1, ap2, etc create links to subdirs with name of card in port, e.g. gpiob, mfser, eth, etc if 2 of same type of card, still make links but use gpiob-2, mfser-2, etc --- io-module/mtac_mfser.c | 192 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 132 insertions(+), 60 deletions(-) (limited to 'io-module/mtac_mfser.c') diff --git a/io-module/mtac_mfser.c b/io-module/mtac_mfser.c index 7c5862c..27ca4dc 100644 --- a/io-module/mtac_mfser.c +++ b/io-module/mtac_mfser.c @@ -1,15 +1,24 @@ -static char* mfser_gpio_pin_name_by_attr_name(const char* name) { - if (! strcmp(name, "rs4xx-term-res:1")) { - return "ap1-gpio3"; - } else if (! strcmp(name, "rts-override:1")) { - return "ap1-gpio4"; - } else if (! strcmp(name, "rs4xx-term-res:2")) { - return "ap2-gpio3"; - } else if (! strcmp(name, "rts-override:2")) { - return "ap2-gpio4"; - } else { - log_error("attirbute name [%s] is invalid for MFSER", name); - return ""; +static char* mfser_gpio_pin_name_by_attr_name(const char* name, int port) { + switch (port) { + case port_1: + if (! strcmp(name, "rs4xx-term-res")) { + return "ap1-gpio3"; + } else if (! strcmp(name, "rts-override")) { + return "ap1-gpio4"; + } else { + log_error("attirbute name [%s] is invalid for MFSER in port %d", name, port); + return ""; + } + + case port_2: + if (! strcmp(name, "rs4xx-term-res")) { + return "ap2-gpio3"; + } else if (! strcmp(name, "rts-override")) { + return "ap2-gpio4"; + } else { + log_error("attirbute name [%s] is invalid for MFSER in port %d", name, port); + return ""; + } } } @@ -18,23 +27,33 @@ static ssize_t mts_attr_show_mfser_mode(struct kobject *kobj, char *buf) { int ret; + int port; int modesel0; int modesel1; struct gpio_pin *pin_modesel0; struct gpio_pin *pin_modesel1; - if (strstr(attr->attr.name, ":1")) { - pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); - pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); - } - else if (strstr(attr->attr.name, ":2")) { - pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); - pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); + port = port_from_kobject(kobj); + if (port < 0) { + log_error("port_from_kobject returned %d", port); + return -EINVAL; } - else { - log_error("unknown serial-mode attr %s", attr->attr.name); - return -ENODEV; + + switch (port) { + case port_1: + pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); + break; + + case port_2: + pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); + break; + + default: + log_error("unknown serial-mode attr [%s]", attr->attr.name); + return -ENODEV; } if (!pin_modesel0 || !pin_modesel1) @@ -64,22 +83,32 @@ static ssize_t mts_attr_show_mfser_mode(struct kobject *kobj, static ssize_t mts_attr_store_mfser_mode(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { + int port; int modesel0; int modesel1; struct gpio_pin *pin_modesel0; struct gpio_pin *pin_modesel1; - if (strstr(attr->attr.name, ":1")) { - pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); - pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); - } - else if (strstr(attr->attr.name, ":2")) { - pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); - pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); + port = port_from_kobject(kobj); + if (port < 0) { + log_error("port_from_kobject returned %d", port); + return -EINVAL; } - else { - log_error("unknown serial-mode attr %s", attr->attr.name); - return -ENODEV; + + switch (port) { + case port_1: + pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); + break; + + case port_2: + pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); + pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); + break; + + default: + log_error("unknown serial-mode attr [%s]", attr->attr.name); + return -ENODEV; } if (!pin_modesel0 || !pin_modesel1) @@ -122,57 +151,97 @@ static ssize_t mts_attr_store_mfser_mode(struct kobject *kobj, // 1 product-id // 1 device-id // 1 hw-version -static int ap_mfser_attrs_size = 7; +// NULL +static size_t ap_mfser_attrs_size = 8; static bool mfser_setup(enum ap port) { + int i; int port_index = port - 1; - struct kobj_attribute *attr; + int index = 0; + int count = 0; + int ret; char buf[32]; + struct kobj_attribute* attr; + struct attribute **attrs; log_info("loading MFSER accessory card in port %d", port); - if (device_attrs_size + ap_mfser_attrs_size >= device_attrs_max_size) { - log_error("can't load MFSER accessory card in port %d - not enough room for attributes", port); + sprintf(buf, "ap%d", port); + ap_subdirs[port_index] = kobject_create_and_add(buf, &mts_io_platform_device->dev.kobj); + if (! ap_subdirs[port_index]) { + log_error("kobject_create_and_add for MFSER in port %d failed", port); return false; } - // mark the attribute indices we're using so we know what to clean up - port_info[port_index]->attrs_start = device_attrs_size; - port_info[port_index]->attrs_end = device_attrs_size + ap_mfser_attrs_size; + // create the link to the apX directory this card is in + // if we're in the first slot, we get plain "mfser" + // if we're in a different slot, we might need to use "mfser-2" to differentiate + if (port > 1) { + for (i = 1; i < port; i++) { + if (port_info[i - 1]) { + if (strstr(port_info[i - 1]->product_id, PRODUCT_ID_MTAC_MFSER)) { + count++; + } + } + } + } + if (count > 0) { + sprintf(buf, "mfser-%d", count + 1); + } else { + sprintf(buf, "mfser"); + } + ret = sysfs_create_link(ap_subdirs[port_index]->parent, ap_subdirs[port_index], buf); + if (ret) { + log_error("failed to link [%s] to [%s], %d", buf, ap_subdirs[port_index]->name, ret); + } + + attrs = kzalloc(sizeof(struct attribute*) * ap_mfser_attrs_size, GFP_KERNEL); + if (! attrs) { + log_error("failed to allocate attribute space for port %d", port); + return false; + } - sprintf(buf, "serial-mode:%d", port); + sprintf(buf, "serial-mode"); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for MFSER in port %d", buf, port); return false; } attr->show = mts_attr_show_mfser_mode; attr->store = mts_attr_store_mfser_mode; - device_attrs[device_attrs_size++] = &attr->attr; + attrs[index++] = &attr->attr; - sprintf(buf, "rs4xx-term-res:%d", port); + sprintf(buf, "rs4xx-term-res"); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for MFSER in port %d", buf, port); return false; } attr->show = mts_attr_show_ap_gpio_pin; attr->store = mts_attr_store_ap_gpio_pin; - device_attrs[device_attrs_size++] = &attr->attr; + attrs[index++] = &attr->attr; - sprintf(buf, "rts-override:%d", port); + sprintf(buf, "rts-override"); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for MFSER in port %d", buf, port); return false; } attr->show = mts_attr_show_ap_gpio_pin; attr->store = mts_attr_store_ap_gpio_pin; - device_attrs[device_attrs_size++] = &attr->attr; + attrs[index++] = &attr->attr; // add attributes for eeprom contents - if (! ap_add_product_info_attributes(port, MTAC_MFSER_0_0)) { - log_error("failed to add product info attributes"); + if (! ap_add_product_info_attributes(port, MTAC_MFSER_0_0, attrs, &index)) { + log_error("failed to add product info attributes for MFSER in port %d", port); + return false; + } + + attrs[index] = NULL; + + ap_attr_groups[port_index].attrs = attrs; + if (sysfs_create_group(ap_subdirs[port_index], &ap_attr_groups[port_index])) { + log_error("sysfs_create_group failed for MFSER in port %d", port); return false; } @@ -182,31 +251,34 @@ static bool mfser_setup(enum ap port) { static bool mfser_teardown(enum ap port) { int i; int port_index = port - 1; + struct attribute **attrs = ap_attr_groups[port_index].attrs; log_info("unloading MFSER accessory card in port %d", port); // clean up allocated memory for attributes - for (i = port_info[port_index]->attrs_start; i < port_info[port_index]->attrs_end; i++) { - if (device_attrs[i]) { - if (device_attrs[i]->name) - kfree(device_attrs[i]->name); + for (i = 0; i < ap_mfser_attrs_size; i++) { + if (attrs[i]) { + if (attrs[i]->name) + kfree(attrs[i]->name); - kfree(device_attrs[i]); + kfree(attrs[i]); } } - port_info[port_index]->attrs_start = 0; - port_info[port_index]->attrs_end = 0; + kfree(attrs); + + // clean up our "apX/" kobject if it exists + if (ap_subdirs[port_index]) { + kobject_put(ap_subdirs[port_index]); + } return true; } bool set_mfser_info(struct ap_info* info) { - info->product_id = MTAC_MFSER_0_0; + snprintf(info->product_id, 32, "%s", PRODUCT_ID_MTAC_MFSER); info->setup = &mfser_setup; info->teardown = &mfser_teardown; - info->attrs_start = 0; - info->attrs_end = 0; info->gpio_pin_name_by_attr_name = &mfser_gpio_pin_name_by_attr_name; return true; -- cgit v1.2.3