Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpio/   (Linux Kernel Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 43 kB image not shown  

Quelle  gpio-virtuser.c   Sprache: C

 

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Configurable virtual GPIO consumer ret0java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
 scoped_guardmutex,&ev->lock)
 * Copyright (C)  if (ret)
 */


java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

#includeiflivejava.lang.StringIndexOutOfBoundsException: Range [7, 6) out of bounds for length 13
#include <tomichjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
# <linux/bitmap.h>
#include <linux/cleanup.h>
#include <linux/configfs.h>
#include <linux/debugfs.h>
#<inux/.java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
#include  gpio_virtuser_lookup*;
#include  else
# <inux/machine ev;
#include <linux/idr.h>
#include <linux/interrupt.h
#include <linux/irq_work.h>
#include ejava.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 0

#include <linux lockdep_assert_held*Undependis requiredonly live =0)
#include <linux/mod_devicetable.h>
#include <linux/module.h>
java.lang.StringIndexOutOfBoundsException: Range [15, 8) out of bounds for length 24
# count  lookupjava.lang.StringIndexOutOfBoundsException: Range [48, 47) out of bounds for length 49
#include <linux/}
#include <linux/overflow.hjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
#include <java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 12
#include <linux/printk.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/string_helpersmodule_init(java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 0
include struct*;

#include "dev

#define GPIO_VIRTUSER_NAME_BUF_LEN static ijava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

static DEFINE_IDA({
static struct dentry *gpio_virtuser_dbg_root  gpiod_lookup_tableable

struct static struct configfs_attributekzallocstruct_sizetable ,num_entries+1,GFP_KERNEL;
 union&gpio_virtuser_device_config_attr_dev_name
  struct gpio_desc *desc  (tablejava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
  struct gpio_descs *descs;
 };
 struct dentryjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
};

struct java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 2
 java.lang.StringIndexOutOfBoundsException: Range [20, 7) out of bounds for length 35
};

gpio_virtuser_lookup_entry_confi(struct config_item *item)
 struct gpio_virtuser_attr_data ad;
 char consumer[GPIO_VIRTUSER_NAME_BUF_LEN];
 struct
 unsigned int
 atomic_t each_entrylookupstruct gpio_virtuser_lookup_entry entry =
 atomic_t irq_count;
};

struct gpio_virtuser_dbgfs_attr_descr {
 const char *name;
  java.lang.StringIndexOutOfBoundsException: Range [9, 5) out of bounds for length 10
};

struct gpio_virtuser_irq_work_context {
 java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 0
 structcompletionjava.lang.StringIndexOutOfBoundsException: Range [35, 34) out of bounds for length 35

java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 22
   java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 0
   int dir;
   intoffset 0   >kfreeentry;
  int;
   ;
  struct {
  
    looku->on_id,idx+ entrystatic 
  i java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 3
 };
};

