23 #include "freertos/FreeRTOS.h" 33 #define PS2_CMD_SETLEDS 0xED 34 #define PS2_CMD_ECHO 0xEE 35 #define PS2_CMD_GETSET_CURRENT_SCANCODE_SET 0xF0 // keyboard specific 36 #define PS2_CMD_SET_REMOTE_MODE 0xF0 // mouse specific 37 #define PS2_CMD_IDENTIFY 0xF2 38 #define PS2_CMD_SET_TYPEMATIC_RATE_AND_DELAY 0xF3 // keyboard specific 39 #define PS2_CMD_SET_SAMPLE_RATE 0xF3 // mouse specific 40 #define PS2_CMD_ENABLE_SCANNING 0xF4 41 #define PS2_CMD_DISABLE_SCANNING 0xF5 42 #define PS2_CMD_SET_DEFAULT_PARAMS 0xF6 43 #define PS2_CMD_RESEND_LAST_BYTE 0xFE 44 #define PS2_CMD_RESET 0xFF 45 #define PS2_CMD_SET_STREAM_MODE 0xEA // mouse specific 46 #define PS2_CMD_STATUS_REQUEST 0xE9 // mouse specific 47 #define PS2_CMD_SET_RESOLUTION 0xE8 // mouse specific 48 #define PS2_CMD_SET_SCALING 0xE6 // mouse specific 50 #define PS2_REPLY_ERROR1 0x00 51 #define PS2_REPLY_ERROR2 0xFF 52 #define PS2_REPLY_SELFTEST_OK 0xAA 53 #define PS2_REPLY_ECHO 0xEE 54 #define PS2_REPLY_ACK 0xFA 55 #define PS2_REPLY_SELFTEST_FAILED1 0xFC 56 #define PS2_REPLY_SELFTEST_FAILED2 0xFD 57 #define PS2_REPLY_RESEND 0xFE 59 #define PS2_DEFAULT_CMD_RETRY_COUNT 3 60 #define PS2_DEFAULT_CMD_TIMEOUT 400 61 #define PS2_DEFAULT_CMD_SUBTIMEOUT (PS2_DEFAULT_CMD_TIMEOUT / 2) 63 #define PS2_QUICK_CMD_RETRY_COUNT 1 64 #define PS2_QUICK_CMD_TIMEOUT 50 65 #define PS2_QUICK_CMD_SUBTIMEOUT (PS2_QUICK_CMD_TIMEOUT / 2) 68 PS2Device::PS2Device()
70 m_retryCount = PS2_DEFAULT_CMD_RETRY_COUNT;
71 m_cmdTimeOut = PS2_DEFAULT_CMD_TIMEOUT;
72 m_cmdSubTimeOut = PS2_DEFAULT_CMD_SUBTIMEOUT;
73 m_deviceLock = xSemaphoreCreateRecursiveMutex();
77 PS2Device::~PS2Device()
79 vSemaphoreDelete(m_deviceLock);
83 void PS2Device::quickCheckHardware()
85 m_retryCount = PS2_QUICK_CMD_RETRY_COUNT;
86 m_cmdTimeOut = PS2_QUICK_CMD_TIMEOUT;
87 m_cmdSubTimeOut = PS2_QUICK_CMD_SUBTIMEOUT;
93 return xSemaphoreTakeRecursive(m_deviceLock, msToTicks(timeOutMS));
99 xSemaphoreGiveRecursive(m_deviceLock);
103 void PS2Device::begin(
int PS2Port)
109 int PS2Device::dataAvailable()
115 bool PS2Device::parityError()
121 int PS2Device::getData(
int timeOutMS)
125 while (!timeout.expired(timeOutMS)) {
129 if (ret > -1 || parityError())
134 vTaskDelay(10 / portTICK_PERIOD_MS);
140 bool PS2Device::sendCommand(uint8_t cmd, uint8_t expectedReply)
142 for (
int i = 0; i < m_retryCount; ++i) {
144 if (getData(m_cmdTimeOut) != expectedReply)
152 void PS2Device::requestToResendLastByte()
158 bool PS2Device::send_cmdLEDs(
bool numLock,
bool capsLock,
bool scrollLock)
160 PS2DeviceLock deviceLock(
this);
161 if (!sendCommand(PS2_CMD_SETLEDS, PS2_REPLY_ACK))
163 bool ret = sendCommand((scrollLock << 0) | (numLock << 1) | (capsLock << 2), PS2_REPLY_ACK);
168 bool PS2Device::send_cmdEcho()
170 PS2DeviceLock deviceLock(
this);
171 return sendCommand(PS2_CMD_ECHO, PS2_REPLY_ECHO);
175 bool PS2Device::send_cmdGetScancodeSet(uint8_t * result)
177 PS2DeviceLock deviceLock(
this);
178 if (!sendCommand(PS2_CMD_GETSET_CURRENT_SCANCODE_SET, PS2_REPLY_ACK))
180 if (!sendCommand(0, PS2_REPLY_ACK))
182 *result = getData(m_cmdTimeOut);
183 return (*result >= 1 || *result <= 3);
187 bool PS2Device::send_cmdSetScancodeSet(uint8_t scancodeSet)
189 PS2DeviceLock deviceLock(
this);
190 if (!sendCommand(PS2_CMD_GETSET_CURRENT_SCANCODE_SET, PS2_REPLY_ACK))
192 return sendCommand(scancodeSet, PS2_REPLY_ACK);
199 PS2DeviceLock deviceLock(
this);
201 if (!send_cmdDisableScanning())
203 if (!sendCommand(PS2_CMD_IDENTIFY, PS2_REPLY_ACK))
205 int b1 = getData(m_cmdTimeOut);
206 int b2 = getData(m_cmdTimeOut);
207 if (b1 == -1 && b2 == -1)
209 else if (b1 == 0x00 && b2 == -1)
211 else if (b1 == 0x03 && b2 == -1)
213 else if (b1 == 0x04 && b2 == -1)
215 else if ((b1 == 0xAB && b2 == 0x41) || (b1 == 0xAB && b2 == 0xC1))
217 else if (b1 == 0xAB && b2 == 0x83)
219 return send_cmdEnableScanning();
223 bool PS2Device::send_cmdDisableScanning()
225 PS2DeviceLock deviceLock(
this);
226 return sendCommand(PS2_CMD_DISABLE_SCANNING, PS2_REPLY_ACK);
230 bool PS2Device::send_cmdEnableScanning()
232 PS2DeviceLock deviceLock(
this);
233 return sendCommand(PS2_CMD_ENABLE_SCANNING, PS2_REPLY_ACK);
237 const int16_t REPEATRATES[32] = { 33, 37, 41, 45, 50, 54, 58, 62, 66, 75, 83, 91,
238 100, 108, 125, 125, 133, 149, 166, 181, 200, 217, 232, 250,
239 270, 303, 333, 370, 400, 434, 476, 500};
244 bool PS2Device::send_cmdTypematicRateAndDelay(
int repeatRateMS,
int repeatDelayMS)
246 PS2DeviceLock deviceLock(
this);
247 if (!sendCommand(PS2_CMD_SET_TYPEMATIC_RATE_AND_DELAY, PS2_REPLY_ACK))
249 uint8_t byteToSend = 0b01011;
250 for (
int i = 0; i < 32; ++i)
251 if (REPEATRATES[i] >= repeatRateMS) {
255 byteToSend |= (repeatDelayMS / 250 - 1) << 5;
256 return sendCommand(byteToSend, PS2_REPLY_ACK);
261 bool PS2Device::send_cmdSetSampleRate(
int sampleRate)
263 PS2DeviceLock deviceLock(
this);
264 if (!sendCommand(PS2_CMD_SET_SAMPLE_RATE, PS2_REPLY_ACK))
266 return sendCommand(sampleRate, PS2_REPLY_ACK);
275 bool PS2Device::send_cmdSetResolution(
int resolution)
277 PS2DeviceLock deviceLock(
this);
278 if (!sendCommand(PS2_CMD_SET_RESOLUTION, PS2_REPLY_ACK))
280 return sendCommand(resolution, PS2_REPLY_ACK);
287 bool PS2Device::send_cmdSetScaling(
int scaling)
289 PS2DeviceLock deviceLock(
this);
290 if (!sendCommand(PS2_CMD_SET_SCALING, PS2_REPLY_ACK))
292 return sendCommand(scaling, PS2_REPLY_ACK);
296 bool PS2Device::send_cmdSetDefaultParams()
298 PS2DeviceLock deviceLock(
this);
299 return sendCommand(PS2_CMD_SET_DEFAULT_PARAMS, PS2_REPLY_ACK);
303 bool PS2Device::send_cmdReset()
305 PS2DeviceLock deviceLock(
this);
306 if (!sendCommand(PS2_CMD_RESET, PS2_REPLY_ACK))
308 return getData(500) == PS2_REPLY_SELFTEST_OK;
bool lock(int timeOutMS)
Gets exclusive access to the device.
int dataAvailable(int PS2Port)
Gets the number of scancodes available in the controller buffer.
PS2DeviceType
Represents the type of device attached to PS/2 port.
void sendData(uint8_t data, int PS2Port)
Sends a command to the device.
This file contains some utility classes and functions.
static PS2Controller * instance()
Returns the singleton instance of PS2Controller class.
int getData(int PS2Port)
Gets a scancode from the queue.
void unlock()
Releases device from exclusive access.
This file contains fabgl::PS2Device definition.