staging: unisys: remove last remnants of proc entry code
All of the proc code using easyproc and procobjecttree support is gone, so we can remove it from the source entirely. Signed-off-by: Benjamin Romer <benjamin.romer@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
862cf60407
commit
3e37a0306c
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil.o
|
obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil.o
|
||||||
|
|
||||||
visorutil-y := charqueue.o easyproc.o periodic_work.o procobjecttree.o \
|
visorutil-y := charqueue.o periodic_work.o memregion_direct.o visorkmodutils.o
|
||||||
memregion_direct.o visorkmodutils.o
|
|
||||||
|
|
||||||
ccflags-y += -Idrivers/staging/unisys/include
|
ccflags-y += -Idrivers/staging/unisys/include
|
||||||
|
@ -1,356 +0,0 @@
|
|||||||
/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
|
||||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file *********************************************************************
|
|
||||||
*
|
|
||||||
* Handle procfs-specific tasks.
|
|
||||||
* Note that this file does not know about any module-specific things, nor
|
|
||||||
* does it know anything about what information to reveal as part of the proc
|
|
||||||
* entries. The 2 functions that take care of displaying device and
|
|
||||||
* driver specific information are passed as parameters to
|
|
||||||
* visor_easyproc_InitDriver().
|
|
||||||
*
|
|
||||||
* void show_device_info(struct seq_file *seq, void *p);
|
|
||||||
* void show_driver_info(struct seq_file *seq);
|
|
||||||
*
|
|
||||||
* The second parameter to show_device_info is actually a pointer to the
|
|
||||||
* device-specific info to show. It is the context that was originally
|
|
||||||
* passed to visor_easyproc_InitDevice().
|
|
||||||
*
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/proc_fs.h>
|
|
||||||
|
|
||||||
#include "timskmod.h"
|
|
||||||
#include "easyproc.h"
|
|
||||||
|
|
||||||
#define MYDRVNAME "easyproc"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* /proc/<ProcId> ProcDir
|
|
||||||
* /proc/<ProcId>/driver ProcDriverDir
|
|
||||||
* /proc/<ProcId>/driver/diag ProcDriverDiagFile
|
|
||||||
* /proc/<ProcId>/device ProcDeviceDir
|
|
||||||
* /proc/<ProcId>/device/0 procDevicexDir
|
|
||||||
* /proc/<ProcId>/device/0/diag procDevicexDiagFile
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static ssize_t proc_write_device(struct file *file, const char __user *buffer,
|
|
||||||
size_t count, loff_t *ppos);
|
|
||||||
static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
|
|
||||||
size_t count, loff_t *ppos);
|
|
||||||
|
|
||||||
static struct proc_dir_entry *
|
|
||||||
createProcDir(char *name, struct proc_dir_entry *parent)
|
|
||||||
{
|
|
||||||
struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int seq_show_driver(struct seq_file *seq, void *offset);
|
|
||||||
static int proc_open_driver(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, seq_show_driver, PDE_DATA(inode));
|
|
||||||
}
|
|
||||||
static const struct file_operations proc_fops_driver = {
|
|
||||||
.open = proc_open_driver,
|
|
||||||
.read = seq_read,
|
|
||||||
.write = proc_write_driver,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int seq_show_device(struct seq_file *seq, void *offset);
|
|
||||||
static int seq_show_device_property(struct seq_file *seq, void *offset);
|
|
||||||
static int proc_open_device(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, seq_show_device, PDE_DATA(inode));
|
|
||||||
}
|
|
||||||
static const struct file_operations proc_fops_device = {
|
|
||||||
.open = proc_open_device,
|
|
||||||
.read = seq_read,
|
|
||||||
.write = proc_write_device,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
static int proc_open_device_property(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, seq_show_device_property, PDE_DATA(inode));
|
|
||||||
}
|
|
||||||
static const struct file_operations proc_fops_device_property = {
|
|
||||||
.open = proc_open_device_property,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_easyproc_InitDriver(struct easyproc_driver_info *pdriver,
|
|
||||||
char *procId,
|
|
||||||
void (*show_driver_info)(struct seq_file *),
|
|
||||||
void (*show_device_info)(struct seq_file *,
|
|
||||||
void *))
|
|
||||||
{
|
|
||||||
memset(pdriver, 0, sizeof(struct easyproc_driver_info));
|
|
||||||
pdriver->ProcId = procId;
|
|
||||||
pdriver->Show_driver_info = show_driver_info;
|
|
||||||
pdriver->Show_device_info = show_device_info;
|
|
||||||
if (pdriver->ProcDir == NULL)
|
|
||||||
pdriver->ProcDir = createProcDir(pdriver->ProcId, NULL);
|
|
||||||
if ((pdriver->ProcDir != NULL) && (pdriver->ProcDriverDir == NULL))
|
|
||||||
pdriver->ProcDriverDir = createProcDir("driver",
|
|
||||||
pdriver->ProcDir);
|
|
||||||
if ((pdriver->ProcDir != NULL) && (pdriver->ProcDeviceDir == NULL))
|
|
||||||
pdriver->ProcDeviceDir = createProcDir("device",
|
|
||||||
pdriver->ProcDir);
|
|
||||||
if ((pdriver->ProcDriverDir != NULL) &&
|
|
||||||
(pdriver->ProcDriverDiagFile == NULL)) {
|
|
||||||
pdriver->ProcDriverDiagFile =
|
|
||||||
proc_create_data("diag", 0,
|
|
||||||
pdriver->ProcDriverDir,
|
|
||||||
&proc_fops_driver, pdriver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_easyproc_InitDriver);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
|
|
||||||
char *procId,
|
|
||||||
void (*show_driver_info)(struct seq_file *),
|
|
||||||
void (*show_device_info)(struct seq_file *,
|
|
||||||
void *),
|
|
||||||
void (*write_driver_info)(char *buf,
|
|
||||||
size_t count,
|
|
||||||
loff_t *ppos),
|
|
||||||
void (*write_device_info)(char *buf,
|
|
||||||
size_t count,
|
|
||||||
loff_t *ppos,
|
|
||||||
void *p))
|
|
||||||
{
|
|
||||||
visor_easyproc_InitDriver(pdriver, procId,
|
|
||||||
show_driver_info, show_device_info);
|
|
||||||
pdriver->Write_driver_info = write_driver_info;
|
|
||||||
pdriver->Write_device_info = write_device_info;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_easyproc_InitDriverEx);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_easyproc_DeInitDriver(struct easyproc_driver_info *pdriver)
|
|
||||||
{
|
|
||||||
if (pdriver->ProcDriverDiagFile != NULL) {
|
|
||||||
remove_proc_entry("diag", pdriver->ProcDriverDir);
|
|
||||||
pdriver->ProcDriverDiagFile = NULL;
|
|
||||||
}
|
|
||||||
if (pdriver->ProcDriverDir != NULL) {
|
|
||||||
remove_proc_entry("driver", pdriver->ProcDir);
|
|
||||||
pdriver->ProcDriverDir = NULL;
|
|
||||||
}
|
|
||||||
if (pdriver->ProcDeviceDir != NULL) {
|
|
||||||
remove_proc_entry("device", pdriver->ProcDir);
|
|
||||||
pdriver->ProcDeviceDir = NULL;
|
|
||||||
}
|
|
||||||
if (pdriver->ProcDir != NULL) {
|
|
||||||
remove_proc_entry(pdriver->ProcId, NULL);
|
|
||||||
pdriver->ProcDir = NULL;
|
|
||||||
}
|
|
||||||
pdriver->ProcId = NULL;
|
|
||||||
pdriver->Show_driver_info = NULL;
|
|
||||||
pdriver->Show_device_info = NULL;
|
|
||||||
pdriver->Write_driver_info = NULL;
|
|
||||||
pdriver->Write_device_info = NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDriver);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_easyproc_InitDevice(struct easyproc_driver_info *pdriver,
|
|
||||||
struct easyproc_device_info *p, int devno,
|
|
||||||
void *devdata)
|
|
||||||
{
|
|
||||||
if ((pdriver->ProcDeviceDir != NULL) && (p->procDevicexDir == NULL)) {
|
|
||||||
char s[29];
|
|
||||||
|
|
||||||
sprintf(s, "%d", devno);
|
|
||||||
p->procDevicexDir = createProcDir(s, pdriver->ProcDeviceDir);
|
|
||||||
p->devno = devno;
|
|
||||||
}
|
|
||||||
p->devdata = devdata;
|
|
||||||
p->pdriver = pdriver;
|
|
||||||
p->devno = devno;
|
|
||||||
if ((p->procDevicexDir != NULL) && (p->procDevicexDiagFile == NULL)) {
|
|
||||||
p->procDevicexDiagFile =
|
|
||||||
proc_create_data("diag", 0, p->procDevicexDir,
|
|
||||||
&proc_fops_device, p);
|
|
||||||
}
|
|
||||||
memset(&(p->device_property_info[0]), 0,
|
|
||||||
sizeof(p->device_property_info));
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_easyproc_InitDevice);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
|
|
||||||
void (*show_property_info)
|
|
||||||
(struct seq_file *, void *),
|
|
||||||
char *property_name)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
struct easyproc_device_property_info *px = NULL;
|
|
||||||
|
|
||||||
if (p->procDevicexDir == NULL)
|
|
||||||
return;
|
|
||||||
for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
|
|
||||||
if (p->device_property_info[i].procEntry == NULL) {
|
|
||||||
px = &(p->device_property_info[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!px)
|
|
||||||
return;
|
|
||||||
|
|
||||||
px->devdata = p->devdata;
|
|
||||||
px->pdriver = p->pdriver;
|
|
||||||
px->procEntry = proc_create_data(property_name, 0, p->procDevicexDir,
|
|
||||||
&proc_fops_device_property, px);
|
|
||||||
if (strlen(property_name)+1 > sizeof(px->property_name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strcpy(px->property_name, property_name);
|
|
||||||
if (px->procEntry == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
px->show_device_property_info = show_property_info;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_easyproc_CreateDeviceProperty);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
|
|
||||||
struct easyproc_device_info *p, int devno)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
|
|
||||||
if (p->device_property_info[i].procEntry != NULL) {
|
|
||||||
struct easyproc_device_property_info *px =
|
|
||||||
&(p->device_property_info[i]);
|
|
||||||
remove_proc_entry(px->property_name, p->procDevicexDir);
|
|
||||||
px->procEntry = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p->procDevicexDiagFile != NULL) {
|
|
||||||
remove_proc_entry("diag", p->procDevicexDir);
|
|
||||||
p->procDevicexDiagFile = NULL;
|
|
||||||
}
|
|
||||||
if (p->procDevicexDir != NULL) {
|
|
||||||
char s[29];
|
|
||||||
|
|
||||||
sprintf(s, "%d", devno);
|
|
||||||
remove_proc_entry(s, pdriver->ProcDeviceDir);
|
|
||||||
p->procDevicexDir = NULL;
|
|
||||||
}
|
|
||||||
p->devdata = NULL;
|
|
||||||
p->pdriver = NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDevice);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int seq_show_driver(struct seq_file *seq, void *offset)
|
|
||||||
{
|
|
||||||
struct easyproc_driver_info *p =
|
|
||||||
(struct easyproc_driver_info *)(seq->private);
|
|
||||||
if (!p)
|
|
||||||
return 0;
|
|
||||||
(*(p->Show_driver_info))(seq);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int seq_show_device(struct seq_file *seq, void *offset)
|
|
||||||
{
|
|
||||||
struct easyproc_device_info *p =
|
|
||||||
(struct easyproc_device_info *)(seq->private);
|
|
||||||
if ((!p) || (!(p->pdriver)))
|
|
||||||
return 0;
|
|
||||||
(*(p->pdriver->Show_device_info))(seq, p->devdata);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int seq_show_device_property(struct seq_file *seq, void *offset)
|
|
||||||
{
|
|
||||||
struct easyproc_device_property_info *p =
|
|
||||||
(struct easyproc_device_property_info *)(seq->private);
|
|
||||||
if ((!p) || (!(p->show_device_property_info)))
|
|
||||||
return 0;
|
|
||||||
(*(p->show_device_property_info))(seq, p->devdata);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
|
|
||||||
size_t count, loff_t *ppos)
|
|
||||||
{
|
|
||||||
struct seq_file *seq = (struct seq_file *)file->private_data;
|
|
||||||
struct easyproc_driver_info *p = NULL;
|
|
||||||
char local_buf[256];
|
|
||||||
|
|
||||||
if (seq == NULL)
|
|
||||||
return 0;
|
|
||||||
p = (struct easyproc_driver_info *)(seq->private);
|
|
||||||
if ((!p) || (!(p->Write_driver_info)))
|
|
||||||
return 0;
|
|
||||||
if (count >= sizeof(local_buf))
|
|
||||||
return -ENOMEM;
|
|
||||||
if (copy_from_user(local_buf, buffer, count))
|
|
||||||
return -EFAULT;
|
|
||||||
local_buf[count] = '\0'; /* be friendly */
|
|
||||||
(*(p->Write_driver_info))(local_buf, count, ppos);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ssize_t proc_write_device(struct file *file, const char __user *buffer,
|
|
||||||
size_t count, loff_t *ppos)
|
|
||||||
{
|
|
||||||
struct seq_file *seq = (struct seq_file *)file->private_data;
|
|
||||||
struct easyproc_device_info *p = NULL;
|
|
||||||
char local_buf[256];
|
|
||||||
|
|
||||||
if (seq == NULL)
|
|
||||||
return 0;
|
|
||||||
p = (struct easyproc_device_info *)(seq->private);
|
|
||||||
if ((!p) || (!(p->pdriver)) || (!(p->pdriver->Write_device_info)))
|
|
||||||
return 0;
|
|
||||||
if (count >= sizeof(local_buf))
|
|
||||||
return -ENOMEM;
|
|
||||||
if (copy_from_user(local_buf, buffer, count))
|
|
||||||
return -EFAULT;
|
|
||||||
local_buf[count] = '\0'; /* be friendly */
|
|
||||||
(*(p->pdriver->Write_device_info))(local_buf, count, ppos, p->devdata);
|
|
||||||
return count;
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
/* easyproc.h
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 - 2013 UNISYS CORPORATION
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
|
||||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file *********************************************************************
|
|
||||||
*
|
|
||||||
* This describes the interfaces necessary for a simple /proc file
|
|
||||||
* implementation for a driver.
|
|
||||||
*
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __EASYPROC_H__
|
|
||||||
#define __EASYPROC_H__
|
|
||||||
|
|
||||||
#include "timskmod.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct easyproc_driver_info {
|
|
||||||
struct proc_dir_entry *ProcDir;
|
|
||||||
struct proc_dir_entry *ProcDriverDir;
|
|
||||||
struct proc_dir_entry *ProcDriverDiagFile;
|
|
||||||
struct proc_dir_entry *ProcDeviceDir;
|
|
||||||
char *ProcId;
|
|
||||||
void (*Show_device_info)(struct seq_file *seq, void *p);
|
|
||||||
void (*Show_driver_info)(struct seq_file *seq);
|
|
||||||
void (*Write_device_info)(char *buf, size_t count,
|
|
||||||
loff_t *ppos, void *p);
|
|
||||||
void (*Write_driver_info)(char *buf, size_t count, loff_t *ppos);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* property is a file under /proc/<x>/device/<x>/<property_name> */
|
|
||||||
struct easyproc_device_property_info {
|
|
||||||
char property_name[25];
|
|
||||||
struct proc_dir_entry *procEntry;
|
|
||||||
struct easyproc_driver_info *pdriver;
|
|
||||||
void *devdata;
|
|
||||||
void (*show_device_property_info)(struct seq_file *seq, void *p);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct easyproc_device_info {
|
|
||||||
struct proc_dir_entry *procDevicexDir;
|
|
||||||
struct proc_dir_entry *procDevicexDiagFile;
|
|
||||||
struct easyproc_driver_info *pdriver;
|
|
||||||
void *devdata;
|
|
||||||
int devno;
|
|
||||||
/* allow for a number of custom properties for each device: */
|
|
||||||
struct easyproc_device_property_info device_property_info[10];
|
|
||||||
};
|
|
||||||
|
|
||||||
void visor_easyproc_InitDevice(struct easyproc_driver_info *pdriver,
|
|
||||||
struct easyproc_device_info *p, int devno,
|
|
||||||
void *devdata);
|
|
||||||
void visor_easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
|
|
||||||
struct easyproc_device_info *p, int devno);
|
|
||||||
void visor_easyproc_InitDriver(struct easyproc_driver_info *pdriver,
|
|
||||||
char *procId,
|
|
||||||
void (*show_driver_info)(struct seq_file *),
|
|
||||||
void (*show_device_info)(struct seq_file *,
|
|
||||||
void *));
|
|
||||||
void visor_easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
|
|
||||||
char *procId,
|
|
||||||
void (*show_driver_info)(struct seq_file *),
|
|
||||||
void (*show_device_info)(struct seq_file *,
|
|
||||||
void *),
|
|
||||||
void (*Write_driver_info)(char *buf,
|
|
||||||
size_t count,
|
|
||||||
loff_t *ppos),
|
|
||||||
void (*Write_device_info)(char *buf,
|
|
||||||
size_t count,
|
|
||||||
loff_t *ppos,
|
|
||||||
void *p));
|
|
||||||
void visor_easyproc_DeInitDriver(struct easyproc_driver_info *pdriver);
|
|
||||||
void visor_easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
|
|
||||||
void (*show_property_info)
|
|
||||||
(struct seq_file *, void *),
|
|
||||||
char *property_name);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,335 +0,0 @@
|
|||||||
/* procobjecttree.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 - 2013 UNISYS CORPORATION
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
|
||||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "procobjecttree.h"
|
|
||||||
|
|
||||||
#define MYDRVNAME "procobjecttree"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** This is context info that we stash in each /proc file entry, which we
|
|
||||||
* need in order to call the callback function that supplies the /proc read
|
|
||||||
* info for that file.
|
|
||||||
*/
|
|
||||||
struct proc_dir_entry_context {
|
|
||||||
void (*show_property)(struct seq_file *, void *, int);
|
|
||||||
MYPROCOBJECT *procObject;
|
|
||||||
int propertyIndex;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/** This describes the attributes of a tree rooted at
|
|
||||||
* <procDirRoot>/<name[0]>/<name[1]>/...
|
|
||||||
* Properties for each object of this type will be located under
|
|
||||||
* <procDirRoot>/<name[0]>/<name[1]>/.../<objectName>/<propertyName>.
|
|
||||||
*/
|
|
||||||
struct MYPROCTYPE_Tag {
|
|
||||||
const char **name; /**< node names for this type, ending with NULL */
|
|
||||||
int nNames; /**< num of node names in <name> */
|
|
||||||
|
|
||||||
/** root dir for this type tree in /proc */
|
|
||||||
struct proc_dir_entry *procDirRoot;
|
|
||||||
|
|
||||||
struct proc_dir_entry **procDirs; /**< for each node in <name> */
|
|
||||||
|
|
||||||
/** bottom dir where objects will be rooted; i.e., this is
|
|
||||||
* <procDirRoot>/<name[0]>/<name[1]>/.../, which is the same as the
|
|
||||||
* last entry in the <procDirs> array. */
|
|
||||||
struct proc_dir_entry *procDir;
|
|
||||||
|
|
||||||
/** name for each property that objects of this type can have */
|
|
||||||
const char **propertyNames;
|
|
||||||
|
|
||||||
int nProperties; /**< num of names in <propertyNames> */
|
|
||||||
|
|
||||||
/** Call this, passing MYPROCOBJECT.context and the property index
|
|
||||||
* whenever someone reads the proc entry */
|
|
||||||
void (*show_property)(struct seq_file *, void *, int);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct MYPROCOBJECT_Tag {
|
|
||||||
MYPROCTYPE *type;
|
|
||||||
|
|
||||||
/** This is the name of the dir node in /proc under which the
|
|
||||||
* properties of this object will appear as files. */
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
int namesize; /**< number of bytes allocated for name */
|
|
||||||
void *context; /**< passed to MYPROCTYPE.show_property */
|
|
||||||
|
|
||||||
/** <type.procDirRoot>/<type.name[0]>/<type.name[1]>/.../<name> */
|
|
||||||
struct proc_dir_entry *procDir;
|
|
||||||
|
|
||||||
/** a proc dir entry for each of the properties of the object;
|
|
||||||
* properties are identified in MYPROCTYPE.propertyNames, so each of
|
|
||||||
* the <procDirProperties> describes a single file like
|
|
||||||
* <type.procDirRoot>/<type.name[0]>/<type.name[1]>/...
|
|
||||||
* /<name>/<propertyName>
|
|
||||||
*/
|
|
||||||
struct proc_dir_entry **procDirProperties;
|
|
||||||
|
|
||||||
/** this is a holding area for the context information that is needed
|
|
||||||
* to run the /proc callback function */
|
|
||||||
struct proc_dir_entry_context *procDirPropertyContexts;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static struct proc_dir_entry *
|
|
||||||
createProcDir(const char *name, struct proc_dir_entry *parent)
|
|
||||||
{
|
|
||||||
struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct proc_dir_entry *
|
|
||||||
createProcFile(const char *name, struct proc_dir_entry *parent,
|
|
||||||
const struct file_operations *fops, void *data)
|
|
||||||
{
|
|
||||||
struct proc_dir_entry *p = proc_create_data(name, 0, parent,
|
|
||||||
fops, data);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int seq_show(struct seq_file *seq, void *offset);
|
|
||||||
static int proc_open(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, seq_show, PDE_DATA(inode));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations proc_fops = {
|
|
||||||
.open = proc_open,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MYPROCTYPE *visor_proc_CreateType(struct proc_dir_entry *procDirRoot,
|
|
||||||
const char **name,
|
|
||||||
const char **propertyNames,
|
|
||||||
void (*show_property)(struct seq_file *,
|
|
||||||
void *, int))
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
MYPROCTYPE *rc = NULL, *type = NULL;
|
|
||||||
struct proc_dir_entry *parent = NULL;
|
|
||||||
|
|
||||||
if (procDirRoot == NULL)
|
|
||||||
goto Away;
|
|
||||||
|
|
||||||
if (name == NULL || name[0] == NULL)
|
|
||||||
goto Away;
|
|
||||||
|
|
||||||
type = kzalloc(sizeof(MYPROCTYPE), GFP_KERNEL | __GFP_NORETRY);
|
|
||||||
if (type == NULL)
|
|
||||||
goto Away;
|
|
||||||
|
|
||||||
type->name = name;
|
|
||||||
type->propertyNames = propertyNames;
|
|
||||||
type->nProperties = 0;
|
|
||||||
type->nNames = 0;
|
|
||||||
type->show_property = show_property;
|
|
||||||
type->procDirRoot = procDirRoot;
|
|
||||||
if (type->propertyNames != NULL)
|
|
||||||
while (type->propertyNames[type->nProperties] != NULL)
|
|
||||||
type->nProperties++;
|
|
||||||
while (type->name[type->nNames] != NULL)
|
|
||||||
type->nNames++;
|
|
||||||
type->procDirs = kcalloc((type->nNames + 1),
|
|
||||||
sizeof(struct proc_dir_entry *),
|
|
||||||
GFP_KERNEL | __GFP_NORETRY);
|
|
||||||
if (type->procDirs == NULL)
|
|
||||||
goto Away;
|
|
||||||
parent = procDirRoot;
|
|
||||||
for (i = 0; i < type->nNames; i++) {
|
|
||||||
type->procDirs[i] = createProcDir(type->name[i], parent);
|
|
||||||
if (type->procDirs[i] == NULL) {
|
|
||||||
rc = NULL;
|
|
||||||
goto Away;
|
|
||||||
}
|
|
||||||
parent = type->procDirs[i];
|
|
||||||
}
|
|
||||||
type->procDir = type->procDirs[type->nNames-1];
|
|
||||||
rc = type;
|
|
||||||
Away:
|
|
||||||
if (rc == NULL) {
|
|
||||||
if (type != NULL) {
|
|
||||||
visor_proc_DestroyType(type);
|
|
||||||
type = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_proc_CreateType);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_proc_DestroyType(MYPROCTYPE *type)
|
|
||||||
{
|
|
||||||
if (type == NULL)
|
|
||||||
return;
|
|
||||||
if (type->procDirs != NULL) {
|
|
||||||
int i = type->nNames-1;
|
|
||||||
|
|
||||||
while (i >= 0) {
|
|
||||||
if (type->procDirs[i] != NULL) {
|
|
||||||
struct proc_dir_entry *parent = NULL;
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
parent = type->procDirRoot;
|
|
||||||
else
|
|
||||||
parent = type->procDirs[i-1];
|
|
||||||
remove_proc_entry(type->name[i], parent);
|
|
||||||
}
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
kfree(type->procDirs);
|
|
||||||
type->procDirs = NULL;
|
|
||||||
}
|
|
||||||
kfree(type);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_proc_DestroyType);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type,
|
|
||||||
const char *name, void *context)
|
|
||||||
{
|
|
||||||
MYPROCOBJECT *obj = NULL, *rc = NULL;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (type == NULL)
|
|
||||||
goto Away;
|
|
||||||
|
|
||||||
obj = kzalloc(sizeof(MYPROCOBJECT), GFP_KERNEL | __GFP_NORETRY);
|
|
||||||
if (obj == NULL)
|
|
||||||
goto Away;
|
|
||||||
|
|
||||||
obj->type = type;
|
|
||||||
obj->context = context;
|
|
||||||
if (name == NULL) {
|
|
||||||
obj->name = NULL;
|
|
||||||
obj->procDir = type->procDir;
|
|
||||||
} else {
|
|
||||||
obj->namesize = strlen(name)+1;
|
|
||||||
obj->name = kmalloc(obj->namesize, GFP_KERNEL | __GFP_NORETRY);
|
|
||||||
if (obj->name == NULL) {
|
|
||||||
obj->namesize = 0;
|
|
||||||
goto Away;
|
|
||||||
}
|
|
||||||
strcpy(obj->name, name);
|
|
||||||
obj->procDir = createProcDir(obj->name, type->procDir);
|
|
||||||
if (obj->procDir == NULL)
|
|
||||||
goto Away;
|
|
||||||
}
|
|
||||||
obj->procDirPropertyContexts =
|
|
||||||
kcalloc((type->nProperties + 1),
|
|
||||||
sizeof(struct proc_dir_entry_context),
|
|
||||||
GFP_KERNEL | __GFP_NORETRY);
|
|
||||||
if (obj->procDirPropertyContexts == NULL)
|
|
||||||
goto Away;
|
|
||||||
obj->procDirProperties = kcalloc((type->nProperties + 1),
|
|
||||||
sizeof(struct proc_dir_entry *),
|
|
||||||
GFP_KERNEL | __GFP_NORETRY);
|
|
||||||
if (obj->procDirProperties == NULL)
|
|
||||||
goto Away;
|
|
||||||
for (i = 0; i < type->nProperties; i++) {
|
|
||||||
obj->procDirPropertyContexts[i].procObject = obj;
|
|
||||||
obj->procDirPropertyContexts[i].propertyIndex = i;
|
|
||||||
obj->procDirPropertyContexts[i].show_property =
|
|
||||||
type->show_property;
|
|
||||||
if (type->propertyNames[i][0] != '\0') {
|
|
||||||
/* only create properties that have names */
|
|
||||||
obj->procDirProperties[i] =
|
|
||||||
createProcFile(type->propertyNames[i],
|
|
||||||
obj->procDir, &proc_fops,
|
|
||||||
&obj->procDirPropertyContexts[i]);
|
|
||||||
if (obj->procDirProperties[i] == NULL) {
|
|
||||||
rc = NULL;
|
|
||||||
goto Away;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc = obj;
|
|
||||||
Away:
|
|
||||||
if (rc == NULL) {
|
|
||||||
if (obj != NULL) {
|
|
||||||
visor_proc_DestroyObject(obj);
|
|
||||||
obj = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_proc_CreateObject);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visor_proc_DestroyObject(MYPROCOBJECT *obj)
|
|
||||||
{
|
|
||||||
MYPROCTYPE *type = NULL;
|
|
||||||
|
|
||||||
if (obj == NULL)
|
|
||||||
return;
|
|
||||||
type = obj->type;
|
|
||||||
if (type == NULL)
|
|
||||||
return;
|
|
||||||
if (obj->procDirProperties != NULL) {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < type->nProperties; i++) {
|
|
||||||
if (obj->procDirProperties[i] != NULL) {
|
|
||||||
remove_proc_entry(type->propertyNames[i],
|
|
||||||
obj->procDir);
|
|
||||||
obj->procDirProperties[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree(obj->procDirProperties);
|
|
||||||
obj->procDirProperties = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(obj->procDirPropertyContexts);
|
|
||||||
obj->procDirPropertyContexts = NULL;
|
|
||||||
|
|
||||||
if (obj->procDir != NULL) {
|
|
||||||
if (obj->name != NULL)
|
|
||||||
remove_proc_entry(obj->name, type->procDir);
|
|
||||||
obj->procDir = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(obj->name);
|
|
||||||
obj->name = NULL;
|
|
||||||
kfree(obj);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(visor_proc_DestroyObject);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int seq_show(struct seq_file *seq, void *offset)
|
|
||||||
{
|
|
||||||
struct proc_dir_entry_context *ctx = seq->private;
|
|
||||||
|
|
||||||
if (ctx == NULL)
|
|
||||||
return 0;
|
|
||||||
(*ctx->show_property)(seq, ctx->procObject->context,
|
|
||||||
ctx->propertyIndex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user