/* * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com * Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com * Copyright 2012 Fredrik Modéen, [firstname]@[lastname] * All rights reserved. Distributed under the terms of the MIT License. */ #include #include #include #include #include #include #include #include #include #include #include #include "KitSupport.h" namespace Bluetooth { LocalDevice* LocalDevice::RequestLocalDeviceID(BMessage* request) { BMessage reply; hci_id hid; LocalDevice* lDevice = NULL; BMessenger* messenger = _RetrieveBluetoothMessenger(); if (messenger == NULL) return NULL; if (messenger->SendMessage(request, &reply) == B_OK && reply.FindInt32("hci_id", &hid) == B_OK ) { if (hid >= 0) lDevice = new (std::nothrow)LocalDevice(hid); } delete messenger; return lDevice; } #if 0 #pragma - #endif LocalDevice* LocalDevice::GetLocalDevice() { BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE); return RequestLocalDeviceID(&request); } LocalDevice* LocalDevice::GetLocalDevice(const hci_id hid) { BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE); request.AddInt32("hci_id", hid); return RequestLocalDeviceID(&request); } LocalDevice* LocalDevice::GetLocalDevice(const bdaddr_t bdaddr) { BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE); request.AddData("bdaddr", B_ANY_TYPE, &bdaddr, sizeof(bdaddr_t)); return RequestLocalDeviceID(&request); } uint32 LocalDevice::GetLocalDeviceCount() { BMessenger* messenger = _RetrieveBluetoothMessenger(); uint32 count = 0; if (messenger != NULL) { BMessage request(BT_MSG_COUNT_LOCAL_DEVICES); BMessage reply; if (messenger->SendMessage(&request, &reply) == B_OK) count = reply.FindInt32("count"); delete messenger; } return count; } DiscoveryAgent* LocalDevice::GetDiscoveryAgent() { // TODO: Study a singleton here return new (std::nothrow)DiscoveryAgent(this); } BString LocalDevice::GetProperty(const char* property) { return NULL; } status_t LocalDevice::GetProperty(const char* property, uint32* value) { if (fMessenger == NULL) return B_ERROR; BMessage request(BT_MSG_GET_PROPERTY); BMessage reply; request.AddInt32("hci_id", fHid); request.AddString("property", property); if (fMessenger->SendMessage(&request, &reply) == B_OK) { if (reply.FindInt32("result", (int32*)value ) == B_OK ) { return B_OK; } } return B_ERROR; } int LocalDevice::GetDiscoverable() { if (fMessenger == NULL) return -1; size_t size; void* command = buildReadScan(&size); if (command == NULL) return -1; BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, command, size); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_SCAN_ENABLE)); int8 discoverable; BMessage reply; if (fMessenger->SendMessage(&request, &reply) == B_OK && reply.FindInt8("scan_enable", &discoverable) == B_OK) return discoverable; return -1; } status_t LocalDevice::SetDiscoverable(int mode) { if (fMessenger == NULL) return B_ERROR; BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; size_t size; int8 bt_status = BT_ERROR; request.AddInt32("hci_id", fHid); void* command = buildWriteScan(mode, &size); if (command == NULL) { return B_NO_MEMORY; } request.AddData("raw command", B_ANY_TYPE, command, size); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE)); if (fMessenger->SendMessage(&request, &reply) == B_OK) { if (reply.FindInt8("status", &bt_status ) == B_OK ) { return bt_status; } } return B_ERROR; } struct authentication_t { uint8 param; }; status_t LocalDevice::SetAuthentication(bool authentication) { return SingleParameterCommandRequest (OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, authentication, NULL, fHid, fMessenger); } bdaddr_t LocalDevice::GetBluetoothAddress() { if (fMessenger == NULL) return bdaddrUtils::LocalAddress(); size_t size; void* command = buildReadBdAddr(&size); if (command == NULL) return bdaddrUtils::LocalAddress(); const bdaddr_t* bdaddr; BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; ssize_t ssize; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, command, size); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR)); if (fMessenger->SendMessage(&request, &reply) == B_OK && reply.FindData("bdaddr", B_ANY_TYPE, 0, (const void**)&bdaddr, &ssize) == B_OK) return *bdaddr; return bdaddrUtils::LocalAddress(); } hci_id LocalDevice::ID(void) const { return fHid; } BString LocalDevice::GetFriendlyName() { if (fMessenger == NULL) return BString("Unknown|Messenger"); size_t size; void* command = buildReadLocalName(&size); if (command == NULL) return BString("Unknown|NoMemory"); BString friendlyname; BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, command, size); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME)); if (fMessenger->SendMessage(&request, &reply) == B_OK && reply.FindString("friendlyname", &friendlyname) == B_OK) return friendlyname; return BString("Unknown|ServerFailed"); } status_t LocalDevice::SetFriendlyName(BString& name) { int8 btStatus = BT_ERROR; if (fMessenger == NULL) return btStatus; BluetoothCommand writeName(OGF_CONTROL_BASEBAND, OCF_WRITE_LOCAL_NAME); strcpy(writeName->local_name, name.String()); BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, writeName.Data(), writeName.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_LOCAL_NAME)); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &btStatus); return btStatus; } DeviceClass LocalDevice::GetDeviceClass() { // if (fDeviceClass.IsUnknownDeviceClass()) { if (fMessenger == NULL) return fDeviceClass; size_t size; void* command = buildReadClassOfDevice(&size); if (command == NULL) return fDeviceClass; BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; const uint8* bufferRecord; ssize_t ssize; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, command, size); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_CLASS_OF_DEV)); if (fMessenger->SendMessage(&request, &reply) == B_OK && reply.FindData("devclass", B_ANY_TYPE, 0, (const void**)&bufferRecord, &ssize) == B_OK) { uint8 record[3] = { bufferRecord[0], bufferRecord[1], bufferRecord[2] }; fDeviceClass.SetRecord(record); } // } return fDeviceClass; } status_t LocalDevice::SetDeviceClass(DeviceClass deviceClass) { int8 bt_status = BT_ERROR; if (fMessenger == NULL) return bt_status; BluetoothCommand setDeviceClass(OGF_CONTROL_BASEBAND, OCF_WRITE_CLASS_OF_DEV); setDeviceClass->dev_class[0] = deviceClass.Record() & 0xFF; setDeviceClass->dev_class[1] = (deviceClass.Record() & 0xFF00) >> 8; setDeviceClass->dev_class[2] = (deviceClass.Record() & 0xFF0000) >> 16; BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, setDeviceClass.Data(), setDeviceClass.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_CLASS_OF_DEV)); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &bt_status); return bt_status; } status_t LocalDevice::_ReadLocalVersion() { int8 bt_status = BT_ERROR; BluetoothCommand<> localVersion(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_VERSION); BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, localVersion.Data(), localVersion.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_VERSION)); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &bt_status); return bt_status; } status_t LocalDevice::_ReadBufferSize() { int8 bt_status = BT_ERROR; BluetoothCommand<> BufferSize(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE); BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, BufferSize.Data(), BufferSize.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE)); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &bt_status); return bt_status; } status_t LocalDevice::_ReadLocalFeatures() { int8 bt_status = BT_ERROR; BluetoothCommand<> LocalFeatures(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_FEATURES); BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, LocalFeatures.Data(), LocalFeatures.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_FEATURES)); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &bt_status); return bt_status; } status_t LocalDevice::_ReadLinkKeys() { int8 bt_status = BT_ERROR; BluetoothCommand<> LocalFeatures(OGF_CONTROL_BASEBAND, OCF_READ_STORED_LINK_KEY); BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, LocalFeatures.Data(), LocalFeatures.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_STORED_LINK_KEY)); request.AddInt16("eventExpected", HCI_EVENT_RETURN_LINK_KEYS); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &bt_status); return bt_status; } struct pageTimeout_t { uint16 param; }; status_t LocalDevice::_ReadTimeouts() { // Read PageTimeout NonParameterCommandRequest(OGF_CONTROL_BASEBAND, OCF_READ_PG_TIMEOUT, NULL, fHid, fMessenger); // Write PageTimeout SingleParameterCommandRequest (OGF_CONTROL_BASEBAND, OCF_WRITE_PG_TIMEOUT, 0x8000, NULL, fHid, fMessenger); // Write PageTimeout return SingleParameterCommandRequest (OGF_CONTROL_BASEBAND, OCF_WRITE_CA_TIMEOUT, 0x7d00, NULL, fHid, fMessenger); } status_t LocalDevice::Reset() { int8 bt_status = BT_ERROR; BluetoothCommand<> Reset(OGF_CONTROL_BASEBAND, OCF_RESET); BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, Reset.Data(), Reset.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_RESET)); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &bt_status); return bt_status; } /* ServiceRecord LocalDevice::getRecord(Connection notifier) { } void LocalDevice::updateRecord(ServiceRecord srvRecord) { } */ LocalDevice::LocalDevice(hci_id hid) : BluetoothDevice(), fHid(hid) { fMessenger = _RetrieveBluetoothMessenger(); _ReadBufferSize(); _ReadLocalFeatures(); _ReadLocalVersion(); _ReadTimeouts(); _ReadLinkKeys(); // Uncomment this if you want your device to have a nicer default name // BString name("HaikuBluetooth"); // SetFriendlyName(name); uint32 value; // HARDCODE -> move this to addons if (GetProperty("manufacturer", &value) == B_OK && value == 15) { // Uncomment this out if your Broadcom dongle is not working properly // Reset(); // Perform a reset to Broadcom buggyland // Uncomment this out if your Broadcom dongle has a null bdaddr //#define BT_WRITE_BDADDR_FOR_BCM2035 #ifdef BT_WRITE_BDADDR_FOR_BCM2035 #warning Writting broadcom bdaddr @ init. // try write bdaddr to a bcm2035 -> will be moved to an addon int8 bt_status = BT_ERROR; BluetoothCommand writeAddress(OGF_VENDOR_CMD, OCF_WRITE_BCM2035_BDADDR); BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); BMessage reply; writeAddress->bdaddr.b[0] = 0x3C; writeAddress->bdaddr.b[1] = 0x19; writeAddress->bdaddr.b[2] = 0x30; writeAddress->bdaddr.b[3] = 0xC9; writeAddress->bdaddr.b[4] = 0x03; writeAddress->bdaddr.b[5] = 0x00; request.AddInt32("hci_id", fHid); request.AddData("raw command", B_ANY_TYPE, writeAddress.Data(), writeAddress.Size()); request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_VENDOR_CMD, OCF_WRITE_BCM2035_BDADDR)); if (fMessenger->SendMessage(&request, &reply) == B_OK) reply.FindInt8("status", &bt_status); #endif } } LocalDevice::~LocalDevice() { delete fMessenger; } } /* end namespace Bluetooth */