]>
Commit | Line | Data |
---|---|---|
f05c7194 JM |
1 | /* |
2 | * wpa_gui - Peers class | |
3 | * Copyright (c) 2009, Atheros Communications | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * Alternatively, this software may be distributed under the terms of BSD | |
10 | * license. | |
11 | * | |
12 | * See README and COPYING for more details. | |
13 | */ | |
14 | ||
e2670b11 | 15 | #include <cstdio> |
f05c7194 | 16 | #include <QImageReader> |
6a88ae86 | 17 | #include <QMessageBox> |
f05c7194 | 18 | |
90973fb2 | 19 | #include "common/wpa_ctrl.h" |
f05c7194 | 20 | #include "wpagui.h" |
6a88ae86 | 21 | #include "stringquery.h" |
f05c7194 JM |
22 | #include "peers.h" |
23 | ||
6a88ae86 | 24 | |
9c6c0cb0 JM |
25 | enum { |
26 | peer_role_address = Qt::UserRole + 1, | |
27 | peer_role_type, | |
28 | peer_role_uuid, | |
29 | peer_role_details, | |
30 | peer_role_pri_dev_type, | |
175bba79 JM |
31 | peer_role_ssid, |
32 | peer_role_config_methods, | |
33 | peer_role_dev_passwd_id | |
9c6c0cb0 | 34 | }; |
6a88ae86 | 35 | |
f05c7194 JM |
36 | /* |
37 | * TODO: | |
f05c7194 | 38 | * - add current AP info (e.g., from WPS) in station mode |
f05c7194 JM |
39 | */ |
40 | ||
b1078a4b JM |
41 | enum peer_type { |
42 | PEER_TYPE_ASSOCIATED_STATION, | |
43 | PEER_TYPE_AP, | |
44 | PEER_TYPE_AP_WPS, | |
d094741c | 45 | PEER_TYPE_WPS_PIN_NEEDED, |
8f089e7f | 46 | PEER_TYPE_WPS_ER_AP, |
e694b344 | 47 | PEER_TYPE_WPS_ER_AP_UNCONFIGURED, |
8f089e7f | 48 | PEER_TYPE_WPS_ER_ENROLLEE |
b1078a4b JM |
49 | }; |
50 | ||
51 | ||
f05c7194 JM |
52 | Peers::Peers(QWidget *parent, const char *, bool, Qt::WFlags) |
53 | : QDialog(parent) | |
54 | { | |
55 | setupUi(this); | |
56 | ||
f05c7194 | 57 | if (QImageReader::supportedImageFormats().contains(QByteArray("svg"))) |
1949f534 | 58 | { |
f05c7194 | 59 | default_icon = new QIcon(":/icons/wpa_gui.svg"); |
1949f534 JM |
60 | ap_icon = new QIcon(":/icons/ap.svg"); |
61 | laptop_icon = new QIcon(":/icons/laptop.svg"); | |
62 | } else { | |
f05c7194 | 63 | default_icon = new QIcon(":/icons/wpa_gui.png"); |
1949f534 JM |
64 | ap_icon = new QIcon(":/icons/ap.png"); |
65 | laptop_icon = new QIcon(":/icons/laptop.png"); | |
66 | } | |
f05c7194 JM |
67 | |
68 | peers->setModel(&model); | |
69 | peers->setResizeMode(QListView::Adjust); | |
70 | ||
6a88ae86 JM |
71 | peers->setContextMenuPolicy(Qt::CustomContextMenu); |
72 | connect(peers, SIGNAL(customContextMenuRequested(const QPoint &)), | |
73 | this, SLOT(context_menu(const QPoint &))); | |
74 | ||
f05c7194 JM |
75 | wpagui = NULL; |
76 | } | |
77 | ||
78 | ||
79 | void Peers::setWpaGui(WpaGui *_wpagui) | |
80 | { | |
81 | wpagui = _wpagui; | |
82 | update_peers(); | |
83 | } | |
84 | ||
85 | ||
86 | Peers::~Peers() | |
87 | { | |
88 | delete default_icon; | |
1949f534 JM |
89 | delete ap_icon; |
90 | delete laptop_icon; | |
f05c7194 JM |
91 | } |
92 | ||
93 | ||
94 | void Peers::languageChange() | |
95 | { | |
96 | retranslateUi(this); | |
97 | } | |
98 | ||
99 | ||
9c6c0cb0 JM |
100 | QString Peers::ItemType(int type) |
101 | { | |
102 | QString title; | |
103 | switch (type) { | |
104 | case PEER_TYPE_ASSOCIATED_STATION: | |
105 | title = tr("Associated station"); | |
106 | break; | |
107 | case PEER_TYPE_AP: | |
108 | title = tr("AP"); | |
109 | break; | |
110 | case PEER_TYPE_AP_WPS: | |
111 | title = tr("WPS AP"); | |
112 | break; | |
113 | case PEER_TYPE_WPS_PIN_NEEDED: | |
114 | title = tr("WPS PIN needed"); | |
115 | break; | |
116 | case PEER_TYPE_WPS_ER_AP: | |
117 | title = tr("ER: WPS AP"); | |
118 | break; | |
119 | case PEER_TYPE_WPS_ER_AP_UNCONFIGURED: | |
120 | title = tr("ER: WPS AP (Unconfigured)"); | |
121 | break; | |
122 | case PEER_TYPE_WPS_ER_ENROLLEE: | |
123 | title = tr("ER: WPS Enrollee"); | |
124 | break; | |
125 | } | |
126 | return title; | |
127 | } | |
128 | ||
129 | ||
6a88ae86 JM |
130 | void Peers::context_menu(const QPoint &pos) |
131 | { | |
132 | QMenu *menu = new QMenu; | |
133 | if (menu == NULL) | |
134 | return; | |
135 | ||
136 | QModelIndex idx = peers->indexAt(pos); | |
137 | if (idx.isValid()) { | |
138 | ctx_item = model.itemFromIndex(idx); | |
b1078a4b | 139 | int type = ctx_item->data(peer_role_type).toInt(); |
9c6c0cb0 | 140 | menu->addAction(Peers::ItemType(type))->setEnabled(false); |
b1078a4b JM |
141 | menu->addSeparator(); |
142 | ||
d6211fbb JM |
143 | int config_methods = -1; |
144 | QVariant var = ctx_item->data(peer_role_config_methods); | |
145 | if (var.isValid()) | |
146 | config_methods = var.toInt(); | |
147 | ||
148 | if ((type == PEER_TYPE_ASSOCIATED_STATION || | |
149 | type == PEER_TYPE_AP_WPS || | |
150 | type == PEER_TYPE_WPS_PIN_NEEDED || | |
151 | type == PEER_TYPE_WPS_ER_ENROLLEE) && | |
152 | (config_methods == -1 || (config_methods & 0x010c))) { | |
9c6c0cb0 | 153 | menu->addAction(tr("Enter WPS PIN"), this, |
b1078a4b JM |
154 | SLOT(enter_pin())); |
155 | } | |
9c6c0cb0 | 156 | |
d6211fbb JM |
157 | if (type == PEER_TYPE_AP_WPS) { |
158 | menu->addAction(tr("Connect (PBC)"), this, | |
159 | SLOT(connect_pbc())); | |
160 | } | |
161 | ||
162 | if ((type == PEER_TYPE_ASSOCIATED_STATION || | |
163 | type == PEER_TYPE_WPS_ER_ENROLLEE) && | |
164 | config_methods >= 0 && (config_methods & 0x0080)) { | |
165 | menu->addAction(tr("Enroll (PBC)"), this, | |
166 | SLOT(connect_pbc())); | |
167 | } | |
168 | ||
d914f788 JM |
169 | if (type == PEER_TYPE_WPS_ER_AP) { |
170 | menu->addAction(tr("Learn Configuration"), this, | |
171 | SLOT(learn_ap_config())); | |
172 | } | |
173 | ||
9c6c0cb0 | 174 | menu->addAction(tr("Properties"), this, SLOT(properties())); |
6a88ae86 JM |
175 | } else { |
176 | ctx_item = NULL; | |
177 | menu->addAction(QString("Refresh"), this, SLOT(ctx_refresh())); | |
178 | } | |
179 | ||
180 | menu->exec(peers->mapToGlobal(pos)); | |
181 | } | |
182 | ||
183 | ||
184 | void Peers::enter_pin() | |
f05c7194 | 185 | { |
6a88ae86 JM |
186 | if (ctx_item == NULL) |
187 | return; | |
8f089e7f | 188 | |
da87d6f8 JM |
189 | int peer_type = ctx_item->data(peer_role_type).toInt(); |
190 | QString uuid; | |
191 | QString addr; | |
192 | if (peer_type == PEER_TYPE_WPS_ER_ENROLLEE) | |
193 | uuid = ctx_item->data(peer_role_uuid).toString(); | |
194 | else | |
195 | addr = ctx_item->data(peer_role_address).toString(); | |
196 | ||
6a88ae86 JM |
197 | StringQuery input(tr("PIN:")); |
198 | input.setWindowTitle(tr("PIN for ") + ctx_item->text()); | |
199 | if (input.exec() != QDialog::Accepted) | |
200 | return; | |
201 | ||
202 | char cmd[100]; | |
203 | char reply[100]; | |
204 | size_t reply_len; | |
8f089e7f | 205 | |
da87d6f8 | 206 | if (peer_type == PEER_TYPE_WPS_ER_ENROLLEE) { |
8f089e7f JM |
207 | snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s", |
208 | uuid.toAscii().constData(), | |
209 | input.get_string().toAscii().constData()); | |
210 | } else { | |
8f089e7f JM |
211 | snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", |
212 | addr.toAscii().constData(), | |
213 | input.get_string().toAscii().constData()); | |
214 | } | |
6a88ae86 JM |
215 | reply_len = sizeof(reply) - 1; |
216 | if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0) { | |
217 | QMessageBox msg; | |
218 | msg.setIcon(QMessageBox::Warning); | |
219 | msg.setText("Failed to set the WPS PIN."); | |
220 | msg.exec(); | |
221 | } | |
222 | } | |
223 | ||
224 | ||
225 | void Peers::ctx_refresh() | |
226 | { | |
227 | update_peers(); | |
f05c7194 JM |
228 | } |
229 | ||
230 | ||
f730b421 JM |
231 | void Peers::add_station(QString info) |
232 | { | |
233 | QStringList lines = info.split(QRegExp("\\n")); | |
234 | QString name; | |
235 | ||
236 | for (QStringList::Iterator it = lines.begin(); | |
237 | it != lines.end(); it++) { | |
238 | int pos = (*it).indexOf('=') + 1; | |
239 | if (pos < 1) | |
240 | continue; | |
241 | ||
242 | if ((*it).startsWith("wpsDeviceName=")) | |
243 | name = (*it).mid(pos); | |
244 | } | |
245 | ||
246 | if (name.isEmpty()) | |
247 | name = lines[0]; | |
248 | ||
1949f534 | 249 | QStandardItem *item = new QStandardItem(*laptop_icon, name); |
f730b421 JM |
250 | if (item) { |
251 | item->setData(lines[0], peer_role_address); | |
252 | item->setData(PEER_TYPE_ASSOCIATED_STATION, | |
253 | peer_role_type); | |
9c6c0cb0 JM |
254 | item->setData(info, peer_role_details); |
255 | item->setToolTip(ItemType(PEER_TYPE_ASSOCIATED_STATION)); | |
f730b421 JM |
256 | model.appendRow(item); |
257 | } | |
258 | } | |
259 | ||
260 | ||
b1078a4b | 261 | void Peers::add_stations() |
f05c7194 JM |
262 | { |
263 | char reply[2048]; | |
264 | size_t reply_len; | |
f730b421 | 265 | char cmd[30]; |
f05c7194 JM |
266 | int res; |
267 | ||
f05c7194 JM |
268 | reply_len = sizeof(reply) - 1; |
269 | if (wpagui->ctrlRequest("STA-FIRST", reply, &reply_len) < 0) | |
270 | return; | |
271 | ||
272 | do { | |
273 | reply[reply_len] = '\0'; | |
274 | QString info(reply); | |
275 | char *txt = reply; | |
276 | while (*txt != '\0' && *txt != '\n') | |
277 | txt++; | |
278 | *txt++ = '\0'; | |
acd8ba74 JM |
279 | if (strncmp(reply, "FAIL", 4) == 0 || |
280 | strncmp(reply, "UNKNOWN", 7) == 0) | |
f05c7194 JM |
281 | break; |
282 | ||
f730b421 | 283 | add_station(info); |
f05c7194 JM |
284 | |
285 | reply_len = sizeof(reply) - 1; | |
286 | snprintf(cmd, sizeof(cmd), "STA-NEXT %s", reply); | |
287 | res = wpagui->ctrlRequest(cmd, reply, &reply_len); | |
288 | } while (res >= 0); | |
289 | } | |
b1078a4b JM |
290 | |
291 | ||
f730b421 JM |
292 | void Peers::add_single_station(const char *addr) |
293 | { | |
294 | char reply[2048]; | |
295 | size_t reply_len; | |
296 | char cmd[30]; | |
297 | ||
298 | reply_len = sizeof(reply) - 1; | |
299 | snprintf(cmd, sizeof(cmd), "STA %s", addr); | |
300 | if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0) | |
301 | return; | |
302 | ||
303 | reply[reply_len] = '\0'; | |
304 | QString info(reply); | |
305 | char *txt = reply; | |
306 | while (*txt != '\0' && *txt != '\n') | |
307 | txt++; | |
308 | *txt++ = '\0'; | |
309 | if (strncmp(reply, "FAIL", 4) == 0 || | |
310 | strncmp(reply, "UNKNOWN", 7) == 0) | |
311 | return; | |
312 | ||
313 | add_station(info); | |
314 | } | |
315 | ||
316 | ||
b1078a4b JM |
317 | void Peers::add_scan_results() |
318 | { | |
319 | char reply[2048]; | |
320 | size_t reply_len; | |
321 | int index; | |
322 | char cmd[20]; | |
323 | ||
324 | index = 0; | |
325 | while (wpagui) { | |
326 | snprintf(cmd, sizeof(cmd), "BSS %d", index++); | |
327 | if (index > 1000) | |
328 | break; | |
329 | ||
330 | reply_len = sizeof(reply) - 1; | |
331 | if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0) | |
332 | break; | |
333 | reply[reply_len] = '\0'; | |
334 | ||
335 | QString bss(reply); | |
336 | if (bss.isEmpty() || bss.startsWith("FAIL")) | |
337 | break; | |
338 | ||
9c6c0cb0 | 339 | QString ssid, bssid, flags, wps_name, pri_dev_type; |
b1078a4b JM |
340 | |
341 | QStringList lines = bss.split(QRegExp("\\n")); | |
342 | for (QStringList::Iterator it = lines.begin(); | |
343 | it != lines.end(); it++) { | |
344 | int pos = (*it).indexOf('=') + 1; | |
345 | if (pos < 1) | |
346 | continue; | |
347 | ||
348 | if ((*it).startsWith("bssid=")) | |
349 | bssid = (*it).mid(pos); | |
350 | else if ((*it).startsWith("flags=")) | |
351 | flags = (*it).mid(pos); | |
352 | else if ((*it).startsWith("ssid=")) | |
353 | ssid = (*it).mid(pos); | |
354 | else if ((*it).startsWith("wps_device_name=")) | |
355 | wps_name = (*it).mid(pos); | |
9c6c0cb0 JM |
356 | else if ((*it).startsWith("wps_primary_device_type=")) |
357 | pri_dev_type = (*it).mid(pos); | |
b1078a4b JM |
358 | } |
359 | ||
360 | QString name = wps_name; | |
361 | if (name.isEmpty()) | |
362 | name = ssid + "\n" + bssid; | |
363 | ||
1949f534 | 364 | QStandardItem *item = new QStandardItem(*ap_icon, name); |
b1078a4b | 365 | if (item) { |
acfbf1f5 | 366 | item->setData(bssid, peer_role_address); |
9c6c0cb0 | 367 | int type; |
614ff64f | 368 | if (flags.contains("[WPS")) |
9c6c0cb0 | 369 | type = PEER_TYPE_AP_WPS; |
b1078a4b | 370 | else |
9c6c0cb0 JM |
371 | type = PEER_TYPE_AP; |
372 | item->setData(type, peer_role_type); | |
b1078a4b JM |
373 | |
374 | for (int i = 0; i < lines.size(); i++) { | |
375 | if (lines[i].length() > 60) { | |
376 | lines[i].remove( | |
377 | 60, lines[i].length()); | |
378 | lines[i] += ".."; | |
379 | } | |
380 | } | |
9c6c0cb0 JM |
381 | item->setToolTip(ItemType(type)); |
382 | item->setData(lines.join("\n"), peer_role_details); | |
383 | if (!pri_dev_type.isEmpty()) | |
384 | item->setData(pri_dev_type, | |
385 | peer_role_pri_dev_type); | |
386 | if (!ssid.isEmpty()) | |
387 | item->setData(ssid, peer_role_ssid); | |
b1078a4b JM |
388 | model.appendRow(item); |
389 | } | |
390 | } | |
391 | } | |
392 | ||
393 | ||
394 | void Peers::update_peers() | |
395 | { | |
396 | model.clear(); | |
397 | if (wpagui == NULL) | |
398 | return; | |
399 | ||
8f089e7f JM |
400 | char reply[20]; |
401 | size_t replylen = sizeof(reply) - 1; | |
402 | wpagui->ctrlRequest("WPS_ER_START", reply, &replylen); | |
403 | ||
b1078a4b JM |
404 | add_stations(); |
405 | add_scan_results(); | |
406 | } | |
d094741c JM |
407 | |
408 | ||
409 | QStandardItem * Peers::find_addr(QString addr) | |
410 | { | |
411 | if (model.rowCount() == 0) | |
412 | return NULL; | |
413 | ||
414 | QModelIndexList lst = model.match(model.index(0, 0), peer_role_address, | |
415 | addr); | |
416 | if (lst.size() == 0) | |
417 | return NULL; | |
418 | return model.itemFromIndex(lst[0]); | |
419 | } | |
420 | ||
421 | ||
8f089e7f JM |
422 | QStandardItem * Peers::find_uuid(QString uuid) |
423 | { | |
424 | if (model.rowCount() == 0) | |
425 | return NULL; | |
426 | ||
427 | QModelIndexList lst = model.match(model.index(0, 0), peer_role_uuid, | |
428 | uuid); | |
429 | if (lst.size() == 0) | |
430 | return NULL; | |
431 | return model.itemFromIndex(lst[0]); | |
432 | } | |
433 | ||
434 | ||
d094741c JM |
435 | void Peers::event_notify(WpaMsg msg) |
436 | { | |
437 | QString text = msg.getMsg(); | |
f730b421 | 438 | |
d094741c JM |
439 | if (text.startsWith(WPS_EVENT_PIN_NEEDED)) { |
440 | /* | |
441 | * WPS-PIN-NEEDED 5a02a5fa-9199-5e7c-bc46-e183d3cb32f7 | |
442 | * 02:2a:c4:18:5b:f3 | |
443 | * [Wireless Client|Company|cmodel|123|12345|1-0050F204-1] | |
444 | */ | |
445 | QStringList items = text.split(' '); | |
446 | QString uuid = items[1]; | |
447 | QString addr = items[2]; | |
448 | QString name = ""; | |
449 | ||
450 | QStandardItem *item = find_addr(addr); | |
451 | if (item) | |
452 | return; | |
453 | ||
454 | int pos = text.indexOf('['); | |
455 | if (pos >= 0) { | |
456 | int pos2 = text.lastIndexOf(']'); | |
457 | if (pos2 >= pos) { | |
458 | items = text.mid(pos + 1, pos2 - pos - 1). | |
459 | split('|'); | |
460 | name = items[0]; | |
461 | items.append(addr); | |
462 | } | |
463 | } | |
464 | ||
1949f534 | 465 | item = new QStandardItem(*laptop_icon, name); |
d094741c JM |
466 | if (item) { |
467 | item->setData(addr, peer_role_address); | |
468 | item->setData(PEER_TYPE_WPS_PIN_NEEDED, | |
469 | peer_role_type); | |
9c6c0cb0 JM |
470 | item->setToolTip(ItemType(PEER_TYPE_WPS_PIN_NEEDED)); |
471 | item->setData(items.join("\n"), peer_role_details); | |
472 | item->setData(items[5], peer_role_pri_dev_type); | |
d094741c JM |
473 | model.appendRow(item); |
474 | } | |
f730b421 JM |
475 | return; |
476 | } | |
477 | ||
478 | if (text.startsWith(AP_STA_CONNECTED)) { | |
479 | /* AP-STA-CONNECTED 02:2a:c4:18:5b:f3 */ | |
480 | QStringList items = text.split(' '); | |
481 | QString addr = items[1]; | |
482 | QStandardItem *item = find_addr(addr); | |
483 | if (item == NULL || item->data(peer_role_type).toInt() != | |
484 | PEER_TYPE_ASSOCIATED_STATION) | |
485 | add_single_station(addr.toAscii().constData()); | |
486 | return; | |
487 | } | |
488 | ||
489 | if (text.startsWith(AP_STA_DISCONNECTED)) { | |
490 | /* AP-STA-DISCONNECTED 02:2a:c4:18:5b:f3 */ | |
491 | QStringList items = text.split(' '); | |
492 | QString addr = items[1]; | |
493 | ||
494 | if (model.rowCount() == 0) | |
495 | return; | |
496 | ||
497 | QModelIndexList lst = model.match(model.index(0, 0), | |
498 | peer_role_address, addr); | |
499 | for (int i = 0; i < lst.size(); i++) { | |
500 | QStandardItem *item = model.itemFromIndex(lst[i]); | |
501 | if (item && item->data(peer_role_type).toInt() == | |
502 | PEER_TYPE_ASSOCIATED_STATION) | |
503 | model.removeRow(lst[i].row()); | |
504 | } | |
505 | return; | |
d094741c | 506 | } |
8f089e7f JM |
507 | |
508 | if (text.startsWith(WPS_EVENT_ER_AP_ADD)) { | |
509 | /* | |
e694b344 JM |
510 | * WPS-ER-AP-ADD 87654321-9abc-def0-1234-56789abc0002 |
511 | * 02:11:22:33:44:55 pri_dev_type=6-0050F204-1 wps_state=1 | |
512 | * |Very friendly name|Company|Long description of the model| | |
8f089e7f JM |
513 | * WAP|http://w1.fi/|http://w1.fi/hostapd/ |
514 | */ | |
e694b344 JM |
515 | QStringList items = text.split(' '); |
516 | if (items.size() < 5) | |
517 | return; | |
518 | QString uuid = items[1]; | |
519 | QString addr = items[2]; | |
9c6c0cb0 | 520 | QString pri_dev_type = items[3].mid(13); |
e694b344 JM |
521 | int wps_state = items[4].mid(10).toInt(); |
522 | ||
523 | int pos = text.indexOf('|'); | |
8f089e7f JM |
524 | if (pos < 0) |
525 | return; | |
e694b344 JM |
526 | items = text.mid(pos + 1).split('|'); |
527 | if (items.size() < 1) | |
8f089e7f JM |
528 | return; |
529 | ||
e694b344 | 530 | QStandardItem *item = find_uuid(uuid); |
8f089e7f JM |
531 | if (item) |
532 | return; | |
533 | ||
e694b344 | 534 | item = new QStandardItem(*ap_icon, items[0]); |
8f089e7f | 535 | if (item) { |
e694b344 JM |
536 | item->setData(uuid, peer_role_uuid); |
537 | item->setData(addr, peer_role_address); | |
9c6c0cb0 JM |
538 | int type = wps_state == 2 ? PEER_TYPE_WPS_ER_AP: |
539 | PEER_TYPE_WPS_ER_AP_UNCONFIGURED; | |
540 | item->setData(type, peer_role_type); | |
541 | item->setToolTip(ItemType(type)); | |
542 | item->setData(pri_dev_type, peer_role_pri_dev_type); | |
543 | item->setData(items.join(QString("\n")), | |
544 | peer_role_details); | |
8f089e7f JM |
545 | model.appendRow(item); |
546 | } | |
547 | ||
548 | return; | |
549 | } | |
550 | ||
551 | if (text.startsWith(WPS_EVENT_ER_AP_REMOVE)) { | |
552 | /* WPS-ER-AP-REMOVE 87654321-9abc-def0-1234-56789abc0002 */ | |
553 | QStringList items = text.split(' '); | |
554 | if (items.size() < 2) | |
555 | return; | |
556 | if (model.rowCount() == 0) | |
557 | return; | |
558 | ||
559 | QModelIndexList lst = model.match(model.index(0, 0), | |
560 | peer_role_uuid, items[1]); | |
561 | for (int i = 0; i < lst.size(); i++) { | |
562 | QStandardItem *item = model.itemFromIndex(lst[i]); | |
e694b344 JM |
563 | if (item && |
564 | (item->data(peer_role_type).toInt() == | |
565 | PEER_TYPE_WPS_ER_AP || | |
566 | item->data(peer_role_type).toInt() == | |
567 | PEER_TYPE_WPS_ER_AP_UNCONFIGURED)) | |
8f089e7f JM |
568 | model.removeRow(lst[i].row()); |
569 | } | |
570 | return; | |
571 | } | |
572 | ||
573 | if (text.startsWith(WPS_EVENT_ER_ENROLLEE_ADD)) { | |
574 | /* | |
575 | * WPS-ER-ENROLLEE-ADD 2b7093f1-d6fb-5108-adbb-bea66bb87333 | |
576 | * 02:66:a0:ee:17:27 M1=1 config_methods=0x14d dev_passwd_id=0 | |
577 | * pri_dev_type=1-0050F204-1 | |
578 | * |Wireless Client|Company|cmodel|123|12345| | |
579 | */ | |
580 | QStringList items = text.split(' '); | |
581 | if (items.size() < 3) | |
582 | return; | |
583 | QString uuid = items[1]; | |
584 | QString addr = items[2]; | |
9c6c0cb0 | 585 | QString pri_dev_type = items[6].mid(13); |
175bba79 JM |
586 | int config_methods = -1; |
587 | int dev_passwd_id = -1; | |
588 | ||
589 | for (int i = 3; i < items.size(); i++) { | |
590 | int pos = items[i].indexOf('=') + 1; | |
591 | if (pos < 1) | |
592 | continue; | |
593 | QString val = items[i].mid(pos); | |
594 | if (items[i].startsWith("config_methods=")) { | |
595 | config_methods = val.toInt(0, 0); | |
596 | } else if (items[i].startsWith("dev_passwd_id=")) { | |
597 | dev_passwd_id = val.toInt(); | |
598 | } | |
599 | } | |
8f089e7f JM |
600 | |
601 | int pos = text.indexOf('|'); | |
602 | if (pos < 0) | |
603 | return; | |
604 | items = text.mid(pos + 1).split('|'); | |
605 | if (items.size() < 1) | |
606 | return; | |
607 | QString name = items[0]; | |
608 | if (name.length() == 0) | |
609 | name = addr; | |
610 | ||
611 | remove_enrollee_uuid(uuid); | |
612 | ||
613 | QStandardItem *item; | |
1949f534 | 614 | item = new QStandardItem(*laptop_icon, name); |
8f089e7f JM |
615 | if (item) { |
616 | item->setData(uuid, peer_role_uuid); | |
617 | item->setData(addr, peer_role_address); | |
618 | item->setData(PEER_TYPE_WPS_ER_ENROLLEE, | |
619 | peer_role_type); | |
9c6c0cb0 JM |
620 | item->setToolTip(ItemType(PEER_TYPE_WPS_ER_ENROLLEE)); |
621 | item->setData(items.join(QString("\n")), | |
622 | peer_role_details); | |
623 | item->setData(pri_dev_type, peer_role_pri_dev_type); | |
175bba79 JM |
624 | if (config_methods >= 0) |
625 | item->setData(config_methods, | |
626 | peer_role_config_methods); | |
627 | if (dev_passwd_id >= 0) | |
628 | item->setData(dev_passwd_id, | |
629 | peer_role_dev_passwd_id); | |
8f089e7f JM |
630 | model.appendRow(item); |
631 | } | |
632 | ||
633 | return; | |
634 | } | |
635 | ||
636 | if (text.startsWith(WPS_EVENT_ER_ENROLLEE_REMOVE)) { | |
637 | /* | |
638 | * WPS-ER-ENROLLEE-REMOVE 2b7093f1-d6fb-5108-adbb-bea66bb87333 | |
639 | * 02:66:a0:ee:17:27 | |
640 | */ | |
641 | QStringList items = text.split(' '); | |
642 | if (items.size() < 2) | |
643 | return; | |
644 | remove_enrollee_uuid(items[1]); | |
645 | return; | |
646 | } | |
647 | } | |
648 | ||
649 | ||
650 | void Peers::closeEvent(QCloseEvent *) | |
651 | { | |
652 | if (wpagui) { | |
653 | char reply[20]; | |
654 | size_t replylen = sizeof(reply) - 1; | |
655 | wpagui->ctrlRequest("WPS_ER_STOP", reply, &replylen); | |
656 | } | |
657 | } | |
658 | ||
659 | ||
660 | void Peers::done(int r) | |
661 | { | |
662 | QDialog::done(r); | |
663 | close(); | |
664 | } | |
665 | ||
666 | ||
667 | void Peers::remove_enrollee_uuid(QString uuid) | |
668 | { | |
669 | if (model.rowCount() == 0) | |
670 | return; | |
671 | ||
672 | QModelIndexList lst = model.match(model.index(0, 0), | |
673 | peer_role_uuid, uuid); | |
674 | for (int i = 0; i < lst.size(); i++) { | |
675 | QStandardItem *item = model.itemFromIndex(lst[i]); | |
676 | if (item && item->data(peer_role_type).toInt() == | |
677 | PEER_TYPE_WPS_ER_ENROLLEE) | |
678 | model.removeRow(lst[i].row()); | |
679 | } | |
d094741c | 680 | } |
9c6c0cb0 JM |
681 | |
682 | ||
683 | void Peers::properties() | |
684 | { | |
685 | if (ctx_item == NULL) | |
686 | return; | |
687 | ||
688 | QMessageBox msg(this); | |
689 | msg.setStandardButtons(QMessageBox::Ok); | |
690 | msg.setDefaultButton(QMessageBox::Ok); | |
691 | msg.setEscapeButton(QMessageBox::Ok); | |
692 | msg.setWindowTitle(tr("Peer Properties")); | |
693 | ||
694 | int type = ctx_item->data(peer_role_type).toInt(); | |
695 | QString title = Peers::ItemType(type); | |
696 | ||
697 | msg.setText(title + QString("\n") + tr("Name: ") + ctx_item->text()); | |
698 | ||
699 | QVariant var; | |
700 | QString info; | |
701 | ||
702 | var = ctx_item->data(peer_role_address); | |
703 | if (var.isValid()) | |
704 | info += tr("Address: ") + var.toString() + QString("\n"); | |
705 | ||
706 | var = ctx_item->data(peer_role_uuid); | |
707 | if (var.isValid()) | |
708 | info += tr("UUID: ") + var.toString() + QString("\n"); | |
709 | ||
710 | var = ctx_item->data(peer_role_pri_dev_type); | |
711 | if (var.isValid()) | |
712 | info += tr("Primary Device Type: ") + var.toString() + | |
713 | QString("\n"); | |
714 | ||
715 | var = ctx_item->data(peer_role_ssid); | |
716 | if (var.isValid()) | |
717 | info += tr("SSID: ") + var.toString() + QString("\n"); | |
718 | ||
175bba79 JM |
719 | var = ctx_item->data(peer_role_config_methods); |
720 | if (var.isValid()) { | |
721 | int methods = var.toInt(); | |
722 | info += tr("Configuration Methods: "); | |
723 | if (methods & 0x0001) | |
724 | info += tr("[USBA]"); | |
725 | if (methods & 0x0002) | |
726 | info += tr("[Ethernet]"); | |
727 | if (methods & 0x0004) | |
728 | info += tr("[Label]"); | |
729 | if (methods & 0x0008) | |
730 | info += tr("[Display]"); | |
731 | if (methods & 0x0010) | |
732 | info += tr("[Ext. NFC Token]"); | |
733 | if (methods & 0x0020) | |
734 | info += tr("[Int. NFC Token]"); | |
735 | if (methods & 0x0040) | |
736 | info += tr("[NFC Interface]"); | |
737 | if (methods & 0x0080) | |
738 | info += tr("[Push Button]"); | |
739 | if (methods & 0x0100) | |
740 | info += tr("[Keypad]"); | |
741 | info += "\n"; | |
742 | } | |
743 | ||
744 | var = ctx_item->data(peer_role_dev_passwd_id); | |
745 | if (var.isValid()) { | |
746 | info += tr("Device Password ID: ") + var.toString(); | |
747 | switch (var.toInt()) { | |
748 | case 0: | |
749 | info += tr(" (Default PIN)"); | |
750 | break; | |
751 | case 1: | |
752 | info += tr(" (User-specified PIN)"); | |
753 | break; | |
754 | case 2: | |
755 | info += tr(" (Machine-specified PIN)"); | |
756 | break; | |
757 | case 3: | |
758 | info += tr(" (Rekey)"); | |
759 | break; | |
760 | case 4: | |
761 | info += tr(" (Push Button)"); | |
762 | break; | |
763 | case 5: | |
764 | info += tr(" (Registrar-specified)"); | |
765 | break; | |
766 | } | |
767 | info += "\n"; | |
768 | } | |
769 | ||
9c6c0cb0 JM |
770 | msg.setInformativeText(info); |
771 | ||
772 | var = ctx_item->data(peer_role_details); | |
773 | if (var.isValid()) | |
774 | msg.setDetailedText(var.toString()); | |
775 | ||
776 | msg.exec(); | |
777 | } | |
d6211fbb JM |
778 | |
779 | ||
780 | void Peers::connect_pbc() | |
781 | { | |
782 | if (ctx_item == NULL) | |
783 | return; | |
784 | ||
785 | char cmd[100]; | |
786 | char reply[100]; | |
787 | size_t reply_len; | |
788 | ||
789 | int peer_type = ctx_item->data(peer_role_type).toInt(); | |
790 | if (peer_type == PEER_TYPE_WPS_ER_ENROLLEE) { | |
791 | snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s", | |
792 | ctx_item->data(peer_role_uuid).toString().toAscii(). | |
793 | constData()); | |
794 | } else { | |
795 | snprintf(cmd, sizeof(cmd), "WPS_PBC"); | |
796 | } | |
797 | reply_len = sizeof(reply) - 1; | |
798 | if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0) { | |
799 | QMessageBox msg; | |
800 | msg.setIcon(QMessageBox::Warning); | |
801 | msg.setText("Failed to start WPS PBC."); | |
802 | msg.exec(); | |
803 | } | |
804 | } | |
d914f788 JM |
805 | |
806 | ||
807 | void Peers::learn_ap_config() | |
808 | { | |
809 | if (ctx_item == NULL) | |
810 | return; | |
811 | ||
812 | QString uuid = ctx_item->data(peer_role_uuid).toString(); | |
813 | ||
814 | StringQuery input(tr("AP PIN:")); | |
815 | input.setWindowTitle(tr("AP PIN for ") + ctx_item->text()); | |
816 | if (input.exec() != QDialog::Accepted) | |
817 | return; | |
818 | ||
819 | char cmd[100]; | |
820 | char reply[100]; | |
821 | size_t reply_len; | |
822 | ||
823 | snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s", | |
824 | uuid.toAscii().constData(), | |
825 | input.get_string().toAscii().constData()); | |
826 | reply_len = sizeof(reply) - 1; | |
827 | if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0) { | |
828 | QMessageBox msg; | |
829 | msg.setIcon(QMessageBox::Warning); | |
830 | msg.setText(tr("Failed to start learning AP configuration.")); | |
831 | msg.exec(); | |
832 | } | |
833 | } |