lkml.org 
[lkml]   [2013]   [Dec]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 15/16] misc: support for I-8042 in LP-8x4x
    Date
    Status of I-8042 16 digital output channels can be managed via
    sysfs.

    Status of I-8042 16 digital input channels can be read via sysfs.

    http://www.icpdas.com/products/Remote_IO/i-8ke/i-8042w.htm

    Signed-off-by: Sergei Ianovich <ynvich@gmail.com>
    ---
    v0..v2
    * no changes

    Documentation/misc-devices/lp8x4x_bus.txt | 4 ++
    drivers/misc/lp8x4x_bus.c | 76 ++++++++++++++++++++++++++++++-
    2 files changed, 78 insertions(+), 2 deletions(-)

    diff --git a/Documentation/misc-devices/lp8x4x_bus.txt b/Documentation/misc-devices/lp8x4x_bus.txt
    index 74df10b..e3a8bcf 100644
    --- a/Documentation/misc-devices/lp8x4x_bus.txt
    +++ b/Documentation/misc-devices/lp8x4x_bus.txt
    @@ -50,6 +50,10 @@ active_slot
    model
    RO - shows expansion module model number

    +input_status
    + RO - get status of digital input channels on the module in
    + the expansion slot.
    +
    output_status
    RW - set status of digital output channels on the module in
    the expansion slot. Value can be read back.
    diff --git a/drivers/misc/lp8x4x_bus.c b/drivers/misc/lp8x4x_bus.c
    index 1ef1726..684e640 100644
    --- a/drivers/misc/lp8x4x_bus.c
    +++ b/drivers/misc/lp8x4x_bus.c
    @@ -27,6 +27,8 @@ struct lp8x4x_slot {
    struct mutex lock;
    unsigned int DO_len;
    u32 DO;
    + unsigned int DI_len;
    + u32 DI;
    struct device dev;
    };

    @@ -89,6 +91,21 @@ static void lp8x4x_slot_release(struct device *dev)
    {
    }

    +static void lp8x4x_slot_get_DI(struct lp8x4x_slot *s)
    +{
    + int i;
    + u32 b;
    +
    + mutex_lock(&s->lock);
    + s->DI = 0;
    + for (i = 0; i < s->DI_len; i++) {
    + b = ioread8(s->data_addr + 2 * (i + 1));
    + b ^= 0xff;
    + s->DI += b << (i * 8);
    + }
    + mutex_unlock(&s->lock);
    +}
    +
    static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
    {
    int i;
    @@ -98,29 +115,70 @@ static void lp8x4x_slot_set_DO(struct lp8x4x_slot *s)
    mutex_unlock(&s->lock);
    }

    +static ssize_t input_status_show(struct device *dev,
    + struct device_attribute *attr, char *buf)
    +{
    + struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
    +
    + lp8x4x_slot_get_DI(s);
    + switch (s->DI_len) {
    + case 4:
    + return sprintf(buf, "0x%08x\n", s->DI);
    + case 2:
    + return sprintf(buf, "0x%04x\n", s->DI);
    + case 1:
    + return sprintf(buf, "0x%02x\n", s->DI);
    + default:
    + break;
    + }
    + return sprintf(buf, "0x%x\n", s->DI);
    +}
    +
    +static DEVICE_ATTR_RO(input_status);
    +
    static ssize_t output_status_show(struct device *dev,
    struct device_attribute *attr, char *buf)
    {
    struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);

    - return sprintf(buf, "0x%08x\n", s->DO);
    + switch (s->DO_len) {
    + case 4:
    + return sprintf(buf, "0x%08x\n", s->DO);
    + case 2:
    + return sprintf(buf, "0x%04x\n", s->DO);
    + case 1:
    + return sprintf(buf, "0x%02x\n", s->DO);
    + default:
    + break;
    + }
    + return sprintf(buf, "0x%x\n", s->DO);
    }

    static ssize_t output_status_store(struct device *dev,
    struct device_attribute *attr, const char *buf, size_t count)
    {
    struct lp8x4x_slot *s = container_of(dev, struct lp8x4x_slot, dev);
    + u32 DO;
    + u8 *b = (void *) &DO;
    + int i;

    if (!buf)
    return count;
    if (0 == count)
    return count;

    - if (kstrtouint(buf, 16, &s->DO) != 0) {
    + if (kstrtouint(buf, 16, &DO) != 0) {
    dev_err(dev, "bad input\n");
    return count;
    }

    + for (i = 4; i > s->DO_len; i--)
    + if (b[i - 1] != 0) {
    + dev_err(dev, "bad input\n");
    + return count;
    + }
    +
    + s->DO = DO;
    lp8x4x_slot_set_DO(s);

    return count;
    @@ -151,6 +209,14 @@ static struct attribute *do_slot_dev_attrs[] = {
    };
    ATTRIBUTE_GROUPS(do_slot_dev);

    +static struct attribute *dio_slot_dev_attrs[] = {
    + &dev_attr_model.attr,
    + &dev_attr_output_status.attr,
    + &dev_attr_input_status.attr,
    + NULL,
    +};
    +ATTRIBUTE_GROUPS(dio_slot_dev);
    +
    static void lp8x4x_master_release(struct device *dev)
    {
    struct lp8x4x_master *m = container_of(dev, struct lp8x4x_master, dev);
    @@ -255,6 +321,12 @@ static void __init lp8x4x_bus_probe_slot(struct lp8x4x_master *m, int i,
    lp8x4x_slot_set_DO(s);
    s->dev.groups = do_slot_dev_groups;
    break;
    + case 42:
    + s->DI_len = 2;
    + s->DO_len = 2;
    + lp8x4x_slot_set_DO(s);
    + s->dev.groups = dio_slot_dev_groups;
    + break;
    default:
    s->dev.groups = slot_dev_groups;
    break;
    --
    1.8.4.3


    \
     
     \ /
      Last update: 2013-12-13 04:21    [W:4.241 / U:0.296 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site