1# Copyright (C) 2012 W. Trevor King <wking@tremily.us>
2#
3# This file is part of python-kmod.
4#
5# python-kmod is free software: you can redistribute it and/or modify it under
6# the terms of the GNU Lesser General Public License version 2.1 as published
7# by the Free Software Foundation.
8#
9# python-kmod is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
12# details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with python-kmod.  If not, see <http://www.gnu.org/licenses/>.
16
17import collections as _collections
18
19cimport libc.errno as _errno
20
21cimport _libkmod_h
22from error import KmodError as _KmodError
23cimport list as _list
24import list as _list
25cimport _util
26import _util
27
28
29cdef class Module (object):
30    "Wrap a struct kmod_module* item"
31    def __cinit__(self):
32        self.module = NULL
33
34    def __dealloc__(self):
35        self._cleanup()
36
37    def _cleanup(self):
38        if self.module is not NULL:
39            _libkmod_h.kmod_module_unref(self.module)
40            self.module = NULL
41
42    cpdef from_mod_list_item(self, _list.ModListItem item):
43        self._cleanup()
44        self.module = _libkmod_h.kmod_module_get_module(item.list)
45
46    def _name_get(self):
47        return _util.char_ptr_to_str(
48            _libkmod_h.kmod_module_get_name(self.module))
49    name = property(fget=_name_get)
50
51    def _path_get(self):
52        return _util.char_ptr_to_str(
53            _libkmod_h.kmod_module_get_path(self.module))
54    path = property(fget=_path_get)
55
56    def _options_get(self):
57        return _util.char_ptr_to_str(
58            _libkmod_h.kmod_module_get_options(self.module))
59    options = property(fget=_options_get)
60
61    def _install_commands_get(self):
62        return _util.char_ptr_to_str(
63            _libkmod_h.kmod_module_get_install_commands(self.module))
64    install_commands = property(fget=_install_commands_get)
65
66    def _remove_commands_get(self):
67        return _util.char_ptr_to_str(
68            _libkmod_h.kmod_module_get_remove_commands(self.module))
69    remove_commands = property(fget=_remove_commands_get)
70
71    def _refcnt_get(self):
72        return _libkmod_h.kmod_module_get_refcnt(self.module)
73    refcnt = property(fget=_refcnt_get)
74
75    def _size_get(self):
76        return _libkmod_h.kmod_module_get_size(self.module)
77    size = property(fget=_size_get)
78
79    def _info_get(self):
80        cdef _list.ModList ml = _list.ModList()
81        cdef _list.ModListItem mli
82        err = _libkmod_h.kmod_module_get_info(self.module, &ml.list)
83        if err < 0:
84            raise _KmodError('Could not get info')
85        info = _collections.OrderedDict()
86        try:
87            for item in ml:
88                mli = <_list.ModListItem> item
89                key = _util.char_ptr_to_str(
90                    _libkmod_h.kmod_module_info_get_key(mli.list))
91                value = _util.char_ptr_to_str(
92                    _libkmod_h.kmod_module_info_get_value(mli.list))
93                info[key] = value
94        finally:
95            _libkmod_h.kmod_module_info_free_list(ml.list)
96            ml.list = NULL
97        return info
98    info = property(fget=_info_get)
99
100    def _versions_get(self):
101        cdef _list.ModList ml = _list.ModList()
102        cdef _list.ModListItem mli
103        err = _libkmod_h.kmod_module_get_versions(self.module, &ml.list)
104        if err < 0:
105            raise _KmodError('Could not get versions')
106        try:
107            for item in ml:
108                mli = <_list.ModListItem> item
109                symbol = _util.char_ptr_to_str(
110                    _libkmod_h.kmod_module_version_get_symbol(mli.list))
111                crc = _libkmod_h.kmod_module_version_get_crc(mli.list)
112                yield {'symbol': symbol, 'crc': crc}
113        finally:
114            _libkmod_h.kmod_module_versions_free_list(ml.list)
115            ml.list = NULL
116    versions = property(fget=_versions_get)
117
118    def insert(self, flags=0, extra_options=None, install_callback=None,
119               data=None, print_action_callback=None):
120        """
121        insert module to current tree. 
122        e.g.
123        km = kmod.Kmod()
124        tp = km.module_from_name("thinkpad_acpi")
125        tp.insert(extra_options='fan_control=1')
126        """
127        cdef char *opt = NULL
128        #cdef _libkmod_h.install_callback_t install = NULL
129        cdef int (*install)(
130            _libkmod_h.kmod_module *, _libkmod_h.const_char_ptr, void *)
131        install = NULL
132        cdef void *d = NULL
133        #cdef _libkmod_h.print_action_callback_t print_action = NULL
134        cdef void (*print_action)(
135            _libkmod_h.kmod_module *, _libkmod_h.bool,
136            _libkmod_h.const_char_ptr)
137        print_action = NULL
138        if extra_options:
139            opt = extra_options
140        # TODO: convert callbacks and data from Python object to C types
141        err = _libkmod_h.kmod_module_probe_insert_module(
142            self.module, flags, opt, install, d, print_action)
143        if err == -_errno.EEXIST:
144            raise _KmodError('Module already loaded')
145        elif err < 0:
146            raise _KmodError('Could not load module')
147
148    def remove(self, flags=0):
149        """
150        remove module from current tree
151        e.g.
152        km = kmod.Kmod()
153        tp = km.module_from_name("thinkpad_acpi")
154        tp.remove()
155        """
156        err = _libkmod_h.kmod_module_remove_module(self.module, flags)
157        if err < 0:
158            raise _KmodError('Could not remove module')
159