aboutsummaryrefslogtreecommitdiffstats
path: root/tmk_core/protocol/ps2.h
blob: e32cc9603f20d4648462aa73e4f69e713182f371 (plain)
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
/*
Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>

This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
GPL-compatible, and OK to use in both free and proprietary applications.
Additions and corrections to this file are welcome.


Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in
  the documentation and/or other materials provided with the
  distribution.

* Neither the name of the copyright holders nor the names of
  contributors may be used to endorse or promote products derived
  from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef PS2_H
#define PS2_H

#include <stdbool.h>
#include "wait.h"
#include "ps2_io.h"
#include "print.h"

/*
 * Primitive PS/2 Library for AVR
 *
 * PS/2 Resources
 * --------------
 * [1] The PS/2 Mouse/Keyboard Protocol
 * http://www.computer-engineering.org/ps2protocol/
 * Concise and thorough primer of PS/2 protocol.
 *
 * [2] Keyboard and Auxiliary Device Controller
 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
 * Signal Timing and Format
 *
 * [3] Keyboards(101- and 102-key)
 * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
 * Keyboard Layout, Scan Code Set, POR, and Commands.
 *
 * [4] PS/2 Reference Manuals
 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
 * Collection of IBM Personal System/2 documents.
 *
 * [5] TrackPoint Engineering Specifications for version 3E
 * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
 */
#define PS2_ACK 0xFA
#define PS2_RESEND 0xFE
#define PS2_SET_LED 0xED

// TODO: error numbers
#define PS2_ERR_NONE 0
#define PS2_ERR_STARTBIT1 1
#define PS2_ERR_STARTBIT2 2
#define PS2_ERR_STARTBIT3 3
#define PS2_ERR_PARITY 0x10
#define PS2_ERR_NODATA 0x20

#define PS2_LED_SCROLL_LOCK 0
#define PS2_LED_NUM_LOCK 1
#define PS2_LED_CAPS_LOCK 2

extern uint8_t ps2_error;

void    ps2_host_init(void);
uint8_t ps2_host_send(uint8_t data);
uint8_t ps2_host_recv_response(void);
uint8_t ps2_host_recv(void);
void    ps2_host_set_led(uint8_t usb_led);

/*--------------------------------------------------------------------
 * static functions
 *------------------------------------------------------------------*/
static inline uint16_t wait_clock_lo(uint16_t us) {
    while (clock_in() && us) {
        asm("");
        wait_us(1);
        us--;
    }
    return us;
}
static inline uint16_t wait_clock_hi(uint16_t us) {
    while (!clock_in() && us) {
        asm("");
        wait_us(1);
        us--;
    }
    return us;
}
static inline uint16_t wait_data_lo(uint16_t us) {
    while (data_in() && us) {
        asm("");
        wait_us(1);
        us--;
    }
    return us;
}
static inline uint16_t wait_data_hi(uint16_t us) {
    while (!data_in() && us) {
        asm("");
        wait_us(1);
        us--;
    }
    return us;
}

/* idle state that device can send */
static inline void idle(void) {
    clock_hi();
    data_hi();
}

/* inhibit device to send */
static inline void inhibit(void) {
    clock_lo();
    data_hi();
}

