1/*
2 * Copyright 2007-2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3 * Copyright 2021, Haiku, Inc.
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 * 		Tri-Edge AI <triedgeai@gmail.com>
8 */
9
10
11#include <stdio.h>
12#include <unistd.h>
13#include <malloc.h>
14
15#include <String.h>
16#include <Message.h>
17#include <Application.h>
18
19#include <Button.h>
20#include <GroupLayoutBuilder.h>
21#include <InterfaceDefs.h>
22#include <SpaceLayoutItem.h>
23#include <StringView.h>
24#include <TextControl.h>
25
26#include <bluetooth/RemoteDevice.h>
27#include <bluetooth/LocalDevice.h>
28#include <bluetooth/bdaddrUtils.h>
29#include <bluetooth/bluetooth_error.h>
30
31#include <bluetooth/HCI/btHCI_command.h>
32#include <bluetooth/HCI/btHCI_event.h>
33
34#include <PincodeWindow.h>
35#include <bluetoothserver_p.h>
36#include <CommandManager.h>
37
38
39#define H_SEPARATION  15
40#define V_SEPARATION  10
41#define BD_ADDR_LABEL "BD_ADDR: "
42
43
44static const uint32 skMessageAcceptButton = 'acCp';
45static const uint32 skMessageCancelButton = 'mVch';
46
47
48namespace Bluetooth
49{
50
51PincodeWindow::PincodeWindow(bdaddr_t address, hci_id hid)
52	: BWindow(BRect(700, 200, 1000, 400), "PIN Code Request",
53		B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
54		B_NOT_ZOOMABLE | B_NOT_RESIZABLE),
55		fBdaddr(address),
56		fHid(hid)
57{
58	InitUI();
59
60	// TODO: Get more info about device" ote name/features/encry/auth... etc
61	SetBDaddr(bdaddrUtils::ToString(fBdaddr));
62
63}
64
65
66PincodeWindow::PincodeWindow(RemoteDevice* rDevice)
67	: BWindow(BRect(700, 200, 1000, 400), "PIN Code Request",
68		B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
69		B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
70{
71	InitUI();
72
73	// TODO: Get more info about device" ote name/features/encry/auth... etc
74	SetBDaddr(bdaddrUtils::ToString(rDevice->GetBluetoothAddress()));
75	fHid = (rDevice->GetLocalDeviceOwner())->ID();
76}
77
78
79void
80PincodeWindow::InitUI()
81{
82	SetLayout(new BGroupLayout(B_HORIZONTAL));
83
84	fIcon = new BluetoothIconView();
85
86	fMessage = new BStringView("fMessage", "Input the PIN code to pair with");
87	fMessage2 = new BStringView("fMessage2", "the following Bluetooth device.");
88
89	fDeviceLabel = new BStringView("fDeviceLabel","Device Name: ");
90	fDeviceLabel->SetFont(be_bold_font);
91
92	fDeviceText = new BStringView("fDeviceText", "<unknown_device>");
93
94	fAddressLabel = new BStringView("fAddressLabel", "MAC Address: ");
95	fAddressLabel->SetFont(be_bold_font);
96
97	fAddressText = new BStringView("fAddressText", "<mac_address>");
98
99	fPincodeText = new BTextControl("fPINCode", "PIN Code:", "0000", NULL);
100	fPincodeText->TextView()->SetMaxBytes(16 * sizeof(fPincodeText->Text()[0]));
101	fPincodeText->MakeFocus();
102
103	fAcceptButton = new BButton("fAcceptButton", "Pair",
104		new BMessage(skMessageAcceptButton));
105
106	fCancelButton = new BButton("fCancelButton", "Cancel",
107		new BMessage(skMessageCancelButton));
108
109	AddChild(BGroupLayoutBuilder(B_VERTICAL, 0)
110		.Add(BGroupLayoutBuilder(B_HORIZONTAL, 0)
111			.Add(BGroupLayoutBuilder(B_HORIZONTAL, 8)
112				.Add(fIcon)
113			)
114			.Add(BGroupLayoutBuilder(B_VERTICAL, 0)
115				.Add(fMessage)
116				.Add(fMessage2)
117				.AddGlue()
118			)
119		)
120		.Add(BGroupLayoutBuilder(B_HORIZONTAL, 0)
121			.Add(fDeviceLabel)
122			.AddGlue()
123			.Add(fDeviceText)
124		)
125		.Add(BGroupLayoutBuilder(B_HORIZONTAL, 0)
126			.Add(fAddressLabel)
127			.AddGlue()
128			.Add(fAddressText)
129		)
130		.AddGlue()
131		.Add(fPincodeText)
132		.AddGlue()
133		.Add(BGroupLayoutBuilder(B_HORIZONTAL, 10)
134			.AddGlue()
135			.Add(fCancelButton)
136			.Add(fAcceptButton)
137		)
138		.SetInsets(8, 8, 8, 8)
139	);
140}
141
142
143void
144PincodeWindow::MessageReceived(BMessage* msg)
145{
146	switch (msg->what)
147	{
148		case skMessageAcceptButton:
149		{
150			BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
151			BMessage reply;
152			size_t size;
153			int8 bt_status = BT_ERROR;
154
155			void* command = buildPinCodeRequestReply(fBdaddr,
156				strlen(fPincodeText->Text()),
157				(char*)fPincodeText->Text(), &size);
158
159			if (command == NULL) {
160				break;
161			}
162
163			request.AddInt32("hci_id", fHid);
164			request.AddData("raw command", B_ANY_TYPE, command, size);
165			request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
166			request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
167				OCF_PIN_CODE_REPLY));
168
169			// we reside in the server
170			if (be_app_messenger.SendMessage(&request, &reply) == B_OK) {
171				if (reply.FindInt8("status", &bt_status ) == B_OK) {
172					PostMessage(B_QUIT_REQUESTED);
173				}
174				// TODO: something failed here
175			}
176			break;
177		}
178
179		case skMessageCancelButton:
180		{
181			BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
182			BMessage reply;
183			size_t size;
184			int8 bt_status = BT_ERROR;
185
186			void* command = buildPinCodeRequestNegativeReply(fBdaddr, &size);
187
188			if (command == NULL) {
189				break;
190			}
191
192			request.AddInt32("hci_id", fHid);
193			request.AddData("raw command", B_ANY_TYPE, command, size);
194			request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
195			request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
196				OCF_PIN_CODE_NEG_REPLY));
197
198			if (be_app_messenger.SendMessage(&request, &reply) == B_OK) {
199				if (reply.FindInt8("status", &bt_status ) == B_OK ) {
200					PostMessage(B_QUIT_REQUESTED);
201				}
202				// TODO: something failed here
203			}
204			break;
205		}
206
207		default:
208			BWindow::MessageReceived(msg);
209			break;
210	}
211}
212
213
214bool
215PincodeWindow::QuitRequested()
216{
217	return BWindow::QuitRequested();
218}
219
220
221void
222PincodeWindow::SetBDaddr(BString address)
223{
224	fAddressText->SetText(address);
225}
226
227} /* end namespace Bluetooth */
228