From patchwork Sat Dec 24 13:22:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peter A. Bigot" X-Patchwork-Id: 9488039 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 97A64601D3 for ; Sat, 24 Dec 2016 13:23:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 86D2B2723E for ; Sat, 24 Dec 2016 13:23:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 77F8227D0E; Sat, 24 Dec 2016 13:23:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AC1702723E for ; Sat, 24 Dec 2016 13:23:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754667AbcLXNXl (ORCPT ); Sat, 24 Dec 2016 08:23:41 -0500 Received: from p3plsmtpa08-09.prod.phx3.secureserver.net ([173.201.193.110]:39086 "EHLO p3plsmtpa08-09.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754791AbcLXNXk (ORCPT ); Sat, 24 Dec 2016 08:23:40 -0500 Received: from lilith.pab ([50.171.212.13]) by :SMTPAUTH: with SMTP id KmHccestN7IxkKmHdcqgjF; Sat, 24 Dec 2016 06:22:45 -0700 From: "Peter A. Bigot" To: linux-hwmon@vger.kernel.org Cc: urs.fleisch@sensirion.com Subject: [PATCH v3] hwmon: (sht21) Add Electronic Identification Code retrieval Date: Sat, 24 Dec 2016 07:22:44 -0600 Message-Id: <1482585764-21529-1-git-send-email-pab@pabigot.com> X-Mailer: git-send-email 2.7.4 X-CMAE-Envelope: MS4wfG8z0bSUKmSscyVLX0kyIH2910LcNkxdLfT28GNAh96LatX3E/u/nWaUR4qfPyDmhNjR3wJU/B71zp7A/OzHLa35dsUYs+xmE+YEAhwPaR6IImzjT6+Y 8ZPf8gTWj2oIWDQ18pYLZDBzgraQ0UTHjh8iKI9I9h1kNXBsidKNEJqJh6rsycPedqSPKVSDPVnNVc5Hiwl4TAQPhmzA0rwBxw0= Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Expose the per-chip unique identifier so it can be used to identify the sensor producing the measurements. Signed-off-by: Peter A. Bigot --- v3: Use permission-specific DEVICE_ATTR for new attribute v2: Remove unnecessary copyright/authorship claims. Define symbolic names for serial number read commands. Provide separate function to read EIC. Rearrange device data structure slightly to reduce alignment padding. Store EIC in ASCII form and mark validity using non-NUL character. Use hard-coded lengths and avoid redundant assignments. Change attribute name. Documentation/hwmon/sht21 | 5 +-- drivers/hwmon/sht21.c | 92 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/Documentation/hwmon/sht21 b/Documentation/hwmon/sht21 index db17fda..47f4765 100644 --- a/Documentation/hwmon/sht21 +++ b/Documentation/hwmon/sht21 @@ -35,6 +35,7 @@ sysfs-Interface temp1_input - temperature input humidity1_input - humidity input +eic - Electronic Identification Code Notes ----- @@ -45,5 +46,5 @@ humidity and 66 ms for temperature. To keep self heating below 0.1 degree Celsius, the device should not be active for more than 10% of the time, e.g. maximum two measurements per second at the given resolution. -Different resolutions, the on-chip heater, using the CRC checksum and reading -the serial number are not supported yet. +Different resolutions, the on-chip heater, and using the CRC checksum +are not supported yet. diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 84cdb1c..06706d2 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -34,23 +34,29 @@ /* I2C command bytes */ #define SHT21_TRIG_T_MEASUREMENT_HM 0xe3 #define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5 +#define SHT21_READ_SNB_CMD1 0xFA +#define SHT21_READ_SNB_CMD2 0x0F +#define SHT21_READ_SNAC_CMD1 0xFC +#define SHT21_READ_SNAC_CMD2 0xC9 /** * struct sht21 - SHT21 device specific data * @hwmon_dev: device registered with hwmon * @lock: mutex to protect measurement values - * @valid: only 0 before first measurement is taken * @last_update: time of last update (jiffies) * @temperature: cached temperature measurement value * @humidity: cached humidity measurement value + * @valid: only 0 before first measurement is taken + * @eic: cached electronic identification code text */ struct sht21 { struct i2c_client *client; struct mutex lock; - char valid; unsigned long last_update; int temperature; int humidity; + char valid; + char eic[18]; }; /** @@ -165,15 +171,97 @@ static ssize_t sht21_show_humidity(struct device *dev, return sprintf(buf, "%d\n", sht21->humidity); } +static ssize_t eic_read(struct sht21 *sht21) +{ + struct i2c_client *client = sht21->client; + u8 tx[2]; + u8 rx[8]; + u8 eic[8]; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = tx, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 8, + .buf = rx, + }, + }; + int ret; + + tx[0] = SHT21_READ_SNB_CMD1; + tx[1] = SHT21_READ_SNB_CMD2; + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) + goto out; + eic[2] = rx[0]; + eic[3] = rx[2]; + eic[4] = rx[4]; + eic[5] = rx[6]; + + tx[0] = SHT21_READ_SNAC_CMD1; + tx[1] = SHT21_READ_SNAC_CMD2; + msgs[1].len = 6; + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) + goto out; + eic[0] = rx[3]; + eic[1] = rx[4]; + eic[6] = rx[0]; + eic[7] = rx[1]; + + ret = snprintf(sht21->eic, sizeof(sht21->eic), + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + eic[0], eic[1], eic[2], eic[3], + eic[4], eic[5], eic[6], eic[7]); +out: + if (ret < 0) + sht21->eic[0] = 0; + + return ret; +} + +/** + * eic_show() - show Electronic Identification Code in sysfs + * @dev: device + * @attr: device attribute + * @buf: sysfs buffer (PAGE_SIZE) where EIC is written + * + * Will be called on read access to eic sysfs attribute. + * Returns number of bytes written into buffer, negative errno on error. + */ +static ssize_t eic_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sht21 *sht21 = dev_get_drvdata(dev); + int ret; + + ret = sizeof(sht21->eic) - 1; + mutex_lock(&sht21->lock); + if (!sht21->eic[0]) + ret = eic_read(sht21); + if (ret > 0) + memcpy(buf, sht21->eic, ret); + mutex_unlock(&sht21->lock); + return ret; +} + /* sysfs attributes */ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature, NULL, 0); static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity, NULL, 0); +static DEVICE_ATTR_RO(eic); static struct attribute *sht21_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_humidity1_input.dev_attr.attr, + &dev_attr_eic.attr, NULL };