-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathkk_ps2.h
219 lines (161 loc) · 7.91 KB
/
kk_ps2.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/**
* kk_ps2.h: A PS/2 host library for AVR
*
* Copyright (c) 2020 Kimmo Kulovesi, https://arkku.dev/
* Provided with absolutely no warranty, use at your own risk only.
* Use and distribute freely, mark modified copies as such.
*/
#ifndef KK_PS2_H
#define KK_PS2_H
#include <stdint.h>
#include <stdbool.h>
// MARK: - Replies
/// The reply timeout for PS/2 commands, in milliseconds. Set to zero
/// to disable the timeout entirely. The default is 100 ms, which is
/// relatively generous compared to the 20 ms specified.
extern uint8_t ps2_reply_timeout_ms;
/// Successfully received and recognized previous byte.
#define PS2_REPLY_ACK ((uint8_t) 0xFAU)
/// Error in previous byte (e.g., invalid command/argument).
#define PS2_REPLY_ERROR ((uint8_t) 0xFCU)
/// Request to resend the previous byte.
#define PS2_REPLY_RESEND ((uint8_t) 0xFEU)
// The power-on/reset test has passed successfully.
#define PS2_REPLY_TEST_PASSED ((uint8_t) 0xAAU)
// MARK: - Commands
/// Reset the device.
#define PS2_COMMAND_RESET ((uint8_t) 0xFFU)
/// Request resend of the previous packet.
#define PS2_COMMAND_RESEND ((uint8_t) 0xFEU)
/// Request id (mouse replies with one byte, keyboard with two).
#define PS2_COMMAND_ID ((uint8_t) 0xF2U)
/// Enable reporting.
#define PS2_COMMAND_ENABLE ((uint8_t) 0xF4U)
/// Disable reporting.
#define PS2_COMMAND_DISABLE ((uint8_t) 0xF5U)
/// Set the keyboard mode / scan code set. The argument is a single byte
/// The argument is a scan code set number (1, 2 or 3), or 0 in which case the
/// mode is unchanged but the current mode is echoed back.
#define PS2_COMMAND_SET_SCAN_CODES ((uint8_t) 0xF0U)
/// Sets a mouse to "remote" mode, in which case the mouse no longer sends
/// updates, but rather the status must be requested by the host with the
/// command `PS2_COMMAND_STATUS`.
#define PS2_COMMAND_SET_REMOTE_MODE ((uint8_t) 0xF0U)
/// Sets a mouse to "stream" mode (the default), in which mode the mouse
/// sends status updates automatically.
#define PS2_COMMAND_STREAM_MODE ((uint8_t) 0xEAU)
/// Request status.
#define PS2_COMMAND_STATUS ((uint8_t) 0xE9U)
/// Set the reporting rate.
/// For a mouse, the argument is the number of updates per second from 10 to
/// 200. For a keyboard, takes two argument bytes, the first of which is
/// a repeat rate from 0x00 (fastest) to 0x1F (slowest), and the second is
/// the delay between repeats from 0x00 (shortest) to 0x03 (longest).
#define PS2_COMMAND_SET_RATE ((uint8_t) 0xF3U)
/// Set the keyboard's LEDs. The argument is a bit mask of LED states,
/// the least significant bits being:
///
/// - bit 0: scroll lock
/// - bit 1: num lock
/// - bit 2: caps lock
#define PS2_COMMAND_SET_LEDS ((uint8_t) 0xEDU)
/// Enable mouse scaling (acceleration).
#define PS2_COMMAND_DISABLE_SCALING ((uint8_t) 0xE6U)
/// Disable mouse scaling (acceleration).
#define PS2_COMMAND_ENABLE_SCALING ((uint8_t) 0xE7U)
/// Set the mouse resolution.
#define PS2_COMMAND_SET_RESOLUTION ((uint8_t) 0xE8U)
#define PS2_RESOLUTION_1_MM ((uint8_t) 0x00U)
#define PS2_RESOLUTION_2_MM ((uint8_t) 0x01U)
#define PS2_RESOLUTION_4_MM ((uint8_t) 0x02U)
#define PS2_RESOLUTION_8_MM ((uint8_t) 0x03U)
/// Set all keys to their normal make/break/typematic repeat in mode 3.
#define PS2_COMMAND_SET_ALL_KEYS_NORMAL ((uint8_t) 0xFAU)
/// Set all keys to make only (no break/repeat).
#define PS2_COMMAND_SET_ALL_KEYS_MAKE ((uint8_t) 0xF9U)
/// Set all keys to make/break (no repeat).
#define PS2_COMMAND_SET_ALL_KEYS_MAKE_BREAK ((uint8_t) 0xF8U)
/// Set all keys to make/repeat (no break).
#define PS2_COMMAND_SET_ALL_KEYS_TYPEMATIC ((uint8_t) 0xF7U)
/// Followed by set 3 make codes, disable break and repeat
/// for the list of keys to follow. List terminated by an invalid
/// make code, e.g., another command.
#define PS2_COMMAND_SET_KEY_MAKE ((uint8_t) 0xFDU)
/// Followed by set 3 make codes, disable repeat (but not break)
/// for the list of keys to follow. List terminated by an invalid
/// make code, e.g., another command.
#define PS2_COMMAND_SET_KEY_MAKE_BREAK ((uint8_t) 0xFCU)
/// Followed by set 3 make codes, disable break (but not repeat)
/// for the list of keys to follow. List terminated by an invalid
/// make code, e.g., another command.
#define PS2_COMMAND_SET_KEY_TYPEMATIC ((uint8_t) 0xFBU)
/// Requests the device to echo back the same data. This is only
/// useful for testing.
#define PS2_COMMAND_ECHO ((uint8_t) 0xEEU)
/// Clears the echo mode if set (and supported).
#define PS2_COMMAND_CLEAR_ECHO ((uint8_t) 0xECU)
// MARK: - Errors
/// Parity error
#define PS2_ERROR_PARITY 'P'
/// Write was requested but did not begin
#define PS2_ERROR_WRITE_BEGIN 'W'
/// Write not acknowledged at the end
#define PS2_ERROR_WRITE_END 'w'
/// Incorrect start bit
#define PS2_ERROR_START_BIT 'S'
/// Incorrect stop bit
#define PS2_ERROR_STOP_BIT 's'
/// PS/2 was busy too long
#define PS2_ERROR_BUSY 'B'
/// PS/2 command did not succeed
#define PS2_ERROR_COMMAND 'C'
// MARK: - Functions
/// Enable the PS/2 host. Reading will commence on the PS/2 CLK signal.
/// This must be called before other `ps2_*` functions. It may also be
/// called again to recover from an error state.
void ps2_enable(void);
/// Is PS/2 ok? Returns `false` if there is an error state. Note that the
/// library does not automatically recover from error states. One recovery
/// option is to simply restart by calling `ps2_enable()` again.
bool ps2_is_ok(void);
/// Send a byte of `data` to the PS/2 device. If `flush_input` is true,
/// then also discards any unread input from the buffer so that any further
/// input will have been sent after sending. Return `true` iff successful
/// in sending (the reply is not read, i.e., the device may still indicate
/// a receive error). See also `ps2_command`.
bool ps2_send(const uint8_t data, const bool flush_input);
/// Send a byte of `data` to the PS/2 device. Return `true` iff successful.
#define ps2_send_byte(data) ps2_send((data), false)
/// Send the single-byte `command` to the PS/2 device, and return its
/// reply. This causes any unread input to be flushed from the buffer.
/// The reply is typically one of the `PS2_REPLY_*` values. The command will
/// automatically be retried if requested.
int ps2_command(const uint8_t command);
/// Send the byte `command` and its argument byte `arg` to the PS/2 device, and
/// return its reply. The reply is typically one of the `PS2_REPLY_*` values.
/// The command will automatically be retried if requested.
int ps2_command_arg(const uint8_t command, const uint8_t arg);
/// Send the single-byte `command` to the PS/2 device.
/// Returns `true` iff the reply is `PS2_REPLY_ACK`.
bool ps2_command_ack(const uint8_t command);
/// Send the byte `command` and its argument byte `arg` to the PS/2 device,
/// Returns `true` iff the reply is `PS2_REPLY_ACK`.
bool ps2_command_arg_ack(const uint8_t command, const uint8_t arg);
/// Reads and returns a byte from the PS/2 device. This blocks until a byte
/// is available to read (or until timed out, in which case `EOF` is returned).
int ps2_recv(void);
/// Reads and returns a byte from the PS/2 device. If no byte is available
/// within the specified number of `milliseconds`, returns `EOF`.
int ps2_recv_timeout(const uint8_t milliseconds);
/// Returns the number of bytes available to read from PS/2.
uint8_t ps2_bytes_available(void);
/// Returns the next available byte, or `EOF` if none available.
int ps2_get_byte(void);
/// Discard any unread bytes from the input buffer.
void ps2_flush_input(void);
/// Send a request to re-send the last byte received.
#define ps2_request_resend() ps2_send(PS2_COMMAND_RESEND, true)
/// Returns a single charater identifying the last error that occurred.
/// This is only valid while `ps2_is_ok` is `false`.
char ps2_last_error(void);
#endif