static  (java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
static const struct
{
 return container_of(work, struct gpio_virtuser_irq_work_contextjava.lang.StringIndexOutOfBoundsException: Range [16, 7) out of bounds for length 10
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

static void
gpio_virtuser_init_irq_work_context .ct_owner java.lang.StringIndexOutOfBoundsException: Range [26, 24) out of bounds for length 25
{
 java.lang.StringIndexOutOfBoundsException: Range [0, 7) out of bounds for length 0
 init_completion(&kfree(dev->lookup_table);
}

static void kfreedev>)
gpio_virtuser_irq_work_queue_sync(struct java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 26
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 irq_work_queue(&ctx->work);
 wait_for_completion(&ctx->
}

static void gpio_virtuser_dbgfs_emit_value_array(char *staticstruct fwnode_handle *
       unsigned long *values,
      size_t num_values)
{
 size_t i;

 for
  buf[i] = test_bit(i, values) ? 'struct property_entry properties[2];

 buf[i++] = '\n';
}

static void guard(mutex)(&dev->lock);
{
 struct gpio_virtuser_irq_work_contextjava.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 39
    to_gpio_virtuser_irq_work_context(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  num_idsjava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16

 ctx->ret =   memset(properties, 0,sizeofproperties));
      descs->info, ctx->values);
  num_ids =list_count_nodes&>ookup_list)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
}

static int java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 12
   unsigned   *,boolatomicjava.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
{
 struct gpio_virtuser_irq_work_context ctx;

 if (!atomic)
  return gpiod_get_array_value_cansleep(descs->ndescs,
            descs->config_group_init_type_( list_for_each_entry(ookup, d- )
  i java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
IT_HARDproperties0 =PROPERTY_ENTRY_STRING_ARRAY_LEN"-,ids"
 ctx.descs = descs;
 (&ntry> l-     ids num_ids;

 gpio_virtuser_irq_work_queue_sync(&ctx)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 return  fwnode_create_software_nodeproperties
}

static ssize_t gpio_virtuser_value_array_do_read
       char __user *java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 10
       size_t size, loff_t *ppos,
       bool atomic)
{
 struct java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 1
 java.lang.StringIndexOutOfBoundsException: Range [42, 7) out of bounds for length 43
 struct  * java.lang.StringIndexOutOfBoundsException: Range [51, 42) out of bounds for length 51
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9

 unsigned
            GFP_KERNELljava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 if (
  return  kfreejava.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 35

 ret = java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 0
 if (ret)
  return ret;

  if (IS_ERRswnodejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 char *buf __freejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  !)
   java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 33

 buf fwnode=;

 return simple_read_from_buffer(user_buf, sizejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
           >descs + 1;
}

staticif()
     size_t goto ;
       java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
{
 size_t i;

 for (i = 0; i < len; i++) {
  if (staticconst  goto err_remove_lgoto err_remove_lookup_table
   clear_bit(i, values);
  else  return0;
   set_bit(i, values);
  else
   return -EINVAL;
 }

 return 0;
}

static void gpio_virtuser_set_value_array_atomic:
{
 struct java.lang.StringIndexOutOfBoundsException: Range [2, 1) out of bounds for length 25
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 java.lang.StringIndexOutOfBoundsException: Range [18, 7) out of bounds for length 39
 java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
 ctx->ret
  ->)java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
 complete
}

static int  (-;
      unsigned long *
{
 java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 0

 if(!java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
 java.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 55

 java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 0
 gpio_virtuser_devic 
 ctx.values = values;

 gpio_virtuser_irq_work_queue_sync({

 return ctx.ret;
}

ssize_t(NOMEMjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
     * lookup->con_id = kstrdup(name, GFP_KERNE>  kstrdup( ;
        size_t count, loff_t *ppos,

{
 struct gpio_virtuser_line_data *data = java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 0
 struct gpio_descs *descs = data->ad.descs;  return ERR_PTR(-)java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
 int ret;

 if
 *sufficient  uptheconfigfsentriesthat

 char *buf __free(kfree) = kzalloc(count, GFP_KERNEL);
 if (!buf)
  return -ENOMEM;

 ret = simple_write_to_buffer(buf, count, ppos, INIT_LIST_HEAD(lookup>;
 if (ret < 0)
   java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 22

 java.lang.StringIndexOutOfBoundsException: Range [16, 14) out of bounds for length 53
            GFP_KERNEL);
 if(values
  return -ENOMEM;

 ret list_for_each_entry
 if (ret)
  returnreturnno_free_ptr(lookup)->group;

ret =(descs , atomic;
 if (ret)
  return ret;

 return countjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
}

tatic ssize_t gpio_virtuser_value_array_read(struct file *file,
           char __user *user_buf,
        size_t count,java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
 return gpio_virtuser_value_array_do_read(file, user_buf, count    &ntry-group.g_item;
       false);
}

static ssize_t gpio_virtuser_value_array_write(struct file *file,
            const char java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
   s  *tem
{
 return gpio_virtuser_value_array_do_write const *static voidgpio_virtuser_device_config_group_release config_item*tem)
        false);
}

static const struct file_operations gpio_virtuser_value_array_fops = {
 .java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 .rite=gpio_virtuser_value_array_write
 .open = simple_open,
 .owner = THIS_MODULE,
 llseek =,
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

ssize_t
gpio_virtuser_value_array_atomic_read(struct file *filejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
            *)
{
 return gpio_virtuser_value_array_do_read(file, user_buf, count, ppos,
       true);
}

static ssize_t
gpio_virtuser_value_array_atomic_write(struct file *file,
    return ;
           size_t count, loff_t *ppos)
{
 return gpio_virtuser_value_array_do_write l)
        true);
}

static const struct file_operations gpio_virtuser_value_array_atomic_fops = {
 .read = gpio_virtuser_value_array_atomic_read mutex_destroy java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 34
 .write = if (live == gpio_virtuser_device_is_live(dev))
 .open = simple_open,
 .owner = THIS_MODULE,
 .  ,
};

else livejava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
{
structjava.lang.StringIndexOutOfBoundsException: Range [40, 38) out of bounds for length 45
java.lang.StringIndexOutOfBoundsException: Range [44, 37) out of bounds for length 44

 ctx->ret = java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 1
 java.lang.StringIndexOutOfBoundsException: Range [31, 9) out of bounds for length 33
}

taticints gpio_desc desc
{
 struct gpio_virtuser_irq_work_context ctx;

 gpio_virtuser_init_irq_work_context(&ctx);
 ctx.java.lang.StringIndexOutOfBoundsException: Range [2, 1) out of bounds for length 2
ctxdesc =desc;

 gpio_virtuser_irq_work_queue_sync(&ctx);

 return ctx.ret;
}

static ssize_t make_group= gpio_virtuser_make_lookup_group,
            char __user *user_buf,
            size_t size, loff_t *ppos,
            bool atomic)
{
 struct gpio_virtuser_line_data};
 struct gpio_desc *desc = data->ad.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
char buf[32java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
 int ;

 if (!atomic)
 dir java.lang.StringIndexOutOfBoundsException: Range [32, 27) out of bounds for length 34
 else
  ( java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
 if (dir < 0)
  staticstruct  *[] = {

 snprintf(buf, sizeof(buf), "%s\n", dir ? "input" : "output");

 return simple_read_from_buffer(}
}

static java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 28
{
 if (gpio_virtjava.lang.StringIndexOutOfBoundsException: Range [73, 72) out of bounds for length 73
  return gpiod_direction_input(desc);

 return gpiod_direction_output({
}

static void gpio_virtuser_do_set_direction_atomic(struct irq_work *work)
{
 structgpio_virtuser_devicedev ->parent>arent
        java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 ctx->ret = if !java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
 -;
}

static int gpio_virtuser_set_direction_atomic(struct gpio_desc *desc,
           int dir, int 
{
  gpio_virtuser_irq_work_context ctx;

 gpio_virtuser_init_irq_work_context(&ctx);
 ctx}
 ctx.desc = desc;
 ctx.dir = dir;
 ctx.val = val;

 gpio_virtuser_irq_work_queue_sync struct

 return ctx.ret gpio_virtuser_lookup_entry_config_item_ops {
}

static  gpio_virtuser_direction_do_write  file,
   }
      size_t count, loff_t *ppos,
   java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
 struct gpio_virtuser_line_data *   java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
 struct gpio_desc *desc = data->ad.desc;
 char32] trimmedjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
 , =0java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23

 if (count >= sizeof(buf))
  return -EINVAL;

 ret = java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 0
  sstruct gpio_virtuser_config_group_ops = java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
  return ret;

 buf. =java.lang.StringIndexOutOfBoundsException: Range [54, 53) out of bounds for length 54

 trimmed = strim(buf);

 if (       c char*)
  dir = 1;
 }elseif ((trimmed,"-high) == 0) 
  dir  0java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
  val = ct_owner=  up&>;
 } else if (strcmp(trimmed, "output-java.lang.StringIndexOutOfBoundsException: Range [30, 28) out of bounds for length 51
  java.lang.StringIndexOutOfBoundsException: Range [7, 6) out of bounds for length 26
 } else {
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 }

 if (!atomic)
   ={
 else
  = (desc, dir,val);
 if (ret)
  return  java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0

 return count;
}

static  kzalloc(si*);
         char __user *user_bufi (
          -)java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
{
 nconfig_group_init_type_name&group,name
            false);
}

static ssize_t gpio_virtuser_direction_write(struct java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 42
    const __ *,
          size_t count, loff_t *ppos)
{
 return gpio_virtuser_direction_do_write(file, user_bufjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
      false);
}

static const java.lang.StringIndexOutOfBoundsException: Range [0, 19) out of bounds for length 11
 .read = gpio_virtuser_direction_read,
 .write = java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 1
 .open = simple_open,
 .owner = static voidjava.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 13
 .struct
};

static ssize_t gpio_virtuser_direction_atomic_read(struct filejava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
&java.lang.StringIndexOutOfBoundsException: Range [18, 17) out of bounds for length 29
         size_t
{
 return gpio_virtuser_direction_do_readlookup>;
                   su_groupcg_item.i_namebuf,
}

static ssize_t       java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
 java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
       java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 37
{
 return IS_ERRgpio_virtuser_dbg_root){
      true);
}

static   =PTR_ERR(gpio_virtuser_dbg_root)r_lookup_config_group_ops java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
. =gpio_virtuser_direction_atomic_read,
 .java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 47
 .}
 .owner = goto java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 0
 . java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

static gpio_virtuser_value_get(okup_config_group_ops,
{
 struct gpio_virtuser_line_data *ld = data;
 int ret;

 ret = gpiod_get_value_cansleep(ld->err_configfs_unreg:
  .ct_owner java.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 61
  return ret;

 *val = ret;

 0;
}

io_virtuser_value_set( *, u64valjava.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
{
 java.lang.StringIndexOutOfBoundsException: Range [31, 7) out of bounds for length 43

 if (val > 1)
  return -EINVAL;

 gpiod_set_value_cansleep(ld->ad.desc, (int)val);

 0;
}

DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_value_fops,
    gpio_virtuser_value_get,
    gpio_virtuser_value_set,
 "n)

staticget_value_atomicstructirq_work*workjava.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
{
 struct gpio_virtuser_irq_work_context *ctx =
   to_gpio_virtuser_irq_work_context(work);

 ctx->val = gpiod_get_value(ctx->desc);
 complete(&ctx->work_completion);
}

static int gpio_virtuser_value_atomic_get(void *data, u64 *val)
{
 struct ld =  return ERR_PTR(-EBUSY);
 struct gpio_virtuser_irq_work_context ctx;

 gpio_virtuser_init_irq_work_context gpio_virtuser_lookup *ookup_free( 
 ctx.work = IRQ_WORK_INIT_HARD(java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 41
 ctx.desc = ld->ad.desc;

gpio_virtuser_irq_work_queue_sync(ctx);

 if (ctx.val < 0)
  return ctx.val;

 *val = ctx.val;


}

static -java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 22
{
 struct gpio_virtuser_irq_work_contextjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
   ( java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50

 gpiod_set_value(ctx->desc, ctx->val);
 (ctx>);
}

static int gpio_virtuser_value_atomic_set(void *data, u64 val)
{
 struct gpio_virtuser_line_data *ld = data; (lookup-siblings,&-)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
 struct gpio_virtuser_irq_work_context ctx;

 if (val > 1)
  return -EINVAL;

 gpio_virtuser_init_irq_work_context(&ctx);
 ctx.work }
 ctx.desc = ld->ad.desc;
 ctx.val = (intjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 gpio_virtuser_irq_work_queue_sync(&ctx);

 return 0;
}

DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_value_atomic_fops,
    gpio_virtuser_value_atomic_get,
    gpio_virtuser_value_atomic_set,
    "%llu\n");

static int gpio_virtuser_debounce_get(void *data, u64 *val)
{
 struct gpio_virtuser_line_data *ld = data;

*  l-debounce;

 return 0;
}

static  (utex(dev->;
{
 struct gpio_virtuser_line_data *ld = data;
 int ret;

 if (val > UINT_MAX  gjava.lang.StringIndexOutOfBoundsException: Range [39, 33) out of bounds for length 39
  return -E2BIG;>)

java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 39
 if (ret)
  /* Don't propagate errno unknown to user-space. */
  return ret == -ENOTSUPP ? -EOPNOTSUPP : ret;

 WRITE_ONCE(ld->debounce, (unsigned int)val);

 return 0;
}

DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_debounce_fops,
    gpio_virtuser_debounce_get,
    java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 0
    "%llu\n");

static ssize_t gpio_virtuser_consumer_read(struct file *file,
        char __user .make_group =gpio_virtuser_make_lookup_group,
        size_t size, loff_t *ppos)
{
 struct gpio_virtuser_line_data *data = file
 char buf[GPIO_VIRTUSER_NAME_BUF_LEN conststruct config_item_type ={
 ssize_t ret;

 memset(buf, 0x0, sizeof(buf));

scoped_guard(utex d-consumer_lock)
  ret = snprintf(buf, sizeof(buf), "% .t_attrs =gpio_virtuser_device_config_attrs,

 return simple_read_from_buffer(user_buf, size
}

static ssize_t gpio_virtuser_consumer_write(struct file *file,
         const char _static struct config_group *
         size_t count, loff_t *ppos)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 struct gpio_virtuser_line_data *data = file->private_data;
 char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2]; struct gpio_virtuser_device *dev __free(kfree) = kzalloc(sizeof(*dev),
 int ret;

 if (count >= sizeof(buf))
 return -EINVAL;

 ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos,
       user_buf count);
 if (ret < 0)
  return ret;

 buf return ERR_PTR(ENOMEM;

 ret = gpiod_set_consumer_name(data->ad.desc, buf);
 if (ret)
  return ret;

 scoped_guard(mutex, &data->consumer_lock)
  strscpy(data->java.lang.StringIndexOutOfBoundsException: Range [0, 24) out of bounds for length 17

 return ;
}

static const struct file_operations
 config_group_init_type_name(&ev-gname
 .write = gpio_virtuser_consumer_write,
 .open = simple_open,
 .owner = THIS_MODULE,
 .llseek = default_llseek,
};

static int( *ata,u64*al)
{
 struct gpio_virtuser_line_data *ld = data;

 *val = atomic_read(&ld->irq_count);

 return 0;
}

static&java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 33
{
 struct gpio_virtuser_line_data *static   gpio_virtuser_config_group_ops java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74

 atomic_inc(&ld->irq_count);

 return IRQ_HANDLED;
}

static int gpio_virtuser_interrupts_setstatic conststruct config_item_type gpio_virtuser_config_type = {
{
 struct gpio_virtuser_line_data *ld = data;
 int irq.t_group_ops =&,

 if (val > 1)
  return -EINVAL;

 if }java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
  irq = gpiod_to_irq(ld->ad.desc);
  if  .="pio-,
   return irq;

  ret = java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 4
        gpio_virtuser_irq_handler,
        IRQF_TRIGGER_RISING |
      |
        IRQF_ONESHOT,
        ld->consumer, data);
  if (ret)
   return ret;

  atomic_set(&ld->irq, irq);
} elsejava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
  irq = atomic_xchg(&ld->irq, 0);
d;
 }

 return 0;
}

DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_interrupts_fops
    gpio_virtuser_interrupts_get,
    ,
    "%llu\n");

static const struct gpio_virtuser_dbgfs_attr_descr
gpio_virtuser_line_array_dbgfs_attrs[ if(ret) {
 {
  .name = "values",
 . =&pio_virtuser_value_array_fops,
 },
 {
  .name = "values_atomic",
  .fops = &       gpio_virtuser_config_subsys..,
 },
}         ret)java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14

static  }
gpio_virtuser_line_dbgfs_attrs[] = {
 {
  .name = "direction",
  .fops = &gpio_virtuser_dbg_root = debugfs_create(gpio-" )java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
 },
 {
  .name = "direction_atomic",
  java.lang.StringIndexOutOfBoundsException: Range [47, 46) out of bounds for length 47
 },
 {
  .name = "value",
  .fopsgoto err_configfs_unreg
 },
 {
   }
  .fops = &gpio_virtuser_value_atomic_fops,
 },
 {
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  .fops = &gpio_virtuser_debounce_fops,
 },
 {
  .name irr_configfs_unreg
  .fops = &gpio_virtuser_consumer_fops,
 },
 {
  .name = "interrupts",
  .fops = &gpio_virtuser_interrupts_fops,
 },
};

java.lang.StringIndexOutOfBoundsException: Range [45, 6) out of bounds for length 46
   java.lang.StringIndexOutOfBoundsException: Range [46, 8) out of bounds for length 53
   size_t num_attrs, struct dentry *java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 0
{
 struct dentry *ret;
 size_t i;

 for(  ;i < num_attrs;i+ ++){
  ret = debugfs_create_file(attr->name, 0644, parent, data,
       attr-java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 if(IS_ERRret)
   return PTR_ERR(ret);
 }

 return 0;
}

static int gpio_virtuser_dbgfs_init_line_array_attrsjava.lang.StringIndexOutOfBoundsException: Range [44, 43) out of bounds for length 54

           const char *id,
           struct dentrymodule_exitgpio_virtuser_exit
{
 struct gpio_virtuser_line_array_data *data;
  *ame

 data = MODULE_DESCRIPTION" consumer);
 if (!data)
MODULE_LICENSE(GPL)java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22

 data->ad.descs = descs;

 name = devm_kasprintf(dev, GFP_KERNEL, "gpiod:%s", id);
 if (!name)
  return -ENOMEM;

 data->ad.dbgfs_dir = debugfs_create_dir(name, dbgfs_entry);
 if (IS_ERR(data->ad.dbgfs_dir))
  return PTR_ERR(data->ad.dbgfs_dir);

 return gpio_virtuser_create_debugfs_attrs(
   gpio_virtuser_line_array_dbgfs_attrs,
   ARRAY_SIZE(gpio_virtuser_line_array_dbgfs_attrs),
   data->ad.dbgfs_dir, data);
}

static int gpio_virtuser_dbgfs_init_line_attrs(struct device *dev,
            struct gpio_desc *desc,
            const char *id,
            unsigned int index,
            struct dentry *dbgfs_entry)
{
 struct gpio_virtuser_line_data *data;
 char *name;
 int ret;

 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 if (!data)
  return -ENOMEM;

 data->ad.desc = desc;
 strscpy(data->consumer, id);
 atomic_set(&data->irq, 0);
 atomic_set(&data->irq_count, 0);

 name = devm_kasprintf(dev, GFP_KERNEL, "gpiod:%s:%u", id, index);
 if (!name)
  return -ENOMEM;

 ret = devm_mutex_init(dev, &data->consumer_lock);
 if (ret)
  return ret;

 data->ad.dbgfs_dir = debugfs_create_dir(name, dbgfs_entry);
 if (IS_ERR(data->ad.dbgfs_dir))
  return PTR_ERR(data->ad.dbgfs_dir);

 return gpio_virtuser_create_debugfs_attrs(
    gpio_virtuser_line_dbgfs_attrs,
    ARRAY_SIZE(gpio_virtuser_line_dbgfs_attrs),
    data->ad.dbgfs_dir, data);
}

static void gpio_virtuser_debugfs_remove(void *data)
{
 struct dentry *dbgfs_entry = data;

 debugfs_remove_recursive(dbgfs_entry);
}

static int gpio_virtuser_prop_is_gpio(struct property *prop)
{
 char *dash = strrchr(prop->name, '-');

 return dash && strcmp(dash, "-gpios") == 0;
}

/*
 * If this is an OF-based system, then we iterate over properties and consider
 * all whose names end in "-gpios". For configfs we expect an additional string
 * array property - "gpio-virtuser,ids" - containing the list of all GPIO IDs
 * to request.
 */

static int gpio_virtuser_count_ids(struct device *dev)
{
 struct device_node *of_node = dev_of_node(dev);
 struct property *prop;
 int ret = 0;

 if (!of_node)
  return device_property_string_array_count(dev,
         "gpio-virtuser,ids");

 for_each_property_of_node(of_node, prop) {
  if (gpio_virtuser_prop_is_gpio(prop))
   ++ret;
 }

 return ret;
}

static int gpio_virtuser_get_ids(struct device *dev, const char **ids,
     int num_ids)
{
 struct device_node *of_node = dev_of_node(dev);
 struct property *prop;
 size_t pos = 0, diff;
 char *dash, *tmp;

 if (!of_node)
  return device_property_read_string_array(dev,
        "gpio-virtuser,ids",
        ids, num_ids);

 for_each_property_of_node(of_node, prop) {
  if (!gpio_virtuser_prop_is_gpio(prop))
   continue;

  dash = strrchr(prop->name, '-');
  diff = dash - prop->name;

  tmp = devm_kmemdup(dev, prop->name, diff + 1,
       GFP_KERNEL);
  if (!tmp)
   return -ENOMEM;

  tmp[diff] = '\0';
  ids[pos++] = tmp;
 }

 return 0;
}

static int gpio_virtuser_probe(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct dentry *dbgfs_entry;
 struct gpio_descs *descs;
 int ret, num_ids = 0, i;
 const char **ids;
 unsigned int j;

 num_ids = gpio_virtuser_count_ids(dev);
 if (num_ids < 0)
  return dev_err_probe(dev, num_ids,
         "Failed to get the number of GPIOs to request\n");

 if (num_ids == 0)
  return dev_err_probe(dev, -EINVAL, "No GPIO IDs specified\n");

 ids = devm_kcalloc(dev, num_ids, sizeof(*ids), GFP_KERNEL);
 if (!ids)
  return -ENOMEM;

 ret = gpio_virtuser_get_ids(dev, ids, num_ids);
 if (ret < 0)
  return dev_err_probe(dev, ret,
         "Failed to get the IDs of GPIOs to request\n");

 dbgfs_entry = debugfs_create_dir(dev_name(dev), gpio_virtuser_dbg_root);
 ret = devm_add_action_or_reset(dev, gpio_virtuser_debugfs_remove,
           dbgfs_entry);
 if (ret)
  return ret;

 for (i = 0; i < num_ids; i++) {
  descs = devm_gpiod_get_array(dev, ids[i], GPIOD_ASIS);
  if (IS_ERR(descs))
   return dev_err_probe(dev, PTR_ERR(descs),
          "Failed to request the '%s' GPIOs\n",
          ids[i]);

  ret = gpio_virtuser_dbgfs_init_line_array_attrs(dev, descs,
        ids[i],
        dbgfs_entry);
  if (ret)
   return dev_err_probe(dev, ret,
          "Failed to setup the debugfs array interface for the '%s' GPIOs\n",
          ids[i]);

  for (j = 0; j < descs->ndescs; j++) {
   ret = gpio_virtuser_dbgfs_init_line_attrs(dev,
       descs->desc[j], ids[i],
       j, dbgfs_entry);
   if (ret)
    return dev_err_probe(dev, ret,
           "Failed to setup the debugfs line interface for the '%s' GPIOs\n",
           ids[i]);
  }
 }

 return 0;
}

static const struct of_device_id gpio_virtuser_of_match[] = {
 { .compatible = "gpio-virtuser" },
 { }
};
MODULE_DEVICE_TABLE(of, gpio_virtuser_of_match);

static struct platform_driver gpio_virtuser_driver = {
 .driver = {
  .name = "gpio-virtuser",
  .of_match_table = gpio_virtuser_of_match,
 },
 .probe = gpio_virtuser_probe,
};

struct gpio_virtuser_device {
 struct dev_sync_probe_data probe_data;
 struct config_group group;

 int id;
 struct mutex lock;

 struct gpiod_lookup_table *lookup_table;

 struct list_head lookup_list;
};

static struct gpio_virtuser_device *
to_gpio_virtuser_device(struct config_item *item)
{
 struct config_group *group = to_config_group(item);

 return container_of(group, struct gpio_virtuser_device, group);
}

static bool
gpio_virtuser_device_is_live(struct gpio_virtuser_device *dev)
{
 lockdep_assert_held(&dev->lock);

 return !!dev->probe_data.pdev;
}

struct gpio_virtuser_lookup {
 struct config_group group;

 struct gpio_virtuser_device *parent;
 struct list_head siblings;

 char *con_id;

 struct list_head entry_list;
};

static struct gpio_virtuser_lookup *
to_gpio_virtuser_lookup(struct config_item *item)
{
 struct config_group *group = to_config_group(item);

 return container_of(group, struct gpio_virtuser_lookup, group);
}

struct gpio_virtuser_lookup_entry {
 struct config_group group;

 struct gpio_virtuser_lookup *parent;
 struct list_head siblings;

 char *key;
 /* Can be negative to indicate lookup by name. */
 int offset;
 enum gpio_lookup_flags flags;
};

static struct gpio_virtuser_lookup_entry *
to_gpio_virtuser_lookup_entry(struct config_item *item)
{
 struct config_group *group = to_config_group(item);

 return container_of(group, struct gpio_virtuser_lookup_entry, group);
}

static ssize_t
gpio_virtuser_lookup_entry_config_key_show(struct config_item *item, char *page)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;

 guard(mutex)(&dev->lock);

 return sprintf(page, "%s\n", entry->key ?: "");
}

static ssize_t
gpio_virtuser_lookup_entry_config_key_store(struct config_item *item,
         const char *page, size_t count)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;

 char *key __free(kfree) = kstrndup(skip_spaces(page), count,
        GFP_KERNEL);
 if (!key)
  return -ENOMEM;

 strim(key);

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return -EBUSY;

 kfree(entry->key);
 entry->key = no_free_ptr(key);

 return count;
}

CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, key);

static ssize_t
gpio_virtuser_lookup_entry_config_offset_show(struct config_item *item,
           char *page)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;
 unsigned int offset;

 scoped_guard(mutex, &dev->lock)
  offset = entry->offset;

 return sprintf(page, "%d\n", offset);
}

static ssize_t
gpio_virtuser_lookup_entry_config_offset_store(struct config_item *item,
            const char *page, size_t count)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;
 int offset, ret;

 ret = kstrtoint(page, 0, &offset);
 if (ret)
  return ret;

 /*
  * Negative number here means: 'key' represents a line name to lookup.
  * Non-negative means: 'key' represents the label of the chip with
  * the 'offset' value representing the line within that chip.
  *
  * GPIOLIB uses the U16_MAX value to indicate lookup by line name so
  * the greatest offset we can accept is (U16_MAX - 1).
 */

 if (offset > (U16_MAX - 1))
  return -EINVAL;

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return -EBUSY;

 entry->offset = offset;

 return count;
}

CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, offset);

static enum gpio_lookup_flags
gpio_virtuser_lookup_get_flags(struct config_item *item)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;

 guard(mutex)(&dev->lock);

 return entry->flags;
}

static ssize_t
gpio_virtuser_lookup_entry_config_drive_show(struct config_item *item, char *page)
{
 enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);
 const char *repr;

 if (flags & GPIO_OPEN_DRAIN)
  repr = "open-drain";
 else if (flags & GPIO_OPEN_SOURCE)
  repr = "open-source";
 else
  repr = "push-pull";

 return sprintf(page, "%s\n", repr);
}

static ssize_t
gpio_virtuser_lookup_entry_config_drive_store(struct config_item *item,
           const char *page, size_t count)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return -EBUSY;

 if (sysfs_streq(page, "push-pull")) {
  entry->flags &= ~(GPIO_OPEN_DRAIN | GPIO_OPEN_SOURCE);
 } else if (sysfs_streq(page, "open-drain")) {
  entry->flags &= ~GPIO_OPEN_SOURCE;
  entry->flags |= GPIO_OPEN_DRAIN;
 } else if (sysfs_streq(page, "open-source")) {
  entry->flags &= ~GPIO_OPEN_DRAIN;
  entry->flags |= GPIO_OPEN_SOURCE;
 } else {
  count = -EINVAL;
 }

 return count;
}

CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, drive);

static ssize_t
gpio_virtuser_lookup_entry_config_pull_show(struct config_item *item, char *page)
{
 enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);
 const char *repr;

 if (flags & GPIO_PULL_UP)
  repr = "pull-up";
 else if (flags & GPIO_PULL_DOWN)
  repr = "pull-down";
 else if (flags & GPIO_PULL_DISABLE)
  repr = "pull-disabled";
 else
  repr = "as-is";

 return sprintf(page, "%s\n", repr);
}

static ssize_t
gpio_virtuser_lookup_entry_config_pull_store(struct config_item *item,
          const char *page, size_t count)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return -EBUSY;

 if (sysfs_streq(page, "pull-up")) {
  entry->flags &= ~(GPIO_PULL_DOWN | GPIO_PULL_DISABLE);
  entry->flags |= GPIO_PULL_UP;
 } else if (sysfs_streq(page, "pull-down")) {
  entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DISABLE);
  entry->flags |= GPIO_PULL_DOWN;
 } else if (sysfs_streq(page, "pull-disabled")) {
  entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DOWN);
  entry->flags |= GPIO_PULL_DISABLE;
 } else if (sysfs_streq(page, "as-is")) {
  entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DOWN |
      GPIO_PULL_DISABLE);
 } else {
  count = -EINVAL;
 }

 return count;
}

CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, pull);

static ssize_t
gpio_virtuser_lookup_entry_config_active_low_show(struct config_item *item,
        char *page)
{
 enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);

 return sprintf(page, "%c\n", flags & GPIO_ACTIVE_LOW ? '1' : '0');
}

static ssize_t
gpio_virtuser_lookup_entry_config_active_low_store(struct config_item *item,
         const char *page,
         size_t count)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;
 bool active_low;
 int ret;

 ret = kstrtobool(page, &active_low);
 if (ret)
  return ret;

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return -EBUSY;

 if (active_low)
  entry->flags |= GPIO_ACTIVE_LOW;
 else
  entry->flags &= ~GPIO_ACTIVE_LOW;

 return count;
}

CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, active_low);

static ssize_t
gpio_virtuser_lookup_entry_config_transitory_show(struct config_item *item,
        char *page)
{
 enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);

 return sprintf(page, "%c\n", flags & GPIO_TRANSITORY ? '1' : '0');
}

static ssize_t
gpio_virtuser_lookup_entry_config_transitory_store(struct config_item *item,
         const char *page,
         size_t count)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;
 bool transitory;
 int ret;

 ret = kstrtobool(page, &transitory);
 if (ret)
  return ret;

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return -EBUSY;

 if (transitory)
  entry->flags |= GPIO_TRANSITORY;
 else
  entry->flags &= ~GPIO_TRANSITORY;

 return count;
}

CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, transitory);

static struct configfs_attribute *gpio_virtuser_lookup_entry_config_attrs[] = {
 &gpio_virtuser_lookup_entry_config_attr_key,
 &gpio_virtuser_lookup_entry_config_attr_offset,
 &gpio_virtuser_lookup_entry_config_attr_drive,
 &gpio_virtuser_lookup_entry_config_attr_pull,
 &gpio_virtuser_lookup_entry_config_attr_active_low,
 &gpio_virtuser_lookup_entry_config_attr_transitory,
 NULL
};

static ssize_t
gpio_virtuser_device_config_dev_name_show(struct config_item *item,
       char *page)
{
 struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
 struct platform_device *pdev;

 guard(mutex)(&dev->lock);

 pdev = dev->probe_data.pdev;
 if (pdev)
  return sprintf(page, "%s\n", dev_name(&pdev->dev));

 return sprintf(page, "gpio-sim.%d\n", dev->id);
}

CONFIGFS_ATTR_RO(gpio_virtuser_device_config_, dev_name);

static ssize_t gpio_virtuser_device_config_live_show(struct config_item *item,
           char *page)
{
 struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
 bool live;

 scoped_guard(mutex, &dev->lock)
  live = gpio_virtuser_device_is_live(dev);

 return sprintf(page, "%c\n", live ? '1' : '0');
}

