1 /*
2  *  Copyright (C) 2014-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "Peripheral.h"
12 #include "input/joysticks/JoystickTypes.h"
13 #include "input/joysticks/interfaces/IDriverReceiver.h"
14 #include "threads/CriticalSection.h"
15 
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 #define JOYSTICK_PORT_UNKNOWN (-1)
21 
22 namespace KODI
23 {
24 namespace JOYSTICK
25 {
26 class CDeadzoneFilter;
27 class CKeymapHandling;
28 class CRumbleGenerator;
29 class IButtonMap;
30 class IDriverHandler;
31 class IInputHandler;
32 } // namespace JOYSTICK
33 } // namespace KODI
34 
35 namespace PERIPHERALS
36 {
37 class CPeripherals;
38 
39 class CPeripheralJoystick : public CPeripheral, //! @todo extend CPeripheralHID
40                             public KODI::JOYSTICK::IDriverReceiver
41 {
42 public:
43   CPeripheralJoystick(CPeripherals& manager,
44                       const PeripheralScanResult& scanResult,
45                       CPeripheralBus* bus);
46 
47   ~CPeripheralJoystick(void) override;
48 
49   // implementation of CPeripheral
50   bool InitialiseFeature(const PeripheralFeature feature) override;
51   void OnUserNotification() override;
52   bool TestFeature(PeripheralFeature feature) override;
53   void RegisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler,
54                                      bool bPromiscuous) override;
55   void UnregisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler) override;
GetDriverReceiver()56   KODI::JOYSTICK::IDriverReceiver* GetDriverReceiver() override { return this; }
57   IKeymap* GetKeymap(const std::string& controllerId) override;
LastActive()58   CDateTime LastActive() override { return m_lastActive; }
59 
60   bool OnButtonMotion(unsigned int buttonIndex, bool bPressed);
61   bool OnHatMotion(unsigned int hatIndex, KODI::JOYSTICK::HAT_STATE state);
62   bool OnAxisMotion(unsigned int axisIndex, float position);
63   void ProcessAxisMotions(void);
64 
65   // implementation of IDriverReceiver
66   bool SetMotorState(unsigned int motorIndex, float magnitude) override;
67 
68   /*!
69    * \brief Get the name of the driver or API providing this joystick
70    */
Provider(void)71   const std::string& Provider(void) const { return m_strProvider; }
72 
73   /*!
74    * \brief Get the specific port number requested by this joystick
75    *
76    * This could indicate that the joystick is connected to a hardware port
77    * with a number label; some controllers, such as the Xbox 360 controller,
78    * also have LEDs that indicate the controller is on a specific port.
79    *
80    * \return The 0-indexed port number, or JOYSTICK_PORT_UNKNOWN if no port is requested
81    */
RequestedPort(void)82   int RequestedPort(void) const { return m_requestedPort; }
83 
84   /*!
85    * \brief Get the number of elements reported by the driver
86    */
ButtonCount(void)87   unsigned int ButtonCount(void) const { return m_buttonCount; }
HatCount(void)88   unsigned int HatCount(void) const { return m_hatCount; }
AxisCount(void)89   unsigned int AxisCount(void) const { return m_axisCount; }
MotorCount(void)90   unsigned int MotorCount(void) const { return m_motorCount; }
SupportsPowerOff(void)91   bool SupportsPowerOff(void) const { return m_supportsPowerOff; }
92 
93   /*!
94    * \brief Set joystick properties
95    */
SetProvider(const std::string & provider)96   void SetProvider(const std::string& provider) { m_strProvider = provider; }
SetRequestedPort(int port)97   void SetRequestedPort(int port) { m_requestedPort = port; }
SetButtonCount(unsigned int buttonCount)98   void SetButtonCount(unsigned int buttonCount) { m_buttonCount = buttonCount; }
SetHatCount(unsigned int hatCount)99   void SetHatCount(unsigned int hatCount) { m_hatCount = hatCount; }
SetAxisCount(unsigned int axisCount)100   void SetAxisCount(unsigned int axisCount) { m_axisCount = axisCount; }
101   void SetMotorCount(unsigned int motorCount); // specialized to update m_features
102   void SetSupportsPowerOff(bool bSupportsPowerOff); // specialized to update m_features
103 
104 protected:
105   void InitializeDeadzoneFiltering();
106 
107   void PowerOff();
108 
109   struct DriverHandler
110   {
111     KODI::JOYSTICK::IDriverHandler* handler;
112     bool bPromiscuous;
113   };
114 
115   // State parameters
116   std::string m_strProvider;
117   int m_requestedPort;
118   unsigned int m_buttonCount;
119   unsigned int m_hatCount;
120   unsigned int m_axisCount;
121   unsigned int m_motorCount;
122   bool m_supportsPowerOff;
123   CDateTime m_lastActive;
124 
125   // Input clients
126   std::unique_ptr<KODI::JOYSTICK::CKeymapHandling> m_appInput;
127   std::unique_ptr<KODI::JOYSTICK::CRumbleGenerator> m_rumbleGenerator;
128   std::unique_ptr<KODI::JOYSTICK::IInputHandler> m_joystickMonitor;
129   std::unique_ptr<KODI::JOYSTICK::IButtonMap> m_buttonMap;
130   std::unique_ptr<KODI::JOYSTICK::CDeadzoneFilter> m_deadzoneFilter;
131   std::vector<DriverHandler> m_driverHandlers;
132 
133   // Synchronization parameters
134   CCriticalSection m_handlerMutex;
135 };
136 } // namespace PERIPHERALS
137