wimax-tools 1.4.4
|
This set of helpers simplify the task of sending commands / waiting for the acks and receiving reports/indications from the i2400m. More...
Functions | |
int | i2400m_create (struct i2400m **_i2400m, const char *ifname, void *priv, i2400m_report_cb report_cb) |
Create a i2400m handle. | |
int | i2400m_create_from_handle (struct i2400m **_i2400m, struct wimaxll_handle *wmx, void *priv, i2400m_report_cb report_cb) |
Create a i2400m handle from an existing WiMAX handle. | |
void | i2400m_destroy (struct i2400m *i2400m) |
Destroy a descriptor created with i2400m_create() | |
void * | i2400m_priv (struct i2400m *i2400m) |
Return the private data associated to a i2400m. | |
struct wimaxll_handle * | i2400m_wmx (struct i2400m *i2400m) |
Return the libwimaxll handle associated to a i2400m. | |
int | i2400m_msg_to_dev (struct i2400m *i2400m, const struct i2400m_l3l4_hdr *l3l4, size_t l3l4_size, i2400m_reply_cb cb, void *cb_priv) |
Execute an i2400m command and wait for a response. | |
ssize_t | i2400m_tlv_match (const struct i2400m_tlv_hdr *tlv, enum i2400m_tlv tlv_type, ssize_t tlv_size) |
Return if a TLV is of a give type and size. | |
struct i2400m_tlv_hdr * | i2400m_tlv_buffer_walk (const void *tlv_buf, size_t buf_size, const struct i2400m_tlv_hdr *tlv_pos) |
Iterate over a buffer of TLVs. | |
struct i2400m_tlv_hdr * | i2400m_tlv_find (const struct i2400m_tlv_hdr *tlv_hdr, size_t size, enum i2400m_tlv tlv_type, ssize_t tlv_size) |
Find a TLV by type (and maybe length) in a buffer of TLVs. |
This set of helpers simplify the task of sending commands / waiting for the acks and receiving reports/indications from the i2400m.
It boils down to a framework to support that only one thread can send a command at the same time; this is because the commands don't have a cookie to identify the issuer -- so a place is needed where to store the "I am waiting for a response for command X".
When the callback from libwimaxll comes back with the response, if it was a reply to said message, then the waiter for that is woken up (using pthread mutexes and conditional variables). See Thread cancellation for more information on what happens when the thread is cancelled.
When a report is received, the report callback is called; care has to be taken not to deadlock. See i2400m_report_cb().
For usage, create a handle:
{ int r; struct i2400m *i2400m; ... r = i2400m_create(&i2400m, "wmx0", my_priv_pointer, my_report_cb); if (r < 0) error; ... // create a message ... r = i2400m_msg_to_dev(i2400m, &message, message_size, message_cb, message_cb_priv); if (r < 0) error; // message_cb has been called i2400m_destroy(i2400m); }
Remember there are limited things that can be done in the callback; calling i2400m_msg_to_dev() will deadlock, as well as waiting for a report.
A report callback with some TLV processing example would be:
static void my_report_cb(struct i2400m *i2400m, const struct i2400m_l3l4_hdr *l3l4, size_t l3l4_size) { struct my_priv *my_priv = i2400m_priv(i2400m); struct wimaxll_handle *wmx = i2400m_wmx(i2400m); // do something with the report...; struct i2400m_tlv *tlv = NULL; while ((tlv = i2400m_tlv_buffer_walk(l3l4->pl, l3l4_size, tlv))) { tlv_type = wimaxll_le16_to_cpu(tlv->type); tlv_length = wimaxll_le16_to_cpu(tlv->length); // do whatever with the tlv } // or find a tlv in a buffer tlv = i2400m_tlv_find(l3l4->pl, l3l4_size - sizeof(*l3l4), I2400M_TLV_SOMETHING, -1); }
All the code that takes mutexes pushes a cleanup handler that will unlock the mutex if the thread is cancelled. This is designed to work only with deferred thread cancellation models. Check POSIX for more information.
int i2400m_create | ( | struct i2400m ** | _i2400m, |
const char * | ifname, | ||
void * | priv, | ||
i2400m_report_cb | report_cb | ||
) |
Create a i2400m handle.
Creates a handle usable to execute commands and use the i2400m helpers.
_i2400m | where to store the handler value (pointer to the descriptor). |
ifname | name of the network interface where the i2400m is |
priv | Pointer that the callbacks can recover from the handle with i2400m_priv() |
report_cb | Callback function called when a report arrives |
int i2400m_create_from_handle | ( | struct i2400m ** | _i2400m, |
struct wimaxll_handle * | wmx, | ||
void * | priv, | ||
i2400m_report_cb | report_cb | ||
) |
Create a i2400m handle from an existing WiMAX handle.
Creates a handle usable to execute commands and use the i2400m helpers.
_i2400m | where to store the handler value (pointer to the descriptor). |
wmx | WiMAX handle to use |
priv | Pointer that the callbacks can recover from the handle with i2400m_priv() |
report_cb | Callback function called when a report arrives |
void i2400m_destroy | ( | struct i2400m * | i2400m | ) |
Destroy a descriptor created with i2400m_create()
i2400m | Handle for an i2400m as returned by i2400m_create(). |
int i2400m_msg_to_dev | ( | struct i2400m * | i2400m, |
const struct i2400m_l3l4_hdr * | l3l4, | ||
size_t | l3l4_size, | ||
i2400m_reply_cb | cb, | ||
void * | cb_priv | ||
) |
Execute an i2400m command and wait for a response.
i2400m | i2400m handle |
l3l4 | Pointer to buffer containing a L3L4 message to send to the device. |
l3l4_size | size of the buffer pointed to by l3l4 (this includes the message header and the TLV payloads, if any) |
cb | Callback function to execute when the reply is received. |
cb_priv | Private pointer to pass to the callback function. |
If the message execution fails in the device, the return value from wimaxll_msg_write() will tell it. It can also be taken (with more detail) by setting a callback function and parsing the reply.
This call can be executed from multiple threads on the same i2400m handle at the same time, as it will be mutexed properly and only one will execute at the same time (likewise, the driver will make sure only one command from different threads is ran at the same time).
This call blocks waiting for the reply to the message; from the callback context no calls to i2400m_msg_dev() or waits for reports on the same handle as the callback can be done, as it would deadlock.
void* i2400m_priv | ( | struct i2400m * | i2400m | ) |
Return the private data associated to a i2400m.
i2400m | i2400m handle |
struct i2400m_tlv_hdr* i2400m_tlv_buffer_walk | ( | const void * | tlv_buf, |
size_t | buf_size, | ||
const struct i2400m_tlv_hdr * | tlv_pos | ||
) | [read] |
Iterate over a buffer of TLVs.
Allows to safely iterate over a buffer of TLVs, making sure bounds are properly checked. Usage:
tlv_itr = NULL; while (tlv_itr = i2400m_tlv_buffer_walk(i2400m, buf, size, tlv_itr)) { ... // Do stuff with tlv_itr, DON'T MODIFY IT ... }
tlv_buf | pointer to the beginning of the TLV buffer |
buf_size | buffer size in bytes |
tlv_pos | seek position; this is assumed to be a pointer returned by i2400m_tlv_buffer_walk() [and thus, validated]. The TLV returned will be the one following this one. |
Referenced by i2400m_tlv_find().
struct i2400m_tlv_hdr* i2400m_tlv_find | ( | const struct i2400m_tlv_hdr * | tlv_hdr, |
size_t | size, | ||
enum i2400m_tlv | tlv_type, | ||
ssize_t | tlv_size | ||
) | [read] |
Find a TLV by type (and maybe length) in a buffer of TLVs.
tlv_hdr | pointer to the first TLV in the sequence |
size | size of the buffer in bytes; all TLVs are assumed to fit fully in the buffer (otherwise we'll complain). |
tlv_type | type of the TLV we are looking for |
tlv_size | expected size of the TLV we are looking for (if -1, don't check the size). This includes the header |
ssize_t i2400m_tlv_match | ( | const struct i2400m_tlv_hdr * | tlv, |
enum i2400m_tlv | tlv_type, | ||
ssize_t | tlv_size | ||
) |
Return if a TLV is of a give type and size.
tlv | pointer to the TLV |
tlv_type | type of the TLV we are looking for |
tlv_size | expected size of the TLV we are looking for (if -1, don't check the size). Size includes the TLV header. |
Referenced by i2400m_tlv_find().
struct wimaxll_handle* i2400m_wmx | ( | struct i2400m * | i2400m | ) | [read] |
Return the libwimaxll handle associated to a i2400m.
i2400m | i2400m handle |