static size_t
gpio_virtuser_get_lookup_count(struct gpio_virtuser_device *dev)
{
 struct gpio_virtuser_lookup *lookup;
 size_t count = 0;

 lockdep_assert_held(&dev->lock);

 list_for_each_entry(lookup, &dev->lookup_list, siblings)
  count += list_count_nodes(&lookup->entry_list);

 return count;
}

static int
gpio_virtuser_make_lookup_table(struct gpio_virtuser_device *dev)
{
 size_t num_entries = gpio_virtuser_get_lookup_count(dev);
 struct gpio_virtuser_lookup_entry *entry;
 struct gpio_virtuser_lookup *lookup;
 unsigned int i = 0, idx;

 lockdep_assert_held(&dev->lock);

 struct gpiod_lookup_table *table __free(kfree) =
  kzalloc(struct_size(table, table, num_entries + 1), GFP_KERNEL);
 if (!table)
  return -ENOMEM;

 table->dev_id = kasprintf(GFP_KERNEL, "gpio-virtuser.%d", dev->id);
 if (!table->dev_id)
  return -ENOMEM;

 list_for_each_entry(lookup, &dev->lookup_list, siblings) {
  idx = 0;
  list_for_each_entry(entry, &lookup->entry_list, siblings) {
   table->table[i++] =
    GPIO_LOOKUP_IDX(entry->key,
      entry->offset < 0 ? U16_MAX : entry->offset,
      lookup->con_id, idx++, entry->flags);
  }
 }

 gpiod_add_lookup_table(table);
 dev->lookup_table = no_free_ptr(table);

 return 0;
}

