코드를 분석 하자.


일단 moused.h



#ifndef MOUSED_H

#define MOUSED_H


#include <syslog.h>


struct rodentparam;

typedef struct rodentparam rodent_t;


struct rodentparam {

char *device;

char *modulename;

char *configfile;

int cfd;            /* /dev/consolectl fd */

int mfd;            /* mouse device fd */


mousemode_t mode;

mousehw_t hw;

mouse_info_t state;


char *packet;    /* Used repeatedly by a plugin, keep it here */


/* Modules will call this to pass deltas to sysmouse(4) */

int (*update)(struct mouse_info *);

void (*logmsg)(int, int, const char *, ...);


/* Module callbacks (called by moused) */

int (*init)(rodent_t *, int, char **);

int (*probe)(rodent_t *);

void (*run)(rodent_t *);                /* for standalone mode */


void (*handler)(rodent_t *);            /* for packet-handler mode */

void (*handler_init)(rodent_t *);       /* for packet-handler init*/


void (*timeout)(rodent_t *);            /* select(2) timeouts call this 

 * when in handler mode */

};


#define MOUSED_INIT_FUNC  int init(rodent_t *rodent, int argc, char **argv)

#define MOUSED_PROBE_FUNC int probe(rodent_t *rodent)

#define MOUSED_HANDLER_FUNC void handler(rodent_t *rodent)

#define MOUSED_HANDLER_INIT_FUNC void handler_init(rodent_t *rodent)


/*

 * *** XXX:DEPRECATED ***

 * Should this (RUN) method even be allowed? Is it useful to have the plugin 

 * handle things like select(2) calls and such?

 */

#define MOUSED_RUN_FUNC   void run(rodent_t *rodent)


/* Probe function return values */

#define MODULE_PROBE_FAIL    0

#define MODULE_PROBE_SUCCESS 1


/* Bit math, helpful for modules */

#define BIT(num, bit) (((num) & (1 << (bit - 1))) ? 1 : 0)

#define NBIT(num, bit) ((BIT(num,bit)) ^ 1)


#define logfatal(e, fmt, args...) do {                         \

logmsg(LOG_DAEMON | LOG_ERR, errno, fmt, ##args);           \

exit(e);                                                    \

} while (0)


#endif




moused.c

/* 
 * new moused
 *
 * $Id$
 */

#include <sys/cdefs.h>
__FBSDID("Happy Cakes!");

#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/select.h>

/* sysmouse stuff */
#include <sys/mouse.h>
#include <sys/consio.h>

#include "moused.h"

static int verbose = 0;

static void logmsg(int log_pri, int errnum, const char *fmt, ...);
static int moused(int argc, char **argv);

/* Load a module into memory (dlopen, etc) */
static void loadmodule(char *path);

/* Modules will call this function when the mouse moves/changes */
static int update(mouse_info_t *delta);

/* Filter the input somehow? */
static void filter(mouse_info_t *delta, int noop);

static void packethandler_main();
void dumpstate(mouse_info_t *delta);

#define debug(level, fmt, args...) do {                        \
if (level <= verbose)                                       \
warnx(fmt, ##args);                                      \
} while (0)

#define MOUSED_OPTIONS "d:m:f:"

static rodent_t rodent = {
.device = NULL,
.modulename = NULL,
.configfile = "/etc/moused.conf",
.cfd = -1,
.mfd = -1,
.update = update, /* Modules call moused's update(...) to talk to sysmouse */
.logmsg = logmsg, /* Modules call moused's logmsg(...) log stuff */

.init = NULL,
.probe = NULL,
.run = NULL,

.handler = NULL,
};

int main(int argc, char **argv) {
int c;

while (-1 != (c = getopt(argc, argv, MOUSED_OPTIONS))) {
switch (c) {
case 'd':
rodent.device = optarg; break;
case 'm':
rodent.modulename = optarg; break;
case 'f':
rodent.configfile = optarg; break;
}
}

argc -= optind;
argv += optind;

if (NULL == rodent.device)
rodent.device = "/dev/psm0";

moused(argc, argv);

return 0;
}

int moused(int argc, char **argv) {
struct mouse_info mouse;

if (-1 == (rodent.cfd = open("/dev/consolectl", O_RDWR, 0))) {
logfatal(1, "Unable to open /dev/consolectl");
}

if (NULL != rodent.modulename) {
char path[256];
snprintf(path, 256, "modules/%s/libmoused_%s.so", 
rodent.modulename, rodent.modulename);
printf("Path: %s\n", path);
loadmodule(path);

if (NULL != rodent.init) {
/* Reset getopt stuffs (do it in case init() likes to use getopt) */
optreset = 1;
optind = 0;
rodent.init(&rodent, argc, argv);
}

if (NULL == rodent.probe)
logfatal(1, "Module '%s' has no PROBE function?!", rodent.modulename);

/* Check if this module is the right module for this mouse device */
if (rodent.probe(&rodent) == MODULE_PROBE_SUCCESS) {

/* Try the RUN method first */
//if (NULL != rodent.run)
//rodent.run(&rodent);
/* else */ if (NULL != rodent.handler)
packethandler_main();
else 
logfatal(1, "Module '%s' has no RUN function?!", rodent.modulename);

/* If we _EVER_ get here, something hs wrong */
warnx("Arrived at unexpected location (RUN or PACKETHANDLER method died?)");
}
} else {
warnx("No module selected.");
exit(1);
}
}

static void logmsg(int log_pri, int errnum, const char *fmt, ...) {
va_list ap;
char buf[256];

va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);

if (errnum) {
strlcat(buf, ": ", sizeof(buf));
strlcat(buf, strerror(errnum), sizeof(buf));
}

/* Syslog if we're in the background? */
warnx("%s", buf);
}

static void loadmodule(char *path) {
void *handle;

if (NULL == (handle = dlopen(path, RTLD_LAZY))) {
logfatal(1, "Unable open module '%s'.", rodent.modulename);
}

rodent.init = dlsym(handle, "init");
rodent.probe = dlsym(handle, "probe");
rodent.run = dlsym(handle, "run");
rodent.handler = dlsym(handle, "handler");
rodent.handler_init = dlsym(handle, "handler_init");
}

static int update(mouse_info_t *delta) {
mouse_info_t mydelta;

/* Store state and copy delta into mydelta if this isn't a no-op */
if (NULL != delta) {
memcpy(&mydelta, delta, sizeof(mouse_info_t));
memcpy(&(rodent.state), delta, sizeof(mouse_info_t));
}
else {
memset(&mydelta, 0, sizeof(mouse_info_t));
}

filter(&mydelta, (NULL == delta) ? 1 : 0);
return ioctl(rodent.cfd, CONS_MOUSECTL, &mydelta);
}

static int state = 0;
static int distance = 0;
#define NORMAL 0
#define SCROLLING 1
#define SCROLLREADY 2
#define SCROLLTIMEOUT 3

/* 
 * This is all the code a filter should have to be 
 * How should this be implemented?
 */
static void filter(mouse_info_t *delta, int noop) {
if (noop == 1) {
if (state == SCROLLREADY) {
warnx("noop");
memcpy(delta, &(rodent.state), sizeof(mouse_info_t));
dumpstate(delta);
state = SCROLLTIMEOUT;
}
} else {
if (delta->u.data.buttons & (1<<1)) {
if (state == SCROLLTIMEOUT)
return;

state = SCROLLREADY;

/* Middle mouse is held */
if (delta->u.data.x != 0 || delta->u.data.y != 0) {
if (state == SCROLLREADY)
state = SCROLLING;

distance += delta->u.data.y;

#define THRESHOLD 3

if (distance > THRESHOLD) {
delta->u.data.z = 1;
distance = 0;
} else if (distance < -THRESHOLD) {
delta->u.data.z = -1;
distance = 0;
}

/* Do not move! */
delta->u.data.x = delta->u.data.y = 0;
}

/* Don't click middle */
delta->u.data.buttons &= ~(1<<1);
} else {
/* 
* We were ready to scroll, but the user let go of middle-mouse
* Fire mouse-down myself (in here), the mouse up will happen on it's
* own in update()
*/
if (SCROLLREADY == state) {
/* Send middle-mouse-down */
delta->u.data.buttons |= (1<<1);
ioctl(rodent.cfd, CONS_MOUSECTL, delta);
delta->u.data.buttons &= ~(1<<1);
}
state = NORMAL;
}
}
}

static void packethandler_main() {
fd_set fds;
struct timeval timeout;

timeout.tv_sec = 0;
timeout.tv_usec = 100000; /* 20mec */

if (NULL != rodent.handler_init)
rodent.handler_init(&rodent);

if (rodent.mfd == -1) {
rodent.mfd = open(rodent.device, O_RDWR);
if (rodent.mfd == -1) 
logfatal(1, "Failed trying to open '%s'", rodent.device);
}

FD_ZERO(&fds);
FD_SET(rodent.mfd, &fds);
for (;;) {
int c;

c = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
if (c < 0)
logfatal(1, "Error with select call");
else if (c > 0)
rodent.handler(&rodent);
else 
rodent.update(NULL); /* TIMEOUT HAPPENED */

FD_SET(rodent.mfd, &fds);
}
}

void dumpstate(mouse_info_t *delta) {
warnx("(%d,%d) z:%d b:%08x", delta->u.data.x, delta->u.data.y,
delta->u.data.z, delta->u.data.buttons);
}






// ./moused -m sysmouse -d /dev/sysmouse

makefile

# $FreeBSD: src/usr.sbin/moused/Makefile,v 1.6 2001/03/26 14:40:51 ru Exp $
#
PROG=   moused 
MAN=    moused.8

SRCS=   moused.c moused.h
.include <bsd.prog.mk>






'GNU > FreeBSD' 카테고리의 다른 글

마우스 컨트롤(sysmouse)  (0) 2016.07.08
마우스 컨트롤(Command)  (0) 2016.07.08
Mouse_Control - 6 번째(moused)  (0) 2016.07.07
Mouse_Control - 5 번째(Consio.h)  (0) 2016.07.06
Mouse_Control - 4 번째(Consio.h)  (0) 2016.07.04

+ Recent posts