~jocave/checkbox/hybrid-amd-gpu-mods

« back to all changes in this revision

Viewing changes to providers/plainbox-provider-resource-generic/src/80211_resource.c

  • Committer: Zygmunt Krynicki
  • Date: 2013-05-17 13:54:25 UTC
  • mto: This revision was merged to the branch mainline in revision 2130.
  • Revision ID: zygmunt.krynicki@canonical.com-20130517135425-cxcenxx5t0qrtbxd
checkbox-ng: add CheckBoxNG sub-project

CheckBoxNG (or lowercase as checkbox-ng, pypi:checkbox-ng) is a clean
implementation of CheckBox on top of PlainBox. It provides a new
executable, 'checkbox' that has some of the same commands that were
previously implemented in the plainbox package.

In particular CheckBoxNG comes with the 'checkbox sru' command
(the same one as in plainbox). Later on this sub-command will be removed
from plainbox.

CheckBoxNG depends on plainbox >= 0.3

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Lite version of iw (the nl80211 userspace tool)
3
 
 *
4
 
 * Copyright (c) 2014  Sylvain Pineau <sylvain.pineau@canonical.com>
5
 
 *
6
 
 * This file incorporates work covered by the following copyright and
7
 
 * permission notice:
8
 
 *
9
 
 * Copyright (c) 2007, 2008     Johannes Berg <johannes@sipsolutions.net>
10
 
 * Copyright (c) 2007           Andy Lutomirski
11
 
 * Copyright (c) 2007           Mike Kershaw
12
 
 * Copyright (c) 2008-2009      Luis R. Rodriguez
13
 
 *
14
 
 * Permission to use, copy, modify, and/or distribute this software for any
15
 
 * purpose with or without fee is hereby granted, provided that the above
16
 
 * copyright notice and this permission notice appear in all copies.
17
 
 *
18
 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19
 
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20
 
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21
 
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22
 
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23
 
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24
 
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
 
 */
26
 
 
27
 
#include <stdlib.h>
28
 
#include <stdio.h>
29
 
#include <string.h>
30
 
#include <errno.h>
31
 
#include <stdbool.h>
32
 
 
33
 
#include <netlink/genl/genl.h>
34
 
#include <netlink/genl/ctrl.h>
35
 
 
36
 
#include <linux/nl80211.h>
37
 
 
38
 
#include "config.h"
39
 
 
40
 
struct nl80211_state {
41
 
        struct nl_sock *nl_sock;
42
 
        int nl80211_id;
43
 
};
44
 
 
45
 
struct wireless_capabilities {
46
 
  unsigned int ac_support : 1;
47
 
  unsigned int n_support : 1;
48
 
  unsigned int bg_support : 1;
49
 
  unsigned int band_5GHz_support : 1;
50
 
};
51
 
 
52
 
static const char *ifmodes[] = {
53
 
        "unspecified",
54
 
        "IBSS",
55
 
        "managed",
56
 
        "AP",
57
 
        "AP_VLAN",
58
 
        "WDS",
59
 
        "monitor",
60
 
        "mesh_point",
61
 
        "P2P_client",
62
 
        "P2P_GO",
63
 
        "P2P_device",
64
 
};
65
 
 
66
 
#define BIT(x) (1ULL<<(x))
67
 
 
68
 
static int nl80211_init(struct nl80211_state *state)
69
 
{
70
 
        int err;
71
 
 
72
 
        state->nl_sock = nl_socket_alloc();
73
 
        if (!state->nl_sock) {
74
 
                fprintf(stderr, "Failed to allocate netlink socket.\n");
75
 
                return -ENOMEM;
76
 
        }
77
 
 
78
 
        nl_socket_set_buffer_size(state->nl_sock, 8192, 8192);
79
 
 
80
 
        if (genl_connect(state->nl_sock)) {
81
 
                fprintf(stderr, "Failed to connect to generic netlink.\n");
82
 
                err = -ENOLINK;
83
 
                goto out_handle_destroy;
84
 
        }
85
 
 
86
 
        state->nl80211_id = genl_ctrl_resolve(state->nl_sock, "nl80211");
87
 
        if (state->nl80211_id < 0) {
88
 
                fprintf(stderr, "nl80211 not found.\n");
89
 
                err = -ENOENT;
90
 
                goto out_handle_destroy;
91
 
        }
92
 
 
93
 
        return 0;
94
 
 
95
 
 out_handle_destroy:
96
 
        nl_socket_free(state->nl_sock);
97
 
        return err;
98
 
}
99
 
 
100
 