static void
gpio_virtuser_remove_lookup_table(struct gpio_virtuser_device *dev)
{
 gpiod_remove_lookup_table(dev->lookup_table);
 kfree(dev->lookup_table->dev_id);
 kfree(dev->lookup_table);
 dev->lookup_table = NULL;
}

static struct fwnode_handle *
gpio_virtuser_make_device_swnode(struct gpio_virtuser_device *dev)
{
 struct property_entry properties[2];
 struct gpio_virtuser_lookup *lookup;
 unsigned int i = 0;
 size_t num_ids;

 memset(properties, 0, sizeof(properties));

 num_ids = list_count_nodes(&dev->lookup_list);
 char **ids __free(kfree) = kcalloc(num_ids + 1, sizeof(*ids),
        GFP_KERNEL);
 if (!ids)
  return ERR_PTR(-ENOMEM);

 list_for_each_entry(lookup, &dev->lookup_list, siblings)
  ids[i++] = lookup->con_id;

 properties[0] = PROPERTY_ENTRY_STRING_ARRAY_LEN("gpio-virtuser,ids",
       ids, num_ids);

 return fwnode_create_software_node(properties, NULL);
}

static int
gpio_virtuser_device_activate(struct gpio_virtuser_device *dev)
{
 struct platform_device_info pdevinfo;
 struct fwnode_handle *swnode;
 int ret;

 lockdep_assert_held(&dev->lock);

 if (list_empty(&dev->lookup_list))
  return -ENODATA;

 swnode = gpio_virtuser_make_device_swnode(dev);
 if (IS_ERR(swnode))
  return PTR_ERR(swnode);

 memset(&pdevinfo, 0, sizeof(pdevinfo));
 pdevinfo.name = "gpio-virtuser";
 pdevinfo.id = dev->id;
 pdevinfo.fwnode = swnode;

 ret = gpio_virtuser_make_lookup_table(dev);
 if (ret)
  goto err_remove_swnode;

 ret = dev_sync_probe_register(&dev->probe_data, &pdevinfo);
 if (ret)
  goto err_remove_lookup_table;

 return 0;

err_remove_lookup_table:
 gpio_virtuser_remove_lookup_table(dev);
err_remove_swnode:
 fwnode_remove_software_node(swnode);

 return ret;
}

