1/*
2 * Copyright 2007-2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6#include <stdio.h>
7#include <unistd.h>
8#include <malloc.h>
9
10#include <String.h>
11#include <Message.h>
12#include <Application.h>
13
14#include <Button.h>
15#include <GroupLayoutBuilder.h>
16#include <InterfaceDefs.h>
17#include <SpaceLayoutItem.h>
18#include <StringView.h>
19#include <TextControl.h>
20
21#include <bluetooth/RemoteDevice.h>
22#include <bluetooth/LocalDevice.h>
23#include <bluetooth/bdaddrUtils.h>
24#include <bluetooth/bluetooth_error.h>
25
26#include <bluetooth/HCI/btHCI_command.h>
27#include <bluetooth/HCI/btHCI_event.h>
28
29#include <PincodeWindow.h>
30#include <bluetoothserver_p.h>
31#include <CommandManager.h>
32
33
34#define H_SEPARATION  15
35#define V_SEPARATION  10
36#define BD_ADDR_LABEL "BD_ADDR: "
37
38static const uint32 skMessageAcceptButton = 'acCp';
39static const uint32 skMessageCancelButton = 'mVch';
40
41
42namespace Bluetooth {
43
44
45#if 0
46#pragma mark -
47#endif
48
49PincodeWindow::PincodeWindow(bdaddr_t address, hci_id hid)
50	: BWindow(BRect(800, 200, 900, 300), "Pincode request",
51		B_FLOATING_WINDOW,
52		B_WILL_ACCEPT_FIRST_CLICK | B_NOT_RESIZABLE|  B_NOT_ZOOMABLE
53		| B_AUTO_UPDATE_SIZE_LIMITS,
54		B_ALL_WORKSPACES), fBdaddr(address), fHid(hid)
55{
56	InitUI();
57
58	// TODO: Get more info about device" ote name/features/encry/auth... etc
59	SetBDaddr(bdaddrUtils::ToString(fBdaddr));
60
61}
62
63
64PincodeWindow::PincodeWindow(RemoteDevice* rDevice)
65	: BWindow(BRect(800, 200, 900, 300), "Pincode request",
66		B_FLOATING_WINDOW,
67		B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_RESIZABLE
68		| B_AUTO_UPDATE_SIZE_LIMITS,
69		B_ALL_WORKSPACES)
70{
71	// TODO: Get more info about device" ote name/features/encry/auth... etc
72	SetBDaddr(bdaddrUtils::ToString(rDevice->GetBluetoothAddress()));
73	fHid = (rDevice->GetLocalDeviceOwner())->ID();
74}
75
76
77void
78PincodeWindow::InitUI()
79{
80	SetLayout(new BGroupLayout(B_HORIZONTAL));
81
82	fMessage = new BStringView("Pincode", "Please enter the pincode ...");
83	fMessage->SetFont(be_bold_font);
84
85	fRemoteInfo = new BStringView("bdaddr","BD_ADDR: ");
86
87	// TODO: Pincode cannot be more than 16 bytes
88	fPincodeText = new BTextControl("pincode TextControl", "PIN code:", "5555", NULL);
89
90	fAcceptButton = new BButton("fAcceptButton", "Pair",
91		new BMessage(skMessageAcceptButton));
92
93	fCancelButton = new BButton("fCancelButton", "Cancel",
94		new BMessage(skMessageCancelButton));
95
96	AddChild(BGroupLayoutBuilder(B_VERTICAL, 10)
97				.Add(fMessage)
98				.Add(fRemoteInfo)
99				.Add(fPincodeText)
100				.Add(BGroupLayoutBuilder(B_HORIZONTAL, 10)
101					.AddGlue()
102					.Add(fCancelButton)
103					.Add(fAcceptButton)
104					.SetInsets(5, 5, 5, 5)
105				)
106			.SetInsets(15, 15, 15, 15)
107	);
108}
109
110
111void
112PincodeWindow::MessageReceived(BMessage *msg)
113{
114//	status_t err = B_OK;
115
116	switch(msg->what)
117	{
118		case skMessageAcceptButton:
119		{
120			BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
121			BMessage reply;
122			size_t size;
123			int8 bt_status = BT_ERROR;
124
125			void* command = buildPinCodeRequestReply(fBdaddr,
126				strlen(fPincodeText->Text()),
127				(char*)fPincodeText->Text(), &size);
128
129			if (command == NULL) {
130				break;
131			}
132
133			request.AddInt32("hci_id", fHid);
134			request.AddData("raw command", B_ANY_TYPE, command, size);
135			request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
136			request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
137				OCF_PIN_CODE_REPLY));
138
139			// we reside in the server
140			if (be_app_messenger.SendMessage(&request, &reply) == B_OK) {
141				if (reply.FindInt8("status", &bt_status ) == B_OK ) {
142					PostMessage(B_QUIT_REQUESTED);
143				}
144				// TODO: something failed here
145			}
146			break;
147		}
148
149		case skMessageCancelButton:
150		{
151			BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
152			BMessage reply;
153			size_t size;
154			int8 bt_status = BT_ERROR;
155
156			void* command = buildPinCodeRequestNegativeReply(fBdaddr, &size);
157
158			if (command == NULL) {
159				break;
160			}
161
162			request.AddInt32("hci_id", fHid);
163			request.AddData("raw command", B_ANY_TYPE, command, size);
164			request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
165			request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
166				OCF_PIN_CODE_NEG_REPLY));
167
168			if (be_app_messenger.SendMessage(&request, &reply) == B_OK) {
169				if (reply.FindInt8("status", &bt_status ) == B_OK ) {
170					PostMessage(B_QUIT_REQUESTED);
171				}
172				// TODO: something failed here
173			}
174			break;
175		}
176
177		default:
178			BWindow::MessageReceived(msg);
179			break;
180	}
181}
182
183
184bool PincodeWindow::QuitRequested()
185{
186	return BWindow::QuitRequested();
187}
188
189
190void PincodeWindow::SetBDaddr(const char* address)
191{
192	BString label;
193
194	label << BD_ADDR_LABEL << address;
195	printf("++ %s\n",label.String());
196	fRemoteInfo->SetText(label.String());
197	fRemoteInfo->ResizeToPreferred();
198	//Invalidate();
199
200}
201
202
203}
204