Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/input/keyboard/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  lm8333.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * LM8333 keypad driver
 * Copyright (C) 2012 Wolfram Sang, Pengutronix <kernel@pengutronix.de>
 */


#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/matrix_keypad.h>
#include <linux/input/lm8333.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>

#define LM8333_FIFO_READ  0x20
#define LM8333_DEBOUNCE   0x22
#define LM8333_READ_INT   0xD0
#define LM8333_ACTIVE   0xE4
#define LM8333_READ_ERROR  0xF0

#define LM8333_KEYPAD_IRQ  (1 << 0)
#define LM8333_ERROR_IRQ  (1 << 3)

#define LM8333_ERROR_KEYOVR  0x04
#define LM8333_ERROR_FIFOOVR  0x40

#define LM8333_FIFO_TRANSFER_SIZE 16

#define LM8333_NUM_ROWS  8
#define LM8333_NUM_COLS  16
#define LM8333_ROW_SHIFT 4

struct lm8333 {
 struct i2c_client *client;
 struct input_dev *input;
 unsigned short keycodes[LM8333_NUM_ROWS << LM8333_ROW_SHIFT];
};

/* The accessors try twice because the first access may be needed for wakeup */
#define LM8333_READ_RETRIES 2

int lm8333_read8(struct lm8333 *lm8333, u8 cmd)
{
 int retries = 0, ret;

 do {
  ret = i2c_smbus_read_byte_data(lm8333->client, cmd);
 } while (ret < 0 && retries++ < LM8333_READ_RETRIES);

 return ret;
}

int lm8333_write8(struct lm8333 *lm8333, u8 cmd, u8 val)
{
 int retries = 0, ret;

 do {
  ret = i2c_smbus_write_byte_data(lm8333->client, cmd, val);
 } while (ret < 0 && retries++ < LM8333_READ_RETRIES);

 return ret;
}

int lm8333_read_block(struct lm8333 *lm8333, u8 cmd, u8 len, u8 *buf)
{
 int retries = 0, ret;

 do {
  ret = i2c_smbus_read_i2c_block_data(lm8333->client,
          cmd, len, buf);
 } while (ret < 0 && retries++ < LM8333_READ_RETRIES);

 return ret;
}

static void lm8333_key_handler(struct lm8333 *lm8333)
{
 struct input_dev *input = lm8333->input;
 u8 keys[LM8333_FIFO_TRANSFER_SIZE];
 u8 code, pressed;
 int i, ret;

 ret = lm8333_read_block(lm8333, LM8333_FIFO_READ,
    LM8333_FIFO_TRANSFER_SIZE, keys);
 if (ret != LM8333_FIFO_TRANSFER_SIZE) {
  dev_err(&lm8333->client->dev,
   "Error %d while reading FIFO\n", ret);
  return;
 }

 for (i = 0; i < LM8333_FIFO_TRANSFER_SIZE && keys[i]; i++) {
  pressed = keys[i] & 0x80;
  code = keys[i] & 0x7f;

  input_event(input, EV_MSC, MSC_SCAN, code);
  input_report_key(input, lm8333->keycodes[code], pressed);
 }

 input_sync(input);
}

static irqreturn_t lm8333_irq_thread(int irq, void *data)
{
 struct lm8333 *lm8333 = data;
 u8 status = lm8333_read8(lm8333, LM8333_READ_INT);

 if (!status)
  return IRQ_NONE;

 if (status & LM8333_ERROR_IRQ) {
  u8 err = lm8333_read8(lm8333, LM8333_READ_ERROR);

  if (err & (LM8333_ERROR_KEYOVR | LM8333_ERROR_FIFOOVR)) {
   u8 dummy[LM8333_FIFO_TRANSFER_SIZE];

   lm8333_read_block(lm8333, LM8333_FIFO_READ,
     LM8333_FIFO_TRANSFER_SIZE, dummy);
  }
  dev_err(&lm8333->client->dev, "Got error %02x\n", err);
 }

 if (status & LM8333_KEYPAD_IRQ)
  lm8333_key_handler(lm8333);

 return IRQ_HANDLED;
}

static int lm8333_probe(struct i2c_client *client)
{
 const struct lm8333_platform_data *pdata =
   dev_get_platdata(&client->dev);
 struct lm8333 *lm8333;
 struct input_dev *input;
 int err, active_time;

 if (!pdata)
  return -EINVAL;

 active_time = pdata->active_time ?: 500;
 if (active_time / 3 <= pdata->debounce_time / 3) {
  dev_err(&client->dev, "Active time not big enough!\n");
  return -EINVAL;
 }

 lm8333 = devm_kzalloc(&client->dev, sizeof(*lm8333), GFP_KERNEL);
 if (!lm8333)
  return -ENOMEM;

 input = devm_input_allocate_device(&client->dev);
 if (!input)
  return -ENOMEM;

 lm8333->client = client;
 lm8333->input = input;

 input->name = client->name;
 input->id.bustype = BUS_I2C;

 input_set_capability(input, EV_MSC, MSC_SCAN);

 err = matrix_keypad_build_keymap(pdata->matrix_data, NULL,
      LM8333_NUM_ROWS, LM8333_NUM_COLS,
      lm8333->keycodes, input);
 if (err)
  return err;

 if (pdata->debounce_time) {
  err = lm8333_write8(lm8333, LM8333_DEBOUNCE,
        pdata->debounce_time / 3);
  if (err)
   dev_warn(&client->dev, "Unable to set debounce time\n");
 }

 if (pdata->active_time) {
  err = lm8333_write8(lm8333, LM8333_ACTIVE,
        pdata->active_time / 3);
  if (err)
   dev_warn(&client->dev, "Unable to set active time\n");
 }

 err = devm_request_threaded_irq(&client->dev, client->irq,
     NULL, lm8333_irq_thread,
     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
     "lm8333", lm8333);
 if (err)
  return err;

 err = input_register_device(input);
 if (err)
  return err;

 i2c_set_clientdata(client, lm8333);
 return 0;
}

static const struct i2c_device_id lm8333_id[] = {
 { "lm8333" },
 { }
};
MODULE_DEVICE_TABLE(i2c, lm8333_id);

static struct i2c_driver lm8333_driver = {
 .driver = {
  .name  = "lm8333",
 },
 .probe  = lm8333_probe,
 .id_table = lm8333_id,
};
module_i2c_driver(lm8333_driver);

MODULE_AUTHOR("Wolfram Sang ");
MODULE_DESCRIPTION("LM8333 keyboard driver");
MODULE_LICENSE("GPL v2");

Messung V0.5
C=99 H=82 G=90

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.