summaryrefslogtreecommitdiffstats
path: root/hal/gonk/GonkSwitch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'hal/gonk/GonkSwitch.cpp')
-rw-r--r--hal/gonk/GonkSwitch.cpp479
1 files changed, 0 insertions, 479 deletions
diff --git a/hal/gonk/GonkSwitch.cpp b/hal/gonk/GonkSwitch.cpp
deleted file mode 100644
index b2c31c973..000000000
--- a/hal/gonk/GonkSwitch.cpp
+++ /dev/null
@@ -1,479 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* Copyright 2012 Mozilla Foundation and Mozilla contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <fcntl.h>
-#include <sysutils/NetlinkEvent.h>
-
-#include "base/message_loop.h"
-#include "base/task.h"
-
-#include "Hal.h"
-#include "HalLog.h"
-#include "mozilla/FileUtils.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/Monitor.h"
-#include "nsPrintfCString.h"
-#include "nsXULAppAPI.h"
-#include "nsThreadUtils.h"
-#include "UeventPoller.h"
-
-using namespace mozilla::hal;
-
-#define SWITCH_HEADSET_DEVPATH "/devices/virtual/switch/h2w"
-#define SWITCH_USB_DEVPATH_GB "/devices/virtual/switch/usb_configuration"
-#define SWITCH_USB_DEVPATH_ICS "/devices/virtual/android_usb/android0"
-
-namespace mozilla {
-namespace hal_impl {
-/**
- * The uevent for a usb on GB insertion looks like:
- *
- * change@/devices/virtual/switch/usb_configuration
- * ACTION=change
- * DEVPATH=/devices/virtual/switch/usb_configuration
- * SUBSYSTEM=switch
- * SWITCH_NAME=usb_configuration
- * SWITCH_STATE=0
- * SEQNUM=5038
- */
-class SwitchHandler
-{
-public:
- NS_INLINE_DECL_REFCOUNTING(SwitchHandler)
-
- SwitchHandler(const char* aDevPath, SwitchDevice aDevice)
- : mDevPath(aDevPath),
- mState(SWITCH_STATE_UNKNOWN),
- mDevice(aDevice)
- {
- GetInitialState();
- }
-
- bool CheckEvent(NetlinkEvent* aEvent)
- {
- if (strcmp(GetSubsystem(), aEvent->getSubsystem()) ||
- strcmp(mDevPath, aEvent->findParam("DEVPATH"))) {
- return false;
- }
-
- mState = ConvertState(GetStateString(aEvent));
- return mState != SWITCH_STATE_UNKNOWN;
- }
-
- SwitchState GetState()
- {
- return mState;
- }
-
- SwitchDevice GetType()
- {
- return mDevice;
- }
-protected:
- virtual ~SwitchHandler()
- {
- }
-
- virtual const char* GetSubsystem()
- {
- return "switch";
- }
-
- virtual const char* GetStateString(NetlinkEvent* aEvent)
- {
- return aEvent->findParam("SWITCH_STATE");
- }
-
- void GetInitialState()
- {
- nsPrintfCString statePath("/sys%s/state", mDevPath);
- int fd = open(statePath.get(), O_RDONLY);
- if (fd <= 0) {
- return;
- }
-
- ScopedClose autoClose(fd);
- char state[16];
- ssize_t bytesRead = read(fd, state, sizeof(state));
- if (bytesRead < 0) {
- HAL_ERR("Read data from %s fails", statePath.get());
- return;
- }
-
- if (state[bytesRead - 1] == '\n') {
- bytesRead--;
- }
-
- state[bytesRead] = '\0';
- mState = ConvertState(state);
- }
-
- virtual SwitchState ConvertState(const char* aState)
- {
- MOZ_ASSERT(aState);
- return aState[0] == '0' ? SWITCH_STATE_OFF : SWITCH_STATE_ON;
- }
-
- const char* mDevPath;
- SwitchState mState;
- SwitchDevice mDevice;
-};
-
-/**
- * The uevent delivered for the USB configuration under ICS looks like,
- *
- * change@/devices/virtual/android_usb/android0
- * ACTION=change
- * DEVPATH=/devices/virtual/android_usb/android0
- * SUBSYSTEM=android_usb
- * USB_STATE=CONFIGURED
- * SEQNUM=1802
- */
-class SwitchHandlerUsbIcs: public SwitchHandler
-{
-public:
- SwitchHandlerUsbIcs(const char* aDevPath) : SwitchHandler(aDevPath, SWITCH_USB)
- {
- SwitchHandler::GetInitialState();
- }
-
- virtual ~SwitchHandlerUsbIcs() { }
-
-protected:
- virtual const char* GetSubsystem()
- {
- return "android_usb";
- }
-
- virtual const char* GetStateString(NetlinkEvent* aEvent)
- {
- return aEvent->findParam("USB_STATE");
- }
-
- SwitchState ConvertState(const char* aState)
- {
- MOZ_ASSERT(aState);
- return strcmp(aState, "CONFIGURED") == 0 ? SWITCH_STATE_ON : SWITCH_STATE_OFF;
- }
-};
-
-/**
- * The uevent delivered for the headset under ICS looks like,
- *
- * change@/devices/virtual/switch/h2w
- * ACTION=change
- * DEVPATH=/devices/virtual/switch/h2w
- * SUBSYSTEM=switch
- * SWITCH_NAME=h2w
- * SWITCH_STATE=2 // Headset with no mic
- * SEQNUM=2581
- * On Otoro, SWITCH_NAME could be Headset/No Device when plug/unplug.
- * change@/devices/virtual/switch/h2w
- * ACTION=change
- * DEVPATH=/devices/virtual/switch/h2w
- * SUBSYSTEM=switch
- * SWITCH_NAME=Headset
- * SWITCH_STATE=1 // Headset with mic
- * SEQNUM=1602
- */
-class SwitchHandlerHeadphone: public SwitchHandler
-{
-public:
- SwitchHandlerHeadphone(const char* aDevPath) :
- SwitchHandler(aDevPath, SWITCH_HEADPHONES)
- {
- SwitchHandler::GetInitialState();
- }
-
- virtual ~SwitchHandlerHeadphone() { }
-
-protected:
- SwitchState ConvertState(const char* aState)
- {
- MOZ_ASSERT(aState);
-
- return aState[0] == '0' ? SWITCH_STATE_OFF :
- (aState[0] == '1' ? SWITCH_STATE_HEADSET : SWITCH_STATE_HEADPHONE);
- }
-};
-
-
-typedef nsTArray<RefPtr<SwitchHandler> > SwitchHandlerArray;
-
-class SwitchEventRunnable : public Runnable
-{
-public:
- SwitchEventRunnable(SwitchEvent& aEvent) : mEvent(aEvent)
- {
- }
-
- NS_IMETHOD Run() override
- {
- NotifySwitchChange(mEvent);
- return NS_OK;
- }
-private:
- SwitchEvent mEvent;
-};
-
-class SwitchEventObserver final : public IUeventObserver
-{
- ~SwitchEventObserver()
- {
- mHandler.Clear();
- }
-
-public:
- NS_INLINE_DECL_REFCOUNTING(SwitchEventObserver)
- SwitchEventObserver()
- : mEnableCount(0),
- mHeadphonesFromInputDev(false)
- {
- Init();
- }
-
- int GetEnableCount()
- {
- return mEnableCount;
- }
-
- void EnableSwitch(SwitchDevice aDevice)
- {
- mEventInfo[aDevice].mEnabled = true;
- mEnableCount++;
- }
-
- void DisableSwitch(SwitchDevice aDevice)
- {
- mEventInfo[aDevice].mEnabled = false;
- mEnableCount--;
- }
-
- void Notify(const NetlinkEvent& aEvent)
- {
- SwitchState currState;
-
- SwitchDevice device = GetEventInfo(aEvent, currState);
- if (device == SWITCH_DEVICE_UNKNOWN) {
- return;
- }
-
- EventInfo& info = mEventInfo[device];
- if (currState == info.mEvent.status()) {
- return;
- }
-
- info.mEvent.status() = currState;
-
- if (info.mEnabled) {
- NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent));
- }
- }
-
- void Notify(SwitchDevice aDevice, SwitchState aState)
- {
- EventInfo& info = mEventInfo[aDevice];
- if (aState == info.mEvent.status()) {
- return;
- }
-
- info.mEvent.status() = aState;
-
- if (info.mEnabled) {
- NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent));
- }
- }
-
- SwitchState GetCurrentInformation(SwitchDevice aDevice)
- {
- return mEventInfo[aDevice].mEvent.status();
- }
-
- void NotifyAnEvent(SwitchDevice aDevice)
- {
- EventInfo& info = mEventInfo[aDevice];
- if (info.mEvent.status() != SWITCH_STATE_UNKNOWN) {
- NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent));
- }
- }
-
- bool GetHeadphonesFromInputDev()
- {
- return mHeadphonesFromInputDev;
- }
-
-private:
- class EventInfo
- {
- public:
- EventInfo() : mEnabled(false)
- {
- mEvent.status() = SWITCH_STATE_UNKNOWN;
- mEvent.device() = SWITCH_DEVICE_UNKNOWN;
- }
- SwitchEvent mEvent;
- bool mEnabled;
- };
-
- EventInfo mEventInfo[NUM_SWITCH_DEVICE];
- size_t mEnableCount;
- SwitchHandlerArray mHandler;
- bool mHeadphonesFromInputDev;
-
- // This function might also get called on the main thread
- // (from IsHeadphoneEventFromInputDev)
- void Init()
- {
- RefPtr<SwitchHandlerHeadphone> switchHeadPhone =
- new SwitchHandlerHeadphone(SWITCH_HEADSET_DEVPATH);
-
- // If the initial state is unknown, it means the headphone event is from input dev
- mHeadphonesFromInputDev = switchHeadPhone->GetState() == SWITCH_STATE_UNKNOWN ? true : false;
-
- if (!mHeadphonesFromInputDev) {
- mHandler.AppendElement(switchHeadPhone);
- } else {
- // If headphone status will be notified from input dev then initialize
- // status to "off" and wait for event notification.
- mEventInfo[SWITCH_HEADPHONES].mEvent.device() = SWITCH_HEADPHONES;
- mEventInfo[SWITCH_HEADPHONES].mEvent.status() = SWITCH_STATE_OFF;
- }
- mHandler.AppendElement(new SwitchHandler(SWITCH_USB_DEVPATH_GB, SWITCH_USB));
- mHandler.AppendElement(new SwitchHandlerUsbIcs(SWITCH_USB_DEVPATH_ICS));
-
- SwitchHandlerArray::index_type handlerIndex;
- SwitchHandlerArray::size_type numHandlers = mHandler.Length();
-
- for (handlerIndex = 0; handlerIndex < numHandlers; handlerIndex++) {
- SwitchState state = mHandler[handlerIndex]->GetState();
- if (state == SWITCH_STATE_UNKNOWN) {
- continue;
- }
-
- SwitchDevice device = mHandler[handlerIndex]->GetType();
- mEventInfo[device].mEvent.device() = device;
- mEventInfo[device].mEvent.status() = state;
- }
- }
-
- SwitchDevice GetEventInfo(const NetlinkEvent& aEvent, SwitchState& aState)
- {
- //working around the android code not being const-correct
- NetlinkEvent *e = const_cast<NetlinkEvent*>(&aEvent);
-
- for (size_t i = 0; i < mHandler.Length(); i++) {
- if (mHandler[i]->CheckEvent(e)) {
- aState = mHandler[i]->GetState();
- return mHandler[i]->GetType();
- }
- }
- return SWITCH_DEVICE_UNKNOWN;
- }
-};
-
-static RefPtr<SwitchEventObserver> sSwitchObserver;
-
-static void
-InitializeResourceIfNeed()
-{
- if (!sSwitchObserver) {
- sSwitchObserver = new SwitchEventObserver();
- RegisterUeventListener(sSwitchObserver);
- }
-}
-
-static void
-ReleaseResourceIfNeed()
-{
- if (sSwitchObserver->GetEnableCount() == 0) {
- UnregisterUeventListener(sSwitchObserver);
- sSwitchObserver = nullptr;
- }
-}
-
-static void
-EnableSwitchNotificationsIOThread(SwitchDevice aDevice, Monitor *aMonitor)
-{
- InitializeResourceIfNeed();
- sSwitchObserver->EnableSwitch(aDevice);
- {
- MonitorAutoLock lock(*aMonitor);
- lock.Notify();
- }
-
- // Notify the latest state if IO thread has the information.
- if (sSwitchObserver->GetEnableCount() > 1) {
- sSwitchObserver->NotifyAnEvent(aDevice);
- }
-}
-
-void
-EnableSwitchNotifications(SwitchDevice aDevice)
-{
- Monitor monitor("EnableSwitch.monitor");
- {
- MonitorAutoLock lock(monitor);
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(EnableSwitchNotificationsIOThread, aDevice, &monitor));
- lock.Wait();
- }
-}
-
-static void
-DisableSwitchNotificationsIOThread(SwitchDevice aDevice)
-{
- MOZ_ASSERT(sSwitchObserver->GetEnableCount());
- sSwitchObserver->DisableSwitch(aDevice);
- ReleaseResourceIfNeed();
-}
-
-void
-DisableSwitchNotifications(SwitchDevice aDevice)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(DisableSwitchNotificationsIOThread, aDevice));
-}
-
-SwitchState
-GetCurrentSwitchState(SwitchDevice aDevice)
-{
- MOZ_ASSERT(sSwitchObserver && sSwitchObserver->GetEnableCount());
- return sSwitchObserver->GetCurrentInformation(aDevice);
-}
-
-static void
-NotifySwitchStateIOThread(SwitchDevice aDevice, SwitchState aState)
-{
- InitializeResourceIfNeed();
- sSwitchObserver->Notify(aDevice, aState);
-}
-
-void NotifySwitchStateFromInputDevice(SwitchDevice aDevice, SwitchState aState)
-{
- XRE_GetIOMessageLoop()->PostTask(
- NewRunnableFunction(NotifySwitchStateIOThread, aDevice, aState));
-}
-
-bool IsHeadphoneEventFromInputDev()
-{
- // Instead of calling InitializeResourceIfNeed, create new SwitchEventObserver
- // to prevent calling RegisterUeventListener in main thread.
- RefPtr<SwitchEventObserver> switchObserver = new SwitchEventObserver();
- return switchObserver->GetHeadphonesFromInputDev();
-}
-
-} // hal_impl
-} //mozilla