Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
caad39421c
170 changed files with 38730 additions and 26170 deletions
|
|
@ -104,6 +104,12 @@ void adb_mouse_task(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool adb_srq = false;
|
||||
bool adb_service_request(void)
|
||||
{
|
||||
return adb_srq;
|
||||
}
|
||||
|
||||
// This sends Talk command to read data from register and returns length of the data.
|
||||
uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
|
||||
{
|
||||
|
|
@ -157,7 +163,8 @@ uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
|
|||
// portion of the stop bit of any command or data transaction. The device must lengthen
|
||||
// the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15."
|
||||
// http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf
|
||||
if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
|
||||
if (!data_in()) { adb_srq = true; } else { adb_srq = false; }
|
||||
if (!wait_data_hi(500)) { // wait for end of SRQ:(310us Adjustable Keyboard)
|
||||
xprintf("R");
|
||||
sei();
|
||||
return 0;
|
||||
|
|
@ -191,12 +198,14 @@ uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
|
|||
// |________| |
|
||||
//
|
||||
uint8_t lo = (uint8_t) wait_data_hi(130);
|
||||
if (!lo)
|
||||
goto error; // no more bit or after stop bit
|
||||
if (!lo) {
|
||||
goto error; // SRQ?
|
||||
}
|
||||
|
||||
uint8_t hi = (uint8_t) wait_data_lo(lo);
|
||||
if (!hi)
|
||||
goto error; // stop bit extedned by Srq?
|
||||
if (!hi) {
|
||||
goto error; // stop bit
|
||||
}
|
||||
|
||||
if (n/8 >= len) continue; // can't store in buf
|
||||
|
||||
|
|
@ -209,6 +218,7 @@ uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
|
|||
|
||||
error:
|
||||
sei();
|
||||
_delay_us(200);
|
||||
return n/8;
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +237,8 @@ void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
|
|||
attention();
|
||||
send_byte((addr<<4) | ADB_CMD_LISTEN | reg);
|
||||
place_bit0(); // Stopbit(0)
|
||||
// TODO: Service Request
|
||||
if (!data_in()) { adb_srq = true; } else { adb_srq = false; }
|
||||
wait_data_hi(500); // Service Request
|
||||
_delay_us(200); // Tlt/Stop to Start
|
||||
place_bit1(); // Startbit(1)
|
||||
for (int8_t i = 0; i < len; i++) {
|
||||
|
|
@ -236,6 +247,7 @@ void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
|
|||
}
|
||||
place_bit0(); // Stopbit(0);
|
||||
sei();
|
||||
_delay_us(200);
|
||||
}
|
||||
|
||||
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l)
|
||||
|
|
@ -254,13 +266,32 @@ void adb_host_flush(uint8_t addr)
|
|||
sei();
|
||||
}
|
||||
|
||||
void adb_host_reset(void)
|
||||
{
|
||||
cli();
|
||||
attention();
|
||||
send_byte(ADB_CMD_RESET);
|
||||
place_bit0(); // Stopbit(0)
|
||||
_delay_us(200); // Tlt/Stop to Start
|
||||
sei();
|
||||
}
|
||||
|
||||
void adb_host_reset_hard(void)
|
||||
{
|
||||
data_lo();
|
||||
_delay_us(3000);
|
||||
data_hi();
|
||||
}
|
||||
|
||||
// send state of LEDs
|
||||
void adb_host_kbd_led(uint8_t addr, uint8_t led)
|
||||
{
|
||||
// Listen Register2
|
||||
// upper byte: not used
|
||||
// lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock
|
||||
adb_host_listen(addr, 2, 0, led & 0x07);
|
||||
uint16_t reg2 = adb_host_talk(addr, 2);
|
||||
_delay_us(400);
|
||||
adb_host_listen(addr, 2, reg2 >> 8, (reg2 & 0xF8) | (led & 0x07));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -68,9 +68,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define ADB_ADDR_13 13
|
||||
#define ADB_ADDR_14 14
|
||||
#define ADB_ADDR_15 15
|
||||
// for temporary purpose, do not use for polling
|
||||
#define ADB_ADDR_TMP 15
|
||||
#define ADB_ADDR_MOUSE_POLL 10
|
||||
// Command Type
|
||||
#define ADB_CMD_RESET 0
|
||||
#define ADB_CMD_FLUSH 1
|
||||
|
|
@ -93,6 +90,15 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define ADB_HANDLER_CLASSIC2_MOUSE 0x02
|
||||
#define ADB_HANDLER_EXTENDED_MOUSE 0x04
|
||||
#define ADB_HANDLER_TURBO_MOUSE 0x32
|
||||
#define ADB_HANDLER_MACALLY2_MOUSE 0x42
|
||||
#define ADB_HANDLER_MICROSPEED_MACTRAC 0x2F
|
||||
#define ADB_HANDLER_MICROSPEED_UNKNOWN 0x5F
|
||||
#define ADB_HANDLER_CONTOUR_MOUSE 0x66
|
||||
#define ADB_HANDLER_CHPRODUCTS_PRO 0x42
|
||||
#define ADB_HANDLER_MOUSESYSTEMS_A3 0x03
|
||||
// pseudo handler
|
||||
#define ADB_HANDLER_LOGITECH 0x4C
|
||||
#define ADB_HANDLER_LOGITECH_EXT 0x4D
|
||||
|
||||
|
||||
// ADB host
|
||||
|
|
@ -104,9 +110,13 @@ uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
|
|||
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l);
|
||||
void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
|
||||
void adb_host_flush(uint8_t addr);
|
||||
void adb_host_reset(void);
|
||||
void adb_host_reset_hard(void);
|
||||
void adb_host_kbd_led(uint8_t addr, uint8_t led);
|
||||
void adb_mouse_task(void);
|
||||
void adb_mouse_init(void);
|
||||
uint8_t adb_mouse_buttons(void);
|
||||
bool adb_service_request(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -42,76 +42,75 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <stdbool.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/atomic.h>
|
||||
#include "ibmpc.h"
|
||||
#include "debug.h"
|
||||
#include "timer.h"
|
||||
#include "wait.h"
|
||||
#include "ibmpc.hpp"
|
||||
|
||||
|
||||
#define WAIT(stat, us, err) do { \
|
||||
if (!wait_##stat(us)) { \
|
||||
ibmpc_error = err; \
|
||||
error = err; \
|
||||
goto ERROR; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
volatile uint16_t ibmpc_isr_debug = 0;
|
||||
volatile uint8_t ibmpc_protocol = IBMPC_PROTOCOL_NO;
|
||||
volatile uint8_t ibmpc_error = IBMPC_ERR_NONE;
|
||||
IBMPC IBMPC::interface0 = IBMPC(IBMPC_CLOCK_BIT, IBMPC_DATA_BIT);
|
||||
#if defined(IBMPC_CLOCK_BIT1) && defined(IBMPC_DATA_BIT1)
|
||||
IBMPC IBMPC::interface1 = IBMPC(IBMPC_CLOCK_BIT1, IBMPC_DATA_BIT1);
|
||||
#endif
|
||||
|
||||
/* 2-byte buffer for data received from keyboard
|
||||
* buffer states:
|
||||
* FFFF: empty
|
||||
* FFss: one data
|
||||
* sstt: two data
|
||||
* eeFF: error
|
||||
* where ss, tt and ee are 0x00-0xFE. 0xFF means empty or no data in buffer.
|
||||
*/
|
||||
static volatile uint16_t recv_data = 0xFFFF;
|
||||
/* internal state of receiving data */
|
||||
static volatile uint16_t isr_state = 0x8000;
|
||||
static uint8_t timer_start = 0;
|
||||
|
||||
void ibmpc_host_init(void)
|
||||
void IBMPC::host_init(void)
|
||||
{
|
||||
// initialize reset pin to HiZ
|
||||
IBMPC_RST_HIZ();
|
||||
inhibit();
|
||||
IBMPC_INT_INIT();
|
||||
IBMPC_INT_OFF();
|
||||
int_init();
|
||||
int_off();
|
||||
host_isr_clear();
|
||||
}
|
||||
|
||||
void ibmpc_host_enable(void)
|
||||
void IBMPC::host_enable(void)
|
||||
{
|
||||
IBMPC_INT_ON();
|
||||
int_on();
|
||||
idle();
|
||||
}
|
||||
|
||||
void ibmpc_host_disable(void)
|
||||
void IBMPC::host_disable(void)
|
||||
{
|
||||
IBMPC_INT_OFF();
|
||||
int_off();
|
||||
inhibit();
|
||||
}
|
||||
|
||||
int16_t ibmpc_host_send(uint8_t data)
|
||||
int16_t IBMPC::host_send(uint8_t data)
|
||||
{
|
||||
bool parity = true;
|
||||
ibmpc_error = IBMPC_ERR_NONE;
|
||||
error = IBMPC_ERR_NONE;
|
||||
uint8_t retry = 0;
|
||||
|
||||
dprintf("w%02X ", data);
|
||||
|
||||
IBMPC_INT_OFF();
|
||||
// Return when receiving data
|
||||
//if (isr_state & 0x0FFF) {
|
||||
if (isr_state != 0x8000) {
|
||||
dprintf("isr:%04X ", isr_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int_off();
|
||||
|
||||
RETRY:
|
||||
/* terminate a transmission if we have */
|
||||
inhibit();
|
||||
wait_us(100); // [5]p.54
|
||||
wait_us(200); // [5]p.54
|
||||
|
||||
/* 'Request to Send' and Start bit */
|
||||
data_lo();
|
||||
wait_us(100);
|
||||
wait_us(200);
|
||||
clock_hi(); // [5]p.54 [clock low]>100us [5]p.50
|
||||
WAIT(clock_lo, 10000, 1); // [5]p.53, -10ms [5]p.50
|
||||
WAIT(clock_lo, 15000, 1); // [5]p.54 T13M, -10ms [5]p.50
|
||||
|
||||
/* Data bit[2-9] */
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
|
|
@ -135,117 +134,89 @@ int16_t ibmpc_host_send(uint8_t data)
|
|||
/* Stop bit */
|
||||
wait_us(15);
|
||||
data_hi();
|
||||
WAIT(clock_hi, 50, 6);
|
||||
if (ibmpc_protocol == IBMPC_PROTOCOL_AT_Z150) { goto RECV; }
|
||||
WAIT(clock_lo, 50, 7);
|
||||
|
||||
/* Ack */
|
||||
WAIT(data_lo, 50, 8);
|
||||
WAIT(data_lo, 300, 6);
|
||||
WAIT(data_hi, 300, 7);
|
||||
WAIT(clock_hi, 300, 8);
|
||||
|
||||
/* wait for idle state */
|
||||
WAIT(clock_hi, 50, 9);
|
||||
WAIT(data_hi, 50, 10);
|
||||
#ifdef SIEMENS_PCD_SUPPORT
|
||||
// inhibit - https://github.com/tmk/tmk_keyboard/issues/747
|
||||
if (protocol & IBMPC_PROTOCOL_AT) {
|
||||
wait_us(15);
|
||||
clock_lo();
|
||||
wait_us(150);
|
||||
}
|
||||
#endif
|
||||
|
||||
RECV:
|
||||
// clear buffer to get response correctly
|
||||
recv_data = 0xFFFF;
|
||||
ibmpc_host_isr_clear();
|
||||
host_isr_clear();
|
||||
|
||||
idle();
|
||||
IBMPC_INT_ON();
|
||||
return ibmpc_host_recv_response();
|
||||
int_on();
|
||||
return host_recv_response();
|
||||
ERROR:
|
||||
ibmpc_error |= IBMPC_ERR_SEND;
|
||||
// Retry for Z-150 AT start bit error
|
||||
if (error == 1 && retry++ < 10) {
|
||||
error = IBMPC_ERR_NONE;
|
||||
dprintf("R ");
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
isr_debug = isr_state;
|
||||
error |= IBMPC_ERR_SEND;
|
||||
inhibit();
|
||||
wait_ms(2);
|
||||
idle();
|
||||
IBMPC_INT_ON();
|
||||
int_on();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data from keyboard
|
||||
*/
|
||||
int16_t ibmpc_host_recv(void)
|
||||
int16_t IBMPC::host_recv(void)
|
||||
{
|
||||
uint16_t data = 0;
|
||||
uint8_t ret = 0xFF;
|
||||
int16_t ret = -1;
|
||||
|
||||
// Enable ISR if buffer was full
|
||||
if (ringbuf_is_full()) {
|
||||
host_isr_clear();
|
||||
int_on();
|
||||
idle();
|
||||
}
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
data = recv_data;
|
||||
|
||||
// remove data from buffer:
|
||||
// FFFF(empty) -> FFFF
|
||||
// FFss(one data) -> FFFF
|
||||
// sstt(two data) -> FFtt
|
||||
// eeFF(errror) -> FFFF
|
||||
recv_data = data | (((data&0xFF00) == 0xFF00) ? 0x00FF : 0xFF00);
|
||||
ret = ringbuf_get();
|
||||
}
|
||||
|
||||
if ((data&0x00FF) == 0x00FF) {
|
||||
// error: eeFF
|
||||
switch (data>>8) {
|
||||
case IBMPC_ERR_FF:
|
||||
// 0xFF(Overrun/Error) from keyboard
|
||||
dprintf("!FF! ");
|
||||
ret = 0xFF;
|
||||
break;
|
||||
case IBMPC_ERR_FULL:
|
||||
// buffer full
|
||||
dprintf("!FULL! ");
|
||||
ret = 0xFF;
|
||||
break;
|
||||
case 0xFF:
|
||||
// empty: FFFF
|
||||
return -1;
|
||||
default:
|
||||
// other errors
|
||||
dprintf("e%02X ", data>>8);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if ((data | 0x00FF) != 0xFFFF) {
|
||||
// two data: sstt
|
||||
dprintf("b:%04X ", data);
|
||||
ret = (data>>8);
|
||||
} else {
|
||||
// one data: FFss
|
||||
ret = (data&0x00FF);
|
||||
}
|
||||
}
|
||||
|
||||
//dprintf("i%04X ", ibmpc_isr_debug); ibmpc_isr_debug = 0;
|
||||
dprintf("r%02X ", ret);
|
||||
if (ret != -1) dprintf("r%02X ", ret&0xFF);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int16_t ibmpc_host_recv_response(void)
|
||||
int16_t IBMPC::host_recv_response(void)
|
||||
{
|
||||
// Command may take 25ms/20ms at most([5]p.46, [3]p.21)
|
||||
uint8_t retry = 25;
|
||||
int16_t data = -1;
|
||||
while (retry-- && (data = ibmpc_host_recv()) == -1) {
|
||||
while (retry-- && (data = host_recv()) == -1) {
|
||||
wait_ms(1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void ibmpc_host_isr_clear(void)
|
||||
void IBMPC::host_isr_clear(void)
|
||||
{
|
||||
ibmpc_isr_debug = 0;
|
||||
ibmpc_protocol = 0;
|
||||
ibmpc_error = 0;
|
||||
isr_debug = 0;
|
||||
protocol = 0;
|
||||
error = 0;
|
||||
isr_state = 0x8000;
|
||||
recv_data = 0xFFFF;
|
||||
ringbuf_reset();
|
||||
}
|
||||
|
||||
#define LO8(w) (*((uint8_t *)&(w)))
|
||||
#define HI8(w) (*(((uint8_t *)&(w))+1))
|
||||
// NOTE: With this ISR data line can be read within 2us after clock falling edge.
|
||||
// To read data line early as possible:
|
||||
// write naked ISR with asembly code to read the line and call C func to do other job?
|
||||
ISR(IBMPC_INT_VECT)
|
||||
void IBMPC::isr(void)
|
||||
{
|
||||
uint8_t dbit;
|
||||
dbit = IBMPC_DATA_PIN&(1<<IBMPC_DATA_BIT);
|
||||
dbit = IBMPC_DATA_PIN&(1<<data_bit);
|
||||
|
||||
// Timeout check
|
||||
uint8_t t;
|
||||
|
|
@ -256,9 +227,9 @@ ISR(IBMPC_INT_VECT)
|
|||
timer_start = t;
|
||||
} else {
|
||||
// This gives 2.0ms at least before timeout
|
||||
if ((uint8_t)(t - timer_start) >= 3) {
|
||||
ibmpc_isr_debug = isr_state;
|
||||
ibmpc_error = IBMPC_ERR_TIMEOUT;
|
||||
if ((uint8_t)(t - timer_start) >= 5) {
|
||||
isr_debug = isr_state;
|
||||
error = IBMPC_ERR_TIMEOUT;
|
||||
goto ERROR;
|
||||
|
||||
// timeout error recovery - start receiving new data
|
||||
|
|
@ -289,13 +260,12 @@ ISR(IBMPC_INT_VECT)
|
|||
// x x x x x x x x | *1 0 0 0 0 0 0 0 midway(8 bits received)
|
||||
// b6 b5 b4 b3 b2 b1 b0 1 | 0 *1 0 0 0 0 0 0 XT_IBM-midway ^1
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 0 *1 0 0 0 0 0 0 AT-midway ^1
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 *1 0 0 0 0 0 0 XT_Clone-done ^3
|
||||
// b6 b5 b4 b3 b2 b1 b0 1 | 1 *1 0 0 0 0 0 0 XT_IBM-error ^3
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 *1 0 0 0 0 0 0 XT_Clone-done
|
||||
// pr b7 b6 b5 b4 b3 b2 b1 | 0 0 *1 0 0 0 0 0 AT-midway[b0=0]
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 0 *1 0 0 0 0 0 XT_IBM-done ^2
|
||||
// pr b7 b6 b5 b4 b3 b2 b1 | 1 0 *1 0 0 0 0 0 AT-midway[b0=1] ^2
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 1 *1 0 0 0 0 0 XT_IBM-error-done
|
||||
// x x x x x x x x | x 1 1 0 0 0 0 0 illegal
|
||||
// x x x x x x x x | 0 1 *1 0 0 0 0 0 illegal
|
||||
// x x x x x x x x | 1 1 *1 0 0 0 0 0 illegal
|
||||
// st pr b7 b6 b5 b4 b3 b2 | b1 b0 0 *1 0 0 0 0 AT-done
|
||||
// x x x x x x x x | x x 1 *1 0 0 0 0 illegal
|
||||
// all other states than above illegal
|
||||
|
|
@ -311,101 +281,120 @@ ISR(IBMPC_INT_VECT)
|
|||
// midway
|
||||
goto NEXT;
|
||||
break;
|
||||
case 0b11000000: // ^3
|
||||
{
|
||||
uint8_t us = 100;
|
||||
// wait for rising and falling edge of b7 of XT_IBM
|
||||
while (!(IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT)) && us) { wait_us(1); us--; }
|
||||
while ( IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT) && us) { wait_us(1); us--; }
|
||||
|
||||
if (us) {
|
||||
// XT_IBM-error: read start(0) as 1
|
||||
goto NEXT;
|
||||
} else {
|
||||
// XT_Clone-done
|
||||
ibmpc_isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_XT_CLONE;
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0b11100000:
|
||||
// XT_IBM-error-done
|
||||
ibmpc_isr_debug = isr_state;
|
||||
case 0b11000000:
|
||||
// XT_Clone-done
|
||||
isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_XT_ERROR;
|
||||
protocol = IBMPC_PROTOCOL_XT_CLONE;
|
||||
goto DONE;
|
||||
break;
|
||||
case 0b10100000: // ^2
|
||||
{
|
||||
uint8_t us = 100;
|
||||
// wait for rising and falling edge of AT stop bit to discriminate between XT and AT
|
||||
while (!(IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT)) && us) { wait_us(1); us--; }
|
||||
while ( IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT) && us) { wait_us(1); us--; }
|
||||
if (!protocol) {
|
||||
while (!(IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
while ( (IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
} else if (protocol == IBMPC_PROTOCOL_XT_IBM) {
|
||||
us = 0;
|
||||
}
|
||||
|
||||
if (us) {
|
||||
// found stop bit: AT-midway - process the stop bit in next ISR
|
||||
goto NEXT;
|
||||
} else {
|
||||
// no stop bit: XT_IBM-done
|
||||
ibmpc_isr_debug = isr_state;
|
||||
isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_XT_IBM;
|
||||
protocol = IBMPC_PROTOCOL_XT_IBM;
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0b00010000:
|
||||
case 0b10010000:
|
||||
case 0b01010000:
|
||||
case 0b11010000:
|
||||
// AT-done
|
||||
// TODO: parity check?
|
||||
ibmpc_isr_debug = isr_state;
|
||||
isr_debug = isr_state;
|
||||
|
||||
// Detect AA with parity error for AT/XT Auto-Switching support
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-Keyboard-Converter#atxt-auto-switching
|
||||
// isr_state: st pr b7 b6 b5 b4 b3 b2 | b1 b0 0 *1 0 0 0 0
|
||||
// 1 '0' 1 0 1 0 1 0 | 1 0 0 *1 0 0 0 0
|
||||
if (isr_state == 0xAA90) {
|
||||
error = IBMPC_ERR_PARITY_AA;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
// parit bit check
|
||||
{
|
||||
// isr_state: st pr b7 b6 b5 b4 b3 b2 | b1 b0 0 *1 0 0 0 0
|
||||
uint8_t p = (isr_state & 0x4000) ? 1 : 0;
|
||||
p ^= (isr_state >> 6);
|
||||
while (p & 0xFE) {
|
||||
p = (p >> 1) ^ (p & 0x01);
|
||||
}
|
||||
|
||||
if (p == 0) {
|
||||
error = IBMPC_ERR_PARITY;
|
||||
goto ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// stop bit check
|
||||
if (isr_state & 0x8000) {
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_AT;
|
||||
protocol = IBMPC_PROTOCOL_AT;
|
||||
} else {
|
||||
// Zenith Z-150 AT(beige/white lable) asserts stop bit as low
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-AT-Keyboard-Protocol#zenith-z-150-beige
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_AT_Z150;
|
||||
protocol = IBMPC_PROTOCOL_AT_Z150;
|
||||
}
|
||||
isr_state = isr_state>>6;
|
||||
goto DONE;
|
||||
break;
|
||||
case 0b01100000:
|
||||
case 0b11100000:
|
||||
case 0b00110000:
|
||||
case 0b10110000:
|
||||
case 0b01110000:
|
||||
case 0b11110000:
|
||||
default: // xxxx_oooo(any 1 in low nibble)
|
||||
// Illegal
|
||||
ibmpc_isr_debug = isr_state;
|
||||
ibmpc_error = IBMPC_ERR_ILLEGAL;
|
||||
protocol = 0;
|
||||
isr_debug = isr_state;
|
||||
error = IBMPC_ERR_ILLEGAL;
|
||||
goto ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ERROR:
|
||||
// error: eeFF
|
||||
recv_data = (ibmpc_error<<8) | 0x00FF;
|
||||
goto CLEAR;
|
||||
DONE:
|
||||
if ((isr_state & 0x00FF) == 0x00FF) {
|
||||
// receive error code 0xFF
|
||||
ibmpc_error = IBMPC_ERR_FF;
|
||||
goto ERROR;
|
||||
}
|
||||
if (HI8(recv_data) != 0xFF && LO8(recv_data) != 0xFF) {
|
||||
// buffer full
|
||||
ibmpc_error = IBMPC_ERR_FULL;
|
||||
goto ERROR;
|
||||
#ifdef SIEMENS_PCD_SUPPORT
|
||||
// inhibit - https://github.com/tmk/tmk_keyboard/issues/747
|
||||
if (protocol & IBMPC_PROTOCOL_AT) {
|
||||
clock_lo();
|
||||
wait_us(150);
|
||||
clock_hi();
|
||||
}
|
||||
#endif
|
||||
|
||||
// store data
|
||||
recv_data = recv_data<<8;
|
||||
recv_data |= isr_state & 0xFF;
|
||||
CLEAR:
|
||||
ringbuf_put(isr_state & 0xFF);
|
||||
if (ringbuf_is_full()) {
|
||||
// Disable ISR if buffer is full
|
||||
int_off();
|
||||
// inhibit: clock_lo() instead of inhibit() for ISR optimization
|
||||
clock_lo();
|
||||
}
|
||||
if (ringbuf_is_empty()) {
|
||||
// buffer overflow
|
||||
error = IBMPC_ERR_FULL;
|
||||
}
|
||||
goto END;
|
||||
ERROR:
|
||||
// inhibit: Use clock_lo() instead of inhibit() for ISR optimization
|
||||
clock_lo();
|
||||
END:
|
||||
// clear for next data
|
||||
isr_state = 0x8000;
|
||||
NEXT:
|
||||
|
|
@ -413,9 +402,25 @@ NEXT:
|
|||
}
|
||||
|
||||
/* send LED state to keyboard */
|
||||
void ibmpc_host_set_led(uint8_t led)
|
||||
void IBMPC::host_set_led(uint8_t led)
|
||||
{
|
||||
if (0xFA == ibmpc_host_send(0xED)) {
|
||||
ibmpc_host_send(led);
|
||||
if (0xFA == host_send(0xED)) {
|
||||
host_send(led);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NOTE: With this ISR data line should be read within 5us after clock falling edge.
|
||||
// Confirmed that ATmega32u4 can read data line in 2.5us from interrupt after
|
||||
// ISR prologue pushs r18, r19, r20, r21, r24, r25 r30 and r31 with GCC 5.4.0
|
||||
ISR(IBMPC_INT_VECT)
|
||||
{
|
||||
IBMPC::interface0.isr();
|
||||
}
|
||||
|
||||
#if defined(IBMPC_CLOCK_BIT1) && defined(IBMPC_DATA_BIT1) && defined(IBMPC_INT_VECT1)
|
||||
ISR(IBMPC_INT_VECT1)
|
||||
{
|
||||
IBMPC::interface1.isr();
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
Copyright 2010,2011,2012,2013,2019 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 IBMPC_H
|
||||
#define IBMPC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "wait.h"
|
||||
#include "print.h"
|
||||
|
||||
/*
|
||||
* IBM PC keyboard protocol
|
||||
*
|
||||
* 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 IBMPC_ACK 0xFA
|
||||
#define IBMPC_RESEND 0xFE
|
||||
#define IBMPC_SET_LED 0xED
|
||||
|
||||
#define IBMPC_PROTOCOL_NO 0
|
||||
#define IBMPC_PROTOCOL_AT 0x10
|
||||
#define IBMPC_PROTOCOL_AT_Z150 0x11
|
||||
#define IBMPC_PROTOCOL_XT 0x20
|
||||
#define IBMPC_PROTOCOL_XT_IBM 0x21
|
||||
#define IBMPC_PROTOCOL_XT_CLONE 0x22
|
||||
#define IBMPC_PROTOCOL_XT_ERROR 0x23
|
||||
|
||||
// Error numbers
|
||||
#define IBMPC_ERR_NONE 0
|
||||
#define IBMPC_ERR_RECV 0x00
|
||||
#define IBMPC_ERR_SEND 0x10
|
||||
#define IBMPC_ERR_TIMEOUT 0x20
|
||||
#define IBMPC_ERR_FULL 0x40
|
||||
#define IBMPC_ERR_ILLEGAL 0x80
|
||||
#define IBMPC_ERR_FF 0xF0
|
||||
|
||||
#define IBMPC_LED_SCROLL_LOCK 0
|
||||
#define IBMPC_LED_NUM_LOCK 1
|
||||
#define IBMPC_LED_CAPS_LOCK 2
|
||||
|
||||
|
||||
extern volatile uint16_t ibmpc_isr_debug;
|
||||
extern volatile uint8_t ibmpc_protocol;
|
||||
extern volatile uint8_t ibmpc_error;
|
||||
|
||||
void ibmpc_host_init(void);
|
||||
void ibmpc_host_enable(void);
|
||||
void ibmpc_host_disable(void);
|
||||
int16_t ibmpc_host_send(uint8_t data);
|
||||
int16_t ibmpc_host_recv_response(void);
|
||||
int16_t ibmpc_host_recv(void);
|
||||
void ibmpc_host_isr_clear(void);
|
||||
void ibmpc_host_set_led(uint8_t usb_led);
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* static functions
|
||||
*------------------------------------------------------------------*/
|
||||
#if defined(__AVR__)
|
||||
/*
|
||||
* Clock
|
||||
*/
|
||||
static inline void clock_lo(void)
|
||||
{
|
||||
IBMPC_CLOCK_PORT &= ~(1<<IBMPC_CLOCK_BIT);
|
||||
IBMPC_CLOCK_DDR |= (1<<IBMPC_CLOCK_BIT);
|
||||
}
|
||||
|
||||
static inline void clock_hi(void)
|
||||
{
|
||||
/* input with pull up */
|
||||
IBMPC_CLOCK_DDR &= ~(1<<IBMPC_CLOCK_BIT);
|
||||
IBMPC_CLOCK_PORT |= (1<<IBMPC_CLOCK_BIT);
|
||||
}
|
||||
|
||||
static inline bool clock_in(void)
|
||||
{
|
||||
IBMPC_CLOCK_DDR &= ~(1<<IBMPC_CLOCK_BIT);
|
||||
IBMPC_CLOCK_PORT |= (1<<IBMPC_CLOCK_BIT);
|
||||
wait_us(1);
|
||||
return IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Data
|
||||
*/
|
||||
static inline void data_lo(void)
|
||||
{
|
||||
IBMPC_DATA_PORT &= ~(1<<IBMPC_DATA_BIT);
|
||||
IBMPC_DATA_DDR |= (1<<IBMPC_DATA_BIT);
|
||||
}
|
||||
|
||||
static inline void data_hi(void)
|
||||
{
|
||||
/* input with pull up */
|
||||
IBMPC_DATA_DDR &= ~(1<<IBMPC_DATA_BIT);
|
||||
IBMPC_DATA_PORT |= (1<<IBMPC_DATA_BIT);
|
||||
}
|
||||
|
||||
static inline bool data_in(void)
|
||||
{
|
||||
IBMPC_DATA_DDR &= ~(1<<IBMPC_DATA_BIT);
|
||||
IBMPC_DATA_PORT |= (1<<IBMPC_DATA_BIT);
|
||||
wait_us(1);
|
||||
return IBMPC_DATA_PIN&(1<<IBMPC_DATA_BIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
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(AT), soft reset(XT) */
|
||||
static inline void inhibit(void)
|
||||
{
|
||||
clock_lo();
|
||||
data_hi();
|
||||
}
|
||||
|
||||
/* inhibit device to send(XT) */
|
||||
static inline void inhibit_xt(void)
|
||||
{
|
||||
clock_hi();
|
||||
data_lo();
|
||||
}
|
||||
#endif
|
||||
275
tmk_core/protocol/ibmpc.hpp
Normal file
275
tmk_core/protocol/ibmpc.hpp
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
Copyright 2010,2011,2012,2013,2019 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 IBMPC_HPP
|
||||
#define IBMPC_HPP
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "wait.h"
|
||||
|
||||
/*
|
||||
* IBM PC keyboard protocol
|
||||
*
|
||||
* 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 IBMPC_ACK 0xFA
|
||||
#define IBMPC_RESEND 0xFE
|
||||
#define IBMPC_SET_LED 0xED
|
||||
|
||||
#define IBMPC_PROTOCOL_NO 0
|
||||
#define IBMPC_PROTOCOL_AT 0x10
|
||||
#define IBMPC_PROTOCOL_AT_Z150 0x11
|
||||
#define IBMPC_PROTOCOL_XT 0x20
|
||||
#define IBMPC_PROTOCOL_XT_IBM 0x21
|
||||
#define IBMPC_PROTOCOL_XT_CLONE 0x22
|
||||
|
||||
// Error numbers
|
||||
#define IBMPC_ERR_NONE 0
|
||||
#define IBMPC_ERR_PARITY 0x01
|
||||
#define IBMPC_ERR_PARITY_AA 0x02
|
||||
#define IBMPC_ERR_SEND 0x10
|
||||
#define IBMPC_ERR_TIMEOUT 0x20
|
||||
#define IBMPC_ERR_FULL 0x40
|
||||
#define IBMPC_ERR_ILLEGAL 0x80
|
||||
|
||||
#define IBMPC_LED_SCROLL_LOCK 0
|
||||
#define IBMPC_LED_NUM_LOCK 1
|
||||
#define IBMPC_LED_CAPS_LOCK 2
|
||||
|
||||
|
||||
class IBMPC
|
||||
{
|
||||
public:
|
||||
static IBMPC interface0;
|
||||
#if defined(IBMPC_CLOCK_BIT1) && defined(IBMPC_DATA_BIT1)
|
||||
static IBMPC interface1;
|
||||
#endif
|
||||
|
||||
volatile uint16_t isr_debug;
|
||||
volatile uint8_t protocol;
|
||||
volatile uint8_t error;
|
||||
|
||||
void host_init(void);
|
||||
void host_enable(void);
|
||||
void host_disable(void);
|
||||
int16_t host_send(uint8_t data);
|
||||
int16_t host_recv_response(void);
|
||||
int16_t host_recv(void);
|
||||
void host_isr_clear(void);
|
||||
void host_set_led(uint8_t led);
|
||||
|
||||
IBMPC(uint8_t clock, uint8_t data) :
|
||||
isr_debug(IBMPC_ERR_NONE), protocol(IBMPC_PROTOCOL_NO), error(IBMPC_ERR_NONE),
|
||||
isr_state(0x8000), timer_start(0), clock_bit(clock), data_bit(data),
|
||||
clock_mask(1 << clock), data_mask(1 << data) {
|
||||
};
|
||||
|
||||
void isr(void);
|
||||
|
||||
|
||||
private:
|
||||
volatile uint16_t isr_state;
|
||||
uint8_t timer_start;
|
||||
|
||||
/* ring buffer */
|
||||
// Size should be power of 2
|
||||
#define RINGBUF_SIZE 16
|
||||
uint8_t rb_head;
|
||||
uint8_t rb_tail;
|
||||
uint8_t rb_buffer[RINGBUF_SIZE];
|
||||
|
||||
const uint8_t clock_bit, data_bit;
|
||||
const uint8_t clock_mask, data_mask;
|
||||
|
||||
|
||||
inline void clock_lo(void) __attribute__((__always_inline__)) // needed for ISR optimization
|
||||
{
|
||||
IBMPC_CLOCK_PORT &= ~clock_mask;
|
||||
IBMPC_CLOCK_DDR |= clock_mask;
|
||||
}
|
||||
|
||||
inline void clock_hi(void)
|
||||
{
|
||||
/* input with pull up */
|
||||
IBMPC_CLOCK_DDR &= ~clock_mask;
|
||||
IBMPC_CLOCK_PORT |= clock_mask;
|
||||
}
|
||||
|
||||
inline bool clock_in(void)
|
||||
{
|
||||
IBMPC_CLOCK_DDR &= ~clock_mask;
|
||||
IBMPC_CLOCK_PORT |= clock_mask;
|
||||
wait_us(1);
|
||||
return IBMPC_CLOCK_PIN & clock_mask;
|
||||
}
|
||||
|
||||
inline void data_lo(void)
|
||||
{
|
||||
IBMPC_DATA_PORT &= ~data_mask;
|
||||
IBMPC_DATA_DDR |= data_mask;
|
||||
}
|
||||
|
||||
inline void data_hi(void)
|
||||
{
|
||||
/* input with pull up */
|
||||
IBMPC_DATA_DDR &= ~data_mask;
|
||||
IBMPC_DATA_PORT |= data_mask;
|
||||
}
|
||||
|
||||
inline bool data_in(void)
|
||||
{
|
||||
IBMPC_DATA_DDR &= ~data_mask;
|
||||
IBMPC_DATA_PORT |= data_mask;
|
||||
wait_us(1);
|
||||
return IBMPC_DATA_PIN & data_mask;
|
||||
}
|
||||
|
||||
inline uint16_t wait_clock_lo(uint16_t us)
|
||||
{
|
||||
while (clock_in() && us) { asm(""); wait_us(1); us--; }
|
||||
return us;
|
||||
}
|
||||
inline uint16_t wait_clock_hi(uint16_t us)
|
||||
{
|
||||
while (!clock_in() && us) { asm(""); wait_us(1); us--; }
|
||||
return us;
|
||||
}
|
||||
inline uint16_t wait_data_lo(uint16_t us)
|
||||
{
|
||||
while (data_in() && us) { asm(""); wait_us(1); us--; }
|
||||
return us;
|
||||
}
|
||||
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 */
|
||||
inline void idle(void)
|
||||
{
|
||||
clock_hi();
|
||||
data_hi();
|
||||
}
|
||||
|
||||
/* inhibit device to send(AT), soft reset(XT) */
|
||||
inline void inhibit(void)
|
||||
{
|
||||
clock_lo();
|
||||
data_hi();
|
||||
}
|
||||
|
||||
/* inhibit device to send(XT) */
|
||||
inline void inhibit_xt(void)
|
||||
{
|
||||
clock_hi();
|
||||
data_lo();
|
||||
}
|
||||
|
||||
void int_init(void)
|
||||
{
|
||||
// interrupt at falling edge
|
||||
if (clock_bit < 4) {
|
||||
EICRA |= (0x2 << ((clock_bit&0x3)*2));
|
||||
} else {
|
||||
EICRB |= (0x2 << ((clock_bit&0x3)*2));
|
||||
}
|
||||
}
|
||||
|
||||
void int_on(void)
|
||||
{
|
||||
EIFR |= clock_mask;
|
||||
EIMSK |= clock_mask;
|
||||
}
|
||||
|
||||
inline void int_off(void) __attribute__((__always_inline__)) // needed for ISR optimization
|
||||
{
|
||||
EIMSK &= ~clock_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* ring buffer
|
||||
*/
|
||||
inline int16_t ringbuf_get(void) __attribute__((__always_inline__))
|
||||
{
|
||||
if (ringbuf_is_empty()) return -1;
|
||||
uint8_t data = rb_buffer[rb_tail];
|
||||
rb_tail++;
|
||||
rb_tail &= (RINGBUF_SIZE - 1);
|
||||
return data;
|
||||
}
|
||||
inline void ringbuf_put(uint8_t data) __attribute__((__always_inline__))
|
||||
{
|
||||
rb_buffer[rb_head] = data;
|
||||
rb_head++;
|
||||
rb_head &= (RINGBUF_SIZE - 1);
|
||||
}
|
||||
inline bool ringbuf_is_empty(void) __attribute__((__always_inline__))
|
||||
{
|
||||
return (rb_head == rb_tail);
|
||||
}
|
||||
inline bool ringbuf_is_full(void) __attribute__((__always_inline__))
|
||||
{
|
||||
return (((rb_head + 1) & (RINGBUF_SIZE - 1)) == rb_tail);
|
||||
}
|
||||
inline void ringbuf_reset(void) __attribute__((__always_inline__))
|
||||
{
|
||||
rb_head = 0;
|
||||
rb_tail = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -4,6 +4,10 @@ TMK_LUFA_DIR = protocol/lufa
|
|||
TMK_LUFA_PATH ?= $(TMK_LUFA_DIR)/lufa-abcminiuser
|
||||
|
||||
|
||||
# Version string
|
||||
TMK_LUFA_VERSION := $(shell (cd $(TMK_DIR)/$(TMK_LUFA_PATH); git rev-parse --short=6 HEAD || echo 'unknown') 2> /dev/null)
|
||||
OPT_DEFS += -DTMK_LUFA_VERSION=$(TMK_LUFA_VERSION)
|
||||
|
||||
# Create the LUFA source path variables by including the LUFA makefile
|
||||
ifneq (, $(wildcard $(TMK_DIR)/$(TMK_LUFA_PATH)/LUFA/Build/LUFA/lufa-sources.mk))
|
||||
LUFA_PATH = $(TMK_LUFA_PATH)/LUFA
|
||||
|
|
@ -47,7 +51,7 @@ TMK_LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_E
|
|||
TMK_LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8
|
||||
TMK_LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1
|
||||
# Remote wakeup fix for ATmega32U2 https://github.com/tmk/tmk_keyboard/issues/361
|
||||
ifeq ($(MCU),atmega32u2)
|
||||
ifeq (atmega32u2,$(strip $(MCU)))
|
||||
TMK_LUFA_OPTS += -DNO_LIMITED_CONTROLLER_CONNECT
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,11 @@
|
|||
/*******************************************************************************
|
||||
* HID Report Descriptors
|
||||
******************************************************************************/
|
||||
#ifndef NO_KEYBOARD
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
||||
{
|
||||
#ifndef NKRO_ENABLE
|
||||
/* 6KRO - Boot protocol */
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
|
|
@ -81,29 +84,65 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
|||
HID_RI_REPORT_SIZE(8, 0x08),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
#else
|
||||
/* NKRO - Report protocol */
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, 0x08),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
|
||||
HID_RI_REPORT_COUNT(8, 0x05),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_REPORT_COUNT(8, 0x01),
|
||||
HID_RI_REPORT_SIZE(8, 0x03),
|
||||
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
|
||||
HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
||||
{
|
||||
#ifdef MOUSE_ENABLE
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x02), /* Mouse */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
HID_RI_USAGE(8, 0x01), /* Pointer */
|
||||
HID_RI_COLLECTION(8, 0x00), /* Physical */
|
||||
|
||||
HID_RI_REPORT_ID(8, REPORT_ID_MOUSE),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x09), /* Button */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Button 5 */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0x08), /* Button 8 */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, 0x05),
|
||||
HID_RI_REPORT_COUNT(8, 0x08),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_RI_REPORT_COUNT(8, 0x01),
|
||||
HID_RI_REPORT_SIZE(8, 0x03),
|
||||
HID_RI_INPUT(8, HID_IOF_CONSTANT),
|
||||
|
||||
#ifndef MOUSE_EXT_REPORT
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x30), /* Usage X */
|
||||
HID_RI_USAGE(8, 0x31), /* Usage Y */
|
||||
|
|
@ -112,6 +151,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
|||
HID_RI_REPORT_COUNT(8, 0x02),
|
||||
HID_RI_REPORT_SIZE(8, 0x08),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
|
||||
#else
|
||||
/* Boot protocol XY ignored in Report protocol */
|
||||
HID_RI_USAGE_PAGE(8, 0xff), /* Vendor */
|
||||
HID_RI_USAGE(8, 0xff), /* Vendor */
|
||||
HID_RI_LOGICAL_MINIMUM(8, -127),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 127),
|
||||
HID_RI_REPORT_COUNT(8, 0x02),
|
||||
HID_RI_REPORT_SIZE(8, 0x08),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x30), /* Usage X */
|
||||
HID_RI_USAGE(8, 0x31), /* Usage Y */
|
||||
HID_RI_LOGICAL_MINIMUM(16, -32767),
|
||||
HID_RI_LOGICAL_MAXIMUM(16, 32767),
|
||||
HID_RI_REPORT_COUNT(8, 0x02),
|
||||
HID_RI_REPORT_SIZE(8, 16),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
|
||||
#endif
|
||||
|
||||
HID_RI_USAGE(8, 0x38), /* Wheel */
|
||||
HID_RI_LOGICAL_MINIMUM(8, -127),
|
||||
|
|
@ -130,12 +188,9 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
|||
|
||||
HID_RI_END_COLLECTION(0),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
|
||||
{
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x80), /* System Control */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
|
|
@ -161,6 +216,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
|
|||
HID_RI_REPORT_COUNT(8, 1),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
@ -186,7 +242,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
|
||||
{
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
|
|
@ -272,6 +328,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
/*
|
||||
* Keyboard
|
||||
*/
|
||||
#ifndef NO_KEYBOARD
|
||||
.Keyboard_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
|
@ -305,14 +362,20 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
#ifdef NKRO_ENABLE
|
||||
.EndpointSize = NKRO_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
#else
|
||||
.EndpointSize = KEYBOARD_EPSIZE,
|
||||
.PollingIntervalMS = 0x0A
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Mouse
|
||||
*/
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
.Mouse_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
|
@ -323,8 +386,13 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
#if defined(MOUSE_ENABLE)
|
||||
.SubClass = HID_CSCP_BootSubclass,
|
||||
.Protocol = HID_CSCP_MouseBootProtocol,
|
||||
#else
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
#endif
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
|
@ -347,49 +415,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = MOUSE_EPSIZE,
|
||||
.PollingIntervalMS = 0x0A
|
||||
},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Extra
|
||||
*/
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
.Extrakey_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = EXTRAKEY_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.Extrakey_HID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
.HIDSpec = VERSION_BCD(1,1,1),
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(ExtrakeyReport)
|
||||
},
|
||||
|
||||
.Extrakey_INEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = EXTRAKEY_EPSIZE,
|
||||
.PollingIntervalMS = 0x0A
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
#endif
|
||||
|
||||
|
|
@ -404,7 +430,8 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.InterfaceNumber = CONSOLE_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 2,
|
||||
//.TotalEndpoints = 2,
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
|
|
@ -434,6 +461,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
|
||||
/*
|
||||
.Console_OUTEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
|
@ -443,12 +471,13 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.EndpointSize = CONSOLE_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NKRO
|
||||
*/
|
||||
#ifdef NKRO_ENABLE
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
.NKRO_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
|
@ -561,29 +590,25 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
|||
break;
|
||||
case HID_DTYPE_HID:
|
||||
switch (wIndex) {
|
||||
#ifndef NO_KEYBOARD
|
||||
case KEYBOARD_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Keyboard_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
case MOUSE_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Mouse_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Extrakey_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONSOLE_ENABLE
|
||||
case CONSOLE_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Console_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
#ifdef NKRO_ENABLE
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
case NKRO_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.NKRO_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
|
|
@ -593,29 +618,25 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
|||
break;
|
||||
case HID_DTYPE_Report:
|
||||
switch (wIndex) {
|
||||
#ifndef NO_KEYBOARD
|
||||
case KEYBOARD_INTERFACE:
|
||||
Address = &KeyboardReport;
|
||||
Size = sizeof(KeyboardReport);
|
||||
break;
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
case MOUSE_INTERFACE:
|
||||
Address = &MouseReport;
|
||||
Size = sizeof(MouseReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
Address = &ExtrakeyReport;
|
||||
Size = sizeof(ExtrakeyReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONSOLE_ENABLE
|
||||
case CONSOLE_INTERFACE:
|
||||
Address = &ConsoleReport;
|
||||
Size = sizeof(ConsoleReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef NKRO_ENABLE
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
case NKRO_INTERFACE:
|
||||
Address = &NKROReport;
|
||||
Size = sizeof(NKROReport);
|
||||
|
|
|
|||
|
|
@ -52,34 +52,29 @@ typedef struct
|
|||
{
|
||||
USB_Descriptor_Configuration_Header_t Config;
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
// Keyboard HID Interface
|
||||
USB_Descriptor_Interface_t Keyboard_Interface;
|
||||
USB_HID_Descriptor_HID_t Keyboard_HID;
|
||||
USB_Descriptor_Endpoint_t Keyboard_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
// Mouse HID Interface
|
||||
USB_Descriptor_Interface_t Mouse_Interface;
|
||||
USB_HID_Descriptor_HID_t Mouse_HID;
|
||||
USB_Descriptor_Endpoint_t Mouse_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
// Extrakey HID Interface
|
||||
USB_Descriptor_Interface_t Extrakey_Interface;
|
||||
USB_HID_Descriptor_HID_t Extrakey_HID;
|
||||
USB_Descriptor_Endpoint_t Extrakey_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
// Console HID Interface
|
||||
USB_Descriptor_Interface_t Console_Interface;
|
||||
USB_HID_Descriptor_HID_t Console_HID;
|
||||
USB_Descriptor_Endpoint_t Console_INEndpoint;
|
||||
USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
||||
// USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
// NKRO HID Interface
|
||||
USB_Descriptor_Interface_t NKRO_Interface;
|
||||
USB_HID_Descriptor_HID_t NKRO_HID;
|
||||
|
|
@ -89,27 +84,25 @@ typedef struct
|
|||
|
||||
|
||||
/* index of interface */
|
||||
#define KEYBOARD_INTERFACE 0
|
||||
#ifndef NO_KEYBOARD
|
||||
# define KEYBOARD_INTERFACE 0
|
||||
#else
|
||||
# define KEYBOARD_INTERFACE -1
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
# define MOUSE_INTERFACE (KEYBOARD_INTERFACE + 1)
|
||||
#else
|
||||
# define MOUSE_INTERFACE KEYBOARD_INTERFACE
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
# define EXTRAKEY_INTERFACE (MOUSE_INTERFACE + 1)
|
||||
#else
|
||||
# define EXTRAKEY_INTERFACE MOUSE_INTERFACE
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
# define CONSOLE_INTERFACE (EXTRAKEY_INTERFACE + 1)
|
||||
# define CONSOLE_INTERFACE (MOUSE_INTERFACE + 1)
|
||||
#else
|
||||
# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
|
||||
# define CONSOLE_INTERFACE MOUSE_INTERFACE
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
|
||||
#else
|
||||
# define NKRO_INTERFACE CONSOLE_INTERFACE
|
||||
|
|
@ -121,28 +114,32 @@ typedef struct
|
|||
|
||||
|
||||
// Endopoint number and size
|
||||
#define KEYBOARD_IN_EPNUM 1
|
||||
#ifndef NO_KEYBOARD
|
||||
# define KEYBOARD_IN_EPNUM 1
|
||||
#else
|
||||
# define KEYBOARD_IN_EPNUM 0
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
# define MOUSE_IN_EPNUM (KEYBOARD_IN_EPNUM + 1)
|
||||
#else
|
||||
# define MOUSE_IN_EPNUM KEYBOARD_IN_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
# define EXTRAKEY_IN_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
#else
|
||||
# define EXTRAKEY_IN_EPNUM MOUSE_IN_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
# define CONSOLE_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
|
||||
# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 1)
|
||||
// ATMega32U2 doesn't support double bank on endpoint 1 and 2, use 3 or 4
|
||||
# if MOUSE_IN_EPNUM < 2
|
||||
# define CONSOLE_IN_EPNUM 3
|
||||
# define CONSOLE_OUT_EPNUM 3
|
||||
# else
|
||||
# define CONSOLE_IN_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
# define CONSOLE_OUT_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
# endif
|
||||
#else
|
||||
# define CONSOLE_OUT_EPNUM EXTRAKEY_IN_EPNUM
|
||||
# define CONSOLE_OUT_EPNUM MOUSE_IN_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
|
||||
#else
|
||||
# define NKRO_IN_EPNUM CONSOLE_OUT_EPNUM
|
||||
|
|
@ -150,13 +147,18 @@ typedef struct
|
|||
|
||||
/* Check number of endpoints. ATmega32u2 has only four except for control endpoint. */
|
||||
#if defined(__AVR_ATmega32U2__) && NKRO_IN_EPNUM > 4
|
||||
# error "Endpoints are not available enough to support all functions. Disable some of build options in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO)"
|
||||
# error "Endpoints are not available enough to support all functions. Disable some of build options in Makefile.(MOUSEKEY, CONSOLE, NKRO)"
|
||||
#endif
|
||||
|
||||
|
||||
#define KEYBOARD_EPSIZE 8
|
||||
|
||||
#if defined(MOUSE_EXT_REPORT)
|
||||
#define MOUSE_EPSIZE 10
|
||||
#else
|
||||
#define MOUSE_EPSIZE 8
|
||||
#define EXTRAKEY_EPSIZE 8
|
||||
#endif
|
||||
|
||||
#define CONSOLE_EPSIZE 32
|
||||
#define NKRO_EPSIZE 32
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "host_driver.h"
|
||||
#include "keyboard.h"
|
||||
#include "action.h"
|
||||
#include "action_util.h"
|
||||
#include "led.h"
|
||||
#include "sendchar.h"
|
||||
#include "ringbuf.h"
|
||||
|
|
@ -68,26 +69,35 @@
|
|||
//#define TMK_LUFA_DEBUG
|
||||
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
uint8_t keyboard_idle = 0;
|
||||
/* 0: Boot Protocol, 1: Report Protocol(default) */
|
||||
uint8_t keyboard_protocol = 1;
|
||||
static uint8_t keyboard_led_stats = 0;
|
||||
static report_keyboard_t keyboard_report_sent = (report_keyboard_t){};
|
||||
#endif
|
||||
|
||||
static report_keyboard_t keyboard_report_sent;
|
||||
#ifdef MOUSE_ENABLE
|
||||
uint8_t mouse_protocol = 1;
|
||||
#endif
|
||||
|
||||
|
||||
/* Host driver */
|
||||
#ifndef NO_KEYBOARD
|
||||
static uint8_t keyboard_leds(void);
|
||||
static void send_keyboard(report_keyboard_t *report);
|
||||
#endif
|
||||
static void send_mouse(report_mouse_t *report);
|
||||
static void send_system(uint16_t data);
|
||||
static void send_consumer(uint16_t data);
|
||||
host_driver_t lufa_driver = {
|
||||
keyboard_leds,
|
||||
send_keyboard,
|
||||
send_mouse,
|
||||
send_system,
|
||||
send_consumer
|
||||
#ifndef NO_KEYBOARD
|
||||
.keyboard_leds = keyboard_leds,
|
||||
.send_keyboard = send_keyboard,
|
||||
#endif
|
||||
.send_mouse = send_mouse,
|
||||
.send_system = send_system,
|
||||
.send_consumer = send_consumer
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -95,7 +105,11 @@ host_driver_t lufa_driver = {
|
|||
* Console
|
||||
******************************************************************************/
|
||||
#ifdef CONSOLE_ENABLE
|
||||
#define SENDBUF_SIZE 256
|
||||
# ifdef _AVR_ATmega32U2_H_
|
||||
# define SENDBUF_SIZE 128
|
||||
# else
|
||||
# define SENDBUF_SIZE 256
|
||||
# endif
|
||||
static uint8_t sbuf[SENDBUF_SIZE];
|
||||
static ringbuf_t sendbuf = {
|
||||
.buffer = sbuf,
|
||||
|
|
@ -296,6 +310,19 @@ void EVENT_USB_Device_Reset(void)
|
|||
#ifdef TMK_LUFA_DEBUG
|
||||
print("[R]");
|
||||
#endif
|
||||
|
||||
// reset to initial state: protocol to Report(default)
|
||||
#ifndef NO_KEYBOARD
|
||||
keyboard_protocol = 1;
|
||||
keyboard_idle = 0;
|
||||
keyboard_led_stats = 0;
|
||||
keyboard_report_sent = (report_keyboard_t){};
|
||||
// keyboard_report keys/bits part is not compatible between Boot and Report protocol
|
||||
clear_keys();
|
||||
#endif
|
||||
#ifdef MOUSE_ENABLE
|
||||
mouse_protocol = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void EVENT_USB_Device_Suspend()
|
||||
|
|
@ -327,33 +354,35 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
|||
#endif
|
||||
bool ConfigSuccess = true;
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
/* Setup Keyboard HID Report Endpoints */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#ifdef NKRO_ENABLE
|
||||
NKRO_EPSIZE,
|
||||
#else
|
||||
KEYBOARD_EPSIZE,
|
||||
#endif
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
|
||||
/* Setup Mouse HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
/* Setup Extra HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
// ATMega32U2 doesn't support double bank on endpoint 1 and 2, use 3 or 4
|
||||
/* Setup Console HID Report Endpoints */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
|
||||
#if 0
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
|
||||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
#ifdef NKRO_6KRO_ENABLE
|
||||
/* Setup NKRO HID Report Endpoints */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
|
|
@ -378,15 +407,16 @@ Other Device Required Optional Optional Optional Optional Opti
|
|||
*/
|
||||
void EVENT_USB_Device_ControlRequest(void)
|
||||
{
|
||||
uint8_t* ReportData = NULL;
|
||||
uint8_t ReportSize = 0;
|
||||
|
||||
/* Handle HID Class specific requests */
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case HID_REQ_GetReport:
|
||||
#ifndef NO_KEYBOARD
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
uint8_t* ReportData = NULL;
|
||||
uint8_t ReportSize = 0;
|
||||
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
// Interface
|
||||
|
|
@ -405,6 +435,7 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
xprintf("[r%d]", USB_ControlRequest.wIndex);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
case HID_REQ_SetReport:
|
||||
|
|
@ -413,8 +444,9 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
|
||||
// Interface
|
||||
switch (USB_ControlRequest.wIndex) {
|
||||
#ifndef NO_KEYBOARD
|
||||
case KEYBOARD_INTERFACE:
|
||||
#ifdef NKRO_ENABLE
|
||||
#ifdef NKRO_6KRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
#endif
|
||||
Endpoint_ClearSETUP();
|
||||
|
|
@ -428,9 +460,10 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
Endpoint_ClearOUT();
|
||||
Endpoint_ClearStatusStage();
|
||||
#ifdef TMK_LUFA_DEBUG
|
||||
xprintf("[L%d]", USB_ControlRequest.wIndex);
|
||||
xprintf("[L%d %02X]", USB_ControlRequest.wIndex, keyboard_led_stats);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -440,6 +473,7 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
case HID_REQ_GetProtocol:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
#ifndef NO_KEYBOARD
|
||||
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
|
||||
Endpoint_ClearSETUP();
|
||||
while (!(Endpoint_IsINReady()));
|
||||
|
|
@ -450,34 +484,58 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
print("[p]");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE)
|
||||
if (USB_ControlRequest.wIndex == MOUSE_INTERFACE) {
|
||||
Endpoint_ClearSETUP();
|
||||
while (!(Endpoint_IsINReady()));
|
||||
Endpoint_Write_8(mouse_protocol);
|
||||
Endpoint_ClearIN();
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
case HID_REQ_SetProtocol:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
#ifndef NO_KEYBOARD
|
||||
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
|
||||
Endpoint_ClearSETUP();
|
||||
Endpoint_ClearStatusStage();
|
||||
|
||||
keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
|
||||
clear_keyboard();
|
||||
#ifdef TMK_LUFA_DEBUG
|
||||
print("[P]");
|
||||
xprintf("[P%d %04X]", USB_ControlRequest.wIndex, USB_ControlRequest.wValue);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE)
|
||||
if (USB_ControlRequest.wIndex == MOUSE_INTERFACE) {
|
||||
Endpoint_ClearSETUP();
|
||||
Endpoint_ClearStatusStage();
|
||||
|
||||
mouse_protocol = (USB_ControlRequest.wValue & 0xFF);
|
||||
#ifdef TMK_LUFA_DEBUG
|
||||
xprintf("[P%d %04X]", USB_ControlRequest.wIndex, USB_ControlRequest.wValue);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
case HID_REQ_SetIdle:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
#ifndef NO_KEYBOARD
|
||||
Endpoint_ClearSETUP();
|
||||
Endpoint_ClearStatusStage();
|
||||
|
||||
keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
|
||||
#ifdef TMK_LUFA_DEBUG
|
||||
xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8);
|
||||
xprintf("[I%d %04X]", USB_ControlRequest.wIndex, USB_ControlRequest.wValue);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -485,6 +543,7 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
case HID_REQ_GetIdle:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
#ifndef NO_KEYBOARD
|
||||
Endpoint_ClearSETUP();
|
||||
while (!(Endpoint_IsINReady()));
|
||||
Endpoint_Write_8(keyboard_idle);
|
||||
|
|
@ -492,6 +551,7 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
Endpoint_ClearStatusStage();
|
||||
#ifdef TMK_LUFA_DEBUG
|
||||
print("[i]");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -502,6 +562,7 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
/*******************************************************************************
|
||||
* Host driver
|
||||
******************************************************************************/
|
||||
#ifndef NO_KEYBOARD
|
||||
static uint8_t keyboard_leds(void)
|
||||
{
|
||||
return keyboard_led_stats;
|
||||
|
|
@ -515,10 +576,14 @@ static void send_keyboard(report_keyboard_t *report)
|
|||
return;
|
||||
|
||||
/* Select the Keyboard Report Endpoint */
|
||||
#ifdef NKRO_ENABLE
|
||||
#if defined(NKRO_ENABLE) || defined(NKRO_6KRO_ENABLE)
|
||||
if (keyboard_protocol && keyboard_nkro) {
|
||||
/* Report protocol - NKRO */
|
||||
#if defined(NKRO_6KRO_ENABLE)
|
||||
Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
|
||||
#else
|
||||
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
|
||||
#endif
|
||||
|
||||
/* Check if write ready for a polling interval around 1ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(8);
|
||||
|
|
@ -546,6 +611,7 @@ static void send_keyboard(report_keyboard_t *report)
|
|||
|
||||
keyboard_report_sent = *report;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void send_mouse(report_mouse_t *report)
|
||||
{
|
||||
|
|
@ -563,7 +629,14 @@ static void send_mouse(report_mouse_t *report)
|
|||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Write Mouse Report Data */
|
||||
Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
|
||||
if (mouse_protocol) {
|
||||
// Report
|
||||
Endpoint_Write_8(REPORT_ID_MOUSE);
|
||||
Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
|
||||
} else {
|
||||
// Boot
|
||||
Endpoint_Write_Stream_LE(report, 3, NULL);
|
||||
}
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
Endpoint_ClearIN();
|
||||
|
|
@ -578,11 +651,19 @@ static void send_system(uint16_t data)
|
|||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
report_extra_t r = {
|
||||
.report_id = REPORT_ID_SYSTEM,
|
||||
.usage = data - SYSTEM_POWER_DOWN + 1
|
||||
};
|
||||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
|
||||
#ifdef MOUSE_ENABLE
|
||||
// Not send while mouse is set to Boot Protocol
|
||||
if (mouse_protocol == 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
report_extra_t r = { .report_id = REPORT_ID_SYSTEM };
|
||||
if (data < SYSTEM_POWER_DOWN) {
|
||||
r.usage = 0;
|
||||
} else {
|
||||
r.usage = data - SYSTEM_POWER_DOWN + 1;
|
||||
}
|
||||
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
|
|
@ -601,11 +682,17 @@ static void send_consumer(uint16_t data)
|
|||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
// Not send while mouse is set to Boot Protocol
|
||||
if (mouse_protocol == 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
report_extra_t r = {
|
||||
.report_id = REPORT_ID_CONSUMER,
|
||||
.usage = data
|
||||
};
|
||||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
|
||||
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
|
|
@ -677,21 +764,40 @@ int main(void)
|
|||
print_set_sendchar(sendchar);
|
||||
host_set_driver(&lufa_driver);
|
||||
|
||||
print("\n\nTMK:" STR(TMK_VERSION) "/LUFA\n\n");
|
||||
print("\nTMK:" STR(TMK_VERSION) "/LUFA:" STR(TMK_LUFA_VERSION)
|
||||
#ifdef TMK_USB_HOST_SHIELD_VERSION
|
||||
"/UHS2:" STR(TMK_USB_HOST_SHIELD_VERSION)
|
||||
#endif
|
||||
"\n");
|
||||
|
||||
hook_early_init();
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
keyboard_setup();
|
||||
#endif
|
||||
|
||||
setup_usb();
|
||||
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_init();
|
||||
#endif
|
||||
|
||||
sei();
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
keyboard_init();
|
||||
#else
|
||||
// TODO: keyboard_init() should be used only for things related to keyboard
|
||||
timer_init();
|
||||
#endif
|
||||
|
||||
#ifndef NO_USB_STARTUP_WAIT_LOOP
|
||||
/* wait for USB startup */
|
||||
while (USB_DeviceState != DEVICE_STATE_Configured) {
|
||||
while (USB_DeviceState != DEVICE_STATE_Configured
|
||||
#ifdef CONSOLE_ENABLE
|
||||
|| !console_is_ready()
|
||||
#endif
|
||||
) {
|
||||
#if defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
;
|
||||
#else
|
||||
|
|
@ -704,7 +810,7 @@ int main(void)
|
|||
|
||||
hook_late_init();
|
||||
|
||||
print("\nKeyboard start.\n");
|
||||
print("\nLoop start.\n");
|
||||
while (1) {
|
||||
#ifndef NO_USB_SUSPEND_LOOP
|
||||
while (USB_DeviceState == DEVICE_STATE_Suspended) {
|
||||
|
|
@ -712,7 +818,11 @@ int main(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
hook_main_loop();
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
keyboard_task();
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
console_task();
|
||||
|
|
@ -732,10 +842,13 @@ void hook_early_init(void) {}
|
|||
__attribute__((weak))
|
||||
void hook_late_init(void) {}
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
static uint8_t _led_stats = 0;
|
||||
#endif
|
||||
__attribute__((weak))
|
||||
void hook_usb_suspend_entry(void)
|
||||
{
|
||||
#ifndef NO_KEYBOARD
|
||||
// Turn off LED to save power and keep its status to resotre it later.
|
||||
// LED status will be updated by keyboard_task() in main loop hopefully.
|
||||
_led_stats = keyboard_led_stats;
|
||||
|
|
@ -745,6 +858,7 @@ void hook_usb_suspend_entry(void)
|
|||
|
||||
matrix_clear();
|
||||
clear_keyboard();
|
||||
#endif
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_enable();
|
||||
#endif
|
||||
|
|
@ -770,8 +884,10 @@ void hook_usb_wakeup(void)
|
|||
sleep_led_disable();
|
||||
#endif
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
// Restore LED status and update at keyboard_task() in main loop
|
||||
keyboard_led_stats = _led_stats;
|
||||
#endif
|
||||
|
||||
// Calling long task here can prevent USB state transition
|
||||
}
|
||||
|
|
|
|||
|
|
@ -494,10 +494,19 @@ RAW CODE:
|
|||
* 0x71, 0x79,DD / 0xF1, 0x79, 0xUU
|
||||
|
||||
|
||||
MODEL NUMBER:
|
||||
M0110: 0x09 00001001 : model number 4 (100)
|
||||
M0110A: 0x0B 00001011 : model number 5 (101)
|
||||
M0110 & M0120: ???
|
||||
MODEL CODE:
|
||||
Model Code Layout Made in Desc
|
||||
---------------------------------------------------------------------
|
||||
M0110(GS536) 0x03 US USA
|
||||
M0110(GS624) 0x09 US USA
|
||||
M0110F 0x03 French Ireland https://github.com/tmk/tmk_keyboard/issues/771
|
||||
M0110A(M923) 0x0B US
|
||||
M0110AJ(M839) 0x0B US
|
||||
M0110AJ(A615) 0x0B US
|
||||
M0120(BCG9GRM0120) 0x11
|
||||
M0120 & M0110(G536) 0x13
|
||||
M0120 & M0110(G624) 0x19
|
||||
M0120 & M0110A(M923) 0x1B
|
||||
|
||||
|
||||
Scan Code
|
||||
|
|
@ -572,8 +581,8 @@ Scan Code
|
|||
References
|
||||
----------
|
||||
Technical Info for 128K/512K and Plus
|
||||
ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf
|
||||
ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf
|
||||
https://www.apple.asimov.net/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf
|
||||
https://www.apple.asimov.net/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf
|
||||
Protocol:
|
||||
Page 20 of Tech Info for 128K/512K
|
||||
http://www.mac.linux-m68k.org/devel/plushw.php
|
||||
|
|
|
|||
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "news.h"
|
||||
|
||||
|
||||
void news_init(void)
|
||||
{
|
||||
NEWS_KBD_RX_INIT();
|
||||
}
|
||||
|
||||
// RX ring buffer
|
||||
#define RBUF_SIZE 8
|
||||
static uint8_t rbuf[RBUF_SIZE];
|
||||
static uint8_t rbuf_head = 0;
|
||||
static uint8_t rbuf_tail = 0;
|
||||
|
||||
uint8_t news_recv(void)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
if (rbuf_head == rbuf_tail) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = rbuf[rbuf_tail];
|
||||
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
|
||||
return data;
|
||||
}
|
||||
|
||||
// USART RX complete interrupt
|
||||
ISR(NEWS_KBD_RX_VECT)
|
||||
{
|
||||
uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
|
||||
if (next != rbuf_tail) {
|
||||
rbuf[rbuf_head] = NEWS_KBD_RX_DATA;
|
||||
rbuf_head = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SONY NEWS Keyboard Protocol
|
||||
===========================
|
||||
|
||||
Resources
|
||||
---------
|
||||
Mouse protocol of NWA-5461(Japanese)
|
||||
http://groups.google.com/group/fj.sys.news/browse_thread/thread/a01b3e3ac6ae5b2d
|
||||
|
||||
SONY NEWS Info(Japanese)
|
||||
http://katsu.watanabe.name/doc/sonynews/
|
||||
|
||||
|
||||
Pinouts
|
||||
-------
|
||||
EIA 232 male connector from NWP-5461
|
||||
-------------
|
||||
\ 1 2 3 4 5 /
|
||||
\ 6 7 8 9 /
|
||||
---------
|
||||
1 VCC
|
||||
2 BZ(Speaker)
|
||||
3 Keyboard Data(from keyboard MCU TxD)
|
||||
4 NC
|
||||
5 GND
|
||||
6 Unknown Input(to keyboard MCU RxD via schmitt trigger)
|
||||
7 Mouse Data(from Mouse Ext connector)
|
||||
8 Unknown Input(to Keyboard MCU Input via diode and buffer)
|
||||
9 FG
|
||||
NOTE: Two LED on keyboard are controlled by pin 6,8?
|
||||
|
||||
EIA 232 male connector from NWP-411A
|
||||
-------------
|
||||
\ 1 2 3 4 5 /
|
||||
\ 6 7 8 9 /
|
||||
---------
|
||||
1 VCC
|
||||
2 BZ(Speaker)
|
||||
3 Keyboard Data(from keyboard MCU TxD)
|
||||
4 NC
|
||||
5 GND
|
||||
6 NC
|
||||
7 Mouse Data(from Mouse Ext connector)
|
||||
8 NC
|
||||
9 FG
|
||||
NOTE: These are just from my guess and not confirmed.
|
||||
|
||||
|
||||
Signaling
|
||||
---------
|
||||
~~~~~~~~~~ ____XOO0X111X222X333X444X555X666X777~~~~ ~~~~~~~
|
||||
Idle Start LSB MSB Stop Idle
|
||||
|
||||
Idle: High
|
||||
Start bit: Low
|
||||
Stop bit: High
|
||||
Bit order: LSB first
|
||||
|
||||
Baud rate: 9600
|
||||
Interface: TTL level(5V) UART
|
||||
|
||||
NOTE: This is observed on NWP-5461 with its DIP switch all OFF.
|
||||
|
||||
|
||||
Format
|
||||
------
|
||||
MSB LSB
|
||||
7 6 5 4 3 2 1 0 bit
|
||||
| | | | | | | |
|
||||
| +-+-+-+-+-+-+-- scan code(00-7F)
|
||||
+---------------- break flag: sets when released
|
||||
|
||||
|
||||
Scan Codes
|
||||
----------
|
||||
SONY NEWS NWP-5461
|
||||
,---. ,------------------------, ,------------------------. ,---------.
|
||||
| 7A| | 01 | 02 | 03 | 04 | 05 | | 06 | 07 | 08 | 09 | 0A | | 68 | 69 | ,-----------.
|
||||
`---' `------------------------' `------------------------' `---------' | 64| 65| 52|
|
||||
,-------------------------------------------------------------. ,---. ,---------------|
|
||||
| 0B| 0C| 0D| 0E| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19 | | 6A| | 4B| 4C| 4D| 4E|
|
||||
|-------------------------------------------------------------| |---| |---------------|
|
||||
| 1A | 1B| 1C| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| | | 6B| | 4F| 50| 51| 56|
|
||||
|---------------------------------------------------------' | |---| |---------------|
|
||||
| 28 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35 | | 6C| | 53| 54| 55| |
|
||||
|-------------------------------------------------------------| |---| |-----------| 5A|
|
||||
| 36 | 37| 38| 39| 3A| 3B| 3C| 3D| 3E| 3F| 40| 41| 42 | | 6D| | 57| 59| 58| |
|
||||
|-------------------------------------------------------------| |---| |---------------|
|
||||
| 43 | 44 | 45 | 46 | 47 | 48| 49| 4A | | 6E| | 66| 5B| 5C| 5D|
|
||||
`-------------------------------------------------------------' `---' `---------------'
|
||||
*/
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
Copyright 2012 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 NEWS_H
|
||||
#define NEWS_H
|
||||
/*
|
||||
* Primitive PS/2 Library for AVR
|
||||
*/
|
||||
|
||||
|
||||
/* host role */
|
||||
void news_init(void);
|
||||
uint8_t news_recv(void);
|
||||
|
||||
/* device role */
|
||||
|
||||
#endif
|
||||
|
|
@ -59,16 +59,10 @@ static inline void query(void);
|
|||
static inline void reset(void);
|
||||
static inline uint32_t response(void);
|
||||
|
||||
/* The keyboard sends signal with 50us pulse width on OUT line
|
||||
* while it seems to miss the 50us pulse on In line.
|
||||
* next_kbd_set_leds() often fails to sync LED status with 50us
|
||||
* but it works well with 51us(+1us) on TMK converter(ATMeaga32u2) at least.
|
||||
* TODO: test on Teensy and Pro Micro configuration
|
||||
*/
|
||||
#define out_hi_delay(intervals) do { out_hi(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
|
||||
#define out_lo_delay(intervals) do { out_lo(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
|
||||
#define query_delay(intervals) do { query(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
|
||||
#define reset_delay(intervals) do { reset(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
|
||||
#define out_hi_delay(intervals) do { out_hi(); _delay_us((NEXT_KBD_TIMING) * intervals); } while (0);
|
||||
#define out_lo_delay(intervals) do { out_lo(); _delay_us((NEXT_KBD_TIMING) * intervals); } while (0);
|
||||
#define query_delay(intervals) do { query(); _delay_us((NEXT_KBD_TIMING) * intervals); } while (0);
|
||||
#define reset_delay(intervals) do { reset(); _delay_us((NEXT_KBD_TIMING) * intervals); } while (0);
|
||||
|
||||
void next_kbd_init(void)
|
||||
{
|
||||
|
|
@ -144,34 +138,14 @@ static inline uint32_t response(void)
|
|||
sei();
|
||||
return 0;
|
||||
}
|
||||
_delay_us(NEXT_KBD_TIMING / 2);
|
||||
_delay_us(NEXT_KBD_TIMING / 2 - 1);
|
||||
for (; i < 22; i++)
|
||||
{
|
||||
if (NEXT_KBD_READ)
|
||||
{
|
||||
data |= ((uint32_t) 1 << i);
|
||||
/* Note:
|
||||
* My testing with the ATmega32u4 showed that there might
|
||||
* something wrong with the timing here; by the end of the
|
||||
* second data byte some of the modifiers can get bumped out
|
||||
* to the next bit over if we just cycle through the data
|
||||
* based on the expected interval. There is a bit (i = 10)
|
||||
* in the middle of the data that is always on followed by
|
||||
* one that is always off - so we'll use that to reset our
|
||||
* timing in case we've gotten ahead of the keyboard;
|
||||
*/
|
||||
if (i == 10)
|
||||
{
|
||||
i++;
|
||||
while (NEXT_KBD_READ) ;
|
||||
_delay_us(NEXT_KBD_TIMING / 2);
|
||||
}
|
||||
} else {
|
||||
/* redundant - but I don't want to remove if it might screw
|
||||
* up the timing
|
||||
*/
|
||||
data |= ((uint32_t) 0 << i);
|
||||
data |= (uint32_t)1 << 22;
|
||||
}
|
||||
data >>= 1;
|
||||
_delay_us(NEXT_KBD_TIMING);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define NEXT_KBD_H
|
||||
|
||||
#define NEXT_KBD_KMBUS_IDLE 0x300600
|
||||
#define NEXT_KBD_TIMING 50
|
||||
|
||||
// https://github.com/tmk/tmk_keyboard/issues/704
|
||||
#define NEXT_KBD_TIMING 52
|
||||
|
||||
extern uint8_t next_kbd_error;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
static report_mouse_t mouse_report = {};
|
||||
static uint8_t last_buttons;
|
||||
|
||||
|
||||
static void print_usb_data(void);
|
||||
|
|
@ -161,6 +162,7 @@ void ps2_mouse_task(void)
|
|||
|
||||
|
||||
host_mouse_send(&mouse_report);
|
||||
last_buttons = mouse_report.buttons;
|
||||
print_usb_data();
|
||||
}
|
||||
// clear report
|
||||
|
|
@ -171,6 +173,11 @@ void ps2_mouse_task(void)
|
|||
mouse_report.buttons = 0;
|
||||
}
|
||||
|
||||
uint8_t ps2_mouse_buttons(void)
|
||||
{
|
||||
return last_buttons;
|
||||
}
|
||||
|
||||
static void print_usb_data(void)
|
||||
{
|
||||
if (!debug_mouse) return;
|
||||
|
|
|
|||
|
|
@ -62,5 +62,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
uint8_t ps2_mouse_init(void);
|
||||
void ps2_mouse_task(void);
|
||||
uint8_t ps2_mouse_buttons(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,5 +29,6 @@ static inline uint8_t serial_mouse_init(void)
|
|||
}
|
||||
|
||||
void serial_mouse_task(void);
|
||||
uint8_t serial_mouse_buttons(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#endif
|
||||
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
|
||||
|
||||
static uint8_t last_buttons;
|
||||
static void print_usb_data(const report_mouse_t *report);
|
||||
|
||||
void serial_mouse_task(void)
|
||||
|
|
@ -71,6 +72,7 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +113,12 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
}
|
||||
|
||||
uint8_t serial_mouse_buttons(void)
|
||||
{
|
||||
return last_buttons;
|
||||
}
|
||||
|
||||
static void print_usb_data(const report_mouse_t *report)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
//#define SERIAL_MOUSE_CENTER_SCROLL
|
||||
|
||||
static uint8_t last_buttons;
|
||||
static void print_usb_data(const report_mouse_t *report);
|
||||
|
||||
void serial_mouse_task(void)
|
||||
|
|
@ -78,6 +79,7 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
|
||||
if (buffer[3] || buffer[4]) {
|
||||
report.h = MAX((int8_t)buffer[3], -127);
|
||||
|
|
@ -85,6 +87,7 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -117,9 +120,15 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t serial_mouse_buttons(void)
|
||||
{
|
||||
return last_buttons;
|
||||
}
|
||||
|
||||
static void print_usb_data(const report_mouse_t *report)
|
||||
{
|
||||
if (!debug_mouse)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
* TODO: delay is not accurate enough. Instruction cycle should be counted and inline assemby is needed.
|
||||
*/
|
||||
|
||||
#define WAIT_US (1000000L/SERIAL_SOFT_BAUD)
|
||||
#define WAIT_US (1000000L/SERIAL_SOFT_BAUD - 1)
|
||||
|
||||
#ifdef SERIAL_SOFT_LOGIC_NEGATIVE
|
||||
#define SERIAL_SOFT_RXD_IN() !(SERIAL_SOFT_RXD_READ())
|
||||
|
|
@ -68,11 +68,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
/* debug for signal timing, see debug pin with oscilloscope */
|
||||
#ifdef SERIAL_SOFT_DEBUG
|
||||
#define SERIAL_SOFT_DEBUG_INIT() (DDRD |= 1<<7)
|
||||
#define SERIAL_SOFT_DEBUG_TGL() (PORTD ^= 1<<7)
|
||||
#else
|
||||
#ifndef SERIAL_SOFT_DEBUG_INIT
|
||||
#define SERIAL_SOFT_DEBUG_INIT()
|
||||
#endif
|
||||
#ifndef SERIAL_SOFT_DEBUG_TGL
|
||||
#define SERIAL_SOFT_DEBUG_TGL()
|
||||
#endif
|
||||
|
||||
|
|
@ -86,7 +85,9 @@ void serial_init(void)
|
|||
}
|
||||
|
||||
/* RX ring buffer */
|
||||
#define RBUF_SIZE 8
|
||||
#ifndef RBUF_SIZE
|
||||
#define RBUF_SIZE 256
|
||||
#endif
|
||||
static uint8_t rbuf[RBUF_SIZE];
|
||||
static uint8_t rbuf_head = 0;
|
||||
static uint8_t rbuf_tail = 0;
|
||||
|
|
@ -175,6 +176,9 @@ void serial_send(uint8_t data)
|
|||
ISR(SERIAL_SOFT_RXD_VECT)
|
||||
{
|
||||
SERIAL_SOFT_DEBUG_TGL();
|
||||
/* can be triggered by other pin. don't know why */
|
||||
if (SERIAL_SOFT_RXD_IN()) { return; }
|
||||
|
||||
SERIAL_SOFT_RXD_INT_ENTER();
|
||||
|
||||
uint8_t data = 0;
|
||||
|
|
@ -194,6 +198,7 @@ ISR(SERIAL_SOFT_RXD_VECT)
|
|||
/* to center of start bit */
|
||||
_delay_us(WAIT_US/2);
|
||||
SERIAL_SOFT_DEBUG_TGL();
|
||||
//if (SERIAL_SOFT_RXD_IN()) { return; }
|
||||
do {
|
||||
/* to center of next bit */
|
||||
_delay_us(WAIT_US);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,9 @@ void serial_init(void)
|
|||
}
|
||||
|
||||
// RX ring buffer
|
||||
#ifndef RBUF_SIZE
|
||||
#define RBUF_SIZE 256
|
||||
#endif
|
||||
static uint8_t rbuf[RBUF_SIZE];
|
||||
static uint8_t rbuf_head = 0;
|
||||
static uint8_t rbuf_tail = 0;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ USB_HOST_SHIELD_SRC = \
|
|||
$(USB_HOST_SHIELD_DIR)/parsetools.cpp \
|
||||
$(USB_HOST_SHIELD_DIR)/message.cpp
|
||||
|
||||
# Version string
|
||||
TMK_USB_HOST_SHIELD_VERSION := $(shell (cd $(TMK_DIR)/$(USB_HOST_SHIELD_DIR); git rev-parse --short=6 HEAD || echo 'unknown') 2> /dev/null)
|
||||
OPT_DEFS += -DTMK_USB_HOST_SHIELD_VERSION=$(TMK_USB_HOST_SHIELD_VERSION)
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
|
|
|||
|
|
@ -51,8 +51,10 @@ size_t Serial_::write(uint8_t c)
|
|||
|
||||
size_t Serial_::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
sendchar(*buffer);
|
||||
return 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
sendchar(buffer[i]);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
Serial_::operator bool() {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,15 @@ void KBDReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *b
|
|||
}
|
||||
xprintf("\r\n");
|
||||
|
||||
/* Keyboard can send report in size other than 8 bytes
|
||||
* https://github.com/tmk/tmk_keyboard/issues/773
|
||||
// boot keyboard report length should be 8
|
||||
if (len != 8) {
|
||||
xprintf(" ignored\r\n");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// Rollover error
|
||||
// Cherry: 0101010101010101
|
||||
// https://geekhack.org/index.php?topic=69169.msg2638223#msg2638223
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue