|
|
Jump to this file's LXR Page |
|
|
File: [CENS] / emstar / fusd / python / fusdmodule.c
(download)
/
(as text)
Revision: 1.3, Fri Jul 11 21:29:39 2003 UTC (6 years, 4 months ago) by cerpa Branch: MAIN CVS Tags: scale_radio_channel, rdd_alpha_version_1, pregeonet, nims-lab-Sep07-2004, nims-jr-Sep05-04, mote, lessgps_release, kiss_release, fusd_with_no_daemon, fusd-1_10, copyright-07-11-03, bp_scale_radio_channel, audio_server, acoustic-05-18-06, ROUTING_EXPERIMENTAL, PRE_TOSNIC_FIX, PRE_NOMEGA_MOTENIC, PRE_MOTENIC_CLEANUP, PRE_CEILING_FIX, PRE_64BIT, MOTENIC_PRE_BUGFIX_20050415, LESSGPS_1_00, LAURA_CALIBRATION_EXPERIMENTS, KISS_1_0, HOSTMOTE_V_6_EXPERIMENTAL, HOSTMOTE_PROTOCOL_VERSION_7, HOSTMOTE_PROTOCOL_VERSION_6_WITH_HOSTMOAP, HOSTMOTE_PROTOCOL_VERSION_5_WITH_HOSTMOAP, HOSTMOTE_PROTOCOL_VERSION_5, HOSTMOTE_PROTOCOL_VERSION_4, HOSTMOTE_PROTOCOL_VERSION_3, HEAD, ESS_RELEASE_3_5, ESS_RELEASE_3_4, ESS_RELEASE_3_3, ESS_RELEASE_3_2, ESS_RELEASE_3_1, ESS_RELEASE_3_0, ESS_RELEASE_2_0, ESS_CONNECTIVITY, ESS_CENTROUTE_TESTING, ESS2-CMS-V1_5_pretest, ESS2-CMS-V1_4cMergeSympathy_2, ESS2-CMS-V1_4c, ESS2-CMS-V1_4b, ESS2-CMS-V1_4a, ESS2-CMS-V1_3, ESS2-CMS-V1_2, ESS2-CMS-V1_1, ESS2-CMS-V1_0, EMSTAR_RELEASE_2_5, EMSTAR_RELEASE_2_1_BRANCH, EMSTAR_RELEASE_2_1, EMSTAR_RELEASE_2_0_beta1, EMSTAR_RELEASE_2_0, EMSTAR_RELEASE_1_3_2, EMSTAR_RELEASE_1_3_1, EMSTAR_RELEASE_1_3, EMSTAR_RELEASE_1_2, EMSTAR_RELEASE_1_1, EMSTAR_RELEASE_1_0, EMSTAR_PRE_HTML, CYCLOPS_RELEASE_CANDIDATE_2_0, CYCLOPS_PRERELEASE_STABLE, CENTROUTE_EMSTAR_SOCKETS, BG_1_0, BANGLADESH_ARSENIC_1_2, BANGLADESH_ARSENIC_1_1, AMARSS_JR_DEPLOYMENT_6_05_07 Changes since 1.2: +24 -29 lines added the copyright notice to all the source code in the cens repository |
/*
*
* Copyright (c) 2003 The Regents of the University of California. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
Copyright (C) 2003 Brian Warner <warner-fusd@lothar.com>
This program is free software, and can be distributed under the same
terms as the rest of FUSD (the BSD 3-clause license). See the file
../LICENSE for details.
*/
#include <stdio.h>
#include <Python.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include "fusd.h"
typedef struct {
PyObject_HEAD
struct fusd_file_info *file;
int active;
PyObject *fp;
} RequestObject;
staticforward PyTypeObject ReadRequest_Type;
staticforward PyTypeObject WriteRequest_Type;
staticforward PyTypeObject IoctlRequest_Type;
staticforward PyTypeObject PollDiffRequest_Type;
#define ReadRequestObject_Check(v) ((v)->ob_type == &ReadRequest_Type)
#define WriteRequestObject_Check(v) ((v)->ob_type == &WriteRequest_Type)
#define IoctlRequestObject_Check(v) ((v)->ob_type == &IoctlRequest_Type)
#define PollDiffRequestObject_Check(v) ((v)->ob_type == &PollDiffRequest_Type)
static RequestObject *
newReadRequestObject(struct fusd_file_info *file, PyObject *fp)
{
RequestObject *self;
self = PyObject_New(RequestObject, &ReadRequest_Type);
if (self == NULL)
return NULL;
self->file = file;
self->active = 1;
self->fp = fp;
return self;
}
static RequestObject *
newWriteRequestObject(struct fusd_file_info *file, PyObject *fp)
{
RequestObject *self;
self = PyObject_New(RequestObject, &WriteRequest_Type);
if (self == NULL)
return NULL;
self->file = file;
self->active = 1;
self->fp = fp;
return self;
}
static RequestObject *
newIoctlRequestObject(struct fusd_file_info *file, PyObject *fp)
{
RequestObject *self;
self = PyObject_New(RequestObject, &IoctlRequest_Type);
if (self == NULL)
return NULL;
self->file = file;
self->active = 1;
self->fp = fp;
return self;
}
static RequestObject *
newPollDiffRequestObject(struct fusd_file_info *file, PyObject *fp)
{
RequestObject *self;
self = PyObject_New(RequestObject, &PollDiffRequest_Type);
if (self == NULL)
return NULL;
self->file = file;
self->active = 1;
self->fp = fp;
return self;
}
static void
Request_dealloc(RequestObject *self)
{
if (self->active) {
/* the python code should not let active requests fall out of scope.
They should all be explicitly .finish()ed or .destroy()ed */
fprintf(stderr, "Warning: Active Request <%s> being destroyed\n",
self->ob_type->tp_name);
self->active = 0;
fusd_destroy(self->file);
}
PyObject_Del(self);
}
static PyObject *
Request_finish(RequestObject *self, PyObject *args)
{
int retval; /* really ssize_t */
int rc;
if (!PyArg_ParseTuple(args, "i:finish", &retval))
return NULL;
if (!self->active) {
PyErr_SetString(PyExc_RuntimeError, "duplicate request->return");
return NULL;
}
rc = fusd_return(self->file, retval);
self->active = 0;
return PyInt_FromLong(rc);
}
static PyObject *
Request_destroy(RequestObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":destroy"))
return NULL;
if (!self->active) {
PyErr_SetString(PyExc_RuntimeError,
"can only destroy active requests");
return NULL;
}
fusd_destroy(self->file);
self->active = 0;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
ReadRequest_setdata(RequestObject *self, PyObject *args)
{
int offset;
char *data;
int datalen;
if (!self->active) {
PyErr_SetString(PyExc_RuntimeError, "setdata on inactive request");
return NULL;
}
if (!PyArg_ParseTuple(args, "is#:setdata", &offset, &data, &datalen))
return NULL;
if ((offset < 0) || (offset+datalen > fusd_get_length(self->file))) {
PyErr_SetString(PyExc_IndexError, "writing beyond buffer");
return NULL;
}
memcpy(fusd_get_read_buffer(self->file), data, datalen);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
WriteRequest_getdata(RequestObject *self, PyObject *args)
{
int offset = 0;
int datalen = fusd_get_length(self->file);
int reqlen = datalen;
PyObject *ret;
if (!self->active) {
PyErr_SetString(PyExc_RuntimeError, "getdata on inactive request");
return NULL;
}
if (!PyArg_ParseTuple(args, "|ii:getdata", &offset, &reqlen))
return NULL;
if ((offset < 0) || (reqlen < 0 ) || (offset+reqlen > datalen)) {
PyErr_SetString(PyExc_IndexError, "reading beyond buffer");
return NULL;
}
ret = Py_BuildValue("s#", fusd_get_write_buffer(self->file) + offset,
reqlen);
return ret;
}
static PyObject *
IoctlRequest_getdata(RequestObject *self, PyObject *args)
{
if (!self->active) {
PyErr_SetString(PyExc_RuntimeError, "getdata on inactive request");
return NULL;
}
// IO_W or IO_WR will have a data pointer
if (fusd_get_ioctl_buffer(self->file)) {
return Py_BuildValue("s#", fusd_get_ioctl_buffer(self->file),
fusd_get_length(self->file));
}
// IO will have an int, IO_R will probably have a zero
return PyInt_FromLong(fusd_get_ioctl_arg(self->file));
}
static PyObject *
IoctlRequest_setdata(RequestObject *self, PyObject *args)
{
char *data;
int datalen;
int cmd = fusd_get_ioctl_request(self->file);
if (!self->active) {
PyErr_SetString(PyExc_RuntimeError, "getdata on inactive request");
return NULL;
}
// IO_R will have a data pointer. IO_W will to, but it isn't used
if ((_IOC_DIR(cmd) & _IOC_READ) && fusd_get_ioctl_buffer(self->file))
{
if (!PyArg_ParseTuple(args, "s#:setdata", &data, &datalen))
return NULL;
if (datalen > fusd_get_length(self->file)) {
PyErr_Format(PyExc_IndexError,
"too much data: ioctl accepts %d bytes, given %d",
fusd_get_length(self->file), datalen);
return NULL;
}
memcpy(fusd_get_ioctl_buffer(self->file), data, datalen);
Py_INCREF(Py_None);
return Py_None;
}
PyErr_SetString(PyExc_TypeError, "this ioctl is read only");
return NULL;
}
static PyMethodDef ReadRequest_methods[] = {
{"setdata", (PyCFunction)ReadRequest_setdata, METH_VARARGS},
{"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
{"finish", (PyCFunction)Request_finish, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
static PyMethodDef WriteRequest_methods[] = {
{"getdata", (PyCFunction)WriteRequest_getdata, METH_VARARGS},
{"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
{"finish", (PyCFunction)Request_finish, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
static PyMethodDef IoctlRequest_methods[] = {
{"getdata", (PyCFunction)IoctlRequest_getdata, METH_VARARGS},
{"setdata", (PyCFunction)IoctlRequest_setdata, METH_VARARGS},
{"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
{"finish", (PyCFunction)Request_finish, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
static PyMethodDef PollDiffRequest_methods[] = {
{"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
{"finish", (PyCFunction)Request_finish, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
static int
Request_getparm(RequestObject *self, char *name, int *valid)
{
*valid = 1;
if (strcmp(name, "length") == 0)
return fusd_get_length(self->file);
if (strcmp(name, "fd") == 0)
return self->file->fd;
if (strcmp(name, "flags") == 0)
return self->file->flags;
if (strcmp(name, "pid") == 0)
return self->file->pid;
if (strcmp(name, "uid") == 0)
return self->file->uid;
if (strcmp(name, "gid") == 0)
return self->file->gid;
if (strcmp(name, "offset") == 0) {
int offset = *(fusd_get_offset(self->file)); /* loff_t */
return offset;
}
*valid = 0;
return 0;
}
static PyObject *
ReadRequest_getattr(RequestObject *self, char *name)
{
int parm, valid;
parm = Request_getparm(self, name, &valid);
if (valid)
return PyInt_FromLong(parm);
return Py_FindMethod(ReadRequest_methods, (PyObject *)self, name);
}
static PyObject *
WriteRequest_getattr(RequestObject *self, char *name)
{
int parm, valid;
parm = Request_getparm(self, name, &valid);
if (valid)
return PyInt_FromLong(parm);
return Py_FindMethod(WriteRequest_methods, (PyObject *)self, name);
}
static PyObject *
IoctlRequest_getattr(RequestObject *self, char *name)
{
int parm, valid;
int cmd = fusd_get_ioctl_request(self->file);
parm = Request_getparm(self, name, &valid);
if (valid)
return PyInt_FromLong(parm);
if (strcmp(name, "cmd") == 0)
return PyInt_FromLong(cmd);
if (strcmp(name, "nr") == 0)
return PyInt_FromLong(_IOC_NR(cmd));
if (strcmp(name, "type") == 0)
return PyInt_FromLong(_IOC_TYPE(cmd));
if (strcmp(name, "size") == 0)
return PyInt_FromLong(_IOC_SIZE(cmd));
if (strcmp(name, "direction") == 0)
return PyInt_FromLong(_IOC_DIR(cmd));
if (strcmp(name, "dir_string") == 0) {
int dir = _IOC_DIR(cmd);
switch (dir) {
case _IOC_NONE:
return PyString_FromString("none");
case _IOC_WRITE:
return PyString_FromString("write");
case _IOC_READ:
return PyString_FromString("read");
case (_IOC_READ | _IOC_WRITE):
return PyString_FromString("readwrite");
}
}
return Py_FindMethod(IoctlRequest_methods, (PyObject *)self, name);
}
static PyObject *
PollDiffRequest_getattr(RequestObject *self, char *name)
{
return Py_FindMethod(PollDiffRequest_methods, (PyObject *)self, name);
}
static int
Request_setattr(RequestObject *self, char *name, PyObject *v)
{
if (strcmp(name, "offset") == 0) {
int offset;
offset = PyInt_AsLong(v);
if (PyErr_Occurred())
return -1;
*(fusd_get_offset(self->file)) = offset; /* loff_t */
return 0;
}
if (strcmp(name, "flags") == 0) {
int flags;
flags = PyInt_AsLong(v);
if (PyErr_Occurred())
return -1;
self->file->flags = flags;
return 0;
}
PyErr_Format(PyExc_AttributeError,
"cannot set Request attribute '%s'", name);
return -1;
}
statichere PyTypeObject ReadRequest_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"fusdmodule.ReadRequest", /*tp_name*/
sizeof(RequestObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Request_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)ReadRequest_getattr, /*tp_getattr*/
(setattrfunc)Request_setattr, /*tp_setattr*/
};
statichere PyTypeObject WriteRequest_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"fusdmodule.WriteRequest", /*tp_name*/
sizeof(RequestObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Request_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)WriteRequest_getattr, /*tp_getattr*/
(setattrfunc)Request_setattr, /*tp_setattr*/
};
statichere PyTypeObject IoctlRequest_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"fusdmodule.IoctlRequest", /*tp_name*/
sizeof(RequestObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Request_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)IoctlRequest_getattr, /*tp_getattr*/
(setattrfunc)Request_setattr, /*tp_setattr*/
};
statichere PyTypeObject PollDiffRequest_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"fusdmodule.PollDiffRequest", /*tp_name*/
sizeof(RequestObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Request_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)PollDiffRequest_getattr, /*tp_getattr*/
0, /*tp_setattr*/
};
static int
client_open(struct fusd_file_info *file)
{
PyObject *ret, *device;
int retval;
unsigned int flags;
PyObject *fp;
device = file->device_info;
ret = PyObject_CallMethod(device, "do_open",
"iiii", file->flags, file->pid,
file->uid, file->gid);
if (!ret) {
/* print and clear the exception */
PyErr_Print();
return -EIO;
}
if (!PyArg_ParseTuple(ret, "iiO", &retval, &flags, &fp))
{
PyErr_Print();
return -EIO;
}
file->flags = flags;
file->private_data = fp;
return retval;
}
static int
client_close(struct fusd_file_info *file)
{
PyObject *ret, *device, *fp;
int retval;
device = file->device_info;
fp = file->private_data;
ret = PyObject_CallMethod(device, "do_close", "Oiiii",
fp, file->flags, file->pid,
file->uid, file->gid);
if (!ret) {
/* print and clear the exception */
PyErr_Print();
return -EIO;
}
if (!PyArg_ParseTuple(ret, "i", &retval))
{
PyErr_Print();
return -EIO;
}
return retval;
}
static ssize_t
client_read(struct fusd_file_info *file, char *buffer, size_t length,
loff_t *offset)
{
PyObject *ret, *fp;
RequestObject *req;
int newoffset;
fp = file->private_data;
newoffset = *offset; /* loff_t */
if (newoffset != *offset) {
fprintf(stderr, "Ack! offset is too large, loff_t is too big\n");
fprintf(stderr, "client_read() failing..\n");
return -EIO;
}
req = newReadRequestObject(file, fp);
if (!req) {
fprintf(stderr, "client_read: unable to allocate RequestObject\n");
return -EIO;
}
ret = PyObject_CallMethod(fp, "do_read", "O", req);
if (ret == Py_None) {
/* this is the normal case. They might have called req.finish, or
they may defer it until later. */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
/* something went wrong */
if (ret) {
fprintf(stderr,
"do_read should not return anything (returned <%s>)\n",
ret->ob_type->tp_name);
} else {
/* print and clear the exception */
PyErr_Print();
}
if (req->active) {
/* they didn't do .finish, so free the Request (preserving the .file
struct) and return an error. */
req->active = 0;
Py_DECREF(req);
return -EIO;
}
/* they did do .finish, so an error code was already sent */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
static ssize_t
client_write(struct fusd_file_info *file, const char *buffer,
size_t length, loff_t *offset)
{
PyObject *ret, *fp;
int newoffset;
RequestObject *req;
/* N.B.: loff_t is larger than an int, so you can't pass *offset to a
varargs function because everything after that argument will be taken
from the wrong place. Downgrade it to an int before handing it to
Py_BuildValue. This also means we can't deal with >2GB files yet. */
fp = file->private_data;
newoffset = *offset;
if (newoffset != *offset) {
fprintf(stderr, "Ack! offset is too large, loff_t is too big\n");
fprintf(stderr, "client_write() failing..\n");
return -EIO;
}
req = newWriteRequestObject(file, fp);
if (!req) {
fprintf(stderr, "client_write: unable to allocate RequestObject\n");
return -EIO;
}
ret = PyObject_CallMethod(fp, "do_write", "O", req);
if (ret == Py_None) {
/* this is the normal case. They might have called req.finish, or
they may defer it until later. */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
/* something went wrong */
if (ret) {
fprintf(stderr,
"do_write should not return anything (returned <%s>)\n",
ret->ob_type->tp_name);
} else {
/* print and clear the exception */
PyErr_Print();
}
if (req->active) {
/* they didn't do .finish, so free the Request (preserving the .file
struct) and return an error. */
req->active = 0;
Py_DECREF(req);
return -EIO;
}
/* they did do .finish, so an error code was already sent */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
static int
client_ioctl(struct fusd_file_info *file, int request, void *data)
{
PyObject *ret, *fp;
RequestObject *req;
fp = file->private_data;
req = newIoctlRequestObject(file, fp);
if (!req) {
fprintf(stderr, "client_ioctl: unable to allocate RequestObject\n");
return -EIO;
}
ret = PyObject_CallMethod(fp, "do_ioctl", "O", req);
if (ret == Py_None) {
/* this is the normal case. They might have called req.finish, or
they may defer it until later. */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
/* something went wrong */
if (ret) {
fprintf(stderr,
"do_ioctl should not return anything (returned <%s>)\n",
ret->ob_type->tp_name);
} else {
/* print and clear the exception */
PyErr_Print();
}
if (req->active) {
/* they didn't do .finish, so free the Request (preserving the .file
struct) and return an error. */
req->active = 0;
Py_DECREF(req);
return -EIO;
}
/* they did do .finish, so an error code was already sent */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
static int
client_poll_diff(struct fusd_file_info *file, unsigned int cached_state)
{
PyObject *ret, *fp;
RequestObject *req;
fp = file->private_data;
req = newPollDiffRequestObject(file, fp);
if (!req) {
fprintf(stderr,
"client_poll_diff: unable to allocate RequestObject\n");
return -EIO;
}
ret = PyObject_CallMethod(fp, "do_poll_diff", "Oi", req, cached_state);
if (ret == Py_None) {
/* this is the normal case. They might have called req.finish, or
they may defer it until later. */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
/* something went wrong */
if (ret) {
fprintf(stderr,
"do_poll_diff should not return anything (returned <%s>)\n",
ret->ob_type->tp_name);
} else {
/* print and clear the exception */
PyErr_Print();
}
if (req->active) {
/* they didn't do .finish, so free the Request (preserving the .file
struct) and return an error. */
req->active = 0;
Py_DECREF(req);
return -EIO;
}
/* they did do .finish, so an error code was already sent */
Py_DECREF(req);
return -FUSD_NOREPLY;
}
static struct fusd_file_operations fops = {
open: client_open,
close: client_close,
read: client_read,
write: client_write,
ioctl: client_ioctl,
poll_diff: client_poll_diff,
};
static PyObject *
do_register(PyObject *self, PyObject *args)
{
const char *name;
PyObject *device_info;
int mode; /* permissions for the /dev/NAME device, like 0666 */
mode_t realmode;
int handle;
if (!PyArg_ParseTuple(args, "siO", &name, &mode, &device_info))
return NULL;
realmode = mode;
handle = fusd_register(name, realmode, device_info, &fops);
if (handle < 0) {
/* errno will be ENOPKG if the kernel module isn't installed */
return PyErr_SetFromErrno(PyExc_RuntimeError);
}
Py_INCREF(device_info);
return PyInt_FromLong(handle);
}
static PyObject *
do_unregister(PyObject *self, PyObject *args)
{
PyObject *device_info;
int rc, fd;
if (!PyArg_ParseTuple(args, "iO", &fd, &device_info))
return NULL;
rc = fusd_unregister(fd);
Py_DECREF(device_info);
if (rc < 0) {
return PyErr_SetFromErrno(PyExc_RuntimeError);
}
return PyInt_FromLong(rc);
}
static PyObject *
do_dispatch(PyObject *self, PyObject *args)
{
int fd;
if (!PyArg_ParseTuple(args, "i", &fd))
return NULL;
fusd_dispatch(fd);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
do_run(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
fusd_run(); /* runs forever */
Py_INCREF(Py_None);
return Py_None; /* but just in case */
}
static
struct PyMethodDef Methods[] =
{
{"register", do_register, METH_VARARGS },
{"unregister", do_unregister, METH_VARARGS },
{"dispatch", do_dispatch, METH_VARARGS },
{"run", do_run, METH_VARARGS },
{NULL, NULL },
};
DL_EXPORT(void)
init_fusd(void)
{
PyObject *module, *d;
ReadRequest_Type.ob_type = &PyType_Type;
WriteRequest_Type.ob_type = &PyType_Type;
IoctlRequest_Type.ob_type = &PyType_Type;
module = Py_InitModule("_fusd", Methods);
/* constants */
d = PyModule_GetDict(module);
PyDict_SetItemString(d, "NOREPLY", PyInt_FromLong(FUSD_NOREPLY));
PyDict_SetItemString(d, "NOTIFY_INPUT",
PyInt_FromLong(FUSD_NOTIFY_INPUT));
PyDict_SetItemString(d, "NOTIFY_OUTPUT",
PyInt_FromLong(FUSD_NOTIFY_OUTPUT));
PyDict_SetItemString(d, "NOTIFY_EXCEPT",
PyInt_FromLong(FUSD_NOTIFY_EXCEPT));
}
| CENS CVS Mailing List |
Powered by ViewCVS 0.9.2 |