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