Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 1 | /* |
| 2 | * libkmod - interface to kernel module operations |
| 3 | * |
Lucas De Marchi | e6b0e49 | 2013-01-16 11:27:21 -0200 | [diff] [blame] | 4 | * Copyright (C) 2011-2013 ProFUSION embedded systems |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
Lucas De Marchi | cb451f3 | 2011-12-12 18:24:35 -0200 | [diff] [blame] | 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
Lucas De Marchi | dea2dfe | 2014-12-25 23:32:03 -0200 | [diff] [blame] | 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 18 | */ |
| 19 | |
Lucas De Marchi | e8fd8fe | 2012-07-18 10:19:48 -0300 | [diff] [blame] | 20 | #pragma once |
Lucas De Marchi | 6ad9830 | 2011-11-23 15:24:34 -0200 | [diff] [blame] | 21 | #ifndef _LIBKMOD_H_ |
| 22 | #define _LIBKMOD_H_ |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 23 | |
Lucas De Marchi | 6806a04 | 2011-11-23 16:10:58 -0200 | [diff] [blame] | 24 | #include <fcntl.h> |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 25 | #include <stdarg.h> |
Lucas De Marchi | 0017862 | 2012-01-13 02:24:18 -0200 | [diff] [blame] | 26 | #include <stdbool.h> |
Lucas De Marchi | 5369797 | 2011-11-22 05:42:09 -0200 | [diff] [blame] | 27 | #include <inttypes.h> |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 28 | |
| 29 | #ifdef __cplusplus |
| 30 | extern "C" { |
| 31 | #endif |
| 32 | |
| 33 | /* |
| 34 | * kmod_ctx |
| 35 | * |
| 36 | * library user context - reads the config and system |
| 37 | * environment, user variables, allows custom logging |
| 38 | */ |
| 39 | struct kmod_ctx; |
Lucas De Marchi | 6a82921 | 2012-01-09 03:08:26 -0200 | [diff] [blame] | 40 | struct kmod_ctx *kmod_new(const char *dirname, const char * const *config_paths); |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 41 | struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx); |
| 42 | struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx); |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 43 | void kmod_set_log_fn(struct kmod_ctx *ctx, |
Gustavo Sverzut Barbieri | 1bdd951 | 2011-12-08 13:47:55 -0200 | [diff] [blame] | 44 | void (*log_fn)(void *log_data, |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 45 | int priority, const char *file, int line, |
| 46 | const char *fn, const char *format, |
| 47 | va_list args), |
Gustavo Sverzut Barbieri | 1bdd951 | 2011-12-08 13:47:55 -0200 | [diff] [blame] | 48 | const void *data); |
Lucas De Marchi | 6d17755 | 2011-11-23 11:52:30 -0200 | [diff] [blame] | 49 | int kmod_get_log_priority(const struct kmod_ctx *ctx); |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 50 | void kmod_set_log_priority(struct kmod_ctx *ctx, int priority); |
Lucas De Marchi | 6d17755 | 2011-11-23 11:52:30 -0200 | [diff] [blame] | 51 | void *kmod_get_userdata(const struct kmod_ctx *ctx); |
Gustavo Sverzut Barbieri | 1ce08a5 | 2011-12-02 20:24:07 -0200 | [diff] [blame] | 52 | void kmod_set_userdata(struct kmod_ctx *ctx, const void *userdata); |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 53 | |
Laura Abbott | b87d01d | 2015-09-28 15:39:11 -0700 | [diff] [blame^] | 54 | const char *kmod_get_dirname(const struct kmod_ctx *ctx); |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 55 | |
| 56 | /* |
| 57 | * Management of libkmod's resources |
| 58 | */ |
Lucas De Marchi | 33bb69b | 2011-12-08 14:59:51 -0200 | [diff] [blame] | 59 | int kmod_load_resources(struct kmod_ctx *ctx); |
| 60 | void kmod_unload_resources(struct kmod_ctx *ctx); |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 61 | |
Lucas De Marchi | c4dc3ca | 2011-12-31 19:28:31 -0200 | [diff] [blame] | 62 | enum kmod_resources { |
| 63 | KMOD_RESOURCES_OK = 0, |
| 64 | KMOD_RESOURCES_MUST_RELOAD = 1, |
| 65 | KMOD_RESOURCES_MUST_RECREATE = 2, |
| 66 | }; |
Lucas De Marchi | c4dc3ca | 2011-12-31 19:28:31 -0200 | [diff] [blame] | 67 | int kmod_validate_resources(struct kmod_ctx *ctx); |
| 68 | |
Lucas De Marchi | b08314f | 2012-01-16 12:01:48 -0200 | [diff] [blame] | 69 | enum kmod_index { |
| 70 | KMOD_INDEX_MODULES_DEP = 0, |
| 71 | KMOD_INDEX_MODULES_ALIAS, |
| 72 | KMOD_INDEX_MODULES_SYMBOL, |
Lucas De Marchi | 3805274 | 2012-02-16 20:43:16 -0200 | [diff] [blame] | 73 | KMOD_INDEX_MODULES_BUILTIN, |
Lucas De Marchi | b08314f | 2012-01-16 12:01:48 -0200 | [diff] [blame] | 74 | /* Padding to make sure enum is not mapped to char */ |
| 75 | _KMOD_INDEX_PAD = (1 << 31), |
| 76 | }; |
Lucas De Marchi | 0224482 | 2012-01-16 16:43:47 -0200 | [diff] [blame] | 77 | int kmod_dump_index(struct kmod_ctx *ctx, enum kmod_index type, int fd); |
Lucas De Marchi | 758428a | 2012-01-16 15:56:17 -0200 | [diff] [blame] | 78 | |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 79 | /* |
| 80 | * kmod_list |
| 81 | * |
| 82 | * access to kmod generated lists |
| 83 | */ |
Lucas De Marchi | 6924e47 | 2011-11-22 05:38:28 -0200 | [diff] [blame] | 84 | struct kmod_list; |
Lucas De Marchi | 6a82921 | 2012-01-09 03:08:26 -0200 | [diff] [blame] | 85 | struct kmod_list *kmod_list_next(const struct kmod_list *list, |
| 86 | const struct kmod_list *curr); |
| 87 | struct kmod_list *kmod_list_prev(const struct kmod_list *list, |
| 88 | const struct kmod_list *curr); |
| 89 | struct kmod_list *kmod_list_last(const struct kmod_list *list); |
Gustavo Sverzut Barbieri | d5ec60b | 2011-12-16 22:32:33 -0200 | [diff] [blame] | 90 | |
Lucas De Marchi | 6924e47 | 2011-11-22 05:38:28 -0200 | [diff] [blame] | 91 | #define kmod_list_foreach(list_entry, first_entry) \ |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 92 | for (list_entry = first_entry; \ |
Lucas De Marchi | e4351b0 | 2011-11-21 14:59:23 -0200 | [diff] [blame] | 93 | list_entry != NULL; \ |
Lucas De Marchi | 6924e47 | 2011-11-22 05:38:28 -0200 | [diff] [blame] | 94 | list_entry = kmod_list_next(first_entry, list_entry)) |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 95 | |
Gustavo Sverzut Barbieri | d6b55b7 | 2011-12-16 22:33:08 -0200 | [diff] [blame] | 96 | #define kmod_list_foreach_reverse(list_entry, first_entry) \ |
| 97 | for (list_entry = kmod_list_last(first_entry); \ |
| 98 | list_entry != NULL; \ |
| 99 | list_entry = kmod_list_prev(first_entry, list_entry)) |
| 100 | |
Lucas De Marchi | 0017862 | 2012-01-13 02:24:18 -0200 | [diff] [blame] | 101 | /* |
| 102 | * kmod_config_iter |
| 103 | * |
| 104 | * access to configuration lists - it allows to get each configuration's |
| 105 | * key/value stored by kmod |
| 106 | */ |
| 107 | struct kmod_config_iter; |
| 108 | struct kmod_config_iter *kmod_config_get_blacklists(const struct kmod_ctx *ctx); |
| 109 | struct kmod_config_iter *kmod_config_get_install_commands(const struct kmod_ctx *ctx); |
| 110 | struct kmod_config_iter *kmod_config_get_remove_commands(const struct kmod_ctx *ctx); |
| 111 | struct kmod_config_iter *kmod_config_get_aliases(const struct kmod_ctx *ctx); |
| 112 | struct kmod_config_iter *kmod_config_get_options(const struct kmod_ctx *ctx); |
| 113 | struct kmod_config_iter *kmod_config_get_softdeps(const struct kmod_ctx *ctx); |
| 114 | const char *kmod_config_iter_get_key(const struct kmod_config_iter *iter); |
| 115 | const char *kmod_config_iter_get_value(const struct kmod_config_iter *iter); |
| 116 | bool kmod_config_iter_next(struct kmod_config_iter *iter); |
| 117 | void kmod_config_iter_free_iter(struct kmod_config_iter *iter); |
| 118 | |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 119 | /* |
| 120 | * kmod_module |
| 121 | * |
| 122 | * Operate on kernel modules |
| 123 | */ |
| 124 | struct kmod_module; |
| 125 | int kmod_module_new_from_name(struct kmod_ctx *ctx, const char *name, |
| 126 | struct kmod_module **mod); |
| 127 | int kmod_module_new_from_path(struct kmod_ctx *ctx, const char *path, |
| 128 | struct kmod_module **mod); |
| 129 | int kmod_module_new_from_lookup(struct kmod_ctx *ctx, const char *given_alias, |
| 130 | struct kmod_list **list); |
| 131 | int kmod_module_new_from_loaded(struct kmod_ctx *ctx, |
| 132 | struct kmod_list **list); |
| 133 | |
| 134 | struct kmod_module *kmod_module_ref(struct kmod_module *mod); |
| 135 | struct kmod_module *kmod_module_unref(struct kmod_module *mod); |
| 136 | int kmod_module_unref_list(struct kmod_list *list); |
| 137 | struct kmod_module *kmod_module_get_module(const struct kmod_list *entry); |
| 138 | |
| 139 | |
Lucas De Marchi | f39dc70 | 2011-12-20 19:31:14 -0200 | [diff] [blame] | 140 | /* Removal flags */ |
Lucas De Marchi | 423f856 | 2011-11-24 15:42:16 -0200 | [diff] [blame] | 141 | enum kmod_remove { |
Lucas De Marchi | 6806a04 | 2011-11-23 16:10:58 -0200 | [diff] [blame] | 142 | KMOD_REMOVE_FORCE = O_TRUNC, |
Lucas De Marchi | 7ab8804 | 2013-09-20 01:30:07 -0500 | [diff] [blame] | 143 | KMOD_REMOVE_NOWAIT = O_NONBLOCK, /* always set */ |
Lucas De Marchi | 6806a04 | 2011-11-23 16:10:58 -0200 | [diff] [blame] | 144 | }; |
| 145 | |
Lucas De Marchi | f39dc70 | 2011-12-20 19:31:14 -0200 | [diff] [blame] | 146 | /* Insertion flags */ |
Lucas De Marchi | 8f788d5 | 2011-11-25 01:22:56 -0200 | [diff] [blame] | 147 | enum kmod_insert { |
| 148 | KMOD_INSERT_FORCE_VERMAGIC = 0x1, |
| 149 | KMOD_INSERT_FORCE_MODVERSION = 0x2, |
Lucas De Marchi | 8f788d5 | 2011-11-25 01:22:56 -0200 | [diff] [blame] | 150 | }; |
| 151 | |
Lucas De Marchi | ddbda02 | 2011-12-27 11:40:10 -0200 | [diff] [blame] | 152 | /* Flags to kmod_module_probe_insert_module() */ |
| 153 | enum kmod_probe { |
Lucas De Marchi | d851e9a | 2012-01-30 16:37:57 -0200 | [diff] [blame] | 154 | KMOD_PROBE_FORCE_VERMAGIC = 0x00001, |
| 155 | KMOD_PROBE_FORCE_MODVERSION = 0x00002, |
| 156 | KMOD_PROBE_IGNORE_COMMAND = 0x00004, |
Lucas De Marchi | 7c10c69 | 2012-01-30 18:54:45 -0200 | [diff] [blame] | 157 | KMOD_PROBE_IGNORE_LOADED = 0x00008, |
Lucas De Marchi | 4c1ffb7 | 2012-01-30 19:00:58 -0200 | [diff] [blame] | 158 | KMOD_PROBE_DRY_RUN = 0x00010, |
Lucas De Marchi | 814a57b | 2012-02-06 12:46:39 -0200 | [diff] [blame] | 159 | KMOD_PROBE_FAIL_ON_LOADED = 0x00020, |
Lucas De Marchi | b1a5125 | 2012-01-29 01:49:09 -0200 | [diff] [blame] | 160 | |
| 161 | /* codes below can be used in return value, too */ |
Lucas De Marchi | d851e9a | 2012-01-30 16:37:57 -0200 | [diff] [blame] | 162 | KMOD_PROBE_APPLY_BLACKLIST_ALL = 0x10000, |
| 163 | KMOD_PROBE_APPLY_BLACKLIST = 0x20000, |
Lucas De Marchi | 6882017 | 2012-08-17 09:38:05 -0300 | [diff] [blame] | 164 | KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY = 0x40000, |
Lucas De Marchi | ddbda02 | 2011-12-27 11:40:10 -0200 | [diff] [blame] | 165 | }; |
| 166 | |
Dave Reisner | d80b103 | 2012-02-24 10:05:11 -0500 | [diff] [blame] | 167 | /* Flags to kmod_module_apply_filter() */ |
| 168 | enum kmod_filter { |
| 169 | KMOD_FILTER_BLACKLIST = 0x00001, |
| 170 | KMOD_FILTER_BUILTIN = 0x00002, |
| 171 | }; |
| 172 | |
Lucas De Marchi | 8f788d5 | 2011-11-25 01:22:56 -0200 | [diff] [blame] | 173 | int kmod_module_remove_module(struct kmod_module *mod, unsigned int flags); |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 174 | int kmod_module_insert_module(struct kmod_module *mod, unsigned int flags, |
| 175 | const char *options); |
Lucas De Marchi | ddbda02 | 2011-12-27 11:40:10 -0200 | [diff] [blame] | 176 | int kmod_module_probe_insert_module(struct kmod_module *mod, |
Lucas De Marchi | 6a82921 | 2012-01-09 03:08:26 -0200 | [diff] [blame] | 177 | unsigned int flags, const char *extra_options, |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 178 | int (*run_install)(struct kmod_module *m, |
| 179 | const char *cmdline, void *data), |
Lucas De Marchi | 6bd0713 | 2012-01-30 17:02:06 -0200 | [diff] [blame] | 180 | const void *data, |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 181 | void (*print_action)(struct kmod_module *m, bool install, |
| 182 | const char *options)); |
| 183 | |
Lucas De Marchi | 8f788d5 | 2011-11-25 01:22:56 -0200 | [diff] [blame] | 184 | |
Gustavo Sverzut Barbieri | 1ce08a5 | 2011-12-02 20:24:07 -0200 | [diff] [blame] | 185 | const char *kmod_module_get_name(const struct kmod_module *mod); |
| 186 | const char *kmod_module_get_path(const struct kmod_module *mod); |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 187 | const char *kmod_module_get_options(const struct kmod_module *mod); |
| 188 | const char *kmod_module_get_install_commands(const struct kmod_module *mod); |
| 189 | const char *kmod_module_get_remove_commands(const struct kmod_module *mod); |
| 190 | struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod); |
| 191 | int kmod_module_get_softdeps(const struct kmod_module *mod, |
| 192 | struct kmod_list **pre, struct kmod_list **post); |
| 193 | int kmod_module_get_filtered_blacklist(const struct kmod_ctx *ctx, |
| 194 | const struct kmod_list *input, |
Dave Reisner | d80b103 | 2012-02-24 10:05:11 -0500 | [diff] [blame] | 195 | struct kmod_list **output) __attribute__ ((deprecated)); |
| 196 | int kmod_module_apply_filter(const struct kmod_ctx *ctx, |
| 197 | enum kmod_filter filter_type, |
| 198 | const struct kmod_list *input, |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 199 | struct kmod_list **output); |
| 200 | |
| 201 | |
| 202 | |
| 203 | /* |
| 204 | * Information regarding "live information" from module's state, as returned |
| 205 | * by kernel |
| 206 | */ |
Lucas De Marchi | 6e869df | 2011-11-30 19:01:01 -0200 | [diff] [blame] | 207 | |
Gustavo Sverzut Barbieri | f12ae3c | 2011-12-04 12:40:00 -0200 | [diff] [blame] | 208 | enum kmod_module_initstate { |
| 209 | KMOD_MODULE_BUILTIN = 0, |
| 210 | KMOD_MODULE_LIVE, |
| 211 | KMOD_MODULE_COMING, |
Lucas De Marchi | 49b741d | 2011-12-05 11:42:12 -0200 | [diff] [blame] | 212 | KMOD_MODULE_GOING, |
| 213 | /* Padding to make sure enum is not mapped to char */ |
| 214 | _KMOD_MODULE_PAD = (1 << 31), |
Gustavo Sverzut Barbieri | f12ae3c | 2011-12-04 12:40:00 -0200 | [diff] [blame] | 215 | }; |
Lucas De Marchi | 6a82921 | 2012-01-09 03:08:26 -0200 | [diff] [blame] | 216 | const char *kmod_module_initstate_str(enum kmod_module_initstate state); |
Gustavo Sverzut Barbieri | f12ae3c | 2011-12-04 12:40:00 -0200 | [diff] [blame] | 217 | int kmod_module_get_initstate(const struct kmod_module *mod); |
| 218 | int kmod_module_get_refcnt(const struct kmod_module *mod); |
| 219 | struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod); |
Gustavo Sverzut Barbieri | f12ae3c | 2011-12-04 12:40:00 -0200 | [diff] [blame] | 220 | struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod); |
| 221 | const char *kmod_module_section_get_name(const struct kmod_list *entry); |
| 222 | unsigned long kmod_module_section_get_address(const struct kmod_list *entry); |
| 223 | void kmod_module_section_free_list(struct kmod_list *list); |
Gustavo Sverzut Barbieri | 69f9dd4 | 2011-12-04 14:02:30 -0200 | [diff] [blame] | 224 | long kmod_module_get_size(const struct kmod_module *mod); |
Gustavo Sverzut Barbieri | f12ae3c | 2011-12-04 12:40:00 -0200 | [diff] [blame] | 225 | |
Gustavo Sverzut Barbieri | bd3f553 | 2011-12-10 20:47:01 -0200 | [diff] [blame] | 226 | |
Lucas De Marchi | 9226dda | 2012-01-31 17:23:35 -0200 | [diff] [blame] | 227 | |
| 228 | /* |
| 229 | * Information retrieved from ELF headers and sections |
| 230 | */ |
Gustavo Sverzut Barbieri | 1c52260 | 2011-12-16 21:18:10 -0200 | [diff] [blame] | 231 | |
Gustavo Sverzut Barbieri | 708624a | 2011-12-18 01:25:06 -0200 | [diff] [blame] | 232 | int kmod_module_get_info(const struct kmod_module *mod, struct kmod_list **list); |
| 233 | const char *kmod_module_info_get_key(const struct kmod_list *entry); |
| 234 | const char *kmod_module_info_get_value(const struct kmod_list *entry); |
| 235 | void kmod_module_info_free_list(struct kmod_list *list); |
| 236 | |
| 237 | int kmod_module_get_versions(const struct kmod_module *mod, struct kmod_list **list); |
| 238 | const char *kmod_module_version_get_symbol(const struct kmod_list *entry); |
| 239 | uint64_t kmod_module_version_get_crc(const struct kmod_list *entry); |
| 240 | void kmod_module_versions_free_list(struct kmod_list *list); |
| 241 | |
Gustavo Sverzut Barbieri | 45e6db9 | 2011-12-19 21:23:13 -0200 | [diff] [blame] | 242 | int kmod_module_get_symbols(const struct kmod_module *mod, struct kmod_list **list); |
| 243 | const char *kmod_module_symbol_get_symbol(const struct kmod_list *entry); |
| 244 | uint64_t kmod_module_symbol_get_crc(const struct kmod_list *entry); |
| 245 | void kmod_module_symbols_free_list(struct kmod_list *list); |
| 246 | |
Gustavo Sverzut Barbieri | 674f859 | 2011-12-20 11:54:53 -0200 | [diff] [blame] | 247 | enum kmod_symbol_bind { |
| 248 | KMOD_SYMBOL_NONE = '\0', |
| 249 | KMOD_SYMBOL_LOCAL = 'L', |
| 250 | KMOD_SYMBOL_GLOBAL = 'G', |
| 251 | KMOD_SYMBOL_WEAK = 'W', |
| 252 | KMOD_SYMBOL_UNDEF = 'U' |
| 253 | }; |
| 254 | |
| 255 | int kmod_module_get_dependency_symbols(const struct kmod_module *mod, struct kmod_list **list); |
| 256 | const char *kmod_module_dependency_symbol_get_symbol(const struct kmod_list *entry); |
| 257 | int kmod_module_dependency_symbol_get_bind(const struct kmod_list *entry); |
| 258 | uint64_t kmod_module_dependency_symbol_get_crc(const struct kmod_list *entry); |
| 259 | void kmod_module_dependency_symbols_free_list(struct kmod_list *list); |
| 260 | |
Lucas De Marchi | 2bd6299 | 2011-11-28 12:03:17 -0200 | [diff] [blame] | 261 | #ifdef __cplusplus |
| 262 | } /* extern "C" */ |
| 263 | #endif |
Lucas De Marchi | 586fc30 | 2011-11-21 14:35:35 -0200 | [diff] [blame] | 264 | #endif |