peers.cpp 19 KB

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