#endif
p_flags; #if CH_USE_DYNAMIC /** * @brief References to this thread. */ trefs_t p_refs; #endif #if CH_USE_NESTED_LOCKS /** * @brief Number of nested locks. */ cnt_t p_locks; #endif #if CH_DBG_THREADS_PROFILING /** * @brief Thread consumed time in ticks. * @note This field can overflow. */ volatile systime_t p_time; #endif /** * @brief State-specific fields. * @note All the fields declared in this union are only valid in the * specified state or condition and are thus volatile. */ union { /** * @brief Thread wakeup code. * @note This field contains the low level message sent to the thread * by the waking thread or interrupt handler. The value is valid * after exiting the @p chSchWakeupS() function. */ msg_t rdymsg; /** * @brief Thread exit code. * @note The thread termination code is stored in this field in order * to be retrieved by the thread performing a @p chThdWait() on * this thread. */ msg_t exitcode; /** * @brief Pointer to a generic "wait" object. * @note This field is used to get a generic pointer to a synchronization * object and is valid when the thread is in one of the wait * states. */ void *wtobjp; #if CH_USE_EVENTS /** * @brief Enabled events mask. * @note This field is only valied while the thread is in the * @p THD_STATE_WTOREVT or @p THD_STATE_WTANDEVT states. */ eventmask_t ewmask; #endif } p_u; #if CH_USE_WAITEXIT /** * @brief Termination waiting list. */ ThreadsList p_waiting; #endif #if CH_USE_MESSAGES /** * @brief Messages queue. */ ThreadsQueue p_msgqueue; /** * @brief Thread message. */ msg_t p_msg; #endif #if CH_USE_EVENTS /** * @brief Pending events mask. */ eventmask_t p_epending; #endif #if CH_USE_MUTEXES /** * @brief List of the mutexes owned by this thread. * @note The list is terminated by a @p NULL in this field. */ Mutex *p_mtxlist; /** * @brief Thread's own, non-inherited, priority. */ tprio_t p_realprio; #endif #if CH_USE_DYNAMIC && CH_USE_MEMPOOLS /** * @brief Memory Pool where the thread workspace is returned. */ void *p_mpool; #endif #if defined(THREAD_EXT_FIELDS) /* Extra fields defined in chconf.h.*/ THREAD_EXT_FIELDS #endif }; /** @brief Thread state: Ready to run, waiting on the ready list.*/ #define THD_STATE_READY 0 /** @brief Thread state: Currently running.*/ #define THD_STATE_CURRENT 1 /** @brief Thread state: Thread created in suspended state.*/ #define THD_STATE_SUSPENDED 2 /** @brief Thread state: Waiting on a semaphore.*/ #define THD_STATE_WTSEM 3 /** @brief Thread state: Waiting on a mutex.*/ #define THD_STATE_WTMTX 4 /** @brief Thread state: Waiting in @p chCondWait().*/ #define THD_STATE_WTCOND 5 /** @brief Thread state: Waiting in @p chThdSleep() or @p chThdSleepUntil().*/ #define THD_STATE_SLEEPING 6 /** @brief Thread state: Waiting in @p chThdWait().*/ #define THD_STATE_WTEXIT 7 /** @brief Thread state: Waiting in @p chEvtWaitXXX().*/ #define THD_STATE_WTOREVT 8 /** @brief Thread state: Waiting in @p chEvtWaitAllTimeout().*/ #define THD_STATE_WTANDEVT 9 /** @brief Thread state: Waiting in @p chMsgSend() (queued).*/ #define THD_STATE_SNDMSGQ 10 /** @brief Thread state: Waiting in @p chMsgSend() (not queued).*/ #define THD_STATE_SNDMSG 11 /** @brief Thread state: Waiting in @p chMsgWait().*/ #define THD_STATE_WTMSG 12 /** @brief Thread state: Waiting on an I/O queue.*/ #define THD_STATE_WTQUEUE 13 /** @brief Thread state: After termination.*/ #define THD_STATE_FINAL 14 /* * Various flags into the thread p_flags field. */ #define THD_MEM_MODE_MASK 3 /**< @brief Thread memory mode mask. */ #define THD_MEM_MODE_STATIC 0 /**< @brief Thread memory mode: static. */ #define THD_MEM_MODE_HEAP 1 /**< @brief Thread memory mode: heap. */ #define THD_MEM_MODE_MEMPOOL 2 /**< @brief Thread memory mode: pool. */ #define THD_TERMINATE 4 /**< @brief Termination requested. */ /** @brief Thread function.*/ typedef msg_t (*tfunc_t)(void *); /* * Threads APIs. */ #ifdef __cplusplus extern "C" { #endif Thread *_thread_init(Thread *tp, tprio_t prio); #if CH_DBG_FILL_THREADS void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v); #endif Thread *chThdCreateI(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg); Thread *chThdCreateStatic(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg); tprio_t chThdSetPriority(tprio_t newprio); Thread *chThdResume(Thread *tp); void chThdTerminate(Thread *tp); void chThdSleep(systime_t time); void chThdSleepUntil(systime_t time); void chThdYield(void); void chThdExit(msg_t msg); #if CH_USE_WAITEXIT msg_t chThdWait(Thread *tp); #endif #ifdef __cplusplus } #endif /** * @brief Returns a pointer to the current @p Thread. * * @api */ #define chThdSelf() currp /** * @brief Returns the current thread priority. * * @api */ #define chThdGetPriority() (currp->p_prio) /** * @brief Returns the number of ticks consumed by the specified thread. * @note This function is only available when the * @p CH_DBG_THREADS_PROFILING configuration option is enabled. * * @param[in] tp pointer to the thread * * @api */ #define chThdGetTicks(tp) ((tp)->p_time) /** * @brief Returns the pointer to the @p Thread local storage area, if any. * * @api */ #define chThdLS() (void *)(currp + 1) /** * @brief Verifies if the specified thread is in the @p THD_STATE_FINAL state. * * @param[in] tp pointer to the thread * @retval TRUE thread terminated. * @retval FALSE thread not terminated. * * @api */ #define chThdTerminated(tp) ((tp)->p_state == THD_STATE_FINAL) /** * @brief Verifies if the current thread has a termination request pending. * * @retval TRUE termination request pended. * @retval FALSE termination request not pended. * * @api */ #define chThdShouldTerminate() (currp->p_flags & THD_TERMINATE) /** * @brief Resumes a thread created with @p chThdInit(). * * @param[in] tp pointer to the thread * * @iclass */ #define chThdResumeI(tp) chSchReadyI(tp) /** * @brief Suspends the invoking thread for the specified time. * * @param[in] time the delay in system ticks, the special values are * handled as follow: * - @a TIME_INFINITE the thread enters an infinite sleep * state. * - @a TIME_IMMEDIATE this value is not allowed. * . * * @sclass */ #define chThdSleepS(time) chSchGoSleepTimeoutS(THD_STATE_SLEEPING, time) /** * @brief Delays the invoking thread for the specified number of seconds. * @note The specified time is rounded up to a value allowed by the real * system clock. * @note The maximum specified value is implementation dependent. * * @param[in] sec time in seconds * * @api */ #define chThdSleepSeconds(sec) chThdSleep(S2ST(sec)) /** * @brief Delays the invoking thread for the specified number of * milliseconds. * @note The specified time is rounded up to a value allowed by the real * system clock. * @note The maximum specified value is implementation dependent. * * @param[in] msec time in milliseconds * * @api */ #define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec)) /** * @brief Delays the invoking thread for the specified number of * microseconds. * @note The specified time is rounded up to a value allowed by the real * system clock. * @note The maximum specified value is implementation dependent. * * @param[in] usec time in microseconds * * @api */ #define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec)) #endif /* _CHTHREADS_H_ */ /** @} */