static void hall_device_enable(struct hall_device_chip *chip, int on) { SENSOR_LOG_INFO("%s hall_device\n",on? "enable" : "disable"); if (on) { hall_device_irq_enable(&(chip->irq_s), true, true); hall_device_irq_enable(&(chip->irq_n), true, true); hall_device_check_state(chip); } else { hall_device_irq_enable(&(chip->irq_s), false, true); hall_device_irq_enable(&(chip->irq_n), false, true); } }
static void hall_device_irq_work_n(struct work_struct *work) { struct hall_device_chip *chip = container_of(work, struct hall_device_chip, irq_work_n); mutex_lock(&chip->lock); //SENSOR_LOG_INFO("enter\n"); if (0 == gpio_get_value(chip->irq_n.irq_pin)) { SENSOR_LOG_INFO("MAGNETIC_DEVICE NEAR\n"); input_report_rel(chip->idev, REL_RX, MAGNETIC_DEVICE_NEAR); hall_device_wakelock_ops(&(chip->wakeup_wakelock),false); } else { SENSOR_LOG_INFO("MAGNETIC_DEVICE FAR\n"); input_report_rel(chip->idev, REL_RX, MAGNETIC_DEVICE_FAR); hrtimer_start(&chip->unlock_wakelock_timer, ktime_set(3, 0), HRTIMER_MODE_REL); } input_sync(chip->idev); chip->on_irq_working = false; hall_device_irq_enable(&(chip->irq_n), true, true); //SENSOR_LOG_INFO("exit\n"); mutex_unlock(&chip->lock); };
static void hall_device_irq_work_n(struct work_struct *work) { struct hall_device_chip *chip = container_of(work, struct hall_device_chip, irq_work_n); unsigned int hall_device_state; mutex_lock(&chip->lock); hall_device_state = gpio_get_value(chip->irq_n.irq_pin) ? MAGNETIC_DEVICE_FAR : MAGNETIC_DEVICE_NEAR; if (hall_device_state==chip->state_n) { SENSOR_LOG_INFO("MAGNETIC_DEVICE N [%s] same state\n",hall_device_state==1? "NEAR" : "FAR"); } else { chip->state_n = hall_device_state; chip->state_s = gpio_get_value(chip->irq_s.irq_pin) ? MAGNETIC_DEVICE_FAR : MAGNETIC_DEVICE_NEAR; SENSOR_LOG_INFO("N is %s, S is %s\n",chip->state_n==1? "NEAR" : "FAR",chip->state_s==1? "NEAR" : "FAR"); input_report_rel(chip->idev, REL_RX, chip->state_s); input_report_rel(chip->idev, REL_RY, chip->state_n); input_sync(chip->idev); } if (chip->state_n==MAGNETIC_DEVICE_NEAR) { hall_device_wakelock_ops(&(chip->wakeup_wakelock),false); } else { hrtimer_start(&chip->unlock_wakelock_timer, ktime_set(3, 0), HRTIMER_MODE_REL); } chip->on_irq_working = false; hall_device_irq_enable(&(chip->irq_n), true, true); mutex_unlock(&chip->lock); };
static irqreturn_t hall_device_irq_n(int irq, void *handle) { struct hall_device_chip *chip = handle; //SENSOR_LOG_INFO("enter\n"); hall_device_irq_enable(&(chip->irq_n), false, false); chip->on_irq_working = true; hrtimer_cancel(&chip->unlock_wakelock_timer); if (true == chip->enabled) { hall_device_wakelock_ops(&(chip->wakeup_wakelock),true); } if (0==schedule_work(&chip->irq_work_n)) { SENSOR_LOG_INFO("schedule_work failed!\n"); } //SENSOR_LOG_INFO("exit\n"); return IRQ_HANDLED; }
static int __devinit hall_device_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; static struct hall_device_chip *chip; SENSOR_LOG_INFO("prob start\n"); chip = kzalloc(sizeof(struct hall_device_chip), GFP_KERNEL); if (!chip) { ret = -ENOMEM; goto malloc_failed; } chip->client = client; i2c_set_clientdata(client, chip); hall_device_chip_data_init(chip); hall_device_parse_dt(chip); SENSOR_LOG_INFO("hall_device_int_s is %d",chip->irq_s.irq_pin); SENSOR_LOG_INFO("hall_device_int_n is %d",chip->irq_n.irq_pin); mutex_init(&chip->lock); hall_device_class = class_create(THIS_MODULE, "hall_device"); chip->hall_device_dev = device_create(hall_device_class, NULL, hall_device_dev_t, &hall_device_driver ,"hall_device"); if (IS_ERR(chip->hall_device_dev)) { ret = PTR_ERR(chip->hall_device_dev); goto create_hall_device_dev_failed; } dev_set_drvdata(chip->hall_device_dev, chip); ret = gpio_request(chip->irq_s.irq_pin, "chip->irq_s.irq_pin"); if (ret) { SENSOR_LOG_INFO("gpio %d is busy and then to free it\n",chip->irq_s.irq_pin); gpio_free(chip->irq_s.irq_pin); ret = gpio_request(chip->irq_s.irq_pin, "chip->irq_s.irq_pin"); if (ret) { SENSOR_LOG_INFO("gpio %d is busy and then to free it\n",chip->irq_s.irq_pin); return ret; } } ret = gpio_tlmm_config(GPIO_CFG(chip->irq_s.irq_pin, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); chip->irq_s.irq_num = gpio_to_irq(chip->irq_s.irq_pin); INIT_WORK(&chip->irq_work_s, hall_device_irq_work_s); ret = request_threaded_irq(chip->irq_s.irq_num, NULL, &hall_device_irq_s, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "hall_device_irq_s", chip); if (ret) { SENSOR_LOG_ERROR("Failed to request irq %d\n", chip->irq_s.irq_num); goto irq_s_register_fail; } ret = gpio_request(chip->irq_n.irq_pin, "chip->irq_n.irq_pin"); if (ret) { SENSOR_LOG_INFO("gpio %d is busy and then to free it\n",chip->irq_n.irq_pin); gpio_free(chip->irq_n.irq_pin); ret = gpio_request(chip->irq_n.irq_pin, "chip->irq_n.irq_pin"); if (ret) { SENSOR_LOG_INFO("gpio %d is busy and then to free it\n",chip->irq_n.irq_pin); return ret; } } ret = gpio_tlmm_config(GPIO_CFG(chip->irq_n.irq_pin, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); chip->irq_n.irq_num = gpio_to_irq(chip->irq_n.irq_pin); INIT_WORK(&chip->irq_work_n, hall_device_irq_work_n); ret = request_threaded_irq(chip->irq_n.irq_num , NULL, &hall_device_irq_n, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "hall_device_irq_n", chip); if (ret) { SENSOR_LOG_ERROR("Failed to request irq %d\n", chip->irq_n.irq_num ); goto irq_n_register_fail; } chip->idev = input_allocate_device(); if (!chip->idev) { SENSOR_LOG_ERROR("no memory for idev\n"); ret = -ENODEV; goto input_alloc_failed; } chip->idev->name = "hall_device"; chip->idev->id.bustype = BUS_I2C; set_bit(EV_REL, chip->idev->evbit); set_bit(REL_RX, chip->idev->relbit); //NEAR set_bit(REL_RY, chip->idev->relbit); //FAR ret = input_register_device(chip->idev); if (ret) { input_free_device(chip->idev); SENSOR_LOG_ERROR("cant register input '%s'\n",chip->idev->name); goto input_register_failed; } create_sysfs_interfaces(chip->hall_device_dev); hall_device_irq_enable(&(chip->irq_s), false, true); hall_device_irq_enable(&(chip->irq_n), false, true); wake_lock_init(&chip->wakeup_wakelock.lock, WAKE_LOCK_SUSPEND, chip->wakeup_wakelock.name); hrtimer_init(&chip->unlock_wakelock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); chip->unlock_wakelock_timer.function = hall_device_unlock_wakelock_work_func; SENSOR_LOG_INFO("prob success\n"); return 0; input_register_failed: input_free_device(chip->idev); input_alloc_failed: malloc_failed: irq_n_register_fail: irq_s_register_fail: create_hall_device_dev_failed: chip->hall_device_dev = NULL; class_destroy(hall_device_class); SENSOR_LOG_INFO("prob failed\n"); return -1; }