Where is struct lws_context defined? - libwebsockets

I am new to libwebsocket and I have code to analyse. I could not find where is struct lws_context defined.
Can any one help me.

If you are searching through the /usr/include folder for the definition of lws_context you won't find it (I also did a quick search on their public doxygen and didn't find a definition there either...). However you can find its definition in their git repo (link on their site here: https://libwebsockets.org/). It is in the following file: lib/core/private-lib-core.h. It is worth mentioning that this is obviously subject to change in the future. For quick reference here is the definition you are looking for:
struct lws_context {
#if defined(LWS_WITH_SERVER)
char canonical_hostname[96];
#endif
#if defined(LWS_WITH_FILE_OPS)
struct lws_plat_file_ops fops_platform;
#endif
#if defined(LWS_WITH_ZIP_FOPS)
struct lws_plat_file_ops fops_zip;
#endif
lws_system_blob_t system_blobs[LWS_SYSBLOB_TYPE_COUNT];
#if defined(LWS_WITH_SYS_SMD)
lws_smd_t smd;
#endif
#if defined(LWS_WITH_SECURE_STREAMS)
struct lws_ss_handle *ss_cpd;
#endif
lws_sorted_usec_list_t sul_cpd_defer;
#if defined(LWS_WITH_NETWORK)
struct lws_context_per_thread pt[LWS_MAX_SMP];
lws_retry_bo_t default_retry;
lws_sorted_usec_list_t sul_system_state;
lws_lifecycle_group_t lcg[LWSLCG_COUNT];
#if defined(LWS_WITH_NETLINK)
lws_sorted_usec_list_t sul_nl_coldplug;
#endif
#if defined(LWS_PLAT_FREERTOS) || defined(WIN32)
struct sockaddr_in frt_pipe_si;
#endif
#if defined(LWS_WITH_HTTP2)
struct http2_settings set;
#endif
#if LWS_MAX_SMP > 1
struct lws_mutex_refcount mr;
#endif
#if defined(LWS_WITH_SYS_METRICS)
lws_dll2_owner_t owner_mtr_dynpol;
/**< owner for lws_metric_policy_dyn_t (dynamic part of metric pols) */
lws_dll2_owner_t owner_mtr_no_pol;
/**< owner for lws_metric_pub_t with no policy to bind to */
#endif
#if defined(LWS_WITH_NETWORK)
/*
* LWS_WITH_NETWORK =====>
*/
lws_dll2_owner_t owner_vh_being_destroyed;
lws_metric_t *mt_service; /* doing service */
const lws_metric_policy_t *metrics_policies;
const char *metrics_prefix;
#if defined(LWS_WITH_SYS_METRICS) && defined(LWS_WITH_CLIENT)
lws_metric_t *mt_conn_tcp; /* client tcp conns */
lws_metric_t *mt_conn_tls; /* client tcp conns */
lws_metric_t *mt_conn_dns; /* client dns external lookups */
lws_metric_t *mth_conn_failures; /* histogram of conn failure reasons */
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
lws_metric_t *mt_http_txn; /* client http transaction */
#endif
#if defined(LWS_WITH_SYS_ASYNC_DNS)
lws_metric_t *mt_adns_cache; /* async dns lookup lat */
#endif
#if defined(LWS_WITH_SECURE_STREAMS)
lws_metric_t *mt_ss_conn; /* SS connection latency */
#endif
#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
lws_metric_t *mt_ss_cliprox_conn; /* SS cli->prox conn */
lws_metric_t *mt_ss_cliprox_paylat; /* cli->prox payload latency */
lws_metric_t *mt_ss_proxcli_paylat; /* prox->cli payload latency */
#endif
#endif /* client */
#if defined(LWS_WITH_SERVER)
lws_metric_t *mth_srv;
#endif
#if defined(LWS_WITH_EVENT_LIBS)
struct lws_plugin *evlib_plugin_list;
void *evlib_ctx; /* overallocated */
#endif
#if defined(LWS_WITH_TLS)
struct lws_context_tls tls;
#endif
#if defined(LWS_WITH_DRIVERS)
lws_netdevs_t netdevs;
#endif
#if defined(LWS_WITH_SYS_ASYNC_DNS)
lws_async_dns_t async_dns;
#endif
#if defined(LWS_WITH_SYS_NTPCLIENT)
void *ntpclient_priv;
#endif
#if defined(LWS_WITH_SECURE_STREAMS)
struct lws_ss_handle *hss_fetch_policy;
#if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM)
struct lws_ss_handle *hss_auth;
lws_sorted_usec_list_t sul_api_amazon_com;
lws_sorted_usec_list_t sul_api_amazon_com_kick;
#endif
#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
struct lws_ss_x509 *server_der_list;
#endif
#endif
#if defined(LWS_WITH_SYS_STATE)
lws_state_manager_t mgr_system;
lws_state_notify_link_t protocols_notify;
#endif
#if defined (LWS_WITH_SYS_DHCP_CLIENT)
lws_dll2_owner_t dhcpc_owner;
/**< list of ifaces with dhcpc */
#endif
/* pointers */
struct lws_vhost *vhost_list;
struct lws_vhost *no_listener_vhost_list;
struct lws_vhost *vhost_pending_destruction_list;
struct lws_vhost *vhost_system;
#if defined(LWS_WITH_SERVER)
const char *server_string;
#endif
const struct lws_event_loop_ops *event_loop_ops;
#endif
#if defined(LWS_WITH_TLS)
const struct lws_tls_ops *tls_ops;
#endif
#if defined(LWS_WITH_PLUGINS)
struct lws_plugin *plugin_list;
#endif
#ifdef _WIN32
/* different implementation between unix and windows */
struct lws_fd_hashtable fd_hashtable[FD_HASHTABLE_MODULUS];
#else
struct lws **lws_lookup;
#endif
/*
* <====== LWS_WITH_NETWORK end
*/
#endif /* NETWORK */
#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
const char *ss_proxy_bind;
const char *ss_proxy_address;
#endif
#if defined(LWS_WITH_FILE_OPS)
const struct lws_plat_file_ops *fops;
#endif
struct lws_context **pcontext_finalize;
#if !defined(LWS_PLAT_FREERTOS)
const char *username, *groupname;
#endif
#if defined(LWS_AMAZON_RTOS) && defined(LWS_WITH_MBEDTLS)
mbedtls_entropy_context mec;
mbedtls_ctr_drbg_context mcdc;
#endif
#if defined(LWS_WITH_THREADPOOL)
struct lws_threadpool *tp_list_head;
#endif
#if defined(LWS_WITH_PEER_LIMITS)
struct lws_peer **pl_hash_table;
struct lws_peer *peer_wait_list;
lws_peer_limits_notify_t pl_notify_cb;
time_t next_cull;
#endif
const lws_system_ops_t *system_ops;
#if defined(LWS_WITH_SECURE_STREAMS)
#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
const char *pss_policies_json;
struct lwsac *ac_policy;
void *pol_args;
#endif
const lws_ss_policy_t *pss_policies;
const lws_ss_auth_t *pss_auths;
#if defined(LWS_WITH_SSPLUGINS)
const lws_ss_plugin_t **pss_plugins;
#endif
#endif
void *external_baggage_free_on_destroy;
const struct lws_token_limits *token_limits;
void *user_space;
#if defined(LWS_WITH_SERVER)
const struct lws_protocol_vhost_options *reject_service_keywords;
lws_reload_func deprecation_cb;
#endif
#if !defined(LWS_PLAT_FREERTOS)
void (*eventlib_signal_cb)(void *event_lib_handle, int signum);
#endif
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
cap_value_t caps[4];
char count_caps;
#endif
lws_usec_t time_up; /* monotonic */
uint64_t options;
time_t last_ws_ping_pong_check_s;
#if defined(LWS_WITH_SECURE_STREAMS)
time_t last_policy;
#endif
#if defined(LWS_PLAT_FREERTOS)
unsigned long time_last_state_dump;
uint32_t last_free_heap;
#endif
unsigned int max_fds;
#if !defined(LWS_NO_DAEMONIZE)
pid_t started_with_parent;
#endif
#if !defined(LWS_PLAT_FREERTOS)
uid_t uid;
gid_t gid;
int fd_random;
int count_cgi_spawned;
#endif
unsigned int fd_limit_per_thread;
unsigned int timeout_secs;
unsigned int pt_serv_buf_size;
unsigned int max_http_header_data;
unsigned int max_http_header_pool;
int simultaneous_ssl_restriction;
int simultaneous_ssl;
#if defined(LWS_WITH_PEER_LIMITS)
uint32_t pl_hash_elements; /* protected by context->lock */
uint32_t count_peers; /* protected by context->lock */
unsigned short ip_limit_ah;
unsigned short ip_limit_wsi;
#endif
unsigned int deprecated:1;
unsigned int inside_context_destroy:1;
unsigned int being_destroyed:1;
unsigned int service_no_longer_possible:1;
unsigned int being_destroyed2:1;
unsigned int requested_stop_internal_loops:1;
unsigned int protocol_init_done:1;
unsigned int doing_protocol_init:1;
unsigned int done_protocol_destroy_cb:1;
unsigned int evlib_finalize_destroy_after_int_loops_stop:1;
unsigned int max_fds_unrelated_to_ulimit:1;
unsigned int policy_updated:1;
#if defined(LWS_WITH_NETLINK)
unsigned int nl_initial_done:1;
#endif
unsigned short count_threads;
unsigned short undestroyed_threads;
short plugin_protocol_count;
short plugin_extension_count;
short server_string_len;
unsigned short deprecation_pending_listen_close_count;
#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
uint16_t ss_proxy_port;
#endif
/* 0 if not known, else us resolution of the poll wait */
uint16_t us_wait_resolution;
uint8_t max_fi;
uint8_t udp_loss_sim_tx_pc;
uint8_t udp_loss_sim_rx_pc;
uint8_t captive_portal_detect;
uint8_t captive_portal_detect_type;
uint8_t destroy_state; /* enum lws_context_destroy */
};

Related

Can different algorithm be used in Realm encryption(other than AES-256)?

There is default support for AES-256 in Realm but can we change encryption algorithm to other than AES-256??
Short Answer: No, it is not a dynamically pluggable system.
The AES Encryption is baked into realm-core, the shared C++ library, at compile time and uses the various platform crypto features available (OS / hardware-based). It is open source, so in theory you could write a different provider and handle changes to methods like realm::util::encryption_read_barrier and realm::util::encryption_write_barrier as needed... or possibly do a paid contract with Realm based upon your custom encryption requirements.
Re: https://github.com/realm/realm-core/blob/master/src/realm/util/aes_cryptor.hpp
class AESCryptor {
public:
AESCryptor(const uint8_t* key);
~AESCryptor() noexcept;
void set_file_size(off_t new_size);
bool read(FileDesc fd, off_t pos, char* dst, size_t size);
void write(FileDesc fd, off_t pos, const char* src, size_t size) noexcept;
private:
enum EncryptionMode {
#if REALM_PLATFORM_APPLE
mode_Encrypt = kCCEncrypt,
mode_Decrypt = kCCDecrypt
#elif defined(_WIN32)
mode_Encrypt = 0,
mode_Decrypt = 1
#else
mode_Encrypt = AES_ENCRYPT,
mode_Decrypt = AES_DECRYPT
#endif
};
#if REALM_PLATFORM_APPLE
CCCryptorRef m_encr;
CCCryptorRef m_decr;
#elif defined(_WIN32)
BCRYPT_KEY_HANDLE m_aes_key_handle;
#else
AES_KEY m_ectx;
AES_KEY m_dctx;
#endif
uint8_t m_hmacKey[32];
std::vector<iv_table> m_iv_buffer;
std::unique_ptr<char[]> m_rw_buffer;
std::unique_ptr<char[]> m_dst_buffer;
void calc_hmac(const void* src, size_t len, uint8_t* dst, const uint8_t* key) const;
bool check_hmac(const void* data, size_t len, const uint8_t* hmac) const;
void crypt(EncryptionMode mode, off_t pos, char* dst, const char* src, const char* stored_iv) noexcept;
iv_table& get_iv_table(FileDesc fd, off_t data_pos) noexcept;
};

Broadcast[UDP] sendto Error on Mac (Code works in Win fine!)

i have a Problem with a Broadcast on MAC using c++ 11
The Code works fine in Windows but on Mac i get a -1 back from my sendto function, maybe u see my error.
#ifdef _WIN32
SOCKET s;
#endif
int recSocket = socket(AF_INET, SOCK_DGRAM, 0);
int askSinlen = sizeof(struct sockaddr_in);
ssize_t askBuflen = MAXBUF;
int recCheckCall;
#ifdef _WIN32
int clientLength;
#elif __APPLE__
socklen_t clientLength;
#endif
int message;
char buf[512];
char askStatus;
char status;
char askBuffer[MAXBUF];
struct sockaddr_in sock_in, server_adress, client_adress, client_adress2;
char askYes = 1;
DEBUG_LOG(35, "Im Boradcast");
#ifdef _WIN32
WSADATA w;
if (int result = WSAStartup(MAKEWORD(2, 2), &w) != 0) // Zugriff auf Winsock Libary
{
DEBUG_LOG(300, "WSA Startup failed");
return -1;
}
#endif
recSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (recSocket == -1)
{
DEBUG_LOG(301, "Receive Socket Error");
#ifdef _WIN32
closesocket(recSocket);
#elif __APPLE__
close(recSocket);
#endif
return -2;
}
sock_in.sin_addr.s_addr = htonl(INADDR_ANY);
sock_in.sin_port = htons(4028);
sock_in.sin_family = PF_INET;
client_adress.sin_family = PF_INET;
client_adress.sin_port = htons(4029);
client_adress.sin_addr.s_addr = htonl(-1);
status = bind(recSocket, (struct sockaddr *)&sock_in, askSinlen);
if (status == -1)
{
DEBUG_LOG(302, "Fehler beim binden des Sockets");
#ifdef _WIN32
closesocket(recSocket);
#elif __APPLE__
close(recSocket);
#endif
return -3;
}
status = setsockopt(recSocket, SOL_SOCKET, SO_BROADCAST, &askYes, sizeof(askYes));
sprintf(askBuffer, "Ciao");
askBuflen = strlen(askBuffer);
status = sendto(recSocket, askBuffer, askBuflen, 0, (struct sockaddr *)&client_adress, sizeof(client_adress));
if (status < 0)
{
DEBUG_LOG(status, "Fehler ist: ");
DEBUG_LOG(303, "Fehler beim senden des Broadcastes");
#ifdef _WIN32
closesocket(recSocket);
#elif __APPLE__
close(recSocket);
#endif
return -4;
}
It would be great if u could help me, i think its just a small bug wich i didnt see...
Have a nice day
Kindly Regards

device_create(...) argument 'void * drvdata'

The function
struct device * device_create ( struct class * class,
struct device * parent,
dev_t devt,
void * drvdata,
const char * fmt,
...);
[link to documentation] takes an argument "void * drvdata". It is described as "the data to be added to the device for callbacks". What callbacks exactly are meant here? The file-operation-functions?
SysFS is one example of where this could be useful: whenever userspace communicates with the driver using SysFS (see "Reading/Writing Attribute Data" in the documentation), the kernel calls the corresponding callbacks. The void * drvdata pointer supplied during device_create can then be obtained by calling dev_get_drvdata(dev). The pointer could be used to refer to a structure containing driver's state for example.
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/device.h>
#include <linux/err.h>
MODULE_LICENSE("GPL");
static ssize_t show_period(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t set_period(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count);
static DEVICE_ATTR(period, S_IWUSR | S_IRUSR, show_period, set_period);
static struct device *s_pDeviceObject;
static struct class *s_pDeviceClass;
static struct pwm_device_state
{
int m_Period;
} s_DeviceState;
static int __init pwmdriver_init(void)
{
int result;
s_pDeviceClass = class_create(THIS_MODULE, "pwmdriver");
BUG_ON(IS_ERR(s_pDeviceClass));
s_pDeviceObject = device_create(s_pDeviceClass, NULL, 0, &s_DeviceState, "channel");
result = device_create_file(s_pDeviceObject, &dev_attr_period);
BUG_ON(result < 0);
return result;
}
static ssize_t show_period(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pwm_device_state *pwm_device_data;
pwm_device_data = dev_get_drvdata(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", pwm_device_data->m_Period);
}
static ssize_t set_period(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
long period_value = 0;
struct pwm_device_state *pwm_device_data;
if (kstrtol(buf, 10, &period_value) < 0)
return -EINVAL;
if (period_value < 10) //Safety check
return -EINVAL;
pwm_device_data = dev_get_drvdata(dev);
pwm_device_data->m_Period = period_value;
return count;
}
static void __exit pwmdriver_exit(void)
{
device_remove_file(s_pDeviceObject, &dev_attr_period);
device_destroy(s_pDeviceClass, 0);
class_destroy(s_pDeviceClass);
}
module_init(pwmdriver_init);
module_exit(pwmdriver_exit);

Error C2491: Function declared in header and defined in C++

I have been trying to build a device adapter for a open-source software called Micro-manager to control a microscope and there are some problems that I am facing, there are these two files (one header and the other CPP) that are already present in the open source package of Micro-Manager.
//MoudluleInterface.h
#ifndef _MODULE_INTERFACE_H_
#define _MODULE_INTERFACE_H_
#ifdef WIN32
#ifdef MODULE_EXPORTS
#define MODULE_API __declspec(dllexport)
#else
#define MODULE_API __declspec(dllimport)
#endif
#else
#define MODULE_API
#endif
#define MM_MODULE_ERR_OK 1000
#define MM_MODULE_ERR_WRONG_INDEX 1001
#define MM_MODULE_ERR_BUFFER_TOO_SMALL 1002
///////////////////////////////////////////////////////////////////////////////
// header version
// NOTE: If any of the exported module API calls changes, the interface version
// must be incremented
// new version 5 supports device discoverability
#define MODULE_INTERFACE_VERSION 7
#ifdef WIN32
const char* const LIB_NAME_PREFIX = "mmgr_dal_";
#else
const char* const LIB_NAME_PREFIX = "libmmgr_dal_";
#endif
#include "MMDevice.h"
///////////////////////////////////////////////////////////////////////////////
// Exported module interface
///////////////////////////////////////////////////////////////////////////////
extern "C" {
MODULE_API MM::Device* CreateDevice(const char* name);
MODULE_API void DeleteDevice(MM::Device* pDevice);
MODULE_API long GetModuleVersion();
MODULE_API long GetDeviceInterfaceVersion();
MODULE_API unsigned GetNumberOfDevices();
MODULE_API bool GetDeviceName(unsigned deviceIndex, char* name, unsigned bufferLength);
MODULE_API bool GetDeviceDescription(const char* deviceName, char* name, unsigned bufferLength);
And here is a part of the CPP file which defines these functions
//ModuleInterface.cpp
#define _CRT_SECURE_NO_DEPRECATE
#include "ModuleInterface.h"
#include <vector>
#include <string>
typedef std::pair<std::string, std::string> DeviceInfo;
std::vector<DeviceInfo> g_availableDevices;
int FindDeviceIndex(const char* deviceName)
{
for (unsigned i=0; i<g_availableDevices.size(); i++)
if (g_availableDevices[i].first.compare(deviceName) == 0)
return i;
return -1;
}
MODULE_API long GetModuleVersion()
{
return MODULE_INTERFACE_VERSION;
}
MODULE_API long GetDeviceInterfaceVersion()
{
return DEVICE_INTERFACE_VERSION;
}
MODULE_API unsigned GetNumberOfDevices()
{
return (unsigned) g_availableDevices.size();
}
MODULE_API bool GetDeviceName(unsigned deviceIndex, char* name, unsigned bufLen)
{
if (deviceIndex >= g_availableDevices.size())
return false;
Now the problem is it gives me an error C2491 (definition of dllimport function not allowed)
I did research about this and it usually is when a function is defined when it is supposed to be declared, I have already defined the function in ModuleInterface.h and then used it in ModuleInterface.cpp but it still shows the same error.
Can there be some other possibility for this error to occur? Or is there something wrong with the code?
You're not supposed to repeat your MODULE_API declaration in the definition, having it as part of the declaration is good enough. Remove the use of MODULE_API from the .cpp file and the code should compile.

How to create proc entry under /proc/driver?

I want to create a file under a /proc/driver directory. I would like to use a macro like proc_root_driver (or something else provided) rather than use "driver/MODULE_NAME" explicitly. I use create_proc_entry :
struct proc_dir_entry *simpleproc_fops_entry;
simpleproc_fops_entry = create_proc_entry(MODULE_NAME, 0400, NULL /* proc_root_dir */);
After googling, I found suggestion to use proc_root_driver, but when I use it, I get the error
proc_root_driver undeclared in this function
And also, proc_root_driver is not available in linux/proc_fs.h.
I have tried to declare structure like this:
struct proc_dir_entry proc_root;
struct proc_dir_entry *proc_root_driver = &proc_root;
The compilation errors gone, but the file didn't appear under /proc/driver or /proc. How can I make create an entry in /proc?
Looking at proc_fs.h, proc_root_driver is defined as :
extern struct proc_dir_entry *proc_root_driver;
so long as CONFIG_PROC_FS is enabled. If you have CONFIG_PROC_FS selected when you configure your kernel, you should be able to use it as you suggested yourself i.e. :
#include <linux/proc_fs.h>
struct proc_dir_entry * procfile
procfile = create_proc_entry("myprocfile", 0400, proc_root_driver);
If this does not work, check that you have CONFIG_PROC_FS set. To make sure, you can compile your source file with the -E option and check that the create_proc_entry call includes a non NULL parameter as the last parameter. If it is NULL, or the call is not there at all, then CONFIG_PROC_FS is not enabled.
/* proc entries for ayyaz */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/err.h>
#include <linux/ioctl.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#ifdef CONFIG_PROC_FS
/*====================================================================*/
/* Support for /proc/ayyaz */
static struct proc_dir_entry *proc_ayyaz;
DEFINE_MUTEX(ayyaz_table_mutex);
/*====================================================================*/
/* Init code */
static int ayyaz_read_proc (char *page, char **start, off_t off, int count,
int *eof, void *data_unused)
{
int len, l, i;
off_t begin = 0;
mutex_lock(&ayyaz_table_mutex);
len = sprintf(page, "hello ayyaz here\n");
mutex_unlock(&ayyaz_table_mutex);
if (off >= len+begin)
return 0;
*start = page + (off-begin);
return ((count < begin+len-off) ? count : begin+len-off);
}
static int __init init_ayyaz(void)
{
if ((proc_ayyaz = create_proc_entry( "ayyaz_maps", 0, NULL )))
proc_ayyaz->read_proc = ayyaz_read_proc;
return 0;
}
static void __exit cleanup_ayyaz(void)
{
if (proc_ayyaz)
remove_proc_entry( "ayyaz", NULL);
}
module_init(init_ayyaz);
module_exit(cleanup_ayyaz);
#else
#error "Please add CONFIG_PROC_FS=y in your .config "
#endif /* CONFIG_PROC_FS */
MODULE_LICENSE("proprietary");
MODULE_AUTHOR("Md.Ayyaz A Mulla <md.ayyaz#gmail.com>");
MODULE_DESCRIPTION("proc files for ayyaz");
Compile this driver. If it compiles sucessfully, then you will see /proc/ayyaz.
#define PROC_ENTRY_NAME "driver/XX"
static struct proc_dir_entry *proc_XX;
static int XX_read_proc (char *page, char **start, off_t off, int count,
int *eof, void *data_unused)
{
return 0;
}
static int XX_write_proc (struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
return 0;
}
static int __init XX_add_driver(void)
{
if ((proc_flash = XX_entry(PROC_ENTRY_NAME, 0, NULL))) {
proc_XX->read_proc = XX_read_proc;
proc_XX->write_proc = XX_write_proc;
}
...
}
static void __exit XX_remove(void)
{
if (proc_flash)
remove_proc_entry(PROC_ENTRY_NAME, NULL);
return;
}
Then you can find the /proc/driver/XX entry.

Resources