|
@@ -32,6 +32,7 @@ enum gsensor_orientation_hex
|
|
|
|
|
|
|
|
#define GSENSOR_MODE_SOFT_RESET BIT(2)
|
|
#define GSENSOR_MODE_SOFT_RESET BIT(2)
|
|
|
#define GSENSOR_MODE_INITIALIZED BIT(1)
|
|
#define GSENSOR_MODE_INITIALIZED BIT(1)
|
|
|
|
|
+#define GSENSOR_MODE_INTERRUPT BIT(0)
|
|
|
|
|
|
|
|
/* Register Definitions */
|
|
/* Register Definitions */
|
|
|
#define ST_ACCEL_WHO_AM_I_ADDR 0x0F
|
|
#define ST_ACCEL_WHO_AM_I_ADDR 0x0F
|
|
@@ -364,19 +365,70 @@ static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
if (!data)
|
|
if (!data)
|
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
- if (kstrtoul(buf, 0, &val))
|
|
|
|
|
|
|
+ int ret = kstrtoul(buf, 0, &val);
|
|
|
|
|
+ if (ret) {
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Valid mode values check
|
|
|
|
|
+ * 0x01 - interrupt mode (BIT0)
|
|
|
|
|
+ * 0x04 - soft reset (BIT2)
|
|
|
|
|
+ * 0x05 - interrupt mode + soft reset (BIT0 | BIT2)
|
|
|
|
|
+ */
|
|
|
|
|
+ if (val != 0x01 && val != 0x04 && val != 0x05) {
|
|
|
|
|
+ dev_err(data->client ? &data->client->dev : NULL,
|
|
|
|
|
+ "Invalid mode value: 0x%02lx. Valid values: 0x01 (interrupt), "
|
|
|
|
|
+ "0x04 (soft reset), 0x05 (interrupt + soft reset)\n", val);
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ mutex_lock(&data->lock);
|
|
|
|
|
|
|
|
|
|
+ /* Handle soft reset (BIT2) */
|
|
|
if (val & GSENSOR_MODE_SOFT_RESET) {
|
|
if (val & GSENSOR_MODE_SOFT_RESET) {
|
|
|
- mutex_lock(&data->lock);
|
|
|
|
|
- gsensor_init_sensor(data);
|
|
|
|
|
- data->orientation_hex = GSENSOR_ORIENT_LANDSCAPE_HEX;
|
|
|
|
|
- strcpy(data->orientation_str, GSENSOR_ORIENT_LANDSCAPE_STR);
|
|
|
|
|
- mutex_unlock(&data->lock);
|
|
|
|
|
|
|
+ bool was_enabled = data->enabled;
|
|
|
|
|
+
|
|
|
|
|
+ /* Disable sensor if enabled */
|
|
|
|
|
+ if (was_enabled) {
|
|
|
|
|
+ cancel_delayed_work_sync(&data->poll_work);
|
|
|
|
|
+ gsensor_set_enable(data, false);
|
|
|
|
|
+ data->enabled = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Reinitialize sensor */
|
|
|
|
|
+ ret = gsensor_init_sensor(data);
|
|
|
|
|
+ if (ret == 0) {
|
|
|
|
|
+ data->orientation_hex = GSENSOR_ORIENT_LANDSCAPE_HEX;
|
|
|
|
|
+ strcpy(data->orientation_str, GSENSOR_ORIENT_LANDSCAPE_STR);
|
|
|
|
|
+ dev_info(&data->client->dev, "Soft reset completed\n");
|
|
|
|
|
+
|
|
|
|
|
+ /* Re-enable if it was enabled before */
|
|
|
|
|
+ if (was_enabled) {
|
|
|
|
|
+ ret = gsensor_set_enable(data, true);
|
|
|
|
|
+ if (ret == 0) {
|
|
|
|
|
+ data->enabled = true;
|
|
|
|
|
+ schedule_delayed_work(&data->poll_work, 0);
|
|
|
|
|
+ gsensor_update_orientation(data);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dev_err(&data->client->dev, "Soft reset failed: %d\n", ret);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return count;
|
|
|
|
|
|
|
+ /* Handle interrupt mode (BIT0) - currently driver uses polling mode */
|
|
|
|
|
+ if (val & GSENSOR_MODE_INTERRUPT) {
|
|
|
|
|
+ dev_info(
|
|
|
|
|
+ &data->client->dev,
|
|
|
|
|
+ "Interrupt mode requested (0x01), but driver uses polling mode\n");
|
|
|
|
|
+ /* Interrupt mode support can be added here if needed */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ mutex_unlock(&data->lock);
|
|
|
|
|
+
|
|
|
|
|
+ return ret < 0 ? ret : count;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
static struct kobj_attribute mode_attr = __ATTR_RW(mode);
|
|
static struct kobj_attribute mode_attr = __ATTR_RW(mode);
|
|
|
|
|
|
|
|
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
|