static void nl80211_cleanup(struct nl80211_state *state)
101
 
{
102
 
        nl_socket_free(state->nl_sock);
103
 
}
104
 
 
105
 
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
106
 
                         void *arg)
107
 
{
108
 
        int *ret = arg;
109
 
        *ret = err->error;
110
 
        return NL_STOP;
111
 
}
112
 
 
113
 
static int finish_handler(struct nl_msg *msg, void *arg)
114
 
{
115
 
        int *ret = arg;
116
 
        *ret = 0;
117
 
        return NL_SKIP;
118
 
}
119
 
 
120
 
/* Search for a specific pattern inside the given file handle.
121
 
 * @arg fp         a FILE pointer
122
 
 * @arg pattern    the search pattern
123
 
 *
124
 
 * @return 0 on success 1 otherwise.
125
 
 */
126
 
static int heuristic_test(FILE *fp, const char *pattern)
127
 
{
128
 
    char *line = NULL;
129
 
    size_t len = 0;
130
 
    ssize_t read;
131
 
    char *p;
132
 
 
133
 
    while ((read = getline(&line, &len, fp)) != -1) {
134
 
        if ((p = strstr(line, pattern)) != NULL) {
135
 
            return 0;
136
 
        }
137
 
    }
138
 
    free(line);
139
 
    return 1;
140
 
}
141
 
 
142
 
static int print_phy_handler(struct nl_msg *msg, void *arg)
143
 
{
144
 
        struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
145
 
        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
146
 
        struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
147
 
        struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
148
 
        struct nlattr *nl_band;
149
 
        struct nlattr *nl_freq;
150
 
        struct nlattr *nl_mode;
151
 
        struct wireless_capabilities *cap = arg;
152
 
        int rem_band, rem_freq, rem_mode;
153
 
 
154
 
        nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
155
 
                  genlmsg_attrlen(gnlh, 0), NULL);
156
 
 
157
 
        if (tb_msg[NL80211_ATTR_WIPHY_BANDS]) {
158
 
                nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {
159
 
                        nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
160
 
                                  nla_len(nl_band), NULL);
161
 
            /* 802.11ac is also known as Very High Throughput (VHT) */
162
 
#if HAVE_NL80211_BAND_ATTR_VHT_CAPA && HAVE_NL80211_BAND_ATTR_VHT_MCS_SET
163
 
            if (tb_band[NL80211_BAND_ATTR_VHT_CAPA] &&
164
 
                            tb_band[NL80211_BAND_ATTR_VHT_MCS_SET])
165
 
                                cap->ac_support = true;
166
 
#endif
167
 
#if HAVE_NL80211_BAND_ATTR_HT_CAPA
168
 
            /* 802.11n can use a new set of rates designed specifically for high throughput (HT) */
169
 
            if (tb_band[NL80211_BAND_ATTR_HT_CAPA])
170
 
                                cap->n_support = true;
171
 
#endif
172
 
            /* Always assume 802.11b/g support */
173
 
            cap->bg_support = true;
174
 
 
175
 
                        if (tb_band[NL80211_BAND_ATTR_FREQS]) {
176
 
                                nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
177
 
                                        uint32_t freq;
178
 
                                        nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
179
 
                                                  nla_len(nl_freq), NULL);
180
 
                                        if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
181
 
                                                continue;
182
 
                    if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) {
183
 
                        continue;
184
 
                    }
185
 
                                        freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
