diff options
| author | Eric Tashakkor <w36098@motorola.com> | 2014-05-06 10:23:34 -0500 | 
|---|---|---|
| committer | ERIC TASHAKKOR <w36098@motorola.com> | 2014-05-07 15:34:05 +0000 | 
| commit | cbe7c918fe51e44e009b2839716c8ca9d5a1fefd (patch) | |
| tree | f8bbcd7fea39310d0ce7dd5dbac7f018f95b2bd9 /drivers/misc/m4sensorhub_pedometer.c | |
| parent | 4f75bd140f9838c09ac62c1cfded9df37327b022 (diff) | |
| download | olio-linux-3.10-cbe7c918fe51e44e009b2839716c8ca9d5a1fefd.tar.xz olio-linux-3.10-cbe7c918fe51e44e009b2839716c8ca9d5a1fefd.zip  | |
IKXCLOCK-1067 Need User Profile to improve pedometer/calorie accuracy (Kernel changes)
Added "userdata" sysfs interface to handle writing/reading M4 user data.
Change-Id: I50c66a96ad4a1f8c060fe886dc20a3dce37a47eb
Signed-off-by: Eric Tashakkor <w36098@motorola.com>
Diffstat (limited to 'drivers/misc/m4sensorhub_pedometer.c')
| -rw-r--r-- | drivers/misc/m4sensorhub_pedometer.c | 129 | 
1 files changed, 129 insertions, 0 deletions
diff --git a/drivers/misc/m4sensorhub_pedometer.c b/drivers/misc/m4sensorhub_pedometer.c index ce932cc4df9..68b2299e1ac 100644 --- a/drivers/misc/m4sensorhub_pedometer.c +++ b/drivers/misc/m4sensorhub_pedometer.c @@ -313,9 +313,138 @@ static ssize_t m4ped_iiodata_show(struct device *dev,  }  static IIO_DEVICE_ATTR(iiodata, S_IRUGO, m4ped_iiodata_show, NULL, 0); +static ssize_t m4ped_userdata_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	int err = 0; +	struct platform_device *pdev = to_platform_device(dev); +	struct iio_dev *iio = platform_get_drvdata(pdev); +	struct m4ped_driver_data *dd = iio_priv(iio); +	ssize_t size = 0; +	uint8_t data[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; + +	mutex_lock(&(dd->mutex)); + +	err = m4sensorhub_reg_read_n(dd->m4, M4SH_REG_USERSETTINGS_VERSION, +		(char *)&(data[0]), ARRAY_SIZE(data)); +	if (err < 0) { +		m4ped_err("%s: Failed to read user data.\n", __func__); +		goto m4ped_userdata_show_fail; +	} else if (err < ARRAY_SIZE(data)) { +		m4ped_err("%s: Read %d bytes instead of %d.\n", +			  __func__, err, size); +		err = -EBADE; +		goto m4ped_userdata_show_fail; +	} + +	if (data[0] > 0) { +		m4ped_err("%s: User settings version is too new (0x%02X)\n", +			  __func__, data[0]); +		err = -EINVAL; +		goto m4ped_userdata_show_fail; +	} + +	size = snprintf(buf, PAGE_SIZE, +		"%s%s\n%s%hhu\n%s%hhu\n%s%hhu\n", +		"Gender (M/F): ", data[2] ? "M" : "F", +		"Age    (yrs): ", data[1], +		"Height  (cm): ", data[3], +		"Weight  (kg): ", data[4]); + +m4ped_userdata_show_fail: +	mutex_unlock(&(dd->mutex)); + +	if (err < 0) +		size = snprintf(buf, PAGE_SIZE, "Read failed (check dmesg)\n"); + +	return size; +} +/* + * Expected input is Gender, Age, Height, Weight + * Example: + *    Female, 22, 168cm, 49kg + *    0x00,0x16,0xA7,0x31\n + */ +static ssize_t m4ped_userdata_store(struct device *dev, +		struct device_attribute *attr, const char *buf, size_t size) +{ +	int err = 0; +	struct platform_device *pdev = to_platform_device(dev); +	struct iio_dev *iio = platform_get_drvdata(pdev); +	struct m4ped_driver_data *dd = iio_priv(iio); +	unsigned int value = 0; +	unsigned char convbuf[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; +	unsigned char outbuf[4] = {0x00, 0x00, 0x00, 0x00}; +	int i = 0; + +	mutex_lock(&(dd->mutex)); + +	/* Size includes a terminating '\n' but not the terminating null */ +	if (size != 20) { +		m4ped_err("%s: Invalid data format.  %s\n", +			  __func__, "Use \"0xHH,0xHH,0xHH,0xHH\\n\" instead."); +		err = -EINVAL; +		goto m4ped_userdata_store_fail; +	} + +	for (i = 0; i < 4; i++) { +		memcpy(convbuf, &(buf[i*5]), 4); +		err = kstrtouint(convbuf, 16, &value); +		if (err < 0) { +			m4ped_err("%s: Argument %d conversion failed.\n", +				  __func__, i); +			goto m4ped_userdata_store_fail; +		} else if (value > 255) { +			m4ped_err("%s: Value 0x%08X is too large.\n", +				  __func__, value); +			err = -EOVERFLOW; +			goto m4ped_userdata_store_fail; +		} +		outbuf[i] = (unsigned char) value; +	} + +	err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERAGE, +		&(outbuf[1]), m4sh_no_mask); +	if (err < 0) { +		m4ped_err("%s: Failed to write user data.\n", __func__); +		goto m4ped_userdata_store_fail; +	} + +	err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERGENDER, +		&(outbuf[0]), m4sh_no_mask); +	if (err < 0) { +		m4ped_err("%s: Failed to write user data.\n", __func__); +		goto m4ped_userdata_store_fail; +	} + +	err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERHEIGHT, +		&(outbuf[2]), m4sh_no_mask); +	if (err < 0) { +		m4ped_err("%s: Failed to write user data.\n", __func__); +		goto m4ped_userdata_store_fail; +	} + +	err = m4sensorhub_reg_write_n(dd->m4, M4SH_REG_USERSETTINGS_USERWEIGHT, +		&(outbuf[3]), m4sh_no_mask, 1); +	if (err < 0) { +		m4ped_err("%s: Failed to write user data.\n", __func__); +		goto m4ped_userdata_store_fail; +	} + +	err = size; + +m4ped_userdata_store_fail: +	mutex_unlock(&(dd->mutex)); + +	return (ssize_t) err; +} +static IIO_DEVICE_ATTR(userdata, S_IRUSR | S_IWUSR, +		m4ped_userdata_show, m4ped_userdata_store, 0); +  static struct attribute *m4ped_iio_attributes[] = {  	&iio_dev_attr_setrate.dev_attr.attr,  	&iio_dev_attr_iiodata.dev_attr.attr, +	&iio_dev_attr_userdata.dev_attr.attr,  	NULL,  };  |