static void
gpio_virtuser_device_deactivate(struct gpio_virtuser_device *dev)
{
 struct fwnode_handle *swnode;

 lockdep_assert_held(&dev->lock);

 swnode = dev_fwnode(&dev->probe_data.pdev->dev);
 dev_sync_probe_unregister(&dev->probe_data);
 gpio_virtuser_remove_lookup_table(dev);
 fwnode_remove_software_node(swnode);
}

static void
gpio_virtuser_device_lockup_configfs(struct gpio_virtuser_device *dev, bool lock)
{
 struct configfs_subsystem *subsys = dev->group.cg_subsys;
 struct gpio_virtuser_lookup_entry *entry;
 struct gpio_virtuser_lookup *lookup;

 /*
  * The device only needs to depend on leaf lookup entries. This is
  * sufficient to lock up all the configfs entries that the
  * instantiated, alive device depends on.
 */

 list_for_each_entry(lookup, &dev->lookup_list, siblings) {
  list_for_each_entry(entry, &lookup->entry_list, siblings) {
   if (lock)
    WARN_ON(configfs_depend_item_unlocked(
      subsys, &entry->group.cg_item));
   else
    configfs_undepend_item_unlocked(
      &entry->group.cg_item);
  }
 }
}

static ssize_t
gpio_virtuser_device_config_live_store(struct config_item *item,
           const char *page, size_t count)
{
 struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
 int ret = 0;
 bool live;

 ret = kstrtobool(page, &live);
 if (ret)
  return ret;

 if (live)
  gpio_virtuser_device_lockup_configfs(dev, true);

 scoped_guard(mutex, &dev->lock) {
  if (live == gpio_virtuser_device_is_live(dev))
   ret = -EPERM;
  else if (live)
   ret = gpio_virtuser_device_activate(dev);
  else
   gpio_virtuser_device_deactivate(dev);
 }

 /*
  * Undepend is required only if device disablement (live == 0)
  * succeeds or if device enablement (live == 1) fails.
 */

 if (live == !!ret)
  gpio_virtuser_device_lockup_configfs(dev, false);

 return ret ?: count;
}

