Browse Source

Fix gsensor build issue on new env system.

user 1 month ago
parent
commit
c7e58c0a0d
2 changed files with 184 additions and 622 deletions
  1. 181 406
      gsensor.c
  2. 3 216
      gsensor.h

+ 181 - 406
gsensor.c

@@ -12,68 +12,55 @@
 #include <linux/sysfs.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/trigger.h>
-#include <linux/iio/triggered_buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/irq.h>
-
-#if 0
+
 extern struct kobject *vfiec_kobj;
 
 /* Verifone API Definitions */
-enum gsensor_orientation_hex {
-    GSENSOR_ORIENT_UNKNOWN_HEX      = 0x00,
-    GSENSOR_ORIENT_PORTRAIT_HEX     = 0x14,
-    GSENSOR_ORIENT_LANDSCAPE_HEX    = 0x15,
-    GSENSOR_ORIENT_PORTRAIT_FLIP_HEX = 0x16,
+enum gsensor_orientation_hex
+{
+    GSENSOR_ORIENT_UNKNOWN_HEX        = 0x00,
+    GSENSOR_ORIENT_PORTRAIT_HEX       = 0x14,
+    GSENSOR_ORIENT_LANDSCAPE_HEX      = 0x15,
+    GSENSOR_ORIENT_PORTRAIT_FLIP_HEX  = 0x16,
     GSENSOR_ORIENT_LANDSCAPE_FLIP_HEX = 0x17,
 };
 
-#define GSENSOR_ORIENT_PORTRAIT_STR     "portrait"
-#define GSENSOR_ORIENT_LANDSCAPE_STR    "landscape"
-#define GSENSOR_ORIENT_PORTRAIT_FLIP_STR "portrait_flip"
+#define GSENSOR_ORIENT_PORTRAIT_STR       "portrait"
+#define GSENSOR_ORIENT_LANDSCAPE_STR      "landscape"
+#define GSENSOR_ORIENT_PORTRAIT_FLIP_STR  "portrait_flip"
 #define GSENSOR_ORIENT_LANDSCAPE_FLIP_STR "landscape_flip"
 
-#define GSENSOR_MODE_SOFT_RESET     BIT(2)
-#define GSENSOR_MODE_INITIALIZED    BIT(1)
+#define GSENSOR_MODE_SOFT_RESET           BIT(2)
+#define GSENSOR_MODE_INITIALIZED          BIT(1)
 
 /* Register Definitions */
-#define ST_ACCEL_WHO_AM_I_ADDR      0x0F
-#define ST_ACCEL_CTRL_REG1_ADDR     0x20
-#define ST_ACCEL_CTRL_REG4_ADDR     0x23
-#define ST_ACCEL_OUT_X_L_ADDR       0x28
-#define ST_ACCEL_STATUS_REG_ADDR    0x27
+#define ST_ACCEL_WHO_AM_I_ADDR            0x0F
+#define ST_ACCEL_CTRL_REG1_ADDR           0x20
+#define ST_ACCEL_CTRL_REG4_ADDR           0x23
+#define ST_ACCEL_OUT_X_L_ADDR             0x28
 
-#define SC7A20_WHO_AM_I_VALUE       0x11
+#define SC7A20_WHO_AM_I_VALUE             0x11
 
 /* Configuration */
-#define GSENSOR_DEBOUNCE_MS     300
-#define GSENSOR_POLL_INTERVAL_MS 200
-#define ST_ACCEL_NUMBER_DATA_CHANNELS 3
+#define GSENSOR_DEBOUNCE_MS               300
+#define GSENSOR_POLL_INTERVAL_MS          200
 
 /* Driver Data Structure */
-
-struct gsensor_data {
+struct gsensor_data
+{
     struct i2c_client *client;
     struct mutex lock;
     struct delayed_work poll_work;
     struct kobject *gsensor_kobj;
-    struct iio_dev *indio_dev;
-    
+
     bool enabled;
     bool initialized;
-    
+
     enum gsensor_orientation_hex orientation_hex;
     enum gsensor_orientation_hex pending_orientation;
     char orientation_str[32];
     unsigned long last_change_jiffies;
-    
-    /* IIO buffer data */
-    s16 buffer[ST_ACCEL_NUMBER_DATA_CHANNELS + 1];
-    
+
     u8 who_am_i;
     int irq;
 };
@@ -96,30 +83,34 @@ static int gsensor_write_reg(struct i2c_client *client, u8 reg, u8 value)
 }
 
 /* Read raw acceleration data (12-bit, right-aligned) */
-static int gsensor_read_raw_data(struct gsensor_data *data, int *x, int *y, int *z)
+static int gsensor_read_raw_data(struct gsensor_data *data, int *x, int *y,
+                                 int *z)
 {
     u8 xl, xh, yl, yh, zl, zh;
     s16 raw_x, raw_y, raw_z;
     int ret;
 
-    /* Read the X-axis byte by byte */
     ret = gsensor_read_reg(data->client, 0x28, &xl);
-    if (ret < 0) return ret;
+    if (ret < 0)
+        return ret;
     ret = gsensor_read_reg(data->client, 0x29, &xh);
-    if (ret < 0) return ret;
+    if (ret < 0)
+        return ret;
 
-    /* Read the Y-axis byte by byte */
     ret = gsensor_read_reg(data->client, 0x2a, &yl);
-    if (ret < 0) return ret;
+    if (ret < 0)
+        return ret;
     ret = gsensor_read_reg(data->client, 0x2b, &yh);
-    if (ret < 0) return ret;
+    if (ret < 0)
+        return ret;
 
-    /* Z-axis */
     ret = gsensor_read_reg(data->client, 0x2c, &zl);
-    if (ret < 0) return ret;
+    if (ret < 0)
+        return ret;
     ret = gsensor_read_reg(data->client, 0x2d, &zh);
-    if (ret < 0) return ret;
-    
+    if (ret < 0)
+        return ret;
+
     raw_x = (s16)((xh << 8) | xl);
     raw_y = (s16)((yh << 8) | yl);
     raw_z = (s16)((zh << 8) | zl);
@@ -128,7 +119,7 @@ static int gsensor_read_raw_data(struct gsensor_data *data, int *x, int *y, int
     *x = (raw_x * 61) / 1000;
     *y = (raw_y * 61) / 1000;
     *z = (raw_z * 61) / 1000;
-    
+
     return 0;
 }
 
@@ -136,79 +127,69 @@ static int gsensor_read_raw_data(struct gsensor_data *data, int *x, int *y, int
 static int gsensor_set_enable(struct gsensor_data *data, bool enable)
 {
     int ret;
-    
+
     if (enable) {
-        /* CTRL_REG1: 0x87 = 100Hz (0x80) + Enable all axes (0x07) */
         ret = gsensor_write_reg(data->client, ST_ACCEL_CTRL_REG1_ADDR, 0x87);
         if (ret < 0)
             return ret;
         msleep(20);
     } else {
-        /* CTRL_REG1: 0x00 = Standby mode */
         ret = gsensor_write_reg(data->client, ST_ACCEL_CTRL_REG1_ADDR, 0x00);
         if (ret < 0)
             return ret;
     }
-    
-    return 0;
-}
 
-static int gsensor_set_dataready_irq(struct gsensor_data *data, bool enable)
-{
-    /* For SC7A20, data ready is automatically enabled when sensor is active */
-    /* This function is for compatibility with st_* trigger framework */
     return 0;
 }
 
+/* Initialize sensor */
 static int gsensor_init_sensor(struct gsensor_data *data)
 {
     u8 who_am_i;
     int ret;
 
-    /* 1. Verify device */
     ret = gsensor_read_reg(data->client, ST_ACCEL_WHO_AM_I_ADDR, &who_am_i);
     if (ret < 0) {
         dev_err(&data->client->dev, "Failed to read WHO_AM_I: %d\n", ret);
         return ret;
     }
-    
+
     data->who_am_i = who_am_i;
     dev_info(&data->client->dev, "WHO_AM_I = 0x%02x\n", who_am_i);
-    
+
     if (who_am_i != SC7A20_WHO_AM_I_VALUE) {
         dev_err(&data->client->dev, "Invalid WHO_AM_I: 0x%02x\n", who_am_i);
         return -ENODEV;
     }
 
-    /* 2. Setting CTRL_REG4: BDU enable */
+    /* Set CTRL_REG4: BDU enable, ±2g */
     ret = gsensor_write_reg(data->client, ST_ACCEL_CTRL_REG4_ADDR, 0x80);
     if (ret < 0)
         return ret;
 
-    /* 3. Disable the sensor at startup */
+    /* Initial disable */
     ret = gsensor_write_reg(data->client, ST_ACCEL_CTRL_REG1_ADDR, 0x00);
     if (ret < 0)
         return ret;
-    
+
     data->initialized = true;
     dev_info(&data->client->dev, "Gsensor initialized successfully\n");
-    
+
     return 0;
 }
 
 /* Orientation Calculation */
-static enum gsensor_orientation_hex gsensor_calc_orientation(int x, int y, int z)
+static enum gsensor_orientation_hex gsensor_calc_orientation(int x, int y,
+                                                             int z)
 {
     int abs_x = abs(x);
     int abs_y = abs(y);
     int abs_z = abs(z);
 
-    /* Device flat - Z axis maximum */
     if (abs_z > 800 && abs_z > abs_x && abs_z > abs_y) {
         return GSENSOR_ORIENT_UNKNOWN_HEX;
     }
 
-    /* Landscape mode: X axis maximum */
     if (abs_x > 800 && abs_x > abs_y) {
         if (x > 0)
             return GSENSOR_ORIENT_LANDSCAPE_FLIP_HEX;
@@ -216,14 +197,13 @@ static enum gsensor_orientation_hex gsensor_calc_orientation(int x, int y, int z
             return GSENSOR_ORIENT_LANDSCAPE_HEX;
     }
 
-    /* Portrait mode: Y axis maximum. */
     if (abs_y > 800 && abs_y > abs_x) {
         if (y > 0)
             return GSENSOR_ORIENT_PORTRAIT_FLIP_HEX;
         else
             return GSENSOR_ORIENT_PORTRAIT_HEX;
     }
-    
+
     return GSENSOR_ORIENT_UNKNOWN_HEX;
 }
 
@@ -232,40 +212,46 @@ static void gsensor_update_orientation(struct gsensor_data *data)
     int x, y, z;
     enum gsensor_orientation_hex new_orient;
     unsigned long now = jiffies;
-    
+
     if (!data->enabled)
         return;
-    
+
     if (gsensor_read_raw_data(data, &x, &y, &z) < 0)
         return;
-    
+
     new_orient = gsensor_calc_orientation(x, y, z);
-    
-    if (new_orient != GSENSOR_ORIENT_UNKNOWN_HEX && new_orient != data->orientation_hex) {
+
+    if (new_orient != GSENSOR_ORIENT_UNKNOWN_HEX &&
+        new_orient != data->orientation_hex) {
         if (new_orient == data->pending_orientation) {
-            if (time_after(now, data->last_change_jiffies + 
-                           msecs_to_jiffies(GSENSOR_DEBOUNCE_MS))) {
-                data->orientation_hex = new_orient;
+            if (time_after(now, data->last_change_jiffies +
+                                    msecs_to_jiffies(GSENSOR_DEBOUNCE_MS))) {
+                data->orientation_hex     = new_orient;
                 data->pending_orientation = GSENSOR_ORIENT_UNKNOWN_HEX;
-                
+
                 switch (new_orient) {
-                case GSENSOR_ORIENT_PORTRAIT_HEX:
-                    strcpy(data->orientation_str, GSENSOR_ORIENT_PORTRAIT_STR);
-                    break;
-                case GSENSOR_ORIENT_LANDSCAPE_HEX:
-                    strcpy(data->orientation_str, GSENSOR_ORIENT_LANDSCAPE_STR);
-                    break;
-                case GSENSOR_ORIENT_PORTRAIT_FLIP_HEX:
-                    strcpy(data->orientation_str, GSENSOR_ORIENT_PORTRAIT_FLIP_STR);
-                    break;
-                case GSENSOR_ORIENT_LANDSCAPE_FLIP_HEX:
-                    strcpy(data->orientation_str, GSENSOR_ORIENT_LANDSCAPE_FLIP_STR);
-                    break;
-                default:
-                    break;
+                    case GSENSOR_ORIENT_PORTRAIT_HEX:
+                        strcpy(data->orientation_str,
+                               GSENSOR_ORIENT_PORTRAIT_STR);
+                        break;
+                    case GSENSOR_ORIENT_LANDSCAPE_HEX:
+                        strcpy(data->orientation_str,
+                               GSENSOR_ORIENT_LANDSCAPE_STR);
+                        break;
+                    case GSENSOR_ORIENT_PORTRAIT_FLIP_HEX:
+                        strcpy(data->orientation_str,
+                               GSENSOR_ORIENT_PORTRAIT_FLIP_STR);
+                        break;
+                    case GSENSOR_ORIENT_LANDSCAPE_FLIP_HEX:
+                        strcpy(data->orientation_str,
+                               GSENSOR_ORIENT_LANDSCAPE_FLIP_STR);
+                        break;
+                    default:
+                        break;
                 }
-                
-                dev_info(&data->client->dev, "Orientation: %s [X=%d, Y=%d, Z=%d]\n",
+
+                dev_info(&data->client->dev,
+                         "Orientation: %s [X=%d, Y=%d, Z=%d]\n",
                          data->orientation_str, x, y, z);
             }
         } else {
@@ -279,225 +265,22 @@ static void gsensor_update_orientation(struct gsensor_data *data)
 
 static void gsensor_poll_work(struct work_struct *work)
 {
-    struct gsensor_data *data = container_of(work, struct gsensor_data,
-                                             poll_work.work);
-    
+    struct gsensor_data *data =
+        container_of(work, struct gsensor_data, poll_work.work);
+
     mutex_lock(&data->lock);
     gsensor_update_orientation(data);
     mutex_unlock(&data->lock);
-    
+
     if (data->enabled)
-        schedule_delayed_work(&data->poll_work, 
+        schedule_delayed_work(&data->poll_work,
                               msecs_to_jiffies(GSENSOR_POLL_INTERVAL_MS));
 }
 
-/* IIO Framework */
-
-static int gsensor_read_raw(struct iio_dev *indio_dev,
-                            struct iio_chan_spec const *ch,
-                            int *val, int *val2, long mask)
-{
-    struct gsensor_data *data = iio_priv(indio_dev);
-    int x, y, z;
-    int err;
-
-    switch (mask) {
-    case IIO_CHAN_INFO_RAW:
-        err = gsensor_read_raw_data(data, &x, &y, &z);
-        if (err < 0)
-            return err;
-
-        switch (ch->channel2) {
-        case IIO_MOD_X:
-            *val = x;
-            return IIO_VAL_INT;
-        case IIO_MOD_Y:
-            *val = y;
-            return IIO_VAL_INT;
-        case IIO_MOD_Z:
-            *val = z;
-            return IIO_VAL_INT;
-        default:
-            return -EINVAL;
-        }
-        
-    case IIO_CHAN_INFO_SCALE:
-        *val = 0;
-        *val2 = 61035;  /* 0.000061035 g */
-        return IIO_VAL_INT_PLUS_NANO;
-        
-    case IIO_CHAN_INFO_SAMP_FREQ:
-        *val = 100;
-        return IIO_VAL_INT;
-        
-    default:
-        return -EINVAL;
-    }
-}
-
-static int gsensor_write_raw(struct iio_dev *indio_dev,
-                             struct iio_chan_spec const *ch,
-                             int val, int val2, long mask)
-{
-    switch (mask) {
-    case IIO_CHAN_INFO_SAMP_FREQ:
-        if (val == 100)
-            return 0;
-        return -EINVAL;
-    default:
-        return -EINVAL;
-    }
-}
-
-/* IIO channels */
-static const struct iio_chan_spec gsensor_channels[] = {
-    {
-        .type = IIO_ACCEL,
-        .modified = 1,
-        .channel2 = IIO_MOD_X,
-        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
-                                    BIT(IIO_CHAN_INFO_SAMP_FREQ),
-        .scan_index = 0,
-        .scan_type = {
-            .sign = 's',
-            .realbits = 16,
-            .storagebits = 16,
-            .endianness = IIO_LE,
-        },
-    },
-    {
-        .type = IIO_ACCEL,
-        .modified = 1,
-        .channel2 = IIO_MOD_Y,
-        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
-                                    BIT(IIO_CHAN_INFO_SAMP_FREQ),
-        .scan_index = 1,
-        .scan_type = {
-            .sign = 's',
-            .realbits = 16,
-            .storagebits = 16,
-            .endianness = IIO_LE,
-        },
-    },
-    {
-        .type = IIO_ACCEL,
-        .modified = 1,
-        .channel2 = IIO_MOD_Z,
-        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
-                                    BIT(IIO_CHAN_INFO_SAMP_FREQ),
-        .scan_index = 2,
-        .scan_type = {
-            .sign = 's',
-            .realbits = 16,
-            .storagebits = 16,
-            .endianness = IIO_LE,
-        },
-    },
-    IIO_CHAN_SOFT_TIMESTAMP(3),
-};
-
-/* Trigger functions */
-static int gsensor_trig_set_state(struct iio_trigger *trig, bool state)
-{
-    struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
-    struct gsensor_data *data = iio_priv(indio_dev);
-    
-    return gsensor_set_dataready_irq(data, state);
-}
-
-static const struct iio_trigger_ops gsensor_trigger_ops = {
-    .set_trigger_state = gsensor_trig_set_state,
-    .validate_device = iio_trigger_validate_own_device,
-};
-
-/* Buffer functions */
-static int gsensor_buffer_postenable(struct iio_dev *indio_dev)
-{
-    struct gsensor_data *data = iio_priv(indio_dev);
-    int err;
-
-    err = gsensor_set_enable(data, true);
-    if (err < 0)
-        return err;
-
-    return gsensor_set_dataready_irq(data, true);
-}
-
-static int gsensor_buffer_predisable(struct iio_dev *indio_dev)
-{
-    struct gsensor_data *data = iio_priv(indio_dev);
-    int err;
-
-    err = gsensor_set_dataready_irq(data, false);
-    if (err < 0)
-        return err;
-
-    return gsensor_set_enable(data, false);
-}
-
-static const struct iio_buffer_setup_ops gsensor_buffer_setup_ops = {
-    .postenable = &gsensor_buffer_postenable,
-    .predisable = &gsensor_buffer_predisable,
-};
-
-/* Trigger handler */
-static irqreturn_t gsensor_trigger_handler(int irq, void *p)
-{
-    struct iio_poll_func *pf = p;
-    struct iio_dev *indio_dev = pf->indio_dev;
-    struct gsensor_data *data = iio_priv(indio_dev);
-    int x, y, z;
-
-    gsensor_read_raw_data(data, &x, &y, &z);
-    data->buffer[0] = x;
-    data->buffer[1] = y;
-    data->buffer[2] = z;
-
-    iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
-                                       iio_get_time_ns(indio_dev));
-    iio_trigger_notify_done(indio_dev->trig);
-
-    return IRQ_HANDLED;
-}
-
-/* IIO attributes */
-static ssize_t gsensor_show_available_freq(struct device *dev,
-                                           struct device_attribute *attr,
-                                           char *buf)
-{
-    return sprintf(buf, "100\n");
-}
-static IIO_DEVICE_ATTR(sampling_frequency_available, 0444,
-                       gsensor_show_available_freq, NULL, 0);
-
-static struct attribute *gsensor_iio_attrs[] = {
-    &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
-    NULL,
-};
-
-static const struct attribute_group gsensor_iio_attr_group = {
-    .attrs = gsensor_iio_attrs,
-};
-
-static const struct iio_info gsensor_iio_info = {
-    .read_raw = gsensor_read_raw,
-    .write_raw = gsensor_write_raw,
-    .attrs = &gsensor_iio_attr_group,
-};
-
-/* Allocate ring buffer and trigger */
-static int gsensor_allocate_ring(struct iio_dev *indio_dev)
-{
-    return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
-        NULL, &gsensor_trigger_handler, &gsensor_buffer_setup_ops);
-}
-
 /* ==================== Verifone Sysfs Interface ==================== */
 
-static ssize_t enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+static ssize_t enable_show(struct kobject *kobj, struct kobj_attribute *attr,
+                           char *buf)
 {
     return sprintf(buf, "%d\n", g_data ? g_data->enabled : 0);
 }
@@ -508,16 +291,16 @@ static ssize_t enable_store(struct kobject *kobj, struct kobj_attribute *attr,
     struct gsensor_data *data = g_data;
     unsigned long val;
     int ret;
-    
+
     if (!data)
         return -ENODEV;
-    
+
     ret = kstrtoul(buf, 0, &val);
     if (ret)
         return ret;
-    
+
     mutex_lock(&data->lock);
-    
+
     if (val && !data->enabled) {
         ret = gsensor_set_enable(data, true);
         if (ret == 0) {
@@ -531,7 +314,7 @@ static ssize_t enable_store(struct kobject *kobj, struct kobj_attribute *attr,
         if (ret == 0)
             data->enabled = false;
     }
-    
+
     mutex_unlock(&data->lock);
     return ret < 0 ? ret : count;
 }
@@ -542,16 +325,20 @@ static ssize_t screen_orientation_show(struct kobject *kobj,
 {
     return sprintf(buf, "%s\n", g_data ? g_data->orientation_str : "unknown");
 }
-static struct kobj_attribute screen_orientation_attr = __ATTR_RO(screen_orientation);
+static struct kobj_attribute screen_orientation_attr =
+    __ATTR_RO(screen_orientation);
 
 static ssize_t instantaneous_orientation_show(struct kobject *kobj,
-                                              struct kobj_attribute *attr, char *buf)
+                                              struct kobj_attribute *attr,
+                                              char *buf)
 {
     return sprintf(buf, "0x%02x\n", g_data ? g_data->orientation_hex : 0);
 }
-static struct kobj_attribute instantaneous_orientation_attr = __ATTR_RO(instantaneous_orientation);
+static struct kobj_attribute instantaneous_orientation_attr =
+    __ATTR_RO(instantaneous_orientation);
 
-static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr,
+                         char *buf)
 {
     u8 mode = 0;
     if (g_data && g_data->initialized)
@@ -564,13 +351,13 @@ static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
 {
     struct gsensor_data *data = g_data;
     unsigned long val;
-    
+
     if (!data)
         return -ENODEV;
-    
+
     if (kstrtoul(buf, 0, &val))
         return -EINVAL;
-    
+
     if (val & GSENSOR_MODE_SOFT_RESET) {
         mutex_lock(&data->lock);
         gsensor_init_sensor(data);
@@ -578,12 +365,13 @@ static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
         strcpy(data->orientation_str, GSENSOR_ORIENT_LANDSCAPE_STR);
         mutex_unlock(&data->lock);
     }
-    
+
     return count;
 }
 static struct kobj_attribute mode_attr = __ATTR_RW(mode);
 
-static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
+                          char *buf)
 {
     u8 state = 0;
     if (g_data && g_data->enabled)
@@ -592,16 +380,17 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, cha
 }
 static struct kobj_attribute state_attr = __ATTR_RO(state);
 
-static ssize_t raw_data_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+static ssize_t raw_data_show(struct kobject *kobj, struct kobj_attribute *attr,
+                             char *buf)
 {
     int x, y, z;
-    
+
     if (!g_data)
         return -ENODEV;
-    
+
     if (gsensor_read_raw_data(g_data, &x, &y, &z) < 0)
         return -EIO;
-    
+
     return sprintf(buf, "%d %d %d\n", x, y, z);
 }
 static struct kobj_attribute raw_data_attr = __ATTR_RO(raw_data);
@@ -620,21 +409,21 @@ static const struct attribute_group gsensor_attr_group = {
     .attrs = gsensor_attrs,
 };
 
-/* I2C Probe/Remove */
+/* ==================== I2C Probe/Remove ==================== */
+
 static int gsensor_probe(struct i2c_client *client)
 {
-    struct iio_dev *indio_dev;
     struct gsensor_data *data;
     int ret;
 
-    indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
-    if (!indio_dev)
+    dev_info(&client->dev, "Gsensor probe\n");
+
+    data = kzalloc(sizeof(*data), GFP_KERNEL);
+    if (!data)
         return -ENOMEM;
 
-    data            = iio_priv(indio_dev);
-    data->client    = client;
-    data->indio_dev = indio_dev;
-    data->irq       = client->irq;
+    data->client = client;
+    data->irq    = client->irq;
 
     mutex_init(&data->lock);
     INIT_DELAYED_WORK(&data->poll_work, gsensor_poll_work);
@@ -643,49 +432,12 @@ static int gsensor_probe(struct i2c_client *client)
     data->pending_orientation = GSENSOR_ORIENT_UNKNOWN_HEX;
     data->last_change_jiffies = jiffies;
 
-    i2c_set_clientdata(client, indio_dev);
+    i2c_set_clientdata(client, data);
 
     ret = gsensor_init_sensor(data);
     if (ret < 0) {
         dev_err(&client->dev, "Init failed: %d\n", ret);
-        return ret;
-    }
-
-    indio_dev->modes        = INDIO_DIRECT_MODE;
-    indio_dev->info         = &gsensor_iio_info;
-    indio_dev->channels     = gsensor_channels;
-    indio_dev->num_channels = ARRAY_SIZE(gsensor_channels);
-
-    ret = gsensor_allocate_ring(indio_dev);
-    if (ret < 0) {
-        dev_err(&client->dev, "Failed to allocate ring buffer: %d\n", ret);
-        return ret;
-    }
-
-    if (data->irq > 0) {
-        struct iio_trigger *trig;
-
-        trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name,
-                                      iio_device_id(indio_dev));
-        if (!trig) {
-            ret = -ENOMEM;
-            goto error;
-        }
-
-        trig->ops = &gsensor_trigger_ops;
-        iio_trigger_set_drvdata(trig, indio_dev);
-
-        ret = devm_iio_trigger_register(&client->dev, trig);
-        if (ret < 0)
-            goto error;
-
-        indio_dev->trig = iio_trigger_get(trig);
-    }
-
-    ret = iio_device_register(indio_dev);
-    if (ret < 0) {
-        dev_err(&client->dev, "Failed to register IIO device: %d\n", ret);
-        goto error;
+        goto err_free;
     }
 
     g_data = data;
@@ -697,18 +449,18 @@ static int gsensor_probe(struct i2c_client *client)
             if (ret < 0) {
                 dev_err(&client->dev, "Failed to create sysfs group\n");
                 kobject_put(data->gsensor_kobj);
-                goto error_unregister;
+                goto err_free;
             }
         } else {
             dev_err(&client->dev, "Failed to create gsensor kobject\n");
-            goto error_unregister;
+            goto err_free;
         }
     } else {
         dev_err(&client->dev, "vfiec_kobj not available\n");
-        goto error_unregister;
+        goto err_free;
     }
 
-    /* ========== auto enable the sensor========== */
+    /* 自动启用传感器 */
     ret = gsensor_set_enable(data, true);
     if (ret == 0) {
         data->enabled = true;
@@ -718,24 +470,23 @@ static int gsensor_probe(struct i2c_client *client)
     } else {
         dev_warn(&client->dev, "Failed to auto-enable sensor: %d\n", ret);
     }
-    /* ================================= */
 
     dev_info(&client->dev, "Gsensor driver loaded (WHO_AM_I=0x%02x)\n",
              data->who_am_i);
     return 0;
 
-error_unregister:
-    iio_device_unregister(indio_dev);
-error:
+err_free:
+    kfree(data);
+    g_data = NULL;
     return ret;
 }
 
 static int gsensor_remove(struct i2c_client *client)
 {
-    struct iio_dev *indio_dev = i2c_get_clientdata(client);
-    struct gsensor_data *data = iio_priv(indio_dev);
-    
+    struct gsensor_data *data = g_data;
+
     if (data) {
+        dev_info(&client->dev, "Removing Gsensor driver...\n");
         cancel_delayed_work_sync(&data->poll_work);
         if (data->enabled)
             gsensor_set_enable(data, false);
@@ -743,8 +494,8 @@ static int gsensor_remove(struct i2c_client *client)
             sysfs_remove_group(data->gsensor_kobj, &gsensor_attr_group);
             kobject_put(data->gsensor_kobj);
         }
-        iio_device_unregister(indio_dev);
         mutex_destroy(&data->lock);
+        kfree(data);
         g_data = NULL;
     }
     return 0;
@@ -753,27 +504,62 @@ static int gsensor_remove(struct i2c_client *client)
 /* ==================== I2C Driver ==================== */
 
 static const struct i2c_device_id gsensor_id_table[] = {
-    { "sc7a20", 0 },
-    { "gsensor", 0 },
-    {}
-};
+    {"sc7a20", 0}, {"gsensor", 0}, {}};
 MODULE_DEVICE_TABLE(i2c, gsensor_id_table);
 
 static struct i2c_driver gsensor_driver = {
-    .driver = {
-        .name = "verifone-gsensor",
-    },
+    .driver =
+        {
+            .name = "verifone-gsensor",
+        },
     .probe_new = gsensor_probe,
-    .remove = gsensor_remove,
-    .id_table = gsensor_id_table,
+    .remove    = gsensor_remove,
+    .id_table  = gsensor_id_table,
 };
 
-/* Init/Exit */
+/* ==================== Init/Exit ==================== */
+static void gsensor_auto_create_i2c_device(void)
+{
+    struct i2c_adapter *adapter;
+    struct i2c_board_info info = {
+        I2C_BOARD_INFO("sc7a20", 0x19),
+    };
+    
+    printk(KERN_INFO "gsensor: auto_create_i2c_device START\n");
+    
+    adapter = i2c_get_adapter(0);
+    if (adapter) {
+        printk(KERN_INFO "gsensor: got adapter for bus 0\n");
+        i2c_new_client_device(adapter, &info);
+        i2c_put_adapter(adapter);
+        printk(KERN_INFO "gsensor: created device at 0x19 on bus 0\n");
+    } else {
+        printk(KERN_INFO "gsensor: no adapter for bus 0\n");
+    }
+    
+    printk(KERN_INFO "gsensor: auto_create_i2c_device END\n");
+}
+
 int gsensor_init_main(void)
 {
-    printk(KERN_INFO "gsensor: Registering driver\n");
-    return i2c_add_driver(&gsensor_driver);
+    int ret;
+    
+    printk(KERN_INFO "gsensor: Registering driver START\n");
+    
+    ret = i2c_add_driver(&gsensor_driver);
+    if (ret < 0) {
+        printk(KERN_ERR "gsensor: Failed to register I2C driver: %d\n", ret);
+        return ret;
+    }
+    
+    printk(KERN_INFO "gsensor: i2c_add_driver done\n");
+    
+    gsensor_auto_create_i2c_device();
+    
+    printk(KERN_INFO "gsensor: Driver initialized\n");
+    return 0;
 }
+
 EXPORT_SYMBOL(gsensor_init_main);
 
 void gsensor_exit_main(void)
@@ -787,14 +573,3 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Verifone, Inc.");
 MODULE_DESCRIPTION("Verifone Gsensor driver for screen orientation");
 
-#endif
-
-void gsensor_exit_main(void)
-{
-
-}
-
-int gsensor_init_main(void)
-{
-    return 0;
-}

+ 3 - 216
gsensor.h

@@ -1,18 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Memsic MXC400xXC Gsensor driver for screen orientation
- * 
- */
-
 #ifndef __GSENSOR_H
 #define __GSENSOR_H
 
-#include <linux/types.h>
-#include <linux/iio/iio.h>
-#include <linux/i2c.h>
-#include <linux/iio/trigger.h>
-#include <linux/iio/triggered_buffer.h>
-
 /* Gsensor orientation values (hex per API spec) */
 enum gsensor_orientation_hex
 {
@@ -23,219 +12,17 @@ enum gsensor_orientation_hex
     GSENSOR_ORIENT_LANDSCAPE_FLIP_HEX = 0x17,
 };
 
-/* Gsensor orientation strings */
 #define GSENSOR_ORIENT_PORTRAIT_STR       "portrait"
 #define GSENSOR_ORIENT_LANDSCAPE_STR      "landscape"
 #define GSENSOR_ORIENT_PORTRAIT_FLIP_STR  "portrait_flip"
 #define GSENSOR_ORIENT_LANDSCAPE_FLIP_STR "landscape_flip"
 
-/* Gsensor mode bits (per API spec) */
-#define GSENSOR_MODE_SOFT_RESET           BIT(2) /* EC17: soft reset */
-#define GSENSOR_MODE_INITIALIZED          BIT(1) /* EC16: 0=not init, 1=init */
-#define GSENSOR_MODE_INTERRUPT            BIT(0) /* 0=poll, 1=interrupt */
-
-/* Memsic MXC400xXC Register Definitions */
-#define MXC400X_REG_WHO_AM_I              0x00
-#define MXC400X_WHO_AM_I_VALUE            0x20
-
-#define MXC400X_REG_XOUT_U                0x04
-#define MXC400X_REG_XOUT_L                0x05
-#define MXC400X_REG_YOUT_U                0x06
-#define MXC400X_REG_YOUT_L                0x07
-#define MXC400X_REG_ZOUT_U                0x08
-#define MXC400X_REG_ZOUT_L                0x09
-
-#define MXC400X_REG_CONTROL               0x0A
-#define MXC400X_CONTROL_MODE_MASK         0x03
-#define MXC400X_CONTROL_MODE_STANDBY      0x00
-#define MXC400X_CONTROL_MODE_ACTIVE       0x01
-#define MXC400X_CONTROL_MODE_RESET        0x02
-
-#define MXC400X_REG_INT_ENABLE            0x0B
-#define MXC400X_INT_ENABLE_DRDY           BIT(0)
-
-#define MXC400X_REG_INT_STATUS            0x0C
-
-
-/* ST LIS2DH12 / SC7A20 register */
-#define ST_ACCEL_WHO_AM_I_ADDR         0x0F
-#define ST_ACCEL_WHO_AM_I_VALUE        0x33  /* LIS2DH12 / SC7A20 */
-#define ST_ACCEL_CTRL_REG1_ADDR        0x20
-#define ST_ACCEL_CTRL_REG4_ADDR        0x23
-#define ST_ACCEL_OUT_X_L_ADDR          0x28
-#define ST_ACCEL_OUT_X_H_ADDR          0x29
-#define ST_ACCEL_OUT_Y_L_ADDR          0x2A
-#define ST_ACCEL_OUT_Y_H_ADDR          0x2B
-#define ST_ACCEL_OUT_Z_L_ADDR          0x2C
-#define ST_ACCEL_OUT_Z_H_ADDR          0x2D
-#define ST_ACCEL_STATUS_REG_ADDR       0x27
-#define ST_ACCEL_STATUS_DRDY           0x07
-
-/* Driver Constants */
-#define GSENSOR_NUMBER_DATA_CHANNELS      3
-#define GSENSOR_DEBOUNCE_MS               100
-#define MXC400X_SCALE_FACTOR              1000 /* mg per count at 2g range */
-
-/* Default I2C address */
-#define MXC400X_DEFAULT_I2C_ADDR          0x15
-
-/* Sensor Settings Structure */
-struct gsensor_fs_avl
-{
-    unsigned int num;   /* Full scale value in g */
-    unsigned int value; /* Register value */
-    unsigned int gain;  /* Gain in micro g per LSB */
-};
-
-struct gsensor_odr_avl
-{
-    unsigned int hz;    /* Output data rate in Hz */
-    unsigned int value; /* Register value */
-};
-
-struct gsensor_settings
-{
-    u8 wai;                         /* WHO_AM_I expected value */
-    u8 wai_addr;                    /* WHO_AM_I register address */
-    const char **sensors_supported; /* Supported device names */
-
-    /* Channel configuration */
-    const struct iio_chan_spec *ch;
-    int num_channels;
-
-    /* ODR configuration */
-    struct
-    {
-        u8 addr;
-        u8 mask;
-        const struct gsensor_odr_avl *odr_avl;
-        int num_odr;
-    } odr;
-
-    /* Power mode configuration */
-    struct
-    {
-        u8 addr;
-        u8 mask;
-        u8 value_on;
-        u8 value_off;
-    } pw;
-
-    /* Full scale configuration */
-    struct
-    {
-        u8 addr;
-        u8 mask;
-        const struct gsensor_fs_avl *fs_avl;
-        int num_fs;
-    } fs;
+#define GSENSOR_MODE_SOFT_RESET           BIT(2)
+#define GSENSOR_MODE_INITIALIZED          BIT(1)
 
-    /* Block Data Update */
-    struct
-    {
-        u8 addr;
-        u8 mask;
-    } bdu;
-
-    /* Data ready interrupt */
-    struct
-    {
-        struct
-        {
-            u8 addr;
-            u8 mask;
-        } int1;
-        u8 addr_ihl;
-        u8 mask_ihl;
-        struct
-        {
-            u8 addr;
-            u8 mask;
-        } stat_drdy;
-    } drdy_irq;
-
-    /* SPI/I2C interface mode */
-    struct
-    {
-        u8 addr;
-        u8 value;
-    } sim;
-
-    bool multi_read_bit;
-    unsigned int bootime;
-};
-
-/* Driver Data Structure */
-struct gsensor_data
-{
-    struct i2c_client *client;
-    struct device *dev;
-    struct mutex lock; /* Protects data access */
-
-    /* Sensor settings */
-    const struct gsensor_settings *sensor_settings;
-
-    /* Current configuration */
-    const struct gsensor_fs_avl *current_fullscale;
-    unsigned int odr;
-
-    /* Orientation data */
-    enum gsensor_orientation_hex orientation_hex;
-    char orientation_str[32];
-    struct delayed_work debounce_work;
-    enum gsensor_orientation_hex pending_orientation;
-    unsigned long last_change_jiffies;
-
-    /* State */
-    bool enabled;
-    bool initialized;
-    bool interrupt_mode;
-    bool irq_enabled;
-
-    /* IIO related */
-    struct iio_dev *indio_dev;
-
-    /* Verifone sysfs */
-    struct kobject *verifone_kobj;
-
-    /* Regulators (optional) */
-    struct regulator *vdd;
-    struct regulator *vdd_io;
-};
-
-/* Core functions */
-int gsensor_common_probe(struct iio_dev *indio_dev);
-void gsensor_common_remove(struct iio_dev *indio_dev);
-const struct gsensor_settings *gsensor_get_settings(const char *name);
-
-/* Buffer functions */
-int gsensor_allocate_ring(struct iio_dev *indio_dev);
-int gsensor_trig_set_state(struct iio_trigger *trig, bool state);
-
-int gsensor_allocate_trigger(struct iio_dev *indio_dev);
-extern const struct iio_trigger_ops gsensor_trigger_ops;
-
-/* Power management */
-int gsensor_power_enable(struct iio_dev *indio_dev);
-int gsensor_power_disable(struct iio_dev *indio_dev);
-
-/* I2C functions */
-int gsensor_i2c_read(struct device *dev, u8 reg, u8 *data, size_t len);
-int gsensor_i2c_write(struct device *dev, u8 reg, u8 value);
+/* Function prototypes */
 int gsensor_init_main(void);
 void gsensor_exit_main(void);
 
-int gsensor_read_raw_data(struct gsensor_data *gs, int *x, int *y, int *z);
-int gsensor_set_enable(struct gsensor_data *gs, bool enable);
-int gsensor_set_dataready_irq(struct gsensor_data *gs, bool enable);
-
-/* Helper macros */
-#define GSENSOR_DEV_ATTR_SAMP_FREQ_AVAIL()                                     \
-    IIO_DEV_ATTR_SAMP_FREQ_AVAIL(gsensor_show_available_odr)
-
-#define GSENSOR_DEV_ATTR_SCALE_AVAIL()                                         \
-    IIO_DEVICE_ATTR(in_accel_scale_available, 0444,                            \
-                    gsensor_show_available_scale, NULL, 0)
-
 #endif /* __GSENSOR_H */