Create the first draft of ksudoku subsystem in one file
Signed-off-by: Sameer Rahmani <lxsameer@gnu.org>
This commit is contained in:
parent
5344bbf719
commit
171b0f6946
248
ksudoku.c
248
ksudoku.c
|
@ -1,65 +1,239 @@
|
|||
#include "ksudoku.h"
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define KSUDOKU_VERSION "0.1"
|
||||
#define KSUDOKU_DESC "Kernel Sudoku Module"
|
||||
|
||||
#define KSUDOKU_READY 0
|
||||
#define KSUDOKU_BUSY 1
|
||||
|
||||
static SUDOKU_ATTR_RO(is_valid);
|
||||
static SUDOKU_ATTR_RO(is_solved);
|
||||
struct ksudoku {
|
||||
struct kobject kobj;
|
||||
const struct attribute_group *attr_group;
|
||||
char *matrix;
|
||||
atomic_t status;
|
||||
};
|
||||
#define to_ksudoku(obj) container_of(obj, struct ksudoku, kobj)
|
||||
|
||||
|
||||
/**
|
||||
* sudoku_create_file - create sysfs attribute file for the given sudoku.
|
||||
* @sudoku: sudoku
|
||||
* @attr: sudoku attribute descriptor.
|
||||
*/
|
||||
int sudoku_create_file(struct sudoku *s,
|
||||
const struct sudoku_attribute *attr)
|
||||
struct ksudoku_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct ksudoku *s, struct ksudoku_attribute *attr,
|
||||
char *buf);
|
||||
ssize_t (*store)(struct ksudoku *s, struct ksudoku_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
bool value;
|
||||
};
|
||||
#define to_ksudoku_attr(_attr) container_of(_attr, struct ksudoku_attribute, attr)
|
||||
|
||||
/*
|
||||
* The default show callback that is called by sysfs when ever a read
|
||||
* operation happens on any attribute on ksudoku subsystem.
|
||||
*/
|
||||
static ssize_t ksudoku_default_attr_show(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int error = 0;
|
||||
struct ksudoku_attribute *attribute;
|
||||
struct ksudoku *sudoku;
|
||||
|
||||
if (s) {
|
||||
WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
|
||||
"Attribute %s: write permission without 'store'\n",
|
||||
attr->attr.name);
|
||||
WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
|
||||
"Attribute %s: read permission without 'show'\n",
|
||||
attr->attr.name);
|
||||
error = sysfs_create_file(&s->kobj, &attr->attr);
|
||||
}
|
||||
attribute = to_ksudoku_attr(attr);
|
||||
sudoku = to_ksudoku(kobj);
|
||||
|
||||
return error;
|
||||
if (!attribute->show)
|
||||
return -EIO;
|
||||
|
||||
return attribute->show(sudoku, attribute, buf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sudoku_create_file);
|
||||
|
||||
|
||||
/* static ssize_t is_valid_show(struct kobject *kobj, struct attribute *attr, */
|
||||
/* char *buf) */
|
||||
/* { */
|
||||
/* struct sudoku_attribute *s_attr = to_sudoku_attr(attr); */
|
||||
/* struct sudoku *s = to_sudoku(kobj); */
|
||||
/* ssize_t ret = -EIO; */
|
||||
/*
|
||||
* The default show callback that is called by sysfs when ever a write
|
||||
* operation happens on any attribute on ksudoku subsystem.
|
||||
*/
|
||||
static ssize_t ksudoku_default_attr_store(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct ksudoku_attribute *attribute;
|
||||
struct ksudoku *sudoku;
|
||||
|
||||
/* if (s_attr->show) */
|
||||
/* ret = s_attr->show(s, s_attr, buf); */
|
||||
attribute = to_ksudoku_attr(attr);
|
||||
sudoku = to_ksudoku(kobj);
|
||||
|
||||
/* if (ret >= (ssize_t)PAGE_SIZE) { */
|
||||
/* printk("is_valid_show: %pS returned bad count\n", */
|
||||
/* s_attr->show); */
|
||||
/* } */
|
||||
/* return ret; */
|
||||
/* } */
|
||||
if (!attribute->store)
|
||||
return -EIO;
|
||||
|
||||
return attribute->store(sudoku, attribute, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a `sysfs_ops` structure in order to register
|
||||
* the default IO operation handlers of ksudoku subsystem.
|
||||
*/
|
||||
static const struct sysfs_ops ksudoku_sysfs_ops = {
|
||||
.show = ksudoku_default_attr_show,
|
||||
.store = ksudoku_default_attr_store,
|
||||
};
|
||||
|
||||
/*
|
||||
* The release function for ksudoku. This is REQUIRED by the kernel to
|
||||
* have. We free the memory held in our object here.
|
||||
*
|
||||
* We should free the memory here rather than the exit method of the
|
||||
* module. Kernel will call this function as soon as the reference
|
||||
* counter on the kobject embedded inside the ksudoku object hits
|
||||
* zero. So it might happen before or after exit function.
|
||||
*
|
||||
* The release function is per kobject so we're going to free
|
||||
* different ksudoku instances separated from eachother.
|
||||
*/
|
||||
static void ksudoku_release(struct kobject *kobj)
|
||||
{
|
||||
struct ksudoku *s;
|
||||
|
||||
s = to_ksudoku(kobj);
|
||||
kfree(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* The show handler of `status` attribute. This callback will
|
||||
* be called via `ksudoku_default_attr_show` which is the
|
||||
* default read handler on ksudoku_type for ksudoku subsystem.
|
||||
*
|
||||
* Since `status` suppose to read only there would not be
|
||||
* a store handler.
|
||||
*/
|
||||
static ssize_t status_show(struct ksudoku *s,
|
||||
struct ksudoku_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d", atomic_read(&s->status));
|
||||
}
|
||||
|
||||
// __ATTR_RO macro will set the `.show` member of
|
||||
// `status_attribute` to `status_show` (name + _show)
|
||||
static struct ksudoku_attribute status_attribute = __ATTR_RO(status);
|
||||
|
||||
|
||||
static ssize_t matrix_show(struct ksudoku *s,
|
||||
struct ksudoku_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s", s->matrix);
|
||||
}
|
||||
|
||||
static ssize_t matrix_store(struct ksudoku *s,
|
||||
struct ksudoku_attribute *attr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
int status = atomic_read(&s->status);
|
||||
|
||||
if (status == KSUDOKU_BUSY)
|
||||
return -EBUSY;
|
||||
|
||||
if (len != 81)
|
||||
return -EIO;
|
||||
|
||||
strncpy(s->matrix, buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct ksudoku_attribute matrix_attribute =
|
||||
__ATTR(matrix, 0664, matrix_show, matrix_store);
|
||||
|
||||
|
||||
static struct attribute *ksudoku_default_attrs[] = {
|
||||
&status_attribute.attr,
|
||||
&matrix_attribute.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ksudoku_default);
|
||||
|
||||
|
||||
static struct kobj_type ksudoku_type = {
|
||||
.sysfs_ops = &ksudoku_sysfs_ops,
|
||||
.release = ksudoku_release,
|
||||
.default_groups = ksudoku_default_groups,
|
||||
};
|
||||
|
||||
|
||||
static struct kset *ksudoku_set;
|
||||
|
||||
static struct ksudoku *create_ksudoku(const char *name)
|
||||
{
|
||||
struct ksudoku *s;
|
||||
int result;
|
||||
|
||||
s = kzalloc(sizeof(*s), GFP_KERNEL);
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
s->kobj.kset = ksudoku_set;
|
||||
|
||||
result = kobject_init_and_add(&s->kobj, &ksudoku_type,
|
||||
NULL, "%s", name);
|
||||
|
||||
if (result) {
|
||||
kobject_put(&s->kobj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
atomic_set(&s->status, KSUDOKU_READY);
|
||||
|
||||
// Let the world now about the new registered kobj
|
||||
kobject_uevent(&s->kobj, KOBJ_ADD);
|
||||
return s;
|
||||
}
|
||||
|
||||
static void destroy_ksudoku(struct ksudoku *s)
|
||||
{
|
||||
kobject_put(&s->kobj);
|
||||
}
|
||||
|
||||
|
||||
static int ksudoku_init(void)
|
||||
{
|
||||
printk(KERN_ALERT "Init ksudoku.\n");
|
||||
printk(KERN_ALERT "Init ksudoku subsystem.\n");
|
||||
|
||||
// kernel_kobj is the kobject related to /sys/kernel
|
||||
ksudoku_set = kset_create_and_add("ksudoku", NULL, kernel_kobj);
|
||||
|
||||
if (!ksudoku_set)
|
||||
return -ENOMEM;
|
||||
|
||||
printk(KERN_ALERT "Ready to register sudokus.\n");
|
||||
/* sudoku = kmalloc(sizeof (struct ksudoku), GFP_KERNEL); */
|
||||
|
||||
/* atomic_set(&sudoku->status, 0); */
|
||||
/* sudoku->attr_group = &attr_group; */
|
||||
|
||||
/* if (!sudoku) */
|
||||
/* return -ENOMEM; */
|
||||
|
||||
/* sudoku->kobj = kobject_create_and_add("ksudoku", kernel_kobj); */
|
||||
|
||||
/* if (!&sudoku->kobj) */
|
||||
/* return -ENOMEM; */
|
||||
|
||||
/* sysfs_result = sysfs_create_group(sudoku->kobj, sudoku->attr_group); */
|
||||
|
||||
/* if (sysfs_result) */
|
||||
/* kobject_put(sudoku->kobj); */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ksudoku_exit(void)
|
||||
{
|
||||
//kobject_put(sudoku->kobj);
|
||||
kset_unregister(ksudoku_set);
|
||||
printk(KERN_ALERT "Exit ksudoku.\n");
|
||||
}
|
||||
|
||||
|
|
63
ksudoku.h
63
ksudoku.h
|
@ -1,36 +1,22 @@
|
|||
#ifndef _KSUDOKU_H_
|
||||
#define _KSUDOKU_H_
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#define to_sudoku(obj) container_of(obj, struct sudoku, kobj)
|
||||
#define to_sudoku_attr(_attr) container_of(_attr, struct sudoku_attribute, attr)
|
||||
|
||||
struct sudoku;
|
||||
|
||||
static ssize_t is_valid_show(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
char *buf);
|
||||
|
||||
static ssize_t is_valid_store(struct kobject *,
|
||||
struct attribute *,
|
||||
const char *, size_t);
|
||||
|
||||
static ssize_t is_solved_show(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
char *buf);
|
||||
|
||||
static ssize_t is_solved_store(struct kobject *,
|
||||
struct attribute *,
|
||||
const char *, size_t);
|
||||
struct ksudoku;
|
||||
|
||||
#define to_ksudoku(obj) container_of(obj, struct ksudoku, kobj)
|
||||
#define to_ksudoku_attr(_attr) container_of(_attr, struct kobj_attribute, attr)
|
||||
|
||||
struct sudoku_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf);
|
||||
ssize_t (*store)(void);
|
||||
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
bool value;
|
||||
};
|
||||
|
||||
|
@ -44,32 +30,25 @@ struct sudoku_attribute {
|
|||
* If "name" is specified, the uevent will contain it in
|
||||
* the DEVTYPE variable.
|
||||
*/
|
||||
struct sudoku_type {
|
||||
const char *name;
|
||||
const struct attribute_group **groups;
|
||||
int (*uevent)(struct sudoku *s, struct kobj_uevent_env *env);
|
||||
char *(*devnode)(struct sudoku *s, umode_t *mode,
|
||||
kuid_t *uid, kgid_t *gid);
|
||||
void (*release)(struct sudoku *s);
|
||||
/* struct sudoku_type { */
|
||||
/* const char *name; */
|
||||
/* const struct attribute_group **groups; */
|
||||
/* int (*uevent)(struct sudoku *s, struct kobj_uevent_env *env); */
|
||||
/* void (*release)(struct kobject *kobj); */
|
||||
/* const struct sysfs_ops *sysfs_ops; */
|
||||
/* }; */
|
||||
|
||||
const struct sysfs_ops *sysfs_ops;
|
||||
};
|
||||
|
||||
struct sudoku {
|
||||
struct kobject kobj;
|
||||
struct sudoku *parent;
|
||||
const struct sudoku_type *type;
|
||||
struct ksudoku {
|
||||
struct kobject *kobj;
|
||||
const struct attribute_group *attr_group;
|
||||
char matrix[81];
|
||||
|
||||
};
|
||||
atomic_t status;
|
||||
} ;
|
||||
|
||||
#define SUDOKU_ATTR_RO(_name) \
|
||||
struct sudoku_attribute sudoku_##_name = __ATTR_RO(_name)
|
||||
struct kobj_attribute sudoku_##_name = __ATTR_RO(_name)
|
||||
|
||||
#define SUDOKU_ATTR_WO(_name) \
|
||||
struct sudoku_attribute sudoku_##_name = __ATTR_WO(_name)
|
||||
|
||||
extern int sudoku_create_file(struct sudoku *s,
|
||||
const struct sudoku_attribute *attr);
|
||||
struct kobj_attribute sudoku_##_name = __ATTR_WO(_name)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/home/lxsameer/src/linux/ksudoku/ksudoku.o
|
||||
|
Loading…
Reference in New Issue