/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GonkSensorsPollInterface.h" #include "HalLog.h" #include <mozilla/UniquePtr.h> namespace mozilla { namespace hal { using namespace mozilla::ipc; // // GonkSensorsPollResultHandler // void GonkSensorsPollResultHandler::OnError(SensorsError aError) { HAL_ERR("Received error code %d", static_cast<int>(aError)); } void GonkSensorsPollResultHandler::EnableSensor() { } void GonkSensorsPollResultHandler::DisableSensor() { } void GonkSensorsPollResultHandler::SetPeriod() { } GonkSensorsPollResultHandler::~GonkSensorsPollResultHandler() { } // // GonkSensorsPollNotificationHandler // void GonkSensorsPollNotificationHandler::ErrorNotification(SensorsError aError) { HAL_ERR("Received error code %d", static_cast<int>(aError)); } void GonkSensorsPollNotificationHandler::SensorDetectedNotification( int32_t aId, SensorsType aType, float aRange, float aResolution, float aPower, int32_t aMinPeriod, int32_t aMaxPeriod, SensorsTriggerMode aTriggerMode, SensorsDeliveryMode aDeliveryMode) { } void GonkSensorsPollNotificationHandler::SensorLostNotification(int32_t aId) { } void GonkSensorsPollNotificationHandler::EventNotification(int32_t aId, const SensorsEvent& aEvent) { } GonkSensorsPollNotificationHandler::~GonkSensorsPollNotificationHandler() { } // // GonkSensorsPollModule // GonkSensorsPollModule::GonkSensorsPollModule() : mProtocolVersion(0) { } GonkSensorsPollModule::~GonkSensorsPollModule() { } nsresult GonkSensorsPollModule::SetProtocolVersion(unsigned long aProtocolVersion) { if ((aProtocolVersion < MIN_PROTOCOL_VERSION) || (aProtocolVersion > MAX_PROTOCOL_VERSION)) { HAL_ERR("Sensors Poll protocol version %lu not supported", aProtocolVersion); return NS_ERROR_ILLEGAL_VALUE; } mProtocolVersion = aProtocolVersion; return NS_OK; } void GonkSensorsPollModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes) { static void (GonkSensorsPollModule::* const HandleOp[])( const DaemonSocketPDUHeader&, DaemonSocketPDU&, DaemonSocketResultHandler*) = { [0] = &GonkSensorsPollModule::HandleRsp, [1] = &GonkSensorsPollModule::HandleNtf }; MOZ_ASSERT(!NS_IsMainThread()); // I/O thread // Negate twice to map bit to 0/1 unsigned long isNtf = !!(aHeader.mOpcode & 0x80); (this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes); } // Commands // nsresult GonkSensorsPollModule::EnableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); UniquePtr<DaemonSocketPDU> pdu = MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_ENABLE_SENSOR, 0); nsresult rv = PackPDU(aId, *pdu); if (NS_FAILED(rv)) { return rv; } rv = Send(pdu.get(), aRes); if (NS_FAILED(rv)) { return rv; } Unused << pdu.release(); return NS_OK; } nsresult GonkSensorsPollModule::DisableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); UniquePtr<DaemonSocketPDU> pdu = MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISABLE_SENSOR, 0); nsresult rv = PackPDU(aId, *pdu); if (NS_FAILED(rv)) { return rv; } rv = Send(pdu.get(), aRes); if (NS_FAILED(rv)) { return rv; } Unused << pdu.release(); return NS_OK; } nsresult GonkSensorsPollModule::SetPeriodCmd(int32_t aId, uint64_t aPeriod, GonkSensorsPollResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); UniquePtr<DaemonSocketPDU> pdu = MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_PERIOD, 0); nsresult rv = PackPDU(aId, *pdu); if (NS_FAILED(rv)) { return rv; } rv = PackPDU(aPeriod, *pdu); if (NS_FAILED(rv)) { return rv; } rv = Send(pdu.get(), aRes); if (NS_FAILED(rv)) { return rv; } Unused << pdu.release(); return NS_OK; } // Responses // void GonkSensorsPollModule::ErrorRsp( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes) { ErrorRunnable::Dispatch( aRes, &GonkSensorsPollResultHandler::OnError, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::EnableSensorRsp( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &GonkSensorsPollResultHandler::EnableSensor, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::DisableSensorRsp( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &GonkSensorsPollResultHandler::DisableSensor, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::SetPeriodRsp( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &GonkSensorsPollResultHandler::SetPeriod, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::HandleRsp( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes) { static void (GonkSensorsPollModule::* const sHandleRsp[])( const DaemonSocketPDUHeader&, DaemonSocketPDU&, GonkSensorsPollResultHandler*) = { [OPCODE_ERROR] = &GonkSensorsPollModule::ErrorRsp, [OPCODE_ENABLE_SENSOR] = &GonkSensorsPollModule::EnableSensorRsp, [OPCODE_DISABLE_SENSOR] = &GonkSensorsPollModule::DisableSensorRsp, [OPCODE_SET_PERIOD] = &GonkSensorsPollModule::SetPeriodRsp, }; MOZ_ASSERT(!NS_IsMainThread()); // I/O thread if (!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(sHandleRsp)) || !sHandleRsp[aHeader.mOpcode]) { HAL_ERR("Sensors poll response opcode %d unknown", aHeader.mOpcode); return; } RefPtr<GonkSensorsPollResultHandler> res = static_cast<GonkSensorsPollResultHandler*>(aRes); if (!res) { return; // Return early if no result handler has been set for response } (this->*(sHandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); } // Notifications // // Returns the current notification handler to a notification runnable class GonkSensorsPollModule::NotificationHandlerWrapper final { public: typedef GonkSensorsPollNotificationHandler ObjectType; static ObjectType* GetInstance() { MOZ_ASSERT(NS_IsMainThread()); return sNotificationHandler; } static GonkSensorsPollNotificationHandler* sNotificationHandler; }; GonkSensorsPollNotificationHandler* GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler; void GonkSensorsPollModule::ErrorNtf( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ErrorNotification::Dispatch( &GonkSensorsPollNotificationHandler::ErrorNotification, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::SensorDetectedNtf( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { SensorDetectedNotification::Dispatch( &GonkSensorsPollNotificationHandler::SensorDetectedNotification, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::SensorLostNtf( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { SensorLostNotification::Dispatch( &GonkSensorsPollNotificationHandler::SensorLostNotification, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::EventNtf( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { EventNotification::Dispatch( &GonkSensorsPollNotificationHandler::EventNotification, UnpackPDUInitOp(aPDU)); } void GonkSensorsPollModule::HandleNtf( const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes) { static void (GonkSensorsPollModule::* const sHandleNtf[])( const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { [0] = &GonkSensorsPollModule::ErrorNtf, [1] = &GonkSensorsPollModule::SensorDetectedNtf, [2] = &GonkSensorsPollModule::SensorLostNtf, [3] = &GonkSensorsPollModule::EventNtf }; MOZ_ASSERT(!NS_IsMainThread()); uint8_t index = aHeader.mOpcode - 0x80; if (!(index < MOZ_ARRAY_LENGTH(sHandleNtf)) || !sHandleNtf[index]) { HAL_ERR("Sensors poll notification opcode %d unknown", aHeader.mOpcode); return; } (this->*(sHandleNtf[index]))(aHeader, aPDU); } // // GonkSensorsPollInterface // GonkSensorsPollInterface::GonkSensorsPollInterface( GonkSensorsPollModule* aModule) : mModule(aModule) { } GonkSensorsPollInterface::~GonkSensorsPollInterface() { } void GonkSensorsPollInterface::SetNotificationHandler( GonkSensorsPollNotificationHandler* aNotificationHandler) { MOZ_ASSERT(NS_IsMainThread()); GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler = aNotificationHandler; } nsresult GonkSensorsPollInterface::SetProtocolVersion(unsigned long aProtocolVersion) { MOZ_ASSERT(mModule); return mModule->SetProtocolVersion(aProtocolVersion); } void GonkSensorsPollInterface::EnableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes) { MOZ_ASSERT(mModule); nsresult rv = mModule->EnableSensorCmd(aId, aRes); if (NS_FAILED(rv)) { DispatchError(aRes, rv); } } void GonkSensorsPollInterface::DisableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes) { MOZ_ASSERT(mModule); nsresult rv = mModule->DisableSensorCmd(aId, aRes); if (NS_FAILED(rv)) { DispatchError(aRes, rv); } } void GonkSensorsPollInterface::SetPeriod(int32_t aId, uint64_t aPeriod, GonkSensorsPollResultHandler* aRes) { MOZ_ASSERT(mModule); nsresult rv = mModule->SetPeriodCmd(aId, aPeriod, aRes); if (NS_FAILED(rv)) { DispatchError(aRes, rv); } } void GonkSensorsPollInterface::DispatchError( GonkSensorsPollResultHandler* aRes, SensorsError aError) { DaemonResultRunnable1<GonkSensorsPollResultHandler, void, SensorsError, SensorsError>::Dispatch( aRes, &GonkSensorsPollResultHandler::OnError, ConstantInitOp1<SensorsError>(aError)); } void GonkSensorsPollInterface::DispatchError( GonkSensorsPollResultHandler* aRes, nsresult aRv) { SensorsError error; if (NS_FAILED(Convert(aRv, error))) { error = SENSORS_ERROR_FAIL; } DispatchError(aRes, error); } } // namespace hal } // namespace mozilla