27 #include "freertos/FreeRTOS.h" 33 #pragma GCC optimize ("O2") 39 #define PS2_CMD_SETLEDS 0xED 40 #define PS2_CMD_ECHO 0xEE 41 #define PS2_CMD_GETSET_CURRENT_SCANCODE_SET 0xF0 // keyboard specific 42 #define PS2_CMD_SET_REMOTE_MODE 0xF0 // mouse specific 43 #define PS2_CMD_IDENTIFY 0xF2 44 #define PS2_CMD_SET_TYPEMATIC_RATE_AND_DELAY 0xF3 // keyboard specific 45 #define PS2_CMD_SET_SAMPLE_RATE 0xF3 // mouse specific 46 #define PS2_CMD_ENABLE_SCANNING 0xF4 47 #define PS2_CMD_DISABLE_SCANNING 0xF5 48 #define PS2_CMD_SET_DEFAULT_PARAMS 0xF6 49 #define PS2_CMD_RESEND_LAST_BYTE 0xFE 50 #define PS2_CMD_RESET 0xFF 51 #define PS2_CMD_SET_STREAM_MODE 0xEA // mouse specific 52 #define PS2_CMD_STATUS_REQUEST 0xE9 // mouse specific 53 #define PS2_CMD_SET_RESOLUTION 0xE8 // mouse specific 54 #define PS2_CMD_SET_SCALING 0xE6 // mouse specific 56 #define PS2_REPLY_ERROR1 0x00 57 #define PS2_REPLY_ERROR2 0xFF 58 #define PS2_REPLY_SELFTEST_OK 0xAA 59 #define PS2_REPLY_ECHO 0xEE 60 #define PS2_REPLY_ACK 0xFA 61 #define PS2_REPLY_SELFTEST_FAILED1 0xFC 62 #define PS2_REPLY_SELFTEST_FAILED2 0xFD 63 #define PS2_REPLY_RESEND 0xFE 65 #define PS2_DEFAULT_CMD_TIMEOUT 500 66 #define PS2_DEFAULT_CMD_SUBTIMEOUT (PS2_DEFAULT_CMD_TIMEOUT / 2) 68 #define PS2_QUICK_CMD_TIMEOUT 50 69 #define PS2_QUICK_CMD_SUBTIMEOUT (PS2_QUICK_CMD_TIMEOUT / 2) 72 PS2Device::PS2Device()
74 m_cmdTimeOut = PS2_DEFAULT_CMD_TIMEOUT;
75 m_cmdSubTimeOut = PS2_DEFAULT_CMD_SUBTIMEOUT;
79 PS2Device::~PS2Device()
84 void PS2Device::quickCheckHardware()
86 m_cmdTimeOut = PS2_QUICK_CMD_TIMEOUT;
87 m_cmdSubTimeOut = PS2_QUICK_CMD_SUBTIMEOUT;
103 void PS2Device::begin(
int PS2Port)
109 int PS2Device::dataAvailable()
115 bool PS2Device::parityError()
117 return PS2Controller::parityError(m_PS2Port);
121 bool PS2Device::syncError()
123 return PS2Controller::syncError(m_PS2Port);
127 bool PS2Device::CLKTimeOutError()
129 return PS2Controller::CLKTimeOutError(m_PS2Port);
145 int PS2Device::getData(
int timeOutMS)
147 constexpr
int INTER_GETDATA_TIMEOUT_MS = 100;
148 constexpr
int INTER_GETDATA_PAUSE_MS = 10;
150 int interTimeOut = timeOutMS > -1 ? imin(timeOutMS, INTER_GETDATA_TIMEOUT_MS) : INTER_GETDATA_TIMEOUT_MS;
158 if (ret > -1 || parityError() || syncError() || CLKTimeOutError() || timeout.expired(timeOutMS))
161 vTaskDelay(INTER_GETDATA_PAUSE_MS / portTICK_PERIOD_MS);
169 constexpr
int INTER_WAITREPLY_TIMEOUT_MS = 10;
171 PS2DeviceLock deviceLock(
this);
174 PS2PortAutoDisableRX autoDisableRX(!m_PS2Port);
181 }
while (!timeout.expired(m_cmdTimeOut));
192 void PS2Device::requestToResendLastByte()
198 bool PS2Device::send_cmdLEDs(
bool numLock,
bool capsLock,
bool scrollLock)
200 PS2DeviceLock deviceLock(
this);
201 return sendCommand(PS2_CMD_SETLEDS, PS2_REPLY_ACK) &&
sendCommand((scrollLock << 0) | (numLock << 1) | (capsLock << 2), PS2_REPLY_ACK);
205 bool PS2Device::send_cmdEcho()
211 bool PS2Device::send_cmdGetScancodeSet(uint8_t * result)
213 PS2DeviceLock deviceLock(
this);
214 if (!
sendCommand(PS2_CMD_GETSET_CURRENT_SCANCODE_SET, PS2_REPLY_ACK))
218 *result = getData(m_cmdTimeOut);
219 return (*result >= 1 || *result <= 3);
223 bool PS2Device::send_cmdSetScancodeSet(uint8_t scancodeSet)
225 PS2DeviceLock deviceLock(
this);
226 if (!
sendCommand(PS2_CMD_GETSET_CURRENT_SCANCODE_SET, PS2_REPLY_ACK))
235 PS2DeviceLock deviceLock(
this);
237 if (!send_cmdDisableScanning())
241 int b1 = getData(m_cmdTimeOut);
242 int b2 = getData(m_cmdTimeOut);
243 m_deviceID = (uint8_t)b1 | ((uint8_t)b2 << 8);
244 if (b1 == -1 && b2 == -1)
246 else if (b1 == 0x00 && b2 == -1)
248 else if (b1 == 0x03 && b2 == -1)
250 else if (b1 == 0x04 && b2 == -1)
252 else if ((b1 == 0xAB && b2 == 0x41) || (b1 == 0xAB && b2 == 0xC1))
254 else if (b1 == 0xAB && b2 == 0x83)
256 return send_cmdEnableScanning();
260 bool PS2Device::send_cmdDisableScanning()
262 return sendCommand(PS2_CMD_DISABLE_SCANNING, PS2_REPLY_ACK);
266 bool PS2Device::send_cmdEnableScanning()
268 return sendCommand(PS2_CMD_ENABLE_SCANNING, PS2_REPLY_ACK);
272 const int16_t REPEATRATES[32] = { 33, 37, 41, 45, 50, 54, 58, 62, 66, 75, 83, 91,
273 100, 108, 125, 125, 133, 149, 166, 181, 200, 217, 232, 250,
274 270, 303, 333, 370, 400, 434, 476, 500};
279 bool PS2Device::send_cmdTypematicRateAndDelay(
int repeatRateMS,
int repeatDelayMS)
281 PS2DeviceLock deviceLock(
this);
282 if (!
sendCommand(PS2_CMD_SET_TYPEMATIC_RATE_AND_DELAY, PS2_REPLY_ACK))
284 uint8_t byteToSend = 0b01011;
285 for (
int i = 0; i < 32; ++i)
286 if (REPEATRATES[i] >= repeatRateMS) {
290 byteToSend |= (repeatDelayMS / 250 - 1) << 5;
296 bool PS2Device::send_cmdSetSampleRate(
int sampleRate)
298 PS2DeviceLock deviceLock(
this);
299 if (!
sendCommand(PS2_CMD_SET_SAMPLE_RATE, PS2_REPLY_ACK))
310 bool PS2Device::send_cmdSetResolution(
int resolution)
312 PS2DeviceLock deviceLock(
this);
313 if (!
sendCommand(PS2_CMD_SET_RESOLUTION, PS2_REPLY_ACK))
322 bool PS2Device::send_cmdSetScaling(
int scaling)
324 PS2DeviceLock deviceLock(
this);
325 if (!
sendCommand(PS2_CMD_SET_SCALING, PS2_REPLY_ACK))
331 bool PS2Device::send_cmdSetDefaultParams()
333 return sendCommand(PS2_CMD_SET_DEFAULT_PARAMS, PS2_REPLY_ACK);
337 bool PS2Device::send_cmdReset()
339 PS2DeviceLock deviceLock(
this);
342 return getData(500) == PS2_REPLY_SELFTEST_OK;
void suspendPort()
Suspends PS/2 port driving the CLK line Low.
bool lock(int timeOutMS)
Gets exclusive access to the device.
bool sendCommand(uint8_t cmd, uint8_t expectedReply)
Sends a raw command to the PS/2 device and wait for reply.
static bool lock(int PS2Port, int timeOutMS)
Gets exclusive access to the specified PS/2 port.
static bool dataAvailable(int PS2Port)
Determines if one byte has been received from the specified port.
PS2DeviceType
Represents the type of device attached to PS/2 port.
static void sendData(uint8_t data, int PS2Port)
Sends a command to the device.
static int getData(int PS2Port, int timeOutMS)
Gets a scancode from the queue.
static void unlock(int PS2Port)
Releases port from exclusive access.
This file contains some utility classes and functions.
static void disableRX(int PS2Port)
Disables inputs from PS/2 port driving the CLK line Low.
void resumePort()
Resumes PS/2 port releasing CLK line.
static void enableRX(int PS2Port)
Enables inputs from PS/2 port releasing CLK line.
void unlock()
Releases device from exclusive access.
This file contains fabgl::PS2Device definition.