Newer
Older
/**
\mainpage Architecture and Design goals
The easy-soc-libs is a collection of libraries (Linux shared objects), which
provide well defined, abstract and hardware agnostic APIs for different
subsystems like WiFi, DSL, Ethernet etc.
The APIs provide interfaces to the underlying platform/hardware for setting
parameters and getting status/statistics information.
Users of the easy-soc-libs can focus on the application logic and not bother
about the nitty-gritty nuances of a platform/hardware.
See IopsysWrt design and architecture documents to know more about easy-soc-libs.
This document focuses only on the easy-soC-libs's WiFi library, which is called
\b libwifi.so.
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
Every WiFi module creates atleast one Linux network interface. Users through this
interface can set/get parameters like ssid, bssid, channel, encryption etc. of
the WiFi device. It is the WiFi module's MAC (or layer2) interface.
This interface can function in one of the various WiFi modes that a WiFi
module supports viz. AP (or Master), Client (or managed), Monitor, AdHoc etc.
Since, IOPSYSWRT is a Router/AP/Gateway software, the WiFI interfaces which
function in either AP or Client modes are of interest and can be managed through
the easy-soc-libs's "libwifi" library.
Any 'real' network interface must also have a PHY associated with it for it to
communicate with the world. In WiFi, this PHY device is the WiFi's Radio interface.
The Radio interface has its own set of registers, fifos, states and status. It
represents Layer1 of the WiFI device.
Thus, a WiFi device can be represented as a Radio interface plus a MAC
interface.
For simplicity, the MAC interface is called only interface (i.e. without the MAC
part), and the radio interface is called radio.
Libwifi's API header file "wifi.h" defines data structures that map to a WiFi
device's radio and ap-interface - "struct wifi_radio" and "struct wifi_ap"
respectively.
\dot
digraph wrel {
wl0 [shape=box label="wlan0"]
wl1 [shape=box label="wlan0.1"]
wl2 [shape=box label="wlan0.2"]
wl3 [shape=box label="wlan0.3"]
wl [shape=box label="WiFi Radio \"wlan0\""]
{wl0, wl1, wl2, wl3} -> wl
}
\enddot
In the above figure, the first (or main) interface name is "wlan0", which is the
same as the radio name "wlan0". Additional (virtual) interfaces have names
wlan0.1, wlan0.2 etc. and so on.
\page dev_new_driver Add support for a new WiFi module
This chapter describes how to easily add support for a "new_wifi" WiFi module.
\section dev_new_wifi_add Implement libwifi APIs for the new WiFi module
It is broadly a four step process:
Step 1. Create a new file "new_wifi_driver.c" within the 'modules' directory.
This file will implement radio and ap related operations for the new wifi.
Define structure instance for the new_wifi driver's operations as follows -
\code
struct wifi_driver new_wifi = {
.name = "new", /* new_wifi driver creates interface names starting with this */
.radio.info = new_wifi_radio_info,
.ap.get_ssid = new_wifi_get_ssid,
.get_channel = new_wifi_get_channel,
/* Add others operations as necessary */
/* See 'nlwifi.c' within the 'modules' folder for implementation of nl/cfg80211 drivers. */
};
\endcode
Step 2. Add "new_wifi" in drivers.c -
\code
const struct wifi_driver *wifi_drivers[] = {
:
:
.
#ifdef NEW_WIFI_MODULE
&new_wifi,
#endif
};
\endcode
Step 3. Add in drivers.h file the following lines -
\code
:
:
.
#ifdef NEW_WIFI_MODULE
extern const struct wifi_driver new_wifi;
#endif
\endcode
Step 4. Finally include "new_wifi" to the build -
Add in the Makefile
\code
:
.
objs_lib += modules/new_wifi_driver.o
\endcode
After successfully building the package with the new_wifi module, a couple of
*.so files will be generated -
libwifi-X.so.a.b.c\n
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
[where X = is based on the wifi.h file's version implementation,\n
a, b, c = major, minor and revision number of the libwifi-X.so.a]
\page dev_new_driver_events Add support for receiving events in new WiFi module
\section HOWTO Register, receive and dispatch events in the new WiFi module
This section describes how to easily add support for receiving (f.e. from a new
netlink family/group) and dispatching of events in the "new_wifi" module.
Step 1. Implement the events' registration and receive functions -
In new_wifi_driver.c file, implement "register_event" and "recv_event"
operations -
\code
struct wifi_driver new_wifi = {
:
:
.
.register_event = new_wifi_register_event,
.recv_event = nlwifi_recv_event,
:
};
\endcode
\code
int new_wifi_register_event(const char *ifname, struct event_struct *req,
void **handle)
{
/* handle new_wifi vendor events, if any */
if (!strncmp(req->family, "nl80211", 7) &&
!(strncmp(req->group, "vendor", 6))) {
req->override_cb = new_wifi_handle_vendor_event;
}
return nlwifi_register_event(ifname, req, handle);
}
\endcode
\code
int new_wifi_handle_vendor_event(struct event_struct *ev)
{
struct nlwifi_event_vendor_resp *r =
(struct nlwifi_event_vendor_resp *)ev->resp.data;
if (r->oui != OUI_NEW_WIFI)
return 0; /* discard as not ours */
/* 'r->subcmd' holds vendor specific commands for handling */
:
:
.
/* dispatch event through 'ev->cb()' after any processing etc. */
if (ev->cb) {
return ev->cb(ev);
}
return 0;
}
\endcode
Libwifi's internal API 'nlwifi_recv_event' is used here receive the new_wifi
driver's "nl80211" vendor specific events.
Obviously, any netlink famiy/group can be easily supported by implementing the
'register_event' and 'recv_event' functions.
\page page_user_app Using libwifi APIs
\section user_app_cmds Functions and APIs
Making use of the libwifi APIs is easy. Users simply include the library header
"wifi.h" in their main application code, and build by linking against the
library .so file with the "-lwifi-6" flag.
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
User application can use the libwifi_supports() API to check if a specific API
is implemented for the WiFi module.
\section user_app_events Receiving Events
Receiving events through libwifi is also easy. The user application first has to
initialize the struct event_struct with information about the event of interest.
It then calls wifi_register_event() to register for the event, passing a 'void*
handle' as the last argument to the function.
In order to receive events, the application has to call wifi_recv_event(), again
passing the same 'void *handle' pointer that it passed to the register function.
\code
int app_register_and_recv_event(struct app_private *priv, ...)
{
:
int ret;
int err;
void *handle;
struct event_struct event;
:
.
/* prepare event_struct for registration */
memset(&event, 0, sizeof(struct event_struct));
strncpy(event.ifname, ifname, 16); /* interface name */
strncpy(event.family, family, 32); /* netlink family name */
strncpy(event.group, group, 32); /* netlink group name */
event.priv = priv; /* application private data */
event.cb = app_event_cb; /* callback function after recv event */
/* setup response buffer */
event.resp.data = calloc(512, sizeof(uint8_t));
if (event.resp.data == NULL)
return -ENOMEM;
:
.
ret = wifi_register_event((char *)ifname, &event, &handle);
if (ret)
return ret; /* handle error */
/* receive events */
for (;;) {
err = wifi_recv_event((char *)ifname, handle);
if (err < 0)
fprintf(stderr, "Error: %s\n", __func__);
}
return 0;
}
\endcode
and
\code
int app_event_cb(struct event_struct *e)
{
struct app_private *priv = (struct app_private *)e->priv;
struct event_response *resp = &e->resp;
char evtbuf[512] = {0};
switch (resp->type) {
case WIFI_EVENT_SCAN_START:
/* handle events */
/* resp holds event response buffer, if any */
break;
case WIFI_EVENT_SCAN_END:
:
.
}
:
}
\endcode
*/