wimax-tools 1.4.4
|
00001 /* 00002 * Linux WiMax 00003 * User Space API 00004 * 00005 * 00006 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. 00007 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * * Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * * Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in 00017 * the documentation and/or other materials provided with the 00018 * distribution. 00019 * * Neither the name of Intel Corporation nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00026 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00027 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00028 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00029 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00030 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00031 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 * 00036 * 00037 */ 00038 /** 00039 * @mainpage 00040 * 00041 * This is a simple library to control WiMAX devices through the 00042 * control API exported by the Linux kernel WiMAX Stack. It provides 00043 * means to execute functions exported by the stack and to receive its 00044 * notifications. 00045 * 00046 * Because of this, this is a callback oriented library. It is 00047 * designed to be operated asynchronously and/or in an event loop. For 00048 * the very simple cases, helpers that implement synchronous 00049 * functionality are available. 00050 * 00051 * This library is provided as a convenience and using it is not 00052 * required to talk to the WiMAX kernel stack. It is possible to do so 00053 * by interacting with it over generic netlink directly. 00054 * 00055 * \note this is a very low level library. It does not provide the 00056 * caller with means to scan, connect, disconnect, etc from a WiMAX 00057 * network. Said capability is provided by higher level services which 00058 * might be users of this library. 00059 * 00060 * @section conventions Conventions 00061 * 00062 * Most function calls return an integer with a negative \a errno 00063 * error code when there is an error. 00064 * 00065 * @section general_usage General usage 00066 * 00067 * The first operation to start controlling a WiMAX device is to open 00068 * a handle for it: 00069 * 00070 * @code 00071 * struct wimaxll_handle *wmx = wimaxll_open("wmx0"); 00072 * @endcode 00073 * 00074 * With an open handle you can execute all the WiMax API 00075 * operations. When done with the handle, it has to be closed: 00076 * 00077 * @code 00078 * wimaxll_close(wmx); 00079 * @endcode 00080 * 00081 * If the device is unloaded/disconnected, the handle will be marked 00082 * as invalid and any operation will fail with -ENODEV. 00083 * 00084 * To reset a WiMAX device, use: 00085 * 00086 * @code 00087 * wimaxll_reset(wmx); 00088 * @endcode 00089 * 00090 * To turn a device \e on or \e off, or to query it's status, use: 00091 * 00092 * @code 00093 * wimaxll_rfkill(wmx, WIMAX_RF_ON); 00094 * @endcode 00095 * 00096 * WIMAX_RF_ON and WIMAX_RF_OFF turn the radio on and off 00097 * respectively, using the software switch and return the current 00098 * status of both switches. WIMAX_RF_QUERY just returns the status of 00099 * both the \e HW and \e SW switches. 00100 * 00101 * See \ref device_management "device management" for more information. 00102 * 00103 * \section receiving Receiving notifications from the WiMAX kernel stack 00104 * 00105 * The WiMAX kernel stack will broadcast notifications and 00106 * driver-specific messages to all the user space clients connected to 00107 * it over a generic netlink multicast group. 00108 * 00109 * To listen to said notifications, a library client needs to block 00110 * waiting for them or set \ref callbacks "callbacks" and integrate 00111 * into some kind of main loop using \e select() call to detect 00112 * incoming notifications. 00113 * 00114 * Simple example of mainloop integration: 00115 * 00116 * @code 00117 * int fd = wimaxll_recv_fd(wmx); 00118 * fd_set pipe_fds, read_fds; 00119 * ... 00120 * // Main loop 00121 * FD_ZERO(&pipe_fds); 00122 * FD_SET(fd, &pipe_fds); 00123 * while(1) { 00124 * read_fds = pipe_fds; 00125 * select(FD_SETSIZE, &read_fds, NULL, NULL, NULL); 00126 * if (FD_ISSET(fd, &read_fds)) 00127 * wimaxll_recv(wmx); 00128 * } 00129 * @endcode 00130 * 00131 * This code will call wimaxll_recv() when notifications are available 00132 * for delivery. Calling said function will execute, for each 00133 * notification, the callback associated to it. 00134 * 00135 * To wait for a \e state \e change notification, for example: 00136 * 00137 * @code 00138 * result = wimaxll_wait_for_state_change(wmx, &old_state, &new_state); 00139 * @endcode 00140 * 00141 * The same thing can be accomplished setting a callback for a state 00142 * change notification with wimaxll_set_cb_state_change() and then 00143 * waiting on a main loop. See \ref state_change_group "state changes" 00144 * for more information. 00145 * 00146 * To wait for a (device-specific) message from the driver, an 00147 * application would use: 00148 * 00149 * @code 00150 * void *msg; 00151 * ... 00152 * 00153 * size = wimaxll_msg_read(wmx, &msg); 00154 * 00155 * ... <act on the message> 00156 * 00157 * wimaxll_msg_free(msg); // done with the message 00158 * @endcode 00159 * 00160 * \e msg points to a buffer which contains the message payload as 00161 * sent by the driver. When done with \a msg it has to be freed with 00162 * wimaxll_msg_free(). 00163 * 00164 * As with \e state \e change notifications, a callback can be set 00165 * that will be executed from a mainloop every time a message is 00166 * received from a message pipe. See 00167 * wimaxll_pipe_set_cb_msg_to_user(). 00168 * 00169 * A message can be sent to the driver with wimaxll_msg_write(). 00170 * not the default \e message pipe. 00171 * 00172 * For more details, see \ref the_messaging_interface. 00173 * 00174 * @section miscellaneous Miscellaneous 00175 * 00176 * @subsection diagnostics Controlling the ouput of diagnostics 00177 * 00178 * \e libwimaxll will output messages by default to \a stderr. See 00179 * \ref helper_log for changing the default destination. 00180 * 00181 * @subsection bytesex Endianess conversion 00182 * 00183 * The following convenience helpers are provided for endianess 00184 * conversion: 00185 * 00186 * - wimaxll_le32_to_cpu() and wimaxll_cpu_to_le32() 00187 * - wimaxll_le16_to_cpu() and wimaxll_cpu_to_le16() 00188 * - wimaxll_swap_16() and wimaxll_swap_32() 00189 * 00190 * @section multithreading Multithreading 00191 * 00192 * This library is not threaded or locked. Internally it uses two 00193 * different netlink handles, one for receiving and one for sending; 00194 * thus the maximum level of paralellism you can do with one handle 00195 * is: 00196 * 00197 * - Functions that can't be executed in parallel when using the same 00198 * wimaxll handle (need to be serialized): 00199 * <ul> 00200 * <li> wimaxll_msg_write(), wimaxll_rfkill(), wimax_reset() 00201 * <li> wimaxll_recv(), wimaxll_msg_read(), 00202 * wimaxll_wait_for_state_change() 00203 * <li> wimax_get_cb_*() and wimax_set_cb_*(). 00204 * <li> wimaxll_recv_fd(), as long as the handle is valid. 00205 * </ul> 00206 * 00207 * - Function calls that have to be always serialized with respect to 00208 * any other: 00209 * <ul> 00210 * <li> wimaxll_open() and wimaxll_close() 00211 * <li> wimax_get_cb_*() and wimax_set_cb_*(). 00212 * </ul> 00213 * 00214 * - callbacks are all executed serially; don't call wimax_recv() from 00215 * inside a callback. 00216 * 00217 * Any function not covered by the in this list can be parallelizable. 00218 */ 00219 00220 00221 #ifndef __lib_wimaxll_h__ 00222 #define __lib_wimaxll_h__ 00223 #include <sys/errno.h> 00224 #include <sys/types.h> 00225 #include <endian.h> 00226 #include <byteswap.h> 00227 #include <stdarg.h> 00228 #include <linux/wimax.h> 00229 00230 struct wimaxll_handle; 00231 00232 struct nlattr; 00233 00234 00235 /** 00236 * \defgroup callbacks Callbacks 00237 * 00238 * When notification callbacks are being executed, the processing of 00239 * notifications from the kernel is effectively blocked by it. Care 00240 * must be taken not to call blocking functions, especially 00241 * wimaxll_recv(). 00242 * 00243 * Callbacks are always passed a pointer to a private context as set 00244 * by the application. 00245 * 00246 * Callbacks can return -%EBUSY to have wimaxll_recv() stop processing 00247 * messages and pass control to the caller (which will see it 00248 * returning -%EBUSY). Callbacks *SHOULD NOT* return -%EINPROGRESS, as 00249 * it is used internally by wimaxll_recv(). 00250 */ 00251 00252 00253 /** 00254 * Callback for a \e message \e to \e user generic netlink message 00255 * 00256 * A \e driver \e specific message has been received from the kernel; 00257 * the pointer to the data and the size are passed in \a data and \a 00258 * size. The callback can access that data, but it's lifetime is valid 00259 * only while the callback is executing. If it will be accessed later, 00260 * it has to be copied to a safe location. 00261 * 00262 * \note See \ref callbacks callbacks for a set of warnings and 00263 * guidelines for using callbacks. 00264 * 00265 * \param wmx WiMAX device handle 00266 * \param priv Context passed by the user with 00267 * wimaxll_pipe_set_cb_msg_to_user(). 00268 * \param pipe_name Name of the pipe the message is sent for 00269 * \param data Pointer to a buffer with the message data. 00270 * \param size Size of the buffer 00271 * \return >= 0 if it is ok to keep processing messages, -EBUSY if 00272 * message processing should stop and control be returned to the 00273 * caller. Any other negative error code to continue processing 00274 * messages skipping the current one. 00275 * 00276 * \ingroup the_messaging_interface 00277 */ 00278 typedef int (*wimaxll_msg_to_user_cb_f)(struct wimaxll_handle *wmx, 00279 void *priv, 00280 const char *pipe_name, 00281 const void *data, size_t size); 00282 00283 /** 00284 * Callback for a \e state \e change notification from the WiMAX 00285 * kernel stack. 00286 * 00287 * The WiMAX device has changed state from \a old_state to \a 00288 * new_state. 00289 * 00290 * \note See \ref callbacks callbacks for a set of warnings and 00291 * guidelines for using callbacks. 00292 * 00293 * \param wmx WiMAX device handle 00294 * \param priv ctx Context passed by the user with 00295 * wimaxll_set_cb_state_change(). 00296 * \param old_state State the WiMAX device left 00297 * \param new_state State the WiMAX device entered 00298 * \return >= 0 if it is ok to keep processing messages, -EBUSY if 00299 * message processing should stop and control be returned to the 00300 * caller. Any other negative error code to continue processing 00301 * messages skipping the current one. 00302 * 00303 * \ingroup state_change_group 00304 */ 00305 typedef int (*wimaxll_state_change_cb_f)( 00306 struct wimaxll_handle *, void *priv, 00307 enum wimax_st old_state, enum wimax_st new_state); 00308 00309 00310 /* Basic handle management */ 00311 struct wimaxll_handle *wimaxll_open(const char *device_name); 00312 void *wimaxll_priv_get(struct wimaxll_handle *); 00313 void wimaxll_priv_set(struct wimaxll_handle *, void *); 00314 void wimaxll_close(struct wimaxll_handle *); 00315 const char *wimaxll_ifname(const struct wimaxll_handle *); 00316 unsigned wimaxll_ifidx(const struct wimaxll_handle *); 00317 00318 /* Wait for data from the kernel, execute callbacks */ 00319 int wimaxll_recv_fd(struct wimaxll_handle *); 00320 ssize_t wimaxll_recv(struct wimaxll_handle *); 00321 00322 /* Default (bidirectional) message pipe from the kernel */ 00323 ssize_t wimaxll_msg_write(struct wimaxll_handle *, const char *, 00324 const void *, size_t); 00325 00326 void wimaxll_get_cb_msg_to_user(struct wimaxll_handle *, 00327 wimaxll_msg_to_user_cb_f *, void **); 00328 void wimaxll_set_cb_msg_to_user(struct wimaxll_handle *, 00329 wimaxll_msg_to_user_cb_f, void *); 00330 00331 #define WIMAX_PIPE_ANY (NULL-1) 00332 ssize_t wimaxll_msg_read(struct wimaxll_handle *, const char *pine_name, 00333 void **); 00334 void wimaxll_msg_free(void *); 00335 00336 /* generic API */ 00337 int wimaxll_rfkill(struct wimaxll_handle *, enum wimax_rf_state); 00338 int wimaxll_reset(struct wimaxll_handle *); 00339 int wimaxll_state_get(struct wimaxll_handle *); 00340 00341 void wimaxll_get_cb_state_change( 00342 struct wimaxll_handle *, wimaxll_state_change_cb_f *, 00343 void **); 00344 void wimaxll_set_cb_state_change( 00345 struct wimaxll_handle *, wimaxll_state_change_cb_f, 00346 void *); 00347 ssize_t wimaxll_wait_for_state_change(struct wimaxll_handle *wmx, 00348 enum wimax_st *old_state, 00349 enum wimax_st *new_state); 00350 00351 00352 /** 00353 * \defgroup miscellaneous_group Miscellaneous utilities 00354 */ 00355 enum wimax_st wimaxll_state_by_name(const char *); 00356 size_t wimaxll_states_snprintf(char *, size_t); 00357 const char * wimaxll_state_to_name(enum wimax_st); 00358 00359 #define wimaxll_array_size(a) (sizeof(a)/sizeof(a[0])) 00360 00361 #define wimaxll_container_of(pointer, type, member) \ 00362 ({ \ 00363 type *object = NULL; \ 00364 size_t offset = (void *) &object->member - (void *) object; \ 00365 (type *) ((void *) pointer - offset); \ 00366 }) 00367 00368 static inline // ugly hack for doxygen 00369 /** 00370 * 00371 * Swap the nibbles in a 16 bit number. 00372 * 00373 * \ingroup miscellaneous_group 00374 * \fn unsigned short wimaxll_swap_16(unsigned short x) 00375 */ 00376 unsigned short wimaxll_swap_16(unsigned short x) 00377 { 00378 return bswap_16(x); 00379 } 00380 00381 00382 static inline // ugly hack for doxygen 00383 /** 00384 * Swap the nibbles in a 32 bit number. 00385 * 00386 * \ingroup miscellaneous_group 00387 * \fn unsigned long wimaxll_swap_32(unsigned long x) 00388 */ 00389 unsigned long wimaxll_swap_32(unsigned long x) 00390 { 00391 return bswap_32(x); 00392 } 00393 00394 00395 static inline // ugly hack for doxygen 00396 /** 00397 * Convert a cpu-order 16 bits to little endian. 00398 * 00399 * \ingroup miscellaneous_group 00400 * \fn unsigned short wimaxll_cpu_to_le16(unsigned short x) 00401 */ 00402 unsigned short wimaxll_cpu_to_le16(unsigned short x) 00403 { 00404 unsigned short le16; 00405 #if __BYTE_ORDER == __LITTLE_ENDIAN 00406 le16 = x; 00407 #elif __BYTE_ORDER == __BIG_ENDIAN 00408 le16 = wimaxll_swap_16(x); 00409 #else 00410 #error ERROR: unknown byte sex - FIXME 00411 #endif 00412 return le16; 00413 } 00414 00415 00416 static inline // ugly hack for doxygen 00417 /** 00418 * Convert a little-endian 16 bits to cpu order. 00419 * 00420 * \ingroup miscellaneous_group 00421 * \fn unsigned short wimaxll_le16_to_cpu(unsigned short le16) 00422 */ 00423 unsigned short wimaxll_le16_to_cpu(unsigned short le16) 00424 { 00425 unsigned short cpu; 00426 #if __BYTE_ORDER == __LITTLE_ENDIAN 00427 cpu = le16; 00428 #elif __BYTE_ORDER == __BIG_ENDIAN 00429 cpu = wimaxll_swap_16(le16); 00430 #else 00431 #error ERROR: unknown byte sex - FIXME 00432 #endif 00433 return cpu; 00434 } 00435 00436 00437 static inline // ugly hack for doxygen 00438 /** 00439 * Convert a cpu-order 32 bits to little endian. 00440 * 00441 * \ingroup miscellaneous_group 00442 * \fn unsigned long wimaxll_cpu_to_le32(unsigned long x) 00443 */ 00444 unsigned long wimaxll_cpu_to_le32(unsigned long x) 00445 { 00446 unsigned long le32; 00447 #if __BYTE_ORDER == __LITTLE_ENDIAN 00448 le32 = x; 00449 #elif __BYTE_ORDER == __BIG_ENDIAN 00450 le32 = wimaxll_swap_32(x); 00451 #else 00452 #error ERROR: unknown byte sex - FIXME 00453 #endif 00454 return le32; 00455 } 00456 00457 00458 static inline // ugly hack for doxygen 00459 /** 00460 * Convert a little-endian 32 bits to cpu order. 00461 * 00462 * \ingroup miscellaneous_group 00463 * \fn unsigned long wimaxll_le32_to_cpu(unsigned long le32) 00464 */ 00465 unsigned long wimaxll_le32_to_cpu(unsigned long le32) 00466 { 00467 unsigned long cpu; 00468 #if __BYTE_ORDER == __LITTLE_ENDIAN 00469 cpu = le32; 00470 #elif __BYTE_ORDER == __BIG_ENDIAN 00471 cpu = wimaxll_swap_32(le32); 00472 #else 00473 #error ERROR: unknown byte sex - FIXME 00474 #endif 00475 return cpu; 00476 } 00477 00478 00479 static inline // ugly hack for doxygen 00480 /** 00481 * Convert a cpu-order 16 bits to big endian. 00482 * 00483 * \ingroup miscellaneous_group 00484 * \fn unsigned short wimaxll_cpu_to_be16(unsigned short x) 00485 */ 00486 unsigned short wimaxll_cpu_to_be16(unsigned short x) 00487 { 00488 unsigned short be16; 00489 #if __BYTE_ORDER == __LITTLE_ENDIAN 00490 be16 = wimaxll_swap_16(x); 00491 #elif __BYTE_ORDER == __BIG_ENDIAN 00492 be16 = x; 00493 #else 00494 #error ERROR: unknown byte sex - FIXME 00495 #endif 00496 return be16; 00497 } 00498 00499 00500 static inline // ugly hack for doxygen 00501 /** 00502 * Convert a big-endian 16 bits to cpu order. 00503 * 00504 * \ingroup miscellaneous_group 00505 * \fn unsigned short wimaxll_be16_to_cpu(unsigned short be16) 00506 */ 00507 unsigned short wimaxll_be16_to_cpu(unsigned short be16) 00508 { 00509 unsigned short cpu; 00510 #if __BYTE_ORDER == __LITTLE_ENDIAN 00511 cpu = wimaxll_swap_16(be16); 00512 #elif __BYTE_ORDER == __BIG_ENDIAN 00513 cpu = be16; 00514 #else 00515 #error ERROR: unknown byte sex - FIXME 00516 #endif 00517 return cpu; 00518 } 00519 00520 00521 static inline // ugly hack for doxygen 00522 /** 00523 * Convert a cpu-order 32 bits to big endian. 00524 * 00525 * \ingroup miscellaneous_group 00526 * \fn unsigned long wimaxll_cpu_to_be32(unsigned long x) 00527 */ 00528 unsigned long wimaxll_cpu_to_be32(unsigned long x) 00529 { 00530 unsigned long be32; 00531 #if __BYTE_ORDER == __LITTLE_ENDIAN 00532 be32 = wimaxll_swap_32(x); 00533 #elif __BYTE_ORDER == __BIG_ENDIAN 00534 be32 = x; 00535 #else 00536 #error ERROR: unknown byte sex - FIXME 00537 #endif 00538 return be32; 00539 } 00540 00541 00542 static inline // ugly hack for doxygen 00543 /** 00544 * Convert a big-endian 32 bits to cpu order. 00545 * 00546 * \ingroup miscellaneous_group 00547 * \fn unsigned long wimaxll_be32_to_cpu(unsigned long be32) 00548 */ 00549 unsigned long wimaxll_be32_to_cpu(unsigned long be32) 00550 { 00551 unsigned long cpu; 00552 #if __BYTE_ORDER == __LITTLE_ENDIAN 00553 cpu = be32; 00554 #elif __BYTE_ORDER == __BIG_ENDIAN 00555 cpu = wimaxll_swap_32(be32); 00556 #else 00557 #error ERROR: unknown byte sex - FIXME 00558 #endif 00559 return cpu; 00560 } 00561 00562 00563 #define __WIMAXLL_ALIGN2_MASK(n, m) (((n) + (m)) & ~(m)) 00564 /** 00565 * Return the value \e n aligned to an order-of-two value \a o2. 00566 */ 00567 #define WIMAXLL_ALIGN2(n, o2) __WIMAXLL_ALIGN2_MASK(n, (typeof(n)) (o2) - 1) 00568 00569 #endif /* #ifndef __lib_wimaxll_h__ */