1/*
2 * Copyright 2007-2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3 * Copyright 2008 Mika Lindqvist
4 * Copyright 2012 Fredrik Mod��en [firstname]@[lastname].se
5 * All rights reserved. Distributed under the terms of the MIT License.
6 */
7#ifndef _COMMAND_MANAGER_H
8#define _COMMAND_MANAGER_H
9
10#include <malloc.h>
11#include <string.h>
12
13#include <bluetooth/bluetooth.h>
14#include <bluetooth/bluetooth_error.h>
15#include <bluetooth/HCI/btHCI_command.h>
16#include <bluetooth/HCI/btHCI_event.h>
17
18#include <Message.h>
19#include <Messenger.h>
20
21#include <bluetoothserver_p.h>
22
23#define typed_command(type) type, sizeof(type)
24
25template <typename Type = void, int paramSize = 0,
26	int HeaderSize = HCI_COMMAND_HDR_SIZE>
27class BluetoothCommand {
28
29public:
30	BluetoothCommand(uint8 ogf, uint8 ocf)
31	{
32		fHeader = (struct hci_command_header*) fBuffer;
33
34		if (paramSize != 0)
35			fContent = (Type*)(fHeader + 1);
36		else
37			// avoid pointing outside in case of not having parameters
38			fContent = (Type*)fHeader;
39
40		fHeader->opcode = B_HOST_TO_LENDIAN_INT16(PACK_OPCODE(ogf, ocf));
41		fHeader->clen = paramSize;
42	}
43
44	Type*
45	operator->() const
46	{
47 		return fContent;
48	}
49
50	void*
51	Data() const
52	{
53		return (void*)fBuffer;
54	}
55
56	size_t Size() const
57	{
58		return HeaderSize + paramSize;
59	}
60
61private:
62	char fBuffer[paramSize + HeaderSize];
63	Type* fContent;
64	struct hci_command_header* fHeader;
65};
66
67
68status_t
69NonParameterCommandRequest(uint8 ofg, uint8 ocf, int32* result, hci_id hId,
70	BMessenger* messenger);
71
72template<typename PARAMETERCONTAINER, typename PARAMETERTYPE>
73status_t
74SingleParameterCommandRequest(uint8 ofg, uint8 ocf, PARAMETERTYPE parameter,
75	int32* result, hci_id hId, BMessenger* messenger)
76{
77	int8 bt_status = BT_ERROR;
78
79	BluetoothCommand<typed_command(PARAMETERCONTAINER)>
80		simpleCommand(ofg, ocf);
81
82	simpleCommand->param = parameter;
83
84	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
85	BMessage reply;
86
87	simpleCommand->param = parameter;
88
89	request.AddInt32("hci_id", hId);
90	request.AddData("raw command", B_ANY_TYPE, simpleCommand.Data(),
91		simpleCommand.Size());
92	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
93	request.AddInt16("opcodeExpected", PACK_OPCODE(ofg, ocf));
94
95	if (messenger->SendMessage(&request, &reply) == B_OK) {
96		reply.FindInt8("status", &bt_status);
97		if (result != NULL)
98			reply.FindInt32("result", result);
99	}
100
101	return bt_status;
102}
103
104
105/* CONTROL BASEBAND */
106void* buildReset(size_t* outsize);
107void* buildReadLocalName(size_t* outsize);
108void* buildReadScan(size_t* outsize);
109void* buildWriteScan(uint8 scanmode, size_t* outsize);
110void* buildReadClassOfDevice(size_t* outsize);
111
112/* LINK CONTROL */
113void* buildRemoteNameRequest(bdaddr_t bdaddr, uint8 pscan_rep_mode,
114	uint16 clock_offset, size_t* outsize);
115void* buildInquiry(uint32 lap, uint8 length, uint8 num_rsp, size_t* outsize);
116void* buildInquiryCancel(size_t* outsize);
117void* buildPinCodeRequestReply(bdaddr_t bdaddr, uint8 length, char pincode[16],
118	size_t* outsize);
119void* buildPinCodeRequestNegativeReply(bdaddr_t bdaddr, size_t* outsize);
120void* buildAcceptConnectionRequest(bdaddr_t bdaddr, uint8 role,
121	size_t* outsize);
122void* buildRejectConnectionRequest(bdaddr_t bdaddr, size_t* outsize);
123
124/* OGF_INFORMATIONAL_PARAM */
125void* buildReadLocalVersionInformation(size_t* outsize);
126void* buildReadBufferSize(size_t* outsize);
127void* buildReadBdAddr(size_t* outsize);
128
129#endif
130