186
 
                    /* http://en.wikipedia.org/wiki/List_of_WLAN_channels */
187
 
                    if (freq >= 4915 && freq <= 5825) 
188
 
                                                cap->band_5GHz_support = true;
189
 
                                }
190
 
                        }
191
 
                }
192
 
        }
193
 
 
194
 
        if (tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]) {
195
 
                nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES], rem_mode) {
196
 
            enum nl80211_iftype iftype = nla_type(nl_mode);
197
 
            if (iftype <= NL80211_IFTYPE_MAX && ifmodes[iftype])
198
 
                printf("%s: supported\n", ifmodes[iftype]);
199
 
        }
200
 
        }
201
 
 
202
 
    return 0;
203
 
}
204
 
 
205
 
int main(int argc, char **argv)
206
 
{
207
 
        struct nl80211_state nlstate;
208
 
        struct wireless_capabilities cap;
209
 
        int err;
210
 
        FILE *pci_fp;
211
 
 
212
 
        err = nl80211_init(&nlstate);
213
 
        if (err)
214
 
                return 1;
215
 
 
216
 
        struct nl_cb *cb;
217
 
        struct nl_cb *s_cb;
218
 
        struct nl_msg *msg;
219
 
 
220
 
        msg = nlmsg_alloc();
221
 
        if (!msg) {
222
 
                fprintf(stderr, "failed to allocate netlink message\n");
223
 
                return 2;
224
 
        }
225
 
 
226
 
        cb = nl_cb_alloc(NL_CB_DEFAULT);
227
 
        s_cb = nl_cb_alloc(NL_CB_DEFAULT);
228
 
        if (!cb || !s_cb) {
229
 
                fprintf(stderr, "failed to allocate netlink callbacks\n");
230
 
                err = 2;
231
 
                goto out_free_msg;
232
 
        }
233
 
 
234
 
        genlmsg_put(msg, 0, 0, nlstate.nl80211_id, 0,
235
 
                    NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
236
 
 
237
 
        nl_socket_set_cb(nlstate.nl_sock, s_cb);
238
 
 
239
 
        err = nl_send_auto_complete(nlstate.nl_sock, msg);
240
 
        if (err < 0)
241
 
                goto out;
242
 
 
243
 
        err = 1;
244
 
        cap.ac_support = 0;
245
 
        cap.n_support = 0;
246
 
        cap.bg_support = 0;
247
 
        cap.band_5GHz_support = 0;
248
 
 
249
 
        nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
250
 
        nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
251
 
    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_phy_handler, &cap);
252
 
 
253
 
        while (err > 0)
254
 
                nl_recvmsgs(nlstate.nl_sock, cb);
255
 
 out:
256
 
        nl_cb_put(cb);
257
 
 out_free_msg:
258
 
        nlmsg_free(msg);
259
 
 
260
 
        if (err < 0)
261
 
                fprintf(stderr, "command failed: %s (%d)\n", strerror(-err), err);
262
 
 
263
 
        nl80211_cleanup(&nlstate);
264
 
 
265
 
    /* Try to guess the ac capabilities using heuristics (sometimes required
266
 
       as some drivers don't expose all their wireless properties to libnl */
267
 
    if (!cap.ac_support) {
268
 
        pci_fp = popen("lspci -nnv", "r");
269
 
        if (!pci_fp) {
270
 
            perror("Something is wrong with lspci");
271
 
            exit(1);
272
 
        }
273
 
        if (heuristic_test(pci_fp, "802.11ac") == 0)
274
 
            cap.ac_support = true;
275
 
        pclose(pci_fp);
276
 
    }
277
 
    if (cap.ac_support)
278
 
        printf("ac: supported\n");
279
 
    if (cap.n_support)
280
 
        printf("n: supported\n");
281
 
    if (cap.bg_support)
282
 
        printf("bg: supported\n");
283
 
    if (cap.band_5GHz_support)
284
 
        printf("band_5GHz: supported\n");
285
 
 
286
 
        return err;
287
 
}