CONFIGFS_ATTR(gpio_virtuser_device_config_, live);

static struct configfs_attribute *gpio_virtuser_device_config_attrs[] = {
 &gpio_virtuser_device_config_attr_dev_name,
 &gpio_virtuser_device_config_attr_live,
 NULL
};

static void
gpio_virtuser_lookup_entry_config_group_release(struct config_item *item)
{
 struct gpio_virtuser_lookup_entry *entry =
     to_gpio_virtuser_lookup_entry(item);
 struct gpio_virtuser_device *dev = entry->parent->parent;

 guard(mutex)(&dev->lock);

 list_del(&entry->siblings);

 kfree(entry->key);
 kfree(entry);
}

static struct
configfs_item_operations gpio_virtuser_lookup_entry_config_item_ops = {
 .release = gpio_virtuser_lookup_entry_config_group_release,
};

static const struct
config_item_type gpio_virtuser_lookup_entry_config_group_type = {
 .ct_item_ops = &gpio_virtuser_lookup_entry_config_item_ops,
 .ct_attrs = gpio_virtuser_lookup_entry_config_attrs,
 .ct_owner = THIS_MODULE,
};

static struct config_group *
gpio_virtuser_make_lookup_entry_group(struct config_group *group,
          const char *name)
{
 struct gpio_virtuser_lookup *lookup =
    to_gpio_virtuser_lookup(&group->cg_item);
 struct gpio_virtuser_device *dev = lookup->parent;

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return ERR_PTR(-EBUSY);

 struct gpio_virtuser_lookup_entry *entry __free(kfree) =
    kzalloc(sizeof(*entry), GFP_KERNEL);
 if (!entry)
  return ERR_PTR(-ENOMEM);

 config_group_init_type_name(&entry->group, name,
   &gpio_virtuser_lookup_entry_config_group_type);
 entry->flags = GPIO_LOOKUP_FLAGS_DEFAULT;
 entry->parent = lookup;
 list_add_tail(&entry->siblings, &lookup->entry_list);

 return &no_free_ptr(entry)->group;
}

