1/*
2 * hidl interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
5 * Copyright (C) 2017 Sony Mobile Communications Inc.
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "hidl_manager.h"
12#include "hidl_return_util.h"
13#include "iface_config_utils.h"
14#include "misc_utils.h"
15#include "p2p_iface.h"
16
17extern "C" {
18#include "ap.h"
19#include "wps_supplicant.h"
20#include "wifi_display.h"
21}
22
23namespace {
24const char kConfigMethodStrPbc[] = "pbc";
25const char kConfigMethodStrDisplay[] = "display";
26const char kConfigMethodStrKeypad[] = "keypad";
27constexpr char kSetMiracastMode[] = "MIRACAST ";
28constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
29constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
30
31using android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
32uint8_t convertHidlMiracastModeToInternal(
33    ISupplicantP2pIface::MiracastMode mode)
34{
35	switch (mode) {
36	case ISupplicantP2pIface::MiracastMode::DISABLED:
37		return 0;
38	case ISupplicantP2pIface::MiracastMode::SOURCE:
39		return 1;
40	case ISupplicantP2pIface::MiracastMode::SINK:
41		return 2;
42	};
43	WPA_ASSERT(false);
44}
45}  // namespace
46
47namespace android {
48namespace hardware {
49namespace wifi {
50namespace supplicant {
51namespace V1_0 {
52namespace implementation {
53using hidl_return_util::validateAndCall;
54
55P2pIface::P2pIface(struct wpa_global* wpa_global, const char ifname[])
56    : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
57{
58}
59
60void P2pIface::invalidate() { is_valid_ = false; }
61bool P2pIface::isValid()
62{
63	return (is_valid_ && (retrieveIfacePtr() != nullptr));
64}
65Return<void> P2pIface::getName(getName_cb _hidl_cb)
66{
67	return validateAndCall(
68	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
69	    &P2pIface::getNameInternal, _hidl_cb);
70}
71
72Return<void> P2pIface::getType(getType_cb _hidl_cb)
73{
74	return validateAndCall(
75	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
76	    &P2pIface::getTypeInternal, _hidl_cb);
77}
78
79Return<void> P2pIface::addNetwork(addNetwork_cb _hidl_cb)
80{
81	return validateAndCall(
82	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
83	    &P2pIface::addNetworkInternal, _hidl_cb);
84}
85
86Return<void> P2pIface::removeNetwork(
87    SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
88{
89	return validateAndCall(
90	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
91	    &P2pIface::removeNetworkInternal, _hidl_cb, id);
92}
93
94Return<void> P2pIface::getNetwork(
95    SupplicantNetworkId id, getNetwork_cb _hidl_cb)
96{
97	return validateAndCall(
98	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
99	    &P2pIface::getNetworkInternal, _hidl_cb, id);
100}
101
102Return<void> P2pIface::listNetworks(listNetworks_cb _hidl_cb)
103{
104	return validateAndCall(
105	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
106	    &P2pIface::listNetworksInternal, _hidl_cb);
107}
108
109Return<void> P2pIface::registerCallback(
110    const sp<ISupplicantP2pIfaceCallback>& callback,
111    registerCallback_cb _hidl_cb)
112{
113	return validateAndCall(
114	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
115	    &P2pIface::registerCallbackInternal, _hidl_cb, callback);
116}
117
118Return<void> P2pIface::getDeviceAddress(getDeviceAddress_cb _hidl_cb)
119{
120	return validateAndCall(
121	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
122	    &P2pIface::getDeviceAddressInternal, _hidl_cb);
123}
124
125Return<void> P2pIface::setSsidPostfix(
126    const hidl_vec<uint8_t>& postfix, setSsidPostfix_cb _hidl_cb)
127{
128	return validateAndCall(
129	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
130	    &P2pIface::setSsidPostfixInternal, _hidl_cb, postfix);
131}
132
133Return<void> P2pIface::setGroupIdle(
134    const hidl_string& group_ifname, uint32_t timeout_in_sec,
135    setGroupIdle_cb _hidl_cb)
136{
137	return validateAndCall(
138	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
139	    &P2pIface::setGroupIdleInternal, _hidl_cb, group_ifname,
140	    timeout_in_sec);
141}
142
143Return<void> P2pIface::setPowerSave(
144    const hidl_string& group_ifname, bool enable, setPowerSave_cb _hidl_cb)
145{
146	return validateAndCall(
147	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
148	    &P2pIface::setPowerSaveInternal, _hidl_cb, group_ifname, enable);
149}
150
151Return<void> P2pIface::find(uint32_t timeout_in_sec, find_cb _hidl_cb)
152{
153	return validateAndCall(
154	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
155	    &P2pIface::findInternal, _hidl_cb, timeout_in_sec);
156}
157
158Return<void> P2pIface::stopFind(stopFind_cb _hidl_cb)
159{
160	return validateAndCall(
161	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
162	    &P2pIface::stopFindInternal, _hidl_cb);
163}
164
165Return<void> P2pIface::flush(flush_cb _hidl_cb)
166{
167	return validateAndCall(
168	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
169	    &P2pIface::flushInternal, _hidl_cb);
170}
171
172Return<void> P2pIface::connect(
173    const hidl_array<uint8_t, 6>& peer_address,
174    ISupplicantP2pIface::WpsProvisionMethod provision_method,
175    const hidl_string& pre_selected_pin, bool join_existing_group,
176    bool persistent, uint32_t go_intent, connect_cb _hidl_cb)
177{
178	return validateAndCall(
179	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
180	    &P2pIface::connectInternal, _hidl_cb, peer_address,
181	    provision_method, pre_selected_pin, join_existing_group, persistent,
182	    go_intent);
183}
184
185Return<void> P2pIface::cancelConnect(cancelConnect_cb _hidl_cb)
186{
187	return validateAndCall(
188	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
189	    &P2pIface::cancelConnectInternal, _hidl_cb);
190}
191
192Return<void> P2pIface::provisionDiscovery(
193    const hidl_array<uint8_t, 6>& peer_address,
194    ISupplicantP2pIface::WpsProvisionMethod provision_method,
195    provisionDiscovery_cb _hidl_cb)
196{
197	return validateAndCall(
198	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
199	    &P2pIface::provisionDiscoveryInternal, _hidl_cb, peer_address,
200	    provision_method);
201}
202
203Return<void> P2pIface::addGroup(
204    bool persistent, SupplicantNetworkId persistent_network_id,
205    addGroup_cb _hidl_cb)
206{
207	return validateAndCall(
208	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
209	    &P2pIface::addGroupInternal, _hidl_cb, persistent,
210	    persistent_network_id);
211}
212
213Return<void> P2pIface::removeGroup(
214    const hidl_string& group_ifname, removeGroup_cb _hidl_cb)
215{
216	return validateAndCall(
217	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
218	    &P2pIface::removeGroupInternal, _hidl_cb, group_ifname);
219}
220
221Return<void> P2pIface::reject(
222    const hidl_array<uint8_t, 6>& peer_address, reject_cb _hidl_cb)
223{
224	return validateAndCall(
225	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
226	    &P2pIface::rejectInternal, _hidl_cb, peer_address);
227}
228
229Return<void> P2pIface::invite(
230    const hidl_string& group_ifname,
231    const hidl_array<uint8_t, 6>& go_device_address,
232    const hidl_array<uint8_t, 6>& peer_address, invite_cb _hidl_cb)
233{
234	return validateAndCall(
235	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
236	    &P2pIface::inviteInternal, _hidl_cb, group_ifname,
237	    go_device_address, peer_address);
238}
239
240Return<void> P2pIface::reinvoke(
241    SupplicantNetworkId persistent_network_id,
242    const hidl_array<uint8_t, 6>& peer_address, reinvoke_cb _hidl_cb)
243{
244	return validateAndCall(
245	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
246	    &P2pIface::reinvokeInternal, _hidl_cb, persistent_network_id,
247	    peer_address);
248}
249
250Return<void> P2pIface::configureExtListen(
251    uint32_t period_in_millis, uint32_t interval_in_millis,
252    configureExtListen_cb _hidl_cb)
253{
254	return validateAndCall(
255	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
256	    &P2pIface::configureExtListenInternal, _hidl_cb, period_in_millis,
257	    interval_in_millis);
258}
259
260Return<void> P2pIface::setListenChannel(
261    uint32_t channel, uint32_t operating_class, setListenChannel_cb _hidl_cb)
262{
263	return validateAndCall(
264	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
265	    &P2pIface::setListenChannelInternal, _hidl_cb, channel,
266	    operating_class);
267}
268
269Return<void> P2pIface::setDisallowedFrequencies(
270    const hidl_vec<FreqRange>& ranges, setDisallowedFrequencies_cb _hidl_cb)
271{
272	return validateAndCall(
273	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
274	    &P2pIface::setDisallowedFrequenciesInternal, _hidl_cb, ranges);
275}
276
277Return<void> P2pIface::getSsid(
278    const hidl_array<uint8_t, 6>& peer_address, getSsid_cb _hidl_cb)
279{
280	return validateAndCall(
281	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
282	    &P2pIface::getSsidInternal, _hidl_cb, peer_address);
283}
284
285Return<void> P2pIface::getGroupCapability(
286    const hidl_array<uint8_t, 6>& peer_address, getGroupCapability_cb _hidl_cb)
287{
288	return validateAndCall(
289	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
290	    &P2pIface::getGroupCapabilityInternal, _hidl_cb, peer_address);
291}
292
293Return<void> P2pIface::addBonjourService(
294    const hidl_vec<uint8_t>& query, const hidl_vec<uint8_t>& response,
295    addBonjourService_cb _hidl_cb)
296{
297	return validateAndCall(
298	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
299	    &P2pIface::addBonjourServiceInternal, _hidl_cb, query, response);
300}
301
302Return<void> P2pIface::removeBonjourService(
303    const hidl_vec<uint8_t>& query, removeBonjourService_cb _hidl_cb)
304{
305	return validateAndCall(
306	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
307	    &P2pIface::removeBonjourServiceInternal, _hidl_cb, query);
308}
309
310Return<void> P2pIface::addUpnpService(
311    uint32_t version, const hidl_string& service_name,
312    addUpnpService_cb _hidl_cb)
313{
314	return validateAndCall(
315	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
316	    &P2pIface::addUpnpServiceInternal, _hidl_cb, version, service_name);
317}
318
319Return<void> P2pIface::removeUpnpService(
320    uint32_t version, const hidl_string& service_name,
321    removeUpnpService_cb _hidl_cb)
322{
323	return validateAndCall(
324	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
325	    &P2pIface::removeUpnpServiceInternal, _hidl_cb, version,
326	    service_name);
327}
328
329Return<void> P2pIface::flushServices(flushServices_cb _hidl_cb)
330{
331	return validateAndCall(
332	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
333	    &P2pIface::flushServicesInternal, _hidl_cb);
334}
335
336Return<void> P2pIface::requestServiceDiscovery(
337    const hidl_array<uint8_t, 6>& peer_address, const hidl_vec<uint8_t>& query,
338    requestServiceDiscovery_cb _hidl_cb)
339{
340	return validateAndCall(
341	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
342	    &P2pIface::requestServiceDiscoveryInternal, _hidl_cb, peer_address,
343	    query);
344}
345
346Return<void> P2pIface::cancelServiceDiscovery(
347    uint64_t identifier, cancelServiceDiscovery_cb _hidl_cb)
348{
349	return validateAndCall(
350	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
351	    &P2pIface::cancelServiceDiscoveryInternal, _hidl_cb, identifier);
352}
353
354Return<void> P2pIface::setMiracastMode(
355    ISupplicantP2pIface::MiracastMode mode, setMiracastMode_cb _hidl_cb)
356{
357	return validateAndCall(
358	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
359	    &P2pIface::setMiracastModeInternal, _hidl_cb, mode);
360}
361
362Return<void> P2pIface::startWpsPbc(
363    const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
364    startWpsPbc_cb _hidl_cb)
365{
366	return validateAndCall(
367	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
368	    &P2pIface::startWpsPbcInternal, _hidl_cb, group_ifname, bssid);
369}
370
371Return<void> P2pIface::startWpsPinKeypad(
372    const hidl_string& group_ifname, const hidl_string& pin,
373    startWpsPinKeypad_cb _hidl_cb)
374{
375	return validateAndCall(
376	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
377	    &P2pIface::startWpsPinKeypadInternal, _hidl_cb, group_ifname, pin);
378}
379
380Return<void> P2pIface::startWpsPinDisplay(
381    const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
382    startWpsPinDisplay_cb _hidl_cb)
383{
384	return validateAndCall(
385	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
386	    &P2pIface::startWpsPinDisplayInternal, _hidl_cb, group_ifname,
387	    bssid);
388}
389
390Return<void> P2pIface::cancelWps(
391    const hidl_string& group_ifname, cancelWps_cb _hidl_cb)
392{
393	return validateAndCall(
394	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
395	    &P2pIface::cancelWpsInternal, _hidl_cb, group_ifname);
396}
397
398Return<void> P2pIface::setWpsDeviceName(
399    const hidl_string& name, setWpsDeviceName_cb _hidl_cb)
400{
401	return validateAndCall(
402	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
403	    &P2pIface::setWpsDeviceNameInternal, _hidl_cb, name);
404}
405
406Return<void> P2pIface::setWpsDeviceType(
407    const hidl_array<uint8_t, 8>& type, setWpsDeviceType_cb _hidl_cb)
408{
409	return validateAndCall(
410	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
411	    &P2pIface::setWpsDeviceTypeInternal, _hidl_cb, type);
412}
413
414Return<void> P2pIface::setWpsManufacturer(
415    const hidl_string& manufacturer, setWpsManufacturer_cb _hidl_cb)
416{
417	return validateAndCall(
418	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
419	    &P2pIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
420}
421
422Return<void> P2pIface::setWpsModelName(
423    const hidl_string& model_name, setWpsModelName_cb _hidl_cb)
424{
425	return validateAndCall(
426	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
427	    &P2pIface::setWpsModelNameInternal, _hidl_cb, model_name);
428}
429
430Return<void> P2pIface::setWpsModelNumber(
431    const hidl_string& model_number, setWpsModelNumber_cb _hidl_cb)
432{
433	return validateAndCall(
434	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
435	    &P2pIface::setWpsModelNumberInternal, _hidl_cb, model_number);
436}
437
438Return<void> P2pIface::setWpsSerialNumber(
439    const hidl_string& serial_number, setWpsSerialNumber_cb _hidl_cb)
440{
441	return validateAndCall(
442	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
443	    &P2pIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
444}
445
446Return<void> P2pIface::setWpsConfigMethods(
447    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
448{
449	return validateAndCall(
450	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
451	    &P2pIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
452}
453
454Return<void> P2pIface::enableWfd(bool enable, enableWfd_cb _hidl_cb)
455{
456	return validateAndCall(
457	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
458	    &P2pIface::enableWfdInternal, _hidl_cb, enable);
459}
460
461Return<void> P2pIface::setWfdDeviceInfo(
462    const hidl_array<uint8_t, 6>& info, setWfdDeviceInfo_cb _hidl_cb)
463{
464	return validateAndCall(
465	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
466	    &P2pIface::setWfdDeviceInfoInternal, _hidl_cb, info);
467}
468
469Return<void> P2pIface::createNfcHandoverRequestMessage(
470    createNfcHandoverRequestMessage_cb _hidl_cb)
471{
472	return validateAndCall(
473	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
474	    &P2pIface::createNfcHandoverRequestMessageInternal, _hidl_cb);
475}
476
477Return<void> P2pIface::createNfcHandoverSelectMessage(
478    createNfcHandoverSelectMessage_cb _hidl_cb)
479{
480	return validateAndCall(
481	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
482	    &P2pIface::createNfcHandoverSelectMessageInternal, _hidl_cb);
483}
484
485Return<void> P2pIface::reportNfcHandoverResponse(
486    const hidl_vec<uint8_t>& request, reportNfcHandoverResponse_cb _hidl_cb)
487{
488	return validateAndCall(
489	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
490	    &P2pIface::reportNfcHandoverResponseInternal, _hidl_cb, request);
491}
492
493Return<void> P2pIface::reportNfcHandoverInitiation(
494    const hidl_vec<uint8_t>& select, reportNfcHandoverInitiation_cb _hidl_cb)
495{
496	return validateAndCall(
497	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
498	    &P2pIface::reportNfcHandoverInitiationInternal, _hidl_cb, select);
499}
500
501Return<void> P2pIface::saveConfig(saveConfig_cb _hidl_cb)
502{
503	return validateAndCall(
504	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
505	    &P2pIface::saveConfigInternal, _hidl_cb);
506}
507
508std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
509{
510	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
511}
512
513std::pair<SupplicantStatus, IfaceType> P2pIface::getTypeInternal()
514{
515	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
516}
517
518std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
519P2pIface::addNetworkInternal()
520{
521	android::sp<ISupplicantP2pNetwork> network;
522	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
523	struct wpa_ssid* ssid = wpa_supplicant_add_network(wpa_s);
524	if (!ssid) {
525		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
526	}
527	HidlManager* hidl_manager = HidlManager::getInstance();
528	if (!hidl_manager ||
529	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
530		wpa_s->ifname, ssid->id, &network)) {
531		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
532	}
533	return {{SupplicantStatusCode::SUCCESS, ""}, network};
534}
535
536SupplicantStatus P2pIface::removeNetworkInternal(SupplicantNetworkId id)
537{
538	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
539	int result = wpa_supplicant_remove_network(wpa_s, id);
540	if (result == -1) {
541		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
542	}
543	if (result != 0) {
544		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
545	}
546	return {SupplicantStatusCode::SUCCESS, ""};
547}
548
549std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
550P2pIface::getNetworkInternal(SupplicantNetworkId id)
551{
552	android::sp<ISupplicantP2pNetwork> network;
553	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
554	struct wpa_ssid* ssid = wpa_config_get_network(wpa_s->conf, id);
555	if (!ssid) {
556		return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
557			network};
558	}
559	HidlManager* hidl_manager = HidlManager::getInstance();
560	if (!hidl_manager ||
561	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
562		wpa_s->ifname, ssid->id, &network)) {
563		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
564	}
565	return {{SupplicantStatusCode::SUCCESS, ""}, network};
566}
567
568std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
569P2pIface::listNetworksInternal()
570{
571	std::vector<SupplicantNetworkId> network_ids;
572	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
573	for (struct wpa_ssid* wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
574	     wpa_ssid = wpa_ssid->next) {
575		network_ids.emplace_back(wpa_ssid->id);
576	}
577	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
578}
579
580SupplicantStatus P2pIface::registerCallbackInternal(
581    const sp<ISupplicantP2pIfaceCallback>& callback)
582{
583	HidlManager* hidl_manager = HidlManager::getInstance();
584	if (!hidl_manager ||
585	    hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
586		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
587	}
588	return {SupplicantStatusCode::SUCCESS, ""};
589}
590
591std::pair<SupplicantStatus, std::array<uint8_t, 6>>
592P2pIface::getDeviceAddressInternal()
593{
594	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
595	std::array<uint8_t, 6> addr;
596	static_assert(ETH_ALEN == addr.size(), "Size mismatch");
597	os_memcpy(addr.data(), wpa_s->global->p2p_dev_addr, ETH_ALEN);
598	return {{SupplicantStatusCode::SUCCESS, ""}, addr};
599}
600
601SupplicantStatus P2pIface::setSsidPostfixInternal(
602    const std::vector<uint8_t>& postfix)
603{
604	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
605	if (p2p_set_ssid_postfix(
606		wpa_s->global->p2p, postfix.data(), postfix.size())) {
607		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
608	}
609	return {SupplicantStatusCode::SUCCESS, ""};
610}
611
612SupplicantStatus P2pIface::setGroupIdleInternal(
613    const std::string& group_ifname, uint32_t timeout_in_sec)
614{
615	struct wpa_supplicant* wpa_group_s =
616	    retrieveGroupIfacePtr(group_ifname);
617	if (!wpa_group_s) {
618		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
619	}
620	wpa_group_s->conf->p2p_group_idle = timeout_in_sec;
621	return {SupplicantStatusCode::SUCCESS, ""};
622}
623
624SupplicantStatus P2pIface::setPowerSaveInternal(
625    const std::string& group_ifname, bool enable)
626{
627	struct wpa_supplicant* wpa_group_s =
628	    retrieveGroupIfacePtr(group_ifname);
629	if (!wpa_group_s) {
630		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
631	}
632	if (wpa_drv_set_p2p_powersave(wpa_group_s, enable, -1, -1)) {
633		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
634	}
635	return {SupplicantStatusCode::SUCCESS, ""};
636}
637
638SupplicantStatus P2pIface::findInternal(uint32_t timeout_in_sec)
639{
640	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
641	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
642		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
643	}
644	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
645	if (wpas_p2p_find(
646		wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
647		nullptr, search_delay, 0, nullptr, 0)) {
648		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
649	}
650	return {SupplicantStatusCode::SUCCESS, ""};
651}
652
653SupplicantStatus P2pIface::stopFindInternal()
654{
655	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
656	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
657		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
658	}
659	wpas_p2p_stop_find(wpa_s);
660	return {SupplicantStatusCode::SUCCESS, ""};
661}
662
663SupplicantStatus P2pIface::flushInternal()
664{
665	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
666	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
667	wpa_s->force_long_sd = 0;
668	wpas_p2p_stop_find(wpa_s);
669	wpa_s->parent->p2ps_method_config_any = 0;
670	if (wpa_s->global->p2p)
671		p2p_flush(wpa_s->global->p2p);
672	return {SupplicantStatusCode::SUCCESS, ""};
673}
674
675// This method only implements support for subset (needed by Android framework)
676// of parameters that can be specified for connect.
677std::pair<SupplicantStatus, std::string> P2pIface::connectInternal(
678    const std::array<uint8_t, 6>& peer_address,
679    ISupplicantP2pIface::WpsProvisionMethod provision_method,
680    const std::string& pre_selected_pin, bool join_existing_group,
681    bool persistent, uint32_t go_intent)
682{
683	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
684	if (go_intent > 15) {
685		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
686	}
687	int go_intent_signed = join_existing_group ? -1 : go_intent;
688	p2p_wps_method wps_method = {};
689	switch (provision_method) {
690	case WpsProvisionMethod::PBC:
691		wps_method = WPS_PBC;
692		break;
693	case WpsProvisionMethod::DISPLAY:
694		wps_method = WPS_PIN_DISPLAY;
695		break;
696	case WpsProvisionMethod::KEYPAD:
697		wps_method = WPS_PIN_KEYPAD;
698		break;
699	}
700	const char* pin = pre_selected_pin.length() > 0 ? pre_selected_pin.data() : nullptr;
701	int new_pin = wpas_p2p_connect(
702	    wpa_s, peer_address.data(), pin, wps_method,
703	    persistent, false, join_existing_group, false, go_intent_signed, 0, 0, -1,
704	    false, false, false, VHT_CHANWIDTH_USE_HT, nullptr, 0);
705	if (new_pin < 0) {
706		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
707	}
708	std::string pin_ret;
709	if (provision_method == WpsProvisionMethod::DISPLAY &&
710	    pre_selected_pin.empty()) {
711		pin_ret = misc_utils::convertWpsPinToString(new_pin);
712	}
713	return {{SupplicantStatusCode::SUCCESS, ""}, pin_ret};
714}
715
716SupplicantStatus P2pIface::cancelConnectInternal()
717{
718	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
719	if (wpas_p2p_cancel(wpa_s)) {
720		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
721	}
722	return {SupplicantStatusCode::SUCCESS, ""};
723}
724
725SupplicantStatus P2pIface::provisionDiscoveryInternal(
726    const std::array<uint8_t, 6>& peer_address,
727    ISupplicantP2pIface::WpsProvisionMethod provision_method)
728{
729	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
730	p2ps_provision* prov_param;
731	const char* config_method_str = nullptr;
732	switch (provision_method) {
733	case WpsProvisionMethod::PBC:
734		config_method_str = kConfigMethodStrPbc;
735		break;
736	case WpsProvisionMethod::DISPLAY:
737		config_method_str = kConfigMethodStrDisplay;
738		break;
739	case WpsProvisionMethod::KEYPAD:
740		config_method_str = kConfigMethodStrKeypad;
741		break;
742	}
743	if (wpas_p2p_prov_disc(
744		wpa_s, peer_address.data(), config_method_str,
745		WPAS_P2P_PD_FOR_GO_NEG, nullptr)) {
746		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
747	}
748	return {SupplicantStatusCode::SUCCESS, ""};
749}
750
751SupplicantStatus P2pIface::addGroupInternal(
752    bool persistent, SupplicantNetworkId persistent_network_id)
753{
754	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
755	int vht = wpa_s->conf->p2p_go_vht;
756	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
757	struct wpa_ssid* ssid =
758	    wpa_config_get_network(wpa_s->conf, persistent_network_id);
759	if (ssid == NULL) {
760		if (wpas_p2p_group_add(
761			wpa_s, persistent, 0, 0, ht40, vht,
762			VHT_CHANWIDTH_USE_HT)) {
763			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
764		} else {
765			return {SupplicantStatusCode::SUCCESS, ""};
766		}
767	} else if (ssid->disabled == 2) {
768		if (wpas_p2p_group_add_persistent(
769			wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
770			VHT_CHANWIDTH_USE_HT, NULL, 0, 0)) {
771			return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
772				""};
773		} else {
774			return {SupplicantStatusCode::SUCCESS, ""};
775		}
776	}
777	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
778}
779
780SupplicantStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
781{
782	struct wpa_supplicant* wpa_group_s =
783	    retrieveGroupIfacePtr(group_ifname);
784	if (!wpa_group_s) {
785		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
786	}
787	if (wpas_p2p_group_remove(wpa_group_s, group_ifname.c_str())) {
788		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
789	}
790	return {SupplicantStatusCode::SUCCESS, ""};
791}
792
793SupplicantStatus P2pIface::rejectInternal(
794    const std::array<uint8_t, 6>& peer_address)
795{
796	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
797	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
798		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
799	}
800	if (wpas_p2p_reject(wpa_s, peer_address.data())) {
801		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
802	}
803	return {SupplicantStatusCode::SUCCESS, ""};
804}
805
806SupplicantStatus P2pIface::inviteInternal(
807    const std::string& group_ifname,
808    const std::array<uint8_t, 6>& go_device_address,
809    const std::array<uint8_t, 6>& peer_address)
810{
811	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
812	if (wpas_p2p_invite_group(
813		wpa_s, group_ifname.c_str(), peer_address.data(),
814		go_device_address.data())) {
815		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
816	}
817	return {SupplicantStatusCode::SUCCESS, ""};
818}
819
820SupplicantStatus P2pIface::reinvokeInternal(
821    SupplicantNetworkId persistent_network_id,
822    const std::array<uint8_t, 6>& peer_address)
823{
824	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
825	int vht = wpa_s->conf->p2p_go_vht;
826	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
827	struct wpa_ssid* ssid =
828	    wpa_config_get_network(wpa_s->conf, persistent_network_id);
829	if (ssid == NULL || ssid->disabled != 2) {
830		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
831	}
832	if (wpas_p2p_invite(
833		wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
834		VHT_CHANWIDTH_USE_HT, 0)) {
835		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
836	}
837	return {SupplicantStatusCode::SUCCESS, ""};
838}
839
840SupplicantStatus P2pIface::configureExtListenInternal(
841    uint32_t period_in_millis, uint32_t interval_in_millis)
842{
843	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
844	if (wpas_p2p_ext_listen(wpa_s, period_in_millis, interval_in_millis)) {
845		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
846	}
847	return {SupplicantStatusCode::SUCCESS, ""};
848}
849
850SupplicantStatus P2pIface::setListenChannelInternal(
851    uint32_t channel, uint32_t operating_class)
852{
853	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
854	if (p2p_set_listen_channel(
855		wpa_s->global->p2p, operating_class, channel, 1)) {
856		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
857	}
858	return {SupplicantStatusCode::SUCCESS, ""};
859}
860
861SupplicantStatus P2pIface::setDisallowedFrequenciesInternal(
862    const std::vector<FreqRange>& ranges)
863{
864	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
865	using DestT = struct wpa_freq_range_list::wpa_freq_range;
866	DestT* freq_ranges = nullptr;
867	// Empty ranges is used to enable all frequencies.
868	if (ranges.size() != 0) {
869		freq_ranges =
870		    static_cast<DestT*>(os_malloc(sizeof(DestT) * ranges.size()));
871		if (!freq_ranges) {
872			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
873		}
874		uint32_t i = 0;
875		for (const auto& range : ranges) {
876			freq_ranges[i].min = range.min;
877			freq_ranges[i].max = range.max;
878			i++;
879		}
880	}
881
882	os_free(wpa_s->global->p2p_disallow_freq.range);
883	wpa_s->global->p2p_disallow_freq.range = freq_ranges;
884	wpa_s->global->p2p_disallow_freq.num = ranges.size();
885	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
886	return {SupplicantStatusCode::SUCCESS, ""};
887}
888
889std::pair<SupplicantStatus, std::vector<uint8_t>> P2pIface::getSsidInternal(
890    const std::array<uint8_t, 6>& peer_address)
891{
892	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
893	const struct p2p_peer_info* info =
894	    p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
895	if (!info) {
896		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
897	}
898	const struct p2p_device* dev =
899	    reinterpret_cast<const struct p2p_device*>(
900		(reinterpret_cast<const uint8_t*>(info)) -
901		offsetof(struct p2p_device, info));
902	std::vector<uint8_t> ssid;
903	if (dev && dev->oper_ssid_len) {
904		ssid.assign(
905		    dev->oper_ssid, dev->oper_ssid + dev->oper_ssid_len);
906	}
907	return {{SupplicantStatusCode::SUCCESS, ""}, ssid};
908}
909
910std::pair<SupplicantStatus, uint32_t> P2pIface::getGroupCapabilityInternal(
911    const std::array<uint8_t, 6>& peer_address)
912{
913	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
914	const struct p2p_peer_info* info =
915	    p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
916	if (!info) {
917		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
918	}
919	return {{SupplicantStatusCode::SUCCESS, ""}, info->group_capab};
920}
921
922SupplicantStatus P2pIface::addBonjourServiceInternal(
923    const std::vector<uint8_t>& query, const std::vector<uint8_t>& response)
924{
925	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
926	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
927	auto response_buf = misc_utils::convertVectorToWpaBuf(response);
928	if (!query_buf || !response_buf) {
929		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
930	}
931	if (wpas_p2p_service_add_bonjour(
932		wpa_s, query_buf.get(), response_buf.get())) {
933		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
934	}
935	// If successful, the wpabuf is referenced internally and hence should
936	// not be freed.
937	query_buf.release();
938	response_buf.release();
939	return {SupplicantStatusCode::SUCCESS, ""};
940}
941
942SupplicantStatus P2pIface::removeBonjourServiceInternal(
943    const std::vector<uint8_t>& query)
944{
945	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
946	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
947	if (!query_buf) {
948		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
949	}
950	if (wpas_p2p_service_del_bonjour(wpa_s, query_buf.get())) {
951		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
952	}
953	return {SupplicantStatusCode::SUCCESS, ""};
954}
955
956SupplicantStatus P2pIface::addUpnpServiceInternal(
957    uint32_t version, const std::string& service_name)
958{
959	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
960	if (wpas_p2p_service_add_upnp(wpa_s, version, service_name.c_str())) {
961		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
962	}
963	return {SupplicantStatusCode::SUCCESS, ""};
964}
965
966SupplicantStatus P2pIface::removeUpnpServiceInternal(
967    uint32_t version, const std::string& service_name)
968{
969	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
970	if (wpas_p2p_service_del_upnp(wpa_s, version, service_name.c_str())) {
971		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
972	}
973	return {SupplicantStatusCode::SUCCESS, ""};
974}
975
976SupplicantStatus P2pIface::flushServicesInternal()
977{
978	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
979	wpas_p2p_service_flush(wpa_s);
980	return {SupplicantStatusCode::SUCCESS, ""};
981}
982
983std::pair<SupplicantStatus, uint64_t> P2pIface::requestServiceDiscoveryInternal(
984    const std::array<uint8_t, 6>& peer_address,
985    const std::vector<uint8_t>& query)
986{
987	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
988	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
989	if (!query_buf) {
990		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
991	}
992	const uint8_t* dst_addr = is_zero_ether_addr(peer_address.data())
993				      ? nullptr
994				      : peer_address.data();
995	uint64_t identifier =
996	    wpas_p2p_sd_request(wpa_s, dst_addr, query_buf.get());
997	if (identifier == 0) {
998		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
999	}
1000	return {{SupplicantStatusCode::SUCCESS, ""}, identifier};
1001}
1002
1003SupplicantStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
1004{
1005	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1006	if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
1007		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1008	}
1009	return {SupplicantStatusCode::SUCCESS, ""};
1010}
1011
1012SupplicantStatus P2pIface::setMiracastModeInternal(
1013    ISupplicantP2pIface::MiracastMode mode)
1014{
1015	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1016	uint8_t mode_internal = convertHidlMiracastModeToInternal(mode);
1017	const std::string cmd_str =
1018	    kSetMiracastMode + std::to_string(mode_internal);
1019	std::vector<char> cmd(
1020	    cmd_str.c_str(), cmd_str.c_str() + cmd_str.size() + 1);
1021	char driver_cmd_reply_buf[4096] = {};
1022	if (wpa_drv_driver_cmd(
1023		wpa_s, cmd.data(), driver_cmd_reply_buf,
1024		sizeof(driver_cmd_reply_buf))) {
1025		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1026	}
1027	return {SupplicantStatusCode::SUCCESS, ""};
1028}
1029
1030SupplicantStatus P2pIface::startWpsPbcInternal(
1031    const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
1032{
1033	struct wpa_supplicant* wpa_group_s =
1034	    retrieveGroupIfacePtr(group_ifname);
1035	if (!wpa_group_s) {
1036		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
1037	}
1038	const uint8_t* bssid_addr =
1039	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
1040#ifdef CONFIG_AP
1041	if (wpa_group_s->ap_iface) {
1042		if (wpa_supplicant_ap_wps_pbc(wpa_group_s, bssid_addr, NULL)) {
1043			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1044		}
1045		return {SupplicantStatusCode::SUCCESS, ""};
1046	}
1047#endif /* CONFIG_AP */
1048	if (wpas_wps_start_pbc(wpa_group_s, bssid_addr, 0)) {
1049		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1050	}
1051	return {SupplicantStatusCode::SUCCESS, ""};
1052}
1053
1054SupplicantStatus P2pIface::startWpsPinKeypadInternal(
1055    const std::string& group_ifname, const std::string& pin)
1056{
1057	struct wpa_supplicant* wpa_group_s =
1058	    retrieveGroupIfacePtr(group_ifname);
1059	if (!wpa_group_s) {
1060		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
1061	}
1062#ifdef CONFIG_AP
1063	if (wpa_group_s->ap_iface) {
1064		if (wpa_supplicant_ap_wps_pin(
1065				wpa_group_s, nullptr, pin.c_str(), nullptr, 0, 0) < 0) {
1066			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1067		}
1068		return {SupplicantStatusCode::SUCCESS, ""};
1069	}
1070#endif /* CONFIG_AP */
1071	if (wpas_wps_start_pin(
1072		wpa_group_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
1073		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1074	}
1075	return {SupplicantStatusCode::SUCCESS, ""};
1076}
1077
1078std::pair<SupplicantStatus, std::string> P2pIface::startWpsPinDisplayInternal(
1079    const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
1080{
1081	struct wpa_supplicant* wpa_group_s =
1082	    retrieveGroupIfacePtr(group_ifname);
1083	if (!wpa_group_s) {
1084		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""}, ""};
1085	}
1086	const uint8_t* bssid_addr =
1087	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
1088	int pin = wpas_wps_start_pin(
1089	    wpa_group_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
1090	if (pin < 0) {
1091		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
1092	}
1093	return {{SupplicantStatusCode::SUCCESS, ""},
1094		misc_utils::convertWpsPinToString(pin)};
1095}
1096
1097SupplicantStatus P2pIface::cancelWpsInternal(const std::string& group_ifname)
1098{
1099	struct wpa_supplicant* wpa_group_s =
1100	    retrieveGroupIfacePtr(group_ifname);
1101	if (!wpa_group_s) {
1102		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
1103	}
1104	if (wpas_wps_cancel(wpa_group_s)) {
1105		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1106	}
1107	return {SupplicantStatusCode::SUCCESS, ""};
1108}
1109
1110SupplicantStatus P2pIface::setWpsDeviceNameInternal(const std::string& name)
1111{
1112	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
1113}
1114
1115SupplicantStatus P2pIface::setWpsDeviceTypeInternal(
1116    const std::array<uint8_t, 8>& type)
1117{
1118	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
1119}
1120
1121SupplicantStatus P2pIface::setWpsManufacturerInternal(
1122    const std::string& manufacturer)
1123{
1124	return iface_config_utils::setWpsManufacturer(
1125	    retrieveIfacePtr(), manufacturer);
1126}
1127
1128SupplicantStatus P2pIface::setWpsModelNameInternal(
1129    const std::string& model_name)
1130{
1131	return iface_config_utils::setWpsModelName(
1132	    retrieveIfacePtr(), model_name);
1133}
1134
1135SupplicantStatus P2pIface::setWpsModelNumberInternal(
1136    const std::string& model_number)
1137{
1138	return iface_config_utils::setWpsModelNumber(
1139	    retrieveIfacePtr(), model_number);
1140}
1141
1142SupplicantStatus P2pIface::setWpsSerialNumberInternal(
1143    const std::string& serial_number)
1144{
1145	return iface_config_utils::setWpsSerialNumber(
1146	    retrieveIfacePtr(), serial_number);
1147}
1148
1149SupplicantStatus P2pIface::setWpsConfigMethodsInternal(uint16_t config_methods)
1150{
1151	return iface_config_utils::setWpsConfigMethods(
1152	    retrieveIfacePtr(), config_methods);
1153}
1154
1155SupplicantStatus P2pIface::enableWfdInternal(bool enable)
1156{
1157	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1158	wifi_display_enable(wpa_s->global, enable);
1159	return {SupplicantStatusCode::SUCCESS, ""};
1160}
1161
1162SupplicantStatus P2pIface::setWfdDeviceInfoInternal(
1163    const std::array<uint8_t, 6>& info)
1164{
1165	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1166	std::vector<char> wfd_device_info_hex(info.size() * 2 + 1);
1167	wpa_snprintf_hex(
1168	    wfd_device_info_hex.data(), wfd_device_info_hex.size(), info.data(),
1169	    info.size());
1170	// |wifi_display_subelem_set| expects the first 2 bytes
1171	// to hold the lenght of the subelement. In this case it's
1172	// fixed to 6, so prepend that.
1173	std::string wfd_device_info_set_cmd_str =
1174	    std::to_string(kWfdDeviceInfoSubelemId) + " " +
1175	    kWfdDeviceInfoSubelemLenHexStr + wfd_device_info_hex.data();
1176	std::vector<char> wfd_device_info_set_cmd(
1177	    wfd_device_info_set_cmd_str.c_str(),
1178	    wfd_device_info_set_cmd_str.c_str() +
1179		wfd_device_info_set_cmd_str.size() + 1);
1180	if (wifi_display_subelem_set(
1181		wpa_s->global, wfd_device_info_set_cmd.data())) {
1182		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1183	}
1184	return {SupplicantStatusCode::SUCCESS, ""};
1185}
1186
1187std::pair<SupplicantStatus, std::vector<uint8_t>>
1188P2pIface::createNfcHandoverRequestMessageInternal()
1189{
1190	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1191	auto buf = misc_utils::createWpaBufUniquePtr(
1192	    wpas_p2p_nfc_handover_req(wpa_s, 1));
1193	if (!buf) {
1194		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
1195	}
1196	return {{SupplicantStatusCode::SUCCESS, ""},
1197		misc_utils::convertWpaBufToVector(buf.get())};
1198}
1199
1200std::pair<SupplicantStatus, std::vector<uint8_t>>
1201P2pIface::createNfcHandoverSelectMessageInternal()
1202{
1203	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1204	auto buf = misc_utils::createWpaBufUniquePtr(
1205	    wpas_p2p_nfc_handover_sel(wpa_s, 1, 0));
1206	if (!buf) {
1207		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
1208	}
1209	return {{SupplicantStatusCode::SUCCESS, ""},
1210		misc_utils::convertWpaBufToVector(buf.get())};
1211}
1212
1213SupplicantStatus P2pIface::reportNfcHandoverResponseInternal(
1214    const std::vector<uint8_t>& request)
1215{
1216	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1217	auto req = misc_utils::convertVectorToWpaBuf(request);
1218	auto sel = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
1219	if (!req || !sel) {
1220		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1221	}
1222
1223	if (wpas_p2p_nfc_report_handover(wpa_s, 0, req.get(), sel.get(), 0)) {
1224		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1225	}
1226	return {SupplicantStatusCode::SUCCESS, ""};
1227}
1228
1229SupplicantStatus P2pIface::reportNfcHandoverInitiationInternal(
1230    const std::vector<uint8_t>& select)
1231{
1232	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1233	auto req = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
1234	auto sel = misc_utils::convertVectorToWpaBuf(select);
1235	if (!req || !sel) {
1236		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1237	}
1238
1239	if (wpas_p2p_nfc_report_handover(wpa_s, 1, req.get(), sel.get(), 0)) {
1240		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1241	}
1242	return {SupplicantStatusCode::SUCCESS, ""};
1243}
1244
1245SupplicantStatus P2pIface::saveConfigInternal()
1246{
1247	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
1248	if (!wpa_s->conf->update_config) {
1249		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1250	}
1251	if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
1252		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
1253	}
1254	return {SupplicantStatusCode::SUCCESS, ""};
1255}
1256
1257/**
1258 * Retrieve the underlying |wpa_supplicant| struct
1259 * pointer for this iface.
1260 * If the underlying iface is removed, then all RPC method calls on this object
1261 * will return failure.
1262 */
1263wpa_supplicant* P2pIface::retrieveIfacePtr()
1264{
1265	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
1266}
1267
1268/**
1269 * Retrieve the underlying |wpa_supplicant| struct
1270 * pointer for this group iface.
1271 */
1272wpa_supplicant* P2pIface::retrieveGroupIfacePtr(const std::string& group_ifname)
1273{
1274	return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
1275}
1276
1277}  // namespace implementation
1278}  // namespace V1_0
1279}  // namespace wifi
1280}  // namespace supplicant
1281}  // namespace hardware
1282}  // namespace android
1283