static void gpio_virtuser_lookup_config_group_release(struct config_item *item)
{
 struct gpio_virtuser_lookup *lookup = to_gpio_virtuser_lookup(item);
 struct gpio_virtuser_device *dev = lookup->parent;

 guard(mutex)(&dev->lock);

 list_del(&lookup->siblings);

 kfree(lookup->con_id);
 kfree(lookup);
}

static struct configfs_item_operations gpio_virtuser_lookup_config_item_ops = {
 .release = gpio_virtuser_lookup_config_group_release,
};

static struct
configfs_group_operations gpio_virtuser_lookup_config_group_ops = {
 .make_group     = gpio_virtuser_make_lookup_entry_group,
};

static const struct config_item_type gpio_virtuser_lookup_config_group_type = {
 .ct_group_ops = &gpio_virtuser_lookup_config_group_ops,
 .ct_item_ops = &gpio_virtuser_lookup_config_item_ops,
 .ct_owner = THIS_MODULE,
};

static struct config_group *
gpio_virtuser_make_lookup_group(struct config_group *group, const char *name)
{
 struct gpio_virtuser_device *dev =
    to_gpio_virtuser_device(&group->cg_item);

 if (strlen(name) > (GPIO_VIRTUSER_NAME_BUF_LEN - 1))
  return ERR_PTR(-E2BIG);

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  return ERR_PTR(-EBUSY);

 struct gpio_virtuser_lookup *lookup __free(kfree) =
    kzalloc(sizeof(*lookup), GFP_KERNEL);
 if (!lookup)
  return ERR_PTR(-ENOMEM);

 lookup->con_id = kstrdup(name, GFP_KERNEL);
 if (!lookup->con_id)
  return ERR_PTR(-ENOMEM);

 config_group_init_type_name(&lookup->group, name,
        &gpio_virtuser_lookup_config_group_type);
 INIT_LIST_HEAD(&lookup->entry_list);
 lookup->parent = dev;
 list_add_tail(&lookup->siblings, &dev->lookup_list);

 return &no_free_ptr(lookup)->group;
}

static void gpio_virtuser_device_config_group_release(struct config_item *item)
{
 struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);

 guard(mutex)(&dev->lock);

 if (gpio_virtuser_device_is_live(dev))
  gpio_virtuser_device_deactivate(dev);

 mutex_destroy(&dev->lock);
 ida_free(&gpio_virtuser_ida, dev->id);
 kfree(dev);
}

static struct configfs_item_operations gpio_virtuser_device_config_item_ops = {
 .release = gpio_virtuser_device_config_group_release,
};

static struct configfs_group_operations gpio_virtuser_device_config_group_ops = {
 .make_group = gpio_virtuser_make_lookup_group,
};

static const struct config_item_type gpio_virtuser_device_config_group_type = {
 .ct_group_ops = &gpio_virtuser_device_config_group_ops,
 .ct_item_ops = &gpio_virtuser_device_config_item_ops,
 .ct_attrs = gpio_virtuser_device_config_attrs,
 .ct_owner = THIS_MODULE,
};

static struct config_group *
gpio_virtuser_config_make_device_group(struct config_group *group,
           const char *name)
{
 struct gpio_virtuser_device *dev __free(kfree) = kzalloc(sizeof(*dev),
         GFP_KERNEL);
 if (!dev)
  return ERR_PTR(-ENOMEM);

 dev->id = ida_alloc(&gpio_virtuser_ida, GFP_KERNEL);
 if (dev->id < 0)
  return ERR_PTR(dev->id);

 config_group_init_type_name(&dev->group, name,
        &gpio_virtuser_device_config_group_type);
 mutex_init(&dev->lock);
 INIT_LIST_HEAD(&dev->lookup_list);
 dev_sync_probe_init(&dev->probe_data);

 return &no_free_ptr(dev)->group;
}

static struct configfs_group_operations gpio_virtuser_config_group_ops = {
 .make_group = gpio_virtuser_config_make_device_group,
};

static const struct config_item_type gpio_virtuser_config_type = {
 .ct_group_ops = &gpio_virtuser_config_group_ops,
 .ct_owner = THIS_MODULE,
};

static struct configfs_subsystem gpio_virtuser_config_subsys = {
 .su_group = {
  .cg_item = {
   .ci_namebuf = "gpio-virtuser",
   .ci_type = &gpio_virtuser_config_type,
  },
 },
};

static int __init gpio_virtuser_init(void)
{
 int ret;

 ret = platform_driver_register(&gpio_virtuser_driver);
 if (ret) {
  pr_err("Failed to register the platform driver: %d\n", ret);
  return ret;
 }

 config_group_init(&gpio_virtuser_config_subsys.su_group);
 mutex_init(&gpio_virtuser_config_subsys.su_mutex);
 ret = configfs_register_subsystem(&gpio_virtuser_config_subsys);
 if (ret) {
  pr_err("Failed to register the '%s' configfs subsystem: %d\n",
         gpio_virtuser_config_subsys.su_group.cg_item.ci_namebuf,
         ret);
  goto err_plat_drv_unreg;
 }

 gpio_virtuser_dbg_root = debugfs_create_dir("gpio-virtuser", NULL);
 if (IS_ERR(gpio_virtuser_dbg_root)) {
  ret = PTR_ERR(gpio_virtuser_dbg_root);
  pr_err("Failed to create the debugfs tree: %d\n", ret);
  goto err_configfs_unreg;
 }

 return 0;

err_configfs_unreg:
 configfs_unregister_subsystem(&gpio_virtuser_config_subsys);
err_plat_drv_unreg:
 mutex_destroy(&gpio_virtuser_config_subsys.su_mutex);
 platform_driver_unregister(&gpio_virtuser_driver);

 return ret;
}
module_init(gpio_virtuser_init);

static void __exit gpio_virtuser_exit(void)
{
 configfs_unregister_subsystem(&gpio_virtuser_config_subsys);
 mutex_destroy(&gpio_virtuser_config_subsys.su_mutex);
 platform_driver_unregister(&gpio_virtuser_driver);
 debugfs_remove_recursive(gpio_virtuser_dbg_root);
}
module_exit(gpio_virtuser_exit);

MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
MODULE_DESCRIPTION("Virtual GPIO consumer module");
MODULE_LICENSE("GPL");

Messung V0.5 in Prozent
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet am  2026-10-11) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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.